mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 09:11:48 +00:00
Add a bunch of slope physics
I know giant commits all at once like this are a bad thing, but too bad I worked without staging commits and now it's all here at once :)
This commit is contained in:
parent
1f0f6b64c1
commit
db883f6a23
5 changed files with 187 additions and 48 deletions
|
@ -409,6 +409,50 @@ angles3d_t *M_VectorAlignTo(float Pitch, float Yaw, float Roll, v3float_t v, byt
|
|||
|
||||
}
|
||||
|
||||
//
|
||||
// RotateVector
|
||||
//
|
||||
// Rotates a vector around another vector
|
||||
//
|
||||
void M_VecRotate(v3fixed_t *rotVec, const v3fixed_t *axisVec, const angle_t angle)
|
||||
{
|
||||
// Rotate the point (x,y,z) around the vector (u,v,w)
|
||||
fixed_t ux = FixedMul(axisVec->x, rotVec->x);
|
||||
fixed_t uy = FixedMul(axisVec->x, rotVec->y);
|
||||
fixed_t uz = FixedMul(axisVec->x, rotVec->z);
|
||||
fixed_t vx = FixedMul(axisVec->y, rotVec->x);
|
||||
fixed_t vy = FixedMul(axisVec->y, rotVec->y);
|
||||
fixed_t vz = FixedMul(axisVec->y, rotVec->z);
|
||||
fixed_t wx = FixedMul(axisVec->z, rotVec->x);
|
||||
fixed_t wy = FixedMul(axisVec->z, rotVec->y);
|
||||
fixed_t wz = FixedMul(axisVec->z, rotVec->z);
|
||||
fixed_t sa = FINESINE(angle>>ANGLETOFINESHIFT);
|
||||
fixed_t ca = FINECOSINE(angle>>ANGLETOFINESHIFT);
|
||||
fixed_t ua = ux+vy+wz;
|
||||
fixed_t ax = FixedMul(axisVec->x,ua);
|
||||
fixed_t ay = FixedMul(axisVec->y,ua);
|
||||
fixed_t az = FixedMul(axisVec->z,ua);
|
||||
fixed_t xs = FixedMul(axisVec->x,axisVec->x);
|
||||
fixed_t ys = FixedMul(axisVec->y,axisVec->y);
|
||||
fixed_t zs = FixedMul(axisVec->z,axisVec->z);
|
||||
fixed_t bx = FixedMul(rotVec->x,ys+zs);
|
||||
fixed_t by = FixedMul(rotVec->y,xs+zs);
|
||||
fixed_t bz = FixedMul(rotVec->z,xs+ys);
|
||||
fixed_t cx = FixedMul(axisVec->x,vy+wz);
|
||||
fixed_t cy = FixedMul(axisVec->y,ux+wz);
|
||||
fixed_t cz = FixedMul(axisVec->z,ux+vy);
|
||||
fixed_t dx = FixedMul(bx-cx, ca);
|
||||
fixed_t dy = FixedMul(by-cy, ca);
|
||||
fixed_t dz = FixedMul(bz-cz, ca);
|
||||
fixed_t ex = FixedMul(vz-wy, sa);
|
||||
fixed_t ey = FixedMul(wx-uz, sa);
|
||||
fixed_t ez = FixedMul(uy-vx, sa);
|
||||
|
||||
rotVec->x = ax+dx+ex;
|
||||
rotVec->y = ay+dy+ey;
|
||||
rotVec->z = az+dz+ez;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -977,50 +1021,6 @@ boolean FV_IntersectedPolygon(const fvector_t *vPoly, const fvector_t *vLine, co
|
|||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// RotateVector
|
||||
//
|
||||
// Rotates a vector around another vector
|
||||
//
|
||||
void FV_Rotate(fvector_t *rotVec, const fvector_t *axisVec, const angle_t angle)
|
||||
{
|
||||
// Rotate the point (x,y,z) around the vector (u,v,w)
|
||||
fixed_t ux = FixedMul(axisVec->x, rotVec->x);
|
||||
fixed_t uy = FixedMul(axisVec->x, rotVec->y);
|
||||
fixed_t uz = FixedMul(axisVec->x, rotVec->z);
|
||||
fixed_t vx = FixedMul(axisVec->y, rotVec->x);
|
||||
fixed_t vy = FixedMul(axisVec->y, rotVec->y);
|
||||
fixed_t vz = FixedMul(axisVec->y, rotVec->z);
|
||||
fixed_t wx = FixedMul(axisVec->z, rotVec->x);
|
||||
fixed_t wy = FixedMul(axisVec->z, rotVec->y);
|
||||
fixed_t wz = FixedMul(axisVec->z, rotVec->z);
|
||||
fixed_t sa = FINESINE(angle);
|
||||
fixed_t ca = FINECOSINE(angle);
|
||||
fixed_t ua = ux+vy+wz;
|
||||
fixed_t ax = FixedMul(axisVec->x,ua);
|
||||
fixed_t ay = FixedMul(axisVec->y,ua);
|
||||
fixed_t az = FixedMul(axisVec->z,ua);
|
||||
fixed_t xs = FixedMul(axisVec->x,axisVec->x);
|
||||
fixed_t ys = FixedMul(axisVec->y,axisVec->y);
|
||||
fixed_t zs = FixedMul(axisVec->z,axisVec->z);
|
||||
fixed_t bx = FixedMul(rotVec->x,ys+zs);
|
||||
fixed_t by = FixedMul(rotVec->y,xs+zs);
|
||||
fixed_t bz = FixedMul(rotVec->z,xs+ys);
|
||||
fixed_t cx = FixedMul(axisVec->x,vy+wz);
|
||||
fixed_t cy = FixedMul(axisVec->y,ux+wz);
|
||||
fixed_t cz = FixedMul(axisVec->z,ux+vy);
|
||||
fixed_t dx = FixedMul(bx-cx, ca);
|
||||
fixed_t dy = FixedMul(by-cy, ca);
|
||||
fixed_t dz = FixedMul(bz-cz, ca);
|
||||
fixed_t ex = FixedMul(vz-wy, sa);
|
||||
fixed_t ey = FixedMul(wx-uz, sa);
|
||||
fixed_t ez = FixedMul(uy-vx, sa);
|
||||
|
||||
rotVec->x = ax+dx+ex;
|
||||
rotVec->y = ay+dy+ey;
|
||||
rotVec->z = az+dz+ez;
|
||||
}
|
||||
|
||||
void FM_Rotate(fmatrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
#define M(row,col) dest->m[row * 4 + col]
|
||||
|
|
|
@ -114,6 +114,8 @@ float M_VectorYaw(v3float_t v);
|
|||
float M_VectorPitch(v3float_t v);
|
||||
angles3d_t *M_VectorAlignTo(float Pitch, float Yaw, float Roll, v3float_t v, byte AngleAxis, float Rate);
|
||||
|
||||
void M_VecRotate(v3fixed_t *rotVec, const v3fixed_t *axisVec, const angle_t angle);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
71
src/p_mobj.c
71
src/p_mobj.c
|
@ -1239,7 +1239,11 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
|
|||
}
|
||||
else if (abs(player->rmomx) < FixedMul(STOPSPEED, mo->scale)
|
||||
&& abs(player->rmomy) < FixedMul(STOPSPEED, mo->scale)
|
||||
&& (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING)))
|
||||
&& (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING))
|
||||
#ifdef ESLOPE
|
||||
&& !(player->mo->standingslope && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// if in a walking frame, stop moving
|
||||
if (player->panim == PA_WALK)
|
||||
|
@ -1383,6 +1387,11 @@ void P_XYMovement(mobj_t *mo)
|
|||
fixed_t xmove, ymove;
|
||||
fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls
|
||||
boolean moved;
|
||||
#ifdef ESLOPE
|
||||
pslope_t *oldslope = NULL;
|
||||
v3fixed_t slopemom;
|
||||
fixed_t predictedz;
|
||||
#endif
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
@ -1414,6 +1423,29 @@ void P_XYMovement(mobj_t *mo)
|
|||
oldx = mo->x;
|
||||
oldy = mo->y;
|
||||
|
||||
#ifdef ESLOPE
|
||||
// adjust various things based on slope
|
||||
if (mo->standingslope) {
|
||||
if (!P_IsObjectOnGround(mo)) { // We fell off at some point? Do the twisty thing!
|
||||
P_SlopeLaunch(mo);
|
||||
xmove = mo->momx;
|
||||
ymove = mo->momy;
|
||||
} else { // Still on the ground.
|
||||
slopemom.x = xmove;
|
||||
slopemom.y = ymove;
|
||||
slopemom.z = 0;
|
||||
P_QuantizeMomentumToSlope(&slopemom, mo->standingslope);
|
||||
|
||||
xmove = slopemom.x;
|
||||
ymove = slopemom.y;
|
||||
|
||||
predictedz = mo->z + slopemom.z; // We'll use this later...
|
||||
|
||||
oldslope = mo->standingslope;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pushables can break some blocks
|
||||
if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE)
|
||||
P_PushableCheckBustables(mo);
|
||||
|
@ -1534,6 +1566,29 @@ void P_XYMovement(mobj_t *mo)
|
|||
if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;;
|
||||
return;
|
||||
|
||||
#ifdef ESLOPE
|
||||
if (moved && oldslope) { // Check to see if we ran off
|
||||
if (oldslope != mo->standingslope) { // First, compare different slopes
|
||||
// Start by quantizing momentum on this slope
|
||||
v3fixed_t test;
|
||||
test.x = mo->momx;
|
||||
test.y = mo->momy;
|
||||
test.z = 0;
|
||||
if (mo->standingslope) // Don't fuss with the rotation if we don't HAVE a slope
|
||||
P_QuantizeMomentumToSlope(&test, mo->standingslope);
|
||||
|
||||
// Now compare the Zs of the different quantizations
|
||||
if (slopemom.z - test.z > 2*FRACUNIT) { // Allow for a bit of sticking - this value can be adjusted later
|
||||
mo->standingslope = oldslope;
|
||||
P_SlopeLaunch(mo);
|
||||
}
|
||||
} else if (predictedz-mo->z > 2*FRACUNIT) { // Now check if we were supposed to stick to this slope
|
||||
mo->standingslope = oldslope;
|
||||
P_SlopeLaunch(mo);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check the gravity status.
|
||||
P_CheckGravity(mo, false);
|
||||
|
||||
|
@ -1819,6 +1874,11 @@ static boolean P_ZMovement(mobj_t *mo)
|
|||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
#ifdef ESLOPE
|
||||
if (mo->standingslope && !P_IsObjectOnGround(mo))
|
||||
P_SlopeLaunch(mo);
|
||||
#endif
|
||||
|
||||
// Intercept the stupid 'fall through 3dfloors' bug
|
||||
if (mo->subsector->sector->ffloors)
|
||||
P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
|
||||
|
@ -2231,6 +2291,11 @@ static void P_PlayerZMovement(mobj_t *mo)
|
|||
if (!mo->player)
|
||||
return;
|
||||
|
||||
#ifdef ESLOPE
|
||||
if (mo->standingslope && !P_IsObjectOnGround(mo))
|
||||
P_SlopeLaunch(mo);
|
||||
#endif
|
||||
|
||||
// Intercept the stupid 'fall through 3dfloors' bug
|
||||
if (mo->subsector->sector->ffloors)
|
||||
P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
|
||||
|
@ -3183,6 +3248,10 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
|
|||
|
||||
P_MobjCheckWater(mobj);
|
||||
|
||||
#ifdef ESLOPE
|
||||
P_ButteredSlope(mobj);
|
||||
#endif
|
||||
|
||||
// momentum movement
|
||||
mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN;
|
||||
|
||||
|
|
|
@ -768,6 +768,69 @@ float P_DistFromPlanef(const v3float_t *point, const v3float_t *pori,
|
|||
(point->z - pori->z) * pnormal->z;
|
||||
}
|
||||
|
||||
//
|
||||
// P_QuantizeMomentumToSlope
|
||||
//
|
||||
// When given a vector, rotates it and aligns it to a slope
|
||||
void P_QuantizeMomentumToSlope(v3fixed_t *momentum, pslope_t *slope)
|
||||
{
|
||||
v3fixed_t axis;
|
||||
axis.x = -slope->d.y;
|
||||
axis.y = slope->d.x;
|
||||
axis.z = 0;
|
||||
|
||||
M_VecRotate(momentum, &axis, slope->zangle);
|
||||
}
|
||||
|
||||
//
|
||||
// P_SlopeLaunch
|
||||
//
|
||||
// Handles slope ejection for objects
|
||||
void P_SlopeLaunch(mobj_t *mo)
|
||||
{
|
||||
// Double the pre-rotation Z, then halve the post-rotation Z. This reduces the
|
||||
// vertical launch given from slopes while increasing the horizontal launch
|
||||
// given. Good for SRB2's gravity and horizontal speeds.
|
||||
v3fixed_t slopemom;
|
||||
slopemom.x = mo->momx;
|
||||
slopemom.y = mo->momy;
|
||||
slopemom.z = mo->momz*2;
|
||||
P_QuantizeMomentumToSlope(&slopemom, mo->standingslope);
|
||||
|
||||
mo->momx = slopemom.x;
|
||||
mo->momy = slopemom.y;
|
||||
mo->momz = slopemom.z/2;
|
||||
|
||||
CONS_Printf("Launched off of slope.\n");
|
||||
mo->standingslope = NULL;
|
||||
}
|
||||
|
||||
// https://yourlogicalfallacyis.com/slippery-slope
|
||||
// Handles sliding down slopes, like if they were made of butter :)
|
||||
void P_ButteredSlope(mobj_t *mo)
|
||||
{
|
||||
fixed_t thrust;
|
||||
|
||||
if (!mo->standingslope)
|
||||
return;
|
||||
|
||||
if (abs(mo->standingslope->zdelta) < FRACUNIT/2)
|
||||
return; // Don't apply physics to slopes that aren't steep enough
|
||||
|
||||
thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1);
|
||||
|
||||
if (!(mo->player && (mo->player->pflags & PF_SPINNING))) {
|
||||
if (mo->momx || mo->momy) // Slightly increase thrust based on the object's speed parallel to the slope direction
|
||||
thrust = FixedMul(thrust, FRACUNIT+P_AproxDistance(mo->momx, mo->momy)/4);
|
||||
// This solves the issue of being able to zigzag up steep slopes
|
||||
}
|
||||
|
||||
// Multiply by gravity
|
||||
thrust = FixedMul(thrust, FRACUNIT/2); // TODO actually get this
|
||||
|
||||
P_Thrust(mo, mo->standingslope->xydirection, thrust);
|
||||
}
|
||||
|
||||
// EOF
|
||||
#endif // #ifdef ESLOPE
|
||||
|
||||
|
|
|
@ -76,6 +76,11 @@ float P_GetZAtf(pslope_t *slope, float x, float y);
|
|||
float P_DistFromPlanef(const v3float_t *point, const v3float_t *pori,
|
||||
const v3float_t *pnormal);
|
||||
|
||||
// Lots of physics-based bullshit
|
||||
void P_QuantizeMomentumToSlope(v3fixed_t *momentum, pslope_t *slope);
|
||||
void P_SlopeLaunch(mobj_t *mo);
|
||||
void P_ButteredSlope(mobj_t *mo);
|
||||
|
||||
#endif
|
||||
|
||||
// EOF
|
||||
|
|
Loading…
Reference in a new issue