Merge branch 'hotfix-pltz' into 'next'

Re-add/fix broken platform momz mobj code.

The changes in this branch re-add the platform's momentum to players and mobjs which leave the platform (eg. by jumping) so that they move with relative velocity as expected. This behavior was unintentionally broken in SRB2 2.0, which adds a lot of artificial difficulty to certain segments of the levels, where you have to jump between high velocity moving platforms which seemingly cut your jump height to nothing.

Not only has the behavior been fixed, but it has now been enhanced to move the camera while free-falling between platforms as well, completing the illusion of full relative velocity with minimal hiccups. [Observe.](http://i.imgur.com/zmSfUyp.gifv)

See merge request !14
This commit is contained in:
Alam Ed Arias 2015-06-18 10:04:54 -04:00
commit a03fc205b4
6 changed files with 57 additions and 69 deletions

View file

@ -7207,6 +7207,7 @@ static const char *const MOBJEFLAG_LIST[] = {
"GOOWATER", // Goo water "GOOWATER", // Goo water
"PUSHED", // Mobj was already pushed this tic "PUSHED", // Mobj was already pushed this tic
"SPRUNG", // Mobj was already sprung this tic "SPRUNG", // Mobj was already sprung this tic
"APPLYPMOMZ", // Platform movement
NULL NULL
}; };

View file

@ -449,6 +449,7 @@ static int mobj_set(lua_State *L)
break; break;
case mobj_pmomz: case mobj_pmomz:
mo->pmomz = (fixed_t)luaL_checkinteger(L, 3); mo->pmomz = (fixed_t)luaL_checkinteger(L, 3);
mo->eflags |= MFE_APPLYPMOMZ;
break; break;
case mobj_tics: case mobj_tics:
mo->tics = luaL_checkinteger(L, 3); mo->tics = luaL_checkinteger(L, 3);

View file

@ -2042,6 +2042,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
// //
static boolean P_ThingHeightClip(mobj_t *thing) static boolean P_ThingHeightClip(mobj_t *thing)
{ {
boolean floormoved;
fixed_t oldfloorz = thing->floorz; fixed_t oldfloorz = thing->floorz;
boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz);
@ -2053,6 +2054,9 @@ static boolean P_ThingHeightClip(mobj_t *thing)
if (P_MobjWasRemoved(thing)) if (P_MobjWasRemoved(thing))
return true; return true;
floormoved = (thing->eflags & MFE_VERTICALFLIP && tmceilingz != thing->ceilingz)
|| (!(thing->eflags & MFE_VERTICALFLIP) && tmfloorz != thing->floorz);
thing->floorz = tmfloorz; thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz; thing->ceilingz = tmceilingz;
@ -2061,20 +2065,13 @@ static boolean P_ThingHeightClip(mobj_t *thing)
if (tmfloorz > oldfloorz+thing->height) if (tmfloorz > oldfloorz+thing->height)
return true; return true;
if (/*!tmfloorthing && */onfloor && !(thing->flags & MF_NOGRAVITY)) if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved)
{ {
if (thing->eflags & MFE_VERTICALFLIP) if (thing->eflags & MFE_VERTICALFLIP)
thing->pmomz = thing->ceilingz - (thing->z + thing->height); thing->pmomz = thing->ceilingz - (thing->z + thing->height);
else else
thing->pmomz = thing->floorz - thing->z; thing->pmomz = thing->floorz - thing->z;
thing->eflags |= MFE_APPLYPMOMZ;
if (thing->player)
{
if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer])
camera2.z += thing->pmomz;
else if (camera.chase && thing->player == &players[displayplayer])
camera.z += thing->pmomz;
}
if (thing->eflags & MFE_VERTICALFLIP) if (thing->eflags & MFE_VERTICALFLIP)
thing->z = thing->ceilingz - thing->height; thing->z = thing->ceilingz - thing->height;

View file

@ -1493,10 +1493,10 @@ static void P_RingZMovement(mobj_t *mo)
P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector); P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
// adjust height // adjust height
if (mo->pmomz && mo->z != mo->floorz) if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{ {
mo->momz += mo->pmomz; mo->momz += mo->pmomz;
mo->pmomz = 0; mo->eflags &= ~MFE_APPLYPMOMZ;
} }
mo->z += mo->momz; mo->z += mo->momz;
@ -1562,10 +1562,10 @@ static boolean P_ZMovement(mobj_t *mo)
P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector); P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
// adjust height // adjust height
if (mo->pmomz && mo->z != mo->floorz) if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{ {
mo->momz += mo->pmomz; mo->momz += mo->pmomz;
mo->pmomz = 0; mo->eflags &= ~MFE_APPLYPMOMZ;
} }
mo->z += mo->momz; mo->z += mo->momz;
@ -1987,11 +1987,11 @@ static void P_PlayerZMovement(mobj_t *mo)
} }
// adjust height // adjust height
/* if (mo->pmomz && mo->z > mo->floorz && !(mo->player->pflags & PF_JUMPED)) if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{ {
mo->momz += mo->pmomz; mo->momz += mo->pmomz;
mo->pmomz = 0; mo->eflags &= ~MFE_APPLYPMOMZ;
}*/ }
mo->z += mo->momz; mo->z += mo->momz;
@ -2008,7 +2008,7 @@ static void P_PlayerZMovement(mobj_t *mo)
else else
mo->z = mo->floorz; mo->z = mo->floorz;
if (mo->player && (mo->player->pflags & PF_NIGHTSMODE)) if (mo->player->pflags & PF_NIGHTSMODE)
{ {
if (mo->player->flyangle < 90 || mo->player->flyangle >= 270) if (mo->player->flyangle < 90 || mo->player->flyangle >= 270)
mo->player->flyangle += P_MobjFlip(mo)*90; mo->player->flyangle += P_MobjFlip(mo)*90;
@ -2023,12 +2023,11 @@ static void P_PlayerZMovement(mobj_t *mo)
if (P_MobjFlip(mo)*mo->momz < 0) // falling if (P_MobjFlip(mo)*mo->momz < 0) // falling
{ {
mo->pmomz = 0; // We're on a new floor, don't keep doing platform movement.
// Squat down. Decrease viewheight for a moment after hitting the ground (hard), // Squat down. Decrease viewheight for a moment after hitting the ground (hard),
if (mo->player) if (P_MobjFlip(mo)*mo->momz < -FixedMul(8*FRACUNIT, mo->scale))
{ mo->player->deltaviewheight = (P_MobjFlip(mo)*mo->momz)>>3; // make sure momz is negative
if (P_MobjFlip(mo)*mo->momz < -FixedMul(8*FRACUNIT, mo->scale))
mo->player->deltaviewheight = (P_MobjFlip(mo)*mo->momz)>>3; // make sure momz is negative
}
if (!tmfloorthing || tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) if (!tmfloorthing || tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
|| tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER) // Spin Attack || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER) // Spin Attack
@ -2101,14 +2100,14 @@ static void P_PlayerZMovement(mobj_t *mo)
// Cut momentum in half when you hit the ground and // Cut momentum in half when you hit the ground and
// aren't pressing any controls. // aren't pressing any controls.
if (!mo->player || (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING))) if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING))
{ {
mo->momx = mo->momx/2; mo->momx = mo->momx/2;
mo->momy = mo->momy/2; mo->momy = mo->momy/2;
} }
} }
if (mo->health && mo->player) if (mo->health)
{ {
if (mo->player->pflags & PF_GLIDING) // ground gliding if (mo->player->pflags & PF_GLIDING) // ground gliding
{ {
@ -2154,7 +2153,7 @@ static void P_PlayerZMovement(mobj_t *mo)
mo->player->powers[pw_tailsfly] = 0; mo->player->powers[pw_tailsfly] = 0;
} }
} }
if (mo->player && !(mo->player->pflags & PF_SPINNING)) if (!(mo->player->pflags & PF_SPINNING))
mo->player->pflags &= ~PF_STARTDASH; mo->player->pflags &= ~PF_STARTDASH;
if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
@ -2197,7 +2196,7 @@ nightsdone:
else else
mo->z = mo->ceilingz - mo->height; mo->z = mo->ceilingz - mo->height;
if (mo->player && (mo->player->pflags & PF_NIGHTSMODE)) if (mo->player->pflags & PF_NIGHTSMODE)
{ {
if (mo->player->flyangle < 90 || mo->player->flyangle >= 270) if (mo->player->flyangle < 90 || mo->player->flyangle >= 270)
mo->player->flyangle -= P_MobjFlip(mo)*90; mo->player->flyangle -= P_MobjFlip(mo)*90;
@ -2212,7 +2211,7 @@ nightsdone:
{ {
msecnode_t *node; msecnode_t *node;
if (CheckForMarioBlocks && mo->player && !(netgame && mo->player->spectator)) // Only let the player punch if (CheckForMarioBlocks && !(netgame && mo->player->spectator)) // Only let the player punch
{ {
// Search the touching sectors, from side-to-side... // Search the touching sectors, from side-to-side...
for (node = mo->touching_sectorlist; node; node = node->m_snext) for (node = mo->touching_sectorlist; node; node = node->m_snext)
@ -2240,7 +2239,7 @@ nightsdone:
if (mariomode) if (mariomode)
S_StartSound(mo, sfx_mario1); S_StartSound(mo, sfx_mario1);
if (!(mo->player && mo->player->climbing)) if (!mo->player->climbing)
mo->momz = 0; mo->momz = 0;
} }
} }
@ -2255,10 +2254,10 @@ static boolean P_SceneryZMovement(mobj_t *mo)
P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector); P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
// adjust height // adjust height
if (mo->pmomz && mo->z != mo->floorz) if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{ {
mo->momz += mo->pmomz; mo->momz += mo->pmomz;
mo->pmomz = 0; mo->eflags &= ~MFE_APPLYPMOMZ;
} }
mo->z += mo->momz; mo->z += mo->momz;
@ -2838,10 +2837,10 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
thiscam->floorz = tmfloorz; thiscam->floorz = tmfloorz;
thiscam->ceilingz = tmceilingz; thiscam->ceilingz = tmceilingz;
if (thiscam->momz) if (thiscam->momz || player->mo->pmomz)
{ {
// adjust height // adjust height
thiscam->z += thiscam->momz; thiscam->z += thiscam->momz + player->mo->pmomz;
if (!itsatwodlevel && !(player->pflags & PF_NOCLIP)) if (!itsatwodlevel && !(player->pflags & PF_NOCLIP))
{ {
@ -2899,6 +2898,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
msecnode_t *node; msecnode_t *node;
I_Assert(mobj != NULL); I_Assert(mobj != NULL);
I_Assert(mobj->player != NULL);
I_Assert(!P_MobjWasRemoved(mobj)); I_Assert(!P_MobjWasRemoved(mobj));
P_MobjCheckWater(mobj); P_MobjCheckWater(mobj);
@ -2917,7 +2917,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
P_CheckPosition(mobj, mobj->x, mobj->y); P_CheckPosition(mobj, mobj->x, mobj->y);
goto animonly; goto animonly;
} }
else if (mobj->player && (mobj->player->pflags & PF_MACESPIN) && mobj->tracer) else if (mobj->player->pflags & PF_MACESPIN && mobj->tracer)
{ {
P_CheckPosition(mobj, mobj->x, mobj->y); P_CheckPosition(mobj, mobj->x, mobj->y);
goto animonly; goto animonly;
@ -2936,7 +2936,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
else else
P_TryMove(mobj, mobj->x, mobj->y, true); P_TryMove(mobj, mobj->x, mobj->y, true);
if (!(netgame && mobj->player && mobj->player->spectator)) if (!(netgame && mobj->player->spectator))
{ {
// Crumbling platforms // Crumbling platforms
for (node = mobj->touching_sectorlist; node; node = node->m_snext) for (node = mobj->touching_sectorlist; node; node = node->m_snext)
@ -3019,18 +3019,14 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
} }
else else
{ {
if (mobj->player) mobj->player->jumping = 0;
mobj->player->pflags &= ~PF_JUMPED;
if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
{ {
mobj->player->jumping = 0; mobj->player->secondjump = 0;
mobj->player->pflags &= ~PF_JUMPED; mobj->player->powers[pw_tailsfly] = 0;
if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly]) P_SetPlayerMobjState(mobj, S_PLAY_RUN1);
{
mobj->player->secondjump = 0;
mobj->player->powers[pw_tailsfly] = 0;
P_SetPlayerMobjState(mobj, S_PLAY_RUN1);
}
} }
mobj->pmomz = 0;
mobj->eflags &= ~MFE_JUSTHITFLOOR; mobj->eflags &= ~MFE_JUSTHITFLOOR;
} }
@ -6648,17 +6644,6 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
} }
else else
{ {
if (mobj->player)
{
mobj->player->jumping = 0;
mobj->player->pflags &= ~PF_JUMPED;
if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
{
mobj->player->secondjump = 0;
mobj->player->powers[pw_tailsfly] = 0;
P_SetPlayerMobjState(mobj, S_PLAY_RUN1);
}
}
mobj->pmomz = 0; // to prevent that weird rocketing gargoyle bug mobj->pmomz = 0; // to prevent that weird rocketing gargoyle bug
mobj->eflags &= ~MFE_JUSTHITFLOOR; mobj->eflags &= ~MFE_JUSTHITFLOOR;
} }
@ -6859,17 +6844,6 @@ void P_SceneryThinker(mobj_t *mobj)
} }
else else
{ {
if (mobj->player)
{
mobj->player->jumping = 0;
mobj->player->pflags &= ~PF_JUMPED;
if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
{
mobj->player->secondjump = 0;
mobj->player->powers[pw_tailsfly] = 0;
P_SetPlayerMobjState(mobj, S_PLAY_RUN1);
}
}
mobj->pmomz = 0; // to prevent that weird rocketing gargoyle bug mobj->pmomz = 0; // to prevent that weird rocketing gargoyle bug
mobj->eflags &= ~MFE_JUSTHITFLOOR; mobj->eflags &= ~MFE_JUSTHITFLOOR;
} }

