Stealth Rock and Toxic Spikes

This commit is contained in:
DizzyEggg 2018-07-24 21:47:00 +02:00
parent 45bc76d94c
commit f8b1f0a45c
10 changed files with 202 additions and 53 deletions

View File

@ -3789,58 +3789,71 @@ BattleScript_DestinyBondTakesLife::
tryfaintmon BS_ATTACKER, FALSE, NULL
return
BattleScript_SpikesOnAttacker::
BattleScript_DmgHazardsOnAttacker::
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
call BattleScript_PrintHurtBySpikes
call BattleScript_PrintHurtByDmgHazards
tryfaintmon BS_ATTACKER, FALSE, NULL
tryfaintmon BS_ATTACKER, TRUE, BattleScript_SpikesOnAttackerFainted
tryfaintmon BS_ATTACKER, TRUE, BattleScript_DmgHazardsOnAttackerFainted
return
BattleScript_SpikesOnAttackerFainted::
BattleScript_DmgHazardsOnAttackerFainted::
setbyte sGIVEEXP_STATE, 0x0
getexp BS_ATTACKER
setbyte sMOVEEND_STATE, 0x0
moveend 0x0, 0x0
goto BattleScript_HandleFaintedMon
BattleScript_SpikesOnTarget::
BattleScript_DmgHazardsOnTarget::
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
call BattleScript_PrintHurtBySpikes
call BattleScript_PrintHurtByDmgHazards
tryfaintmon BS_TARGET, FALSE, NULL
tryfaintmon BS_TARGET, TRUE, BattleScript_SpikesOnTargetFainted
tryfaintmon BS_TARGET, TRUE, BattleScript_DmgHazardsOnTargetFainted
return
BattleScript_SpikesOnTargetFainted::
BattleScript_DmgHazardsOnTargetFainted::
setbyte sGIVEEXP_STATE, 0x0
getexp BS_TARGET
setbyte sMOVEEND_STATE, 0x0
moveend 0x0, 0x0
goto BattleScript_HandleFaintedMon
BattleScript_SpikesOnFaintedBattler::
BattleScript_DmgHazardsOnFaintedBattler::
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000
healthbarupdate BS_FAINTED
datahpupdate BS_FAINTED
call BattleScript_PrintHurtBySpikes
call BattleScript_PrintHurtByDmgHazards
tryfaintmon BS_FAINTED, FALSE, NULL
tryfaintmon BS_FAINTED, TRUE, BattleScript_SpikesOnFaintedBattlerFainted
tryfaintmon BS_FAINTED, TRUE, BattleScript_DmgHazardsOnFaintedBattlerFainted
return
BattleScript_SpikesOnFaintedBattlerFainted::
BattleScript_DmgHazardsOnFaintedBattlerFainted::
setbyte sGIVEEXP_STATE, 0x0
getexp BS_FAINTED
setbyte sMOVEEND_STATE, 0x0
moveend 0x0, 0x0
goto BattleScript_HandleFaintedMon
BattleScript_PrintHurtBySpikes::
printstring STRINGID_PKMNHURTBYSPIKES
BattleScript_PrintHurtByDmgHazards::
printfromtable gDmgHazardsStringIds
waitmessage 0x40
return
BattleScript_ToxicSpikesAbsorbed::
printstring STRINGID_TOXICSPIKESABSORBED
waitmessage 0x40
return
BattleScript_ToxicSpikesPoisoned::
printstring STRINGID_TOXICSPIKESPOISONED
waitmessage 0x40
statusanimation BS_SCRIPTING
updatestatusicon BS_SCRIPTING
waitstate
return
BattleScript_PerishSongTakesLife::
printstring STRINGID_PKMNPERISHCOUNTFELL

View File

@ -256,6 +256,7 @@ struct SideTimer
/*0x09*/ u8 followmeTarget;
/*0x0A*/ u8 spikesAmount;
u8 toxicSpikesAmount;
u8 stealthRockAmount;
u8 auroraVeilTimer;
u8 auroraVeilBattlerId;
u8 tailwindTimer;

View File

