From fc0e457ed26ef1d2d568c753bbac2b4ca9dd6324 Mon Sep 17 00:00:00 2001 From: havoc Date: Mon, 17 Jan 2005 22:52:16 +0000 Subject: [PATCH] reverted back to per-entity prethink-think-move-postthink process to fix mods git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4941 d7cf8633-e32d-0410-b094-e92efae38249 --- sv_phys.c | 201 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 103 insertions(+), 98 deletions(-) diff --git a/sv_phys.c b/sv_phys.c index 9f7a0adc..b1e8814a 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -128,6 +128,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 ; ie->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); -- 2.39.2