Heal Bell/Aromatherapy/Sparkly Swirl improvements and fixes (#6210)

This commit is contained in:
Eduardo Quezada 2025-02-09 17:54:03 -03:00 committed by GitHub
parent 5f13f9545f
commit a2ad5d2ca3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 230 additions and 185 deletions

View File

@ -956,15 +956,6 @@ BattleScript_MoveEffectIonDeluge::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
return return
BattleScript_EffectSparklySwirl::
call BattleScript_EffectHit_Ret
tryfaintmon BS_TARGET
healpartystatus
waitstate
updatestatusicon BS_ATTACKER_WITH_PARTNER
waitstate
goto BattleScript_MoveEnd
BattleScript_MoveEffectHaze:: BattleScript_MoveEffectHaze::
printstring STRINGID_STATCHANGESGONE printstring STRINGID_STATCHANGESGONE
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
@ -4075,13 +4066,16 @@ BattleScript_EffectHealBell::
attackcanceler attackcanceler
attackstring attackstring
ppreduce ppreduce
healpartystatus
waitstate
attackanimation attackanimation
waitanimation waitanimation
BattleScript_EffectHealBell_FromHeal::
healpartystatus
waitstate
printfromtable gPartyStatusHealStringIds printfromtable gPartyStatusHealStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
jumpifnotmove MOVE_HEAL_BELL, BattleScript_PartyHealEnd jumpifblockedbysoundproof BS_ATTACKER_PARTNER, BattleScript_HealBellSoundproof
goto BattleScript_PartyHealEnd
BattleScript_HealBellSoundproof::
jumpifbyte CMP_NO_COMMON_BITS, cMULTISTRING_CHOOSER, B_MSG_BELL_SOUNDPROOF_ATTACKER, BattleScript_CheckHealBellMon2Unaffected jumpifbyte CMP_NO_COMMON_BITS, cMULTISTRING_CHOOSER, B_MSG_BELL_SOUNDPROOF_ATTACKER, BattleScript_CheckHealBellMon2Unaffected
printstring STRINGID_PKMNSXBLOCKSY printstring STRINGID_PKMNSXBLOCKSY
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
@ -9966,29 +9960,6 @@ BattleScript_HealOneSixthAlliesEnd:
restoretarget restoretarget
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
BattleScript_EffectCureStatusAllies::
jumpifteamhealthy BS_ATTACKER, BattleScript_MoveEnd
savetarget
copybyte gBattlerTarget, gBattlerAttacker
BattleScript_CureStatusAlliesLoop:
jumpifabsent BS_TARGET, BattleScript_CureStatusAlliesIncrement
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_CureStatusActivate
BattleScript_CureStatusAlliesIncrement:
jumpifbytenotequal gBattlerTarget, gBattlerAttacker, BattleScript_CureStatusAlliesEnd
setallytonexttarget BattleScript_CureStatusAlliesLoop
BattleScript_CureStatusAlliesEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_CureStatusActivate:
curestatus BS_TARGET
updatestatusicon BS_TARGET
swapattackerwithtarget
printstring STRINGID_PKMNSTATUSNORMAL
waitmessage B_WAIT_TIME_LONG
swapattackerwithtarget
goto BattleScript_CureStatusAlliesIncrement
BattleScript_EffectRecycleBerriesAllies:: BattleScript_EffectRecycleBerriesAllies::
savetarget savetarget
copybyte gBattlerTarget, gBattlerAttacker copybyte gBattlerTarget, gBattlerAttacker

View File

@ -17,6 +17,7 @@
#include "battle_dynamax.h" #include "battle_dynamax.h"
#include "battle_terastal.h" #include "battle_terastal.h"
#include "battle_gimmick.h" #include "battle_gimmick.h"
#include "generational_changes.h"
#include "move.h" #include "move.h"
#include "random.h" // for rng_value_t #include "random.h" // for rng_value_t
#include "trainer_slide.h" #include "trainer_slide.h"

View File

@ -554,7 +554,6 @@ extern const u8 BattleScript_EffectMeanLookSide[];
extern const u8 BattleScript_TormentEnds[]; extern const u8 BattleScript_TormentEnds[];
extern const u8 BattleScript_EffectRaiseCritAlliesAnim[]; extern const u8 BattleScript_EffectRaiseCritAlliesAnim[];
extern const u8 BattleScript_EffectHealOneSixthAllies[]; extern const u8 BattleScript_EffectHealOneSixthAllies[];
extern const u8 BattleScript_EffectCureStatusAllies[];
extern const u8 BattleScript_EffectRecycleBerriesAllies[]; extern const u8 BattleScript_EffectRecycleBerriesAllies[];
extern const u8 BattleScript_RemoveGenericType[]; extern const u8 BattleScript_RemoveGenericType[];
@ -644,6 +643,7 @@ extern const u8 BattleScript_EffectSleepTalk[];
extern const u8 BattleScript_EffectDestinyBond[]; extern const u8 BattleScript_EffectDestinyBond[];
extern const u8 BattleScript_EffectSpite[]; extern const u8 BattleScript_EffectSpite[];
extern const u8 BattleScript_EffectHealBell[]; extern const u8 BattleScript_EffectHealBell[];
extern const u8 BattleScript_EffectHealBell_FromHeal[];
extern const u8 BattleScript_EffectMeanLook[]; extern const u8 BattleScript_EffectMeanLook[];
extern const u8 BattleScript_EffectNightmare[]; extern const u8 BattleScript_EffectNightmare[];
extern const u8 BattleScript_EffectMinimize[]; extern const u8 BattleScript_EffectMinimize[];
@ -822,7 +822,6 @@ extern const u8 BattleScript_MoveEffectLightScreen[];
extern const u8 BattleScript_MoveEffectReflect[]; extern const u8 BattleScript_MoveEffectReflect[];
extern const u8 BattleScript_MoveEffectLeechSeed[]; extern const u8 BattleScript_MoveEffectLeechSeed[];
extern const u8 BattleScript_MoveEffectHaze[]; extern const u8 BattleScript_MoveEffectHaze[];
extern const u8 BattleScript_EffectSparklySwirl[];
extern const u8 BattleScript_MoveEffectIonDeluge[]; extern const u8 BattleScript_MoveEffectIonDeluge[];
extern const u8 BattleScript_EffectHyperspaceFury[]; extern const u8 BattleScript_EffectHyperspaceFury[];
extern const u8 BattleScript_EffectAuraWheel[]; extern const u8 BattleScript_EffectAuraWheel[];

View File

@ -295,7 +295,6 @@ enum {
EFFECT_RECOIL_HP_25, EFFECT_RECOIL_HP_25,
EFFECT_STUFF_CHEEKS, EFFECT_STUFF_CHEEKS,
EFFECT_GRAV_APPLE, EFFECT_GRAV_APPLE,
EFFECT_SPARKLY_SWIRL,
EFFECT_HYPERSPACE_FURY, EFFECT_HYPERSPACE_FURY,
EFFECT_AURA_WHEEL, EFFECT_AURA_WHEEL,
EFFECT_PHOTON_GEYSER, EFFECT_PHOTON_GEYSER,

View File

@ -4,6 +4,7 @@
enum GenConfigTag enum GenConfigTag
{ {
GEN_CONFIG_GALE_WINGS, GEN_CONFIG_GALE_WINGS,
GEN_CONFIG_HEAL_BELL_SOUNDPROOF,
GEN_CONFIG_COUNT GEN_CONFIG_COUNT
}; };

View File

@ -6,7 +6,8 @@
static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] =
{ {
[GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS, [GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS,
[GEN_CONFIG_HEAL_BELL_SOUNDPROOF] = B_HEAL_BELL_SOUNDPROOF,
}; };
#if TESTING #if TESTING

View File

@ -3160,7 +3160,9 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
battlerOnField1 = gBattlerPartyIndexes[battlerId]; battlerOnField1 = gBattlerPartyIndexes[battlerId];
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battlerId)))]; battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battlerId)))];
// Check partner's status // Check partner's status
if ((B_HEAL_BELL_SOUNDPROOF == GEN_5 || AI_DATA->abilities[BATTLE_PARTNER(battlerId)] != ABILITY_SOUNDPROOF || !checkSoundproof) if ((GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|| AI_DATA->abilities[BATTLE_PARTNER(battlerId)] != ABILITY_SOUNDPROOF
|| !checkSoundproof)
&& GetMonData(&party[battlerOnField2], MON_DATA_STATUS) != STATUS1_NONE) && GetMonData(&party[battlerOnField2], MON_DATA_STATUS) != STATUS1_NONE)
return TRUE; return TRUE;
} }
@ -3171,7 +3173,8 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
} }
// Check attacker's status // Check attacker's status
if ((B_HEAL_BELL_SOUNDPROOF == GEN_5 || B_HEAL_BELL_SOUNDPROOF >= GEN_8 if ((GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|| GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8
|| AI_DATA->abilities[battlerId] != ABILITY_SOUNDPROOF || !checkSoundproof) || AI_DATA->abilities[battlerId] != ABILITY_SOUNDPROOF || !checkSoundproof)
&& GetMonData(&party[battlerOnField1], MON_DATA_STATUS) != STATUS1_NONE) && GetMonData(&party[battlerOnField1], MON_DATA_STATUS) != STATUS1_NONE)
return TRUE; return TRUE;
@ -3181,7 +3184,9 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
{ {
if (i == battlerOnField1 || i == battlerOnField2) if (i == battlerOnField1 || i == battlerOnField2)
continue; continue;
if (B_HEAL_BELL_SOUNDPROOF < GEN_5 && checkSoundproof && GetMonAbility(&party[i]) == ABILITY_SOUNDPROOF) if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) < GEN_5
&& checkSoundproof
&& GetMonAbility(&party[i]) == ABILITY_SOUNDPROOF)
continue; continue;
if (GetMonData(&party[i], MON_DATA_STATUS) != STATUS1_NONE) if (GetMonData(&party[i], MON_DATA_STATUS) != STATUS1_NONE)
return TRUE; return TRUE;

View File

@ -25,7 +25,6 @@
#include "event_data.h" #include "event_data.h"
#include "evolution_scene.h" #include "evolution_scene.h"
#include "field_weather.h" #include "field_weather.h"
#include "generational_changes.h"
#include "graphics.h" #include "graphics.h"
#include "gpu_regs.h" #include "gpu_regs.h"
#include "international_string_util.h" #include "international_string_util.h"

View File

@ -4633,7 +4633,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
break; break;
case MOVE_EFFECT_AROMATHERAPY: case MOVE_EFFECT_AROMATHERAPY:
BattleScriptPush(gBattlescriptCurrInstr + 1); BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectCureStatusAllies; gBattlescriptCurrInstr = BattleScript_EffectHealBell_FromHeal;
break; break;
case MOVE_EFFECT_RECYCLE_BERRIES: case MOVE_EFFECT_RECYCLE_BERRIES:
{ {
@ -13946,106 +13946,87 @@ static void Cmd_healpartystatus(void)
{ {
CMD_ARGS(); CMD_ARGS();
u32 zero = 0; u32 i, zero = 0;
u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker)));
u8 toHeal = 0; u8 toHeal = 0;
struct Pokemon *party = GetBattlerParty(gBattlerAttacker); struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
s32 i; bool32 isSoundMove = IsSoundMove(gCurrentMove);
if (gCurrentMove == MOVE_HEAL_BELL) if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|| GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8
|| !(isSoundMove && GetBattlerAbility(gBattlerAttacker) == ABILITY_SOUNDPROOF))
{ {
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL; if (isSoundMove)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL;
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF
|| B_HEAL_BELL_SOUNDPROOF == GEN_5 || B_HEAL_BELL_SOUNDPROOF >= GEN_8)
{
gBattleMons[gBattlerAttacker].status1 = 0;
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
}
else else
{ gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOOTHING_AROMA;
RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability);
gBattleCommunication[MULTISTRING_CHOOSER] |= B_MSG_BELL_SOUNDPROOF_ATTACKER;
}
gBattleScripting.battler = partner;
if (IsBattlerAlive(partner))
{
if (GetBattlerAbility(partner) != ABILITY_SOUNDPROOF || B_HEAL_BELL_SOUNDPROOF == GEN_5)
{
gBattleMons[partner].status1 = 0;
gBattleMons[partner].status2 &= ~STATUS2_NIGHTMARE;
}
else
{
RecordAbilityBattle(partner, gBattleMons[partner].ability);
gBattleCommunication[MULTISTRING_CHOOSER] |= B_MSG_BELL_SOUNDPROOF_PARTNER;
}
}
// Because the above MULTISTRING_CHOOSER are ORd, if both are set then it will be B_MSG_BELL_BOTH_SOUNDPROOF
for (i = 0; i < PARTY_SIZE; i++)
{
u16 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG);
u8 abilityNum = GetMonData(&party[i], MON_DATA_ABILITY_NUM);
if (species != SPECIES_NONE && species != SPECIES_EGG)
{
u16 ability;
bool32 isAttacker = gBattlerPartyIndexes[gBattlerAttacker] == i;
bool32 isDoublesPartner = gBattlerPartyIndexes[partner] == i && IsBattlerAlive(partner);
if (B_HEAL_BELL_SOUNDPROOF == GEN_5 || (isAttacker && B_HEAL_BELL_SOUNDPROOF >= GEN_8))
ability = ABILITY_NONE;
else if (B_HEAL_BELL_SOUNDPROOF > GEN_5 && !isAttacker && !isDoublesPartner)
ability = ABILITY_NONE;
else if (isAttacker)
ability = GetBattlerAbility(gBattlerAttacker);
else if (isDoublesPartner)
ability = GetBattlerAbility(partner);
else
{
ability = GetAbilityBySpecies(species, abilityNum);
#if TESTING
if (gTestRunnerEnabled)
{
u32 side = GetBattlerSide(gBattlerAttacker);
if (TestRunner_Battle_GetForcedAbility(side, i))
ability = TestRunner_Battle_GetForcedAbility(side, i);
}
#endif
}
if (ability != ABILITY_SOUNDPROOF)
{
toHeal |= (1 << i);
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i);
}
}
}
}
else // Aromatherapy
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOOTHING_AROMA;
toHeal = (1 << PARTY_SIZE) - 1;
for (i = 0; i < PARTY_SIZE; i++)
{
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i);
}
gBattleMons[gBattlerAttacker].status1 = 0; gBattleMons[gBattlerAttacker].status1 = 0;
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
}
else
{
RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL_SOUNDPROOF_ATTACKER;
}
if (IsDoubleBattle() gBattleScripting.battler = partner;
&& !(gAbsentBattlerFlags & (1u <<partner)))
if (IsBattlerAlive(partner))
{
if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|| !(isSoundMove && GetBattlerAbility(partner) == ABILITY_SOUNDPROOF))
{ {
gBattleMons[partner].status1 = 0; gBattleMons[partner].status1 = 0;
gBattleMons[partner].status2 &= ~STATUS2_NIGHTMARE; gBattleMons[partner].status2 &= ~STATUS2_NIGHTMARE;
} }
else
{
RecordAbilityBattle(partner, gBattleMons[partner].ability);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL_SOUNDPROOF_PARTNER;
}
}
// Because the above MULTISTRING_CHOOSER are ORd, if both are set then it will be B_MSG_BELL_BOTH_SOUNDPROOF
for (i = 0; i < PARTY_SIZE; i++)
{
u16 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG);
u8 abilityNum = GetMonData(&party[i], MON_DATA_ABILITY_NUM);
if (species != SPECIES_NONE && species != SPECIES_EGG)
{
u16 ability;
bool32 isAttacker = gBattlerPartyIndexes[gBattlerAttacker] == i;
bool32 isDoublesPartner = gBattlerPartyIndexes[partner] == i && IsBattlerAlive(partner);
if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|| (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 && isAttacker))
ability = ABILITY_NONE;
else if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) > GEN_5 && !isAttacker && !isDoublesPartner)
ability = ABILITY_NONE;
else if (isAttacker)
ability = GetBattlerAbility(gBattlerAttacker);
else if (isDoublesPartner)
ability = GetBattlerAbility(partner);
else
{
ability = GetAbilityBySpecies(species, abilityNum);
#if TESTING
if (gTestRunnerEnabled)
{
u32 side = GetBattlerSide(gBattlerAttacker);
if (TestRunner_Battle_GetForcedAbility(side, i))
ability = TestRunner_Battle_GetForcedAbility(side, i);
}
#endif
}
if (!(isSoundMove && ability == ABILITY_SOUNDPROOF))
{
toHeal |= (1 << i);
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i);
}
}
} }
if (toHeal) if (toHeal)

