Bubble Shield adjustments
Primarily to improve its defensive capabilities * Trade penetrating attacks (like a Thunder Shield's AoE attack) * Remove bump-chip * Make how items damage the Bubble Shield more modular overall
This commit is contained in:
parent
289db04dec
commit
4b448de85e
4 changed files with 108 additions and 37 deletions
|
|
@ -519,7 +519,7 @@ void K_ThunderShieldAttack(mobj_t *actor, fixed_t size)
|
|||
P_BlockThingsIterator(bx, by, PIT_ThunderShieldAttack);
|
||||
}
|
||||
|
||||
static void K_BubbleShieldCollideDrain(player_t *player, mobj_t *bubble)
|
||||
static void K_BubbleShieldCollideDrain(player_t *player, mobj_t *bubble, INT16 dmg)
|
||||
{
|
||||
if (!player)
|
||||
{
|
||||
|
|
@ -533,10 +533,20 @@ static void K_BubbleShieldCollideDrain(player_t *player, mobj_t *bubble)
|
|||
return;
|
||||
}
|
||||
|
||||
// Pop the bubble immediately after an item hit.
|
||||
K_RemoveBubbleHealth(player, BUBBLEITMDAMAGE);
|
||||
// Damage the shield after an item hit.
|
||||
K_RemoveBubbleHealth(player, dmg);
|
||||
|
||||
if (player->bubblehealth > 0)
|
||||
if (K_GetShieldFromPlayer(player) == KSHIELD_BUBBLE)
|
||||
{
|
||||
if ((dmg > 0) && (bubble) && (!P_MobjWasRemoved(bubble)))
|
||||
{
|
||||
// Play a distinct "crack!" noise to clue the player in.
|
||||
S_StartSound(bubble, sfx_s3k6e);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply a cooldown if the Bubble Shield took damage without shattering.
|
||||
if ((player->bubblehealth > 0) && (dmg > 0))
|
||||
{
|
||||
player->bubblecool = 15*4;
|
||||
player->itemflags &= ~IF_HOLDREADY;
|
||||
|
|
@ -603,6 +613,47 @@ static boolean K_PlayerCanBeBubbleBumped(player_t *player)
|
|||
|| (player->growshrinktimer > 0));
|
||||
}
|
||||
|
||||
static INT16 K_GetBubbleDamage(mobj_t* itm)
|
||||
{
|
||||
if ((!itm) || (P_MobjWasRemoved(itm)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT16 dmg = BUBBLEITMDAMAGE;
|
||||
|
||||
switch (itm->type)
|
||||
{
|
||||
case MT_EGGMANITEM:
|
||||
case MT_BALLHOG:
|
||||
// Experiment: Let Bubble Shields hard-counter Ballhogs and Eggboxes.
|
||||
dmg = 0;
|
||||
break;
|
||||
case MT_SINK:
|
||||
case MT_JAWZ:
|
||||
case MT_PLAYER:
|
||||
// Sinks, Jawz, and powered-up players smash Bubble Shields to bits.
|
||||
dmg = MAXBUBBLEHEALTH;
|
||||
break;
|
||||
case MT_ORBINAUT:
|
||||
fixed_t momentum = K_Momentum3D(itm);
|
||||
fixed_t orbi_momentum_epsilon = FixedMul(FixedMul(itm->radius, itm->scale),
|
||||
K_GetKartGameSpeedScalar(gamespeed));
|
||||
|
||||
// Reward players on the offensive by letting fast Orbinauts shatter Bubble Shields.
|
||||
if (momentum >= orbi_momentum_epsilon)
|
||||
{
|
||||
dmg = MAXBUBBLEHEALTH;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return dmg;
|
||||
}
|
||||
|
||||
boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (t2->type == MT_PLAYER)
|
||||
|
|
@ -624,7 +675,7 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
|||
if (reflected)
|
||||
{
|
||||
// Drain my stuff please.
|
||||
K_BubbleShieldCollideDrain(t1->target->player, t1);
|
||||
K_BubbleShieldCollideDrain(t1->target->player, t1, K_GetBubbleDamage(t2));
|
||||
}
|
||||
|
||||
return reflected;
|
||||
|
|
@ -637,7 +688,7 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
|||
if (shootable)
|
||||
{
|
||||
// Drain my stuff please.
|
||||
K_BubbleShieldCollideDrain(t1->target->player, t1);
|
||||
K_BubbleShieldCollideDrain(t1->target->player, t1, K_GetBubbleDamage(t2));
|
||||
}
|
||||
|
||||
return shootable;
|
||||
|
|
|
|||
38
src/k_kart.c
38
src/k_kart.c
|
|
@ -760,18 +760,7 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean sol
|
|||
p1shield = K_GetShieldFromPlayer(mobj1->player);
|
||||
|
||||
// Moved here so it only fires once on bump.
|
||||
if (p1shield == KSHIELD_BUBBLE)
|
||||
{
|
||||
// Each bump does chip damage to the shield.
|
||||
K_RemoveBubbleHealth(mobj1->player, BUBBLEBUMPCHIP);
|
||||
|
||||
if (mobj1->player->bubblehealth > 0)
|
||||
{
|
||||
// Play a distinct "crack!" noise to clue the player in.
|
||||
S_StartSound(mobj1, sfx_s3k6e);
|
||||
}
|
||||
}
|
||||
else if (p1shield == KSHIELD_NONE)
|
||||
if (p1shield == KSHIELD_NONE)
|
||||
{
|
||||
if (mobj2->player && (mobj1->player->rings > 0))
|
||||
{
|
||||
|
|
@ -796,18 +785,7 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean sol
|
|||
p2shield = K_GetShieldFromPlayer(mobj2->player);
|
||||
|
||||
// Moved here so it only fires once on bump.
|
||||
if (p2shield == KSHIELD_BUBBLE)
|
||||
{
|
||||
// Each bump does chip damage to the shield.
|
||||
K_RemoveBubbleHealth(mobj2->player, BUBBLEBUMPCHIP);
|
||||
|
||||
if (mobj2->player->bubblehealth > 0)
|
||||
{
|
||||
// Play a distinct "crack!" noise to clue the player in.
|
||||
S_StartSound(mobj2, sfx_s3k6e);
|
||||
}
|
||||
}
|
||||
else if (p2shield == KSHIELD_NONE)
|
||||
if (p2shield == KSHIELD_NONE)
|
||||
{
|
||||
if (mobj1->player && (mobj2->player->rings > 0))
|
||||
{
|
||||
|
|
@ -3027,6 +3005,18 @@ angle_t K_MomentumAngle(mobj_t *mo)
|
|||
}
|
||||
}
|
||||
|
||||
fixed_t K_GetMomentum(mobj_t *mo, boolean twodee)
|
||||
{
|
||||
fixed_t xydist = R_PointToDist2(0, 0, mo->momx, mo->momy);
|
||||
|
||||
if (twodee)
|
||||
{
|
||||
return xydist;
|
||||
}
|
||||
|
||||
return R_PointToDist2(0, 0, xydist, mo->momz);
|
||||
}
|
||||
|
||||
void K_AwardPlayerRings(player_t *player, UINT16 rings, boolean overload)
|
||||
{
|
||||
UINT16 superring;
|
||||
|
|
|
|||
13
src/k_kart.h
13
src/k_kart.h
|
|
@ -71,15 +71,11 @@ extern vector3_t clusterpoint, clusterdtf;
|
|||
// Bubble Shield's maximum health
|
||||
#define MAXBUBBLEHEALTH 6
|
||||
|
||||
// Chip damage done to a Bubble Shield upon bumping a player
|
||||
#define BUBBLEBUMPCHIP 1
|
||||
|
||||
// HP cost for a Bubble Shield to inflate
|
||||
#define BUBBLEUSECOST (MAXBUBBLEHEALTH / 3)
|
||||
|
||||
// Damage done to an inflated Bubble Shield by items. By default, this is the maximum health,
|
||||
// so that the shield immediately breaks
|
||||
#define BUBBLEITMDAMAGE (MAXBUBBLEHEALTH)
|
||||
// Damage done to an inflated Bubble Shield by items.
|
||||
#define BUBBLEITMDAMAGE (1)
|
||||
|
||||
// Invincibility-related constants
|
||||
#define INVINDIST CV_Get(&cv_kartinvindist)
|
||||
|
|
@ -211,6 +207,11 @@ UINT8 K_RaceLapCount(INT16 mapNum);
|
|||
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
|
||||
void K_KartPlayerAfterThink(player_t *player);
|
||||
angle_t K_MomentumAngle(mobj_t *mo);
|
||||
|
||||
fixed_t K_GetMomentum(mobj_t *mo, boolean twodee);
|
||||
#define K_Momentum2D(mo) (K_GetMomentum(mo, true))
|
||||
#define K_Momentum3D(mo) (K_GetMomentum(mo, false))
|
||||
|
||||
void K_AwardPlayerRings(player_t *player, UINT16 rings, boolean overload);
|
||||
void K_HandleRaceSplits(player_t *player, tic_t time, UINT8 checkpoint);
|
||||
void K_DoInstashield(player_t *player);
|
||||
|
|
|
|||
|
|
@ -2133,6 +2133,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
boolean force = false;
|
||||
boolean spbpop = false;
|
||||
boolean painsound = false;
|
||||
boolean bubbleinvuln = false;
|
||||
INT32 myShield = KSHIELD_NONE;
|
||||
|
||||
if (objectplacing)
|
||||
return false;
|
||||
|
|
@ -2231,6 +2233,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
{
|
||||
const UINT8 type = (damagetype & DMG_TYPEMASK);
|
||||
const boolean explosioncombo = (type == DMG_EXPLODE); // This damage type can do evil stuff like ALWAYS combo
|
||||
myShield = K_GetShieldFromPlayer(player);
|
||||
|
||||
// Check if the player is allowed to be damaged!
|
||||
// If not, then spawn the instashield effect instead.
|
||||
|
|
@ -2262,6 +2265,32 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((myShield == KSHIELD_BUBBLE) && (player->bubbleblowup))
|
||||
{
|
||||
// This player is on the defensive; protect them from certain attacks.
|
||||
switch (type)
|
||||
{
|
||||
case DMG_WIPEOUT:
|
||||
bubbleinvuln = true;
|
||||
break;
|
||||
case DMG_VOLTAGE:
|
||||
case DMG_NORMAL:
|
||||
bubbleinvuln = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bubbleinvuln)
|
||||
{
|
||||
// This attack likely penetrated. Defense!
|
||||
player->flashing = K_GetKartFlashing(player);
|
||||
player->bubblecool = player->bubbleblowup*2;
|
||||
K_DoInstashield(player);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we should allow explosion combos.
|
||||
if ((explosioncombo == false) && (player->flashing > 0 || player->squishedtimer > 0))
|
||||
{
|
||||
|
|
@ -2425,7 +2454,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
}
|
||||
|
||||
// Have a shield? You get hit, but don't lose your rings!
|
||||
if (K_GetShieldFromPlayer(player) != KSHIELD_NONE)
|
||||
if (myShield != KSHIELD_NONE)
|
||||
{
|
||||
ringburst = 0;
|
||||
K_PopPlayerShield(player);
|
||||
|
|
|
|||
Loading…
Reference in a new issue