reverted back to per-entity prethink-think-move-postthink process to fix mods
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 17 Jan 2005 22:52:16 +0000 (22:52 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 17 Jan 2005 22:52:16 +0000 (22:52 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4941 d7cf8633-e32d-0410-b094-e92efae38249

sv_phys.c

index 9f7a0ad..b1e8814 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -129,6 +129,37 @@ void SV_CheckVelocity (edict_t *ent)
 }
 
 /*
+=============
+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.
+=============
+*/
+qboolean SV_RunThink (edict_t *ent)
+{
+       float thinktime;
+
+       thinktime = ent->v->nextthink;
+       if (thinktime <= 0 || thinktime > sv.time + sv.frametime)
+               return true;
+
+       // don't let things stay in the past.
+       // it is possible to start that way by a trigger with a local time.
+       if (thinktime < sv.time)
+               thinktime = sv.time;
+
+       ent->v->nextthink = 0;
+       pr_global_struct->time = thinktime;
+       pr_global_struct->self = EDICT_TO_PROG(ent);
+       pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
+       PR_ExecuteProgram (ent->v->think, "QC function self.think is missing");
+       return !ent->e->free;
+}
+
+/*
 ==================
 SV_Impact
 
@@ -1105,6 +1136,9 @@ void SV_Physics_Follow (edict_t *ent)
        edict_t *e;
 
        // regular thinking
+       if (!SV_RunThink (ent))
+               return;
+
        // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
        e = PROG_TO_EDICT(ent->v->aiment);
        if (e->v->angles[0] == ent->v->punchangle[0] && e->v->angles[1] == ent->v->punchangle[1] && e->v->angles[2] == ent->v->punchangle[2])
@@ -1188,6 +1222,10 @@ void SV_Physics_Toss (edict_t *ent)
        vec3_t move;
        edict_t *groundentity;
 
+       // regular thinking
+       if (!SV_RunThink (ent))
+               return;
+
        // don't stick to ground if onground and moving upward
        if (ent->v->velocity[2] >= (1.0 / 32.0) && ((int)ent->v->flags & FL_ONGROUND))
                ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
@@ -1329,6 +1367,9 @@ void SV_Physics_Step (edict_t *ent)
                        SV_StartSound(ent, 0, "demon/dland2.wav", 255, 1);
        }
 
+// regular thinking
+       SV_RunThink(ent);
+
        SV_CheckWaterTransition(ent);
 }
 
@@ -1342,9 +1383,7 @@ SV_Physics
 */
 void SV_Physics (void)
 {
-       int i, end, retouch;
-       float nexttime;
-       vec3_t oldorigin;
+       int i;
        edict_t *ent;
 
 // let the progs know that a new frame has started
@@ -1353,16 +1392,32 @@ void SV_Physics (void)
        pr_global_struct->time = sv.time;
        PR_ExecuteProgram (pr_global_struct->StartFrame, "QC function StartFrame is missing");
 
-       retouch = pr_global_struct->force_retouch > 0;
-       end = i = sv_freezenonclients.integer ? svs.maxclients + 1 : sv.num_edicts;
-       for (i = 0, ent = sv.edicts;i < end;i++, ent = NEXT_EDICT(ent))
+//
+// treat each object in turn
+//
+       ent = sv.edicts;
+       for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
        {
-               if (ent->e->free || ent->v->movetype == MOVETYPE_NONE)
+               if (ent->e->free)
                        continue;
 
-               // LordHavoc: merged client and normal entity physics
-               VectorCopy(ent->v->origin, oldorigin);
+               if (pr_global_struct->force_retouch)
+                       SV_LinkEdict (ent, true);       // force retouch even for stationary
+
+               if (i >= 1 && i <= svs.maxclients && svs.clients[i-1].spawned)
+               {
+                       // connected slot
+                       // call standard client pre-think
+                       SV_CheckVelocity (ent);
+                       pr_global_struct->time = sv.time;
+                       pr_global_struct->self = EDICT_TO_PROG(ent);
+                       PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
+                       SV_CheckVelocity (ent);
+               }
+               else if (sv_freezenonclients.integer)
+                       continue;
 
+               // LordHavoc: merged client and normal entity physics
                switch ((int) ent->v->movetype)
                {
                case MOVETYPE_PUSH:
@@ -1370,127 +1425,77 @@ void SV_Physics (void)
                        SV_Physics_Pusher (ent);
                        break;
                case MOVETYPE_NONE:
+                       // LordHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects
+                       if (ent->v->nextthink > 0 && ent->v->nextthink <= sv.time + sv.frametime)
+                               SV_RunThink (ent);
                        break;
                case MOVETYPE_FOLLOW:
                        SV_Physics_Follow (ent);
                        break;
                case MOVETYPE_NOCLIP:
-                       SV_CheckWater(ent);
-                       VectorMA(ent->v->origin, sv.frametime, ent->v->velocity, ent->v->origin);
-                       VectorMA(ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles);
+                       if (SV_RunThink(ent))
+                       {
+                               SV_CheckWater(ent);
+                               VectorMA(ent->v->origin, sv.frametime, ent->v->velocity, ent->v->origin);
+                               VectorMA(ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles);
+                       }
+                       // relink normal entities here, players always get relinked so don't relink twice
+                       if (!(i > 0 && i <= svs.maxclients))
+                               SV_LinkEdict(ent, false);
                        break;
                case MOVETYPE_STEP:
                        SV_Physics_Step (ent);
                        break;
                case MOVETYPE_WALK:
-                       if (!SV_CheckWater(ent) && ! ((int)ent->v->flags & FL_WATERJUMP) )
-                               SV_AddGravity(ent);
-                       SV_CheckStuck(ent);
-                       SV_WalkMove(ent);
+                       if (SV_RunThink (ent))
+                       {
+                               if (!SV_CheckWater (ent) && ! ((int)ent->v->flags & FL_WATERJUMP) )
+                                       SV_AddGravity (ent);
+                               SV_CheckStuck (ent);
+                               SV_WalkMove (ent);
+                               // relink normal entities here, players always get relinked so don't relink twice
+                               if (!(i > 0 && i <= svs.maxclients))
+                                       SV_LinkEdict (ent, true);
+                       }
                        break;
                case MOVETYPE_TOSS:
                case MOVETYPE_BOUNCE:
                case MOVETYPE_BOUNCEMISSILE:
                case MOVETYPE_FLYMISSILE:
-                       SV_Physics_Toss(ent);
+                       SV_Physics_Toss (ent);
                        break;
                case MOVETYPE_FLY:
-                       if (i >= 1 && i <= svs.maxclients && svs.clients[i-1].spawned)
+                       if (i > 0 && i <= svs.maxclients)
                        {
-                               SV_CheckWater(ent);
-                               SV_WalkMove(ent);
+                               if (SV_RunThink (ent))
+                               {
+                                       SV_CheckWater (ent);
+                                       SV_WalkMove (ent);
+                               }
                        }
                        else
-                               SV_Physics_Toss(ent);
+                               SV_Physics_Toss (ent);
                        break;
                default:
                        Host_Error ("SV_Physics: bad movetype %i", (int)ent->v->movetype);
                        break;
                }
 
-               if (!VectorCompare(ent->v->origin, oldorigin) || retouch)
-                       SV_LinkEdict(ent, true);
-       }
-
-       for (i = 1, ent = NEXT_EDICT(sv.edicts);i <= svs.maxclients;i++, ent = NEXT_EDICT(ent))
-       {
-               if (ent->e->free || !svs.clients[i-1].spawned)
-                       continue;
+               if (i >= 1 && i <= svs.maxclients && svs.clients[i-1].spawned)
+               {
+                       SV_CheckVelocity (ent);
 
-               // call standard client pre-think
-               SV_CheckVelocity (ent);
-               pr_global_struct->time = sv.time;
-               pr_global_struct->self = EDICT_TO_PROG(ent);
-               PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
-               SV_CheckVelocity (ent);
-       }
+                       // call standard player post-think
+                       SV_LinkEdict (ent, true);
 
-       nexttime = sv.time + sv.frametime;
-       end = i = sv_freezenonclients.integer ? svs.maxclients + 1 : sv.num_edicts;
-       for (i = 0, ent = sv.edicts;i < end;i++, ent = NEXT_EDICT(ent))
-       {
-               if (ent->e->free)
-                       continue;
+                       SV_CheckVelocity (ent);
 
-               // LordHavoc: merged client and normal entity physics
-               switch ((int) ent->v->movetype)
-               {
-               case MOVETYPE_PUSH:
-               case MOVETYPE_FAKEPUSH:
-                       // push thinks are called from SV_Physics_Pusher 
-                       break;
-               case MOVETYPE_NONE:
-               case MOVETYPE_FOLLOW:
-               case MOVETYPE_NOCLIP:
-               case MOVETYPE_STEP:
-               case MOVETYPE_WALK:
-               case MOVETYPE_TOSS:
-               case MOVETYPE_BOUNCE:
-               case MOVETYPE_BOUNCEMISSILE:
-               case MOVETYPE_FLY:
-               case MOVETYPE_FLYMISSILE:
-                       // LordHavoc: manually inlined SV_RunThink here
-                       if (ent->v->nextthink > 0 && ent->v->nextthink <= nexttime)
-                       {
-                               /*
-                               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.
-                               */
-                               float thinktime = ent->v->nextthink;
-                               if (thinktime && thinktime < sv.time + sv.frametime)
-                               {
-                                       ent->v->nextthink = 0;
-                                       // don't let things stay in the past.
-                                       // it is possible to start that way by a trigger with a local time.
-                                       pr_global_struct->time = max(thinktime, sv.time);
-                                       pr_global_struct->self = EDICT_TO_PROG(ent);
-                                       pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
-                                       PR_ExecuteProgram (ent->v->think, "QC function self.think is missing");
-                               }
-                       }
-                       break;
-               default:
-                       Host_Error ("SV_Physics: bad movetype %i", (int)ent->v->movetype);
-                       break;
+                       pr_global_struct->time = sv.time;
+                       pr_global_struct->self = EDICT_TO_PROG(ent);
+                       PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
                }
        }
 
-       for (i = 1, ent = NEXT_EDICT(sv.edicts);i <= svs.maxclients;i++, ent = NEXT_EDICT(ent))
-       {
-               if (ent->e->free || !svs.clients[i-1].spawned)
-                       continue;
-
-               // call standard player post-think
-               SV_LinkEdict (ent, true);
-               SV_CheckVelocity (ent);
-               pr_global_struct->time = sv.time;
-               pr_global_struct->self = EDICT_TO_PROG(ent);
-               PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
-       }
-
        if (pr_global_struct->force_retouch > 0)
                pr_global_struct->force_retouch = max(0, pr_global_struct->force_retouch - 1);