Teetering now supports slopes properly.

Behaves ALMOST as you'd expect. It gets the z position of the slope at the player coordinates when it comes to the sectorlist check (which is first), though, so there's a few oddities that are amplified with steep slopes:
* If the slope's sloping away from you at a steep angle, you might not be able to step down onto it, but you won't teeter (because it's at a step-down-able height if it extended to directly beneath you)
* If the slope's sloping towards you at a steep angle, you might end up in teetering frames when you're able to step down onto it (because it's NOT at a step-down-able height if it extended to directly beneath you)

HOWEVER, it would be pretty obnoxious to hold back code which is functionally superior in every way otherwise, and it doesn't really seem like there's a good way to get that checked tbph
This commit is contained in:
toasterbabe 2016-06-07 17:37:25 +01:00
parent 3591e92dfa
commit 9d221f4f3f

View file

@ -2853,13 +2853,31 @@ static void P_DoTeeter(player_t *player)
boolean teeter = false; boolean teeter = false;
boolean roverfloor; // solid 3d floors? boolean roverfloor; // solid 3d floors?
boolean checkedforteeter = false; boolean checkedforteeter = false;
fixed_t floorheight, ceilingheight;
fixed_t topheight, bottomheight; // for 3d floor usage
const fixed_t tiptop = FixedMul(MAXSTEPMOVE, player->mo->scale); // Distance you have to be above the ground in order to teeter. const fixed_t tiptop = FixedMul(MAXSTEPMOVE, player->mo->scale); // Distance you have to be above the ground in order to teeter.
#define maxzdelta 3<<(FRACBITS-2) // 3/4 on the fixed scale
if (player->mo->standingslope && player->mo->standingslope->zdelta >= maxzdelta) // Always teeter if the slope is too steep.
teeter = true;
#undef maxzdelta
else // Let's do some checks...
{
for (node = player->mo->touching_sectorlist; node; node = node->m_snext) for (node = player->mo->touching_sectorlist; node; node = node->m_snext)
{ {
// Ledge teetering. Check if any nearby sectors are low enough from your current one. // Ledge teetering. Check if any nearby sectors are low enough from your current one.
checkedforteeter = true; checkedforteeter = true;
roverfloor = false; roverfloor = false;
ceilingheight = node->m_sector->ceilingheight;
floorheight = node->m_sector->floorheight;
#ifdef ESLOPE
if (node->m_sector->c_slope)
ceilingheight = P_GetZAt(node->m_sector->c_slope, player->mo->x, player->mo->y) + FixedMul(node->m_sector->c_slope->zdelta, tiptop);
if (node->m_sector->f_slope)
floorheight = P_GetZAt(node->m_sector->f_slope, player->mo->x, player->mo->y);
#endif
if (node->m_sector->ffloors) if (node->m_sector->ffloors)
{ {
ffloor_t *rover; ffloor_t *rover;
@ -2867,6 +2885,16 @@ static void P_DoTeeter(player_t *player)
{ {
if (!(rover->flags & FF_EXISTS)) continue; if (!(rover->flags & FF_EXISTS)) continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
#ifdef ESLOPE
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y);
#endif
if (P_CheckSolidLava(player->mo, rover)) if (P_CheckSolidLava(player->mo, rover))
; ;
else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND)) else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND))
@ -2874,12 +2902,12 @@ static void P_DoTeeter(player_t *player)
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
{ {
if (*rover->bottomheight > node->m_sector->ceilingheight) // Above the ceiling if (bottomheight > ceilingheight) // Above the ceiling
continue; continue;
if (*rover->bottomheight > player->mo->z + player->mo->height + tiptop if (bottomheight > player->mo->z + player->mo->height + tiptop
|| (*rover->topheight < player->mo->z || (topheight < player->mo->z
&& player->mo->z + player->mo->height < node->m_sector->ceilingheight - tiptop)) && player->mo->z + player->mo->height < ceilingheight - tiptop))
{ {
teeter = true; teeter = true;
roverfloor = true; roverfloor = true;
@ -2893,12 +2921,12 @@ static void P_DoTeeter(player_t *player)
} }
else else
{ {
if (*rover->topheight < node->m_sector->floorheight) // Below the floor if (topheight < floorheight) // Below the floor
continue; continue;
if (*rover->topheight < player->mo->z - tiptop if (topheight < player->mo->z - tiptop
|| (*rover->bottomheight > player->mo->z + player->mo->height || (bottomheight > player->mo->z + player->mo->height
&& player->mo->z > node->m_sector->floorheight + tiptop)) && player->mo->z > floorheight + tiptop))
{ {
teeter = true; teeter = true;
roverfloor = true; roverfloor = true;
@ -2917,26 +2945,32 @@ static void P_DoTeeter(player_t *player)
{ {
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
{ {
if (node->m_sector->ceilingheight > player->mo->z + player->mo->height + tiptop) if (ceilingheight > player->mo->z + player->mo->height + tiptop)
teeter = true; teeter = true;
} }
else else
{ {
if (node->m_sector->floorheight < player->mo->z - tiptop) if (floorheight < player->mo->z - tiptop)
teeter = true; teeter = true;
} }
} }
} }
}
if (checkedforteeter && !teeter) // Backup code if (checkedforteeter && !teeter) // Backup code
{ {
subsector_t *subsec[4]; // changed abcd into array instead subsector_t *subsec[4]; // changed abcd into array instead
fixed_t subsecfloorheight[4];
fixed_t subsecceilingheight[4];
UINT8 i; UINT8 i;
// Following is replaced by xsign and ysign code
/*
subsec[0] = R_PointInSubsector(player->mo->x + FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y + FixedMul(5*FRACUNIT, player->mo->scale)); subsec[0] = R_PointInSubsector(player->mo->x + FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y + FixedMul(5*FRACUNIT, player->mo->scale));
subsec[1] = R_PointInSubsector(player->mo->x - FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y + FixedMul(5*FRACUNIT, player->mo->scale)); subsec[1] = R_PointInSubsector(player->mo->x - FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y + FixedMul(5*FRACUNIT, player->mo->scale));
subsec[2] = R_PointInSubsector(player->mo->x + FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y - FixedMul(5*FRACUNIT, player->mo->scale)); subsec[2] = R_PointInSubsector(player->mo->x + FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y - FixedMul(5*FRACUNIT, player->mo->scale));
subsec[3] = R_PointInSubsector(player->mo->x - FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y - FixedMul(5*FRACUNIT, player->mo->scale)); subsec[3] = R_PointInSubsector(player->mo->x - FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y - FixedMul(5*FRACUNIT, player->mo->scale));
*/
teeter = false; teeter = false;
roverfloor = false; roverfloor = false;
@ -2944,6 +2978,24 @@ static void P_DoTeeter(player_t *player)
{ {
ffloor_t *rover; ffloor_t *rover;
#define xsign ((i & 1) ? -1 : 1) // 0 -> 1 | 1 -> -1 | 2 -> 1 | 3 -> -1
#define ysign ((i & 2) ? 1 : -1) // 0 -> 1 | 1 -> 1 | 2 -> -1 | 3 -> -1
fixed_t checkx = player->mo->x + (xsign*FixedMul(5*FRACUNIT, player->mo->scale));
fixed_t checky = player->mo->y + (ysign*FixedMul(5*FRACUNIT, player->mo->scale));
subsec[i] = R_PointInSubsector(checkx, checky);
subsecceilingheight[i] = subsec[i]->sector->ceilingheight;
subsecfloorheight[i] = subsec[i]->sector->floorheight;
#ifdef ESLOPE
if (subsec[i]->sector->c_slope)
subsecceilingheight[i] = P_GetZAt(subsec[i]->sector->c_slope, checkx, checky);
if (subsec[i]->sector->f_slope)
subsecfloorheight[i] = P_GetZAt(subsec[i]->sector->f_slope, checkx, checky);
#endif
#undef xsign
#undef ysign
if (!(subsec[i]->sector->ffloors)) if (!(subsec[i]->sector->ffloors))
continue; // move on to the next subsector continue; // move on to the next subsector
@ -2951,6 +3003,16 @@ static void P_DoTeeter(player_t *player)
{ {
if (!(rover->flags & FF_EXISTS)) continue; if (!(rover->flags & FF_EXISTS)) continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
#ifdef ESLOPE
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y);
#endif
if (P_CheckSolidLava(player->mo, rover)) if (P_CheckSolidLava(player->mo, rover))
; ;
else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND)) else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND))
@ -2958,12 +3020,12 @@ static void P_DoTeeter(player_t *player)
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
{ {
if (*rover->bottomheight > subsec[i]->sector->ceilingheight) // Above the ceiling if (bottomheight > subsecceilingheight[i]) // Above the ceiling
continue; continue;
if (*rover->bottomheight > player->mo->z + player->mo->height + tiptop if (bottomheight > player->mo->z + player->mo->height + tiptop
|| (*rover->topheight < player->mo->z || (topheight < player->mo->z
&& player->mo->z + player->mo->height < subsec[i]->sector->ceilingheight - tiptop)) && player->mo->z + player->mo->height < subsecceilingheight[i] - tiptop))
{ {
teeter = true; teeter = true;
roverfloor = true; roverfloor = true;
@ -2977,12 +3039,12 @@ static void P_DoTeeter(player_t *player)
} }
else else
{ {
if (*rover->topheight < subsec[i]->sector->floorheight) // Below the floor if (topheight < subsecfloorheight[i]) // Below the floor
continue; continue;
if (*rover->topheight < player->mo->z - tiptop if (topheight < player->mo->z - tiptop
|| (*rover->bottomheight > player->mo->z + player->mo->height || (bottomheight > player->mo->z + player->mo->height
&& player->mo->z > subsec[i]->sector->floorheight + tiptop)) && player->mo->z > subsecfloorheight[i] + tiptop))
{ {
teeter = true; teeter = true;
roverfloor = true; roverfloor = true;
@ -3000,18 +3062,18 @@ static void P_DoTeeter(player_t *player)
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
{ {
if (!teeter && !roverfloor && (subsec[0]->sector->ceilingheight > player->mo->ceilingz + tiptop if (!teeter && !roverfloor && (subsecceilingheight[0] > player->mo->ceilingz + tiptop
|| subsec[1]->sector->ceilingheight > player->mo->ceilingz + tiptop || subsecceilingheight[1] > player->mo->ceilingz + tiptop
|| subsec[2]->sector->ceilingheight > player->mo->ceilingz + tiptop || subsecceilingheight[2] > player->mo->ceilingz + tiptop
|| subsec[3]->sector->ceilingheight > player->mo->ceilingz + tiptop)) || subsecceilingheight[3] > player->mo->ceilingz + tiptop))
teeter = true; teeter = true;
} }
else else
{ {
if (!teeter && !roverfloor && (subsec[0]->sector->floorheight < player->mo->floorz - tiptop if (!teeter && !roverfloor && (subsecfloorheight[0] < player->mo->floorz - tiptop
|| subsec[1]->sector->floorheight < player->mo->floorz - tiptop || subsecfloorheight[1] < player->mo->floorz - tiptop
|| subsec[2]->sector->floorheight < player->mo->floorz - tiptop || subsecfloorheight[2] < player->mo->floorz - tiptop
|| subsec[3]->sector->floorheight < player->mo->floorz - tiptop)) || subsecfloorheight[3] < player->mo->floorz - tiptop))
teeter = true; teeter = true;
} }
} }