// clip to entities
// because this uses World_EntitiestoBox, we know all entity boxes overlap
// the clip region, so we can skip culling checks in the loop below
- numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
// clip to entities
// because this uses World_EntitiestoBox, we know all entity boxes overlap
// the clip region, so we can skip culling checks in the loop below
- numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
// clip to entities
// because this uses World_EntitiestoBox, we know all entity boxes overlap
// the clip region, so we can skip culling checks in the loop below
- numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
return supercontents;
// get list of entities at this point
- numtouchedicts = World_EntitiesInBox(&sv.world, point, point, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(point, point, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
===============================================================================
*/
+int SV_EntitiesInBox(const vec3_t mins, const vec3_t maxs, int maxedicts, prvm_edict_t **resultedicts)
+{
+ vec3_t paddedmins, paddedmaxs;
+ if (maxedicts < 1 || resultedicts == NULL)
+ return 0;
+ VectorSet(paddedmins, mins[0] - 10, mins[1] - 10, mins[2] - 1);
+ VectorSet(paddedmaxs, maxs[0] + 10, maxs[1] + 10, maxs[2] + 1);
+ if (sv_areadebug.integer)
+ {
+ int numresultedicts = 0;
+ int edictindex;
+ prvm_edict_t *ed;
+ for (edictindex = 1;edictindex < prog->num_edicts;edictindex++)
+ {
+ ed = PRVM_EDICT_NUM(edictindex);
+ if (!ed->priv.required->free && BoxesOverlap(PRVM_serveredictvector(ed, absmin), PRVM_serveredictvector(ed, absmax), paddedmins, paddedmaxs))
+ {
+ resultedicts[numresultedicts++] = ed;
+ if (numresultedicts == maxedicts)
+ break;
+ }
+ }
+ return numresultedicts;
+ }
+ else
+ return World_EntitiesInBox(&sv.world, paddedmins, paddedmaxs, maxedicts, resultedicts);
+}
+
void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent)
{
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(touch);
// build a list of edicts to touch, because the link loop can be corrupted
// by IncreaseEdicts called during touch functions
- numtouchedicts = World_EntitiesInBox(&sv.world, ent->priv.server->areamins, ent->priv.server->areamaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(ent->priv.server->areamins, ent->priv.server->areamaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
trace_t trace;
contents = SV_GenericHitSuperContentsMask(ent);
VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
- trace = SV_TraceBox(org, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), PRVM_serveredictvector(ent, origin), MOVE_NOMONSTERS, ent, contents);
+ trace = SV_TraceBox(org, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), PRVM_serveredictvector(ent, origin), ((PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), ent, contents);
if (trace.startsupercontents & contents)
return true;
else
if (PRVM_serveredictfloat(check, movetype) == MOVETYPE_PUSH
|| PRVM_serveredictfloat(check, movetype) == MOVETYPE_NONE
|| PRVM_serveredictfloat(check, movetype) == MOVETYPE_FOLLOW
- || PRVM_serveredictfloat(check, movetype) == MOVETYPE_NOCLIP)
+ || PRVM_serveredictfloat(check, movetype) == MOVETYPE_NOCLIP
+ || PRVM_serveredictfloat(check, movetype) == MOVETYPE_FLY_WORLDONLY)
continue;
if (SV_TestEntityPosition (check, vec3_origin))
===============================================================================
*/
+static qboolean SV_NudgeOutOfSolid_PivotIsKnownGood(prvm_edict_t *ent, vec3_t pivot)
+{
+ int bump;
+ trace_t stucktrace;
+ vec3_t stuckorigin;
+ vec3_t stuckmins, stuckmaxs;
+ vec3_t goodmins, goodmaxs;
+ vec3_t testorigin;
+ vec_t nudge;
+ vec3_t move;
+ VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
+ VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
+ VectorCopy(pivot, goodmins);
+ VectorCopy(pivot, goodmaxs);
+ for (bump = 0;bump < 6;bump++)
+ {
+ int coord = 2-(bump >> 1);
+ //int coord = (bump >> 1);
+ int dir = (bump & 1);
+ int subbump;
+
+ for(subbump = 0; ; ++subbump)
+ {
+ VectorCopy(stuckorigin, testorigin);
+ if(dir)
+ {
+ // pushing maxs
+ testorigin[coord] += stuckmaxs[coord] - goodmaxs[coord];
+ }
+ else
+ {
+ // pushing mins
+ testorigin[coord] += stuckmins[coord] - goodmins[coord];
+ }
+
+ stucktrace = SV_TraceBox(stuckorigin, goodmins, goodmaxs, testorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
+ if (stucktrace.bmodelstartsolid)
+ {
+ // BAD BAD, can't fix that
+ return false;
+ }
+
+ if (stucktrace.fraction >= 1)
+ break; // it WORKS!
+
+ if(subbump >= 10)
+ {
+ // BAD BAD, can't fix that
+ return false;
+ }
+
+ // we hit something... let's move out of it
+ VectorSubtract(stucktrace.endpos, testorigin, move);
+ nudge = DotProduct(stucktrace.plane.normal, move) + 0.03125f; // FIXME cvar this constant
+ VectorMA(stuckorigin, nudge, stucktrace.plane.normal, stuckorigin);
+ }
+ /*
+ if(subbump > 0)
+ Con_Printf("subbump: %d\n", subbump);
+ */
+
+ if(dir)
+ {
+ // pushing maxs
+ goodmaxs[coord] = stuckmaxs[coord];
+ }
+ else
+ {
+ // pushing mins
+ goodmins[coord] = stuckmins[coord];
+ }
+ }
+
+ // WE WIN
+ VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
+
+ return true;
+}
+
+static qboolean SV_NudgeOutOfSolid(prvm_edict_t *ent)
+{
+ int bump;
+ trace_t stucktrace;
+ vec3_t stuckorigin;
+ vec3_t stuckmins, stuckmaxs;
+ vec_t nudge;
+ vec_t separation = sv_gameplayfix_nudgeoutofsolid_separation.value;
+ if (sv.worldmodel && sv.worldmodel->brushq1.numclipnodes)
+ separation = 0.0f; // when using hulls, it can not be enlarged
+ VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
+ VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
+ stuckmins[0] -= separation;
+ stuckmins[1] -= separation;
+ stuckmins[2] -= separation;
+ stuckmaxs[0] += separation;
+ stuckmaxs[1] += separation;
+ stuckmaxs[2] += separation;
+ for (bump = 0;bump < 10;bump++)
+ {
+ stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
+ if (!stucktrace.bmodelstartsolid || stucktrace.startdepth >= 0)
+ {
+ // found a good location, use it
+ VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
+ return true;
+ }
+ nudge = -stucktrace.startdepth;
+ VectorMA(stuckorigin, nudge, stucktrace.startdepthnormal, stuckorigin);
+ }
+ return false;
+}
+
/*
============
SV_PushEntity
int solid;
int movetype;
int type;
- int bump;
vec3_t mins, maxs;
- vec3_t original, original_velocity;
vec3_t start;
vec3_t end;
// move start position out of solids
if (sv_gameplayfix_nudgeoutofsolid.integer && sv_gameplayfix_nudgeoutofsolid_separation.value >= 0)
{
- trace_t stucktrace;
- vec3_t stuckorigin;
- vec3_t stuckmins, stuckmaxs;
- vec_t nudge;
- vec_t separation = sv_gameplayfix_nudgeoutofsolid_separation.value;
- if (sv.worldmodel && sv.worldmodel->brushq1.numclipnodes)
- separation = 0.0f; // when using hulls, it can not be enlarged
- VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
- VectorCopy(mins, stuckmins);
- VectorCopy(maxs, stuckmaxs);
- stuckmins[0] -= separation;
- stuckmins[1] -= separation;
- stuckmins[2] -= separation;
- stuckmaxs[0] += separation;
- stuckmaxs[1] += separation;
- stuckmaxs[2] += separation;
- for (bump = 0;bump < 10;bump++)
- {
- stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
- if (!stucktrace.bmodelstartsolid || stucktrace.startdepth >= 0)
- {
- // found a good location, use it
- VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
- break;
- }
- nudge = -stucktrace.startdepth;
- VectorMA(stuckorigin, nudge, stucktrace.startdepthnormal, stuckorigin);
- }
+ SV_NudgeOutOfSolid(ent);
}
VectorCopy(PRVM_serveredictvector(ent, origin), start);
if (movetype == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
+ else if (movetype == MOVETYPE_FLY_WORLDONLY)
+ type = MOVE_WORLDONLY;
else if (solid == SOLID_TRIGGER || solid == SOLID_NOT)
type = MOVE_NOMONSTERS; // only clip against bmodels
else
VectorCopy(trace->endpos, PRVM_serveredictvector(ent, origin));
- VectorCopy(PRVM_serveredictvector(ent, origin), original);
- VectorCopy(PRVM_serveredictvector(ent, velocity), original_velocity);
+ ent->priv.required->mark = PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN; // -2: setorigin running
SV_LinkEdict(ent);
if((PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace->ent && (!((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND) || PRVM_serveredictedict(ent, groundentity) != PRVM_EDICT_TO_PROG(trace->ent))))
SV_Impact (ent, trace);
- return VectorCompare(PRVM_serveredictvector(ent, origin), original) && VectorCompare(PRVM_serveredictvector(ent, velocity), original_velocity);
+ if(ent->priv.required->mark == PRVM_EDICT_MARK_SETORIGIN_CAUGHT)
+ {
+ ent->priv.required->mark = 0;
+ return false;
+ }
+ else if(ent->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
+ {
+ ent->priv.required->mark = 0;
+ return true;
+ }
+ else
+ {
+ Con_Printf("The edict mark had been overwritten! Please debug this.\n");
+ return true;
+ }
}
trace_t trace, trace2;
matrix4x4_t pusherfinalmatrix, pusherfinalimatrix;
static unsigned short moved_edicts[MAX_EDICTS];
+ vec3_t pivot;
if (!PRVM_serveredictvector(pusher, velocity)[0] && !PRVM_serveredictvector(pusher, velocity)[1] && !PRVM_serveredictvector(pusher, velocity)[2] && !PRVM_serveredictvector(pusher, avelocity)[0] && !PRVM_serveredictvector(pusher, avelocity)[1] && !PRVM_serveredictvector(pusher, avelocity)[2])
{
// see if any solid entities are inside the final position
num_moved = 0;
- numcheckentities = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, checkentities);
+ if (PRVM_serveredictfloat(pusher, movetype) == MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push...
+ numcheckentities = 0;
+ else // MOVETYPE_PUSH
+ numcheckentities = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, checkentities);
for (e = 0;e < numcheckentities;e++)
{
prvm_edict_t *check = checkentities[e];
case MOVETYPE_PUSH:
case MOVETYPE_FOLLOW:
case MOVETYPE_NOCLIP:
- case MOVETYPE_FAKEPUSH:
+ case MOVETYPE_FLY_WORLDONLY:
continue;
default:
break;
}
}
+ VectorLerp(PRVM_serveredictvector(check, mins), 0.5f, PRVM_serveredictvector(check, maxs), pivot);
+ //VectorClear(pivot);
+
if (rotated)
{
vec3_t org2;
VectorSubtract (PRVM_serveredictvector(check, origin), PRVM_serveredictvector(pusher, origin), org);
+ VectorAdd (org, pivot, org);
org2[0] = DotProduct (org, forward);
org2[1] = DotProduct (org, left);
org2[2] = DotProduct (org, up);
Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents);
if (trace.startsolid)
{
- // try moving the contacted entity a tiny bit further to account for precision errors
vec3_t move2;
- PRVM_serveredictfloat(pusher, solid) = SOLID_NOT;
- VectorScale(move, 1.1, move2);
- VectorCopy (check->priv.server->moved_from, PRVM_serveredictvector(check, origin));
- VectorCopy (check->priv.server->moved_fromangles, PRVM_serveredictvector(check, angles));
- if(!SV_PushEntity (&trace2, check, move2, true, true))
+ if(SV_NudgeOutOfSolid_PivotIsKnownGood(check, pivot))
{
- // entity "check" got teleported
- continue;
- }
- PRVM_serveredictfloat(pusher, solid) = savesolid;
- Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents);
- if (trace.startsolid)
- {
- // try moving the contacted entity a tiny bit less to account for precision errors
- PRVM_serveredictfloat(pusher, solid) = SOLID_NOT;
- VectorScale(move, 0.9, move2);
- VectorCopy (check->priv.server->moved_from, PRVM_serveredictvector(check, origin));
- VectorCopy (check->priv.server->moved_fromangles, PRVM_serveredictvector(check, angles));
- if(!SV_PushEntity (&trace2, check, move2, true, true))
+ // hack to invoke all necessary movement triggers
+ VectorClear(move2);
+ if(!SV_PushEntity(&trace2, check, move2, true, true))
{
// entity "check" got teleported
continue;
}
- PRVM_serveredictfloat(pusher, solid) = savesolid;
- Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents);
- if (trace.startsolid)
- {
- // still inside pusher, so it's really blocked
-
- // fail the move
- if (PRVM_serveredictvector(check, mins)[0] == PRVM_serveredictvector(check, maxs)[0])
- continue;
- if (PRVM_serveredictfloat(check, solid) == SOLID_NOT || PRVM_serveredictfloat(check, solid) == SOLID_TRIGGER)
- {
- // corpse
- PRVM_serveredictvector(check, mins)[0] = PRVM_serveredictvector(check, mins)[1] = 0;
- VectorCopy (PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs));
- continue;
- }
-
- VectorCopy (pushorig, PRVM_serveredictvector(pusher, origin));
- VectorCopy (pushang, PRVM_serveredictvector(pusher, angles));
- PRVM_serveredictfloat(pusher, ltime) = pushltime;
- SV_LinkEdict(pusher);
-
- // move back any entities we already moved
- for (i = 0;i < num_moved;i++)
- {
- prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]);
- VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin));
- VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles));
- SV_LinkEdict(ed);
- }
-
- // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
- if (PRVM_serveredictfunction(pusher, blocked))
- {
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(pusher);
- PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(check);
- PRVM_ExecuteProgram (PRVM_serveredictfunction(pusher, blocked), "QC function self.blocked is missing");
- }
- break;
- }
+ // we could fix it
+ continue;
}
+
+ // still inside pusher, so it's really blocked
+
+ // fail the move
+ if (PRVM_serveredictvector(check, mins)[0] == PRVM_serveredictvector(check, maxs)[0])
+ continue;
+ if (PRVM_serveredictfloat(check, solid) == SOLID_NOT || PRVM_serveredictfloat(check, solid) == SOLID_TRIGGER)
+ {
+ // corpse
+ PRVM_serveredictvector(check, mins)[0] = PRVM_serveredictvector(check, mins)[1] = 0;
+ VectorCopy (PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs));
+ continue;
+ }
+
+ VectorCopy (pushorig, PRVM_serveredictvector(pusher, origin));
+ VectorCopy (pushang, PRVM_serveredictvector(pusher, angles));
+ PRVM_serveredictfloat(pusher, ltime) = pushltime;
+ SV_LinkEdict(pusher);
+
+ // move back any entities we already moved
+ for (i = 0;i < num_moved;i++)
+ {
+ prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]);
+ VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin));
+ VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles));
+ SV_LinkEdict(ed);
+ }
+
+ // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
+ if (PRVM_serveredictfunction(pusher, blocked))
+ {
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(pusher);
+ PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(check);
+ PRVM_ExecuteProgram (PRVM_serveredictfunction(pusher, blocked), "QC function self.blocked is missing");
+ }
+ break;
}
}
PRVM_serveredictvector(pusher, angles)[0] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[0] * (1.0 / 360.0));
if (sv.frametime <= 0)
return;
- SV_CheckStuck (ent);
+ if (sv_gameplayfix_unstickplayers.integer)
+ SV_CheckStuck (ent);
applygravity = !SV_CheckWater (ent) && PRVM_serveredictfloat(ent, movetype) == MOVETYPE_WALK && ! ((int)PRVM_serveredictfloat(ent, flags) & FL_WATERJUMP);
VectorSet(downmove, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2] - 1);
if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
+ else if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY)
+ type = MOVE_WORLDONLY;
else if (PRVM_serveredictfloat(ent, solid) == SOLID_TRIGGER || PRVM_serveredictfloat(ent, solid) == SOLID_NOT)
type = MOVE_NOMONSTERS; // only clip against bmodels
else
*/
void SV_CheckWaterTransition (prvm_edict_t *ent)
{
+ // LordHavoc: bugfixes in this function are keyed to the sv_gameplayfix_bugfixedcheckwatertransition cvar - if this cvar is 0 then all the original bugs should be reenabled for compatibility
int cont;
cont = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_serveredictvector(ent, origin)));
if (!PRVM_serveredictfloat(ent, watertype))
{
// just spawned here
- PRVM_serveredictfloat(ent, watertype) = cont;
- PRVM_serveredictfloat(ent, waterlevel) = 1;
- return;
+ if (!sv_gameplayfix_fixedcheckwatertransition.integer)
+ {
+ PRVM_serveredictfloat(ent, watertype) = cont;
+ PRVM_serveredictfloat(ent, waterlevel) = 1;
+ return;
+ }
}
-
// DRESK - Support for Entity Contents Transition Event
// NOTE: Call here BEFORE updating the watertype below,
// and suppress watersplash sound if a valid function
// call was made to allow for custom "splash" sounds.
- if( !SV_CheckContentsTransition(ent, cont) )
+ else if( !SV_CheckContentsTransition(ent, cont) )
{ // Contents Transition Function Invalid; Potentially Play Water Sound
// check if the entity crossed into or out of water
if (sv_sound_watersplash.string && ((PRVM_serveredictfloat(ent, watertype) == CONTENTS_WATER || PRVM_serveredictfloat(ent, watertype) == CONTENTS_SLIME) != (cont == CONTENTS_WATER || cont == CONTENTS_SLIME)))
- SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1);
+ SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, false, 1.0f);
}
if (cont <= CONTENTS_WATER)
else
{
PRVM_serveredictfloat(ent, watertype) = CONTENTS_EMPTY;
- PRVM_serveredictfloat(ent, waterlevel) = 0;
+ PRVM_serveredictfloat(ent, waterlevel) = sv_gameplayfix_fixedcheckwatertransition.integer ? 0 : cont;
}
}
Toss, bounce, and fly movement. When onground, do nothing.
=============
*/
+
void SV_Physics_Toss (prvm_edict_t *ent)
{
trace_t trace;
vec_t movetime;
int bump;
prvm_edict_t *groundentity;
+ float d, ent_gravity;
+ float bouncefactor;
+ float bouncestop;
// if onground, return without moving
if ((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND)
for (bump = 0;bump < MAX_CLIP_PLANES && movetime > 0;bump++)
{
// move origin
- VectorScale (PRVM_serveredictvector(ent, velocity), movetime, move);
- if(!SV_PushEntity (&trace, ent, move, true, true))
+ VectorScale(PRVM_serveredictvector(ent, velocity), movetime, move);
+ if(!SV_PushEntity(&trace, ent, move, true, true))
return; // teleported
if (ent->priv.server->free)
return;
if (trace.bmodelstartsolid)
{
// try to unstick the entity
- SV_UnstickEntity(ent);
- if(!SV_PushEntity (&trace, ent, move, false, true))
+ if (sv_gameplayfix_unstickentities.integer)
+ SV_UnstickEntity(ent);
+ if(!SV_PushEntity(&trace, ent, move, false, true))
return; // teleported
if (ent->priv.server->free)
return;
if (trace.fraction == 1)
break;
movetime *= 1 - min(1, trace.fraction);
- if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_BOUNCEMISSILE)
+ switch((int)PRVM_serveredictfloat(ent, movetype))
{
- float bouncefactor;
+ case MOVETYPE_BOUNCEMISSILE:
bouncefactor = PRVM_serveredictfloat(ent, bouncefactor);
if (!bouncefactor)
bouncefactor = 1.0f;
- ClipVelocity (PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1 + bouncefactor);
+ ClipVelocity(PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1 + bouncefactor);
PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
- }
- else if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_BOUNCE)
- {
- float d, ent_gravity;
- float bouncefactor;
- float bouncestop;
-
+ if (!sv_gameplayfix_slidemoveprojectiles.integer)
+ movetime = 0;
+ break;
+ case MOVETYPE_BOUNCE:
bouncefactor = PRVM_serveredictfloat(ent, bouncefactor);
if (!bouncefactor)
bouncefactor = 0.5f;
if (!bouncestop)
bouncestop = 60.0f / 800.0f;
- ClipVelocity (PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1 + bouncefactor);
+ ClipVelocity(PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1 + bouncefactor);
ent_gravity = PRVM_serveredictfloat(ent, gravity);
if (!ent_gravity)
ent_gravity = 1.0f;
// LordHavoc: fixed grenades not bouncing when fired down a slope
if (sv_gameplayfix_grenadebouncedownslopes.integer)
+ d = fabs(DotProduct(trace.plane.normal, PRVM_serveredictvector(ent, velocity)));
+ else
+ d = PRVM_serveredictvector(ent, velocity)[2];
+ if (trace.plane.normal[2] > 0.7 && d < sv_gravity.value * bouncestop * ent_gravity)
{
- d = DotProduct(trace.plane.normal, PRVM_serveredictvector(ent, velocity));
- if (trace.plane.normal[2] > 0.7 && fabs(d) < sv_gravity.value * bouncestop * ent_gravity)
- {
- PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
- PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
- VectorClear (PRVM_serveredictvector(ent, velocity));
- VectorClear (PRVM_serveredictvector(ent, avelocity));
- }
- else
- PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
+ PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
+ PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
+ VectorClear(PRVM_serveredictvector(ent, velocity));
+ VectorClear(PRVM_serveredictvector(ent, avelocity));
+ movetime = 0;
}
else
{
- if (trace.plane.normal[2] > 0.7 && PRVM_serveredictvector(ent, velocity)[2] < sv_gravity.value * bouncestop * ent_gravity)
- {
- PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
- PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
- VectorClear (PRVM_serveredictvector(ent, velocity));
- VectorClear (PRVM_serveredictvector(ent, avelocity));
- }
- else
- PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
+ PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
+ if (!sv_gameplayfix_slidemoveprojectiles.integer)
+ movetime = 0;
}
- }
- else
- {
+ break;
+ default:
ClipVelocity (PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1.0);
if (trace.plane.normal[2] > 0.7)
{
}
else
PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
- }
- if (!sv_gameplayfix_slidemoveprojectiles.integer || (PRVM_serveredictfloat(ent, movetype) != MOVETYPE_BOUNCE && PRVM_serveredictfloat(ent, movetype) == MOVETYPE_BOUNCEMISSILE) || ((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND))
+ movetime = 0;
break;
+ }
}
// check for in water
else
// Check for Engine Landing Sound
if(sv_sound_land.string)
- SV_StartSound(ent, 0, sv_sound_land.string, 255, 1);
+ SV_StartSound(ent, 0, sv_sound_land.string, 255, 1, false, 1.0f);
}
ent->priv.server->waterposition_forceupdate = true;
}
case MOVETYPE_BOUNCEMISSILE:
case MOVETYPE_FLYMISSILE:
case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
// regular thinking
if (SV_RunThink (ent))
SV_Physics_Toss (ent);
SV_Physics_Toss (ent);
break;
case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
SV_RunThink (ent);
SV_WalkMove (ent);
break;