X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=6a6dda8c68383f6e84c4159f86ab708f39ec65de;hb=49a0d411fae28787e20dc45a4906722a5e51b7bc;hp=b7adc93ba1c0be1be68fe8d7eb28258f45dfbe91;hpb=ff5e045d96c0815080d93fca3b48978dead980d4;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index b7adc93b..6a6dda8c 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -107,7 +107,7 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const // matrices to transform into/out of other entity's space matrix4x4_t matrix, imatrix; // model of other entity - model_t *model; + dp_model_t *model; // list of entities to test for collisions int numtouchedicts; prvm_edict_t *touchedicts[MAX_EDICTS]; @@ -225,9 +225,9 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const 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, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask); + Collision_ClipToGenericEntity(&trace, model, (int) 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, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask); + Collision_ClipToGenericEntity(&trace, model, (int) 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); } @@ -255,6 +255,63 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const } #endif +int SV_PointSuperContents(const vec3_t point) +{ + int supercontents = 0; + int i; + prvm_edict_t *touch; + vec3_t transformed; + // matrices to transform into/out of other entity's space + matrix4x4_t matrix, imatrix; + // model of other entity + dp_model_t *model; + unsigned int modelindex; + int frame; + // list of entities to test for collisions + int numtouchedicts; + prvm_edict_t *touchedicts[MAX_EDICTS]; + + // get world supercontents at this point + if (sv.worldmodel && sv.worldmodel->PointSuperContents) + supercontents = sv.worldmodel->PointSuperContents(sv.worldmodel, 0, point); + + // if sv_gameplayfix_swiminbmodels is off we're done + if (!sv_gameplayfix_swiminbmodels.integer) + return supercontents; + + // get list of entities at this point + numtouchedicts = World_EntitiesInBox(&sv.world, point, point, MAX_EDICTS, touchedicts); + if (numtouchedicts > MAX_EDICTS) + { + // this never happens + Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS); + numtouchedicts = MAX_EDICTS; + } + for (i = 0;i < numtouchedicts;i++) + { + touch = touchedicts[i]; + + // we only care about SOLID_BSP for pointcontents + if (touch->fields.server->solid != SOLID_BSP) + continue; + + // might interact, so do an exact clip + modelindex = (unsigned int)touch->fields.server->modelindex; + if (modelindex >= MAX_MODELS) + continue; + model = sv.models[(int)touch->fields.server->modelindex]; + if (!model || !model->PointSuperContents) + continue; + 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); + Matrix4x4_Invert_Simple(&imatrix, &matrix); + Matrix4x4_Transform(&imatrix, point, transformed); + frame = (int)touch->fields.server->frame; + supercontents |= model->PointSuperContents(model, bound(0, frame, (model->numframes - 1)), transformed); + } + + return supercontents; +} + /* =============================================================================== @@ -321,7 +378,7 @@ SV_LinkEdict */ void SV_LinkEdict (prvm_edict_t *ent, qboolean touch_triggers) { - model_t *model; + dp_model_t *model; vec3_t mins, maxs; if (ent == prog->edicts) @@ -699,17 +756,32 @@ Returns the clipflags if the velocity was modified (hit something solid) If stepnormal is not NULL, the plane normal of any vertical wall hit will be stored ============ */ +static float SV_Gravity (prvm_edict_t *ent); // LordHavoc: increased from 5 to 32 #define MAX_CLIP_PLANES 32 -int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal, int hitsupercontentsmask) +static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, float *stepnormal, int hitsupercontentsmask) { int blocked, bumpcount; int i, j, impact, numplanes; - float d, time_left; + float d, time_left, gravity; vec3_t dir, end, planes[MAX_CLIP_PLANES], primal_velocity, original_velocity, new_velocity; trace_t trace; if (time <= 0) return 0; + gravity = 0; + if (applygravity) + { + if (sv_gameplayfix_gravityunaffectedbyticrate.integer) + { + gravity = SV_Gravity(ent) * 0.5f; + ent->fields.server->velocity[2] -= gravity; + } + else + { + applygravity = false; + ent->fields.server->velocity[2] -= SV_Gravity(ent); + } + } blocked = 0; VectorCopy(ent->fields.server->velocity, original_velocity); VectorCopy(ent->fields.server->velocity, primal_velocity); @@ -923,16 +995,18 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal, int hitsuperco // LordHavoc: this came from QW and allows you to get out of water more easily if (sv_gameplayfix_easierwaterjump.integer && ((int)ent->fields.server->flags & FL_WATERJUMP)) VectorCopy(primal_velocity, ent->fields.server->velocity); + if (applygravity && !((int)ent->fields.server->flags & FL_ONGROUND)) + ent->fields.server->velocity[2] -= gravity; return blocked; } /* ============ -SV_AddGravity +SV_Gravity ============ */ -void SV_AddGravity (prvm_edict_t *ent) +static float SV_Gravity (prvm_edict_t *ent) { float ent_gravity; prvm_eval_t *val; @@ -942,7 +1016,7 @@ void SV_AddGravity (prvm_edict_t *ent) ent_gravity = val->_float; else ent_gravity = 1.0; - ent->fields.server->velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime; + return ent_gravity * sv_gravity.value * sv.frametime; } @@ -998,12 +1072,15 @@ SV_PushMove void SV_PushMove (prvm_edict_t *pusher, float movetime) { int i, e, index; + int pusherowner, pusherprog; + int checkcontents; + qboolean rotated; float savesolid, movetime2, pushltime; vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org; int num_moved; int numcheckentities; static prvm_edict_t *checkentities[MAX_EDICTS]; - model_t *pushermodel; + dp_model_t *pushermodel; trace_t trace; matrix4x4_t pusherfinalmatrix, pusherfinalimatrix; unsigned short moved_edicts[MAX_EDICTS]; @@ -1044,6 +1121,10 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) return; } pushermodel = sv.models[index]; + pusherowner = pusher->fields.server->owner; + pusherprog = PRVM_EDICT_TO_PROG(pusher); + + rotated = VectorLength2(pusher->fields.server->angles) + VectorLength2(pusher->fields.server->avelocity) > 0; movetime2 = movetime; VectorScale(pusher->fields.server->velocity, movetime2, move1); @@ -1126,7 +1207,6 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) for (e = 0;e < numcheckentities;e++) { prvm_edict_t *check = checkentities[e]; - int checkcontents = SV_GenericHitSuperContentsMask(check); if (check->fields.server->movetype == MOVETYPE_NONE || check->fields.server->movetype == MOVETYPE_PUSH || check->fields.server->movetype == MOVETYPE_FOLLOW @@ -1134,18 +1214,34 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) || check->fields.server->movetype == MOVETYPE_FAKEPUSH) continue; + if (check->fields.server->owner == pusherprog) + continue; + + if (pusherowner == PRVM_EDICT_TO_PROG(check)) + continue; + + //Con_Printf("%i %s ", PRVM_NUM_FOR_EDICT(check), PRVM_GetString(check->fields.server->classname)); + + // tell any MOVETYPE_STEP entity that it may need to check for water transitions + check->priv.server->waterposition_forceupdate = true; + + checkcontents = SV_GenericHitSuperContentsMask(check); + // if the entity is standing on the pusher, it will definitely be moved // 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) { - 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, checkcontents); + Collision_ClipToGenericEntity(&trace, pushermodel, (int) 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, checkcontents); + //trace = SV_Move(check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, MOVE_NOMONSTERS, check, checkcontents); if (!trace.startsolid) + { + //Con_Printf("- not in solid\n"); continue; + } } - - if (forward[0] != 1 || left[1] != 1) // quick way to check if any rotation is used + if (rotated) { vec3_t org2; VectorSubtract (check->fields.server->origin, pusher->fields.server->origin, org); @@ -1158,6 +1254,8 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) else VectorCopy (move1, move); + //Con_Printf("- pushing %f %f %f\n", move[0], move[1], move[2]); + VectorCopy (check->fields.server->origin, check->priv.server->moved_from); VectorCopy (check->fields.server->angles, check->priv.server->moved_fromangles); moved_edicts[num_moved++] = PRVM_NUM_FOR_EDICT(check); @@ -1177,7 +1275,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) 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, checkcontents); + Collision_ClipToGenericEntity(&trace, pushermodel, (int) 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, checkcontents); if (trace.startsolid) { // try moving the contacted entity a tiny bit further to account for precision errors @@ -1188,7 +1286,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) VectorCopy (check->priv.server->moved_fromangles, check->fields.server->angles); SV_PushEntity (check, move2, true); pusher->fields.server->solid = savesolid; - 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, checkcontents); + Collision_ClipToGenericEntity(&trace, pushermodel, (int) 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, checkcontents); if (trace.startsolid) { // try moving the contacted entity a tiny bit less to account for precision errors @@ -1198,7 +1296,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) VectorCopy (check->priv.server->moved_fromangles, check->fields.server->angles); SV_PushEntity (check, move2, true); pusher->fields.server->solid = savesolid; - 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, checkcontents); + Collision_ClipToGenericEntity(&trace, pushermodel, (int) 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, checkcontents); if (trace.startsolid) { // still inside pusher, so it's really blocked @@ -1302,21 +1400,37 @@ static float unstickoffsets[] = 1, 1, 0, 0, 0, -1, 0, 0, 1, + 0, 0, -2, 0, 0, 2, + 0, 0, -3, 0, 0, 3, + 0, 0, -4, 0, 0, 4, + 0, 0, -5, 0, 0, 5, + 0, 0, -6, 0, 0, 6, + 0, 0, -7, 0, 0, 7, + 0, 0, -8, 0, 0, 8, + 0, 0, -9, 0, 0, 9, + 0, 0, -10, 0, 0, 10, + 0, 0, -11, 0, 0, 11, + 0, 0, -12, 0, 0, 12, + 0, 0, -13, 0, 0, 13, + 0, 0, -14, 0, 0, 14, + 0, 0, -15, 0, 0, 15, + 0, 0, -16, 0, 0, 16, + 0, 0, -17, 0, 0, 17, }; @@ -1360,13 +1474,13 @@ void SV_CheckStuck (prvm_edict_t *ent) Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname)); } -static void SV_UnstickEntity (prvm_edict_t *ent) +qboolean SV_UnstickEntity (prvm_edict_t *ent) { int i; // if not stuck in a bmodel, just return if (!SV_TestEntityPosition(ent, vec3_origin)) - return; + return true; for (i = 0;i < (int)(sizeof(unstickoffsets) / sizeof(unstickoffsets[0]));i += 3) { @@ -1374,12 +1488,13 @@ static void SV_UnstickEntity (prvm_edict_t *ent) { Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname), unstickoffsets[i+0], unstickoffsets[i+1], unstickoffsets[i+2]); SV_LinkEdict (ent, true); - return; + return true; } } if (developer.integer >= 100) Con_Printf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname)); + return false; } @@ -1530,12 +1645,17 @@ void SV_WalkMove (prvm_edict_t *ent) 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; + qboolean applygravity; // if frametime is 0 (due to client sending the same timestamp twice), // don't move if (sv.frametime <= 0) return; + SV_CheckStuck (ent); + + applygravity = !SV_CheckWater (ent) && ent->fields.server->movetype == MOVETYPE_WALK && ! ((int)ent->fields.server->flags & FL_WATERJUMP); + hitsupercontentsmask = SV_GenericHitSuperContentsMask(ent); SV_CheckVelocity(ent); @@ -1546,13 +1666,14 @@ void SV_WalkMove (prvm_edict_t *ent) VectorCopy (ent->fields.server->origin, start_origin); VectorCopy (ent->fields.server->velocity, start_velocity); - clip = SV_FlyMove (ent, sv.frametime, NULL, hitsupercontentsmask); + clip = SV_FlyMove (ent, sv.frametime, applygravity, 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); + SV_LinkEdict (ent, true); VectorCopy(ent->fields.server->origin, originalmove_origin); VectorCopy(ent->fields.server->velocity, originalmove_velocity); @@ -1598,10 +1719,11 @@ void SV_WalkMove (prvm_edict_t *ent) // move forward ent->fields.server->velocity[2] = 0; - clip = SV_FlyMove (ent, sv.frametime, stepnormal, hitsupercontentsmask); + clip = SV_FlyMove (ent, sv.frametime, applygravity, stepnormal, hitsupercontentsmask); ent->fields.server->velocity[2] += start_velocity[2]; SV_CheckVelocity(ent); + SV_LinkEdict (ent, true); // check for stuckness, possibly due to the limited precision of floats // in the clipping hulls @@ -1665,6 +1787,7 @@ void SV_WalkMove (prvm_edict_t *ent) } SV_CheckVelocity(ent); + SV_LinkEdict (ent, true); } //============================================================================ @@ -1773,6 +1896,8 @@ void SV_Physics_Toss (prvm_edict_t *ent) { trace_t trace; vec3_t move; + vec_t movetime; + int bump; // if onground, return without moving if ((int)ent->fields.server->flags & FL_ONGROUND) @@ -1802,27 +1927,30 @@ void SV_Physics_Toss (prvm_edict_t *ent) // add gravity if (ent->fields.server->movetype == MOVETYPE_TOSS || ent->fields.server->movetype == MOVETYPE_BOUNCE) - SV_AddGravity (ent); + ent->fields.server->velocity[2] -= SV_Gravity(ent); // move angles VectorMA (ent->fields.server->angles, sv.frametime, ent->fields.server->avelocity, ent->fields.server->angles); -// move origin - VectorScale (ent->fields.server->velocity, sv.frametime, move); - trace = SV_PushEntity (ent, move, true); - if (ent->priv.server->free) - return; - if (trace.bmodelstartsolid) + movetime = sv.frametime; + for (bump = 0;bump < MAX_CLIP_PLANES && movetime > 0;bump++) { - // try to unstick the entity - SV_UnstickEntity(ent); - trace = SV_PushEntity (ent, move, false); + // move origin + VectorScale (ent->fields.server->velocity, movetime, move); + trace = SV_PushEntity (ent, move, true); if (ent->priv.server->free) return; - } - - if (trace.fraction < 1) - { + if (trace.bmodelstartsolid) + { + // try to unstick the entity + SV_UnstickEntity(ent); + trace = SV_PushEntity (ent, move, false); + if (ent->priv.server->free) + return; + } + if (trace.fraction == 1) + break; + movetime *= 1 - min(1, trace.fraction); if (ent->fields.server->movetype == MOVETYPE_BOUNCEMISSILE) { ClipVelocity (ent->fields.server->velocity, trace.plane.normal, ent->fields.server->velocity, 2.0); @@ -1830,13 +1958,19 @@ void SV_Physics_Toss (prvm_edict_t *ent) } else if (ent->fields.server->movetype == MOVETYPE_BOUNCE) { - float d; + float d, ent_gravity; + prvm_eval_t *val; ClipVelocity (ent->fields.server->velocity, trace.plane.normal, ent->fields.server->velocity, 1.5); // LordHavoc: fixed grenades not bouncing when fired down a slope + val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.gravity); + if (val!=0 && val->_float) + ent_gravity = val->_float; + else + ent_gravity = 1.0; if (sv_gameplayfix_grenadebouncedownslopes.integer) { d = DotProduct(trace.plane.normal, ent->fields.server->velocity); - if (trace.plane.normal[2] > 0.7 && fabs(d) < 60) + if (trace.plane.normal[2] > 0.7 && fabs(d) < sv_gravity.value * (60.0 / 800.0) * ent_gravity) { ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND; ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent); @@ -1848,7 +1982,7 @@ void SV_Physics_Toss (prvm_edict_t *ent) } else { - if (trace.plane.normal[2] > 0.7 && ent->fields.server->velocity[2] < 60) + if (trace.plane.normal[2] > 0.7 && ent->fields.server->velocity[2] < sv_gravity.value * (60.0 / 800.0) * ent_gravity) { ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND; ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent); @@ -1874,6 +2008,8 @@ void SV_Physics_Toss (prvm_edict_t *ent) else ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND; } + if (!sv_gameplayfix_slidemoveprojectiles.integer || (ent->fields.server->movetype != MOVETYPE_BOUNCE && ent->fields.server->movetype == MOVETYPE_BOUNCEMISSILE) || ((int)ent->fields.server->flags & FL_ONGROUND)) + break; } // check for in water @@ -1902,6 +2038,13 @@ will fall if the floor is pulled out from under them. void SV_Physics_Step (prvm_edict_t *ent) { int flags = (int)ent->fields.server->flags; + + // DRESK + // Backup Velocity in the event that movetypesteplandevent is called, + // to provide a parameter with the entity's velocity at impact. + prvm_eval_t *movetypesteplandevent; + vec3_t backupVelocity; + VectorCopy(ent->fields.server->velocity, backupVelocity); // don't fall at all if fly/swim if (!(flags & (FL_FLY | FL_SWIM))) { @@ -1912,10 +2055,10 @@ void SV_Physics_Step (prvm_edict_t *ent) if ((ent->fields.server->velocity[2] >= (1.0 / 32.0) && sv_gameplayfix_upwardvelocityclearsongroundflag.integer) || ent->fields.server->groundentity) { ent->fields.server->flags -= FL_ONGROUND; - SV_AddGravity(ent); SV_CheckVelocity(ent); - SV_FlyMove(ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent)); + SV_FlyMove(ent, sv.frametime, true, NULL, SV_GenericHitSuperContentsMask(ent)); SV_LinkEdict(ent, true); + ent->priv.server->waterposition_forceupdate = true; } } else @@ -1923,31 +2066,63 @@ void SV_Physics_Step (prvm_edict_t *ent) // freefall if not onground int hitsound = ent->fields.server->velocity[2] < sv_gravity.value * -0.1; - SV_AddGravity(ent); SV_CheckVelocity(ent); - SV_FlyMove(ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent)); + SV_FlyMove(ent, sv.frametime, true, NULL, SV_GenericHitSuperContentsMask(ent)); SV_LinkEdict(ent, true); // just hit ground - if (hitsound && (int)ent->fields.server->flags & FL_ONGROUND && sv_sound_land.string) - SV_StartSound(ent, 0, sv_sound_land.string, 255, 1); + if (hitsound && (int)ent->fields.server->flags & FL_ONGROUND) + { + // DRESK - Check for Entity Land Event Function + movetypesteplandevent = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.movetypesteplandevent); + + if(movetypesteplandevent->function) + { // Valid Function; Execute + // Prepare Parameters + // Assign Velocity at Impact + PRVM_G_VECTOR(OFS_PARM0)[0] = backupVelocity[0]; + PRVM_G_VECTOR(OFS_PARM0)[1] = backupVelocity[1]; + PRVM_G_VECTOR(OFS_PARM0)[2] = backupVelocity[2]; + // Assign Self + prog->globals.server->self = PRVM_EDICT_TO_PROG(ent); + // Execute VM Function + PRVM_ExecuteProgram(movetypesteplandevent->function, "movetypesteplandevent: NULL function"); + } + else + // Check for Engine Landing Sound + if(sv_sound_land.string) + SV_StartSound(ent, 0, sv_sound_land.string, 255, 1); + } + ent->priv.server->waterposition_forceupdate = true; } } // regular thinking - SV_RunThink(ent); + if (!SV_RunThink(ent)) + return; - SV_CheckWaterTransition(ent); + if (ent->priv.server->waterposition_forceupdate || !VectorCompare(ent->fields.server->origin, ent->priv.server->waterposition_origin)) + { + ent->priv.server->waterposition_forceupdate = false; + VectorCopy(ent->fields.server->origin, ent->priv.server->waterposition_origin); + SV_CheckWaterTransition(ent); + } } //============================================================================ static void SV_Physics_Entity (prvm_edict_t *ent) { - // don't run a move on newly spawned projectiles as it messes up movement - // interpolation and rocket trails + // don't run think/move on newly spawned projectiles as it messes up + // movement interpolation and rocket trails, and is inconsistent with + // respect to entities spawned in the same frame + // (if an ent spawns a higher numbered ent, it moves in the same frame, + // but if it spawns a lower numbered ent, it doesn't - this never moves + // ents in the first frame regardless) qboolean runmove = ent->priv.server->move; ent->priv.server->move = true; + if (!runmove && sv_gameplayfix_delayprojectiles.integer) + return; switch ((int) ent->fields.server->movetype) { case MOVETYPE_PUSH: @@ -1976,13 +2151,7 @@ static void SV_Physics_Entity (prvm_edict_t *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_LinkEdict (ent, true); - } break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: @@ -1990,7 +2159,7 @@ static void SV_Physics_Entity (prvm_edict_t *ent) case MOVETYPE_FLYMISSILE: case MOVETYPE_FLY: // regular thinking - if (SV_RunThink (ent) && (runmove || !sv_gameplayfix_delayprojectiles.integer)) + if (SV_RunThink (ent)) SV_Physics_Toss (ent); break; default: @@ -2025,17 +2194,8 @@ void SV_Physics_ClientMove(void) VectorClear(ent->fields.server->velocity); // perform MOVETYPE_WALK behavior - if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) ) - SV_AddGravity (ent); - SV_CheckStuck (ent); SV_WalkMove (ent); - SV_CheckVelocity (ent); - - SV_LinkEdict (ent, true); - - SV_CheckVelocity (ent); - // call standard player post-think, with frametime = 0 prog->globals.server->time = sv.time; prog->globals.server->frametime = 0; @@ -2065,8 +2225,11 @@ void SV_Physics_ClientEntity(prvm_edict_t *ent) } // don't run physics here if running asynchronously - if (host_client->clmovement_skipphysicsframes <= 0) + if (host_client->clmovement_inputtimeout <= 0) + { SV_ClientThink(); + //host_client->cmd.time = max(host_client->cmd.time, sv.time); + } // make sure the velocity is sane (not a NaN) SV_CheckVelocity(ent); @@ -2109,14 +2272,8 @@ void SV_Physics_ClientEntity(prvm_edict_t *ent) case MOVETYPE_WALK: SV_RunThink (ent); // don't run physics here if running asynchronously - if (host_client->clmovement_skipphysicsframes <= 0) - { - if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) ) - SV_AddGravity (ent); - SV_CheckStuck (ent); + if (host_client->clmovement_inputtimeout <= 0) SV_WalkMove (ent); - host_client->cmd.time = max(host_client->cmd.time, sv.time); // ignore client movement data for anything before NOW - } break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: @@ -2128,7 +2285,6 @@ void SV_Physics_ClientEntity(prvm_edict_t *ent) break; case MOVETYPE_FLY: SV_RunThink (ent); - SV_CheckWater (ent); SV_WalkMove (ent); break; default: @@ -2138,8 +2294,10 @@ void SV_Physics_ClientEntity(prvm_edict_t *ent) // decrement the countdown variable used to decide when to go back to // synchronous physics - if (host_client->clmovement_skipphysicsframes > 0) - host_client->clmovement_skipphysicsframes--; + if (host_client->clmovement_inputtimeout > sv.frametime) + host_client->clmovement_inputtimeout -= sv.frametime; + else + host_client->clmovement_inputtimeout = 0; SV_CheckVelocity (ent);