Improve slope physics on solid middle textures

This commit is contained in:
Lactozilla 2024-05-19 20:40:40 -03:00
parent 3a62ebbe3e
commit e67e225ff2
10 changed files with 189 additions and 35 deletions

View file

@ -399,6 +399,7 @@ extern camera_t *mapcampointer;
extern fixed_t tmx; extern fixed_t tmx;
extern fixed_t tmy; extern fixed_t tmy;
extern pslope_t *tmfloorslope, *tmceilingslope; extern pslope_t *tmfloorslope, *tmceilingslope;
extern line_t *tmfloorline, *tmceilingline;
/* cphipps 2004/08/30 */ /* cphipps 2004/08/30 */
extern void P_MapStart(void); extern void P_MapStart(void);

View file

@ -55,6 +55,7 @@ mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz
mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) mobj_t *tmhitthing; // the solid thing you bumped into (for collisions)
ffloor_t *tmfloorrover, *tmceilingrover; ffloor_t *tmfloorrover, *tmceilingrover;
pslope_t *tmfloorslope, *tmceilingslope; pslope_t *tmfloorslope, *tmceilingslope;
line_t *tmfloorline, *tmceilingline;
// keep track of the line that lowers the ceiling, // keep track of the line that lowers the ceiling,
// so missiles don't explode against sky hack walls // so missiles don't explode against sky hack walls
@ -1760,6 +1761,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
tmfloorz = thing->z + thing->height; tmfloorz = thing->z + thing->height;
tmfloorrover = NULL; tmfloorrover = NULL;
tmfloorslope = NULL; tmfloorslope = NULL;
tmfloorline = NULL;
} }
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
@ -1779,6 +1781,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
tmfloorz = tmceilingz = topz; // block while in air tmfloorz = tmceilingz = topz; // block while in air
tmceilingrover = NULL; tmceilingrover = NULL;
tmceilingslope = NULL; tmceilingslope = NULL;
tmceilingline = NULL;
tmfloorthing = thing; // needed for side collision tmfloorthing = thing; // needed for side collision
collide = CHECKTHING_COLLIDE; collide = CHECKTHING_COLLIDE;
@ -1788,6 +1791,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
tmceilingz = topz; tmceilingz = topz;
tmceilingrover = NULL; tmceilingrover = NULL;
tmceilingslope = NULL; tmceilingslope = NULL;
tmceilingline = NULL;
tmfloorthing = thing; // thing we may stand on tmfloorthing = thing; // thing we may stand on
collide = CHECKTHING_COLLIDE; collide = CHECKTHING_COLLIDE;
@ -1805,6 +1809,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
tmceilingz = thing->z; tmceilingz = thing->z;
tmceilingrover = NULL; tmceilingrover = NULL;
tmceilingslope = NULL; tmceilingslope = NULL;
tmceilingline = NULL;
} }
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
@ -1824,6 +1829,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
tmfloorz = tmceilingz = topz; // block while in air tmfloorz = tmceilingz = topz; // block while in air
tmfloorrover = NULL; tmfloorrover = NULL;
tmfloorslope = NULL; tmfloorslope = NULL;
tmfloorline = NULL;
tmfloorthing = thing; // needed for side collision tmfloorthing = thing; // needed for side collision
collide = CHECKTHING_COLLIDE; collide = CHECKTHING_COLLIDE;
@ -1833,6 +1839,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
tmfloorz = topz; tmfloorz = topz;
tmfloorrover = NULL; tmfloorrover = NULL;
tmfloorslope = NULL; tmfloorslope = NULL;
tmfloorline = NULL;
tmfloorthing = thing; // thing we may stand on tmfloorthing = thing; // thing we may stand on
collide = CHECKTHING_COLLIDE; collide = CHECKTHING_COLLIDE;
@ -2000,6 +2007,7 @@ static boolean PIT_CheckLine(line_t *ld)
ceilingline = ld; ceilingline = ld;
tmceilingrover = openceilingrover; tmceilingrover = openceilingrover;
tmceilingslope = opentopslope; tmceilingslope = opentopslope;
tmceilingline = opentopline;
} }
if (openbottom > tmfloorz) if (openbottom > tmfloorz)
@ -2007,6 +2015,7 @@ static boolean PIT_CheckLine(line_t *ld)
tmfloorz = openbottom; tmfloorz = openbottom;
tmfloorrover = openfloorrover; tmfloorrover = openfloorrover;
tmfloorslope = openbottomslope; tmfloorslope = openbottomslope;
tmfloorline = openbottomline;
} }
if (highceiling > tmdrpoffceilz) if (highceiling > tmdrpoffceilz)
@ -2057,6 +2066,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight;
tmfloorrover = NULL; tmfloorrover = NULL;
tmceilingrover = NULL; tmceilingrover = NULL;
tmfloorline = NULL;
tmceilingline = NULL;
tmfloorslope = newsubsec->sector->f_slope; tmfloorslope = newsubsec->sector->f_slope;
tmceilingslope = newsubsec->sector->c_slope; tmceilingslope = newsubsec->sector->c_slope;
@ -2642,6 +2653,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
ffloor_t *oldceilrover = tmceilingrover; ffloor_t *oldceilrover = tmceilingrover;
pslope_t *oldfslope = tmfloorslope; pslope_t *oldfslope = tmfloorslope;
pslope_t *oldcslope = tmceilingslope; pslope_t *oldcslope = tmceilingslope;
line_t *oldfline = tmfloorline;
line_t *oldcline = tmceilingline;
// Move the player // Move the player
P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true); P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true);
@ -2658,6 +2671,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
tmceilingrover = oldceilrover; tmceilingrover = oldceilrover;
tmfloorslope = oldfslope; tmfloorslope = oldfslope;
tmceilingslope = oldcslope; tmceilingslope = oldcslope;
tmfloorline = oldfline;
tmceilingline = oldcline;
thing->momz = stand->momz; thing->momz = stand->momz;
} }
else else
@ -2899,11 +2914,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
// Assign thing's standingslope if needed // Assign thing's standingslope if needed
if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) { if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) {
if (!startingonground && tmfloorslope) if (!startingonground && tmfloorslope)
P_HandleSlopeLanding(thing, tmfloorslope); P_HandleSlopeLanding(thing, tmfloorslope, tmfloorline);
if (thing->momz <= 0) if (thing->momz <= 0)
{ {
thing->standingslope = tmfloorslope; thing->standingslope = tmfloorslope;
thing->standingline = tmfloorline;
P_SetPitchRollFromSlope(thing, thing->standingslope); P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground) if (thing->momz == 0 && thing->player && !startingonground)
@ -2912,11 +2928,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
} }
else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) {
if (!startingonground && tmceilingslope) if (!startingonground && tmceilingslope)
P_HandleSlopeLanding(thing, tmceilingslope); P_HandleSlopeLanding(thing, tmceilingslope, tmceilingline);
if (thing->momz >= 0) if (thing->momz >= 0)
{ {
thing->standingslope = tmceilingslope; thing->standingslope = tmceilingslope;
thing->standingline = tmceilingline;
P_SetPitchRollFromSlope(thing, thing->standingslope); P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground) if (thing->momz == 0 && thing->player && !startingonground)
@ -2924,8 +2941,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
} }
} }
} }
else // don't set standingslope if you're not going to clip against it else
{
// don't set standingslope or standingline if you're not going to clip against them
thing->standingslope = NULL; thing->standingslope = NULL;
thing->standingline = NULL;
}
thing->x = x; thing->x = x;
thing->y = y; thing->y = y;

