From fb142de49500089011a291a8ef86cc71c1f62e8f Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Sat, 28 Oct 2023 01:24:29 -0300 Subject: [PATCH 01/15] Remove existing `over_under` implementation --- src/p_map.c | 37 +------------------------------------ src/p_mobj.c | 11 ++--------- src/p_mobj.h | 5 ++--- 3 files changed, 5 insertions(+), 48 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 8cb2c83d2..3cc93f959 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -552,14 +552,6 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static int damage = ((P_Random(pr_skullfly)%8)+1)*tmthing->info->damage; - // [Nugget]: [crispy] check if attacking skull flies over/under thing - if (casual_play && over_under) { - if (tmthing->z > thing->z + thing->height) - { return true; } // over - else if (tmthing->z + tmthing->height < thing->z) - { return true; } // under - } - // [Nugget] Fix lost soul collision if (casual_play && comp_lscollision && !(thing->flags & MF_SHOOTABLE)) { return !(thing->flags & MF_SOLID); } @@ -571,7 +563,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static // [Nugget] Fix forgetful lost soul if (casual_play && comp_lsamnesia) - { P_SetMobjState(tmthing, tmthing->info->seestate); } + P_SetMobjState(tmthing, tmthing->info->seestate); else P_SetMobjState (tmthing, tmthing->info->spawnstate); @@ -661,33 +653,6 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static return !solid; } - // [Nugget] Allow things to move over/under solid things - if (casual_play && over_under && (thing->flags & MF_SOLID)) - { - if (tmthing->z >= thing->z + thing->height) { // Over - thing->intflags |= MIF_OVERUNDER; - tmthing->intflags |= MIF_OVERUNDER; - - tmfloorz = MAX(thing->z + thing->height, tmfloorz); - thing->ceilingz = MIN(tmthing->z, thing->ceilingz); - - return true; - } - else if (tmthing->z + tmthing->height <= thing->z) { // Under - thing->intflags |= MIF_OVERUNDER; - tmthing->intflags |= MIF_OVERUNDER; - - tmceilingz = MIN(thing->z, tmceilingz); - thing->floorz = MAX(tmthing->z + tmthing->height, thing->floorz); - - return true; - } - else { - thing->intflags &= ~MIF_OVERUNDER; - tmthing->intflags &= ~MIF_OVERUNDER; - } - } - // RjY // comperr_hangsolid, an attempt to handle blocking hanging bodies // A solid hanging body will allow sufficiently small things underneath it. diff --git a/src/p_mobj.c b/src/p_mobj.c index 4b80abd3f..c3038b3a6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -145,8 +145,7 @@ void P_XYMovement (mobj_t* mo) fixed_t oldx,oldy; // phares 9/10/98: reducing bobbing/momentum on ice - if (!(mo->momx | mo->momy) // Any momentum? - && !(mo->intflags & MIF_OVERUNDER)) // [Nugget] + if (!(mo->momx | mo->momy)) // Any momentum? { if (mo->flags & MF_SKULLFLY) { @@ -774,14 +773,8 @@ void P_MobjThinker (mobj_t* mobj) // removed old code which looked at target references // (we use pointer reference counting now) - // [Nugget] Things with both MF_SKULLFLY and MIF_OVERUNDER - // have buggy behavior, so take the latter away - if ((mobj->flags & MF_SKULLFLY) && (mobj->intflags & MIF_OVERUNDER)) - { mobj->intflags &= ~MIF_OVERUNDER; } - // momentum movement - if (mobj->momx | mobj->momy || mobj->flags & MF_SKULLFLY - || mobj->intflags & MIF_OVERUNDER) // [Nugget] + if (mobj->momx | mobj->momy || mobj->flags & MF_SKULLFLY) { P_XYMovement(mobj); mobj->intflags &= ~MIF_SCROLLING; diff --git a/src/p_mobj.h b/src/p_mobj.h index 8dd355beb..e60c6a53a 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -235,9 +235,8 @@ enum { MIF_FLIP = 16, // [Nugget] MIF_CROUCHING = 32, // Mobj (player) is crouching - MIF_OVERUNDER = 64, // Mobj is over/under another mobj - MIF_EXTRASPAWNED = 128, // [So Doom] Nightmare-spawned, Icon of Sin-spawned and Archvile-resurrected monsters - MIF_CHEESE = 256, + MIF_EXTRASPAWNED = 64, // [So Doom] Nightmare-spawned, Icon of Sin-spawned and Archvile-resurrected monsters + MIF_CHEESE = 128, }; // Map Object definition. From a46e795674edef380ea2c28b18882ad68546a3f3 Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Sat, 28 Oct 2023 18:59:40 -0300 Subject: [PATCH 02/15] New `over_under` implementation, from DSDA Issues so far: - The check for being on a mobj fails every other tic, resulting in less friction and choppy bobbing while moving on things - The player can get stuck in things if crouching while on them - Lift-lowered (and raised?) things can clip into other things --- src/p_map.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/p_map.h | 2 + src/p_mobj.c | 58 ++++++++++++++++++- src/p_mobj.h | 3 +- src/p_user.c | 9 ++- 5 files changed, 222 insertions(+), 7 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 3cc93f959..1ee952d62 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -543,6 +543,15 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static return true; } + // [Nugget]: [DSDA] check if a mobj passed over/under another object + if (casual_play && over_under + && (tmthing->flags & MF_SOLID) && !(thing->flags & MF_SPECIAL) + && ( ( thing->z + thing->height <= tmthing->z) // Over + || (tmthing->z + tmthing->height < thing->z))) // Under + { + return true; + } + // check for skulls slamming into things if (tmthing->flags & MF_SKULLFLY) @@ -2445,6 +2454,154 @@ void P_MapEnd(void) tmthing = NULL; } +// [Nugget]: [DSDA] heretic /------------------------------------------------- + +mobj_t *onmobj; + +boolean PIT_CheckOnmobjZ(mobj_t *thing) +{ + fixed_t blockdist; + + if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE))) + { return true; } // Can't hit thing + + blockdist = thing->radius + tmthing->radius; + + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + { return true; } // Didn't hit thing + + if (thing == tmthing) + { return true; } // Don't clip against self + + if ( ( thing->z + thing->height <= tmthing->z) // Over thing + || (tmthing->z + tmthing->height < thing->z)) // Under thing + { return true; } + + if (thing->flags & MF_SOLID) + { onmobj = thing; } + + return (!(thing->flags & MF_SOLID)); +} + +void P_FakeZMovement(mobj_t *mo) +{ + int dist; + int delta; + + // Adjust height + mo->z += mo->momz; + if (mo->flags & MF_FLOAT && mo->target) + { + // Float down towards target if too close + if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) + { + dist = P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); + delta = (mo->target->z + (mo->height >> 1)) - mo->z; + + if (delta < 0 && dist < -(delta * 3)) { mo->z -= FLOATSPEED; } + else if (delta > 0 && dist < (delta * 3)) { mo->z += FLOATSPEED; } + } + } + + // Clip movement + if (mo->z <= mo->floorz) + { + // Hit the floor + + mo->z = mo->floorz; + + if (mo->momz < 0) { mo->momz = 0; } + + if (mo->flags & MF_SKULLFLY) + { mo->momz = -mo->momz; } // The skull slammed into something + } + else if (mo->flags2 & MF2_LOGRAV) + { + if (mo->momz == 0) { mo->momz = -(GRAVITY >> 3) * 2; } + else { mo->momz -= GRAVITY >> 3; } + } + else if (!(mo->flags & MF_NOGRAVITY)) + { + if (mo->momz == 0) { mo->momz = -GRAVITY * 2; } + else { mo->momz -= GRAVITY; } + } + + if (mo->z + mo->height > mo->ceilingz) + { + // Hit the ceiling + + mo->z = mo->ceilingz - mo->height; + + if (mo->momz > 0) { mo->momz = 0; } + + if (mo->flags & MF_SKULLFLY) + { mo->momz = -mo->momz; } // The skull slammed into something + } +} + +// Checks if the new Z position is legal +mobj_t *P_CheckOnmobj(mobj_t *thing) +{ + int xl, xh, yl, yh, bx, by; + subsector_t *newsubsec; + fixed_t x; + fixed_t y; + mobj_t oldmo; + + x = thing->x; + y = thing->y; + tmthing = thing; + tmflags = thing->flags; + oldmo = *thing; // Save the old mobj before the fake zmovement + P_FakeZMovement(tmthing); + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector(x, y); + ceilingline = NULL; + + // The base floor / ceiling is from the subsector that contains the + // point. Any contacted lines the step closer together will adjust them + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + if (tmflags & MF_NOCLIP) { + *tmthing = oldmo; + return NULL; + } + + // Check things first, possibly picking things up + // the bounding box is extended by MAXRADIUS because mobj_ts are grouped + // into mapblocks based on their origin point, and can overlap into adjacent + // blocks by up to MAXRADIUS units + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockThingsIterator(bx, by, PIT_CheckOnmobjZ)) + { + *tmthing = oldmo; + return onmobj; + } + + *tmthing = oldmo; + return NULL; +} + +// [Nugget] -----------------------------------------------------------------/ + // [FG] SPECHITS overflow emulation from Chocolate Doom / PrBoom+ static void SpechitOverrun(line_t *ld) diff --git a/src/p_map.h b/src/p_map.h index df0171fb5..ad591fafd 100644 --- a/src/p_map.h +++ b/src/p_map.h @@ -78,6 +78,8 @@ extern msecnode_t *sector_list; // phares 3/16/98 extern fixed_t tmbbox[4]; // phares 3/20/98 extern line_t *blockline; // killough 8/11/98 +mobj_t *P_CheckOnmobj(mobj_t *thing); // [Nugget]: [DSDA] + extern boolean boomshot; // [Nugget] Explosive hitscan cheat #endif // __P_MAP__ diff --git a/src/p_mobj.c b/src/p_mobj.c index c3038b3a6..100626163 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -292,8 +292,10 @@ void P_XYMovement (mobj_t* mo) // no friction for missiles or skulls ever, no friction when airborne if (mo->flags & (MF_MISSILE | MF_SKULLFLY) - // [Nugget] Do apply friction if airborne with the flight cheat on - || (!(player && player->cheats & CF_FLY) && (mo->z > mo->floorz))) + // [Nugget] Do apply friction if... + || ((mo->z > mo->floorz) + && !( (player && player->cheats & CF_FLY) // ... using flight cheat + || (mo->intflags & MIF_ONMOBJ)))) // ... on top of a mobj return; // killough 8/11/98: add bouncers @@ -784,7 +786,57 @@ void P_MobjThinker (mobj_t* mobj) if (mobj->z != mobj->floorz || mobj->momz) { - P_ZMovement(mobj); + // [Nugget] + if (casual_play && over_under && (mobj->flags & MF_SOLID)) + { + mobj_t *onmo; + + if (!(onmo = P_CheckOnmobj(mobj))) + { + P_ZMovement(mobj); + mobj->intflags &= ~MIF_ONMOBJ; + } + else + { + if (mobj->player) + { + if (mobj->momz < 0) + { + mobj->intflags |= MIF_ONMOBJ; + mobj->momz = 0; + } + + if (onmo->player) + { + mobj->momx = onmo->momx; + mobj->momy = onmo->momy; + + if (onmo->z < onmo->floorz) + { + mobj->z += onmo->floorz - onmo->z; + + onmo->player->viewheight -= onmo->floorz - onmo->z; + onmo->player->deltaviewheight = ((!strictmode ? viewheight_value*FRACUNIT : VIEWHEIGHT) + - onmo->player->viewheight) >> 3; + + onmo->z = onmo->floorz; + } + } + } + else { + mobj->momz = 0; + + if (onmo->z + onmo->height - mobj->z <= 24 * FRACUNIT) + { + mobj->z = onmo->z + onmo->height; + mobj->intflags |= MIF_ONMOBJ; + } + } + } + } + else + P_ZMovement(mobj); + if (mobj->thinker.function.p1 == (actionf_p1)P_RemoveThinkerDelayed) // killough return; // mobj was removed } diff --git a/src/p_mobj.h b/src/p_mobj.h index e60c6a53a..87e30701c 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -235,8 +235,9 @@ enum { MIF_FLIP = 16, // [Nugget] MIF_CROUCHING = 32, // Mobj (player) is crouching - MIF_EXTRASPAWNED = 64, // [So Doom] Nightmare-spawned, Icon of Sin-spawned and Archvile-resurrected monsters + MIF_EXTRASPAWNED = 64, // [So Doom] Nightmare-spawned, Icon of Sin-spawned and Archvile-resurrected monsters MIF_CHEESE = 128, + MIF_ONMOBJ = 256, // [DSDA] mobj is resting on top of another }; // Map Object definition. diff --git a/src/p_user.c b/src/p_user.c index ba417f11c..9fec98a2d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -221,9 +221,11 @@ void P_MovePlayer (player_t* player) int cforwardmove, csidemove; mo->angle += cmd->angleturn << 16; - onground = mo->z <= mo->floorz; - // [Nugget] Allow mid-air control with noclip or fly enabled - onground |= ((player->mo->flags & MF_NOCLIP) || (player->cheats & CF_FLY)); + onground = (mo->z <= mo->floorz + // [Nugget] + || (casual_play && (mo->intflags & MIF_ONMOBJ)) // [DSDA] + // Mid-air control with noclip or flight cheat enabled + || (player->mo->flags & MF_NOCLIP) || (player->cheats & CF_FLY)); // [Nugget] if (player->cheats & CF_FLY) @@ -269,6 +271,7 @@ void P_MovePlayer (player_t* player) { // Jump player->mo->momz = 8*FRACUNIT; player->jumptics = 20; +// player->mo->intflags &= ~MIF_ONMOBJ; // [DSDA] // [NS] Jump sound. S_StartSoundOptional(player->mo, sfx_pljump, -1); // [crispy] squat down weapon sprite a bit From 7eee8a528cf906767dadbbb871a4035dd0411743 Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Mon, 30 Oct 2023 04:00:12 -0300 Subject: [PATCH 03/15] Some fixes Thanks to these, the check for being on a mobj doesn't fail anymore, fixing the reduced friction and choppy bobbing, and seemingly the crouching issue too. --- src/p_map.c | 14 +++++++------- src/p_mobj.c | 39 +++++++++------------------------------ 2 files changed, 16 insertions(+), 37 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 1ee952d62..dffcdae5f 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -547,7 +547,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static if (casual_play && over_under && (tmthing->flags & MF_SOLID) && !(thing->flags & MF_SPECIAL) && ( ( thing->z + thing->height <= tmthing->z) // Over - || (tmthing->z + tmthing->height < thing->z))) // Under + || (tmthing->z + tmthing->height <= thing->z))) // Under { return true; } @@ -2473,8 +2473,8 @@ boolean PIT_CheckOnmobjZ(mobj_t *thing) if (thing == tmthing) { return true; } // Don't clip against self - if ( ( thing->z + thing->height <= tmthing->z) // Over thing - || (tmthing->z + tmthing->height < thing->z)) // Under thing + if ( ( thing->z + thing->height < tmthing->z) // Over thing + || (tmthing->z + tmthing->height < thing->z)) // Under thing { return true; } if (thing->flags & MF_SOLID) @@ -2517,13 +2517,13 @@ void P_FakeZMovement(mobj_t *mo) } else if (mo->flags2 & MF2_LOGRAV) { - if (mo->momz == 0) { mo->momz = -(GRAVITY >> 3) * 2; } - else { mo->momz -= GRAVITY >> 3; } + if (!mo->momz) { mo->momz = -(GRAVITY >> 3) * 2; } + else { mo->momz -= GRAVITY >> 3; } } else if (!(mo->flags & MF_NOGRAVITY)) { - if (mo->momz == 0) { mo->momz = -GRAVITY * 2; } - else { mo->momz -= GRAVITY; } + if (!mo->momz) { mo->momz = -GRAVITY; } + else { mo->momz -= GRAVITY; } } if (mo->z + mo->height > mo->ceilingz) diff --git a/src/p_mobj.c b/src/p_mobj.c index 100626163..7f73f0fda 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -798,39 +798,18 @@ void P_MobjThinker (mobj_t* mobj) } else { - if (mobj->player) - { - if (mobj->momz < 0) - { - mobj->intflags |= MIF_ONMOBJ; - mobj->momz = 0; - } - - if (onmo->player) - { - mobj->momx = onmo->momx; - mobj->momy = onmo->momy; - - if (onmo->z < onmo->floorz) - { - mobj->z += onmo->floorz - onmo->z; + mobj->momz = 0; - onmo->player->viewheight -= onmo->floorz - onmo->z; - onmo->player->deltaviewheight = ((!strictmode ? viewheight_value*FRACUNIT : VIEWHEIGHT) - - onmo->player->viewheight) >> 3; - - onmo->z = onmo->floorz; - } + if (onmo->z + onmo->height - mobj->z <= 24 * FRACUNIT) + { + if (mobj->player) { + mobj->player->viewheight -= onmo->z + onmo->height - mobj->z; + mobj->player->deltaviewheight = ((!strictmode ? viewheight_value*FRACUNIT : VIEWHEIGHT) + - mobj->player->viewheight) >> 3; } - } - else { - mobj->momz = 0; - if (onmo->z + onmo->height - mobj->z <= 24 * FRACUNIT) - { - mobj->z = onmo->z + onmo->height; - mobj->intflags |= MIF_ONMOBJ; - } + mobj->z = onmo->z + onmo->height; + mobj->intflags |= MIF_ONMOBJ; } } } From 420f7a5077a784ba0ff515bbf435596357a5c9c3 Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Mon, 30 Oct 2023 04:14:26 -0300 Subject: [PATCH 04/15] Little cleanup --- src/p_user.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 9fec98a2d..837fc31ce 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -223,7 +223,7 @@ void P_MovePlayer (player_t* player) mo->angle += cmd->angleturn << 16; onground = (mo->z <= mo->floorz // [Nugget] - || (casual_play && (mo->intflags & MIF_ONMOBJ)) // [DSDA] + || (mo->intflags & MIF_ONMOBJ) // [DSDA] // Mid-air control with noclip or flight cheat enabled || (player->mo->flags & MF_NOCLIP) || (player->cheats & CF_FLY)); @@ -271,7 +271,6 @@ void P_MovePlayer (player_t* player) { // Jump player->mo->momz = 8*FRACUNIT; player->jumptics = 20; -// player->mo->intflags &= ~MIF_ONMOBJ; // [DSDA] // [NS] Jump sound. S_StartSoundOptional(player->mo, sfx_pljump, -1); // [crispy] squat down weapon sprite a bit From 3f39013dba33f02fb2b13fad39fbc65146f9041a Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Sun, 26 Nov 2023 07:40:58 -0300 Subject: [PATCH 05/15] Tweaks Flying things can still get stuck in each other. --- src/p_map.c | 65 +++++++++++++++++++++------------------------------- src/p_mobj.c | 2 +- 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 1c79be933..2b7ff2e4e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2465,9 +2465,9 @@ void P_MapEnd(void) // [Nugget]: [DSDA] heretic /------------------------------------------------- -mobj_t *onmobj; +static mobj_t *onmobj; -boolean PIT_CheckOnmobjZ(mobj_t *thing) +static boolean PIT_CheckOnmobjZ(mobj_t *thing) { fixed_t blockdist; @@ -2489,27 +2489,22 @@ boolean PIT_CheckOnmobjZ(mobj_t *thing) if (thing->flags & MF_SOLID) { onmobj = thing; } - return (!(thing->flags & MF_SOLID)); + return !((thing->flags & MF_SOLID && !(thing->flags & MF_NOCLIP)) + && (tmthing->flags & MF_SOLID || demo_compatibility)); } -void P_FakeZMovement(mobj_t *mo) +static void P_FakeZMovement(mobj_t *mo) { - int dist; - int delta; - // Adjust height mo->z += mo->momz; - if (mo->flags & MF_FLOAT && mo->target) + + // Float down towards target if too close + if (!((mo->flags ^ MF_FLOAT) & (MF_FLOAT | MF_SKULLFLY | MF_INFLOAT)) && mo->target) { - // Float down towards target if too close - if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) - { - dist = P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); - delta = (mo->target->z + (mo->height >> 1)) - mo->z; + const fixed_t delta = mo->target->z + (mo->height >> 1) - mo->z; - if (delta < 0 && dist < -(delta * 3)) { mo->z -= FLOATSPEED; } - else if (delta > 0 && dist < (delta * 3)) { mo->z += FLOATSPEED; } - } + if (P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y) < abs(delta) * 3) + { mo->z += (delta < 0) ? -FLOATSPEED : FLOATSPEED; } } // Clip movement @@ -2553,27 +2548,20 @@ mobj_t *P_CheckOnmobj(mobj_t *thing) { int xl, xh, yl, yh, bx, by; subsector_t *newsubsec; - fixed_t x; - fixed_t y; - mobj_t oldmo; + mobj_t oldmo = *thing; // Save the old mobj before the fake movement - x = thing->x; - y = thing->y; + tmx = thing->x; + tmy = thing->y; tmthing = thing; tmflags = thing->flags; - oldmo = *thing; // Save the old mobj before the fake zmovement - P_FakeZMovement(tmthing); - - tmx = x; - tmy = y; - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; + tmbbox[BOXTOP] = tmy + tmthing->radius; + tmbbox[BOXBOTTOM] = tmy - tmthing->radius; + tmbbox[BOXRIGHT] = tmx + tmthing->radius; + tmbbox[BOXLEFT] = tmx - tmthing->radius; - newsubsec = R_PointInSubsector(x, y); - ceilingline = NULL; + newsubsec = R_PointInSubsector(tmx, tmy); + floorline = blockline = ceilingline = NULL; // The base floor / ceiling is from the subsector that contains the // point. Any contacted lines the step closer together will adjust them @@ -2583,19 +2571,18 @@ mobj_t *P_CheckOnmobj(mobj_t *thing) validcount++; numspechit = 0; - if (tmflags & MF_NOCLIP) { - *tmthing = oldmo; - return NULL; - } + if (tmflags & MF_NOCLIP) { return NULL; } // Check things first, possibly picking things up // the bounding box is extended by MAXRADIUS because mobj_ts are grouped // into mapblocks based on their origin point, and can overlap into adjacent // blocks by up to MAXRADIUS units - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + P_FakeZMovement(tmthing); for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) diff --git a/src/p_mobj.c b/src/p_mobj.c index 8dd76bd4c..94d772e2b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -789,7 +789,7 @@ void P_MobjThinker (mobj_t* mobj) if (mobj->z != mobj->floorz || mobj->momz) { - // [Nugget] + // [Nugget]: [DSDA] if (casual_play && over_under && (mobj->flags & MF_SOLID)) { mobj_t *onmo; From 1e60f242861af2ef9bcef7e4712d1e3786f02e80 Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Sun, 26 Nov 2023 08:22:42 -0300 Subject: [PATCH 06/15] Add checks in `P_Move()` The `z` movement in `P_Move()` would seemingly not account for the possibility of things being over/under other things. This commit appears to fix that. --- src/p_enemy.c | 16 +++++++++++++++- src/p_map.c | 4 +++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 762a0454b..dc65d4e72 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -407,11 +407,25 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 if (actor->flags & MF_FLOAT && floatok) { + const mobj_t *onmo; // [Nugget] + if (actor->z < tmfloorz) // must adjust height - actor->z += FLOATSPEED; + { + actor->z += FLOATSPEED; + + // [Nugget] + if ((onmo = P_CheckOnmobj(actor))) + { actor->z = onmo->z - actor->height; } + } else + { actor->z -= FLOATSPEED; + // [Nugget] + if ((onmo = P_CheckOnmobj(actor))) + { actor->z = onmo->z + onmo->height; } + } + actor->flags |= MF_INFLOAT; return true; diff --git a/src/p_map.c b/src/p_map.c index 2b7ff2e4e..5ed314ae7 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2548,7 +2548,9 @@ mobj_t *P_CheckOnmobj(mobj_t *thing) { int xl, xh, yl, yh, bx, by; subsector_t *newsubsec; - mobj_t oldmo = *thing; // Save the old mobj before the fake movement + const mobj_t oldmo = *thing; // Save the old mobj before the fake movement + + if (!(casual_play && over_under)) { return NULL; } tmx = thing->x; tmy = thing->y; From 8eb4afbbe2471b59d0a391e442d6ffd2d66bae50 Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Sun, 26 Nov 2023 20:26:45 -0300 Subject: [PATCH 07/15] Don't perform fake movement for `P_Move()` checks --- src/p_enemy.c | 4 ++-- src/p_map.c | 4 ++-- src/p_map.h | 2 +- src/p_mobj.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index dc65d4e72..016244e9e 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -414,7 +414,7 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 actor->z += FLOATSPEED; // [Nugget] - if ((onmo = P_CheckOnmobj(actor))) + if ((onmo = P_CheckOnmobj(actor, false))) { actor->z = onmo->z - actor->height; } } else @@ -422,7 +422,7 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 actor->z -= FLOATSPEED; // [Nugget] - if ((onmo = P_CheckOnmobj(actor))) + if ((onmo = P_CheckOnmobj(actor, false))) { actor->z = onmo->z + onmo->height; } } diff --git a/src/p_map.c b/src/p_map.c index 5ed314ae7..3233c3204 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2544,7 +2544,7 @@ static void P_FakeZMovement(mobj_t *mo) } // Checks if the new Z position is legal -mobj_t *P_CheckOnmobj(mobj_t *thing) +mobj_t *P_CheckOnmobj(mobj_t *thing, boolean fakemove) { int xl, xh, yl, yh, bx, by; subsector_t *newsubsec; @@ -2584,7 +2584,7 @@ mobj_t *P_CheckOnmobj(mobj_t *thing) yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - P_FakeZMovement(tmthing); + if (fakemove) { P_FakeZMovement(tmthing); } for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) diff --git a/src/p_map.h b/src/p_map.h index ad591fafd..f92f60524 100644 --- a/src/p_map.h +++ b/src/p_map.h @@ -78,7 +78,7 @@ extern msecnode_t *sector_list; // phares 3/16/98 extern fixed_t tmbbox[4]; // phares 3/20/98 extern line_t *blockline; // killough 8/11/98 -mobj_t *P_CheckOnmobj(mobj_t *thing); // [Nugget]: [DSDA] +mobj_t *P_CheckOnmobj(mobj_t *thing, boolean fakemove); // [Nugget]: [DSDA] extern boolean boomshot; // [Nugget] Explosive hitscan cheat diff --git a/src/p_mobj.c b/src/p_mobj.c index 94d772e2b..c87db2a0e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -794,7 +794,7 @@ void P_MobjThinker (mobj_t* mobj) { mobj_t *onmo; - if (!(onmo = P_CheckOnmobj(mobj))) + if (!(onmo = P_CheckOnmobj(mobj, true))) { P_ZMovement(mobj); mobj->intflags &= ~MIF_ONMOBJ; From 97980507ee45f791ce0a5d27a5a1553b79e2d23f Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Tue, 28 Nov 2023 04:02:10 -0300 Subject: [PATCH 08/15] `P_Move()`: Do horiz. move if vert. is blocked --- src/p_enemy.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 016244e9e..9d4abc6d5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -407,13 +407,15 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 if (actor->flags & MF_FLOAT && floatok) { - const mobj_t *onmo; // [Nugget] + // [Nugget] Over/Under + const mobj_t *onmo; + const fixed_t oldz = actor->z; if (actor->z < tmfloorz) // must adjust height { actor->z += FLOATSPEED; - // [Nugget] + // [Nugget] Don't ascend into other things if ((onmo = P_CheckOnmobj(actor, false))) { actor->z = onmo->z - actor->height; } } @@ -421,14 +423,17 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 { actor->z -= FLOATSPEED; - // [Nugget] + // [Nugget] Don't descend into other things if ((onmo = P_CheckOnmobj(actor, false))) { actor->z = onmo->z + onmo->height; } } - actor->flags |= MF_INFLOAT; - - return true; + // [Nugget] Conditions: only if we actually moved + if (casual_play && actor->z != oldz) + { + actor->flags |= MF_INFLOAT; + return true; + } } if (!numspechit) From a645004f190829133cd24f68cdba8434553d0c6b Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Tue, 28 Nov 2023 05:14:26 -0300 Subject: [PATCH 09/15] Allow player-only over/under --- src/m_menu.c | 8 ++++++-- src/m_misc.c | 4 ++-- src/p_map.c | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3b776a2b0..200e79ddd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4840,6 +4840,10 @@ setup_menu_t gen_settings5[] = { // General Settings screen5 // [Nugget] /----------------------------------------------------------------- +static const char *over_under_str[] = { + "Off", "Player Only", "All Things", NULL +}; + static const char *impact_pitch_str[] = { "Off", "Fall", "Damage", "Both", NULL }; @@ -4852,8 +4856,8 @@ setup_menu_t gen_settings6[] = { {"Nugget - Gameplay", S_SKIP|S_TITLE, m_null, M_X, M_Y + gen6_title1 * M_SPC}, - {"Things Move Over/Under Things", S_YESNO|S_STRICT|S_CRITICAL, m_null, M_X, M_Y + gen6_overunder * M_SPC, {"over_under"}}, - {"Allow Jumping/Crouching", S_YESNO|S_STRICT|S_CRITICAL, m_null, M_X, M_Y + gen6_jump_crouch * M_SPC, {"jump_crouch"}}, + {"Move Over/Under Things", S_CHOICE|S_STRICT|S_CRITICAL, m_null, M_X, M_Y + gen6_overunder * M_SPC, {"over_under"}, 0, NULL, over_under_str}, + {"Allow Jumping/Crouching", S_YESNO |S_STRICT|S_CRITICAL, m_null, M_X, M_Y + gen6_jump_crouch * M_SPC, {"jump_crouch"}}, {"", S_SKIP, m_null, M_X, M_Y + gen6_stub1 * M_SPC}, {"Nugget - View", S_SKIP|S_TITLE, m_null, M_X, M_Y + gen6_title2 * M_SPC}, diff --git a/src/m_misc.c b/src/m_misc.c index bb3f0895e..4a6b84347 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -719,8 +719,8 @@ default_t defaults[] = { { "over_under", (config_t *) &over_under, NULL, - {0}, {0,1}, number, ss_gen, wad_yes, - "1 to allow things to move over/under other things" + {0}, {0,2}, number, ss_gen, wad_yes, + "Allow movement over/under things (1 = Player only, 2 = All things)" }, { diff --git a/src/p_map.c b/src/p_map.c index 3233c3204..ae30406bc 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -546,6 +546,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static // [Nugget]: [DSDA] check if a mobj passed over/under another object if (casual_play && over_under && (tmthing->flags & MF_SOLID) && !(thing->flags & MF_SPECIAL) + && ((over_under == 2) || tmthing->player || thing->player) && ( ( thing->z + thing->height <= tmthing->z) // Over || (tmthing->z + tmthing->height <= thing->z))) // Under { From 734be5a589c8ec7e216bd2293bb44089a465c369 Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Thu, 7 Dec 2023 01:31:34 -0300 Subject: [PATCH 10/15] The Grand Rework Instead of using a flag, mobjs now have pointers to the mobjs right below and above them. Thanks to this, lift logic has been improved, and non-player mobjs can actually walk on other mobjs now. --- src/p_enemy.c | 27 ++++-- src/p_map.c | 239 ++++++++++++++++++++++++++++++++++++++++++-------- src/p_map.h | 8 +- src/p_mobj.c | 59 +++++++++---- src/p_mobj.h | 1 - src/p_user.c | 3 +- 6 files changed, 273 insertions(+), 64 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 9d4abc6d5..d72a15903 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -408,28 +408,33 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 if (actor->flags & MF_FLOAT && floatok) { // [Nugget] Over/Under - const mobj_t *onmo; const fixed_t oldz = actor->z; if (actor->z < tmfloorz) // must adjust height { actor->z += FLOATSPEED; - // [Nugget] Don't ascend into other things - if ((onmo = P_CheckOnmobj(actor, false))) - { actor->z = onmo->z - actor->height; } + // [Nugget] Over/Under: don't ascend into other things + if (actor->above_thing + && (actor->above_thing->z < (actor->z + actor->height))) + { + actor->z = actor->above_thing->z - actor->height; + } } else { actor->z -= FLOATSPEED; - // [Nugget] Don't descend into other things - if ((onmo = P_CheckOnmobj(actor, false))) - { actor->z = onmo->z + onmo->height; } + // [Nugget] Over/Under: don't descend into other things + if (actor->below_thing + && (actor->z < (actor->below_thing->z + actor->below_thing->height))) + { + actor->z = actor->below_thing->z + actor->below_thing->height; + } } // [Nugget] Conditions: only if we actually moved - if (casual_play && actor->z != oldz) + if (NOTCASUALPLAY(actor->z != oldz)) { actor->flags |= MF_INFLOAT; return true; @@ -479,8 +484,14 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 // killough 11/98: fall more slowly, under gravity, if felldown==true if (!(actor->flags & MF_FLOAT) && (!felldown || demo_version < 203)) + { actor->z = actor->floorz; + // [Nugget] Over/Under + if (actor->below_thing) + { actor->z = MAX(actor->floorz, actor->below_thing->z + actor->below_thing->height); } + } + return true; } diff --git a/src/p_map.c b/src/p_map.c index ae30406bc..5e5b505fe 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -494,6 +494,11 @@ static boolean P_ProjectileImmune(mobj_t *target, mobj_t *source) ); } +// [Nugget] Over/Under: potential over/under mobjs +static mobj_t *p_below_tmthing, *p_above_tmthing, // For `tmthing` + *p_below_thing_s, *p_above_thing_s, // For `thing` ("setter") + *p_below_thing_g, *p_above_thing_g; // `thing` itself ("getter") + static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static { fixed_t blockdist; @@ -546,11 +551,46 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static // [Nugget]: [DSDA] check if a mobj passed over/under another object if (casual_play && over_under && (tmthing->flags & MF_SOLID) && !(thing->flags & MF_SPECIAL) - && ((over_under == 2) || tmthing->player || thing->player) - && ( ( thing->z + thing->height <= tmthing->z) // Over - || (tmthing->z + tmthing->height <= thing->z))) // Under + && ((over_under == 2) || tmthing->player || thing->player)) { - return true; + if (thing->z + thing->height <= tmthing->z) + { + // Over + + if ((!p_below_tmthing) + || ((p_below_tmthing->z + p_below_tmthing->height) < (thing->z + thing->height))) + { + p_below_tmthing = thing; + } + + if ((!p_above_thing_s) + || (tmthing->z < p_above_thing_s->z)) + { + p_above_thing_s = tmthing; + p_above_thing_g = thing; + } + + return true; + } + else if (tmthing->z + tmthing->height <= thing->z) + { + // Under + + if ((!p_above_tmthing) + || (thing->z < p_above_tmthing->z)) + { + p_above_tmthing = thing; + } + + if ((!p_below_thing_s) + || ((p_below_thing_s->z + p_below_thing_s->height) < (tmthing->z + tmthing->height))) + { + p_below_thing_s = tmthing; + p_below_thing_g = thing; + } + + return true; + } } // check for skulls slamming into things @@ -811,6 +851,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + // [Nugget] Over/Under + p_below_tmthing = p_below_thing_s = p_below_thing_g = + p_above_tmthing = p_above_thing_s = p_above_thing_g = NULL; + for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) @@ -856,6 +900,30 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean dropoff) if (!P_CheckPosition(thing, x, y)) return false; // solid wall or thing + // [Nugget] Over/Under: if move was valid, set new over/under mobjs + if (casual_play && over_under) + { + mobj_t *pbtg = p_below_thing_g ? p_below_thing_g->below_thing : NULL, + *pbts = p_below_thing_s, + *patg = p_above_thing_g ? p_above_thing_g->above_thing : NULL, + *pats = p_above_thing_s; + + thing->below_thing = p_below_tmthing; + thing->above_thing = p_above_tmthing; + + if (p_below_thing_g + && ((!pbtg) || ((pbtg->z + pbtg->height) < (pbts->z + pbts->height)))) + { + p_below_thing_g->below_thing = p_below_thing_s; + } + + if (p_above_thing_g + && ((!patg) || (pats->z < patg->z))) + { + p_above_thing_g->above_thing = p_above_thing_s; + } + } + if (!(thing->flags & MF_NOCLIP)) { // killough 7/26/98: reformatted slightly @@ -1101,8 +1169,42 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (onfloor) // walking monsters rise and fall with the floor { + // [Nugget] Over/Under + const fixed_t oldz = thing->z; + thing->z = thing->floorz; + if (casual_play && over_under) + { + if (thing->z < oldz && thing->below_thing) + { thing->z = MAX(thing->z, thing->below_thing->z + thing->below_thing->height); } + + if (oldz < thing->z) + { + mobj_t *below_thing = thing, *above_thing; + + do { + if ((above_thing = below_thing->above_thing)) + { + above_thing->z = MAX(above_thing->z, below_thing->z + below_thing->height); + } + } while ((below_thing = below_thing->above_thing)); + } + else if (thing->z < oldz) + { + mobj_t *below_thing = thing, *above_thing; + const fixed_t diff = oldz - thing->z; + + do { + if ((above_thing = below_thing->above_thing) + && ((above_thing->z - diff) == (below_thing->z + below_thing->height))) + { + above_thing->z = below_thing->z + below_thing->height; + } + } while ((below_thing = below_thing->above_thing)); + } + } + // killough 11/98: Possibly upset balance of objects hanging off ledges if (thing->intflags & MIF_FALLING && thing->gear >= MAXGEAR) thing->gear = 0; @@ -2466,36 +2568,12 @@ void P_MapEnd(void) // [Nugget]: [DSDA] heretic /------------------------------------------------- -static mobj_t *onmobj; - -static boolean PIT_CheckOnmobjZ(mobj_t *thing) -{ - fixed_t blockdist; - - if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE))) - { return true; } // Can't hit thing - - blockdist = thing->radius + tmthing->radius; - - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - { return true; } // Didn't hit thing - - if (thing == tmthing) - { return true; } // Don't clip against self - - if ( ( thing->z + thing->height < tmthing->z) // Over thing - || (tmthing->z + tmthing->height < thing->z)) // Under thing - { return true; } - - if (thing->flags & MF_SOLID) - { onmobj = thing; } - - return !((thing->flags & MF_SOLID && !(thing->flags & MF_NOCLIP)) - && (tmthing->flags & MF_SOLID || demo_compatibility)); -} +static overunder_t zdir = OU_NONE; static void P_FakeZMovement(mobj_t *mo) { + const fixed_t oldz = mo->z; + // Adjust height mo->z += mo->momz; @@ -2542,16 +2620,77 @@ static void P_FakeZMovement(mobj_t *mo) if (mo->flags & MF_SKULLFLY) { mo->momz = -mo->momz; } // The skull slammed into something } + + zdir = (oldz < mo->z) ? OU_OVER : OU_UNDER; +} + +static boolean PIT_CheckOverUnderMobjZ(mobj_t *thing) +{ + fixed_t blockdist; + + if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE))) + { return true; } // Can't hit thing + + blockdist = thing->radius + tmthing->radius; + + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + { return true; } // Didn't hit thing + + if (thing == tmthing) + { return true; } // Don't clip against self + + if (thing->z + thing->height <= tmthing->z) + { + // Over + + if ((!p_below_tmthing) + || ((p_below_tmthing->z + p_below_tmthing->height) < (thing->z + thing->height))) + { + p_below_tmthing = thing; + } + + if ((!p_above_thing_s) + || (tmthing->z < p_above_thing_s->z)) + { + p_above_thing_s = tmthing; + p_above_thing_g = thing; + } + + return true; + } + else if (tmthing->z + tmthing->height <= thing->z) + { + // Under + + if ((!p_above_tmthing) + || (thing->z < p_above_tmthing->z)) + { + p_above_tmthing = thing; + } + + if ((!p_below_thing_s) + || ((p_below_thing_s->z + p_below_thing_s->height) < (tmthing->z + tmthing->height))) + { + p_below_thing_s = tmthing; + p_below_thing_g = thing; + } + + return true; + } + + return !((thing->flags & MF_SOLID && !(thing->flags & MF_NOCLIP)) + && (tmthing->flags & MF_SOLID || demo_compatibility)); } // Checks if the new Z position is legal -mobj_t *P_CheckOnmobj(mobj_t *thing, boolean fakemove) +overunder_t P_CheckOverUnderMobj(mobj_t *thing, boolean fakemove) { int xl, xh, yl, yh, bx, by; subsector_t *newsubsec; const mobj_t oldmo = *thing; // Save the old mobj before the fake movement + overunder_t ret = OU_NONE; - if (!(casual_play && over_under)) { return NULL; } + if (!(casual_play && over_under)) { return ret; } tmx = thing->x; tmy = thing->y; @@ -2574,7 +2713,7 @@ mobj_t *P_CheckOnmobj(mobj_t *thing, boolean fakemove) validcount++; numspechit = 0; - if (tmflags & MF_NOCLIP) { return NULL; } + if (tmflags & MF_NOCLIP) { return ret; } // Check things first, possibly picking things up // the bounding box is extended by MAXRADIUS because mobj_ts are grouped @@ -2585,18 +2724,42 @@ mobj_t *P_CheckOnmobj(mobj_t *thing, boolean fakemove) yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + p_below_tmthing = p_below_thing_s = p_below_thing_g = + p_above_tmthing = p_above_thing_s = p_above_thing_g = NULL; + + zdir = OU_NONE; + if (fakemove) { P_FakeZMovement(tmthing); } for (bx = xl; bx <= xh; bx++) for (by = yl; by <= yh; by++) - if (!P_BlockThingsIterator(bx, by, PIT_CheckOnmobjZ)) + if (!P_BlockThingsIterator(bx, by, PIT_CheckOverUnderMobjZ)) { - *tmthing = oldmo; - return onmobj; + mobj_t *pbtg = p_below_thing_g ? p_below_thing_g->below_thing : NULL, + *pbts = p_below_thing_s, + *patg = p_above_thing_g ? p_above_thing_g->above_thing : NULL, + *pats = p_above_thing_s; + + tmthing->below_thing = p_below_tmthing; + tmthing->above_thing = p_above_tmthing; + + if (p_below_thing_g + && ((!pbtg) || ((pbtg->z + pbtg->height) < (pbts->z + pbts->height)))) + { + p_below_thing_g->below_thing = p_below_thing_s; + } + + if (p_above_thing_g + && ((!patg) || (pats->z < patg->z))) + { + p_above_thing_g->above_thing = p_above_thing_s; + } + + ret = zdir; } *tmthing = oldmo; - return NULL; + return ret; } // [Nugget] -----------------------------------------------------------------/ diff --git a/src/p_map.h b/src/p_map.h index f92f60524..1b9d071bf 100644 --- a/src/p_map.h +++ b/src/p_map.h @@ -78,7 +78,13 @@ extern msecnode_t *sector_list; // phares 3/16/98 extern fixed_t tmbbox[4]; // phares 3/20/98 extern line_t *blockline; // killough 8/11/98 -mobj_t *P_CheckOnmobj(mobj_t *thing, boolean fakemove); // [Nugget]: [DSDA] +typedef enum { + OU_UNDER = -1, + OU_NONE, + OU_OVER, +} overunder_t; + +overunder_t P_CheckOverUnderMobj(mobj_t *thing, boolean fakemove); // [Nugget]: [DSDA] extern boolean boomshot; // [Nugget] Explosive hitscan cheat diff --git a/src/p_mobj.c b/src/p_mobj.c index c87db2a0e..181e9a396 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -295,7 +295,8 @@ void P_XYMovement (mobj_t* mo) // [Nugget] Do apply friction if... || ((mo->z > mo->floorz) && !( (player && player->cheats & CF_FLY) // ... using flight cheat - || (mo->intflags & MIF_ONMOBJ)))) // ... on top of a mobj + || (mo->below_thing // ... on top of a mobj + && (mo->z == (mo->below_thing->z + mo->below_thing->height)))))) return; // killough 8/11/98: add bouncers @@ -729,6 +730,7 @@ static inline void MusInfoThinker (mobj_t *thing) void P_MobjThinker (mobj_t* mobj) { extern boolean cheese; // [Nugget] cheese :) + boolean oucheck = false; // [Nugget] Over/Under // [crispy] support MUSINFO lump (dynamic music changing) if (mobj->type == MT_MUSICSOURCE) @@ -785,6 +787,8 @@ void P_MobjThinker (mobj_t* mobj) mobj->intflags &= ~MIF_SCROLLING; if (mobj->thinker.function.p1 == (actionf_p1)P_RemoveThinkerDelayed) // killough return; // mobj was removed + + oucheck = true; // [Nugget] Over/Under } if (mobj->z != mobj->floorz || mobj->momz) @@ -792,28 +796,20 @@ void P_MobjThinker (mobj_t* mobj) // [Nugget]: [DSDA] if (casual_play && over_under && (mobj->flags & MF_SOLID)) { - mobj_t *onmo; + overunder_t zdir; - if (!(onmo = P_CheckOnmobj(mobj, true))) + if (!(zdir = P_CheckOverUnderMobj(mobj, true))) { P_ZMovement(mobj); - mobj->intflags &= ~MIF_ONMOBJ; } else { mobj->momz = 0; - if (onmo->z + onmo->height - mobj->z <= 24 * FRACUNIT) - { - if (mobj->player) { - mobj->player->viewheight -= onmo->z + onmo->height - mobj->z; - mobj->player->deltaviewheight = ((!strictmode ? viewheight_value*FRACUNIT : VIEWHEIGHT) - - mobj->player->viewheight) >> 3; - } - - mobj->z = onmo->z + onmo->height; - mobj->intflags |= MIF_ONMOBJ; - } + if (zdir == OU_UNDER && mobj->below_thing) + { mobj->z = mobj->below_thing->z + mobj->below_thing->height; } + else if (mobj->above_thing) + { mobj->z = mobj->above_thing->z - mobj->height; } } } else @@ -821,6 +817,8 @@ void P_MobjThinker (mobj_t* mobj) if (mobj->thinker.function.p1 == (actionf_p1)P_RemoveThinkerDelayed) // killough return; // mobj was removed + + oucheck = true; // [Nugget] Over/Under } else if (!(mobj->momx | mobj->momy) && !sentient(mobj)) @@ -838,6 +836,37 @@ void P_MobjThinker (mobj_t* mobj) mobj->intflags &= ~MIF_FALLING, mobj->gear = 0; // Reset torque } + // [Nugget] Over/Under: if we didn't check for over/under mobjs already, + // it means that this mobj is immobile, and its over/under mobjs, if any, + // were set by other mobj(s); check if they're still valid + if (casual_play && over_under && !oucheck) + { + mobj_t *oumobj; + fixed_t blockdist; + + if ((oumobj = mobj->below_thing)) + { + blockdist = mobj->radius + oumobj->radius; + + if ( abs(mobj->x - oumobj->x) >= blockdist + || abs(mobj->y - oumobj->y) >= blockdist) + { + mobj->below_thing = NULL; + } + } + + if ((oumobj = mobj->above_thing)) + { + blockdist = mobj->radius + oumobj->radius; + + if ( abs(mobj->x - oumobj->x) >= blockdist + || abs(mobj->y - oumobj->y) >= blockdist) + { + mobj->above_thing = NULL; + } + } + } + if (mbf21) { sector_t* sector = mobj->subsector->sector; diff --git a/src/p_mobj.h b/src/p_mobj.h index 87e30701c..9db5afeb0 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -237,7 +237,6 @@ enum { MIF_CROUCHING = 32, // Mobj (player) is crouching MIF_EXTRASPAWNED = 64, // [So Doom] Nightmare-spawned, Icon of Sin-spawned and Archvile-resurrected monsters MIF_CHEESE = 128, - MIF_ONMOBJ = 256, // [DSDA] mobj is resting on top of another }; // Map Object definition. diff --git a/src/p_user.c b/src/p_user.c index 78c401dd9..07d849774 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -226,7 +226,8 @@ void P_MovePlayer (player_t* player) mo->angle += cmd->angleturn << 16; onground = (mo->z <= mo->floorz // [Nugget] - || (mo->intflags & MIF_ONMOBJ) // [DSDA] + // On top of a mobj + || (mo->below_thing && (mo->z == (mo->below_thing->z + mo->below_thing->height))) // Mid-air control with noclip or flight cheat enabled || (player->mo->flags & MF_NOCLIP) || (player->cheats & CF_FLY)); From 352987f16f7eff65af6b9f265f31b367b0dd44aa Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Sat, 9 Dec 2023 04:45:39 -0300 Subject: [PATCH 11/15] Reformatting --- src/p_map.c | 84 +++++++++++++++++++++++----------------------------- src/p_mobj.c | 14 ++++----- 2 files changed, 44 insertions(+), 54 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 5e5b505fe..685c50bab 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -494,11 +494,41 @@ static boolean P_ProjectileImmune(mobj_t *target, mobj_t *source) ); } -// [Nugget] Over/Under: potential over/under mobjs +// [Nugget] Over/Under /------------------------------------------------------ + +// Potential over/under mobjs static mobj_t *p_below_tmthing, *p_above_tmthing, // For `tmthing` *p_below_thing_s, *p_above_thing_s, // For `thing` ("setter") *p_below_thing_g, *p_above_thing_g; // `thing` itself ("getter") +static void P_SetOverUnderMobjs(mobj_t *thing) +{ + if (casual_play && over_under) + { + mobj_t *pbtg = p_below_thing_g ? p_below_thing_g->below_thing : NULL, + *pbts = p_below_thing_s, + *patg = p_above_thing_g ? p_above_thing_g->above_thing : NULL, + *pats = p_above_thing_s; + + thing->below_thing = p_below_tmthing; + thing->above_thing = p_above_tmthing; + + if (p_below_thing_g + && ((!pbtg) || ((pbtg->z + pbtg->height) < (pbts->z + pbts->height)))) + { + p_below_thing_g->below_thing = p_below_thing_s; + } + + if (p_above_thing_g + && ((!patg) || (pats->z < patg->z))) + { + p_above_thing_g->above_thing = p_above_thing_s; + } + } +} + +// [Nugget] -----------------------------------------------------------------/ + static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static { fixed_t blockdist; @@ -901,28 +931,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean dropoff) return false; // solid wall or thing // [Nugget] Over/Under: if move was valid, set new over/under mobjs - if (casual_play && over_under) - { - mobj_t *pbtg = p_below_thing_g ? p_below_thing_g->below_thing : NULL, - *pbts = p_below_thing_s, - *patg = p_above_thing_g ? p_above_thing_g->above_thing : NULL, - *pats = p_above_thing_s; - - thing->below_thing = p_below_tmthing; - thing->above_thing = p_above_tmthing; - - if (p_below_thing_g - && ((!pbtg) || ((pbtg->z + pbtg->height) < (pbts->z + pbts->height)))) - { - p_below_thing_g->below_thing = p_below_thing_s; - } - - if (p_above_thing_g - && ((!patg) || (pats->z < patg->z))) - { - p_above_thing_g->above_thing = p_above_thing_s; - } - } + P_SetOverUnderMobjs(thing); if (!(thing->flags & MF_NOCLIP)) { @@ -1169,11 +1178,11 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (onfloor) // walking monsters rise and fall with the floor { - // [Nugget] Over/Under - const fixed_t oldz = thing->z; + const fixed_t oldz = thing->z; // [Nugget] Over/Under thing->z = thing->floorz; + // [Nugget] Over/Under if (casual_play && over_under) { if (thing->z < oldz && thing->below_thing) @@ -1193,11 +1202,11 @@ static boolean P_ThingHeightClip(mobj_t *thing) else if (thing->z < oldz) { mobj_t *below_thing = thing, *above_thing; - const fixed_t diff = oldz - thing->z; + const fixed_t zdiff = oldz - thing->z; do { if ((above_thing = below_thing->above_thing) - && ((above_thing->z - diff) == (below_thing->z + below_thing->height))) + && ((above_thing->z - zdiff) == (below_thing->z + below_thing->height))) { above_thing->z = below_thing->z + below_thing->height; } @@ -2735,26 +2744,7 @@ overunder_t P_CheckOverUnderMobj(mobj_t *thing, boolean fakemove) for (by = yl; by <= yh; by++) if (!P_BlockThingsIterator(bx, by, PIT_CheckOverUnderMobjZ)) { - mobj_t *pbtg = p_below_thing_g ? p_below_thing_g->below_thing : NULL, - *pbts = p_below_thing_s, - *patg = p_above_thing_g ? p_above_thing_g->above_thing : NULL, - *pats = p_above_thing_s; - - tmthing->below_thing = p_below_tmthing; - tmthing->above_thing = p_above_tmthing; - - if (p_below_thing_g - && ((!pbtg) || ((pbtg->z + pbtg->height) < (pbts->z + pbts->height)))) - { - p_below_thing_g->below_thing = p_below_thing_s; - } - - if (p_above_thing_g - && ((!patg) || (pats->z < patg->z))) - { - p_above_thing_g->above_thing = p_above_thing_s; - } - + P_SetOverUnderMobjs(tmthing); ret = zdir; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 181e9a396..b716f33b6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -806,9 +806,9 @@ void P_MobjThinker (mobj_t* mobj) { mobj->momz = 0; - if (zdir == OU_UNDER && mobj->below_thing) + if (mobj->below_thing && zdir == OU_UNDER) { mobj->z = mobj->below_thing->z + mobj->below_thing->height; } - else if (mobj->above_thing) + else if (mobj->above_thing) // zdir == OU_OVER { mobj->z = mobj->above_thing->z - mobj->height; } } } @@ -841,15 +841,15 @@ void P_MobjThinker (mobj_t* mobj) // were set by other mobj(s); check if they're still valid if (casual_play && over_under && !oucheck) { - mobj_t *oumobj; + const mobj_t *oumobj; fixed_t blockdist; if ((oumobj = mobj->below_thing)) { blockdist = mobj->radius + oumobj->radius; - if ( abs(mobj->x - oumobj->x) >= blockdist - || abs(mobj->y - oumobj->y) >= blockdist) + if ( (abs(mobj->x - oumobj->x) >= blockdist) + || (abs(mobj->y - oumobj->y) >= blockdist)) { mobj->below_thing = NULL; } @@ -859,8 +859,8 @@ void P_MobjThinker (mobj_t* mobj) { blockdist = mobj->radius + oumobj->radius; - if ( abs(mobj->x - oumobj->x) >= blockdist - || abs(mobj->y - oumobj->y) >= blockdist) + if ( (abs(mobj->x - oumobj->x) >= blockdist) + || (abs(mobj->y - oumobj->y) >= blockdist)) { mobj->above_thing = NULL; } From 7ca1b66f49b3e145682c6ffa7d2801174f235908 Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Sat, 9 Dec 2023 06:50:32 -0300 Subject: [PATCH 12/15] Further improve lift logic Things on and near lifts now get their over/under mobjs set and/or cleared in `P_ThingHeightClip()`. --- src/p_map.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_map.c b/src/p_map.c index 685c50bab..6d877eb55 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1169,6 +1169,8 @@ static boolean P_ThingHeightClip(mobj_t *thing) P_CheckPosition(thing, thing->x, thing->y); + P_SetOverUnderMobjs(tmthing); // [Nugget] Over/Under + // what about stranding a monster partially off an edge? // killough 11/98: Answer: see below (upset balance if hanging off ledge) From 12a2447a4fd16e63dd964a59823a50fdd3585d3b Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Fri, 15 Dec 2023 20:03:18 -0300 Subject: [PATCH 13/15] Fix clipping into things when moving up steps --- src/p_map.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 4292e643e..94424af6b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -930,8 +930,16 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean dropoff) if (!P_CheckPosition(thing, x, y)) return false; // solid wall or thing - // [Nugget] Over/Under: if move was valid, set new over/under mobjs - P_SetOverUnderMobjs(thing); + // [Nugget] Over/Under + if (casual_play && over_under) + { + // `tmfloorz` may have changed, so make sure the thing fits + if (p_above_tmthing && (p_above_tmthing->z < (tmfloorz + thing->height))) + { return false; } + + // If move was valid, set new over/under mobjs + P_SetOverUnderMobjs(thing); + } if (!(thing->flags & MF_NOCLIP)) { From 1f834504aaccd750cfbf2b8f951a3455f26510fd Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Thu, 28 Dec 2023 07:14:38 -0300 Subject: [PATCH 14/15] Update documentation --- CHANGELOG.md | 5 +++++ README.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5afb0c207..7d925e065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,14 @@ ## Changes +- **Reimplemented _Move Over/Under Things_ feature**ยน, making it much less bug-prone - **Improved Automap line thickening when the window is downscaled** - **Tweaked zooming effect** +**1\.** Among other changes, the setting itself has been extended: a value of `1` enables the feature only for players, +while a value of `2` enables it for all Things. This differs from the previous implementation, wherein `1` would enable +the feature for all Things. + ## Bug Fixes - **FOV effects not being cleared thoroughly upon loading levels** diff --git a/README.md b/README.md index daa6ce2d8..61e88792d 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ For these settings, their CVAR names are provided alongside the _CFG-Only_ label - **Extended _Level Brightness_ range:** [-8, 8] - **_"Direct + Auto"_ mode for Vertical Aiming** - **_Direct Vertical Aiming_ for melee attacks** -- **_Things move over/under things_** setting [p.f. Crispy Doom] +- **_Move Over/Under Things_** setting [partially p.f. Crispy Doom, DSDA-Doom] - **Jumping** (default key: Alt, must be enabled first) [p.f. Crispy Doom] - **Crouching/ducking** (default key: C, must be enabled first) [i.b. ZDoom] - **_Field of View_** setting [p.f. Doom Retro] From b4b3d811174ea6588c4eeb20e6e84374e87fdd2e Mon Sep 17 00:00:00 2001 From: Alaux <73968015+MrAlaux@users.noreply.github.com> Date: Thu, 28 Dec 2023 07:48:47 -0300 Subject: [PATCH 15/15] Fix excess speed when airborne with noclip --- src/p_mobj.c | 22 ++++++++++++++++------ src/p_user.c | 16 ++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index b716f33b6..c4d7d35b5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -291,14 +291,24 @@ void P_XYMovement (mobj_t* mo) } // no friction for missiles or skulls ever, no friction when airborne - if (mo->flags & (MF_MISSILE | MF_SKULLFLY) - // [Nugget] Do apply friction if... - || ((mo->z > mo->floorz) - && !( (player && player->cheats & CF_FLY) // ... using flight cheat - || (mo->below_thing // ... on top of a mobj - && (mo->z == (mo->below_thing->z + mo->below_thing->height)))))) + if (mo->flags & (MF_MISSILE | MF_SKULLFLY)) return; + // [Nugget] Do apply friction if airborne... + if ( + (mo->z > mo->floorz) + && !(casual_play + && ( // ... using noclip or flight cheat + (player && player->cheats & (CF_NOCLIP|CF_FLY)) + // ... on top of a mobj + || (mo->below_thing && (mo->z == (mo->below_thing->z + mo->below_thing->height))) + ) + ) + ) + { + return; + } + // killough 8/11/98: add bouncers // killough 9/15/98: add objects falling off ledges // killough 11/98: only include bouncers hanging off ledges diff --git a/src/p_user.c b/src/p_user.c index 2ef56795c..2d17bb139 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -233,12 +233,16 @@ void P_MovePlayer (player_t* player) static boolean crouchKeyDown = false; // [Nugget] mo->angle += cmd->angleturn << 16; - onground = (mo->z <= mo->floorz - // [Nugget] - // On top of a mobj - || (mo->below_thing && (mo->z == (mo->below_thing->z + mo->below_thing->height))) - // Mid-air control with noclip or flight cheat enabled - || (player->mo->flags & MF_NOCLIP) || (player->cheats & CF_FLY)); + onground = mo->z <= mo->floorz; + + // [Nugget] Allow movement if... + if (casual_play) { + onground |= + // ... using noclip or flight cheat + (player->cheats & (CF_NOCLIP|CF_FLY)) + // ... on top of a mobj + || (mo->below_thing && (mo->z == (mo->below_thing->z + mo->below_thing->height))); + } // [Nugget] if (player->cheats & CF_FLY)