X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=aed6049af5acfaa3ed12dcb6263eb1163bfa2a7f;hb=187f34c6c239f91e60dca9e4c520f94fd420c305;hp=fdb597ca16972c635dc8f4cd04bd600af856f0f4;hpb=fae3f808509f33714801bd1512f025cb6ddc18a4;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index fdb597ca..aed6049a 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -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 + 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; +} + /* =============================================================================== @@ -343,7 +400,7 @@ void SV_LinkEdict (prvm_edict_t *ent, qboolean touch_triggers) model = sv.models[modelindex]; if (model != NULL) { - if (!model->TraceBox) + if (!model->TraceBox && developer.integer >= 1) Con_Printf("edict %i: SOLID_BSP with non-collidable model\n", PRVM_NUM_FOR_EDICT(ent)); if (ent->fields.server->angles[0] || ent->fields.server->angles[2] || ent->fields.server->avelocity[0] || ent->fields.server->avelocity[2]) @@ -552,12 +609,12 @@ void SV_CheckVelocity (prvm_edict_t *ent) { if (IS_NAN(ent->fields.server->velocity[i])) { - Con_Printf("Got a NaN velocity on %s\n", PRVM_GetString(ent->fields.server->classname)); + Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(ent->fields.server->classname)); ent->fields.server->velocity[i] = 0; } if (IS_NAN(ent->fields.server->origin[i])) { - Con_Printf("Got a NaN origin on %s\n", PRVM_GetString(ent->fields.server->classname)); + Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(ent->fields.server->classname)); ent->fields.server->origin[i] = 0; } } @@ -921,7 +978,7 @@ 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_qwplayerphysics.integer && ((int)ent->fields.server->flags & FL_WATERJUMP)) + if (sv_gameplayfix_easierwaterjump.integer && ((int)ent->fields.server->flags & FL_WATERJUMP)) VectorCopy(primal_velocity, ent->fields.server->velocity); return blocked; } @@ -998,6 +1055,8 @@ SV_PushMove void SV_PushMove (prvm_edict_t *pusher, float movetime) { int i, e, index; + 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; @@ -1045,6 +1104,8 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) } pushermodel = sv.models[index]; + rotated = VectorLength2(pusher->fields.server->angles) + VectorLength2(pusher->fields.server->avelocity) > 0; + movetime2 = movetime; VectorScale(pusher->fields.server->velocity, movetime2, move1); VectorScale(pusher->fields.server->avelocity, movetime2, moveangle); @@ -1126,7 +1187,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 +1194,28 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) || check->fields.server->movetype == MOVETYPE_FAKEPUSH) 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); + //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 +1228,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); @@ -1302,21 +1374,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 +1448,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 +1462,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; } @@ -1916,6 +2005,7 @@ void SV_Physics_Step (prvm_edict_t *ent) SV_CheckVelocity(ent); SV_FlyMove(ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent)); SV_LinkEdict(ent, true); + ent->priv.server->waterposition_forceupdate = true; } } else @@ -1931,13 +2021,20 @@ void SV_Physics_Step (prvm_edict_t *ent) // 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); + 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); + } } //============================================================================ @@ -1990,7 +2087,7 @@ static void SV_Physics_Entity (prvm_edict_t *ent) case MOVETYPE_FLYMISSILE: case MOVETYPE_FLY: // regular thinking - if (SV_RunThink (ent) && runmove) + if (SV_RunThink (ent) && (runmove || !sv_gameplayfix_delayprojectiles.integer)) SV_Physics_Toss (ent); break; default: