Fix cure status item effect not working properly in doubles (#8339)

This commit is contained in:
FosterProgramming 2025-11-24 18:34:00 +01:00 committed by GitHub
parent 1ea0500b95
commit 68a974af86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 130 additions and 15 deletions

View File

@ -1421,9 +1421,10 @@
.4byte \restoreBattlerInstr
.endm
.macro itemcurestatus jumpInstr:req
.macro itemcurestatus jumpInstr:req, restoreBattlerInstr:req
callnative BS_ItemCureStatus
.4byte \jumpInstr
.4byte \restoreBattlerInstr
.endm
.macro itemincreasestat

View File

@ -87,13 +87,18 @@ BattleScript_ItemRestoreHP_SendOutRevivedBattler:
BattleScript_ItemCureStatus::
call BattleScript_UseItemMessage
BattleScript_ItemCureStatusAfterItemMsg:
itemcurestatus BattleScript_ItemCureStatusEnd
updatestatusicon BS_SCRIPTING
itemcurestatus BattleScript_ItemCureStatusEnd, BattleScript_CureStatus_Battler
printstring STRINGID_ITEMCUREDSPECIESSTATUS
waitmessage B_WAIT_TIME_LONG
BattleScript_ItemCureStatusEnd:
end
BattleScript_CureStatus_Battler::
updatestatusicon BS_SCRIPTING
printstring STRINGID_ITEMCUREDSPECIESSTATUS
waitmessage B_WAIT_TIME_LONG
end
BattleScript_ItemHealAndCureStatus::
call BattleScript_UseItemMessage
itemrestorehp BattleScript_ItemCureStatusAfterItemMsg, BattleScript_ItemHealAndCureStatus_Battler

View File

@ -15202,37 +15202,49 @@ void BS_ItemRestoreHP(void)
void BS_ItemCureStatus(void)
{
NATIVE_ARGS(const u8 *noStatusInstr);
u32 battler = gBattlerAttacker;
NATIVE_ARGS(const u8 *noStatusInstr, const u8 *restoreBattlerInstr);
u32 targetBattler = MAX_BATTLERS_COUNT;
bool32 statusChanged = FALSE;
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
// Heal volatile conditions if battler is active.
if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker])
statusChanged = ItemHealMonVolatile(battler, gLastUsedItem);
{
statusChanged = ItemHealMonVolatile(gBattlerAttacker, gLastUsedItem);
targetBattler = gBattlerAttacker;
}
else if (IsDoubleBattle()
&& gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)])
{
statusChanged = ItemHealMonVolatile(BATTLE_PARTNER(gBattlerAttacker), gLastUsedItem);
targetBattler = BATTLE_PARTNER(gBattlerAttacker);
}
// Heal Status1 conditions.
if (!HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), battler))
if (!HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), targetBattler))
{
statusChanged = TRUE;
if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP)
gBattleMons[battler].volatiles.nightmare = FALSE;
gBattleMons[targetBattler].volatiles.nightmare = FALSE;
if (ItemHasVolatileFlag(gLastUsedItem, VOLATILE_CONFUSION))
gBattleMons[battler].volatiles.infiniteConfusion = FALSE;
gBattleMons[targetBattler].volatiles.infiniteConfusion = FALSE;
}
if (statusChanged)
if (!statusChanged)
{
gBattlescriptCurrInstr = cmd->noStatusInstr;
return;
}
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES));
if (targetBattler == MAX_BATTLERS_COUNT)
{
gBattleScripting.battler = battler;
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES));
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
{
gBattlescriptCurrInstr = cmd->noStatusInstr;
gBattleScripting.battler = targetBattler;
gBattlescriptCurrInstr = cmd->restoreBattlerInstr;
}
}

View File

