Fixes Natural Gift moveend execution (#7274)

This commit is contained in:
Alex 2025-07-05 21:05:35 +02:00 committed by GitHub
parent 5cfab59209
commit f808201945
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 108 additions and 20 deletions

View File

@ -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

View File

@ -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,

View File

@ -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;
}

View File

@ -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")

BIN
tools/compresSmol/compresSmol Executable file

Binary file not shown.

Binary file not shown.