Turning some shield attributes into flags means that environmental protection and ring-pulling can be more elegantly handled. As a consequence, the S3 shields now have all their passives, and are just waiting on me to give them actives (two of which don't have the necessary sprites for...)

This commit is contained in:
toasterbabe 2016-10-13 15:13:33 +01:00
parent 3aa9d2a1b1
commit aa8a454ea9
7 changed files with 60 additions and 43 deletions

View file

@ -181,25 +181,35 @@ typedef enum
typedef enum typedef enum
{ {
SH_NONE = 0, SH_NONE = 0,
// Standard shields
// Shield flags
SH_PROTECTFIRE = 0x400,
SH_PROTECTWATER = 0x800,
SH_PROTECTELECTRICITY = 0x1000,
// Indivisible shields
SH_PITY = 1,
SH_JUMP, SH_JUMP,
SH_ATTRACT,
SH_ELEMENTAL,
SH_BOMB, 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, 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. // The force shield uses the lower 8 bits to count how many extra hits are left.
SH_FORCE = 0x100, SH_FORCE = 0x100,
SH_FORCEHP = 0xFF, // to be used as a bitmask only 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_MUSHROOM = 0x200,
SH_STACK = SH_MUSHROOM, //|SH_FIREFLOWER,
SH_STACK = SH_MUSHROOM, // second-layer shields
SH_NOSTACK = ~SH_STACK SH_NOSTACK = ~SH_STACK
} shieldtype_t; // pw_shield } shieldtype_t; // pw_shield

View file

@ -7174,21 +7174,28 @@ struct {
{"PRECIP_STORM_NOSTRIKES",PRECIP_STORM_NOSTRIKES}, {"PRECIP_STORM_NOSTRIKES",PRECIP_STORM_NOSTRIKES},
// Shields // Shields
// These ones use the lower 8 bits
{"SH_NONE",SH_NONE}, {"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_JUMP",SH_JUMP},
{"SH_BOMB",SH_BOMB},
{"SH_FIREFLOWER",SH_FIREFLOWER},
// normal shields that use flags
{"SH_ATTRACT",SH_ATTRACT}, {"SH_ATTRACT",SH_ATTRACT},
{"SH_ELEMENTAL",SH_ELEMENTAL}, {"SH_ELEMENTAL",SH_ELEMENTAL},
{"SH_BOMB",SH_BOMB}, // Sonic 3 shields
{"SH_FLAMEAURA",SH_FLAMEAURA},
{"SH_BUBBLEWRAP",SH_BUBBLEWRAP}, {"SH_BUBBLEWRAP",SH_BUBBLEWRAP},
{"SH_THUNDERCOIN",SH_THUNDERCOIN}, {"SH_THUNDERCOIN",SH_THUNDERCOIN},
{"SH_FLAMEAURA",SH_FLAMEAURA}, // The force shield uses the lower 8 bits to count how many extra hits are left.
{"SH_PITY",SH_PITY}, {"SH_FORCE",SH_FORCE},
{"SH_FIREFLOWER",SH_FIREFLOWER}, {"SH_FORCEHP",SH_FORCEHP}, // to be used as a bitmask only
// These ones are special and use the upper bits // Mostly for use with Mario mode.
{"SH_FORCE",SH_FORCE}, // Lower bits are how many hits left, 0 is the last hit {"SH_MUSHROOM", SH_MUSHROOM},
{"SH_MUSHROOM", SH_MUSHROOM}, // Can stack with other shields
// Stack masks
{"SH_STACK",SH_STACK}, {"SH_STACK",SH_STACK},
{"SH_NOSTACK",SH_NOSTACK}, {"SH_NOSTACK",SH_NOSTACK},

View file

@ -741,7 +741,7 @@ static boolean P_LookForShield(mobj_t *actor)
(actor->type == MT_BLUETEAMRING && player->ctfteam != 2)) (actor->type == MT_BLUETEAMRING && player->ctfteam != 2))
continue; 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_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); P_SetTarget(&actor->tracer, player->mo);
@ -3817,7 +3817,7 @@ void A_AttractChase(mobj_t *actor)
// Turn flingrings back into regular rings if attracted. // Turn flingrings back into regular rings if attracted.
if (actor->tracer && actor->tracer->player 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; mobj_t *newring;
newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); 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 // A non-homing ring getting attracted by a
// magnetic player. If he gets too far away, make // magnetic player. If he gets too far away, make
// sure to stop the attraction! // 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, && 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))) 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) 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; const INT32 temp = actor->threshold;
actor->threshold = 32000; actor->threshold = 32000;
@ -4098,7 +4098,7 @@ void A_ThrownRing(mobj_t *actor)
if (!P_CheckSight(actor, player->mo)) if (!P_CheckSight(actor, player->mo))
continue; // out of sight 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)) && dist < FixedMul(RING_DIST/4, player->mo->scale))
P_SetTarget(&actor->tracer, player->mo); P_SetTarget(&actor->tracer, player->mo);
return; return;