View file

@ -235,6 +235,8 @@ typedef enum
MFE_PUSHED = 1<<7, MFE_PUSHED = 1<<7,
// Mobj was already sprung this tic // Mobj was already sprung this tic
MFE_SPRUNG = 1<<8, MFE_SPRUNG = 1<<8,
// Platform movement
MFE_APPLYPMOMZ = 1<<9,
// free: to and including 1<<15 // free: to and including 1<<15
} mobjeflag_t; } mobjeflag_t;

View file

@ -3635,11 +3635,22 @@ void P_DoJump(player_t *player, boolean soundandstate)
// set just an eensy above the ground // set just an eensy above the ground
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
{
player->mo->z--; player->mo->z--;
if (player->mo->pmomz < 0)
player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump.
else
player->mo->pmomz = 0;
}
else else
{
player->mo->z++; player->mo->z++;
if (player->mo->pmomz > 0)
player->mo->z += player->mo->pmomz; // Solves problem of 'hitting around again after jumping on a moving platform'. player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump.
else
player->mo->pmomz = 0;
}
player->mo->eflags &= ~MFE_APPLYPMOMZ;
player->pflags |= PF_JUMPED; player->pflags |= PF_JUMPED;
@ -9046,7 +9057,6 @@ void P_PlayerThink(player_t *player)
player->mo->tracer->flags2 &= ~MF2_DONTDRAW; player->mo->tracer->flags2 &= ~MF2_DONTDRAW;
} }
player->mo->pmomz = 0;
player->pflags &= ~PF_SLIDING; player->pflags &= ~PF_SLIDING;
/* /*
@ -9399,4 +9409,7 @@ void P_PlayerAfterThink(player_t *player)
player->mo->flags2 |= MF2_DONTDRAW; player->mo->flags2 |= MF2_DONTDRAW;
player->mo->flags |= MF_NOGRAVITY; player->mo->flags |= MF_NOGRAVITY;
} }
if (P_IsObjectOnGround(player->mo))
player->mo->pmomz = 0;
} }