X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=67578e7b6b7b6a6e5c9aacc7a2f9f05218e937fd;hb=1f112c6b87a77dbefe643479d4066f4c5983ae4a;hp=f85429b4dbed37ac37aa7d138a6ca20dcb1ab1dd;hpb=16742571f9a7d696a654668febdc10b4f4affd57;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index f85429b4..67578e7b 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -102,6 +102,8 @@ int SV_GenericHitSuperContentsMask(const prvm_edict_t *passedict) } else if (passedict->fields.server->solid == SOLID_CORPSE) return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY; + else if (passedict->fields.server->solid == SOLID_TRIGGER) + return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY; else return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE; } @@ -121,7 +123,7 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const #endif { vec3_t hullmins, hullmaxs; - int i; + int i, bodysupercontents; int passedictprog; qboolean pointtrace; prvm_edict_t *traceowner, *touch; @@ -240,6 +242,8 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const continue; } + bodysupercontents = touch->fields.server->solid == SOLID_CORPSE ? SUPERCONTENTS_CORPSE : SUPERCONTENTS_BODY; + // might interact, so do an exact clip model = NULL; if ((int) touch->fields.server->solid == SOLID_BSP || type == MOVE_HITMODEL) @@ -248,15 +252,17 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const // if the modelindex is 0, it shouldn't be SOLID_BSP! if (modelindex > 0 && modelindex < MAX_MODELS) model = sv.models[(int)touch->fields.server->modelindex]; - Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1); } + if (model) + Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1); else Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]); Matrix4x4_Invert_Simple(&imatrix, &matrix); if ((int)touch->fields.server->flags & FL_MONSTER) - Collision_ClipToGenericEntity(&trace, model, touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, SUPERCONTENTS_BODY, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask); + Collision_ClipToGenericEntity(&trace, model, touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask); else - Collision_ClipToGenericEntity(&trace, model, touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, SUPERCONTENTS_BODY, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask); + Collision_ClipToGenericEntity(&trace, model, touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask); + Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.server->solid == SOLID_BSP); } @@ -803,13 +809,7 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal, int hitsuperco trace.ent = prog->edicts; } - if (((int) ent->fields.server->flags & FL_ONGROUND) && ent->fields.server->groundentity == PRVM_EDICT_TO_PROG(trace.ent)) - impact = false; - else - { - ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND; - impact = true; - } + impact = !((int) ent->fields.server->flags & FL_ONGROUND) || ent->fields.server->groundentity != PRVM_EDICT_TO_PROG(trace.ent); if (trace.plane.normal[2]) { @@ -1149,15 +1149,10 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) continue; // if the entity is standing on the pusher, it will definitely be moved - if (((int)check->fields.server->flags & FL_ONGROUND) && PRVM_PROG_TO_EDICT(check->fields.server->groundentity) == pusher) + // if the entity is not standing on the pusher, but is in the pusher's + // final position, move it + if (!((int)check->fields.server->flags & FL_ONGROUND) || PRVM_PROG_TO_EDICT(check->fields.server->groundentity) != pusher) { - // remove the onground flag for non-players - if (check->fields.server->movetype != MOVETYPE_WALK) - check->fields.server->flags = (int)check->fields.server->flags & ~FL_ONGROUND; - } - else - { - // if the entity is not inside the pusher's final position, leave it alone Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); if (!trace.startsolid) continue; @@ -1189,6 +1184,11 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) pusher->fields.server->solid = savesolid; // was SOLID_BSP //Con_Printf("%s:%d frac %f startsolid %d bmodelstartsolid %d allsolid %d\n", __FILE__, __LINE__, trace.fraction, trace.startsolid, trace.bmodelstartsolid, trace.allsolid); + // this check is for items riding platforms that are passing under (or + // through) walls intended to knock the items off + if (trace.fraction < 1 && check->fields.server->movetype != MOVETYPE_WALK) + check->fields.server->flags = (int)check->fields.server->flags & ~FL_ONGROUND; + // if it is still inside the pusher, block Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY); if (trace.startsolid) @@ -1527,7 +1527,7 @@ Only used by players */ void SV_WalkMove (prvm_edict_t *ent) { - int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity; + int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity, hitsupercontentsmask; vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity; trace_t downtrace; @@ -1536,16 +1536,21 @@ void SV_WalkMove (prvm_edict_t *ent) if (sv.frametime <= 0) return; + hitsupercontentsmask = SV_GenericHitSuperContentsMask(ent); + SV_CheckVelocity(ent); // do a regular slide move unless it looks like you ran into a step oldonground = (int)ent->fields.server->flags & FL_ONGROUND; - ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND; VectorCopy (ent->fields.server->origin, start_origin); VectorCopy (ent->fields.server->velocity, start_velocity); - clip = SV_FlyMove (ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent)); + clip = SV_FlyMove (ent, sv.frametime, NULL, hitsupercontentsmask); + + // if the move did not hit the ground at any point, we're not on ground + if (!(clip & 1)) + ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND; SV_CheckVelocity(ent); @@ -1593,7 +1598,7 @@ void SV_WalkMove (prvm_edict_t *ent) // move forward ent->fields.server->velocity[2] = 0; - clip = SV_FlyMove (ent, sv.frametime, stepnormal, SV_GenericHitSuperContentsMask(ent)); + clip = SV_FlyMove (ent, sv.frametime, stepnormal, hitsupercontentsmask); ent->fields.server->velocity[2] += start_velocity[2]; SV_CheckVelocity(ent); @@ -1622,8 +1627,8 @@ void SV_WalkMove (prvm_edict_t *ent) if (clip & 2 && sv_wallfriction.integer) SV_WallFriction (ent, stepnormal); } - // skip out if stepdown is enabled, moving downward, not in water, and the move started onground and ended offground - else if (!(sv_gameplayfix_stepdown.integer && ent->fields.server->waterlevel < 2 && start_velocity[2] < (1.0 / 32.0) && oldonground && !((int)ent->fields.server->flags & FL_ONGROUND))) + // don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground + else if (!sv_gameplayfix_stepdown.integer || ent->fields.server->waterlevel >= 3 || start_velocity[2] >= (1.0 / 32.0) || !oldonground || ((int)ent->fields.server->flags & FL_ONGROUND)) return; // move down @@ -1635,7 +1640,7 @@ void SV_WalkMove (prvm_edict_t *ent) if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7) { // this has been disabled so that you can't jump when you are stepping - // up while already jumping (also known as the Quake2 stair jump bug) + // up while already jumping (also known as the Quake2 double jump bug) #if 0 // LordHavoc: disabled this check so you can walk on monsters/players //if (ent->fields.server->solid == SOLID_BSP) @@ -1994,20 +1999,27 @@ static void SV_Physics_Entity (prvm_edict_t *ent) } } -void SV_Physics_ClientEntity (prvm_edict_t *ent) +void SV_Physics_ClientMove(void) { - SV_ApplyClientMove(); - // make sure the velocity is sane (not a NaN) - SV_CheckVelocity(ent); - // LordHavoc: QuakeC replacement for SV_ClientThink (player movement) - if (prog->funcoffsets.SV_PlayerPhysics && sv_playerphysicsqc.integer) + prvm_edict_t *ent; + ent = host_client->edict; + if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) ) + SV_AddGravity (ent); + SV_CheckStuck (ent); + SV_WalkMove (ent); +} + +void SV_Physics_ClientEntity(prvm_edict_t *ent) +{ + // don't do physics on disconnected clients, FrikBot relies on this + if (!host_client->spawned) { - prog->globals.server->time = sv.time; - prog->globals.server->self = PRVM_EDICT_TO_PROG(ent); - PRVM_ExecuteProgram (prog->funcoffsets.SV_PlayerPhysics, "QC function SV_PlayerPhysics is missing"); + memset(&host_client->cmd, 0, sizeof(host_client->cmd)); + return; } - else - SV_ClientThink (); + + SV_ClientThink(); + // make sure the velocity is sane (not a NaN) SV_CheckVelocity(ent); // LordHavoc: a hack to ensure that the (rather silly) id1 quakec @@ -2037,45 +2049,43 @@ void SV_Physics_ClientEntity (prvm_edict_t *ent) SV_Physics_Follow (ent); break; case MOVETYPE_NOCLIP: - if (SV_RunThink(ent)) - { - SV_CheckWater(ent); - VectorMA(ent->fields.server->origin, sv.frametime, ent->fields.server->velocity, ent->fields.server->origin); - VectorMA(ent->fields.server->angles, sv.frametime, ent->fields.server->avelocity, ent->fields.server->angles); - } + SV_RunThink(ent); + SV_CheckWater(ent); + VectorMA(ent->fields.server->origin, sv.frametime, ent->fields.server->velocity, ent->fields.server->origin); + VectorMA(ent->fields.server->angles, sv.frametime, ent->fields.server->avelocity, ent->fields.server->angles); break; case MOVETYPE_STEP: SV_Physics_Step (ent); break; case MOVETYPE_WALK: - if (SV_RunThink (ent)) - { - if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) ) - SV_AddGravity (ent); - SV_CheckStuck (ent); - SV_WalkMove (ent); - } + SV_RunThink (ent); + // don't run physics here if running asynchronously + if (host_client->clmovement_skipphysicsframes <= 0) + SV_Physics_ClientMove(); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_BOUNCEMISSILE: case MOVETYPE_FLYMISSILE: // regular thinking - if (SV_RunThink (ent)) - SV_Physics_Toss (ent); + SV_RunThink (ent); + SV_Physics_Toss (ent); break; case MOVETYPE_FLY: - if (SV_RunThink (ent)) - { - SV_CheckWater (ent); - SV_WalkMove (ent); - } + SV_RunThink (ent); + SV_CheckWater (ent); + SV_WalkMove (ent); break; default: Con_Printf ("SV_Physics_ClientEntity: bad movetype %i\n", (int)ent->fields.server->movetype); break; } + // decrement the countdown variable used to decide when to go back to + // synchronous physics + if (host_client->clmovement_skipphysicsframes > 0) + host_client->clmovement_skipphysicsframes--; + SV_CheckVelocity (ent); // call standard player post-think @@ -2086,6 +2096,17 @@ void SV_Physics_ClientEntity (prvm_edict_t *ent) prog->globals.server->time = sv.time; prog->globals.server->self = PRVM_EDICT_TO_PROG(ent); PRVM_ExecuteProgram (prog->globals.server->PlayerPostThink, "QC function PlayerPostThink is missing"); + + if(ent->fields.server->fixangle) + { + // angle fixing was requested by physics code... + // so store the current angles for later use + memcpy(host_client->fixangle_angles, ent->fields.server->angles, sizeof(host_client->fixangle_angles)); + host_client->fixangle_angles_set = TRUE; + + // and clear fixangle for the next frame + ent->fields.server->fixangle = 0; + } } /* @@ -2118,19 +2139,8 @@ void SV_Physics (void) // run physics on the client entities for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++) - { if (!ent->priv.server->free) - { - // don't do physics on disconnected clients, FrikBot relies on this - if (!host_client->spawned) - memset(&host_client->cmd, 0, sizeof(host_client->cmd)); - // don't run physics here if running asynchronously - else if (host_client->clmovement_skipphysicsframes > 0) - host_client->clmovement_skipphysicsframes--; - else SV_Physics_ClientEntity(ent); - } - } // run physics on all the non-client entities if (!sv_freezenonclients.integer)