diff --git a/src/b_bot.c b/src/b_bot.c index c59c084e9..0f2c80d55 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -41,12 +41,13 @@ static inline void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cm return; #endif - if (tails->player->pflags & (PF_MACESPIN|PF_ITEMHANG)) + if (tails->player->powers[pw_carry] == CR_MACESPIN || tails->player->powers[pw_carry] == CR_GENERIC) { + boolean isrelevant = (sonic->player->powers[pw_carry] == CR_MACESPIN || sonic->player->powers[pw_carry] == CR_GENERIC); dist = P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y); - if (sonic->player->cmd.buttons & BT_JUMP && sonic->player->pflags & (PF_JUMPED|PF_MACESPIN|PF_ITEMHANG)) + if (sonic->player->cmd.buttons & BT_JUMP && (sonic->player->pflags & PF_JUMPED) && isrelevant) cmd->buttons |= BT_JUMP; - if (sonic->player->pflags & (PF_MACESPIN|PF_ITEMHANG)) + if (isrelevant) { cmd->forwardmove = sonic->player->cmd.forwardmove; cmd->angleturn = abs((signed)(tails->angle - sonic->angle))>>16; @@ -211,8 +212,9 @@ boolean B_CheckRespawn(player_t *player) // Check if Sonic is busy first. // If he's doing any of these things, he probably doesn't want to see us. - if (sonic->player->pflags & (PF_ROPEHANG|PF_GLIDING|PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_NIGHTSMODE) - || (sonic->player->panim != PA_IDLE && sonic->player->panim != PA_WALK)) + if (sonic->player->pflags & (PF_GLIDING|PF_SLIDING|PF_NIGHTSMODE) + || (sonic->player->panim != PA_IDLE && sonic->player->panim != PA_WALK) + || (sonic->player->powers[pw_carry])) return false; // Low ceiling, do not want! diff --git a/src/d_player.h b/src/d_player.h index 59875b4cc..f1d4d4395 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -44,6 +44,7 @@ typedef enum SF_STOMPDAMAGE = 1<<9, // Always damage enemies, etc by landing on them, no matter your vunerability? SF_MARIODAMAGE = SF_NOJUMPDAMAGE|SF_STOMPDAMAGE, // The Mario method of being able to damage enemies, etc. SF_MACHINE = 1<<10, // Beep boop. Are you a robot? + // free up to and including 1<<31 } skinflags_t; //Primary and secondary skin abilities @@ -128,40 +129,28 @@ typedef enum // Are you gliding? PF_GLIDING = 1<<16, - // Tails pickup! - PF_CARRIED = 1<<17, - // Sliding (usually in water) like Labyrinth/Oil Ocean - PF_SLIDING = 1<<18, - - // Hanging on a rope - PF_ROPEHANG = 1<<19, - - // Hanging on an item of some kind - zipline, chain, etc. (->tracer) - PF_ITEMHANG = 1<<20, - - // On the mace chain spinning around (->tracer) - PF_MACESPIN = 1<<21, + PF_SLIDING = 1<<17, /*** NIGHTS STUFF ***/ // Is the player in NiGHTS mode? - PF_NIGHTSMODE = 1<<22, - PF_TRANSFERTOCLOSEST = 1<<23, + PF_NIGHTSMODE = 1<<18, + PF_TRANSFERTOCLOSEST = 1<<19, // Spill rings after falling - PF_NIGHTSFALL = 1<<24, - PF_DRILLING = 1<<25, - PF_SKIDDOWN = 1<<26, + PF_NIGHTSFALL = 1<<20, + PF_DRILLING = 1<<21, + PF_SKIDDOWN = 1<<22, /*** TAG STUFF ***/ - PF_TAGGED = 1<<27, // Player has been tagged and awaits the next round in hide and seek. - PF_TAGIT = 1<<28, // The player is it! For Tag Mode + PF_TAGGED = 1<<23, // Player has been tagged and awaits the next round in hide and seek. + PF_TAGIT = 1<<24, // The player is it! For Tag Mode /*** misc ***/ - PF_FORCESTRAFE = 1<<29, // Turning inputs are translated into strafing inputs - PF_ANALOGMODE = 1<<30, // Analog mode? + PF_FORCESTRAFE = 1<<25, // Turning inputs are translated into strafing inputs + PF_ANALOGMODE = 1<<26, // Analog mode? - // free: 1<<30 and 1<<31 + // free up to and including 1<<31 } pflags_t; typedef enum @@ -204,7 +193,20 @@ typedef enum SH_STACK = SH_FIREFLOWER, SH_NOSTACK = ~SH_STACK -} shieldtype_t; +} shieldtype_t; // pw_shield + +typedef enum +{ + CR_NONE = 0, + // The generic case is suitable for most objects. + CR_GENERIC, + // Tails carry. + CR_PLAYER, + // Specific level gimmicks. + CR_ZOOMTUBE, + CR_ROPEHANG, + CR_MACESPIN +} carrytype_t; // pw_carry // Player powers. (don't edit this comment) typedef enum @@ -213,6 +215,7 @@ typedef enum pw_sneakers, pw_flashing, pw_shield, + pw_carry, pw_tailsfly, // tails flying pw_underwater, // underwater timer pw_spacetime, // In space, no one can hear you spin! diff --git a/src/dehacked.c b/src/dehacked.c index a512e1029..b4cc8f519 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6750,21 +6750,9 @@ static const char *const PLAYERFLAG_LIST[] = { // Are you gliding? "GLIDING", - // Tails pickup! - "CARRIED", - // Sliding (usually in water) like Labyrinth/Oil Ocean "SLIDING", - // Hanging on a rope - "ROPEHANG", - - // Hanging on an item of some kind - zipline, chain, etc. (->tracer) - "ITEMHANG", - - // On the mace chain spinning around (->tracer) - "MACESPIN", - /*** NIGHTS STUFF ***/ // Is the player in NiGHTS mode? "NIGHTSMODE", @@ -6903,6 +6891,7 @@ static const char *const POWERS_LIST[] = { "SNEAKERS", "FLASHING", "SHIELD", + "CARRY", "TAILSFLY", // tails flying "UNDERWATER", // underwater timer "SPACETIME", // In space, no one can hear you spin! @@ -7138,6 +7127,14 @@ struct { {"SH_STACK",SH_STACK}, {"SH_NOSTACK",SH_NOSTACK}, + // Carrying + {"CR_NONE",CR_NONE}, + {"CR_GENERIC",CR_GENERIC}, + {"CR_PLAYER",CR_PLAYER}, + {"CR_ZOOMTUBE",CR_ZOOMTUBE}, + {"CR_ROPEHANG",CR_ROPEHANG}, + {"CR_MACESPIN",CR_MACESPIN}, + // Ring weapons (ringweapons_t) // Useful for A_GiveWeapon {"RW_AUTO",RW_AUTO}, diff --git a/src/p_enemy.c b/src/p_enemy.c index 3790633ea..73ec2a79d 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5428,8 +5428,8 @@ void A_MixUp(mobj_t *actor) // Zoom tube stuff mobj_t *tempthing = NULL; //tracer - pflags_t flags1,flags2; //player pflags - INT32 transspeed; //player speed + UINT16 carry1,carry2; //carry + INT32 transspeed; //player speed // Starpost stuff INT16 starpostx, starposty, starpostz; @@ -5466,8 +5466,8 @@ void A_MixUp(mobj_t *actor) players[two].speed = transspeed; //set flags variables now but DON'T set them. - flags1 = (players[one].pflags & (PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG)); - flags2 = (players[two].pflags & (PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG)); + carry1 = (players[one].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[one].powers[pw_carry]); + carry2 = (players[two].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[two].powers[pw_carry]); x = players[one].mo->x; y = players[one].mo->y; @@ -5492,12 +5492,10 @@ void A_MixUp(mobj_t *actor) starpostnum, starposttime, starpostangle, mflags2); - //flags set after mixup. Stupid P_ResetPlayer() takes away some of the flags we look for... - //but not all of them! So we need to make sure they aren't set wrong or anything. - players[one].pflags &= ~(PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG); - players[one].pflags |= flags2; - players[two].pflags &= ~(PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG); - players[two].pflags |= flags1; + //carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for... + //but not all of it! So we need to make sure they aren't set wrong or anything. + players[one].powers[pw_carry] = carry2; + players[two].powers[pw_carry] = carry1; teleported[one] = true; teleported[two] = true; @@ -5509,8 +5507,9 @@ void A_MixUp(mobj_t *actor) INT32 pindex[MAXPLAYERS], counter = 0, teleportfrom = 0; // Zoom tube stuff - mobj_t *transtracer[MAXPLAYERS]; //tracer - pflags_t transflag[MAXPLAYERS]; //player pflags + mobj_t *transtracer[MAXPLAYERS]; //tracer + //pflags_t transflag[MAXPLAYERS]; //cyan pink white pink cyan + UINT16 transcarry[MAXPLAYERS]; //player carry INT32 transspeed[MAXPLAYERS]; //player speed // Star post stuff @@ -5544,7 +5543,7 @@ void A_MixUp(mobj_t *actor) players[i].rmomx = players[i].rmomy = 1; players[i].cmomx = players[i].cmomy = 0; - transflag[counter] = (players[i].pflags & (PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG)); + transcarry[counter] = (players[i].powers[pw_carry] == CR_PLAYER ? CR_NONE : players[i].powers[pw_carry]); transspeed[counter] = players[i].speed; transtracer[counter] = players[i].mo->tracer; @@ -5596,9 +5595,8 @@ void A_MixUp(mobj_t *actor) starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom], flags2[teleportfrom]); - //...flags after. same reasoning. - players[i].pflags &= ~(PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG); - players[i].pflags |= transflag[teleportfrom]; + //...carry after. same reasoning. + players[i].powers[pw_carry] = transcarry[teleportfrom]; teleported[i] = true; counter++; @@ -6165,7 +6163,7 @@ void A_Boss7Chase(mobj_t *actor) if (actor->health <= actor->info->damage && actor->target && actor->target->player - && (actor->target->player->pflags & PF_ITEMHANG)) + && (actor->target->player->powers[pw_carry] == CR_GENERIC)) { A_FaceTarget(actor); P_SetMobjState(actor, S_BLACKEGG_SHOOT1); diff --git a/src/p_inter.c b/src/p_inter.c index 936747ce6..4349be579 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1249,10 +1249,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->powers[pw_ingoop] = 2; - if (player->pflags & PF_ITEMHANG) + if (player->powers[pw_carry] == CR_GENERIC) { P_SetTarget(&toucher->tracer, NULL); - player->pflags &= ~PF_ITEMHANG; + player->powers[pw_carry] = CR_NONE; } P_ResetPlayer(player); @@ -1337,7 +1337,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_BIGMACECHAIN: // Is this the last link in the chain? if (toucher->momz > 0 || !(special->flags & MF_AMBUSH) - || (player->pflags & PF_ITEMHANG) || (player->pflags & PF_MACESPIN)) + || (player->powers[pw_carry])) return; if (toucher->z > special->z + special->height/2) @@ -1354,12 +1354,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->target && (special->target->type == MT_SPINMACEPOINT || special->target->type == MT_HIDDEN_SLING)) { - player->pflags |= PF_MACESPIN; + player->powers[pw_carry] = CR_MACESPIN; S_StartSound(toucher, sfx_spin); P_SetPlayerMobjState(toucher, S_PLAY_SPIN); } else - player->pflags |= PF_ITEMHANG; + player->powers[pw_carry] = CR_GENERIC; // Can't jump first frame player->pflags |= PF_JUMPSTASIS; @@ -2623,7 +2623,9 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) { - player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE); + player->pflags &= ~(PF_SLIDING|PF_NIGHTSMODE); + + player->powers[pw_carry] = CR_NONE; // Burst weapons and emeralds in Match/CTF only if (source && (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF)) diff --git a/src/p_map.c b/src/p_map.c index 6d4acf1a2..92ed14f57 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -302,9 +302,9 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) INT32 p; fixed_t zdist; // z distance between the two players' bottoms - if ((tails->pflags & PF_CARRIED) && tails->mo->tracer == sonic->mo) + if (tails->powers[pw_carry] == CR_PLAYER)// && tails->mo->tracer == sonic->mo) <-- why was this here? return; - if ((sonic->pflags & PF_CARRIED) && sonic->mo->tracer == tails->mo) + if (sonic->powers[pw_carry] == CR_PLAYER && sonic->mo->tracer == tails->mo) return; if (tails->charability != CA_FLY && tails->charability != CA_SWIM) @@ -319,8 +319,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) if (sonic->pflags & PF_NIGHTSMODE) return; - if (sonic->mo->tracer && sonic->mo->tracer->type == MT_TUBEWAYPOINT - && !(sonic->pflags & PF_ROPEHANG)) + if (sonic->mo->tracer && sonic->powers[pw_carry] == CR_ZOOMTUBE) return; // don't steal players from zoomtubes! if ((sonic->mo->eflags & MFE_VERTICALFLIP) != (tails->mo->eflags & MFE_VERTICALFLIP)) @@ -337,7 +336,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) // Search in case another player is already being carried by this fox. for (p = 0; p < MAXPLAYERS; p++) if (playeringame[p] && players[p].mo - && players[p].pflags & PF_CARRIED && players[p].mo->tracer == tails->mo) + && players[p].powers[pw_carry] == CR_PLAYER && players[p].mo->tracer == tails->mo) return; if (tails->mo->eflags & MFE_VERTICALFLIP) @@ -357,16 +356,16 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) || (G_TagGametype() && (!(tails->pflags & PF_TAGIT) != !(sonic->pflags & PF_TAGIT))) || (gametype == GT_MATCH) || (G_GametypeHasTeams() && tails->ctfteam != sonic->ctfteam)) - sonic->pflags &= ~PF_CARRIED; */ + sonic->powers[pw_carry] = CR_NONE; */ if (tails->spectator || sonic->spectator) - sonic->pflags &= ~PF_CARRIED; + sonic->powers[pw_carry] = CR_NONE; else { if (sonic-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, false); P_ResetPlayer(sonic); P_SetTarget(&sonic->mo->tracer, tails->mo); - sonic->pflags |= PF_CARRIED; + sonic->powers[pw_carry] = CR_PLAYER; S_StartSound(sonic->mo, sfx_s3k4a); P_UnsetThingPosition(sonic->mo); sonic->mo->x = tails->mo->x; @@ -377,199 +376,10 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) else { if (sonic-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, true); - sonic->pflags &= ~PF_CARRIED; + sonic->powers[pw_carry] = CR_NONE; } } -// -// 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 // @@ -858,7 +668,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->flags & MF_MISSILE && thing->player && tmthing->target && tmthing->target->player && thing->player->ctfteam == tmthing->target->player->ctfteam - && thing->player->pflags & PF_CARRIED && thing->tracer == tmthing->target) + && thing->player->powers[pw_carry] == CR_PLAYER && thing->tracer == tmthing->target) return true; // Don't give rings to your carry player by accident. if (thing->type == MT_EGGSHIELD) @@ -901,7 +711,7 @@ static boolean PIT_CheckThing(mobj_t *thing) && tmthing->target != thing) { // Hop on the missile for a ride! - thing->player->pflags |= PF_ITEMHANG; + thing->player->powers[pw_carry] = CR_GENERIC; thing->player->pflags &= ~PF_JUMPED; P_SetTarget(&thing->tracer, tmthing); P_SetTarget(&tmthing->target, thing); // Set owner to the player @@ -920,7 +730,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player && ((thing->player->pflags & PF_ITEMHANG) || (thing->player->pflags & PF_JUMPED))) + else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player && ((thing->player->powers[pw_carry] == CR_GENERIC) || (thing->player->pflags & PF_JUMPED))) { // Ignore } @@ -1121,7 +931,8 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (thing->player) { if (thing->player-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, true); - thing->player->pflags &= ~PF_CARRIED; + if (thing->player->powers[pw_carry] == CR_PLAYER) + thing->player->powers[pw_carry] = CR_NONE; } if (thing->player) @@ -1199,8 +1010,99 @@ 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 } - else - return P_ConsiderSolids(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 + 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 + } + } + } // not solid not blocked return true; diff --git a/src/p_mobj.c b/src/p_mobj.c index 7d9c32451..c156581c0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3998,20 +3998,23 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN; // Zoom tube - if (mobj->tracer && mobj->tracer->type == MT_TUBEWAYPOINT) + if (mobj->tracer) { - P_UnsetThingPosition(mobj); - mobj->x += mobj->momx; - mobj->y += mobj->momy; - mobj->z += mobj->momz; - P_SetThingPosition(mobj); - P_CheckPosition(mobj, mobj->x, mobj->y); - goto animonly; - } - else if (mobj->player->pflags & PF_MACESPIN && mobj->tracer) - { - P_CheckPosition(mobj, mobj->x, mobj->y); - goto animonly; + if (mobj->player->powers[pw_carry] == CR_ZOOMTUBE) + { + P_UnsetThingPosition(mobj); + mobj->x += mobj->momx; + mobj->y += mobj->momy; + mobj->z += mobj->momz; + P_SetThingPosition(mobj); + P_CheckPosition(mobj, mobj->x, mobj->y); + goto animonly; + } + else if (mobj->player->powers[pw_carry] == CR_MACESPIN) + { + P_CheckPosition(mobj, mobj->x, mobj->y); + goto animonly; + } } // Needed for gravity boots diff --git a/src/p_spec.c b/src/p_spec.c index a3d6cecfa..ed8a12a5d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3889,7 +3889,7 @@ DoneSection2: mobj_t *mo2; angle_t an; - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) break; // Find line #3 tagged to this sector @@ -3938,6 +3938,7 @@ DoneSection2: break; // behind back P_SetTarget(&player->mo->tracer, waypoint); + player->powers[pw_carry] = CR_ZOOMTUBE; player->speed = speed; player->pflags |= PF_SPINNING; player->pflags &= ~PF_JUMPED; @@ -3962,7 +3963,7 @@ DoneSection2: mobj_t *mo2; angle_t an; - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) break; // Find line #3 tagged to this sector @@ -4012,6 +4013,7 @@ DoneSection2: break; // behind back P_SetTarget(&player->mo->tracer, waypoint); + player->powers[pw_carry] = CR_ZOOMTUBE; player->speed = speed; player->pflags |= PF_SPINNING; player->pflags &= ~PF_JUMPED; @@ -4084,7 +4086,7 @@ DoneSection2: vertex_t v1, v2, resulthigh, resultlow; mobj_t *highest = NULL; - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) break; if (player->mo->momz > 0) @@ -4305,6 +4307,7 @@ DoneSection2: } P_SetTarget(&player->mo->tracer, closest); + player->powers[pw_carry] = CR_ROPEHANG; // Option for static ropes. if (lines[lineindex].flags & ML_NOCLIMB) @@ -4312,7 +4315,7 @@ DoneSection2: else player->speed = speed; - player->pflags |= PF_ROPEHANG; + player->powers[pw_carry] = CR_ROPEHANG; S_StartSound(player->mo, sfx_s3k4a); @@ -7165,7 +7168,7 @@ static inline boolean PIT_PushThing(mobj_t *thing) if (thing->eflags & MFE_PUSHED) return false; - if (thing->player && thing->player->pflags & PF_ROPEHANG) + if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) return false; // Allow this to affect pushable objects at some point? @@ -7398,7 +7401,7 @@ void T_Pusher(pusher_t *p) if (thing->eflags & MFE_PUSHED) continue; - if (thing->player && thing->player->pflags & PF_ROPEHANG) + if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) continue; if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics)) diff --git a/src/p_telept.c b/src/p_telept.c index 4921040b4..671accb0f 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -160,9 +160,9 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle INT32 p; // Search for any players you might be carrying, so you can get them off before they end up being taken with you! for (p = 0; p < MAXPLAYERS; p++) - if (playeringame[p] && players[p].mo && players[p].pflags & PF_CARRIED && players[p].mo->tracer == thing) + if (playeringame[p] && players[p].mo && players[p].powers[pw_carry] == CR_PLAYER && players[p].mo->tracer == thing) { - players[p].pflags &= ~PF_CARRIED; + players[p].powers[pw_carry] = CR_NONE; break; } thing->player->cmomx = thing->player->cmomy = 0; diff --git a/src/p_user.c b/src/p_user.c index f6e9270ec..4f8a96de0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -873,7 +873,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) P_InstaThrust(player->mo, ang, fallbackspeed); - if (player->pflags & PF_ROPEHANG) + if (player->powers[pw_carry] == CR_ROPEHANG) P_SetTarget(&player->mo->tracer, NULL); // Point penalty for hitting a hazard during tag. @@ -900,7 +900,8 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) // Useful when you want to kill everything the player is doing. void P_ResetPlayer(player_t *player) { - player->pflags &= ~(PF_ROPEHANG|PF_ITEMHANG|PF_MACESPIN|PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_GLIDING|PF_THOKKED|PF_CARRIED); + player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_GLIDING|PF_THOKKED); + player->powers[pw_carry] = CR_NONE; player->jumping = 0; player->secondjump = 0; player->glidetime = 0; @@ -3415,7 +3416,7 @@ static void P_DoSuperStuff(player_t *player) ? (SKINCOLOR_SUPERSILVER1 + 5*((leveltime >> 1) % 7)) // A wholesome easter egg. : skins[player->skin].supercolor + (unsigned)abs( ( (signed)(leveltime >> 1) % 9) - 4); // This is where super flashing is handled. - if ((cmd->forwardmove != 0 || cmd->sidemove != 0 || player->pflags & (PF_CARRIED|PF_ROPEHANG|PF_ITEMHANG|PF_MACESPIN)) + if ((cmd->forwardmove != 0 || cmd->sidemove != 0 || player->powers[pw_carry]) && !(leveltime % TICRATE) && (player->mo->momx || player->mo->momy)) { spark = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SUPERSPARK); @@ -3583,22 +3584,22 @@ void P_DoJump(player_t *player, boolean soundandstate) return; // Jump this high. - if (player->pflags & PF_CARRIED) + if (player->powers[pw_carry] == CR_PLAYER) { player->mo->momz = 9*FRACUNIT; - player->pflags &= ~PF_CARRIED; + player->powers[pw_carry] = CR_NONE; if (player-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, true); } - else if (player->pflags & PF_ITEMHANG) + else if (player->powers[pw_carry] == CR_GENERIC) { player->mo->momz = 9*FRACUNIT; - player->pflags &= ~PF_ITEMHANG; + player->powers[pw_carry] = CR_NONE; } - else if (player->pflags & PF_ROPEHANG) + else if (player->powers[pw_carry] == CR_ROPEHANG) { player->mo->momz = 12*FRACUNIT; - player->pflags &= ~PF_ROPEHANG; + player->powers[pw_carry] = CR_NONE; P_SetTarget(&player->mo->tracer, NULL); } else if (player->mo->eflags & MFE_GOOWATER) @@ -3935,9 +3936,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_USE && !(player->pflags & PF_JUMPDOWN) && !player->exiting && !P_PlayerInPain(player)) { - if (onground || player->climbing || player->pflags & (PF_CARRIED|PF_ITEMHANG|PF_ROPEHANG)) + if (player->mo->tracer && player->powers[pw_carry] == CR_MACESPIN) {} - else if (player->pflags & PF_MACESPIN && player->mo->tracer) + else if (onground || player->climbing || (player->mo->tracer && player->powers[pw_carry])) {} else if (!(player->pflags & PF_SLIDING) && ((gametype != GT_CTF) || (!player->gotflag))) { @@ -4010,19 +4011,19 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->secondjump = 0; player->pflags &= ~PF_THOKKED; } + else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer) + { + player->powers[pw_carry] = CR_NONE; + player->powers[pw_flashing] = TICRATE/4; + } else // can't jump while in air, can't jump while jumping - if (onground || player->climbing || player->pflags & (PF_CARRIED|PF_ITEMHANG|PF_ROPEHANG)) + if (onground || player->climbing || player->powers[pw_carry]) { P_DoJump(player, true); player->secondjump = 0; player->pflags &= ~PF_THOKKED; } - else if (player->pflags & PF_MACESPIN && player->mo->tracer) - { - player->pflags &= ~PF_MACESPIN; - player->powers[pw_flashing] = TICRATE/4; - } else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag)) ; else if (P_SuperReady(player)) @@ -6973,7 +6974,7 @@ static void P_MovePlayer(player_t *player) // Check for teeter! if (!(player->mo->momz || player->mo->momx || player->mo->momy) && !(player->mo->eflags & MFE_GOOWATER) - && player->panim == PA_IDLE && !(player->pflags & (PF_CARRIED|PF_ITEMHANG|PF_ROPEHANG))) + && player->panim == PA_IDLE && !(player->powers[pw_carry])) P_DoTeeter(player); // Toss a flag @@ -7244,6 +7245,7 @@ static void P_DoZoomTube(player_t *player) else { P_SetTarget(&player->mo->tracer, NULL); // Else, we just let him fly. + player->powers[pw_carry] = CR_NONE; CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, releasing from track...\n"); } @@ -7291,7 +7293,7 @@ static void P_DoRopeHang(player_t *player) P_SetTarget(&player->mo->tracer, NULL); player->pflags |= PF_JUMPED; - player->pflags &= ~PF_ROPEHANG; + player->powers[pw_carry] = CR_NONE; if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED) && !(player->panim == PA_JUMP)) @@ -7309,6 +7311,10 @@ static void P_DoRopeHang(player_t *player) sequence = player->mo->tracer->threshold; + // If not allowed to move, we're done here. + if (!speed) + return; + // change slope dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - playerz); @@ -7319,22 +7325,28 @@ static void P_DoRopeHang(player_t *player) speedy = FixedMul(FixedDiv(player->mo->tracer->y - player->mo->y, dist), (speed)); speedz = FixedMul(FixedDiv(player->mo->tracer->z - playerz, dist), (speed)); - // If not allowed to move, we're done here. - if (!speed) - return; - // Calculate the distance between the player and the waypoint // 'dist' already equals this. - // Will the player be FURTHER away if the momx/momy/momz is added to - // his current coordinates, or closer? (shift down to fracunits to avoid approximation errors) - if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x - speedx, player->mo->tracer->y - player->mo->y - speedy), player->mo->tracer->z - playerz - speedz)>>FRACBITS) + // Will the player go past the waypoint? + if ( + ((speedx || speedy) + && (R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y) + - R_PointToAngle2(player->mo->x + speedx, player->mo->y + speedy, player->mo->tracer->x, player->mo->tracer->y)) > ANG1) + || ((speedz) + && ((playerz - player->mo->tracer->z) > 0) != ((playerz + speedz - player->mo->tracer->z) > 0)) + ) { + if (speed > dist) + speed -= dist; + else + speed = 0; // If further away, set XYZ of player to waypoint location P_UnsetThingPosition(player->mo); player->mo->x = player->mo->tracer->x; player->mo->y = player->mo->tracer->y; player->mo->z = player->mo->tracer->z - player->mo->height; + playerz = player->mo->tracer->z; P_SetThingPosition(player->mo); CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); @@ -7390,6 +7402,8 @@ static void P_DoRopeHang(player_t *player) { CONS_Debug(DBG_GAMELOGIC, "Found waypoint (sequence %d, number %d).\n", waypoint->threshold, waypoint->health); + P_SetTarget(&player->mo->tracer, waypoint); + // calculate MOMX/MOMY/MOMZ for next waypoint // change slope dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - playerz); @@ -7400,15 +7414,12 @@ static void P_DoRopeHang(player_t *player) player->mo->momx = FixedMul(FixedDiv(player->mo->tracer->x - player->mo->x, dist), (speed)); player->mo->momy = FixedMul(FixedDiv(player->mo->tracer->y - player->mo->y, dist), (speed)); player->mo->momz = FixedMul(FixedDiv(player->mo->tracer->z - playerz, dist), (speed)); - - P_SetTarget(&player->mo->tracer, waypoint); } else { if (player->mo->tracer->flags & MF_SLIDEME) { player->pflags |= PF_JUMPED; - player->pflags &= ~PF_ROPEHANG; if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED) && !(player->panim == PA_JUMP)) @@ -7416,6 +7427,7 @@ static void P_DoRopeHang(player_t *player) } P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_carry] = CR_NONE; CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found!\n"); } @@ -8109,7 +8121,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { dist = camdist; - if (player->climbing || player->exiting || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG))) + if (player->climbing || player->exiting || player->playerstate == PST_DEAD || (player->powers[pw_carry] && player->powers[pw_carry] != CR_PLAYER)) dist <<= 1; } @@ -8979,9 +8991,9 @@ void P_PlayerThink(player_t *player) // for a bit after a teleport. if (player->mo->reactiontime) player->mo->reactiontime--; - else if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) + else if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && (player->powers[pw_carry] == CR_ROPEHANG || player->powers[pw_carry] == CR_ZOOMTUBE)) { - if (player->pflags & PF_ROPEHANG) + if (player->powers[pw_carry] == CR_ROPEHANG) { if (!P_AnalogMove(player)) player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */); @@ -8994,7 +9006,7 @@ void P_PlayerThink(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); P_DoJumpStuff(player, &player->cmd); } - else + else if (player->powers[pw_carry] == CR_ZOOMTUBE) { P_DoZoomTube(player); if (!(player->panim == PA_ROLL)) @@ -9406,14 +9418,14 @@ void P_PlayerAfterThink(player_t *player) && !(player->charflags & SF_NOJUMPSPIN)) P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); - if (player->pflags & PF_CARRIED && player->mo->tracer) + if (player->powers[pw_carry] == CR_PLAYER && player->mo->tracer) { player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14*FRACUNIT,10*FRACUNIT)); if (player->mo->tracer->player && !player->mo->tracer->player->powers[pw_tailsfly] && player->mo->tracer->state-states != S_PLAY_FLY_TIRED) - player->pflags &= ~PF_CARRIED; + player->powers[pw_carry] = CR_NONE; if (player->mo->eflags & MFE_VERTICALFLIP) { @@ -9421,7 +9433,7 @@ void P_PlayerAfterThink(player_t *player) && (player->mo->tracer->eflags & MFE_VERTICALFLIP)) // Reverse gravity check for the carrier - Flame player->mo->z = player->mo->tracer->z + player->mo->tracer->height + FixedMul(FRACUNIT, player->mo->scale); else - player->pflags &= ~PF_CARRIED; + player->powers[pw_carry] = CR_NONE; } else { @@ -9429,11 +9441,11 @@ void P_PlayerAfterThink(player_t *player) && !(player->mo->tracer->eflags & MFE_VERTICALFLIP)) // Correct gravity check for the carrier - Flame player->mo->z = player->mo->tracer->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale); else - player->pflags &= ~PF_CARRIED; + player->powers[pw_carry] = CR_NONE; } if (player->mo->tracer->health <= 0) - player->pflags &= ~PF_CARRIED; + player->powers[pw_carry] = CR_NONE; else { P_TryMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, true); @@ -9456,14 +9468,14 @@ void P_PlayerAfterThink(player_t *player) } if (P_AproxDistance(player->mo->x - player->mo->tracer->x, player->mo->y - player->mo->tracer->y) > player->mo->radius) - player->pflags &= ~PF_CARRIED; + player->powers[pw_carry] = CR_NONE; P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); if (player-players == consoleplayer && botingame) - CV_SetValue(&cv_analog2, !(player->pflags & PF_CARRIED)); + CV_SetValue(&cv_analog2, (player->powers[pw_carry] != CR_PLAYER)); } - else if (player->pflags & PF_ITEMHANG && player->mo->tracer) + else if (player->powers[pw_carry] == CR_GENERIC && player->mo->tracer) { // tracer is what you're hanging onto P_UnsetThingPosition(player->mo); @@ -9491,12 +9503,12 @@ void P_PlayerAfterThink(player_t *player) if (player->mo->z <= player->mo->floorz || player->mo->tracer->health <= 0) { - player->pflags &= ~PF_ITEMHANG; + player->powers[pw_carry] = CR_NONE; P_SetTarget(&player->mo->tracer, NULL); } } } - else if (player->pflags & PF_MACESPIN && player->mo->tracer && player->mo->tracer->target) + else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer && player->mo->tracer->target) { player->mo->height = P_GetPlayerSpinHeight(player); // tracer is what you're hanging onto....