View File

@ -1895,12 +1895,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
.battleTvScore = 0, // TODO: Assign points .battleTvScore = 0, // TODO: Assign points
}, },
[EFFECT_SPARKLY_SWIRL] =
{
.battleScript = BattleScript_EffectSparklySwirl,
.battleTvScore = 0, // TODO: Assign points
},
[EFFECT_HYPERSPACE_FURY] = [EFFECT_HYPERSPACE_FURY] =
{ {
.battleScript = BattleScript_EffectHyperspaceFury, .battleScript = BattleScript_EffectHyperspaceFury,

View File

@ -17068,7 +17068,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.description = COMPOUND_STRING( .description = COMPOUND_STRING(
"Wrap foe with whirlwind of\n" "Wrap foe with whirlwind of\n"
"scent. Heals party's status."), "scent. Heals party's status."),
.effect = EFFECT_SPARKLY_SWIRL, // Temprorary .effect = EFFECT_HIT,
.power = B_UPDATED_MOVE_DATA >= GEN_8 ? 120 : 90, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 120 : 90,
.type = TYPE_FAIRY, .type = TYPE_FAIRY,
.accuracy = B_UPDATED_MOVE_DATA >= GEN_8 ? 85 : 100, .accuracy = B_UPDATED_MOVE_DATA >= GEN_8 ? 85 : 100,
@ -17078,11 +17078,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.category = DAMAGE_CATEGORY_SPECIAL, .category = DAMAGE_CATEGORY_SPECIAL,
.mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8,
.metronomeBanned = TRUE, .metronomeBanned = TRUE,
// .additionalEffects = ADDITIONAL_EFFECTS({ .additionalEffects = ADDITIONAL_EFFECTS({
// .moveEffect = 0, // MOVE_EFFECT_AROMATHERAPY, Added 0 for Sheer Force boost .moveEffect = MOVE_EFFECT_AROMATHERAPY,
// .chance = 100, .chance = 100,
// .sheerForceBoost = SHEER_FORCE_NO_BOOST, .sheerForceBoost = SHEER_FORCE_NO_BOOST,
// }), }),
.battleAnimScript = gBattleAnimMove_SparklySwirl, .battleAnimScript = gBattleAnimMove_SparklySwirl,
}, },

