Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disguise fixes + gen8 hp loss config #4360

Merged
merged 3 commits into from
Apr 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -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::
Expand Down
2 changes: 1 addition & 1 deletion include/battle_script_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions include/config/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 11 additions & 8 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/data/moves_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -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] =
{
Expand All @@ -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] =
{
Expand All @@ -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] =
{
Expand Down
123 changes: 123 additions & 0 deletions test/battle/ability/disguise.c
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading