Merge branch '_RHH/master' into _RHH/upcoming

This commit is contained in:
Eduardo Quezada 2025-01-01 18:34:42 -03:00
commit a50c78bb1e
51 changed files with 686 additions and 314 deletions

View file

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.10.0 (Latest release)
- 1.10.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
- 1.10.0
- 1.9.4
- 1.9.3
- 1.9.2

View file

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.10.0 (Latest release)
- 1.10.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
- 1.10.0
- 1.9.4
- 1.9.3
- 1.9.2

View file

@ -23,9 +23,10 @@ body:
label: Version
description: What version of pokeemerald-expansion are you using as a base?
options:
- 1.10.0 (Latest release)
- 1.10.1 (Latest release)
- master (default, unreleased bugfixes)
- upcoming (Edge)
- 1.10.0
- 1.9.4
- 1.9.3
- 1.9.2

View file

@ -1,6 +1,7 @@
# Pokeemerald-Expansion Changelogs
## 1.10.x
- **[Version 1.10.1](docs/changelogs/1.10.x/1.10.1.md) - 🧹 Bugfix Release**
- **[Version 1.10.0](docs/changelogs/1.10.x/1.10.0.md) - ✨ Feature Release**
## 1.9.x

View file

@ -10,7 +10,7 @@ The main advantage of using vanilla pokeemerald as a base is being able to link
If you use pokeemerald-expansion in your hack, please add RHH (Rom Hacking Hideout) to your credits list. Optionally, you can list the version used, so it can help players know what features to expect.
You can phrase it as the following:
```
Based off RHH's pokeemerald-expansion 1.10.0 https://github.com/rh-hideout/pokeemerald-expansion/
Based off RHH's pokeemerald-expansion 1.10.1 https://github.com/rh-hideout/pokeemerald-expansion/
```
#### Important: DO NOT use GitHub's "Download Zip" option. Using this option will not download the commit history required to update your expansion version or merge other feature branches. Instead, please read [this guide](https://github.com/Pawkkie/Team-Aquas-Asset-Repo/wiki/The-Basics-of-GitHub) to learn how to fork the repository and clone locally from there.

View file

@ -9604,13 +9604,6 @@ BattleScript_EjectPackActivates::
jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd
goto BattleScript_EjectPackActivate_Ret
BattleScript_EjectPackMissesTiming::
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_EJECTBUTTONACTIVATE
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
return
BattleScript_DarkTypePreventsPrankster::
attackstring
ppreduce

View file

@ -20,6 +20,7 @@
- [How to use the Testing System](tutorials/how_to_testing_system.md)
- [Changelog](./CHANGELOG.md)
- [1.10.x]()
- [Version 1.10.1](changelogs/1.10.x/1.10.1.md)
- [Version 1.10.0](changelogs/1.10.x/1.10.0.md)
- [1.9.x]()
- [Version 1.9.4](changelogs/1.9.x/1.9.4.md)

View file

@ -0,0 +1,140 @@
# Version 1.10.1
```md
## How to update
- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`.
- Once you have your remote set up, run the command `git pull RHH expansion/1.10.1`.
```
## 🧬 General 🧬
### Added
* Added `FONT_SHORT_NARROWER` by @AsparagusEduardo (commit originally by @agsmgmaster64) in [#5101](https://github.com/rh-hideout/pokeemerald-expansion/pull/5101)
* Narrower font tweaks and font fitting fixes by @kittenchilly in [#5782](https://github.com/rh-hideout/pokeemerald-expansion/pull/5782)
### Changed
* Adds Thief/Covet config to send stolen item to bag and Pickup config to pickup user's item in wild battles by @PhallenTree in [#5829](https://github.com/rh-hideout/pokeemerald-expansion/pull/5829)
### Fixed
* trainerproc: Fix showing incorrect error context by @mrgriffin in [#5769](https://github.com/rh-hideout/pokeemerald-expansion/pull/5769)
* Fixes UB in caps.c by @AlexOn1ine in [#5878](https://github.com/rh-hideout/pokeemerald-expansion/pull/5878)
## 🗺️ Overworld 🗺️
### Fixed
* Fix Off-by-One Error in Move Relearner by @iriv24 and @luckytyphlosion in [#5778](https://github.com/rh-hideout/pokeemerald-expansion/pull/5778)
* Fix HGSS dex sort orders working incorrectly by @ravepossum in [#5790](https://github.com/rh-hideout/pokeemerald-expansion/pull/5790)
* Egg cycle length fix by @hedara90 and @/BolaDeQueijo on discord discovered the issue. in [#5828](https://github.com/rh-hideout/pokeemerald-expansion/pull/5828)
* Fixed givemon not respecting perfect IVs for species by @AsparagusEduardo in [#5873](https://github.com/rh-hideout/pokeemerald-expansion/pull/5873)
- Also removed redundant `RemoveIVIndexFromList` function in `src/daycare.c`, so it uses `src/pokemon.c`'s instead
* Fix Script Scrollable Multichoice Arrow Positions by @ghoulslash in [#5884](https://github.com/rh-hideout/pokeemerald-expansion/pull/5884)
## 🐉 Pokémon 🐉
### Changed
* Updated Ogerpon, Enamorus and Sinistcha sprites by @kittenchilly in [#5793](https://github.com/rh-hideout/pokeemerald-expansion/pull/5793)
* New Enamorus-Incarnate sprite by @kittenchilly in [#5797](https://github.com/rh-hideout/pokeemerald-expansion/pull/5797)
### Fixed
* Fixes Wormadam define for teachable learnset script by @AlexOn1ine in [#5783](https://github.com/rh-hideout/pokeemerald-expansion/pull/5783)
* Fix "PlantCloak" references by @AsparagusEduardo in [#5821](https://github.com/rh-hideout/pokeemerald-expansion/pull/5821)
* Misc pokemon sprite fixes by @Cafeei in [#5846](https://github.com/rh-hideout/pokeemerald-expansion/pull/5846)
## ⚔️ Battle General ⚔️
### Changed
* Adds Thief/Covet config to send stolen item to bag and Pickup config to pickup user's item in wild battles by @PhallenTree in [#5829](https://github.com/rh-hideout/pokeemerald-expansion/pull/5829)
### Fixed
* Fixes items preventing other switch in effects by @AlexOn1ine in [#5732](https://github.com/rh-hideout/pokeemerald-expansion/pull/5732)
* Fix Pokemon with No Guard failing OHKO Moves into Semi-Invulnerable Pokemon by @iriv24 and @Cafeei in [#5779](https://github.com/rh-hideout/pokeemerald-expansion/pull/5779)
* Fix move category and category icon when PSS is off by @ravepossum in [#5786](https://github.com/rh-hideout/pokeemerald-expansion/pull/5786)
* Added the missing config to use new terrains by @hedara90 in [#5792](https://github.com/rh-hideout/pokeemerald-expansion/pull/5792)
* Fixes Shed Tail substitute health by @AlexOn1ine in [#5826](https://github.com/rh-hideout/pokeemerald-expansion/pull/5826)
* `B_LAST_USED_BALL` and `.importance` by @AERDU in [#5834](https://github.com/rh-hideout/pokeemerald-expansion/pull/5834)
- prevents `B_LAST_USED_BALL` from removing balls with `.importance = 1`
* Fixes Quash-affected battlers having the wrong order for End Turn effects by @PhallenTree in [#5838](https://github.com/rh-hideout/pokeemerald-expansion/pull/5838)
* Fixes Cotton Down and Gulp Missile not interacting correctly with stat reduction prevention effects by @PhallenTree in [#5841](https://github.com/rh-hideout/pokeemerald-expansion/pull/5841)
* Fix Hit Escape moves giving Exp to the mon that switches in by @kittenchilly in [#5844](https://github.com/rh-hideout/pokeemerald-expansion/pull/5844)
* Fixed Wish triggering Disguise by @AsparagusEduardo in [#5860](https://github.com/rh-hideout/pokeemerald-expansion/pull/5860)
* Fixed `MOVE_EFFECT_FREEZE_OR_FROSTBITE` not being usable in battle scripts by @AsparagusEduardo in [#5859](https://github.com/rh-hideout/pokeemerald-expansion/pull/5859)
* Fixed Ally Switch breaking Illusion by @AsparagusEduardo in [#5879](https://github.com/rh-hideout/pokeemerald-expansion/pull/5879)
* Fixes gen3 Style Shadows out of place by @AlexOn1ine in [#5880](https://github.com/rh-hideout/pokeemerald-expansion/pull/5880)
* Fix Salt Cure script by @ghoulslash in [#5895](https://github.com/rh-hideout/pokeemerald-expansion/pull/5895)
* Fixes Eject Pack / Intimidate issue by @AlexOn1ine in [#5902](https://github.com/rh-hideout/pokeemerald-expansion/pull/5902)
* Adds Generational config for Magic Guard (Fix for Gen4+) by @AlexOn1ine in [#5893](https://github.com/rh-hideout/pokeemerald-expansion/pull/5893)
* Fixes Stance Change, Sleep Talk interaction by @AlexOn1ine in [#5909](https://github.com/rh-hideout/pokeemerald-expansion/pull/5909)
* Fixes Round doubling it's BP if previous Round failed by @AlexOn1ine in [#5907](https://github.com/rh-hideout/pokeemerald-expansion/pull/5907)
## 🤹 Moves 🤹
### Fixed
* Fixes absorb still draining HP when flinched by @AlexOn1ine in [#5814](https://github.com/rh-hideout/pokeemerald-expansion/pull/5814)
* Fixes Tidy Up by @AlexOn1ine in [#5819](https://github.com/rh-hideout/pokeemerald-expansion/pull/5819)
* Ally Switch extra battlerId tracking by @ghoulslash in [#5823](https://github.com/rh-hideout/pokeemerald-expansion/pull/5823)
* Sheer Force fix and move effect cleanup by @AlexOn1ine in [#5812](https://github.com/rh-hideout/pokeemerald-expansion/pull/5812)
* New U-turn animation to fix visibility by @AlexOn1ine in [#5910](https://github.com/rh-hideout/pokeemerald-expansion/pull/5910)
## 🧶 Items 🧶
### Fixed
* Prevent Key Items that open other menus from causing a crash if registered and used from the field by @iriv24 in [#5810](https://github.com/rh-hideout/pokeemerald-expansion/pull/5810)
* Fixes Clear Amulet displaying the wrong battler and Starting Status displaying the wrong message by @PhallenTree in [#5831](https://github.com/rh-hideout/pokeemerald-expansion/pull/5831)
* Fixes Room Service lowering the opposite mon in specific scenario by @AlexOn1ine in [#5827](https://github.com/rh-hideout/pokeemerald-expansion/pull/5827)
## 🤖 Battle AI 🤖
### Fixed
* Fixed ace switching bugs by @Pawkkie and @iriv24 for their diligent testing and debugging support in [#5922](https://github.com/rh-hideout/pokeemerald-expansion/pull/5922)
## 🧹 Other Cleanup 🧹
* Converted Stance Change to proper Form Change + Tests by @AsparagusEduardo in [#5749](https://github.com/rh-hideout/pokeemerald-expansion/pull/5749)
* Removed testing strings for automatic line breaks by @hedara90 in [#5757](https://github.com/rh-hideout/pokeemerald-expansion/pull/5757)
* Added NBSP and up+down arrows to all fonts by @hedara90 in [#5767](https://github.com/rh-hideout/pokeemerald-expansion/pull/5767)
- Use `~` or `{NBSP}` to insert a non-breaking space into a string.
* Palette cleanup by @hedara90 in [#5661](https://github.com/rh-hideout/pokeemerald-expansion/pull/5661)
- Resized some move anim palettes from 256 to 16
* Replace power checks with IS_MOVE_STATUS by @Bassoonian and @AsparagusEduardo in [#5820](https://github.com/rh-hideout/pokeemerald-expansion/pull/5820)
* Changes Various defines to an Enum by @AsparagusEduardo in [#5840](https://github.com/rh-hideout/pokeemerald-expansion/pull/5840)
* Fix `IS_MOVE_STATUS` regression by @Bassoonian in [#5848](https://github.com/rh-hideout/pokeemerald-expansion/pull/5848)
* Remove unused various by @Bassoonian in [#5851](https://github.com/rh-hideout/pokeemerald-expansion/pull/5851)
* Removed redundant call to FillPalBufferBlack in FRLG whiteout sequence by @AsparagusEduardo in [#5854](https://github.com/rh-hideout/pokeemerald-expansion/pull/5854)
* Improve README.md by @AsparagusEduardo in [#5640](https://github.com/rh-hideout/pokeemerald-expansion/pull/5640)
* Fix wrong value for NUM_MOVE_EFFECTS by @Bassoonian in [#5913](https://github.com/rh-hideout/pokeemerald-expansion/pull/5913)
* Renamed OW type effectiveness function for clarity by @AsparagusEduardo in [#5917](https://github.com/rh-hideout/pokeemerald-expansion/pull/5917)
- Renamed `GetTypeEffectiveness` to `GetOverworldTypeEffectiveness`.
## 🧪 Test Runner 🧪
### Changed
* Gravity fix + Sky Drop Test by @ghoulslash in [#5780](https://github.com/rh-hideout/pokeemerald-expansion/pull/5780)
* Added missing Belch tests by @AsparagusEduardo in [#5881](https://github.com/rh-hideout/pokeemerald-expansion/pull/5881)
* Added missing Move Effect TODO tests - Volume D by @AsparagusEduardo in [#5887](https://github.com/rh-hideout/pokeemerald-expansion/pull/5887)
* Comment out Ally Switch Illusion test by @AsparagusEduardo in [#5901](https://github.com/rh-hideout/pokeemerald-expansion/pull/5901)
* Fixed leaking tasks not showing up in summary by @AsparagusEduardo in [#5890](https://github.com/rh-hideout/pokeemerald-expansion/pull/5890)
* Setting Battle configs during tests by @AsparagusEduardo and @SBird1337, @mrgriffin in [#5803](https://github.com/rh-hideout/pokeemerald-expansion/pull/5803)
* Speed up tests in headless mode by @AsparagusEduardo and @SBird1337 for the original fast intro code. in [#5889](https://github.com/rh-hideout/pokeemerald-expansion/pull/5889)
- This introduced the config option `B_FAST_INTRO_NO_SLIDE` which removes the sliding into for battles.
* Added missing Move Effect TODO tests - Volume E by @AsparagusEduardo in [#5915](https://github.com/rh-hideout/pokeemerald-expansion/pull/5915)
### Fixed
* Fix test `TIMEOUT` messaging in summary by @AsparagusEduardo in [#5772](https://github.com/rh-hideout/pokeemerald-expansion/pull/5772)
* Fix octolock + defiant by @ghoulslash in [#5781](https://github.com/rh-hideout/pokeemerald-expansion/pull/5781)
* Added missing tests + Fix Coaching/Crafty Shield interaction by @AsparagusEduardo in [#5796](https://github.com/rh-hideout/pokeemerald-expansion/pull/5796)
* Fixed TODO tests not showing up when filtering by name by @AsparagusEduardo in [#5894](https://github.com/rh-hideout/pokeemerald-expansion/pull/5894)
## 📚 Documentation 📚
* Fixed changelog links to changelog 1.10 by @AsparagusEduardo in [#5758](https://github.com/rh-hideout/pokeemerald-expansion/pull/5758)
* Added scope document and made changes to pull request template by @pkmnsnfrn and @Pawkkie and arguably the entire senate in [#5706](https://github.com/rh-hideout/pokeemerald-expansion/pull/5706)
* Added instructions in PR template to make crediting people more clear by @pkmnsnfrn and @AsparagusEduardo made changes to my text in [#5755](https://github.com/rh-hideout/pokeemerald-expansion/pull/5755)
* Fix website not showing the "How to add mon" 1.10 tutorial by @AsparagusEduardo in [#5813](https://github.com/rh-hideout/pokeemerald-expansion/pull/5813)
* Install instructions by @hedara90 in [#5876](https://github.com/rh-hideout/pokeemerald-expansion/pull/5876)
* Change install.md to mention make debug instead of DINFO=1 by @ravepossum in [#5882](https://github.com/rh-hideout/pokeemerald-expansion/pull/5882)
* Backport changes from the wiki by @AsparagusEduardo in [#5900](https://github.com/rh-hideout/pokeemerald-expansion/pull/5900)
* Improve README.md by @AsparagusEduardo in [#5640](https://github.com/rh-hideout/pokeemerald-expansion/pull/5640)
## 📦 Branch Synchronisation 📦
### pret
* 20th of December in [#5845](https://github.com/rh-hideout/pokeemerald-expansion/pull/5845)
* Fix recorded battle link player loops by @AsparagusEduardo in [pret#2071](https://github.com/pret/pokeemerald/pull/2071)
* Added `POKEMART_LIST_END` to avoid users accidentally removing it by @AsparagusEduardo in [pret#1947](https://github.com/pret/pokeemerald/pull/1947)
* Fixed brace style inconsistencies by @AsparagusEduardo in [pret#2072](https://github.com/pret/pokeemerald/pull/2072)
* remove `sBirchSpeechPlatformBlackPal` by @DizzyEggg in [pret#2075](https://github.com/pret/pokeemerald/pull/2075)
**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.10.0...expansion/1.10.1
<!--Last PR: 5922-->
<!--Used to keep track of the last PR merged in case new ones come in before the changelog is done.-->

View file

@ -6,6 +6,7 @@ void FreeBattleSpritesData(void);
u16 ChooseMoveAndTargetInBattlePalace(u32 battler);
void SpriteCB_WaitForBattlerBallReleaseAnim(struct Sprite *sprite);
void SpriteCB_TrainerSlideIn(struct Sprite *sprite);
void SpriteCB_TrainerSpawn(struct Sprite *sprite);
void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isStatus2, u32 status);
bool8 TryHandleLaunchBattleTableAnimation(u8 activeBattlerId, u8 attacker, u8 target, u8 tableId, u16 argument);
void InitAndLaunchSpecialAnimation(u8 activeBattlerId, u8 attacker, u8 target, u8 tableId);

View file

@ -422,7 +422,6 @@ extern const u8 BattleScript_EjectButtonActivates[];
extern const u8 BattleScript_EjectPackActivate_Ret[];
extern const u8 BattleScript_EjectPackActivate_End2[];
extern const u8 BattleScript_EjectPackActivates[];
extern const u8 BattleScript_EjectPackMissesTiming[];
extern const u8 BattleScript_MentalHerbCureRet[];
extern const u8 BattleScript_MentalHerbCureEnd2[];
extern const u8 BattleScript_TerrainPreventsEnd2[];

View file

@ -230,7 +230,8 @@
// Interface settings
#define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle.
#define B_FAST_INTRO TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end.
#define B_FAST_INTRO_PKMN_TEXT TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end.
#define B_FAST_INTRO_NO_SLIDE FALSE // If set to TRUE, the slide animation that happens at the beginning of the battle is skipped.
#define B_FAST_HP_DRAIN TRUE // If set to TRUE, HP bars will move faster.
#define B_FAST_EXP_GROW TRUE // If set to TRUE, EXP bars will move faster.
#define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move.

View file

@ -1,7 +1,7 @@
#ifndef GUARD_CONSTANTS_EXPANSION_H
#define GUARD_CONSTANTS_EXPANSION_H
// Last version: 1.10.0
// Last version: 1.10.1
#define EXPANSION_VERSION_MAJOR 1
#define EXPANSION_VERSION_MINOR 11
#define EXPANSION_VERSION_PATCH 0

View file

@ -925,7 +925,6 @@ bool32 ShouldSwitch(u32 battler)
struct Pokemon *party;
s32 i;
s32 availableToSwitch;
bool32 hasAceMon = FALSE;
if (gBattleMons[battler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
return FALSE;
@ -973,21 +972,13 @@ bool32 ShouldSwitch(u32 battler)
if (i == gBattleStruct->monToSwitchIntoId[battlerIn2])
continue;
if (IsAceMon(battler, i))
{
hasAceMon = TRUE;
continue;
}
availableToSwitch++;
}
if (availableToSwitch == 0)
{
if (hasAceMon) // If the ace mon is the only available mon, use it
availableToSwitch++;
else
return FALSE;
}
// NOTE: The sequence of the below functions matter! Do not change unless you have carefully considered the outcome.
// Since the order is sequencial, and some of these functions prompt switch to specific party members.
@ -1778,7 +1769,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
{
int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE;
int batonPassId = PARTY_SIZE, typeMatchupId = PARTY_SIZE, typeMatchupEffectiveId = PARTY_SIZE, defensiveMonId = PARTY_SIZE, aceMonId = PARTY_SIZE, trapperId = PARTY_SIZE;
int i, j, aliveCount = 0, bits = 0;
int i, j, aliveCount = 0, bits = 0, aceMonCount = 0;
s32 defensiveMonHitKOThreshold = 3; // 3HKO threshold that candidate defensive mons must exceed
s32 playerMonHP = gBattleMons[opposingBattler].hp, maxDamageDealt = 0, damageDealt = 0;
u32 aiMove, hitsToKOAI, maxHitsToKO = 0;
@ -1801,6 +1792,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
else if (IsAceMon(battler, i))
{
aceMonId = i;
aceMonCount++;
continue;
}
else
@ -1947,7 +1939,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
else if (batonPassId != PARTY_SIZE) return batonPassId;
}
// If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon.
if (aceMonId != PARTY_SIZE && IsSwitchOutEffect(GetMoveEffect(gLastUsedMove)))
if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount && IsSwitchOutEffect(GetMoveEffect(gLastUsedMove)))
return aceMonId;
return PARTY_SIZE;
@ -2025,7 +2017,7 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
// This all handled by the GetBestMonIntegrated function if the AI_FLAG_SMART_MON_CHOICES flag is set
else
{
s32 i, aliveCount = 0;
s32 i, aliveCount = 0, aceMonCount = 0;
u32 invalidMons = 0, aceMonId = PARTY_SIZE;
// Get invalid slots ids.
for (i = firstId; i < lastId; i++)
@ -2042,6 +2034,7 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
else if (IsAceMon(battler, i)) // Save Ace Pokemon for last.
{
aceMonId = i;
aceMonCount++;
invalidMons |= 1u << i;
}
else
@ -2061,8 +2054,8 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
if (bestMonId != PARTY_SIZE)
return bestMonId;
// If ace mon is the last available Pokemon and switch move was used - switch to the mon.
if (aceMonId != PARTY_SIZE)
// If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon.
if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount && IsSwitchOutEffect(gMovesInfo[gLastUsedMove].effect))
return aceMonId;
return PARTY_SIZE;

View file

@ -2542,7 +2542,10 @@ void BtlController_HandleDrawTrainerPic(u32 battler, u32 trainerPicId, bool32 is
gSprites[gBattlerSpriteIds[battler]].x2 = DISPLAY_WIDTH;
gSprites[gBattlerSpriteIds[battler]].sSpeedX = -2;
}
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
if (B_FAST_INTRO_NO_SLIDE || gTestRunnerHeadless)
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSpawn;
else
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCB_TrainerSlideIn;
gBattlerControllerFuncs[battler] = Controller_WaitForTrainerPic;
}

View file

@ -435,6 +435,18 @@ void SpriteCB_TrainerSlideIn(struct Sprite *sprite)
}
}
void SpriteCB_TrainerSpawn(struct Sprite *sprite)
{
if (!(gIntroSlideFlags & 1))
{
sprite->x2 = 0;
if (sprite->y2 != 0)
sprite->callback = SpriteCB_TrainerSlideVertical;
else
sprite->callback = SpriteCallbackDummy;
}
}
// Slide up to 0 if necessary (used by multi battle intro)
static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite)
{

View file

@ -8,6 +8,7 @@
#include "main.h"
#include "scanline_effect.h"
#include "task.h"
#include "test_runner.h"
#include "trig.h"
#include "constants/battle_partner.h"
#include "constants/trainers.h"
@ -17,6 +18,7 @@ static void BattleIntroSlide2(u8);
static void BattleIntroSlide3(u8);
static void BattleIntroSlideLink(u8);
static void BattleIntroSlidePartner(u8);
static void BattleIntroNoSlide(u8);
static const u8 sBattleAnimBgCnts[] = {REG_OFFSET_BG0CNT, REG_OFFSET_BG1CNT, REG_OFFSET_BG2CNT, REG_OFFSET_BG3CNT};
@ -149,9 +151,59 @@ static void BattleIntroSlideEnd(u8 taskId)
SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR);
}
static void BattleIntroNoSlide(u8 taskId)
{
switch (gTasks[taskId].tState)
{
case 0:
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
{
gTasks[taskId].data[2] = 16;
gTasks[taskId].tState++;
gIntroSlideFlags &= ~1;
}
else
{
gTasks[taskId].data[2] = 1;
gTasks[taskId].tState++;
gIntroSlideFlags &= ~1;
}
break;
case 1:
gTasks[taskId].data[2]--;
if (gTasks[taskId].data[2] == 0)
{
gTasks[taskId].tState++;
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR);
gScanlineEffect.state = 3;
}
break;
case 2:
gBattle_WIN0V -= 0xFF * 2;
if ((gBattle_WIN0V & 0xFF00) == 0)
{
gTasks[taskId].tState++;
}
break;
case 3:
gTasks[taskId].tState++;
CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE);
SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 0);
SetBgAttribute(2, BG_ATTR_CHARBASEINDEX, 0);
SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512);
SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256);
break;
case 4:
BattleIntroSlideEnd(taskId);
break;
}
}
static void BattleIntroSlide1(u8 taskId)
{
int i;
if (B_FAST_INTRO_NO_SLIDE || gTestRunnerHeadless)
return BattleIntroNoSlide(taskId);
gBattle_BG1_X += 6;
switch (gTasks[taskId].tState)
@ -237,6 +289,8 @@ static void BattleIntroSlide1(u8 taskId)
static void BattleIntroSlide2(u8 taskId)
{
int i;
if (B_FAST_INTRO_NO_SLIDE || gTestRunnerHeadless)
return BattleIntroNoSlide(taskId);
switch (gTasks[taskId].tTerrain)
{
@ -349,6 +403,8 @@ static void BattleIntroSlide2(u8 taskId)
static void BattleIntroSlide3(u8 taskId)
{
int i;
if (B_FAST_INTRO_NO_SLIDE || gTestRunnerHeadless)
return BattleIntroNoSlide(taskId);
gBattle_BG1_X += 8;
switch (gTasks[taskId].tState)

View file

@ -484,21 +484,24 @@ static void CB2_InitBattleInternal(void)
else
{
gBattle_WIN0V = WIN_RANGE(DISPLAY_HEIGHT / 2, DISPLAY_HEIGHT / 2 + 1);
ScanlineEffect_Clear();
for (i = 0; i < DISPLAY_HEIGHT / 2; i++)
if (B_FAST_INTRO_NO_SLIDE == FALSE && !gTestRunnerHeadless)
{
gScanlineEffectRegBuffers[0][i] = 0xF0;
gScanlineEffectRegBuffers[1][i] = 0xF0;
}
ScanlineEffect_Clear();
for (; i < DISPLAY_HEIGHT; i++)
{
gScanlineEffectRegBuffers[0][i] = 0xFF10;
gScanlineEffectRegBuffers[1][i] = 0xFF10;
}
for (i = 0; i < DISPLAY_HEIGHT / 2; i++)
{
gScanlineEffectRegBuffers[0][i] = 0xF0;
gScanlineEffectRegBuffers[1][i] = 0xF0;
}
ScanlineEffect_SetParams(sIntroScanlineParams16Bit);
for (; i < DISPLAY_HEIGHT; i++)
{
gScanlineEffectRegBuffers[0][i] = 0xFF10;
gScanlineEffectRegBuffers[1][i] = 0xFF10;
}
ScanlineEffect_SetParams(sIntroScanlineParams16Bit);
}
}
ResetPaletteFade();
@ -529,7 +532,8 @@ static void CB2_InitBattleInternal(void)
LoadBattleTextboxAndBackground();
ResetSpriteData();
ResetTasks();
DrawBattleEntryBackground();
if (B_FAST_INTRO_NO_SLIDE == FALSE && !gTestRunnerHeadless)
DrawBattleEntryBackground();
FreeAllSpritePalettes();
gReservedSpritePaletteCount = MAX_BATTLERS_COUNT;
SetVBlankCallback(VBlankCB_Battle);
@ -2648,17 +2652,24 @@ void SpriteCB_WildMon(struct Sprite *sprite)
{
sprite->callback = SpriteCB_MoveWildMonToRight;
StartSpriteAnimIfDifferent(sprite, 0);
if (WILD_DOUBLE_BATTLE)
BeginNormalPaletteFade((0x10000 << sprite->sBattler) | (0x10000 << BATTLE_PARTNER(sprite->sBattler)), 0, 10, 10, RGB(8, 8, 8));
else
BeginNormalPaletteFade((0x10000 << sprite->sBattler), 0, 10, 10, RGB(8, 8, 8));
if (B_FAST_INTRO_NO_SLIDE == FALSE && !gTestRunnerHeadless)
{
if (WILD_DOUBLE_BATTLE)
BeginNormalPaletteFade((0x10000 << sprite->sBattler) | (0x10000 << BATTLE_PARTNER(sprite->sBattler)), 0, 10, 10, RGB(8, 8, 8));
else
BeginNormalPaletteFade((0x10000 << sprite->sBattler), 0, 10, 10, RGB(8, 8, 8));
}
}
static void SpriteCB_MoveWildMonToRight(struct Sprite *sprite)
{
if ((gIntroSlideFlags & 1) == 0)
{
sprite->x2 += 2;
if (B_FAST_INTRO_NO_SLIDE == FALSE && !gTestRunnerHeadless)
sprite->x2 += 2;
else
sprite->x2 = 0;
if (sprite->x2 == 0)
{
sprite->callback = SpriteCB_WildMonShowHealthbox;
@ -2674,10 +2685,13 @@ static void SpriteCB_WildMonShowHealthbox(struct Sprite *sprite)
SetHealthboxSpriteVisible(gHealthboxSpriteIds[sprite->sBattler]);
sprite->callback = SpriteCB_WildMonAnimate;
StartSpriteAnimIfDifferent(sprite, 0);
if (WILD_DOUBLE_BATTLE)
BeginNormalPaletteFade((0x10000 << sprite->sBattler) | (0x10000 << BATTLE_PARTNER(sprite->sBattler)), 0, 10, 0, RGB(8, 8, 8));
else
BeginNormalPaletteFade((0x10000 << sprite->sBattler), 0, 10, 0, RGB(8, 8, 8));
if (B_FAST_INTRO_NO_SLIDE == FALSE && !gTestRunnerHeadless)
{
if (WILD_DOUBLE_BATTLE)
BeginNormalPaletteFade((0x10000 << sprite->sBattler) | (0x10000 << BATTLE_PARTNER(sprite->sBattler)), 0, 10, 0, RGB(8, 8, 8));
else
BeginNormalPaletteFade((0x10000 << sprite->sBattler), 0, 10, 0, RGB(8, 8, 8));
}
}
}
@ -3583,7 +3597,7 @@ static void DoBattleIntro(void)
}
else // Skip party summary since it is a wild battle.
{
if (B_FAST_INTRO == TRUE)
if (B_FAST_INTRO_PKMN_TEXT == TRUE)
gBattleStruct->introState = BATTLE_INTRO_STATE_INTRO_TEXT; // Don't wait for sprite, print message at the same time.
else
gBattleStruct->introState++; // Wait for sprite to load.
@ -3655,7 +3669,7 @@ static void DoBattleIntro(void)
}
else
{
if (B_FAST_INTRO == TRUE)
if (B_FAST_INTRO_PKMN_TEXT == TRUE)
gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT;
else
gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_TRAINER_2_SEND_OUT_ANIM;
@ -3694,7 +3708,7 @@ static void DoBattleIntro(void)
BtlController_EmitIntroTrainerBallThrow(battler, BUFFER_A);
MarkBattlerForControllerExec(battler);
}
if (B_FAST_INTRO == TRUE
if (B_FAST_INTRO_PKMN_TEXT == TRUE
&& !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK)))
gBattleStruct->introState = BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT; // Print at the same time as trainer sends out second mon.
else
@ -3717,7 +3731,7 @@ static void DoBattleIntro(void)
battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
// A hack that makes fast intro work in trainer battles too.
if (B_FAST_INTRO == TRUE
if (B_FAST_INTRO_PKMN_TEXT == TRUE
&& gBattleTypeFlags & BATTLE_TYPE_TRAINER
&& !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK))
&& gSprites[gHealthboxSpriteIds[battler ^ BIT_SIDE]].callback == SpriteCallbackDummy)

View file

@ -3020,6 +3020,8 @@ static void Cmd_waitmessage(void)
else
{
u16 toWait = cmd->time;
if (gTestRunnerHeadless)
gPauseCounterBattle = toWait;
if (++gPauseCounterBattle >= toWait)
{
gPauseCounterBattle = 0;
@ -5521,6 +5523,8 @@ static void Cmd_pause(void)
if (gBattleControllerExecFlags == 0)
{
u16 value = cmd->frames;
if (gTestRunnerHeadless)
gPauseCounterBattle = value;
if (++gPauseCounterBattle >= value)
{
gPauseCounterBattle = 0;
@ -6727,19 +6731,13 @@ static void Cmd_moveend(void)
}
else // Eject Pack
{
if (gBattleResources->flags->flags[gBattlerTarget] & RESOURCE_FLAG_EMERGENCY_EXIT)
{
gBattlescriptCurrInstr = BattleScript_EjectPackMissesTiming;
gProtectStructs[battler].statFell = FALSE;
}
else
if (!(gBattleResources->flags->flags[gBattlerTarget] & RESOURCE_FLAG_EMERGENCY_EXIT))
{
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
AI_DATA->ejectPackSwitch = TRUE;
// Are these 2 lines below needed?
gProtectStructs[battler].statFell = FALSE;
gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage = TRUE;
}
gProtectStructs[battler].statFell = FALSE;
}
break; // Only the fastest Eject item activates
}
@ -10692,6 +10690,7 @@ static void Cmd_various(void)
{
gBattlerSpriteIds[BATTLE_PARTNER(battler)] = gBattleScripting.savedDmg >> 8;
gBattlerSpriteIds[battler] = gBattleScripting.savedDmg & 0xFF;
gBattleScripting.savedDmg = 0;
if (IsBattlerAlive(battler))
{
SetBattlerShadowSpriteCallback(battler, gBattleMons[battler].species);

View file

@ -39,6 +39,7 @@
#include "string_util.h"
#include "strings.h"
#include "task.h"
#include "test_runner.h"
#include "text.h"
#include "trainer_hill.h"
#include "util.h"
@ -6305,7 +6306,7 @@ void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality)
bool8 HasTwoFramesAnimation(u16 species)
{
return P_TWO_FRAME_FRONT_SPRITES && species != SPECIES_UNOWN;
return P_TWO_FRAME_FRONT_SPRITES && species != SPECIES_UNOWN && !gTestRunnerHeadless;
}
static bool8 ShouldSkipFriendshipChange(void)
@ -6925,7 +6926,7 @@ void HealBoxPokemon(struct BoxPokemon *boxMon)
u16 GetCryIdBySpecies(u16 species)
{
species = SanitizeSpeciesId(species);
if (P_CRIES_ENABLED == FALSE || gSpeciesInfo[species].cryId >= CRY_COUNT)
if (P_CRIES_ENABLED == FALSE || gSpeciesInfo[species].cryId >= CRY_COUNT || gTestRunnerHeadless)
return CRY_NONE;
return gSpeciesInfo[species].cryId;
}

View file

@ -5,6 +5,7 @@
#include "pokemon_animation.h"
#include "sprite.h"
#include "task.h"
#include "test_runner.h"
#include "trig.h"
#include "util.h"
#include "data.h"
@ -508,7 +509,10 @@ static void Task_HandleMonAnimation(u8 taskId)
for (i = 2; i < ARRAY_COUNT(sprite->data); i++)
sprite->data[i] = 0;
sprite->callback = sMonAnimFunctions[gTasks[taskId].tAnimId];
if (gTestRunnerHeadless)
sprite->callback = WaitAnimEnd;
else
sprite->callback = sMonAnimFunctions[gTasks[taskId].tAnimId];
sIsSummaryAnim = FALSE;
gTasks[taskId].tState++;

View file

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Electric Surge creates Electric Terrain when entering the battle");

View file

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Grassy Surge creates Grassy Terrain when entering the battle");

View file

@ -0,0 +1,72 @@
#include "global.h"
#include "test/battle.h"
static const u16 terrainData[][2] =
{
{ MOVE_ELECTRIC_TERRAIN, TYPE_ELECTRIC, },
{ MOVE_PSYCHIC_TERRAIN, TYPE_PSYCHIC, },
{ MOVE_GRASSY_TERRAIN, TYPE_GRASS, },
{ MOVE_MISTY_TERRAIN, TYPE_FAIRY, },
};
SINGLE_BATTLE_TEST("Mimicry changes the battler's type based on Terrain")
{
u32 j;
u32 terrainMove = MOVE_NONE;
u32 terrainType = TYPE_NONE;
for (j = 0; j < ARRAY_COUNT(terrainData); j++)
PARAMETRIZE { terrainMove = terrainData[j][0]; terrainType = terrainData[j][1]; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_STUNFISK_GALAR) { Ability(ABILITY_MIMICRY); }
} WHEN {
TURN { MOVE(player, terrainMove); }
} SCENE {
ABILITY_POPUP(opponent);
switch (terrainMove)
{
case MOVE_ELECTRIC_TERRAIN: MESSAGE("The opposing Stunfisk's type changed to Electric!"); break;
case MOVE_PSYCHIC_TERRAIN: MESSAGE("The opposing Stunfisk's type changed to Psychic!"); break;
case MOVE_GRASSY_TERRAIN: MESSAGE("The opposing Stunfisk's type changed to Grass!"); break;
case MOVE_MISTY_TERRAIN: MESSAGE("The opposing Stunfisk's type changed to Fairy!"); break;
}
} THEN {
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[0], terrainType);
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[1], terrainType);
}
}
SINGLE_BATTLE_TEST("Mimicry restores the battler's types when terrain is removed by Steel Roller and Ice Spinner")
{
u32 j;
u32 terrainMove = MOVE_NONE;
u32 removeTerrainMove = MOVE_NONE;
for (j = 0; j < ARRAY_COUNT(terrainData); j++)
{
PARAMETRIZE { removeTerrainMove = MOVE_STEEL_ROLLER; terrainMove = terrainData[j][0]; }
PARAMETRIZE { removeTerrainMove = MOVE_ICE_SPINNER; terrainMove = terrainData[j][0]; }
}
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_STUNFISK_GALAR].types[0] == TYPE_GROUND);
ASSUME(gSpeciesInfo[SPECIES_STUNFISK_GALAR].types[1] == TYPE_STEEL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_STUNFISK_GALAR) { Ability(ABILITY_MIMICRY); }
} WHEN {
TURN { MOVE(opponent, terrainMove); MOVE(player, removeTerrainMove); }
} SCENE {
switch (terrainMove)
{
case MOVE_ELECTRIC_TERRAIN: MESSAGE("The electricity disappeared from the battlefield."); break;
case MOVE_PSYCHIC_TERRAIN: MESSAGE("The weirdness disappeared from the battlefield!"); break;
case MOVE_GRASSY_TERRAIN: MESSAGE("The grass disappeared from the battlefield."); break;
case MOVE_MISTY_TERRAIN: MESSAGE("The mist disappeared from the battlefield."); break;
}
} THEN {
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[0], TYPE_GROUND);
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[1], TYPE_STEEL);
}
}

View file

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Misty Surge creates Misty Terrain when entering the battle");

View file

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Psychic Surge creates Psychic Terrain when entering the battle");

View file

@ -924,3 +924,61 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI correctly handles abilities
TURN { MOVE(player, MOVE_WATER_GUN); EXPECT_MOVE(opponent, MOVE_ABSORB); }
}
}
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch out if Yawn'd with only Ace mon remaining")
{
u32 aceFlag;
PARAMETRIZE{ aceFlag = 0; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; }
GIVEN {
ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | aceFlag | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_SMART_SWITCHING);
PLAYER(SPECIES_SLOWKING) { Moves(MOVE_YAWN, MOVE_CONFUSION, MOVE_POWER_GEM, MOVE_WATER_PULSE); Item(ITEM_LEFTOVERS); }
OPPONENT(SPECIES_SCOLIPEDE) { Moves(MOVE_POISON_TAIL); }
OPPONENT(SPECIES_ABSOL) { Moves(MOVE_KNOCK_OFF, MOVE_CRUNCH); }
} WHEN {
TURN { MOVE(player, MOVE_YAWN); EXPECT_MOVE(opponent, MOVE_POISON_TAIL); }
if (aceFlag)
TURN { MOVE(player, MOVE_POWER_GEM); EXPECT_MOVE(opponent, MOVE_POISON_TAIL); }
else
TURN { MOVE(player, MOVE_POWER_GEM); EXPECT_SWITCH(opponent, 1); }
}
}
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch in ace mon after U-Turn if other options available")
{
u32 aceFlag;
PARAMETRIZE{ aceFlag = 0; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; }
GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | aceFlag | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_SMART_SWITCHING);
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SURF); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); }
OPPONENT(SPECIES_NUMEL) { Level(5); Moves(MOVE_SPLASH); }
OPPONENT(SPECIES_SCIZOR) { Moves(MOVE_BUG_BITE); }
} WHEN {
if (aceFlag)
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 1); MOVE(player, MOVE_SURF); }
else
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 2); MOVE(player, MOVE_SURF); }
}
}
AI_SINGLE_BATTLE_TEST("Switch AI: AI won't switch in ace mon after U-Turn if other options available")
{
u32 aceFlag;
PARAMETRIZE{ aceFlag = 0; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; }
GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | aceFlag | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT);
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SURF); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); }
OPPONENT(SPECIES_NUMEL) { Level(5); Moves(MOVE_SPLASH); }
OPPONENT(SPECIES_SCIZOR) { Moves(MOVE_BUG_BITE); }
} WHEN {
if (aceFlag)
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 1); MOVE(player, MOVE_SURF); }
else
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 2); MOVE(player, MOVE_SURF); }
}
}

View file

@ -227,41 +227,6 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon can have their ability changed o
}
}
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon are immune to Encore")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, gimmick: GIMMICK_DYNAMAX); MOVE(opponent, MOVE_ENCORE); }
TURN { MOVE(player, MOVE_EMBER); }
} SCENE {
MESSAGE("Wobbuffet used Max Strike!");
MESSAGE("The opposing Wobbuffet used Encore!");
MESSAGE("But it failed!");
MESSAGE("Wobbuffet used Max Flare!");
}
}
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon can be encored immediately after reverting")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(50); }; // yes, this speed is necessary
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); };
} WHEN {
TURN { MOVE(player, MOVE_ARM_THRUST, gimmick: GIMMICK_DYNAMAX); }
TURN { MOVE(player, MOVE_ARM_THRUST); }
TURN { MOVE(player, MOVE_ARM_THRUST); }
TURN { MOVE(opponent, MOVE_ENCORE); MOVE(player, MOVE_TACKLE); }
} SCENE {
MESSAGE("Wobbuffet used Max Knuckle!");
MESSAGE("Wobbuffet used Max Knuckle!");
MESSAGE("Wobbuffet used Max Knuckle!");
MESSAGE("The opposing Wobbuffet used Encore!");
MESSAGE("Wobbuffet used Arm Thrust!");
}
}
// Max Moves don't make contact, so Cursed Body doesn't need to be tested, but it is coded for.
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon's Max Moves cannot be disabled")
{

View file

@ -76,12 +76,13 @@ SINGLE_BATTLE_TEST("Eject Pack will miss timing to switch out user if Emergency
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_OVERHEAT, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet is switched out with the Eject Pack!");
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet is switched out with the Eject Pack!");
}
ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
} THEN {
EXPECT(player->species == SPECIES_WOBBUFFET);
EXPECT(player->item == ITEM_NONE);
EXPECT(opponent->species == SPECIES_WYNAUT);
}
}

View file

@ -0,0 +1,62 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Electric Seed raises the holder's Defense on Electric Terrain")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_ELECTRIC_SEED].holdEffect == HOLD_EFFECT_SEEDS);
ASSUME(gItemsInfo[ITEM_ELECTRIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIC_SEED); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!");
}
}
SINGLE_BATTLE_TEST("Grassy Seed raises the holder's Defense on Grassy Terrain")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_GRASSY_SEED].holdEffect == HOLD_EFFECT_SEEDS);
ASSUME(gItemsInfo[ITEM_GRASSY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_GRASSY_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRASSY_SEED); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_GRASSY_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!");
}
}
SINGLE_BATTLE_TEST("Misty Seed raises the holder's Sp. Defense on Misty Terrain")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_MISTY_SEED].holdEffect == HOLD_EFFECT_SEEDS);
ASSUME(gItemsInfo[ITEM_MISTY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_MISTY_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MISTY_SEED); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_MISTY_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!");
}
}
SINGLE_BATTLE_TEST("Psychic Seed raises the holder's Sp. Defense on Psychic Terrain")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_PSYCHIC_SEED].holdEffect == HOLD_EFFECT_SEEDS);
ASSUME(gItemsInfo[ITEM_PSYCHIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_SEED); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!");
}
}

View file

@ -113,4 +113,5 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used")
}
TO_DO_BATTLE_TEST("Beak Blast's charging message is shown regardless if it would've missed");
TO_DO_BATTLE_TEST("Beak Blast fails if it's forced by Encore after choosing a different move");
TO_DO_BATTLE_TEST("Bulletproof is immune to Beak Blast but not to the burn it causes");

View file

@ -0,0 +1,7 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Echoed Voice's power is multiplied for every consecutive turn used, capped at 5");
TO_DO_BATTLE_TEST("Echoed Voice's power is reset when using a different move");
TO_DO_BATTLE_TEST("Echoed Voice's power is increased even if it misses");
TO_DO_BATTLE_TEST("Echoed Voice's power is increased even if it's blocked by Protect");

View file

@ -19,25 +19,6 @@ SINGLE_BATTLE_TEST("Electric Terrain protects grounded battlers from falling asl
}
}
SINGLE_BATTLE_TEST("Electric Terrain activates Electric Seed and Mimicry")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_ELECTRIC_SEED].holdEffect == HOLD_EFFECT_SEEDS);
ASSUME(gItemsInfo[ITEM_ELECTRIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIC_SEED); }
OPPONENT(SPECIES_STUNFISK_GALAR) { Ability(ABILITY_MIMICRY); }
} WHEN {
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!");
ABILITY_POPUP(opponent);
MESSAGE("The opposing Stunfisk's type changed to Electric!");
} THEN {
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[0], TYPE_ELECTRIC);
}
}
SINGLE_BATTLE_TEST("Electric Terrain increases power of Electric-type moves by 30/50 percent", s16 damage)
{
bool32 terrain;

View file

@ -0,0 +1,5 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Electrify makes the target's move Electric-type for the remainder of the turn");
TO_DO_BATTLE_TEST("Electrify can change status moves to Electric-type"); // Test type immunity

View file

@ -0,0 +1,5 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Electro Ball inflicts more damage the faster the user is compared to the target");
TO_DO_BATTLE_TEST("Electro Ball considers speed modifiers"); // Stat modifiers, paralysis, Iron Ball, Abilities

View file

@ -6,91 +6,56 @@ ASSUMPTIONS
ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE);
}
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for player: Encore used before move")
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns: Encore used before move")
{
struct BattlePokemon *encoreUser = NULL;
struct BattlePokemon *encoreTarget = NULL;
u32 speedPlayer, speedOpponent;
PARAMETRIZE { encoreUser = opponent; encoreTarget = player; speedPlayer = 10; speedOpponent = 20; }
PARAMETRIZE { encoreUser = player; encoreTarget = opponent; speedPlayer = 20; speedOpponent = 10; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
PLAYER(SPECIES_WOBBUFFET) { Speed(speedPlayer); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(speedOpponent); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); }
TURN { MOVE(opponent, MOVE_ENCORE); MOVE(player, MOVE_CELEBRATE); }
// TURN { FORCED_MOVE(player); }
TURN { FORCED_MOVE(player); }
TURN { FORCED_MOVE(player); }
TURN { MOVE(player, MOVE_SPLASH); }
TURN { MOVE(encoreUser, MOVE_CELEBRATE); MOVE(encoreTarget, MOVE_CELEBRATE); }
TURN { MOVE(encoreUser, MOVE_ENCORE); MOVE(encoreTarget, MOVE_CELEBRATE); }
TURN { FORCED_MOVE(encoreTarget); }
TURN { FORCED_MOVE(encoreTarget); }
TURN { MOVE(encoreTarget, MOVE_SPLASH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreUser);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, encoreUser);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, encoreTarget);
}
}
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for player: Encore used after move")
{
struct BattlePokemon *encoreUser = NULL;
struct BattlePokemon *encoreTarget = NULL;
u32 speedPlayer, speedOpponent;
PARAMETRIZE { encoreUser = opponent; encoreTarget = player; speedPlayer = 20; speedOpponent = 10; }
PARAMETRIZE { encoreUser = player; encoreTarget = opponent; speedPlayer = 10; speedOpponent = 20; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
PLAYER(SPECIES_WOBBUFFET) { Speed(speedPlayer); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(speedOpponent); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_ENCORE); }
TURN { FORCED_MOVE(player); }
TURN { FORCED_MOVE(player); }
TURN { FORCED_MOVE(player); }
TURN { MOVE(player, MOVE_SPLASH); }
TURN { MOVE(encoreTarget, MOVE_CELEBRATE); MOVE(encoreUser, MOVE_ENCORE); }
TURN { FORCED_MOVE(encoreTarget); }
TURN { FORCED_MOVE(encoreTarget); }
TURN { FORCED_MOVE(encoreTarget); }
TURN { MOVE(encoreTarget, MOVE_SPLASH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, player);
}
}
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for opponent: Encore used before move")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(player, MOVE_ENCORE); MOVE(opponent, MOVE_CELEBRATE); }
// TURN { FORCED_MOVE(opponent); }
TURN { FORCED_MOVE(opponent); }
TURN { FORCED_MOVE(opponent); }
TURN { MOVE(opponent, MOVE_SPLASH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, opponent);
}
}
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for opponent: Encore used after move")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_ENCORE); }
TURN { FORCED_MOVE(opponent); }
TURN { FORCED_MOVE(opponent); }
TURN { FORCED_MOVE(opponent); }
TURN { MOVE(opponent, MOVE_SPLASH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, encoreUser);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, encoreTarget);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, encoreTarget);
}
}
@ -121,3 +86,44 @@ SINGLE_BATTLE_TEST("Encore overrides the chosen move if it occurs first")
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
}
}
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon are immune to Encore")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, gimmick: GIMMICK_DYNAMAX); MOVE(opponent, MOVE_ENCORE); }
TURN { MOVE(player, MOVE_EMBER); }
} SCENE {
MESSAGE("Wobbuffet used Max Strike!");
MESSAGE("The opposing Wobbuffet used Encore!");
MESSAGE("But it failed!");
MESSAGE("Wobbuffet used Max Flare!");
}
}
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon can be encored immediately after reverting")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(50); }; // yes, this speed is necessary
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); };
} WHEN {
TURN { MOVE(player, MOVE_ARM_THRUST, gimmick: GIMMICK_DYNAMAX); }
TURN { MOVE(player, MOVE_ARM_THRUST); }
TURN { MOVE(player, MOVE_ARM_THRUST); }
TURN { MOVE(opponent, MOVE_ENCORE); MOVE(player, MOVE_TACKLE); }
} SCENE {
MESSAGE("Wobbuffet used Max Knuckle!");
MESSAGE("Wobbuffet used Max Knuckle!");
MESSAGE("Wobbuffet used Max Knuckle!");
MESSAGE("The opposing Wobbuffet used Encore!");
MESSAGE("Wobbuffet used Arm Thrust!");
}
}
TO_DO_BATTLE_TEST("Encore's effect ends if the encored move runs out of PP");
TO_DO_BATTLE_TEST("Encore lasts for 2-6 turns (Gen 2-3)");
TO_DO_BATTLE_TEST("Encore lasts for 4-8 turns (Gen 4)");
TO_DO_BATTLE_TEST("Encore lasts for 3 turns (Gen 5+)");
TO_DO_BATTLE_TEST("Encore randomly chooses an opponent target");

View file

@ -20,4 +20,4 @@ SINGLE_BATTLE_TEST("Endeavor causes the target's HP to equal the user's current
}
}
TO_DO_BATTLE_TEST("Endeavor does not change HP if the target has less HP than the user, but still plays the animation")
TO_DO_BATTLE_TEST("Endeavor doesn't ignore type immunity") // Ghost types
TO_DO_BATTLE_TEST("Endeavor fails on Ghost-type Pokémon");

View file

@ -0,0 +1,35 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Endure allows the user to survive any attack with 1 HP left");
SINGLE_BATTLE_TEST("Endure does not prevent multiple hits and stat changes occur at the end of the turn")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SCALE_SHOT) == EFFECT_MULTI_HIT);
ASSUME(GetMoveEffect(MOVE_ENDURE) == EFFECT_ENDURE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
} WHEN {
TURN { MOVE(opponent, MOVE_ENDURE); MOVE(player, MOVE_SCALE_SHOT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENDURE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
MESSAGE("The Pokémon was hit 5 time(s)!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Defense fell!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Speed rose!");
}
}
TO_DO_BATTLE_TEST("Endure's success rate decreases for every consecutively used turn");
TO_DO_BATTLE_TEST("Endure uses the same counter as Protect");
TO_DO_BATTLE_TEST("Endure doesn't trigger effects that require damage to be done to the Pokémon (Gen 2-4)"); // Eg. Rough Skin
TO_DO_BATTLE_TEST("Endure triggers effects that require damage to be done to the Pokémon (Gen 5+)"); // Eg. Rough Skin
TO_DO_BATTLE_TEST("Endure doesn't protect against Future Sight (Gen 2-4)");
TO_DO_BATTLE_TEST("Endure protects against Future Sight (Gen 5+)");

View file

@ -0,0 +1,6 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Entrainment changes the target's Ability to match the user's");
TO_DO_BATTLE_TEST("Entrainment fails if the user's ability has cantBeCopied flag");
TO_DO_BATTLE_TEST("Entrainment fails if the targets's ability has cantBeOverwritten flag");

View file

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Sweet Scent lowers evasion by 1 stage (Gen 2-5)");

View file

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Sweet Scent lowers evasion by 1 stage (Gen 6+)");

View file

@ -6,7 +6,7 @@ ASSUMPTIONS
ASSUME(GetMoveEffect(MOVE_DOUBLE_TEAM) == EFFECT_EVASION_UP);
}
SINGLE_BATTLE_TEST("Double Team raises Evasion")
SINGLE_BATTLE_TEST("Double Team raises Evasion by 1 stage")
{
PASSES_RANDOMLY(GetMoveAccuracy(MOVE_SCRATCH) * 3 / 4, 100, RNG_ACCURACY);
GIVEN {

View file

@ -0,0 +1,28 @@
#include "global.h"
#include "test/battle.h"
// There's no move with EFFECT_EVASION_UP_2 effect. Below is a theoretical test.
/*
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_X].effect == EFFECT_EVASION_UP_2);
}
SINGLE_BATTLE_TEST("Double Team raises Evasion by 1 stage")
{
PASSES_RANDOMLY(gMovesInfo[MOVE_SCRATCH].accuracy * 3 / 5, 100, RNG_ACCURACY);
GIVEN {
ASSUME(gMovesInfo[MOVE_SCRATCH].accuracy == 100);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_X); MOVE(opponent, MOVE_SCRATCH); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_X, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's evasiveness sharply rose!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
}
}
*/

View file

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Expanding Force's power increases by 50% if the user is affected by Psychic Terrain");

View file

@ -0,0 +1,4 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Extreme Evoboost increases the user's Attack, Defense, Special Attack, Special Defense, and Speed stats by 2 stages each");

View file

@ -18,25 +18,6 @@ SINGLE_BATTLE_TEST("Grassy Terrain recovers 1/16th HP at end of turn")
}
}
SINGLE_BATTLE_TEST("Grassy Terrain activates Grassy Seed and Mimicry")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_GRASSY_SEED].holdEffect == HOLD_EFFECT_SEEDS);
ASSUME(gItemsInfo[ITEM_GRASSY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_GRASSY_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRASSY_SEED); }
OPPONENT(SPECIES_STUNFISK_GALAR) { Ability(ABILITY_MIMICRY); }
} WHEN {
TURN { MOVE(player, MOVE_GRASSY_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!");
ABILITY_POPUP(opponent);
MESSAGE("The opposing Stunfisk's type changed to Grass!");
} THEN {
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[0], TYPE_GRASS);
}
}
SINGLE_BATTLE_TEST("Grassy Terrain increases power of Grass-type moves by 30/50 percent", s16 damage)
{
bool32 terrain;

View file

@ -83,7 +83,7 @@ SINGLE_BATTLE_TEST("Ice Spinner doesn't fail if there is no terrain on the field
}
}
AI_SINGLE_BATTLE_TEST("Steel Roller will not be chosen by the AI if it might fail")
AI_SINGLE_BATTLE_TEST("AI will not choose Steel Roller if it might fail")
{
u32 move;
@ -104,7 +104,7 @@ AI_SINGLE_BATTLE_TEST("Steel Roller will not be chosen by the AI if it might fai
}
}
AI_SINGLE_BATTLE_TEST("Ice Spinner can be chosen by the AI regardless if there is a terrain or not")
AI_SINGLE_BATTLE_TEST("AI will can choose Ice Spinner regardless if there is a terrain or not")
{
u32 move;
@ -124,35 +124,3 @@ AI_SINGLE_BATTLE_TEST("Ice Spinner can be chosen by the AI regardless if there i
}
}
}
SINGLE_BATTLE_TEST("Steel Roller and Ice Spinner reverts typing on Mimicry users")
{
u32 j;
static const u16 terrainMoves[] =
{
MOVE_ELECTRIC_TERRAIN,
MOVE_PSYCHIC_TERRAIN,
MOVE_GRASSY_TERRAIN,
MOVE_MISTY_TERRAIN,
};
u16 terrainMove = MOVE_NONE;
u16 removeTerrainMove = MOVE_NONE;
for (j = 0; j < ARRAY_COUNT(terrainMoves); j++)
{
PARAMETRIZE { removeTerrainMove = MOVE_STEEL_ROLLER; terrainMove = terrainMoves[j]; }
PARAMETRIZE { removeTerrainMove = MOVE_ICE_SPINNER; terrainMove = terrainMoves[j]; }
}
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_STUNFISK_GALAR].types[1] == TYPE_STEEL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_STUNFISK_GALAR) { Ability(ABILITY_MIMICRY); }
} WHEN {
TURN { MOVE(opponent, terrainMove); MOVE(player, removeTerrainMove); }
TURN { MOVE(player, MOVE_TOXIC); }
} SCENE {
MESSAGE("It doesn't affect the opposing Stunfisk…");
}
}

View file

@ -19,25 +19,6 @@ SINGLE_BATTLE_TEST("Misty Terrain protects grounded battlers from non-volatile s
}
}
SINGLE_BATTLE_TEST("Misty Terrain activates Misty Seed and Mimicry")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_MISTY_SEED].holdEffect == HOLD_EFFECT_SEEDS);
ASSUME(gItemsInfo[ITEM_MISTY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_MISTY_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MISTY_SEED); }
OPPONENT(SPECIES_STUNFISK_GALAR) { Ability(ABILITY_MIMICRY); }
} WHEN {
TURN { MOVE(player, MOVE_MISTY_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!");
ABILITY_POPUP(opponent);
MESSAGE("The opposing Stunfisk's type changed to Fairy!");
} THEN {
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[0], TYPE_FAIRY);
}
}
SINGLE_BATTLE_TEST("Misty Terrain does not increase the power of Fairy-type moves", s16 damage)
{
bool32 terrain;

View file

@ -200,30 +200,6 @@ DOUBLE_BATTLE_TEST("Scale Shot does not corrupt the next turn move used")
}
}
SINGLE_BATTLE_TEST("Endure does not prevent multiple hits and stat changes occur at the end of the turn")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_SCALE_SHOT) == EFFECT_MULTI_HIT);
ASSUME(GetMoveEffect(MOVE_ENDURE) == EFFECT_ENDURE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
} WHEN {
TURN { MOVE(opponent, MOVE_ENDURE); MOVE(player, MOVE_SCALE_SHOT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENDURE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALE_SHOT, player);
MESSAGE("The Pokémon was hit 5 time(s)!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Defense fell!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Speed rose!");
}
}
SINGLE_BATTLE_TEST("Scale Shot decreases defense and increases speed after the 4th hit of Loaded Dice")
{
PASSES_RANDOMLY(50, 100, RNG_LOADED_DICE);

View file

@ -18,25 +18,6 @@ SINGLE_BATTLE_TEST("Psychic Terrain protects grounded battlers from priority mov
}
}
SINGLE_BATTLE_TEST("Psychic Terrain activates Psychic Seed and Mimicry")
{
GIVEN {
ASSUME(gItemsInfo[ITEM_PSYCHIC_SEED].holdEffect == HOLD_EFFECT_SEEDS);
ASSUME(gItemsInfo[ITEM_PSYCHIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_SEED); }
OPPONENT(SPECIES_STUNFISK_GALAR) { Ability(ABILITY_MIMICRY); }
} WHEN {
TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!");
ABILITY_POPUP(opponent);
MESSAGE("The opposing Stunfisk's type changed to Psychic!");
} THEN {
EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[0], TYPE_PSYCHIC);
}
}
SINGLE_BATTLE_TEST("Psychic Terrain increases power of Psychic-type moves by 30/50 percent", s16 damage)
{
bool32 terrain;

View file

@ -10,7 +10,7 @@
#include "test_runner.h"
#include "test/test.h"
#define TIMEOUT_SECONDS 55
#define TIMEOUT_SECONDS 60
void CB2_TestRunner(void);