fix conflict

This commit is contained in:
AlexOn1ine 2024-11-12 23:30:49 +01:00
commit 4dc784bd2d
15 changed files with 214 additions and 84 deletions

View file

@ -1104,7 +1104,7 @@
.byte 0xcc
.endm
.macro cureifburnedparalysedorpoisoned failInstr:req
.macro curestatuswithmove failInstr:req
.byte 0xcd
.4byte \failInstr
.endm

View file

@ -443,7 +443,7 @@ BattleScript_EffectTakeHeart::
attackcanceler
attackstring
ppreduce
cureifburnedparalysedorpoisoned BattleScript_CalmMindTryToRaiseStats
curestatuswithmove BattleScript_CalmMindTryToRaiseStats
attackanimation
waitanimation
updatestatusicon BS_ATTACKER
@ -5230,7 +5230,7 @@ BattleScript_EffectRefresh::
attackcanceler
attackstring
ppreduce
cureifburnedparalysedorpoisoned BattleScript_ButItFailed
curestatuswithmove BattleScript_ButItFailed
attackanimation
waitanimation
printstring STRINGID_PKMNSTATUSNORMAL
@ -6988,26 +6988,17 @@ BattleScript_WishMegaEvolution::
goto BattleScript_MegaEvolutionAfterString
BattleScript_PrimalReversion::
call BattleScript_PrimalReversionRet
end3
BattleScript_PrimalReversionRestoreAttacker::
call BattleScript_PrimalReversionRet
copybyte gBattlerAttacker, sSAVED_BATTLER
end3
BattleScript_PrimalReversionRet::
flushtextbox
setbyte gIsCriticalHit, 0
handleprimalreversion BS_ATTACKER, 0
handleprimalreversion BS_ATTACKER, 1
playanimation BS_ATTACKER, B_ANIM_PRIMAL_REVERSION
handleprimalreversion BS_SCRIPTING, 0
handleprimalreversion BS_SCRIPTING, 1
playanimation BS_SCRIPTING, B_ANIM_PRIMAL_REVERSION
waitanimation
handleprimalreversion BS_ATTACKER, 2
handleprimalreversion BS_SCRIPTING, 2
printstring STRINGID_PKMNREVERTEDTOPRIMAL
waitmessage B_WAIT_TIME_LONG
switchinabilities BS_ATTACKER
return
switchinabilities BS_SCRIPTING
end3
BattleScript_UltraBurst::
flushtextbox
@ -9680,6 +9671,13 @@ BattleScript_EjectPackActivates::
jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd
goto BattleScript_EjectPackActivate_Ret
BattleScript_EjectPackMissesTiming::
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_EJECTBUTTONACTIVATE
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
return
BattleScript_DarkTypePreventsPrankster::
attackstring
ppreduce

View file

@ -828,6 +828,7 @@ struct BattleStruct
u8 commandingDondozo;
u16 commanderActive[NUM_BATTLE_SIDES];
u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side
u8 redCardActivates:1;
u8 usedEjectItem;
u8 usedMicleBerry;
};

View file

