From f6c08c08b6cbd0640551a4cc8825ec6e86daaa77 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:55:35 +0100 Subject: [PATCH] Fix item usage in double battles (#3977) * Fix item usage in double battles * fix failing tests --------- Co-authored-by: Eduardo Quezada D'Ottone --- data/battle_scripts_2.s | 20 +++++++++++++------- include/battle_scripts.h | 1 + include/pokemon.h | 2 +- src/battle_script_commands.c | 34 ++++++++++++++++++++-------------- src/pokemon.c | 18 +++++++++--------- 5 files changed, 44 insertions(+), 31 deletions(-) diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index 46d4d195ea..78e077fbd5 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -49,11 +49,17 @@ BattleScript_UseItemMessage: BattleScript_ItemRestoreHP:: call BattleScript_UseItemMessage itemrestorehp - jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_ItemRestoreHP_SendOutRevivedBattler bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_SCRIPTING + datahpupdate BS_SCRIPTING + printstring STRINGID_ITEMRESTOREDSPECIESHEALTH + waitmessage B_WAIT_TIME_LONG + end + +BattleScript_ItemRestoreHP_Party:: + jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_ItemRestoreHP_SendOutRevivedBattler + bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT printstring STRINGID_ITEMRESTOREDSPECIESHEALTH waitmessage B_WAIT_TIME_LONG end @@ -67,7 +73,7 @@ BattleScript_ItemRestoreHP_SendOutRevivedBattler: BattleScript_ItemCureStatus:: call BattleScript_UseItemMessage itemcurestatus - updatestatusicon BS_ATTACKER + updatestatusicon BS_SCRIPTING printstring STRINGID_ITEMCUREDSPECIESSTATUS waitmessage B_WAIT_TIME_LONG end @@ -80,9 +86,9 @@ BattleScript_ItemHealAndCureStatus:: waitmessage B_WAIT_TIME_LONG bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER - updatestatusicon BS_ATTACKER + healthbarupdate BS_SCRIPTING + datahpupdate BS_SCRIPTING + updatestatusicon BS_SCRIPTING printstring STRINGID_ITEMRESTOREDSPECIESHEALTH waitmessage B_WAIT_TIME_LONG end diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 4790998cc4..c2d7e74e48 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -490,6 +490,7 @@ extern const u8 BattleScript_TheRainbowDisappeared[]; extern const u8 BattleScript_HurtByTheSeaOfFire[]; extern const u8 BattleScript_TheSeaOfFireDisappeared[]; extern const u8 BattleScript_TheSwampDisappeared[]; +extern const u8 BattleScript_ItemRestoreHP_Party[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; diff --git a/include/pokemon.h b/include/pokemon.h index e86d710b37..5071a77a94 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -627,7 +627,7 @@ void PokemonToBattleMon(struct Pokemon *src, struct BattlePokemon *dst); void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex); bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex); bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex, u8 e); -bool8 HealStatusConditions(struct Pokemon *mon, u32 battlePartyId, u32 healMask, u8 battlerId); +bool8 HealStatusConditions(struct Pokemon *mon, u32 healMask, u8 battlerId); u8 GetItemEffectParamOffset(u32 battler, u16 itemId, u8 effectByte, u8 effectBit); u8 *UseStatIncreaseItem(u16 itemId); u8 GetNature(struct Pokemon *mon); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a509a4c8cb..5f946a2588 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14985,7 +14985,7 @@ static void Cmd_handleballthrow(void) if (gLastUsedItem == ITEM_HEAL_BALL) { MonRestorePP(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]); - HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], gBattlerPartyIndexes[gBattlerTarget], STATUS1_ANY, gBattlerTarget); + HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], STATUS1_ANY, gBattlerTarget); gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp); } @@ -15039,7 +15039,7 @@ static void Cmd_handleballthrow(void) if (gLastUsedItem == ITEM_HEAL_BALL) { MonRestorePP(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]); - HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], gBattlerPartyIndexes[gBattlerTarget], STATUS1_ANY, gBattlerTarget); + HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], STATUS1_ANY, gBattlerTarget); gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp); } @@ -15866,10 +15866,14 @@ void BS_ItemRestoreHP(void) if (hp + healAmount > maxHP) healAmount = maxHP - hp; + gBattleScripting.battler = battler; + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); + // Heal is applied as move damage if battler is active. if (battler != MAX_BATTLERS_COUNT && hp != 0) { gBattleMoveDamage = -healAmount; + gBattlescriptCurrInstr = cmd->nextInstr; } else { @@ -15880,21 +15884,18 @@ void BS_ItemRestoreHP(void) if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && battler != MAX_BATTLERS_COUNT) { gAbsentBattlerFlags &= ~gBitTable[battler]; - gBattleScripting.battler = battler; gBattleCommunication[MULTIUSE_STATE] = TRUE; } + gBattlescriptCurrInstr = BattleScript_ItemRestoreHP_Party; } - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); - gBattlescriptCurrInstr = cmd->nextInstr; } void BS_ItemCureStatus(void) { NATIVE_ARGS(); - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - - // Heal Status1 conditions. - HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], gBattleStruct->itemPartyIndex[gBattlerAttacker], GetItemStatus1Mask(gLastUsedItem), gBattlerAttacker); + u32 battler = gBattlerAttacker; + u32 side = GetBattlerSide(gBattlerAttacker); + struct Pokemon *party = GetSideParty(side); // Heal Status2 conditions if battler is active. if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) @@ -15905,14 +15906,18 @@ void BS_ItemCureStatus(void) && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) { gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); - gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker); + battler = BATTLE_PARTNER(gBattlerAttacker); } - if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; - if (GetItemStatus2Mask(gLastUsedItem) & STATUS2_CONFUSION) - gStatuses4[gBattlerAttacker] &= ~STATUS4_INFINITE_CONFUSION; + // Heal Status1 conditions. + HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), battler); + if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) + gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + if (GetItemStatus2Mask(gLastUsedItem) & STATUS2_CONFUSION) + gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; + + gBattleScripting.battler = battler; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -15975,6 +15980,7 @@ void BS_ItemRestorePP(void) } } } + gBattleScripting.battler = battler; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(mon, MON_DATA_SPECIES)); gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/src/pokemon.c b/src/pokemon.c index f46a443389..050e5e14d8 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -858,7 +858,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &iv); SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &iv); } - else if (P_LEGENDARY_PERFECT_IVS >= GEN_6 + else if (P_LEGENDARY_PERFECT_IVS >= GEN_6 && (gSpeciesInfo[species].isLegendary || gSpeciesInfo[species].isMythical || gSpeciesInfo[species].isUltraBeast)) @@ -1824,11 +1824,11 @@ void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition) gMultiuseSpriteTemplate.paletteTag = speciesTag; if (battlerPosition == B_POSITION_PLAYER_LEFT || battlerPosition == B_POSITION_PLAYER_RIGHT) gMultiuseSpriteTemplate.anims = gAnims_MonPic; - else + else { if (speciesTag > SPECIES_SHINY_TAG) speciesTag = speciesTag - SPECIES_SHINY_TAG; - + speciesTag = SanitizeSpeciesId(speciesTag); if (gSpeciesInfo[speciesTag].frontAnimFrames != NULL) gMultiuseSpriteTemplate.anims = gSpeciesInfo[speciesTag].frontAnimFrames; @@ -3206,15 +3206,15 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov } // Cure status - if ((itemEffect[i] & ITEM3_SLEEP) && HealStatusConditions(mon, partyIndex, STATUS1_SLEEP, battlerId) == 0) + if ((itemEffect[i] & ITEM3_SLEEP) && HealStatusConditions(mon, STATUS1_SLEEP, battlerId) == 0) retVal = FALSE; - if ((itemEffect[i] & ITEM3_POISON) && HealStatusConditions(mon, partyIndex, STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER, battlerId) == 0) + if ((itemEffect[i] & ITEM3_POISON) && HealStatusConditions(mon, STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER, battlerId) == 0) retVal = FALSE; - if ((itemEffect[i] & ITEM3_BURN) && HealStatusConditions(mon, partyIndex, STATUS1_BURN, battlerId) == 0) + if ((itemEffect[i] & ITEM3_BURN) && HealStatusConditions(mon, STATUS1_BURN, battlerId) == 0) retVal = FALSE; - if ((itemEffect[i] & ITEM3_FREEZE) && HealStatusConditions(mon, partyIndex, STATUS1_FREEZE | STATUS1_FROSTBITE, battlerId) == 0) + if ((itemEffect[i] & ITEM3_FREEZE) && HealStatusConditions(mon, STATUS1_FREEZE | STATUS1_FROSTBITE, battlerId) == 0) retVal = FALSE; - if ((itemEffect[i] & ITEM3_PARALYSIS) && HealStatusConditions(mon, partyIndex, STATUS1_PARALYSIS, battlerId) == 0) + if ((itemEffect[i] & ITEM3_PARALYSIS) && HealStatusConditions(mon, STATUS1_PARALYSIS, battlerId) == 0) retVal = FALSE; break; @@ -3550,7 +3550,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov return retVal; } -bool8 HealStatusConditions(struct Pokemon *mon, u32 battlePartyId, u32 healMask, u8 battlerId) +bool8 HealStatusConditions(struct Pokemon *mon, u32 healMask, u8 battlerId) { u32 status = GetMonData(mon, MON_DATA_STATUS, 0);