diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e32dfd2859..60432842f9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2841,13 +2841,7 @@ BattleScript_EffectNaturalGift:: jumpifability BS_ATTACKER, ABILITY_KLUTZ, BattleScript_ButItFailed jumpifstatus3 BS_ATTACKER, STATUS3_EMBARGO, BattleScript_ButItFailed accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE - call BattleScript_EffectHit_RetFromCritCalc - jumpifmovehadnoeffect BattleScript_EffectNaturalGiftEnd - checkparentalbondcounter 2, BattleScript_EffectNaturalGiftEnd - removeitem BS_ATTACKER -BattleScript_EffectNaturalGiftEnd: - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd + call BattleScript_HitFromCritCalc BattleScript_MakeMoveMissed:: setmoveresultflags MOVE_RESULT_MISSED diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 1da5f3b134..9e0556d8c5 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -283,8 +283,8 @@ enum MoveEndEffects MOVEEND_HIT_ESCAPE, MOVEEND_OPPORTUNIST, // Occurs after other stat change items/abilities to try and copy the boosts MOVEEND_PICKPOCKET, - MOVEEND_REMOVE_TERRAIN, MOVEEND_WHITE_HERB, + MOVEEND_THIRD_MOVE_BLOCK, MOVEEND_CHANGED_ITEMS, MOVEEND_SAME_MOVE_TURNS, MOVEEND_CLEAR_BITS, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 25edc5d759..664fa22f25 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -347,6 +347,7 @@ static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move); static void ResetValuesForCalledMove(void); static void TryRestoreDamageAfterCheekPouch(u32 battler); +static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd); static void Cmd_attackcanceler(void); static void Cmd_accuracycheck(void); @@ -7363,21 +7364,50 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_REMOVE_TERRAIN: - if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER // Steel Roller has to check the chosen move, Otherwise it would fail in certain cases - && IsBattlerTurnDamaged(gBattlerTarget)) + case MOVEEND_THIRD_MOVE_BLOCK: + // Special case for Steel Roller since it has to check the chosen move + if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER && IsBattlerTurnDamaged(gBattlerTarget)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_RemoveTerrain; effect = TRUE; + gBattleScripting.moveendState++; + break; } - else if (moveEffect == EFFECT_ICE_SPINNER - && IsBattlerAlive(gBattlerAttacker) - && IsBattlerTurnDamaged(gBattlerTarget)) + + switch (moveEffect) { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_RemoveTerrain; - effect = TRUE; + case EFFECT_ICE_SPINNER: + if (IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_RemoveTerrain; + effect = TRUE; + } + break; + case EFFECT_NATURAL_GIFT: + if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && GetItemPocket(gBattleMons[gBattlerAttacker].item) == POCKET_BERRIES) + { + u32 item = gBattleMons[gBattlerAttacker].item; + gBattleMons[gBattlerAttacker].item = ITEM_NONE; + gBattleStruct->battlerState[gBattlerAttacker].canPickupItem = TRUE; + gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)] = item; + CheckSetUnburden(gBattlerAttacker); + BtlController_EmitSetMonData( + gBattlerAttacker, + B_COMM_TO_CONTROLLER, + REQUEST_HELDITEM_BATTLE, + 0, + sizeof(gBattleMons[gBattlerAttacker].item), + &gBattleMons[gBattlerAttacker].item); + MarkBattlerForControllerExec(gBattlerAttacker); + ClearBattlerItemEffectHistory(gBattlerAttacker); + + if (!TrySymbiosis(gBattlerAttacker, item, TRUE)) + effect = TRUE; + } + default: + break; } gBattleScripting.moveendState++; break; @@ -9193,7 +9223,7 @@ static void BestowItem(u32 battlerAtk, u32 battlerDef) } // Called by Cmd_removeitem. itemId represents the item that was removed, not being given. -static bool32 TrySymbiosis(u32 battler, u32 itemId) +static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd) { if (!gBattleStruct->itemLost[B_SIDE_PLAYER][gBattlerPartyIndexes[battler]].stolen && gBattleStruct->changedItems[battler] == ITEM_NONE @@ -9207,7 +9237,10 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId) BestowItem(BATTLE_PARTNER(battler), battler); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability; gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler); - BattleScriptPush(gBattlescriptCurrInstr + 2); + if (moveEnd) + BattleScriptPushCursor(); + else + BattleScriptPush(gBattlescriptCurrInstr + 2); gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; return TRUE; } @@ -9245,7 +9278,7 @@ static void Cmd_removeitem(void) MarkBattlerForControllerExec(battler); ClearBattlerItemEffectHistory(battler); - if (!TryCheekPouch(battler, itemId) && !TrySymbiosis(battler, itemId)) + if (!TryCheekPouch(battler, itemId) && !TrySymbiosis(battler, itemId, FALSE)) gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/test/battle/move_effect/natural_gift.c b/test/battle/move_effect/natural_gift.c index dd9b0bd466..ab483db1da 100644 --- a/test/battle/move_effect/natural_gift.c +++ b/test/battle/move_effect/natural_gift.c @@ -1,4 +1,65 @@ #include "global.h" #include "test/battle.h" +SINGLE_BATTLE_TEST("Natural Gift removes berry if move fails due to an immunity") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PECHA_BERRY); } + OPPONENT(SPECIES_PHANPY); + } WHEN { + TURN { MOVE(player, MOVE_NATURAL_GIFT); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player); + } THEN { + EXPECT(player->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Natural Gift does not remove berry if user is ejected out") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PECHA_BERRY); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); } + } WHEN { + TURN { MOVE(player, MOVE_NATURAL_GIFT); } + TURN { SWITCH(player, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } THEN { + EXPECT(player->item == ITEM_PECHA_BERRY); + } +} + +SINGLE_BATTLE_TEST("Natural Gift does not remove berry if user is unable to use a move") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PECHA_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_THUNDER_WAVE); MOVE(player, MOVE_NATURAL_GIFT, WITH_RNG(RNG_PARALYSIS, FALSE)); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player); + } THEN { + EXPECT(player->item == ITEM_PECHA_BERRY); + } +} + +SINGLE_BATTLE_TEST("Natural Gift removes the berry if user missed") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PECHA_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SAND_ATTACK); MOVE(player, MOVE_NATURAL_GIFT, hit: FALSE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SAND_ATTACK, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player); + } THEN { + EXPECT(player->item == ITEM_NONE); + } +} + TO_DO_BATTLE_TEST("TODO: Write Natural Gift (Move Effect) test titles") diff --git a/tools/compresSmol/compresSmol b/tools/compresSmol/compresSmol new file mode 100755 index 0000000000..c518f8381b Binary files /dev/null and b/tools/compresSmol/compresSmol differ diff --git a/tools/compresSmol/compresSmolTilemap b/tools/compresSmol/compresSmolTilemap new file mode 100755 index 0000000000..63403b2a83 Binary files /dev/null and b/tools/compresSmol/compresSmolTilemap differ