mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 07:21:58 +00:00
Add avelocity support to MOVETYPE_PUSH entities, to go with rotated SOLID_BSP support (kinda pointless without this commit too tbh).
This commit is contained in:
parent
9d15653e46
commit
9278c740db
1 changed files with 213 additions and 0 deletions
213
Quake/sv_phys.c
213
Quake/sv_phys.c
|
@ -447,6 +447,210 @@ trace_t SV_PushEntity (edict_t *ent, vec3_t push)
|
|||
SV_PushMove
|
||||
============
|
||||
*/
|
||||
static qboolean SV_PushMoveAngles (edict_t *pusher, float movetime)
|
||||
{
|
||||
int i, e;
|
||||
edict_t *check, *block;
|
||||
vec3_t mins, maxs;
|
||||
//float oldsolid;
|
||||
vec3_t org, org2, move2, forward, right, up;
|
||||
vec3_t move, amove;
|
||||
struct {
|
||||
edict_t *ent;
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
} *pushed, *pushed_p, *p;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
move[i] = pusher->v.velocity[i] * movetime;
|
||||
amove[i] = pusher->v.avelocity[i] * movetime;
|
||||
mins[i] = pusher->v.absmin[i] + move[i];
|
||||
maxs[i] = pusher->v.absmax[i] + move[i];
|
||||
}
|
||||
|
||||
//using johnfitz's dynamic alloc strategy, consistent with SV_PushMove
|
||||
pushed_p = pushed = Hunk_Alloc (qcvm->num_edicts*sizeof(*pushed));
|
||||
|
||||
// find the bounding box
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
mins[i] = pusher->v.absmin[i] + move[i];
|
||||
maxs[i] = pusher->v.absmax[i] + move[i];
|
||||
}
|
||||
|
||||
// we need this for pushing things later
|
||||
VectorSubtract(vec3_origin, amove, org);
|
||||
AngleVectors (org, forward, right, up);
|
||||
|
||||
// save the pusher's original position
|
||||
pushed_p->ent = pusher;
|
||||
VectorCopy (pusher->v.origin, pushed_p->origin);
|
||||
VectorCopy (pusher->v.angles, pushed_p->angles);
|
||||
pushed_p++;
|
||||
|
||||
// move the pusher to it's final position
|
||||
VectorAdd (pusher->v.origin, move, pusher->v.origin);
|
||||
VectorAdd (pusher->v.angles, amove, pusher->v.angles);
|
||||
SV_LinkEdict (pusher, false);
|
||||
|
||||
// see if any solid entities are inside the final position
|
||||
check = NEXT_EDICT(qcvm->edicts);
|
||||
for (e = 1; e < qcvm->num_edicts; e++, check = NEXT_EDICT(check))
|
||||
{
|
||||
if (check->free)
|
||||
continue;
|
||||
|
||||
if (check->v.movetype == MOVETYPE_PUSH
|
||||
|| check->v.movetype == MOVETYPE_NONE
|
||||
|| check->v.movetype == MOVETYPE_NOCLIP
|
||||
|| check->v.movetype == MOVETYPE_ANGLENOCLIP)
|
||||
continue;
|
||||
/*
|
||||
oldsolid = pusher->v->solid;
|
||||
pusher->v->solid = SOLID_NOT;
|
||||
block = World_TestEntityPosition (w, check);
|
||||
pusher->v->solid = oldsolid;
|
||||
if (block)
|
||||
continue;
|
||||
*/
|
||||
// if the entity is standing on the pusher, it will definitely be moved
|
||||
if ( ! ( ((int)check->v.flags & FL_ONGROUND)
|
||||
&& PROG_TO_EDICT(check->v.groundentity) == pusher) )
|
||||
{
|
||||
// see if the ent needs to be tested
|
||||
if ( check->v.absmin[0] >= maxs[0]
|
||||
|| check->v.absmin[1] >= maxs[1]
|
||||
|| check->v.absmin[2] >= maxs[2]
|
||||
|| check->v.absmax[0] <= mins[0]
|
||||
|| check->v.absmax[1] <= mins[1]
|
||||
|| check->v.absmax[2] <= mins[2] )
|
||||
continue;
|
||||
|
||||
|
||||
// see if the ent's bbox is inside the pusher's final position
|
||||
if (!SV_TestEntityPosition (check))
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((pusher->v.movetype == MOVETYPE_PUSH) || (PROG_TO_EDICT(check->v.groundentity) == pusher))
|
||||
{
|
||||
// move this entity
|
||||
pushed_p->ent = check;
|
||||
VectorCopy (check->v.origin, pushed_p->origin);
|
||||
VectorCopy (check->v.angles, pushed_p->angles);
|
||||
pushed_p++;
|
||||
|
||||
// try moving the contacted entity
|
||||
VectorAdd (check->v.origin, move, check->v.origin);
|
||||
VectorAdd (check->v.angles, amove, check->v.angles);
|
||||
|
||||
// figure movement due to the pusher's amove
|
||||
VectorSubtract (check->v.origin, pusher->v.origin, org);
|
||||
org2[0] = DotProduct (org, forward);
|
||||
org2[1] = -DotProduct (org, right);
|
||||
org2[2] = DotProduct (org, up);
|
||||
VectorSubtract (org2, org, move2);
|
||||
VectorAdd (check->v.origin, move2, check->v.origin);
|
||||
|
||||
if (check->v.movetype != MOVETYPE_WALK)
|
||||
check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
|
||||
|
||||
// may have pushed them off an edge
|
||||
if (PROG_TO_EDICT(check->v.groundentity) != pusher)
|
||||
check->v.groundentity = 0;
|
||||
|
||||
block = SV_TestEntityPosition (check);
|
||||
if (!block)
|
||||
{ // pushed ok
|
||||
SV_LinkEdict (check, false);
|
||||
// impact?
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if it is ok to leave in the old position, do it
|
||||
// this is only relevent for riding entities, not pushed
|
||||
// FIXME: this doesn't acount for rotation
|
||||
VectorCopy (pushed_p[-1].origin, check->v.origin);
|
||||
block = SV_TestEntityPosition (check);
|
||||
if (!block)
|
||||
{
|
||||
pushed_p--;
|
||||
continue;
|
||||
}
|
||||
|
||||
//okay, that didn't work, try pushing the against stuff
|
||||
SV_PushEntity(check, move);
|
||||
block = SV_TestEntityPosition (check);
|
||||
if (!block)
|
||||
continue;
|
||||
|
||||
VectorCopy(check->v.origin, move);
|
||||
for (i = 0; i < 8 && block; i++)
|
||||
{
|
||||
//precision errors can strike when you least expect it. lets try and reduce them.
|
||||
check->v.origin[0] = move[0] + ((i&1)?-1:1)/8.0;
|
||||
check->v.origin[1] = move[1] + ((i&2)?-1:1)/8.0;
|
||||
check->v.origin[2] = move[2] + ((i&4)?-1:1)/8.0;
|
||||
block = SV_TestEntityPosition (check);
|
||||
}
|
||||
if (!block)
|
||||
{
|
||||
SV_LinkEdict (check, false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// if it is sitting on top. Do not block.
|
||||
if (check->v.mins[0] == check->v.maxs[0])
|
||||
{
|
||||
SV_LinkEdict (check, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
//some pushers are contents brushes, and are not solid. water cannot crush. the player just enters the water.
|
||||
//but, the player will be moved along with the water if possible.
|
||||
if (pusher->v.skin < 0)
|
||||
continue;
|
||||
|
||||
if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
|
||||
{ // corpse
|
||||
check->v.mins[0] = check->v.mins[1] = 0;
|
||||
VectorCopy (check->v.mins, check->v.maxs);
|
||||
SV_LinkEdict (check, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Con_Printf("Pusher hit %s\n", PR_GetString(w->progs, check->v->classname));
|
||||
if (pusher->v.blocked)
|
||||
{
|
||||
pr_global_struct->self = EDICT_TO_PROG(pusher);
|
||||
pr_global_struct->other = EDICT_TO_PROG(check);
|
||||
PR_ExecuteProgram (pusher->v.blocked);
|
||||
}
|
||||
|
||||
// move back any entities we already moved
|
||||
// go backwards, so if the same entity was pushed
|
||||
// twice, it goes back to the original position
|
||||
for (p=pushed_p-1 ; p>=pushed ; p--)
|
||||
{
|
||||
VectorCopy (p->origin, p->ent->v.origin);
|
||||
VectorCopy (p->angles, p->ent->v.angles);
|
||||
SV_LinkEdict (p->ent, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//FIXME: is there a better way to handle this?
|
||||
// see if anything we moved has touched a trigger
|
||||
for (p=pushed_p-1 ; p>=pushed ; p--)
|
||||
SV_LinkEdict (p->ent, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SV_PushMove (edict_t *pusher, float movetime)
|
||||
{
|
||||
int i, e;
|
||||
|
@ -459,6 +663,15 @@ void SV_PushMove (edict_t *pusher, float movetime)
|
|||
int mark; //johnfitz
|
||||
float solid_backup;
|
||||
|
||||
if ((pusher->v.avelocity[0] || pusher->v.avelocity[1] || pusher->v.avelocity[2]) && pr_checkextension.value)
|
||||
{ //spike -- added this block for proper rotations
|
||||
mark = Hunk_LowMark ();
|
||||
if (SV_PushMoveAngles (pusher, movetime))
|
||||
pusher->v.ltime += movetime;
|
||||
Hunk_FreeToLowMark (mark);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
|
||||
{
|
||||
pusher->v.ltime += movetime;
|
||||
|
|
Loading…
Reference in a new issue