Merge branch 'master' into master-upcoming
Conflicts: include/battle.h include/constants/battle_string_ids.h src/battle_ai_util.c src/battle_main.c src/battle_util.c test/battle/ai/ai.c
This commit is contained in:
commit
1abfa7acfa
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@ -10,7 +10,6 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container: devkitpro/devkitarm
|
||||
env:
|
||||
GAME_VERSION: EMERALD
|
||||
GAME_REVISION: 0
|
||||
@ -24,10 +23,8 @@ jobs:
|
||||
- name: Install binutils
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y build-essential libpng-dev libelf-dev
|
||||
sudo apt install -y binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi libpng-dev python3
|
||||
# build-essential and git are already installed
|
||||
# gcc-arm-none-eabi is only needed for the modern build
|
||||
# as an alternative to dkP
|
||||
|
||||
- name: ROM
|
||||
env:
|
||||
|
||||
3
Makefile
3
Makefile
@ -366,6 +366,9 @@ clean-generated:
|
||||
COMPETITIVE_PARTY_SYNTAX := $(shell PATH="$(PATH)"; echo 'COMPETITIVE_PARTY_SYNTAX' | $(CPP) $(CPPFLAGS) -imacros include/gba/defines.h -imacros include/config/general.h | tail -n1)
|
||||
ifeq ($(COMPETITIVE_PARTY_SYNTAX),1)
|
||||
%.h: %.party ; $(CPP) $(CPPFLAGS) -traditional-cpp - < $< | $(TRAINERPROC) -o $@ -i $< -
|
||||
|
||||
AUTO_GEN_TARGETS += $(DATA_SRC_SUBDIR)/trainers.h
|
||||
AUTO_GEN_TARGETS += $(DATA_SRC_SUBDIR)/battle_partners.h
|
||||
endif
|
||||
|
||||
$(C_BUILDDIR)/librfu_intr.o: CFLAGS := -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast
|
||||
|
||||
@ -2717,12 +2717,12 @@ BattleScript_EffectGravity::
|
||||
attackstring
|
||||
ppreduce
|
||||
setgravity BattleScript_ButItFailed
|
||||
savetarget
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_EffectGravitySuccess::
|
||||
printstring STRINGID_GRAVITYINTENSIFIED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
savetarget
|
||||
selectfirstvalidtarget
|
||||
BattleScript_GravityLoop:
|
||||
movevaluescleanup
|
||||
@ -6041,6 +6041,14 @@ BattleScript_ToxicSpikesPoisoned::
|
||||
waitstate
|
||||
return
|
||||
|
||||
BattleScript_ToxicSpikesBadlyPoisoned::
|
||||
printstring STRINGID_TOXICSPIKESBADLYPOISONED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
statusanimation BS_SCRIPTING
|
||||
updatestatusicon BS_SCRIPTING
|
||||
waitstate
|
||||
return
|
||||
|
||||
BattleScript_StickyWebOnSwitchIn::
|
||||
savetarget
|
||||
saveattacker
|
||||
@ -9902,15 +9910,16 @@ BattleScript_CouldntFullyProtect::
|
||||
return
|
||||
|
||||
BattleScript_BerserkGeneRet::
|
||||
saveattacker
|
||||
savetarget
|
||||
copybyte gBattlerTarget, sBATTLER
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse
|
||||
setgraphicalstatchangevalues
|
||||
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
|
||||
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
|
||||
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM
|
||||
call BattleScript_StatUp
|
||||
BattleScript_BerserkGeneRet_TryConfuse:
|
||||
jumpifability BS_SCRIPTING, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents
|
||||
jumpifability BS_ATTACKER, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents
|
||||
jumpifsafeguard BattleScript_BerserkGeneRet_SafeguardProtected
|
||||
seteffectprimary MOVE_EFFECT_CONFUSION
|
||||
goto BattleScript_BerserkGeneRet_End
|
||||
@ -9925,9 +9934,14 @@ BattleScript_BerserkGeneRet_OwnTempoPrevents:
|
||||
printstring STRINGID_PKMNPREVENTSCONFUSIONWITH
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_BerserkGeneRet_End:
|
||||
restoreattacker
|
||||
restoretarget
|
||||
removeitem BS_SCRIPTING
|
||||
end3
|
||||
removeitem BS_ATTACKER
|
||||
return
|
||||
|
||||
BattleScript_BerserkGeneRetEnd2::
|
||||
call BattleScript_BerserkGeneRet
|
||||
end2
|
||||
|
||||
BattleScript_BoosterEnergyEnd2::
|
||||
call BattleScript_BoosterEnergyRet
|
||||
|
||||
@ -265,13 +265,12 @@ BattleScript_ActionWallyThrow:
|
||||
end2
|
||||
|
||||
BattleScript_TrainerASlideMsgRet::
|
||||
handletrainerslidemsg BS_SCRIPTING, 0
|
||||
trainerslidein BS_OPPONENT1
|
||||
handletrainerslidemsg BS_SCRIPTING, 1
|
||||
handletrainerslidemsg BS_SCRIPTING, PRINT_SLIDE_MESSAGE
|
||||
waitstate
|
||||
trainerslideout BS_OPPONENT1
|
||||
waitstate
|
||||
handletrainerslidemsg BS_SCRIPTING, 2
|
||||
handletrainerslidemsg BS_SCRIPTING, RESTORE_BATTLER_SLIDE_CONTROL
|
||||
return
|
||||
|
||||
BattleScript_TrainerASlideMsgEnd2::
|
||||
@ -279,13 +278,12 @@ BattleScript_TrainerASlideMsgEnd2::
|
||||
end2
|
||||
|
||||
BattleScript_TrainerBSlideMsgRet::
|
||||
handletrainerslidemsg BS_SCRIPTING, 0
|
||||
trainerslidein BS_OPPONENT2
|
||||
handletrainerslidemsg BS_SCRIPTING, 1
|
||||
handletrainerslidemsg BS_SCRIPTING, PRINT_SLIDE_MESSAGE
|
||||
waitstate
|
||||
trainerslideout BS_OPPONENT2
|
||||
waitstate
|
||||
handletrainerslidemsg BS_SCRIPTING, 2
|
||||
handletrainerslidemsg BS_SCRIPTING, RESTORE_BATTLER_SLIDE_CONTROL
|
||||
return
|
||||
|
||||
BattleScript_TrainerBSlideMsgEnd2::
|
||||
|
||||
@ -583,7 +583,6 @@ struct BattlerState
|
||||
u32 multipleSwitchInBattlers:1;
|
||||
u32 alreadyStatusedMoveAttempt:1; // For example when using Thunder Wave on an already paralyzed Pokémon.
|
||||
u32 activeAbilityPopUps:1;
|
||||
u32 lastMoveFailed:1; // For Stomping Tantrum
|
||||
u32 forcedSwitch:1;
|
||||
u32 storedHealingWish:1;
|
||||
u32 storedLunarDance:1;
|
||||
@ -591,8 +590,9 @@ struct BattlerState
|
||||
u32 sleepClauseEffectExempt:1; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore)
|
||||
u32 usedMicleBerry:1;
|
||||
u32 pursuitTarget:1;
|
||||
u32 stompingTantrumTimer:2;
|
||||
u32 canPickupItem:1;
|
||||
u32 padding:17;
|
||||
u32 padding:16;
|
||||
// End of Word
|
||||
};
|
||||
|
||||
@ -785,7 +785,6 @@ struct BattleStruct
|
||||
u8 noTargetPresent:1;
|
||||
struct MessageStatus slideMessageStatus;
|
||||
u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT];
|
||||
u8 storeBattlerSpriteId;
|
||||
u16 opponentMonCanTera:6;
|
||||
u16 opponentMonCanDynamax:6;
|
||||
u16 padding:4;
|
||||
|
||||
@ -283,6 +283,7 @@ extern const u8 BattleScript_BadDreamsActivates[];
|
||||
extern const u8 BattleScript_SwitchInAbilityMsg[];
|
||||
extern const u8 BattleScript_SwitchInAbilityMsgRet[];
|
||||
extern const u8 BattleScript_ToxicSpikesPoisoned[];
|
||||
extern const u8 BattleScript_ToxicSpikesBadlyPoisoned[];
|
||||
extern const u8 BattleScript_ToxicSpikesAbsorbed[];
|
||||
extern const u8 BattleScript_StickyWebOnSwitchIn[];
|
||||
extern const u8 BattleScript_SolarPowerActivates[];
|
||||
@ -493,6 +494,7 @@ extern const u8 BattleScript_MoveEffectStockpileWoreOff[];
|
||||
extern const u8 BattleScript_StealthRockActivates[];
|
||||
extern const u8 BattleScript_SpikesActivates[];
|
||||
extern const u8 BattleScript_BerserkGeneRet[];
|
||||
extern const u8 BattleScript_BerserkGeneRetEnd2[];
|
||||
extern const u8 BattleScript_TargetFormChangeWithStringNoPopup[];
|
||||
extern const u8 BattleScript_DefDown[];
|
||||
extern const u8 BattleScript_UltraBurst[];
|
||||
|
||||
@ -186,6 +186,7 @@
|
||||
#define B_SAFARI_BALL_MODIFIER GEN_LATEST // In Gen8+, Safari Ball's catch multiplier was reduced from x1.5 to x1.
|
||||
#define B_FRIEND_BALL_MODIFIER GEN_LATEST // In Gen8+, Friend Ball's friendship boost was reduced from 200 to 150.
|
||||
#define B_SERENE_GRACE_BOOST GEN_LATEST // In Gen5+, Serene Grace boosts the added flinch chance of King's Rock and Razor Fang.
|
||||
#define B_IRON_BALL GEN_LATEST // In Gen5+, Flying-type Pokemon holding Iron Ball take x1 damage from Ground-type moves regardless of their other types, except during Inverse Battles or if the Pokemon is grounded by any other effect.
|
||||
|
||||
// Flag settings
|
||||
// To use the following features, change the 0 for a flag present in include/constants/flags.h, preferably an unused one.
|
||||
|
||||
@ -1136,6 +1136,8 @@
|
||||
// Flags
|
||||
#undef B_FLAG_SLEEP_CLAUSE
|
||||
#define B_FLAG_SLEEP_CLAUSE TESTING_FLAG_SLEEP_CLAUSE
|
||||
#undef B_FLAG_INVERSE_BATTLE
|
||||
#define B_FLAG_INVERSE_BATTLE TESTING_FLAG_INVERSE_BATTLE
|
||||
|
||||
// Move animation testing
|
||||
#define T_SHOULD_RUN_MOVE_ANIM FALSE // If TRUE, enables the move animation tests, these are very computationally heavy and takes a long time to run.
|
||||
|
||||
@ -600,4 +600,10 @@ enum StartingStatus
|
||||
STARTING_STATUS_SWAMP_OPPONENT,
|
||||
};
|
||||
|
||||
enum SlideMsgStates
|
||||
{
|
||||
PRINT_SLIDE_MESSAGE,
|
||||
RESTORE_BATTLER_SLIDE_CONTROL,
|
||||
};
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_H
|
||||
|
||||
@ -735,6 +735,7 @@ enum StringID
|
||||
STRINGID_TIMETOGIGANTAMAX,
|
||||
STRINGID_QUESTIONFORFEITBATTLE,
|
||||
STRINGID_FORFEITBATTLEGAVEMONEY,
|
||||
STRINGID_TOXICSPIKESBADLYPOISONED,
|
||||
STRINGID_COUNT
|
||||
};
|
||||
|
||||
|
||||
@ -1663,7 +1663,7 @@
|
||||
#if TESTING
|
||||
#define TESTING_FLAGS_START 0x5000
|
||||
#define TESTING_FLAG_SLEEP_CLAUSE (TESTING_FLAGS_START + 0x0)
|
||||
#define TESTING_FLAG_UNUSED_1 (TESTING_FLAGS_START + 0x1)
|
||||
#define TESTING_FLAG_INVERSE_BATTLE (TESTING_FLAGS_START + 0x1)
|
||||
#define TESTING_FLAG_UNUSED_2 (TESTING_FLAGS_START + 0x2)
|
||||
#define TESTING_FLAG_UNUSED_3 (TESTING_FLAGS_START + 0x3)
|
||||
#define TESTING_FLAG_UNUSED_4 (TESTING_FLAGS_START + 0x4)
|
||||
|
||||
@ -12,6 +12,7 @@ enum GenConfigTag
|
||||
GEN_CONFIG_GALE_WINGS,
|
||||
GEN_CONFIG_HEAL_BELL_SOUNDPROOF,
|
||||
GEN_CONFIG_TELEPORT_BEHAVIOR,
|
||||
GEN_CONFIG_ABILITY_WEATHER,
|
||||
GEN_CONFIG_MOODY_STATS,
|
||||
GEN_CONFIG_BATTLE_BOND,
|
||||
GEN_CONFIG_ATE_MULTIPLIER,
|
||||
|
||||
@ -15,6 +15,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] =
|
||||
[GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS,
|
||||
[GEN_CONFIG_HEAL_BELL_SOUNDPROOF] = B_HEAL_BELL_SOUNDPROOF,
|
||||
[GEN_CONFIG_TELEPORT_BEHAVIOR] = B_TELEPORT_BEHAVIOR,
|
||||
[GEN_CONFIG_ABILITY_WEATHER] = B_ABILITY_WEATHER,
|
||||
[GEN_CONFIG_MOODY_STATS] = B_MOODY_ACC_EVASION,
|
||||
[GEN_CONFIG_BATTLE_BOND] = B_BATTLE_BOND,
|
||||
[GEN_CONFIG_FELL_STINGER_STAT_RAISE] = B_FELL_STINGER_STAT_RAISE,
|
||||
|
||||
@ -11,6 +11,7 @@ INCLUDECONSTS_OUTDIR := include/constants
|
||||
|
||||
AUTO_GEN_TARGETS += $(INCLUDECONSTS_OUTDIR)/map_groups.h
|
||||
AUTO_GEN_TARGETS += $(INCLUDECONSTS_OUTDIR)/layouts.h
|
||||
AUTO_GEN_TARGETS += $(DATA_SRC_SUBDIR)/map_group_count.h
|
||||
|
||||
MAP_DIRS := $(dir $(wildcard $(MAPS_DIR)/*/map.json))
|
||||
MAP_CONNECTIONS := $(patsubst $(MAPS_DIR)/%/,$(MAPS_DIR)/%/connections.inc,$(MAP_DIRS))
|
||||
|
||||
@ -169,20 +169,20 @@ void RecordLastUsedMoveBy(u32 battlerId, u32 move)
|
||||
BATTLE_HISTORY->moveHistory[battlerId][*index] = move;
|
||||
}
|
||||
|
||||
void RecordKnownMove(u32 battlerId, u32 move)
|
||||
void RecordKnownMove(u32 battler, u32 move)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
s32 moveIndex;
|
||||
|
||||
if (BATTLE_HISTORY->usedMoves[battlerId][i] == move)
|
||||
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
if (gBattleMons[battler].moves[moveIndex] == move)
|
||||
break;
|
||||
if (BATTLE_HISTORY->usedMoves[battlerId][i] == MOVE_NONE)
|
||||
{
|
||||
BATTLE_HISTORY->usedMoves[battlerId][i] = move;
|
||||
AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].moves[i] = move;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (moveIndex < MAX_MON_MOVES && BATTLE_HISTORY->usedMoves[battler][moveIndex] == MOVE_NONE)
|
||||
{
|
||||
BATTLE_HISTORY->usedMoves[battler][moveIndex] = move;
|
||||
AI_PARTY->mons[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].moves[moveIndex] = move;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3196,7 +3196,7 @@ void SwitchInClearSetData(u32 battler)
|
||||
gBattleStruct->lastTakenMoveFrom[battler][1] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][2] = 0;
|
||||
gBattleStruct->lastTakenMoveFrom[battler][3] = 0;
|
||||
gBattleStruct->battlerState[battler].lastMoveFailed = FALSE;
|
||||
gBattleStruct->battlerState[battler].stompingTantrumTimer = 0;
|
||||
gBattleStruct->palaceFlags &= ~(1u << battler);
|
||||
gBattleStruct->battlerState[battler].canPickupItem = FALSE;
|
||||
|
||||
@ -3975,6 +3975,9 @@ void BattleTurnPassed(void)
|
||||
gStatuses4[i] &= ~STATUS4_ELECTRIFIED;
|
||||
gBattleMons[i].status2 &= ~STATUS2_FLINCHED;
|
||||
gBattleMons[i].status2 &= ~STATUS2_POWDER;
|
||||
|
||||
if (gBattleStruct->battlerState[i].stompingTantrumTimer > 0)
|
||||
gBattleStruct->battlerState[i].stompingTantrumTimer--;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_BATTLE_SIDES; i++)
|
||||
@ -6041,7 +6044,10 @@ void SetTypeBeforeUsingMove(u32 move, u32 battler)
|
||||
gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | F_DYNAMIC_TYPE_SET;
|
||||
|
||||
// Check if a gem should activate.
|
||||
if (holdEffect == HOLD_EFFECT_GEMS && GetBattleMoveType(move) == ItemId_GetSecondaryId(heldItem))
|
||||
if (holdEffect == HOLD_EFFECT_GEMS
|
||||
&& GetBattleMoveType(move) == ItemId_GetSecondaryId(heldItem)
|
||||
&& GetMoveEffect(move) != EFFECT_PLEDGE
|
||||
&& GetMovePower(move) > 1)
|
||||
{
|
||||
gSpecialStatuses[battler].gemParam = GetBattlerHoldEffectParam(battler);
|
||||
gSpecialStatuses[battler].gemBoost = TRUE;
|
||||
|
||||
@ -637,6 +637,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
||||
[STRINGID_STEALTHROCKDMG] = COMPOUND_STRING("Pointed stones dug into {B_SCR_NAME_WITH_PREFIX2}!"),
|
||||
[STRINGID_TOXICSPIKESABSORBED] = COMPOUND_STRING("The poison spikes disappeared from the ground around {B_SCR_TEAM2} team!"),
|
||||
[STRINGID_TOXICSPIKESPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was poisoned!"),
|
||||
[STRINGID_TOXICSPIKESBADLYPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was badly poisoned!"),
|
||||
[STRINGID_STICKYWEBSWITCHIN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was caught in a sticky web!"),
|
||||
[STRINGID_HEALINGWISHCAMETRUE] = COMPOUND_STRING("The healing wish came true for {B_ATK_NAME_WITH_PREFIX2}!"),
|
||||
[STRINGID_HEALINGWISHHEALED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} regained health!"),
|
||||
|
||||
@ -1731,6 +1731,8 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 numTargets = 0;
|
||||
u32 numMisses = 0;
|
||||
u32 moveType = GetBattleMoveType(move);
|
||||
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move);
|
||||
bool32 calcSpreadMove = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(move);
|
||||
@ -1745,6 +1747,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
||||
|| (gBattleStruct->noResultString[battlerDef] && gBattleStruct->noResultString[battlerDef] != DO_ACCURACY_CHECK))
|
||||
continue;
|
||||
|
||||
numTargets++;
|
||||
if (JumpIfMoveAffectedByProtect(move, battlerDef, FALSE) || AccuracyCalcHelper(move, battlerDef))
|
||||
continue;
|
||||
|
||||
@ -1760,6 +1763,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
||||
{
|
||||
gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_MISSED;
|
||||
gBattleStruct->missStringId[battlerDef] = gBattleCommunication[MISS_TYPE] = B_MSG_MISSED;
|
||||
numMisses++;
|
||||
|
||||
if (holdEffectAtk == HOLD_EFFECT_BLUNDER_POLICY)
|
||||
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks
|
||||
@ -1771,6 +1775,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
||||
&& !TargetFullyImmuneToCurrMove(gBattlerAttacker, BATTLE_PARTNER(battlerDef)))
|
||||
{
|
||||
// Smart target to partner if miss
|
||||
numMisses = 0; // Other dart might hit
|
||||
gBattlerTarget = BATTLE_PARTNER(battlerDef);
|
||||
AccuracyCheck(TRUE, nextInstr, failInstr, move);
|
||||
return;
|
||||
@ -1781,6 +1786,9 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
||||
}
|
||||
}
|
||||
|
||||
if (numTargets == numMisses)
|
||||
gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2;
|
||||
|
||||
if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_MISSED)
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] = MOVE_RESULT_MISSED;
|
||||
|
||||
@ -2272,7 +2280,6 @@ static void Cmd_adjustdamage(void)
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)
|
||||
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& gBattleMons[gBattlerAttacker].item
|
||||
&& moveEffect != EFFECT_PLEDGE
|
||||
&& gCurrentMove != MOVE_STRUGGLE)
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
@ -2398,7 +2405,6 @@ static inline bool32 TryActivateWeakenessBerry(u32 battlerDef)
|
||||
{
|
||||
if (gSpecialStatuses[battlerDef].berryReduced && gBattleMons[battlerDef].item != ITEM_NONE)
|
||||
{
|
||||
gSpecialStatuses[battlerDef].berryReduced = FALSE;
|
||||
gBattleScripting.battler = battlerDef;
|
||||
gLastUsedItem = gBattleMons[battlerDef].item;
|
||||
gBattleStruct->partyState[GetBattlerSide(battlerDef)][gBattlerPartyIndexes[battlerDef]].ateBerry = TRUE;
|
||||
@ -6052,14 +6058,16 @@ static bool32 TryKnockOffBattleScript(u32 battlerDef)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define SYMBIOSIS_CHECK(battler, ally) \
|
||||
GetBattlerAbility(ally) == ABILITY_SYMBIOSIS \
|
||||
&& gBattleMons[battler].item == ITEM_NONE \
|
||||
&& gBattleMons[ally].item != ITEM_NONE \
|
||||
&& CanBattlerGetOrLoseItem(battler, gBattleMons[ally].item) \
|
||||
&& CanBattlerGetOrLoseItem(ally, gBattleMons[ally].item) \
|
||||
&& IsBattlerAlive(battler) \
|
||||
&& IsBattlerAlive(ally)
|
||||
static inline bool32 TryTriggerSymbiosis(u32 battler, u32 ally)
|
||||
{
|
||||
return GetBattlerAbility(ally) == ABILITY_SYMBIOSIS
|
||||
&& gBattleMons[battler].item == ITEM_NONE
|
||||
&& gBattleMons[ally].item != ITEM_NONE
|
||||
&& CanBattlerGetOrLoseItem(battler, gBattleMons[ally].item)
|
||||
&& CanBattlerGetOrLoseItem(ally, gBattleMons[ally].item)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& IsBattlerAlive(ally);
|
||||
}
|
||||
|
||||
static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent)
|
||||
{
|
||||
@ -6702,9 +6710,7 @@ static void Cmd_moveend(void)
|
||||
if ((gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE))
|
||||
|| (gBattleMons[gBattlerAttacker].status2 & (STATUS2_FLINCHED))
|
||||
|| gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility)
|
||||
gBattleStruct->battlerState[gBattlerAttacker].lastMoveFailed = TRUE;
|
||||
else
|
||||
gBattleStruct->battlerState[gBattlerAttacker].lastMoveFailed = FALSE;
|
||||
gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2;
|
||||
|
||||
// Set ShellTrap to activate after the attacker's turn if target was hit by a physical move.
|
||||
if (GetMoveEffect(gChosenMoveByBattler[gBattlerTarget]) == EFFECT_SHELL_TRAP
|
||||
@ -7335,7 +7341,7 @@ static void Cmd_moveend(void)
|
||||
{
|
||||
if ((gSpecialStatuses[i].berryReduced
|
||||
|| (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost))
|
||||
&& SYMBIOSIS_CHECK(i, BATTLE_PARTNER(i)))
|
||||
&& TryTriggerSymbiosis(i, BATTLE_PARTNER(i)))
|
||||
{
|
||||
BestowItem(BATTLE_PARTNER(i), i);
|
||||
gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability;
|
||||
@ -8243,8 +8249,11 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
{
|
||||
if (CanBePoisoned(gBattlerAttacker, battler, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(battler)))
|
||||
{
|
||||
if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2)
|
||||
u32 tspikes = 0;
|
||||
if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2) {
|
||||
tspikes = 1;
|
||||
gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON;
|
||||
}
|
||||
else
|
||||
gBattleMons[battler].status1 |= STATUS1_POISON;
|
||||
|
||||
@ -8252,7 +8261,10 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
MarkBattlerForControllerExec(battler);
|
||||
gBattleScripting.battler = battler;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned;
|
||||
if (tspikes == 0)
|
||||
gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_ToxicSpikesBadlyPoisoned;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9122,7 +9134,7 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId)
|
||||
&& (B_SYMBIOSIS_GEMS < GEN_7 || !(gSpecialStatuses[battler].gemBoost))
|
||||
&& gCurrentMove != MOVE_FLING //Fling and damage-reducing berries are handled separately.
|
||||
&& !gSpecialStatuses[battler].berryReduced
|
||||
&& SYMBIOSIS_CHECK(battler, BATTLE_PARTNER(battler)))
|
||||
&& TryTriggerSymbiosis(battler, BATTLE_PARTNER(battler)))
|
||||
{
|
||||
BestowItem(BATTLE_PARTNER(battler), battler);
|
||||
gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability;
|
||||
@ -10987,20 +10999,13 @@ static void Cmd_various(void)
|
||||
case VARIOUS_HANDLE_TRAINER_SLIDE_MSG:
|
||||
{
|
||||
VARIOUS_ARGS(u8 case_);
|
||||
if (cmd->case_ == 0)
|
||||
{
|
||||
// Save sprite IDs, because trainer slide in will overwrite gBattlerSpriteIds variable.
|
||||
gBattleStruct->storeBattlerSpriteId = (gBattlerSpriteIds[battler] & 0xFF) | (gBattlerSpriteIds[BATTLE_PARTNER(battler)] << 8);
|
||||
}
|
||||
else if (cmd->case_ == 1)
|
||||
if (cmd->case_ == PRINT_SLIDE_MESSAGE)
|
||||
{
|
||||
BtlController_EmitPrintString(battler, BUFFER_A, STRINGID_TRAINERSLIDE);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
}
|
||||
else
|
||||
else if (cmd->case_ == RESTORE_BATTLER_SLIDE_CONTROL)
|
||||
{
|
||||
gBattlerSpriteIds[BATTLE_PARTNER(battler)] = gBattleStruct->storeBattlerSpriteId >> 8;
|
||||
gBattlerSpriteIds[battler] = gBattleStruct->storeBattlerSpriteId & 0xFF;
|
||||
if (IsBattlerAlive(battler))
|
||||
{
|
||||
SetBattlerShadowSpriteCallback(battler, gBattleMons[battler].species);
|
||||
@ -16829,7 +16834,7 @@ void BS_TrySymbiosis(void)
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
//called by Bestow, Fling, and Bug Bite, which don't work with Cmd_removeitem.
|
||||
u32 partner = BATTLE_PARTNER(battler);
|
||||
if (SYMBIOSIS_CHECK(battler, partner))
|
||||
if (TryTriggerSymbiosis(battler, partner))
|
||||
{
|
||||
BestowItem(partner, battler);
|
||||
gLastUsedAbility = gBattleMons[partner].ability;
|
||||
|
||||
@ -2750,7 +2750,7 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbilit
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else if (B_ABILITY_WEATHER < GEN_6 && viaAbility)
|
||||
else if (GetGenConfig(GEN_CONFIG_ABILITY_WEATHER) < GEN_6 && viaAbility)
|
||||
{
|
||||
gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag;
|
||||
return TRUE;
|
||||
@ -3631,7 +3631,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
{
|
||||
move = gBattleMons[i].moves[j];
|
||||
moveType = GetBattleMoveType(move);
|
||||
if (CalcTypeEffectivenessMultiplier(move, moveType, i, battler, ABILITY_ANTICIPATION, FALSE) >= UQ_4_12(2.0))
|
||||
if (CalcTypeEffectivenessMultiplier(move, moveType, i, battler, ABILITY_ANTICIPATION, FALSE) >= UQ_4_12(2.0) || GetMoveEffect(move) == EFFECT_OHKO)
|
||||
{
|
||||
effect++;
|
||||
break;
|
||||
@ -6117,6 +6117,28 @@ static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID)
|
||||
return ITEM_NO_EFFECT;
|
||||
}
|
||||
|
||||
static enum ItemEffect ConsumeBerserkGene(u32 battler, enum ItemCaseId caseID)
|
||||
{
|
||||
if (CanBeInfinitelyConfused(battler))
|
||||
gStatuses4[battler] |= STATUS4_INFINITE_CONFUSION;
|
||||
|
||||
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
|
||||
gBattlerAttacker = gEffectBattler = battler;
|
||||
SET_STATCHANGER(STAT_ATK, 2, FALSE);
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_BerserkGeneRetEnd2);
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_BerserkGeneRet;
|
||||
}
|
||||
return ITEM_STATS_CHANGE;
|
||||
}
|
||||
|
||||
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID)
|
||||
{
|
||||
struct Pokemon *mon = GetBattlerMon(battler);
|
||||
@ -6530,19 +6552,7 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect)
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_BERSERK_GENE:
|
||||
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
|
||||
gEffectBattler = battler;
|
||||
if (CanBeInfinitelyConfused(gEffectBattler))
|
||||
{
|
||||
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
|
||||
}
|
||||
SET_STATCHANGER(STAT_ATK, 2, FALSE);
|
||||
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
effect = ConsumeBerserkGene(battler, ITEMEFFECT_NONE);
|
||||
break;
|
||||
case HOLD_EFFECT_MIRROR_HERB:
|
||||
effect = TryConsumeMirrorHerb(battler, ITEMEFFECT_NONE);
|
||||
@ -6815,19 +6825,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
effect = TryEjectPack(battler, caseID);
|
||||
break;
|
||||
case HOLD_EFFECT_BERSERK_GENE:
|
||||
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
|
||||
gEffectBattler = battler;
|
||||
if (CanBeInfinitelyConfused(gEffectBattler))
|
||||
{
|
||||
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
|
||||
}
|
||||
SET_STATCHANGER(STAT_ATK, 2, FALSE);
|
||||
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
effect = ConsumeBerserkGene(battler, caseID);
|
||||
break;
|
||||
case HOLD_EFFECT_MIRROR_HERB:
|
||||
effect = TryConsumeMirrorHerb(battler, caseID);
|
||||
@ -7030,19 +7028,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
effect = TrySetMicleBerry(battler, gLastUsedItem, caseID);
|
||||
break;
|
||||
case HOLD_EFFECT_BERSERK_GENE:
|
||||
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
|
||||
gEffectBattler = battler;
|
||||
if (CanBeInfinitelyConfused(gEffectBattler))
|
||||
{
|
||||
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
|
||||
}
|
||||
SET_STATCHANGER(STAT_ATK, 2, FALSE);
|
||||
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
effect = ConsumeBerserkGene(battler, caseID);
|
||||
break;
|
||||
case HOLD_EFFECT_MIRROR_HERB:
|
||||
effect = TryConsumeMirrorHerb(battler, caseID);
|
||||
@ -7164,6 +7150,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
break;
|
||||
case HOLD_EFFECT_LIFE_ORB:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !IsBattleMoveStatus(gCurrentMove)
|
||||
&& (IsBattlerTurnDamaged(gBattlerTarget) || !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Needs the second check in case of Substitute
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
@ -7819,12 +7806,24 @@ u32 GetProtectType(enum ProtectMethod method)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Only called directly when calculating damage type effectiveness
|
||||
static bool32 IsBattlerGroundedInverseCheck(u32 battler, bool32 considerInverse)
|
||||
enum InverseBattleCheck
|
||||
{
|
||||
INVERSE_BATTLE,
|
||||
NOT_INVERSE_BATTLE
|
||||
};
|
||||
|
||||
enum IronBallCheck
|
||||
{
|
||||
CHECK_IRON_BALL,
|
||||
IGNORE_IRON_BALL
|
||||
};
|
||||
|
||||
// Only called directly when calculating damage type effectiveness, and Iron Ball's type effectiveness mechanics
|
||||
static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall)
|
||||
{
|
||||
enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE);
|
||||
|
||||
if (holdEffect == HOLD_EFFECT_IRON_BALL)
|
||||
if (!(checkIronBall == IGNORE_IRON_BALL) && holdEffect == HOLD_EFFECT_IRON_BALL)
|
||||
return TRUE;
|
||||
if (gFieldStatuses & STATUS_FIELD_GRAVITY)
|
||||
return TRUE;
|
||||
@ -7840,14 +7839,14 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, bool32 considerInverse)
|
||||
return FALSE;
|
||||
if ((AI_DATA->aiCalcInProgress ? AI_DATA->abilities[battler] : GetBattlerAbility(battler)) == ABILITY_LEVITATE)
|
||||
return FALSE;
|
||||
if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!considerInverse || !FlagGet(B_FLAG_INVERSE_BATTLE)))
|
||||
if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!(checkInverse == INVERSE_BATTLE) || !FlagGet(B_FLAG_INVERSE_BATTLE)))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 IsBattlerGrounded(u32 battler)
|
||||
{
|
||||
return IsBattlerGroundedInverseCheck(battler, FALSE);
|
||||
return IsBattlerGroundedInverseCheck(battler, NOT_INVERSE_BATTLE, CHECK_IRON_BALL);
|
||||
}
|
||||
|
||||
u32 GetMoveSlot(u16 *moves, u32 move)
|
||||
@ -8358,7 +8357,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData *
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(0.5));
|
||||
break;
|
||||
case EFFECT_STOMPING_TANTRUM:
|
||||
if (gBattleStruct->battlerState[battlerAtk].lastMoveFailed)
|
||||
if (gBattleStruct->battlerState[battlerAtk].stompingTantrumTimer == 1)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(2.0));
|
||||
break;
|
||||
case EFFECT_MAGNITUDE:
|
||||
@ -9764,7 +9763,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov
|
||||
if (B_GLARE_GHOST < GEN_4 && move == MOVE_GLARE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST))
|
||||
modifier = UQ_4_12(0.0);
|
||||
}
|
||||
else if (moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(battlerDef, TRUE) && !(MoveIgnoresTypeIfFlyingAndUngrounded(move)))
|
||||
else if (moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(battlerDef, INVERSE_BATTLE, CHECK_IRON_BALL) && !(MoveIgnoresTypeIfFlyingAndUngrounded(move)))
|
||||
{
|
||||
modifier = UQ_4_12(0.0);
|
||||
if (recordAbilities && defAbility == ABILITY_LEVITATE)
|
||||
@ -9789,6 +9788,17 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov
|
||||
modifier = UQ_4_12(1.0);
|
||||
}
|
||||
|
||||
// Iron Ball ignores type modifiers for flying-type mons if it is the only source of grounding
|
||||
if (B_IRON_BALL >= GEN_5
|
||||
&& moveType == TYPE_GROUND
|
||||
&& IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING)
|
||||
&& GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_IRON_BALL
|
||||
&& !IsBattlerGroundedInverseCheck(battlerDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL)
|
||||
&& !FlagGet(B_FLAG_INVERSE_BATTLE))
|
||||
{
|
||||
modifier = UQ_4_12(1.0);
|
||||
}
|
||||
|
||||
if (((defAbility == ABILITY_WONDER_GUARD && modifier <= UQ_4_12(1.0))
|
||||
|| (defAbility == ABILITY_TELEPATHY && battlerDef == BATTLE_PARTNER(battlerAtk)))
|
||||
&& GetMovePower(move) != 0)
|
||||
@ -11369,8 +11379,8 @@ void ClearDamageCalcResults(void)
|
||||
bool32 DoesDestinyBondFail(u32 battler)
|
||||
{
|
||||
if (B_DESTINY_BOND_FAIL >= GEN_7
|
||||
&& GetMoveEffect(gLastResultingMoves[battler]) == EFFECT_DESTINY_BOND
|
||||
&& !gBattleStruct->battlerState[battler].lastMoveFailed)
|
||||
&& GetMoveEffect(gLastLandedMoves[battler]) == EFFECT_DESTINY_BOND
|
||||
&& GetMoveEffect(gLastResultingMoves[battler]) == EFFECT_DESTINY_BOND)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -4278,6 +4278,13 @@ static const u16 sBasculinEggMoveLearnset[] = {
|
||||
MOVE_HEAD_SMASH,
|
||||
MOVE_UNAVAILABLE,
|
||||
};
|
||||
#if P_HISUIAN_FORMS
|
||||
static const u16 sBasculinWhiteStripedEggMoveLearnset[] = {
|
||||
MOVE_ENDEAVOR,
|
||||
MOVE_LAST_RESPECTS,
|
||||
MOVE_UNAVAILABLE,
|
||||
};
|
||||
#endif //P_HISUIAN_FORMS
|
||||
#endif //P_FAMILY_BASCULIN
|
||||
|
||||
#if P_FAMILY_SANDILE
|
||||
|
||||
@ -4502,6 +4502,7 @@ const struct SpeciesInfo gSpeciesInfoGen5[] =
|
||||
)
|
||||
.levelUpLearnset = sBasculinWhiteStripedLevelUpLearnset,
|
||||
.teachableLearnset = sBasculinWhiteStripedTeachableLearnset,
|
||||
.eggMoveLearnset = sBasculinWhiteStripedEggMoveLearnset,
|
||||
.formSpeciesIdTable = sBasculinFormSpeciesIdTable,
|
||||
.evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_BASCULEGION_M, CONDITIONS({IF_RECOIL_DAMAGE_GE, 294}, {IF_GENDER, MON_MALE})},
|
||||
{EVO_LEVEL, 0, SPECIES_BASCULEGION_F, CONDITIONS({IF_RECOIL_DAMAGE_GE, 294}, {IF_GENDER, MON_FEMALE})}),
|
||||
|
||||
@ -1110,7 +1110,7 @@ void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFix
|
||||
void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
|
||||
{
|
||||
u8 speciesName[POKEMON_NAME_LENGTH + 1];
|
||||
u32 personality;
|
||||
u32 personality = Random32();
|
||||
u32 value;
|
||||
u16 checksum;
|
||||
u8 i;
|
||||
@ -1120,11 +1120,6 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
|
||||
|
||||
ZeroBoxMonData(boxMon);
|
||||
|
||||
if (hasFixedPersonality)
|
||||
personality = fixedPersonality;
|
||||
else
|
||||
personality = Random32();
|
||||
|
||||
// Determine original trainer ID
|
||||
if (otIdType == OT_ID_RANDOM_NO_SHINY)
|
||||
{
|
||||
@ -1134,7 +1129,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
|
||||
else if (otIdType == OT_ID_PRESET)
|
||||
{
|
||||
value = fixedOtId;
|
||||
isShiny = GET_SHINY_VALUE(value, personality) < SHINY_ODDS;
|
||||
isShiny = GET_SHINY_VALUE(value, hasFixedPersonality ? fixedPersonality : personality) < SHINY_ODDS;
|
||||
}
|
||||
else // Player is the OT
|
||||
{
|
||||
@ -1180,6 +1175,9 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
|
||||
isShiny = GET_SHINY_VALUE(value, personality) < SHINY_ODDS;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFixedPersonality)
|
||||
personality = fixedPersonality;
|
||||
|
||||
SetBoxMonData(boxMon, MON_DATA_PERSONALITY, &personality);
|
||||
SetBoxMonData(boxMon, MON_DATA_OT_ID, &value);
|
||||
|
||||
@ -1,24 +1,353 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a super-effective move");
|
||||
TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a One-hit KO move");
|
||||
TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a Self-Destruct or Explosion (Gen4)");
|
||||
TO_DO_BATTLE_TEST("Anticipation treats Self-Destruct and Explosion like all other Normal types (Gen5+)");
|
||||
SINGLE_BATTLE_TEST("Anticipation causes notifies if an opponent has a super-effective move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CLOSE_COMBAT, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation causes notifies if an opponent has a One-hit KO move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FISSURE) == EFFECT_OHKO);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_FISSURE, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation treats Self-Destruct and Explosion like all other Normal types (Gen5+)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_EXPLOSION, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation doesn't consider Normalize into their effectiveness (Gen5+)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_DELCATTY) { Ability(ABILITY_NORMALIZE); Moves(MOVE_CLOSE_COMBAT, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation doesn't consider Scrappy into their effectiveness (Gen5+)")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); Moves(MOVE_CLOSE_COMBAT, MOVE_TRICK_OR_TREAT, MOVE_SKILL_SWAP, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TRICK_OR_TREAT); MOVE(player, MOVE_SKILL_SWAP); }
|
||||
TURN { MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK_OR_TREAT, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation doesn't consider Gravity into their effectiveness (Gen5+)")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SKARMORY);
|
||||
OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_EARTHQUAKE, MOVE_GRAVITY, MOVE_SCRATCH, MOVE_POUND); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_GRAVITY); MOVE(player, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRAVITY, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player);
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation counts Counter, Metal Burst or Mirror Coat as attacking moves of their types (Gen5+)")
|
||||
{
|
||||
u32 move, species, typeAtk, typeDef;
|
||||
PARAMETRIZE { move = MOVE_COUNTER; species = SPECIES_RATICATE; typeAtk = TYPE_FIGHTING; typeDef = TYPE_NORMAL; }
|
||||
PARAMETRIZE { move = MOVE_METAL_BURST; species = SPECIES_ROGGENROLA; typeAtk = TYPE_STEEL; typeDef = TYPE_ROCK; }
|
||||
PARAMETRIZE { move = MOVE_MIRROR_COAT; species = SPECIES_NIDORINO; typeAtk = TYPE_PSYCHIC; typeDef = TYPE_POISON; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(move) == typeAtk);
|
||||
ASSUME(gSpeciesInfo[species].types[0] == typeDef);
|
||||
ASSUME(gSpeciesInfo[species].types[1] == typeDef);
|
||||
PLAYER(species);
|
||||
OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(move, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation considers Synchronoise as an ordinary Psychic-type move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_SYNCHRONOISE) == TYPE_PSYCHIC);
|
||||
ASSUME(gSpeciesInfo[SPECIES_NIDORINO].types[0] == TYPE_POISON);
|
||||
ASSUME(gSpeciesInfo[SPECIES_NIDORINO].types[1] == TYPE_POISON);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] != TYPE_POISON);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] != TYPE_POISON);
|
||||
PLAYER(SPECIES_NIDORINO);
|
||||
OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_SYNCHRONOISE, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation considers Freeze-Dry as an ordinary Ice-type move")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_FREEZE_DRY) == TYPE_ICE);
|
||||
ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[0] == TYPE_WATER);
|
||||
ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[1] == TYPE_WATER);
|
||||
PLAYER(SPECIES_SQUIRTLE);
|
||||
OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_FREEZE_DRY, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation considers Flying Press as an ordinary Fighting-type move")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_FLYING_PRESS) == TYPE_FIGHTING);
|
||||
ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[0] == TYPE_GRASS);
|
||||
ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[1] == TYPE_GRASS);
|
||||
PLAYER(SPECIES_TANGELA);
|
||||
OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_FLYING_PRESS, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation considers Aura Wheel as an ordinary Electric-type move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_AURA_WHEEL) == TYPE_ELECTRIC);
|
||||
ASSUME(gSpeciesInfo[SPECIES_PONYTA_GALAR].types[0] == TYPE_PSYCHIC);
|
||||
ASSUME(gSpeciesInfo[SPECIES_PONYTA_GALAR].types[1] == TYPE_PSYCHIC);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_PONYTA_GALAR) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); Moves(MOVE_AURA_WHEEL, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { SWITCH(player, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Judgment")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_JUDGMENT) == EFFECT_CHANGE_TYPE_ON_ITEM);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_ARCEUS) { Item(ITEM_FIST_PLATE); Moves(MOVE_JUDGMENT, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Weather Ball")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_WEATHER_BALL) == EFFECT_WEATHER_BALL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[0] == TYPE_GRASS);
|
||||
ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[1] == TYPE_STEEL);
|
||||
PLAYER(SPECIES_FERROTHORN) { Ability(ABILITY_ANTICIPATION); Speed(2); }
|
||||
OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); Moves(MOVE_WEATHER_BALL, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); Speed(4); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SKILL_SWAP); MOVE(player, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_DROUGHT);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player);
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Natural Gift")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_NATURAL_GIFT) == EFFECT_NATURAL_GIFT);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LEPPA_BERRY); Moves(MOVE_NATURAL_GIFT, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Techno Blast")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_TECHNO_BLAST) == EFFECT_CHANGE_TYPE_ON_ITEM);
|
||||
ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[0] == TYPE_GRASS);
|
||||
ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[1] == TYPE_STEEL);
|
||||
PLAYER(SPECIES_FERROTHORN) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_GENESECT) { Item(ITEM_BURN_DRIVE); Moves(MOVE_TECHNO_BLAST, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Revelation Dance")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_REVELATION_DANCE) == EFFECT_REVELATION_DANCE);
|
||||
ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[0] == TYPE_GRASS);
|
||||
ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[1] == TYPE_STEEL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_ORICORIO_BAILE].types[0] == TYPE_FIRE);
|
||||
PLAYER(SPECIES_FERROTHORN) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_ORICORIO_BAILE) { Moves(MOVE_REVELATION_DANCE, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Multi-Attack")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_MULTI_ATTACK) == EFFECT_CHANGE_TYPE_ON_ITEM);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_SILVALLY) { Item(ITEM_FIGHTING_MEMORY); Moves(MOVE_MULTI_ATTACK, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation does not consider Strong Winds on type matchups")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_RAYQUAZA_MEGA].types[0] == TYPE_DRAGON);
|
||||
ASSUME(gSpeciesInfo[SPECIES_RAYQUAZA_MEGA].types[1] == TYPE_FLYING);
|
||||
PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_ROCK_SLIDE, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_DELTA_STREAM);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation does not consider ate-abilities")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_SCRATCH) == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_WORMADAM_PLANT].types[0] == TYPE_BUG);
|
||||
ASSUME(gSpeciesInfo[SPECIES_WORMADAM_PLANT].types[1] == TYPE_GRASS);
|
||||
PLAYER(SPECIES_WORMADAM_PLANT) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_AURORUS) { Ability(ABILITY_REFRIGERATE); Moves(MOVE_GROWL, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation treats Hidden Power as its dynamic type (Gen6+)")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Item(ITEM_CHOPLE_BERRY); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_HIDDEN_POWER, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); HPIV(30); AttackIV(2); DefenseIV(31); SpAttackIV(30); SpDefenseIV(30); SpeedIV(30); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_HIDDEN_POWER); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); // Check that the item is triggered
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HIDDEN_POWER, opponent);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("It's super effective!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anticipation considers Inverse Battle types")
|
||||
{
|
||||
GIVEN {
|
||||
FLAG_SET(B_FLAG_INVERSE_BATTLE);
|
||||
ASSUME(GetMoveType(MOVE_SCRATCH) == TYPE_NORMAL);
|
||||
ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[0] == TYPE_GRASS);
|
||||
ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[1] == TYPE_STEEL);
|
||||
PLAYER(SPECIES_FERROTHORN) { Ability(ABILITY_ANTICIPATION); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_GROWL, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_ANTICIPATION);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a Self-Destruct or Explosion (Gen4)");
|
||||
TO_DO_BATTLE_TEST("Anticipation considers Scrappy and Normalize into their effectiveness (Gen4)");
|
||||
TO_DO_BATTLE_TEST("Anticipation doesn't consider Scrappy and Normalize into their effectiveness (Gen5+)");
|
||||
TO_DO_BATTLE_TEST("Anticipation considers Gravity into their effectiveness (Gen4)");
|
||||
TO_DO_BATTLE_TEST("Anticipation doesn't consider Gravity into their effectiveness (Gen5+)");
|
||||
TO_DO_BATTLE_TEST("Anticipation doesn't trigger from Counter, Metal Burst or Mirror Coat (Gen4)");
|
||||
TO_DO_BATTLE_TEST("Anticipation counts Counter, Metal Burst or Mirror Coat as attacking moves of their types (Gen5+)");
|
||||
TO_DO_BATTLE_TEST("Anticipation considers Synchronoise as an ordinary Psychic-type move");
|
||||
TO_DO_BATTLE_TEST("Anticipation considers Freeze-Dry as an ordinary Ice-type move");
|
||||
TO_DO_BATTLE_TEST("Anticipation considers Flying Press as an ordinary Fighting-type move");
|
||||
TO_DO_BATTLE_TEST("Anticipation considers Aura Wheel as an ordinary Electric-type move");
|
||||
TO_DO_BATTLE_TEST("Anticipation considers Inverse Battle types"); //Check with Normal-type moves
|
||||
TO_DO_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal)"); // Judgment, Weather Ball, Natural Gift, Techno Blast, Revelation Dance, Multi Attack
|
||||
TO_DO_BATTLE_TEST("Anticipation treats Hidden Power as Normal Type (Gen4-5)");
|
||||
TO_DO_BATTLE_TEST("Anticipation treats Hidden Power as its dynamic type (Gen6+)");
|
||||
TO_DO_BATTLE_TEST("Anticipation does not consider Strong Winds on type matchups");
|
||||
TO_DO_BATTLE_TEST("Anticipation does not consider ate-abilities");
|
||||
|
||||
@ -1,5 +1,83 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)");
|
||||
TO_DO_BATTLE_TEST("Drought sets up permanent sun (Gen3-5)");
|
||||
SINGLE_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_DROUGHT);
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight faded.");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Drought sets up sun for 8 turns with Heat Rock (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_6);
|
||||
PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); Item(ITEM_HEAT_ROCK); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_DROUGHT);
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight faded.");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Drought sets up permanent sun (Gen3-5)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_3);
|
||||
PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_DROUGHT);
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The sunlight is strong.");
|
||||
NOT MESSAGE("The sunlight faded.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,5 +138,27 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder"
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4");
|
||||
TO_DO_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+");
|
||||
SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+")
|
||||
{
|
||||
s16 damage;
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_SLEEP);
|
||||
ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_TENTACRUEL) { Ability(ABILITY_LIQUID_OOZE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SCRATCH); MOVE(player, MOVE_SPORE); }
|
||||
TURN { MOVE(player, MOVE_DREAM_EATER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
|
||||
HP_BAR(player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DREAM_EATER, player);
|
||||
HP_BAR(opponent);
|
||||
HP_BAR(player, captureDamage: &damage);
|
||||
} THEN {
|
||||
EXPECT_LT(damage, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4")
|
||||
|
||||
@ -1,6 +1,63 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Sand Force prevents damage from sandstorm");
|
||||
TO_DO_BATTLE_TEST("Sand Force increases the power of Rock-, Ground- and Steel-type moves by 30% in sandstorm");
|
||||
TO_DO_BATTLE_TEST("Sand Force increases move power if Cloud Nine/Air Lock is on the field");
|
||||
SINGLE_BATTLE_TEST("Sand Force prevents damage from sandstorm")
|
||||
{
|
||||
u32 type1 = gSpeciesInfo[SPECIES_SHELLOS].types[0];
|
||||
u32 type2 = gSpeciesInfo[SPECIES_SHELLOS].types[1];
|
||||
GIVEN {
|
||||
ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK);
|
||||
ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND);
|
||||
ASSUME(type1 != TYPE_STEEL && type2 != TYPE_STEEL);
|
||||
PLAYER(SPECIES_SHELLOS) { Ability(ABILITY_SAND_FORCE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SANDSTORM); }
|
||||
} SCENE {
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sand Force increases the power of Rock-, Ground- and Steel-type moves by 30% in sandstorm", s16 damage)
|
||||
{
|
||||
u32 moveOpponent, movePlayer;
|
||||
PARAMETRIZE { moveOpponent = MOVE_CELEBRATE; movePlayer = MOVE_ROCK_THROW; }
|
||||
PARAMETRIZE { moveOpponent = MOVE_SANDSTORM; movePlayer = MOVE_ROCK_THROW; }
|
||||
PARAMETRIZE { moveOpponent = MOVE_CELEBRATE; movePlayer = MOVE_EARTHQUAKE; }
|
||||
PARAMETRIZE { moveOpponent = MOVE_SANDSTORM; movePlayer = MOVE_EARTHQUAKE; }
|
||||
PARAMETRIZE { moveOpponent = MOVE_CELEBRATE; movePlayer = MOVE_IRON_HEAD; }
|
||||
PARAMETRIZE { moveOpponent = MOVE_SANDSTORM; movePlayer = MOVE_IRON_HEAD; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_ROCK_THROW) == TYPE_ROCK);
|
||||
ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND);
|
||||
ASSUME(GetMoveType(MOVE_IRON_HEAD) == TYPE_STEEL);
|
||||
PLAYER(SPECIES_SHELLOS) { Ability(ABILITY_SAND_FORCE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, moveOpponent); MOVE(player, movePlayer); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage);
|
||||
EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.3), results[3].damage);
|
||||
EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.3), results[5].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sand Force don't increase move power if Cloud Nine/Air Lock is on the field", s16 damage)
|
||||
{
|
||||
u32 move;
|
||||
PARAMETRIZE { move = MOVE_CELEBRATE; }
|
||||
PARAMETRIZE { move = MOVE_SANDSTORM; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_ROCK_THROW) == TYPE_ROCK);
|
||||
PLAYER(SPECIES_SHELLOS) { Ability(ABILITY_SAND_FORCE); }
|
||||
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, move); MOVE(player, MOVE_ROCK_THROW); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,51 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Sand Rush prevents damage from sandstorm");
|
||||
TO_DO_BATTLE_TEST("Sand Rush doubles speed from sandstorm");
|
||||
TO_DO_BATTLE_TEST("Sand Rush doesn't double speed if Cloud Nine/Air Lock is on the field");
|
||||
SINGLE_BATTLE_TEST("Sand Rush prevents damage from sandstorm")
|
||||
{
|
||||
u32 type1 = gSpeciesInfo[SPECIES_STOUTLAND].types[0];
|
||||
u32 type2 = gSpeciesInfo[SPECIES_STOUTLAND].types[1];
|
||||
GIVEN {
|
||||
ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK);
|
||||
ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND);
|
||||
ASSUME(type1 != TYPE_STEEL && type2 != TYPE_STEEL);
|
||||
PLAYER(SPECIES_STOUTLAND) { Ability(ABILITY_SAND_RUSH); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SANDSTORM); }
|
||||
} SCENE {
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sand Rush doubles speed from sandstorm")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SANDSLASH) { Ability(ABILITY_SAND_RUSH); Speed(100); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(199); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SANDSTORM); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SANDSTORM, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sand Rush doesn't double speed if Cloud Nine/Air Lock is on the field")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SANDSLASH) { Ability(ABILITY_SAND_RUSH); Speed(100); }
|
||||
OPPONENT(SPECIES_GOLDUCK) { Speed(199); Ability(ABILITY_CLOUD_NINE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SANDSTORM); }
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SANDSTORM, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,5 +29,17 @@ SINGLE_BATTLE_TEST("Sand Veil increases evasion during sandstorm")
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Sand Veil doesn't prevent Sandstorm damage if Cloud Nine/Air Lock is on the field");
|
||||
TO_DO_BATTLE_TEST("Sand Veil doesn't increase evasion if Cloud Nine/Air Lock is on the field");
|
||||
SINGLE_BATTLE_TEST("Sand Veil doesn't increase evasion if Cloud Nine/Air Lock is on the field")
|
||||
{
|
||||
PASSES_RANDOMLY(5, 5, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveAccuracy(MOVE_POUND) == 100);
|
||||
PLAYER(SPECIES_SANDSHREW) { Ability(ABILITY_SAND_VEIL); }
|
||||
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SANDSTORM); }
|
||||
TURN { MOVE(opponent, MOVE_POUND); }
|
||||
} SCENE {
|
||||
HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,65 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Slush Rush doubles speed from hail");
|
||||
TO_DO_BATTLE_TEST("Slush Rush doubles speed from snow");
|
||||
TO_DO_BATTLE_TEST("Slush Rush doesn't double speed if Cloud Nine/Air Lock is on the field");
|
||||
SINGLE_BATTLE_TEST("Slush Rush doubles speed from hail")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_CETITAN) { Ability(ABILITY_SLUSH_RUSH); Speed(100); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(199); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_HAIL); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HAIL, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Slush Rush doubles speed from snow")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_CETITAN) { Ability(ABILITY_SLUSH_RUSH); Speed(100); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(199); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SNOWSCAPE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Slush Rush doesn't double speed if Cloud Nine/Air Lock is on the field")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_CETITAN) { Ability(ABILITY_SLUSH_RUSH); Speed(100); }
|
||||
OPPONENT(SPECIES_GOLDUCK) { Speed(199); Ability(ABILITY_CLOUD_NINE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SNOWSCAPE); }
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Slush Rush doesn't prevent non-Ice types from taking damage in Hail")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_ICE);
|
||||
ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_ICE);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_CETITAN) { Ability(ABILITY_SLUSH_RUSH); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_HAIL); MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HAIL, player);
|
||||
HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,70 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Solar Power increases a Sp. Attack by x1.5 in Sun");
|
||||
TO_DO_BATTLE_TEST("Solar Power doesn't increases a Sp. Attack if Cloud Nine/Air Lock is on the field");
|
||||
TO_DO_BATTLE_TEST("Solar Power causes the Pokémon to lose 1/8 max HP in Sun");
|
||||
TO_DO_BATTLE_TEST("Solar Power doesn't cause the Pokémon to lose 1/8 max HP if Cloud Nine/Air Lock is on the field");
|
||||
SINGLE_BATTLE_TEST("Solar Power increases a Sp. Attack by x1.5 in Sun", s16 damage)
|
||||
{
|
||||
u32 move;
|
||||
PARAMETRIZE { move = MOVE_CELEBRATE; }
|
||||
PARAMETRIZE { move = MOVE_SUNNY_DAY; }
|
||||
GIVEN {
|
||||
ASSUME(GetMovePower(MOVE_HYPER_VOICE) > 0);
|
||||
ASSUME(GetMoveCategory(MOVE_HYPER_VOICE) == DAMAGE_CATEGORY_SPECIAL);
|
||||
PLAYER(SPECIES_CHARIZARD) { Ability(ABILITY_SOLAR_POWER); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, move); MOVE(player, MOVE_HYPER_VOICE); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
if (move == MOVE_SUNNY_DAY)
|
||||
HP_BAR(player);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Solar Power doesn't increases a Sp. Attack if Cloud Nine/Air Lock is on the field", s16 damage)
|
||||
{
|
||||
u32 move;
|
||||
PARAMETRIZE { move = MOVE_CELEBRATE; }
|
||||
PARAMETRIZE { move = MOVE_SUNNY_DAY; }
|
||||
GIVEN {
|
||||
ASSUME(GetMovePower(MOVE_HYPER_VOICE) > 0);
|
||||
ASSUME(GetMoveCategory(MOVE_HYPER_VOICE) == DAMAGE_CATEGORY_SPECIAL);
|
||||
PLAYER(SPECIES_CHARIZARD) { Ability(ABILITY_SOLAR_POWER); }
|
||||
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, move); MOVE(player, MOVE_HYPER_VOICE); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Solar Power causes the Pokémon to lose 1/8 max HP in Sun")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_CHARIZARD) { Ability(ABILITY_SOLAR_POWER); MaxHP(80); HP(80); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} SCENE {
|
||||
TURN { MOVE(opponent, MOVE_SUNNY_DAY); }
|
||||
} SCENE {
|
||||
HP_BAR(player);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->hp, player->maxHP - player->maxHP/8);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Solar Power doesn't cause the Pokémon to lose 1/8 max HP if Cloud Nine/Air Lock is on the field")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_CHARIZARD) { Ability(ABILITY_SOLAR_POWER); MaxHP(80); HP(80); }
|
||||
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUNNY_DAY); }
|
||||
} SCENE {
|
||||
NOT HP_BAR(player);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->hp, player->maxHP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ DOUBLE_BATTLE_TEST("Symbiosis transfers its item to an ally after it consumes an
|
||||
MESSAGE("Oranguru passed its Toxic Orb to Wobbuffet through Symbiosis!");
|
||||
// end of turn, wobb gets poisoned
|
||||
MESSAGE("Wobbuffet was badly poisoned!");
|
||||
STATUS_ICON(playerLeft, STATUS1_TOXIC_POISON);
|
||||
STATUS_ICON(playerLeft, STATUS1_TOXIC_POISON);
|
||||
} THEN {
|
||||
EXPECT_EQ(playerLeft->item, ITEM_TOXIC_ORB);
|
||||
EXPECT_EQ(playerRight->item, ITEM_NONE);
|
||||
@ -111,3 +111,24 @@ DOUBLE_BATTLE_TEST("Symbiosis triggers after partner flings its item")
|
||||
EXPECT_EQ(playerRight->item, ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Symbiosis transfers its item to an ally after it consumes a weakness berry")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_CHILAN_BERRY].holdEffect == HOLD_EFFECT_RESIST_BERRY);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_CHILAN_BERRY); }
|
||||
PLAYER(SPECIES_ORANGURU) { Ability(ABILITY_SYMBIOSIS); Item(ITEM_TOXIC_ORB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_TACKLE, target: playerLeft); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft);
|
||||
ABILITY_POPUP(playerRight, ABILITY_SYMBIOSIS);
|
||||
STATUS_ICON(playerLeft, STATUS1_TOXIC_POISON);
|
||||
} THEN {
|
||||
EXPECT_EQ(playerLeft->item, ITEM_TOXIC_ORB);
|
||||
EXPECT_EQ(playerRight->item, ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -931,6 +931,29 @@ AI_SINGLE_BATTLE_TEST("AI sees popped Air Balloon after Air Balloon mon switches
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("AI correctly records used moves")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, MOVE_GROWL, MOVE_FLOWER_TRICK, MOVE_TORCH_SONG); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_RAGE_FIST, MOVE_PSYCHIC, MOVE_SCRATCH, MOVE_EARTHQUAKE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_EARTHQUAKE); }
|
||||
TURN { MOVE(player, MOVE_FLOWER_TRICK); MOVE(opponent, MOVE_SCRATCH); }
|
||||
TURN { MOVE(player, MOVE_TORCH_SONG); MOVE(opponent, MOVE_PSYCHIC); }
|
||||
TURN { MOVE(player, MOVE_GROWL); MOVE(opponent, MOVE_RAGE_FIST); }
|
||||
} THEN {
|
||||
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_PLAYER_LEFT][0], MOVE_TACKLE);
|
||||
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_PLAYER_LEFT][1], MOVE_GROWL);
|
||||
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_PLAYER_LEFT][2], MOVE_FLOWER_TRICK);
|
||||
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_PLAYER_LEFT][3], MOVE_TORCH_SONG);
|
||||
|
||||
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_OPPONENT_LEFT][0], MOVE_RAGE_FIST);
|
||||
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_OPPONENT_LEFT][1], MOVE_PSYCHIC);
|
||||
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_OPPONENT_LEFT][2], MOVE_SCRATCH);
|
||||
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_OPPONENT_LEFT][3], MOVE_EARTHQUAKE);
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI won't boost stats against opponent with Unaware")
|
||||
{
|
||||
GIVEN {
|
||||
|
||||
@ -236,3 +236,19 @@ SINGLE_BATTLE_TEST("Berserk Gene causes confusion timer to not tick down", u32 s
|
||||
EXPECT_EQ(results[0].status2, results[1].status2);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Berserk Gene does not cause an infinite loop")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_BESTOW) == EFFECT_BESTOW);
|
||||
PLAYER(SPECIES_TOXEL) { Item(ITEM_BERSERK_GENE); Ability(ABILITY_KLUTZ); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BESTOW); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Using Berserk Gene, the Attack of the opposing Wobbuffet sharply rose!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,3 +87,19 @@ SINGLE_BATTLE_TEST("Gem is consumed if the move type is changed")
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FEINT_ATTACK, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Gem is not consumed if a no type damage move is used") //ie. Counter, Psywave, Super Fang. All these moves have 1 base power.
|
||||
{
|
||||
ASSUME(GetMovePower(MOVE_PSYWAVE) == 1);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_GEM); };
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_PSYWAVE); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
|
||||
MESSAGE("The Psychic Gem strengthened Wobbuffet's power!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
test/battle/hold_effect/iron_ball.c
Normal file
22
test/battle/hold_effect/iron_ball.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS{
|
||||
ASSUME(gItemsInfo[ITEM_IRON_BALL].holdEffect == HOLD_EFFECT_IRON_BALL);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Ground-type moves do neutral damage to non-grounded Flying types holding Iron Ball regardless of other typings") //gen5+ only
|
||||
{
|
||||
ASSUME(B_IRON_BALL >= GEN_5);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SKARMORY) { Item(ITEM_IRON_BALL); };
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_EARTHQUAKE); };
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, player);
|
||||
NONE_OF {
|
||||
MESSAGE("It's super effective!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,3 +15,19 @@ SINGLE_BATTLE_TEST("Life Orb activates if it hits a Substitute")
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Life Orb does not activate if using a status move")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_GROWL); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, player);
|
||||
NONE_OF {
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ ASSUMPTIONS
|
||||
ASSUME(GetMoveEffect(MOVE_STOMPING_TANTRUM) == EFFECT_STOMPING_TANTRUM);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stomping Tatrum will deal double damage if user flinched on the previous turn")
|
||||
SINGLE_BATTLE_TEST("Stomping Tantrum will deal double damage if user flinched on the previous turn")
|
||||
{
|
||||
s16 damage[3];
|
||||
GIVEN {
|
||||
@ -36,7 +36,7 @@ SINGLE_BATTLE_TEST("Stomping Tatrum will deal double damage if user flinched on
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stomping Tatrum will deal double damage if user failed to attack due to paralysis")
|
||||
SINGLE_BATTLE_TEST("Stomping Tantrum will deal double damage if user failed to attack due to paralysis")
|
||||
{
|
||||
s16 damage[3];
|
||||
PASSES_RANDOMLY(25, 100, RNG_PARALYSIS);
|
||||
@ -66,7 +66,7 @@ SINGLE_BATTLE_TEST("Stomping Tatrum will deal double damage if user failed to at
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stomping Tatrum will not deal double damage if target protects")
|
||||
SINGLE_BATTLE_TEST("Stomping Tantrum will not deal double damage if target protects")
|
||||
{
|
||||
s16 damage[2];
|
||||
GIVEN {
|
||||
@ -90,7 +90,7 @@ SINGLE_BATTLE_TEST("Stomping Tatrum will not deal double damage if target protec
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stomping Tatrum will not deal double if it missed")
|
||||
SINGLE_BATTLE_TEST("Stomping Tantrum will not deal double if it missed")
|
||||
{
|
||||
s16 damage[2];
|
||||
GIVEN {
|
||||
@ -107,11 +107,11 @@ SINGLE_BATTLE_TEST("Stomping Tatrum will not deal double if it missed")
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STOMPING_TANTRUM, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[1]);
|
||||
} THEN {
|
||||
EXPECT_EQ(damage[0], damage[1]);
|
||||
EXPECT_MUL_EQ(damage[0], Q_4_12(2.0), damage[1]);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Stomping Tatrum will deal double damage if user was immune to previous move")
|
||||
SINGLE_BATTLE_TEST("Stomping Tantrum will deal double damage if user was immune to previous move")
|
||||
{
|
||||
s16 damage[2];
|
||||
GIVEN {
|
||||
|
||||
@ -235,3 +235,34 @@ SINGLE_BATTLE_TEST("Toxic Spikes inflicts poison on switch in after Primal Rever
|
||||
STATUS_ICON(player, poison: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Spikes print normal poison for 1 layer")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TOXIC_SPIKES); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
MESSAGE("The opposing Wynaut was poisoned!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Toxic Spikes print bad poison for 2 layers")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TOXIC_SPIKES); }
|
||||
TURN { MOVE(player, MOVE_TOXIC_SPIKES); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
MESSAGE("The opposing Wynaut was badly poisoned!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,3 +90,17 @@ SINGLE_BATTLE_TEST("Hail damage rounds properly when maxHP < 16")
|
||||
HP_BAR(player, damage: 1);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Hail doesn't do damage when weather is negated")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_ICE);
|
||||
ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_ICE);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_HAIL); }
|
||||
} SCENE {
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,3 +94,20 @@ SINGLE_BATTLE_TEST("Sandstorm damage rounds properly when maxHP < 16")
|
||||
HP_BAR(player, damage: 1);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sandstorm doesn't do damage when weather is negated")
|
||||
{
|
||||
u32 type1 = gSpeciesInfo[SPECIES_STOUTLAND].types[0];
|
||||
u32 type2 = gSpeciesInfo[SPECIES_STOUTLAND].types[1];
|
||||
GIVEN {
|
||||
ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK);
|
||||
ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND);
|
||||
ASSUME(type1 != TYPE_STEEL && type2 != TYPE_STEEL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SANDSTORM); }
|
||||
} SCENE {
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user