Execute() public static method

PR_ExecuteProgram
public static Execute ( int fnum ) : void
fnum int
return void
示例#1
0
        /// <summary>
        /// SV_RunThink
        /// Runs thinking code if time.  There is some play in the exact time the think
        /// function will be called, because it is called before any movement is done
        /// in a frame.  Not used for pushmove objects, because they must be exact.
        /// Returns false if the entity removed itself.
        /// </summary>
        static bool RunThink(edict_t ent)
        {
            float thinktime;

            thinktime = ent.v.nextthink;
            if (thinktime <= 0 || thinktime > sv.time + Host.FrameTime)
            {
                return(true);
            }

            if (thinktime < sv.time)
            {
                thinktime = (float)sv.time;    // don't let things stay in the past.
            }

            // it is possible to start that way
            // by a trigger with a local time.
            ent.v.nextthink          = 0;
            Progs.GlobalStruct.time  = thinktime;
            Progs.GlobalStruct.self  = EdictToProg(ent);
            Progs.GlobalStruct.other = EdictToProg(sv.edicts[0]);
            Progs.Execute(ent.v.think);

            return(!ent.free);
        }
示例#2
0
        /// <summary>
        /// SV_DropClient
        /// Called when the player is getting totally kicked off the host
        /// if (crash = true), don't bother sending signofs
        /// </summary>
        public static void DropClient(bool crash)
        {
            client_t client = Host.HostClient;

            if (!crash)
            {
                // send any final messages (don't check for errors)
                if (Net.CanSendMessage(client.netconnection))
                {
                    MsgWriter msg = client.message;
                    msg.WriteByte(Protocol.svc_disconnect);
                    Net.SendMessage(client.netconnection, msg);
                }

                if (client.edict != null && client.spawned)
                {
                    // call the prog function for removing a client
                    // this will set the body to a dead frame, among other things
                    int saveSelf = Progs.GlobalStruct.self;
                    Progs.GlobalStruct.self = EdictToProg(client.edict);
                    Progs.Execute(Progs.GlobalStruct.ClientDisconnect);
                    Progs.GlobalStruct.self = saveSelf;
                }

                Con.DPrint("Client {0} removed\n", client.name);
            }

            // break the net connection
            Net.Close(client.netconnection);
            client.netconnection = null;

            // free the client (the body stays around)
            client.active    = false;
            client.name      = null;
            client.old_frags = -999999;
            Net.ActiveConnections--;

            // send notification to all clients
            for (int i = 0; i < Server.svs.maxclients; i++)
            {
                client_t cl = Server.svs.clients[i];
                if (!cl.active)
                {
                    continue;
                }

                cl.message.WriteByte(Protocol.svc_updatename);
                cl.message.WriteByte(Host.ClientNum);
                cl.message.WriteString("");
                cl.message.WriteByte(Protocol.svc_updatefrags);
                cl.message.WriteByte(Host.ClientNum);
                cl.message.WriteShort(0);
                cl.message.WriteByte(Protocol.svc_updatecolors);
                cl.message.WriteByte(Host.ClientNum);
                cl.message.WriteByte(0);
            }
        }
示例#3
0
        /// <summary>
        /// SV_TouchLinks
        /// </summary>
        static void TouchLinks(edict_t ent, areanode_t node)
        {
            // touch linked edicts
            LinkList next;

            for (LinkList l = node.trigger_edicts.Next; l != node.trigger_edicts; l = next)
            {
                next = l.Next;
                edict_t touch = (edict_t)l.Owner;// EDICT_FROM_AREA(l);
                if (touch == ent)
                {
                    continue;
                }

                if (touch.v.touch == 0 || touch.v.solid != Solids.SOLID_TRIGGER)
                {
                    continue;
                }

                if (ent.v.absmin.x > touch.v.absmax.x || ent.v.absmin.y > touch.v.absmax.y ||
                    ent.v.absmin.z > touch.v.absmax.z || ent.v.absmax.x < touch.v.absmin.x ||
                    ent.v.absmax.y < touch.v.absmin.y || ent.v.absmax.z < touch.v.absmin.z)
                {
                    continue;
                }

                int old_self  = Progs.GlobalStruct.self;
                int old_other = Progs.GlobalStruct.other;

                Progs.GlobalStruct.self  = EdictToProg(touch);
                Progs.GlobalStruct.other = EdictToProg(ent);
                Progs.GlobalStruct.time  = (float)sv.time;
                Progs.Execute(touch.v.touch);

                Progs.GlobalStruct.self  = old_self;
                Progs.GlobalStruct.other = old_other;
            }

            // recurse down both sides
            if (node.axis == -1)
            {
                return;
            }

            if (Mathlib.Comp(ref ent.v.absmax, node.axis) > node.dist)
            {
                TouchLinks(ent, node.children[0]);
            }

            if (Mathlib.Comp(ref ent.v.absmin, node.axis) < node.dist)
            {
                TouchLinks(ent, node.children[1]);
            }
        }
