01/01/26 Master to upcoming merge

This commit is contained in:
AlexOn1ine 2026-01-01 10:24:19 +01:00
commit a1948b7c40
85 changed files with 2829 additions and 1451 deletions

View File

@ -32,11 +32,11 @@ jobs:
env:
COMPARE: 0
run: make -j${nproc} -O all
- name: LTO
- name: Release
run: |
make tidy
make -j${nproc} LTO=1
make -j${nproc} release
# make tidy to purge previous build
- name: Test

View File

@ -122,21 +122,20 @@ Once all items on the merge checklist are true, the branch will be merged in.
## Maintainers
This list was last updated 2025 April 1.
This list was last updated 2025 Dec 23.
| Name | Discord | Currently Active | Areas of Expertise |
| --- | --- | --- | --- |
| [Alex](https://github.com/AlexOn1ine) | rainonline | ✅ | Battle Engine, Battle AI
| [Egg](https://github.com/DizzyEggg) | egg9255 | ✅ | Battle Engine, Battle AI
| [ghoulslash](https://github.com/ghoulslash) | ghoulslash | ✅ | Dexnav, Overworld, Battle Engine
| [Jasper](https://github.com/Bassoonian) | bassoonian | ✅ | Berries, Day / Night System, Followers, Feature Branches
| [MGriffin](https://github.com/mrgriffin) | mgriffin | ✅ | Tests, Trainer Control
| [psf](https://github.com/pkmnsnfrn) | pkmnsnfrn | ✅ | Rematches, Difficulty, Trainer Slides, Fake RTC, Fishing Minigames, Imperial / Metric, OW Item Balls, Sky Battles
| [Hedara](https://github.com/hedara90) | hedara | ✅ | Compression, Sprites
| [Pawkkie](https://github.com/Pawkkie) | pawkkie | ✅ | Battle AI
| [SBird](https://github.com/SBird1337) | karathan | ✅ | Dynamic Multichoice, Damage Calculation, Animations, Trainer Control, Tests
| [Agustin](https://github.com/AgustinGDLV) | agustingdlv | Inactive | Gimmicks, Battle Engine, Tests, Items
| [tertu](https://github.com/tertu-m) | tertu | Inactive | Randomizer
| [Jamie](https://github.com/FosterProgramming) | foster_harmony | ✅ | Overworld, Tests, Day / Night System, Dexnav, Battle Frontier, HGSS Dex, Pokerus, Learnsets, Mon Generation, Vs Seeker
| [grintoul](https://github.com/grintoul1) | grintoul | ✅ | Tests, Battle AI, Battle Engine, Overworld, Trainer Slides, Follower NPCs, Multi Battles
## Attribution
This guide is based on the [contributing.md](https://contributing.md/generator)!

View File

@ -140,7 +140,7 @@ git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion
2. Pull your desired branch
There are three different options to pull from.
```console
git pull RHH master # if you've chosen to use the upcoming branch, replace the word master with upcoming.
git pull RHH master # if you've chosen to use the upcoming branch, replace the word master with upcoming.
# If you've chosen the latest patch, replace the word master with expansion
# If you've chosen Latest Patch, replace the word master with expansion/1.11.0 where 1.11.0 is replaced with whatever the latest released version is.
```
@ -173,7 +173,7 @@ For example, if your version is 1.7.0, you should update to 1.7.4.
git pull RHH expansion/X.Y.Z # Replace X, Y and Z with the target version, such as `1.9.3`, `master`, or `upcoming`.
```
You may have merge conflicts that you need to resolve.
You may have merge conflicts that you need to resolve.
If you targeted a specific version that is not the latest version listed on the [tags](https://github.com/rh-hideout/pokeemerald-expansion/tags) page, you should repeat steps 3 and 4 until you are.

View File

@ -2451,3 +2451,8 @@
.byte \gen
.4byte \jumpInstr
.endm
@ Absorbs Toxic Spikes when a grounded Poison-type faints to entry hazards.
.macro tryabsorbtoxicspikesonfaint
callnative BS_TryAbsorbToxicSpikesOnFaint
.endm

View File

@ -1534,10 +1534,10 @@ BattleScript_EffectInstruct::
tryinstruct BattleScript_ButItFailed
attackanimation
waitanimation
copybyte gBattlerAttacker, gBattlerTarget
copybyte gBattlerTarget, gEffectBattler
printstring STRINGID_USEDINSTRUCTEDMOVE
waitmessage B_WAIT_TIME_LONG
copybyte gBattlerAttacker, gBattlerTarget
copybyte gBattlerTarget, gEffectBattler
jumptocalledmove TRUE
BattleScript_EffectAutotomize::

View File

@ -497,10 +497,10 @@ Causes the test to fail if the `SCENE` command succeeds before the following com
```
Causes the test to fail unless one of the `SCENE` commands succeeds.
```
ONE_OF {
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("Wobbuffet couldn't move because it's paralyzed!");
}
ONE_OF {
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("Wobbuffet couldn't move because it's paralyzed!");
}
```
### `NONE_OF`
@ -511,12 +511,12 @@ Causes the test to fail unless one of the `SCENE` commands succeeds.
```
Causes the test to fail if one of the `SCENE` commands succeeds before the command after the `NONE_OF` succeeds.
```
// Our Wobbuffet does not move before the foe's.
NONE_OF {
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("Wobbuffet couldn't move because it's paralyzed!");
}
MESSAGE("The opposing Wobbuffet used Celebrate!");
// Our Wobbuffet does not move before the foe's.
NONE_OF {
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("Wobbuffet couldn't move because it's paralyzed!");
}
MESSAGE("The opposing Wobbuffet used Celebrate!");
```
### `PLAYER_PARTY`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 989 B

After

Width:  |  Height:  |  Size: 998 B

View File

@ -12,7 +12,7 @@ JASC-PAL
101 101 94
144 144 137
172 41 65
0 0 0
255 255 255
0 0 0
0 0 0
0 0 0

View File

@ -12,7 +12,7 @@ JASC-PAL
103 92 90
144 144 137
214 66 61
0 0 0
255 255 255
0 0 0
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -9,11 +9,11 @@ JASC-PAL
146 129 121
47 47 40
147 63 121
104 40 71
88 56 64
200 95 172
229 229 247
0 0 0
0 0 0
0 0 0
0 0 0
84 21 43
131 41 57
222 82 90
161 48 74
0 0 0

View File

@ -1,19 +1,19 @@
JASC-PAL
0100
16
153 210 164
82 32 47
136 40 51
180 68 48
152 208 160
93 41 57
238 98 16
7 7 7
208 192 128
174 151 96
216 201 140
175 152 96
47 47 40
224 80 69
104 40 71
173 74 69
96 88 62
224 107 96
229 229 247
0 0 0
0 0 0
0 0 0
0 0 0
84 21 43
131 41 57
222 82 90
178 81 60
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 949 B

After

Width:  |  Height:  |  Size: 1008 B

View File

@ -5,14 +5,14 @@ JASC-PAL
55 55 55
87 87 87
0 0 0
24 56 64
31 72 64
232 128 56
11 55 112
24 112 104
32 160 136
176 104 32
236 79 47
172 47 25
236 204 110
153 115 64
33 33 33
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 B

After

Width:  |  Height:  |  Size: 727 B

View File

@ -1,11 +1,11 @@
JASC-PAL
0100
16
152 208 160
0 0 0
115 202 202
52 19 21
88 152 48
144 200 8
88 152 48
36 86 26
152 120 8
248 208 64
192 152 64
@ -14,6 +14,6 @@ JASC-PAL
80 80 80
224 128 8
152 120 8
0 0 0
192 185 180
0 0 0
0 0 0

View File

@ -2,18 +2,18 @@ JASC-PAL
0100
16
152 208 160
0 0 0
24 52 31
64 152 104
104 184 144
88 152 48
60 96 48
120 64 72
240 248 168
200 232 48
206 252 139
168 211 48
112 128 16
252 252 252
80 80 80
248 88 64
152 120 8
0 0 0
192 185 180
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

After

Width:  |  Height:  |  Size: 656 B

View File

@ -10,9 +10,9 @@ JASC-PAL
121 40 55
191 79 104
236 112 129
95 47 40
55 47 40
229 229 247
138 87 79
105 96 91
79 47 5
164 104 5
112 71 5

View File

@ -2,18 +2,18 @@ JASC-PAL
0100
16
152 208 160
80 61 60
96 88 62
208 192 128
2 2 2
175 151 96
2 2 2
186 71 45
186 71 45
236 112 129
80 61 60
139 55 62
173 74 69
224 107 96
93 41 57
213 210 213
186 71 45
79 47 5
186 71 45
164 104 5
112 71 5
218 172 87

Binary file not shown.

Before

Width:  |  Height:  |  Size: 698 B

After

Width:  |  Height:  |  Size: 764 B

View File

@ -6,12 +6,12 @@ JASC-PAL
64 56 72
100 85 143
128 104 160
88 152 136
88 163 136
0 0 0
64 64 80
40 40 40
168 128 64
208 176 96
209 128 175
208 176 185
96 80 128
0 0 0
0 0 0

View File

@ -154,7 +154,6 @@ enum MoveCanceler
MOVE_STEP_SUCCESS,
MOVE_STEP_BREAK, // Breaks out of the function to run a script
MOVE_STEP_FAILURE, // Same as break but breaks out of it due to move failure and jumps to script that handles the failure
MOVE_STEP_REMOVES_STATUS,
};
extern const struct TypePower gNaturalGiftTable[];
@ -356,7 +355,7 @@ bool32 IsPartnerMonFromSameTrainer(u32 battler);
enum DamageCategory GetCategoryBasedOnStats(u32 battler);
void SetShellSideArmCategory(void);
bool32 MoveIsAffectedBySheerForce(u32 move);
bool32 TestIfSheerForceAffected(u32 battler, u16 move);
bool32 IsSheerForceAffected(u16 move, enum Ability ability);
void TryRestoreHeldItems(void);
bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item);
void TrySaveExchangedItem(u32 battler, u16 stolenItem);

View File

@ -32,7 +32,7 @@
F(HIDDEN_POWER_DMG, hiddenPowerDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(ROUGH_SKIN_DMG, roughSkinDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(KNOCK_OFF_DMG, knockOffDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(SPORT_DMG_REDUCTION, sportDmgReduction, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(SPORT_DMG_REDUCTION, sportDmgReduction, (u32, GEN_COUNT - 1)) \
F(EXPLOSION_DEFENSE, explosionDefense, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(PARENTAL_BOND_DMG, parentalBondDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(MULTIPLE_TARGETS_DMG, multipleTargetsDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
@ -47,11 +47,11 @@
F(ROOST_PURE_FLYING, roostPureFlying, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(STATUS_TYPE_IMMUNITY, statusTypeImmunity, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
/* Turn settings */ \
F(BINDING_TURNS, bindingTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(BINDING_TURNS, bindingTurns, (u32, GEN_COUNT - 1)) \
F(UPROAR_TURNS, uproarTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(UPROAR_IGNORE_SOUNDPROOF, uproarIgnoreSoundproof, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(DISABLE_TURNS, disableTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(TAILWIND_TURNS, tailwindTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(TAILWIND_TURNS, tailwindTurns, (u32, GEN_COUNT - 1)) \
F(SLEEP_TURNS, sleepTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(TAUNT_TURNS, tauntTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(SPORT_TURNS, sportTurns, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
@ -66,7 +66,7 @@
F(RECOIL_IF_MISS_DMG, recoilIfMissDmg, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(KLUTZ_FLING_INTERACTION, klutzFlingInteraction, (u32, GEN_COUNT - 1)) \
F(UPDATED_CONVERSION, updatedConversion, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(UPDATED_CONVERSION_2, updatedConversion2, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(UPDATED_CONVERSION_2, updatedConversion2, (u32, GEN_COUNT - 1)) \
F(PP_REDUCED_BY_SPITE, ppReducedBySpite, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
F(EXTRAPOLATED_MOVE_FLAGS, extrapolatedMoveFlags, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
/* Ability data settings */ \

View File

@ -772,7 +772,7 @@ struct BattleTestData
u8 gender;
u8 nature;
bool8 isShiny;
enum Ability forcedAbilities[NUM_BATTLE_SIDES][PARTY_SIZE];
enum Ability forcedAbilities[MAX_BATTLERS_COUNT][PARTY_SIZE];
u8 chosenGimmick[MAX_BATTLERS_COUNT][PARTY_SIZE];
u8 forcedEnvironment;

View File

@ -30,7 +30,7 @@ void TestRunner_CheckMemory(void);
void TestRunner_Battle_CheckBattleRecordActionType(u32 battlerId, u32 recordIndex, u32 actionType);
u32 TestRunner_Battle_GetForcedAbility(u32 side, u32 partyIndex);
u32 TestRunner_Battle_GetForcedAbility(u32 array, u32 partyIndex);
u32 TestRunner_Battle_GetChosenGimmick(u32 battler, u32 partyIndex);
u32 TestRunner_Battle_GetForcedEnvironment(void);

View File

@ -5687,7 +5687,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
ADJUST_SCORE(GOOD_EFFECT);
break;
case EFFECT_MAGNET_RISE:
if (AI_IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC)
if (AI_IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_GROUND)
&& !(effectiveness == UQ_4_12(0.0))) // Doesn't resist ground move
{
if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker goes first
@ -5698,8 +5698,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
}
else // Opponent Goes First
{
if (HasDamagingMoveOfType(battlerDef, TYPE_GROUND))
ADJUST_SCORE(DECENT_EFFECT);
ADJUST_SCORE(DECENT_EFFECT);
break;
}
}
@ -5877,17 +5876,14 @@ static s32 AI_CalcAdditionalEffectScore(u32 battlerAtk, u32 battlerDef, u32 move
// Set battlerDef best dmg moves
GetBestDmgMovesFromBattler(battlerDef, battlerAtk, AI_DEFENDING, defBestMoves);
if (IsSheerForceAffected(move, aiData->abilities[battlerAtk]))
return score;
// check move additional effects that are likely to happen
for (u32 effectId = 0; effectId < additionalEffectCount; effectId++)
{
const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, effectId);
if (aiData->abilities[battlerAtk] == ABILITY_SHEER_FORCE)
{
if ((additionalEffect->chance > 0) != additionalEffect->sheerForceOverride)
continue;
}
// Only consider effects with a guaranteed chance to happen
if (!MoveEffectIsGuaranteed(battlerAtk, aiData->abilities[battlerAtk], additionalEffect))
continue;

View File

@ -1173,14 +1173,8 @@ bool32 ShouldSwitchDynFuncExample(u32 battler)
return FALSE;
}
bool32 ShouldSwitch(u32 battler)
static bool32 CanBattlerConsiderSwitch(u32 battler)
{
u32 battlerIn1, battlerIn2;
s32 firstId;
s32 lastId; // + 1
struct Pokemon *party;
s32 availableToSwitch;
if (gBattleMons[battler].volatiles.wrapped)
return FALSE;
if (gBattleMons[battler].volatiles.escapePrevention)
@ -1189,8 +1183,23 @@ bool32 ShouldSwitch(u32 battler)
return FALSE;
if (IsAbilityPreventingEscape(battler))
return FALSE;
if (gBattleStruct->battlerState[battler].commanderSpecies)
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
return FALSE;
return TRUE;
}
bool32 ShouldSwitch(u32 battler)
{
u32 battlerIn1, battlerIn2;
s32 firstId;
s32 lastId; // + 1
struct Pokemon *party;
s32 availableToSwitch;
if (!CanBattlerConsiderSwitch(battler))
return FALSE;
// Sequence Switching AI never switches mid-battle
if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING)
@ -1324,15 +1333,7 @@ void ModifySwitchAfterMoveScoring(u32 battler)
struct Pokemon *party;
s32 availableToSwitch;
if (gBattleMons[battler].volatiles.wrapped)
return;
if (gBattleMons[battler].volatiles.escapePrevention)
return;
if (gBattleMons[battler].volatiles.root)
return;
if (IsAbilityPreventingEscape(battler))
return;
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
if (!CanBattlerConsiderSwitch(battler))
return;
// Sequence Switching AI never switches mid-battle

View File

@ -896,6 +896,10 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
struct AiLogicData *aiData = gAiLogicData;
gAiLogicData->aiCalcInProgress = TRUE;
if (moveEffect == EFFECT_HIT_ENEMY_HEAL_ALLY
&& battlerDef == BATTLE_PARTNER(battlerAtk))
return simDamage;
if (moveEffect == EFFECT_NATURE_POWER)
move = GetNaturePowerMove(battlerAtk);
@ -1027,6 +1031,9 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3
u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData);
bool32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY);
if (IsSheerForceAffected(move, abilityAtk))
return FALSE;
switch (GetMoveEffect(move))
{
case EFFECT_ABSORB:

View File

@ -45,6 +45,7 @@ static void RecordedPartnerHandleIntroTrainerBallThrow(u32 battler);
static void RecordedPartnerHandleDrawPartyStatusSummary(u32 battler);
static void RecordedPartnerHandleEndLinkBattle(u32 battler);
static void RecordedPartnerBufferRunCommand(u32 battler);
static void RecordedPartnerHandleStatusIconUpdate(u32 battler);
static void (*const sRecordedPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) =
{
@ -73,7 +74,7 @@ static void (*const sRecordedPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 b
[CONTROLLER_23] = BtlController_Empty,
[CONTROLLER_HEALTHBARUPDATE] = BtlController_HandleHealthBarUpdate,
[CONTROLLER_EXPUPDATE] = PlayerHandleExpUpdate, // Partner's player gets experience the same way as the player.
[CONTROLLER_STATUSICONUPDATE] = BtlController_HandleStatusIconUpdate,
[CONTROLLER_STATUSICONUPDATE] = RecordedPartnerHandleStatusIconUpdate,
[CONTROLLER_STATUSANIMATION] = BtlController_HandleStatusAnimation,
[CONTROLLER_STATUSXOR] = BtlController_Empty,
[CONTROLLER_DATATRANSFER] = BtlController_Empty,
@ -288,3 +289,13 @@ static void RecordedPartnerHandleEndLinkBattle(u32 battler)
BtlController_Complete(battler);
gBattlerControllerFuncs[battler] = SetBattleEndCallbacks;
}
static void RecordedPartnerHandleStatusIconUpdate(u32 battler)
{
if (!IsBattleSEPlaying(battler))
{
DoStatusIconUpdate(battler);
if (gTestRunnerEnabled)
TestRunner_Battle_RecordStatus1(battler, GetMonData(GetBattlerMon(battler), MON_DATA_STATUS));
}
}

View File

@ -1486,10 +1486,10 @@ static u32 GetBattlerMonData(u32 battler, struct Pokemon *party, u32 monId, u8 *
#if TESTING
if (gTestRunnerEnabled)
{
u32 side = GetBattlerSide(battler);
u32 array = (!IsPartnerMonFromSameTrainer(battler)) ? battler : GetBattlerSide(battler);
u32 partyIndex = gBattlerPartyIndexes[battler];
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
if (TestRunner_Battle_GetForcedAbility(array, partyIndex))
gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(array, partyIndex);
}
#endif
break;

View File

@ -955,8 +955,8 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, u8 changeType)
if (changeType == SPECIES_GFX_CHANGE_TRANSFORM)
{
personalityValue = gBattleMons[battlerAtk].volatiles.transformedMonPID;
isShiny = gBattleMons[battlerAtk].volatiles.isTransformedMonShiny;
personalityValue = gTransformedPersonalities[battlerAtk];
isShiny = gTransformedShininess[battlerAtk];
}
else
{

View File

@ -3254,10 +3254,10 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
#if TESTING
if (gTestRunnerEnabled)
{
u32 side = GetBattlerSide(battler);
u32 array = (!IsPartnerMonFromSameTrainer(battler)) ? battler : GetBattlerSide(battler);
u32 partyIndex = gBattlerPartyIndexes[battler];
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
if (TestRunner_Battle_GetForcedAbility(array, partyIndex))
gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(array, partyIndex);
}
#endif // TESTING
@ -3460,10 +3460,10 @@ static void DoBattleIntro(void)
#if TESTING
if (gTestRunnerEnabled)
{
u32 side = GetBattlerSide(battler);
u32 array = (!IsPartnerMonFromSameTrainer(battler)) ? battler : GetBattlerSide(battler);
u32 partyIndex = gBattlerPartyIndexes[battler];
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
if (TestRunner_Battle_GetForcedAbility(array, partyIndex))
gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(array, partyIndex);
}
#endif
}
@ -3755,10 +3755,10 @@ static void TryDoEventsBeforeFirstTurn(void)
{
for (i = 0; i < gBattlersCount; ++i)
{
u32 side = GetBattlerSide(i);
u32 array = (!IsPartnerMonFromSameTrainer(i)) ? i : GetBattlerSide(i);
u32 partyIndex = gBattlerPartyIndexes[i];
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
if (TestRunner_Battle_GetForcedAbility(array, partyIndex))
gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(array, partyIndex);
}
}
#endif // TESTING

View File

@ -679,7 +679,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
[STRINGID_SWEETVEILPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} can't fall asleep due to a veil of sweetness!"),
[STRINGID_AROMAVEILPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is protected by an aromatic veil!"),
[STRINGID_CELEBRATEMESSAGE] = COMPOUND_STRING("Congratulations, {B_PLAYER_NAME}!"),
[STRINGID_USEDINSTRUCTEDMOVE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} followed {B_SCR_NAME_WITH_PREFIX2}'s instructions!"),
[STRINGID_USEDINSTRUCTEDMOVE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} followed {B_ATK_NAME_WITH_PREFIX2}'s instructions!"),
[STRINGID_THROATCHOPENDS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} can use sound-based moves again!"),
[STRINGID_PKMNCANTUSEMOVETHROATCHOP] = COMPOUND_STRING("The effects of Throat Chop prevent {B_ATK_NAME_WITH_PREFIX2} from using certain moves!\p"),
[STRINGID_LASERFOCUS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} concentrated intensely!"),

View File

@ -67,7 +67,7 @@ static enum MoveEndResult MoveEnd_ProtectLikeEffect(void)
result = MOVEEND_STEP_RUN_SCRIPT;
break;
case PROTECT_BANEFUL_BUNKER:
if (CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker)))
if (CanBePoisoned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerTarget), GetBattlerAbility(gBattlerAttacker)))
{
gBattleScripting.moveEffect = MOVE_EFFECT_POISON;
BattleScriptCall(BattleScript_BanefulBunkerEffect);
@ -446,7 +446,8 @@ static enum MoveEndResult MoveEnd_FaintBlock(void)
&& IsBattlerAlive(gBattlerAttacker)
&& !IsBattlerAlly(gBattlerAttacker, gBattlerTarget)
&& !IsZMove(gCurrentMove)
&& gCurrentMove != MOVE_STRUGGLE)
&& gCurrentMove != MOVE_STRUGGLE
&& GetMoveEffect(gCurrentMove) != EFFECT_FUTURE_SIGHT)
{
gBattleStruct->tryGrudge = TRUE;
}
@ -570,7 +571,7 @@ static enum MoveEndResult MoveEnd_UpdateLastMoves(void)
&& gBattlerTarget != gBattlerAttacker
&& !IsBattlerAlly(gBattlerTarget, gBattlerAttacker)
&& gProtectStructs[gBattlerTarget].physicalBattlerId == gBattlerAttacker
&& !TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove))
&& !IsSheerForceAffected(gCurrentMove, GetBattlerAbility(gBattlerAttacker)))
{
gProtectStructs[gBattlerTarget].shellTrap = TRUE;
// Change move order in double battles, so the hit mon with shell trap moves immediately after being hit.
@ -1098,7 +1099,7 @@ static enum MoveEndResult MoveEnd_AbilityEffectFoesFainted(void)
static enum MoveEndResult MoveEnd_SheerForce(void)
{
if (TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove))
if (IsSheerForceAffected(gCurrentMove, GetBattlerAbility(gBattlerAttacker)))
gBattleScripting.moveendState = MOVEEND_EJECT_PACK;
else
gBattleScripting.moveendState++;
@ -1272,7 +1273,6 @@ static enum MoveEndResult MoveEnd_LifeOrbShellBell(void)
if (ItemBattleEffects(gBattlerAttacker, 0, GetBattlerHoldEffect(gBattlerAttacker), IsLifeOrbShellBellActivation))
result = MOVEEND_STEP_RUN_SCRIPT;
// DebugPrintf("[11]");
gBattleScripting.moveendState++;
return result;
}

View File

@ -2744,6 +2744,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
case MOVE_EFFECT_STEALTH_ROCK:
case MOVE_EFFECT_PAYDAY:
case MOVE_EFFECT_BUG_BITE:
case MOVE_EFFECT_FLAME_BURST:
activateAfterFaint = TRUE;
break;
default:
@ -2757,7 +2758,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
if (!primary && !affectsUser && IsMoveEffectBlockedByTarget(battlerAbility))
moveEffect = MOVE_EFFECT_NONE;
else if (!primary
&& TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)
&& IsSheerForceAffected(gCurrentMove, GetBattlerAbility(battler))
&& !(moveEffect == MOVE_EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE))
moveEffect = MOVE_EFFECT_NONE;
else if (!IsBattlerAlive(gEffectBattler) && !activateAfterFaint)
@ -5376,10 +5377,10 @@ static void Cmd_switchindataupdate(void)
#if TESTING
if (gTestRunnerEnabled)
{
u32 side = GetBattlerSide(battler);
u32 array = (!IsPartnerMonFromSameTrainer(battler)) ? battler : GetBattlerSide(battler);
u32 partyIndex = gBattlerPartyIndexes[battler];
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex);
if (TestRunner_Battle_GetForcedAbility(array, partyIndex))
gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(array, partyIndex);
}
#endif
@ -9028,10 +9029,10 @@ static void Cmd_mimicattackcopy(void)
{
CMD_ARGS(const u8 *failInstr);
if ((IsMoveMimicBanned(gLastMoves[gBattlerTarget]))
|| (gBattleMons[gBattlerAttacker].volatiles.transformed)
|| gLastMoves[gBattlerTarget] == MOVE_NONE
|| gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE)
if (gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE
|| gLastMoves[gBattlerTarget] == MOVE_NONE
|| gBattleMons[gBattlerAttacker].volatiles.transformed
|| IsMoveMimicBanned(gLastMoves[gBattlerTarget]))
{
gBattlescriptCurrInstr = cmd->failInstr;
}
@ -9200,120 +9201,75 @@ static void Cmd_settypetorandomresistance(void)
// Before Gen 5 Conversion 2 only worked on a move the attacker was actually hit by.
// This changed later to the last move used by the selected target.
if (B_UPDATED_CONVERSION_2 < GEN_5)
u32 moveToCheck;
u32 typeToCheck;
if (GetConfig(CONFIG_UPDATED_CONVERSION_2) < GEN_5)
{
if (gLastLandedMoves[gBattlerAttacker] == MOVE_NONE
|| gLastLandedMoves[gBattlerAttacker] == MOVE_UNAVAILABLE)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (gBattleMoveEffects[GetMoveEffect(gLastLandedMoves[gBattlerAttacker])].twoTurnEffect
&& gBattleMons[gLastHitBy[gBattlerAttacker]].volatiles.multipleTurns)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR || gLastHitByType[gBattlerAttacker] == TYPE_MYSTERY)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
moveToCheck = gLastLandedMoves[gBattlerAttacker];
if (GetMoveEffect(moveToCheck) == EFFECT_STRUGGLE)
typeToCheck = TYPE_NORMAL;
else
{
u32 i, resistTypes = 0;
u32 hitByType = gLastHitByType[gBattlerAttacker];
for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist.
{
switch (GetTypeModifier(hitByType, i))
{
case UQ_4_12(0):
case UQ_4_12(0.5):
resistTypes |= 1u << i;
break;
}
}
while (resistTypes != 0)
{
i = Random() % NUMBER_OF_MON_TYPES;
if (resistTypes & 1u << i)
{
if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i))
{
resistTypes &= ~(1u << i); // Type resists, but the user is already of this type.
}
else
{
SET_BATTLER_TYPE(gBattlerAttacker, i);
PREPARE_TYPE_BUFFER(gBattleTextBuff1, i);
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
}
}
gBattlescriptCurrInstr = cmd->failInstr;
}
typeToCheck = gLastHitByType[gBattlerAttacker];
}
else
{
if (gLastResultingMoves[gBattlerTarget] == MOVE_NONE
|| gLastResultingMoves[gBattlerTarget] == MOVE_UNAVAILABLE
|| gLastResultingMoves[gBattlerTarget] == MOVE_STRUGGLE)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (!BreaksThroughSemiInvulnerablity(gBattlerTarget, gCurrentMove))
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (gLastUsedMoveType[gBattlerTarget] == TYPE_NONE || gLastUsedMoveType[gBattlerTarget] == TYPE_STELLAR || gLastUsedMoveType[gBattlerTarget] == TYPE_MYSTERY)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else
{
u32 i, resistTypes = 0;
moveToCheck = gLastResultingMoves[gBattlerTarget];
typeToCheck = gLastUsedMoveType[gBattlerTarget];
}
for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist.
if (moveToCheck == MOVE_NONE
|| moveToCheck == MOVE_UNAVAILABLE)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (!BreaksThroughSemiInvulnerablity(gBattlerTarget, moveToCheck))
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else if (typeToCheck == TYPE_NONE || typeToCheck == TYPE_STELLAR || typeToCheck == TYPE_MYSTERY)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else
{
u32 i, resistTypes = 0;
for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist.
{
switch (GetTypeModifier(typeToCheck, i))
{
switch (GetTypeModifier(gLastUsedMoveType[gBattlerTarget], i))
case UQ_4_12(0):
case UQ_4_12(0.5):
resistTypes |= 1u << i;
break;
}
}
while (resistTypes != 0)
{
i = Random() % NUMBER_OF_MON_TYPES;
if (resistTypes & 1u << i)
{
if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i))
{
case UQ_4_12(0):
case UQ_4_12(0.5):
resistTypes |= 1u << i;
break;
resistTypes &= ~(1u << i); // Type resists, but the user is already of this type.
}
else
{
SET_BATTLER_TYPE(gBattlerAttacker, i);
PREPARE_TYPE_BUFFER(gBattleTextBuff1, i);
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
}
while (resistTypes != 0)
{
i = Random() % NUMBER_OF_MON_TYPES;
if (resistTypes & 1u << i)
{
if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i))
{
resistTypes &= ~(1u << i); // Type resists, but the user is already of this type.
}
else
{
SET_BATTLER_TYPE(gBattlerAttacker, i);
PREPARE_TYPE_BUFFER(gBattleTextBuff1, i);
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
}
}
gBattlescriptCurrInstr = cmd->failInstr;
}
gBattlescriptCurrInstr = cmd->failInstr;
}
}
@ -9413,7 +9369,7 @@ static void Cmd_settailwind(void)
if (!(gSideStatuses[side] & SIDE_STATUS_TAILWIND))
{
gSideStatuses[side] |= SIDE_STATUS_TAILWIND;
gSideTimers[side].tailwindTimer = (B_TAILWIND_TURNS >= GEN_5 ? 4 : 3);
gSideTimers[side].tailwindTimer = (GetConfig(CONFIG_TAILWIND_TURNS) >= GEN_5 ? 4 : 3);
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
@ -9565,9 +9521,9 @@ static void Cmd_healpartystatus(void)
#if TESTING
if (gTestRunnerEnabled)
{
u32 side = GetBattlerSide(gBattlerAttacker);
if (TestRunner_Battle_GetForcedAbility(side, i))
ability = TestRunner_Battle_GetForcedAbility(side, i);
u32 array = (!IsPartnerMonFromSameTrainer(gBattlerAttacker)) ? gBattlerAttacker : GetBattlerSide(gBattlerAttacker);
if (TestRunner_Battle_GetForcedAbility(array, i))
ability = TestRunner_Battle_GetForcedAbility(array, i);
}
#endif
}
@ -10375,7 +10331,7 @@ static void Cmd_tryswapitems(void)
if (GetBattlerAbility(gBattlerTarget) != ABILITY_GORILLA_TACTICS)
gBattleStruct->choicedMove[gBattlerTarget] = MOVE_NONE;
if (GetBattlerAbility(gBattlerTarget) != ABILITY_GORILLA_TACTICS)
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_GORILLA_TACTICS)
gBattleStruct->choicedMove[gBattlerAttacker] = MOVE_NONE;
gBattlescriptCurrInstr = cmd->nextInstr;
@ -10909,47 +10865,50 @@ static void Cmd_settypebasedhalvers(void)
bool8 worked = FALSE;
if (GetMoveEffect(gCurrentMove) == EFFECT_MUD_SPORT)
if (!gBattleStruct->isSkyBattle)
{
if (B_SPORT_TURNS >= GEN_6)
if (GetMoveEffect(gCurrentMove) == EFFECT_MUD_SPORT)
{
if (!(gFieldStatuses & STATUS_FIELD_MUDSPORT))
if (B_SPORT_TURNS >= GEN_6)
{
gFieldStatuses |= STATUS_FIELD_MUDSPORT;
gFieldTimers.mudSportTimer = 5;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC;
worked = TRUE;
if (!(gFieldStatuses & STATUS_FIELD_MUDSPORT))
{
gFieldStatuses |= STATUS_FIELD_MUDSPORT;
gFieldTimers.mudSportTimer = 5;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC;
worked = TRUE;
}
}
else
{
if (!gBattleMons[gBattlerAttacker].volatiles.mudSport)
{
gBattleMons[gBattlerAttacker].volatiles.mudSport = TRUE;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC;
worked = TRUE;
}
}
}
else
else // Water Sport
{
if (!gBattleMons[gBattlerAttacker].volatiles.waterSport)
if (B_SPORT_TURNS >= GEN_6)
{
gBattleMons[gBattlerAttacker].volatiles.waterSport = TRUE;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC;
worked = TRUE;
if (!(gFieldStatuses & STATUS_FIELD_WATERSPORT))
{
gFieldStatuses |= STATUS_FIELD_WATERSPORT;
gFieldTimers.waterSportTimer = 5;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE;
worked = TRUE;
}
}
}
}
else // Water Sport
{
if (B_SPORT_TURNS >= GEN_6)
{
if (!(gFieldStatuses & STATUS_FIELD_WATERSPORT))
else
{
gFieldStatuses |= STATUS_FIELD_WATERSPORT;
gFieldTimers.waterSportTimer = 5;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE;
worked = TRUE;
}
}
else
{
if (!gBattleMons[gBattlerAttacker].volatiles.mudSport)
{
gBattleMons[gBattlerAttacker].volatiles.mudSport = TRUE;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE;
worked = TRUE;
if (!gBattleMons[gBattlerAttacker].volatiles.waterSport)
{
gBattleMons[gBattlerAttacker].volatiles.waterSport = TRUE;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE;
worked = TRUE;
}
}
}
}
@ -14196,7 +14155,27 @@ void BS_GetStatValue(void)
{
NATIVE_ARGS(u8 stat);
u32 stat = cmd->stat;
gBattleStruct->passiveHpUpdate[gBattlerAttacker] = *(u16 *)(&gBattleMons[gBattlerTarget].attack) + (stat - 1);
switch (stat)
{
case STAT_ATK:
gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerTarget].attack;
break;
case STAT_DEF:
gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerTarget].defense;
break;
case STAT_SPATK:
gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerTarget].spAttack;
break;
case STAT_SPDEF:
gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerTarget].spDefense;
break;
case STAT_SPEED:
gBattleStruct->passiveHpUpdate[gBattlerAttacker] = gBattleMons[gBattlerTarget].speed;
break;
default:
// Add errorf here on upcoming
return;
}
gBattleStruct->passiveHpUpdate[gBattlerAttacker] *= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][0];
gBattleStruct->passiveHpUpdate[gBattlerAttacker] /= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][1];
gBattlescriptCurrInstr = cmd->nextInstr;
@ -15626,3 +15605,29 @@ void BS_JumpIfGenConfigLowerThan(void)
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
// Used when the Pokemon faints before Toxic Spikes would normally be processed in the hazards queue.
void BS_TryAbsorbToxicSpikesOnFaint(void)
{
NATIVE_ARGS();
u32 battler = gBattlerFainted;
u32 side = GetBattlerSide(battler);
if (gSideTimers[side].toxicSpikesAmount == 0)
{
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
if (IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))
&& IS_BATTLER_OF_TYPE(battler, TYPE_POISON))
{
gSideTimers[side].toxicSpikesAmount = 0;
RemoveHazardFromField(side, HAZARDS_TOXIC_SPIKES);
gEffectBattler = battler;
BattleScriptCall(BattleScript_ToxicSpikesAbsorbed);
return;
}
gBattlescriptCurrInstr = cmd->nextInstr;
}

View File

@ -2023,6 +2023,18 @@ static inline bool32 TryActivatePowderStatus(u32 move)
return FALSE;
}
static void RequestNonVolatileChangee(u32 battlerAtk)
{
BtlController_EmitSetMonData(
battlerAtk,
B_COMM_TO_CONTROLLER,
REQUEST_STATUS_BATTLE,
0,
4,
&gBattleMons[battlerAtk].status1);
MarkBattlerForControllerExec(battlerAtk);
}
static enum MoveCanceler CancelerClearFlags(struct BattleContext *ctx)
{
gBattleMons[ctx->battlerAtk].volatiles.grudge = FALSE;
@ -2061,6 +2073,8 @@ static enum MoveCanceler CancelerRecharge(struct BattleContext *ctx)
static enum MoveCanceler CancelerAsleepOrFrozen(struct BattleContext *ctx)
{
enum MoveCanceler effect = MOVE_STEP_BREAK;
if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP)
{
if (UproarWakeUpCheck(ctx->battlerAtk))
@ -2070,16 +2084,17 @@ static enum MoveCanceler CancelerAsleepOrFrozen(struct BattleContext *ctx)
gBattleMons[ctx->battlerAtk].volatiles.nightmare = FALSE;
gEffectBattler = ctx->battlerAtk;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR;
effect = MOVE_STEP_BREAK;
BattleScriptCall(BattleScript_MoveUsedWokeUp);
return MOVE_STEP_REMOVES_STATUS;
}
else
{
u8 toSub;
u32 toSub;
if (IsAbilityAndRecord(ctx->battlerAtk, ctx->abilityAtk, ABILITY_EARLY_BIRD))
toSub = 2;
else
toSub = 1;
if ((gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) < toSub)
gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_SLEEP;
else
@ -2090,8 +2105,12 @@ static enum MoveCanceler CancelerAsleepOrFrozen(struct BattleContext *ctx)
{
if (!IsUsableWhileAsleepEffect(moveEffect))
{
effect = MOVE_STEP_FAILURE;
gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep;
return MOVE_STEP_FAILURE;
}
else
{
effect = MOVE_STEP_BREAK;
}
}
else
@ -2099,27 +2118,30 @@ static enum MoveCanceler CancelerAsleepOrFrozen(struct BattleContext *ctx)
TryDeactivateSleepClause(GetBattlerSide(ctx->battlerAtk), gBattlerPartyIndexes[ctx->battlerAtk]);
gBattleMons[ctx->battlerAtk].volatiles.nightmare = FALSE;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP;
effect = MOVE_STEP_BREAK;
BattleScriptCall(BattleScript_MoveUsedWokeUp);
return MOVE_STEP_REMOVES_STATUS;
}
}
RequestNonVolatileChangee(ctx->battlerAtk);
}
else if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FREEZE && !MoveThawsUser(ctx->move))
{
if (!RandomPercentage(RNG_FROZEN, 20))
{
effect = MOVE_STEP_FAILURE;
gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen;
return MOVE_STEP_FAILURE;
}
else // unfreeze
{
gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FREEZE;
effect = MOVE_STEP_BREAK;
BattleScriptCall(BattleScript_MoveUsedUnfroze);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED;
return MOVE_STEP_REMOVES_STATUS;
}
RequestNonVolatileChangee(ctx->battlerAtk);
}
return MOVE_STEP_SUCCESS;
return effect;
}
static enum MoveCanceler CancelerObedience(struct BattleContext *ctx)
@ -2521,27 +2543,39 @@ static enum MoveCanceler CancelerCallSubmove(struct BattleContext *ctx)
static enum MoveCanceler CancelerThaw(struct BattleContext *ctx)
{
enum MoveCanceler effect = MOVE_STEP_BREAK;
if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FREEZE)
{
if (!(IsMoveEffectRemoveSpeciesType(ctx->move, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE)))
{
gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FREEZE;
effect = MOVE_STEP_BREAK;
BattleScriptCall(BattleScript_MoveUsedUnfroze);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED_BY_MOVE;
}
return MOVE_STEP_REMOVES_STATUS;
else
{
effect = MOVE_STEP_FAILURE;
}
RequestNonVolatileChangee(ctx->battlerAtk);
}
if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FROSTBITE && MoveThawsUser(ctx->move))
else if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FROSTBITE && MoveThawsUser(ctx->move))
{
if (!(IsMoveEffectRemoveSpeciesType(ctx->move, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE)))
{
gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FROSTBITE;
effect = MOVE_STEP_BREAK;
BattleScriptCall(BattleScript_MoveUsedUnfrostbite);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FROSTBITE_HEALED_BY_MOVE;
}
return MOVE_STEP_REMOVES_STATUS;
else
{
effect = MOVE_STEP_FAILURE;
}
RequestNonVolatileChangee(ctx->battlerAtk);
}
return MOVE_STEP_SUCCESS;
return effect;
}
static enum MoveCanceler CancelerStanceChangeTwo(struct BattleContext *ctx)
@ -3101,18 +3135,6 @@ enum MoveCanceler AtkCanceler_MoveSuccessOrder(struct BattleContext *ctx)
gBattleStruct->eventState.atkCanceler++;
}
if (effect == MOVE_STEP_REMOVES_STATUS)
{
BtlController_EmitSetMonData(
ctx->battlerAtk,
B_COMM_TO_CONTROLLER,
REQUEST_STATUS_BATTLE,
0,
4,
&gBattleMons[gBattlerAttacker].status1);
MarkBattlerForControllerExec(ctx->battlerAtk);
}
return effect;
}
@ -4984,7 +5006,8 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
}
break;
case ABILITY_BALL_FETCH:
if (gBattleMons[battler].item == ITEM_NONE
if (!(gBattleTypeFlags & BATTLE_TYPE_RAID)
&& gBattleMons[battler].item == ITEM_NONE
&& gBattleResults.catchAttempts[ItemIdToBallId(gLastUsedBall)] >= 1
&& !gHasFetchedBall)
{
@ -6309,6 +6332,7 @@ bool32 IsBattlerTerrainAffected(u32 battler, enum Ability ability, enum HoldEffe
u32 GetHighestStatId(u32 battler)
{
u32 highestId = STAT_ATK;
bool32 wonderRoom = (gFieldStatuses & STATUS_FIELD_WONDER_ROOM) != 0;
u32 highestStat = gBattleMons[battler].attack;
for (u32 stat = STAT_DEF; stat < NUM_STATS; stat++)
@ -6316,10 +6340,28 @@ u32 GetHighestStatId(u32 battler)
if (stat == STAT_SPEED)
continue;
u16 *statVal = &gBattleMons[battler].attack + (stat - 1);
if (*statVal > highestStat)
u32 statVal;
switch (stat)
{
highestStat = *statVal;
case STAT_ATK:
statVal = gBattleMons[battler].attack;
break;
case STAT_DEF:
statVal = wonderRoom ? gBattleMons[battler].spDefense : gBattleMons[battler].defense;
break;
case STAT_SPATK:
statVal = gBattleMons[battler].spAttack;
break;
case STAT_SPDEF:
statVal = wonderRoom ? gBattleMons[battler].defense : gBattleMons[battler].spDefense;
break;
default:
continue;
}
if (statVal > highestStat)
{
highestStat = statVal;
highestId = stat;
}
}
@ -7408,7 +7450,10 @@ static inline u32 CalcTerrainBoostedPower(struct BattleContext *ctx, u32 basePow
static inline u32 IsFieldMudSportAffected(enum Type moveType)
{
if (moveType == TYPE_ELECTRIC && (gFieldStatuses & STATUS_FIELD_MUDSPORT))
if (moveType != TYPE_ELECTRIC)
return FALSE;
if (gFieldStatuses & STATUS_FIELD_MUDSPORT)
return TRUE;
if (B_SPORT_TURNS < GEN_6)
@ -7425,7 +7470,10 @@ static inline u32 IsFieldMudSportAffected(enum Type moveType)
static inline u32 IsFieldWaterSportAffected(enum Type moveType)
{
if (moveType == TYPE_FIRE && (gFieldStatuses & STATUS_FIELD_WATERSPORT))
if (moveType != TYPE_FIRE)
return FALSE;
if (gFieldStatuses & STATUS_FIELD_WATERSPORT)
return TRUE;
if (B_SPORT_TURNS < GEN_6)
@ -7764,9 +7812,9 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct BattleContext *ctx)
if (IsPsychicTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, ctx->fieldStatuses) && moveType == TYPE_PSYCHIC)
modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5)));
if (IsFieldMudSportAffected(ctx->moveType))
modifier = uq4_12_multiply(modifier, UQ_4_12(B_SPORT_DMG_REDUCTION >= GEN_5 ? 0.33 : 0.5));
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_SPORT_DMG_REDUCTION) >= GEN_5 ? 0.33 : 0.5));
if (IsFieldWaterSportAffected(ctx->moveType))
modifier = uq4_12_multiply(modifier, UQ_4_12(B_SPORT_DMG_REDUCTION >= GEN_5 ? 0.33 : 0.5));
modifier = uq4_12_multiply(modifier, UQ_4_12(GetConfig(CONFIG_SPORT_DMG_REDUCTION) >= GEN_5 ? 0.33 : 0.5));
// attacker's abilities
switch (ctx->abilityAtk)
@ -8238,7 +8286,8 @@ static inline u32 CalcAttackStat(struct BattleContext *ctx)
}
break;
case ABILITY_ORICHALCUM_PULSE:
if (ctx->weather & B_WEATHER_SUN && IsBattleMovePhysical(move))
if (ctx->weather & B_WEATHER_SUN && IsBattleMovePhysical(move)
&& ctx->holdEffectAtk != HOLD_EFFECT_UTILITY_UMBRELLA)
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3333));
break;
case ABILITY_HADRON_ENGINE:
@ -10511,9 +10560,9 @@ bool32 IsBattlerAffectedByHazards(u32 battler, enum HoldEffect holdEffect, bool3
return ret;
}
bool32 TestIfSheerForceAffected(u32 battler, u16 move)
bool32 IsSheerForceAffected(u16 move, enum Ability ability)
{
return GetBattlerAbility(battler) == ABILITY_SHEER_FORCE && MoveIsAffectedBySheerForce(move);
return ability == ABILITY_SHEER_FORCE && MoveIsAffectedBySheerForce(move);
}
// This function is the body of "jumpifstat", but can be used dynamically in a function
@ -12055,9 +12104,9 @@ void SetWrapTurns(u32 battler, enum HoldEffect holdEffect)
{
u32 normalWrapTurns = B_WRAP_TURNS - 2; // 5 turns
if (holdEffect == HOLD_EFFECT_GRIP_CLAW)
gBattleMons[battler].volatiles.wrapTurns = B_BINDING_TURNS >= GEN_5 ? B_WRAP_TURNS : normalWrapTurns;
gBattleMons[battler].volatiles.wrapTurns = GetConfig(CONFIG_BINDING_TURNS) >= GEN_5 ? B_WRAP_TURNS : normalWrapTurns;
else
gBattleMons[battler].volatiles.wrapTurns = B_BINDING_TURNS >= GEN_5 ? RandomUniform(RNG_WRAP, 4, normalWrapTurns) : RandomUniform(RNG_WRAP, 2, normalWrapTurns);
gBattleMons[battler].volatiles.wrapTurns = GetConfig(CONFIG_BINDING_TURNS) >= GEN_5 ? RandomUniform(RNG_WRAP, 4, normalWrapTurns) : RandomUniform(RNG_WRAP, 2, normalWrapTurns);
}
// Return True if the order was changed, and false if the order was not changed(for example because the target would move after the attacker anyway).
@ -12110,11 +12159,12 @@ void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMov
u32 i, j;
if (IsOnPlayerSide(gBattlerAttacker)
&& !(gBattleTypeFlags & (BATTLE_TYPE_LINK
&& ((TESTING && IsDoubleBattle()) // To be removed when Wild Double Battles are added to tests
|| !(gBattleTypeFlags & (BATTLE_TYPE_LINK
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_RECORDED_LINK
| BATTLE_TYPE_TRAINER_HILL
| BATTLE_TYPE_FRONTIER)))
| BATTLE_TYPE_FRONTIER))))
{
const struct Evolution *evolutions = GetSpeciesEvolutions(gBattleMons[gBattlerAttacker].species);
if (evolutions == NULL)

View File

@ -37,7 +37,7 @@ sp_irq: .word IWRAM_END - 0x60
.pool
.arm
.section .iwram.code
.section .iwram.code, "ax", %progbits
.align 2, 0
IntrMain::
mov r3, #REG_BASE

View File

@ -12580,7 +12580,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
.category = DAMAGE_CATEGORY_SPECIAL,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_FLAME_BURST,
.self = TRUE,
}),
.contestEffect = CONTEST_EFFECT_SHIFT_JUDGE_ATTENTION,
.contestCategory = CONTEST_CATEGORY_BEAUTY,

View File

@ -5048,41 +5048,22 @@ const struct SpeciesInfo gSpeciesInfoGen1[] =
"It flies by using the power of\n"
"moonlight to control gravity within\n"
"a radius of over 32 feet around it."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Clefable)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sClefableLevelUpLearnset,
.teachableLearnset = sClefableTeachableLearnset,
@ -9252,41 +9233,22 @@ const struct SpeciesInfo gSpeciesInfoGen1[] =
"has increased due to Mega Evolution,\n"
"filling its mouth. If not careful,\n"
"the acid will overflow and spill out."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Victreebel)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sVictreebelLevelUpLearnset,
.teachableLearnset = sVictreebelTeachableLearnset,
@ -15682,41 +15644,22 @@ const struct SpeciesInfo gSpeciesInfoGen1[] =
"humanlike. Whether it's simply\n"
"trying to communicate or wants to\n"
"supplant humanity is unclear."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Starmie)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sStarmieLevelUpLearnset,
.teachableLearnset = sStarmieTeachableLearnset,
@ -20228,41 +20171,22 @@ const struct SpeciesInfo gSpeciesInfoGen1[] =
"powered up this Pokémon's feelings\n"
"of kindness. It finishes off its\n"
"opponents with mercy in its heart."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Dragonite)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sDragoniteLevelUpLearnset,
.teachableLearnset = sDragoniteTeachableLearnset,

View File

@ -267,41 +267,22 @@ const struct SpeciesInfo gSpeciesInfoGen2[] =
"powerful Solar Beam from its four\n"
"flowers. Another name for this is\n"
"Mega Sol Cannon."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Meganium)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sMeganiumLevelUpLearnset,
.teachableLearnset = sMeganiumTeachableLearnset,
@ -853,41 +834,22 @@ const struct SpeciesInfo gSpeciesInfoGen2[] =
"Pokémon forms a gigantic set of jaws\n"
"with a bite 10 times as powerful\n"
"as Mega Feraligatr's actual jaws."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Feraligatr)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sFeraligatrLevelUpLearnset,
.teachableLearnset = sFeraligatrTeachableLearnset,
@ -7309,41 +7271,22 @@ const struct SpeciesInfo gSpeciesInfoGen2[] =
"its pincers have taken a more\n"
"diabolical form, ripping anything\n"
"they pierce to shreds."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Skarmory)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sSkarmoryLevelUpLearnset,
.teachableLearnset = sSkarmoryTeachableLearnset,

View File

@ -10743,41 +10743,22 @@ const struct SpeciesInfo gSpeciesInfoGen3[] =
"air imbued with ghost energy to\n"
"freeze even insubstantial things,\n"
"such as flames or the wind."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Froslass)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sFroslassLevelUpLearnset,
.teachableLearnset = sFroslassTeachableLearnset,

View File

@ -548,41 +548,22 @@ const struct SpeciesInfo gSpeciesInfoGen5[] =
"shaped like a serpentine spear,\n"
"it rushes in to save its\n"
"imperiled allies."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Emboar)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sEmboarLevelUpLearnset,
.teachableLearnset = sEmboarTeachableLearnset,
@ -2879,41 +2860,22 @@ const struct SpeciesInfo gSpeciesInfoGen5[] =
"head together to form a streamlined\n"
"shape and spins at high speeds,\n"
"it can destroy anything."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Excadrill)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sExcadrillLevelUpLearnset,
.teachableLearnset = sExcadrillTeachableLearnset,
@ -4127,41 +4089,22 @@ const struct SpeciesInfo gSpeciesInfoGen5[] =
"Its deadly venom gives off a faint\n"
"glow. The venom affects Scolipede's\n"
"mind, honing its viciousness."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Scolipede)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sScolipedeLevelUpLearnset,
.teachableLearnset = sScolipedeTeachableLearnset,
@ -5882,41 +5825,22 @@ const struct SpeciesInfo gSpeciesInfoGen5[] =
"shed skin to turn white, growing\n"
"tough and supple. Of course, this\n"
"Pokémon is still as feisty as ever."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Scrafty)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sScraftyLevelUpLearnset,
.teachableLearnset = sScraftyTeachableLearnset,
@ -9889,41 +9813,22 @@ const struct SpeciesInfo gSpeciesInfoGen5[] =
"electricity it did before Mega\n"
"Evolving. It discharges this energy\n"
"from its false Eelektrik made of mucus."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Eelektross)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sEelektrossLevelUpLearnset,
.teachableLearnset = sEelektrossTeachableLearnset,
@ -10330,41 +10235,22 @@ const struct SpeciesInfo gSpeciesInfoGen5[] =
"our world with the afterlife.\n"
"This Pokémon draws in hatred and\n"
"converts it into power."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Chandelure)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sChandelureLevelUpLearnset,
.teachableLearnset = sChandelureTeachableLearnset,

View File

@ -244,41 +244,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"It has fortified armor and a\n"
"will to defend at all costs.\n"
"Both are absurdly strong."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Chesnaught)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sChesnaughtLevelUpLearnset,
.teachableLearnset = sChesnaughtTeachableLearnset,
@ -534,41 +515,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"dazzle its opponents before\n"
"incinerating them with a\n"
"huge fireball."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Delphox)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sDelphoxLevelUpLearnset,
.teachableLearnset = sDelphoxTeachableLearnset,
@ -945,41 +907,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"shuriken at high speed to make it\n"
"float, then clings to it upside\n"
"down to catch opponents unawares."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Greninja)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sGreninjaLevelUpLearnset,
.teachableLearnset = sGreninjaTeachableLearnset,
@ -1934,41 +1877,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"than 18,000 degrees Fahrenheit.\n"
"It swings around its grand, blazing\n"
"mane as it protects its allies."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Pyroar)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sPyroarLevelUpLearnset,
.teachableLearnset = sPyroarTeachableLearnset,
@ -2354,41 +2278,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"all the energy from Mega\n"
"Evolution. The flower now attacks\n"
"enemies on its own."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Floette)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sFloetteEternalLevelUpLearnset,
.teachableLearnset = sFloetteEternalTeachableLearnset,
@ -3708,41 +3613,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"overwrite the personality and\n"
"memories of others-and to\n"
"control them."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Malamar)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sMalamarLevelUpLearnset,
.teachableLearnset = sMalamarTeachableLearnset,
@ -3925,41 +3811,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"It uses its many arms to toy\n"
"with its opponents. This\n"
"keeps the head extremely busy."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Barbaracle)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sBarbaracleLevelUpLearnset,
.teachableLearnset = sBarbaracleTeachableLearnset,
@ -4145,41 +4012,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"regenerative power of cells to run\n"
"wild. The liquid is deadly poison\n"
"to everything other than itself."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Dragalge)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sDragalgeLevelUpLearnset,
.teachableLearnset = sDragalgeTeachableLearnset,
@ -4864,41 +4712,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"Mega Evolution has pumped up all\n"
"its muscles. Hawlucha flexes to\n"
"show off its strength."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Hawlucha)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sHawluchaLevelUpLearnset,
.teachableLearnset = sHawluchaTeachableLearnset,
@ -7087,41 +6916,22 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
"during an unprecedented crisis,\n"
"Zygarde Mega Evolves and calms the\n"
"situation with its unmatched power."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Zygarde)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.isRestrictedLegendary = TRUE,
.levelUpLearnset = sZygardeLevelUpLearnset,

View File

@ -5240,41 +5240,22 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
"invigorated, allowing it to regain\n"
"its youth. It manipulates the\n"
"atmosphere to summon storms."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Drampa)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sDrampaLevelUpLearnset,
.teachableLearnset = sDrampaTeachableLearnset,

View File

@ -5277,41 +5277,22 @@ const struct SpeciesInfo gSpeciesInfoGen8[] =
"ultimate battle formation, which\n"
"can be achieved only if the troopers\n"
"and brass have the strongest of bonds."),
.frontPic = gMonFrontPic_CircledQuestionMark,
.frontPicSize = MON_COORDS_SIZE(40, 40),
.frontPicYOffset = 12,
.frontAnimFrames = sAnims_TwoFramePlaceHolder,
.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
.backPic = gMonBackPic_CircledQuestionMark,
.backPicSize = MON_COORDS_SIZE(40, 40),
.backPicYOffset = 12,
.backAnimId = BACK_ANIM_NONE,
.palette = gMonPalette_CircledQuestionMark,
.shinyPalette = gMonShinyPalette_CircledQuestionMark,
.iconSprite = gMonIcon_QuestionMark,
.iconPalIndex = 0,
//.frontPic = gMonFrontPic_CircledQuestionMark,
//.frontPicSize = MON_COORDS_SIZE(40, 40),
//.frontPicYOffset = 12,
//.frontAnimFrames = sAnims_TwoFramePlaceHolder,
//.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,
//.backPic = gMonBackPic_CircledQuestionMark,
//.backPicSize = MON_COORDS_SIZE(40, 40),
//.backPicYOffset = 12,
//.backAnimId = BACK_ANIM_NONE,
//.palette = gMonPalette_CircledQuestionMark,
//.shinyPalette = gMonShinyPalette_CircledQuestionMark,
//.iconSprite = gMonIcon_QuestionMark,
//.iconPalIndex = 0,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
FOOTPRINT(QuestionMark)
SHADOW(-1, 0, SHADOW_SIZE_M)
#if OW_BATTLE_ONLY_FORMS
.overworldData = {
.tileTag = TAG_NONE,
.paletteTag = OBJ_EVENT_PAL_TAG_SUBSTITUTE,
.reflectionPaletteTag = OBJ_EVENT_PAL_TAG_NONE,
.size = 512,
.width = 32,
.height = 32,
.paletteSlot = PALSLOT_NPC_1,
.shadowSize = SHADOW_SIZE_M,
.inanimate = FALSE,
.compressed = COMP,
.tracks = TRACKS_FOOT,
.oam = &gObjectEventBaseOam_32x32,
.subspriteTables = sOamTables_32x32,
.anims = sAnimTable_Following,
.images = sPicTable_Substitute,
},
#endif //OW_BATTLE_ONLY_FORMS
FOOTPRINT(Falinks)
//SHADOW(-1, 0, SHADOW_SIZE_M)
.isMegaEvolution = TRUE,
.levelUpLearnset = sFalinksLevelUpLearnset,
.teachableLearnset = sFalinksTeachableLearnset,

View File

@ -2129,7 +2129,7 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
.iconSprite = gMonIcon_Naclstack,
.iconPalIndex = 2,
.pokemonJumpType = PKMN_JUMP_TYPE_SLOW,
SHADOW(0, 5, SHADOW_SIZE_L)
SHADOW(0, 2, SHADOW_SIZE_L)
FOOTPRINT(Naclstack)
OVERWORLD(
sPicTable_Naclstack,
@ -2193,7 +2193,7 @@ const struct SpeciesInfo gSpeciesInfoGen9[] =
.iconSprite = gMonIcon_Garganacl,
.iconPalIndex = 2,
.pokemonJumpType = PKMN_JUMP_TYPE_NONE,
SHADOW(0, 13, SHADOW_SIZE_L)
SHADOW(0, 9, SHADOW_SIZE_L)
FOOTPRINT(Garganacl)
OVERWORLD(
sPicTable_Garganacl,

View File

@ -1,7 +1,7 @@
.syntax unified
.arm
.section .iwram.code
.section .iwram.code, "ax", %progbits
.align 2
.global FastUnsafeCopy32

View File

@ -85,7 +85,7 @@ lt_o_SoundInfo_pcmBuffer: .word o_SoundInfo_pcmBuffer
lt_PCM_DMA_BUF_SIZE: .word PCM_DMA_BUF_SIZE
thumb_func_end SoundMain
.section .iwram.code
.section .iwram.code, "ax", %progbits
thumb_func_start SoundMainRAM
SoundMainRAM:
ldrb r3, [r0, o_SoundInfo_reverb]

View File

@ -1707,11 +1707,12 @@ static void OverworldBasic(void)
gTimeUpdateCounter = (SECONDS_PER_MINUTE * 60 / FakeRtc_GetSecondsRatio());
UpdateTimeOfDay();
FormChangeTimeUpdate();
if (bld0[0] != bld1[0]
if (MapHasNaturalLight(gMapHeader.mapType) &&
(bld0[0] != bld1[0]
|| bld0[1] != bld1[1]
|| bld0[2] != bld1[2])
|| bld0[2] != bld1[2]))
{
ApplyWeatherColorMapIfIdle(gWeatherPtr->colorMapIndex);
ApplyWeatherColorMapIfIdle(gWeatherPtr->colorMapIndex);
}
}
}

View File

@ -58,37 +58,6 @@ static struct PokemonSpriteVisualizer *GetStructPtr(u8 taskId)
return (struct PokemonSpriteVisualizer*)(T1_READ_PTR(taskDataPtr));
}
static const union AnimCmd sAnim_Follower_1[] =
{
ANIMCMD_FRAME(0, 30),
ANIMCMD_FRAME(1, 30),
ANIMCMD_FRAME(0, 30),
ANIMCMD_FRAME(1, 30),
ANIMCMD_FRAME(0, 10),
ANIMCMD_FRAME(2, 30),
ANIMCMD_FRAME(3, 30),
ANIMCMD_FRAME(2, 30),
ANIMCMD_FRAME(3, 30),
ANIMCMD_FRAME(2, 10),
ANIMCMD_FRAME(4, 30),
ANIMCMD_FRAME(5, 30),
ANIMCMD_FRAME(4, 30),
ANIMCMD_FRAME(5, 30),
ANIMCMD_FRAME(4, 10),
ANIMCMD_FRAME(4, 30, .hFlip = TRUE),
ANIMCMD_FRAME(5, 30, .hFlip = TRUE),
ANIMCMD_FRAME(4, 30, .hFlip = TRUE),
ANIMCMD_FRAME(5, 30, .hFlip = TRUE),
ANIMCMD_FRAME(4, 10, .hFlip = TRUE),
ANIMCMD_END,
};
static const union AnimCmd *const sAnims_Follower[] =
{
sAnim_GeneralFrame0,
sAnim_Follower_1,
};
//BgTemplates
static const struct BgTemplate sBgTemplates[] =
{
@ -842,32 +811,32 @@ static void SpriteCB_EnemyShadowCustom(struct Sprite *shadowSprite)
static void SpriteCB_Follower(struct Sprite *sprite)
{
if (sprite->animDelayCounter == 0)
if (sprite->data[3] == 0)
{
sprite->animDelayCounter = 60;
sprite->data[3] = 120;
switch (sprite->animNum)
{
default:
case 0:
case 1:
StartSpriteAnim(sprite, GetFaceDirectionAnimNum(DIR_NORTH));
break;
case 2:
StartSpriteAnim(sprite, GetFaceDirectionAnimNum(DIR_WEST));
break;
case 3:
StartSpriteAnim(sprite, GetFaceDirectionAnimNum(DIR_EAST));
break;
case 4:
StartSpriteAnim(sprite, GetFaceDirectionAnimNum(DIR_SOUTH));
StartSpriteAnim(sprite, GetMoveDirectionAnimNum(DIR_NORTH));
break;
case 5:
StartSpriteAnim(sprite, GetMoveDirectionAnimNum(DIR_WEST));
break;
case 6:
StartSpriteAnim(sprite, GetMoveDirectionAnimNum(DIR_EAST));
break;
default:
case 7:
StartSpriteAnim(sprite, GetMoveDirectionAnimNum(DIR_SOUTH));
break;
}
}
else
{
sprite->animDelayCounter--;
sprite->data[3]--;
}
}
static void LoadAndCreateEnemyShadowSpriteCustom(struct PokemonSpriteVisualizer *data, u16 species)
{
bool8 invisible = FALSE;
@ -1315,9 +1284,26 @@ void CB2_Pokemon_Sprite_Visualizer(void)
gSprites[data->iconspriteId].oam.priority = 0;
//Follower Sprite
data->followerspriteId = CreateObjectGraphicsSprite(OBJ_EVENT_MON + species, SpriteCB_Follower, VISUALIZER_FOLLOWER_X, VISUALIZER_FOLLOWER_Y, 0);
u16 graphicsId = species + OBJ_EVENT_MON;
if (data->isShiny)
graphicsId += OBJ_EVENT_MON_SHINY;
if (data->isFemale)
graphicsId += OBJ_EVENT_MON_FEMALE;
data->followerspriteId = CreateObjectGraphicsSprite(graphicsId,
SpriteCB_Follower,
VISUALIZER_FOLLOWER_X,
VISUALIZER_FOLLOWER_Y,
0);
gSprites[data->followerspriteId].oam.priority = 0;
gSprites[data->followerspriteId].anims = sAnims_Follower;
const struct ObjectEventGraphicsInfo *graphicsInfo = SpeciesToGraphicsInfo(species, data->isShiny, data->isFemale);
if (graphicsInfo != NULL)
{
gSprites[data->followerspriteId].oam.shape = graphicsInfo->oam->shape;
gSprites[data->followerspriteId].oam.size = graphicsInfo->oam->size;
gSprites[data->followerspriteId].images = graphicsInfo->images;
gSprites[data->followerspriteId].anims = graphicsInfo->anims;
gSprites[data->followerspriteId].subspriteTables = graphicsInfo->subspriteTables;
}
//Modify Arrows
SetUpModifyArrows(data);
@ -2017,7 +2003,15 @@ static void ReloadPokemonSprites(struct PokemonSpriteVisualizer *data)
VISUALIZER_FOLLOWER_Y,
0);
gSprites[data->followerspriteId].oam.priority = 0;
gSprites[data->followerspriteId].anims = sAnims_Follower;
const struct ObjectEventGraphicsInfo *graphicsInfo = SpeciesToGraphicsInfo(species, data->isShiny, data->isFemale);
if (graphicsInfo != NULL)
{
gSprites[data->followerspriteId].oam.shape = graphicsInfo->oam->shape;
gSprites[data->followerspriteId].oam.size = graphicsInfo->oam->size;
gSprites[data->followerspriteId].images = graphicsInfo->images;
gSprites[data->followerspriteId].anims = graphicsInfo->anims;
gSprites[data->followerspriteId].subspriteTables = graphicsInfo->subspriteTables;
}
//Modify Arrows
LoadSpritePalette(&gSpritePalette_Arrow);

View File

@ -17,23 +17,26 @@ SINGLE_BATTLE_TEST("Beast Boost boosts the most proficient stat when knocking ou
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
switch(i) {
case 0:
MESSAGE("Nihilego's Attack rose!");
break;
case 1:
MESSAGE("Nihilego's Defense rose!");
break;
case 2:
MESSAGE("Nihilego's Sp. Atk rose!");
break;
case 3:
MESSAGE("Nihilego's Sp. Def rose!");
break;
case 4:
MESSAGE("Nihilego's Speed rose!");
break;
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
u32 expectedStat = STAT_ATK;
switch (i) {
case 1:
expectedStat = STAT_DEF;
break;
case 2:
expectedStat = STAT_SPATK;
break;
case 3:
expectedStat = STAT_SPDEF;
break;
case 4:
expectedStat = STAT_SPEED;
break;
}
EXPECT_EQ(player->statStages[expectedStat], DEFAULT_STAT_STAGE + 1);
}
}
@ -73,28 +76,180 @@ SINGLE_BATTLE_TEST("Beast Boost prioritizes stats in the case of a tie in the fo
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
switch(i) {
case 0:
MESSAGE("Nihilego's Attack rose!");
break;
case 1:
MESSAGE("Nihilego's Defense rose!");
break;
case 2:
MESSAGE("Nihilego's Sp. Atk rose!");
break;
case 3:
MESSAGE("Nihilego's Sp. Def rose!");
break;
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
u32 expectedStat = STAT_ATK;
switch (i) {
case 1:
expectedStat = STAT_DEF;
break;
case 2:
expectedStat = STAT_SPATK;
break;
case 3:
expectedStat = STAT_SPDEF;
break;
}
EXPECT_EQ(player->statStages[expectedStat], DEFAULT_STAT_STAGE + 1);
}
}
TO_DO_BATTLE_TEST("Beast Boost considers Power Split");
TO_DO_BATTLE_TEST("Beast Boost considers Guard Split");
TO_DO_BATTLE_TEST("Beast Boost considers Power Trick");
TO_DO_BATTLE_TEST("Beast Boost considers Wonder Room");
TO_DO_BATTLE_TEST("Beast Boost considers Speed Swap");
TO_DO_BATTLE_TEST("Beast Boost doesn't consider stat stages");
TO_DO_BATTLE_TEST("Beast Boost doesn't consider held items");
TO_DO_BATTLE_TEST("Beast Boost doesn't consider status condition reductions");
SINGLE_BATTLE_TEST("Beast Boost considers Power Split")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_POWER_SPLIT) == EFFECT_POWER_SPLIT);
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Attack(200); Defense(30); SpAttack(50); SpDefense(30); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Attack(10); SpAttack(250); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_POWER_SPLIT); }
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWER_SPLIT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Beast Boost considers Guard Split")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_GUARD_SPLIT) == EFFECT_GUARD_SPLIT);
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Attack(80); Defense(20); SpAttack(70); SpDefense(10); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Defense(200); SpDefense(30); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_GUARD_SPLIT); }
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GUARD_SPLIT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Beast Boost considers Power Trick")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_POWER_TRICK) == EFFECT_POWER_TRICK);
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Attack(40); Defense(200); SpAttack(60); SpDefense(50); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_POWER_TRICK); }
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWER_TRICK, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Beast Boost considers Wonder Room")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_WONDER_ROOM) == EFFECT_WONDER_ROOM);
ASSUME(GetMovePower(MOVE_SCRATCH) > 0);
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Attack(100); Defense(50); SpAttack(70); SpDefense(200); Speed(120); Moves(MOVE_SPLASH, MOVE_EXTREME_SPEED); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(200); Moves(MOVE_WONDER_ROOM, MOVE_SPLASH); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(30); }
} WHEN {
TURN { MOVE(opponent, MOVE_WONDER_ROOM); MOVE(player, MOVE_SPLASH); }
TURN { MOVE(player, MOVE_EXTREME_SPEED); MOVE(opponent, MOVE_SPLASH); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WONDER_ROOM, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EXTREME_SPEED, player);
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Beast Boost considers Speed Swap")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SPEED_SWAP) == EFFECT_SPEED_SWAP);
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Attack(60); Defense(60); SpAttack(70); SpDefense(60); Speed(30); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(200); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(50); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SPEED_SWAP); }
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPEED_SWAP, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Beast Boost doesn't consider stat stages")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Attack(100); Defense(60); SpAttack(150); SpDefense(60); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SWORDS_DANCE); }
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Beast Boost doesn't consider held items")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_CHOICE_BAND].holdEffect == HOLD_EFFECT_CHOICE_BAND);
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Item(ITEM_CHOICE_BAND); Attack(120); Defense(60); SpAttack(150); SpDefense(60); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1);
}
}
SINGLE_BATTLE_TEST("Beast Boost doesn't consider status condition reductions")
{
GIVEN {
PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Status1(STATUS1_BURN); Attack(150); Defense(60); SpAttack(100); SpDefense(60); }
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); SEND_OUT(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
ABILITY_POPUP(player, ABILITY_BEAST_BOOST);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
} THEN {
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
}
}

View File

@ -239,9 +239,115 @@ SINGLE_BATTLE_TEST("Corrosion's effect is lost if the move used by the Pokémon
}
}
TO_DO_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Baneful Bunker")
TO_DO_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Psycho Shift while poisoned")
TO_DO_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Fling while holding a Toxic Orb")
TO_DO_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Fling while holding a Poison Barb")
SINGLE_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Baneful Bunker")
{
u16 species;
PARAMETRIZE { species = SPECIES_ODDISH; }
PARAMETRIZE { species = SPECIES_BELDUM; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_BANEFUL_BUNKER) == EFFECT_PROTECT);
ASSUME(MoveMakesContact(MOVE_SCRATCH));
PLAYER(SPECIES_SALANDIT) { Ability(ABILITY_CORROSION); }
OPPONENT(species);
} WHEN {
TURN { MOVE(player, MOVE_BANEFUL_BUNKER); MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_BANEFUL_BUNKER, player);
MESSAGE("Salandit protected itself!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
MESSAGE("Salandit protected itself!");
STATUS_ICON(opponent, poison: TRUE);
}
}
SINGLE_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Psycho Shift while poisoned")
{
u16 species;
PARAMETRIZE { species = SPECIES_ODDISH; }
PARAMETRIZE { species = SPECIES_BELDUM; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_PSYCHO_SHIFT) == EFFECT_PSYCHO_SHIFT);
PLAYER(SPECIES_SALANDIT) { Ability(ABILITY_CORROSION); Status1(STATUS1_POISON); }
OPPONENT(species);
} WHEN {
TURN { MOVE(player, MOVE_PSYCHO_SHIFT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHO_SHIFT, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
STATUS_ICON(opponent, poison: TRUE);
STATUS_ICON(player, none: TRUE);
}
}
SINGLE_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Fling while holding a Toxic Orb")
{
u16 species;
PARAMETRIZE { species = SPECIES_ODDISH; }
PARAMETRIZE { species = SPECIES_BELDUM; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_FLING) == EFFECT_FLING);
ASSUME(gItemsInfo[ITEM_TOXIC_ORB].holdEffect == HOLD_EFFECT_TOXIC_ORB);
PLAYER(SPECIES_SALANDIT) { Ability(ABILITY_CORROSION); Item(ITEM_TOXIC_ORB); }
OPPONENT(species);
} WHEN {
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
STATUS_ICON(opponent, badPoison: TRUE);
}
}
SINGLE_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Fling while holding a Poison Barb")
{
u16 species;
PARAMETRIZE { species = SPECIES_ODDISH; }
PARAMETRIZE { species = SPECIES_BELDUM; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_FLING) == EFFECT_FLING);
ASSUME(gItemsInfo[ITEM_POISON_BARB].holdEffect == HOLD_EFFECT_TYPE_POWER);
ASSUME(gItemsInfo[ITEM_POISON_BARB].secondaryId == TYPE_POISON);
PLAYER(SPECIES_SALANDIT) { Ability(ABILITY_CORROSION); Item(ITEM_POISON_BARB); }
OPPONENT(species);
} WHEN {
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
STATUS_ICON(opponent, poison: TRUE);
}
}
SINGLE_BATTLE_TEST("Corrosion does not affect Poison Spikes")
{
u16 species;
PARAMETRIZE { species = SPECIES_ODDISH; }
PARAMETRIZE { species = SPECIES_BELDUM; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_TOXIC_SPIKES) == EFFECT_TOXIC_SPIKES);
PLAYER(SPECIES_SALANDIT) { Ability(ABILITY_CORROSION); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(species);
} WHEN {
TURN { MOVE(player, MOVE_TOXIC_SPIKES); }
TURN { SWITCH(opponent, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, player);
} THEN {
EXPECT_EQ(opponent->status1, STATUS1_NONE);
}
}
TO_DO_BATTLE_TEST("Dynamax: Corrosion can poison Poison/Steel types if the Pokémon uses G-Max Malodor")
TO_DO_BATTLE_TEST("Corrosion does not affect Poison Spikes")

View File

@ -5,5 +5,45 @@
//TO_DO_BATTLE_TEST("Delta Stream doesn't activate if is sent-out in a rotated-out position (Rotation)")
//TO_DO_BATTLE_TEST("Delta Stream doesn't activate if is rotated-in (Rotation)")
TO_DO_BATTLE_TEST("Delta Stream doesn't activate if there's already strong winds")
TO_DO_BATTLE_TEST("Strong winds continue as long as there's a Pokémon with Delta Stream on the field") // Doesn't need to be the original mon
DOUBLE_BATTLE_TEST("Delta Stream doesn't activate if there's already strong winds")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { SWITCH(playerLeft, 2); }
} SCENE {
ABILITY_POPUP(opponentLeft, ABILITY_DELTA_STREAM);
MESSAGE("Mysterious strong winds are protecting Flying-type Pokémon!");
SWITCH_OUT_MESSAGE("Wobbuffet");
SEND_IN_MESSAGE("Rayquaza");
NONE_OF {
ABILITY_POPUP(playerLeft, ABILITY_DELTA_STREAM);
MESSAGE("Mysterious strong winds are protecting Flying-type Pokémon!");
}
}
}
DOUBLE_BATTLE_TEST("Strong winds continue as long as there's a Pokémon with Delta Stream on the field")
{
GIVEN {
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); HP(1); }
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft); SEND_OUT(playerLeft, 2); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
HP_BAR(playerLeft, hp: 0);
MESSAGE("Rayquaza fainted!");
SEND_IN_MESSAGE("Wobbuffet");
NOT MESSAGE("The mysterious strong winds have dissipated!");
} THEN {
EXPECT(gBattleWeather & B_WEATHER_STRONG_WINDS);
}
}

View File

@ -99,14 +99,81 @@ SINGLE_BATTLE_TEST("Desolate Land is removed immediately if user faints")
}
}
TO_DO_BATTLE_TEST("Desolate Land makes Sunny Day fail")
TO_DO_BATTLE_TEST("Desolate Land makes Rain Dance fail")
TO_DO_BATTLE_TEST("Desolate Land makes Sandstorm fail")
TO_DO_BATTLE_TEST("Desolate Land makes Hail fail")
TO_DO_BATTLE_TEST("Desolate Land makes Snowscape fail") // Extrapolation
TO_DO_BATTLE_TEST("Desolate Land makes Drought fail to activate")
TO_DO_BATTLE_TEST("Desolate Land makes Drizzle fail to activate")
TO_DO_BATTLE_TEST("Desolate Land makes Sand Stream fail to activate")
TO_DO_BATTLE_TEST("Desolate Land makes Snow Warning fail to activate")
TO_DO_BATTLE_TEST("Desolate Land can be replaced by Delta Stream")
TO_DO_BATTLE_TEST("Desolate Land can be replaced by Primordial Sea")
SINGLE_BATTLE_TEST("Desolate Land blocks weather-setting moves")
{
u16 move;
PARAMETRIZE { move = MOVE_SUNNY_DAY; }
PARAMETRIZE { move = MOVE_RAIN_DANCE; }
PARAMETRIZE { move = MOVE_SANDSTORM; }
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_SUNNY_DAY) == EFFECT_SUNNY_DAY);
ASSUME(GetMoveEffect(MOVE_RAIN_DANCE) == EFFECT_RAIN_DANCE);
ASSUME(GetMoveEffect(MOVE_SANDSTORM) == EFFECT_SANDSTORM);
ASSUME(GetMoveEffect(MOVE_HAIL) == EFFECT_HAIL);
ASSUME(GetMoveEffect(MOVE_SNOWSCAPE) == EFFECT_SNOWSCAPE);
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent);
} THEN {
EXPECT(gBattleWeather & B_WEATHER_SUN_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Desolate Land prevents other weather abilities")
{
u16 ability, species;
PARAMETRIZE { ability = ABILITY_DROUGHT; species = SPECIES_NINETALES; }
PARAMETRIZE { ability = ABILITY_DRIZZLE; species = SPECIES_POLITOED; }
PARAMETRIZE { ability = ABILITY_SAND_STREAM; species = SPECIES_HIPPOWDON; }
PARAMETRIZE { ability = ABILITY_SNOW_WARNING; species = SPECIES_ABOMASNOW; }
GIVEN {
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ability);
} THEN {
EXPECT(gBattleWeather & B_WEATHER_SUN_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Desolate Land can be replaced by Delta Stream")
{
GIVEN {
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_DELTA_STREAM);
MESSAGE("Mysterious strong winds are protecting Flying-type Pokémon!");
} THEN {
EXPECT(gBattleWeather & B_WEATHER_STRONG_WINDS);
}
}
SINGLE_BATTLE_TEST("Desolate Land can be replaced by Primordial Sea")
{
GIVEN {
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_PRIMORDIAL_SEA);
MESSAGE("A heavy rain began to fall!");
} THEN {
EXPECT(gBattleWeather & B_WEATHER_RAIN_PRIMAL);
}
}

View File

@ -22,3 +22,84 @@ SINGLE_BATTLE_TEST("Drizzle summons rain", s16 damage)
EXPECT_MUL_EQ(results[1].damage, Q_4_12(1.5), results[0].damage);
}
}
SINGLE_BATTLE_TEST("Drizzle sets up rain for 5 turns (Gen6+)")
{
GIVEN {
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
PLAYER(SPECIES_POLITOED) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DRIZZLE); }
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_DRIZZLE);
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("The rain stopped.");
}
}
SINGLE_BATTLE_TEST("Drizzle sets up rain for 8 turns with Damp Rock (Gen6+)")
{
GIVEN {
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
PLAYER(SPECIES_POLITOED) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DRIZZLE); Item(ITEM_DAMP_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_DRIZZLE);
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("The rain stopped.");
}
}
SINGLE_BATTLE_TEST("Drizzle sets up permanent rain (Gen3-5)")
{
GIVEN {
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_3);
PLAYER(SPECIES_POLITOED) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DRIZZLE); }
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_DRIZZLE);
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
MESSAGE("Rain continues to fall.");
NOT MESSAGE("The rain stopped.");
}
}

View File

@ -1,4 +1,52 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Heatproof (Ability) test titles")
ASSUMPTIONS
{
ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE);
ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_OVERWRITE_ABILITY);
}
SINGLE_BATTLE_TEST("Heatproof halves damage from fire type moves")
{
s16 damage[2];
GIVEN {
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_BRONZONG) { Ability(ABILITY_HEATPROOF); }
}
WHEN {
TURN { MOVE(player, MOVE_EMBER); }
TURN { MOVE(player, MOVE_WORRY_SEED); }
TURN { MOVE(player, MOVE_EMBER); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
HP_BAR(opponent, captureDamage: &damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
HP_BAR(opponent, captureDamage: &damage[1]);
EXPECT_MUL_EQ(damage[0], Q_4_12(2), damage[1]);
}
}
SINGLE_BATTLE_TEST("Heatproof halves the damage done by burn from 1/8th to 1/16th (Gen1-6) or 1/16th to 1/32nd (Gen 7+)")
{
u32 config, burnRate;
PARAMETRIZE { config = GEN_7; burnRate = 32; }
PARAMETRIZE { config = GEN_6; burnRate = 16; }
GIVEN {
WITH_CONFIG(CONFIG_BURN_DAMAGE, config);
PLAYER (SPECIES_BRONZONG) { Ability(ABILITY_HEATPROOF); Status1(STATUS1_BURN); }
OPPONENT (SPECIES_WOBBUFFET);
}
WHEN {
TURN {}
}
SCENE {
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
HP_BAR(player, damage: maxHP / burnRate);
}
}

View File

@ -112,3 +112,47 @@ SINGLE_BATTLE_TEST("Intrepid Sword and Dauntless Shield both can be Skill Swappe
MESSAGE("Wobbuffet's Dauntless Shield raised its Defense!");
}
}
SINGLE_BATTLE_TEST("Intrepid Sword and Dauntless Shield do not proc at max stage (Skill Swap)")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP);
ASSUME(GetMoveEffect(MOVE_IRON_DEFENSE) == EFFECT_DEFENSE_UP_2);
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
PLAYER(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); }
} WHEN {
TURN { MOVE(player, MOVE_IRON_DEFENSE); MOVE(opponent, MOVE_SWORDS_DANCE);}
TURN { MOVE(player, MOVE_IRON_DEFENSE); MOVE(opponent, MOVE_SWORDS_DANCE);}
TURN { MOVE(player, MOVE_IRON_DEFENSE); MOVE(opponent, MOVE_SWORDS_DANCE);}
TURN { MOVE(player, MOVE_SKILL_SWAP); }
} SCENE {
NONE_OF {
ABILITY_POPUP(player, ABILITY_DAUNTLESS_SHIELD);
ABILITY_POPUP(opponent, ABILITY_INTREPID_SWORD);
}
}
}
SINGLE_BATTLE_TEST("Intrepid Sword and Dauntless Shield do not proc at max stage (Baton Pass)")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS);
ASSUME(GetMoveEffect(MOVE_IRON_DEFENSE) == EFFECT_DEFENSE_UP_2);
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
} WHEN {
TURN { MOVE(player, MOVE_IRON_DEFENSE); MOVE(opponent, MOVE_SWORDS_DANCE);}
TURN { MOVE(player, MOVE_IRON_DEFENSE); MOVE(opponent, MOVE_SWORDS_DANCE);}
TURN { MOVE(player, MOVE_IRON_DEFENSE); MOVE(opponent, MOVE_SWORDS_DANCE);}
TURN { MOVE(player, MOVE_BATON_PASS); MOVE(opponent, MOVE_BATON_PASS); SEND_OUT(player, 1); SEND_OUT(opponent, 1);}
} SCENE {
NONE_OF {
ABILITY_POPUP(player, ABILITY_DAUNTLESS_SHIELD);
ABILITY_POPUP(opponent, ABILITY_INTREPID_SWORD);
}
}
}

View File

@ -163,7 +163,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of h
}
}
SINGLE_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4")
SINGLE_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4)")
{
s16 damage;
GIVEN {

View File

@ -1,5 +1,112 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Orichalcum Pulse sets up sun for 5 turns");
TO_DO_BATTLE_TEST("Orichalcum Pulse boosts the Pokémon's Attack by 33% in sun, even if it's holding an Utility Umbrella");
SINGLE_BATTLE_TEST("Orichalcum Pulse sets up sun for 5 turns")
{
GIVEN {
PLAYER(SPECIES_KORAIDON) { Moves(MOVE_CELEBRATE); Ability(ABILITY_ORICHALCUM_PULSE); }
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_ORICHALCUM_PULSE);
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("Orichalcum Pulse sets up sun for 8 turns with Heat Rock")
{
GIVEN {
PLAYER(SPECIES_KORAIDON) { Moves(MOVE_CELEBRATE); Ability(ABILITY_ORICHALCUM_PULSE); 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_ORICHALCUM_PULSE);
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("Orichalcum Pulse boosts physical moves by 33% in sun", s16 damage)
{
u16 setupMove;
PARAMETRIZE { setupMove = MOVE_CELEBRATE; }
PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; }
GIVEN {
ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_KORAIDON) { Ability(ABILITY_ORICHALCUM_PULSE); Moves(MOVE_SCRATCH); Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_RAIN_DANCE, MOVE_CELEBRATE); Speed(10); }
} WHEN {
TURN { MOVE(opponent, setupMove); MOVE(player, MOVE_SCRATCH); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ORICHALCUM_PULSE);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[1].damage, Q_4_12(1.3333), results[0].damage);
}
}
SINGLE_BATTLE_TEST("Orichalcum Pulse boost applies even if the target holds Utility Umbrella", s16 damage)
{
u16 targetItem;
PARAMETRIZE { targetItem = ITEM_NONE; }
PARAMETRIZE { targetItem = ITEM_UTILITY_UMBRELLA; }
GIVEN {
ASSUME(gItemsInfo[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_KORAIDON) { Ability(ABILITY_ORICHALCUM_PULSE); Moves(MOVE_SCRATCH); Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(10); Item(targetItem); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SCRATCH); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ORICHALCUM_PULSE);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_EQ(results[0].damage, results[1].damage);
}
}
SINGLE_BATTLE_TEST("Orichalcum Pulse does not boost physical moves if holder has Utility Umbrella", s16 damage)
{
u16 holdItem;
PARAMETRIZE { holdItem = ITEM_NONE; }
PARAMETRIZE { holdItem = ITEM_UTILITY_UMBRELLA; }
GIVEN {
ASSUME(gItemsInfo[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA);
ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_KORAIDON) { Ability(ABILITY_ORICHALCUM_PULSE); Moves(MOVE_SCRATCH); Speed(5); Item(holdItem); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); Speed(10); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SCRATCH); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ORICHALCUM_PULSE);
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[1].damage, Q_4_12(1.3333), results[0].damage);
}
}

View File

@ -65,14 +65,81 @@ SINGLE_BATTLE_TEST("Primordial Sea does not block a move if Pokémon is asleep a
}
}
TO_DO_BATTLE_TEST("Primordial Sea makes Sunny Day fail")
TO_DO_BATTLE_TEST("Primordial Sea makes Rain Dance fail")
TO_DO_BATTLE_TEST("Primordial Sea makes Sandstorm fail")
TO_DO_BATTLE_TEST("Primordial Sea makes Hail fail")
TO_DO_BATTLE_TEST("Primordial Sea makes Snowscape fail") // Extrapolation
TO_DO_BATTLE_TEST("Primordial Sea makes Drought fail to activate")
TO_DO_BATTLE_TEST("Primordial Sea makes Drizzle fail to activate")
TO_DO_BATTLE_TEST("Primordial Sea makes Sand Stream fail to activate")
TO_DO_BATTLE_TEST("Primordial Sea makes Snow Warning fail to activate")
TO_DO_BATTLE_TEST("Primordial Sea can be replaced by Delta Stream")
TO_DO_BATTLE_TEST("Primordial Sea can be replaced by Desolate Land")
SINGLE_BATTLE_TEST("Primordial Sea blocks weather-setting moves")
{
u16 move;
PARAMETRIZE { move = MOVE_SUNNY_DAY; }
PARAMETRIZE { move = MOVE_RAIN_DANCE; }
PARAMETRIZE { move = MOVE_SANDSTORM; }
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_SUNNY_DAY) == EFFECT_SUNNY_DAY);
ASSUME(GetMoveEffect(MOVE_RAIN_DANCE) == EFFECT_RAIN_DANCE);
ASSUME(GetMoveEffect(MOVE_SANDSTORM) == EFFECT_SANDSTORM);
ASSUME(GetMoveEffect(MOVE_HAIL) == EFFECT_HAIL);
ASSUME(GetMoveEffect(MOVE_SNOWSCAPE) == EFFECT_SNOWSCAPE);
PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent);
} THEN {
EXPECT(gBattleWeather & B_WEATHER_RAIN_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Primordial Sea prevents other weather abilities")
{
u16 ability, species;
PARAMETRIZE { ability = ABILITY_DROUGHT; species = SPECIES_NINETALES; }
PARAMETRIZE { ability = ABILITY_DRIZZLE; species = SPECIES_POLITOED; }
PARAMETRIZE { ability = ABILITY_SAND_STREAM; species = SPECIES_HIPPOWDON; }
PARAMETRIZE { ability = ABILITY_SNOW_WARNING; species = SPECIES_ABOMASNOW; }
GIVEN {
PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ability);
} THEN {
EXPECT(gBattleWeather & B_WEATHER_RAIN_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Primordial Sea can be replaced by Delta Stream")
{
GIVEN {
PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_DELTA_STREAM);
MESSAGE("Mysterious strong winds are protecting Flying-type Pokémon!");
} THEN {
EXPECT(gBattleWeather & B_WEATHER_STRONG_WINDS);
}
}
SINGLE_BATTLE_TEST("Primordial Sea can be replaced by Desolate Land")
{
GIVEN {
PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_DESOLATE_LAND);
MESSAGE("The sunlight turned extremely harsh!");
} THEN {
EXPECT(gBattleWeather & B_WEATHER_SUN_PRIMAL);
}
}

View File

@ -1,4 +1,77 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Sand Spit (Ability) test titles")
SINGLE_BATTLE_TEST("Sand Spit sets up sandstorm for 5 turns when hit")
{
GIVEN {
PLAYER(SPECIES_SANDSLASH) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SAND_SPIT); }
OPPONENT(SPECIES_LANDORUS) { Moves(MOVE_TACKLE, MOVE_CELEBRATE); }
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
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 {
MESSAGE("The opposing Landorus used Tackle!");
HP_BAR(player);
ABILITY_POPUP(player, ABILITY_SAND_SPIT);
MESSAGE("A sandstorm kicked up!");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm subsided.");
}
}
SINGLE_BATTLE_TEST("Sand Spit sets up sandstorm for 8 turns when hit with Smooth Rock")
{
GIVEN {
PLAYER(SPECIES_SANDSLASH) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SAND_SPIT); Item(ITEM_SMOOTH_ROCK); }
OPPONENT(SPECIES_LANDORUS) { Moves(MOVE_TACKLE, MOVE_CELEBRATE); }
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
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 {
MESSAGE("The opposing Landorus used Tackle!");
HP_BAR(player);
ABILITY_POPUP(player, ABILITY_SAND_SPIT);
MESSAGE("A sandstorm kicked up!");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm subsided.");
}
}
SINGLE_BATTLE_TEST("Sand Spit triggers even if the user is knocked out by the hit")
{
GIVEN {
PLAYER(SPECIES_SANDSLASH) { Ability(ABILITY_SAND_SPIT); HP(1); Speed(1); }
PLAYER(SPECIES_LANDORUS) { Moves(MOVE_CELEBRATE); Speed(5); }
OPPONENT(SPECIES_LANDORUS) { Moves(MOVE_TACKLE, MOVE_CELEBRATE); Speed(10); }
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); }
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); }
} SCENE {
MESSAGE("The opposing Landorus used Tackle!");
HP_BAR(player);
ABILITY_POPUP(player, ABILITY_SAND_SPIT);
MESSAGE("A sandstorm kicked up!");
MESSAGE("The sandstorm is raging.");
MESSAGE("The opposing Landorus used Celebrate!");
MESSAGE("Landorus used Celebrate!");
MESSAGE("The sandstorm is raging.");
}
}

View File

@ -1,4 +1,83 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Sand Stream (Ability) test titles")
SINGLE_BATTLE_TEST("Sand Stream sets up sandstorm for 5 turns (Gen6+)")
{
GIVEN {
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
PLAYER(SPECIES_HIPPOWDON) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SAND_STREAM); }
OPPONENT(SPECIES_SANDSLASH) { 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_SAND_STREAM);
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm subsided.");
}
}
SINGLE_BATTLE_TEST("Sand Stream sets up sandstorm for 8 turns with Smooth Rock (Gen6+)")
{
GIVEN {
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
PLAYER(SPECIES_HIPPOWDON) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SAND_STREAM); Item(ITEM_SMOOTH_ROCK); }
OPPONENT(SPECIES_SANDSLASH) { 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_SAND_STREAM);
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm subsided.");
}
}
SINGLE_BATTLE_TEST("Sand Stream sets up permanent sandstorm (Gen3-5)")
{
GIVEN {
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_3);
PLAYER(SPECIES_HIPPOWDON) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SAND_STREAM); }
OPPONENT(SPECIES_SANDSLASH) { 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_SAND_STREAM);
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
MESSAGE("The sandstorm is raging.");
NOT MESSAGE("The sandstorm subsided.");
}
}

View File

@ -1,30 +1,138 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Snow Warning summons hail (Gen4-8)")
SINGLE_BATTLE_TEST("Snow Warning sets up hail for 5 turns (Gen6-8)")
{
GIVEN {
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_8);
PLAYER(SPECIES_ABOMASNOW) { Ability(ABILITY_SNOW_WARNING); }
OPPONENT(SPECIES_WOBBUFFET);
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
} WHEN {
TURN {}
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 {
MESSAGE("It started to hail!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HAIL_CONTINUES);
ABILITY_POPUP(player, ABILITY_SNOW_WARNING);
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail stopped.");
}
}
SINGLE_BATTLE_TEST("Snow Warning summons snow (Gen9+)")
SINGLE_BATTLE_TEST("Snow Warning sets up hail for 8 turns with Icy Rock (Gen6-8)")
{
GIVEN {
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_8);
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_6);
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); Item(ITEM_ICY_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_SNOW_WARNING);
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail stopped.");
}
}
SINGLE_BATTLE_TEST("Snow Warning sets up permanent hail (Gen4-5)")
{
GIVEN {
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_8);
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_5);
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); }
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_SNOW_WARNING);
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
MESSAGE("The hail is crashing down.");
NOT MESSAGE("The hail stopped.");
}
}
SINGLE_BATTLE_TEST("Snow Warning sets up snow for 5 turns (Gen9+)")
{
GIVEN {
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_9);
PLAYER(SPECIES_ABOMASNOW) { Ability(ABILITY_SNOW_WARNING); }
OPPONENT(SPECIES_WOBBUFFET);
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_9);
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); }
} WHEN {
TURN {}
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 {
MESSAGE("It started to snow!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SNOW_CONTINUES);
ABILITY_POPUP(player, ABILITY_SNOW_WARNING);
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("The snow stopped.");
}
}
SINGLE_BATTLE_TEST("Snow Warning sets up snow for 8 turns with Icy Rock (Gen9+)")
{
GIVEN {
WITH_CONFIG(CONFIG_SNOW_WARNING, GEN_9);
WITH_CONFIG(CONFIG_ABILITY_WEATHER, GEN_9);
PLAYER(SPECIES_ABOMASNOW) { Moves(MOVE_CELEBRATE); Ability(ABILITY_SNOW_WARNING); Item(ITEM_ICY_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_SNOW_WARNING);
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("Snow continues to fall.");
MESSAGE("The snow stopped.");
}
}

View File

@ -1,4 +1,39 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Thick Fat (Ability) test titles")
ASSUMPTIONS
{
ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE);
ASSUME(GetMoveType(MOVE_POWDER_SNOW) == TYPE_ICE);
ASSUME(GetMoveEffect(MOVE_WORRY_SEED) == EFFECT_OVERWRITE_ABILITY);
}
SINGLE_BATTLE_TEST("Thick Fat halves damage from fire and ice type moves", s16 damage[2])
{
u16 move;
PARAMETRIZE { move = MOVE_POWDER_SNOW; }
PARAMETRIZE { move = MOVE_EMBER; }
GIVEN {
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_SNORLAX) { Ability(ABILITY_THICK_FAT); }
}
WHEN {
TURN { MOVE(player, move); }
TURN { MOVE(player, MOVE_WORRY_SEED); }
TURN { MOVE(player, move); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent, captureDamage: &results[i].damage[0]);
ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, player);
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent, captureDamage: &results[i].damage[1]);
}
FINALLY {
EXPECT_MUL_EQ(results[0].damage[0], Q_4_12(2), results[0].damage[1]);
EXPECT_MUL_EQ(results[1].damage[0], Q_4_12(2), results[1].damage[1]);
}
}

View File

@ -259,6 +259,19 @@ AI_SINGLE_BATTLE_TEST("HasMoveThatChangesKOThreshold - AI should not see self-ta
}
}
AI_SINGLE_BATTLE_TEST("AI_IsMoveEffectInPlus - AI should not see secondary effect of Sheer Force boosted moves as beneficial")
{
GIVEN {
ASSUME(GetMovePower(MOVE_PSYCHIC) == 90);
ASSUME(MoveHasAdditionalEffect(MOVE_PSYCHIC, MOVE_EFFECT_SP_DEF_MINUS_1) == TRUE);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT);
PLAYER(SPECIES_STEELIX) { Level(100); Nature(NATURE_SASSY); Item(ITEM_STEELIXITE); Ability(ABILITY_STURDY); Speed(58); Moves(MOVE_GYRO_BALL); }
OPPONENT(SPECIES_BRAVIARY_HISUI) { Level(100); Nature(NATURE_TIMID); Ability(ABILITY_SHEER_FORCE); Speed(251); Moves(MOVE_PSYCHIC, MOVE_NIGHT_SHADE); }
} WHEN {
TURN { MOVE(player, MOVE_GYRO_BALL); SCORE_EQ_VAL(opponent, MOVE_PSYCHIC, 101); SCORE_EQ_VAL(opponent, MOVE_NIGHT_SHADE, 101); }
}
}
AI_SINGLE_BATTLE_TEST("Fillet Away AI handling")
{
u16 move;

View File

@ -222,3 +222,31 @@ AI_MULTI_BATTLE_TEST("AI opponents do not steal their partner pokemon in multi b
EXPECT_EQ(SPECIES_VENUSAUR, opponentLeft->species);
}
}
AI_MULTI_BATTLE_TEST("Pollen Puff: AI correctly scores moves with EFFECT_HIT_ENEMY_HEAL_ALLY as damaging opponents but not allies")
{
GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
ASSUME(GetMoveEffect(MOVE_POLLEN_PUFF) == EFFECT_HIT_ENEMY_HEAL_ALLY);
// Speed tie so all think they are faster
MULTI_PLAYER(SPECIES_WOBBUFFET) { Speed(1); HP(50); Moves(MOVE_POLLEN_PUFF, MOVE_CELEBRATE); }
MULTI_PARTNER(SPECIES_WOBBUFFET) { Speed(1); HP(50); Moves(MOVE_POLLEN_PUFF); }
MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Speed(1); HP(50); Moves(MOVE_POLLEN_PUFF); }
MULTI_OPPONENT_B(SPECIES_WOBBUFFET) { Speed(1); HP(50); Moves(MOVE_POLLEN_PUFF); }
} WHEN {
TURN {
// Targeting ally
SCORE_EQ_VAL(opponentLeft, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + WEAK_EFFECT, target:opponentRight);
SCORE_EQ_VAL(playerRight, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + WEAK_EFFECT, target:playerLeft);
SCORE_EQ_VAL(opponentRight, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + WEAK_EFFECT, target:opponentLeft);
// Targeting opponent
SCORE_EQ_VAL(opponentLeft, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + BEST_DAMAGE_MOVE + FAST_KILL, target:playerLeft);
SCORE_EQ_VAL(opponentLeft, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + BEST_DAMAGE_MOVE + FAST_KILL, target:playerRight);
SCORE_EQ_VAL(playerRight, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + BEST_DAMAGE_MOVE + FAST_KILL, target:opponentLeft);
SCORE_EQ_VAL(playerRight, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + BEST_DAMAGE_MOVE + FAST_KILL, target:opponentRight);
SCORE_EQ_VAL(opponentRight, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + BEST_DAMAGE_MOVE + FAST_KILL, target:playerLeft);
SCORE_EQ_VAL(opponentRight, MOVE_POLLEN_PUFF, AI_SCORE_DEFAULT + BEST_DAMAGE_MOVE + FAST_KILL, target:playerRight);
}
}
}

View File

@ -1949,6 +1949,27 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI considers both meeting and
}
}
AI_DOUBLE_BATTLE_TEST("AI will not choose to switch out Dondozo with Commander Tatsugiri")
{
PASSES_RANDOMLY(100, 100);
GIVEN {
ASSUME(GetMoveEffect(MOVE_PERISH_SONG) == EFFECT_PERISH_SONG);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES);
OPPONENT(SPECIES_DONDOZO) { Level(50); Moves(MOVE_WATER_GUN); }
OPPONENT(SPECIES_TATSUGIRI) { Moves(MOVE_WATER_GUN); Ability(ABILITY_COMMANDER); }
OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_HEADBUTT); }
PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH); }
PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_CELEBRATE, MOVE_PERISH_SONG); }
PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_CELEBRATE); }
PLAYER(SPECIES_ZIGZAGOON) { Moves (MOVE_CELEBRATE); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_CELEBRATE); MOVE(playerRight, MOVE_PERISH_SONG); }
TURN { MOVE(playerLeft, MOVE_CELEBRATE); MOVE(playerRight, MOVE_CELEBRATE); }
TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); }
TURN { MOVE(playerLeft, MOVE_CELEBRATE); MOVE(playerRight, MOVE_CELEBRATE); EXPECT_MOVE(opponentLeft, MOVE_WATER_GUN); }
}
}
AI_SINGLE_BATTLE_TEST("AI_FLAG_RANDOMIZE_SWITCHIN: AI will randomly choose between eligible switchin candidates of the same category")
{
u32 trials; // Two trial counts to ensure randomization is scalable

View File

@ -0,0 +1,137 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gSpeciesInfo[SPECIES_BISHARP].evolutions[0].params->condition == IF_DEFEAT_X_WITH_ITEMS);
ASSUME(gSpeciesInfo[SPECIES_BISHARP].evolutions[0].params->arg1 == SPECIES_BISHARP);
ASSUME(gSpeciesInfo[SPECIES_BISHARP].evolutions[0].params->arg2 == ITEM_LEADERS_CREST);
}
WILD_BATTLE_TEST("Evolution Tracker: Bisharp KO-ing a Bisharp that holds Leader's Crest increases tracker")
{
GIVEN {
PLAYER(SPECIES_BISHARP);
OPPONENT(SPECIES_BISHARP) { Item(ITEM_LEADERS_CREST); HP(1); }
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); }
} SCENE {
HP_BAR(opponent, hp: 0);
} THEN {
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EVOLUTION_TRACKER), 1);
}
}
// To be replaced with WILD_DOUBLE_BATTLE_TEST when that is made possible (also see TryUpdateEvolutionTracker)
DOUBLE_BATTLE_TEST("Evolution Tracker: Bisharp KO-ing multiple Bisharps holding Leader's Crest increases tracker multiple times")
{
GIVEN {
ASSUME(GetMoveTarget(MOVE_LAVA_PLUME) == TARGET_FOES_AND_ALLY);
PLAYER(SPECIES_BISHARP);
PLAYER(SPECIES_BISHARP) { Item(ITEM_LEADERS_CREST); HP(1); }
OPPONENT(SPECIES_BISHARP) { Item(ITEM_LEADERS_CREST); HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_LAVA_PLUME); }
} SCENE {
HP_BAR(opponentLeft, hp: 0);
HP_BAR(playerRight, hp: 0);
} THEN {
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EVOLUTION_TRACKER), 2);
}
}
WILD_BATTLE_TEST("Evolution Tracker: Bisharp KO-ing a Bisharp that doesn't hold Leader's Crest doesn't increase tracker")
{
GIVEN {
PLAYER(SPECIES_BISHARP);
OPPONENT(SPECIES_BISHARP) { HP(1); }
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); }
} SCENE {
HP_BAR(opponent, hp: 0);
} THEN {
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EVOLUTION_TRACKER), 0);
}
}
WILD_BATTLE_TEST("Evolution Tracker: Bisharp KO-ing a non-Bisharp that holds Leader's Crest doesn't increase tracker")
{
u32 species;
PARAMETRIZE { species = SPECIES_WOBBUFFET; }
PARAMETRIZE { species = SPECIES_PAWNIARD; }
GIVEN {
PLAYER(SPECIES_BISHARP);
OPPONENT(species) { Item(ITEM_LEADERS_CREST); HP(1); }
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); }
} SCENE {
HP_BAR(opponent, hp: 0);
} THEN {
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EVOLUTION_TRACKER), 0);
}
}
WILD_BATTLE_TEST("Evolution Tracker: Pawniard KO-ing a Bisharp that holds Leader's Crest doesn't increase tracker")
{
GIVEN {
PLAYER(SPECIES_PAWNIARD);
OPPONENT(SPECIES_BISHARP) { Item(ITEM_LEADERS_CREST); HP(1); }
} WHEN {
TURN { MOVE(player, MOVE_SCRATCH); }
} SCENE {
HP_BAR(opponent, hp: 0);
} THEN {
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EVOLUTION_TRACKER), 0);
}
}
WILD_BATTLE_TEST("Evolution Tracker: Bisharp KO-ing eligible battler from contact effects doesn't increase tracker")
{
GIVEN {
ASSUME(GetItemHoldEffect(ITEM_ROCKY_HELMET) == HOLD_EFFECT_ROCKY_HELMET);
ASSUME(MoveMakesContact(MOVE_SCRATCH));
PLAYER(SPECIES_BISHARP) { Item(ITEM_ROCKY_HELMET); }
OPPONENT(SPECIES_BISHARP) { Item(ITEM_LEADERS_CREST); HP(1); }
} WHEN {
TURN { MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
HP_BAR(opponent, hp: 0);
} THEN {
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EVOLUTION_TRACKER), 0);
}
}
WILD_BATTLE_TEST("Evolution Tracker: Bisharp KO-ing eligible battler with passive damage doesn't increase tracker")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_LEECH_SEED) == EFFECT_LEECH_SEED);
PLAYER(SPECIES_BISHARP);
OPPONENT(SPECIES_BISHARP) { Item(ITEM_LEADERS_CREST); HP(1); }
} WHEN {
TURN { MOVE(player, MOVE_LEECH_SEED); }
} SCENE {
HP_BAR(opponent, hp: 0);
} THEN {
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EVOLUTION_TRACKER), 0);
}
}
// To be replaced with WILD_DOUBLE_BATTLE_TEST when that is made possible (also see TryUpdateEvolutionTracker)
DOUBLE_BATTLE_TEST("Evolution Tracker: Bisharp KO-ing eligible battler with bursting flames doesn't increase tracker")
{
GIVEN {
ASSUME(MoveHasAdditionalEffect(MOVE_FLAME_BURST, MOVE_EFFECT_FLAME_BURST));
PLAYER(SPECIES_BISHARP);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_BISHARP) { Item(ITEM_LEADERS_CREST); HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FLAME_BURST, target: opponentRight); }
} SCENE {
HP_BAR(opponentLeft, hp: 0);
} THEN {
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EVOLUTION_TRACKER), 0);
}
}

View File

@ -327,33 +327,6 @@ SINGLE_BATTLE_TEST("(TERA) Reflect Type fails if used by a Terastallized Pokemon
}
}
SINGLE_BATTLE_TEST("(TERA) Conversion fails if used by a Terastallized Pokemon")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { TeraType(TYPE_PSYCHIC); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CONVERSION, gimmick: GIMMICK_TERA); }
} SCENE {
MESSAGE("Wobbuffet used Conversion!");
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("(TERA) Conversion2 fails if used by a Terastallized Pokemon")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { TeraType(TYPE_PSYCHIC); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SCRATCH); }
TURN { MOVE(player, MOVE_CONVERSION_2, gimmick: GIMMICK_TERA); }
} SCENE {
MESSAGE("Wobbuffet used Conversion 2!");
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("(TERA) Reflect Type copies a Terastallized Pokemon's Tera Type")
{
GIVEN {
@ -506,26 +479,6 @@ SINGLE_BATTLE_TEST("(TERA) Revelation Dance uses a Stellar-type Pokemon's base t
}
}
#if B_UPDATED_CONVERSION_2 < GEN_5
SINGLE_BATTLE_TEST("(TERA) Conversion2 fails if last hit by a Stellar-type move")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { TeraType(TYPE_STELLAR); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TERA_BLAST, gimmick: GIMMICK_TERA); }
TURN { MOVE(opponent, MOVE_CONVERSION_2); }
} SCENE {
// turn 1
MESSAGE("Wobbuffet used Tera Blast!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TERA_BLAST, player);
// turn 2
MESSAGE("The opposing Wobbuffet used Conversion 2!");
MESSAGE("But it failed!");
}
}
#endif
SINGLE_BATTLE_TEST("(TERA) Roost does not remove Flying-type ground immunity when Terastallized into the Stellar type")
{
GIVEN {

View File

@ -151,7 +151,7 @@ SINGLE_BATTLE_TEST("White Herb wont have time to activate if it is knocked off o
}
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet returned its stats to normal using its White Herb!");
MESSAGE("Slugma returned its stats to normal using its White Herb!");
}
} THEN {
EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE - 1);
@ -176,7 +176,7 @@ SINGLE_BATTLE_TEST("White Herb wont have time to activate if Magician steals it"
MESSAGE("The opposing Fennekin stole Slugma's White Herb!");
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet returned its stats to normal using its White Herb!");
MESSAGE("Slugma returned its stats to normal using its White Herb!");
}
} THEN {
EXPECT(player->statStages[STAT_DEF] = DEFAULT_STAT_STAGE - 1);

View File

@ -8,3 +8,16 @@ TO_DO_BATTLE_TEST("Conversion fails if all the user's moves share types with the
TO_DO_BATTLE_TEST("Conversion changes the user's types to the one in the user's first slot (Gen 6+)");
TO_DO_BATTLE_TEST("Conversion can read the user's first move slot even if that move cannot be selected (Gen 6+)"); //Eg. Disable
TO_DO_BATTLE_TEST("Conversion can change the user's types to Conversion's type");
SINGLE_BATTLE_TEST("(TERA) Conversion fails if used by a Terastallized Pokemon")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { TeraType(TYPE_PSYCHIC); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CONVERSION, gimmick: GIMMICK_TERA); }
} SCENE {
MESSAGE("Wobbuffet used Conversion!");
MESSAGE("But it failed!");
}
}

View File

@ -3,10 +3,10 @@
TO_DO_BATTLE_TEST("Conversion 2's type change considers Inverse Battles");
#if B_UPDATED_CONVERSION_2 < GEN_5
SINGLE_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type that resists the last move that hit the user (Gen 3-4)")
SINGLE_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type that resists the last move that hit the user (Gen 1-4)")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_4);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -16,15 +16,16 @@ SINGLE_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type
MESSAGE("Wobbuffet used Ominous Wind!");
// turn 1
ONE_OF {
MESSAGE("The opposing Wobbuffet transformed into the Normal type!");
MESSAGE("The opposing Wobbuffet transformed into the Dark type!");
MESSAGE("The opposing Wobbuffet transformed into the Normal type!");
MESSAGE("The opposing Wobbuffet transformed into the Dark type!");
}
}
}
SINGLE_BATTLE_TEST("Conversion 2's type change considers Struggle to be Normal type (Gen 3-4)")
SINGLE_BATTLE_TEST("Conversion 2's type change considers Struggle to be Normal type (Gen 1-4)")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_4);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -35,18 +36,17 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers Struggle to be Normal t
MESSAGE("The opposing Wobbuffet used Struggle!");
// turn 2
ONE_OF {
MESSAGE("Wobbuffet transformed into the Steel type!");
MESSAGE("Wobbuffet transformed into the Rock type!");
MESSAGE("Wobbuffet transformed into the Ghost type!");
MESSAGE("Wobbuffet transformed into the Steel type!");
MESSAGE("Wobbuffet transformed into the Rock type!");
MESSAGE("Wobbuffet transformed into the Ghost type!");
}
}
}
#endif
#if B_UPDATED_CONVERSION_2 >= GEN_5
SINGLE_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type that resists the last used target's move (Gen 5+)")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_5);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -56,8 +56,8 @@ SINGLE_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type
MESSAGE("Wobbuffet used Ominous Wind!");
// turn 1
ONE_OF {
MESSAGE("The opposing Wobbuffet transformed into the Normal type!");
MESSAGE("The opposing Wobbuffet transformed into the Dark type!");
MESSAGE("The opposing Wobbuffet transformed into the Normal type!");
MESSAGE("The opposing Wobbuffet transformed into the Dark type!");
}
}
}
@ -65,6 +65,7 @@ SINGLE_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type
SINGLE_BATTLE_TEST("Conversion 2's type change considers status moves (Gen 5+)")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_5);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -75,8 +76,8 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers status moves (Gen 5+)")
MESSAGE("The opposing Wobbuffet used Curse!");
// turn 2
ONE_OF {
MESSAGE("Wobbuffet transformed into the Normal type!");
MESSAGE("Wobbuffet transformed into the Dark type!");
MESSAGE("Wobbuffet transformed into the Normal type!");
MESSAGE("Wobbuffet transformed into the Dark type!");
}
}
}
@ -84,6 +85,7 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers status moves (Gen 5+)")
SINGLE_BATTLE_TEST("Conversion 2's type change considers the type of moves called by other moves")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_5);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -94,8 +96,8 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers the type of moves calle
MESSAGE("The opposing Wobbuffet used Mirror Move!");
// turn 2
ONE_OF {
MESSAGE("Wobbuffet transformed into the Normal type!");
MESSAGE("Wobbuffet transformed into the Dark type!");
MESSAGE("Wobbuffet transformed into the Normal type!");
MESSAGE("Wobbuffet transformed into the Dark type!");
}
}
}
@ -103,6 +105,7 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers the type of moves calle
SINGLE_BATTLE_TEST("Conversion 2's type change considers dynamic type moves")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_5);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -113,10 +116,10 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers dynamic type moves")
MESSAGE("The opposing Wobbuffet used Weather Ball!");
// turn 2
ONE_OF {
MESSAGE("Wobbuffet transformed into the Steel type!");
MESSAGE("Wobbuffet transformed into the Fire type!");
MESSAGE("Wobbuffet transformed into the Water type!");
MESSAGE("Wobbuffet transformed into the Ice type!");
MESSAGE("Wobbuffet transformed into the Steel type!");
MESSAGE("Wobbuffet transformed into the Fire type!");
MESSAGE("Wobbuffet transformed into the Water type!");
MESSAGE("Wobbuffet transformed into the Ice type!");
}
}
}
@ -124,6 +127,7 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers dynamic type moves")
SINGLE_BATTLE_TEST("Conversion 2's type change considers move types changed by Normalize and Electrify")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_5);
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NORMALIZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -136,17 +140,17 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers move types changed by N
MESSAGE("The opposing Wobbuffet used Pound!");
// turn 2
ONE_OF {
MESSAGE("Wobbuffet transformed into the Ground type!");
MESSAGE("Wobbuffet transformed into the Dragon type!");
MESSAGE("Wobbuffet transformed into the Grass type!");
MESSAGE("Wobbuffet transformed into the Electric type!");
MESSAGE("Wobbuffet transformed into the Ground type!");
MESSAGE("Wobbuffet transformed into the Dragon type!");
MESSAGE("Wobbuffet transformed into the Grass type!");
MESSAGE("Wobbuffet transformed into the Electric type!");
}
// turn 3
MESSAGE("Wobbuffet used Water Gun!");
ONE_OF {
MESSAGE("The opposing Wobbuffet transformed into the Steel type!");
MESSAGE("The opposing Wobbuffet transformed into the Rock type!");
MESSAGE("The opposing Wobbuffet transformed into the Ghost type!");
MESSAGE("The opposing Wobbuffet transformed into the Steel type!");
MESSAGE("The opposing Wobbuffet transformed into the Rock type!");
MESSAGE("The opposing Wobbuffet transformed into the Ghost type!");
}
}
}
@ -154,6 +158,7 @@ SINGLE_BATTLE_TEST("Conversion 2's type change considers move types changed by N
SINGLE_BATTLE_TEST("Conversion 2's type change fails targeting Struggle (Gen 5+)")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_5);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -171,6 +176,7 @@ SINGLE_BATTLE_TEST("Conversion 2's type change fails targeting Struggle (Gen 5+)
SINGLE_BATTLE_TEST("Conversion 2 fails if the move used is of typeless damage (Gen 5+)")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_5);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_ENTEI);
} WHEN {
@ -187,7 +193,6 @@ SINGLE_BATTLE_TEST("Conversion 2 fails if the move used is of typeless damage (G
MESSAGE("But it failed!");
}
}
#endif
SINGLE_BATTLE_TEST("Conversion 2 fails if the targeted move is Stellar Type")
{
@ -205,3 +210,35 @@ SINGLE_BATTLE_TEST("Conversion 2 fails if the targeted move is Stellar Type")
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("Conversion 2 fails if used by a Terastallized Pokemon")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { TeraType(TYPE_PSYCHIC); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_CONVERSION_2, gimmick: GIMMICK_TERA); }
} SCENE {
MESSAGE("Wobbuffet used Conversion 2!");
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("Conversion 2 fails if last hit by a Stellar-type move (Gen 1-4)")
{
GIVEN {
WITH_CONFIG(CONFIG_UPDATED_CONVERSION_2, GEN_4);
PLAYER(SPECIES_WOBBUFFET) { TeraType(TYPE_STELLAR); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TERA_BLAST, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_CONVERSION_2); }
} SCENE {
// turn 1
MESSAGE("Wobbuffet used Tera Blast!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TERA_BLAST, player);
// turn 2
MESSAGE("The opposing Wobbuffet used Conversion 2!");
MESSAGE("But it failed!");
}
}

View File

@ -81,6 +81,7 @@ DOUBLE_BATTLE_TEST("Court Change swaps entry hazards used by the player")
DOUBLE_BATTLE_TEST("Court Change used by the player swaps Mist, Safeguard, Aurora Veil, Reflect, Light Screen, Tailwind")
{
GIVEN {
WITH_CONFIG(CONFIG_TAILWIND_TURNS, GEN_5);
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WYNAUT);
@ -119,6 +120,7 @@ DOUBLE_BATTLE_TEST("Court Change used by the player swaps Mist, Safeguard, Auror
DOUBLE_BATTLE_TEST("Court Change used by the opponent swaps Mist, Safeguard, Aurora Veil, Reflect, Light Screen, Tailwind")
{
GIVEN {
WITH_CONFIG(CONFIG_TAILWIND_TURNS, GEN_5);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
@ -246,4 +248,3 @@ AI_SINGLE_BATTLE_TEST("AI uses Court Change")
TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_COURT_CHANGE); }
}
}

View File

@ -50,12 +50,258 @@ SINGLE_BATTLE_TEST("Grudge does not deplete PP of a Z-Move")
}
}
TO_DO_BATTLE_TEST("Grudge depletes all PP from a Max Move's base move")
TO_DO_BATTLE_TEST("Grudge does not activate for Struggle")
TO_DO_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Move");
TO_DO_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Sleep");
TO_DO_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Paralysis");
TO_DO_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Flinching");
TO_DO_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Sandstorm");
TO_DO_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Leech Seed");
TO_DO_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Future Sight");
SINGLE_BATTLE_TEST("Grudge depletes all PP from a Max Move's base move")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_POUND, MOVE_SURF); Item(ITEM_LAGGING_TAIL); }
} WHEN {
TURN { MOVE(player, MOVE_GRUDGE); MOVE(opponent, MOVE_SCRATCH, gimmick: GIMMICK_DYNAMAX); SEND_OUT(player, 1); }
} SCENE {
MESSAGE("Wobbuffet used Grudge!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
MESSAGE("The opposing Wobbuffet used Max Strike!");
MESSAGE("Wobbuffet fainted!");
MESSAGE("The opposing Wobbuffet's Scratch lost all its PP due to the grudge!");
} THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_EQ(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}
SINGLE_BATTLE_TEST("Grudge does not activate for Struggle")
{
GIVEN {
PLAYER (SPECIES_WOBBUFFET) { HP(1); }
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_STRUGGLE, MOVE_POUND, MOVE_SURF); };
}
WHEN {
TURN { MOVE(player, MOVE_GRUDGE); MOVE(opponent, MOVE_STRUGGLE); SEND_OUT(player, 1); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, opponent);
MESSAGE("Wobbuffet fainted!");
NOT MESSAGE("The opposing Wobbuffet's Struggle lost all its PP due to the grudge!");
}
THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_GT(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}
SINGLE_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Move")
{
GIVEN {
PLAYER (SPECIES_WOBBUFFET) { HP(1); }
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_POUND, MOVE_SURF); };
}
WHEN {
TURN { MOVE(player, MOVE_GRUDGE); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SCRATCH); SEND_OUT(player, 1); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
MESSAGE("Wobbuffet fainted!");
NOT MESSAGE("The opposing Wobbuffet's Scratch lost all its PP due to the grudge!");
}
THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_GT(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}
SINGLE_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Sleep")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS);
ASSUME(gMovesInfo[SanitizeMoveId(MOVE_SPORE)].argument.nonVolatileStatus == MOVE_EFFECT_SLEEP);
PLAYER (SPECIES_WOBBUFFET) { HP(1);}
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_VITAL_THROW, MOVE_SPORE, MOVE_SURF); }
}
WHEN {
TURN { MOVE(player, MOVE_GRUDGE); MOVE(opponent, MOVE_SPORE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_VITAL_THROW); SEND_OUT(player, 1); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player);
MESSAGE("Wobbuffet fell asleep!");
STATUS_ICON(player, sleep: TRUE);
MESSAGE("Wobbuffet is fast asleep.");
ANIMATION(ANIM_TYPE_MOVE, MOVE_VITAL_THROW, opponent);
MESSAGE("Wobbuffet fainted!");
NOT MESSAGE("The opposing Wobbuffet's Scratch lost all its PP due to the grudge!");
}
THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_GT(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}
SINGLE_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Paralysis")
{
PASSES_RANDOMLY(25, 100, RNG_PARALYSIS);
GIVEN {
ASSUME(GetMoveEffect(MOVE_STUN_SPORE) == EFFECT_NON_VOLATILE_STATUS);
ASSUME(gMovesInfo[SanitizeMoveId(MOVE_STUN_SPORE)].argument.nonVolatileStatus == MOVE_EFFECT_PARALYSIS);
ASSUME(GetMovePriority(MOVE_VITAL_THROW) == -1);
PLAYER (SPECIES_WOBBUFFET) { HP(1);}
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_VITAL_THROW, MOVE_STUN_SPORE, MOVE_SURF); };\
}
WHEN {
TURN { MOVE(player, MOVE_GRUDGE); MOVE(opponent, MOVE_STUN_SPORE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_VITAL_THROW); SEND_OUT(player, 1); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, opponent);
MESSAGE("Wobbuffet is paralyzed, so it may be unable to move!");
STATUS_ICON(player, paralysis: TRUE);
MESSAGE("Wobbuffet couldn't move because it's paralyzed!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_VITAL_THROW, opponent);
MESSAGE("Wobbuffet fainted!");
NOT MESSAGE("The opposing Wobbuffet's Scratch lost all its PP due to the grudge!");
}
THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_GT(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}
SINGLE_BATTLE_TEST("Grudge's effect disappears if the user takes a new turn - Flinching")
{
PASSES_RANDOMLY(10, 100, RNG_HOLD_EFFECT_FLINCH);
GIVEN {
ASSUME(GetMoveEffect(MOVE_FALSE_SWIPE) == EFFECT_FALSE_SWIPE);
PLAYER (SPECIES_WOBBUFFET) { HP(1); }
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_FALSE_SWIPE, MOVE_SURF); Item(ITEM_KINGS_ROCK); }
}
WHEN {
TURN { SWITCH(opponent, 1); MOVE(player, MOVE_GRUDGE); }
TURN { MOVE(opponent, MOVE_FALSE_SWIPE); MOVE(player, MOVE_CELEBRATE); }
TURN { MOVE(opponent, MOVE_SCRATCH); MOVE(player, MOVE_CELEBRATE); SEND_OUT(player, 1); }
}
SCENE {
SEND_IN_MESSAGE("Wobbuffet");
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, opponent);
MESSAGE("Wobbuffet flinched and couldn't move!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
MESSAGE("Wobbuffet fainted!");
NOT MESSAGE("The opposing Wobbuffet's Scratch lost all its PP due to the grudge!");
}
THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_GT(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}
SINGLE_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Sandstorm")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SANDSTORM) == EFFECT_SANDSTORM);
PLAYER (SPECIES_WOBBUFFET) { HP(1); }
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_SANDSTORM, MOVE_SURF); }
}
WHEN {
TURN { MOVE(player, MOVE_GRUDGE); MOVE(opponent, MOVE_SANDSTORM); SEND_OUT(player, 1); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SANDSTORM, opponent);
MESSAGE("The sandstorm is raging.");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SANDSTORM_CONTINUES);
MESSAGE("Wobbuffet is buffeted by the sandstorm!");
MESSAGE("Wobbuffet fainted!");
NOT MESSAGE("The opposing Wobbuffet's Sandstorm lost all its PP due to the grudge!");
}
THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_GT(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}
SINGLE_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Leech Seed")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_LEECH_SEED) == EFFECT_LEECH_SEED);
PLAYER (SPECIES_WOBBUFFET) { HP(1); }
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_LEECH_SEED, MOVE_SURF); }
}
WHEN {
TURN { MOVE(player, MOVE_GRUDGE); MOVE(opponent, MOVE_LEECH_SEED); SEND_OUT(player, 1); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, opponent);
MESSAGE("Wobbuffet was seeded!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_LEECH_SEED_DRAIN, player);
MESSAGE("Wobbuffet fainted!");
NOT MESSAGE("The opposing Wobbuffet's Leech Seed lost all its PP due to the grudge!");
}
THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_GT(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}
SINGLE_BATTLE_TEST("Grudge's effect doesn't trigger on indirect damage - Future Sight")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_FUTURE_SIGHT) == EFFECT_FUTURE_SIGHT);
PLAYER (SPECIES_WOBBUFFET) { HP(1); }
PLAYER (SPECIES_WOBBUFFET);
OPPONENT (SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_FUTURE_SIGHT, MOVE_SURF); }
}
WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_FUTURE_SIGHT); }
TURN {}
TURN { MOVE(player, MOVE_GRUDGE); SEND_OUT(player, 1); }
}
SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, opponent);
MESSAGE("The opposing Wobbuffet foresaw an attack!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRUDGE, player);
MESSAGE("Wobbuffet took the Future Sight attack!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FUTURE_SIGHT_HIT);
MESSAGE("Wobbuffet fainted!");
NOT MESSAGE("The opposing Wobbuffet's Future Sight lost all its PP due to the grudge!");
}
THEN {
EXPECT_GT(opponent->pp[0], 0);
EXPECT_GT(opponent->pp[1], 0);
EXPECT_GT(opponent->pp[2], 0);
EXPECT_GT(opponent->pp[3], 0);
}
}

View File

@ -322,3 +322,28 @@ DOUBLE_BATTLE_TEST("Instructed move will be redirected by Rage Powder after inst
HP_BAR(opponentLeft);
}
}
DOUBLE_BATTLE_TEST("Instruct message references the correct battlers")
{
GIVEN {
PLAYER(SPECIES_TREECKO);
PLAYER(SPECIES_SCEPTILE);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN {
MOVE(playerLeft, MOVE_CELEBRATE);
MOVE(playerRight, MOVE_SCRATCH, target: opponentLeft);
MOVE(opponentLeft, MOVE_DRAGON_DARTS, target:playerLeft);
MOVE(opponentRight, MOVE_INSTRUCT, target: playerRight);
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerRight);
MESSAGE("The opposing Wynaut used Instruct!");
NONE_OF {
MESSAGE("Sceptile followed the opposing Wobbuffet's instructions!");
}
MESSAGE("Sceptile followed the opposing Wynaut's instructions!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerRight);
}
}

View File

@ -1,4 +1,20 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Mimic doesn't error when the last move used by the target resolves to MOVE_UNAVAILABLE")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {MOVE(opponent, MOVE_TRANSFORM); MOVE(player, MOVE_MIMIC); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRANSFORM, opponent);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MIMIC, player);
} THEN {
EXPECT_EQ(gLastMoves[1], MOVE_UNAVAILABLE); // This test depends on the current implementation of Transform, if this changes, the test should be changed
}
}
TO_DO_BATTLE_TEST("TODO: Write Mimic (Move Effect) test titles")

View File

@ -3,11 +3,15 @@
TO_DO_BATTLE_TEST("TODO: Write Mud Sport (Move Effect) test titles")
SINGLE_BATTLE_TEST("Mud Sport reduces the damage of Electric Type moves by 67% (Gen5+)")
SINGLE_BATTLE_TEST("Mud Sport reduces the damage of Electric Type moves by 50% (Gen3-4) or 67% (Gen5+)")
{
u32 config;
s16 playerDmg[2];
s16 opponentDmg[2];
PARAMETRIZE { config = GEN_4; }
PARAMETRIZE { config = GEN_5; }
GIVEN {
WITH_CONFIG(CONFIG_SPORT_DMG_REDUCTION, config);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -28,7 +32,13 @@ SINGLE_BATTLE_TEST("Mud Sport reduces the damage of Electric Type moves by 67% (
HP_BAR(player, captureDamage: &playerDmg[1]);
} THEN {
EXPECT_MUL_EQ(opponentDmg[0], Q_4_12(0.33), opponentDmg[1]);
EXPECT_MUL_EQ(playerDmg[0], Q_4_12(0.33), playerDmg[1]);
if (config >= GEN_5) {
EXPECT_MUL_EQ(opponentDmg[0], Q_4_12(0.33), opponentDmg[1]);
EXPECT_MUL_EQ(playerDmg[0], Q_4_12(0.33), playerDmg[1]);
}
else {
EXPECT_MUL_EQ(opponentDmg[0], Q_4_12(0.5), opponentDmg[1]);
EXPECT_MUL_EQ(playerDmg[0], Q_4_12(0.5), playerDmg[1]);
}
}
}

View File

@ -6,10 +6,13 @@ ASSUMPTIONS
ASSUME(GetMoveEffect(MOVE_TAILWIND) == EFFECT_TAILWIND);
}
SINGLE_BATTLE_TEST("Tailwind applies for 4 turns")
SINGLE_BATTLE_TEST("Tailwind applies for 3 turns (Gen4) or 4 turns (Gen5+)")
{
u32 config;
PARAMETRIZE { config = GEN_4; }
PARAMETRIZE { config = GEN_5; }
GIVEN {
ASSUME(B_TAILWIND_TURNS >= GEN_5);
WITH_CONFIG(CONFIG_TAILWIND_TURNS, config);
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(15); }
} WHEN {
@ -28,8 +31,10 @@ SINGLE_BATTLE_TEST("Tailwind applies for 4 turns")
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("The opposing Wobbuffet used Celebrate!");
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("The opposing Wobbuffet used Celebrate!");
if (config >= GEN_5) {
MESSAGE("Wobbuffet used Celebrate!");
MESSAGE("The opposing Wobbuffet used Celebrate!");
}
MESSAGE("The opposing Wobbuffet used Celebrate!");
MESSAGE("Wobbuffet used Celebrate!");

View File

@ -3,11 +3,15 @@
TO_DO_BATTLE_TEST("TODO: Write Water Sport (Move Effect) test titles")
SINGLE_BATTLE_TEST("Water Sport reduces the damage of Fire Type moves by 67% (Gen5+)")
SINGLE_BATTLE_TEST("Water Sport reduces the damage of Fire Type moves by 50% (Gen3-4) or 67% (Gen5+)")
{
u32 config;
s16 playerDmg[2];
s16 opponentDmg[2];
PARAMETRIZE { config = GEN_4; }
PARAMETRIZE { config = GEN_5; }
GIVEN {
WITH_CONFIG(CONFIG_SPORT_DMG_REDUCTION, config);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -28,7 +32,13 @@ SINGLE_BATTLE_TEST("Water Sport reduces the damage of Fire Type moves by 67% (Ge
HP_BAR(player, captureDamage: &playerDmg[1]);
} THEN {
EXPECT_MUL_EQ(opponentDmg[0], Q_4_12(0.33), opponentDmg[1]);
EXPECT_MUL_EQ(playerDmg[0], Q_4_12(0.33), playerDmg[1]);
if (config >= GEN_5) {
EXPECT_MUL_EQ(opponentDmg[0], Q_4_12(0.33), opponentDmg[1]);
EXPECT_MUL_EQ(playerDmg[0], Q_4_12(0.33), playerDmg[1]);
}
else {
EXPECT_MUL_EQ(opponentDmg[0], Q_4_12(0.5), opponentDmg[1]);
EXPECT_MUL_EQ(playerDmg[0], Q_4_12(0.5), playerDmg[1]);
}
}
}

View File

@ -6,10 +6,14 @@ ASSUMPTIONS
ASSUME(MoveHasAdditionalEffect(MOVE_WRAP, MOVE_EFFECT_WRAP));
}
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 5 turns 50% of the time")
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 5 turns 25% (Gen3-4) or 50% (Gen5+) of the time")
{
PASSES_RANDOMLY(50, 100, RNG_WRAP);
u32 config, passes, trials;
PARAMETRIZE { config = GEN_4; passes = 25; trials = 100; }
PARAMETRIZE { config = GEN_5; passes = 50; trials = 100; }
PASSES_RANDOMLY(passes, trials, RNG_WRAP);
GIVEN {
WITH_CONFIG(CONFIG_BINDING_TURNS, config);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -32,10 +36,14 @@ SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 5 turns 50% of the time"
}
}
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 4 turns 50% of the time")
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 4 turns 25% (Gen3-4) or 50% (Gen5+) of the time")
{
PASSES_RANDOMLY(50, 100, RNG_WRAP);
u32 config, passes, trials;
PARAMETRIZE { config = GEN_4; passes = 25; trials = 100; }
PARAMETRIZE { config = GEN_5; passes = 50; trials = 100; }
PASSES_RANDOMLY(passes, trials, RNG_WRAP);
GIVEN {
WITH_CONFIG(CONFIG_BINDING_TURNS, config);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -56,9 +64,13 @@ SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 4 turns 50% of the time"
}
}
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon 7 turns while holding a Grip Claw")
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon 5 turns (Gen4) or 7 turns (Gen5+) while holding a Grip Claw")
{
u32 config;
PARAMETRIZE { config = GEN_4; }
PARAMETRIZE { config = GEN_5; }
GIVEN {
WITH_CONFIG(CONFIG_BINDING_TURNS, config);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRIP_CLAW); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -79,8 +91,10 @@ SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon 7 turns while holding a Grip
HP_BAR(opponent); // Residual Damage
HP_BAR(opponent); // Residual Damage
HP_BAR(opponent); // Residual Damage
HP_BAR(opponent); // Residual Damage
HP_BAR(opponent); // Residual Damage
if (config >= GEN_5) {
HP_BAR(opponent); // Residual Damage
HP_BAR(opponent); // Residual Damage
}
NOT HP_BAR(opponent); // Residual Damage
}
}

View File

@ -80,3 +80,17 @@ SINGLE_BATTLE_TEST("Changing forms doesn't overwrite set stats (HP)")
EXPECT_EQ(player->maxHP, 10);
}
}
MULTI_BATTLE_TEST("Multi Battle Tests register partner's status1")
{
GIVEN {
MULTI_PLAYER(SPECIES_WOBBUFFET);
MULTI_PARTNER(SPECIES_WOBBUFFET);
MULTI_OPPONENT_A(SPECIES_WOBBUFFET);
MULTI_OPPONENT_B(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_WILL_O_WISP, target: playerRight); }
} SCENE {
STATUS_ICON(playerRight, STATUS1_BURN);
}
}

View File

@ -1,17 +1,249 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers") // Electric, Ice, Rock
TO_DO_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers - Inverse Battle") // Bug, Fighting, Grass
TO_DO_BATTLE_TEST("Strong winds don't affect Stealth Rock's damage")
TO_DO_BATTLE_TEST("Strong winds makes Sunny Day fail")
TO_DO_BATTLE_TEST("Strong winds makes Rain Dance fail")
TO_DO_BATTLE_TEST("Strong winds makes Sandstorm fail")
TO_DO_BATTLE_TEST("Strong winds makes Hail fail")
TO_DO_BATTLE_TEST("Strong winds makes Snowscape fail") // Extrapolation
TO_DO_BATTLE_TEST("Strong winds makes Drought fail to activate")
TO_DO_BATTLE_TEST("Strong winds makes Drizzle fail to activate")
TO_DO_BATTLE_TEST("Strong winds makes Sand Stream fail to activate")
TO_DO_BATTLE_TEST("Strong winds makes Snow Warning fail to activate")
TO_DO_BATTLE_TEST("Strong winds can be replaced by Desolate Land")
TO_DO_BATTLE_TEST("Strong winds can be replaced by Primordial Sea")
DOUBLE_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers") // Electric, Ice, Rock
{
u16 move;
bool32 targetPlayer;
PARAMETRIZE { move = MOVE_THUNDER_SHOCK; targetPlayer = TRUE; }
PARAMETRIZE { move = MOVE_ICE_BEAM; targetPlayer = TRUE; }
PARAMETRIZE { move = MOVE_ROCK_THROW; targetPlayer = TRUE; }
PARAMETRIZE { move = MOVE_THUNDER_SHOCK; targetPlayer = FALSE; }
PARAMETRIZE { move = MOVE_ICE_BEAM; targetPlayer = FALSE; }
PARAMETRIZE { move = MOVE_ROCK_THROW; targetPlayer = FALSE; }
GIVEN {
ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC);
ASSUME(GetMoveType(MOVE_ICE_BEAM) == TYPE_ICE);
ASSUME(GetMoveType(MOVE_ROCK_THROW) == TYPE_ROCK);
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_NORMAL);
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
PLAYER(SPECIES_PIDGEY);
OPPONENT(SPECIES_PIDGEY);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (targetPlayer)
TURN { MOVE(opponentLeft, move, target: playerRight); }
else
TURN { MOVE(playerRight, move, target: opponentLeft); }
} SCENE {
if (targetPlayer) {
if (move == MOVE_THUNDER_SHOCK)
MESSAGE("The opposing Pidgey used Thunder Shock!");
else if (move == MOVE_ICE_BEAM)
MESSAGE("The opposing Pidgey used Ice Beam!");
else
MESSAGE("The opposing Pidgey used Rock Throw!");
MESSAGE("The mysterious strong winds weakened the attack!");
ANIMATION(ANIM_TYPE_MOVE, move, opponentLeft);
} else {
if (move == MOVE_THUNDER_SHOCK)
MESSAGE("Pidgey used Thunder Shock!");
else if (move == MOVE_ICE_BEAM)
MESSAGE("Pidgey used Ice Beam!");
else
MESSAGE("Pidgey used Rock Throw!");
MESSAGE("The mysterious strong winds weakened the attack!");
ANIMATION(ANIM_TYPE_MOVE, move, playerRight);
}
}
}
DOUBLE_BATTLE_TEST("Strong winds remove Flying-type weaknesses of all battlers - Inverse Battle", s16 damagePlayer, s16 damageOpponent) // Bug, Fighting, Grass
{
u16 move;
bool32 strongWinds;
PARAMETRIZE { move = MOVE_BUG_BITE; strongWinds = FALSE; }
PARAMETRIZE { move = MOVE_BUG_BITE; strongWinds = TRUE; }
PARAMETRIZE { move = MOVE_KARATE_CHOP; strongWinds = FALSE; }
PARAMETRIZE { move = MOVE_KARATE_CHOP; strongWinds = TRUE; }
PARAMETRIZE { move = MOVE_VINE_WHIP; strongWinds = FALSE; }
PARAMETRIZE { move = MOVE_VINE_WHIP; strongWinds = TRUE; }
GIVEN {
FLAG_SET(B_FLAG_INVERSE_BATTLE);
ASSUME(GetMoveType(MOVE_BUG_BITE) == TYPE_BUG);
ASSUME(GetMoveType(MOVE_KARATE_CHOP) == TYPE_FIGHTING);
ASSUME(GetMoveType(MOVE_VINE_WHIP) == TYPE_GRASS);
ASSUME(GetSpeciesType(SPECIES_TORNADUS, 0) == TYPE_FLYING);
ASSUME(GetSpeciesType(SPECIES_TORNADUS, 1) == TYPE_FLYING);
if (strongWinds)
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
else
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_TORNADUS);
OPPONENT(SPECIES_TORNADUS);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(opponentLeft, move, target: playerRight);
MOVE(playerRight, move, target: opponentLeft);
}
} SCENE {
HP_BAR(playerRight, captureDamage: &results[i].damagePlayer);
HP_BAR(opponentLeft, captureDamage: &results[i].damageOpponent);
} FINALLY {
EXPECT_GT(results[0].damagePlayer, results[1].damagePlayer);
EXPECT_GT(results[0].damageOpponent, results[1].damageOpponent);
EXPECT_GT(results[2].damagePlayer, results[3].damagePlayer);
EXPECT_GT(results[2].damageOpponent, results[3].damageOpponent);
EXPECT_GT(results[4].damagePlayer, results[5].damagePlayer);
EXPECT_GT(results[4].damageOpponent, results[5].damageOpponent);
}
}
SINGLE_BATTLE_TEST("Strong winds prevent Weakness Policy from activating on Flying-type weaknesses")
{
GIVEN {
ASSUME(GetItemHoldEffect(ITEM_WEAKNESS_POLICY) == HOLD_EFFECT_WEAKNESS_POLICY);
ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC);
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_NORMAL);
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); Moves(MOVE_THUNDER_SHOCK); }
OPPONENT(SPECIES_PIDGEY) { Item(ITEM_WEAKNESS_POLICY); }
} WHEN {
TURN { MOVE(player, MOVE_THUNDER_SHOCK); }
} SCENE {
MESSAGE("Rayquaza used Thunder Shock!");
MESSAGE("The mysterious strong winds weakened the attack!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, player);
HP_BAR(opponent);
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
}
}
SINGLE_BATTLE_TEST("Anticipation still triggers with Strong Winds active")
{
GIVEN {
ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC);
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_NORMAL);
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); Moves(MOVE_THUNDER_SHOCK, MOVE_CELEBRATE); }
OPPONENT(SPECIES_PIDGEY) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_CELEBRATE); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_ANTICIPATION);
MESSAGE("Rayquaza used Celebrate!");
MESSAGE("The opposing Pidgey used Celebrate!");
}
}
SINGLE_BATTLE_TEST("Anticipation still triggers with Strong Winds active in Inverse Battle")
{
GIVEN {
FLAG_SET(B_FLAG_INVERSE_BATTLE);
ASSUME(GetMoveType(MOVE_VINE_WHIP) == TYPE_GRASS);
ASSUME(GetSpeciesType(SPECIES_TORNADUS, 0) == TYPE_FLYING);
ASSUME(GetSpeciesType(SPECIES_TORNADUS, 1) == TYPE_FLYING);
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); Moves(MOVE_VINE_WHIP, MOVE_CELEBRATE); }
OPPONENT(SPECIES_TORNADUS) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_CELEBRATE); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_ANTICIPATION);
MESSAGE("Rayquaza used Celebrate!");
MESSAGE("The opposing Tornadus used Celebrate!");
}
}
SINGLE_BATTLE_TEST("Strong winds don't affect Stealth Rock's damage")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_STEALTH_ROCK) == EFFECT_STEALTH_ROCK);
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 0) == TYPE_NORMAL);
ASSUME(GetSpeciesType(SPECIES_PIDGEY, 1) == TYPE_FLYING);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_PIDGEY);
OPPONENT(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
} WHEN {
TURN { MOVE(opponent, MOVE_STEALTH_ROCK); }
TURN { SWITCH(player, 1); }
} SCENE {
s32 maxHP = GetMonData(&PLAYER_PARTY[1], MON_DATA_MAX_HP);
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
HP_BAR(player, damage: maxHP / 4);
}
}
SINGLE_BATTLE_TEST("Strong winds block weather-setting moves")
{
u16 move;
PARAMETRIZE { move = MOVE_SUNNY_DAY; }
PARAMETRIZE { move = MOVE_RAIN_DANCE; }
PARAMETRIZE { move = MOVE_SANDSTORM; }
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_SUNNY_DAY) == EFFECT_SUNNY_DAY);
ASSUME(GetMoveEffect(MOVE_RAIN_DANCE) == EFFECT_RAIN_DANCE);
ASSUME(GetMoveEffect(MOVE_SANDSTORM) == EFFECT_SANDSTORM);
ASSUME(GetMoveEffect(MOVE_HAIL) == EFFECT_HAIL);
ASSUME(GetMoveEffect(MOVE_SNOWSCAPE) == EFFECT_SNOWSCAPE);
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent);
} THEN {
EXPECT(gBattleWeather & B_WEATHER_STRONG_WINDS);
}
}
SINGLE_BATTLE_TEST("Strong winds prevent other weather abilities")
{
u16 ability, species;
PARAMETRIZE { ability = ABILITY_DROUGHT; species = SPECIES_NINETALES; }
PARAMETRIZE { ability = ABILITY_DRIZZLE; species = SPECIES_POLITOED; }
PARAMETRIZE { ability = ABILITY_SAND_STREAM; species = SPECIES_HIPPOWDON; }
PARAMETRIZE { ability = ABILITY_SNOW_WARNING; species = SPECIES_ABOMASNOW; }
GIVEN {
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(species) { Ability(ability); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ability);
} THEN {
EXPECT(gBattleWeather & B_WEATHER_STRONG_WINDS);
}
}
SINGLE_BATTLE_TEST("Strong winds can be replaced by Desolate Land")
{
GIVEN {
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_DESOLATE_LAND);
MESSAGE("The sunlight turned extremely harsh!");
} THEN {
EXPECT(gBattleWeather & B_WEATHER_SUN_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Strong winds can be replaced by Primordial Sea")
{
GIVEN {
PLAYER(SPECIES_RAYQUAZA) { Ability(ABILITY_DELTA_STREAM); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
} WHEN {
TURN { SWITCH(opponent, 1); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_PRIMORDIAL_SEA);
MESSAGE("A heavy rain began to fall!");
} THEN {
EXPECT(gBattleWeather & B_WEATHER_RAIN_PRIMAL);
}
}

View File

@ -3376,9 +3376,9 @@ void ValidateFinally(u32 sourceLine)
INVALID_IF(STATE->parametersCount == 0, "FINALLY without PARAMETRIZE");
}
u32 TestRunner_Battle_GetForcedAbility(u32 side, u32 partyIndex)
u32 TestRunner_Battle_GetForcedAbility(u32 array, u32 partyIndex)
{
return DATA.forcedAbilities[side][partyIndex];
return DATA.forcedAbilities[array][partyIndex];
}
u32 TestRunner_Battle_GetForcedEnvironment(void)

View File

@ -1,6 +1,7 @@
#include "global.h"
#include "test/battle.h"
#include "test/test.h"
#include "test/battle.h"
TEST("Tests resume after CRASH")
{
@ -9,6 +10,25 @@ TEST("Tests resume after CRASH")
f();
}
MULTI_BATTLE_TEST("Forced Abilities are set correctly in multi battle tests")
{
GIVEN {
MULTI_PLAYER(SPECIES_WOBBUFFET);
MULTI_PARTNER(SPECIES_WOBBUFFET);
MULTI_PARTNER(SPECIES_NINETALES_ALOLA) { Ability(ABILITY_DRIZZLE); }
MULTI_OPPONENT_A(SPECIES_WOBBUFFET);
MULTI_OPPONENT_A(SPECIES_NINETALES_ALOLA) { Ability(ABILITY_SAND_STREAM); }
MULTI_OPPONENT_B(SPECIES_WYNAUT);
MULTI_OPPONENT_B(SPECIES_NINETALES_ALOLA) { Ability(ABILITY_DROUGHT); }
} WHEN {
TURN { SWITCH(opponentLeft, 1); SWITCH(playerRight, 4); SWITCH(opponentRight, 4); }
} SCENE {
ABILITY_POPUP(opponentLeft, ABILITY_SAND_STREAM);
ABILITY_POPUP(playerRight, ABILITY_DRIZZLE);
ABILITY_POPUP(opponentRight, ABILITY_DROUGHT);
}
}
SINGLE_BATTLE_TEST("Substitute hits are detected by SUB_HIT")
{
GIVEN {