@ -31,6 +31,29 @@ SINGLE_BATTLE_TEST("Antidote heals a battler from being poisoned")
}
}
DOUBLE_BATTLE_TEST("Antidote heals a battler from being poisoned (doubles)")
{
u32 index;
struct BattlePokemon *user = NULL;
struct BattlePokemon *target = NULL;
PARAMETRIZE { index = 0; user = playerRight; target = playerLeft;}
PARAMETRIZE { index = 1; user = playerLeft; target = playerRight;}
PARAMETRIZE { index = 0; user = playerLeft; target = playerLeft;}
PARAMETRIZE { index = 1; user = playerRight; target = playerRight; }
GIVEN {
ASSUME(gItemsInfo[ITEM_ANTIDOTE].battleUsage == EFFECT_ITEM_CURE_STATUS);
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); }
PLAYER(SPECIES_WYNAUT) { }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { USE_ITEM(user, ITEM_ANTIDOTE, partyIndex: index); }
} THEN {
EXPECT_EQ(target->status1, STATUS1_NONE);
}
}
SINGLE_BATTLE_TEST("Antidote heals a battler from being badly poisoned")
{
GIVEN {
@ -135,6 +158,43 @@ SINGLE_BATTLE_TEST("Full Heal heals a battler from any primary status")
}
}
DOUBLE_BATTLE_TEST("Full Heal heals a battler from any primary status (doubles)")
{
u32 statusParameters[7] =
{
STATUS1_SLEEP,
STATUS1_POISON,
STATUS1_BURN,
STATUS1_FREEZE,
STATUS1_PARALYSIS,
STATUS1_TOXIC_POISON,
STATUS1_FROSTBITE
};
u16 status = 0;
u32 index = 0;
struct BattlePokemon *user = NULL;
struct BattlePokemon *target = NULL;
for (u32 j = 0; j < 7; j++)
{
PARAMETRIZE {status = statusParameters[j]; user = playerRight; target = playerLeft; index = 0;}
PARAMETRIZE {status = statusParameters[j]; user = playerLeft; target = playerRight; index = 1;}
PARAMETRIZE {status = statusParameters[j]; user = playerLeft; target = playerLeft; index = 0;}
PARAMETRIZE {status = statusParameters[j]; user = playerRight; target = playerRight; index = 1;}
}
GIVEN {
ASSUME(gItemsInfo[ITEM_FULL_HEAL].battleUsage == EFFECT_ITEM_CURE_STATUS);
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { USE_ITEM(user, ITEM_FULL_HEAL, partyIndex: index); }
} THEN {
EXPECT_EQ(target->status1, STATUS1_NONE);
}
}
SINGLE_BATTLE_TEST("Heal Powder heals a battler from any primary status")
{
u16 status;
@ -158,6 +218,43 @@ SINGLE_BATTLE_TEST("Heal Powder heals a battler from any primary status")
}
}
DOUBLE_BATTLE_TEST("Heal Powder heals a battler from any primary status (doubles)")
{
u32 statusParameters[7] =
{
STATUS1_SLEEP,
STATUS1_POISON,
STATUS1_BURN,
STATUS1_FREEZE,
STATUS1_PARALYSIS,
STATUS1_TOXIC_POISON,
STATUS1_FROSTBITE
};
u16 status = 0;
u32 index = 0;
struct BattlePokemon *user = NULL;
struct BattlePokemon *target = NULL;
for (u32 j = 0; j < 7; j++)
{
PARAMETRIZE {status = statusParameters[j]; user = playerRight; target = playerLeft; index = 0;}
PARAMETRIZE {status = statusParameters[j]; user = playerLeft; target = playerRight; index = 1;}
PARAMETRIZE {status = statusParameters[j]; user = playerLeft; target = playerLeft; index = 0;}
PARAMETRIZE {status = statusParameters[j]; user = playerRight; target = playerRight; index = 1;}
}
GIVEN {
ASSUME(gItemsInfo[ITEM_HEAL_POWDER].battleUsage == EFFECT_ITEM_CURE_STATUS);
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { USE_ITEM(user, ITEM_HEAL_POWDER, partyIndex: index); }
} THEN {
EXPECT_EQ(target->status1, STATUS1_NONE);
}
}
SINGLE_BATTLE_TEST("Pewter Crunchies heals a battler from any primary status")
{
u16 status;

View File

@ -43,8 +43,8 @@ SINGLE_BATTLE_TEST("Full Restore restores a party members HP and cures any prima
PARAMETRIZE { status = STATUS1_SLEEP; }
PARAMETRIZE { status = STATUS1_NONE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(300); Status1(status); }
PLAYER(SPECIES_WYNAUT) { HP(1); MaxHP(300); Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { HP(100); MaxHP(300); Status1(status); }
PLAYER(SPECIES_WYNAUT) { HP(100); MaxHP(300); Status1(status); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { USE_ITEM(player, ITEM_FULL_RESTORE, partyIndex: 1); }