示例#4
0
        /// <summary>
        /// SV_SaveSpawnparms
        /// Grabs the current state of each client for saving across the
        /// transition to another level
        /// </summary>
        public static void SaveSpawnparms()
        {
            Server.svs.serverflags = (int)Progs.GlobalStruct.serverflags;

            for (int i = 0; i < svs.maxclients; i++)
            {
                Host.HostClient = Server.svs.clients[i];
                if (!Host.HostClient.active)
                {
                    continue;
                }

                // call the progs to get default spawn parms for the new client
                Progs.GlobalStruct.self = EdictToProg(Host.HostClient.edict);
                Progs.Execute(Progs.GlobalStruct.SetChangeParms);
                AssignGlobalSpawnparams(Host.HostClient);
            }
        }
示例#5
0
        /// <summary>
        /// Host_Kill_f
        /// </summary>
        private static void Kill_f()
        {
            if (Cmd.Source == cmd_source_t.src_command)
            {
                Cmd.ForwardToServer();
                return;
            }

            if (Server.Player.v.health <= 0)
            {
                Server.ClientPrint("Can't suicide -- allready dead!\n");
                return;
            }

            Progs.GlobalStruct.time = (float)Server.sv.time;
            Progs.GlobalStruct.self = Server.EdictToProg(Server.Player);
            Progs.Execute(Progs.GlobalStruct.ClientKill);
        }
示例#6
0
        /// <summary>
        /// SV_ConnectClient
        /// Initializes a client_t for a new net connection.  This will only be called
        /// once for a player each game, not once for each level change.
        /// </summary>
        static void ConnectClient(int clientnum)
        {
            client_t client = svs.clients[clientnum];

            Con.DPrint("Client {0} connected\n", client.netconnection.address);

            int     edictnum = clientnum + 1;
            edict_t ent      = EdictNum(edictnum);

            // set up the client_t
            qsocket_t netconnection = client.netconnection;

            float[] spawn_parms = new float[NUM_SPAWN_PARMS];
            if (sv.loadgame)
            {
                Array.Copy(client.spawn_parms, spawn_parms, spawn_parms.Length);
            }

            client.Clear();
            client.netconnection         = netconnection;
            client.name                  = "unconnected";
            client.active                = true;
            client.spawned               = false;
            client.edict                 = ent;
            client.message.AllowOverflow = true; // we can catch it
            client.privileged            = false;

            if (sv.loadgame)
            {
                Array.Copy(spawn_parms, client.spawn_parms, spawn_parms.Length);
            }
            else
            {
                // call the progs to get default spawn parms for the new client
                Progs.Execute(Progs.GlobalStruct.SetNewParms);

                AssignGlobalSpawnparams(client);
            }

            SendServerInfo(client);
        }
示例#7
0
        /// <summary>
        /// SV_Impact
        /// Two entities have touched, so run their touch functions
        /// </summary>
        static void Impact(edict_t e1, edict_t e2)
        {
            int old_self  = Progs.GlobalStruct.self;
            int old_other = Progs.GlobalStruct.other;

            Progs.GlobalStruct.time = (float)sv.time;
            if (e1.v.touch != 0 && e1.v.solid != Solids.SOLID_NOT)
            {
                Progs.GlobalStruct.self  = EdictToProg(e1);
                Progs.GlobalStruct.other = EdictToProg(e2);
                Progs.Execute(e1.v.touch);
            }

            if (e2.v.touch != 0 && e2.v.solid != Solids.SOLID_NOT)
            {
                Progs.GlobalStruct.self  = EdictToProg(e2);
                Progs.GlobalStruct.other = EdictToProg(e1);
                Progs.Execute(e2.v.touch);
            }

            Progs.GlobalStruct.self  = old_self;
            Progs.GlobalStruct.other = old_other;
        }
示例#8
0
        /// <summary>
        /// SV_Physics_Pusher
        /// </summary>
        static void Physics_Pusher(edict_t ent)
        {
            float oldltime  = ent.v.ltime;
            float thinktime = ent.v.nextthink;
            float movetime;

            if (thinktime < ent.v.ltime + Host.FrameTime)
            {
                movetime = thinktime - ent.v.ltime;
                if (movetime < 0)
                {
                    movetime = 0;
                }
            }
            else
            {
                movetime = (float)Host.FrameTime;
            }

            if (movetime != 0)
            {
                PushMove(ent, movetime);        // advances ent.v.ltime if not blocked
            }

            if (thinktime > oldltime && thinktime <= ent.v.ltime)
            {
                ent.v.nextthink          = 0;
                Progs.GlobalStruct.time  = (float)sv.time;
                Progs.GlobalStruct.self  = EdictToProg(ent);
                Progs.GlobalStruct.other = EdictToProg(sv.edicts[0]);
                Progs.Execute(ent.v.think);
                if (ent.free)
                {
                    return;
                }
            }
        }
示例#9
0
        /// <summary>
        /// SV_Physics_Client
        /// Player character actions
        /// </summary>
        static void Physics_Client(edict_t ent, int num)
        {
            if (!svs.clients[num - 1].active)
            {
                return;         // unconnected slot
            }
            //
            // call standard client pre-think
            //
            Progs.GlobalStruct.time = (float)sv.time;
            Progs.GlobalStruct.self = EdictToProg(ent);
            Progs.Execute(Progs.GlobalStruct.PlayerPreThink);

            //
            // do a move
            //
            CheckVelocity(ent);

            //
            // decide which move function to call
            //
            switch ((int)ent.v.movetype)
            {
            case Movetypes.MOVETYPE_NONE:
                if (!RunThink(ent))
                {
                    return;
                }
                break;

            case Movetypes.MOVETYPE_WALK:
                if (!RunThink(ent))
                {
                    return;
                }
                if (!CheckWater(ent) && ((int)ent.v.flags & EdictFlags.FL_WATERJUMP) == 0)
                {
                    AddGravity(ent);
                }
                CheckStuck(ent);

                WalkMove(ent);
                break;

            case Movetypes.MOVETYPE_TOSS:
            case Movetypes.MOVETYPE_BOUNCE:
                Physics_Toss(ent);
                break;

            case Movetypes.MOVETYPE_FLY:
                if (!RunThink(ent))
                {
                    return;
                }
                FlyMove(ent, (float)Host.FrameTime, null);
                break;

            case Movetypes.MOVETYPE_NOCLIP:
                if (!RunThink(ent))
                {
                    return;
                }
                Mathlib.VectorMA(ref ent.v.origin, (float)Host.FrameTime, ref ent.v.velocity, out ent.v.origin);
                break;

            default:
                Sys.Error("SV_Physics_client: bad movetype {0}", (int)ent.v.movetype);
                break;
            }

            //
            // call standard player post-think
            //
            LinkEdict(ent, true);

            Progs.GlobalStruct.time = (float)sv.time;
            Progs.GlobalStruct.self = EdictToProg(ent);
            Progs.Execute(Progs.GlobalStruct.PlayerPostThink);
        }
示例#10
0
        /// <summary>
        /// SV_Physics
        /// </summary>
        public static void Physics()
        {
            // let the progs know that a new frame has started
            Progs.GlobalStruct.self  = EdictToProg(sv.edicts[0]);
            Progs.GlobalStruct.other = Progs.GlobalStruct.self;
            Progs.GlobalStruct.time  = (float)sv.time;
            Progs.Execute(Progs.GlobalStruct.StartFrame);

            //
            // treat each object in turn
            //
            for (int i = 0; i < sv.num_edicts; i++)
            {
                edict_t ent = sv.edicts[i];
                if (ent.free)
                {
                    continue;
                }

                if (Progs.GlobalStruct.force_retouch != 0)
                {
                    LinkEdict(ent, true);       // force retouch even for stationary
                }

                if (i > 0 && i <= svs.maxclients)
                {
                    Physics_Client(ent, i);
                }
                else
                {
                    switch ((int)ent.v.movetype)
                    {
                    case Movetypes.MOVETYPE_PUSH:
                        Physics_Pusher(ent);
                        break;

                    case Movetypes.MOVETYPE_NONE:
                        Physics_None(ent);
                        break;

                    case Movetypes.MOVETYPE_NOCLIP:
                        Physics_Noclip(ent);
                        break;

                    case Movetypes.MOVETYPE_STEP:
                        Physics_Step(ent);
                        break;

                    case Movetypes.MOVETYPE_TOSS:
                    case Movetypes.MOVETYPE_BOUNCE:
                    case Movetypes.MOVETYPE_FLY:
                    case Movetypes.MOVETYPE_FLYMISSILE:
                        Physics_Toss(ent);
                        break;

                    default:
                        Sys.Error("SV_Physics: bad movetype {0}", (int)ent.v.movetype);
                        break;
                    }
                }
            }

            if (Progs.GlobalStruct.force_retouch != 0)
            {
                Progs.GlobalStruct.force_retouch -= 1;
            }

            sv.time += Host.FrameTime;
        }