View File

@ -203,7 +203,7 @@ AI_DOUBLE_BATTLE_TEST("AI chooses moves that cure self or partner")
GIVEN { GIVEN {
ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL);
ASSUME(B_HEAL_BELL_SOUNDPROOF >= GEN_8); WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, GEN_8);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET);
@ -219,21 +219,22 @@ AI_DOUBLE_BATTLE_TEST("AI chooses moves that cure self or partner")
AI_SINGLE_BATTLE_TEST("AI chooses moves that cure inactive party members") AI_SINGLE_BATTLE_TEST("AI chooses moves that cure inactive party members")
{ {
u32 status, ability; u32 status, ability, config;
PARAMETRIZE { status = STATUS1_TOXIC_POISON; ability = ABILITY_SCRAPPY; } PARAMETRIZE { status = STATUS1_TOXIC_POISON; ability = ABILITY_SCRAPPY; }
PARAMETRIZE { status = STATUS1_NONE; ability = ABILITY_SCRAPPY; } PARAMETRIZE { status = STATUS1_NONE; ability = ABILITY_SCRAPPY; }
PARAMETRIZE { status = STATUS1_TOXIC_POISON; ability = ABILITY_SOUNDPROOF; } PARAMETRIZE { status = STATUS1_TOXIC_POISON; ability = ABILITY_SOUNDPROOF; config = GEN_4; }
PARAMETRIZE { status = STATUS1_TOXIC_POISON; ability = ABILITY_SOUNDPROOF; config = GEN_5; }
GIVEN { GIVEN {
ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL);
ASSUME(B_HEAL_BELL_SOUNDPROOF >= GEN_5); WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, config);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_REGIROCK) { Moves(MOVE_BODY_PRESS, MOVE_HEAL_BELL); } OPPONENT(SPECIES_REGIROCK) { Moves(MOVE_BODY_PRESS, MOVE_HEAL_BELL); }
OPPONENT(SPECIES_EXPLOUD) { Status1(status); Ability(ability); } OPPONENT(SPECIES_EXPLOUD) { Status1(status); Ability(ability); }
} WHEN { } WHEN {
if (status == STATUS1_NONE) if (status == STATUS1_NONE || (ability == ABILITY_SOUNDPROOF && config <= GEN_4))
TURN { EXPECT_MOVE(opponent, MOVE_BODY_PRESS); } TURN { EXPECT_MOVE(opponent, MOVE_BODY_PRESS); }
else else
TURN { EXPECT_MOVE(opponent, MOVE_HEAL_BELL); } TURN { EXPECT_MOVE(opponent, MOVE_HEAL_BELL); }

View File

@ -1376,10 +1376,15 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Finale heals allies by 1/6 of their health")
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions") DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions")
{ {
u32 j;
GIVEN { GIVEN {
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_SWEETNESS, MOVE_EFFECT_AROMATHERAPY)); ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_SWEETNESS, MOVE_EFFECT_AROMATHERAPY));
PLAYER(SPECIES_APPLETUN) { Status1(STATUS1_POISON); GigantamaxFactor(TRUE); } PLAYER(SPECIES_APPLETUN) { Status1(STATUS1_POISON); GigantamaxFactor(TRUE); }
PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); } PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); }
PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); }
PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); }
PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); }
PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); }
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
} WHEN { } WHEN {
@ -1387,9 +1392,10 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions")
} SCENE { } SCENE {
MESSAGE("Appletun used G-Max Sweetness!"); MESSAGE("Appletun used G-Max Sweetness!");
STATUS_ICON(playerLeft, none: TRUE); STATUS_ICON(playerLeft, none: TRUE);
MESSAGE("Appletun's status returned to normal!");
STATUS_ICON(playerRight, none: TRUE); STATUS_ICON(playerRight, none: TRUE);
MESSAGE("Applin's status returned to normal!"); } THEN {
for (j = 0; j < PARTY_SIZE; j++)
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_STATUS), STATUS1_NONE);
} }
} }

View File

@ -4,48 +4,70 @@
ASSUMPTIONS ASSUMPTIONS
{ {
ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL);
ASSUME(GetMoveEffect(MOVE_AROMATHERAPY) == EFFECT_HEAL_BELL);
} }
DOUBLE_BATTLE_TEST("Heal Bell cures the entire party") DOUBLE_BATTLE_TEST("Heal Bell/Aromatherapy cures the entire party of the user from primary status effects")
{ {
u32 move; u32 j, move, status;
PARAMETRIZE { move = MOVE_HEAL_BELL; status = STATUS1_SLEEP; }
PARAMETRIZE { move = MOVE_HEAL_BELL; } PARAMETRIZE { move = MOVE_AROMATHERAPY; status = STATUS1_SLEEP; }
PARAMETRIZE { move = MOVE_AROMATHERAPY; } PARAMETRIZE { move = MOVE_HEAL_BELL; status = STATUS1_POISON; }
PARAMETRIZE { move = MOVE_AROMATHERAPY; status = STATUS1_POISON; }
PARAMETRIZE { move = MOVE_HEAL_BELL; status = STATUS1_BURN; }
PARAMETRIZE { move = MOVE_AROMATHERAPY; status = STATUS1_BURN; }
PARAMETRIZE { move = MOVE_HEAL_BELL; status = STATUS1_FREEZE; }
PARAMETRIZE { move = MOVE_AROMATHERAPY; status = STATUS1_FREEZE; }
PARAMETRIZE { move = MOVE_HEAL_BELL; status = STATUS1_PARALYSIS; }
PARAMETRIZE { move = MOVE_AROMATHERAPY; status = STATUS1_PARALYSIS; }
PARAMETRIZE { move = MOVE_HEAL_BELL; status = STATUS1_TOXIC_POISON; }
PARAMETRIZE { move = MOVE_AROMATHERAPY; status = STATUS1_TOXIC_POISON; }
PARAMETRIZE { move = MOVE_HEAL_BELL; status = STATUS1_FROSTBITE; }
PARAMETRIZE { move = MOVE_AROMATHERAPY; status = STATUS1_FROSTBITE; }
GIVEN { GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } ASSUME(GetMoveEffect(MOVE_AROMATHERAPY) == EFFECT_HEAL_BELL);
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } PLAYER(SPECIES_WOBBUFFET) {
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } if (status != STATUS1_SLEEP && status != STATUS1_FREEZE)
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } Status1(status);
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } }
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
OPPONENT(SPECIES_WYNAUT); OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WYNAUT); OPPONENT(SPECIES_WYNAUT);
} WHEN { } WHEN {
TURN { MOVE(playerLeft, move, target: playerLeft); } TURN { MOVE(playerLeft, move, target: playerLeft); }
TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); } TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); }
} SCENE { } SCENE {
int i;
ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
NOT MESSAGE("Wobbuffet was hurt by its poisoning!"); switch(status)
for (i = 0; i < 6; i++) {
case STATUS1_SLEEP: STATUS_ICON(playerLeft, sleep: FALSE); STATUS_ICON(playerRight, sleep: FALSE); break;
case STATUS1_POISON: STATUS_ICON(playerLeft, poison: FALSE); STATUS_ICON(playerRight, poison: FALSE); break;
case STATUS1_BURN: STATUS_ICON(playerLeft, burn: FALSE); STATUS_ICON(playerRight, burn: FALSE); break;
case STATUS1_PARALYSIS: STATUS_ICON(playerLeft, paralysis: FALSE); STATUS_ICON(playerRight, paralysis: FALSE); break;
case STATUS1_TOXIC_POISON: STATUS_ICON(playerLeft, badPoison: FALSE); STATUS_ICON(playerRight, badPoison: FALSE); break;
case STATUS1_FROSTBITE: STATUS_ICON(playerLeft, frostbite: FALSE); STATUS_ICON(playerRight, frostbite: FALSE); break;
}
for (j = 0; j < PARTY_SIZE; j++)
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_STATUS), STATUS1_NONE); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_STATUS), STATUS1_NONE);
} }
} }
DOUBLE_BATTLE_TEST("Heal Bell does not cure soundproof partners") DOUBLE_BATTLE_TEST("Heal Bell does not cure Soundproof partners (Gen 4, Gen 6+)")
{ {
u32 ability; u32 ability, config;
PARAMETRIZE { ability = ABILITY_SCRAPPY; } PARAMETRIZE { ability = ABILITY_SCRAPPY; config = GEN_4; }
PARAMETRIZE { ability = ABILITY_SOUNDPROOF; } PARAMETRIZE { ability = ABILITY_SOUNDPROOF; config = GEN_4; }
PARAMETRIZE { ability = ABILITY_SOUNDPROOF; config = GEN_5; }
ASSUME(B_HEAL_BELL_SOUNDPROOF != GEN_5); PARAMETRIZE { ability = ABILITY_SOUNDPROOF; config = GEN_6; }
GIVEN { GIVEN {
ASSUME(IsSoundMove(MOVE_HEAL_BELL));
WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, config);
PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_EXPLOUD) { Ability(ability); Status1(STATUS1_POISON); } PLAYER(SPECIES_EXPLOUD) { Ability(ability); Status1(STATUS1_POISON); }
OPPONENT(SPECIES_WYNAUT); OPPONENT(SPECIES_WYNAUT);
@ -54,7 +76,7 @@ DOUBLE_BATTLE_TEST("Heal Bell does not cure soundproof partners")
TURN { MOVE(playerLeft, MOVE_HEAL_BELL, target: playerLeft); } TURN { MOVE(playerLeft, MOVE_HEAL_BELL, target: playerLeft); }
} SCENE { } SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAL_BELL, playerLeft); ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAL_BELL, playerLeft);
if (ability == ABILITY_SOUNDPROOF) { if (ability == ABILITY_SOUNDPROOF && config != GEN_5) {
MESSAGE("Exploud was hurt by its poisoning!"); MESSAGE("Exploud was hurt by its poisoning!");
} else { } else {
NOT MESSAGE("Exploud was hurt by its poisoning!"); NOT MESSAGE("Exploud was hurt by its poisoning!");
@ -62,16 +84,17 @@ DOUBLE_BATTLE_TEST("Heal Bell does not cure soundproof partners")
} }
} }
SINGLE_BATTLE_TEST("Heal Bell cures inactive soundproof Pokemon") SINGLE_BATTLE_TEST("Heal Bell cures inactive Soundproof Pokemon (Gen5+)")
{ {
u32 ability; u32 config, ability;
PARAMETRIZE { ability = ABILITY_SCRAPPY; } PARAMETRIZE { config = GEN_4, ability = ABILITY_SCRAPPY; }
PARAMETRIZE { ability = ABILITY_SOUNDPROOF; } PARAMETRIZE { config = GEN_4, ability = ABILITY_SOUNDPROOF; }
PARAMETRIZE { config = GEN_5, ability = ABILITY_SOUNDPROOF; }
ASSUME(B_HEAL_BELL_SOUNDPROOF >= GEN_5);
GIVEN { GIVEN {
ASSUME(IsSoundMove(MOVE_HEAL_BELL));
WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, config);
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); }
PLAYER(SPECIES_EXPLOUD) { Ability(ability); Status1(STATUS1_POISON); } PLAYER(SPECIES_EXPLOUD) { Ability(ability); Status1(STATUS1_POISON); }
OPPONENT(SPECIES_WYNAUT); OPPONENT(SPECIES_WYNAUT);
@ -81,21 +104,35 @@ SINGLE_BATTLE_TEST("Heal Bell cures inactive soundproof Pokemon")
} SCENE { } SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAL_BELL, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAL_BELL, player);
SEND_IN_MESSAGE("Exploud"); SEND_IN_MESSAGE("Exploud");
NOT MESSAGE("Exploud was hurt by its poisoning!"); if (ability == ABILITY_SCRAPPY || config >= GEN_5) {
NOT MESSAGE("Exploud was hurt by its poisoning!");
} else {
MESSAGE("Exploud was hurt by its poisoning!");
}
} }
} }
SINGLE_BATTLE_TEST("Heal Bell cures a soundproof user") SINGLE_BATTLE_TEST("Heal Bell cures a Soundproof user (Gen5, Gen8+)")
{ {
u32 config;
PARAMETRIZE { config = GEN_4; }
PARAMETRIZE { config = GEN_5; }
PARAMETRIZE { config = GEN_6; }
PARAMETRIZE { config = GEN_8; }
GIVEN { GIVEN {
ASSUME(B_HEAL_BELL_SOUNDPROOF == GEN_5 || B_HEAL_BELL_SOUNDPROOF >= GEN_8); ASSUME(IsSoundMove(MOVE_HEAL_BELL));
WITH_CONFIG(GEN_CONFIG_HEAL_BELL_SOUNDPROOF, config);
PLAYER(SPECIES_EXPLOUD) { Ability(ABILITY_SOUNDPROOF); Status1(STATUS1_POISON); } PLAYER(SPECIES_EXPLOUD) { Ability(ABILITY_SOUNDPROOF); Status1(STATUS1_POISON); }
OPPONENT(SPECIES_WYNAUT); OPPONENT(SPECIES_WYNAUT);
} WHEN { } WHEN {
TURN { MOVE(player, MOVE_HEAL_BELL, target: player); } TURN { MOVE(player, MOVE_HEAL_BELL, target: player); }
} SCENE { } SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAL_BELL, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAL_BELL, player);
NOT MESSAGE("Exploud was hurt by its poisoning!"); if (config == GEN_5 || config >= GEN_8) {
NOT MESSAGE("Exploud was hurt by its poisoning!");
} else {
MESSAGE("Exploud was hurt by its poisoning!");
}
} }
} }

