diff --git a/src/d_player.h b/src/d_player.h index 77ad34dab..a7b19439d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -181,25 +181,35 @@ typedef enum typedef enum { SH_NONE = 0, - // Standard shields + + // Shield flags + SH_PROTECTFIRE = 0x400, + SH_PROTECTWATER = 0x800, + SH_PROTECTELECTRICITY = 0x1000, + + // Indivisible shields + SH_PITY = 1, SH_JUMP, - SH_ATTRACT, - SH_ELEMENTAL, SH_BOMB, - // Pity shield: the world's most basic shield ever, given to players who suck at Match - SH_PITY, - // Sonic 3 shields - SH_FLAMEAURA, - SH_BUBBLEWRAP, - SH_THUNDERCOIN, - // The fireflower used to be stackable with other shields. Not anymore. SH_FIREFLOWER, + + // normal shields that use flags + SH_ATTRACT = SH_PROTECTELECTRICITY, + SH_ELEMENTAL = SH_PROTECTFIRE|SH_PROTECTWATER, + + // Sonic 3 shields + SH_FLAMEAURA = SH_PROTECTFIRE, + SH_BUBBLEWRAP = SH_PROTECTWATER, + SH_THUNDERCOIN = SH_JUMP|SH_PROTECTELECTRICITY, + // The force shield uses the lower 8 bits to count how many extra hits are left. SH_FORCE = 0x100, SH_FORCEHP = 0xFF, // to be used as a bitmask only - // The mushroom CAN stack with other shields. + + // Mostly for use with Mario mode. SH_MUSHROOM = 0x200, - SH_STACK = SH_MUSHROOM, //|SH_FIREFLOWER, + + SH_STACK = SH_MUSHROOM, // second-layer shields SH_NOSTACK = ~SH_STACK } shieldtype_t; // pw_shield diff --git a/src/dehacked.c b/src/dehacked.c index bd3f8455f..20dce51d4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7174,21 +7174,28 @@ struct { {"PRECIP_STORM_NOSTRIKES",PRECIP_STORM_NOSTRIKES}, // Shields - // These ones use the lower 8 bits {"SH_NONE",SH_NONE}, + // Shield flags + {"SH_PROTECTFIRE",SH_PROTECTFIRE}, + {"SH_PROTECTWATER",SH_PROTECTWATER}, + {"SH_PROTECTELECTRICITY",SH_PROTECTELECTRICITY}, + // Indivisible shields + {"SH_PITY",SH_PITY}, {"SH_JUMP",SH_JUMP}, + {"SH_BOMB",SH_BOMB}, + {"SH_FIREFLOWER",SH_FIREFLOWER}, + // normal shields that use flags {"SH_ATTRACT",SH_ATTRACT}, {"SH_ELEMENTAL",SH_ELEMENTAL}, - {"SH_BOMB",SH_BOMB}, + // Sonic 3 shields + {"SH_FLAMEAURA",SH_FLAMEAURA}, {"SH_BUBBLEWRAP",SH_BUBBLEWRAP}, {"SH_THUNDERCOIN",SH_THUNDERCOIN}, - {"SH_FLAMEAURA",SH_FLAMEAURA}, - {"SH_PITY",SH_PITY}, - {"SH_FIREFLOWER",SH_FIREFLOWER}, - // These ones are special and use the upper bits - {"SH_FORCE",SH_FORCE}, // Lower bits are how many hits left, 0 is the last hit - {"SH_MUSHROOM", SH_MUSHROOM}, // Can stack with other shields - // Stack masks + // The force shield uses the lower 8 bits to count how many extra hits are left. + {"SH_FORCE",SH_FORCE}, + {"SH_FORCEHP",SH_FORCEHP}, // to be used as a bitmask only + // Mostly for use with Mario mode. + {"SH_MUSHROOM", SH_MUSHROOM}, {"SH_STACK",SH_STACK}, {"SH_NOSTACK",SH_NOSTACK}, diff --git a/src/p_enemy.c b/src/p_enemy.c index 7ef87ac44..6345a89c4 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -741,7 +741,7 @@ static boolean P_LookForShield(mobj_t *actor) (actor->type == MT_BLUETEAMRING && player->ctfteam != 2)) continue; - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT + if ((player->powers[pw_shield] & SH_PROTECTELECTRICITY) && (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST, player->mo->scale))) { P_SetTarget(&actor->tracer, player->mo); @@ -3817,7 +3817,7 @@ void A_AttractChase(mobj_t *actor) // Turn flingrings back into regular rings if attracted. if (actor->tracer && actor->tracer->player - && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) + && !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRICITY) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) { mobj_t *newring; newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); @@ -4022,7 +4022,7 @@ void A_ThrownRing(mobj_t *actor) // A non-homing ring getting attracted by a // magnetic player. If he gets too far away, make // sure to stop the attraction! - if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT + if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRICITY) && P_AproxDistance(P_AproxDistance(actor->tracer->x-actor->x, actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST/4, actor->tracer->scale))) { @@ -4030,7 +4030,7 @@ void A_ThrownRing(mobj_t *actor) } if (actor->tracer && (actor->tracer->health) - && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)// Already found someone to follow. + && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRICITY))// Already found someone to follow. { const INT32 temp = actor->threshold; actor->threshold = 32000; @@ -4098,7 +4098,7 @@ void A_ThrownRing(mobj_t *actor) if (!P_CheckSight(actor, player->mo)) continue; // out of sight - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT + if ((player->powers[pw_shield] & SH_PROTECTELECTRICITY) && dist < FixedMul(RING_DIST/4, player->mo->scale)) P_SetTarget(&actor->tracer, player->mo); return; diff --git a/src/p_inter.c b/src/p_inter.c index 0b2262ab7..c5938c90e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1459,7 +1459,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_EXTRALARGEBUBBLE: - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) + if (player->powers[pw_shield] & SH_PROTECTWATER) return; if (maptol & TOL_NIGHTS) return; @@ -3022,28 +3022,23 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && (maptol & TOL_NIGHTS)) return false; -#define shieldtype (player->powers[pw_shield] & SH_NOSTACK) switch (damagetype) { case DMG_WATER: - if (shieldtype == SH_BUBBLEWRAP - || shieldtype == SH_ELEMENTAL) + if (player->powers[pw_shield] & SH_PROTECTWATER) return false; // Invincible to water damage break; case DMG_FIRE: - if (shieldtype == SH_FLAMEAURA - || shieldtype == SH_ELEMENTAL) + if (player->powers[pw_shield] & SH_PROTECTFIRE) return false; // Invincible to fire damage break; case DMG_ELECTRIC: - if (shieldtype == SH_ATTRACT - || shieldtype == SH_THUNDERCOIN) + if (player->powers[pw_shield] & SH_PROTECTELECTRICITY) return false; // Invincible to electric damage break; default: break; } -#undef shieldtype } if (player->pflags & PF_NIGHTSMODE) // NiGHTS damage handling @@ -3067,7 +3062,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!force && inflictor && inflictor->flags & MF_FIRE) { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) + if (player->powers[pw_shield] & SH_PROTECTFIRE) return false; // Invincible to fire objects if (G_PlatformGametype() && inflictor && source && source->player) diff --git a/src/p_mobj.c b/src/p_mobj.c index 2cd6b7d77..d87e3cc20 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3619,15 +3619,20 @@ void P_MobjCheckWater(mobj_t *mobj) { if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability]))) { - if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) - { // Water removes attract shield. + if (p->powers[pw_shield] & SH_PROTECTELECTRICITY) + { // Water removes electric shields... p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK; P_FlashPal(p, PAL_WHITE, 1); } + else if ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER)) + { // ...and fire-only shields. + p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK; + P_FlashPal(p, PAL_NUKE, 1); + } } // Drown timer setting - if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL // Has elemental + if ((p->powers[pw_shield] & SH_PROTECTWATER) // Has water protection || (p->exiting) // Or exiting || (maptol & TOL_NIGHTS) // Or in NiGHTS mode || (mariomode)) // Or in Mario mode... diff --git a/src/p_spec.c b/src/p_spec.c index ed2ff055c..0119664aa 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3562,7 +3562,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_PlayerFlagBurst(player, false); break; case 12: // Space Countdown - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL && !player->powers[pw_spacetime]) + if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime]) player->powers[pw_spacetime] = spacetimetics + 1; break; case 13: // Ramp Sector (Increase step-up/down) diff --git a/src/p_user.c b/src/p_user.c index df28806b6..8ceef8d6e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2229,7 +2229,7 @@ static void P_DoBubbleBreath(player_t *player) fixed_t z = player->mo->z; mobj_t *bubble = NULL; - if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && !(player->pflags & PF_NIGHTSMODE)) || player->spectator) + if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_PROTECTWATER) && !(player->pflags & PF_NIGHTSMODE)) || player->spectator) return; if (player->charflags & SF_MACHINE) @@ -9242,7 +9242,7 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX && player->charability != CA_SWIM && !(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) // tails fly counter player->powers[pw_tailsfly]--; - if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)) + if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER))) { if (player->powers[pw_underwater] <= 12*TICRATE+1) P_RestoreMusic(player); //incase they were about to drown @@ -9252,7 +9252,7 @@ void P_PlayerThink(player_t *player) else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer player->powers[pw_underwater]--; - if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)) + if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER))) player->powers[pw_spacetime] = 0; else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer player->powers[pw_spacetime]--;