diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 8240a56801..0a3eff0e43 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -23,20 +23,15 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.3 (Latest release) + - 1.10.0 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.4 + - 1.9.3 - 1.9.2 - 1.9.1 - 1.9.0 - - 1.8.6 - - 1.8.5 - - 1.8.4 - - 1.8.3 - - 1.8.2 - - 1.8.1 - - 1.8.0 - - pre-1.8.0 + - pre-1.9.0 validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 5688f8a7fb..4b8eec3a43 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -23,20 +23,15 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.3 (Latest release) + - 1.10.0 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.4 + - 1.9.3 - 1.9.2 - 1.9.1 - 1.9.0 - - 1.8.6 - - 1.8.5 - - 1.8.4 - - 1.8.3 - - 1.8.2 - - 1.8.1 - - 1.8.0 - - pre-1.8.0 + - pre-1.9.0 validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index add0633d95..54335ca5e4 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -23,20 +23,15 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.3 (Latest release) + - 1.10.0 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.4 + - 1.9.3 - 1.9.2 - 1.9.1 - 1.9.0 - - 1.8.6 - - 1.8.5 - - 1.8.4 - - 1.8.3 - - 1.8.2 - - 1.8.1 - - 1.8.0 - - pre-1.8.0 + - pre-1.9.0 validations: required: true - type: input diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9fec3e7e..13d6e4f4eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Pokeemerald-Expansion Changelogs +## 1.10.x +- **[Version 1.10.0](docs/changelogs/1.10.x/1.10.0.md) - ✨ Feature Release** + ## 1.9.x +- **[Version 1.9.4](docs/changelogs/1.9.x/1.9.4.md) - 🧹 Bugfix Release** +- **[Version 1.9.3](docs/changelogs/1.9.x/1.9.3.md) - 🧹 Bugfix Release** - **[Version 1.9.2](docs/changelogs/1.9.x/1.9.2.md) - 🧹 Bugfix Release** - **[Version 1.9.1](docs/changelogs/1.9.x/1.9.1.md) - 🧹 Bugfix Release** - **[Version 1.9.0](docs/changelogs/1.9.x/1.9.0.md) - ✨ Feature Release** diff --git a/Makefile b/Makefile index f38b551b0c..71d2a48af9 100644 --- a/Makefile +++ b/Makefile @@ -438,6 +438,7 @@ libagbsyscall: @$(MAKE) -C libagbsyscall TOOLCHAIN=$(TOOLCHAIN) MODERN=1 # Elf from object files +LDFLAGS = -Map ../../$(MAP) $(ELF): $(LD_SCRIPT) $(LD_SCRIPT_DEPS) $(OBJS) libagbsyscall @cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ../../$< --print-memory-usage -o ../../$@ $(OBJS_REL) $(LIB) | cat @echo "cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ../../$< --print-memory-usage -o ../../$@ | cat" diff --git a/README.md b/README.md index 5330e40981..277dae2be7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ pokeemerald-expansion is a decomp hack base project based off pret's [pokeemeral 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.9.3 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.10.0 https://github.com/rh-hideout/pokeemerald-expansion/ ``` Please follow the instructions in `INSTALL.md` to get pokeemerald-expansion set up on your machine. @@ -177,7 +177,7 @@ With this, you'll get the latest version of pokeemerald-expansion, plus a couple - Check your current version. - You can check in the debug menu's `Utilities -> Expansion Version` option. - If the option is not available, you possibly have version 1.6.2 or older. In that case, please check the [changelogs](CHANGELOG.md) to determine your version based on the features available on your repository. -- Once you have your remote set up, run the command `git pull RHH expansion/X.Y.Z`, replacing X, Y and Z with the digits of the respective version you want to update to (eg, to update to 1.9.3, use `git pull RHH expansion/1.9.3`). +- Once you have your remote set up, run the command `git pull RHH expansion/X.Y.Z`, replacing X, Y and Z with the digits of the respective version you want to update to (eg, to update to 1.10.0, use `git pull RHH expansion/1.10.0`). - ***Important:*** If you are several versions behind, we recommend updating one minor version at a time, skipping directly to the latest patch version (eg, 1.5.3 -> 1.6.2 -> 1.7.4 and so on) - Alternatively, you can update to unreleased versions of the expansion. - ***master (stable):*** It contains unreleased **bugfixes** that will come in the next patch version. To merge, use `git pull RHH master`. diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 6241f120b8..26835c2e0d 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -798,9 +798,7 @@ 2: .endm - .macro setmultihitcounter value:req - .byte 0x8d - .byte \value + .macro unused_0x8d .endm .macro initmultihitstring @@ -1669,6 +1667,11 @@ callnative BS_DamageToQuarterTargetHP .endm + .macro jumpifsleepclause jumpInstr:req + callnative BS_JumpIfSleepClause + .4byte \jumpInstr + .endm + .macro ficklebeamdamagecalculation callnative BS_FickleBeamDamageCalculation .endm @@ -2027,9 +2030,10 @@ .4byte \jumpInstr .endm - .macro trypsychoshift failInstr:req + .macro trypsychoshift failInstr:req sleepClauseFailInstr:req various BS_ATTACKER, VARIOUS_PSYCHO_SHIFT .4byte \failInstr + .4byte \sleepClauseFailInstr .endm .macro curestatus battler:req diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 07d172cdf8..80d50710ba 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -34742,7 +34742,7 @@ gBattleAnimMove_GMaxTerror:: gBattleAnimMove_MaxPhantasm:: createvisualtask AnimTask_DynamaxGrowth, 0x5, 0x1, 0x1 waitforvisualfinish - goto gBattleAnimMove_PhantomForce + goto gBattleAnimMove_ShadowBall end gBattleAnimMove_GMaxGravitas:: diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 43eb17880f..44cb8ff6bc 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1639,7 +1639,7 @@ BattleScript_EffectPsychoShift:: BattleScript_EffectPsychoShiftCanWork: jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed jumpifsafeguard BattleScript_SafeguardProtected - trypsychoshift BattleScript_ButItFailed + trypsychoshift BattleScript_ButItFailed, BattleScript_SleepClauseBlocked attackanimation waitanimation copybyte gEffectBattler, gBattlerTarget @@ -2892,6 +2892,7 @@ BattleScript_EffectSleep:: jumpifleafguardprotected BS_TARGET, BattleScript_AbilityProtectsDoesntAffect jumpifshieldsdown BS_TARGET, BattleScript_AbilityProtectsDoesntAffect jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed + jumpifsleepclause BattleScript_SleepClauseBlocked jumpifterrainaffected BS_TARGET, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE @@ -3869,26 +3870,39 @@ BattleScript_EffectDoNothing:: attackcanceler attackstring ppreduce - jumpifmove MOVE_HOLD_HANDS, BattleScript_EffectHoldHands attackanimation waitanimation - jumpifmove MOVE_CELEBRATE, BattleScript_EffectCelebrate - jumpifmove MOVE_HAPPY_HOUR, BattleScript_EffectHappyHour incrementgamestat GAME_STAT_USED_SPLASH printstring STRINGID_BUTNOTHINGHAPPENED waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectHoldHands: + +BattleScript_EffectHoldHands:: + attackcanceler + attackstring + ppreduce jumpifsideaffecting BS_TARGET, SIDE_STATUS_CRAFTY_SHIELD, BattleScript_ButItFailed jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_ButItFailed attackanimation waitanimation goto BattleScript_MoveEnd -BattleScript_EffectCelebrate: + +BattleScript_EffectCelebrate:: + attackcanceler + attackstring + ppreduce + attackanimation + waitanimation printstring STRINGID_CELEBRATEMESSAGE waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectHappyHour: + +BattleScript_EffectHappyHour:: + attackcanceler + attackstring + ppreduce + attackanimation + waitanimation seteffectprimary MOVE_EFFECT_HAPPY_HOUR goto BattleScript_MoveEnd @@ -5140,6 +5154,7 @@ BattleScript_EffectYawn:: jumpifflowerveil BattleScript_FlowerVeilProtects jumpifleafguardprotected BS_TARGET, BattleScript_AbilityProtectsDoesntAffect jumpifshieldsdown BS_TARGET, BattleScript_AbilityProtectsDoesntAffect + jumpifsleepclause BattleScript_SleepClauseBlocked jumpifsubstituteblocks BattleScript_ButItFailed jumpifsafeguard BattleScript_SafeguardProtected accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON @@ -10081,3 +10096,16 @@ BattleScript_EffectSnow:: call BattleScript_CheckPrimalWeather setfieldweather ENUM_WEATHER_SNOW goto BattleScript_MoveWeatherChange + +BattleScript_SleepClauseBlocked:: + pause B_WAIT_TIME_SHORT + setmoveresultflags MOVE_RESULT_FAILED + printstring STRINGID_BLOCKEDBYSLEEPCLAUSE + waitmessage B_WAIT_TIME_LONG + goto BattleScript_MoveEnd + +BattleScript_SleepClausePreventsEnd:: + pause B_WAIT_TIME_SHORT + printstring STRINGID_BLOCKEDBYSLEEPCLAUSE + waitmessage B_WAIT_TIME_LONG + end2 diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index ac4698fdc3..cb02bb306e 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -18,7 +18,10 @@ - [v1.6.x](tutorials/how_to_new_pokemon_1_6_0.md) - [How to use the Testing System](tutorials/how_to_testing_system.md) - [Changelog](./CHANGELOG.md) + - [1.10.x]() + - [Version 1.10.0](changelogs/1.9.x/1.9.4.md) - [1.9.x]() + - [Version 1.9.4](changelogs/1.9.x/1.9.4.md) - [Version 1.9.3](changelogs/1.9.x/1.9.3.md) - [Version 1.9.2](changelogs/1.9.x/1.9.2.md) - [Version 1.9.1](changelogs/1.9.x/1.9.1.md) diff --git a/docs/changelogs/1.10.0/1.10.0.md b/docs/changelogs/1.10.0/1.10.0.md new file mode 100644 index 0000000000..9cf2f9b41e --- /dev/null +++ b/docs/changelogs/1.10.0/1.10.0.md @@ -0,0 +1,324 @@ +# Version 1.10.0 + +```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.0`. +``` + +## 🌋 *REFACTORS* 🌋 +📜 = Uses a migration script. +* Changes Evolution methods to Enums by @AlexOn1ine in [#4977](https://github.com/rh-hideout/pokeemerald-expansion/pull/4977) +* Turn item hold effects into an enum by @Bassoonian in [#5498](https://github.com/rh-hideout/pokeemerald-expansion/pull/5498) +* Change `GET_MOVE_TYPE` to a function by @AlexOn1ine in [#5090](https://github.com/rh-hideout/pokeemerald-expansion/pull/5090) +* Created `COMPOUND_STRING`s for default player names by @fdeblasio in [#5037](https://github.com/rh-hideout/pokeemerald-expansion/pull/5037) +* Removed agbcc by @mrgriffin in [#4994](https://github.com/rh-hideout/pokeemerald-expansion/pull/4994) +* Refactor Frontier Brains by @fdeblasio in [#5027](https://github.com/rh-hideout/pokeemerald-expansion/pull/5027) +* Removed all instances of `gBitTable[x]` by @hedara90 in [#5123](https://github.com/rh-hideout/pokeemerald-expansion/pull/5123) +* Made `BuildColorMaps` redundant by using static tables by @pkmnsnfrn in [#5289](https://github.com/rh-hideout/pokeemerald-expansion/pull/5289) +* Removed `FRONTIER_BRAIN_SPRITES` and updated `TRAINER_SPRITE`, `TRAINER_BACK_SPRITE`, and `TRAINER_CLASS` by @fdeblasio in [#5166](https://github.com/rh-hideout/pokeemerald-expansion/pull/5166) +* Added `ShouldSwitch` result to `AiLogicData` by @Pawkkie and @AlexOn1ine had the idea! in [#5440](https://github.com/rh-hideout/pokeemerald-expansion/pull/5440) +* Switch AI refactor + considers free switches by @Pawkkie in [#5379](https://github.com/rh-hideout/pokeemerald-expansion/pull/5379) +* Refactor `ShouldSwitchIfAllBadMoves` by @Pawkkie in [#5452](https://github.com/rh-hideout/pokeemerald-expansion/pull/5452) +* Updated Wring Out effects to match Eruption effects by @AsparagusEduardo in [#5549](https://github.com/rh-hideout/pokeemerald-expansion/pull/5549) + - Changed Wring Out/Crush Grip/Hard Press to use `power` instead of `argument` to determine its max power, just like how Eruption/Water Spout/Dragon Energy do it. + - Also: + - Renamed `EFFECT_VARY_POWER_BASED_ON_HP` to `EFFECT_POWER_BASED_ON_TARGET_HP` + - Renamed `EFFECT_ERUPTION` to `EFFECT_POWER_BASED_ON_USER_HP` +* Update battle messages to Gen 5+ standards by @kittenchilly in [#3240](https://github.com/rh-hideout/pokeemerald-expansion/pull/3240) +* Should switch refactor to facilitate switch prediction by @Pawkkie in [#5466](https://github.com/rh-hideout/pokeemerald-expansion/pull/5466) +* Unwind `TRAINER_CLASS` macro by @SBird1337 in [#5611](https://github.com/rh-hideout/pokeemerald-expansion/pull/5611) +* Refactors Absorb to use `Moveend` by @AlexOn1ine in [#5670](https://github.com/rh-hideout/pokeemerald-expansion/pull/5670) + * For new absorbing moves an argument should be added in `moves_info.h` +* Changes name of `B_SCR_NAME_WITH_PREFIX` by @AlexOn1ine in [#5675](https://github.com/rh-hideout/pokeemerald-expansion/pull/5675) + +## 🧬 General 🧬 +### Added +* Added performance counter by @hedara90 and @SBird1337 provided the actual code in [#5284](https://github.com/rh-hideout/pokeemerald-expansion/pull/5284) +* Added debug build target by @u8-Salem in [#4817](https://github.com/rh-hideout/pokeemerald-expansion/pull/4817) +* Added `AUTO_SCROLL_TEXT` and `NUM_FRAMES_AUTO_SCROLL_DELAY` by @pkmnsnfrn in [#5054](https://github.com/rh-hideout/pokeemerald-expansion/pull/5054) +* Adds `SAVE_TYPE_ERROR_SCREEN` by @pkmnsnfrn in [#5188](https://github.com/rh-hideout/pokeemerald-expansion/pull/5188) +* Move Relearner and Renaming From Summary Screen by @ravepossum in [#5513](https://github.com/rh-hideout/pokeemerald-expansion/pull/5513) +* Automatic Line Breaks, somewhat even lines by @hedara90 and @AsparagusEduardo in [#5689](https://github.com/rh-hideout/pokeemerald-expansion/pull/5689) + - Automatically insert line breaks into a string with `BreakStringAutomatic`. + - This function does not modify strings with existing line breaks. + - Remove existing line breaks from a string with `StripLineBreaks`. + +### Changed +* Removed agbcc by @mrgriffin in [#4994](https://github.com/rh-hideout/pokeemerald-expansion/pull/4994) +* Removed all instances of `gBitTable[x]` by @hedara90 in [#5123](https://github.com/rh-hideout/pokeemerald-expansion/pull/5123) +* Converted Mechadoll text to `COMPOUND_STRING`s by @fdeblasio in [#5276](https://github.com/rh-hideout/pokeemerald-expansion/pull/5276) +* New terrain bgs by @TheTrueSadfish in [#5162](https://github.com/rh-hideout/pokeemerald-expansion/pull/5162) +* Removed agbcc screenshots from `.gitignore` by @Bassoonian in [#5538](https://github.com/rh-hideout/pokeemerald-expansion/pull/5538) +* Set default battle shadow to Gen3 by @hedara90 in [#5632](https://github.com/rh-hideout/pokeemerald-expansion/pull/5632) + - Note: Trainerslides don't work properly with Gen4 shadows. +* Convert 3 variouses to `callnatives` by @AlexOn1ine in [#5646](https://github.com/rh-hideout/pokeemerald-expansion/pull/5646) + +## 🗺️ Overworld 🗺️ +### Added +* FRLG+ whiteout message by @cawtds in [#4967](https://github.com/rh-hideout/pokeemerald-expansion/pull/4967) +* Dynamic Move Types in Summary Screen/Battle by @Galaxeeh in [#5084](https://github.com/rh-hideout/pokeemerald-expansion/pull/5084) +* Adds `OW_BERRY_IMMORTAL` by @pkmnsnfrn in [#5187](https://github.com/rh-hideout/pokeemerald-expansion/pull/5187) +* (Default Off) Item Description Headers by @ghoulslash in [#4767](https://github.com/rh-hideout/pokeemerald-expansion/pull/4767) +* RTC-based wild encounters by @hjk321 in [#5313](https://github.com/rh-hideout/pokeemerald-expansion/pull/5313) +* Added `MB_X_Y_STAIR_WARP` metatile behaviors by @pkmnsnfrn in [#5278](https://github.com/rh-hideout/pokeemerald-expansion/pull/5278) +* Added Sideways Stairs by @ghoulslash in [#4836](https://github.com/rh-hideout/pokeemerald-expansion/pull/4836) +* Added `OW_UNION_DISABLE_CHECK` and `OW_FLAG_MOVE_UNION_ROOM_CHECK` by @pkmnsnfrn in [#5448](https://github.com/rh-hideout/pokeemerald-expansion/pull/5448) +* Adds new scripting macros to increase developer quality of life by @pkmnsnfrn in [#5177](https://github.com/rh-hideout/pokeemerald-expansion/pull/5177) +* Added more later gen fishing mechanics by @kittenchilly in [#5518](https://github.com/rh-hideout/pokeemerald-expansion/pull/5518) + +### Changed +* Created PokeNav `COMPOUND_STRING`s by @fdeblasio in [#4983](https://github.com/rh-hideout/pokeemerald-expansion/pull/4983) +* Added `I_REPEL_INCLUDE_FAINTED` config and behavior by @kittenchilly in [#5239](https://github.com/rh-hideout/pokeemerald-expansion/pull/5239) +* RTC-based wild encounters follow up by @AlexOn1ine in [#5328](https://github.com/rh-hideout/pokeemerald-expansion/pull/5328) +* Revert rtc based encounters by @AlexOn1ine in [#5331](https://github.com/rh-hideout/pokeemerald-expansion/pull/5331) +* Made BuildColorMaps redundant by using static tables by @pkmnsnfrn in [#5289](https://github.com/rh-hideout/pokeemerald-expansion/pull/5289) +* Added `OW_AUTO_SIGNPOST` and associated metatile behaviors by @pkmnsnfrn in [#5044](https://github.com/rh-hideout/pokeemerald-expansion/pull/5044) +* Added support for overworld sprite gender differences + add all the sprites by @kittenchilly in [#5394](https://github.com/rh-hideout/pokeemerald-expansion/pull/5394) + +### Fixed +* Added some null pointer checks by @tertu-m in [#5130](https://github.com/rh-hideout/pokeemerald-expansion/pull/5130) +* Reset item flags on new game by @ghoulslash in [#5363](https://github.com/rh-hideout/pokeemerald-expansion/pull/5363) +* Follower female fix by @hedara90 in [#5475](https://github.com/rh-hideout/pokeemerald-expansion/pull/5475) + +## 🐉 Pokémon 🐉 +### Added +* Added config to change Vivillon's breeding form by @kittenchilly in [#4813](https://github.com/rh-hideout/pokeemerald-expansion/pull/4813) +* Added back GBA sprites via config by @AsparagusEduardo and @AlexOn1ine for their help with script to migrate data from vanilla to our current `gSpeciesInfo` in [#5206](https://github.com/rh-hideout/pokeemerald-expansion/pull/5206) +* Added config to disable gender differences by @AsparagusEduardo in [#5595](https://github.com/rh-hideout/pokeemerald-expansion/pull/5595) + +### Changed +* Made perfect IV count into a granular setting by @AsparagusEduardo in [#5115](https://github.com/rh-hideout/pokeemerald-expansion/pull/5115) +* Updated species defines by @pkmnsnfrn in [#5075](https://github.com/rh-hideout/pokeemerald-expansion/pull/5075) +* Added support for overworld sprite gender differences + add all the sprites by @kittenchilly in [#5394](https://github.com/rh-hideout/pokeemerald-expansion/pull/5394) +* Renamed folders and symbols to match species defines by @AsparagusEduardo in [#5581](https://github.com/rh-hideout/pokeemerald-expansion/pull/5581) + - Burmy and Wormadam footprints were in a `plant` subfolder. They have been moved to the species root folder + - Paldean Wooper's subfolder was named `wooper_paldean` instead of just `paldean`. This has been corrected. + - Zen Mode Galarian Darmanitan's folder was located in `darmanitan/galarian/zen_mode`. This has been corrected to `darmanitan/galar_zen`, alongside Galarian Standard Mode's `darmanitan/galar_standard`. + - Also updated Ogerpon's folders similarly. + - Renamed `SPECIES_PIKACHU_PARTNER_CAP` to `SPECIES_PIKACHU_PARTNER`. +* Changing `EVO_NONE` from `0xFFFE` to `0` by @GhoulMage in [#5547](https://github.com/rh-hideout/pokeemerald-expansion/pull/5547) + - There could be a case for out of bounds errors if arrays or iterations are happening where you're using + 1 or - 1, as `EVO_FRIENDSHIP` used to be the first index although it started with 1. + +### Fixed +* Follower female fix by @hedara90 in [#5475](https://github.com/rh-hideout/pokeemerald-expansion/pull/5475) +* Fixed some gba sprites by @SubzeroEclipse in [#5607](https://github.com/rh-hideout/pokeemerald-expansion/pull/5607) + +## ⚔️ Battle General ⚔️ +### Added +* FRLG+ whiteout message by @cawtds in [#4967](https://github.com/rh-hideout/pokeemerald-expansion/pull/4967) +* Added B_SHOW_TYPES and cleaned up IsDoubleBattle by @pkmnsnfrn in [#5131](https://github.com/rh-hideout/pokeemerald-expansion/pull/5131) +* EV Caps and EV Items by @Flash1Lucky and @AlexOn1ine in [#5269](https://github.com/rh-hideout/pokeemerald-expansion/pull/5269) +* Added in-battle shadows underneath all enemy battlers by @lhearachel in [#5178](https://github.com/rh-hideout/pokeemerald-expansion/pull/5178) +* Added Gen 1 Crit Chance by @Pawkkie in [#5439](https://github.com/rh-hideout/pokeemerald-expansion/pull/5439) +* Added battle flag that prevents running from wild Pokémon by @SarnPoke in [#5502](https://github.com/rh-hideout/pokeemerald-expansion/pull/5502) + +### Changed +* Refactor Frontier Brains by @fdeblasio in [#5027](https://github.com/rh-hideout/pokeemerald-expansion/pull/5027) +* Removed some hardcoding of move IDs + Gen4/5 Defog by @AsparagusEduardo in [#5156](https://github.com/rh-hideout/pokeemerald-expansion/pull/5156) +* Convert 8 various to `callnatives` by @AsparagusEduardo in [#5172](https://github.com/rh-hideout/pokeemerald-expansion/pull/5172) +* Anger Shell use `saveattacker` by @ghoulslash in [#5409](https://github.com/rh-hideout/pokeemerald-expansion/pull/5409) +* Clean up Unseen Fist Check by @AlexOn1ine in [#5420](https://github.com/rh-hideout/pokeemerald-expansion/pull/5420) +* Updated species defines by @pkmnsnfrn in [#5075](https://github.com/rh-hideout/pokeemerald-expansion/pull/5075) +* Removes Crit Chance preproc by @AlexOn1ine in [#5520](https://github.com/rh-hideout/pokeemerald-expansion/pull/5520) +* Update battle messages to Gen 5+ standards by @kittenchilly in [#3240](https://github.com/rh-hideout/pokeemerald-expansion/pull/3240) +* More post-#3240 cleanup by @kittenchilly in [#5593](https://github.com/rh-hideout/pokeemerald-expansion/pull/5593) +* Unwind `TRAINER_CLASS` macro by @SBird1337 in [#5611](https://github.com/rh-hideout/pokeemerald-expansion/pull/5611) +* Removes redundant Decorate check by @AlexOn1ine in [#5696](https://github.com/rh-hideout/pokeemerald-expansion/pull/5696) +* Changes target bit of Flower Shield by @AlexOn1ine in [#5698](https://github.com/rh-hideout/pokeemerald-expansion/pull/5698) + +### Fixed +* Fixed a sprite issue with `B_SHOW_TYPES` by @pkmnsnfrn in [#5157](https://github.com/rh-hideout/pokeemerald-expansion/pull/5157) +* Dynamic Move Display fixes by @Galaxeeh in [#5251](https://github.com/rh-hideout/pokeemerald-expansion/pull/5251) +* Fixed a display issue with `B_SHOW_TYPES` by @pkmnsnfrn and @iriv24 in [#5201](https://github.com/rh-hideout/pokeemerald-expansion/pull/5201) +* Fixed Gen 3 foreseen and Beat Up damage type by @hedara90 in [#5323](https://github.com/rh-hideout/pokeemerald-expansion/pull/5323) +* Fixes Defog used by the wrong side when there is a Substitue and Screen by @AlexOn1ine in [#5381](https://github.com/rh-hideout/pokeemerald-expansion/pull/5381) +* Fixes Hidden Power dynamic type bug by @AlexOn1ine in [#5463](https://github.com/rh-hideout/pokeemerald-expansion/pull/5463) +* Display the correct shadow size when sending out a new Pokemon by @lhearachel in [#5618](https://github.com/rh-hideout/pokeemerald-expansion/pull/5618) +* Fixed text wrap obtaining the incorrect glyph width by @AsparagusEduardo and @AlexOn1ine for their help verifying that the fix works with one of his custom strings in [#5620](https://github.com/rh-hideout/pokeemerald-expansion/pull/5620) +* Improve line breaks/scrolls by @cawtds in [#5641](https://github.com/rh-hideout/pokeemerald-expansion/pull/5641) +* Fixed Order Up + Tera Stellar breaking each other with Commander by @PhallenTree in [#5667](https://github.com/rh-hideout/pokeemerald-expansion/pull/5667) +* Fixes wrong Id when AI chooses mon to switch in by @AlexOn1ine in [#5684](https://github.com/rh-hideout/pokeemerald-expansion/pull/5684) +* Fixes Absorb regression caused by #5670 by @AlexOn1ine in [#5688](https://github.com/rh-hideout/pokeemerald-expansion/pull/5688) +* Fixes heal blocked leeach seed in tests by @AlexOn1ine in [#5700](https://github.com/rh-hideout/pokeemerald-expansion/pull/5700) +* Trainer class+name expansion fix for Battle Frontier by @hedara90 in [#5699](https://github.com/rh-hideout/pokeemerald-expansion/pull/5699) + +## 🤹 Moves 🤹 +### Changed +* Added Population Bomb animation by @kittenchilly in [#5194](https://github.com/rh-hideout/pokeemerald-expansion/pull/5194) +* Move battle anim arrays to C by @cawtds in [#5306](https://github.com/rh-hideout/pokeemerald-expansion/pull/5306) +* Grass/Water Pledge Swamp Animation + Sea of Fire animation tweak by @SonikkuA-DatH in [#5325](https://github.com/rh-hideout/pokeemerald-expansion/pull/5325) +* New animations for many moves more details in description by @TheTrueSadfish in [#5367](https://github.com/rh-hideout/pokeemerald-expansion/pull/5367) +* Use move effect for some moves instead of ids by @AlexOn1ine in [#5433](https://github.com/rh-hideout/pokeemerald-expansion/pull/5433) +* Adds Commander and Order Up by @AlexOn1ine in [#5246](https://github.com/rh-hideout/pokeemerald-expansion/pull/5246) +* Heart Swap Move Animation by @SonikkuA-DatH in [#5460](https://github.com/rh-hideout/pokeemerald-expansion/pull/5460) +* Update `shed_tail.c` by @Bassoonian in [#5494](https://github.com/rh-hideout/pokeemerald-expansion/pull/5494) +* Added Ion Deluge animation by @kittenchilly in [#5467](https://github.com/rh-hideout/pokeemerald-expansion/pull/5467) +* Updated Wring Out effects to match Eruption effects by @AsparagusEduardo in [#5549](https://github.com/rh-hideout/pokeemerald-expansion/pull/5549) + - Changed Wring Out/Crush Grip/Hard Press to use `power` instead of `argument` to determine its max power, just like how Eruption/Water Spout/Dragon Energy do it. Also: + - Renamed `EFFECT_VARY_POWER_BASED_ON_HP` to `EFFECT_POWER_BASED_ON_TARGET_HP` + - Renamed `EFFECT_ERUPTION` to `EFFECT_POWER_BASED_ON_USER_HP` +* Refactors Absorb to use Moveend by @AlexOn1ine in [#5670](https://github.com/rh-hideout/pokeemerald-expansion/pull/5670) + * For new absorbing moves an argument should be added in `moves_info.h` + +### Fixed +* Dark Void, Clangorous Soulblaze, vortex animation fixes by @TheTrueSadfish in [#5650](https://github.com/rh-hideout/pokeemerald-expansion/pull/5650) + +## 🎭 Abilities 🎭 +### Changed +* Adds Commander and Order Up by @AlexOn1ine in [#5246](https://github.com/rh-hideout/pokeemerald-expansion/pull/5246) + +## 🧶 Items 🧶 +### Added +* Adds `OW_BERRY_IMMORTAL` by @pkmnsnfrn in [#5187](https://github.com/rh-hideout/pokeemerald-expansion/pull/5187) +* Added functionality to Poké Flute and Town Map by @kittenchilly and @LOuroboros basically did the Town Map implementation in [#5405](https://github.com/rh-hideout/pokeemerald-expansion/pull/5405) +* Decouple Poke Ball ids from item ids by @AlexOn1ine in [#5560](https://github.com/rh-hideout/pokeemerald-expansion/pull/5560) + +### Changed +* Consolidated the values of Rotom's moves and added Gen9 base form effect by @fdeblasio in [#5186](https://github.com/rh-hideout/pokeemerald-expansion/pull/5186) +* Added `I_REPEL_INCLUDE_FAINTED` config and behavior by @kittenchilly in [#5239](https://github.com/rh-hideout/pokeemerald-expansion/pull/5239) + +### Fixed +* Replace hardcoded flute check with consumability check by @Bassoonian in [#5508](https://github.com/rh-hideout/pokeemerald-expansion/pull/5508) + +## 🤖 Battle AI 🤖 +### Added +* Adds config to show target of ingame partner by @AlexOn1ine in [#5307](https://github.com/rh-hideout/pokeemerald-expansion/pull/5307) +* Switch AI refactor + considers free switches by @Pawkkie in [#5379](https://github.com/rh-hideout/pokeemerald-expansion/pull/5379) +* New AI flag for marking the two last Pokémon as Ace Pokémon by @GhoulMage in [#5587](https://github.com/rh-hideout/pokeemerald-expansion/pull/5587) + +### Changed +* Chilly Reception AI by @kittenchilly in [#5271](https://github.com/rh-hideout/pokeemerald-expansion/pull/5271) +* Shed Tail AI by @SarnPoke and @AlexOn1ine, @Pawkkie in [#5275](https://github.com/rh-hideout/pokeemerald-expansion/pull/5275) +* More missing AI logic by @kittenchilly in [#5279](https://github.com/rh-hideout/pokeemerald-expansion/pull/5279) +* Adds basic trainer and smart trainer flags by @AlexOn1ine in [#5298](https://github.com/rh-hideout/pokeemerald-expansion/pull/5298) +* `AI_FLAG_SETUP_FIRST_TURN` rename and clarifications by @Pawkkie in [#5310](https://github.com/rh-hideout/pokeemerald-expansion/pull/5310) +* Added Composite AI Flags to Docs by @Pawkkie in [#5349](https://github.com/rh-hideout/pokeemerald-expansion/pull/5349) +* AI frostbite score fixes and improvements by @Pawkkie and @kittenchilly for the suggestion! in [#5362](https://github.com/rh-hideout/pokeemerald-expansion/pull/5362) +* Switch AI `hitsToKO` considers one shot prevention by @Pawkkie in [#5371](https://github.com/rh-hideout/pokeemerald-expansion/pull/5371) +* Adds `CanEndureHit` AI function by @AlexOn1ine in [#5373](https://github.com/rh-hideout/pokeemerald-expansion/pull/5373) +* Switch AI `hitsToKO` considers Disguise by @Pawkkie in [#5375](https://github.com/rh-hideout/pokeemerald-expansion/pull/5375) +* Added `ShouldSwitch` result to `AiLogicData` by @Pawkkie and @AlexOn1ine had the idea! in [#5440](https://github.com/rh-hideout/pokeemerald-expansion/pull/5440) +* Removes duplicate code in AI functions by @AlexOn1ine in [#5457](https://github.com/rh-hideout/pokeemerald-expansion/pull/5457) +* Unify `GetBattlerAbility`/`TerrainAffected` to remove duplicate ai function by @AlexOn1ine in [#5497](https://github.com/rh-hideout/pokeemerald-expansion/pull/5497) +* `ShouldSwitchIfGameStatePrompt` Tests by @Pawkkie in [#5462](https://github.com/rh-hideout/pokeemerald-expansion/pull/5462) +* `AI_FLAG_ACE_POKEMON` takes into account separate trainers by @GhoulMage and @/uvula on Discord noted the weird behaviour. in [#5608](https://github.com/rh-hideout/pokeemerald-expansion/pull/5608) + - Fix for the AI not considering both trainers Ace Pokémons in double battles with `AI_FLAG_ACE_POKEMON`. +* Moves that deal a Fixed amount don't need AI handling by @AlexOn1ine in [#5614](https://github.com/rh-hideout/pokeemerald-expansion/pull/5614) +* Combines `CalculateMoveDamage` arguments into a struct by @AlexOn1ine in [#5570](https://github.com/rh-hideout/pokeemerald-expansion/pull/5570) + +### Fixed +* AI burn score fixes and improvements by @Pawkkie and @iriv24 and @AlexOn1ine in [#5356](https://github.com/rh-hideout/pokeemerald-expansion/pull/5356) +* Improve AI's Skill Swap handling in double battles by @Pawkkie in [#5360](https://github.com/rh-hideout/pokeemerald-expansion/pull/5360) +* Refactor `ShouldSwitchIfAllBadMoves` by @Pawkkie in [#5452](https://github.com/rh-hideout/pokeemerald-expansion/pull/5452) +* Should switch refactor to facilitate switch prediction by @Pawkkie in [#5466](https://github.com/rh-hideout/pokeemerald-expansion/pull/5466) +* Fixes Switch in flag not restoring mons properly with test by @Pawkkie and @iriv24 for finding, @AlexOn1ine for fixing in [#5746](https://github.com/rh-hideout/pokeemerald-expansion/pull/5746) + +## 🧹 Other Cleanup 🧹 +* Removed metadata in AIF files by @SombrAbsol in [#4958](https://github.com/rh-hideout/pokeemerald-expansion/pull/4958) +* Removed `gPaletteDecompressionBuffer` and unused palette functions/vars by @DizzyEggg in [#4841](https://github.com/rh-hideout/pokeemerald-expansion/pull/4841) +* Changes Evolution methods to `enum`s by @AlexOn1ine in [#4977](https://github.com/rh-hideout/pokeemerald-expansion/pull/4977) +* Doesn't compile on some compilers by @AlexOn1ine in [#5099](https://github.com/rh-hideout/pokeemerald-expansion/pull/5099) +* Update `event.inc` to accomodate new `gDecompressionBuffer` name by @Bassoonian in [#5100](https://github.com/rh-hideout/pokeemerald-expansion/pull/5100) +* Created `COMPOUND_STRING`s for default player names by @fdeblasio in [#5037](https://github.com/rh-hideout/pokeemerald-expansion/pull/5037) +* Changed single-use berry blender strings to be `COMPOUND_STRING`s by @fdeblasio in [#4963](https://github.com/rh-hideout/pokeemerald-expansion/pull/4963) +* Made perfect IV count into a granular setting by @AsparagusEduardo in [#5115](https://github.com/rh-hideout/pokeemerald-expansion/pull/5115) +* Dynamic move type clean up by @AlexOn1ine in [#5132](https://github.com/rh-hideout/pokeemerald-expansion/pull/5132) +* Refactor Frontier Brains by @fdeblasio in [#5027](https://github.com/rh-hideout/pokeemerald-expansion/pull/5027) +* Removed some hardcoding of move IDs + Gen4/5 Defog by @AsparagusEduardo in [#5156](https://github.com/rh-hideout/pokeemerald-expansion/pull/5156) +* Teatime animations use `B_WAIT_TIME_LONG` by @AsparagusEduardo in [#5173](https://github.com/rh-hideout/pokeemerald-expansion/pull/5173) +* Created PokeNav `COMPOUND_STRING`s by @fdeblasio in [#4983](https://github.com/rh-hideout/pokeemerald-expansion/pull/4983) +* Removed `gBitTable` usage again by @hedara90 in [#5193](https://github.com/rh-hideout/pokeemerald-expansion/pull/5193) +* Removed support for the original LCG random number generator by @tertu-m in [#5078](https://github.com/rh-hideout/pokeemerald-expansion/pull/5078) +* Deprecate MMBN Names by @pkmnsnfrn in [#5240](https://github.com/rh-hideout/pokeemerald-expansion/pull/5240) +* Convert 8 various to `callnatives` by @AsparagusEduardo in [#5172](https://github.com/rh-hideout/pokeemerald-expansion/pull/5172) +* Converted PC strings to `COMPOUND_STRING`s by @fdeblasio in [#5314](https://github.com/rh-hideout/pokeemerald-expansion/pull/5314) +* Cleaned up duplicate dynamic type functions by @AsparagusEduardo in [#5338](https://github.com/rh-hideout/pokeemerald-expansion/pull/5338) +* Removes redundant `moveTargetType` ai function by @AlexOn1ine in [#5354](https://github.com/rh-hideout/pokeemerald-expansion/pull/5354) +* Made `BuildColorMaps` redundant by using static tables by @pkmnsnfrn in [#5289](https://github.com/rh-hideout/pokeemerald-expansion/pull/5289) +* Some strings were switched by @AlexOn1ine in [#5374](https://github.com/rh-hideout/pokeemerald-expansion/pull/5374) +* Switch AI hitsToKO considers Disguise by @Pawkkie in [#5375](https://github.com/rh-hideout/pokeemerald-expansion/pull/5375) +* Cleaned up a bit of code with `GetBattlerPartyData` by @AlexOn1ine in [#5378](https://github.com/rh-hideout/pokeemerald-expansion/pull/5378) +* Minor Gem check optimazation by @AlexOn1ine in [#5401](https://github.com/rh-hideout/pokeemerald-expansion/pull/5401) +* Simplify HP Logic by @AreaZR in [#5403](https://github.com/rh-hideout/pokeemerald-expansion/pull/5403) +* Anger Shell use `saveattacker` by @ghoulslash in [#5409](https://github.com/rh-hideout/pokeemerald-expansion/pull/5409) +* Converted berry and PokeBlock strings to `COMPOUND_STRING`s by @fdeblasio in [#5324](https://github.com/rh-hideout/pokeemerald-expansion/pull/5324) +* Merge item description branch history by @Bassoonian in [#5419](https://github.com/rh-hideout/pokeemerald-expansion/pull/5419) +* Clean up Unseen Fist Check by @AlexOn1ine in [#5420](https://github.com/rh-hideout/pokeemerald-expansion/pull/5420) +* Merge level_caps and ev_caps into one caps file by @kittenchilly in [#5429](https://github.com/rh-hideout/pokeemerald-expansion/pull/5429) +* Removed trailing whitespace pass 10-2-2024 (Upcoming) by @kittenchilly in [#5456](https://github.com/rh-hideout/pokeemerald-expansion/pull/5456) +* Fixed Commander test name by @Bassoonian in [#5458](https://github.com/rh-hideout/pokeemerald-expansion/pull/5458) +* Updated species defines by @pkmnsnfrn in [#5075](https://github.com/rh-hideout/pokeemerald-expansion/pull/5075) +* Adds padding in `AiLogicData` by @AlexOn1ine in [#5468](https://github.com/rh-hideout/pokeemerald-expansion/pull/5468) +* Simplify `BS_FAINTED_MULTIPLE_1` double battle logic in openpartyscreen by @ghoulslash in [#5435](https://github.com/rh-hideout/pokeemerald-expansion/pull/5435) +* Removes duplicate code in AI functions by @AlexOn1ine in [#5457](https://github.com/rh-hideout/pokeemerald-expansion/pull/5457) +* `ShouldPivot` type cleanup by @Pawkkie in [#5441](https://github.com/rh-hideout/pokeemerald-expansion/pull/5441) +* Turn item hold effects into an enum by @Bassoonian in [#5498](https://github.com/rh-hideout/pokeemerald-expansion/pull/5498) +* Unify `GetBattlerAbility`/`TerrainAffected` to remove duplicate ai function by @AlexOn1ine in [#5497](https://github.com/rh-hideout/pokeemerald-expansion/pull/5497) +* Clean up Shedinja code by @Bassoonian in [#5501](https://github.com/rh-hideout/pokeemerald-expansion/pull/5501) +* Clean up `scrcmd` PR by @Bassoonian in [#5511](https://github.com/rh-hideout/pokeemerald-expansion/pull/5511) +* Removes Crit Chance preproc by @AlexOn1ine in [#5520](https://github.com/rh-hideout/pokeemerald-expansion/pull/5520) +* Removed agbcc screenshots from gitignore by @Bassoonian in [#5538](https://github.com/rh-hideout/pokeemerald-expansion/pull/5538) +* Removed unnecessary `gBattlerAttacker` usage by @AlexOn1ine in [#5554](https://github.com/rh-hideout/pokeemerald-expansion/pull/5554) +* Removed remaining line breaks from #3240 + Prefix wrap fix by @AsparagusEduardo in [#5556](https://github.com/rh-hideout/pokeemerald-expansion/pull/5556) +* More post-#3240 cleanup by @kittenchilly in [#5593](https://github.com/rh-hideout/pokeemerald-expansion/pull/5593) +* Renamed folders and symbols to match species defines by @AsparagusEduardo in [#5581](https://github.com/rh-hideout/pokeemerald-expansion/pull/5581) + - Also: + - Burmy and Wormadam footprints were in a `plant` subfolder. They have been moved to the species root folder + - Paldean Wooper's subfolder was named `wooper_paldean` instead of just `paldean`. This has been corrected. + - Zen Mode Galarian Darmanitan's folder was located in `darmanitan/galarian/zen_mode`. This has been corrected to `darmanitan/galar_zen`, alongside Galarian Standard Mode's `darmanitan/galar_standard`. + - Also updated Ogerpon's folders similarly. + - Renamed `SPECIES_PIKACHU_PARTNER_CAP` to `SPECIES_PIKACHU_PARTNER`. +* Minor `BattleStruct` clean up by @AlexOn1ine in [#5585](https://github.com/rh-hideout/pokeemerald-expansion/pull/5585) +* Fixed a ball update oversight by @Bassoonian in [#5609](https://github.com/rh-hideout/pokeemerald-expansion/pull/5609) +* `AI_FLAG_ACE_POKEMON` takes into account separate trainers by @GhoulMage and @/uvula on Discord noted the weird behaviour in [#5608](https://github.com/rh-hideout/pokeemerald-expansion/pull/5608) + - Fix for the AI not considering both trainers Ace Pokémons in double battles with `AI_FLAG_ACE_POKEMON`. +* Moves that deal a Fixed amount don't need AI handling by @AlexOn1ine in [#5614](https://github.com/rh-hideout/pokeemerald-expansion/pull/5614) +* Combines `CalculateMoveDamage` arguments into a struct by @AlexOn1ine in [#5570](https://github.com/rh-hideout/pokeemerald-expansion/pull/5570) +* Follow up for #5570 by @AlexOn1ine in [#5625](https://github.com/rh-hideout/pokeemerald-expansion/pull/5625) +* `AI_CalcDamage` clean up by @AlexOn1ine in [#5629](https://github.com/rh-hideout/pokeemerald-expansion/pull/5629) +* Convert 3 variouses to `callnatives` by @AlexOn1ine in [#5646](https://github.com/rh-hideout/pokeemerald-expansion/pull/5646) +* Convert `gBattleStringsTable` to `COMPOUND_STRING`s by @AsparagusEduardo in [#5649](https://github.com/rh-hideout/pokeemerald-expansion/pull/5649) +* Added merged placeholder text for trainer name with class by @kittenchilly in [#5622](https://github.com/rh-hideout/pokeemerald-expansion/pull/5622) +* Cleans up Primal Reversion code by @AlexOn1ine in [#5659](https://github.com/rh-hideout/pokeemerald-expansion/pull/5659) +* Critical Hit documentation and distorted match up struct switch by @AlexOn1ine in [#5665](https://github.com/rh-hideout/pokeemerald-expansion/pull/5665) +* Changes name of `B_SCR_NAME_WITH_PREFIX` by @AlexOn1ine in [#5675](https://github.com/rh-hideout/pokeemerald-expansion/pull/5675) +* Removes redundant Decorate check by @AlexOn1ine in [#5696](https://github.com/rh-hideout/pokeemerald-expansion/pull/5696) +* Changes taget bit of Flower Shield by @AlexOn1ine in [#5698](https://github.com/rh-hideout/pokeemerald-expansion/pull/5698) +* Changing `EVO_NONE` from `0xFFFE` to `0` by @GhoulMage in [#5547](https://github.com/rh-hideout/pokeemerald-expansion/pull/5547) + - There could be a case for out of bounds errors if arrays or iterations are happening where you're using + 1 or - 1, as `EVO_FRIENDSHIP` used to be the first index although it started with 1. + +## 🧪 Test Runner 🧪 +### Changed +* Fixed Commander test name by @Bassoonian in [#5458](https://github.com/rh-hideout/pokeemerald-expansion/pull/5458) +* `ShouldSwitchIfGameStatePrompt` Tests by @Pawkkie in [#5462](https://github.com/rh-hideout/pokeemerald-expansion/pull/5462) +* Added various tests, add `RNG_RANDOM_TARGET` by @ghoulslash in [#5438](https://github.com/rh-hideout/pokeemerald-expansion/pull/5438) +* Added Costar Tests, Download Test for Doubles by @ghoulslash in [#5526](https://github.com/rh-hideout/pokeemerald-expansion/pull/5526) +* Updated Wring Out effects to match Eruption effects by @AsparagusEduardo in [#5549](https://github.com/rh-hideout/pokeemerald-expansion/pull/5549) + - Changed Wring Out/Crush Grip/Hard Press to use `power` instead of `argument` to determine its max power, just like how Eruption/Water Spout/Dragon Energy do it. Also: + - Renamed `EFFECT_VARY_POWER_BASED_ON_HP` to `EFFECT_POWER_BASED_ON_TARGET_HP` + - Renamed `EFFECT_ERUPTION` to `EFFECT_POWER_BASED_ON_USER_HP` +* Healer ability tests by @Pawkkie in [#5559](https://github.com/rh-hideout/pokeemerald-expansion/pull/5559) +* Mark all tests as used by @mrgriffin in [#5531](https://github.com/rh-hideout/pokeemerald-expansion/pull/5531) + +### Fixed +* Should switch refactor to facilitate switch prediction by @Pawkkie in [#5466](https://github.com/rh-hideout/pokeemerald-expansion/pull/5466) + +## 📚 Documentation 📚 +* `DoBattleIntro` state documentation by @AsparagusEduardo and @ShinyDragonHunter in [#5231](https://github.com/rh-hideout/pokeemerald-expansion/pull/5231) +* Deprecate MMBN Names by @pkmnsnfrn in [#5240](https://github.com/rh-hideout/pokeemerald-expansion/pull/5240) +* `AI_FLAG_SETUP_FIRST_TURN` Rename and Clarifications by @Pawkkie in [#5310](https://github.com/rh-hideout/pokeemerald-expansion/pull/5310) +* Added Composite AI Flags to Docs by @Pawkkie in [#5349](https://github.com/rh-hideout/pokeemerald-expansion/pull/5349) +* Updated the new pokemon tutorial for 1.10 by @hedara90 in [#5721](https://github.com/rh-hideout/pokeemerald-expansion/pull/5721) + - Some changes compared to previous. + +## New Contributors +* @SombrAbsol made their first contribution in [#4958](https://github.com/rh-hideout/pokeemerald-expansion/pull/4958) +* @Galaxeeh made their first contribution in [#5084](https://github.com/rh-hideout/pokeemerald-expansion/pull/5084) +* @Flash1Lucky made their first contribution in [#5269](https://github.com/rh-hideout/pokeemerald-expansion/pull/5269) +* @GhoulMage made their first contribution in [#5547](https://github.com/rh-hideout/pokeemerald-expansion/pull/5547) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.9.4...expansion/1.10.0 + + + diff --git a/docs/changelogs/1.9.x/1.9.4.md b/docs/changelogs/1.9.x/1.9.4.md new file mode 100644 index 0000000000..2a41988bd4 --- /dev/null +++ b/docs/changelogs/1.9.x/1.9.4.md @@ -0,0 +1,201 @@ +# Version 1.9.4 + +```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.9.4`. +``` + +## 🌋 IMPORTANT 🌋 +- This update integrates pret's latest Makefile changes, which rearranges the entire file in order to speed up compilation times overall. If you did any changes to it (such as installing Poryscript) and are having issues resolving the conflicts, keep expansion's version of Makefile and reapply your changes afterwards. + +## 🧬 General 🧬 +### Fixed +* Fixed alignment errors in `EWRAM_INIT` and friends when using u8, u16, etc. by @aronson in [#5512](https://github.com/rh-hideout/pokeemerald-expansion/pull/5512) +* Update test LD script to respect 4 byte data section alignment by @aronson in [#5517](https://github.com/rh-hideout/pokeemerald-expansion/pull/5517) +* Fixed Missing `string_util.h` include in `mini_printf.c` by @mrgriffin in [#5572](https://github.com/rh-hideout/pokeemerald-expansion/pull/5572) +* Fixed unnecessary dependency scanning for test build and test rom names by @ravepossum in [#5594](https://github.com/rh-hideout/pokeemerald-expansion/pull/5594) +* Fixed makefile: dependencies for `map_group_count.h` by @SBird1337 in [#5648](https://github.com/rh-hideout/pokeemerald-expansion/pull/5648) + - Fixes an issue that caused the build to fail on updates to `src/debug.c` due to mismatched dependency. + +## 🗺️ Overworld 🗺️ +### Changed +* Followers sprite fixes by @Cafeei in [#5669](https://github.com/rh-hideout/pokeemerald-expansion/pull/5669) +* Follower fixes, Melmetal, Patrat, Woobat by @hedara90 in [#5685](https://github.com/rh-hideout/pokeemerald-expansion/pull/5685) +* Fixed Farfetch'd overworld sprite by @hedara90 in [#5711](https://github.com/rh-hideout/pokeemerald-expansion/pull/5711) + +### Fixed +* Fixed Berry mutations always generating a Persim Berry by @Bassoonian in [#5504](https://github.com/rh-hideout/pokeemerald-expansion/pull/5504) + +## 🐉 Pokémon 🐉 +### Changed +* Changing `EVO_NONE` from `0xFFFE` to `0` by @GhoulMage in [#5547](https://github.com/rh-hideout/pokeemerald-expansion/pull/5547) + - There could be a case for out of bounds errors if arrays or iterations are happening where you're using + 1 or - 1, as `EVO_FRIENDSHIP` used to be the first index although it started with 1. +* PokeCommunity sprites batch (October) by @kittenchilly in [#5655](https://github.com/rh-hideout/pokeemerald-expansion/pull/5655) +* Followers sprite fixes by @Cafeei in [#5669](https://github.com/rh-hideout/pokeemerald-expansion/pull/5669) +* Follower fixes, Melmetal, Patrat, Woobat by @hedara90 in [#5685](https://github.com/rh-hideout/pokeemerald-expansion/pull/5685) +* Fixed Farfetch'd overworld sprite by @hedara90 in [#5711](https://github.com/rh-hideout/pokeemerald-expansion/pull/5711) + +### Fixed +* Fixed `P_FRIENDSHIP_EVO_THRESHOLD` not checking for Gen 8 by @kittenchilly in [#5503](https://github.com/rh-hideout/pokeemerald-expansion/pull/5503) +* Fixed HGSS dex search printing wrong mon after selecting evos by @ravepossum in [#5552](https://github.com/rh-hideout/pokeemerald-expansion/pull/5552) +* Fixed 64px uncompressed followers by @hedara90 in [#5601](https://github.com/rh-hideout/pokeemerald-expansion/pull/5601) +* Deoxys Sprite/Animation Fixes by @SarnPoke in [#5603](https://github.com/rh-hideout/pokeemerald-expansion/pull/5603) +* Fixes Aegislash not reverting back by @AlexOn1ine in [#5734](https://github.com/rh-hideout/pokeemerald-expansion/pull/5734) + +## ⚔️ Battle General ⚔️ +### Changed +* Fixed damage calc modifiers by @AlexOn1ine in [#5604](https://github.com/rh-hideout/pokeemerald-expansion/pull/5604) + +### Fixed +* Fixed Shiny Pokemon not being shiny after transforming with a gimmick by @hedara90 in [#5573](https://github.com/rh-hideout/pokeemerald-expansion/pull/5573) +* Handle showdowns apostrophe the same way as ASCII apostrophe by @cawtds in [#5712](https://github.com/rh-hideout/pokeemerald-expansion/pull/5712) +* Fixes Misty Terrain displaying wrong message by @AlexOn1ine in [#5742](https://github.com/rh-hideout/pokeemerald-expansion/pull/5742) +* Fixes Dynamax dynamic move type by @AlexOn1ine in [#5739](https://github.com/rh-hideout/pokeemerald-expansion/pull/5739) + +## 🤹 Moves 🤹 +### Changed +* Fixed damage calc modifiers by @AlexOn1ine in [#5604](https://github.com/rh-hideout/pokeemerald-expansion/pull/5604) +* Updated ability popups for Skill Swap, Mummy/Lingering Aroma, Worry Seed, Simple Beam, fix Doodle/Role Play bugs by @PhallenTree in [#5493](https://github.com/rh-hideout/pokeemerald-expansion/pull/5493) + +### Fixed +* Fixed Follow Me failing in Single Battles for Gen 6/7 config by @AsparagusEduardo in [#5542](https://github.com/rh-hideout/pokeemerald-expansion/pull/5542) +* Fixed `AnimTask_HorizontalShake` uses for shaking screen in battle anims by @ghoulslash in [#5562](https://github.com/rh-hideout/pokeemerald-expansion/pull/5562) +* Fixed weather genie move anims and Springtide Storm targets by @ravepossum in [#5553](https://github.com/rh-hideout/pokeemerald-expansion/pull/5553) +* Fixes Magic Guard not preventing Salt Cure by @AlexOn1ine in [#5583](https://github.com/rh-hideout/pokeemerald-expansion/pull/5583) +* Fixes Dragon Tail using the effect twice during a Parental Bond attack by @AlexOn1ine in [#5630](https://github.com/rh-hideout/pokeemerald-expansion/pull/5630) +* Fixes Magic Coat message by @AlexOn1ine in [#5645](https://github.com/rh-hideout/pokeemerald-expansion/pull/5645) +* Fixes Take heart by @AlexOn1ine in [#5658](https://github.com/rh-hideout/pokeemerald-expansion/pull/5658) +* Fixed Floral Healing anim by @AlexOn1ine in [#5733](https://github.com/rh-hideout/pokeemerald-expansion/pull/5733) +* Fixes Population Bomb / Triple Kick missing message by @AlexOn1ine in [#5747](https://github.com/rh-hideout/pokeemerald-expansion/pull/5747) +* Changes Max Phantasm move anim script call by @AlexOn1ine in [#5737](https://github.com/rh-hideout/pokeemerald-expansion/pull/5737) +* Fixes Partner targeting and Acupressure/Ally Switch interaction by @AlexOn1ine in [#5446](https://github.com/rh-hideout/pokeemerald-expansion/pull/5446) +* Revival Blessing fixes + Using Lunar Blessing's animation by @ghoulslash in [#5490](https://github.com/rh-hideout/pokeemerald-expansion/pull/5490) +* Fixed curse + Protean interaction by @hedara90 in [#5663](https://github.com/rh-hideout/pokeemerald-expansion/pull/5663) +* Added Minimize interaction to Supercell Slam by @hedara90 in [#5713](https://github.com/rh-hideout/pokeemerald-expansion/pull/5713) + +## 🎭 Abilities 🎭 +### Changed +* Fixed damage calc modifiers by @AlexOn1ine in [#5604](https://github.com/rh-hideout/pokeemerald-expansion/pull/5604) + +### Fixed +* Adds tests and Costar fix from PR #5526 by @AlexOn1ine in [#5529](https://github.com/rh-hideout/pokeemerald-expansion/pull/5529) +* Fixes Red Card / Eject Pack interaction with Emergency Exit by @AlexOn1ine in [#5657](https://github.com/rh-hideout/pokeemerald-expansion/pull/5657) +* Fixed curse + Protean interaction by @hedara90 in [#5663](https://github.com/rh-hideout/pokeemerald-expansion/pull/5663) +* Mimicry updates typing with `RemoveAllTerrains()` by @AERDU in [#5666](https://github.com/rh-hideout/pokeemerald-expansion/pull/5666) +* Updated ability popups for Skill Swap, Mummy/Lingering Aroma, Worry Seed, Simple Beam, fix Doodle/Role Play bugs by @PhallenTree in [#5493](https://github.com/rh-hideout/pokeemerald-expansion/pull/5493) +* Fixed curse + Protean interaction by @hedara90 in [#5663](https://github.com/rh-hideout/pokeemerald-expansion/pull/5663) +* Fixes Ice Face regression by @AlexOn1ine in [#5678](https://github.com/rh-hideout/pokeemerald-expansion/pull/5678) +* Fixes Neutralizing Gas crashes + adds missing interaction, Regenerator small fix by @PhallenTree in [#5694](https://github.com/rh-hideout/pokeemerald-expansion/pull/5694) + +## 🧶 Items 🧶 +### Changed +* Removes duplicate Booster Energy code by @AlexOn1ine in [#5656](https://github.com/rh-hideout/pokeemerald-expansion/pull/5656) + +### Fixed +* Fixes Red Card / Eject Pack interaction with Emergency Exit by @AlexOn1ine in [#5657](https://github.com/rh-hideout/pokeemerald-expansion/pull/5657) +* Fixes Red Card / Eject Pack interaction by @AlexOn1ine in [#5724](https://github.com/rh-hideout/pokeemerald-expansion/pull/5724) +* Fixes gems triggering on confusion damage by @AlexOn1ine in [#5723](https://github.com/rh-hideout/pokeemerald-expansion/pull/5723) +* Fixes Kee Maranga and Enigma Berry by @AlexOn1ine in [#5727](https://github.com/rh-hideout/pokeemerald-expansion/pull/5727) +* Fixes Blunder Policy by @AlexOn1ine in [#5722](https://github.com/rh-hideout/pokeemerald-expansion/pull/5722) +* Fixes Rusted Shield/Sword allowed to be Knocked Off from Zamazenta/Zacian by @iriv24 in [#5750](https://github.com/rh-hideout/pokeemerald-expansion/pull/5750) + +## 🤖 Battle AI 🤖 +### Fixed +* Fixed certain move data being cleared on turn end by @Pawkkie and @AlexOn1ine in [#5488](https://github.com/rh-hideout/pokeemerald-expansion/pull/5488) +* Global is used instead of passed var by @AlexOn1ine in [#5546](https://github.com/rh-hideout/pokeemerald-expansion/pull/5546) +* Fixes `dynamicMoveType` global not being reset during AI calcs by @AlexOn1ine in [#5628](https://github.com/rh-hideout/pokeemerald-expansion/pull/5628) + +## 🧹 Other Cleanup 🧹 +* Remove one redundant call of `SetAiLogicDataForTurn` in `DoBattleIntro` by @AlexOn1ine in [#5491](https://github.com/rh-hideout/pokeemerald-expansion/pull/5491) +* Cleanup extraneous function in `battle_anim.h` by @hedara90 in [#5506](https://github.com/rh-hideout/pokeemerald-expansion/pull/5506) +* Add newline to move relearner string by @Bassoonian in [#5523](https://github.com/rh-hideout/pokeemerald-expansion/pull/5523) +* Fixed 10,000,000 Volt Thunderbolt name by @AsparagusEduardo in [#5533](https://github.com/rh-hideout/pokeemerald-expansion/pull/5533) +* Added constant to expansion inclusive copyright magic number by @pkmnsnfrn in [#5413](https://github.com/rh-hideout/pokeemerald-expansion/pull/5413) +* Centralise AI Tests trainer name by @Bassoonian in [#5532](https://github.com/rh-hideout/pokeemerald-expansion/pull/5532) +* Remove now outdated information from readme by @Bassoonian in [#5548](https://github.com/rh-hideout/pokeemerald-expansion/pull/5548) +* Changing `EVO_NONE` from `0xFFFE` to `0` by @GhoulMage in [#5547](https://github.com/rh-hideout/pokeemerald-expansion/pull/5547) + - There could be a case for out of bounds errors if arrays or iterations are happening where you're using + 1 or - 1, as `EVO_FRIENDSHIP` used to be the first index although it started with 1. +* Shed Skin chance fix by @Pawkkie in [#5558](https://github.com/rh-hideout/pokeemerald-expansion/pull/5558) +* Restore test file dependencies so they're rebuilt properly by @ravepossum in [#5617](https://github.com/rh-hideout/pokeemerald-expansion/pull/5617) +* Improve `SEND_OUT` error message; require Speed for all battlers by @mrgriffin in [#5631](https://github.com/rh-hideout/pokeemerald-expansion/pull/5631) +* Removes duplicate Booster Energy code by @AlexOn1ine in [#5656](https://github.com/rh-hideout/pokeemerald-expansion/pull/5656) +* Wrong assumtion in dauntless_shield.c by @AlexOn1ine in [#5692](https://github.com/rh-hideout/pokeemerald-expansion/pull/5692) + +## 🧪 Test Runner 🧪 +### Added +* Add curious medicine test by @ghoulslash in [#5540](https://github.com/rh-hideout/pokeemerald-expansion/pull/5540) +* Tests: detect task leaks by @mrgriffin in [#5528](https://github.com/rh-hideout/pokeemerald-expansion/pull/5528) + +### Changed +* Add text width tests for move, ability, item, and pokedex descriptions by @kittenchilly in [#5505](https://github.com/rh-hideout/pokeemerald-expansion/pull/5505) +* Centralise AI Tests trainer name by @Bassoonian in [#5532](https://github.com/rh-hideout/pokeemerald-expansion/pull/5532) +* Add basic Steam Engine, Guard Dog Tests by @ghoulslash in [#5569](https://github.com/rh-hideout/pokeemerald-expansion/pull/5569) +* Fixed damage test by @GhoulMage and @mrgriffin for teaching me pokeemerald-expansion tests in [#5574](https://github.com/rh-hideout/pokeemerald-expansion/pull/5574) +* Fallback `memmem` implementation by @mrgriffin in [#5561](https://github.com/rh-hideout/pokeemerald-expansion/pull/5561) +* Hydra: Support `%p` in test summaries by @mrgriffin in [#5626](https://github.com/rh-hideout/pokeemerald-expansion/pull/5626) +* Improve `SEND_OUT` error message; require Speed for all battlers by @mrgriffin in [#5631](https://github.com/rh-hideout/pokeemerald-expansion/pull/5631) +* Check that `PASSES_RANDOMLY` affected a `Random` call by @mrgriffin in [#5635](https://github.com/rh-hideout/pokeemerald-expansion/pull/5635) +* Wrong assumtion in dauntless_shield.c by @AlexOn1ine in [#5692](https://github.com/rh-hideout/pokeemerald-expansion/pull/5692) + +### Fixed +* Update test LD script to respect 4 byte data section alignment by @aronson in [#5517](https://github.com/rh-hideout/pokeemerald-expansion/pull/5517) +* Adds tests and Costar fix from PR #5526 by @AlexOn1ine in [#5529](https://github.com/rh-hideout/pokeemerald-expansion/pull/5529) +* Fixed broken Starting Terrain test by @hedara90 in [#5582](https://github.com/rh-hideout/pokeemerald-expansion/pull/5582) + +## 📚 Documentation 📚 +* Add changelog header in PR template to aid automation by @AsparagusEduardo in [#5539](https://github.com/rh-hideout/pokeemerald-expansion/pull/5539) +* Added compressed OW mon VRAM notice in config file by @AsparagusEduardo in [#5599](https://github.com/rh-hideout/pokeemerald-expansion/pull/5599) +* Update `README.md` to link to `INSTALL.md` by @Pawkkie in [#5720](https://github.com/rh-hideout/pokeemerald-expansion/pull/5720) +* Fixes minor move desc errors by @AlexOn1ine in [#5728](https://github.com/rh-hideout/pokeemerald-expansion/pull/5728) + +## 📦 Branch Synchronisation 📦 +### pret +* 15th of October in [#5527](https://github.com/rh-hideout/pokeemerald-expansion/pull/5527) + * Slight storage system documentation by @luckytyphlosion in [pret#2024](https://github.com/pret/pokeemerald/pull/2024) + * Clean up defines lacking spaces by @Bassoonian in [pret#2025](https://github.com/pret/pokeemerald/pull/2025) + * UB fix in battle_transition.c by @cawtds in [pret#2007](https://github.com/pret/pokeemerald/pull/2007) + * preproc: support arbitrary expressions in enums by @mrgriffin in [pret#2026](https://github.com/pret/pokeemerald/pull/2026) + * [Build System Rewrite] Refactored `Makefile` by @Icedude907 in [pret#1950](https://github.com/pret/pokeemerald/pull/1950) + * Fixed incorrect point macros in contest_ai_script.inc by @NTx86 in [pret#2028](https://github.com/pret/pokeemerald/pull/2028) + * [Build System Rewrite] Massive build speed improvement via scaninc changes by @Icedude907 in [pret#1954](https://github.com/pret/pokeemerald/pull/1954) + * [Build System Rewrite] Improved audio rules by @Icedude907 in [pret#1957](https://github.com/pret/pokeemerald/pull/1957) + * Update INSTALL.md to state that Windows 8 is no longer supported by Microsoft by @luciofstars in [pret#2029](https://github.com/pret/pokeemerald/pull/2029) + * Update pull_request_template.md to include Discord username update by @luciofstars in [pret#2030](https://github.com/pret/pokeemerald/pull/2030) + * remove ScriptContext_Enable from secret_base.h by @DizzyEggg in [pret#2032](https://github.com/pret/pokeemerald/pull/2032) + * Remove gflib by @Kurausukun in [pret#2033](https://github.com/pret/pokeemerald/pull/2033) + * Minor toolchain fixes by @GriffinRichards in [pret#2031](https://github.com/pret/pokeemerald/pull/2031) + * Bugfix for cable car hikerGraphicsIds array by @Scyrous in [pret#2039](https://github.com/pret/pokeemerald/pull/2039) + * Remove explicit symbol sizes in sym_common.txt by @GriffinRichards in [pret#2038](https://github.com/pret/pokeemerald/pull/2038) + * Ignore mGBA screenshots by @Jaizu in [pret#2041](https://github.com/pret/pokeemerald/pull/2041) + * Replaced copyright magic numbers in intro.c with constants by @pkmnsnfrn in [pret#2035](https://github.com/pret/pokeemerald/pull/2035) + * Fixed typo: | should be || in Task_TryFieldPoisonWhiteOut by @AreaZR in [pret#2044](https://github.com/pret/pokeemerald/pull/2044) + * [preproc] support C23 enum underlying type syntax by @mrgriffin in [pret#2043](https://github.com/pret/pokeemerald/pull/2043) + * Fixed deleting files with dependency files by @mid-kid in [pret#2045](https://github.com/pret/pokeemerald/pull/2045) + * Remove unnecessary looping for rule generation and unroll macros by @mid-kid in [pret#2046](https://github.com/pret/pokeemerald/pull/2046) + * Get rid of common syms by @luckytyphlosion in [pret#2040](https://github.com/pret/pokeemerald/pull/2040) + * Bugfix for cable car hikerGraphicsIds array by @Scyrous in [pret#2039](https://github.com/pret/pokeemerald/pull/2039) + * UB fix in battle_transition.c by @cawtds in [pret#2007](https://github.com/pret/pokeemerald/pull/2007) + * Fixed typo: | should be || in Task_TryFieldPoisonWhiteOut by @AreaZR in [pret#2044](https://github.com/pret/pokeemerald/pull/2044) + * Get rid of common syms by @luckytyphlosion in [pret#2040](https://github.com/pret/pokeemerald/pull/2040) + * Fixed incorrect point macros in contest_ai_script.inc by @NTx86 in [pret#2028](https://github.com/pret/pokeemerald/pull/2028) +* 5th of November in [#5644](https://github.com/rh-hideout/pokeemerald-expansion/pull/5644) + * Added define value for bard sound length by @fdeblasio in [pret#2052](https://github.com/pret/pokeemerald/pull/2052) + * Silence 'Nothing to be done for generated' messages by @GriffinRichards in [pret#2059](https://github.com/pret/pokeemerald/pull/2059) + * Lay out emerald version png horizontally by @GriffinRichards in [pret#2062](https://github.com/pret/pokeemerald/pull/2062) +* 29 of November in [#5736](https://github.com/rh-hideout/pokeemerald-expansion/pull/5736) + * Remove usage of gHeap in sSpritePalettes_ContestantsTurnBlinkEffect by @Lactozilla in [pret#2064](https://github.com/pret/pokeemerald/pull/2064) + * BUGFIX: Fix Counter and Mirror Coat checking the wrong category by @surtr-games in [pret#2066](https://github.com/pret/pokeemerald/pull/2066) + * Add TRY_DRAW_SPOT_PIXEL by @GriffinRichards in [pret#2055](https://github.com/pret/pokeemerald/pull/2055) + * Added extra encoded character support by @AsparagusEduardo in [pret#2050](https://github.com/pret/pokeemerald/pull/2050) +### merrp's followers +* Merrp merge (12th of October) by @Bassoonian in [#5514](https://github.com/rh-hideout/pokeemerald-expansion/pull/5514) + - d80190fe105eee12bbf74ae29647ac909084d35c fix: Dig in Sealed Chamber no longer freezes follower. + +## New Contributors +* @AERDU made their first contribution in [#5666](https://github.com/rh-hideout/pokeemerald-expansion/pull/5666) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.9.3...expansion/1.9.4 + + + diff --git a/graphics/pokemon/deoxys/anim_front.png b/graphics/pokemon/deoxys/anim_front.png index d2f3e99381..fc782931d1 100644 Binary files a/graphics/pokemon/deoxys/anim_front.png and b/graphics/pokemon/deoxys/anim_front.png differ diff --git a/graphics/pokemon/deoxys/attack/anim_front.png b/graphics/pokemon/deoxys/attack/anim_front.png index 0b43a9fe11..566e80eafd 100644 Binary files a/graphics/pokemon/deoxys/attack/anim_front.png and b/graphics/pokemon/deoxys/attack/anim_front.png differ diff --git a/graphics/pokemon/deoxys/attack/normal.pal b/graphics/pokemon/deoxys/attack/normal.pal index 246d4784a2..52ddbb8fc6 100644 --- a/graphics/pokemon/deoxys/attack/normal.pal +++ b/graphics/pokemon/deoxys/attack/normal.pal @@ -3,8 +3,8 @@ JASC-PAL 16 248 160 176 96 56 56 -248 112 72 -184 104 104 +255 115 74 +204 65 65 24 24 24 104 200 224 80 144 176 diff --git a/graphics/pokemon/deoxys/defense/anim_front.png b/graphics/pokemon/deoxys/defense/anim_front.png index 2ee6e0c527..ce3cdad39c 100644 Binary files a/graphics/pokemon/deoxys/defense/anim_front.png and b/graphics/pokemon/deoxys/defense/anim_front.png differ diff --git a/graphics/pokemon/deoxys/defense/normal.pal b/graphics/pokemon/deoxys/defense/normal.pal index 8b37f5111e..4beda86136 100644 --- a/graphics/pokemon/deoxys/defense/normal.pal +++ b/graphics/pokemon/deoxys/defense/normal.pal @@ -3,9 +3,9 @@ JASC-PAL 16 248 160 176 96 56 56 -192 104 104 -248 112 72 -96 64 48 +204 65 65 +255 115 74 +68 28 89 240 176 144 104 200 224 80 144 176 diff --git a/graphics/pokemon/deoxys/defense/shiny.pal b/graphics/pokemon/deoxys/defense/shiny.pal index c1f34410a4..3f285246c6 100644 --- a/graphics/pokemon/deoxys/defense/shiny.pal +++ b/graphics/pokemon/deoxys/defense/shiny.pal @@ -5,7 +5,7 @@ JASC-PAL 112 96 16 168 168 56 248 232 64 -96 64 48 +49 29 82 248 248 216 112 208 168 72 160 112 diff --git a/graphics/pokemon/deoxys/normal.pal b/graphics/pokemon/deoxys/normal.pal index 59124c56a9..e11c277719 100644 --- a/graphics/pokemon/deoxys/normal.pal +++ b/graphics/pokemon/deoxys/normal.pal @@ -2,12 +2,12 @@ JASC-PAL 0100 16 248 160 176 -184 104 104 +204 65 65 248 176 144 -248 112 72 +255 115 74 96 56 56 104 200 224 -88 56 48 +68 28 89 56 80 96 80 144 176 152 96 176 diff --git a/graphics/pokemon/deoxys/shiny.pal b/graphics/pokemon/deoxys/shiny.pal index 5bbc6b683a..621aac6d42 100644 --- a/graphics/pokemon/deoxys/shiny.pal +++ b/graphics/pokemon/deoxys/shiny.pal @@ -7,7 +7,7 @@ JASC-PAL 248 232 64 112 96 16 112 208 168 -112 96 16 +51 27 101 56 96 88 72 160 112 96 120 192 diff --git a/graphics/pokemon/deoxys/speed/anim_front.png b/graphics/pokemon/deoxys/speed/anim_front.png index 947052f81d..1f2063bddf 100644 Binary files a/graphics/pokemon/deoxys/speed/anim_front.png and b/graphics/pokemon/deoxys/speed/anim_front.png differ diff --git a/graphics/pokemon/deoxys/speed/normal.pal b/graphics/pokemon/deoxys/speed/normal.pal index dad052e1da..ea1073a0ee 100644 --- a/graphics/pokemon/deoxys/speed/normal.pal +++ b/graphics/pokemon/deoxys/speed/normal.pal @@ -6,9 +6,9 @@ JASC-PAL 80 144 176 104 200 224 96 56 56 -248 112 72 +255 115 74 24 24 24 -192 104 104 +204 65 65 192 192 208 152 96 176 248 248 248 diff --git a/include/battle.h b/include/battle.h index 3c09e2f3fb..9639c217cb 100644 --- a/include/battle.h +++ b/include/battle.h @@ -831,8 +831,11 @@ struct BattleStruct u16 commanderActive[MAX_BATTLERS_COUNT]; u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side u8 redCardActivates:1; + u8 padding1:7; u8 usedEjectItem; - u8 usedMicleBerry; + u8 monCausingSleepClause[NUM_BATTLE_SIDES]; // Stores which pokemon on a given side is causing Sleep Clause to be active as the mon's index in the party + u8 sleepClauseEffectExempt:4; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore) + u8 usedMicleBerry:4; s32 battlerExpReward; // Simultaneous hp reduction for spread moves @@ -846,7 +849,7 @@ struct BattleStruct u8 calculatedSpreadMoveAccuracy:1; u8 printedStrongWindsWeakenedAttack:1; u8 numSpreadTargets:2; - u8 padding:2; + u8 padding2:2; }; // The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider, diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index c74cad2e78..56dd8aa6e1 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -185,6 +185,7 @@ bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove); bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck); bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove); bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove); +bool32 PartnerMoveActivatesSleepClause(u32 move); bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move); // party logic diff --git a/include/battle_scripts.h b/include/battle_scripts.h index f86cf0bda9..59a53f6c2c 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -519,6 +519,7 @@ extern const u8 BattleScript_Terastallization[]; extern const u8 BattleScript_BoosterEnergyEnd2[]; extern const u8 BattleScript_TeraShellDistortingTypeMatchups[]; extern const u8 BattleScript_TeraFormChange[]; +extern const u8 BattleScript_SleepClausePreventsEnd[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; @@ -623,6 +624,9 @@ extern const u8 BattleScript_EffectMimic[]; extern const u8 BattleScript_EffectMetronome[]; extern const u8 BattleScript_EffectLeechSeed[]; extern const u8 BattleScript_EffectDoNothing[]; +extern const u8 BattleScript_EffectHoldHands[]; +extern const u8 BattleScript_EffectCelebrate[]; +extern const u8 BattleScript_EffectHappyHour[]; extern const u8 BattleScript_EffectDisable[]; extern const u8 BattleScript_EffectLevelDamage[]; extern const u8 BattleScript_EffectPsywave[]; diff --git a/include/battle_util.h b/include/battle_util.h index 836e9c0931..03b7c2029f 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -99,6 +99,7 @@ enum CANCELLER_SKY_DROP, CANCELLER_ASLEEP, CANCELLER_FROZEN, + CANCELLER_OBEDIENCE, CANCELLER_TRUANT, CANCELLER_RECHARGE, CANCELLER_FLINCH, @@ -291,7 +292,7 @@ bool32 MoveHasChargeTurnAdditionalEffect(u32 move); bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef); bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef); -bool32 CanBeSlept(u32 battler, u32 ability); +bool32 CanBeSlept(u32 battler, u32 ability, u32 isBlockedBySleepClause); bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 defAbility); bool32 CanBeBurned(u32 battler, u32 ability); bool32 CanBeParalyzed(u32 battler, u32 ability); @@ -314,6 +315,9 @@ bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon); bool8 IsMonBannedFromSkyBattles(u16 species); void RemoveBattlerType(u32 battler, u8 type); u32 GetMoveType(u32 move); +void TryActivateSleepClause(u32 battler, u32 indexInParty); +void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty); +bool32 IsSleepClauseActiveForSide(u32 battlerSide); void ClearDamageCalcResults(void); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/config/battle.h b/include/config/battle.h index 7467bd47f1..43da403010 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -6,7 +6,7 @@ #define B_CRIT_MULTIPLIER GEN_LATEST // In Gen6+, critical hits multiply damage by 1.5 instead of 2. #define B_PARALYSIS_SPEED GEN_LATEST // In Gen7+, Speed is decreased by 50% instead of 75%. #define B_CONFUSION_SELF_DMG_CHANCE GEN_LATEST // In Gen7+, confusion has a 33.3% of self-damage, instead of 50%. -#define B_MULTI_HIT_CHANCE GEN_LATEST // In Gen5+, multi-hit moves have different %. See Cmd_setmultihitcounter for values. +#define B_MULTI_HIT_CHANCE GEN_LATEST // In Gen5+, multi-hit moves have different %. See SetRandomMultiHitCounter for values. #define B_WHITEOUT_MONEY GEN_LATEST // In Gen4+, the amount of money lost by losing a battle is determined by the amount of badges earned. Previously, it would cut the current money by half. (While this change was also in FRLG, for the sake of simplicity, setting this to GEN_3 will result in RSE behavior.) #define B_LIGHT_BALL_ATTACK_BOOST GEN_LATEST // In Gen4+, Light Ball doubles the power of physical moves in addition to special moves. #define B_SANDSTORM_SPDEF_BOOST GEN_LATEST // In Gen4+, Sandstorm weather multiplies the Sp. Defense of Rock-type Pokémon by x1.5. @@ -192,6 +192,7 @@ #define B_FLAG_DYNAMAX_BATTLE 0 // If this flag is set, the ability to Dynamax in battle is enabled for all trainers. #define B_FLAG_TERA_ORB_CHARGED 0 // If this flag is set, the Tera Orb is charged. It is automatically set upon healing and cleared upon Terastallizing once configured. #define B_FLAG_TERA_ORB_NO_COST 0 // If this flag is set, the Tera Orb does not use up its charge upon Terastallization. In S/V, this occurs after an event with Terapagos. +#define B_FLAG_SLEEP_CLAUSE 0 // If this flag is set, sleep clause is enabled; if the player / AI has already put a Pokémon on the opponent's side to sleep and it is still sleeping, another one can't be put to sleep. AI requires AI_FLAG_CHECK_BAD_MOVE to understand. // Var Settings // To use the following features in scripting, replace the 0s with the var ID you're assigning it to. diff --git a/include/config/test.h b/include/config/test.h index 708c2ca581..cce97484df 100644 --- a/include/config/test.h +++ b/include/config/test.h @@ -1129,4 +1129,8 @@ #undef P_FAMILY_PECHARUNT #define P_FAMILY_PECHARUNT TRUE +// Flags +#undef B_FLAG_SLEEP_CLAUSE +#define B_FLAG_SLEEP_CLAUSE FLAG_SPECIAL_FLAG_UNUSED_0x4003 + #endif // GUARD_CONFIG_TEST_H diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index b1472d0280..15edbd28ef 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -67,6 +67,9 @@ enum { EFFECT_METRONOME, EFFECT_LEECH_SEED, EFFECT_DO_NOTHING, + EFFECT_HOLD_HANDS, + EFFECT_CELEBRATE, + EFFECT_HAPPY_HOUR, EFFECT_DISABLE, EFFECT_LEVEL_DAMAGE, EFFECT_PSYWAVE, diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 9d6e4682a5..b2a569aef8 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -727,8 +727,9 @@ #define STRINGID_SUPEREFFECTIVETWOFOES 725 #define STRINGID_NOTVERYEFFECTIVETWOFOES 726 #define STRINGID_ITDOESNTAFFECTTWOFOES 727 +#define STRINGID_BLOCKEDBYSLEEPCLAUSE 728 -#define BATTLESTRINGS_COUNT 728 +#define BATTLESTRINGS_COUNT 729 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/include/constants/expansion.h b/include/constants/expansion.h index 327a502e22..6b3a5ace78 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -1,9 +1,9 @@ #ifndef GUARD_CONSTANTS_EXPANSION_H #define GUARD_CONSTANTS_EXPANSION_H -// Last version: 1.9.3 +// Last version: 1.10.1 #define EXPANSION_VERSION_MAJOR 1 -#define EXPANSION_VERSION_MINOR 10 +#define EXPANSION_VERSION_MINOR 11 #define EXPANSION_VERSION_PATCH 0 // FALSE if this this version of Expansion is not a tagged commit, i.e. diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 3c031de092..28ac8f48d1 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -982,6 +982,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_SLEEP: if (!AI_CanPutToSleep(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove)) ADJUST_SCORE(-10); + if (PartnerMoveActivatesSleepClause(aiData->partnerMove)) + ADJUST_SCORE(-20); break; case EFFECT_EXPLOSION: if (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_WILL_SUICIDE)) @@ -1794,7 +1796,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_REST: - if (!CanBeSlept(battlerAtk, aiData->abilities[battlerAtk])) + if (!CanBeSlept(battlerAtk, aiData->abilities[battlerAtk], FALSE)) ADJUST_SCORE(-10); //fallthrough case EFFECT_RESTORE_HP: @@ -2077,6 +2079,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); else if (!AI_CanPutToSleep(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove)) ADJUST_SCORE(-10); + if (PartnerMoveActivatesSleepClause(aiData->partnerMove)) + ADJUST_SCORE(-20); break; case EFFECT_SKILL_SWAP: if (aiData->abilities[battlerAtk] == ABILITY_NONE || aiData->abilities[battlerDef] == ABILITY_NONE @@ -2412,6 +2416,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: ADJUST_SCORE(-10); break; case EFFECT_INSTRUCT: @@ -2673,7 +2680,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsMoveEffectWeather(move)) ADJUST_SCORE(-10); break; - } + } } // check partner move effect // Adjust for always crit moves @@ -3451,7 +3458,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_REST: - if (!(CanBeSlept(battlerAtk, aiData->abilities[battlerAtk]))) + if (!(CanBeSlept(battlerAtk, aiData->abilities[battlerAtk], FALSE))) { break; } @@ -3513,6 +3520,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: //todo - check z splash, z celebrate, z happy hour (lol) break; case EFFECT_TELEPORT: // Either remove or add better logic @@ -4399,7 +4409,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_REVIVAL_BLESSING: if (GetFirstFaintedPartyIndex(battlerAtk) != PARTY_SIZE) + { ADJUST_SCORE(DECENT_EFFECT); + if (AI_DATA->shouldSwitch & (1u << battlerAtk)) // Bad matchup + ADJUST_SCORE(WEAK_EFFECT); + if (AI_DATA->mostSuitableMonId[battlerAtk] != PARTY_SIZE) // Good mon to send in after + ADJUST_SCORE(WEAK_EFFECT); + } break; //case EFFECT_EXTREME_EVOBOOST: // TODO //break; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index b679124b31..05600faca1 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -381,6 +381,11 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) else if (gMovesInfo[predictedMove].type == TYPE_GROUND || (isOpposingBattlerChargingOrInvulnerable && gMovesInfo[incomingMove].type == TYPE_GROUND)) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_EARTH_EATER; + absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_LEVITATE; + } + else if (gMovesInfo[predictedMove].soundMove || (isOpposingBattlerChargingOrInvulnerable && gMovesInfo[incomingMove].soundMove)) + { + absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_SOUNDPROOF; } else { @@ -497,7 +502,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) { //Yawn if (gStatuses3[battler] & STATUS3_YAWN - && CanBeSlept(battler, monAbility) + && CanBeSlept(battler, monAbility, TRUE) && gBattleMons[battler].hp > gBattleMons[battler].maxHP / 3) { switchMon = TRUE; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 58da3bd5cc..18ceb7fab2 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2901,7 +2901,7 @@ bool32 IsBattlerIncapacitated(u32 battler, u32 ability) bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) { - if (!CanBeSlept(battlerDef, defAbility) + if (!CanBeSlept(battlerDef, defAbility, TRUE) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) // shouldn't try to sleep mon that partner is trying to make sleep return FALSE; @@ -3391,6 +3391,17 @@ bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMov return FALSE; } +bool32 PartnerMoveActivatesSleepClause(u32 partnerMove) +{ + u32 effect = gMovesInfo[partnerMove].effect; + if (!IsDoubleBattle() || !FlagGet(B_FLAG_SLEEP_CLAUSE)) + return FALSE; + if (effect == EFFECT_SLEEP + || effect == EFFECT_YAWN) + return TRUE; + return FALSE; +} + bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move) { u32 i; diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 5a6d795757..1763333b6a 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -280,7 +280,10 @@ static u16 GetTypeBasedMaxMove(u32 battler, u32 type) // Returns the appropriate Max Move or G-Max Move for a battler to use. u16 GetMaxMove(u32 battler, u32 baseMove) { - u32 move = baseMove; + u32 moveType; + SetTypeBeforeUsingMove(baseMove, battler); + moveType = GetMoveType(baseMove); + if (baseMove == MOVE_NONE) // for move display { return MOVE_NONE; @@ -291,18 +294,12 @@ u16 GetMaxMove(u32 battler, u32 baseMove) } else if (gMovesInfo[baseMove].category == DAMAGE_CATEGORY_STATUS) { - move = MOVE_MAX_GUARD; - } - else if (gBattleStruct->dynamicMoveType) - { - move = GetTypeBasedMaxMove(battler, gBattleStruct->dynamicMoveType & DYNAMIC_TYPE_MASK); + return MOVE_MAX_GUARD; } else { - move = GetTypeBasedMaxMove(battler, gMovesInfo[baseMove].type); + return GetTypeBasedMaxMove(battler, moveType); } - - return move; } // First value is for Fighting, Poison and Multi-Attack. The second is for everything else. @@ -762,7 +759,7 @@ void BS_SetMaxMoveEffect(void) { static const u8 sSnoozeEffects[] = {TRUE, FALSE}; if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN) - && CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget)) + && CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget), TRUE) && RandomElement(RNG_G_MAX_SNOOZE, sSnoozeEffects)) // 50% chance of success { gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); @@ -884,12 +881,14 @@ void BS_TrySetStatus1(void) } break; case STATUS1_SLEEP: - if (CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget))) + if (CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget), TRUE)) { if (B_SLEEP_TURNS >= GEN_5) gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2); else gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3); + + TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); gBattleCommunication[MULTISTRING_CHOOSER] = 4; effect++; } diff --git a/src/battle_main.c b/src/battle_main.c index d76d880497..0799313544 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3117,6 +3117,13 @@ static void BattleStartClearSetData(void) gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing gCategoryIconSpriteId = 0xFF; + + if(FlagGet(B_FLAG_SLEEP_CLAUSE)) + { + // If monCausingSleepClause[side] equals PARTY_SIZE, Sleep Clause is not active for the given side. + gBattleStruct->monCausingSleepClause[B_SIDE_PLAYER] = PARTY_SIZE; + gBattleStruct->monCausingSleepClause[B_SIDE_OPPONENT] = PARTY_SIZE; + } } void SwitchInClearSetData(u32 battler) diff --git a/src/battle_message.c b/src/battle_message.c index 49b85e96d5..412d105585 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -890,6 +890,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_SUPEREFFECTIVETWOFOES] = COMPOUND_STRING("It's super effective on {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}!"), [STRINGID_NOTVERYEFFECTIVETWOFOES] = COMPOUND_STRING("It's not very effective on {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}!"), [STRINGID_ITDOESNTAFFECTTWOFOES] = COMPOUND_STRING("It doesn't affect {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}…"), + [STRINGID_BLOCKEDBYSLEEPCLAUSE] = COMPOUND_STRING("Sleep Clause kept {B_DEF_NAME_WITH_PREFIX2} awake!"), }; const u16 gTrainerUsedItemStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index cc24aeaaa9..64c603fd48 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -479,7 +479,7 @@ static void Cmd_statbuffchange(void); static void Cmd_normalisebuffs(void); static void Cmd_setbide(void); static void Cmd_twoturnmoveschargestringandanimation(void); -static void Cmd_setmultihitcounter(void); +static void Cmd_unused_0x8d(void); static void Cmd_initmultihitstring(void); static void Cmd_forcerandomswitch(void); static void Cmd_tryconversiontypechange(void); @@ -738,7 +738,7 @@ void (* const gBattleScriptingCommandsTable[])(void) = Cmd_normalisebuffs, //0x8A Cmd_setbide, //0x8B Cmd_twoturnmoveschargestringandanimation, //0x8C - Cmd_setmultihitcounter, //0x8D + Cmd_unused_0x8d, //0x8D Cmd_initmultihitstring, //0x8E Cmd_forcerandomswitch, //0x8F Cmd_tryconversiontypechange, //0x90 @@ -1287,53 +1287,6 @@ static void Cmd_attackcanceler(void) gHitMarker &= ~HITMARKER_ALLOW_NO_PP; - if (!(gHitMarker & HITMARKER_OBEYS) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) - { - switch (gBattleStruct->obedienceResult) - { - case OBEYS: - break; - case DISOBEYS_LOAFS: - // Randomly select, then print a disobedient string - // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE - gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS); - gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - return; - case DISOBEYS_HITS_SELF: - gBattlerTarget = gBattlerAttacker; - struct DamageCalculationData damageCalcData; - damageCalcData.battlerAtk = damageCalcData.battlerDef = gBattlerAttacker; - damageCalcData.move = MOVE_NONE; - damageCalcData.moveType = TYPE_MYSTERY; - damageCalcData.isCrit = FALSE; - damageCalcData.randomFactor = FALSE; - damageCalcData.updateFlags = TRUE; - gBattleStruct->calculatedDamage[gBattlerTarget] = CalculateMoveDamage(&damageCalcData, 40); - gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - gHitMarker |= HITMARKER_OBEYS; - return; - case DISOBEYS_FALL_ASLEEP: - gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - return; - case DISOBEYS_WHILE_ASLEEP: - gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - return; - case DISOBEYS_RANDOM_MOVE: - gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; - SetAtkCancellerForCalledMove(); - gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; - gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gHitMarker |= HITMARKER_DISOBEDIENT_MOVE; - gHitMarker |= HITMARKER_OBEYS; - return; - } - } - - gHitMarker |= HITMARKER_OBEYS; // Check if no available target present on the field or if Sky Battles ban the move if ((NoTargetPresent(gBattlerAttacker, gCurrentMove) && (!gBattleMoveEffects[gMovesInfo[gCurrentMove].effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))) @@ -2935,10 +2888,19 @@ static void Cmd_resultmessage(void) } if (*moveResultFlags & MOVE_RESULT_MISSED - && (!(*moveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE) || gBattleStruct->missStringId[gBattlerTarget] > 2)) + && (!(*moveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE) || gBattleStruct->missStringId[gBattlerTarget] > B_MSG_AVOIDED_ATK)) { + if (gMultiHitCounter && gMultiHitCounter < gMovesInfo[gCurrentMove].strikeCount) + { + gMultiHitCounter = 0; + *moveResultFlags &= ~MOVE_RESULT_MISSED; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MultiHitPrintStrings; + return; + } + if (gBattleStruct->missStringId[gBattlerTarget] > B_MSG_AVOIDED_ATK) // Wonder Guard or Levitate - show the ability pop-up - CreateAbilityPopUp(gBattlerTarget, gBattleMons[gBattlerTarget].ability, (IsDoubleBattle()) != 0); + CreateAbilityPopUp(gBattlerTarget, gBattleMons[gBattlerTarget].ability, IsDoubleBattle()); gBattleCommunication[MSG_DISPLAY] = 1; stringId = gMissStringIds[gBattleStruct->missStringId[gBattlerTarget]]; } @@ -3314,7 +3276,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) if (i != gBattlersCount) break; - if (!CanBeSlept(gEffectBattler, GetBattlerAbility(gEffectBattler))) + if (!CanBeSlept(gEffectBattler, GetBattlerAbility(gEffectBattler), TRUE) && !(gBattleStruct->sleepClauseEffectExempt & (1u << gEffectBattler))) break; cancelMultiTurnMovesResult = CancelMultiTurnMoves(gEffectBattler); @@ -3533,6 +3495,8 @@ void SetMoveEffect(bool32 primary, bool32 certain) gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 1, 3)); else gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 2, 5)); + + TryActivateSleepClause(gEffectBattler, gBattlerPartyIndexes[gEffectBattler]); } else { @@ -4499,6 +4463,8 @@ static void Cmd_tryfaintmon(void) PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].moves[moveIndex]) } + + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } else { @@ -6243,6 +6209,7 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal; break; case STATUS1_SLEEP: + TryDeactivateSleepClause(GetBattlerSide(gBattlerTarget), gBattlerPartyIndexes[gBattlerTarget]); gBattlescriptCurrInstr = BattleScript_TargetWokeUp; break; case STATUS1_BURN: @@ -10506,7 +10473,7 @@ static void Cmd_various(void) } case VARIOUS_PSYCHO_SHIFT: { - VARIOUS_ARGS(const u8 *failInstr); + VARIOUS_ARGS(const u8 *failInstr, const u8 *sleepClauseFailInstr); u32 targetAbility = GetBattlerAbility(gBattlerTarget); // Psycho shift works if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, targetAbility)) @@ -10517,10 +10484,15 @@ static void Cmd_various(void) gBattleCommunication[MULTISTRING_CHOOSER] = 2; else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && CanBeParalyzed(gBattlerTarget, targetAbility)) gBattleCommunication[MULTISTRING_CHOOSER] = 3; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerTarget, targetAbility)) + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerTarget, targetAbility, TRUE)) gBattleCommunication[MULTISTRING_CHOOSER] = 4; else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanGetFrostbite(gBattlerTarget)) gBattleCommunication[MULTISTRING_CHOOSER] = 5; + else if (IsSleepClauseActiveForSide(GetBattlerSide(battler))) + { + gBattlescriptCurrInstr = cmd->sleepClauseFailInstr; + return; + } else { gBattlescriptCurrInstr = cmd->failInstr; @@ -10531,11 +10503,16 @@ static void Cmd_various(void) BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; + TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]); return; } case VARIOUS_CURE_STATUS: { VARIOUS_ARGS(); + + if (gBattleMons[battler].status1 & STATUS1_SLEEP) + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + gBattleMons[battler].status1 = 0; BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); @@ -12329,33 +12306,8 @@ static void Cmd_twoturnmoveschargestringandanimation(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setmultihitcounter(void) +static void Cmd_unused_0x8d(void) { - CMD_ARGS(u8 value); - - if (cmd->value) - { - gMultiHitCounter = cmd->value; - } - else - { - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_SKILL_LINK) - { - gMultiHitCounter = 5; - } - else - { - // WARNING: These seem to be unused, see SetRandomMultiHitCounter. - if (B_MULTI_HIT_CHANCE >= GEN_5) - // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits. - gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); - else - // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits. - gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); - } - } - - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_initmultihitstring(void) @@ -13627,12 +13579,11 @@ static void Cmd_healpartystatus(void) u32 zero = 0; u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); u8 toHeal = 0; + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); + s32 i; if (gCurrentMove == MOVE_HEAL_BELL) { - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - s32 i; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL; if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF @@ -13698,7 +13649,10 @@ static void Cmd_healpartystatus(void) } if (ability != ABILITY_SOUNDPROOF) + { toHeal |= (1 << i); + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i); + } } } } @@ -13707,6 +13661,11 @@ static void Cmd_healpartystatus(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOOTHING_AROMA; toHeal = (1 << PARTY_SIZE) - 1; + for (i = 0; i < PARTY_SIZE; i++) + { + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i); + } + gBattleMons[gBattlerAttacker].status1 = 0; gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; @@ -14482,6 +14441,9 @@ static void Cmd_curestatuswithmove(void) if (shouldHeal) { + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); + gBattleMons[gBattlerAttacker].status1 = 0; gBattlescriptCurrInstr = cmd->nextInstr; BtlController_EmitSetMonData(gBattlerAttacker, BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].status1), &gBattleMons[gBattlerAttacker].status1); @@ -15090,6 +15052,9 @@ static void Cmd_switchoutabilities(void) switch (GetBattlerAbility(battler)) { case ABILITY_NATURAL_CURE: + if (gBattleMons[battler].status1 & STATUS1_SLEEP) + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + gBattleMons[battler].status1 = 0; BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 1u << *(gBattleStruct->battlerPartyIndexes + battler), @@ -17609,6 +17574,25 @@ void BS_DamageToQuarterTargetHP(void) gBattlescriptCurrInstr = cmd->nextInstr; } +void BS_JumpIfSleepClause(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + + // Can freely sleep own partner + if (IsDoubleBattle() && B_FLAG_SLEEP_CLAUSE && GetBattlerSide(gBattlerAttacker) == GetBattlerSide(gBattlerTarget)) + { + gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerTarget); + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + gBattleStruct->sleepClauseEffectExempt &= ~(1u << gBattlerTarget); + // Can't sleep if clause is active otherwise + if (IsSleepClauseActiveForSide(GetBattlerSide(gBattlerTarget))) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + void BS_FickleBeamDamageCalculation(void) { NATIVE_ARGS(); diff --git a/src/battle_util.c b/src/battle_util.c index 5c3c5244eb..01086e059a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -146,8 +146,6 @@ void HandleAction_UseMove(void) gBattleScripting.savedMoveEffect = 0; gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerAttacker); - gBattleStruct->obedienceResult = GetAttackerObedienceForAction(); - // choose move if (gProtectStructs[gBattlerAttacker].noValidMoves) { @@ -2775,7 +2773,7 @@ u8 DoBattlerEndTurnEffects(void) && !IsLeafGuardProtected(battler)) { CancelMultiTurnMoves(battler); - gEffectBattler = battler; + gEffectBattler = gBattlerTarget = battler; if (IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_ELECTRIC; @@ -2786,6 +2784,10 @@ u8 DoBattlerEndTurnEffects(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_MISTY; BattleScriptExecute(BattleScript_TerrainPreventsEnd2); } + else if (IsSleepClauseActiveForSide(GetBattlerSide(battler))) + { + BattleScriptExecute(BattleScript_SleepClausePreventsEnd); + } else { if (B_SLEEP_TURNS >= GEN_5) @@ -2793,6 +2795,7 @@ u8 DoBattlerEndTurnEffects(void) else gBattleMons[battler].status1 |= ((Random() % 4) + 3); + TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]); BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); BattleScriptExecute(BattleScript_YawnMakesAsleep); @@ -3213,7 +3216,8 @@ void SetAtkCancellerForCalledMove(void) u8 AtkCanceller_UnableToUseMove(u32 moveType) { - u8 effect = 0; + u32 effect = 0; + u32 obedienceResult; do { switch (gBattleStruct->atkCancellerTracker) @@ -3239,6 +3243,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) { if (UproarWakeUpCheck(gBattlerAttacker)) { + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; BattleScriptPushCursor(); @@ -3268,6 +3273,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) } else { + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; BattleScriptPushCursor(); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP; @@ -3297,6 +3303,62 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) } gBattleStruct->atkCancellerTracker++; break; + case CANCELLER_OBEDIENCE: + obedienceResult = GetAttackerObedienceForAction(); + if (obedienceResult != OBEYS + && !(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves + && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) + { + switch (obedienceResult) + { + case DISOBEYS_LOAFS: + // Randomly select, then print a disobedient string + // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE + gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS); + gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + break; + case DISOBEYS_HITS_SELF: + gBattlerTarget = gBattlerAttacker; + struct DamageCalculationData damageCalcData; + damageCalcData.battlerAtk = damageCalcData.battlerDef = gBattlerAttacker; + damageCalcData.move = MOVE_NONE; + damageCalcData.moveType = TYPE_MYSTERY; + damageCalcData.isCrit = FALSE; + damageCalcData.randomFactor = FALSE; + damageCalcData.updateFlags = TRUE; + gBattleStruct->calculatedDamage[gBattlerAttacker] = CalculateMoveDamage(&damageCalcData, 40); + gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + gHitMarker |= HITMARKER_OBEYS; + break; + case DISOBEYS_FALL_ASLEEP: + if (FlagGet(B_FLAG_SLEEP_CLAUSE)) + gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + break; + case DISOBEYS_WHILE_ASLEEP: + gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + break; + case DISOBEYS_RANDOM_MOVE: + gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; + SetAtkCancellerForCalledMove(); + gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; + gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); + gHitMarker |= HITMARKER_DISOBEDIENT_MOVE; + gHitMarker |= HITMARKER_OBEYS; + break; + } + effect = 1; + } + else + { + gHitMarker |= HITMARKER_OBEYS; + } + gBattleStruct->atkCancellerTracker++; + break; case CANCELLER_TRUANT: // truant if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) { @@ -3551,7 +3613,6 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) gBattleStruct->calculatedDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE - || gBattleStruct->obedienceResult != OBEYS || HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE)) gBattlescriptCurrInstr = BattleScript_MoveUsedPowder; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; @@ -3572,8 +3633,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) gBattleStruct->atkCancellerTracker++; break; case CANCELLER_Z_MOVES: - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE - && gBattleStruct->obedienceResult == OBEYS) + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) { // For Z-Mirror Move, so it doesn't play the animation twice. bool32 alreadyUsed = HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE); @@ -5206,7 +5266,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gBattleMons[battler].status1 & (STATUS1_POISON | STATUS1_TOXIC_POISON)) StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); if (gBattleMons[battler].status1 & STATUS1_SLEEP) + { StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + } + if (gBattleMons[battler].status1 & STATUS1_PARALYSIS) StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); if (gBattleMons[battler].status1 & STATUS1_BURN) @@ -5809,10 +5873,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED - && CanBeSlept(gBattlerAttacker, ability) + && CanBeSlept(gBattlerAttacker, ability, FALSE) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker)) { + if (FlagGet(B_FLAG_SLEEP_CLAUSE)) + gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker); gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_SLEEP; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptPushCursor(); @@ -6245,6 +6311,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_VITAL_SPIRIT: if (gBattleMons[battler].status1 & STATUS1_SLEEP) { + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); effect = 1; @@ -6667,8 +6734,11 @@ bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag) return IsBattlerGrounded(battler); } -bool32 CanBeSlept(u32 battler, u32 ability) +bool32 CanBeSlept(u32 battler, u32 ability, u32 isBlockedBySleepClause) { + if(IsSleepClauseActiveForSide(GetBattlerSide(battler)) && isBlockedBySleepClause) + return FALSE; + if (ability == ABILITY_INSOMNIA || ability == ABILITY_VITAL_SPIRIT || ability == ABILITY_COMATOSE @@ -7338,6 +7408,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect) BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_BerryCureSlpRet; effect = ITEM_STATUS_CHANGE; + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } break; case HOLD_EFFECT_CURE_CONFUSION: @@ -7369,6 +7440,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect) { gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } if (gBattleMons[battler].status1 & STATUS1_PARALYSIS) @@ -7579,6 +7651,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; BattleScriptExecute(BattleScript_BerryCureSlpEnd2); effect = ITEM_STATUS_CHANGE; + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } break; case HOLD_EFFECT_CURE_STATUS: @@ -7597,6 +7670,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); i++; + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } if (gBattleMons[battler].status1 & STATUS1_PARALYSIS) { @@ -7876,6 +7950,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; BattleScriptExecute(BattleScript_BerryCureSlpEnd2); effect = ITEM_STATUS_CHANGE; + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } break; case HOLD_EFFECT_CURE_CONFUSION: @@ -7900,6 +7975,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); i++; + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } if (gBattleMons[battler].status1 & STATUS1_PARALYSIS) { @@ -8540,7 +8616,7 @@ u8 GetAttackerObedienceForAction() obedienceLevel = levelReferenced - obedienceLevel; calc = ((rnd >> 16) & 255); - if (calc < obedienceLevel && CanBeSlept(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) + if (calc < obedienceLevel && CanBeSlept(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), FALSE)) { // try putting asleep int i; @@ -10762,6 +10838,7 @@ bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) case FORM_CHANGE_BATTLE_PRIMAL_REVERSION: case FORM_CHANGE_BATTLE_ULTRA_BURST: case FORM_CHANGE_ITEM_HOLD: + case FORM_CHANGE_BEGIN_BATTLE: if (formChanges[i].param1 == heldItemId) return TRUE; break; @@ -11967,6 +12044,34 @@ u32 GetMoveType(u32 move) return gMovesInfo[move].type; } +void TryActivateSleepClause(u32 battler, u32 indexInParty) +{ + if (gBattleStruct->sleepClauseEffectExempt & (1u << battler)) + { + gBattleStruct->sleepClauseEffectExempt &= ~(1u << battler); + return; + } + + if (FlagGet(B_FLAG_SLEEP_CLAUSE)) + gBattleStruct->monCausingSleepClause[GetBattlerSide(battler)] = indexInParty; +} + +void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty) +{ + // If the pokemon on the given side at the given index in the party is the one causing Sleep Clause to be active, + // set monCausingSleepClause[battlerSide] = PARTY_SIZE, which means Sleep Clause is not active for the given side + if (FlagGet(B_FLAG_SLEEP_CLAUSE) && gBattleStruct->monCausingSleepClause[battlerSide] == indexInParty) + gBattleStruct->monCausingSleepClause[battlerSide] = PARTY_SIZE; +} + +bool32 IsSleepClauseActiveForSide(u32 battlerSide) +{ + // If monCausingSleepClause[battlerSide] == PARTY_SIZE, Sleep Clause is not active for the given side. + // If monCausingSleepClause[battlerSide] < PARTY_SIZE, it means it is storing the index of the mon that is causing Sleep Clause to be active, + // from which it follows that Sleep Clause is active. + return (FlagGet(B_FLAG_SLEEP_CLAUSE) && (gBattleStruct->monCausingSleepClause[battlerSide] < PARTY_SIZE)); +} + void ClearDamageCalcResults(void) { for (u32 battler = 0; battler < MAX_BATTLERS_COUNT; battler++) diff --git a/src/contest.c b/src/contest.c index 16e5fde9af..e03d5e8b3b 100644 --- a/src/contest.c +++ b/src/contest.c @@ -949,23 +949,22 @@ static const struct CompressedSpriteSheet sSpriteSheets_ContestantsTurnBlinkEffe } }; -// Yup this is super dangerous but that's how it is here static const struct SpritePalette sSpritePalettes_ContestantsTurnBlinkEffect[CONTESTANT_COUNT] = { { - .data = (u16 *)(gHeap + 0x1A0A4), + .data = eContestTempSave.cachedWindowPalettes[5], .tag = TAG_BLINK_EFFECT_CONTESTANT0 }, { - .data = (u16 *)(gHeap + 0x1A0C4), + .data = eContestTempSave.cachedWindowPalettes[6], .tag = TAG_BLINK_EFFECT_CONTESTANT1 }, { - .data = (u16 *)(gHeap + 0x1A0E4), + .data = eContestTempSave.cachedWindowPalettes[7], .tag = TAG_BLINK_EFFECT_CONTESTANT2 }, { - .data = (u16 *)(gHeap + 0x1A104), + .data = eContestTempSave.cachedWindowPalettes[8], .tag = TAG_BLINK_EFFECT_CONTESTANT3 } }; diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index b5b3e539c8..ab70de3681 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -425,6 +425,27 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .encourageEncore = TRUE, }, + [EFFECT_HOLD_HANDS] = + { + .battleScript = BattleScript_EffectHoldHands, + .battleTvScore = 1, + .encourageEncore = TRUE, + }, + + [EFFECT_CELEBRATE] = + { + .battleScript = BattleScript_EffectCelebrate, + .battleTvScore = 1, + .encourageEncore = TRUE, + }, + + [EFFECT_HAPPY_HOUR] = + { + .battleScript = BattleScript_EffectHappyHour, + .battleTvScore = 1, + .encourageEncore = TRUE, + }, + [EFFECT_DISABLE] = { .battleScript = BattleScript_EffectDisable, diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 180d0d74ac..49d35c0897 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -15010,7 +15010,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Doubles the amount of\n" "Prize Money received."), - .effect = EFFECT_DO_NOTHING, + .effect = EFFECT_HAPPY_HOUR, .power = 0, .type = TYPE_NORMAL, .accuracy = 0, @@ -15080,7 +15080,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Congratulates you on your\n" "special day."), - .effect = EFFECT_DO_NOTHING, + .effect = EFFECT_CELEBRATE, .power = 0, .type = TYPE_NORMAL, .accuracy = 0, @@ -15110,7 +15110,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "The user and ally hold hands\n" "making them happy."), - .effect = EFFECT_DO_NOTHING, + .effect = EFFECT_HOLD_HANDS, .power = 0, .type = TYPE_NORMAL, .accuracy = 0, diff --git a/src/data/pokemon_graphics/front_pic_anims.h b/src/data/pokemon_graphics/front_pic_anims.h index 8452e24732..deceeb0420 100644 --- a/src/data/pokemon_graphics/front_pic_anims.h +++ b/src/data/pokemon_graphics/front_pic_anims.h @@ -5205,8 +5205,7 @@ static const union AnimCmd sAnim_DeoxysNormal_1[] = { ANIMCMD_FRAME(0, 16), ANIMCMD_FRAME(1, 16), - ANIMCMD_FRAME(0, 26), - ANIMCMD_FRAME(1, 16), + ANIMCMD_FRAME(1, 26), ANIMCMD_FRAME(0, 16), ANIMCMD_END, }; diff --git a/src/mini_printf.c b/src/mini_printf.c index c5b1e09bdc..9332a270a4 100644 --- a/src/mini_printf.c +++ b/src/mini_printf.c @@ -86,6 +86,8 @@ static inline char mini_pchar_decode(char encoded) ret = '('; // opening parentheses else if (encoded == CHAR_RIGHT_PAREN) ret = ')'; // closing parentheses + else if (encoded == CHAR_HYPHEN) + ret = '-'; // hyphen return ret; } @@ -133,7 +135,31 @@ static s32 _putsEncoded(char *s, s32 len, void *buf) { break; } - *(b->pbuffer ++) = mini_pchar_decode(s[i]); + if (s[i] == CHAR_NEWLINE) + { + *(b->pbuffer ++) = '\\'; + *(b->pbuffer ++) = 'n'; + } + else if (s[i] == CHAR_PROMPT_SCROLL) + { + *(b->pbuffer ++) = '\\'; + *(b->pbuffer ++) = 'l'; + } + else if (s[i] == CHAR_PROMPT_CLEAR) + { + *(b->pbuffer ++) = '\\'; + *(b->pbuffer ++) = 'p'; + } + else if (s[i] == CHAR_ELLIPSIS) + { + *(b->pbuffer ++) = '.'; + *(b->pbuffer ++) = '.'; + *(b->pbuffer ++) = '.'; + } + else + { + *(b->pbuffer ++) = mini_pchar_decode(s[i]); + } } *(b->pbuffer) = 0; return b->pbuffer - p0; diff --git a/src/pokemon.c b/src/pokemon.c index 9f716e3a79..743f5b2771 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -4199,7 +4199,24 @@ bool8 HealStatusConditions(struct Pokemon *mon, u32 healMask, u8 battlerId) status &= ~healMask; SetMonData(mon, MON_DATA_STATUS, &status); if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT) + { gBattleMons[battlerId].status1 &= ~healMask; + if((healMask & STATUS1_SLEEP)) + { + u32 i = 0; + u32 battlerSide = GetBattlerSide(battlerId); + struct Pokemon *party = GetSideParty(battlerSide); + + for (i = 0; i < PARTY_SIZE; i++) + { + if (&party[i] == mon) + { + TryDeactivateSleepClause(battlerSide, i); + break; + } + } + } + } return FALSE; } else @@ -4977,16 +4994,25 @@ u16 HoennToNationalOrder(u16 hoennNum) The function then loops over the 16x16 spot image. For each bit in the spot's binary image, if the bit is set then it's part of the spot; try to draw it. A pixel is drawn on Spinda if the - pixel on Spinda satisfies the following formula: ((u8)(colorIndex - 1) <= 2). The -1 excludes - transparent pixels, as these are index 0. Therefore only colors 1, 2, or 3 on Spinda will - allow a spot to be drawn. These color indexes are Spinda's light brown body colors. To create + pixel is between FIRST_SPOT_COLOR and LAST_SPOT_COLOR (so only colors 1, 2, or 3 on Spinda will + allow a spot to be drawn). These color indexes are Spinda's light brown body colors. To create the spot it adds 4 to the color index, so Spinda's spots will be colors 5, 6, and 7. - The above is done two different ways in the function: one with << 4, and one without. This - is because Spinda's sprite is a 4 bits per pixel image, but the pointer to Spinda's pixels + The above is done in TRY_DRAW_SPOT_PIXEL two different ways: one with << 4, and one without. + This is because Spinda's sprite is a 4 bits per pixel image, but the pointer to Spinda's pixels (destPixels) is an 8 bit pointer, so it addresses two pixels. Shifting by 4 accesses the 2nd of these pixels, so this is done every other time. */ + +// Draw spot pixel if this is Spinda's body color +#define TRY_DRAW_SPOT_PIXEL(pixels, shift) \ + if (((*(pixels) & (0xF << (shift))) >= (FIRST_SPOT_COLOR << (shift))) \ + && ((*(pixels) & (0xF << (shift))) <= (LAST_SPOT_COLOR << (shift)))) \ + { \ + *(pixels) += (SPOT_COLOR_ADJUSTMENT << (shift)); \ + } + + void DrawSpindaSpots(u32 personality, u8 *dest, bool32 isSecondFrame) { s32 i; @@ -5028,16 +5054,12 @@ void DrawSpindaSpots(u32 personality, u8 *dest, bool32 isSecondFrame) if (column & 1) { /* Draw spot pixel if this is Spinda's body color */ - if ((u8)((*destPixels & 0xF0) - (FIRST_SPOT_COLOR << 4)) - <= ((LAST_SPOT_COLOR - FIRST_SPOT_COLOR) << 4)) - *destPixels += (SPOT_COLOR_ADJUSTMENT << 4); + TRY_DRAW_SPOT_PIXEL(destPixels, 4); } else { /* Draw spot pixel if this is Spinda's body color */ - if ((u8)((*destPixels & 0xF) - FIRST_SPOT_COLOR) - <= (LAST_SPOT_COLOR - FIRST_SPOT_COLOR)) - *destPixels += SPOT_COLOR_ADJUSTMENT; + TRY_DRAW_SPOT_PIXEL(destPixels, 0); } } diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 71c960fcc5..0883e3cc59 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -806,3 +806,28 @@ AI_SINGLE_BATTLE_TEST("AI uses a guaranteed KO move instead of the move with the NOT MESSAGE("Wobbuffet fainted!"); } } + +AI_SINGLE_BATTLE_TEST("AI stays choice locked into moves in spite of the player's ability disabling them") +{ + u32 playerMon, ability, aiMove; + PARAMETRIZE { ability = ABILITY_DAZZLING; playerMon = SPECIES_BRUXISH; aiMove = MOVE_QUICK_ATTACK; } + PARAMETRIZE { ability = ABILITY_QUEENLY_MAJESTY; playerMon = SPECIES_TSAREENA; aiMove = MOVE_QUICK_ATTACK; } + PARAMETRIZE { ability = ABILITY_ARMOR_TAIL; playerMon = SPECIES_FARIGIRAF; aiMove = MOVE_QUICK_ATTACK; } + PARAMETRIZE { ability = ABILITY_SOUNDPROOF; playerMon = SPECIES_EXPLOUD; aiMove = MOVE_BOOMBURST; } + PARAMETRIZE { ability = ABILITY_BULLETPROOF; playerMon = SPECIES_CHESNAUGHT; aiMove = MOVE_BULLET_SEED; } + + GIVEN { + ASSUME(gItemsInfo[ITEM_CHOICE_BAND].holdEffect == HOLD_EFFECT_CHOICE_BAND); + ASSUME(gMovesInfo[MOVE_QUICK_ATTACK].priority == 1); + ASSUME(gMovesInfo[MOVE_BOOMBURST].soundMove == TRUE); + ASSUME(gMovesInfo[MOVE_BULLET_SEED].ballisticMove == TRUE); + ASSUME(gMovesInfo[MOVE_TAIL_WHIP].category == DAMAGE_CATEGORY_STATUS); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(playerMon) { Ability(ability); } + OPPONENT(SPECIES_SMEARGLE) { Item(ITEM_CHOICE_BAND); Moves(aiMove, MOVE_TACKLE); } + } WHEN { + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, aiMove); } + TURN { EXPECT_MOVE(opponent, aiMove); } + } +} diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 20d05bc0c3..00caff5932 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -708,15 +708,29 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's m AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has an absorber") { + u32 aiMon; u32 move; u32 absorbingAbility; + PARAMETRIZE { aiMon = SPECIES_NINETALES; absorbingAbility = ABILITY_FLASH_FIRE; move = MOVE_FLAMETHROWER;} + PARAMETRIZE { aiMon = SPECIES_MANTINE; absorbingAbility = ABILITY_WATER_ABSORB; move = MOVE_SURF;} + PARAMETRIZE { aiMon = SPECIES_TOXICROAK; absorbingAbility = ABILITY_DRY_SKIN; move = MOVE_SURF;} + PARAMETRIZE { aiMon = SPECIES_GASTRODON; absorbingAbility = ABILITY_STORM_DRAIN; move = MOVE_SURF;} + PARAMETRIZE { aiMon = SPECIES_JOLTEON; absorbingAbility = ABILITY_VOLT_ABSORB; move = MOVE_THUNDERBOLT;} + PARAMETRIZE { aiMon = SPECIES_ELECTIVIRE; absorbingAbility = ABILITY_MOTOR_DRIVE; move = MOVE_THUNDERBOLT;} + PARAMETRIZE { aiMon = SPECIES_MANECTRIC; absorbingAbility = ABILITY_LIGHTNING_ROD; move = MOVE_THUNDERBOLT;} + PARAMETRIZE { aiMon = SPECIES_ELECTIVIRE; absorbingAbility = ABILITY_MOTOR_DRIVE; move = MOVE_THUNDERBOLT;} + PARAMETRIZE { aiMon = SPECIES_AZUMARILL; absorbingAbility = ABILITY_SAP_SIPPER; move = MOVE_GIGA_DRAIN;} + PARAMETRIZE { aiMon = SPECIES_ORTHWORM; absorbingAbility = ABILITY_EARTH_EATER; move = MOVE_EARTHQUAKE;} + PARAMETRIZE { aiMon = SPECIES_BRONZONG; absorbingAbility = ABILITY_LEVITATE; move = MOVE_EARTHQUAKE;} + PARAMETRIZE { aiMon = SPECIES_ELECTRODE; absorbingAbility = ABILITY_SOUNDPROOF; move = MOVE_HYPER_VOICE;} GIVEN { + ASSUME(B_REDIRECT_ABILITY_IMMUNITY >= GEN_5); ASSUME(gMovesInfo[MOVE_WATER_GUN].type == TYPE_WATER); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); - PLAYER(SPECIES_LUVDISC) { Moves(MOVE_WATER_GUN); } + PLAYER(SPECIES_ZIGZAGOON) { Moves(move); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } - OPPONENT(SPECIES_MANTINE) { Moves(MOVE_TACKLE); Ability(ABILITY_WATER_ABSORB); } + OPPONENT(aiMon) { Moves(MOVE_TACKLE); Ability(absorbingAbility); } } WHEN { - TURN { MOVE(player, MOVE_WATER_GUN) ; EXPECT_MOVE(opponent, MOVE_TACKLE); } - TURN { MOVE(player, MOVE_WATER_GUN) ; EXPECT_SWITCH(opponent, 1); } + TURN { MOVE(player, move); EXPECT_MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(player, move); EXPECT_SWITCH(opponent, 1); } } } diff --git a/test/battle/move_effect/hold_hands.c b/test/battle/move_effect/hold_hands.c new file mode 100644 index 0000000000..bcdb6a952a --- /dev/null +++ b/test/battle/move_effect/hold_hands.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_HOLD_HANDS].effect == EFFECT_HOLD_HANDS); +} + +DOUBLE_BATTLE_TEST("Hold Hands is blocked by Crafty Shield") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(playerLeft, MOVE_CRAFTY_SHIELD, target: opponentLeft); + MOVE(playerRight, MOVE_HOLD_HANDS, target: playerLeft); + } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HOLD_HANDS, playerLeft); + MESSAGE("Wynaut protected itself!"); + } +} diff --git a/test/battle/move_effect/knock_off.c b/test/battle/move_effect/knock_off.c index aa1081ff67..61bb062a25 100644 --- a/test/battle/move_effect/knock_off.c +++ b/test/battle/move_effect/knock_off.c @@ -202,6 +202,126 @@ SINGLE_BATTLE_TEST("Knock Off doesn't knock off items from Pokemon behind substi } WHEN { TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_KNOCK_OFF); } } SCENE { - NOT MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Poké Ball"); + NOT MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Poké Ball!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off does knock off Mega Stones from Pokemon that don't actually use them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ABSOLITE); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Absolite!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off doesn't knock off Mega Stones from Pokemon that actually use them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ABSOL) { Item(ITEM_ABSOLITE); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + NOT MESSAGE("Wobbuffet knocked off the opposing Absol's Absolite!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off does knock off Orbs for Primal Reversion from Pokemon that don't actually use them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RED_ORB); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Red Orb!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off doesn't knock off Orbs for Primal Reversion from Pokemon that actually use them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + NOT MESSAGE("Wobbuffet knocked off the opposing Groudon's Red Orb!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off doesn't knock off Z-Crystals") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIUM_Z); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + NOT MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Electrium Z!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off doesn't knock off Ultranecrozium Z from Pokemon that actually use it") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_NECROZMA_DUSK_MANE) { Item(ITEM_ULTRANECROZIUM_Z); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + NOT MESSAGE("Wobbuffet knocked off the opposing Necrozma's Ultranecrozium Z!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off does knock off other form-change hold items from Pokemon that don't actually use them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SKY_PLATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Sky Plate!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off doesn't knock off other form-change hold items from Pokemon that actually use them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ARCEUS) { Item(ITEM_SKY_PLATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + NOT MESSAGE("Wobbuffet knocked off the opposing Arceus's Sky Plate!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off does knock off begin-battle form-change hold items from Pokemon that don't actually use them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RUSTED_SHIELD); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Rusted Shield!"); + } +} + +SINGLE_BATTLE_TEST("Knock Off doesn't knock off begin-battle form-change hold items from Pokemon that actually use them") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZAMAZENTA_HERO) { Item(ITEM_RUSTED_SHIELD); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + NOT MESSAGE("Wobbuffet knocked off the opposing Zamazenta's Rusted Shield!"); } } diff --git a/test/battle/sleep_clause.c b/test/battle/sleep_clause.c new file mode 100644 index 0000000000..c8393685b8 --- /dev/null +++ b/test/battle/sleep_clause.c @@ -0,0 +1,1816 @@ +#include "global.h" +#include "test/battle.h" + +AI_SINGLE_BATTLE_TEST("Sleep Clause: AI will not use sleep moves while sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Moves(MOVE_SPORE, MOVE_MACH_PUNCH); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_SPORE); } + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, MOVE_MACH_PUNCH); } + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_MACH_PUNCH); } + } +} + +AI_DOUBLE_BATTLE_TEST("Sleep Clause: AI will not use sleep moves while sleep clause is active (Doubles)") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Moves(MOVE_SPORE, MOVE_MACH_PUNCH); } + OPPONENT(SPECIES_BRELOOM) { Moves(MOVE_MACH_PUNCH); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_CELEBRATE); MOVE(playerRight, MOVE_CELEBRATE); EXPECT_MOVE(opponentLeft, MOVE_SPORE); EXPECT_MOVE(opponentRight, MOVE_MACH_PUNCH); } + TURN { SWITCH(playerLeft, 2); MOVE(playerRight, MOVE_CELEBRATE); EXPECT_MOVE(opponentLeft, MOVE_MACH_PUNCH); EXPECT_MOVE(opponentRight, MOVE_MACH_PUNCH); } + TURN { MOVE(playerLeft, MOVE_CELEBRATE); MOVE(playerRight, MOVE_CELEBRATE); EXPECT_MOVE(opponentLeft, MOVE_MACH_PUNCH); EXPECT_MOVE(opponentRight, MOVE_MACH_PUNCH); } + } +} + +AI_DOUBLE_BATTLE_TEST("Sleep Clause: AI will not use sleep move if partner is already using a sleep move") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Moves(MOVE_SPORE, MOVE_MACH_PUNCH); } + OPPONENT(SPECIES_BRELOOM) { Moves(MOVE_SPORE, MOVE_MACH_PUNCH); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_CELEBRATE); MOVE(playerRight, MOVE_CELEBRATE); EXPECT_MOVE(opponentLeft, MOVE_SPORE); EXPECT_MOVE(opponentRight, MOVE_MACH_PUNCH); } + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep moves fail when sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_SPORE); SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } + MESSAGE("Sleep Clause kept the opposing Wobbuffet awake!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep moves fail when sleep clause is active (Doubles)") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target: opponentRight); MOVE(playerRight, MOVE_SPORE, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponentRight, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerRight); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + } + MESSAGE("Sleep Clause kept the opposing Wobbuffet awake!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Rest does not activate sleep clause") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_REST].effect == EFFECT_REST); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_REST); } + TURN { MOVE(player, MOVE_SPORE); SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Rest does not activate sleep clause (Doubles)") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_REST].effect == EFFECT_REST); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_REST); MOVE(playerLeft, MOVE_SPORE, target: opponentRight); } + } SCENE { + STATUS_ICON(opponentLeft, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponentRight, sleep: TRUE); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Rest can still be used when sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_REST].effect == EFFECT_REST); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_TACKLE); SWITCH(opponent, 1); } + TURN { MOVE(opponent, MOVE_REST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + STATUS_ICON(opponent, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, opponent); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Rest can still be used when sleep clause is active (Doubles)") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_REST].effect == EFFECT_REST); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target: opponentRight); MOVE(opponentLeft, MOVE_REST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponentRight, sleep: TRUE); + STATUS_ICON(opponentLeft, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, opponentLeft); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Psycho Shift'ing sleep will fail if sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_SLEEP_TALK].effect == EFFECT_SLEEP_TALK); + ASSUME(gMovesInfo[MOVE_PSYCHO_SHIFT].effect == EFFECT_PSYCHO_SHIFT); + PLAYER(SPECIES_WOBBUFFET) + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SLEEP_TALK, MOVE_PSYCHO_SHIFT); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + TURN { MOVE(opponent, MOVE_SPORE); MOVE(player, MOVE_SLEEP_TALK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHO_SHIFT, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + STATUS_ICON(opponent, sleep: TRUE); + } + MESSAGE("Sleep Clause kept the opposing Wobbuffet awake!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Psycho Shift'ing sleep will activate sleep clause") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_SLEEP_TALK].effect == EFFECT_SLEEP_TALK); + ASSUME(gMovesInfo[MOVE_PSYCHO_SHIFT].effect == EFFECT_PSYCHO_SHIFT); + PLAYER(SPECIES_ZIGZAGOON) + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SLEEP_TALK, MOVE_PSYCHO_SHIFT); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); MOVE(opponent, MOVE_SLEEP_TALK); } + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + TURN { MOVE(opponent, MOVE_SPORE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHO_SHIFT, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + STATUS_ICON(player, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } + MESSAGE("Sleep Clause kept Zigzagoon awake!"); + } +} + +AI_SINGLE_BATTLE_TEST("Sleep Clause: AI will not use Yawn while sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Moves(MOVE_YAWN, MOVE_MACH_PUNCH); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_YAWN); } + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_MACH_PUNCH); } + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, MOVE_MACH_PUNCH); } + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_MACH_PUNCH); } + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Yawn will fail when sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_YAWN); } + TURN { } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_YAWN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("Wobbuffet fell asleep!"); + STATUS_ICON(player, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + STATUS_ICON(player, sleep: TRUE); + } + MESSAGE("Sleep Clause kept Wobbuffet awake!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Effect Spore causes sleep 11% of the time with sleep clause active") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SPORE); } + TURN { SWITCH(player, 1); } + TURN { MOVE(player, MOVE_TACKLE); } + TURN { } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!"); + STATUS_ICON(player, sleep: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Effect Spore causes sleep 11% of the time with sleep clause active (Doubles)") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SPORE, target:playerRight); MOVE(playerLeft, MOVE_TACKLE, target:opponentLeft);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Wobbuffet fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + ABILITY_POPUP(opponentLeft, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerLeft); + MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!"); + STATUS_ICON(playerLeft, sleep: TRUE); + } +} + + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep from Effect Spore will not activate sleep clause") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN {} + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_SPORE); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!"); + STATUS_ICON(player, sleep: TRUE); + 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); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep from Effect Spore will not activate sleep clause (Doubles)") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target:opponentLeft); MOVE(opponentLeft, MOVE_SPORE, target:playerRight); } + } SCENE { + ABILITY_POPUP(opponentLeft, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerLeft); + MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!"); + STATUS_ICON(playerLeft, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Wobbuffet fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Moves with sleep effect chance will activate sleep clause") +{ + PASSES_RANDOMLY(10, 100, RNG_SECONDARY_EFFECT); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(MoveHasAdditionalEffect(MOVE_RELIC_SONG, MOVE_EFFECT_SLEEP)); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_RELIC_SONG); } + TURN { MOVE(player, MOVE_SPORE); SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + STATUS_ICON(opponent, sleep: TRUE); + MESSAGE("Wobbuffet used Spore!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Moves with sleep effect chance will still do damage when sleep clause active, but won't sleep") +{ + PASSES_RANDOMLY(100, 100, RNG_SECONDARY_EFFECT); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(MoveHasAdditionalEffect(MOVE_RELIC_SONG, MOVE_EFFECT_SLEEP)); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_RELIC_SONG); SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + STATUS_ICON(opponent, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player); + HP_BAR(opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Dire Claw cannot sleep a mon when sleep clause is active") +{ + PASSES_RANDOMLY(100, 100, RNG_SECONDARY_EFFECT); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(MoveHasAdditionalEffect(MOVE_DIRE_CLAW, MOVE_EFFECT_DIRE_CLAW)); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_DIRE_CLAW); SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + STATUS_ICON(opponent, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); + HP_BAR(opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Dark Void can only sleep one opposing mon if sleep clause is active") +{ + // Source: https://bulbapedia.bulbagarden.net/wiki/Dark_Void_(move) + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_DARK_VOID].effect == EFFECT_DARK_VOID); + PLAYER(SPECIES_DARKRAI); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_DARK_VOID); } + TURN { MOVE(playerLeft, MOVE_DARK_VOID); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DARK_VOID, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + STATUS_ICON(opponentRight, sleep: TRUE); + MESSAGE("The opposing Wobbuffet fell asleep!"); + } + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: G-Max Befuddle can only sleep one opposing mon if sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_G_MAX_BEFUDDLE].argument == MAX_EFFECT_EFFECT_SPORE_FOES); + PLAYER(SPECIES_BUTTERFREE) { GigantamaxFactor(TRUE); } + PLAYER(SPECIES_CATERPIE); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_BUG_BITE, target: opponentLeft, gimmick: GIMMICK_DYNAMAX, + WITH_RNG(RNG_G_MAX_BEFUDDLE, STATUS1_SLEEP)); } + } SCENE { + MESSAGE("Butterfree used G-Max Befuddle!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + STATUS_ICON(opponentRight, sleep: TRUE); + MESSAGE("The opposing Wobbuffet fell asleep!"); + } + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon wakes up") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(B_SLEEP_TURNS >= GEN_5); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN {} + TURN {} + TURN {} + TURN { MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("The opposing Wobbuffet woke up!"); + MESSAGE("Wobbuffet used Spore!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up with Aromatherapy / Heal Bell / Sparkly Swirl") +{ + u32 move = MOVE_NONE, switchIndex = 0; + struct BattlePokemon *healingSlot = opponentRight; + struct BattlePokemon *sporedSlot = opponentLeft; + PARAMETRIZE { move = MOVE_AROMATHERAPY; healingSlot = opponentRight; sporedSlot = opponentLeft; switchIndex = 0; } + PARAMETRIZE { move = MOVE_HEAL_BELL; healingSlot = opponentRight; sporedSlot = opponentLeft; switchIndex = 0; } + PARAMETRIZE { move = MOVE_SPARKLY_SWIRL; healingSlot = opponentRight; sporedSlot = opponentLeft; switchIndex = 0; } + PARAMETRIZE { move = MOVE_AROMATHERAPY; healingSlot = opponentLeft; sporedSlot = opponentRight; switchIndex = 1; } + PARAMETRIZE { move = MOVE_HEAL_BELL; healingSlot = opponentLeft; sporedSlot = opponentRight; switchIndex = 1; } + PARAMETRIZE { move = MOVE_SPARKLY_SWIRL; healingSlot = opponentLeft; sporedSlot = opponentRight; switchIndex = 1; } + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_AROMATHERAPY].effect == EFFECT_HEAL_BELL); + ASSUME(gMovesInfo[MOVE_HEAL_BELL].effect == EFFECT_HEAL_BELL); + ASSUME(gMovesInfo[MOVE_SPARKLY_SWIRL].effect == EFFECT_SPARKLY_SWIRL); + ASSUME(B_SLEEP_TURNS >= GEN_5); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target:sporedSlot); } + TURN { SWITCH(sporedSlot, 2); MOVE(playerLeft, MOVE_SPORE, target:healingSlot); } + if (move == MOVE_SPARKLY_SWIRL) + TURN { SWITCH(sporedSlot, switchIndex); MOVE(healingSlot, move, target: playerRight); MOVE(playerLeft, MOVE_SPORE, target:sporedSlot); } + else + TURN { SWITCH(sporedSlot, switchIndex); MOVE(healingSlot, move); MOVE(playerLeft, MOVE_SPORE, target:sporedSlot); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, sporedSlot); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(sporedSlot, sleep: TRUE); + MESSAGE("Zigzagoon used Spore!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, healingSlot); + STATUS_ICON(healingSlot, sleep: TRUE); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } + MESSAGE("Sleep Clause kept the opposing Zigzagoon awake!"); + if (move == MOVE_AROMATHERAPY) + { + MESSAGE("The opposing Zigzagoon used Aromatherapy!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_AROMATHERAPY, healingSlot); + } + else if (move == MOVE_HEAL_BELL) + { + MESSAGE("The opposing Zigzagoon used Heal Bell!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_HEAL_BELL, healingSlot); + } + else + { + MESSAGE("The opposing Zigzagoon used Sparkly Swirl!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPARKLY_SWIRL, healingSlot); + } + STATUS_ICON(sporedSlot, sleep: FALSE); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, sporedSlot); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up forcefully by a move from an opponent") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(MoveHasAdditionalEffect(MOVE_WAKE_UP_SLAP, MOVE_EFFECT_REMOVE_STATUS)); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target:opponentLeft); } + TURN { SWITCH(opponentLeft, 2); MOVE(playerLeft, MOVE_SPORE, target:opponentRight); } + TURN { SWITCH(opponentLeft, 0); MOVE(playerLeft, MOVE_WAKE_UP_SLAP, target:opponentLeft); } + TURN { MOVE(playerLeft, MOVE_SPORE, target:opponentLeft); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + MESSAGE("Zigzagoon used Spore!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + STATUS_ICON(opponentRight, sleep: TRUE); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } + MESSAGE("Sleep Clause kept the opposing Zigzagoon awake!"); + MESSAGE("Zigzagoon used Wake-Up Slap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WAKE_UP_SLAP, playerLeft); + MESSAGE("The opposing Zigzagoon woke up!"); + STATUS_ICON(opponentLeft, sleep: FALSE); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up forcefully by Uproar") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_UPROAR].effect == EFFECT_UPROAR); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target:opponentLeft); MOVE(playerRight, MOVE_UPROAR); MOVE(opponentRight, MOVE_ROAR, target:playerRight); } + TURN { MOVE(playerLeft, MOVE_SPORE, target:opponentLeft); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + MESSAGE("Zigzagoon used Uproar!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_UPROAR, playerRight); + MESSAGE("Zigzagoon caused an uproar!"); + MESSAGE("The uproar woke the opposing Zigzagoon!"); + STATUS_ICON(opponentLeft, sleep: FALSE); + MESSAGE("The opposing Zigzagoon used Roar!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROAR, opponentRight); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by using Sleep Talk into a status curing move") +{ + u32 move; + PARAMETRIZE { move = MOVE_PSYCHO_SHIFT; } + PARAMETRIZE { move = MOVE_JUNGLE_HEALING; } + PARAMETRIZE { move = MOVE_LUNAR_BLESSING; } + PARAMETRIZE { move = MOVE_TAKE_HEART; } + PARAMETRIZE { move = MOVE_AROMATHERAPY; } + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_SLEEP_TALK].effect == EFFECT_SLEEP_TALK); + ASSUME(gMovesInfo[MOVE_PSYCHO_SHIFT].effect == EFFECT_PSYCHO_SHIFT); + ASSUME(gMovesInfo[MOVE_JUNGLE_HEALING].effect == EFFECT_JUNGLE_HEALING); + ASSUME(gMovesInfo[MOVE_LUNAR_BLESSING].effect == EFFECT_JUNGLE_HEALING); + ASSUME(gMovesInfo[MOVE_PURIFY].effect == EFFECT_PURIFY); + ASSUME(gMovesInfo[MOVE_TAKE_HEART].effect == EFFECT_TAKE_HEART); + ASSUME(gMovesInfo[MOVE_AROMATHERAPY].effect == EFFECT_HEAL_BELL); + ASSUME(gItemsInfo[ITEM_CHESTO_BERRY].holdEffect == HOLD_EFFECT_CURE_SLP); + PLAYER(SPECIES_ZIGZAGOON) { Item(ITEM_CHESTO_BERRY); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SLEEP_TALK, move); } + } WHEN { + TURN { MOVE(player, MOVE_SPORE); MOVE(opponent, MOVE_SLEEP_TALK); } + TURN { MOVE(player, MOVE_SPORE); MOVE(opponent, move); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + MESSAGE("The opposing Zigzagoon used Sleep Talk!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, opponent); + if (move == MOVE_PSYCHO_SHIFT) + { + MESSAGE("The opposing Zigzagoon used Psycho Shift!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHO_SHIFT, opponent); + } + else if (move == MOVE_JUNGLE_HEALING) + { + MESSAGE("The opposing Zigzagoon used Jungle Healing!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_JUNGLE_HEALING, opponent); + } + else if (move == MOVE_LUNAR_BLESSING) + { + MESSAGE("The opposing Zigzagoon used Lunar Blessing!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_LUNAR_BLESSING, opponent); + } + else if (move == MOVE_TAKE_HEART) + { + MESSAGE("The opposing Zigzagoon used Take Heart!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAKE_HEART, opponent); + } + else if (move == MOVE_AROMATHERAPY) + { + MESSAGE("The opposing Zigzagoon used Aromatherapy!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_AROMATHERAPY, opponent); + } + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by Hydration in the rain") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_PELIPPER) { Ability(ABILITY_DRIZZLE); } + OPPONENT(SPECIES_LUVDISC) { Ability(ABILITY_HYDRATION); } + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Pelipper used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Luvdisc fell asleep!"); + MESSAGE("The opposing Luvdisc's Hydration cured its sleep problem!"); + STATUS_ICON(opponent, sleep: FALSE); + MESSAGE("Pelipper used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Luvdisc fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by Natural Cure") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_SWABLU) { Ability(ABILITY_NATURAL_CURE); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { SWITCH(opponent, 1); } + TURN { SWITCH(opponent, 0); MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Swablu fell asleep!"); + MESSAGE("2 withdrew Swablu!"); + MESSAGE("2 sent out Swablu!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Swablu fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by Shed Skin") +{ + if (B_ABILITY_TRIGGER_CHANCE == GEN_4) + PASSES_RANDOMLY(30, 100, RNG_SHED_SKIN); + else + PASSES_RANDOMLY(33, 100, RNG_SHED_SKIN); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_DRATINI) { Ability(ABILITY_SHED_SKIN); } + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Dratini fell asleep!"); + MESSAGE("The opposing Dratini's Shed Skin cured its sleep problem!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Dratini fell asleep!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by Healer") +{ + PASSES_RANDOMLY(30, 100, RNG_HEALER); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_CHANSEY) { Ability(ABILITY_HEALER); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target:opponentLeft); } + TURN { MOVE(playerLeft, MOVE_SPORE, target:opponentLeft); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + MESSAGE("The opposing Chansey's Healer cured the opposing Zigzagoon's problem!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by using a held item") +{ + u32 heldItem = ITEM_NONE; + PARAMETRIZE { heldItem = ITEM_CHESTO_BERRY; } + PARAMETRIZE { heldItem = ITEM_LUM_BERRY; } + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gItemsInfo[ITEM_CHESTO_BERRY].holdEffect == HOLD_EFFECT_CURE_SLP); + ASSUME(gItemsInfo[ITEM_LUM_BERRY].holdEffect == HOLD_EFFECT_CURE_STATUS); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON) { Item(heldItem); } + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + if (heldItem == ITEM_CHESTO_BERRY) + MESSAGE("The opposing Zigzagoon's Chesto Berry woke it up!"); + else + MESSAGE("The opposing Zigzagoon's Lum Berry cured its sleep problem!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by Flinging a held item") +{ + u32 heldItem = ITEM_NONE; + PARAMETRIZE { heldItem = ITEM_CHESTO_BERRY; } + PARAMETRIZE { heldItem = ITEM_LUM_BERRY; } + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_FLING].effect == EFFECT_FLING); + ASSUME(gItemsInfo[ITEM_CHESTO_BERRY].holdEffect == HOLD_EFFECT_CURE_SLP); + ASSUME(gItemsInfo[ITEM_LUM_BERRY].holdEffect == HOLD_EFFECT_CURE_STATUS); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON) { Item(heldItem); } + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target: opponentLeft); MOVE(playerRight, MOVE_FLING, target: opponentLeft); } + TURN { MOVE(playerLeft, MOVE_SPORE, target: opponentLeft); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + MESSAGE("Zigzagoon used Fling!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, playerRight); + if (heldItem == ITEM_CHESTO_BERRY) + MESSAGE("The opposing Zigzagoon's Chesto Berry woke it up!"); + else + MESSAGE("The opposing Zigzagoon's Lum Berry cured its sleep problem!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by using an item") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gItemsInfo[ITEM_AWAKENING].battleUsage == EFFECT_ITEM_CURE_STATUS); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { USE_ITEM(opponent, ITEM_AWAKENING, partyIndex: 0); MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + MESSAGE("Zigzagoon had its status healed!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon faints") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON) { Level(5); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_TACKLE); SEND_OUT(opponent, 1); } + TURN { MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + MESSAGE("The opposing Zigzagoon fainted!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon faints (Doubles)") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON) { Level(5); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target: opponentLeft); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); } + TURN { MOVE(playerLeft, MOVE_SPORE, target: opponentRight);} + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + MESSAGE("The opposing Zigzagoon fainted!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up by gaining the ability Insomnia / Vital Spirit") +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } + PARAMETRIZE { ability = ABILITY_INSOMNIA; } + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_DELIBIRD) { Ability(ability); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SLEEP_TALK, MOVE_SKILL_SWAP); } + } WHEN { + TURN { MOVE(player, MOVE_SPORE); MOVE(opponent, MOVE_SLEEP_TALK); } + TURN { MOVE(opponent, MOVE_SKILL_SWAP); } + TURN { MOVE(player, MOVE_SPORE); MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + MESSAGE("Delibird used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + MESSAGE("The opposing Zigzagoon used Sleep Talk!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SLEEP_TALK, opponent); + MESSAGE("The opposing Zigzagoon used Skill Swap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + if (ability == ABILITY_VITAL_SPIRIT) + MESSAGE("The opposing Zigzagoon's Vital Spirit cured its sleep problem!"); + if (ability == ABILITY_INSOMNIA) + MESSAGE("The opposing Zigzagoon's Insomnia cured its sleep problem!"); + MESSAGE("The opposing Zigzagoon used Skill Swap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + MESSAGE("Delibird used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is sent out, has Trace, and Traces Insomnia / Vital spirit") +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } + PARAMETRIZE { ability = ABILITY_INSOMNIA; } + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON) + PLAYER(SPECIES_DELIBIRD) { Ability(ability); } + OPPONENT(SPECIES_RALTS) { Ability(ABILITY_TRACE); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + TURN { SWITCH(opponent, 0); } + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Ralts fell asleep!"); + MESSAGE("2 sent out Zigzagoon!"); + MESSAGE("2 sent out Ralts!"); + if (ability == ABILITY_VITAL_SPIRIT) + MESSAGE("The opposing Ralts's Vital Spirit cured its sleep problem!"); + if (ability == ABILITY_INSOMNIA) + MESSAGE("The opposing Ralts's Insomnia cured its sleep problem!"); + MESSAGE("2 sent out Zigzagoon!"); + MESSAGE("Delibird used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is sent out and transforms into a mon with Insomnia / Vital spirit") +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } + PARAMETRIZE { ability = ABILITY_INSOMNIA; } + KNOWN_FAILING; // Sleep Clause parts work, but Imposter seems broken with battle messages / targeting. Issue #5565 https://github.com/rh-hideout/pokeemerald-expansion/issues/5565 + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gItemsInfo[ITEM_LAGGING_TAIL].holdEffect == HOLD_EFFECT_LAGGING_TAIL); + PLAYER(SPECIES_ZIGZAGOON) + PLAYER(SPECIES_DELIBIRD) { Ability(ability); } + OPPONENT(SPECIES_DITTO) { Ability(ABILITY_IMPOSTER); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + TURN { SWITCH(opponent, 0); } + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("The opposing Ditto transformed into Zigzagoon using Imposter!"); + MESSAGE("Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Ditto fell asleep!"); + MESSAGE("2 sent out Zigzagoon!"); + MESSAGE("2 sent out Ditto!"); + if (ability == ABILITY_VITAL_SPIRIT) + MESSAGE("The opposing Ditto's Vital Spirit cured its sleep problem!"); + else + MESSAGE("The opposing Ditto's Insomnia cured its sleep problem!"); + MESSAGE("2 sent out Zigzagoon!"); + MESSAGE("Delibird used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + } +} + +AI_SINGLE_BATTLE_TEST("Sleep Clause: AI will use sleep moves again when sleep clause has been deactivated") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gItemsInfo[ITEM_CHESTO_BERRY].holdEffect == HOLD_EFFECT_CURE_SLP); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_CHESTO_BERRY); } + OPPONENT(SPECIES_BRELOOM) { Moves(MOVE_SPORE, MOVE_MACH_PUNCH); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_SPORE); } + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_SPORE); } + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mon is woken up with G-Max Sweetness") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_G_MAX_SWEETNESS].argument == MAX_EFFECT_AROMATHERAPY); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_APPLETUN) { GigantamaxFactor(TRUE); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, MOVE_SPORE, target: playerRight); } + TURN { MOVE(playerLeft, MOVE_VINE_WHIP, target: opponentLeft, gimmick: GIMMICK_DYNAMAX); } + TURN { MOVE(opponentRight, MOVE_SPORE, target: playerRight); } + } SCENE { + MESSAGE("The opposing Wobbuffet used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Wobbuffet fell asleep!"); + MESSAGE("Appletun used G-Max Sweetness!"); + MESSAGE("Wobbuffet's status returned to normal!"); + MESSAGE("The opposing Wobbuffet used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Wobbuffet fell asleep!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Pre-existing sleep condition doesn't activate sleep clause") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON) { Status1(STATUS1_SLEEP); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_SPORE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Sleep caused by Effect Spore does not prevent sleep clause from ever activating") // checks that sleepClauseEffectExempt works properly +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_AROMATHERAPY].effect == EFFECT_HEAL_BELL); + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_SPORE); } + TURN { SWITCH(player, 2); MOVE(opponent, MOVE_SPORE); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("The opposing Breloom's Effect Spore made Zigzagoon sleep!"); + STATUS_ICON(player, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(player, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(player, sleep: TRUE); + } + MESSAGE("Sleep Clause kept Zigzagoon awake!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Waking up after Effect Spore doesn't deactivate sleep clause") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN {} + TURN {} + TURN {} + TURN { MOVE(opponent, MOVE_SPORE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_SPORE); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("The opposing Breloom's Effect Spore made Zigzagoon sleep!"); + STATUS_ICON(player, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(player, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(player, sleep: TRUE); + } + MESSAGE("Sleep Clause kept Zigzagoon awake!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Waking up after Effect Spore doesn't deactivate sleep clause (Doubles)") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_AROMATHERAPY].effect == EFFECT_HEAL_BELL); + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); MOVE(opponentRight, MOVE_SPORE, target:playerRight); } + TURN { SWITCH(playerLeft, 2); } + TURN { MOVE(playerLeft, MOVE_AROMATHERAPY); MOVE(opponentRight, MOVE_SPORE, target:playerRight); MOVE(opponentLeft, MOVE_SPORE, target:playerLeft); } + } SCENE { + ABILITY_POPUP(opponentLeft, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerLeft); + MESSAGE("The opposing Breloom's Effect Spore made Zigzagoon sleep!"); + STATUS_ICON(playerLeft, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_AROMATHERAPY, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerLeft); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerLeft, sleep: TRUE); + } + MESSAGE("Sleep Clause kept Zigzagoon awake!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Waking up after Rest doesn't deactivate sleep clause") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_REST].effect == EFFECT_REST); + PLAYER(SPECIES_ZIGZAGOON) { HP(1); MaxHP(100); } + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_REST); } + TURN {} + TURN {} + TURN {} + TURN { MOVE(opponent, MOVE_SPORE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_SPORE); } + } SCENE { + MESSAGE("Zigzagoon went to sleep!"); + STATUS_ICON(player, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("Zigzagoon woke up!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(player, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(player, sleep: TRUE); + } + MESSAGE("Sleep Clause kept Zigzagoon awake!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Waking up after Rest doesn't deactivate sleep clause (Doubles)") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_REST].effect == EFFECT_REST); + PLAYER(SPECIES_ZIGZAGOON) { HP(1); MaxHP(100); } + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_REST); MOVE(opponentRight, MOVE_SPORE, target:playerRight); } + TURN { SWITCH(playerRight, 2); } + TURN {} + TURN {} + TURN { MOVE(opponentRight, MOVE_SPORE, target:playerRight); } + } SCENE { + MESSAGE("Zigzagoon went to sleep!"); + STATUS_ICON(playerLeft, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, playerLeft); + MESSAGE("The opposing Zigzagoon used Spore!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + MESSAGE("Zigzagoon woke up!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + } + MESSAGE("Sleep Clause kept Zigzagoon awake!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Suppressing and then sleeping Vital Spirit / Insomnia and switching back in deactivates sleep clause") +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } + PARAMETRIZE { ability = ABILITY_INSOMNIA; } + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_DELIBIRD) { Ability(ability); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_GASTRO_ACID); } + TURN { MOVE(player, MOVE_SPORE); } + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_SPORE); } + TURN { SWITCH(opponent, 0); } + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_SPORE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Delibird fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + MESSAGE("Sleep Clause kept the opposing Zigzagoon awake!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Mold Breaker Pokémon sleeping Vital Spirit / Insomnia activates sleep clause") +{ + KNOWN_FAILING; // Interaction between Mold Breaker and Vital Spirit / Insomnia is broken. Issue #5578 https://github.com/rh-hideout/pokeemerald-expansion/issues/5578 + u32 ability; + PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; } + PARAMETRIZE { ability = ABILITY_INSOMNIA; } + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_PANCHAM) { Ability(ABILITY_MOLD_BREAKER); } + OPPONENT(SPECIES_DELIBIRD) { Ability(ability); } + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_SPORE); } + TURN { SWITCH(opponent, 0); } + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_SPORE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Delibird fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + MESSAGE("Sleep Clause kept the opposing Delibird awake!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Yawn'd Pokémon slept due to Effect Spore before Yawn triggers does not activate sleep clause") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); + ASSUME(gMovesInfo[MOVE_TACKLE].makesContact); + PLAYER(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_YAWN); } + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(opponent, 1); MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("The opposing Zigzagoon grew drowsy!"); + ABILITY_POPUP(player, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("Breloom's Effect Spore made the opposing Zigzagoon sleep!"); + STATUS_ICON(opponent, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Yawn'd Pokémon who's partner is slept before Yawn triggers will not fall asleep due to sleep clause being activated") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_YAWN, target: opponentLeft); MOVE(playerRight, MOVE_YAWN, target: opponentRight); } + TURN { MOVE(playerLeft, MOVE_SPORE, target: opponentLeft); } + } SCENE { + MESSAGE("The opposing Zigzagoon grew drowsy!"); + MESSAGE("The opposing Zigzagoon grew drowsy!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + NONE_OF { + MESSAGE( "The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentRight, sleep: TRUE); + } + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: If both Pokémon on one side are Yawn'd at the same time, one will fall asleep and the other will not") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); + PLAYER(SPECIES_ZIGZAGOON) { Speed(5); } + PLAYER(SPECIES_ZIGZAGOON) { Speed(4); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(3); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(2); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_YAWN, target: opponentLeft); MOVE(playerRight, MOVE_YAWN, target: opponentRight); } + TURN { } + } SCENE { + MESSAGE("The opposing Zigzagoon grew drowsy!"); + MESSAGE("The opposing Zigzagoon grew drowsy!"); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + NONE_OF { + MESSAGE( "The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentRight, sleep: TRUE); + } + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Reflection moves (ie. Magic Coat) fail if sleep clause is active and they reflect a sleep move") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_MAGIC_COAT].effect == EFFECT_MAGIC_COAT); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_SPORE); } + TURN { SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_MAGIC_COAT); MOVE(opponent, MOVE_SPORE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_COAT, player); + MESSAGE("The opposing Zigzagoon bounced the Spore back!"); // Should be MESSAGE("Zigzagoon bounced the Spore back!"); Issue #5579 https://github.com/rh-hideout/pokeemerald-expansion/issues/5579 + MESSAGE("Sleep Clause kept the opposing Zigzagoon awake!"); + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Reflection moves (ie. Magic Coat) that reflect a sleep move activate sleep clause") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_MAGIC_COAT].effect == EFFECT_MAGIC_COAT); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_MAGIC_COAT); MOVE(opponent, MOVE_SPORE); } + TURN { SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_SPORE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_COAT, player); + MESSAGE("Zigzagoon bounced the Spore back!"); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } + MESSAGE("Sleep Clause kept the opposing Zigzagoon awake!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Reflection moves (ie. Magic Coat) that reflect Dark Void only sleep one opposing Pokémon") +{ + // Source: https://bulbapedia.bulbagarden.net/wiki/Dark_Void_(move) + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_MAGIC_COAT].effect == EFFECT_MAGIC_COAT); + ASSUME(gMovesInfo[MOVE_DARK_VOID].effect == EFFECT_DARK_VOID); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_DARKRAI); + OPPONENT(SPECIES_DARKRAI); + } WHEN { + TURN { MOVE(playerLeft, MOVE_MAGIC_COAT); MOVE(opponentLeft, MOVE_DARK_VOID); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DARK_VOID, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Darkrai fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + STATUS_ICON(opponentRight, sleep: TRUE); + MESSAGE("The opposing Darkrai fell asleep!"); + } + } +} + +SINGLE_BATTLE_TEST("Sleep Clause: Magic Bounce'ing a sleep move activates sleep clause, and fails if sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); } + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(opponent, MOVE_SPORE); } + TURN { SWITCH(opponent, 1); } + TURN { MOVE(opponent, MOVE_SPORE); } + } SCENE { + MESSAGE("The opposing Zigzagoon's Spore was bounced back by Espeon's Magic Bounce!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + MESSAGE("The opposing Zigzagoon's Spore was bounced back by Espeon's Magic Bounce!"); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } + MESSAGE("Sleep Clause kept the opposing Zigzagoon awake!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Magic Bounce reflecting Dark Void only sleeps one opposing Pokémon") +{ + // Source: https://bulbapedia.bulbagarden.net/wiki/Dark_Void_(move) + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_DARK_VOID].effect == EFFECT_DARK_VOID); + PLAYER(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_DARKRAI); + OPPONENT(SPECIES_DARKRAI); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_DARK_VOID); } + } SCENE { + MESSAGE("The opposing Darkrai's Dark Void was bounced back by Espeon's Magic Bounce!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Darkrai fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + STATUS_ICON(opponentRight, sleep: TRUE); + MESSAGE("The opposing Darkrai fell asleep!"); + } + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep Clause does not prevent sleeping your partner Pokémon with sleep effects") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target: playerRight); } + TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_SPORE, target: playerRight); } + TURN { SWITCH(playerRight, 3); MOVE(playerLeft, MOVE_SPORE, target: playerRight); } + TURN { SWITCH(playerRight, 4); MOVE(playerLeft, MOVE_SPORE, target: playerRight); } + TURN { SWITCH(playerRight, 5); MOVE(playerLeft, MOVE_SPORE, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep Clause does not prevent sleeping your partner Pokémon with Yawn") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_YAWN, target: playerRight); } + TURN {} + TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_YAWN, target: playerRight); } + TURN {} + TURN { SWITCH(playerRight, 3); MOVE(playerLeft, MOVE_YAWN, target: playerRight); } + TURN {} + TURN { SWITCH(playerRight, 4); MOVE(playerLeft, MOVE_YAWN, target: playerRight); } + TURN {} + TURN { SWITCH(playerRight, 5); MOVE(playerLeft, MOVE_YAWN, target: playerRight); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft); + MESSAGE("Zigzagoon grew drowsy!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft); + MESSAGE("Zigzagoon grew drowsy!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft); + MESSAGE("Zigzagoon grew drowsy!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft); + MESSAGE("Zigzagoon grew drowsy!"); + STATUS_ICON(playerRight, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft); + MESSAGE("Zigzagoon grew drowsy!"); + STATUS_ICON(playerRight, sleep: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Sleep moves used after being Encore'd are prevented when sleep clause is active") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SPORE, target: playerLeft); MOVE(playerRight, MOVE_ENCORE, target: opponentLeft); } + TURN { SWITCH(playerLeft, 2); FORCED_MOVE(opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerLeft); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerLeft, sleep: TRUE); + MESSAGE("Zigzagoon used Encore!"); + MESSAGE("Go! Zigzagoon!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerLeft); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerLeft, sleep: TRUE); + } + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Spore'ing opponent after Yawn'ing partner does not prevent Yawn's effect from sleeping partner") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SPORE, target: playerRight); } + TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_YAWN, target: playerRight); } + TURN { MOVE(playerLeft, MOVE_SPORE, target: opponentLeft); MOVE(playerRight, MOVE_SPORE, target: opponentRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + MESSAGE("Go! Zigzagoon!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft); + MESSAGE("Zigzagoon grew drowsy!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentLeft); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, playerRight); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponentRight); + MESSAGE("The opposing Zigzagoon fell asleep!"); + STATUS_ICON(opponentRight, sleep: TRUE); + } + MESSAGE("Zigzagoon fell asleep!"); + } +} + +DOUBLE_BATTLE_TEST("Sleep Clause: Opponent Spore'ing player's partner after partner was Yawn'd by player does not prevent Spore's effect from sleeping partner and activating clause") +{ + GIVEN { + FLAG_SET(B_FLAG_SLEEP_CLAUSE); + ASSUME(gMovesInfo[MOVE_SPORE].effect == EFFECT_SLEEP); + ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(playerLeft, MOVE_YAWN, target: playerRight); } + TURN { MOVE(opponentLeft, MOVE_SPORE, target: playerRight); MOVE(opponentRight, MOVE_SPORE, target:playerLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft); + MESSAGE("Zigzagoon grew drowsy!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerRight); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerRight, sleep: TRUE); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponentRight); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, playerLeft); + MESSAGE("Zigzagoon fell asleep!"); + STATUS_ICON(playerLeft, sleep: TRUE); + } + MESSAGE("Sleep Clause kept Zigzagoon awake!"); + } +} diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index b073ac226a..6faf6a4715 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1371,7 +1371,6 @@ static inline rng_value_t MakeRngValue(const u16 seed) static void CB2_BattleTest_NextTrial(void) { - ClearFlagAfterTest(); TearDownBattle(); SetMainCallback2(CB2_BattleTest_NextParameter);