@ -78,11 +78,11 @@ extern const u8 BattleScript_SelectingDisabledMoveInPalace[];
extern const u8 BattleScript_SelectingUnusableMoveInPalace[];
extern const u8 BattleScript_EncoredNoMore[];
extern const u8 BattleScript_DestinyBondTakesLife[];
extern const u8 BattleScript_SpikesOnAttacker[];
extern const u8 BattleScript_DmgHazardsOnAttacker[];
extern const u8 BattleScript_82DAE7A[];
extern const u8 BattleScript_SpikesOnTarget[];
extern const u8 BattleScript_DmgHazardsOnTarget[];
extern const u8 BattleScript_82DAEB1[];
extern const u8 BattleScript_SpikesOnFaintedBattler[];
extern const u8 BattleScript_DmgHazardsOnFaintedBattler[];
extern const u8 BattleScript_82DAEE8[];
extern const u8 BattleScript_82DAEFE[];
extern const u8 BattleScript_PerishSongTakesLife[];
@ -314,5 +314,7 @@ extern const u8 BattleScript_AttackerAbilityStatRaiseEnd3[];
extern const u8 BattleScript_PoisonHealActivates[];
extern const u8 BattleScript_BadDreamsActivates[];
extern const u8 BattleScript_SwitchInAbilityMsg[];
extern const u8 BattleScript_ToxicSpikesPoisoned[];
extern const u8 BattleScript_ToxicSpikesAbsorbed[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -84,5 +84,6 @@ s32 CalculateMoveDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32
u16 CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities);
u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u8 abilityDef);
u16 GetTypeModifier(u8 atkType, u8 defType);
s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -188,19 +188,22 @@
#define HITMARKER_UNK(battler) (0x10000000 << battler)
// Per-side statuses that affect an entire party
#define SIDE_STATUS_REFLECT (1 << 0)
#define SIDE_STATUS_LIGHTSCREEN (1 << 1)
#define SIDE_STATUS_X4 (1 << 2)
#define SIDE_STATUS_SPIKES (1 << 4)
#define SIDE_STATUS_SAFEGUARD (1 << 5)
#define SIDE_STATUS_FUTUREATTACK (1 << 6)
#define SIDE_STATUS_MIST (1 << 8)
#define SIDE_STATUS_SPIKES_DAMAGED (1 << 9)
#define SIDE_STATUS_TAILWIND (1 << 10)
#define SIDE_STATUS_AURORA_VEIL (1 << 11)
#define SIDE_STATUS_LUCKY_CHANT (1 << 12)
#define SIDE_STATUS_TOXIC_SPIKES (1 << 13)
#define SIDE_STATUS_STEALTH_ROCK (1 << 14)
#define SIDE_STATUS_REFLECT (1 << 0)
#define SIDE_STATUS_LIGHTSCREEN (1 << 1)
#define SIDE_STATUS_STICKY_WEB (1 << 2)
#define SIDE_STATUS_SPIKES (1 << 4)
#define SIDE_STATUS_SAFEGUARD (1 << 5)
#define SIDE_STATUS_FUTUREATTACK (1 << 6)
#define SIDE_STATUS_MIST (1 << 8)
#define SIDE_STATUS_SPIKES_DAMAGED (1 << 9)
#define SIDE_STATUS_TAILWIND (1 << 10)
#define SIDE_STATUS_AURORA_VEIL (1 << 11)
#define SIDE_STATUS_LUCKY_CHANT (1 << 12)
#define SIDE_STATUS_TOXIC_SPIKES (1 << 13)
#define SIDE_STATUS_STEALTH_ROCK (1 << 14)
#define SIDE_STATUS_STEALTH_ROCK_DAMAGED (1 << 15)
#define SIDE_STATUS_TOXIC_SPIKES_DAMAGED (1 << 16)
#define SIDE_STATUS_STICKY_WEB_DAMAGED (1 << 17)
// Field affecting statuses.
#define STATUS_FIELD_MAGIC_ROOM 0x1

View File

@ -473,7 +473,10 @@
#define STRINGID_MAGICBOUNCEACTIVATES 470
#define STRINGID_PROTEANTYPECHANGE 471
#define STRINGID_SYMBIOSISITEMPASS 472
#define STRINGID_STEALTHROCKDMG 473
#define STRINGID_TOXICSPIKESABSORBED 474
#define STRINGID_TOXICSPIKESPOISONED 475
#define BATTLESTRINGS_COUNT 463
#define BATTLESTRINGS_COUNT 466
#endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H

