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
{
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

View file

@ -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},

View file

@ -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;

View file

@ -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)

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_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...

View file

@ -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)

View file

@ -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]--;