View file

@ -280,6 +280,7 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1)
fixed_t opentop, openbottom, openrange, lowfloor, highceiling; fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
pslope_t *opentopslope, *openbottomslope; pslope_t *opentopslope, *openbottomslope;
ffloor_t *openfloorrover, *openceilingrover; ffloor_t *openfloorrover, *openceilingrover;
line_t *opentopline, *openbottomline;
// P_CameraLineOpening // P_CameraLineOpening
// P_LineOpening, but for camera // P_LineOpening, but for camera
@ -440,6 +441,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
I_Assert(back != NULL); I_Assert(back != NULL);
openfloorrover = openceilingrover = NULL; openfloorrover = openceilingrover = NULL;
opentopline = openbottomline = NULL;
if (linedef->polyobj) if (linedef->polyobj)
{ {
// set these defaults so that polyobjects don't interfere with collision above or below them // set these defaults so that polyobjects don't interfere with collision above or below them
@ -544,6 +547,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if ((linedef->flags & ML_MIDPEG) != 0) { if ((linedef->flags & ML_MIDPEG) != 0) {
opentopslope = openbottomslope; opentopslope = openbottomslope;
} }
opentopline = linedef;
} }
} else { // Above } else { // Above
if (openbottom < textop) { if (openbottom < textop) {
@ -551,6 +555,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if ((linedef->flags & ML_MIDPEG) == 0) { if ((linedef->flags & ML_MIDPEG) == 0) {
openbottomslope = opentopslope; openbottomslope = opentopslope;
} }
openbottomline = linedef;
} }
} }
} }

