Disguise fixes + gen8 hp loss config (#4360)

* Disguise fixes + gen8 hp loss config

* fix battler arg

* Update test/battle/ability/disguise.c

---------

Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
This commit is contained in:
Alex 2024-04-07 00:07:55 +02:00 committed by GitHub
parent 77db5d9d1e
commit c740c4ba19
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 146 additions and 12 deletions

View file

@ -7058,11 +7058,15 @@ BattleScript_CudChewActivates::
BattleScript_TargetFormChangeNoPopup:
flushtextbox
handleformchange BS_TARGET, 0
handleformchange BS_TARGET, 1
handleformchange BS_SCRIPTING, 0
handleformchange BS_SCRIPTING, 1
playanimation BS_TARGET, B_ANIM_FORM_CHANGE
waitanimation
handleformchange BS_TARGET, 2
handleformchange BS_SCRIPTING, 2
.if B_DISGUISE_HP_LOSS >= GEN_8
healthbarupdate BS_SCRIPTING
datahpupdate BS_SCRIPTING
.endif
return
BattleScript_TargetFormChange::

View file

@ -37,7 +37,7 @@ void BufferMoveToLearnIntoBattleTextBuff2(void);
void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags);
bool8 UproarWakeUpCheck(u8 battlerId);
bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 DoesDisguiseBlockMove(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 DoesDisguiseBlockMove(u32 battler, u32 move);
bool32 CanPoisonType(u8 battlerAttacker, u8 battlerTarget);
bool32 CanParalyzeType(u8 battlerAttacker, u8 battlerTarget);
bool32 CanUseLastResort(u8 battlerId);

View file

@ -143,6 +143,7 @@
#define B_PROTEAN_LIBERO GEN_LATEST // In Gen9+, Protean and Libero change the user's type only once per Battle.
#define B_INTREPID_SWORD GEN_LATEST // In Gen9+, Intrepid Sword raises Attack by one stage only once per Battle.
#define B_DAUNTLESS_SHIELD GEN_LATEST // In Gen9+, Dauntless Shield raises Defense by one stage only once per Battle.
#define B_DISGUISE_HP_LOSS GEN_LATEST // In Gen8+, when a Disguised Mimikyu's Disguise is busted, upon changing to its Busted Form it loses HP equal to 1/8 of its maximum HP.
// Item settings
#define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore HP activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn.

View file

@ -2006,7 +2006,7 @@ static void Cmd_adjustdamage(void)
if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))
goto END;
if (DoesDisguiseBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))
if (DoesDisguiseBlockMove(gBattlerTarget, gCurrentMove))
{
gBattleStruct->enduredDamage |= gBitTable[gBattlerTarget];
goto END;
@ -2258,7 +2258,7 @@ static void Cmd_healthbarupdate(void)
{
PrepareStringBattle(STRINGID_SUBSTITUTEDAMAGED, battler);
}
else if (!DoesDisguiseBlockMove(gBattlerAttacker, battler, gCurrentMove))
else if (!DoesDisguiseBlockMove(battler, gCurrentMove))
{
s16 healthValue = min(gBattleMoveDamage, 10000); // Max damage (10000) not present in R/S, ensures that huge damage values don't change sign
@ -2311,16 +2311,19 @@ static void Cmd_datahpupdate(void)
return;
}
}
else if (DoesDisguiseBlockMove(gBattlerAttacker, battler, gCurrentMove))
else if (DoesDisguiseBlockMove(battler, gCurrentMove))
{
// TODO: Convert this to a proper FORM_CHANGE type.
u32 side = GetBattlerSide(battler);
gBattleScripting.battler = battler;
if (gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battler]] == SPECIES_NONE)
gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battler]] = gBattleMons[battler].species;
if (gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED)
gBattleMons[battler].species = SPECIES_MIMIKYU_TOTEM_BUSTED;
else
gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED;
if (B_DISGUISE_HP_LOSS >= GEN_8)
gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 8;
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = BattleScript_TargetFormChange;
return;
@ -14736,13 +14739,13 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move)
return TRUE;
}
bool32 DoesDisguiseBlockMove(u32 battlerAtk, u32 battlerDef, u32 move)
bool32 DoesDisguiseBlockMove(u32 battler, u32 move)
{
if (!(gBattleMons[battlerDef].species == SPECIES_MIMIKYU_DISGUISED || gBattleMons[battlerDef].species == SPECIES_MIMIKYU_TOTEM_DISGUISED)
|| gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED
|| IS_MOVE_STATUS(move)
if (!(gBattleMons[battler].species == SPECIES_MIMIKYU_DISGUISED || gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED)
|| gBattleMons[battler].status2 & STATUS2_TRANSFORMED
|| (!gProtectStructs[battler].confusionSelfDmg && (IS_MOVE_STATUS(move) || gHitMarker & HITMARKER_PASSIVE_DAMAGE))
|| gHitMarker & HITMARKER_IGNORE_DISGUISE
|| GetBattlerAbility(battlerDef) != ABILITY_DISGUISE)
|| GetBattlerAbility(battler) != ABILITY_DISGUISE)
return FALSE;
else
return TRUE;

View file

@ -20231,6 +20231,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.ignoresTargetAbility = TRUE,
},
[MOVE_MENACING_MOONRAZE_MAELSTROM] =
{
@ -20244,6 +20245,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_SPECIAL,
.ignoresTargetAbility = TRUE,
},
[MOVE_LIGHT_THAT_BURNS_THE_SKY] =
{
@ -20257,6 +20259,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_SPECIAL,
.ignoresTargetAbility = TRUE,
},
[MOVE_SOUL_STEALING_7_STAR_STRIKE] =
{

View file

@ -0,0 +1,123 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_AERIAL_ACE].category == DAMAGE_CATEGORY_PHYSICAL);
}
SINGLE_BATTLE_TEST("Disguised Mimikyu will lose 1/8 of its max HP upon changing to its busted form")
{
s16 disguiseDamage;
GIVEN {
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_AERIAL_ACE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_AERIAL_ACE, opponent);
ABILITY_POPUP(player, ABILITY_DISGUISE);
HP_BAR(player, captureDamage: &disguiseDamage);
} THEN {
EXPECT_EQ(player->species, SPECIES_MIMIKYU_BUSTED);
EXPECT_EQ(disguiseDamage, player->maxHP / 8);
}
}
SINGLE_BATTLE_TEST("Disguised Mimikyu takes no damage from a confusion hit and changes to its busted form")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_CONFUSE_RAY].effect == EFFECT_CONFUSE);
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_CONFUSE_RAY); }
TURN { }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
MESSAGE("Mimikyu became confused!");
MESSAGE("Mimikyu is confused!");
MESSAGE("It hurt itself in its confusion!");
NOT HP_BAR(player);
ABILITY_POPUP(player, ABILITY_DISGUISE);
} THEN {
EXPECT_EQ(player->species, SPECIES_MIMIKYU_BUSTED);
}
}
SINGLE_BATTLE_TEST("Disguised Mimikyu's Air Balloon will pop upon changing to its busted form")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_AIR_BALLOON].holdEffect == HOLD_EFFECT_AIR_BALLOON);
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); Item(ITEM_AIR_BALLOON); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_AERIAL_ACE); }
} SCENE {
MESSAGE("Mimikyu floats in the air with its Air Balloon!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_AERIAL_ACE, opponent);
NOT HP_BAR(player);
ABILITY_POPUP(player, ABILITY_DISGUISE);
MESSAGE("Mimikyu's Air Balloon popped!");
} THEN {
EXPECT_EQ(player->species, SPECIES_MIMIKYU_BUSTED);
}
}
SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from secondary damage without breaking the disguise")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_STEALTH_ROCK].effect == EFFECT_STEALTH_ROCK);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_STEALTH_ROCK); }
TURN { SWITCH(player, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
HP_BAR(player);
MESSAGE("Pointed stones dug into Mimikyu!");
} THEN {
EXPECT_EQ(player->species, SPECIES_MIMIKYU_DISGUISED);
}
}
SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from Rocky Helmet without breaking the disguise")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_ROCKY_HELMET].holdEffect == HOLD_EFFECT_ROCKY_HELMET);
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); }
} WHEN {
TURN { MOVE(player, MOVE_AERIAL_ACE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_AERIAL_ACE, player);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
HP_BAR(player);
MESSAGE("Mimikyu was hurt by Foe Wobbuffet's Rocky Helmet!");
} THEN {
EXPECT_EQ(player->species, SPECIES_MIMIKYU_DISGUISED);
}
}
SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from Rough Skin without breaking the disguise")
{
GIVEN {
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
OPPONENT(SPECIES_CARVANHA) { Ability(ABILITY_ROUGH_SKIN); }
} WHEN {
TURN { MOVE(player, MOVE_AERIAL_ACE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_AERIAL_ACE, player);
HP_BAR(opponent);
ABILITY_POPUP(opponent, ABILITY_ROUGH_SKIN);
HP_BAR(player);
MESSAGE("Mimikyu was hurt by Foe Carvanha's Rough Skin!");
} THEN {
EXPECT_EQ(player->species, SPECIES_MIMIKYU_DISGUISED);
}
}