Use Path traversal if sweep lines fail
Not very pretty with lots of duped code but it works? Designed to handle collision line sweep miss edgecases as they occur until line sweeps can be improved
This commit is contained in:
parent
4192ca3da6
commit
89f0ef836b
3 changed files with 630 additions and 19 deletions
|
|
@ -7001,7 +7001,7 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
cur->flags &= ~MF_NOCLIPTHING;
|
||||
|
||||
if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true, &result))
|
||||
P_SlideMove(cur,&result);
|
||||
P_SlideMoveOLD(cur);
|
||||
|
||||
if (P_IsObjectOnGround(player->mo))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -500,6 +500,7 @@ boolean P_Move(mobj_t *actor, fixed_t speed);
|
|||
boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
void P_SlideMove(mobj_t *mo, TryMoveResult_t *result);
|
||||
void P_SlideMoveOLD(mobj_t *mo);
|
||||
void P_BounceMove(mobj_t *mo, TryMoveResult_t *result);
|
||||
boolean P_CheckSight(mobj_t *t1, mobj_t *t2);
|
||||
boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2);
|
||||
|
|
|
|||
646
src/p_map.c
646
src/p_map.c
|
|
@ -3100,7 +3100,9 @@ static boolean P_ThingHeightClip(mobj_t *thing)
|
|||
// SLIDE MOVE
|
||||
// Allows the player to slide along any angled walls.
|
||||
//
|
||||
static fixed_t bestslidefrac, secondslidefrac;
|
||||
static line_t *bestslideline;
|
||||
static line_t *secondslideline;
|
||||
static mobj_t *slidemo;
|
||||
static fixed_t tmxmove, tmymove;
|
||||
|
||||
|
|
@ -3170,6 +3172,41 @@ static void P_PlayerHitBounceLine(line_t *ld, vector2_t* normal)
|
|||
}
|
||||
}
|
||||
|
||||
static void P_PlayerHitBounceLineOLD(line_t *ld)
|
||||
{
|
||||
INT32 side;
|
||||
angle_t lineangle;
|
||||
fixed_t movelen;
|
||||
fixed_t x, y;
|
||||
|
||||
side = P_PointOnLineSide(slidemo->x, slidemo->y, ld);
|
||||
lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy)-ANGLE_90;
|
||||
|
||||
if (side == 1)
|
||||
lineangle += ANGLE_180;
|
||||
|
||||
lineangle >>= ANGLETOFINESHIFT;
|
||||
|
||||
movelen = P_AproxDistance(tmxmove, tmymove);
|
||||
|
||||
if (slidemo->player && movelen < (15*mapobjectscale))
|
||||
movelen = (15*mapobjectscale);
|
||||
|
||||
x = FixedMul(movelen, FINECOSINE(lineangle));
|
||||
y = FixedMul(movelen, FINESINE(lineangle));
|
||||
|
||||
if (ld && P_IsLineTripWire(ld))
|
||||
{
|
||||
tmxmove = FixedMul(x, FRACUNIT+(FRACUNIT/2));
|
||||
tmymove = FixedMul(y, FRACUNIT+(FRACUNIT/2));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmxmove += x;
|
||||
tmymove += y;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_HitBounceLine
|
||||
//
|
||||
|
|
@ -3211,7 +3248,6 @@ static void P_HitBounceLine(line_t *ld)
|
|||
deltaangle = R_PointToAngle2(0, 0, tmxmove, tmymove);
|
||||
}
|
||||
|
||||
/*
|
||||
static boolean PTR_LineIsBlocking(line_t *li)
|
||||
{
|
||||
opening_t open = {0};
|
||||
|
|
@ -3237,9 +3273,7 @@ static boolean PTR_LineIsBlocking(line_t *li)
|
|||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static boolean PTR_SlideTraverse(intercept_t *in)
|
||||
{
|
||||
line_t *li;
|
||||
|
|
@ -3269,7 +3303,6 @@ static boolean PTR_SlideTraverse(intercept_t *in)
|
|||
|
||||
return false; // stop
|
||||
}
|
||||
*/
|
||||
|
||||
static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
|
||||
{
|
||||
|
|
@ -3405,7 +3438,28 @@ void P_SlideMove(mobj_t *mo, TryMoveResult_t *result)
|
|||
bestslideline = result->line;
|
||||
|
||||
if (bestslideline == NULL)
|
||||
{
|
||||
if (cv_showgremlins.value)
|
||||
{
|
||||
// debug
|
||||
mobj_t*x = P_SpawnMobj(mo->x, mo->y, mo->z, MT_THOK);
|
||||
x->frame = FF_FULLBRIGHT | FF_ADD;
|
||||
x->renderflags = RF_ALWAYSONTOP;
|
||||
x->color = SKINCOLOR_RED;
|
||||
|
||||
CONS_Printf(
|
||||
"SLIDE GREMLIN: leveltime=%u x=%f y=%f z=%f",
|
||||
leveltime,
|
||||
FixedToFloat(mo->x),
|
||||
FixedToFloat(mo->y),
|
||||
FixedToFloat(mo->z)
|
||||
);
|
||||
}
|
||||
|
||||
// We were not succesful, try the old version.
|
||||
P_SlideMoveOLD(mo);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff)
|
||||
{
|
||||
|
|
@ -3469,12 +3523,390 @@ papercollision:
|
|||
} while(tmxmove || tmymove);
|
||||
}
|
||||
|
||||
void P_SlideMoveOLD(mobj_t *mo)
|
||||
{
|
||||
fixed_t leadx, leady, trailx, traily, newx, newy;
|
||||
INT16 hitcount = 0;
|
||||
boolean success = false;
|
||||
|
||||
boolean papercol = false;
|
||||
vertex_t v1, v2; // fake vertexes
|
||||
static line_t junk; // fake linedef
|
||||
|
||||
memset(&junk, 0x00, sizeof(junk));
|
||||
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
if (g_tm.hitthing && mo->z + mo->height > g_tm.hitthing->z && mo->z < g_tm.hitthing->z + g_tm.hitthing->height)
|
||||
{
|
||||
// Don't mess with your momentum if it's a pushable object. Pushables do their own crazy things already.
|
||||
if (g_tm.hitthing->flags & MF_PUSHABLE)
|
||||
return;
|
||||
|
||||
if (g_tm.hitthing->flags & MF_PAPERCOLLISION)
|
||||
{
|
||||
fixed_t cosradius, sinradius, num, den;
|
||||
|
||||
// trace along the three leading corners
|
||||
if (mo->momx > 0)
|
||||
{
|
||||
leadx = mo->x + mo->radius;
|
||||
trailx = mo->x - mo->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leadx = mo->x - mo->radius;
|
||||
trailx = mo->x + mo->radius;
|
||||
}
|
||||
|
||||
if (mo->momy > 0)
|
||||
{
|
||||
leady = mo->y + mo->radius;
|
||||
traily = mo->y - mo->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leady = mo->y - mo->radius;
|
||||
traily = mo->y + mo->radius;
|
||||
}
|
||||
|
||||
papercol = true;
|
||||
slidemo = mo;
|
||||
bestslideline = &junk;
|
||||
|
||||
cosradius = FixedMul(g_tm.hitthing->radius, FINECOSINE(g_tm.hitthing->angle>>ANGLETOFINESHIFT));
|
||||
sinradius = FixedMul(g_tm.hitthing->radius, FINESINE(g_tm.hitthing->angle>>ANGLETOFINESHIFT));
|
||||
|
||||
v1.x = g_tm.hitthing->x - cosradius;
|
||||
v1.y = g_tm.hitthing->y - sinradius;
|
||||
v2.x = g_tm.hitthing->x + cosradius;
|
||||
v2.y = g_tm.hitthing->y + sinradius;
|
||||
|
||||
// Can we box collision our way into smooth movement..?
|
||||
if (sinradius && mo->y + mo->radius <= min(v1.y, v2.y))
|
||||
{
|
||||
mo->momy = 0;
|
||||
P_TryMove(mo, mo->x + mo->momx, min(v1.y, v2.y) - mo->radius, true, NULL);
|
||||
return;
|
||||
}
|
||||
else if (sinradius && mo->y - mo->radius >= max(v1.y, v2.y))
|
||||
{
|
||||
mo->momy = 0;
|
||||
P_TryMove(mo, mo->x + mo->momx, max(v1.y, v2.y) + mo->radius, true, NULL);
|
||||
return;
|
||||
}
|
||||
else if (cosradius && mo->x + mo->radius <= min(v1.x, v2.x))
|
||||
{
|
||||
mo->momx = 0;
|
||||
P_TryMove(mo, min(v1.x, v2.x) - mo->radius, mo->y + mo->momy, true, NULL);
|
||||
return;
|
||||
}
|
||||
else if (cosradius && mo->x - mo->radius >= max(v1.x, v2.x))
|
||||
{
|
||||
mo->momx = 0;
|
||||
P_TryMove(mo, max(v1.x, v2.x) + mo->radius, mo->y + mo->momy, true, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// nope, gotta fuck around with a fake linedef!
|
||||
junk.v1 = &v1;
|
||||
junk.v2 = &v2;
|
||||
junk.dx = 2*cosradius; // v2.x - v1.x;
|
||||
junk.dy = 2*sinradius; // v2.y - v1.y;
|
||||
|
||||
junk.slopetype = !cosradius ? ST_VERTICAL : !sinradius ? ST_HORIZONTAL :
|
||||
((sinradius > 0) == (cosradius > 0)) ? ST_POSITIVE : ST_NEGATIVE;
|
||||
|
||||
bestslidefrac = FRACUNIT+1;
|
||||
|
||||
den = FixedMul(junk.dy>>8, mo->momx) - FixedMul(junk.dx>>8, mo->momy);
|
||||
|
||||
if (!den)
|
||||
bestslidefrac = 0;
|
||||
else
|
||||
{
|
||||
fixed_t frac;
|
||||
#define P_PaperTraverse(startx, starty) \
|
||||
num = FixedMul((v1.x - leadx)>>8, junk.dy) + FixedMul((leady - v1.y)>>8, junk.dx); \
|
||||
frac = FixedDiv(num, den); \
|
||||
if (frac < bestslidefrac) \
|
||||
bestslidefrac = frac
|
||||
P_PaperTraverse(leadx, leady);
|
||||
P_PaperTraverse(trailx, leady);
|
||||
P_PaperTraverse(leadx, traily);
|
||||
#undef dowork
|
||||
}
|
||||
|
||||
goto papercollision;
|
||||
}
|
||||
|
||||
// Thankfully box collisions are a lot simpler than arbitrary lines. There's only four possible cases.
|
||||
if (mo->y + mo->radius <= g_tm.hitthing->y - g_tm.hitthing->radius)
|
||||
{
|
||||
mo->momy = 0;
|
||||
P_TryMove(mo, mo->x + mo->momx, g_tm.hitthing->y - g_tm.hitthing->radius - mo->radius, true, NULL);
|
||||
}
|
||||
else if (mo->y - mo->radius >= g_tm.hitthing->y + g_tm.hitthing->radius)
|
||||
{
|
||||
mo->momy = 0;
|
||||
P_TryMove(mo, mo->x + mo->momx, g_tm.hitthing->y + g_tm.hitthing->radius + mo->radius, true, NULL);
|
||||
}
|
||||
else if (mo->x + mo->radius <= g_tm.hitthing->x - g_tm.hitthing->radius)
|
||||
{
|
||||
mo->momx = 0;
|
||||
P_TryMove(mo, g_tm.hitthing->x - g_tm.hitthing->radius - mo->radius, mo->y + mo->momy, true, NULL);
|
||||
}
|
||||
else if (mo->x - mo->radius >= g_tm.hitthing->x + g_tm.hitthing->radius)
|
||||
{
|
||||
mo->momx = 0;
|
||||
P_TryMove(mo, g_tm.hitthing->x + g_tm.hitthing->radius + mo->radius, mo->y + mo->momy, true, NULL);
|
||||
}
|
||||
else
|
||||
mo->momx = mo->momy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
slidemo = mo;
|
||||
bestslideline = NULL;
|
||||
|
||||
retry:
|
||||
if ((++hitcount == 3) || papercol)
|
||||
{
|
||||
if (!P_MobjWasRemoved(mo))
|
||||
{
|
||||
// the move must have hit the middle, so stairstep
|
||||
if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true, NULL)) //Allow things to drop off.
|
||||
P_TryMove(mo, mo->x + mo->momx, mo->y, true, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// trace along the three leading corners
|
||||
if (mo->momx > 0)
|
||||
{
|
||||
leadx = mo->x + mo->radius;
|
||||
trailx = mo->x - mo->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leadx = mo->x - mo->radius;
|
||||
trailx = mo->x + mo->radius;
|
||||
}
|
||||
|
||||
if (mo->momy > 0)
|
||||
{
|
||||
leady = mo->y + mo->radius;
|
||||
traily = mo->y - mo->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leady = mo->y - mo->radius;
|
||||
traily = mo->y + mo->radius;
|
||||
}
|
||||
|
||||
bestslidefrac = FRACUNIT+1;
|
||||
|
||||
P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy,
|
||||
PT_ADDLINES, PTR_SlideTraverse);
|
||||
P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy,
|
||||
PT_ADDLINES, PTR_SlideTraverse);
|
||||
P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy,
|
||||
PT_ADDLINES, PTR_SlideTraverse);
|
||||
|
||||
if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff)
|
||||
{
|
||||
sector_t *sec = P_PointOnLineSide(mo->x, mo->y, bestslideline) ? bestslideline->frontsector : bestslideline->backsector;
|
||||
P_CheckLavaWall(mo, sec);
|
||||
}
|
||||
|
||||
papercollision:
|
||||
// move up to the wall
|
||||
if (bestslidefrac == FRACUNIT+1)
|
||||
{
|
||||
if (!P_MobjWasRemoved(mo))
|
||||
{
|
||||
// the move must have hit the middle, so stairstep
|
||||
if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true, NULL)) //Allow things to drop off.
|
||||
P_TryMove(mo, mo->x + mo->momx, mo->y, true, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// fudge a bit to make sure it doesn't hit
|
||||
bestslidefrac -= 0x800;
|
||||
if (bestslidefrac > 0)
|
||||
{
|
||||
newx = FixedMul(mo->momx, bestslidefrac);
|
||||
newy = FixedMul(mo->momy, bestslidefrac);
|
||||
|
||||
if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true, NULL))
|
||||
{
|
||||
if (!P_MobjWasRemoved(mo))
|
||||
{
|
||||
if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true, NULL)) //Allow things to drop off.
|
||||
P_TryMove(mo, mo->x + mo->momx, mo->y, true, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (P_MobjWasRemoved(mo))
|
||||
return;
|
||||
}
|
||||
|
||||
// Now continue along the wall.
|
||||
// First calculate remainder.
|
||||
bestslidefrac = FRACUNIT - (bestslidefrac+0x800);
|
||||
|
||||
if (bestslidefrac > FRACUNIT)
|
||||
bestslidefrac = FRACUNIT;
|
||||
|
||||
if (bestslidefrac <= 0)
|
||||
return;
|
||||
|
||||
tmxmove = FixedMul(mo->momx, bestslidefrac);
|
||||
tmymove = FixedMul(mo->momy, bestslidefrac);
|
||||
|
||||
P_HitSlideLine(bestslideline); // clip the moves
|
||||
|
||||
mo->momx = tmxmove;
|
||||
mo->momy = tmymove;
|
||||
|
||||
const fixed_t tmradius = mo->radius > 8 ? mo->radius : 8;
|
||||
|
||||
do {
|
||||
if (tmxmove > tmradius) {
|
||||
newx = mo->x + tmradius;
|
||||
tmxmove -= tmradius;
|
||||
} else if (tmxmove < -tmradius) {
|
||||
newx = mo->x - tmradius;
|
||||
tmxmove += tmradius;
|
||||
} else {
|
||||
newx = mo->x + tmxmove;
|
||||
tmxmove = 0;
|
||||
}
|
||||
if (tmymove > tmradius) {
|
||||
newy = mo->y + tmradius;
|
||||
tmymove -= tmradius;
|
||||
} else if (tmymove < -tmradius) {
|
||||
newy = mo->y - tmradius;
|
||||
tmymove += tmradius;
|
||||
} else {
|
||||
newy = mo->y + tmymove;
|
||||
tmymove = 0;
|
||||
}
|
||||
if (!P_TryMove(mo, newx, newy, true, NULL)) {
|
||||
if (success || P_MobjWasRemoved(mo))
|
||||
return; // Good enough!!
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
if (P_MobjWasRemoved(mo))
|
||||
return;
|
||||
success = true;
|
||||
} while(tmxmove || tmymove);
|
||||
}
|
||||
|
||||
//
|
||||
// P_BouncePlayerMove
|
||||
//
|
||||
// Bounce move, for players.
|
||||
//
|
||||
|
||||
static void P_BouncePlayerMoveOLD(mobj_t *mo)
|
||||
{
|
||||
fixed_t leadx, leady;
|
||||
fixed_t trailx, traily;
|
||||
fixed_t mmomx = 0, mmomy = 0;
|
||||
fixed_t oldmomx = mo->momx, oldmomy = mo->momy;
|
||||
|
||||
if (!mo->player)
|
||||
return;
|
||||
|
||||
slidemo = mo;
|
||||
|
||||
mmomx = mo->player->rmomx;
|
||||
mmomy = mo->player->rmomy;
|
||||
|
||||
// trace along the three leading corners
|
||||
if (mo->momx > 0)
|
||||
{
|
||||
leadx = mo->x + mo->radius;
|
||||
trailx = mo->x - mo->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leadx = mo->x - mo->radius;
|
||||
trailx = mo->x + mo->radius;
|
||||
}
|
||||
|
||||
if (mo->momy > 0)
|
||||
{
|
||||
leady = mo->y + mo->radius;
|
||||
traily = mo->y - mo->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leady = mo->y - mo->radius;
|
||||
traily = mo->y + mo->radius;
|
||||
}
|
||||
|
||||
bestslidefrac = FRACUNIT + 1;
|
||||
|
||||
P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
|
||||
// Now continue along the wall.
|
||||
// First calculate remainder.
|
||||
bestslidefrac = FRACUNIT - bestslidefrac;
|
||||
|
||||
if (bestslidefrac > FRACUNIT)
|
||||
bestslidefrac = FRACUNIT;
|
||||
|
||||
if (bestslidefrac <= 0)
|
||||
return;
|
||||
|
||||
if (mo->eflags & MFE_JUSTBOUNCEDWALL) // Stronger push-out
|
||||
{
|
||||
tmxmove = mmomx;
|
||||
tmymove = mmomy;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
|
||||
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
|
||||
}
|
||||
|
||||
if (bestslideline && P_IsLineTripWire(bestslideline))
|
||||
{
|
||||
// TRIPWIRE CANNOT BE MADE NONBOUNCY
|
||||
K_ApplyTripWire(mo->player, TRIPSTATE_BLOCKED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Some walls aren't bouncy even if you are
|
||||
if (bestslideline && (bestslideline->flags & ML_NOTBOUNCY))
|
||||
{
|
||||
// SRB2Kart: Non-bouncy line!
|
||||
P_SlideMoveOLD(mo);
|
||||
return;
|
||||
}
|
||||
|
||||
K_SpawnBumpEffect(mo);
|
||||
}
|
||||
|
||||
P_PlayerHitBounceLineOLD(bestslideline);
|
||||
mo->eflags |= MFE_JUSTBOUNCEDWALL;
|
||||
|
||||
mo->momx = tmxmove;
|
||||
mo->momy = tmymove;
|
||||
mo->player->cmomx = tmxmove;
|
||||
mo->player->cmomy = tmymove;
|
||||
|
||||
if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true, NULL)) {
|
||||
P_TryMove(mo, mo->x - oldmomx, mo->y - oldmomy, true, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
|
||||
{
|
||||
fixed_t mmomx = 0, mmomy = 0;
|
||||
|
|
@ -3487,7 +3919,9 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
|
|||
return;
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mo->player->spectator)
|
||||
{
|
||||
|
|
@ -3512,25 +3946,38 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
|
|||
mo->player->pogospring = 0;
|
||||
}
|
||||
|
||||
if (G_CompatLevel(0x0002))
|
||||
{
|
||||
P_BouncePlayerMoveOLD(mo);
|
||||
return;
|
||||
}
|
||||
|
||||
slidemo = mo;
|
||||
bestslideline = result->line;
|
||||
|
||||
if (bestslideline == NULL && cv_showgremlins.value)
|
||||
if (bestslideline == NULL)
|
||||
{
|
||||
// debug
|
||||
mobj_t*x = P_SpawnMobj(mo->x, mo->y, mo->z, MT_THOK);
|
||||
x->frame = FF_FULLBRIGHT | FF_ADD;
|
||||
x->renderflags = RF_ALWAYSONTOP;
|
||||
x->color = SKINCOLOR_RED;
|
||||
if (cv_showgremlins.value)
|
||||
{
|
||||
// debug
|
||||
mobj_t*x = P_SpawnMobj(mo->x, mo->y, mo->z, MT_THOK);
|
||||
x->frame = FF_FULLBRIGHT | FF_ADD;
|
||||
x->renderflags = RF_ALWAYSONTOP;
|
||||
x->color = SKINCOLOR_RED;
|
||||
|
||||
CONS_Printf(
|
||||
"GREMLIN: leveltime=%u x=%f y=%f z=%f angle=%f\n",
|
||||
leveltime,
|
||||
FixedToFloat(mo->x),
|
||||
FixedToFloat(mo->y),
|
||||
FixedToFloat(mo->z),
|
||||
AngleToFloat(R_PointToAngle2(0, 0, oldmomx, oldmomy))
|
||||
);
|
||||
CONS_Printf(
|
||||
"BOUNCEPLAYER GREMLIN: leveltime=%u x=%f y=%f z=%f angle=%f\n",
|
||||
leveltime,
|
||||
FixedToFloat(mo->x),
|
||||
FixedToFloat(mo->y),
|
||||
FixedToFloat(mo->z),
|
||||
AngleToFloat(R_PointToAngle2(0, 0, oldmomx, oldmomy))
|
||||
);
|
||||
}
|
||||
|
||||
// We were not succesful, try the old version.
|
||||
P_BouncePlayerMoveOLD(mo);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mo->eflags & MFE_JUSTBOUNCEDWALL) // Stronger push-out
|
||||
|
|
@ -3584,6 +4031,149 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
|
|||
//
|
||||
// The momx / momy move is bad, so try to bounce off a wall.
|
||||
//
|
||||
|
||||
static void P_BounceMoveOLD(mobj_t *mo)
|
||||
{
|
||||
fixed_t leadx, leady;
|
||||
fixed_t trailx, traily;
|
||||
fixed_t newx, newy;
|
||||
INT32 hitcount;
|
||||
fixed_t mmomx = 0, mmomy = 0;
|
||||
|
||||
slidemo = mo;
|
||||
hitcount = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (++hitcount == 3)
|
||||
goto bounceback; // don't loop forever
|
||||
|
||||
if (mo->player)
|
||||
{
|
||||
mmomx = mo->player->rmomx;
|
||||
mmomy = mo->player->rmomy;
|
||||
}
|
||||
else
|
||||
{
|
||||
mmomx = mo->momx;
|
||||
mmomy = mo->momy;
|
||||
}
|
||||
|
||||
// trace along the three leading corners
|
||||
if (mo->momx > 0)
|
||||
{
|
||||
leadx = mo->x + mo->radius;
|
||||
trailx = mo->x - mo->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leadx = mo->x - mo->radius;
|
||||
trailx = mo->x + mo->radius;
|
||||
}
|
||||
|
||||
if (mo->momy > 0)
|
||||
{
|
||||
leady = mo->y + mo->radius;
|
||||
traily = mo->y - mo->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leady = mo->y - mo->radius;
|
||||
traily = mo->y + mo->radius;
|
||||
}
|
||||
|
||||
bestslidefrac = FRACUNIT + 1;
|
||||
|
||||
P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
|
||||
// move up to the wall
|
||||
if (bestslidefrac == FRACUNIT + 1)
|
||||
{
|
||||
// the move must have hit the middle, so bounce straight back
|
||||
bounceback:
|
||||
if (P_TryMove(mo, mo->x - mmomx, mo->y - mmomy, true, NULL))
|
||||
{
|
||||
mo->momx *= -1;
|
||||
mo->momy *= -1;
|
||||
mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
|
||||
mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
|
||||
|
||||
if (mo->player)
|
||||
{
|
||||
mo->player->cmomx *= -1;
|
||||
mo->player->cmomy *= -1;
|
||||
mo->player->cmomx = FixedMul(mo->player->cmomx,
|
||||
(FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
|
||||
mo->player->cmomy = FixedMul(mo->player->cmomy,
|
||||
(FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// fudge a bit to make sure it doesn't hit
|
||||
bestslidefrac -= 0x800;
|
||||
if (bestslidefrac > 0)
|
||||
{
|
||||
newx = FixedMul(mmomx, bestslidefrac);
|
||||
newy = FixedMul(mmomy, bestslidefrac);
|
||||
|
||||
if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true, NULL))
|
||||
{
|
||||
if (P_MobjWasRemoved(mo))
|
||||
return;
|
||||
goto bounceback;
|
||||
}
|
||||
}
|
||||
|
||||
// Now continue along the wall.
|
||||
// First calculate remainder.
|
||||
bestslidefrac = FRACUNIT - bestslidefrac;
|
||||
|
||||
if (bestslidefrac > FRACUNIT)
|
||||
bestslidefrac = FRACUNIT;
|
||||
|
||||
if (bestslidefrac <= 0)
|
||||
return;
|
||||
|
||||
if (mo->type == MT_SHELL)
|
||||
{
|
||||
tmxmove = mmomx;
|
||||
tmymove = mmomy;
|
||||
}
|
||||
else if (mo->type == MT_THROWNBOUNCE)
|
||||
{
|
||||
tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5)));
|
||||
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5)));
|
||||
}
|
||||
else if (mo->type == MT_THROWNGRENADE || mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE)
|
||||
{
|
||||
// Quickly decay speed as it bounces
|
||||
tmxmove = FixedDiv(mmomx, 2*FRACUNIT);
|
||||
tmymove = FixedDiv(mmomy, 2*FRACUNIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
|
||||
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
|
||||
}
|
||||
|
||||
P_HitBounceLine(bestslideline); // clip the moves
|
||||
|
||||
mo->momx = tmxmove;
|
||||
mo->momy = tmymove;
|
||||
|
||||
if (mo->player)
|
||||
{
|
||||
mo->player->cmomx = tmxmove;
|
||||
mo->player->cmomy = tmymove;
|
||||
}
|
||||
}
|
||||
while (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true, NULL) && !P_MobjWasRemoved(mo));
|
||||
}
|
||||
|
||||
void P_BounceMove(mobj_t *mo, TryMoveResult_t *result)
|
||||
{
|
||||
fixed_t mmomx = 0, mmomy = 0;
|
||||
|
|
@ -3610,7 +4200,27 @@ void P_BounceMove(mobj_t *mo, TryMoveResult_t *result)
|
|||
bestslideline = result->line;
|
||||
|
||||
if (bestslideline == NULL)
|
||||
{
|
||||
if (cv_showgremlins.value)
|
||||
{
|
||||
// debug
|
||||
mobj_t*x = P_SpawnMobj(mo->x, mo->y, mo->z, MT_THOK);
|
||||
x->frame = FF_FULLBRIGHT | FF_ADD;
|
||||
x->renderflags = RF_ALWAYSONTOP;
|
||||
x->color = SKINCOLOR_RED;
|
||||
|
||||
CONS_Printf(
|
||||
"BOUNCE GREMLIN: leveltime=%u x=%f y=%f z=%f\n",
|
||||
leveltime,
|
||||
FixedToFloat(mo->x),
|
||||
FixedToFloat(mo->y),
|
||||
FixedToFloat(mo->z));
|
||||
}
|
||||
|
||||
// We were not succesful, try the old version.
|
||||
P_BounceMoveOLD(mo);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mo->type == MT_SHELL)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue