/* * G_RunEntity * */ void G_RunEntity( edict_t *ent ) { edict_t *part; if( !level.canSpawnEntities ) { // don't try to think before map entities are spawned return; } if( ISEVENTENTITY( &ent->s ) ) { // events do not think return; } if( ent->timeDelta && !( ent->r.svflags & SVF_PROJECTILE ) ) { G_Printf( "Warning: G_RunEntity 'Fixing timeDelta on non projectile entity\n" ); ent->timeDelta = 0; } // only team captains decide the think, and they make think their team members when they do if( !( ent->flags & FL_TEAMSLAVE ) ) { for( part = ent; part; part = part->teamchain ) { SV_RunThink( part ); } } switch( (int)ent->movetype ) { case MOVETYPE_NONE: case MOVETYPE_NOCLIP: // only used for clients, that use pmove SV_Physics_None( ent ); break; case MOVETYPE_PLAYER: SV_Physics_None( ent ); break; case MOVETYPE_PUSH: case MOVETYPE_STOP: SV_Physics_Pusher( ent ); break; case MOVETYPE_BOUNCE: case MOVETYPE_BOUNCEGRENADE: SV_Physics_Toss( ent ); break; case MOVETYPE_TOSS: SV_Physics_Toss( ent ); break; case MOVETYPE_FLY: SV_Physics_Toss( ent ); break; case MOVETYPE_LINEARPROJECTILE: SV_Physics_LinearProjectile( ent ); break; case MOVETYPE_TOSSSLIDE: G_BoxSlideMove( ent, ent->r.clipmask ? ent->r.clipmask : MASK_PLAYERSOLID, 1.01f, 10 ); break; case MOVETYPE_STEP: SV_Physics_Step( ent ); break; default: G_Error( "SV_Physics: bad movetype %i", (int)ent->movetype ); } }
/* ================ SV_Physics ================ */ void SV_Physics (void) { int i; edict_t *ent; // let the progs know that a new frame has started pr_global_struct->self = ((int)EDICT_TO_PROG(sv.edicts)); pr_global_struct->other = ((int)EDICT_TO_PROG(sv.edicts)); pr_global_struct->time = sv.time; PR_ExecuteProgram (pr_global_struct->StartFrame); //SV_CheckAllEnts (); // // treat each object in turn // ent = sv.edicts; for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) { if (ent->free) continue; if (pr_global_struct->force_retouch) { SV_LinkEdict (ent, true); // force retouch even for stationary } if (i > 0 && i <= svs.maxclients) SV_Physics_Client (ent, i); else if (ent->v.movetype == MOVETYPE_PUSH) SV_Physics_Pusher (ent); else if (ent->v.movetype == MOVETYPE_FAKEPUSH) SV_Physics_FakePusher (ent); else if (ent->v.movetype == MOVETYPE_NONE) SV_Physics_None (ent); #ifdef QUAKE2 else if (ent->v.movetype == MOVETYPE_FOLLOW) SV_Physics_Follow (ent); #endif else if (ent->v.movetype == MOVETYPE_NOCLIP) SV_Physics_Noclip (ent); else if (ent->v.movetype == MOVETYPE_STEP) SV_Physics_Step (ent); else if (ent->v.movetype == MOVETYPE_TOSS || ent->v.movetype == MOVETYPE_BOUNCE #ifdef QUAKE2 || ent->v.movetype == MOVETYPE_BOUNCEMISSILE #endif || ent->v.movetype == MOVETYPE_FLY || ent->v.movetype == MOVETYPE_FLYMISSILE) SV_Physics_Toss (ent); else Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); } if (pr_global_struct->force_retouch) pr_global_struct->force_retouch--; sv.time += host_frametime; }
/* ================ SV_RunEntity ================ */ void SV_RunEntity (edict_t *ent) { if (ent->v.lastruntime == (float)realtime) return; ent->v.lastruntime = (float)realtime; switch ( (int)ent->v.movetype) { case MOVETYPE_PUSH: SV_Physics_Pusher (ent); break; case MOVETYPE_NONE: SV_Physics_None (ent); break; case MOVETYPE_NOCLIP: SV_Physics_Noclip (ent); break; case MOVETYPE_STEP: SV_Physics_Step (ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: SV_Physics_Toss (ent); break; default: SV_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); } }
/* ================ G_RunEntity ================ */ void G_RunEntity (edict_t *ent) { if (ent->prethink) ent->prethink (ent); switch ( (int)ent->movetype) { case MOVETYPE_PUSH: case MOVETYPE_STOP: SV_Physics_Pusher (ent); break; case MOVETYPE_NONE: SV_Physics_None (ent); break; case MOVETYPE_NOCLIP: SV_Physics_Noclip (ent); break; case MOVETYPE_STEP: SV_Physics_Step (ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: case MOVETYPE_WALLBOUNCE: case MOVETYPE_TOSS_SLIDE: SV_Physics_Toss (ent); break; default: gi.error ("SV_Physics: bad movetype %i", (int)ent->movetype); } }
//============================================================================ static void SV_Physics_Entity( edict_t *ent ) { // user dll can override movement type (Xash3D extension) if( svgame.physFuncs.SV_PhysicsEntity && svgame.physFuncs.SV_PhysicsEntity( ent )) return; // overrided SV_UpdateBaseVelocity( ent ); if(!( ent->v.flags & FL_BASEVELOCITY ) && !VectorIsNull( ent->v.basevelocity )) { // Apply momentum (add in half of the previous frame of velocity first) VectorMA( ent->v.velocity, 1.0f + (host.frametime * 0.5f), ent->v.basevelocity, ent->v.velocity ); VectorClear( ent->v.basevelocity ); } ent->v.flags &= ~FL_BASEVELOCITY; if( svgame.globals->force_retouch != 0.0f ) { // force retouch even for stationary SV_LinkEdict( ent, true ); } switch( ent->v.movetype ) { case MOVETYPE_NONE: SV_Physics_None( ent ); break; case MOVETYPE_NOCLIP: SV_Physics_Noclip( ent ); break; case MOVETYPE_FOLLOW: SV_Physics_Follow( ent ); break; case MOVETYPE_COMPOUND: SV_Physics_Compound( ent ); break; case MOVETYPE_STEP: case MOVETYPE_PUSHSTEP: SV_Physics_Step( ent ); break; case MOVETYPE_FLY: case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLYMISSILE: case MOVETYPE_BOUNCEMISSILE: SV_Physics_Toss( ent ); break; case MOVETYPE_PUSH: SV_Physics_Pusher( ent ); break; case MOVETYPE_WALK: Host_Error( "SV_Physics: bad movetype %i\n", ent->v.movetype ); break; } // g-cont. don't alow free entities during loading because // this produce a corrupted baselines if( sv.state == ss_active && ent->v.flags & FL_KILLME ) SV_FreeEdict( ent ); }
/* ================ G_RunEntity ================ */ void G_RunEntity (edict_t *ent) { //PGM trace_t trace; vec3_t previous_origin; if(ent->movetype == MOVETYPE_STEP) VectorCopy(ent->s.origin, previous_origin); //PGM if (ent->prethink) ent->prethink (ent); switch ( (int)ent->movetype) { case MOVETYPE_PUSH: case MOVETYPE_STOP: SV_Physics_Pusher (ent); break; case MOVETYPE_NONE: SV_Physics_None (ent); break; case MOVETYPE_NOCLIP: SV_Physics_Noclip (ent); break; case MOVETYPE_STEP: SV_Physics_Step (ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: SV_Physics_Toss (ent); break; case MOVETYPE_NEWTOSS: SV_Physics_NewToss (ent); break; default: gi.error ("SV_Physics: bad movetype %i", (int)ent->movetype); } //PGM if(ent->movetype == MOVETYPE_STEP) { // if we moved, check and fix origin if needed if (!VectorCompare(ent->s.origin, previous_origin)) { trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, previous_origin, ent, MASK_MONSTERSOLID); if(trace.allsolid || trace.startsolid) VectorCopy (previous_origin, ent->s.origin); } } //PGM }
/* * ================ G_RunEntity ================ */ void G_RunEntity(edict_t * ent) { if (!ent) return; if (ent->prethink) ent->prethink(ent); switch ((int)ent->movetype) { #ifdef WITH_ACEBOT /* ACEBOT_ADD */ case MOVETYPE_WALK: SV_RunThink(ent); break; /* ACEBOT_END */ #endif case MOVETYPE_PUSH: case MOVETYPE_STOP: SV_Physics_Pusher(ent); break; case MOVETYPE_NONE: SV_Physics_None(ent); break; case MOVETYPE_NOCLIP: SV_Physics_Noclip(ent); break; case MOVETYPE_STEP: SV_Physics_Step(ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: // RAFAEL case MOVETYPE_WALLBOUNCE: SV_Physics_Toss(ent); break; default: gi.error("SV_Physics: bad movetype %i", (int)ent->movetype); } }
/* ================ G_RunEntity ================ */ void G_RunEntity (edict_t * ent) { if (ent->prethink) ent->prethink (ent); switch ((int) ent->movetype) { case MOVETYPE_PUSH: case MOVETYPE_STOP: SV_Physics_Pusher (ent); break; case MOVETYPE_NONE: SV_Physics_None (ent); break; case MOVETYPE_NOCLIP: SV_Physics_Noclip (ent); break; case MOVETYPE_STEP: SV_Physics_Step (ent); break; case MOVETYPE_BOUNCE: SV_Physics_Bounce (ent); // provided by siris break; case MOVETYPE_TOSS: case MOVETYPE_FLY: // zucc added for blood splatting case MOVETYPE_BLOOD: // zucc case MOVETYPE_FLYMISSILE: SV_Physics_Toss (ent); break; default: gi.error ("SV_Physics: bad movetype %i", (int) ent->movetype); } }
/* ================ SV_Physics_Client Player character actions ================ */ void SV_Physics_Client (edict_t *ent, int num) { if ( ! svs.clients[num-1].active ) return; // unconnected slot // // call standard client pre-think // pr_global_struct->time = sv.time; pr_global_struct->self = ((int)EDICT_TO_PROG(ent)); PR_ExecuteProgram (pr_global_struct->PlayerPreThink); // // do a move // SV_CheckVelocity (ent); // // decide which move function to call // switch ((int)ent->v.movetype) { case MOVETYPE_NONE: if (!SV_RunThink (ent)) return; break; case MOVETYPE_WALK: if (!SV_RunThink (ent)) return; if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) SV_AddGravity (ent); SV_CheckStuck (ent); #ifdef QUAKE2 VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); #endif SV_WalkMove (ent); #ifdef QUAKE2 VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity); #endif break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: SV_Physics_Toss (ent); break; case MOVETYPE_FLY: if (!SV_RunThink (ent)) return; SV_FlyMove (ent, host_frametime, NULL); break; case MOVETYPE_NOCLIP: if (!SV_RunThink (ent)) return; VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); break; default: Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype); } // // call standard player post-think // SV_LinkEdict (ent, true); pr_global_struct->time = sv.time; pr_global_struct->self = ((int)EDICT_TO_PROG(ent)); PR_ExecuteProgram (pr_global_struct->PlayerPostThink); }
/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ void SV_Physics_Toss (edict_t *ent) { trace_t trace; vec3_t move; float backoff; edict_t *slave; qboolean wasinwater; qboolean isinwater; vec3_t old_origin; // regular thinking SV_RunThink (ent); // if not a team captain, so movement will be handled elsewhere if ( ent->flags & FL_TEAMSLAVE) return; if (ent->velocity[2] > 0) ent->groundentity = NULL; // check for the groundentity going away if (ent->groundentity) if (!ent->groundentity->inuse) ent->groundentity = NULL; // if onground, return without moving if ( ent->groundentity && ent->movetype != MOVETYPE_TOSS_SLIDE ) { // JOSEPH 7-OCT-98 if (ent->fallerflag) { // JOSEPH 22-JAN-99 // If the object just hit the floor if (ent->fallingflag) { ent->fallingflag = 0; if (!strcmp(ent->classname, "props_trashcanA")) { gi.sound (ent, CHAN_AUTO, gi.soundindex ("world/trash2.wav"), 1, ATTN_NORM, 0); } else if (!strcmp(ent->classname, "props_crate")) { gi.sound (ent, CHAN_AUTO, gi.soundindex ("world/crate2.wav"), 1, ATTN_NORM, 0); } } // END JOSEPH // Fix if sitting off center ent->movetype = MOVETYPE_STEP; think_checkedges(ent); } // END JOSEPH return; } VectorCopy (ent->s.origin, old_origin); SV_CheckVelocity (ent); // add gravity if (ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE) SV_AddGravity (ent); // move angles VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); // move origin VectorScale (ent->velocity, FRAMETIME, move); trace = SV_PushEntity (ent, move); if (!ent->inuse) return; if (trace.fraction < 1) { // RAFAEL if (ent->movetype == MOVETYPE_WALLBOUNCE) backoff = 2.0; // RAFAEL ( else ) else if (ent->movetype == MOVETYPE_BOUNCE) backoff = 1.5; // Ridah, testing else if (ent->velocity[2] > -120) backoff = 1; else backoff = 1.3; ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff); // RAFAEL if (ent->movetype == MOVETYPE_WALLBOUNCE) vectoangles (ent->velocity, ent->s.angles); // stop if on ground // RAFAEL if (trace.plane.normal[2] > 0.7 && ent->movetype != MOVETYPE_WALLBOUNCE && ent->movetype != MOVETYPE_TOSS_SLIDE) // Ridah, testing { if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE ) { ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; VectorCopy (vec3_origin, ent->velocity); VectorCopy (vec3_origin, ent->avelocity); } } // Ridah, testing if (trace.plane.normal[2] > 0.0 && ent->movetype == MOVETYPE_TOSS_SLIDE) // Ridah, testing { VectorMA( ent->velocity, -0.07, ent->velocity, ent->velocity ); // add some friction ent->velocity[2] += ent->gravity * sv_gravity->value * FRAMETIME * trace.plane.normal[2]; if (trace.fraction <= 0.1) { float oldpitch; oldpitch = ent->s.angles[PITCH]; vectoangles (ent->velocity, ent->s.angles); ent->s.angles[PITCH] = oldpitch; VectorCopy (vec3_origin, ent->avelocity); ent->avelocity[PITCH] = -300 * VectorLength(ent->velocity)/800; // roll in direction we're going SV_Physics_Toss(ent); return; } } // if (ent->touch) // ent->touch (ent, trace.ent, &trace.plane, trace.surface); } // check for water transition wasinwater = (ent->watertype & MASK_WATER); ent->watertype = gi.pointcontents (ent->s.origin); isinwater = ent->watertype & MASK_WATER; if (isinwater) ent->waterlevel = 1; else ent->waterlevel = 0; // JOSEPH 13-MAY-99 /*if (!wasinwater && isinwater) gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); else if (wasinwater && !isinwater) gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);*/ // END JOSEPH // move teamslaves for (slave = ent->teamchain; slave; slave = slave->teamchain) { VectorCopy (ent->s.origin, slave->s.origin); gi.linkentity (slave); } }
/* ================ SV_Physics ================ */ void SV_Physics (void) { int i; edict_t *ent; // 2000-04-30 NVS HANDSHAKE SRV<->CL/QC<->CL by Maddes start eval_t *val; // let the QuakeC code know the NVS versions of the server and clients if (pr_field_nvs_svc) { // set world/server // 2001-11-15 Better GetEdictFieldValue performance by LordHavoc/Maddes start // val = GetEdictFieldValue(sv.edicts, "nvs_svc"); val = GETEDICTFIELDVALUE(sv.edicts, pr_field_nvs_svc); // 2001-11-15 Better GetEdictFieldValue performance by LordHavoc/Maddes end if (val) { val->_float = nvs_current_ssvc->value; } // set clients ent = NEXT_EDICT(sv.edicts); // set to first not-world entity (=1st client) for (i=1 ; i<=svs.maxclients && i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) { if (ent->free) continue; if (!svs.clients[i-1].active) continue; // unconnected slot // 2001-11-15 Better GetEdictFieldValue performance by LordHavoc/Maddes start // val = GetEdictFieldValue(ent, "nvs_svc"); val = GETEDICTFIELDVALUE(ent, pr_field_nvs_svc); // 2001-11-15 Better GetEdictFieldValue performance by LordHavoc/Maddes end if (val) { val->_float = svs.clients[i-1].nvs_csvc; } } } // 2000-04-30 NVS HANDSHAKE SRV<->CL/QC<->CL by Maddes end // let the progs know that a new frame has started pr_global_struct->self = EDICT_TO_PROG(sv.edicts); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); pr_global_struct->time = sv.time; PR_ExecuteProgram (pr_global_struct->StartFrame); //SV_CheckAllEnts (); // // treat each object in turn // ent = sv.edicts; for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) { if (ent->free) continue; if (pr_global_struct->force_retouch) { SV_LinkEdict (ent, true); // force retouch even for stationary } if (i > 0 && i <= svs.maxclients) SV_Physics_Client (ent, i); else if (ent->v.movetype == MOVETYPE_PUSH) SV_Physics_Pusher (ent); else if (ent->v.movetype == MOVETYPE_NONE) SV_Physics_None (ent); else if (ent->v.movetype == MOVETYPE_FOLLOW) SV_Physics_Follow (ent); else if (ent->v.movetype == MOVETYPE_NOCLIP) SV_Physics_Noclip (ent); else if (ent->v.movetype == MOVETYPE_STEP) SV_Physics_Step (ent); else if (ent->v.movetype == MOVETYPE_TOSS || ent->v.movetype == MOVETYPE_BOUNCE || ent->v.movetype == MOVETYPE_BOUNCEMISSILE || ent->v.movetype == MOVETYPE_FLY || ent->v.movetype == MOVETYPE_FLYMISSILE) SV_Physics_Toss (ent); else Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); } // 2000-01-02 EndFrame function by Maddes/FrikaC start if (pr_func_endframe) { // let the progs know that a new frame has ended pr_global_struct->self = EDICT_TO_PROG(sv.edicts); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); pr_global_struct->time = sv.time; PR_ExecuteProgram (pr_func_endframe); } // 2000-01-02 EndFrame function by Maddes/FrikaC end if (pr_global_struct->force_retouch) pr_global_struct->force_retouch--; sv.time += host_frametime; }
/* ================ SV_Physics ================ */ void SV_Physics (void) { int i; edict_t *ent; // let the progs know that a new frame has started #ifdef HEXEN2_SUPPORT edict_t *ent2; vec3_t oldOrigin, oldAngle; int originMoved, c; #endif PR_GLOBAL(self) = EDICT_TO_PROG(sv.edicts); PR_GLOBAL(other) = EDICT_TO_PROG(sv.edicts); PR_GLOBAL(time) = sv.time; PR_ExecuteProgram (PR_GLOBAL(StartFrame)); //SV_CheckAllEnts (); // treat each object in turn ent = sv.edicts; for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) { if (ent->free) continue; #ifndef RQM_SV_ONLY if (!isDedicated && ((i+1) % 100 == 0)) S_ExtraUpdateTime (); // BJP: Improve sound when many entities #endif #ifdef HEXEN2_SUPPORT if (hexen2) { ent2 = PROG_TO_EDICT (ent->v.movechain); if (ent2 != sv.edicts) { VectorCopy (ent->v.origin, oldOrigin); VectorCopy (ent->v.angles, oldAngle); } } #endif if (pr_global_ptrs.force_retouch && *pr_global_ptrs.force_retouch) SV_LinkEdict (ent, true); // force retouch even for stationary if (i > 0 && i <= svs.maxclients) SV_Physics_Client (ent, i); else if (ent->v.movetype == MOVETYPE_PUSH) SV_Physics_Pusher (ent); else if (ent->v.movetype == MOVETYPE_NONE) SV_Physics_None (ent); else if (ent->v.movetype == MOVETYPE_NOCLIP) SV_Physics_Noclip (ent); else if (ent->v.movetype == MOVETYPE_STEP) SV_Physics_Step (ent); #ifdef HEXEN2_SUPPORT else if ((hexen2) && (ent->v.movetype == MOVETYPE_PUSHPULL)) SV_Physics_Step (ent); #endif else if (ent->v.movetype == MOVETYPE_TOSS || ent->v.movetype == MOVETYPE_BOUNCE #ifdef HEXEN2_SUPPORT || ((hexen2) && ((ent->v.movetype == MOVETYPE_BOUNCEMISSILE) || (ent->v.movetype == MOVETYPE_SWIM))) #endif || ent->v.movetype == MOVETYPE_FLY || ent->v.movetype == MOVETYPE_FLYMISSILE) SV_Physics_Toss (ent); else Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); #ifdef HEXEN2_SUPPORT if ((hexen2) && (ent2 != sv.edicts)) { originMoved = !VectorCompare(ent->v.origin, oldOrigin); if (originMoved || !VectorCompare(ent->v.angles, oldAngle)) { VectorSubtract(ent->v.origin, oldOrigin, oldOrigin); VectorSubtract(ent->v.angles, oldAngle, oldAngle); for (c=0; c<10; c++) { // chain a max of 10 objects if (ent2->free) break; VectorAdd(oldOrigin, ent2->v.origin, ent2->v.origin); if ((int) ent2->v.flags & FL_MOVECHAIN_ANGLE) { VectorAdd(oldAngle, ent2->v.angles, ent2->v.angles); } if (originMoved && ent2->v.chainmoved) { // callback function *pr_global_ptrs.self = EDICT_TO_PROG(ent2); *pr_global_ptrs.other = EDICT_TO_PROG(ent); PR_ExecuteProgram(ent2->v.chainmoved); } ent2 = PROG_TO_EDICT( ent2->v.movechain ); if (ent2 == sv.edicts) break; } } } #endif } if (pr_global_ptrs.force_retouch && *pr_global_ptrs.force_retouch) PR_GLOBAL(force_retouch)--; sv.time += host_frametime; }
/* ================ SV_Physics_Client Player character actions ================ */ void SV_Physics_Client (edict_t *ent, int num) { client_t *cl; vec3_t v; qboolean was_angle_set; cl = &svs.clients[num-1]; if (!cl->active) return; // unconnected slot // call standard client pre-think PR_GLOBAL(time) = sv.time; PR_GLOBAL(self) = EDICT_TO_PROG(ent); PR_ExecuteProgram (PR_GLOBAL(PlayerPreThink)); // for cutscene hack (see below) if (isDedicated || (num != 1)) was_angle_set = false; // do it on local client only else was_angle_set = (ent->v.fixangle != 0); // do a move SV_CheckVelocity (ent); // decide which move function to call switch ((int)ent->v.movetype) { case MOVETYPE_NONE: if (!SV_RunThink(ent)) return; break; case MOVETYPE_WALK: if (!SV_RunThink(ent)) return; if (!SV_CheckWater(ent) && !((int)ent->v.flags & FL_WATERJUMP)) SV_AddGravity (ent); SV_CheckStuck (ent); SV_WalkMove (ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: SV_Physics_Toss (ent); break; case MOVETYPE_FLY: #ifdef HEXEN2_SUPPORT case MOVETYPE_SWIM: #endif if (!SV_RunThink(ent)) return; SV_FlyMove (ent, host_frametime, NULL); break; case MOVETYPE_NOCLIP: if (!SV_RunThink(ent)) return; VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); break; default: Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype); } // JDH: hack for cutscenes made by Darin McNeil's Cutscene Construction Kit: // (note that the extra precision is noticeable only if the viewangles // are sent from server to client as 2-byte values; hence the addition // of the new svc_setpreciseangle message code) if (was_angle_set && (ent->v.view_ofs[2] == 0) && host_cutscenehack.value && !strcmp (pr_strings + ent->v.classname, "camera")) { // - when camera changes back to player, classname remains "camera" for // 1 frame, but movedir is no longer valid. So as an additional check, // I verify that view_ofs[2] is still 0 // - early version(s?) of Cutscene Construction Kit don't move the camera, // so movedir is not used. I determine the version by checking *when* // the viewangle is set: early version does it in the .think function; // later ones in PlayerPreThink. was_angle_set will be true only if // it was changed in PlayerPreThink //if (!sv_oldprotocol.value) { v[0] = ent->v.movedir[0] - ent->v.origin[0]; v[1] = ent->v.movedir[1] - ent->v.origin[1]; v[2] = ent->v.origin[2] - ent->v.movedir[2]; //vectoangles (v, ent->v.angles); vectoangles (v, cl->cutscene_viewangles); } if (!cl->in_cutscene) { int i; edict_t *ed; // by this time, the player's viewangles have already been changed. // But the dummy entity spawned in place of the player has the values for (i = 1 ; i < sv.num_edicts ; i++) { // get the current server version ed = EDICT_NUM(i); if (ed->free) continue; if (!strcmp(pr_strings + ed->v.classname, "dummy")) { VectorCopy (ed->v.angles, cl->prev_viewangles); break; } } cl->in_cutscene = true; } //sv.found_cutscene = true; } else { if (cl->in_cutscene) { // I'm not sure why, but last viewangle while in_cutscene isn't final angle ent->v.fixangle = 1; VectorCopy (cl->prev_viewangles, ent->v.angles); cl->in_cutscene = false; } } SV_LinkEdict (ent, true); PR_GLOBAL(time) = sv.time; PR_GLOBAL(self) = EDICT_TO_PROG(ent); // JDH: another hack, this time for progs that lack CycleWeaponReverse if ((ent->v.impulse == 12.0) && ((sv_imp12hack.value >= 2) || (sv_imp12hack.value && !pr_handles_imp12)) && !ent->v.deadflag && (ent->v.view_ofs[0] || ent->v.view_ofs[1] || ent->v.view_ofs[2])) { eval_t *val = GETEDICTFIELD(ent, eval_attack_finished); if (val && (sv.time >= val->_float)) { SV_CycleWeaponReverse (ent); } } // call standard player post-think PR_ExecuteProgram (PR_GLOBAL(PlayerPostThink)); }
/* ================ SV_Physics ================ */ void SV_Physics (void) { int i; int entity_cap; // For sv_freezenonclients edict_t *ent; // let the progs know that a new frame has started pr_global_struct->self = EDICT_TO_PROG(sv.edicts); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); pr_global_struct->time = sv.time; PR_ExecuteProgram (pr_global_struct->StartFrame); //SV_CheckAllEnts (); // // treat each object in turn // ent = sv.edicts; if (sv.frozen) entity_cap = svs.maxclients + 1; // Only run physics on clients and the world else entity_cap = sv.num_edicts; for (i=0 ; i<entity_cap ; i++, ent = NEXT_EDICT(ent)) // for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) { if (ent->free) continue; if (pr_global_struct->force_retouch) { SV_LinkEdict (ent, true); // force retouch even for stationary } if (i > 0 && i <= svs.maxclients) SV_Physics_Client (ent, i); else if (ent->v.movetype == MOVETYPE_PUSH) SV_Physics_Pusher (ent); else if (ent->v.movetype == MOVETYPE_NONE) SV_Physics_None (ent); else if (ent->v.movetype == MOVETYPE_FOLLOW) // Nehahra SV_Physics_Follow (ent); else if (ent->v.movetype == MOVETYPE_NOCLIP) SV_Physics_Noclip (ent); else if (ent->v.movetype == MOVETYPE_STEP) SV_Physics_Step (ent); else if (ent->v.movetype == MOVETYPE_WALK) // Nehahra { if (!SV_RunThink (ent)) return; if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) SV_AddGravity (ent); SV_CheckStuck (ent); SV_WalkMove (ent); } else if (ent->v.movetype == MOVETYPE_TOSS || ent->v.movetype == MOVETYPE_BOUNCE || ent->v.movetype == MOVETYPE_FLY || ent->v.movetype == MOVETYPE_FLYMISSILE) SV_Physics_Toss (ent); else Host_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype); } if (pr_global_struct->force_retouch) pr_global_struct->force_retouch--; if (!sv.frozen) sv.time += host_frametime; }
/* ================ SV_Physics_Client Player character actions ================ */ void SV_Physics_Client (edict_t *ent, int num) { if ( ! svs.clients[num-1].active ) return; // unconnected slot // // call standard client pre-think // pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(ent); PR_ExecuteProgram (pr_global_struct->PlayerPreThink); // // do a move // SV_CheckVelocity (ent); // // decide which move function to call // switch ((int)ent->v.movetype) { case MOVETYPE_NONE: if (!SV_RunThink (ent)) return; break; case MOVETYPE_WALK: if (!SV_RunThink (ent)) return; if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) SV_AddGravity (ent); SV_CheckStuck (ent); SV_WalkMove (ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: SV_Physics_Toss (ent); break; case MOVETYPE_FLY: if (!SV_RunThink (ent)) return; SV_CheckWater (ent); SV_FlyMove (ent, host_frametime, NULL); break; case MOVETYPE_NOCLIP: if (!SV_RunThink (ent)) return; ent->v.waterlevel = 0; // Avoid annoying waterjumps in noclip ent->v.watertype = CONTENTS_EMPTY; // Avoid annoying waterjumps in noclip VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); break; default: Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype); } // // call standard player post-think // if (ent->v.movetype == MOVETYPE_NOCLIP) SV_LinkEdict (ent, false); // don't touch triggers in noclip else SV_LinkEdict (ent, true); pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(ent); PR_ExecuteProgram (pr_global_struct->PlayerPostThink); }