示例#11
0
        /// <summary>
        /// SV_PushMove
        /// </summary>
        static void PushMove(edict_t pusher, float movetime)
        {
            if (pusher.v.velocity.IsEmpty)
            {
                pusher.v.ltime += movetime;
                return;
            }

            v3f move, mins, maxs;

            Mathlib.VectorScale(ref pusher.v.velocity, movetime, out move);
            Mathlib.VectorAdd(ref pusher.v.absmin, ref move, out mins);
            Mathlib.VectorAdd(ref pusher.v.absmax, ref move, out maxs);

            v3f pushorig = pusher.v.origin;

            edict_t[] moved_edict = new edict_t[QDef.MAX_EDICTS];
            v3f[]     moved_from  = new v3f[QDef.MAX_EDICTS];

            // move the pusher to it's final position

            Mathlib.VectorAdd(ref pusher.v.origin, ref move, out pusher.v.origin);
            pusher.v.ltime += movetime;
            LinkEdict(pusher, false);


            // see if any solid entities are inside the final position
            int num_moved = 0;

            for (int e = 1; e < sv.num_edicts; e++)
            {
                edict_t check = sv.edicts[e];
                if (check.free)
                {
                    continue;
                }
                if (check.v.movetype == Movetypes.MOVETYPE_PUSH ||
                    check.v.movetype == Movetypes.MOVETYPE_NONE ||
                    check.v.movetype == Movetypes.MOVETYPE_NOCLIP)
                {
                    continue;
                }

                // if the entity is standing on the pusher, it will definately be moved
                if (!(((int)check.v.flags & EdictFlags.FL_ONGROUND) != 0 && ProgToEdict(check.v.groundentity) == pusher))
                {
                    if (check.v.absmin.x >= maxs.x || check.v.absmin.y >= maxs.y ||
                        check.v.absmin.z >= maxs.z || check.v.absmax.x <= mins.x ||
                        check.v.absmax.y <= mins.y || check.v.absmax.z <= mins.z)
                    {
                        continue;
                    }

                    // see if the ent's bbox is inside the pusher's final position
                    if (TestEntityPosition(check) == null)
                    {
                        continue;
                    }
                }

                // remove the onground flag for non-players
                if (check.v.movetype != Movetypes.MOVETYPE_WALK)
                {
                    check.v.flags = (int)check.v.flags & ~EdictFlags.FL_ONGROUND;
                }

                v3f entorig = check.v.origin;
                moved_from[num_moved]  = entorig;
                moved_edict[num_moved] = check;
                num_moved++;

                // try moving the contacted entity
                pusher.v.solid = Solids.SOLID_NOT;
                PushEntity(check, ref move);
                pusher.v.solid = Solids.SOLID_BSP;

                // if it is still inside the pusher, block
                edict_t block = TestEntityPosition(check);
                if (block != null)
                {
                    // fail the move
                    if (check.v.mins.x == check.v.maxs.x)
                    {
                        continue;
                    }
                    if (check.v.solid == Solids.SOLID_NOT || check.v.solid == Solids.SOLID_TRIGGER)
                    {
                        // corpse
                        check.v.mins.x = check.v.mins.y = 0;
                        check.v.maxs   = check.v.mins;
                        continue;
                    }

                    check.v.origin = entorig;
                    LinkEdict(check, true);

                    pusher.v.origin = pushorig;
                    LinkEdict(pusher, false);
                    pusher.v.ltime -= movetime;

                    // if the pusher has a "blocked" function, call it
                    // otherwise, just stay in place until the obstacle is gone
                    if (pusher.v.blocked != 0)
                    {
                        Progs.GlobalStruct.self  = EdictToProg(pusher);
                        Progs.GlobalStruct.other = EdictToProg(check);
                        Progs.Execute(pusher.v.blocked);
                    }

                    // move back any entities we already moved
                    for (int i = 0; i < num_moved; i++)
                    {
                        moved_edict[i].v.origin = moved_from[i];
                        LinkEdict(moved_edict[i], false);
                    }
                    return;
                }
            }
        }