@ -419,6 +419,7 @@ extern const u8 BattleScript_EjectButtonActivates[];
extern const u8 BattleScript_EjectPackActivate_Ret[];
extern const u8 BattleScript_EjectPackActivate_End2[];
extern const u8 BattleScript_EjectPackActivates[];
extern const u8 BattleScript_EjectPackMissesTiming[];
extern const u8 BattleScript_MentalHerbCureRet[];
extern const u8 BattleScript_MentalHerbCureEnd2[];
extern const u8 BattleScript_TerrainPreventsEnd2[];
@ -438,7 +439,6 @@ extern const u8 BattleScript_AttackWeakenedByStrongWinds[];
extern const u8 BattleScript_BlockedByPrimalWeatherEnd3[];
extern const u8 BattleScript_BlockedByPrimalWeatherRet[];
extern const u8 BattleScript_PrimalReversion[];
extern const u8 BattleScript_PrimalReversionRestoreAttacker[];
extern const u8 BattleScript_HyperspaceFuryRemoveProtect[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTacticsInPalace[];

View file

@ -121,6 +121,8 @@
#define STATUS1_PSN_ANY (STATUS1_POISON | STATUS1_TOXIC_POISON)
#define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)
#define STATUS1_REFRESH (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)
// Volatile status ailments
// These are removed after exiting the battle or switching out
#define STATUS2_CONFUSION (1 << 0 | 1 << 1 | 1 << 2)

View file

@ -716,6 +716,7 @@ struct BattleTestRunnerState
u16 observedRatio;
u16 trialRatio;
bool8 runRandomly:1;
bool8 didRunRandomly:1;
bool8 runGiven:1;
bool8 runWhen:1;
bool8 runScene:1;

View file

@ -22,12 +22,10 @@ $(DATA_ASM_BUILDDIR)/maps.o: $(DATA_ASM_SUBDIR)/maps.s $(LAYOUTS_DIR)/layouts.in
$(DATA_ASM_BUILDDIR)/map_events.o: $(DATA_ASM_SUBDIR)/map_events.s $(MAPS_DIR)/events.inc $(MAP_EVENTS)
$(PREPROC) $< charmap.txt | $(CPP) -I include - | $(PREPROC) -ie $< charmap.txt | $(AS) $(ASFLAGS) -o $@
$(DATA_SRC_SUBDIR)/map_group_count.h: $(MAPS_DIR)/headers.inc ;
$(MAPS_OUTDIR)/%/header.inc $(MAPS_OUTDIR)/%/events.inc $(MAPS_OUTDIR)/%/connections.inc: $(MAPS_DIR)/%/map.json
$(MAPJSON) map emerald $< $(LAYOUTS_DIR)/layouts.json $(@D)
$(MAPS_OUTDIR)/connections.inc $(MAPS_OUTDIR)/groups.inc $(MAPS_OUTDIR)/events.inc $(MAPS_OUTDIR)/headers.inc $(INCLUDECONSTS_OUTDIR)/map_groups.h: $(MAPS_DIR)/map_groups.json
$(MAPS_OUTDIR)/connections.inc $(MAPS_OUTDIR)/groups.inc $(MAPS_OUTDIR)/events.inc $(MAPS_OUTDIR)/headers.inc $(INCLUDECONSTS_OUTDIR)/map_groups.h $(DATA_SRC_SUBDIR)/map_group_count.h: $(MAPS_DIR)/map_groups.json
$(MAPJSON) groups emerald $< $(MAPS_OUTDIR) $(INCLUDECONSTS_OUTDIR)
$(LAYOUTS_OUTDIR)/layouts.inc $(LAYOUTS_OUTDIR)/layouts_table.inc $(INCLUDECONSTS_OUTDIR)/layouts.h: $(LAYOUTS_DIR)/layouts.json

View file

@ -750,7 +750,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_MYSTERIOUSAIRCURRENTBLOWSON] = COMPOUND_STRING("The mysterious strong winds blow on regardless!"),
[STRINGID_ATTACKWEAKENEDBSTRONGWINDS] = COMPOUND_STRING("The mysterious strong winds weakened the attack!"),
[STRINGID_STUFFCHEEKSCANTSELECT] = COMPOUND_STRING("It can't use the move because it doesn't have a Berry!\p"),
[STRINGID_PKMNREVERTEDTOPRIMAL] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s Primal Reversion! It reverted to its primal state!"),
[STRINGID_PKMNREVERTEDTOPRIMAL] = COMPOUND_STRING("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s Primal Reversion! It reverted to its primal state!"),
[STRINGID_BUTPOKEMONCANTUSETHEMOVE] = COMPOUND_STRING("But {B_ATK_NAME_WITH_PREFIX2} can't use the move!"),
[STRINGID_BUTHOOPACANTUSEIT] = COMPOUND_STRING("But {B_ATK_NAME_WITH_PREFIX2} can't use it the way it is now!"),
[STRINGID_BROKETHROUGHPROTECTION] = COMPOUND_STRING("It broke through {B_DEF_NAME_WITH_PREFIX2}'s protection!"),

View file

