Skip to content

Commit

Permalink
Disguise fixes + gen8 hp loss config
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexOn1ine committed Apr 6, 2024
1 parent 29a4444 commit 71b56a2
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 12 deletions.
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[gBattlerAttacker].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 Rocky Helmet 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);
}
}

0 comments on commit 71b56a2

Please sign in to comment.