From d6ca5b4925133817b0d2e81477e21ecd2775dabc Mon Sep 17 00:00:00 2001 From: Paf2020 Date: Mon, 26 Jan 2026 20:26:46 -0500 Subject: [PATCH] Fixed issue [#703](https://github.com/Paf2020/crispy-doom-zaxis-fix/issues/703) and also issue [#381](https://github.com/Paf2020/crispy-doom-zaxis-fix/issues/381) (not sure about that ot that one), although with minor overreach (All objects can be walked over/under now, might need to add custom heights or a option for custom heights for objects without realistic default heights.) I think it's all properly guarded with if (critical->overunder)." --- src/doom/p_local.h | 3 + src/doom/p_map.c | 195 ++++++++++++++++++++++++++++++++------------- src/doom/p_mobj.c | 38 +++++++++ 3 files changed, 182 insertions(+), 54 deletions(-) diff --git a/src/doom/p_local.h b/src/doom/p_local.h index 55d208942..5b98308c4 100644 --- a/src/doom/p_local.h +++ b/src/doom/p_local.h @@ -228,6 +228,9 @@ extern line_t* ceilingline; extern line_t** spechit; // [crispy] remove SPECHIT limit extern int numspechit; +void P_ResyncAboveThings(mobj_t* supporter); +void P_UpdateMobjHeights(mobj_t* mo); // i dont want to redefine this everywhere i use it + boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); boolean P_TryMove (mobj_t* thing, fixed_t x, fixed_t y); boolean P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y); diff --git a/src/doom/p_map.c b/src/doom/p_map.c index b0a38ac04..1348cabae 100644 --- a/src/doom/p_map.c +++ b/src/doom/p_map.c @@ -312,8 +312,8 @@ boolean PIT_CheckThing (mobj_t* thing) // check for skulls slamming into things if (tmthing->flags & MF_SKULLFLY) { - // [crispy] check if attacking skull flies over player - if (critical->overunder && thing->player) + // [crispy] check if attacking skull flies over target + if (critical->overunder) { if (tmthing->z > thing->z + thing->height) { @@ -394,60 +394,40 @@ boolean PIT_CheckThing (mobj_t* thing) return !solid; } - if (critical->overunder) + if (critical->overunder && !(tmthing->flags & MF_MISSILE) && (thing->flags & MF_SOLID) && !(thing->flags & MF_NOBLOCKMAP)) { - // [crispy] a solid hanging body will allow sufficiently small things underneath it - if (thing->flags & MF_SOLID && thing->flags & MF_SPAWNCEILING) + // [crispy] allow the usual 24 units step-up even across monsters' heads, + // only if the current height has not been reached by "low" jumping + fixed_t step_up = (tmthing->player && tmthing->player->jumpTics > 7) ? 0 : 24*FRACUNIT; + + if (tmthing->z + step_up >= thing->z + thing->height) { - if (tmthing->z + tmthing->height <= thing->z) - { - if (thing->z < tmceilingz) - { - tmceilingz = thing->z; - } - return true; - } + // walk over object + tmfloorz = MAX(thing->z + thing->height, tmfloorz); + return true; } - - // [crispy] allow players to walk over/under shootable objects - if (tmthing->player && thing->flags & MF_SHOOTABLE) + else if (tmthing->z + tmthing->height <= thing->z) { - // [crispy] allow the usual 24 units step-up even across monsters' heads, - // only if the current height has not been reached by "low" jumping - fixed_t step_up = tmthing->player->jumpTics > 7 ? 0 : 24*FRACUNIT; + // walk underneath object + tmceilingz = MIN(thing->z, tmceilingz); + return true; + } - if (tmthing->z + step_up >= thing->z + thing->height) - { - // player walks over object - tmfloorz = MAX(thing->z + thing->height, tmfloorz); - thing->ceilingz = MIN(tmthing->z, thing->ceilingz); - return true; - } - else - if (tmthing->z + tmthing->height <= thing->z) - { - // player walks underneath object - tmceilingz = MIN(thing->z, tmceilingz); - thing->floorz = MAX(tmthing->z + tmthing->height, thing->floorz); - return true; - } + // [crispy] check if things are stuck and allow them to move further apart + // taken from doomretro/src/p_map.c:319-332 + if (tmx == tmthing->x && tmy == tmthing->y) + { + unblocking = true; + } + else if (thing->flags & MF_SHOOTABLE) + { + fixed_t newdist = P_AproxDistance(thing->x - tmx, thing->y - tmy); + fixed_t olddist = P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y); - // [crispy] check if things are stuck and allow them to move further apart - // taken from doomretro/src/p_map.c:319-332 - if (tmx == tmthing->x && tmy == tmthing->y) + if (newdist > olddist) { - unblocking = true; - } - else - { - fixed_t newdist = P_AproxDistance(thing->x - tmx, thing->y - tmy); - fixed_t olddist = P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y); - - if (newdist > olddist) - { - unblocking = (tmthing->z < thing->z + thing->height - && tmthing->z + tmthing->height > thing->z); - } + unblocking = (tmthing->z < thing->z + thing->height + && tmthing->z + tmthing->height > thing->z); } } } @@ -455,6 +435,97 @@ boolean PIT_CheckThing (mobj_t* thing) return !(thing->flags & MF_SOLID) || unblocking; } +mobj_t* resync_supporter; + +// +// P_UpdateMobjHeights +// +void P_UpdateMobjHeights(mobj_t* mo) +{ + if (critical->overunder) + { + P_CheckPosition(mo, mo->x, mo->y); + mo->floorz = tmfloorz; + mo->ceilingz = tmceilingz; + } +} + +// +// Paf - the atcual reyncer +// PIT_ResyncThing +// +boolean PIT_ResyncThing(mobj_t *thing) +{ + if (thing == resync_supporter) + return true; + + if (resync_supporter) + { + // they are overlapping, check if thing is above supporter + if (abs(thing->x - resync_supporter->x) < (thing->radius + resync_supporter->radius) && + abs(thing->y - resync_supporter->y) < (thing->radius + resync_supporter->radius)) + { + if (thing->z < resync_supporter->z + resync_supporter->height) + return true; + } + } + + if (critical->overunder && (thing->flags & (MF_SHOOTABLE | MF_SOLID))) + { + P_UpdateMobjHeights(thing); + + if ((thing->flags & MF_SHOOTABLE) && thing->z < thing->floorz) + thing->z = thing->floorz; + } + return true; +} + +// +// Paf - resync stacked objects with the sector when their support leaves +// P_CheckThingsAbove +// +void P_CheckThingsAbove(int x, int y, mobj_t *supporter) +{ + int z, height, radius; + int xl, xh, yl, yh; + int bx, by; + + z = supporter->z; + height = supporter->height; + radius = supporter->radius; + + resync_supporter = supporter; // can be NULL if we just want to check an area i think + + xl = (x - radius - MAPBLOCKSIZE - bmaporgx) >> MAPBLOCKSHIFT; + xh = (x + radius + MAPBLOCKSIZE - bmaporgx) >> MAPBLOCKSHIFT; + yl = (y - radius - MAPBLOCKSIZE - bmaporgy) >> MAPBLOCKSHIFT; + yh = (y + radius + MAPBLOCKSIZE - bmaporgy) >> MAPBLOCKSHIFT; + + if (xl < 0) xl = 0; + if (yl < 0) yl = 0; + if (xh >= bmapwidth) xh = bmapwidth - 1; + if (yh >= bmapheight) yh = bmapheight - 1; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + P_BlockThingsIterator(bx, by, PIT_ResyncThing); +} + +// +// P_ResyncAboveThings +// +void P_ResyncAboveThings(mobj_t *supporter) +{ + if (!(supporter->flags & MF_SOLID) || + (supporter->flags & + (MF_SPECIAL || MF_PICKUP || MF_CORPSE)) || !critical->overunder) // i believe these are the only cases we shouldn't do this + { + return; + } + + P_CheckThingsAbove(supporter->x, supporter->y, supporter); +} + // // MOVEMENT CLIPPING @@ -574,7 +645,7 @@ P_TryMove floatok = false; if (!P_CheckPosition (thing, x, y)) - return false; // solid wall or thing + return false; // solid wall or thing if ( !(thing->flags & MF_NOCLIP) ) { @@ -608,7 +679,7 @@ P_TryMove thing->y = y; P_SetThingPosition (thing); - + // if any special lines were hit, do the effect if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) ) { @@ -626,10 +697,21 @@ P_TryMove } } + if (critical->overunder) + { + // resync at old position + if (thing->flags & MF_SOLID) + P_CheckThingsAbove(oldx, oldy, thing); + + // resync at new position (we might have moved under) + P_ResyncAboveThings(thing); + } + return true; } - +boolean P_IsZMovementLegal (mobj_t* mo); +boolean P_IsResyncNeeded(mobj_t* mo); // // P_ThingHeightClip // Takes a valid thing and adjusts the thing->floorz, @@ -665,8 +747,13 @@ boolean P_ThingHeightClip (mobj_t* thing) } if (thing->ceilingz - thing->floorz < thing->height) - return false; - + { + return false; + } + + if (critical->overunder) + P_ResyncAboveThings(thing); + return true; } diff --git a/src/doom/p_mobj.c b/src/doom/p_mobj.c index 7a6f00632..5ae8aca6f 100644 --- a/src/doom/p_mobj.c +++ b/src/doom/p_mobj.c @@ -299,6 +299,31 @@ void P_XYMovement (mobj_t* mo) mo->momx = FixedMul (mo->momx, FRICTION); mo->momy = FixedMul (mo->momy, FRICTION); } + + if (critical->overunder && (mo->flags & MF_SHOOTABLE)) + { + P_UpdateMobjHeights(mo); + P_ResyncAboveThings(mo); + } +} + + +void P_ResyncAboveThings(mobj_t *supporter); +// +// P_IsZMovementLegal +// +boolean P_IsZMovementLegal (mobj_t* mo) { + if (critical->overunder && (!(mo->flags & MF_SOLID) || (mo->flags & (MF_SPECIAL|MF_PICKUP|MF_CORPSE)))) { + return true; + } + + P_UpdateMobjHeights(mo); + + if (mo->z+mo->height > mo->ceilingz) + return false; + + P_ResyncAboveThings(mo); + return true; } // @@ -474,6 +499,8 @@ void P_ZMovement (mobj_t* mo) return; } } + if (critical->overunder) + P_ResyncAboveThings(mo); } @@ -582,6 +609,11 @@ void P_MobjThinker (mobj_t* mobj) mobj->oldangle = mobj->angle; } + if (critical->overunder && (mobj->flags & MF_SHOOTABLE)) + { + P_UpdateMobjHeights(mobj); + } + // momentum movement if (mobj->momx || mobj->momy @@ -593,6 +625,7 @@ void P_MobjThinker (mobj_t* mobj) if (mobj->thinker.function.acv == (actionf_v) (-1)) return; // mobj was removed } + if ( (mobj->z != mobj->floorz) || mobj->momz ) { @@ -737,6 +770,11 @@ P_SpawnMobjSafe mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; P_AddThinker (&mobj->thinker); + if (critical->overunder && (mobj->flags & MF_SHOOTABLE)) + { + P_UpdateMobjHeights(mobj); + P_IsZMovementLegal(mobj); + } return mobj; }