@ -543,7 +543,7 @@ static void Cmd_trymemento(void);
static void Cmd_setforcedtarget(void);
static void Cmd_setcharge(void);
static void Cmd_callterrainattack(void);
static void Cmd_cureifburnedparalysedorpoisoned(void);
static void Cmd_curestatuswithmove(void);
static void Cmd_settorment(void);
static void Cmd_jumpifnodamage(void);
static void Cmd_settaunt(void);
@ -802,7 +802,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_setforcedtarget, //0xCA
Cmd_setcharge, //0xCB
Cmd_callterrainattack, //0xCC
Cmd_cureifburnedparalysedorpoisoned, //0xCD
Cmd_curestatuswithmove, //0xCD
Cmd_settorment, //0xCE
Cmd_jumpifnodamage, //0xCF
Cmd_settaunt, //0xD0
@ -6361,11 +6361,19 @@ static void Cmd_moveend(void)
}
else // Eject Pack
{
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
AI_DATA->ejectPackSwitch = TRUE;
// Are these 2 lines below needed?
gProtectStructs[battler].statFell = FALSE;
gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage = TRUE;
if (gBattleResources->flags->flags[gBattlerTarget] & RESOURCE_FLAG_EMERGENCY_EXIT)
{
gBattlescriptCurrInstr = BattleScript_EjectPackMissesTiming;
gProtectStructs[battler].statFell = FALSE;
}
else
{
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
AI_DATA->ejectPackSwitch = TRUE;
// Are these 2 lines below needed?
gProtectStructs[battler].statFell = FALSE;
gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage = TRUE;
}
}
break; // Only the fastest Eject item activates
}
@ -6422,6 +6430,7 @@ static void Cmd_moveend(void)
SaveBattlerTarget(battler); // save battler with red card
gBattleScripting.battler = battler;
gEffectBattler = gBattlerAttacker;
gBattleStruct->redCardActivates = TRUE;
if (gMovesInfo[gCurrentMove].effect == EFFECT_HIT_ESCAPE)
gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection
BattleScriptPushCursor();
@ -6528,6 +6537,11 @@ static void Cmd_moveend(void)
case MOVEEND_EMERGENCY_EXIT: // Special case, because moves hitting multiple opponents stop after switching out
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleStruct->redCardActivates)
{
gBattleResources->flags->flags[i] &= ~RESOURCE_FLAG_EMERGENCY_EXIT;
continue;
}
if (gBattleResources->flags->flags[i] & RESOURCE_FLAG_EMERGENCY_EXIT)
{
gBattleResources->flags->flags[i] &= ~RESOURCE_FLAG_EMERGENCY_EXIT;
@ -6633,6 +6647,7 @@ static void Cmd_moveend(void)
gBattleStruct->additionalEffectsCounter = 0;
gBattleStruct->poisonPuppeteerConfusion = FALSE;
gBattleStruct->fickleBeamBoosted = FALSE;
gBattleStruct->redCardActivates = FALSE;
gBattleStruct->usedMicleBerry &= ~(1u << gBattlerAttacker);
if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
gBattleStruct->pledgeMove = FALSE;
@ -14114,12 +14129,17 @@ u32 GetNaturePowerMove(u32 battler)
return move;
}
// Refresh
static void Cmd_cureifburnedparalysedorpoisoned(void)
static void Cmd_curestatuswithmove(void)
{
CMD_ARGS(const u8 *failInstr);
u32 shouldHeal;
if (gBattleMons[gBattlerAttacker].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE))
if (gMovesInfo[gCurrentMove].effect == EFFECT_REFRESH)
shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_REFRESH;
else // Take Heart
shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY;
if (shouldHeal)
{
gBattleMons[gBattlerAttacker].status1 = 0;
gBattlescriptCurrInstr = cmd->nextInstr;

View file

@ -6425,17 +6425,8 @@ bool32 TryPrimalReversion(u32 battler)
if (GetBattlerHoldEffect(battler, FALSE) == HOLD_EFFECT_PRIMAL_ORB
&& GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE)
{
if (gBattlerAttacker == battler)
{
BattleScriptPushCursorAndCallback(BattleScript_PrimalReversion);
}
else
{
// edge case for scenarios like a switch-in after activated eject button
gBattleScripting.savedBattler = gBattlerAttacker;
gBattlerAttacker = battler;
BattleScriptPushCursorAndCallback(BattleScript_PrimalReversionRestoreAttacker);
}
gBattleScripting.battler = battler;
BattleScriptPushCursorAndCallback(BattleScript_PrimalReversion);
return TRUE;
}
return FALSE;
@ -7123,6 +7114,24 @@ static u8 TryConsumeMirrorHerb(u32 battler, bool32 execute)
return effect;
}
static inline u32 TryBoosterEnergy(u32 battler)
{
if (gBattleStruct->boosterEnergyActivates & (1u << battler) || gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
return ITEM_NO_EFFECT;
if (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT))
|| ((GetBattlerAbility(battler) == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)))
{
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
gBattlerAbility = gBattleScripting.battler = battler;
gBattleStruct->boosterEnergyActivates |= 1u << battler;
BattleScriptExecute(BattleScript_BoosterEnergyEnd2);
return ITEM_EFFECT_OTHER;
}
return ITEM_NO_EFFECT;
}
static u32 RestoreWhiteHerbStats(u32 battler)
{
u32 i, effect = 0;
@ -7639,17 +7648,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
effect = TryConsumeMirrorHerb(battler, TRUE);
break;
case HOLD_EFFECT_BOOSTER_ENERGY:
if (!(gBattleStruct->boosterEnergyActivates & (1u << battler))
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
&& (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT))
|| ((GetBattlerAbility(battler) == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))))
{
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
gBattleScripting.battler = battler;
gBattleStruct->boosterEnergyActivates |= 1u << battler;
BattleScriptExecute(BattleScript_BoosterEnergyEnd2);
effect = ITEM_EFFECT_OTHER;
}
effect = TryBoosterEnergy(battler);
break;
}
if (effect != 0)
@ -7907,17 +7906,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
effect = TryConsumeMirrorHerb(battler, TRUE);
break;
case HOLD_EFFECT_BOOSTER_ENERGY:
if (!(gBattleStruct->boosterEnergyActivates & (1u << battler))
&& !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
&& (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT))
|| ((GetBattlerAbility(battler) == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))))
{
PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler));
gBattlerAbility = gBattleScripting.battler = battler;
gBattleStruct->boosterEnergyActivates |= 1u << battler;
BattleScriptExecute(BattleScript_BoosterEnergyEnd2);
effect = ITEM_EFFECT_OTHER;
}
effect = TryBoosterEnergy(battler);
break;
}

