vec3_t hullmins, hullmaxs;
int i, bodysupercontents;
int passedictprog;
+ float pitchsign;
qboolean pointtrace;
prvm_edict_t *traceowner, *touch;
trace_t trace;
// if the modelindex is 0, it shouldn't be SOLID_BSP!
if (modelindex > 0 && modelindex < MAX_MODELS)
model = sv.models[(int)touch->fields.server->modelindex];
+ pitchsign = 1;
+ if (
+ ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex]))
+ ?
+ model->type == mod_alias
+ :
+ (
+ (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
+ ||
+ ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32)))
+ )
+ )
+ pitchsign = -1;
}
if (model)
- Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
+ Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
else
Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
SV_Impact
Two entities have touched, so run their touch functions
+returns true if the impact kept the origin of the touching entity intact
==================
*/
extern void VM_SetTraceGlobals(const trace_t *trace);
extern sizebuf_t vm_tempstringsbuf;
-void SV_Impact (prvm_edict_t *e1, trace_t *trace)
+qboolean SV_Impact (prvm_edict_t *e1, trace_t *trace)
{
int restorevm_tempstringsbuf_cursize;
int old_self, old_other;
+ vec3_t org;
prvm_edict_t *e2 = (prvm_edict_t *)trace->ent;
prvm_eval_t *val;
old_other = prog->globals.server->other;
restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
+ VectorCopy(e1->fields.server->origin, org);
+
VM_SetTraceGlobals(trace);
prog->globals.server->time = sv.time;
prog->globals.server->self = old_self;
prog->globals.server->other = old_other;
vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+
+ return VectorCompare(e1->fields.server->origin, org);
}
============
*/
static float SV_Gravity (prvm_edict_t *ent);
-static trace_t SV_PushEntity (prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink);
+static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink);
// LordHavoc: increased from 5 to 32
#define MAX_CLIP_PLANES 32
static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, float *stepnormal, int hitsupercontentsmask)
#if 0
VectorAdd(ent->fields.server->origin, push, end);
#endif
- trace = SV_PushEntity(ent, push, false, false); // the caller calls SV_LinkEntity on the own later
-
- VectorCopy(trace.endpos, push); // convert to float for comparing
- if(!VectorCompare(push, ent->fields.server->origin))
+ if(!SV_PushEntity(&trace, ent, push, false, false))
{
// we got teleported by a touch function
// let's abort the move
SV_PushEntity
Does not change the entities velocity at all
+The trace struct is filled with the trace that has been done.
+Returns true if the push did not result in the entity being teleported by QC code.
============
*/
-static trace_t SV_PushEntity (prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink)
+static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink)
{
int type;
- trace_t trace;
vec3_t end;
qboolean impact;
else
type = MOVE_NORMAL;
- trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent));
- if (trace.bmodelstartsolid && failonbmodelstartsolid)
- return trace;
+ *trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent));
+ if (trace->bmodelstartsolid && failonbmodelstartsolid)
+ return true;
- VectorCopy (trace.endpos, ent->fields.server->origin);
+ VectorCopy (trace->endpos, ent->fields.server->origin);
- impact = (ent->fields.server->solid >= SOLID_TRIGGER && trace.ent && (!((int)ent->fields.server->flags & FL_ONGROUND) || ent->fields.server->groundentity != PRVM_EDICT_TO_PROG(trace.ent)));
+#if 0
+ if(!trace->startsolid)
+ if(SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, type, ent, SV_GenericHitSuperContentsMask(ent)).startsolid)
+ {
+ Con_Printf("something eeeeevil happened\n");
+ }
+#endif
+
+ impact = (ent->fields.server->solid >= SOLID_TRIGGER && trace->ent && (!((int)ent->fields.server->flags & FL_ONGROUND) || ent->fields.server->groundentity != PRVM_EDICT_TO_PROG(trace->ent)));
if(impact)
{
SV_LinkEdict (ent, dolink);
- SV_Impact (ent, &trace);
+ return SV_Impact (ent, trace);
}
else if(dolink)
SV_LinkEdict (ent, true);
- return trace;
+ return true;
}
int numcheckentities;
static prvm_edict_t *checkentities[MAX_EDICTS];
dp_model_t *pushermodel;
- trace_t trace;
+ trace_t trace, trace2;
matrix4x4_t pusherfinalmatrix, pusherfinalimatrix;
unsigned short moved_edicts[MAX_EDICTS];
// try moving the contacted entity
pusher->fields.server->solid = SOLID_NOT;
- trace = SV_PushEntity (check, move, true, true);
+ if(!SV_PushEntity (&trace, check, move, true, true))
+ {
+ // entity "check" got teleported
+ check->fields.server->angles[1] += trace.fraction * moveangle[1];
+ pusher->fields.server->solid = savesolid; // was SOLID_BSP
+ continue; // pushed enough
+ }
// FIXME: turn players specially
check->fields.server->angles[1] += trace.fraction * moveangle[1];
pusher->fields.server->solid = savesolid; // was SOLID_BSP
VectorScale(move, 1.1, move2);
VectorCopy (check->priv.server->moved_from, check->fields.server->origin);
VectorCopy (check->priv.server->moved_fromangles, check->fields.server->angles);
- SV_PushEntity (check, move2, true, true);
+ if(!SV_PushEntity (&trace2, check, move2, true, true))
+ {
+ // entity "check" got teleported
+ continue;
+ }
pusher->fields.server->solid = savesolid;
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)
VectorScale(move, 0.9, move2);
VectorCopy (check->priv.server->moved_from, check->fields.server->origin);
VectorCopy (check->priv.server->moved_fromangles, check->fields.server->angles);
- SV_PushEntity (check, move2, true, true);
+ if(!SV_PushEntity (&trace2, check, move2, true, true))
+ {
+ // entity "check" got teleported
+ continue;
+ }
pusher->fields.server->solid = savesolid;
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)
case 7: dir[0] = -2; dir[1] = -2; break;
}
- SV_PushEntity (ent, dir, false, true);
+ SV_PushEntity (&trace, ent, dir, false, true);
// retry the original move
ent->fields.server->velocity[0] = oldvel[0];
{
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;
+ trace_t downtrace, trace;
qboolean applygravity;
// if frametime is 0 (due to client sending the same timestamp twice),
// move up
VectorClear (upmove);
upmove[2] = sv_stepheight.value;
- SV_PushEntity(ent, upmove, false, true);
+ if(!SV_PushEntity(&trace, ent, upmove, false, true))
+ {
+ // we got teleported when upstepping... must abort the move
+ return;
+ }
// move forward
ent->fields.server->velocity[2] = 0;
clip = SV_FlyMove (ent, sv.frametime, applygravity, stepnormal, hitsupercontentsmask);
ent->fields.server->velocity[2] += start_velocity[2];
+ if(clip & 8)
+ {
+ // we got teleported when upstepping... must abort the move
+ // note that z velocity handling may not be what QC expects here, but we cannot help it
+ return;
+ }
SV_CheckVelocity(ent);
SV_LinkEdict (ent, true);
// move down
VectorClear (downmove);
downmove[2] = -sv_stepheight.value + start_velocity[2]*sv.frametime;
- downtrace = SV_PushEntity (ent, downmove, false, true);
+ if(!SV_PushEntity (&downtrace, ent, downmove, false, true))
+ {
+ // we got teleported when downstepping... must abort the move
+ return;
+ }
if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7)
{
{
// move origin
VectorScale (ent->fields.server->velocity, movetime, move);
- trace = SV_PushEntity (ent, move, true, true);
+ 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);
- trace = SV_PushEntity (ent, move, false, true);
+ if(!SV_PushEntity (&trace, ent, move, false, true))
+ return; // teleported
if (ent->priv.server->free)
return;
}