示例#12
0
        /// <summary>
        /// Host_Spawn_f
        /// </summary>
        private static void Spawn_f()
        {
            if (Cmd.Source == cmd_source_t.src_command)
            {
                Con.Print("spawn is not valid from the console\n");
                return;
            }

            if (Host.HostClient.spawned)
            {
                Con.Print("Spawn not valid -- allready spawned\n");
                return;
            }

            edict_t ent;

            // run the entrance script
            if (Server.sv.loadgame)
            {
                // loaded games are fully inited allready
                // if this is the last client to be connected, unpause
                Server.sv.paused = false;
            }
            else
            {
                // set up the edict
                ent = Host.HostClient.edict;

                ent.Clear(); //memset(&ent.v, 0, progs.entityfields * 4);
                ent.v.colormap = Server.NumForEdict(ent);
                ent.v.team     = (Host.HostClient.colors & 15) + 1;
                ent.v.netname  = Progs.NewString(Host.HostClient.name);

                // copy spawn parms out of the client_t
                Progs.GlobalStruct.SetParams(Host.HostClient.spawn_parms);

                // call the spawn function

                Progs.GlobalStruct.time = (float)Server.sv.time;
                Progs.GlobalStruct.self = Server.EdictToProg(Server.Player);
                Progs.Execute(Progs.GlobalStruct.ClientConnect);

                if ((Sys.GetFloatTime() - Host.HostClient.netconnection.connecttime) <= Server.sv.time)
                {
                    Con.DPrint("{0} entered the game\n", Host.HostClient.name);
                }

                Progs.Execute(Progs.GlobalStruct.PutClientInServer);
            }

            // send all current names, colors, and frag counts
            MsgWriter msg = Host.HostClient.message;

            msg.Clear();

            // send time of update
            msg.WriteByte(Protocol.svc_time);
            msg.WriteFloat((float)Server.sv.time);

            for (int i = 0; i < Server.svs.maxclients; i++)
            {
                client_t client = Server.svs.clients[i];
                msg.WriteByte(Protocol.svc_updatename);
                msg.WriteByte(i);
                msg.WriteString(client.name);
                msg.WriteByte(Protocol.svc_updatefrags);
                msg.WriteByte(i);
                msg.WriteShort(client.old_frags);
                msg.WriteByte(Protocol.svc_updatecolors);
                msg.WriteByte(i);
                msg.WriteByte(client.colors);
            }

            // send all current light styles
            for (int i = 0; i < QDef.MAX_LIGHTSTYLES; i++)
            {
                msg.WriteByte(Protocol.svc_lightstyle);
                msg.WriteByte((char)i);
                msg.WriteString(Server.sv.lightstyles[i]);
            }

            //
            // send some stats
            //
            msg.WriteByte(Protocol.svc_updatestat);
            msg.WriteByte(QStats.STAT_TOTALSECRETS);
            msg.WriteLong((int)Progs.GlobalStruct.total_secrets);

            msg.WriteByte(Protocol.svc_updatestat);
            msg.WriteByte(QStats.STAT_TOTALMONSTERS);
            msg.WriteLong((int)Progs.GlobalStruct.total_monsters);

            msg.WriteByte(Protocol.svc_updatestat);
            msg.WriteByte(QStats.STAT_SECRETS);
            msg.WriteLong((int)Progs.GlobalStruct.found_secrets);

            msg.WriteByte(Protocol.svc_updatestat);
            msg.WriteByte(QStats.STAT_MONSTERS);
            msg.WriteLong((int)Progs.GlobalStruct.killed_monsters);

            //
            // send a fixangle
            // Never send a roll angle, because savegames can catch the server
            // in a state where it is expecting the client to correct the angle
            // and it won't happen if the game was just loaded, so you wind up
            // with a permanent head tilt
            ent = Server.EdictNum(1 + Host.ClientNum);
            msg.WriteByte(Protocol.svc_setangle);
            msg.WriteAngle(ent.v.angles.x);
            msg.WriteAngle(ent.v.angles.y);
            msg.WriteAngle(0);

            Server.WriteClientDataToMessage(Server.Player, Host.HostClient.message);

            msg.WriteByte(Protocol.svc_signonnum);
            msg.WriteByte(3);
            Host.HostClient.sendsignon = true;
        }