View file

@ -63,3 +63,25 @@ SINGLE_BATTLE_TEST("Eject Pack is triggered by self-inflicting stat decreases")
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
}
}
SINGLE_BATTLE_TEST("Eject Pack will miss timing to switch out user if Emergency Exit was activated on target")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(133); };
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(player, MOVE_OVERHEAT); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_OVERHEAT, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet is switched out with the Eject Pack!");
ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
} THEN {
EXPECT(player->species == SPECIES_WOBBUFFET);
EXPECT(player->item == ITEM_NONE);
EXPECT(opponent->species == SPECIES_WYNAUT);
}
}

View file

@ -380,24 +380,6 @@ SINGLE_BATTLE_TEST("Red Card does not activate if attacker's Sheer Force applied
}
}
SINGLE_BATTLE_TEST("Red Card activates before Emergency Exit")
{
GIVEN {
PLAYER(SPECIES_GOLISOPOD) { MaxHP(100); HP(51); Item(ITEM_RED_CARD); }
PLAYER(SPECIES_WIMPOD);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Golisopod held up its Red Card against the opposing Wobbuffet!");
ABILITY_POPUP(player, ABILITY_EMERGENCY_EXIT);
SEND_IN_MESSAGE("Wimpod");
}
}
SINGLE_BATTLE_TEST("Red Card is consumed after dragged out replacement has its Speed lowered by Sticky Web")
{
GIVEN {
@ -468,4 +450,21 @@ SINGLE_BATTLE_TEST("Red Card does not activate if holder is switched in mid-turn
}
}
SINGLE_BATTLE_TEST("Red Card prevents Emergency Exit activation when triggered")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_GOLISOPOD) { Item(ITEM_RED_CARD); Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SUPER_FANG); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPER_FANG, player);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
NOT ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
}
}
TO_DO_BATTLE_TEST("Red Card activates but fails if the attacker has Dynamaxed");

View file

