// sv_phys.c
#include "quakedef.h"
+#include "prvm_cmds.h"
/*
void SV_Physics_Toss (prvm_edict_t *ent);
-int SV_GetPitchSign(prvm_edict_t *ent)
+int SV_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
{
dp_model_t *model;
if (
int SV_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
{
+ prvm_prog_t *prog = SVVM_prog;
if (passedict)
{
int dphitcontentsmask = (int)PRVM_serveredictfloat(passedict, dphitcontentsmask);
*/
trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, bodysupercontents;
int passedictprog;
float pitchsign = 1;
// 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
if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
{
model = SV_GetModelFromEdict(touch);
- pitchsign = SV_GetPitchSign(touch);
+ pitchsign = SV_GetPitchSign(prog, touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1);
else
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
- VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
else
trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
#endif
{
+ prvm_prog_t *prog = SVVM_prog;
int i, bodysupercontents;
int passedictprog;
float pitchsign = 1;
// 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
if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
{
model = SV_GetModelFromEdict(touch);
- pitchsign = SV_GetPitchSign(touch);
+ pitchsign = SV_GetPitchSign(prog, touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1);
else
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
- VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
#endif
#endif
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t hullmins, hullmaxs;
int i, bodysupercontents;
int passedictprog;
// 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
if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
{
model = SV_GetModelFromEdict(touch);
- pitchsign = SV_GetPitchSign(touch);
+ pitchsign = SV_GetPitchSign(prog, touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1);
else
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
- VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
int SV_PointSuperContents(const vec3_t point)
{
+ prvm_prog_t *prog = SVVM_prog;
int supercontents = 0;
int i;
prvm_edict_t *touch;
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)
+{
+ prvm_prog_t *prog = SVVM_prog;
+ 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_prog_t *prog = SVVM_prog;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(touch);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(ent);
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobalfloat(trace_dphitcontents) = 0;
PRVM_serverglobalfloat(trace_dphitq3surfaceflags) = 0;
PRVM_serverglobalstring(trace_dphittexturename) = 0;
- PRVM_ExecuteProgram (PRVM_serveredictfunction(touch, touch), "QC function self.touch is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(touch, touch), "QC function self.touch is missing");
}
void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, numtouchedicts, old_self, old_other;
prvm_edict_t *touch;
static prvm_edict_t *touchedicts[MAX_EDICTS];
// 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
*/
void SV_LinkEdict (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
dp_model_t *model;
vec3_t mins, maxs;
int modelindex;
}
model = SV_GetModelByIndex(modelindex);
- VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
+ VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
// set the abs box
*/
static int SV_TestEntityPosition (prvm_edict_t *ent, vec3_t offset)
{
+ prvm_prog_t *prog = SVVM_prog;
int contents;
vec3_t org;
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
return false;
}
-/*
-================
-SV_CheckAllEnts
-================
-*/
-void SV_CheckAllEnts (void)
-{
- int e;
- prvm_edict_t *check;
-
- // see if any solid entities are inside the final position
- check = PRVM_NEXT_EDICT(prog->edicts);
- for (e = 1;e < prog->num_edicts;e++, check = PRVM_NEXT_EDICT(check))
- {
- if (check->priv.server->free)
- continue;
- 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)
- continue;
-
- if (SV_TestEntityPosition (check, vec3_origin))
- Con_Print("entity in invalid position\n");
- }
-}
-
// DRESK - Support for Entity Contents Transition Event
/*
================
returns true if entity had a valid contentstransition function call
================
*/
-int SV_CheckContentsTransition(prvm_edict_t *ent, const int nContents)
+static int SV_CheckContentsTransition(prvm_edict_t *ent, const int nContents)
{
+ prvm_prog_t *prog = SVVM_prog;
int bValidFunctionCall;
// Default Valid Function Call to False
// Assign Valid Function
bValidFunctionCall = true;
// Prepare Parameters (Original Contents, New Contents)
- // Original Contents
- PRVM_G_FLOAT(OFS_PARM0) = PRVM_serveredictfloat(ent, watertype);
- // New Contents
- PRVM_G_FLOAT(OFS_PARM1) = nContents;
- // Assign Self
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ // Original Contents
+ PRVM_G_FLOAT(OFS_PARM0) = PRVM_serveredictfloat(ent, watertype);
+ // New Contents
+ PRVM_G_FLOAT(OFS_PARM1) = nContents;
+ // Assign Self
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ // Set Time
+ PRVM_serverglobalfloat(time) = sv.time;
// Execute VM Function
- PRVM_ExecuteProgram(PRVM_serveredictfunction(ent, contentstransition), "contentstransition: NULL function");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, contentstransition), "contentstransition: NULL function");
}
}
*/
void SV_CheckVelocity (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
float wishspeed;
{
if (IS_NAN(PRVM_serveredictvector(ent, velocity)[i]))
{
- Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
PRVM_serveredictvector(ent, velocity)[i] = 0;
}
if (IS_NAN(PRVM_serveredictvector(ent, origin)[i]))
{
- Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
PRVM_serveredictvector(ent, origin)[i] = 0;
}
}
Returns false if the entity removed itself.
=============
*/
-qboolean SV_RunThink (prvm_edict_t *ent)
+static qboolean SV_RunThink (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int iterations;
// don't let things stay in the past.
PRVM_serveredictfloat(ent, nextthink) = 0;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(prog->edicts);
- PRVM_ExecuteProgram (PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
// mods often set nextthink to time to cause a think every frame,
// we don't want to loop in that case, so exit if the new nextthink is
// <= the time the qc was told, also exit if it is past the end of the
Two entities have touched, so run their touch functions
==================
*/
-extern void VM_SetTraceGlobals(const trace_t *trace);
-extern sizebuf_t vm_tempstringsbuf;
-void SV_Impact (prvm_edict_t *e1, trace_t *trace)
+static void SV_Impact (prvm_edict_t *e1, trace_t *trace)
{
+ prvm_prog_t *prog = SVVM_prog;
int restorevm_tempstringsbuf_cursize;
int old_self, old_other;
prvm_edict_t *e2 = (prvm_edict_t *)trace->ent;
old_self = PRVM_serverglobaledict(self);
old_other = PRVM_serverglobaledict(other);
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
- VM_SetTraceGlobals(trace);
+ VM_SetTraceGlobals(prog, trace);
- PRVM_serverglobalfloat(time) = sv.time;
if (!e1->priv.server->free && !e2->priv.server->free && PRVM_serveredictfunction(e1, touch) && PRVM_serveredictfloat(e1, solid) != SOLID_NOT)
{
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(e1);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(e2);
- PRVM_ExecuteProgram (PRVM_serveredictfunction(e1, touch), "QC function self.touch is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(e1, touch), "QC function self.touch is missing");
}
if (!e1->priv.server->free && !e2->priv.server->free && PRVM_serveredictfunction(e2, touch) && PRVM_serveredictfloat(e2, solid) != SOLID_NOT)
{
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(e2);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(e1);
VectorCopy(PRVM_serveredictvector(e2, origin), PRVM_serverglobalvector(trace_endpos));
PRVM_serverglobalfloat(trace_dphitcontents) = 0;
PRVM_serverglobalfloat(trace_dphitq3surfaceflags) = 0;
PRVM_serverglobalstring(trace_dphittexturename) = 0;
- PRVM_ExecuteProgram (PRVM_serveredictfunction(e2, touch), "QC function self.touch is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(e2, touch), "QC function self.touch is missing");
}
PRVM_serverglobaledict(self) = old_self;
PRVM_serverglobaledict(other) = old_other;
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
}
==================
*/
#define STOP_EPSILON 0.1
-void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
+static void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
{
int i;
float backoff;
#define MAX_CLIP_PLANES 5
static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, float *stepnormal, int hitsupercontentsmask, float stepheight)
{
+ prvm_prog_t *prog = SVVM_prog;
int blocked, bumpcount;
int i, j, numplanes;
float d, time_left, gravity;
return 0;
gravity = 0;
- if(sv_gameplayfix_nogravityonground.integer)
- if((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND)
- applygravity = false;
-
- if (applygravity)
+ if(applygravity)
{
- if (sv_gameplayfix_gravityunaffectedbyticrate.integer)
- {
- gravity = SV_Gravity(ent) * 0.5f;
- PRVM_serveredictvector(ent, velocity)[2] -= gravity;
- }
- else
+ gravity = SV_Gravity(ent);
+
+ if(!sv_gameplayfix_nogravityonground.integer || !((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND))
{
- applygravity = false;
- PRVM_serveredictvector(ent, velocity)[2] -= SV_Gravity(ent);
+ if (sv_gameplayfix_gravityunaffectedbyticrate.integer)
+ PRVM_serveredictvector(ent, velocity)[2] -= gravity * 0.5f;
+ else
+ PRVM_serveredictvector(ent, velocity)[2] -= gravity;
}
}
+
blocked = 0;
VectorCopy(PRVM_serveredictvector(ent, velocity), original_velocity);
VectorCopy(PRVM_serveredictvector(ent, velocity), primal_velocity);
// LordHavoc: this came from QW and allows you to get out of water more easily
if (sv_gameplayfix_easierwaterjump.integer && ((int)PRVM_serveredictfloat(ent, flags) & FL_WATERJUMP) && !(blocked & 8))
VectorCopy(primal_velocity, PRVM_serveredictvector(ent, velocity));
- if (applygravity && !((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND))
- PRVM_serveredictvector(ent, velocity)[2] -= gravity;
+
+ if(applygravity)
+ {
+ if(!sv_gameplayfix_nogravityonground.integer || !((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND))
+ {
+ if (sv_gameplayfix_gravityunaffectedbyticrate.integer)
+ PRVM_serveredictvector(ent, velocity)[2] -= gravity * 0.5f;
+ }
+ }
+
return blocked;
}
*/
static float SV_Gravity (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
float ent_gravity;
ent_gravity = PRVM_serveredictfloat(ent, gravity);
===============================================================================
*/
+static qboolean SV_NudgeOutOfSolid_PivotIsKnownGood(prvm_edict_t *ent, vec3_t pivot)
+{
+ prvm_prog_t *prog = SVVM_prog;
+ 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)
+{
+ prvm_prog_t *prog = SVVM_prog;
+ 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
*/
static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink)
{
+ prvm_prog_t *prog = SVVM_prog;
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;
+ }
}
============
*/
-void SV_PushMove (prvm_edict_t *pusher, float movetime)
+static void SV_PushMove (prvm_edict_t *pusher, float movetime)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, e, index;
int pusherowner, pusherprog;
int checkcontents;
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_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(pusher);
+ PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(check);
+ prog->ExecuteProgram(prog, 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));
================
*/
-void SV_Physics_Pusher (prvm_edict_t *ent)
+static void SV_Physics_Pusher (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
float thinktime, oldltime, movetime;
oldltime = PRVM_serveredictfloat(ent, ltime);
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(prog->edicts);
- PRVM_ExecuteProgram (PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
}
}
}
unstickresult_t;
-unstickresult_t SV_UnstickEntityReturnOffset (prvm_edict_t *ent, vec3_t offset)
+static unstickresult_t SV_UnstickEntityReturnOffset (prvm_edict_t *ent, vec3_t offset)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, maxunstick;
// if not stuck in a bmodel, just return
qboolean SV_UnstickEntity (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t offset;
switch(SV_UnstickEntityReturnOffset(ent, offset))
{
case UNSTICK_GOOD:
return true;
case UNSTICK_UNSTUCK:
- Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
+ Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
return true;
case UNSTICK_STUCK:
if (developer_extra.integer)
- Con_DPrintf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_DPrintf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
return false;
default:
Con_Printf("SV_UnstickEntityReturnOffset returned a value outside its enum.\n");
clipping hull.
=============
*/
-void SV_CheckStuck (prvm_edict_t *ent)
+static void SV_CheckStuck (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t offset;
switch(SV_UnstickEntityReturnOffset(ent, offset))
VectorCopy (PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, oldorigin));
break;
case UNSTICK_UNSTUCK:
- Con_DPrintf("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
+ Con_DPrintf("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
break;
case UNSTICK_STUCK:
VectorSubtract(PRVM_serveredictvector(ent, oldorigin), PRVM_serveredictvector(ent, origin), offset);
if (!SV_TestEntityPosition(ent, offset))
{
- Con_DPrintf("Unstuck player entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_DPrintf("Unstuck player entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
SV_LinkEdict(ent);
//SV_LinkEdict_TouchAreaGrid(ent);
}
else
- Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
break;
default:
Con_Printf("SV_UnstickEntityReturnOffset returned a value outside its enum.\n");
SV_CheckWater
=============
*/
-qboolean SV_CheckWater (prvm_edict_t *ent)
+static qboolean SV_CheckWater (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int cont;
int nNativeContents;
vec3_t point;
============
*/
-void SV_WallFriction (prvm_edict_t *ent, float *stepnormal)
+static void SV_WallFriction (prvm_edict_t *ent, float *stepnormal)
{
+ prvm_prog_t *prog = SVVM_prog;
float d, i;
vec3_t forward, into, side;
Only used by players
======================
*/
-void SV_WalkMove (prvm_edict_t *ent)
+static void SV_WalkMove (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int clip;
int oldonground;
//int originalmove_clip;
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
Entities that are "stuck" to another entity
=============
*/
-void SV_Physics_Follow (prvm_edict_t *ent)
+static void SV_Physics_Follow (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t vf, vr, vu, angles, v;
prvm_edict_t *e;
=============
*/
-void SV_CheckWaterTransition (prvm_edict_t *ent)
+static void SV_CheckWaterTransition (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
+ // 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)
{
+ prvm_prog_t *prog = SVVM_prog;
trace_t trace;
vec3_t move;
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
will fall if the floor is pulled out from under them.
=============
*/
-void SV_Physics_Step (prvm_edict_t *ent)
+static void SV_Physics_Step (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int flags = (int)PRVM_serveredictfloat(ent, flags);
// DRESK
if(PRVM_serveredictfunction(ent, movetypesteplandevent))
{ // 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
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ // 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
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ // Set Time
+ PRVM_serverglobalfloat(time) = sv.time;
// Execute VM Function
- PRVM_ExecuteProgram(PRVM_serveredictfunction(ent, movetypesteplandevent), "movetypesteplandevent: NULL function");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, movetypesteplandevent), "movetypesteplandevent: NULL function");
}
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;
}
static void SV_Physics_Entity (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
// 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
case MOVETYPE_BOUNCEMISSILE:
case MOVETYPE_FLYMISSILE:
case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
// regular thinking
if (SV_RunThink (ent))
SV_Physics_Toss (ent);
void SV_Physics_ClientMove(void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *ent;
ent = host_client->edict;
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobalfloat(frametime) = 0;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
PRVM_serverglobalfloat(frametime) = sv.frametime;
// make sure the velocity is sane (not a NaN)
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobalfloat(frametime) = 0;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
PRVM_serverglobalfloat(frametime) = sv.frametime;
if(PRVM_serveredictfloat(ent, fixangle))
static void SV_Physics_ClientEntity_PreThink(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
if (!host_client->spawned)
return;
// call standard client pre-think
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram(PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
// make sure the velocity is still sane (not a NaN)
SV_CheckVelocity(ent);
static void SV_Physics_ClientEntity_PostThink(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
if (!host_client->spawned)
return;
// call standard player post-think
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram(PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
// make sure the velocity is still sane (not a NaN)
SV_CheckVelocity(ent);
static void SV_Physics_ClientEntity(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
if (!host_client->spawned)
{
SV_Physics_Toss (ent);
break;
case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
SV_RunThink (ent);
SV_WalkMove (ent);
break;
*/
void SV_Physics (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
prvm_edict_t *ent;
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(prog->edicts);
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobalfloat(frametime) = sv.frametime;
- PRVM_ExecuteProgram (PRVM_serverfunction(StartFrame), "QC function StartFrame is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(StartFrame), "QC function StartFrame is missing");
// run physics engine
World_Physics_Frame(&sv.world, sv.frametime, sv_gravity.value);
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(prog->edicts);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(prog->edicts);
PRVM_serverglobalfloat(time) = sv.time;
- PRVM_ExecuteProgram (PRVM_serverfunction(EndFrame), "QC function EndFrame is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(EndFrame), "QC function EndFrame is missing");
}
// decrement prog->num_edicts if the highest number entities died
- for (;PRVM_ED_CanAlloc(PRVM_EDICT_NUM(prog->num_edicts - 1));prog->num_edicts--);
+ for (;PRVM_ED_CanAlloc(prog, PRVM_EDICT_NUM(prog->num_edicts - 1));prog->num_edicts--);
if (!sv_freezenonclients.integer)
sv.time += sv.frametime;