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] diff --git a/src/m_menu.c b/src/m_menu.c index 1a8621943..a713b1154 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4892,6 +4892,10 @@ static void M_ChangeViewHeight(void) oldviewheight = viewheight_value; } +static const char *over_under_str[] = { + "Off", "Player Only", "All Things", NULL +}; + static const char *impact_pitch_str[] = { "Off", "Fall", "Damage", "Both", NULL }; @@ -4904,8 +4908,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 3fad66048..703a6b375 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -721,8 +721,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_enemy.c b/src/p_enemy.c index 762a0454b..d72a15903 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -407,14 +407,38 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) // killough 9/12/98 if (actor->flags & MF_FLOAT && floatok) { + // [Nugget] Over/Under + const fixed_t oldz = actor->z; + if (actor->z < tmfloorz) // must adjust height - actor->z += FLOATSPEED; + { + actor->z += FLOATSPEED; + + // [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; - actor->flags |= MF_INFLOAT; + // [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; + } + } - return true; + // [Nugget] Conditions: only if we actually moved + if (NOTCASUALPLAY(actor->z != oldz)) + { + actor->flags |= MF_INFLOAT; + return true; + } } if (!numspechit) @@ -460,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 117669088..94424af6b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -494,6 +494,41 @@ 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 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; @@ -543,6 +578,51 @@ 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) + && ((over_under == 2) || tmthing->player || thing->player)) + { + 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 if (tmthing->flags & MF_SKULLFLY) @@ -552,15 +632,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); } @@ -662,37 +733,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. @@ -841,6 +881,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)) @@ -886,6 +930,17 @@ 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 (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)) { // killough 7/26/98: reformatted slightly @@ -1122,6 +1177,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) @@ -1131,8 +1188,42 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (onfloor) // walking monsters rise and fall with the floor { + 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) + { 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 zdiff = oldz - thing->z; + + do { + if ((above_thing = below_thing->above_thing) + && ((above_thing->z - zdiff) == (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; @@ -2494,6 +2585,185 @@ void P_MapEnd(void) tmthing = NULL; } +// [Nugget]: [DSDA] heretic /------------------------------------------------- + +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; + + // Float down towards target if too close + if (!((mo->flags ^ MF_FLOAT) & (MF_FLOAT | MF_SKULLFLY | MF_INFLOAT)) && mo->target) + { + const fixed_t delta = mo->target->z + (mo->height >> 1) - mo->z; + + if (P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y) < abs(delta) * 3) + { mo->z += (delta < 0) ? -FLOATSPEED : 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) { mo->momz = -(GRAVITY >> 3) * 2; } + else { mo->momz -= GRAVITY >> 3; } + } + else if (!(mo->flags & MF_NOGRAVITY)) + { + if (!mo->momz) { mo->momz = -GRAVITY; } + 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 + } + + 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 +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 ret; } + + tmx = thing->x; + tmy = thing->y; + tmthing = thing; + tmflags = thing->flags; + + tmbbox[BOXTOP] = tmy + tmthing->radius; + tmbbox[BOXBOTTOM] = tmy - tmthing->radius; + tmbbox[BOXRIGHT] = tmx + tmthing->radius; + tmbbox[BOXLEFT] = tmx - tmthing->radius; + + 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 + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + 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 + // 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; + + 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_CheckOverUnderMobjZ)) + { + P_SetOverUnderMobjs(tmthing); + ret = zdir; + } + + *tmthing = oldmo; + return ret; +} + +// [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..1b9d071bf 100644 --- a/src/p_map.h +++ b/src/p_map.h @@ -78,6 +78,14 @@ 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 +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 #endif // __P_MAP__ diff --git a/src/p_mobj.c b/src/p_mobj.c index ca332be16..c4d7d35b5 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) { @@ -292,12 +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 airborne with noclip or flight cheat enabled - || (mo->z > mo->floorz - && !(casual_play && player && (mo->flags & MF_NOCLIP || player->cheats & CF_FLY)))) + 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 @@ -729,6 +740,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) @@ -778,26 +790,45 @@ 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; 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) { - P_ZMovement(mobj); + // [Nugget]: [DSDA] + if (casual_play && over_under && (mobj->flags & MF_SOLID)) + { + overunder_t zdir; + + if (!(zdir = P_CheckOverUnderMobj(mobj, true))) + { + P_ZMovement(mobj); + } + else + { + mobj->momz = 0; + + if (mobj->below_thing && zdir == OU_UNDER) + { mobj->z = mobj->below_thing->z + mobj->below_thing->height; } + else if (mobj->above_thing) // zdir == OU_OVER + { mobj->z = mobj->above_thing->z - mobj->height; } + } + } + else + P_ZMovement(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)) @@ -815,6 +846,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) + { + 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)) + { + 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 8dd355beb..9db5afeb0 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. diff --git a/src/p_user.c b/src/p_user.c index 4bf734fb4..2d17bb139 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -234,9 +234,15 @@ void P_MovePlayer (player_t* player) mo->angle += cmd->angleturn << 16; onground = mo->z <= mo->floorz; - // [Nugget] Allow mid-air control with noclip or flight cheat enabled - if (casual_play) - { onground |= ((player->mo->flags & MF_NOCLIP) || (player->cheats & CF_FLY)); } + + // [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)