View file

@ -57,6 +57,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y);
extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling; extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
extern pslope_t *opentopslope, *openbottomslope; extern pslope_t *opentopslope, *openbottomslope;
extern ffloor_t *openfloorrover, *openceilingrover; extern ffloor_t *openfloorrover, *openceilingrover;
extern line_t *opentopline, *openbottomline;
void P_LineOpening(line_t *plinedef, mobj_t *mobj); void P_LineOpening(line_t *plinedef, mobj_t *mobj);

View file

@ -1672,6 +1672,7 @@ void P_XYMovement(mobj_t *mo)
fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls
boolean moved; boolean moved;
pslope_t *oldslope = NULL; pslope_t *oldslope = NULL;
line_t *oldstandingline = NULL;
vector3_t slopemom = {0,0,0}; vector3_t slopemom = {0,0,0};
fixed_t predictedz = 0; fixed_t predictedz = 0;
@ -1704,7 +1705,10 @@ void P_XYMovement(mobj_t *mo)
oldy = mo->y; oldy = mo->y;
if (mo->flags & MF_NOCLIPHEIGHT) if (mo->flags & MF_NOCLIPHEIGHT)
{
mo->standingslope = NULL; mo->standingslope = NULL;
mo->standingline = NULL;
}
// adjust various things based on slope // adjust various things based on slope
if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) { if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) {
@ -1716,7 +1720,7 @@ void P_XYMovement(mobj_t *mo)
slopemom.x = xmove; slopemom.x = xmove;
slopemom.y = ymove; slopemom.y = ymove;
slopemom.z = 0; slopemom.z = 0;
P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); P_QuantizeObjectMomentumToSlope(mo, &slopemom);
xmove = slopemom.x; xmove = slopemom.x;
ymove = slopemom.y; ymove = slopemom.y;
@ -1724,6 +1728,7 @@ void P_XYMovement(mobj_t *mo)
predictedz = mo->z + slopemom.z; // We'll use this later... predictedz = mo->z + slopemom.z; // We'll use this later...
oldslope = mo->standingslope; oldslope = mo->standingslope;
oldstandingline = mo->standingline;
} }
} else if (P_IsObjectOnGround(mo) && !mo->momz) } else if (P_IsObjectOnGround(mo) && !mo->momz)
predictedz = mo->z; predictedz = mo->z;
@ -1799,12 +1804,16 @@ void P_XYMovement(mobj_t *mo)
{ // try to slide along it { // try to slide along it
// Wall transfer part 1. // Wall transfer part 1.
pslope_t *transferslope = NULL; pslope_t *transferslope = NULL;
line_t *transferline = NULL;
fixed_t transfermomz = 0; fixed_t transfermomz = 0;
if (oldslope && (P_MobjFlip(mo)*(predictedz - mo->z) > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls if (oldslope && (P_MobjFlip(mo)*(predictedz - mo->z) > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls
{ {
angle_t zangle;
transferslope = ((mo->standingslope) ? mo->standingslope : oldslope); transferslope = ((mo->standingslope) ? mo->standingslope : oldslope);
if (((transferslope->zangle < ANGLE_180) ? transferslope->zangle : InvAngle(transferslope->zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes. transferline = ((mo->standingline) ? mo->standingline : oldstandingline);
transfermomz = P_GetWallTransferMomZ(mo, transferslope); zangle = P_GetStandingSlopeZAngle(transferslope, transferline);
if (((zangle < ANGLE_180) ? zangle : InvAngle(zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes.
transfermomz = P_GetWallTransferMomZ(mo, transferslope, transferline);
} }
P_SlideMove(mo); P_SlideMove(mo);
@ -1817,7 +1826,7 @@ void P_XYMovement(mobj_t *mo)
{ {
angle_t relation; // Scale transfer momentum based on how head-on it is to the slope. angle_t relation; // Scale transfer momentum based on how head-on it is to the slope.
if (mo->momx || mo->momy) // "Guess" the angle of the wall you hit using new momentum if (mo->momx || mo->momy) // "Guess" the angle of the wall you hit using new momentum
relation = transferslope->xydirection - R_PointToAngle2(0, 0, mo->momx, mo->momy); relation = P_GetStandingSlopeDirection(transferslope, transferline) - R_PointToAngle2(0, 0, mo->momx, mo->momy);
else // Give it for free, I guess. else // Give it for free, I guess.
relation = ANGLE_90; relation = ANGLE_90;
transfermomz = FixedMul(transfermomz, transfermomz = FixedMul(transfermomz,
@ -1826,6 +1835,7 @@ void P_XYMovement(mobj_t *mo)
{ {
mo->momz = transfermomz; mo->momz = transfermomz;
mo->standingslope = NULL; mo->standingslope = NULL;
mo->standingline = NULL;
if (player) if (player)
{ {
player->powers[pw_justlaunched] = 2; player->powers[pw_justlaunched] = 2;
@ -1875,7 +1885,7 @@ void P_XYMovement(mobj_t *mo)
oldangle = FixedMul((signed)oldslope->zangle, FINECOSINE((moveangle - oldslope->xydirection) >> ANGLETOFINESHIFT)); oldangle = FixedMul((signed)oldslope->zangle, FINECOSINE((moveangle - oldslope->xydirection) >> ANGLETOFINESHIFT));
if (mo->standingslope) if (mo->standingslope)
newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT)); newangle = FixedMul((signed)P_GetObjectStandingSlopeZAngle(mo), FINECOSINE((moveangle - P_GetObjectStandingSlopeDirection(mo)) >> ANGLETOFINESHIFT));
else else
newangle = 0; newangle = 0;
@ -1899,7 +1909,7 @@ void P_XYMovement(mobj_t *mo)
} }
} else if (moved && mo->standingslope && predictedz) { } else if (moved && mo->standingslope && predictedz) {
angle_t moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy); angle_t moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
angle_t newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT)); angle_t newangle = FixedMul((signed)P_GetObjectStandingSlopeZAngle(mo), FINECOSINE((moveangle - P_GetObjectStandingSlopeDirection(mo)) >> ANGLETOFINESHIFT));
/*CONS_Printf("flat to angle %f - predicted z of %f\n", /*CONS_Printf("flat to angle %f - predicted z of %f\n",
FIXED_TO_FLOAT(AngleFixed(ANGLE_MAX-newangle)), FIXED_TO_FLOAT(AngleFixed(ANGLE_MAX-newangle)),
@ -2432,8 +2442,9 @@ boolean P_ZMovement(mobj_t *mo)
if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM))
{ {
mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
mo->standingline = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingline : tmfloorline;
P_SetPitchRollFromSlope(mo, mo->standingslope); P_SetPitchRollFromSlope(mo, mo->standingslope);
P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); P_ReverseQuantizeObjectMomentumToSlope(mo, &mom);
} }
// hit the floor // hit the floor
@ -2579,7 +2590,7 @@ boolean P_ZMovement(mobj_t *mo)
mom.z = tmfloorthing->momz; mom.z = tmfloorthing->momz;
if (mo->standingslope) { // MT_STEAM will never have a standingslope, see above. if (mo->standingslope) { // MT_STEAM will never have a standingslope, see above.
P_QuantizeMomentumToSlope(&mom, mo->standingslope); P_QuantizeObjectMomentumToSlope(mo, &mom);
} }
mo->momx = mom.x; mo->momx = mom.x;
@ -2825,7 +2836,9 @@ void P_PlayerZMovement(mobj_t *mo)
if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) {
// Handle landing on slope during Z movement // Handle landing on slope during Z movement
P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)); P_HandleSlopeLanding(mo,
(mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope),
(mo->eflags & MFE_VERTICALFLIP ? tmceilingline : tmfloorline));
} }
if (P_MobjFlip(mo)*mo->momz < 0) // falling if (P_MobjFlip(mo)*mo->momz < 0) // falling

View file

@ -412,7 +412,9 @@ typedef struct mobj_s
INT32 cusval; INT32 cusval;
INT32 cvmem; INT32 cvmem;
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) (it does)
struct line_s *standingline; // The line that the object is standing on
boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation) boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation)
boolean colorized; // Whether the mobj uses the rainbow colormap boolean colorized; // Whether the mobj uses the rainbow colormap

View file

@ -1746,7 +1746,8 @@ typedef enum
MD2_DISPOFFSET = 1<<23, MD2_DISPOFFSET = 1<<23,
MD2_DRAWONLYFORPLAYER = 1<<24, MD2_DRAWONLYFORPLAYER = 1<<24,
MD2_DONTDRAWFORVIEWMOBJ = 1<<25, MD2_DONTDRAWFORVIEWMOBJ = 1<<25,
MD2_TRANSLATION = 1<<26 MD2_TRANSLATION = 1<<26,
MD2_STANDINGLINE = 1<<27
} mobj_diff2_t; } mobj_diff2_t;
typedef enum typedef enum
@ -1953,6 +1954,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_CEILINGROVER; diff2 |= MD2_CEILINGROVER;
if (mobj->standingslope) if (mobj->standingslope)
diff2 |= MD2_SLOPE; diff2 |= MD2_SLOPE;
if (mobj->standingline)
diff2 |= MD2_STANDINGLINE;
if (mobj->colorized) if (mobj->colorized)
diff2 |= MD2_COLORIZED; diff2 |= MD2_COLORIZED;
if (mobj->mirrored) if (mobj->mirrored)
@ -2125,6 +2128,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEUINT32(save_p, mobj->hprev->mobjnum); WRITEUINT32(save_p, mobj->hprev->mobjnum);
if (diff2 & MD2_SLOPE) if (diff2 & MD2_SLOPE)
WRITEUINT16(save_p, mobj->standingslope->id); WRITEUINT16(save_p, mobj->standingslope->id);
if (diff2 & MD2_STANDINGLINE)
WRITEUINT32(save_p, SaveLine(mobj->standingline));
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
WRITEUINT8(save_p, mobj->colorized); WRITEUINT8(save_p, mobj->colorized);
if (diff2 & MD2_MIRRORED) if (diff2 & MD2_MIRRORED)
@ -3181,6 +3186,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
if (diff2 & MD2_SLOPE) if (diff2 & MD2_SLOPE)
mobj->standingslope = P_SlopeById(READUINT16(save_p)); mobj->standingslope = P_SlopeById(READUINT16(save_p));
if (diff2 & MD2_STANDINGLINE)
mobj->standingline = LoadLine(READUINT32(save_p));
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p); mobj->colorized = READUINT8(save_p);
if (diff2 & MD2_MIRRORED) if (diff2 & MD2_MIRRORED)

View file

@ -859,11 +859,10 @@ fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y)
// When given a vector, rotates it and aligns it to a slope // When given a vector, rotates it and aligns it to a slope
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope)
{ {
vector3_t axis; // Fuck you, C90.
if (slope->flags & SL_NOPHYSICS) if (slope->flags & SL_NOPHYSICS)
return; // No physics, no quantizing. return; // No physics, no quantizing.
vector3_t axis;
axis.x = -slope->d.y; axis.x = -slope->d.y;
axis.y = slope->d.x; axis.y = slope->d.x;
axis.z = 0; axis.z = 0;
@ -877,9 +876,91 @@ void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope)
// When given a vector, rotates and aligns it to a flat surface (from being relative to a given slope) // When given a vector, rotates and aligns it to a flat surface (from being relative to a given slope)
void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope)
{ {
slope->zangle = InvAngle(slope->zangle); if (slope->flags & SL_NOPHYSICS)
P_QuantizeMomentumToSlope(momentum, slope); return; // No physics, no quantizing.
slope->zangle = InvAngle(slope->zangle);
vector3_t axis;
axis.x = -slope->d.y;
axis.y = slope->d.x;
axis.z = 0;
FV3_Rotate(momentum, &axis, InvAngle(slope->zangle) >> ANGLETOFINESHIFT);
}
angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line)
{
angle_t zangle = slope->zangle;
if (line)
{
zangle = R_PointToAngle2(0, P_GetSlopeZAt(slope, line->v1->x, line->v1->y),
R_PointToDist2(line->v1->x, line->v1->y, line->v2->x, line->v2->y), P_GetSlopeZAt(slope, line->v2->x, line->v2->y));
}
return zangle;
}
angle_t P_GetStandingSlopeDirection(pslope_t *slope, line_t *line)
{
angle_t xydirection = slope->xydirection;
if (line)
{
xydirection = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y);
}
return xydirection;
}
angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo)
{
return P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline);
}
angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo)
{
return P_GetStandingSlopeDirection(mo->standingslope, mo->standingline);
}
static void QuantizeMomentumToSlope(pslope_t *slope, line_t *line, vector3_t *momentum, boolean reverse)
{
if (!slope || slope->flags & SL_NOPHYSICS)
return;
angle_t zangle = P_GetStandingSlopeZAngle(slope, line);
if (reverse)
zangle = InvAngle(zangle);
vector3_t axis;
axis.z = 0;
if (line)
{
fixed_t len = R_PointToDist2(0, 0, line->dx, line->dy);
axis.x = FixedDiv(line->dy, len);
axis.y = -FixedDiv(line->dx, len);
}
else
{
axis.x = -slope->d.y;
axis.y = slope->d.x;
}
FV3_Rotate(momentum, &axis, zangle >> ANGLETOFINESHIFT);
}
// Given a vector of the object's momentum, rotates it and aligns it to the slope the object is standing on
void P_QuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum)
{
QuantizeMomentumToSlope(mo->standingslope, mo->standingline, momentum, false);
}
// Given a vector of the object's momentum, rotates and aligns it to a flat surface
// (from being relative to the slope the object is standing on)
void P_ReverseQuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum)
{
QuantizeMomentumToSlope(mo->standingslope, mo->standingline, momentum, true);
} }
// //
@ -899,7 +980,7 @@ void P_SlopeLaunch(mobj_t *mo)
slopemom.x = mo->momx; slopemom.x = mo->momx;
slopemom.y = mo->momy; slopemom.y = mo->momy;
slopemom.z = mo->momz*2; slopemom.z = mo->momz*2;
P_QuantizeMomentumToSlope(&slopemom, mo->standingslope); P_QuantizeObjectMomentumToSlope(mo, &slopemom);
mo->momx = slopemom.x; mo->momx = slopemom.x;
mo->momy = slopemom.y; mo->momy = slopemom.y;
@ -919,7 +1000,7 @@ void P_SlopeLaunch(mobj_t *mo)
// It would be nice to have a single function that does everything necessary for slope-to-wall transfer. // It would be nice to have a single function that does everything necessary for slope-to-wall transfer.
// However, it needs to be seperated out in P_XYMovement to take into account momentum before and after hitting the wall. // However, it needs to be seperated out in P_XYMovement to take into account momentum before and after hitting the wall.
// This just performs the necessary calculations for getting the base vertical momentum; the horizontal is already reasonably calculated by P_SlideMove. // This just performs the necessary calculations for getting the base vertical momentum; the horizontal is already reasonably calculated by P_SlideMove.
fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line)
{ {
vector3_t slopemom, axis; vector3_t slopemom, axis;
angle_t ang; angle_t ang;
@ -927,18 +1008,30 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope)
if (slope->flags & SL_NOPHYSICS) if (slope->flags & SL_NOPHYSICS)
return 0; return 0;
angle_t zangle = P_GetStandingSlopeZAngle(slope, line);
// If there's physics, time for launching. // If there's physics, time for launching.
// Doesn't kill the vertical momentum as much as P_SlopeLaunch does. // Doesn't kill the vertical momentum as much as P_SlopeLaunch does.
ang = slope->zangle + ANG15*((slope->zangle > 0) ? 1 : -1); ang = zangle + ANG15*((zangle > 0) ? 1 : -1);
if (ang > ANGLE_90 && ang < ANGLE_180) if (ang > ANGLE_90 && ang < ANGLE_180)
ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards ang = ((zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards
slopemom.x = mo->momx; slopemom.x = mo->momx;
slopemom.y = mo->momy; slopemom.y = mo->momy;
slopemom.z = 3*(mo->momz/2); slopemom.z = 3*(mo->momz/2);
axis.x = -slope->d.y; if (line)
axis.y = slope->d.x; {
fixed_t len = R_PointToDist2(0, 0, line->dx, line->dy);
axis.x = FixedDiv(line->dy, len);
axis.y = -FixedDiv(line->dx, len);
}
else
{
axis.x = -slope->d.y;
axis.y = slope->d.x;
}
axis.z = 0; axis.z = 0;
FV3_Rotate(&slopemom, &axis, ang >> ANGLETOFINESHIFT); FV3_Rotate(&slopemom, &axis, ang >> ANGLETOFINESHIFT);
@ -947,7 +1040,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope)
} }
// Function to help handle landing on slopes // Function to help handle landing on slopes
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line)
{ {
vector3_t mom; // Ditto. vector3_t mom; // Ditto.
if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated. if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated.
@ -966,12 +1059,13 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
mom.y = thing->momy; mom.y = thing->momy;
mom.z = thing->momz*2; mom.z = thing->momz*2;
P_ReverseQuantizeMomentumToSlope(&mom, slope); QuantizeMomentumToSlope(slope, line, &mom, true);
if (P_MobjFlip(thing)*mom.z < 0) { // falling, land on slope if (P_MobjFlip(thing)*mom.z < 0) { // falling, land on slope
thing->momx = mom.x; thing->momx = mom.x;
thing->momy = mom.y; thing->momy = mom.y;
thing->standingslope = slope; thing->standingslope = slope;
thing->standingline = line;
P_SetPitchRollFromSlope(thing, slope); P_SetPitchRollFromSlope(thing, slope);
if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) if (!thing->player || !(thing->player->pflags & PF_BOUNCING))
thing->momz = -P_MobjFlip(thing); thing->momz = -P_MobjFlip(thing);
@ -983,6 +1077,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
void P_ButteredSlope(mobj_t *mo) void P_ButteredSlope(mobj_t *mo)
{ {
fixed_t thrust; fixed_t thrust;
angle_t zangle, xydirection;
if (!mo->standingslope) if (!mo->standingslope)
return; return;
@ -1001,12 +1096,15 @@ void P_ButteredSlope(mobj_t *mo)
return; // Allow the player to stand still on slopes below a certain steepness return; // Allow the player to stand still on slopes below a certain steepness
} }
thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 3 / 2 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); zangle = P_GetStandingSlopeZAngle(mo->standingslope, mo->standingline);
xydirection = P_GetStandingSlopeDirection(mo->standingslope, mo->standingline);
thrust = FINESINE(zangle>>ANGLETOFINESHIFT) * 3 / 2 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1);
if (mo->player && (mo->player->pflags & PF_SPINNING)) { if (mo->player && (mo->player->pflags & PF_SPINNING)) {
fixed_t mult = 0; fixed_t mult = 0;
if (mo->momx || mo->momy) { if (mo->momx || mo->momy) {
angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - mo->standingslope->xydirection; angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - xydirection;
if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0) if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0)
angle ^= ANGLE_180; angle ^= ANGLE_180;
@ -1027,5 +1125,5 @@ void P_ButteredSlope(mobj_t *mo)
// ... and its friction against the ground for good measure (divided by original friction to keep behaviour for normal slopes the same). // ... and its friction against the ground for good measure (divided by original friction to keep behaviour for normal slopes the same).
thrust = FixedMul(thrust, FixedDiv(mo->friction, ORIG_FRICTION)); thrust = FixedMul(thrust, FixedDiv(mo->friction, ORIG_FRICTION));
P_Thrust(mo, mo->standingslope->xydirection, thrust); P_Thrust(mo, xydirection, thrust);
} }

View file

@ -84,9 +84,15 @@ fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y);
// Lots of physics-based bullshit // Lots of physics-based bullshit
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
void P_QuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum);
void P_ReverseQuantizeObjectMomentumToSlope(mobj_t *mo, vector3_t *momentum);
angle_t P_GetStandingSlopeZAngle(pslope_t *slope, line_t *line);
angle_t P_GetStandingSlopeDirection(pslope_t *slope, line_t *line);
angle_t P_GetObjectStandingSlopeZAngle(mobj_t *mo);
angle_t P_GetObjectStandingSlopeDirection(mobj_t *mo);
void P_SlopeLaunch(mobj_t *mo); void P_SlopeLaunch(mobj_t *mo);
fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope); fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope, line_t *line);
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope, line_t *line);
void P_ButteredSlope(mobj_t *mo); void P_ButteredSlope(mobj_t *mo);
pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const double c, const double d); pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const double c, const double d);

View file

@ -6257,15 +6257,15 @@ static void P_3dMovement(player_t *player)
&& player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) { && player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) {
// Factor thrust to slope, but only for the part pushing up it! // Factor thrust to slope, but only for the part pushing up it!
// The rest is unaffected. // The rest is unaffected.
angle_t thrustangle = R_PointToAngle2(0, 0, totalthrust.x, totalthrust.y)-player->mo->standingslope->xydirection; angle_t thrustangle = R_PointToAngle2(0, 0, totalthrust.x, totalthrust.y)-P_GetObjectStandingSlopeDirection(player->mo);
if (player->mo->standingslope->zdelta < 0) { // Direction goes down, so thrustangle needs to face toward if (player->mo->standingslope->zdelta < 0) { // Direction goes down, so thrustangle needs to face toward
if (thrustangle < ANGLE_90 || thrustangle > ANGLE_270) { if (thrustangle < ANGLE_90 || thrustangle > ANGLE_270) {
P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope); P_QuantizeObjectMomentumToSlope(player->mo, &totalthrust);
} }
} else { // Direction goes up, so thrustangle needs to face away } else { // Direction goes up, so thrustangle needs to face away
if (thrustangle > ANGLE_90 && thrustangle < ANGLE_270) { if (thrustangle > ANGLE_90 && thrustangle < ANGLE_270) {
P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope); P_QuantizeObjectMomentumToSlope(player->mo, &totalthrust);
} }
} }
} }