diff --git a/src/p_map.c b/src/p_map.c index b8123fc0c..7bdbcdc23 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -378,6 +378,195 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) } } +// +// P_ConsiderSolids (moved out of PIT_CheckThing in order to have additional flexibility) +// + +static boolean P_ConsiderSolids(mobj_t *thing) +{ + // Monitors are not treated as solid to players who are jumping, spinning or gliding, + // unless it's a CTF team monitor and you're on the wrong team + if (thing->flags & MF_MONITOR && tmthing->player + && (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) + || ((tmthing->player->pflags & PF_JUMPED) + && !(tmthing->player->charflags & SF_NOJUMPDAMAGE + && !(tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) + || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) + || ((tmthing->player->charflags & SF_STOMPDAMAGE) + && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))) + && !((thing->type == MT_REDRINGBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_BLUERINGBOX && tmthing->player->ctfteam != 2))) + ; + // z checking at last + // Treat noclip things as non-solid! + else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID + && (tmthing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID) + { + fixed_t topz, tmtopz; + + if (tmthing->eflags & MFE_VERTICALFLIP) + { + // pass under + tmtopz = tmthing->z; + + if (tmtopz > thing->z + thing->height) + { + if (thing->z + thing->height > tmfloorz) + { + tmfloorz = thing->z + thing->height; +#ifdef ESLOPE + tmfloorslope = NULL; +#endif + } + return true; + } + + topz = thing->z - FixedMul(FRACUNIT, thing->scale); + + // block only when jumping not high enough, + // (dont climb max. 24units while already in air) + // if not in air, let P_TryMove() decide if it's not too high + if (tmthing->player && tmthing->z + tmthing->height > topz + && tmthing->z + tmthing->height < tmthing->ceilingz) + return false; // block while in air + + if (thing->flags & MF_SPRING) + ; + else if (topz < tmceilingz && tmthing->z+tmthing->height <= thing->z+thing->height) + { + tmceilingz = topz; +#ifdef ESLOPE + tmceilingslope = NULL; +#endif + tmfloorthing = thing; // thing we may stand on + } + } + else + { + // pass under + tmtopz = tmthing->z + tmthing->height; + + if (tmtopz < thing->z) + { + if (thing->z < tmceilingz) + { + tmceilingz = thing->z; +#ifdef ESLOPE + tmceilingslope = NULL; +#endif + } + return true; + } + + topz = thing->z + thing->height + FixedMul(FRACUNIT, thing->scale); + + // block only when jumping not high enough, + // (dont climb max. 24units while already in air) + // if not in air, let P_TryMove() decide if it's not too high + if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz) + return false; // block while in air + + if (thing->flags & MF_SPRING) + ; + else if (topz > tmfloorz && tmthing->z >= thing->z) + { + tmfloorz = topz; +#ifdef ESLOPE + tmfloorslope = NULL; +#endif + tmfloorthing = thing; // thing we may stand on + } + } + } + + // not solid not blocked + return true; +} + +#if 0 +// +// PIT_CheckSolid (PIT_CheckThing, but for solids only, and guaranteed no side effects) +// +static boolean PIT_CheckSolid(mobj_t *thing) +{ + fixed_t blockdist; + + // don't clip against self + if (thing == tmthing) + return true; + + // Ignore... things. + if (!tmthing || !thing || P_MobjWasRemoved(thing)) + return true; + + I_Assert(!P_MobjWasRemoved(tmthing)); + I_Assert(!P_MobjWasRemoved(thing)); + + if (!(thing->flags & MF_SOLID)) + return true; + + // Ignore spectators + if ((tmthing->player && tmthing->player->spectator) + || (thing->player && thing->player->spectator)) + return true; + + // Metal Sonic destroys tiny baby objects. + if (tmthing->type == MT_METALSONIC_RACE + && (thing->flags & (MF_MISSILE|MF_ENEMY|MF_BOSS) || thing->type == MT_SPIKE)) + return true; + + // CA_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes. + if ((tmthing->player) + && (((tmthing->player->charability == CA_DASHMODE) && (tmthing->player->dashmode >= 3*TICRATE) + && (thing->flags & (MF_MONITOR) || thing->type == MT_SPIKE)) + || ((((tmthing->player->charability == CA_TWINSPIN) && (tmthing->player->panim == PA_ABILITY)) + || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)) + && (thing->type == MT_SPIKE)))) + return true; + + // Don't collide with your buddies while NiGHTS-flying. + if (tmthing->player && thing->player && (maptol & TOL_NIGHTS) + && ((tmthing->player->pflags & PF_NIGHTSMODE) || (thing->player->pflags & PF_NIGHTSMODE))) + return true; + + blockdist = thing->radius + tmthing->radius; + + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + return true; // didn't hit it + + // Force solid players in hide and seek to avoid corner stacking. + if (cv_tailspickup.value && gametype != GT_HIDEANDSEEK) + { + if (tmthing->player && thing->player) + return true; + } + + if (tmthing->player) // Is the moving/interacting object the player? + { + if (!tmthing->health) + return true; + + // Are you touching the side of the object you're interacting with? + else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height + && thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) >= tmthing->z) + { + if (thing->flags & MF_MONITOR + && (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) + || ((tmthing->player->pflags & PF_JUMPED) + && !(tmthing->player->charflags & SF_NOJUMPDAMAGE + && !(tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) + || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) + || ((tmthing->player->charflags & SF_STOMPDAMAGE) + && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)))) + { + return false; + } + } + } + + return P_ConsiderSolids(thing); +} +#endif + // // PIT_CheckThing // @@ -1007,99 +1196,8 @@ static boolean PIT_CheckThing(mobj_t *thing) if (iwassprung) // this spring caused you to gain MFE_SPRUNG just now... return false; // "cancel" P_TryMove via blocking so you keep your current position } - // Monitors are not treated as solid to players who are jumping, spinning or gliding, - // unless it's a CTF team monitor and you're on the wrong team - else if (thing->flags & MF_MONITOR && tmthing->player - && (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) - || ((tmthing->player->pflags & PF_JUMPED) - && !(tmthing->player->charflags & SF_NOJUMPDAMAGE - && !(tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) - || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) - || ((tmthing->player->charflags & SF_STOMPDAMAGE) - && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))) - && !((thing->type == MT_REDRINGBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_BLUERINGBOX && tmthing->player->ctfteam != 2))) - ; - // z checking at last - // Treat noclip things as non-solid! - else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID - && (tmthing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID) - { - fixed_t topz, tmtopz; - - if (tmthing->eflags & MFE_VERTICALFLIP) - { - // pass under - tmtopz = tmthing->z; - - if (tmtopz > thing->z + thing->height) - { - if (thing->z + thing->height > tmfloorz) - { - tmfloorz = thing->z + thing->height; -#ifdef ESLOPE - tmfloorslope = NULL; -#endif - } - return true; - } - - topz = thing->z - FixedMul(FRACUNIT, thing->scale); - - // block only when jumping not high enough, - // (dont climb max. 24units while already in air) - // if not in air, let P_TryMove() decide if it's not too high - if (tmthing->player && tmthing->z + tmthing->height > topz - && tmthing->z + tmthing->height < tmthing->ceilingz) - return false; // block while in air - - if (thing->flags & MF_SPRING) - ; - else if (topz < tmceilingz && tmthing->z+tmthing->height <= thing->z+thing->height) - { - tmceilingz = topz; -#ifdef ESLOPE - tmceilingslope = NULL; -#endif - tmfloorthing = thing; // thing we may stand on - } - } - else - { - // pass under - tmtopz = tmthing->z + tmthing->height; - - if (tmtopz < thing->z) - { - if (thing->z < tmceilingz) - { - tmceilingz = thing->z; -#ifdef ESLOPE - tmceilingslope = NULL; -#endif - } - return true; - } - - topz = thing->z + thing->height + FixedMul(FRACUNIT, thing->scale); - - // block only when jumping not high enough, - // (dont climb max. 24units while already in air) - // if not in air, let P_TryMove() decide if it's not too high - if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz) - return false; // block while in air - - if (thing->flags & MF_SPRING) - ; - else if (topz > tmfloorz && tmthing->z >= thing->z) - { - tmfloorz = topz; -#ifdef ESLOPE - tmfloorslope = NULL; -#endif - tmfloorthing = thing; // thing we may stand on - } - } - } + else + return P_ConsiderSolids(thing); // not solid not blocked return true; diff --git a/src/p_user.c b/src/p_user.c index 5c3476b45..1d0fb38c9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4997,22 +4997,21 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad In some ways worse, in some ways better. I did the following this way because the player object has to deal with touchspecials too, not just solids. There were all sorts of fun bugs when the player got to touch the goal a frame earlier than it should've. - We could've applied MF_NOCLIPTHING, but then we'd lose out on clipping against MF_SOLIDs. Which is bad. - Instead, the object TEMPORARILY LOSES ITS PLAYER STATUS. Is that nuts? It's probably a little nuts. I know - we probably could've kept around MT_NIGHTSCHAR in some fashion, having an invisible hitbox following the + Technically, we lose out on being blocked by MF_SOLID objects, but official stages don't use them on the track. + I know we probably could've kept around MT_NIGHTSCHAR in some fashion, having an invisible hitbox following the player around... but I'd already removed all its references, restructured the way the chaos emerald follows the player around to fill the player->mo->tracer gap left behind, and NiGHTS is a lag magnet (lagnet?) - enough as it is... so whatever. You're welcome to tell me I'm terrible, but at least it works. + enough as it is... so whatever. ~toast */ { fixed_t prevx = player->mo->x; fixed_t prevy = player->mo->y; boolean notallowed; - player->mo->player = NULL; // YIKES + player->mo->flags |= MF_NOCLIPTHING; // player = NULL; // YIKES notallowed = (!(P_TryMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, true))); P_TeleportMove(player->mo, prevx, prevy, player->mo->z); - player->mo->player = player; // unyikes + player->mo->flags &= ~MF_NOCLIPTHING; // player = player; // unyikes if (notallowed) return; }