View File

@ -0,0 +1,51 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(MoveHasAdditionalEffect(MOVE_SPARKLY_SWIRL, MOVE_EFFECT_AROMATHERAPY));
}
DOUBLE_BATTLE_TEST("Sparkly Swirl cures the entire party of the user from primary status effects")
{
u32 j;
u32 status;
PARAMETRIZE { status = STATUS1_SLEEP; }
PARAMETRIZE { status = STATUS1_POISON; }
PARAMETRIZE { status = STATUS1_BURN; }
PARAMETRIZE { status = STATUS1_FREEZE; }
PARAMETRIZE { status = STATUS1_PARALYSIS; }
PARAMETRIZE { status = STATUS1_TOXIC_POISON; }
PARAMETRIZE { status = STATUS1_FROSTBITE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) {
if (status != STATUS1_SLEEP && status != STATUS1_FREEZE)
Status1(status);
}
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
PLAYER(SPECIES_WOBBUFFET) { Status1(status); }
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_SPARKLY_SWIRL, target: opponentLeft); }
TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); }
} SCENE {
MESSAGE("Wobbuffet used Sparkly Swirl!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPARKLY_SWIRL, playerLeft);
switch(status)
{
case STATUS1_SLEEP: STATUS_ICON(playerLeft, sleep: FALSE); STATUS_ICON(playerRight, sleep: FALSE); break;
case STATUS1_POISON: STATUS_ICON(playerLeft, poison: FALSE); STATUS_ICON(playerRight, poison: FALSE); break;
case STATUS1_BURN: STATUS_ICON(playerLeft, burn: FALSE); STATUS_ICON(playerRight, burn: FALSE); break;
case STATUS1_PARALYSIS: STATUS_ICON(playerLeft, paralysis: FALSE); STATUS_ICON(playerRight, paralysis: FALSE); break;
case STATUS1_TOXIC_POISON: STATUS_ICON(playerLeft, badPoison: FALSE); STATUS_ICON(playerRight, badPoison: FALSE); break;
case STATUS1_FROSTBITE: STATUS_ICON(playerLeft, frostbite: FALSE); STATUS_ICON(playerRight, frostbite: FALSE); break;
}
} THEN {
for (j = 0; j < PARTY_SIZE; j++)
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_STATUS), STATUS1_NONE);
}
}

View File

@ -567,7 +567,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_SLEEP); ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_SLEEP);
ASSUME(GetMoveEffect(MOVE_AROMATHERAPY) == EFFECT_HEAL_BELL); ASSUME(GetMoveEffect(MOVE_AROMATHERAPY) == EFFECT_HEAL_BELL);
ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL);
ASSUME(GetMoveEffect(MOVE_SPARKLY_SWIRL) == EFFECT_SPARKLY_SWIRL); ASSUME(MoveHasAdditionalEffect(MOVE_SPARKLY_SWIRL, MOVE_EFFECT_AROMATHERAPY));
ASSUME(B_SLEEP_TURNS >= GEN_5); ASSUME(B_SLEEP_TURNS >= GEN_5);
PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON);
PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON);
@ -1147,7 +1147,6 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight);
MESSAGE("Wobbuffet fell asleep!"); MESSAGE("Wobbuffet fell asleep!");
MESSAGE("Appletun used G-Max Sweetness!"); MESSAGE("Appletun used G-Max Sweetness!");
MESSAGE("Wobbuffet's status returned to normal!");
MESSAGE("The opposing Wobbuffet used Spore!"); MESSAGE("The opposing Wobbuffet used Spore!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight); ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight);