ServerEntity_t *Server_FindRadius(MathVector3f_t origin, float radius) { int i,j; ServerEntity_t *eEntity, *eChain; MathVector3f_t eorg; eChain = sv.edicts; eEntity = NEXT_EDICT(sv.edicts); for(i = 1; i < sv.num_edicts; i++,eEntity = NEXT_EDICT(eEntity)) { if(eEntity->free && eEntity->Physics.iSolid == SOLID_NOT) continue; for(j = 0; j < 3; j++) eorg[j] = origin[j]-(eEntity->v.origin[j]+(eEntity->v.mins[j]+eEntity->v.maxs[j])*0.5f); if(Math_Length(eorg) > radius) continue; eEntity->v.chain = eChain; eChain = eEntity; } return eChain; }
/* ** SV_RunNQNewmis ** ** sv_player will be valid */ void SV_RunNQNewmis (void) { edict_t *ent; double save_frametime; int i, pl; pl = EDICT_TO_PROG(sv_player); ent = NEXT_EDICT(sv.edicts); for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) { if (!ent->inuse) continue; if (ent->lastruntime || ent->v.owner != pl) continue; if (ent->v.movetype != MOVETYPE_FLY && ent->v.movetype != MOVETYPE_FLYMISSILE && ent->v.movetype != MOVETYPE_BOUNCE) continue; if (ent->v.solid != SOLID_BBOX && ent->v.solid != SOLID_TRIGGER) continue; save_frametime = sv_frametime; sv_frametime = 0.05; SV_RunEntity (ent); sv_frametime = save_frametime; return; } }
static void AddAllEntsToPmove (void) { int e; edict_t *check; int i; physent_t *pe; int pl; pl = EDICT_TO_PROG(sv_player); check = NEXT_EDICT(sv.edicts); for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.owner == pl) continue; if (check->v.solid == SOLID_BSP || check->v.solid == SOLID_BBOX || check->v.solid == SOLID_SLIDEBOX) { if (check == sv_player) continue; for (i = 0; i < 3; i++) { if (check->v.absmin[i] > pmove_maxs[i] || check->v.absmax[i] < pmove_mins[i]) break; } if (i != 3) continue; pe = &pmove.physents[pmove.numphysent]; VectorCopy (check->v.origin, pe->origin); VectorCopy (check->v.angles, pe->angles); pmove.physents[pmove.numphysent].info = e; if (check->v.solid == SOLID_BSP) pe->model = sv.models[(int)(check->v.modelindex)]; else { pe->model = NULL; VectorCopy (check->v.mins, pe->mins); VectorCopy (check->v.maxs, pe->maxs); } if (++pmove.numphysent == MAX_PHYSENTS) break; } } }
/* ================ R_ShowBoundingBoxes -- johnfitz draw bounding boxes -- the server-side boxes, not the renderer cullboxes ================ */ void R_ShowBoundingBoxes (void) { extern edict_t *sv_player; vec3_t mins,maxs; edict_t *ed; int i; if (!r_showbboxes.value || cl.maxclients > 1 || !r_drawentities.value || !sv.active) return; glDisable (GL_DEPTH_TEST); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); GL_PolygonOffset (OFFSET_SHOWTRIS); glDisable (GL_TEXTURE_2D); glDisable (GL_CULL_FACE); glColor3f (1,1,1); for (i=0, ed=NEXT_EDICT(sv.edicts) ; i<sv.num_edicts ; i++, ed=NEXT_EDICT(ed)) { if (ed == sv_player) continue; //don't draw player's own bbox // if (r_showbboxes.value != 2) // if (!SV_VisibleToClient (sv_player, ed, sv.worldmodel)) // continue; //don't draw if not in pvs if (ed->v.mins[0] == ed->v.maxs[0] && ed->v.mins[1] == ed->v.maxs[1] && ed->v.mins[2] == ed->v.maxs[2]) { //point entity R_EmitWirePoint (ed->v.origin); } else { //box entity VectorAdd (ed->v.mins, ed->v.origin, mins); VectorAdd (ed->v.maxs, ed->v.origin, maxs); R_EmitWireBox (mins, maxs); } } glColor3f (1,1,1); glEnable (GL_TEXTURE_2D); glEnable (GL_CULL_FACE); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); GL_PolygonOffset (OFFSET_NONE); glEnable (GL_DEPTH_TEST); Sbar_Changed (); //so we don't get dots collecting on the statusbar }
/* ================ 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_CheckAllEnts ================ */ void SV_CheckAllEnts(void) { int e; edict_t *check; // see if any solid entities are inside the final position check = NEXT_EDICT(sv.edicts); for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) continue; if (SV_TestEntityPosition(check)) Con_Printf("entity in invalid position\n"); } }
/* ================ SV_Physics ================ */ void SV_Physics (void) { int i; edict_t *ent; if (sv.state != ss_game) return; if (sv.old_time) { // don't bother running a frame if sv_mintic seconds haven't passed sv_frametime = sv.time - sv.old_time; if (sv_frametime < sv_mintic.value) return; if (sv_frametime > sv_maxtic.value) sv_frametime = sv_maxtic.value; sv.old_time = sv.time; } else sv_frametime = 0.1; // initialization frame if (pr_nqprogs) NQP_Reset (); PR_GLOBAL(frametime) = sv_frametime; SV_ProgStartFrame (); // // treat each object in turn // even the world gets a chance to think // ent = sv.edicts; for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) { if (!ent->inuse) continue; if (PR_GLOBAL(force_retouch)) SV_LinkEdict (ent, true); // force retouch even for stationary if (i > 0 && i <= MAX_CLIENTS) continue; // clients are run directly from packets SV_RunEntity (ent); SV_RunNewmis (); } if (PR_GLOBAL(force_retouch)) PR_GLOBAL(force_retouch)--; SV_RunBots (); }
/* draw bounding boxes -- the server-side boxes, not the renderer cullboxes */ void Video_ShowBoundingBoxes(void) { extern ServerEntity_t *sv_player; MathVector3f_t mins, maxs; ClientEntity_t *clEntity; ServerEntity_t *ed; int i; if (!r_showbboxes.value || (cl.maxclients > 1) || !r_drawentities.value || (!sv.active && !g_state.embedded)) return; VideoLayer_Disable(VIDEO_DEPTH_TEST | VIDEO_TEXTURE_2D); VideoLayer_Enable(VIDEO_BLEND); for (i=0, ed=NEXT_EDICT(sv.edicts) ; i<sv.num_edicts ; i++, ed=NEXT_EDICT(ed)) { if(ed == sv_player && !chase_active.value) continue; glColor3f(1,1,1); R_EmitWirePoint (ed->v.origin); Math_VectorAdd(ed->v.mins,ed->v.origin,mins); Math_VectorAdd(ed->v.maxs,ed->v.origin,maxs); glColor4f(0, 0.5f, 0, 0.5f); R_EmitWireBox(mins,maxs, 1, 1, 1); } // Cycle through client-side entities. for (i = 0, clEntity = cl_entities; i < cl.num_entities; i++, clEntity++) Video_DrawClientBoundingBox(clEntity); for (i = 0, clEntity = cl_temp_entities; i < cl_numvisedicts; i++, clEntity++) Video_DrawClientBoundingBox(clEntity); VideoLayer_Disable(VIDEO_BLEND); VideoLayer_Enable(VIDEO_TEXTURE_2D | VIDEO_DEPTH_TEST); }
/* ================ SV_Physics ================ */ void SV_Physics (void) { int i; edict_t *ent; static double old_time; // don't bother running a frame if sys_ticrate seconds haven't passed host_frametime = realtime - old_time; if (host_frametime < sv_mintic.value) return; if (host_frametime > sv_maxtic.value) host_frametime = sv_maxtic.value; old_time = realtime; pr_global_struct->frametime = host_frametime; SV_ProgStartFrame (); // // treat each object in turn // even the world gets a chance to think // 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 <= MAX_CLIENTS) continue; // clients are run directly from packets SV_RunEntity (ent); SV_RunNewmis (); } if (pr_global_struct->force_retouch) pr_global_struct->force_retouch--; }
/* ============ SV_Push ============ */ qboolean SV_Push (edict_t *pusher, vec3_t move) { int i, e; edict_t *check, *block; vec3_t mins, maxs; vec3_t pushorig; int num_moved; edict_t *moved_edict[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS]; for (i=0 ; i<3 ; i++) { mins[i] = pusher->v.absmin[i] + move[i]; maxs[i] = pusher->v.absmax[i] + move[i]; } VectorCopy (pusher->v.origin, pushorig); // move the pusher to it's final position VectorAdd (pusher->v.origin, move, pusher->v.origin); SV_LinkEdict (pusher, false); // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) continue; pusher->v.solid = SOLID_NOT; block = SV_TestEntityPosition (check); pusher->v.solid = SOLID_BSP; if (block) continue; // if the entity is standing on the pusher, it will definately be moved if ( ! ( ((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher) ) { if ( check->v.absmin[0] >= maxs[0] || check->v.absmin[1] >= maxs[1] || check->v.absmin[2] >= maxs[2] || check->v.absmax[0] <= mins[0] || check->v.absmax[1] <= mins[1] || check->v.absmax[2] <= mins[2] ) continue; // see if the ent's bbox is inside the pusher's final position if (!SV_TestEntityPosition (check)) continue; } VectorCopy (check->v.origin, moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // try moving the contacted entity VectorAdd (check->v.origin, move, check->v.origin); block = SV_TestEntityPosition (check); if (!block) { // pushed ok SV_LinkEdict (check, false); continue; } // if it is ok to leave in the old position, do it VectorSubtract (check->v.origin, move, check->v.origin); block = SV_TestEntityPosition (check); if (!block) { num_moved--; continue; } // if it is still inside the pusher, block if (check->v.mins[0] == check->v.maxs[0]) { SV_LinkEdict (check, false); continue; } if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; VectorCopy (check->v.mins, check->v.maxs); SV_LinkEdict (check, false); continue; } VectorCopy (pushorig, pusher->v.origin); SV_LinkEdict (pusher, false); // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (pusher->v.blocked) { pr_global_struct->self = EDICT_TO_PROG(pusher); pr_global_struct->other = EDICT_TO_PROG(check); PR_ExecuteProgram (pusher->v.blocked); } // move back any entities we already moved for (i=0 ; i<num_moved ; i++) { VectorCopy (moved_from[i], moved_edict[i]->v.origin); SV_LinkEdict (moved_edict[i], false); } return false; } return true; }
// [18/5/2013] TODO: Merge with SV_PushMove ~hogsy static void Server_PushRotate(edict_t *pusher,float movetime) { int i,e,num_moved,slaves_moved; edict_t *check,*block,*moved_edict[MAX_EDICTS],*ground,*slave,*master; vec3_t move,a,amove,entorig,pushorig,moved_from[MAX_EDICTS],org,org2,forward,right,up; bool bMoveIt; for (i = 0; i < 3; i++) amove[i] = pusher->v.avelocity[i] * movetime; Math_VectorNegate(amove,a); Math_AngleVectors(a,forward,right,up); Math_VectorCopy(pusher->v.angles,pushorig); // move the pusher to it's final position Math_VectorAdd(pusher->v.angles,amove,pusher->v.angles); pusher->v.ltime += movetime; SV_LinkEdict (pusher, false); slaves_moved = 0; master = pusher; while(master->v.aiment) { slave = PROG_TO_EDICT(master->v.aiment); slaves_moved++; Math_VectorCopy (slave->v.angles, moved_from[MAX_EDICTS - slaves_moved]); moved_edict[MAX_EDICTS - slaves_moved] = slave; if (slave->v.movedir[PITCH]) slave->v.angles[PITCH] = master->v.angles[PITCH]; else slave->v.angles[PITCH] += slave->v.avelocity[PITCH] * movetime; if (slave->v.movedir[YAW]) slave->v.angles[YAW] = master->v.angles[YAW]; else slave->v.angles[YAW] += slave->v.avelocity[YAW] * movetime; if (slave->v.movedir[ROLL]) slave->v.angles[ROLL] = master->v.angles[ROLL]; else slave->v.angles[ROLL] += slave->v.avelocity[ROLL] * movetime; slave->v.ltime = master->v.ltime; SV_LinkEdict(slave,false); master = slave; } // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definitely be moved bMoveIt = false; ground = check->v.groundentity; if(check->v.flags & FL_ONGROUND) { if (ground == pusher) bMoveIt = true; else { for (i = 0; i < slaves_moved; i++) { if (ground == moved_edict[MAX_EDICTS - i - 1]) { bMoveIt = true; break; } } } } if(!bMoveIt) { if( check->v.absmin[0] >= pusher->v.absmax[0] || check->v.absmin[1] >= pusher->v.absmax[1] || check->v.absmin[2] >= pusher->v.absmax[2] || check->v.absmax[0] <= pusher->v.absmin[0] || check->v.absmax[1] <= pusher->v.absmin[1] || check->v.absmax[2] <= pusher->v.absmin[2]) { for (i = 0; i < slaves_moved; i++) { slave = moved_edict[MAX_EDICTS-i-1]; if( check->v.absmin[0] >= slave->v.absmax[0] || check->v.absmin[1] >= slave->v.absmax[1] || check->v.absmin[2] >= slave->v.absmax[2] || check->v.absmax[0] <= slave->v.absmin[0] || check->v.absmax[1] <= slave->v.absmin[1] || check->v.absmax[2] <= slave->v.absmin[2] ) continue; } if (i == slaves_moved) continue; } // See if the ent's bbox is inside the pusher's final position if(!SV_TestEntityPosition(check)) continue; } // remove the onground flag for non-players if(check->v.movetype != MOVETYPE_WALK) check->v.flags = check->v.flags & ~FL_ONGROUND; Math_VectorCopy(check->v.origin,entorig); Math_VectorCopy(check->v.origin,moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // calculate destination position Math_VectorSubtract(check->v.origin,pusher->v.origin,org); org2[0] = Math_DotProduct(org,forward); org2[1] = -Math_DotProduct(org,right); org2[2] = Math_DotProduct(org,up); Math_VectorSubtract (org2,org,move); // try moving the contacted entity pusher->Physics.iSolid = SOLID_NOT; SV_PushEntity (check, move); //@@TODO: do we ever want to do anybody's angles? maybe just yaw??? if(check->monster.iType != 1) { #if 0 vec3_t vYaw; vYaw[YAW] = Math_AngleMod(pusher->v.angles[YAW]+check->v.angles[YAW]); Con_Printf("%i %i\n",(int)check->v.angles[YAW],(int)vYaw[YAW]); //check->v.angles[YAW] = vYaw[YAW]; //check->v.angles[YAW] = Math_AngleMod(vYaw[YAW]); #endif // move back any entities we already moved for (i = 0; i < num_moved; i++) { Math_VectorAdd(moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); moved_edict[i]->v.angles[YAW] += amove[YAW]/2.0f; SV_LinkEdict(moved_edict[i],false); } } pusher->Physics.iSolid = SOLID_BSP; // If it is still inside the pusher, block block = SV_TestEntityPosition (check); if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->Physics.iSolid == SOLID_NOT || check->Physics.iSolid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; Math_VectorCopy(check->v.mins,check->v.maxs); continue; } Math_VectorCopy(entorig,check->v.origin); SV_LinkEdict(check,true); Math_VectorCopy(pushorig,pusher->v.angles); SV_LinkEdict(pusher,false); pusher->v.ltime -= movetime; for(i = 0; i < slaves_moved; i++) { slave = moved_edict[MAX_EDICTS - i - 1]; Math_VectorCopy(moved_from[MAX_EDICTS - i - 1], slave->v.angles); SV_LinkEdict(slave,false); slave->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) pusher->v.blocked(pusher,check); // move back any entities we already moved for (i = 0; i < num_moved; i++) { Math_VectorCopy (moved_from[i], moved_edict[i]->v.origin); //@@TODO:: see above // if (!((int)moved_edict[i]->v.flags & (FL_CLIENT | FL_MONSTER))) Math_VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); moved_edict[i]->v.angles[YAW] -= amove[YAW]; SV_LinkEdict(moved_edict[i],false); } return; } } }
void SV_PushMove (edict_t *pusher, float movetime) { int i, e; edict_t *check, *block; vec3_t mins, maxs, move; vec3_t entorig, pushorig; int num_moved; edict_t **moved_edict; //johnfitz -- dynamically allocate vec3_t *moved_from; //johnfitz -- dynamically allocate int mark; //johnfitz if(!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) { pusher->v.ltime += movetime; return; } for (i=0 ; i<3 ; i++) { move[i] = pusher->v.velocity[i] * movetime; mins[i] = pusher->v.absmin[i] + move[i]; maxs[i] = pusher->v.absmax[i] + move[i]; } Math_VectorCopy (pusher->v.origin, pushorig); // move the pusher to it's final position Math_VectorAdd (pusher->v.origin, move, pusher->v.origin); pusher->v.ltime += movetime; SV_LinkEdict(pusher,false); //johnfitz -- dynamically allocate mark = Hunk_LowMark (); moved_edict = (edict_t**)Hunk_Alloc(sv.num_edicts*sizeof(edict_t*)); moved_from = (vec3_t(*))Hunk_Alloc (sv.num_edicts*sizeof(vec3_t)); //johnfitz // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definately be moved if(!((check->v.flags & FL_ONGROUND) && check->v.groundentity == pusher)) { if ( check->v.absmin[0] >= maxs[0] || check->v.absmin[1] >= maxs[1] || check->v.absmin[2] >= maxs[2] || check->v.absmax[0] <= mins[0] || check->v.absmax[1] <= mins[1] || check->v.absmax[2] <= mins[2] ) continue; // see if the ent's bbox is inside the pusher's final position if (!SV_TestEntityPosition (check)) continue; } // remove the onground flag for non-players if (check->v.movetype != MOVETYPE_WALK) check->v.flags = check->v.flags & ~FL_ONGROUND; Math_VectorCopy(check->v.origin,entorig); Math_VectorCopy(check->v.origin,moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // try moving the contacted entity pusher->Physics.iSolid = SOLID_NOT; SV_PushEntity (check, move); pusher->Physics.iSolid = SOLID_BSP; // if it is still inside the pusher, block block = SV_TestEntityPosition (check); if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->Physics.iSolid == SOLID_NOT || check->Physics.iSolid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; Math_VectorCopy(check->v.mins,check->v.maxs); continue; } Math_VectorCopy(entorig,check->v.origin); SV_LinkEdict(check,true); Math_VectorCopy(pushorig,pusher->v.origin); SV_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) { pr_global_struct.self = EDICT_TO_PROG(pusher); pr_global_struct.eOther = check; pusher->v.blocked(pusher,check); } // move back any entities we already moved for (i=0 ; i<num_moved ; i++) { Math_VectorCopy(moved_from[i],moved_edict[i]->v.origin); SV_LinkEdict (moved_edict[i], false); } Hunk_FreeToLowMark (mark); //johnfitz return; } } Hunk_FreeToLowMark (mark); //johnfitz }
void Physics_ServerFrame(void) { int i; edict_t *eEntity; // Let the progs know that a new frame has started pr_global_struct.self = EDICT_TO_PROG(sv.edicts); pr_global_struct.eOther = sv.edicts; // TODO: should we pass the time to this? ~hogsy Game->Server_StartFrame(); // Treat each object in turn eEntity = sv.edicts; for(i = 0; i < sv.num_edicts; i++,eEntity = NEXT_EDICT(eEntity)) { if(eEntity->free) continue; if(pr_global_struct.force_retouch) SV_LinkEdict(eEntity,true); // Force retouch even for stationary // [11/7/2013] Cleaned this up and gave it its own function ~hogsy Game->Server_EntityFrame(eEntity); if(i > 0 && i <= svs.maxclients) SV_Physics_Client(eEntity,i); else { switch(eEntity->v.movetype) { case MOVETYPE_NONE: Server_RunThink(eEntity); break; case MOVETYPE_PUSH: SV_Physics_Pusher(eEntity); break; case MOVETYPE_NOCLIP: Physics_NoClip(eEntity); break; case MOVETYPE_WALK: case MOVETYPE_STEP: Game->Physics_CheckVelocity(eEntity); Game->Physics_SetGravity(eEntity); Physics_AddFriction(eEntity,eEntity->v.velocity,eEntity->v.origin); SV_WalkMove(eEntity); SV_LinkEdict(eEntity,true); Server_RunThink(eEntity); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: case MOVETYPE_FLYBOUNCE: Physics_Toss(eEntity); break; default: Con_Warning("Bad movetype set for entity! (%s)",eEntity->v.cClassname); } } } if(pr_global_struct.force_retouch) pr_global_struct.force_retouch--; sv.time += host_frametime; }
/* ============ SV_PushMove ============ */ void SV_PushMove (edict_t *pusher, float movetime) { int i, e; edict_t *check, *block; vec3_t mins, maxs, move; vec3_t entorig, pushorig; int num_moved; edict_t *moved_edict[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS]; if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) { pusher->v.ltime += movetime; return; } for (i=0 ; i<3 ; i++) { move[i] = pusher->v.velocity[i] * movetime; mins[i] = pusher->v.absmin[i] + move[i]; maxs[i] = pusher->v.absmax[i] + move[i]; } VectorCopy (pusher->v.origin, pushorig); // move the pusher to it's final position VectorAdd (pusher->v.origin, move, pusher->v.origin); pusher->v.ltime += movetime; SV_LinkEdict (pusher, false); // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_FOLLOW // Nehahra || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definately be moved if ( ! ( ((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher) ) { if ( check->v.absmin[0] >= maxs[0] || check->v.absmin[1] >= maxs[1] || check->v.absmin[2] >= maxs[2] || check->v.absmax[0] <= mins[0] || check->v.absmax[1] <= mins[1] || check->v.absmax[2] <= mins[2] ) continue; // see if the ent's bbox is inside the pusher's final position if (!SV_TestEntityPosition (check)) continue; } // remove the onground flag for non-players if (check->v.movetype != MOVETYPE_WALK) check->v.flags = (int)check->v.flags & ~FL_ONGROUND; VectorCopy (check->v.origin, entorig); VectorCopy (check->v.origin, moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // only check for types that can block if (pusher->v.solid == SOLID_BSP // everything that blocks: bsp models, map brushes, doors, plats etc. || pusher->v.solid == SOLID_BBOX // normally boxes || pusher->v.solid == SOLID_SLIDEBOX) // normally monsters { // store out the previous solid value because we're going to change it next float savepushervsolid = pusher->v.solid; // try moving the contacted entity pusher->v.solid = SOLID_NOT; SV_PushEntity (check, move); // restore from the stored solid pusher->v.solid = savepushervsolid; // if it is still inside the pusher, block block = SV_TestEntityPosition (check); } else { // not blocked block = NULL; } if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; VectorCopy (check->v.mins, check->v.maxs); continue; } VectorCopy (entorig, check->v.origin); SV_LinkEdict (check, true); VectorCopy (pushorig, pusher->v.origin); SV_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) { pr_global_struct->self = EDICT_TO_PROG(pusher); pr_global_struct->other = EDICT_TO_PROG(check); PR_ExecuteProgram (pusher->v.blocked); } // move back any entities we already moved for (i=0 ; i<num_moved ; i++) { VectorCopy (moved_from[i], moved_edict[i]->v.origin); SV_LinkEdict (moved_edict[i], false); } return; } } }
/* ================ 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_PushMove ============ */ void SV_PushMove (edict_t *pusher, float movetime) { int i, e; edict_t *check, *block; vec3_t mins, maxs, move; vec3_t entorig, pushorig; int num_moved; edict_t *moved_edict[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS]; float solid_backup; //movetype_push error fix - Eradicator if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) { pusher->v.ltime += movetime; return; } for (i=0 ; i<3 ; i++) { move[i] = pusher->v.velocity[i] * movetime; mins[i] = pusher->v.absmin[i] + move[i]; maxs[i] = pusher->v.absmax[i] + move[i]; } VectorCopy (pusher->v.origin, pushorig); // move the pusher to it's final position VectorAdd (pusher->v.origin, move, pusher->v.origin); pusher->v.ltime += movetime; SV_LinkEdict (pusher, false); // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE #ifdef QUAKE2 || check->v.movetype == MOVETYPE_FOLLOW #endif || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definately be moved if ( ! ( ((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher) ) { if ( check->v.absmin[0] >= maxs[0] || check->v.absmin[1] >= maxs[1] || check->v.absmin[2] >= maxs[2] || check->v.absmax[0] <= mins[0] || check->v.absmax[1] <= mins[1] || check->v.absmax[2] <= mins[2] ) continue; // see if the ent's bbox is inside the pusher's final position if (!SV_TestEntityPosition (check)) continue; } // remove the onground flag for non-players if (check->v.movetype != MOVETYPE_WALK) check->v.flags = (int)check->v.flags & ~FL_ONGROUND; VectorCopy (check->v.origin, entorig); VectorCopy (check->v.origin, moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; //START - movetype_push error fix - Eradicator solid_backup = pusher->v.solid; if ( solid_backup == SOLID_BSP || solid_backup == SOLID_BBOX || solid_backup == SOLID_SLIDEBOX ) { //END - movetype_push error fix - Eradicator // try moving the contacted entity pusher->v.solid = SOLID_NOT; SV_PushEntity (check, move); //pusher->v.solid = SOLID_BSP; //Old pusher->v.solid = solid_backup; //movetype_push error fix - Eradicator // if it is still inside the pusher, block block = SV_TestEntityPosition (check); } //movetype_push error fix - Eradicator else block = NULL; if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; VectorCopy (check->v.mins, check->v.maxs); continue; } VectorCopy (entorig, check->v.origin); SV_LinkEdict (check, true); VectorCopy (pushorig, pusher->v.origin); SV_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) { pr_global_struct->self = ((int)EDICT_TO_PROG(pusher)); pr_global_struct->other = ((int)EDICT_TO_PROG(check)); PR_ExecuteProgram (pusher->v.blocked); } // move back any entities we already moved for (i=0 ; i<num_moved ; i++) { VectorCopy (moved_from[i], moved_edict[i]->v.origin); SV_LinkEdict (moved_edict[i], false); } return; } } }
/* ============ SV_PushMove ============ */ void SV_PushMove (edict_t *pusher, float movetime) { int i, e; edict_t *check, *block; vec3_t mins, maxs, move; vec3_t entorig, pushorig; int num_moved; // 2001-09-20 Configurable entity limits by Maddes start /* edict_t *moved_edict[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS]; */ // 2001-09-20 Configurable entity limits by Maddes end float solid_backup; // 1999-10-07 MOVETYPE_PUSH fix by LordHavoc/Maddes if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) { pusher->v.ltime += movetime; return; } // 2001-09-20 Configurable entity limits by Maddes start // FIXME: is this really necessary memset (moved_edict, 0, sv.max_edicts*sizeof(edict_t *)); memset (moved_from, 0, sv.max_edicts*sizeof(vec3_t)); // 2001-09-20 Configurable entity limits by Maddes end for (i=0 ; i<3 ; i++) { move[i] = pusher->v.velocity[i] * movetime; mins[i] = pusher->v.absmin[i] + move[i]; maxs[i] = pusher->v.absmax[i] + move[i]; } VectorCopy (pusher->v.origin, pushorig); // move the pusher to it's final position VectorAdd (pusher->v.origin, move, pusher->v.origin); pusher->v.ltime += movetime; SV_LinkEdict (pusher, false); // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_FOLLOW || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definately be moved if ( ! ( ((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher) ) { if ( check->v.absmin[0] >= maxs[0] || check->v.absmin[1] >= maxs[1] || check->v.absmin[2] >= maxs[2] || check->v.absmax[0] <= mins[0] || check->v.absmax[1] <= mins[1] || check->v.absmax[2] <= mins[2] ) continue; // see if the ent's bbox is inside the pusher's final position if (!SV_TestEntityPosition (check)) continue; } // remove the onground flag for non-players if (check->v.movetype != MOVETYPE_WALK) check->v.flags = (int)check->v.flags & ~FL_ONGROUND; VectorCopy (check->v.origin, entorig); VectorCopy (check->v.origin, moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // 1999-10-07 MOVETYPE_PUSH fix by LordHavoc/Maddes start solid_backup = pusher->v.solid; if ( solid_backup == SOLID_BSP // everything that blocks: bsp models==map brushes==doors,plats,etc. || solid_backup == SOLID_BBOX // normally boxes || solid_backup == SOLID_SLIDEBOX ) // normally monsters { // 1999-10-07 MOVETYPE_PUSH fix by LordHavoc/Maddes end // try moving the contacted entity pusher->v.solid = SOLID_NOT; SV_PushEntity (check, move); // 1999-10-07 MOVETYPE_PUSH fix by LordHavoc/Maddes start // pusher->v.solid = SOLID_BSP; pusher->v.solid = solid_backup; // 1999-10-07 MOVETYPE_PUSH fix by LordHavoc/Maddes end // if it is still inside the pusher, block // 1999-10-07 MOVETYPE_PUSH fix by LordHavoc/Maddes start block = SV_TestEntityPosition (check); } else block = NULL; // 1999-10-07 MOVETYPE_PUSH fix by LordHavoc/Maddes end if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; VectorCopy (check->v.mins, check->v.maxs); continue; } VectorCopy (entorig, check->v.origin); SV_LinkEdict (check, true); VectorCopy (pushorig, pusher->v.origin); SV_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) { pr_global_struct->self = EDICT_TO_PROG(pusher); pr_global_struct->other = EDICT_TO_PROG(check); PR_ExecuteProgram (pusher->v.blocked); } // move back any entities we already moved for (i=0 ; i<num_moved ; i++) { VectorCopy (moved_from[i], moved_edict[i]->v.origin); SV_LinkEdict (moved_edict[i], false); } return; } } }
/* ================ 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_PushRotate ============ */ void SV_PushRotate (edict_t *pusher, float movetime) { int i, e, t, num_moved, slaves_moved; edict_t *check, *block, *ground, *master, *slave; edict_t *moved_edict[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS]; vec3_t move, a, amove, mins, maxs, move2, move3, testmove; vec3_t entorig, pushorig, pushorigangles; vec3_t org, org2, check_center; vec3_t forward, right, up; qboolean moveit; for (i=0 ; i<3 ; i++) { amove[i] = pusher->v.avelocity[i] * movetime; move[i] = pusher->v.velocity[i] * movetime; mins[i] = pusher->v.absmin[i] + move[i]; maxs[i] = pusher->v.absmax[i] + move[i]; } VectorSubtract (vec3_origin, amove, a); AngleVectors (a, forward, right, up); VectorCopy (pusher->v.origin, pushorig); VectorCopy (pusher->v.angles, pushorigangles); // move the pusher to it's final position VectorAdd (pusher->v.origin, move, pusher->v.origin); VectorAdd (pusher->v.angles, amove, pusher->v.angles); pusher->v.ltime += movetime; SV_LinkEdict (pusher, false); master = pusher; slaves_moved = 0; // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_FOLLOW || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definitely be moved moveit = false; ground = PROG_TO_EDICT(check->v.groundentity); if ((int)check->v.flags & FL_ONGROUND) { if (ground == pusher) { moveit = true; } else { for (i=0; i<slaves_moved; i++) { if (ground == moved_edict[MAX_EDICTS - i - 1]) { moveit = true; break; } } } } if (!moveit) { if ( check->v.absmin[0] >= maxs[0] || check->v.absmin[1] >= maxs[1] || check->v.absmin[2] >= maxs[2] || check->v.absmax[0] <= mins[0] || check->v.absmax[1] <= mins[1] || check->v.absmax[2] <= mins[2] ) { for (i=0; i<slaves_moved; i++) { slave = moved_edict[MAX_EDICTS - i - 1]; if ( check->v.absmin[0] >= slave->v.absmax[0] || check->v.absmin[1] >= slave->v.absmax[1] || check->v.absmin[2] >= slave->v.absmax[2] || check->v.absmax[0] <= slave->v.absmin[0] || check->v.absmax[1] <= slave->v.absmin[1] || check->v.absmax[2] <= slave->v.absmin[2] ) continue; } if (i == slaves_moved) continue; } // see if the ent's bbox is inside the pusher's final position if (!SV_TestEntityPosition (check)) continue; } // remove the onground flag for non-players if (check->v.movetype != MOVETYPE_WALK) check->v.flags = (int)check->v.flags & ~FL_ONGROUND; VectorCopy (check->v.origin, entorig); VectorCopy (check->v.origin, moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; //put check in first move spot VectorAdd (check->v.origin, move, check->v.origin); //Use center of model, like in QUAKE!!!! Our origins are on the bottom!!! for (i=0 ; i<3 ; i++) check_center[i] = (check->v.absmin[i] + check->v.absmax[i])/2; // calculate destination position VectorSubtract (check_center, pusher->v.origin, org); //put check back VectorSubtract (check->v.origin, move, check->v.origin); org2[0] = DotProduct (org, forward); org2[1] = -DotProduct (org, right); org2[2] = DotProduct (org, up); VectorSubtract (org2, org, move2); //Add all moves together VectorAdd(move,move2,move3); // try moving the contacted entity for( t = 0; t < 13; t++) { switch(t) { case 0: //try x, y and z VectorCopy(move3,testmove); break; case 1: //Try xy only VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=move3[0]; testmove[1]=move3[1]; testmove[2]=0; break; case 2: //Try z only VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=0; testmove[1]=0; testmove[2]=move3[2]; break; case 3: //Try none VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=0; testmove[1]=0; testmove[2]=0; break; case 4: //Try xy in opposite dir testmove[0]=move3[0]*-1; testmove[1]=move3[1]*-1; testmove[2]=move3[2]; break; case 5: //Try z in opposite dir VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=move3[0]; testmove[1]=move3[1]; testmove[2]=move3[2]*-1; break; case 6: //Try xyz in opposite dir VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=move3[0]*-1; testmove[1]=move3[1]*-1; testmove[2]=move3[2]*-1; break; case 7: //Try move3 times 2 VectorSubtract(check->v.origin,testmove,check->v.origin); VectorScale(move3,2,testmove); break; case 8: //Try normalized org VectorSubtract(check->v.origin,testmove,check->v.origin); VectorScale(org,movetime,org);//movetime*20? VectorCopy(org,testmove); break; case 9: //Try normalized org z * 3 only VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=0; testmove[1]=0; testmove[2]=org[2]*3;//was: +org[2]*(fastfabs(org[1])+fastfabs(org[2])); break; case 10: //Try normalized org xy * 2 only VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=org[0]*2;//was: +org[0]*fastfabs(org[2]); testmove[1]=org[1]*2;//was: +org[1]*fastfabs(org[2]); testmove[2]=0; break; case 11: //Try xy in opposite org dir VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=org[0]*-2; testmove[1]=org[1]*-2; testmove[2]=org[2]; break; case 12: //Try z in opposite dir VectorSubtract(check->v.origin,testmove,check->v.origin); testmove[0]=org[0]; testmove[1]=org[1]; testmove[2]=org[2]*-3; break; } if(t!=3) { //THIS IS VERY BAD BAD HACK... pusher->v.solid = SOLID_NOT; SV_PushEntity (check, move3); //@@TODO: do we ever want to do anybody's angles? maybe just yaw??? // if (!((int)check->v.flags & (FL_CLIENT | FL_MONSTER))) // VectorAdd (check->v.angles, amove, check->v.angles); check->v.angles[YAW] += amove[YAW]; pusher->v.solid = SOLID_BSP; } // if it is still inside the pusher, block block = SV_TestEntityPosition (check); if(!block) break; } if (block) { // fail the move // Con_DPrintf("Check blocked\n"); if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; VectorCopy (check->v.mins, check->v.maxs); continue; } VectorCopy (entorig, check->v.origin); SV_LinkEdict (check, true); VectorCopy (pushorig, pusher->v.origin); VectorCopy (pushorigangles, pusher->v.angles); SV_LinkEdict (pusher, false); pusher->v.ltime -= movetime; for (i=0; i<slaves_moved; i++) { slave = moved_edict[MAX_EDICTS - i - 1]; VectorCopy (moved_from[MAX_EDICTS - i - 1], slave->v.angles); SV_LinkEdict (slave, false); slave->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) { *pr_global_ptrs.self = EDICT_TO_PROG(pusher); *pr_global_ptrs.other = EDICT_TO_PROG(check); PR_ExecuteProgram (pusher->v.blocked); } // move back any entities we already moved for (i=0 ; i<num_moved ; i++) { VectorCopy (moved_from[i], moved_edict[i]->v.origin); //@@TODO:: see above // if (!((int)moved_edict[i]->v.flags & (FL_CLIENT | FL_MONSTER))) // VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); moved_edict[i]->v.angles[YAW] -= amove[YAW]; SV_LinkEdict (moved_edict[i], false); } return; } } }
/* ============ SV_PushRotate ============ */ void SV_PushRotate (edict_t *pusher, float movetime) { int i, e; edict_t *check, *block; vec3_t move, a, amove; vec3_t entorig, pushorig; int num_moved; edict_t *moved_edict[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS]; vec3_t org, org2; vec3_t forward, right, up; if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2]) { pusher->v.ltime += movetime; return; } for (i=0 ; i<3 ; i++) amove[i] = pusher->v.avelocity[i] * movetime; VectorSubtract (vec3_origin, amove, a); AngleVectors (a, forward, right, up); VectorCopy (pusher->v.angles, pushorig); // move the pusher to it's final position VectorAdd (pusher->v.angles, amove, pusher->v.angles); pusher->v.ltime += movetime; SV_LinkEdict (pusher, false); // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE #ifdef QUAKE2 || check->v.movetype == MOVETYPE_FOLLOW #endif || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definately be moved if ( ! ( ((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher) ) { if ( check->v.absmin[0] >= pusher->v.absmax[0] || check->v.absmin[1] >= pusher->v.absmax[1] || check->v.absmin[2] >= pusher->v.absmax[2] || check->v.absmax[0] <= pusher->v.absmin[0] || check->v.absmax[1] <= pusher->v.absmin[1] || check->v.absmax[2] <= pusher->v.absmin[2] ) continue; // see if the ent's bbox is inside the pusher's final position if (!SV_TestEntityPosition (check)) continue; } // remove the onground flag for non-players if (check->v.movetype != MOVETYPE_WALK) check->v.flags = (int)check->v.flags & ~FL_ONGROUND; VectorCopy (check->v.origin, entorig); VectorCopy (check->v.origin, moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // calculate destination position VectorSubtract (check->v.origin, pusher->v.origin, org); org2[0] = DotProduct (org, forward); org2[1] = -DotProduct (org, right); org2[2] = DotProduct (org, up); VectorSubtract (org2, org, move); // try moving the contacted entity pusher->v.solid = SOLID_NOT; SV_PushEntity (check, move); pusher->v.solid = SOLID_BSP; // if it is still inside the pusher, block block = SV_TestEntityPosition (check); if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; VectorCopy (check->v.mins, check->v.maxs); continue; } VectorCopy (entorig, check->v.origin); SV_LinkEdict (check, true); VectorCopy (pushorig, pusher->v.angles); SV_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) { pr_global_struct->self = ((int)EDICT_TO_PROG(pusher)); pr_global_struct->other = ((int)EDICT_TO_PROG(check)); PR_ExecuteProgram (pusher->v.blocked); } // move back any entities we already moved for (i=0 ; i<num_moved ; i++) { VectorCopy (moved_from[i], moved_edict[i]->v.origin); VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); SV_LinkEdict (moved_edict[i], false); } return; } else { VectorAdd (check->v.angles, amove, check->v.angles); } } }
/* ================ SV_Physics ================ */ void SV_Physics (void) { int i; static double old_time; byte *ent_global_ptr = (byte *) sv.edicts; DEBUGPRINT(PHYSICS,MEDIUM) printf("GAJA: In Physics parallel\n"); // don't bother running a frame if sys_ticrate seconds haven't passed host_frametime = realtime - old_time; if (host_frametime < sv_mintic.value) return; if (host_frametime > sv_maxtic.value) host_frametime = sv_maxtic.value; old_time = realtime; pr_global_struct->frametime = host_frametime; SV_ProgStartFrame (); // // treat each object in turn // even the world gets a chance to think // if (pr_global_struct->force_retouch) { // GAJA: RUN SERIAL edict_t *ent; ent = sv.edicts; for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent)) { if (ent->free) continue; SV_LinkEdict (ent, true); // force retouch even for stationary if (i > 0 && i <= MAX_CLIENTS) continue; // clients are run directly from packets SV_RunEntity (ent); SV_RunNewmis (); } } else { // GAJA: RUN PARALLEL omp_set_num_threads(NoThreads); #pragma omp parallel for schedule(dynamic,1) private(i) shared(svs, sv, sv_areanodes, pr_global_struct, realtime, movevars) for (i=0 ; i<sv.num_edicts ; i++) { edict_t *ent = (edict_t *) (ent_global_ptr + pr_edict_size * i); if (ent->free || i <= MAX_CLIENTS) continue; DEBUGPRINT(PHYSICS,HIGH) printf("Thread= %d\t\tBefore Transaction\n", omp_get_thread_num()); inTransaction = true; // ~+~+~+~+~+ // StartTransaction LOCK(global_lock) TRANSACTION //if (pr_global_struct->force_retouch) // SV_LinkEdict (ent, true); // force retouch even for stationary //if (i > MAX_CLIENTS) // don't run client entities (clients are run directly from packets) //{ SV_RunEntity (ent); SV_RunNewmis (); //} TRANSACTION_END UNLOCK(global_lock) // EndTransaction inTransaction = false; DEBUGPRINT(PHYSICS,HIGH) printf("Thread= %d\t\tAfter Transaction\n", omp_get_thread_num()); // send messages and packets generated during transaction FlushTMOutput(); } // end for } //end if if (pr_global_struct->force_retouch) pr_global_struct->force_retouch--; }