@ -0,0 +1,68 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_REFRESH].effect == EFFECT_REFRESH);
}
SINGLE_BATTLE_TEST("Refresh cures the user of burn, frostbite, poison, and paralysis")
{
u32 status1;
PARAMETRIZE { status1 = STATUS1_POISON; }
PARAMETRIZE { status1 = STATUS1_BURN; }
PARAMETRIZE { status1 = STATUS1_PARALYSIS; }
PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; }
PARAMETRIZE { status1 = STATUS1_FROSTBITE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Status1(status1); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_REFRESH); }
} SCENE {
MESSAGE("Wobbuffet's status returned to normal!");
STATUS_ICON(player, none: TRUE);
}
}
SINGLE_BATTLE_TEST("Refresh does not cure the user of Freeze")
{
PASSES_RANDOMLY(20, 100, RNG_FROZEN);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_REFRESH); }
} SCENE {
MESSAGE("Wobbuffet used Refresh!");
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_REFRESH, player);
STATUS_ICON(player, none: TRUE); }
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("Refresh does not cure sleep when used by Sleep Talk")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP);
ASSUME(gMovesInfo[MOVE_SLEEP_TALK].effect == EFFECT_SLEEP_TALK);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SLEEP_TALK, MOVE_REFRESH); }
} WHEN {
TURN { MOVE(player, MOVE_SPORE); MOVE(opponent, MOVE_SLEEP_TALK); }
TURN { MOVE(player, MOVE_SPORE); MOVE(opponent, MOVE_REFRESH); }
} SCENE {
MESSAGE("Wobbuffet used Spore!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent);
MESSAGE("The opposing Wobbuffet fell asleep!");
MESSAGE("The opposing Wobbuffet used Sleep Talk!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, opponent);
MESSAGE("The opposing Wobbuffet used Refresh!");
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_REFRESH, player);
STATUS_ICON(player, none: TRUE); }
MESSAGE("But it failed!");
}
}

View file

@ -40,8 +40,32 @@ SINGLE_BATTLE_TEST("Take Heart cures the user of all status conditions")
STATUS_ICON(player, none: TRUE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} else {
STATUS_ICON(player, none: TRUE);
MESSAGE("Wobbuffet's status returned to normal!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
}
}
}
SINGLE_BATTLE_TEST("Take Heart cures sleep when used by Sleep Talk")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP);
ASSUME(gMovesInfo[MOVE_SLEEP_TALK].effect == EFFECT_SLEEP_TALK);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SLEEP_TALK, MOVE_TAKE_HEART); }
} WHEN {
TURN { MOVE(player, MOVE_SPORE); MOVE(opponent, MOVE_SLEEP_TALK); }
} SCENE {
MESSAGE("Wobbuffet used Spore!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent);
MESSAGE("The opposing Wobbuffet fell asleep!");
MESSAGE("The opposing Wobbuffet used Sleep Talk!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, opponent);
MESSAGE("The opposing Wobbuffet used Take Heart!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TAKE_HEART, opponent);
STATUS_ICON(opponent, none: TRUE);
MESSAGE("The opposing Wobbuffet's status returned to normal!");
}
}

View file

@ -365,6 +365,7 @@ u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi)
if (tag == STATE->rngTag)
{
STATE->didRunRandomly = TRUE;
u32 n = hi - lo + 1;
if (STATE->trials == 1)
{
@ -401,6 +402,7 @@ u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32
if (tag == STATE->rngTag)
{
STATE->didRunRandomly = TRUE;
if (STATE->trials == 1)
{
u32 n = 0, i;
@ -449,6 +451,7 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights)
if (tag == STATE->rngTag)
{
STATE->didRunRandomly = TRUE;
if (STATE->trials == 1)
{
STATE->trials = n;
@ -522,6 +525,7 @@ const void *RandomElementArray(enum RandomTag tag, const void *array, size_t siz
if (tag == STATE->rngTag)
{
STATE->didRunRandomly = TRUE;
if (STATE->trials == 1)
{
STATE->trials = count;
@ -1349,6 +1353,7 @@ static void CB2_BattleTest_NextParameter(void)
else
{
STATE->trials = 0;
STATE->didRunRandomly = FALSE;
BattleTest_Run(gTestRunnerState.test->data);
}
}
@ -1395,6 +1400,9 @@ static void CB2_BattleTest_NextTrial(void)
}
else
{
if (STATE->rngTag && !STATE->didRunRandomly && STATE->expectedRatio != Q_4_12(0.0) && STATE->expectedRatio != Q_4_12(1.0))
Test_ExitWithResult(TEST_RESULT_INVALID, SourceLine(0), ":L%s:%d: PASSES_RANDOMLY specified but no Random* call with that tag executed", gTestRunnerState.test->filename, SourceLine(0));
// This is a tolerance of +/- ~2%.
if (abs(STATE->observedRatio - STATE->expectedRatio) <= Q_4_12(0.02))
gTestRunnerState.result = TEST_RESULT_PASS;