int SV_GetPitchSign(prvm_edict_t *ent)
{
dp_model_t *model;
- int modelindex;
if (
- ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
+ (model = SV_GetModelFromEdict(ent))
?
model->type == mod_alias
:
model = NULL;
if ((int) touch->fields.server->solid == SOLID_BSP || type == MOVE_HITMODEL)
{
- unsigned int modelindex = (unsigned int)touch->fields.server->modelindex;
- // 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];
+ model = SV_GetModelFromEdict(touch);
pitchsign = SV_GetPitchSign(touch);
}
if (model)
else
Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
+ VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+ VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)touch->fields.server->flags & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
else
- Collision_ClipPointToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
+ Collision_ClipPointToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, hitsupercontentsmask);
Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.server->solid == SOLID_BSP);
}
vec3_t end;
vec_t len = 0;
- if(!VectorCompare(start, pEnd))
+ if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
{
// TRICK: make the trace 1 qu longer!
VectorSubtract(pEnd, start, end);
len = VectorNormalizeLength(end);
- VectorAdd(pEnd, end, end);
+ VectorMA(pEnd, collision_endposnudge.value, end, end);
}
else
VectorCopy(pEnd, end);
model = NULL;
if ((int) touch->fields.server->solid == SOLID_BSP || type == MOVE_HITMODEL)
{
- unsigned int modelindex = (unsigned int)touch->fields.server->modelindex;
- // 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];
+ model = SV_GetModelFromEdict(touch);
pitchsign = SV_GetPitchSign(touch);
}
if (model)
else
Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
+ VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+ VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)touch->fields.server->flags & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
- Collision_ClipLineToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask);
+ Collision_ClipLineToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask);
Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.server->solid == SOLID_BSP);
}
finished:
#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
- if(!VectorCompare(start, pEnd))
- Collision_ShortenTrace(&cliptrace, len / (len + 1), pEnd);
+ if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
+ Collision_ShortenTrace(&cliptrace, len / (len + collision_endposnudge.value), pEnd);
#endif
return cliptrace;
}
vec3_t end;
vec_t len = 0;
- if(!VectorCompare(start, pEnd))
+ if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
{
// TRICK: make the trace 1 qu longer!
VectorSubtract(pEnd, start, end);
len = VectorNormalizeLength(end);
- VectorAdd(pEnd, end, end);
+ VectorMA(pEnd, collision_endposnudge.value, end, end);
}
else
VectorCopy(pEnd, end);
model = NULL;
if ((int) touch->fields.server->solid == SOLID_BSP || type == MOVE_HITMODEL)
{
- unsigned int modelindex = (unsigned int)touch->fields.server->modelindex;
- // 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;
+ model = SV_GetModelFromEdict(touch);
pitchsign = SV_GetPitchSign(touch);
}
if (model)
else
Matrix4x4_CreateTranslate(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
+ VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
+ VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)touch->fields.server->flags & FL_MONSTER)
- Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
- Collision_ClipToGenericEntity(&trace, model, (int) touch->fields.server->frame, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
+ Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, touch->fields.server->mins, touch->fields.server->maxs, bodysupercontents, &matrix, &imatrix, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
Collision_CombineTraces(&cliptrace, &trace, (void *)touch, touch->fields.server->solid == SOLID_BSP);
}
finished:
#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
- if(!VectorCompare(start, pEnd))
- Collision_ShortenTrace(&cliptrace, len / (len + 1), pEnd);
+ if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
+ Collision_ShortenTrace(&cliptrace, len / (len + collision_endposnudge.value), pEnd);
#endif
return cliptrace;
}
matrix4x4_t matrix, imatrix;
// model of other entity
dp_model_t *model;
- unsigned int modelindex;
int frame;
// list of entities to test for collisions
int numtouchedicts;
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];
+ model = SV_GetModelFromEdict(touch);
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);
{
dp_model_t *model;
vec3_t mins, maxs;
+ int modelindex;
if (ent == prog->edicts)
return; // don't add the world
if (ent->priv.server->free)
return;
+ modelindex = (int)ent->fields.server->modelindex;
+ if (modelindex < 0 || modelindex >= MAX_MODELS)
+ {
+ Con_Printf("edict %i: SOLID_BSP with invalid modelindex!\n", PRVM_NUM_FOR_EDICT(ent));
+ modelindex = 0;
+ }
+ model = SV_GetModelByIndex(modelindex);
+
+ VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
+ VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
+ VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
+
// set the abs box
if (ent->fields.server->movetype == MOVETYPE_PHYSICS)
}
else if (ent->fields.server->solid == SOLID_BSP)
{
- int modelindex = (int)ent->fields.server->modelindex;
- if (modelindex < 0 || modelindex >= MAX_MODELS)
- {
- Con_Printf("edict %i: SOLID_BSP with invalid modelindex!\n", PRVM_NUM_FOR_EDICT(ent));
- modelindex = 0;
- }
- model = sv.models[modelindex];
if (model != NULL)
{
if (!model->TraceBox && developer.integer >= 1)
Con_Printf("SV_PushMove: entity #%i has an invalid modelindex %f\n", PRVM_NUM_FOR_EDICT(pusher), pusher->fields.server->modelindex);
return;
}
- pushermodel = sv.models[index];
+ pushermodel = SV_GetModelByIndex(index);
pusherowner = pusher->fields.server->owner;
pusherprog = PRVM_EDICT_TO_PROG(pusher);
pusher->fields.server->ltime += movetime;
SV_LinkEdict(pusher);
- pushermodel = NULL;
- if (pusher->fields.server->modelindex >= 1 && pusher->fields.server->modelindex < MAX_MODELS)
- pushermodel = sv.models[(int)pusher->fields.server->modelindex];
+ pushermodel = SV_GetModelFromEdict(pusher);
Matrix4x4_CreateFromQuakeEntity(&pusherfinalmatrix, pusher->fields.server->origin[0], pusher->fields.server->origin[1], pusher->fields.server->origin[2], pusher->fields.server->angles[0], pusher->fields.server->angles[1], pusher->fields.server->angles[2], 1);
Matrix4x4_Invert_Simple(&pusherfinalimatrix, &pusherfinalmatrix);
// 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, (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);
+ Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, 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_TraceBox(check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, MOVE_NOMONSTERS, check, checkcontents);
if (!trace.startsolid)
{
check->fields.server->flags = (int)check->fields.server->flags & ~FL_ONGROUND;
// if it is still inside the pusher, block
- 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);
+ Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, checkcontents);
if (trace.startsolid)
{
// try moving the contacted entity a tiny bit further to account for precision errors
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);
+ Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, checkcontents);
if (trace.startsolid)
{
// try moving the contacted entity a tiny bit less to account for precision errors
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);
+ Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, checkcontents);
if (trace.startsolid)
{
// still inside pusher, so it's really blocked
*/
void SV_WalkMove (prvm_edict_t *ent)
{
- int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity, hitsupercontentsmask;
+ int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity, hitsupercontentsmask, type;
vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity;
trace_t downtrace, trace;
qboolean applygravity;
clip = SV_FlyMove (ent, sv.frametime, applygravity, NULL, hitsupercontentsmask);
+ if(sv_gameplayfix_downtracesupportsongroundflag.integer)
+ if(!(clip & 1))
+ {
+ // only try this if there was no floor in the way in the trace (no,
+ // this check seems to be not REALLY necessary, because if clip & 1,
+ // our trace will hit that thing too)
+ VectorSet(upmove, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + 1);
+ VectorSet(downmove, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] - 1);
+ if (ent->fields.server->movetype == MOVETYPE_FLYMISSILE)
+ type = MOVE_MISSILE;
+ else if (ent->fields.server->solid == SOLID_TRIGGER || ent->fields.server->solid == SOLID_NOT)
+ type = MOVE_NOMONSTERS; // only clip against bmodels
+ else
+ type = MOVE_NORMAL;
+ trace = SV_TraceBox(upmove, ent->fields.server->mins, ent->fields.server->maxs, downmove, type, ent, SV_GenericHitSuperContentsMask(ent));
+ if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
+ clip |= 1; // but we HAVE found a floor
+ }
+
// if the move did not hit the ground at any point, we're not on ground
- if (!(clip & 1))
+ if(!(clip & 1))
ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
SV_CheckVelocity(ent);
vec3_t move;
vec_t movetime;
int bump;
+ prvm_edict_t *groundentity;
// if onground, return without moving
if ((int)ent->fields.server->flags & FL_ONGROUND)
{
+ groundentity = PRVM_PROG_TO_EDICT(ent->fields.server->groundentity);
if (ent->fields.server->velocity[2] >= (1.0 / 32.0) && sv_gameplayfix_upwardvelocityclearsongroundflag.integer)
{
// don't stick to ground if onground and moving upward
// we can trust FL_ONGROUND if groundentity is world because it never moves
return;
}
- else if (ent->priv.server->suspendedinairflag && PRVM_PROG_TO_EDICT(ent->fields.server->groundentity)->priv.server->free)
+ else if (ent->priv.server->suspendedinairflag && groundentity->priv.server->free)
{
// if ent was supported by a brush model on previous frame,
// and groundentity is now freed, set groundentity to 0 (world)
if (sv_gameplayfix_noairborncorpse_allowsuspendeditems.integer)
return;
}
+ else if (BoxesOverlap(ent->priv.server->cullmins, ent->priv.server->cullmaxs, groundentity->priv.server->cullmins, groundentity->priv.server->cullmaxs))
+ {
+ // don't slide if still touching the groundentity
+ return;
+ }
}
ent->priv.server->suspendedinairflag = false;
{
// freefall if onground and moving upward
// freefall if not standing on a world surface (it may be a lift or trap door)
- if ((ent->fields.server->velocity[2] >= (1.0 / 32.0) && sv_gameplayfix_upwardvelocityclearsongroundflag.integer) || ent->fields.server->groundentity)
+ if (ent->fields.server->velocity[2] >= (1.0 / 32.0) && sv_gameplayfix_upwardvelocityclearsongroundflag.integer)
{
ent->fields.server->flags -= FL_ONGROUND;
SV_CheckVelocity(ent);