View file

@ -1459,7 +1459,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return; return;
case MT_EXTRALARGEBUBBLE: case MT_EXTRALARGEBUBBLE:
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) if (player->powers[pw_shield] & SH_PROTECTWATER)
return; return;
if (maptol & TOL_NIGHTS) if (maptol & TOL_NIGHTS)
return; 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)) if (!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && (maptol & TOL_NIGHTS))
return false; return false;
#define shieldtype (player->powers[pw_shield] & SH_NOSTACK)
switch (damagetype) switch (damagetype)
{ {
case DMG_WATER: case DMG_WATER:
if (shieldtype == SH_BUBBLEWRAP if (player->powers[pw_shield] & SH_PROTECTWATER)
|| shieldtype == SH_ELEMENTAL)
return false; // Invincible to water damage return false; // Invincible to water damage
break; break;
case DMG_FIRE: case DMG_FIRE:
if (shieldtype == SH_FLAMEAURA if (player->powers[pw_shield] & SH_PROTECTFIRE)
|| shieldtype == SH_ELEMENTAL)
return false; // Invincible to fire damage return false; // Invincible to fire damage
break; break;
case DMG_ELECTRIC: case DMG_ELECTRIC:
if (shieldtype == SH_ATTRACT if (player->powers[pw_shield] & SH_PROTECTELECTRICITY)
|| shieldtype == SH_THUNDERCOIN)
return false; // Invincible to electric damage return false; // Invincible to electric damage
break; break;
default: default:
break; break;
} }
#undef shieldtype
} }
if (player->pflags & PF_NIGHTSMODE) // NiGHTS damage handling 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 (!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 return false; // Invincible to fire objects
if (G_PlatformGametype() && inflictor && source && source->player) if (G_PlatformGametype() && inflictor && source && source->player)

View file

@ -3619,15 +3619,20 @@ void P_MobjCheckWater(mobj_t *mobj)
{ {
if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability]))) if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability])))
{ {
if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) if (p->powers[pw_shield] & SH_PROTECTELECTRICITY)
{ // Water removes attract shield. { // Water removes electric shields...
p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK; p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK;
P_FlashPal(p, PAL_WHITE, 1); 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 // 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 || (p->exiting) // Or exiting
|| (maptol & TOL_NIGHTS) // Or in NiGHTS mode || (maptol & TOL_NIGHTS) // Or in NiGHTS mode
|| (mariomode)) // Or in Mario mode... || (mariomode)) // Or in Mario mode...

View file

@ -3562,7 +3562,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
break; break;
case 12: // Space Countdown 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; player->powers[pw_spacetime] = spacetimetics + 1;
break; break;
case 13: // Ramp Sector (Increase step-up/down) case 13: // Ramp Sector (Increase step-up/down)

View file

@ -2229,7 +2229,7 @@ static void P_DoBubbleBreath(player_t *player)
fixed_t z = player->mo->z; fixed_t z = player->mo->z;
mobj_t *bubble = NULL; 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; return;
if (player->charflags & SF_MACHINE) 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 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]--; 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) if (player->powers[pw_underwater] <= 12*TICRATE+1)
P_RestoreMusic(player); //incase they were about to drown 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 else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
player->powers[pw_underwater]--; 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; player->powers[pw_spacetime] = 0;
else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
player->powers[pw_spacetime]--; player->powers[pw_spacetime]--;