View File

@ -115,7 +115,9 @@ enum
LIST_SIDE_MIST,
LIST_SIDE_AURORA_VEIL,
LIST_SIDE_LUCKY_CHANT,
LIST_SIDE_TAILWIND
LIST_SIDE_TAILWIND,
LIST_SIDE_STEALTH_ROCK,
LIST_SIDE_TOXIC_SPIKES,
};
// const rom data
@ -173,6 +175,8 @@ static const u8 sText_AuroraVeil[] = _("Aurora Veil");
static const u8 sText_LuckyChant[] = _("Lucky Chant");
static const u8 sText_Tailwind[] = _("Tailwind");
static const u8 sText_PP[] = _("PP");
static const u8 sText_StealthRock[] = _("Stealth Rock");
static const u8 sText_ToxicSpikes[] = _("Toxic Spikes");
static const u8 sText_EmptyString[] = _("");
@ -323,6 +327,8 @@ static const struct ListMenuItem sSideStatusListItems[] =
{sText_AuroraVeil, LIST_SIDE_AURORA_VEIL},
{sText_LuckyChant, LIST_SIDE_LUCKY_CHANT},
{sText_Tailwind, LIST_SIDE_TAILWIND},
{sText_StealthRock, LIST_SIDE_STEALTH_ROCK},
{sText_ToxicSpikes, LIST_SIDE_TOXIC_SPIKES},
};
static const struct ListMenuItem sSecondaryListItems[] =
@ -1111,6 +1117,24 @@ static u8 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus,
sideTimer->tailwindBattlerId = data->battlerId;
}
return &sideTimer->tailwindTimer;
case LIST_SIDE_STEALTH_ROCK:
if (changeStatus)
{
if (statusTrue)
*(u32*)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEALTH_ROCK;
else
*(u32*)(data->modifyArrows.modifiedValPtr) &= ~(SIDE_STATUS_STEALTH_ROCK);
}
return &sideTimer->stealthRockAmount;
case LIST_SIDE_TOXIC_SPIKES:
if (changeStatus)
{
if (statusTrue)
*(u32*)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_TOXIC_SPIKES;
else
*(u32*)(data->modifyArrows.modifiedValPtr) &= ~(SIDE_STATUS_TOXIC_SPIKES);
}
return &sideTimer->toxicSpikesAmount;
default:
return NULL;
}
@ -1219,6 +1243,8 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data)
if (data->currentSecondaryListItemId == LIST_SIDE_SPIKES)
data->modifyArrows.maxValue = 3;
else if (data->currentSecondaryListItemId == LIST_SIDE_STEALTH_ROCK)
data->modifyArrows.maxValue = 1;
else
data->modifyArrows.maxValue = 9;

View File

@ -588,8 +588,6 @@ static const u8 sText_GravityEnds[] = _("Gravity returned to normal!");
static const u8 sText_AquaRingHeal[] = _("Aqua Ring restored\n{B_ATK_NAME_WITH_PREFIX}s HP!");
static const u8 sText_TargetAbilityRaisedStat[] = _("{B_DEF_NAME_WITH_PREFIX}s {B_ATK_ABILITY}\n raised its {B_BUFF1}!");
static const u8 sText_AttackerAbilityRaisedStat[] = _("{B_ATK_NAME_WITH_PREFIX}s {B_ATK_ABILITY}\n raised its {B_BUFF1}!");
// These strings are currently placeholders, to be fixed.
static const u8 sText_AuroraVeilEnds[] = _("{B_DEF_NAME_WITH_PREFIX}s {B_DEF_ABILITY}\nwore off!");
static const u8 sText_ElectricTerrainEnds[] = _("{B_ATK_ABILITY} wore off.");
static const u8 sText_MistyTerrainEnds[] = _("{B_ATK_ABILITY} wore off.");
@ -616,6 +614,9 @@ static const u8 sText_MoxieAtkRise[] = _("{B_ATK_NAME_WITH_PREFIX}s {B_ATK_AB
static const u8 sText_MagicBounceActivates[] = _("The {B_DEF_NAME_WITH_PREFIX} bounced the\n{B_ATK_NAME_WITH_PREFIX} back!");
static const u8 sText_ProteanTypeChange[] = _("{B_ATK_NAME_WITH_PREFIX}s {B_ATK_ABILITY} transformed\nit into the {B_BUFF1} type!");
static const u8 sText_SymbiosisItemPass[] = _("{B_ATK_NAME_WITH_PREFIX} passed its {B_LAST_ITEM}\nto {B_SCR_ACTIVE_NAME_WITH_PREFIX} through {B_ATK_ABILITY}!");
static const u8 sText_StealthRockDmg[] = _("Pointed stones dug into\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}!");
static const u8 sText_ToxicSpikesAbsorbed[] = _("");
static const u8 sText_ToxicSpikesPoisoned[] = _("");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
@ -1081,6 +1082,14 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
sText_MagicBounceActivates,
sText_ProteanTypeChange,
sText_SymbiosisItemPass,
sText_StealthRockDmg,
sText_ToxicSpikesAbsorbed,
sText_ToxicSpikesPoisoned,
};
const u16 gDmgHazardsStringIds[] =
{
STRINGID_PKMNHURTBYSPIKES, STRINGID_STEALTHROCKDMG
};
const u16 gSwitchInAbilityStringIds[] =

