Merge branch 'movement-refactor' into 'next'

Clean up some movement code

See merge request STJr/SRB2!912
This commit is contained in:
MascaraSnake 2020-06-01 07:21:41 -04:00
commit 8d7f4e3265
3 changed files with 615 additions and 568 deletions

View File

@ -3291,9 +3291,128 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
return false;
}
//
// PTR_SlideTraverse
//
static boolean PTR_LineIsBlocking(line_t *li)
{
// one-sided linedefs are always solid to sliding movement.
if (!li->backsector)
return !P_PointOnLineSide(slidemo->x, slidemo->y, li);
if (!(slidemo->flags & MF_MISSILE))
{
if (li->flags & ML_IMPASSIBLE)
return true;
if ((slidemo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS)
return true;
}
// set openrange, opentop, openbottom
P_LineOpening(li, slidemo);
if (openrange < slidemo->height)
return true; // doesn't fit
if (opentop - slidemo->z < slidemo->height)
return true; // mobj is too high
if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale))
return true; // too big a step up
return false;
}
static void PTR_GlideClimbTraverse(line_t *li)
{
line_t *checkline = li;
ffloor_t *rover;
fixed_t topheight, bottomheight;
boolean fofline = false;
sector_t *checksector = (li->backsector && !P_PointOnLineSide(slidemo->x, slidemo->y, li)) ? li->backsector : li->frontsector;
if (checksector->ffloors)
{
for (rover = checksector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
continue;
topheight = P_GetFFloorTopZAt (rover, slidemo->x, slidemo->y);
bottomheight = P_GetFFloorBottomZAt(rover, slidemo->x, slidemo->y);
if (topheight < slidemo->z)
continue;
if (bottomheight > slidemo->z + slidemo->height)
continue;
// Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this?
if (rover->master->flags & ML_TFERLINE)
{
size_t linenum = li-checksector->lines[0];
checkline = rover->master->frontsector->lines[0] + linenum;
fofline = true;
}
break;
}
}
// see about climbing on the wall
if (!(checkline->flags & ML_NOCLIMB) && checkline->special != HORIZONSPECIAL)
{
boolean canclimb;
angle_t climbangle, climbline;
INT32 whichside = P_PointOnLineSide(slidemo->x, slidemo->y, li);
climbangle = climbline = R_PointToAngle2(li->v1->x, li->v1->y, li->v2->x, li->v2->y);
if (whichside) // on second side?
climbline += ANGLE_180;
climbangle += (ANGLE_90 * (whichside ? -1 : 1));
canclimb = (li->backsector ? P_IsClimbingValid(slidemo->player, climbangle) : true);
if (((!slidemo->player->climbing && abs((signed)(slidemo->angle - ANGLE_90 - climbline)) < ANGLE_45)
|| (slidemo->player->climbing == 1 && abs((signed)(slidemo->angle - climbline)) < ANGLE_135))
&& canclimb)
{
slidemo->angle = climbangle;
/*if (!demoplayback || P_ControlStyle(slidemo->player) == CS_LMAOGALOG)
{
if (slidemo->player == &players[consoleplayer])
localangle = slidemo->angle;
else if (slidemo->player == &players[secondarydisplayplayer])
localangle2 = slidemo->angle;
}*/
if (!slidemo->player->climbing)
{
S_StartSound(slidemo->player->mo, sfx_s3k4a);
slidemo->player->climbing = 5;
}
slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED);
slidemo->player->glidetime = 0;
slidemo->player->secondjump = 0;
if (slidemo->player->climbing > 1)
slidemo->momz = slidemo->momx = slidemo->momy = 0;
if (fofline)
whichside = 0;
if (!whichside)
{
slidemo->player->lastsidehit = checkline->sidenum[whichside];
slidemo->player->lastlinehit = (INT16)(checkline - lines);
}
P_Thrust(slidemo, slidemo->angle, FixedMul(5*FRACUNIT, slidemo->scale));
}
}
}
static boolean PTR_SlideTraverse(intercept_t *in)
{
line_t *li;
@ -3302,146 +3421,20 @@ static boolean PTR_SlideTraverse(intercept_t *in)
li = in->d.line;
// one-sided linedefs are always solid to sliding movement.
// one-sided linedef
if (!li->backsector)
{
if (P_PointOnLineSide(slidemo->x, slidemo->y, li))
return true; // don't hit the back side
goto isblocking;
}
if (!PTR_LineIsBlocking(li))
return true;
if (!(slidemo->flags & MF_MISSILE))
{
if (li->flags & ML_IMPASSIBLE)
goto isblocking;
if ((slidemo->flags & (MF_ENEMY|MF_BOSS)) && li->flags & ML_BLOCKMONSTERS)
goto isblocking;
}
// set openrange, opentop, openbottom
P_LineOpening(li, slidemo);
if (openrange < slidemo->height)
goto isblocking; // doesn't fit
if (opentop - slidemo->z < slidemo->height)
goto isblocking; // mobj is too high
if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale))
goto isblocking; // too big a step up
// this line doesn't block movement
return true;
// the line does block movement,
// the line blocks movement,
// see if it is closer than best so far
isblocking:
if (li->polyobj && slidemo->player)
{
if ((li->polyobj->lines[0]->backsector->flags & SF_TRIGGERSPECIAL_TOUCH) && !(li->polyobj->flags & POF_NOSPECIALS))
P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector);
}
if (slidemo->player && (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing)
&& slidemo->player->charability == CA_GLIDEANDCLIMB)
{
line_t *checkline = li;
sector_t *checksector;
ffloor_t *rover;
fixed_t topheight, bottomheight;
boolean fofline = false;
INT32 side = P_PointOnLineSide(slidemo->x, slidemo->y, li);
if (!side && li->backsector)
checksector = li->backsector;
else
checksector = li->frontsector;
if (checksector->ffloors)
{
for (rover = checksector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
continue;
topheight = P_GetFFloorTopZAt (rover, slidemo->x, slidemo->y);
bottomheight = P_GetFFloorBottomZAt(rover, slidemo->x, slidemo->y);
if (topheight < slidemo->z)
continue;
if (bottomheight > slidemo->z + slidemo->height)
continue;
// Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this?
if (rover->master->flags & ML_TFERLINE)
{
size_t linenum = li-checksector->lines[0];
checkline = rover->master->frontsector->lines[0] + linenum;
fofline = true;
}
break;
}
}
// see about climbing on the wall
if (!(checkline->flags & ML_NOCLIMB) && checkline->special != HORIZONSPECIAL)
{
boolean canclimb;
angle_t climbangle, climbline;
INT32 whichside = P_PointOnLineSide(slidemo->x, slidemo->y, li);
climbangle = climbline = R_PointToAngle2(li->v1->x, li->v1->y, li->v2->x, li->v2->y);
if (whichside) // on second side?
climbline += ANGLE_180;
climbangle += (ANGLE_90 * (whichside ? -1 : 1));
canclimb = (li->backsector ? P_IsClimbingValid(slidemo->player, climbangle) : true);
if (((!slidemo->player->climbing && abs((signed)(slidemo->angle - ANGLE_90 - climbline)) < ANGLE_45)
|| (slidemo->player->climbing == 1 && abs((signed)(slidemo->angle - climbline)) < ANGLE_135))
&& canclimb)
{
slidemo->angle = climbangle;
/*if (!demoplayback || P_ControlStyle(slidemo->player) == CS_LMAOGALOG)
{
if (slidemo->player == &players[consoleplayer])
localangle = slidemo->angle;
else if (slidemo->player == &players[secondarydisplayplayer])
localangle2 = slidemo->angle;
}*/
if (!slidemo->player->climbing)
{
S_StartSound(slidemo->player->mo, sfx_s3k4a);
slidemo->player->climbing = 5;
}
slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED);
slidemo->player->glidetime = 0;
slidemo->player->secondjump = 0;
if (slidemo->player->climbing > 1)
slidemo->momz = slidemo->momx = slidemo->momy = 0;
if (fofline)
whichside = 0;
if (!whichside)
{
slidemo->player->lastsidehit = checkline->sidenum[whichside];
slidemo->player->lastlinehit = (INT16)(checkline - lines);
}
P_Thrust(slidemo, slidemo->angle, FixedMul(5*FRACUNIT, slidemo->scale));
}
}
}
if (slidemo->player && slidemo->player->charability == CA_GLIDEANDCLIMB
&& (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing))
PTR_GlideClimbTraverse(li);
if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing))
{

View File

@ -1669,70 +1669,74 @@ static void P_PushableCheckBustables(mobj_t *mo)
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
if (!node->m_sector)
break;
if (node->m_sector->ffloors)
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
if (!(rover->flags & FF_EXISTS))
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
if (!(rover->flags & FF_BUSTUP))
continue;
// Needs ML_EFFECT4 flag for pushables to break it
if (!(rover->master->flags & ML_EFFECT4))
continue;
if (rover->master->frontsector->crumblestate != CRUMBLE_NONE)
continue;
topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
// Height checks
if (rover->flags & FF_SHATTERBOTTOM)
{
if (!(rover->flags & FF_EXISTS)) continue;
if (mo->z + mo->momz + mo->height < bottomheight)
continue;
if (!(rover->flags & FF_BUSTUP)) continue;
// Needs ML_EFFECT4 flag for pushables to break it
if (!(rover->master->flags & ML_EFFECT4)) continue;
if (rover->master->frontsector->crumblestate == CRUMBLE_NONE)
{
topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
// Height checks
if (rover->flags & FF_SHATTERBOTTOM)
{
if (mo->z+mo->momz + mo->height < bottomheight)
continue;
if (mo->z+mo->height > bottomheight)
continue;
}
else if (rover->flags & FF_SPINBUST)
{
if (mo->z+mo->momz > topheight)
continue;
if (mo->z+mo->height < bottomheight)
continue;
}
else if (rover->flags & FF_SHATTER)
{
if (mo->z+mo->momz > topheight)
continue;
if (mo->z+mo->momz + mo->height < bottomheight)
continue;
}
else
{
if (mo->z >= topheight)
continue;
if (mo->z+mo->height < bottomheight)
continue;
}
EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor??
if (rover->master->flags & ML_EFFECT5)
P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), mo, node->m_sector);
goto bustupdone;
}
if (mo->z + mo->height > bottomheight)
continue;
}
else if (rover->flags & FF_SPINBUST)
{
if (mo->z + mo->momz > topheight)
continue;
if (mo->z + mo->height < bottomheight)
continue;
}
else if (rover->flags & FF_SHATTER)
{
if (mo->z + mo->momz > topheight)
continue;
if (mo->z + mo->momz + mo->height < bottomheight)
continue;
}
else
{
if (mo->z >= topheight)
continue;
if (mo->z + mo->height < bottomheight)
continue;
}
EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor??
if (rover->master->flags & ML_EFFECT5)
P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), mo, node->m_sector);
goto bustupdone;
}
}
bustupdone:
@ -2793,6 +2797,94 @@ static boolean P_ZMovement(mobj_t *mo)
return true;
}
// Check for "Mario" blocks to hit and bounce them
static void P_CheckMarioBlocks(mobj_t *mo)
{
msecnode_t *node;
if (netgame && mo->player->spectator)
return;
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_MARIO))
continue;
if (mo->eflags & MFE_VERTICALFLIP)
continue; // if you were flipped, your head isn't actually hitting your ceilingz is it?
if (*rover->bottomheight != mo->ceilingz)
continue;
if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
EV_CrumbleChain(node->m_sector, rover);
else // Question block!
EV_MarioBlock(rover, node->m_sector, mo);
}
}
}
// Check if we're on a polyobject that triggers a linedef executor.
static boolean P_PlayerPolyObjectZMovement(mobj_t *mo)
{
msecnode_t *node;
boolean stopmovecut = false;
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
sector_t *sec = node->m_sector;
subsector_t *newsubsec;
size_t i;
for (i = 0; i < numsubsectors; i++)
{
polyobj_t *po;
sector_t *polysec;
newsubsec = &subsectors[i];
if (newsubsec->sector != sec)
continue;
for (po = newsubsec->polyList; po; po = (polyobj_t *)(po->link.next))
{
if (!(po->flags & POF_SOLID))
continue;
if (!P_MobjInsidePolyobj(po, mo))
continue;
polysec = po->lines[0]->backsector;
// Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red
if ((mo->z == polysec->ceilingheight || mo->z + mo->height == polysec->floorheight) && po->thinker)
stopmovecut = true;
if (!(po->flags & POF_LDEXEC))
continue;
if (mo->z != polysec->ceilingheight)
continue;
// We're landing on a PO, so check for a linedef executor.
// Trigger tags are 32000 + the PO's ID number.
P_LinedefExecute((INT16)(32000 + po->id), mo, NULL);
}
}
}
return stopmovecut;
}
static void P_PlayerZMovement(mobj_t *mo)
{
boolean onground;
@ -2889,66 +2981,8 @@ static void P_PlayerZMovement(mobj_t *mo)
mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack
if (!P_PlayerPolyObjectZMovement(mo))
{
// Check if we're on a polyobject
// that triggers a linedef executor.
msecnode_t *node;
boolean stopmovecut = false;
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
sector_t *sec = node->m_sector;
subsector_t *newsubsec;
size_t i;
for (i = 0; i < numsubsectors; i++)
{
newsubsec = &subsectors[i];
if (newsubsec->sector != sec)
continue;
if (newsubsec->polyList)
{
polyobj_t *po = newsubsec->polyList;
sector_t *polysec;
while(po)
{
if (!P_MobjInsidePolyobj(po, mo) || !(po->flags & POF_SOLID))
{
po = (polyobj_t *)(po->link.next);
continue;
}
// We're inside it! Yess...
polysec = po->lines[0]->backsector;
// Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red
if ((mo->z == polysec->ceilingheight || mo->z+mo->height == polysec->floorheight) && po->thinker)
stopmovecut = true;
if (!(po->flags & POF_LDEXEC))
{
po = (polyobj_t *)(po->link.next);
continue;
}
if (mo->z == polysec->ceilingheight)
{
// We're landing on a PO, so check for
// a linedef executor.
// Trigger tags are 32000 + the PO's ID number.
P_LinedefExecute((INT16)(32000 + po->id), mo, NULL);
}
po = (polyobj_t *)(po->link.next);
}
}
}
}
if (!stopmovecut)
// Cut momentum in half when you hit the ground and
// aren't pressing any controls.
if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING))
@ -3014,39 +3048,10 @@ nightsdone:
}
}
// Check for "Mario" blocks to hit and bounce them
if (P_MobjFlip(mo)*mo->momz > 0)
{
msecnode_t *node;
if (CheckForMarioBlocks && !(netgame && mo->player->spectator)) // Only let the player punch
{
// Search the touching sectors, from side-to-side...
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
// Come on, it's time to go...
if (rover->flags & FF_MARIO
&& !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it?
&& *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom!
{
// DO THE MARIO!
if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
EV_CrumbleChain(node->m_sector, rover);
else // Question block!
EV_MarioBlock(rover, node->m_sector, mo);
}
}
} // Ugly ugly billions of braces! Argh!
}
if (CheckForMarioBlocks)
P_CheckMarioBlocks(mo);
// hit the ceiling
if (mariomode)
@ -3750,13 +3755,114 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
return false;
}
//
// P_PlayerMobjThinker
//
static void P_PlayerMobjThinker(mobj_t *mobj)
static void P_CheckCrumblingPlatforms(mobj_t *mobj)
{
msecnode_t *node;
if (netgame && mobj->player->spectator)
return;
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_CRUMBLE))
continue;
if (mobj->eflags & MFE_VERTICALFLIP)
{
if (P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z + mobj->height)
continue;
}
else
{
if (P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z)
continue;
}
EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN));
}
}
}
static boolean P_MobjTouchesSectorWithWater(mobj_t *mobj)
{
msecnode_t *node;
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_SWIMMABLE))
continue;
return true;
}
}
return false;
}
// Check for floating water platforms and bounce them
static void P_CheckFloatbobPlatforms(mobj_t *mobj)
{
msecnode_t *node;
// Can't land on anything if you're not moving downwards
if (P_MobjFlip(mobj)*mobj->momz >= 0)
return;
if (!P_MobjTouchesSectorWithWater(mobj))
return;
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_FLOATBOB))
continue;
if (mobj->eflags & MFE_VERTICALFLIP)
{
if (abs(*rover->bottomheight - (mobj->z + mobj->height)) > abs(mobj->momz))
continue;
}
else
{
if (abs(*rover->topheight - mobj->z) > abs(mobj->momz))
continue;
}
// Initiate a 'bouncy' elevator function which slowly diminishes.
EV_BounceSector(rover->master->frontsector, -mobj->momz, rover->master);
}
}
}
static void P_PlayerMobjThinker(mobj_t *mobj)
{
I_Assert(mobj != NULL);
I_Assert(mobj->player != NULL);
I_Assert(!P_MobjWasRemoved(mobj));
@ -3809,77 +3915,10 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
else
P_TryMove(mobj, mobj->x, mobj->y, true);
if (!(netgame && mobj->player->spectator))
{
// Crumbling platforms
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
fixed_t topheight, bottomheight;
ffloor_t *rover;
P_CheckCrumblingPlatforms(mobj);
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_CRUMBLE))
continue;
topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector);
bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector);
if ((topheight == mobj->z && !(mobj->eflags & MFE_VERTICALFLIP))
|| (bottomheight == mobj->z + mobj->height && mobj->eflags & MFE_VERTICALFLIP)) // You nut.
EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN));
}
}
}
// Check for floating water platforms and bounce them
if (CheckForFloatBob && P_MobjFlip(mobj)*mobj->momz < 0)
{
boolean thereiswater = false;
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
if (node->m_sector->ffloors)
{
ffloor_t *rover;
// Get water boundaries first
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (rover->flags & FF_SWIMMABLE) // Is there water?
{
thereiswater = true;
break;
}
}
}
}
if (thereiswater)
{
for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next)
{
if (node->m_sector->ffloors)
{
ffloor_t *rover;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_FLOATBOB))
continue;
if ((!(mobj->eflags & MFE_VERTICALFLIP) && abs(*rover->topheight-mobj->z) <= abs(mobj->momz)) // The player is landing on the cheese!
|| (mobj->eflags & MFE_VERTICALFLIP && abs(*rover->bottomheight-(mobj->z+mobj->height)) <= abs(mobj->momz)))
{
// Initiate a 'bouncy' elevator function
// which slowly diminishes.
EV_BounceSector(rover->master->frontsector, -mobj->momz, rover->master);
}
}
}
}
} // Ugly ugly billions of braces! Argh!
}
if (CheckForFloatBob)
P_CheckFloatbobPlatforms(mobj);
// always do the gravity bit now, that's simpler
// BUT CheckPosition only if wasn't done before.

