diff --git a/src/objects/shrink.c b/src/objects/shrink.c index 7df715982..ab2cba295 100644 --- a/src/objects/shrink.c +++ b/src/objects/shrink.c @@ -24,17 +24,6 @@ #include "../k_waypoint.h" #include "../music.h" -// -// ███████╗██╗██╗░░██╗███╗░░░███╗███████╗ -// ██╔════╝██║╚██╗██╔╝████╗░████║██╔════╝ -// █████╗░░██║░╚███╔╝░██╔████╔██║█████╗░░ -// ██╔══╝░░██║░██╔██╗░██║╚██╔╝██║██╔══╝░░ -// ██║░░░░░██║██╔╝╚██╗██║░╚═╝░██║███████╗ -// ╚═╝░░░░░╚═╝╚═╝░░╚═╝╚═╝░░░░░╚═╝╚══════╝ -// -// FIXME (because it was completely unsearchable): vertical flip -// - #define POHBEE_HOVER (128 << FRACBITS) #define POHBEE_SPEED (128 << FRACBITS) #define POHBEE_TIME (30 * TICRATE) @@ -135,7 +124,7 @@ static fixed_t GenericDistance( static fixed_t PohbeeWaypointZ(mobj_t *pohbee, mobj_t *dest) { - return dest->z + (pohbee_height(pohbee) + FixedMul(POHBEE_HOVER, mapobjectscale) * P_MobjFlip(dest)); + return dest->z + (pohbee_height(pohbee) + FixedMul(POHBEE_HOVER, mapobjectscale)) * P_MobjFlip(dest); } static void PohbeeSpawn(mobj_t *pohbee) @@ -303,6 +292,13 @@ static void DoGunSwing(mobj_t *gun, mobj_t *pohbee) dist, FINESINE(pitch >> ANGLETOFINESHIFT) ); + // When in reverse gravity, flip the z offset and make up the difference in height between the Poh-Bee and its gun. + if (P_IsObjectFlipped(gun)) + { + offsetZ *= -1; + offsetZ += pohbee->height - gun->height; + } + PohbeeMoveTo(gun, pohbee->x + offsetX, pohbee->y + offsetY, pohbee->z + offsetZ); } @@ -311,8 +307,21 @@ static void ShrinkLaserThinker(mobj_t *pohbee, mobj_t *gun, mobj_t *laser) const fixed_t gunX = gun->x + gun->momx; const fixed_t gunY = gun->y + gun->momy; const fixed_t gunZ = P_GetMobjFeet(gun) + gun->momz; + fixed_t groundZ, spriteHeight; - PohbeeMoveTo(laser, gunX, gunY, gun->floorz); + // Target the ceiling in reverse gravity, otherwise target the floor. + if (P_IsObjectFlipped(laser)) + { + groundZ = gun->ceilingz - laser->height; + spriteHeight = gun->ceilingz - gunZ; + } + else + { + groundZ = gun->floorz; + spriteHeight = gunZ - gun->floorz; + } + + PohbeeMoveTo(laser, gunX, gunY, groundZ); if (ShrinkLaserActive(pohbee) == true) { @@ -330,7 +339,7 @@ static void ShrinkLaserThinker(mobj_t *pohbee, mobj_t *gun, mobj_t *laser) laser->spritexscale = FRACUNIT; } - laser->spriteyscale = FixedDiv(FixedDiv(gunZ - gun->floorz, mapobjectscale), laser->info->height); + laser->spriteyscale = FixedDiv(FixedDiv(spriteHeight, mapobjectscale), laser->info->height); particle = P_SpawnMobjFromMobj(laser, 0, 0, 0, MT_SHRINK_PARTICLE); @@ -383,6 +392,13 @@ static void DoGunChains(mobj_t *gun, mobj_t *pohbee) fixed_t curY = gunY + (offsetY / 2); fixed_t curZ = gunZ + (offsetZ / 2); + // The starting z coordinate is the bottom of the chain at the top of the gun. + // In reverse gravity, offset the z coordinate by the height of a chain, so that it's the top of the chain at the bottom of the gun. + if (P_IsObjectFlipped(gun)) + { + curZ -= FixedMul(gun->scale, mobjinfo[MT_SHRINK_CHAIN].height); + } + chain = gun_chains(gun); while (chain != NULL && P_MobjWasRemoved(chain) == false) { @@ -692,6 +708,18 @@ static void CreatePohbee(player_t *owner, waypoint_t *start, waypoint_t *end, UI pohbee = P_SpawnMobjFromMobj(start->mobj, 0, 0, (baseSegs * CHAIN_SIZE * FRACUNIT) + POHBEE_HOVER * 3, MT_SHRINK_POHBEE); pohbee_owner(pohbee) = owner - players; + // Flip the Poh-Bee if its target waypoint is flipped. + const boolean waypointflipped = P_IsObjectFlipped(end->mobj); + if (waypointflipped != P_IsObjectFlipped(pohbee)) + { + pohbee->flags2 ^= MF2_OBJECTFLIP; + pohbee->eflags ^= MFE_VERTICALFLIP; + } + if (waypointflipped) // now equivalent to P_IsObjectFlipped(pohbee) + { + size += pohbee->height - end->mobj->height; + } + pohbee_mode(pohbee) = POHBEE_MODE_SPAWN; pohbee_timer(pohbee) = POHBEE_TIME; pohbee_height(pohbee) = size; diff --git a/src/p_local.h b/src/p_local.h index 7545c88d9..d0805b6ad 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -594,6 +594,7 @@ fixed_t P_GetMobjHead(const mobj_t *); fixed_t P_GetMobjFeet(const mobj_t *); fixed_t P_GetMobjGround(const mobj_t *); fixed_t P_GetMobjZMovement(mobj_t *mo); +boolean P_MobjCanChangeFlip(mobj_t *mobj); void P_InitTIDHash(void); void P_SetThingTID(mobj_t *mo, mtag_t tid); diff --git a/src/p_mobj.c b/src/p_mobj.c index 732dabcf5..a2aa2f977 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1116,7 +1116,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) gravityadd = -FixedMul(gravity, gravfactor); - if ((rover->master->frontsector->flags & MSF_GRAVITYFLIP) && gravityadd > 0) + if ((rover->master->frontsector->flags & MSF_GRAVITYFLIP) && gravityadd > 0 && P_MobjCanChangeFlip(mo)) mo->eflags |= MFE_VERTICALFLIP; no3dfloorgrav = false; @@ -1128,7 +1128,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) { gravityadd = -FixedMul(gravity, P_GetSectorGravityFactor(mo->subsector->sector)); - if ((mo->subsector->sector->flags & MSF_GRAVITYFLIP) && gravityadd > 0) + if ((mo->subsector->sector->flags & MSF_GRAVITYFLIP) && gravityadd > 0 && P_MobjCanChangeFlip(mo)) mo->eflags |= MFE_VERTICALFLIP; } @@ -14980,6 +14980,25 @@ fixed_t P_GetMobjZMovement(mobj_t *mo) return P_ReturnThrustY(mo, slope->zangle, P_ReturnThrustX(mo, angDiff, speed)); } +// Returns whether this mobj is affected by gravflip sector effects. +boolean P_MobjCanChangeFlip(mobj_t *mobj) +{ + switch (mobj->type) + { + case MT_SHRINK_POHBEE: + case MT_SHRINK_GUN: + case MT_SHRINK_CHAIN: + case MT_SHRINK_LASER: + case MT_SHRINK_PARTICLE: + return false; + + default: + break; + } + + return true; +} + // // Thing IDs / tags // diff --git a/src/p_spec.c b/src/p_spec.c index 774811b99..68356d7ca 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3293,7 +3293,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha break; case 433: // Flip/flop gravity. Works on pushables, too! - if (!mo) + if (!mo || !P_MobjCanChangeFlip(mo)) return false; if (args[0])