View File

@ -2765,7 +2765,7 @@ static void atk19_tryfaintmon(void)
BattleScriptPop();
gBattlescriptCurrInstr = BS_ptr;
gSideStatuses[GetBattlerSide(gActiveBattler)] &= ~(SIDE_STATUS_SPIKES_DAMAGED);
gSideStatuses[GetBattlerSide(gActiveBattler)] &= ~(SIDE_STATUS_SPIKES_DAMAGED | SIDE_STATUS_TOXIC_SPIKES_DAMAGED | SIDE_STATUS_STEALTH_ROCK_DAMAGED | SIDE_STATUS_STICKY_WEB_DAMAGED);
}
else
{
@ -5315,6 +5315,22 @@ static void atk51_switchhandleorder(void)
gBattlescriptCurrInstr += 3;
}
static void SetDmgHazardsBattlescript(u8 battlerId, u8 multistringId)
{
gBattleMons[battlerId].status2 &= ~(STATUS2_DESTINY_BOND);
gHitMarker &= ~(HITMARKER_DESTINYBOND);
gBattleScripting.battler = battlerId;
gBattleCommunication[MULTISTRING_CHOOSER] = multistringId;
BattleScriptPushCursor();
if (gBattlescriptCurrInstr[1] == BS_TARGET)
gBattlescriptCurrInstr = BattleScript_DmgHazardsOnTarget;
else if (gBattlescriptCurrInstr[1] == BS_ATTACKER)
gBattlescriptCurrInstr = BattleScript_DmgHazardsOnAttacker;
else
gBattlescriptCurrInstr = BattleScript_DmgHazardsOnFaintedBattler;
}
static void atk52_switchineffects(void)
{
s32 i;
@ -5327,30 +5343,57 @@ static void atk52_switchineffects(void)
if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES_DAMAGED)
&& (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES)
&& !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_FLYING)
&& gBattleMons[gActiveBattler].ability != ABILITY_LEVITATE)
&& IsBattlerGrounded(gActiveBattler))
{
u8 spikesDmg;
gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_SPIKES_DAMAGED;
gBattleMons[gActiveBattler].status2 &= ~(STATUS2_DESTINY_BOND);
gHitMarker &= ~(HITMARKER_DESTINYBOND);
spikesDmg = (5 - gSideTimers[GetBattlerSide(gActiveBattler)].spikesAmount) * 2;
u8 spikesDmg = (5 - gSideTimers[GetBattlerSide(gActiveBattler)].spikesAmount) * 2;
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / (spikesDmg);
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleScripting.battler = gActiveBattler;
BattleScriptPushCursor();
gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_SPIKES_DAMAGED;
SetDmgHazardsBattlescript(gActiveBattler, 0);
}
else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STEALTH_ROCK_DAMAGED)
&& (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STEALTH_ROCK))
{
gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_STEALTH_ROCK_DAMAGED;
gBattleMoveDamage = GetStealthHazardDamage(gBattleMoves[MOVE_STEALTH_ROCK].type, gActiveBattler);
if (gBattlescriptCurrInstr[1] == BS_TARGET)
gBattlescriptCurrInstr = BattleScript_SpikesOnTarget;
else if (gBattlescriptCurrInstr[1] == BS_ATTACKER)
gBattlescriptCurrInstr = BattleScript_SpikesOnAttacker;
if (gBattleMoveDamage != 0)
SetDmgHazardsBattlescript(gActiveBattler, 1);
}
else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES_DAMAGED)
&& (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_TOXIC_SPIKES)
&& IsBattlerGrounded(gActiveBattler))
{
gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_TOXIC_SPIKES_DAMAGED;
if (IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_POISON)) // Absorb the toxic spikes.
{
gSideStatuses[GetBattlerSide(gActiveBattler)] &= ~(SIDE_STATUS_TOXIC_SPIKES);
gSideTimers[GetBattlerSide(gActiveBattler)].toxicSpikesAmount = 0;
gBattleScripting.battler = gActiveBattler;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_ToxicSpikesAbsorbed;
}
else
gBattlescriptCurrInstr = BattleScript_SpikesOnFaintedBattler;
{
if (!(gBattleMons[gActiveBattler].status1 & STATUS1_ANY)
&& !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL)
&& GetBattlerAbility(gActiveBattler) != ABILITY_IMMUNITY
&& !(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SAFEGUARD))
{
if (gSideTimers[GetBattlerSide(gActiveBattler)].toxicSpikesAmount >= 2)
gBattleMons[gActiveBattler].status1 |= STATUS1_TOXIC_POISON;
else
gBattleMons[gActiveBattler].status1 |= STATUS1_POISON;
BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1);
MarkBattlerForControllerExec(gActiveBattler);
gBattleScripting.battler = gActiveBattler;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned;
}
}
}
else
{
@ -5362,7 +5405,7 @@ static void atk52_switchineffects(void)
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gActiveBattler, 0, 0, 0) == 0 &&
ItemBattleEffects(0, gActiveBattler, 0) == 0)
{
gSideStatuses[GetBattlerSide(gActiveBattler)] &= ~(SIDE_STATUS_SPIKES_DAMAGED);
gSideStatuses[GetBattlerSide(gActiveBattler)] &= ~(SIDE_STATUS_SPIKES_DAMAGED | SIDE_STATUS_TOXIC_SPIKES_DAMAGED | SIDE_STATUS_STEALTH_ROCK_DAMAGED | SIDE_STATUS_STICKY_WEB_DAMAGED);
for (i = 0; i < gBattlersCount; i++)
{
@ -9484,6 +9527,7 @@ static void atkDC_setstealthrock(void)
else
{
gSideStatuses[targetSide] |= SIDE_STATUS_STEALTH_ROCK;
gSideTimers[targetSide].stealthRockAmount = 1;
gBattlescriptCurrInstr += 5;
}
}

View File

@ -5230,3 +5230,50 @@ u16 GetTypeModifier(u8 atkType, u8 defType)
{
return sTypeEffectivenessTable[atkType][defType];
}
s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId)
{
u8 type1 = gBattleMons[battlerId].type1;
u8 type2 = gBattleMons[battlerId].type2;
u32 maxHp = gBattleMons[battlerId].maxHP;
s32 dmg = 0;
u16 modifier = UQ_4_12(1.0);
MulModifier(&modifier, GetTypeModifier(hazardType, type1));
if (type2 != type1)
MulModifier(&modifier, GetTypeModifier(hazardType, type2));
switch (modifier)
{
case UQ_4_12(0.0):
dmg = 0;
break;
case UQ_4_12(0.25):
dmg = maxHp / 32;
if (dmg == 0)
dmg = 1;
break;
case UQ_4_12(0.5):
dmg = maxHp / 16;
if (dmg == 0)
dmg = 1;
break;
case UQ_4_12(1.0):
dmg = maxHp / 8;
if (dmg == 0)
dmg = 1;
break;
case UQ_4_12(2.0):
dmg = maxHp / 4;
if (dmg == 0)
dmg = 1;
break;
case UQ_4_12(4.0):
dmg = maxHp / 2;
if (dmg == 0)
dmg = 1;
break;
}
return dmg;
}