diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8ca71ad48e..a53d977f0b 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8489,6 +8489,16 @@ BattleScript_ZeroToHeroActivates:: waitmessage B_WAIT_TIME_LONG end3 +BattleScript_HospitalityActivates:: + pause B_WAIT_TIME_SHORT + call BattleScript_AbilityPopUp + printstring STRINGID_HOSPITALITYRESTORATION + waitmessage B_WAIT_TIME_LONG + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + end3 + BattleScript_AttackWeakenedByStrongWinds:: pause B_WAIT_TIME_SHORT printstring STRINGID_ATTACKWEAKENEDBSTRONGWINDS @@ -8885,6 +8895,7 @@ BattleScript_BattlerAbilityStatRaiseOnSwitchIn:: waitanimation printstring STRINGID_BATTLERABILITYRAISEDSTAT waitmessage B_WAIT_TIME_LONG + copybyte gBattlerAttacker, sSAVED_BATTLER end3 BattleScript_ScriptingAbilityStatRaise:: diff --git a/include/battle_scripts.h b/include/battle_scripts.h index d9eaa629bc..8ed4ff4d55 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -459,6 +459,7 @@ extern const u8 BattleScript_CudChewActivates[]; extern const u8 BattleScript_SupremeOverlordActivates[]; extern const u8 BattleScript_CostarActivates[]; extern const u8 BattleScript_ZeroToHeroActivates[]; +extern const u8 BattleScript_HospitalityActivates[]; extern const u8 BattleScript_ToxicDebrisActivates[]; extern const u8 BattleScript_EarthEaterActivates[]; extern const u8 BattleScript_MimicryActivates_End3[]; diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 6263f87a38..5b571c9fb2 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -696,8 +696,9 @@ #define STRINGID_SWAMPENVELOPEDSIDE 694 #define STRINGID_THESWAMPDISAPPEARED 695 #define STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE 696 +#define STRINGID_HOSPITALITYRESTORATION 697 -#define BATTLESTRINGS_COUNT 697 +#define BATTLESTRINGS_COUNT 698 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/include/item_use.h b/include/item_use.h index 90d671bd42..3117e603d5 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -53,5 +53,6 @@ enum { }; bool32 CanThrowBall(void); +bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon); #endif // GUARD_ITEM_USE_H diff --git a/src/battle_message.c b/src/battle_message.c index b5e4db71aa..35ff5379ec 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -833,9 +833,11 @@ static const u8 sText_HurtByTheSeaOfFire[] = _("{B_ATK_TEAM1} {B_ATK_NAME_WITH_P static const u8 sText_TheSeaOfFireDisappeared[] = _("The sea of fire around {B_ATK_TEAM2}\nteam disappeared!"); static const u8 sText_SwampEnvelopedSide[] = _("A swamp enveloped\n{B_DEF_TEAM2} team!"); static const u8 sText_TheSwampDisappeared[] = _("The swamp around {B_ATK_TEAM2}\nteam disappeared!"); +static const u8 sText_HospitalityRestoration[] = _("The {B_ATK_PARTNER_NAME} drank down all\nthe matcha that Sinistcha made!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_HOSPITALITYRESTORATION - BATTLESTRINGS_TABLE_START] = sText_HospitalityRestoration, [STRINGID_THESWAMPDISAPPEARED - BATTLESTRINGS_TABLE_START] = sText_TheSwampDisappeared, [STRINGID_SWAMPENVELOPEDSIDE - BATTLESTRINGS_TABLE_START] = sText_SwampEnvelopedSide, [STRINGID_THESEAOFFIREDISAPPEARED - BATTLESTRINGS_TABLE_START] = sText_TheSeaOfFireDisappeared, diff --git a/src/battle_util.c b/src/battle_util.c index e0d7650640..3a28869193 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4314,6 +4314,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 u32 moveType, move; u32 side; u32 i, j; + u32 partner; struct Pokemon *mon; if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) @@ -4799,6 +4800,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) && !(gBattleStruct->intrepidSwordBoost[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])) { + gBattleScripting.savedBattler = gBattlerAttacker; gBattlerAttacker = battler; if (B_INTREPID_SWORD == GEN_9) gBattleStruct->intrepidSwordBoost[GetBattlerSide(battler)] |= gBitTable[gBattlerPartyIndexes[battler]]; @@ -4812,6 +4814,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN) && !(gBattleStruct->dauntlessShieldBoost[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])) { + gBattleScripting.savedBattler = gBattlerAttacker; gBattlerAttacker = battler; if (B_DAUNTLESS_SHIELD == GEN_9) gBattleStruct->dauntlessShieldBoost[GetBattlerSide(battler)] |= gBitTable[gBattlerPartyIndexes[battler]]; @@ -4922,6 +4925,46 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + case ABILITY_HOSPITALITY: + partner = BATTLE_PARTNER(battler); + + if (!gSpecialStatuses[battler].switchInAbilityDone && IsDoubleBattle() && gBattleMons[partner].hp < gBattleMons[partner].maxHP) + { + gBattlerTarget = partner; + gSpecialStatuses[battler].switchInAbilityDone = TRUE; + gBattleMoveDamage = (GetNonDynamaxMaxHP(partner) / 4) * -1; + BattleScriptPushCursorAndCallback(BattleScript_HospitalityActivates); + effect++; + } + break; + case ABILITY_EMBODY_ASPECT_TEAL: + case ABILITY_EMBODY_ASPECT_HEARTHFLAME: + case ABILITY_EMBODY_ASPECT_WELLSPRING: + case ABILITY_EMBODY_ASPECT_CORNERSTONE: + if (!gSpecialStatuses[battler].switchInAbilityDone) + { + u32 stat = STAT_SPATK; + + if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_TEAL) + stat = STAT_SPATK; + else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_HEARTHFLAME) + stat = STAT_ATK; + else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_WELLSPRING) + stat = STAT_SPDEF; + else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_CORNERSTONE) + stat = STAT_DEF; + + if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_EQUAL)) + break; + + gBattleScripting.savedBattler = gBattlerAttacker; + gBattlerAttacker = battler; + gSpecialStatuses[battler].switchInAbilityDone = TRUE; + SET_STATCHANGER(stat, 1, FALSE); + BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); + effect++; + } + break; } break; case ABILITYEFFECT_ENDTURN: // 1 diff --git a/src/item_use.c b/src/item_use.c index 6abec6498a..bce5d83ed6 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -78,7 +78,6 @@ static void SetDistanceOfClosestHiddenItem(u8, s16, s16); static void CB2_OpenPokeblockFromBag(void); static void ItemUseOnFieldCB_Honey(u8 taskId); static bool32 IsValidLocationForVsSeeker(void); -static bool32 CannotUseBagBattleItem(u16 itemId); // EWRAM variables EWRAM_DATA static void(*sItemUseOnFieldCB)(u8 taskId) = NULL; @@ -1142,11 +1141,13 @@ void ItemUseInBattle_PartyMenuChooseMove(u8 taskId) } // Returns whether an item can be used in battle and sets the fail text. -static bool32 CannotUseBagBattleItem(u16 itemId) +bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) { - u8 cannotUse = FALSE; u16 battleUsage = ItemId_GetBattleUsage(itemId); + bool8 cannotUse = FALSE; const u8* failStr = NULL; + u32 i; + u16 hp = GetMonData(mon, MON_DATA_HP); // Embargo Check if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO) @@ -1154,77 +1155,105 @@ static bool32 CannotUseBagBattleItem(u16 itemId) { return TRUE; } - // X-Items - if (battleUsage == EFFECT_ITEM_INCREASE_STAT - && gBattleMons[gBattlerInMenuId].statStages[gItemEffectTable[itemId][1]] == MAX_STAT_STAGE) - { - cannotUse++; - } - // Dire Hit - if (battleUsage == EFFECT_ITEM_SET_FOCUS_ENERGY - && (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY)) - { - cannotUse++; - } - // Guard Spec - if (battleUsage == EFFECT_ITEM_SET_MIST - && gSideStatuses[GetBattlerSide(gBattlerInMenuId)] & SIDE_STATUS_MIST) - { - cannotUse++; - } - // Escape Items - if (battleUsage == EFFECT_ITEM_ESCAPE - && gBattleTypeFlags & BATTLE_TYPE_TRAINER) - { - cannotUse++; - } - // Poke Balls - if (battleUsage == EFFECT_ITEM_THROW_BALL) + + // battleUsage checks + switch (battleUsage) { + case EFFECT_ITEM_INCREASE_STAT: + if (gBattleMons[gBattlerInMenuId].statStages[gItemEffectTable[itemId][1]] == MAX_STAT_STAGE) + cannotUse = TRUE; + break; + case EFFECT_ITEM_SET_FOCUS_ENERGY: + if (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY) + cannotUse = TRUE; + break; + case EFFECT_ITEM_SET_MIST: + if (gSideStatuses[GetBattlerSide(gBattlerInMenuId)] & SIDE_STATUS_MIST) + cannotUse = TRUE; + break; + case EFFECT_ITEM_ESCAPE: + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + cannotUse = TRUE; + break; + case EFFECT_ITEM_THROW_BALL: switch (GetBallThrowableState()) { - case BALL_THROW_UNABLE_TWO_MONS: - failStr = sText_CantThrowPokeBall_TwoMons; - cannotUse++; - break; - case BALL_THROW_UNABLE_NO_ROOM: - failStr = gText_BoxFull; - cannotUse++; - break; - case BALL_THROW_UNABLE_SEMI_INVULNERABLE: - failStr = sText_CantThrowPokeBall_SemiInvulnerable; - cannotUse++; - break; - case BALL_THROW_UNABLE_DISABLED_FLAG: - failStr = sText_CantThrowPokeBall_Disabled; - cannotUse++; - break; + case BALL_THROW_UNABLE_TWO_MONS: + failStr = sText_CantThrowPokeBall_TwoMons; + cannotUse = TRUE; + break; + case BALL_THROW_UNABLE_NO_ROOM: + failStr = gText_BoxFull; + cannotUse = TRUE; + break; + case BALL_THROW_UNABLE_SEMI_INVULNERABLE: + failStr = sText_CantThrowPokeBall_SemiInvulnerable; + cannotUse = TRUE; + break; + case BALL_THROW_UNABLE_DISABLED_FLAG: + failStr = sText_CantThrowPokeBall_Disabled; + cannotUse = TRUE; + break; } - } - // Max Mushrooms - if (battleUsage == EFFECT_ITEM_INCREASE_ALL_STATS) - { - u32 i; - for (i = 1; i < NUM_STATS; i++) + break; + case EFFECT_ITEM_INCREASE_ALL_STATS: + for (i = STAT_ATK; i < NUM_STATS; i++) { if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL)) { - cannotUse++; + cannotUse = TRUE; break; } } + break; + case EFFECT_ITEM_RESTORE_HP: + if (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP)) + cannotUse = TRUE; + break; + case EFFECT_ITEM_CURE_STATUS: + if (!((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) + || (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId)))) + cannotUse = TRUE; + break; + case EFFECT_ITEM_HEAL_AND_CURE_STATUS: + if ((hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP)) + && !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) + || (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId)))) + cannotUse = TRUE; + break; + case EFFECT_ITEM_REVIVE: + if (hp != 0) + cannotUse = TRUE; + break; + case EFFECT_ITEM_RESTORE_PP: + if (GetItemEffect(itemId)[6] == ITEM4_HEAL_PP) + { + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (GetMonData(mon, MON_DATA_PP1 + i) < CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + i), GetMonData(mon, MON_DATA_PP_BONUSES), i)); + break; + } + if (i == MAX_MON_MOVES) + cannotUse = TRUE; + } + else if (GetMonData(mon, MON_DATA_PP1 + gPartyMenu.data1) == CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + gPartyMenu.data1), GetMonData(mon, MON_DATA_PP_BONUSES), gPartyMenu.data1)) + { + cannotUse = TRUE; + } + break; } if (failStr != NULL) StringExpandPlaceholders(gStringVar4, failStr); else StringExpandPlaceholders(gStringVar4, gText_WontHaveEffect); + return cannotUse; } void ItemUseInBattle_BagMenu(u8 taskId) { - if (CannotUseBagBattleItem(gSpecialVar_ItemId)) + if (CannotUseItemsInBattle(gSpecialVar_ItemId, NULL)) { if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); diff --git a/src/party_menu.c b/src/party_menu.c index f333db02fb..e973100586 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -504,7 +504,6 @@ static bool8 SetUpFieldMove_Dive(void); void TryItemHoldFormChange(struct Pokemon *mon); static void ShowMoveSelectWindow(u8 slot); static void Task_HandleWhichMoveInput(u8 taskId); -static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon); // static const data #include "data/party_menu.h" @@ -4557,70 +4556,11 @@ static bool8 IsItemFlute(u16 item) return FALSE; } -static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon) -{ - u8 i; - u8 cannotUse = FALSE; - u16 battleUsage = ItemId_GetBattleUsage(itemId); - u16 hp = GetMonData(mon, MON_DATA_HP); - - // Embargo Check - if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO) - || (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO)) - { - return FALSE; - } - // Items that restore HP (Potions, Sitrus Berry, etc.) - if (battleUsage == EFFECT_ITEM_RESTORE_HP && (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))) - { - cannotUse++; - } - // Items that cure status (Burn Heal, Awakening, etc.) - if (battleUsage == EFFECT_ITEM_CURE_STATUS - && !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) - || (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId)))) - { - cannotUse++; - } - // Items that restore HP and cure status (Full Restore) - if (battleUsage == EFFECT_ITEM_HEAL_AND_CURE_STATUS - && (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP)) - && !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) - || (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId)))) - { - cannotUse++; - } - // Items that revive a party member - if (battleUsage == EFFECT_ITEM_REVIVE && hp != 0) - { - cannotUse++; - } - // Items that restore PP (Elixir, Ether, Leppa Berry) - if (battleUsage == EFFECT_ITEM_RESTORE_PP) - { - if (GetItemEffect(itemId)[6] == ITEM4_HEAL_PP) - { - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (GetMonData(mon, MON_DATA_PP1 + i) < CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + i), GetMonData(mon, MON_DATA_PP_BONUSES), i)); - break; - } - if (i == MAX_MON_MOVES) - cannotUse++; - } - else if (GetMonData(mon, MON_DATA_PP1 + gPartyMenu.data1) == CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + gPartyMenu.data1), GetMonData(mon, MON_DATA_PP_BONUSES), gPartyMenu.data1)) - { - cannotUse++; - } - } - return cannotUse; -} - // Battle scripts called in HandleAction_UseItem void ItemUseCB_BattleScript(u8 taskId, TaskFunc task) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; - if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon)) + if (CannotUseItemsInBattle(gSpecialVar_ItemId, mon)) { gPartyMenuUseExitCallback = FALSE; PlaySE(SE_SELECT); @@ -5129,7 +5069,7 @@ static void TryUseItemOnMove(u8 taskId) // In battle, set appropriate variables to be used in battle script. if (gMain.inBattle) { - if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon)) + if (CannotUseItemsInBattle(gSpecialVar_ItemId, mon)) { gPartyMenuUseExitCallback = FALSE; PlaySE(SE_SELECT); diff --git a/test/battle/ability/dauntless_shield.c b/test/battle/ability/dauntless_shield.c index eb7b5c15cb..b646d00b0d 100644 --- a/test/battle/ability/dauntless_shield.c +++ b/test/battle/ability/dauntless_shield.c @@ -3,7 +3,6 @@ ASSUMPTIONS { - ASSUME(P_GEN_8_POKEMON == TRUE); ASSUME(B_PROTEAN_LIBERO == GEN_9); } @@ -45,3 +44,23 @@ SINGLE_BATTLE_TEST("Dauntless Shield raises Attack by one stage only once per ba EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE); } } + +SINGLE_BATTLE_TEST("Dauntless Shield activates when it's no longer effected by Neutralizing Gas") +{ + GIVEN { + PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); } + } WHEN { + TURN { SWITCH(player, 1); } + } SCENE { + ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS); + MESSAGE("Neutralizing Gas filled the area!"); + MESSAGE("Weezing, that's enough! Come back!"); + MESSAGE("The effects of Neutralizing Gas wore off!"); + ABILITY_POPUP(opponent, ABILITY_DAUNTLESS_SHIELD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Zamazenta's Dauntless Shield raised its Defense!"); + } +} + diff --git a/test/battle/ability/embody_aspect.c b/test/battle/ability/embody_aspect.c new file mode 100644 index 0000000000..8b37dd1a74 --- /dev/null +++ b/test/battle/ability/embody_aspect.c @@ -0,0 +1,59 @@ +#include "global.h" +#include "test/battle.h" + + +SINGLE_BATTLE_TEST("Embodoy Aspect raises a stat depending on the users form by one stage") +{ + u16 species, ability; + + PARAMETRIZE { species = SPECIES_OGERPON_TEAL_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_TEAL; } + PARAMETRIZE { species = SPECIES_OGERPON_HEARTHFLAME_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_HEARTHFLAME; } + PARAMETRIZE { species = SPECIES_OGERPON_WELLSPRING_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_WELLSPRING; } + PARAMETRIZE { species = SPECIES_OGERPON_CORNERSTONE_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_CORNERSTONE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(opponent, ability); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + if (ability == ABILITY_EMBODY_ASPECT_TEAL) + MESSAGE("Foe Ogerpon's Embody Aspect raised its Sp. Atk!"); + else if (ability == ABILITY_EMBODY_ASPECT_HEARTHFLAME) + MESSAGE("Foe Ogerpon's Embody Aspect raised its Attack!"); + else if (ability == ABILITY_EMBODY_ASPECT_WELLSPRING) + MESSAGE("Foe Ogerpon's Embody Aspect raised its Sp. Def!"); + else if (ability == ABILITY_EMBODY_ASPECT_CORNERSTONE) + MESSAGE("Foe Ogerpon's Embody Aspect raised its Defense!"); + } THEN { + if (ability == ABILITY_EMBODY_ASPECT_TEAL) + EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + else if (ability == ABILITY_EMBODY_ASPECT_HEARTHFLAME) + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + else if (ability == ABILITY_EMBODY_ASPECT_WELLSPRING) + EXPECT_EQ(opponent->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + else if (ability == ABILITY_EMBODY_ASPECT_CORNERSTONE) + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Embodoy Aspect activates when it's no longer effected by Neutralizing Gas") +{ + GIVEN { + PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_OGERPON_TEAL_MASK_TERA) { Ability(ABILITY_EMBODY_ASPECT_TEAL); } + } WHEN { + TURN { SWITCH(player, 1); } + } SCENE { + ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS); + MESSAGE("Neutralizing Gas filled the area!"); + MESSAGE("Weezing, that's enough! Come back!"); + MESSAGE("The effects of Neutralizing Gas wore off!"); + ABILITY_POPUP(opponent, ABILITY_EMBODY_ASPECT_TEAL); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Ogerpon's Embody Aspect raised its Sp. Atk!"); + } +} diff --git a/test/battle/ability/hospitality.c b/test/battle/ability/hospitality.c new file mode 100644 index 0000000000..8bb78bffc0 --- /dev/null +++ b/test/battle/ability/hospitality.c @@ -0,0 +1,70 @@ +#include "global.h" +#include "test/battle.h" + +DOUBLE_BATTLE_TEST("Hospitality user restores 25% of ally's health") +{ + s16 health; + + PARAMETRIZE { health = 75; } + PARAMETRIZE { health = 100; } + + GIVEN { + PLAYER(SPECIES_POLTCHAGEIST) { Ability(ABILITY_HOSPITALITY); } + PLAYER(SPECIES_WOBBUFFET) { HP(health); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { } + } SCENE { + if (health == 75) { + ABILITY_POPUP(playerLeft, ABILITY_HOSPITALITY); + MESSAGE("The Wobbuffet drank down all the matcha that Sinistcha made!"); + HP_BAR(playerRight, damage: -25); + } else { + NONE_OF { + ABILITY_POPUP(playerLeft, ABILITY_HOSPITALITY); + MESSAGE("The Wobbuffet drank down all the matcha that Sinistcha made!"); + HP_BAR(playerRight, damage: -25); + } + } + } +} + +DOUBLE_BATTLE_TEST("Hospitality user restores 25% of ally's health on switch-in") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) + PLAYER(SPECIES_WOBBUFFET) { HP(75); MaxHP(100); } + PLAYER(SPECIES_POLTCHAGEIST) { Ability(ABILITY_HOSPITALITY); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(playerLeft, 2); } + } SCENE { + MESSAGE("Wobbuffet, that's enough! Come back!"); + MESSAGE("Go! Ptchageist!"); + ABILITY_POPUP(playerLeft, ABILITY_HOSPITALITY); + MESSAGE("The Wobbuffet drank down all the matcha that Sinistcha made!"); + HP_BAR(playerRight, damage: -25); + } +} + +DOUBLE_BATTLE_TEST("Hospitality ignores Substitute") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_POLTCHAGEIST) { Ability(ABILITY_HOSPITALITY); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerRight, MOVE_SUBSTITUTE); } + TURN { SWITCH(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, playerRight); + MESSAGE("Wobbuffet, that's enough! Come back!"); + MESSAGE("Go! Ptchageist!"); + ABILITY_POPUP(playerLeft, ABILITY_HOSPITALITY); + MESSAGE("The Wobbuffet drank down all the matcha that Sinistcha made!"); + } +} diff --git a/test/battle/ability/intrepid_sword.c b/test/battle/ability/intrepid_sword.c index 88228bbe78..9f2901a8d2 100644 --- a/test/battle/ability/intrepid_sword.c +++ b/test/battle/ability/intrepid_sword.c @@ -3,7 +3,6 @@ ASSUMPTIONS { - ASSUME(P_GEN_8_POKEMON == TRUE); ASSUME(B_INTREPID_SWORD == GEN_9); } @@ -45,3 +44,23 @@ SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage only once per batt EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); } } + +SINGLE_BATTLE_TEST("Intrepid Sword activates when it's no longer effected by Neutralizing Gas") +{ + GIVEN { + PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); } + } WHEN { + TURN { SWITCH(player, 1); } + } SCENE { + ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS); + MESSAGE("Neutralizing Gas filled the area!"); + MESSAGE("Weezing, that's enough! Come back!"); + MESSAGE("The effects of Neutralizing Gas wore off!"); + ABILITY_POPUP(opponent, ABILITY_INTREPID_SWORD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Zacian's Intrepid Sword raised its Attack!"); + } +} + diff --git a/test/battle/move_effect/hit_escape.c b/test/battle/move_effect/hit_escape.c index b9d1bc99e7..49a8c58627 100644 --- a/test/battle/move_effect/hit_escape.c +++ b/test/battle/move_effect/hit_escape.c @@ -98,7 +98,6 @@ SINGLE_BATTLE_TEST("U-turn switches the user out if Wimp Out fails to activate") SINGLE_BATTLE_TEST("U-turn switches the user out after Ice Face activates") { GIVEN { - ASSUME(P_GEN_8_POKEMON == TRUE); PLAYER(SPECIES_BEEDRILL); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_EISCUE) { Ability(ABILITY_ICE_FACE); }