View File

@ -2521,6 +2521,72 @@ boolean P_InQuicksand(mobj_t *mo) // Returns true if you are in quicksand
return false; // No sand here, Captain!
}
static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover)
{
if (!(rover->flags & FF_EXISTS))
return false;
if (!(rover->flags & FF_BUSTUP))
return false;
/*if (rover->master->frontsector->crumblestate != CRUMBLE_NONE)
return false;*/
// If it's an FF_SHATTER, you can break it just by touching it.
if (rover->flags & FF_SHATTER)
return true;
// If it's an FF_SPINBUST, you can break it if you are in your spinning frames
// (either from jumping or spindashing).
if (rover->flags & FF_SPINBUST)
{
if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_STARTDASH))
return true;
if ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE))
return true;
}
// Strong abilities can break even FF_STRONGBUST.
if (player->charability == CA_GLIDEANDCLIMB)
return true;
if (player->pflags & PF_BOUNCING)
return true;
if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)
return true;
if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)
return true;
// Everyone else is out of luck.
if (rover->flags & FF_STRONGBUST)
return false;
// Spinning (and not jumping)
if ((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED))
return true;
// Super
if (player->powers[pw_super])
return true;
// Dashmode
if ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) && player->dashmode >= DASHMODE_THRESHOLD)
return true;
// NiGHTS drill
if (player->pflags & PF_DRILLING)
return true;
// Recording for Metal Sonic
if (metalrecording)
return true;
return false;
}
static void P_CheckBustableBlocks(player_t *player)
{
msecnode_t *node;
@ -2543,121 +2609,83 @@ static void P_CheckBustableBlocks(player_t *player)
for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
if (!node->m_sector)
break;
if (node->m_sector->ffloors)
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
if (!P_PlayerCanBust(player, rover))
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
if (((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY))
|| ((P_MobjFlip(player->mo)*player->mo->momz < 0) && (player->pflags & PF_BOUNCING || ((player->charability2 == CA2_MELEE) && (player->panim == PA_ABILITY2)))))
{
if (!(rover->flags & FF_EXISTS)) continue;
if ((rover->flags & FF_BUSTUP)/* && rover->master->frontsector->crumblestate == CRUMBLE_NONE*/)
{
// If it's an FF_SHATTER, you can break it just by touching it.
if (rover->flags & FF_SHATTER)
goto bust;
// If it's an FF_SPINBUST, you can break it if you are in your spinning frames
// (either from jumping or spindashing).
if (rover->flags & FF_SPINBUST
&& (((player->pflags & PF_SPINNING) && !(player->pflags & PF_STARTDASH))
|| (player->pflags & PF_JUMPED && !(player->pflags & PF_NOJUMPDAMAGE))))
goto bust;
// You can always break it if you have CA_GLIDEANDCLIMB
// or if you are bouncing on it
// or you are using CA_TWINSPIN/CA2_MELEE.
if (player->charability == CA_GLIDEANDCLIMB
|| (player->pflags & PF_BOUNCING)
|| ((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY))
|| (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
goto bust;
if (rover->flags & FF_STRONGBUST)
continue;
// If it's not an FF_STRONGBUST, you can break if you are spinning (and not jumping)
// or you are super
// or you are in dashmode with SF_DASHMODE
// or you are drilling in NiGHTS
// or you are recording for Metal Sonic
if (!((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED))
&& !(player->powers[pw_super])
&& !(((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)) && (player->dashmode >= DASHMODE_THRESHOLD))
&& !(player->pflags & PF_DRILLING)
&& !metalrecording)
continue;
bust:
topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
if (((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY))
|| ((P_MobjFlip(player->mo)*player->mo->momz < 0) && (player->pflags & PF_BOUNCING || ((player->charability2 == CA2_MELEE) && (player->panim == PA_ABILITY2)))))
{
topheight -= player->mo->momz;
bottomheight -= player->mo->momz;
}
// Height checks
if (rover->flags & FF_SHATTERBOTTOM)
{
if (player->mo->z+player->mo->momz + player->mo->height < bottomheight)
continue;
if (player->mo->z+player->mo->height > bottomheight)
continue;
}
else if (rover->flags & FF_SPINBUST)
{
if (player->mo->z+player->mo->momz > topheight)
continue;
if (player->mo->z + player->mo->height < bottomheight)
continue;
}
else if (rover->flags & FF_SHATTER)
{
if (player->mo->z + player->mo->momz > topheight)
continue;
if (player->mo->z+player->mo->momz + player->mo->height < bottomheight)
continue;
}
else
{
if (player->mo->z >= topheight)
continue;
if (player->mo->z + player->mo->height < bottomheight)
continue;
}
// Impede the player's fall a bit
if (((rover->flags & FF_SPINBUST) || (rover->flags & FF_SHATTER)) && player->mo->z >= topheight)
player->mo->momz >>= 1;
else if (rover->flags & FF_SHATTER)
{
player->mo->momx >>= 1;
player->mo->momy >>= 1;
}
//if (metalrecording)
// G_RecordBustup(rover);
EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor??
if (rover->master->flags & ML_EFFECT5)
P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), player->mo, node->m_sector);
goto bustupdone;
}
topheight -= player->mo->momz;
bottomheight -= player->mo->momz;
}
// Height checks
if (rover->flags & FF_SHATTERBOTTOM)
{
if (player->mo->z + player->mo->momz + player->mo->height < bottomheight)
continue;
if (player->mo->z + player->mo->height > bottomheight)
continue;
}
else if (rover->flags & FF_SPINBUST)
{
if (player->mo->z + player->mo->momz > topheight)
continue;
if (player->mo->z + player->mo->height < bottomheight)
continue;
}
else if (rover->flags & FF_SHATTER)
{
if (player->mo->z + player->mo->momz > topheight)
continue;
if (player->mo->z + player->mo->momz + player->mo->height < bottomheight)
continue;
}
else
{
if (player->mo->z >= topheight)
continue;
if (player->mo->z + player->mo->height < bottomheight)
continue;
}
// Impede the player's fall a bit
if (((rover->flags & FF_SPINBUST) || (rover->flags & FF_SHATTER)) && player->mo->z >= topheight)
player->mo->momz >>= 1;
else if (rover->flags & FF_SHATTER)
{
player->mo->momx >>= 1;
player->mo->momy >>= 1;
}
//if (metalrecording)
// G_RecordBustup(rover);
EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor??
if (rover->master->flags & ML_EFFECT5)
P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), player->mo, node->m_sector);
goto bustupdone;
}
}
bustupdone:
@ -2690,122 +2718,109 @@ static void P_CheckBouncySectors(player_t *player)
for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
ffloor_t *rover;
if (!node->m_sector)
break;
if (node->m_sector->ffloors)
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
ffloor_t *rover;
boolean top = true;
fixed_t bouncestrength;
fixed_t topheight, bottomheight;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
if (!(rover->flags & FF_EXISTS))
continue; // FOFs should not be bouncy if they don't even "exist"
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 15)
continue; // this sector type is required for FOFs to be bouncy
topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
if (player->mo->z > topheight)
continue;
if (player->mo->z + player->mo->height < bottomheight)
continue;
bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100;
if (oldz < P_GetFOFTopZ(player->mo, node->m_sector, rover, oldx, oldy, NULL)
&& oldz + player->mo->height > P_GetFOFBottomZ(player->mo, node->m_sector, rover, oldx, oldy, NULL))
{
if (!(rover->flags & FF_EXISTS))
continue; // FOFs should not be bouncy if they don't even "exist"
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 15)
continue; // this sector type is required for FOFs to be bouncy
topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
if (player->mo->z > topheight)
continue;
if (player->mo->z + player->mo->height < bottomheight)
continue;
if (oldz < P_GetFOFTopZ(player->mo, node->m_sector, rover, oldx, oldy, NULL)
&& oldz + player->mo->height > P_GetFOFBottomZ(player->mo, node->m_sector, rover, oldx, oldy, NULL))
top = false;
player->mo->momx = -FixedMul(player->mo->momx,bouncestrength);
player->mo->momy = -FixedMul(player->mo->momy,bouncestrength);
if (player->pflags & PF_SPINNING)
{
fixed_t linedist;
linedist = P_AproxDistance(rover->master->v1->x-rover->master->v2->x, rover->master->v1->y-rover->master->v2->y);
linedist = FixedDiv(linedist,100*FRACUNIT);
if (top)
{
fixed_t newmom;
pslope_t *slope;
if (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) { // Hit top
slope = *rover->t_slope;
} else { // Hit bottom
slope = *rover->b_slope;
}
momentum.x = player->mo->momx;
momentum.y = player->mo->momy;
momentum.z = player->mo->momz*2;
if (slope)
P_ReverseQuantizeMomentumToSlope(&momentum, slope);
newmom = momentum.z = -FixedMul(momentum.z,linedist)/2;
if (abs(newmom) < (linedist*2))
{
goto bouncydone;
}
if (!(rover->master->flags & ML_BOUNCY))
{
if (newmom > 0)
{
if (newmom < 8*FRACUNIT)
newmom = 8*FRACUNIT;
}
else if (newmom > -8*FRACUNIT && newmom != 0)
newmom = -8*FRACUNIT;
}
if (newmom > P_GetPlayerHeight(player)/2)
newmom = P_GetPlayerHeight(player)/2;
else if (newmom < -P_GetPlayerHeight(player)/2)
newmom = -P_GetPlayerHeight(player)/2;
momentum.z = newmom*2;
if (slope)
P_QuantizeMomentumToSlope(&momentum, slope);
player->mo->momx = momentum.x;
player->mo->momy = momentum.y;
player->mo->momz = momentum.z/2;
if (player->pflags & PF_SPINNING)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
player->pflags |= PF_THOKKED;
}
}
else
{
player->mo->momx = -FixedMul(player->mo->momx,linedist);
player->mo->momy = -FixedMul(player->mo->momy,linedist);
if (player->pflags & PF_SPINNING)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
player->pflags |= PF_THOKKED;
}
}
if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<<FRACBITS, player->mo->scale) && player->mo->momz)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
}
goto bouncydone;
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
player->pflags |= PF_THOKKED;
}
}
else
{
fixed_t newmom;
pslope_t *slope = (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) ? *rover->t_slope : *rover->b_slope;
momentum.x = player->mo->momx;
momentum.y = player->mo->momy;
momentum.z = player->mo->momz*2;
if (slope)
P_ReverseQuantizeMomentumToSlope(&momentum, slope);
newmom = momentum.z = -FixedMul(momentum.z,bouncestrength)/2;
if (abs(newmom) < (bouncestrength*2))
goto bouncydone;
if (!(rover->master->flags & ML_BOUNCY))
{
if (newmom > 0)
{
if (newmom < 8*FRACUNIT)
newmom = 8*FRACUNIT;
}
else if (newmom < 0)
{
if (newmom > -8*FRACUNIT)
newmom = -8*FRACUNIT;
}
}
if (newmom > P_GetPlayerHeight(player)/2)
newmom = P_GetPlayerHeight(player)/2;
else if (newmom < -P_GetPlayerHeight(player)/2)
newmom = -P_GetPlayerHeight(player)/2;
momentum.z = newmom*2;
if (slope)
P_QuantizeMomentumToSlope(&momentum, slope);
player->mo->momx = momentum.x;
player->mo->momy = momentum.y;
player->mo->momz = momentum.z/2;
if (player->pflags & PF_SPINNING)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
player->pflags |= PF_THOKKED;
}
}
if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<<FRACBITS, player->mo->scale) && player->mo->momz)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
}
goto bouncydone;
}
}
bouncydone: