diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 9ffdc70fba..8240a56801 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -23,9 +23,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.2 (Latest release) + - 1.9.3 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.2 - 1.9.1 - 1.9.0 - 1.8.6 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index ce50b0bffd..5688f8a7fb 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -23,9 +23,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.2 (Latest release) + - 1.9.3 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.2 - 1.9.1 - 1.9.0 - 1.8.6 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index c78093d60e..add0633d95 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -23,9 +23,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.9.2 (Latest release) + - 1.9.3 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.9.2 - 1.9.1 - 1.9.0 - 1.8.6 diff --git a/README.md b/README.md index 37ea8336b7..427caafd0a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,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.2 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.9.3 https://github.com/rh-hideout/pokeemerald-expansion/ ``` ## What features are included? @@ -178,7 +178,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.2, use `git pull RHH expansion/1.9.2`). +- 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`). - ***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/data/battle_scripts_1.s b/data/battle_scripts_1.s index 94f5736317..fa56c3ff7a 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -214,27 +214,25 @@ BattleScript_EffectDoodle:: attackcanceler attackstring ppreduce + trycopyability BS_ATTACKER, BattleScript_ButItFailed attackanimation waitanimation setbyte gBattleCommunication, 0 + goto BattleScript_EffectDoodle_AfterCopy BattleScript_EffectDoodle_CopyAbility: - trycopyability BS_ATTACKER, BattleScript_ButItFailed + trycopyability BS_ATTACKER, BattleScript_MoveEnd +BattleScript_EffectDoodle_AfterCopy: .if B_ABILITY_POP_UP == TRUE - setbyte sFIXED_ABILITY_POPUP, TRUE - showabilitypopup BS_ATTACKER - pause 60 - sethword sABILITY_OVERWRITE, 0 - updateabilitypopup BS_ATTACKER - pause 20 - destroyabilitypopup - pause 40 + copybyte gBattlerAbility, gBattlerAttacker + call BattleScript_AbilityPopUpOverwriteThenNormal .endif + recordability BS_ATTACKER printstring STRINGID_PKMNCOPIEDFOE waitmessage B_WAIT_TIME_LONG switchinabilities BS_ATTACKER jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0x0, BattleScript_MoveEnd addbyte gBattleCommunication, 1 - jumpifnoally BS_TARGET, BattleScript_MoveEnd + jumpifnoally BS_ATTACKER, BattleScript_MoveEnd setallytonextattacker BattleScript_EffectDoodle_CopyAbility goto BattleScript_MoveEnd @@ -2346,6 +2344,11 @@ BattleScript_EffectSimpleBeam:: setabilitysimple BS_TARGET, BattleScript_ButItFailed attackanimation waitanimation +.if B_ABILITY_POP_UP == TRUE + copybyte gBattlerAbility, gBattlerTarget + call BattleScript_AbilityPopUpOverwriteThenNormal +.endif + recordability BS_TARGET printstring STRINGID_PKMNACQUIREDSIMPLE waitmessage B_WAIT_TIME_LONG trytoclearprimalweather @@ -2444,11 +2447,17 @@ BattleScript_EffectWorrySeed:: tryworryseed BattleScript_ButItFailed attackanimation waitanimation +.if B_ABILITY_POP_UP == TRUE + copybyte gBattlerAbility, gBattlerTarget + call BattleScript_AbilityPopUpOverwriteThenNormal +.endif + recordability BS_TARGET printstring STRINGID_PKMNACQUIREDABILITY waitmessage B_WAIT_TIME_LONG trytoclearprimalweather tryrevertweatherform flushtextbox + tryendneutralizinggas BS_TARGET goto BattleScript_MoveEnd BattleScript_EffectPowerSplit:: @@ -5034,15 +5043,10 @@ BattleScript_EffectRolePlay:: attackanimation waitanimation .if B_ABILITY_POP_UP == TRUE - setbyte sFIXED_ABILITY_POPUP, TRUE - showabilitypopup BS_ATTACKER - pause 60 - sethword sABILITY_OVERWRITE, 0 - updateabilitypopup BS_ATTACKER - pause 20 - destroyabilitypopup - pause 40 + copybyte gBattlerAbility, gBattlerAttacker + call BattleScript_AbilityPopUpOverwriteThenNormal .endif + recordability BS_ATTACKER printstring STRINGID_PKMNCOPIEDFOE waitmessage B_WAIT_TIME_LONG switchinabilities BS_ATTACKER @@ -5185,12 +5189,17 @@ BattleScript_EffectSkillSwap:: tryswapabilities BattleScript_ButItFailed attackanimation waitanimation + jumpiftargetally BattleScript_EffectSkillSwap_AfterAbilityPopUp .if B_ABILITY_POP_UP == TRUE - call BattleScript_AbilityPopUpTarget - pause 20 copybyte gBattlerAbility, gBattlerAttacker - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpOverwriteThenNormal + copybyte gBattlerAbility, gBattlerTarget + copyhword sABILITY_OVERWRITE, gLastUsedAbility + call BattleScript_AbilityPopUpOverwriteThenNormal .endif +BattleScript_EffectSkillSwap_AfterAbilityPopUp: + recordability BS_ATTACKER + recordability BS_TARGET printstring STRINGID_PKMNSWAPPEDABILITIES waitmessage B_WAIT_TIME_LONG .if B_SKILL_SWAP >= GEN_4 @@ -7605,6 +7614,18 @@ BattleScript_AbilityPopUpScripting: sethword sABILITY_OVERWRITE, 0 return +BattleScript_AbilityPopUpOverwriteThenNormal: + setbyte sFIXED_ABILITY_POPUP, TRUE + showabilitypopup BS_ABILITY_BATTLER + pause 60 + sethword sABILITY_OVERWRITE, 0 + updateabilitypopup BS_ABILITY_BATTLER + pause 20 + recordability BS_ABILITY_BATTLER + destroyabilitypopup + pause 40 + return + BattleScript_SpeedBoostActivates:: statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_SpeedBoostActivatesEnd call BattleScript_AbilityPopUp @@ -8366,33 +8387,30 @@ BattleScript_CursedBodyActivates:: return BattleScript_MummyActivates:: - call BattleScript_AbilityPopUp +.if B_ABILITY_POP_UP == TRUE + call BattleScript_AbilityPopUpTarget + setbyte sFIXED_ABILITY_POPUP, TRUE + copybyte gBattlerAbility, gBattlerAttacker + copyhword sABILITY_OVERWRITE, gLastUsedAbility + call BattleScript_AbilityPopUpOverwriteThenNormal +.endif + recordability BS_TARGET + recordability BS_ATTACKER printstring STRINGID_ATTACKERACQUIREDABILITY waitmessage B_WAIT_TIME_LONG return BattleScript_WanderingSpiritActivates:: .if B_ABILITY_POP_UP == TRUE - setbyte sFIXED_ABILITY_POPUP, TRUE + copybyte gBattlerAbility, gBattlerTarget sethword sABILITY_OVERWRITE, ABILITY_WANDERING_SPIRIT - showabilitypopup BS_TARGET - pause 60 - sethword sABILITY_OVERWRITE, 0 - updateabilitypopup BS_TARGET - pause 20 - destroyabilitypopup - pause 40 + call BattleScript_AbilityPopUpOverwriteThenNormal copybyte gBattlerAbility, gBattlerAttacker - setbyte sFIXED_ABILITY_POPUP, TRUE copyhword sABILITY_OVERWRITE, gLastUsedAbility - showabilitypopup BS_ATTACKER - pause 60 - sethword sABILITY_OVERWRITE, 0 - updateabilitypopup BS_ATTACKER - pause 20 - destroyabilitypopup - pause 40 + call BattleScript_AbilityPopUpOverwriteThenNormal .endif + recordability BS_TARGET + recordability BS_ATTACKER printstring STRINGID_SWAPPEDABILITIES waitmessage B_WAIT_TIME_LONG switchinabilities BS_ATTACKER diff --git a/data/scripts/field_move_scripts.inc b/data/scripts/field_move_scripts.inc index 6e2450822c..0a7660b4ce 100644 --- a/data/scripts/field_move_scripts.inc +++ b/data/scripts/field_move_scripts.inc @@ -368,6 +368,23 @@ EventScript_EndSurface:: releaseall end +EventScript_DigCommon: + isfollowerfieldmoveuser VAR_0x8004 + setfieldeffectargument 3, VAR_0x8004 @ skip pose if true + dofieldeffect FLDEFF_USE_DIG + waitstate +EventScript_DigSealedChamber:: @ fallthrough + setflag FLAG_SAFE_FOLLOWER_MOVEMENT + call_if_eq VAR_0x8004, TRUE, EventScript_FollowerFieldMove + callnative DoBrailleDigEffect + releaseall + end + +@ Use Dig from party menu +EventScript_UseDig:: + lockall + goto EventScript_DigCommon + Text_CantDive: .string "The sea is deep here. A POKéMON\n" .string "may be able to go underwater.$" diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index faeb069783..ac4698fdc3 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -5,20 +5,21 @@ - [Setting up WSL1 (Legacy Portion)](./legacy_WSL1_INSTALL.md) - [Run documentation site locally](local_mdbook/index.md) - [Ubuntu WSL1/WSL2](local_mdbook/ubuntu_WSL.md) -- [AI Flags](./ai_flags.md) - [Tutorials]() - - [How to add new AI Flags](./ai_logic.md) - - [How to add new battle script commands/macros](./how_to_battle_script_command_macro.md) - - [How to add a new move](./how_to_new_move.md) - - [How to add a new trainer class](./how_to_trainer_class.md) + - [What are AI Flags?](tutorials/ai_flags.md) + - [How to add new AI Flags](tutorials/ai_logic.md) + - [How to add new battle script commands/macros](tutorials/how_to_battle_script_command_macro.md) + - [How to add a new move](tutorials/how_to_new_move.md) + - [How to add a new trainer class](tutorials/how_to_trainer_class.md) - [How to add a new Pokémon]() - - [v1.9.x](./how_to_new_pokemon_1_9_0.md) - - [v1.8.x](./how_to_new_pokemon_1_8_0.md) - - [v1.7.x](./how_to_new_pokemon_1_7_0.md) - - [v1.6.x](./how_to_new_pokemon_1_6_0.md) - - [How to use the Testing System](./how_to_testing_system.md) + - [v1.9.x](tutorials/how_to_new_pokemon_1_9_0.md) + - [v1.8.x](tutorials/how_to_new_pokemon_1_8_0.md) + - [v1.7.x](tutorials/how_to_new_pokemon_1_7_0.md) + - [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.9.x]() + - [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) - [Version 1.9.0](changelogs/1.9.x/1.9.0.md) @@ -30,43 +31,36 @@ - [Version 1.8.2](changelogs/1.8.x/1.8.2.md) - [Version 1.8.1](changelogs/1.8.x/1.8.1.md) - [Version 1.8.0](changelogs/1.8.x/1.8.0.md) - - [1.7.x]() - [Version 1.7.4](changelogs/1.7.x/1.7.4.md) - [Version 1.7.3](changelogs/1.7.x/1.7.3.md) - [Version 1.7.2](changelogs/1.7.x/1.7.2.md) - [Version 1.7.1](changelogs/1.7.x/1.7.1.md) - [Version 1.7.0](changelogs/1.7.x/1.7.0.md) - - [1.6.x]() - [Version 1.6.2](changelogs/1.6.x/1.6.2.md) - [Version 1.6.1](changelogs/1.6.x/1.6.1.md) - [Version 1.6.0](changelogs/1.6.x/1.6.0.md) - - [1.5.x]() - [Version 1.5.3](changelogs/1.5.x/1.5.3.md) - [Version 1.5.2](changelogs/1.5.x/1.5.2.md) - [Version 1.5.1](changelogs/1.5.x/1.5.1.md) - [Version 1.5.0](changelogs/1.5.x/1.5.0.md) - - [1.4.x]() - [Version 1.4.3](changelogs/1.4.x/1.4.3.md) - [Version 1.4.2](changelogs/1.4.x/1.4.2.md) - [Version 1.4.1](changelogs/1.4.x/1.4.1.md) - [Version 1.4.0](changelogs/1.4.x/1.4.0.md) - - [1.3.x]() - [Version 1.3.0](changelogs/1.3.x/1.3.0.md) - - [1.2.x]() - [Version 1.2.0](changelogs/1.2.x/1.2.0.md) - - [1.1.x]() - [Version 1.1.1](changelogs/1.1.x/1.1.1.md) - [Version 1.1.0](changelogs/1.1.x/1.1.0.md) - - [1.0.x]() - [Version 1.0.0](changelogs/1.0.x/1.0.0.md) - - [Pre-1.0.x]() - [Version 0.9.0](changelogs/0.9.x/0.9.0.md) +- [Team Procedures]() + - [How to make an Expansion version](team_procedures/expansion_versions.md) diff --git a/docs/changelogs/1.9.x/1.9.3.md b/docs/changelogs/1.9.x/1.9.3.md new file mode 100644 index 0000000000..2fe981435e --- /dev/null +++ b/docs/changelogs/1.9.x/1.9.3.md @@ -0,0 +1,106 @@ +# Version 1.9.3 + +```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.3`. +``` + +## 🌋 *REFACTORS* 🌋 +📜 = Uses a migration script. +* Converted `settotemboost` command to `callnative` in [#5418](https://github.com/rh-hideout/pokeemerald-expansion/pull/5418) +* Removed unused `RESOURCE_FLAG_TRACED` in [#5430](https://github.com/rh-hideout/pokeemerald-expansion/pull/5430) +* Changed `MOVEEND_` defines to an enum in [#5449](https://github.com/rh-hideout/pokeemerald-expansion/pull/5449) + +## ✨ Feature Branches ✨ +### ***merrp/aarant's Followers*** +#### Fixed +* Fixed Expansion-exclusive issue that caused trainers to not play their "pointing" animation when Followers were out during battle intro by @kittenchilly in [#5406](https://github.com/rh-hideout/pokeemerald-expansion/pull/5406) + +## ⚔️ Battle General ⚔️ ## +### Changed +* Improved Mega evolution animation to make it a little smoother by @kleenxfeu in [#4816](https://github.com/rh-hideout/pokeemerald-expansion/pull/4816) +### Fixed +* Fixed affection check for exp multiplier by @Bassoonian in [#5421](https://github.com/rh-hideout/pokeemerald-expansion/pull/5421) +* Fixed multiple Primal Reversions not occurring if multiple battlers fainted on the previous turn by @PhallenTree in [#5430](https://github.com/rh-hideout/pokeemerald-expansion/pull/5430) + +## 🤹 Moves 🤹 +### Added +* Added missing `B_AFTER_YOU_TURN_ORDER` config by @PhallenTree in [#5400](https://github.com/rh-hideout/pokeemerald-expansion/pull/5400) + * Gen 5-7: After You fails if the order remains the same after using After You. + * Gen 8+: After You no longer fails if the turn order remains the same after using After You. +* Added missing `B_QUASH_TURN_ORDER` config by @PhallenTree in [#5400](https://github.com/rh-hideout/pokeemerald-expansion/pull/5400) + * Gen 5-7: If multiple Pokémon are affected by Quash, they move in the order they were affected by Quash. + * Gen 8+: If multiple Pokémon are affected by Quash, they now move fastest to slowest. +* Added missing updated `B_UPDATED_CONVERSION_2` by @wiz1989 in [#5453](https://github.com/rh-hideout/pokeemerald-expansion/pull/5453) + * Gens 2-4: Conversion 2 changes the user's type to a type that is resistant/immune to the last move the user was hit by. + * Gen 5+: Conversion 2 changes the user's type to a type that resists the last move used by the selected target. +### Fixed +* Fixed Scale Shot corrupting the move used on the next turn by @AlexOn1ine in [#5397](https://github.com/rh-hideout/pokeemerald-expansion/pull/5397) +* Fixed Growth's description not being updated based on `B_GROWTH_STAT_RAISE` by @nescioquid in [#5398](https://github.com/rh-hideout/pokeemerald-expansion/pull/5398) +* Fixed Quash not updating the battlers' actions correctly by @PhallenTree in [#5400](https://github.com/rh-hideout/pokeemerald-expansion/pull/5400) + * Cleanup by @PhallenTree in [#5430](https://github.com/rh-hideout/pokeemerald-expansion/pull/5430) +* Fixed Snatched Swallow not recovering HP if the Snatcher is not under the effect of Stockpile (should still heal) by @PhallenTree in [#5430](https://github.com/rh-hideout/pokeemerald-expansion/pull/5430) +* Fixed Counter users being damaged by Spiky Shield by @AlexOn1ine in [#5402](https://github.com/rh-hideout/pokeemerald-expansion/pull/5402) +* Fixed Electrified Dragon Darts not correctly avoiding targets with ability immunity (Volt Absorb, Motor Drive) by @PhallenTree in [#5430](https://github.com/rh-hideout/pokeemerald-expansion/pull/5430) +* Fixed Trace not activating a switch-in ability it traces (eg. Intimidate) by @PhallenTree in [#5430](https://github.com/rh-hideout/pokeemerald-expansion/pull/5430) + * Removed unused `RESOURCE_FLAG_TRACED`. +* Fixed recoil damage not triggering healing berries by @AlexOn1ine in [#5449](https://github.com/rh-hideout/pokeemerald-expansion/pull/5449) + * Also changed `MOVEEND_` defines to an enum. +## 🎭 Abilities 🎭 +### Fixed +* Fixed Dancer activating even if the dance move is stolen by Snatch by @PhallenTree in [#5430](https://github.com/rh-hideout/pokeemerald-expansion/pull/5430) +* Fixed Ability popup when multiple Pokémon faint at the same time by @PhallenTree in [#5430](https://github.com/rh-hideout/pokeemerald-expansion/pull/5430) +* Multiple ability fixes by @PhallenTree in [#5447](https://github.com/rh-hideout/pokeemerald-expansion/pull/5447) + * Fixed Protosynthesis/Quark Drive sometimes not activating ability popup despite still gaining the boost as they should. + * Fixed Protosynthesis/Quark Drive activating on Transformed battlers. + * Fixed Protosynthesis activating despite Cloud Nine being present on the field. + * Fixed Quark Drive not activating if the battler is not grounded. + * Fixed Protosynthesis/Quark Drive/Beast Boost stat raise priority when multiple stats are tied for the highest one. + * Before: `Attack, Defense, Speed, Special Attack, Special Defense`. + * After: `Attack, Defense, Special Attack, Special Defense, Speed`. + +## 🧶 Items 🧶 +### Fixed +* Fixed Ogerpon's Masks not increasing the power of moves by 20% by @AlexOn1ine in [#5391](https://github.com/rh-hideout/pokeemerald-expansion/pull/5391) +* Fixed Jubilife Muffin not working by @kittenchilly in [#5444](https://github.com/rh-hideout/pokeemerald-expansion/pull/5444) +* Fixed duplicating flute bug in double battles by @ghoulslash in [#5436](https://github.com/rh-hideout/pokeemerald-expansion/pull/5436) + +## 🤖 Battle AI 🤖 +### Fixed +* Fixed Trick/Switcheroo giving AI score even if the opponent has no held item by @kittenchilly in [#5412](https://github.com/rh-hideout/pokeemerald-expansion/pull/5412) +* Various AI fixes in `AI_CalcMoveEffectScore` by @ghoulslash in [#5474](https://github.com/rh-hideout/pokeemerald-expansion/pull/5474) + * Missing break from `EFFECT_ABSORB` switch case. + * Using last used move for Mirror Move instead of predicted move. + +## 🧹 Other Cleanup 🧹 +### Changed +* Converted `settotemboost` command to `callnative` by @ghoulslash in [#5418](https://github.com/rh-hideout/pokeemerald-expansion/pull/5418) +* Removed trailing whitespace by @kittenchilly in [#5455](https://github.com/rh-hideout/pokeemerald-expansion/pull/5455) +* Removed binary match workaround for Rayquaza's tail in Sootopolis' cutscene by @hedara90 in https://github.com/rh-hideout/pokeemerald-expansion/pull/5480 +### Fixed +* Fixed potential uninitialized behavior in `ChangeOrderTargetAfterAttacker` by @AlexOn1ine in [#5393](https://github.com/rh-hideout/pokeemerald-expansion/pull/5393) +* Fallback on default BW map pop-up theme to reduce potential for error by @ravepossum in [#5392](https://github.com/rh-hideout/pokeemerald-expansion/pull/5392) +* Multiple typo fixes by @nescioquid in [#5398](https://github.com/rh-hideout/pokeemerald-expansion/pull/5398) +* VS Seeker documentation fix by @Bassoonian in [#5415](https://github.com/rh-hideout/pokeemerald-expansion/pull/5415) + +## 🧪 Test Runner 🧪 +### Added +* Added missing After You and Quash tests by @PhallenTree in [#5400](https://github.com/rh-hideout/pokeemerald-expansion/pull/5400) +### Changed +* Improved Tangling Hair test to make sure that chained effects do not overwrite relevant battler IDs by @ghoulslash in [#5423](https://github.com/rh-hideout/pokeemerald-expansion/pull/5423) +* Improved Full Heal item tests by @kittenchilly in [#5444](https://github.com/rh-hideout/pokeemerald-expansion/pull/5444) +### Fixed +* Fixed Wake-Up Slap test typo by @Pawkkie in [#5442](https://github.com/rh-hideout/pokeemerald-expansion/pull/5442) +* Fixed test assumption fail summary fields using more memory than needed by @AsparagusEduardo in [#5443](https://github.com/rh-hideout/pokeemerald-expansion/pull/5443) +* Fixed issue with `PASSES_RANDOMLY` in AI tests by @Pawkkie in https://github.com/rh-hideout/pokeemerald-expansion/pull/5486 + +## New Contributors +* @nescioquid made their first contribution in [#5398](https://github.com/rh-hideout/pokeemerald-expansion/pull/5398) +* @kleenxfeu made their first contribution in [#4816](https://github.com/rh-hideout/pokeemerald-expansion/pull/4816) +* @wiz1989 made their first contribution in [#5453](https://github.com/rh-hideout/pokeemerald-expansion/pull/5453) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.9.2...expansion/1.9.3 + + + diff --git a/docs/team_procedures/expansion_versions.md b/docs/team_procedures/expansion_versions.md new file mode 100644 index 0000000000..b53631bfa5 --- /dev/null +++ b/docs/team_procedures/expansion_versions.md @@ -0,0 +1,187 @@ +# How to make an Expansion version + +*If you need instructions on how to release a new Expansion version, check out the enclosed instruction book. - AsparagusEduardo* + +## 1.- Autogenerating a changelog for the `master` branch. + *Requires Write access to the repo.* + +If the changelog you're making is for a minor version (Eg. 1.3.0), make sure to sync the `upcoming` branch with `master` before starting. Keep in mind that if there are unreleased changes in `master`, they should be made into a patch version released alongside minor version. +- Go to https://github.com/rh-hideout/pokeemerald-expansion/releases. +- Press the option "Draft a new release". +- Fill the following fields: + - In "Choose a tag", write the name of the tag for the desired release number. + - Eg. for version 1.2.3, write `expansion/1.2.3`. ***It cannot be an existing tag.*** + - In "Target" choose `master`. + - In "Previous tag", select the latest version released. +- Press "Generate release notes". This will fill the description with a list of PRs made to the `master` branch since the lastest release. +- You may copy the contents to your editor of choice for step 2. +- If the changelog you're making is for a minor version (Eg. 1.3.0), proceed to step 1B, without closing the current window. + +## 1B.- Autogenerating a changelog for the `upcoming` branch. +- Delete the text and title generated in the site. +- Change "Target" to `upcoming`. +- Press "Generate release notes". This will autogenerate the description with changes from both branches, as they've been merged. +- Use a comparison tool to remove any shared PRs from `master`. (I use [WinMerge](https://winmerge.org/) for this). + - Also remove any shared "New Contributor" entries. +- You should now have a text that only contains PRs made to `upcoming`. + +## 2.- Sorting PRs in the changelog +- Copy the `docs/changelogs/template.md` file into a new file with the corresponding version for file and folder. Eg, for 1.2.3, you copy the file into `docs/changelogs/1.2.x/1.2.3.md`. +- Use the following Regex to adapt all PR links into the format currently used: + - Search + ``` + in https://github\.com/rh-hideout/pokeemerald-expansion/pull/(\d+) + ``` + - Replace + ``` + in [#$1](https://github.com/rh-hideout/pokeemerald-expansion/pull/$1) + ``` +- At the bottom of the template, replace the "____" in `` with the number of the last PR in your autogenerated changelog. This will help you keep track of any new PRs that are merged in before you're finished with your changelog. +- Sort the PRs by the categories present in the PR taking the following considerations: + - Keep the language of the changelog as newbie friendly as possible, explaining how the PR affects them. + - The format of the main line is the following: + ``` + {{Description of the change}} by @{{GitHub user}} in {{PR link}} + ``` + - If a PR reverted by a different PR, both should be removed. + - If the reverted PR's contents are then re-added it should be treated as if it's the first time added, with all the proper documentation needed. + - If a PR's content fits into multiple categories, like fixing two unrelated Ability and Move effects, you may duplicate the PR line and put it in both categories, changing the description of it accordingly. + - When refering to an element present in the code, always enclose them with ` to easily tell them apart. Eg: + - "Converted `settotemboost` command to `callnative`" + - "Changed `MOVEEND_` defines to an enum" + - A PR's technical changes that may conflict with user changes should have an entry in the "**REFACTORS**" section at the beginning of the changelog. Any of these changes that requires a migration script should also be marked as such by appending the corresponding emoji listed there. The section should include, but it's not limited to: + - Massive data format and/or structuring changes. + - Converting defines to enums. + - Renaming structs and/or their fields. + - Removing enums/defines/structs. + - For fixes: + - Once on their respective categories, if a PR fixes multiple issues at once in that category, you may make a sublist of those issues to properly detail each one and avoid just writing "Fixed multiple ability issues" or an overly verbose sentence for the PR. + - Try to fit the contents of a PR as a single sentence in past tense that. + - ***DON'T*** write something like "Fixed Parental Bond", as this doesn't explain *what* was fixed in Parental Bond. Instead, write something like "Fixed Parental Bond not affecting Snore". + - For new configs: + - Add the name of the config as part of the sentence, with subitems explaining what they do based on their generation if it's a generational config. Eg: + ``` + * Added missing `B_AFTER_YOU_TURN_ORDER` config by @PhallenTree in [#5400](https://github.com/rh-hideout/pokeemerald-expansion/pull/5400) + * Gen 5-7: After You fails if the order remains the same after using After You. + * Gen 8+: After You no longer fails if the turn order remains the same after using After You. + ``` + - For other new features: + - Explain how to use the feature completely, listing all its features as needed. For now, this is the only source of documentation for these features, so it's important to be thorough. + +# 3.- Preparing the code for the new version +- Search for all non-changelog instances of the previous released version and update them to the newer version. As of writing, it's these files: + - `README.md`: + ```diff + -Based off RHH's pokeemerald-expansion 1.2.2 https://github.com/rh-hideout/pokeemerald-expansion/ + +Based off RHH's pokeemerald-expansion 1.2.3 https://github.com/rh-hideout/pokeemerald-expansion/ + ``` + ```diff + -- 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.2.2, use `git pull RHH expansion/1.2.2`). + +- 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.2.3, use `git pull RHH expansion/1.2.3`). + ``` + - `.github/ISSUE_TEMPLATE/*.yaml` + - Patch version: + ```diff + options: + - 1.2.2 (Latest release) + + 1.2.3 (Latest release) + master (default, unreleased bugfixes) + upcoming (Edge) + + 1.2.2 + 1.2.1 + 1.2.0 + ``` + - Minor Version: + ```diff + options: + - 1.2.2 (Latest release) + + 1.2.3 (Latest release) + master (default, unreleased bugfixes) + upcoming (Edge) + + 1.2.2 + 1.2.1 + 1.2.0 + - 1.1.6 + - 1.1.5 + - 1.1.4 + - 1.1.3 + - 1.1.2 + - 1.1.1 + - 1.1.0 + - pre-1.1.0 + + pre-1.2.0 + ``` + - `docs/SUMMARY.md`: + - Patch version: + ```diff + [Changelog](./CHANGELOG.md) + - [1.2.x]() + + - [Version 1.2.3](changelogs/1.2.x/1.2.3.md) + - [Version 1.2.2](changelogs/1.2.x/1.2.2.md) + - [Version 1.2.1](changelogs/1.2.x/1.2.1.md) + - [Version 1.2.0](changelogs/1.2.x/1.2.0.md) + ``` + - Minor version: + ```diff + [Changelog](./CHANGELOG.md) + + - [1.3.x]() + + - [Version 1.3.0](changelogs/1.3.x/1.3.0.md) + - [1.2.x]() + - [Version 1.2.2](changelogs/1.2.x/1.2.2.md) + - [Version 1.2.1](changelogs/1.2.x/1.2.1.md) + - [Version 1.2.0](changelogs/1.2.x/1.2.0.md) + ``` + - `include/constants/expansion.h`: + - The defines should already have the version we're targetting as part of the previous changelog process. + ```diff + -// Last version: 1.2.2 + +// Last version: 1.2.3 + #define EXPANSION_VERSION_MAJOR 1 + #define EXPANSION_VERSION_MINOR 2 + #define EXPANSION_VERSION_PATCH 3 + + // FALSE if this this version of Expansion is not a tagged commit, i.e. + // it contains unreleased changes. + -#define EXPANSION_TAGGED_RELEASE FALSE + +#define EXPANSION_TAGGED_RELEASE TRUE + ``` +# 4.- Make a PR with the changes listed in Steps 2/3. +- Also post the changelog for feedback from contributors and maintainers. +- Once all feedback has been addresses, you may merge. +# 5.- Create the release on GitHub +- Copy the contents of your manual changelog into the description of your release. +- Modify the title to "Version {{version}}", eg. "Version 1.2.3" +- Be sure to have the "Set as the latest release" option set, +- Press "Publish Release". +- This will create a new tag in the repo that users can pull from like they can with branches. +# 6.- Post-release handling +- ***DON'T ACCEPT ANY NEW PRs YET.*** We have to prepare for the next cycle first. +- Go to `include/constants/expansion.h` and merge the following changes to the repo (PR or direct commit, doesn't matter much): + - Patch version: + ```diff + // Last version: 1.2.3 + #define EXPANSION_VERSION_MAJOR 1 + #define EXPANSION_VERSION_MINOR 2 + - #define EXPANSION_VERSION_PATCH 3 + + #define EXPANSION_VERSION_PATCH 4 + + // FALSE if this this version of Expansion is not a tagged commit, i.e. + // it contains unreleased changes. + -#define EXPANSION_TAGGED_RELEASE TRUE + +#define EXPANSION_TAGGED_RELEASE FALSE + ``` +With this, the repo is ready again to receive new PRs. + +# Now you're ready to make the announcements! +- We tend to post on the following Discord Servers: + - [RH-Hideout](https://discord.gg/6CzjAG6GZk) + - Requires role to post in #announcements channel. + - [Team Aqua's Hideout](https://discord.gg/team-aqua-s-hideout-976252009114140682) + - Requires role to post in #romhacking-updates channel. + - [What a Hack!](https://discord.gg/whack-a-hack-292436944670162955) + - Announcements are done in Spanish, but not the changelogs themselves. + - Requires role to ping "Decompilaciones" role. + - [pret](https://discord.gg/R4c3FA95dP) + - [PokéCommunity](https://discord.gg/pokecommunity) + +You can make a highlight of changes in the announcement itself, but it's not needed. (I also like using Discord emotes to highlight certain features during announcements, but gain, it's not needed). diff --git a/docs/ai_flags.md b/docs/tutorials/ai_flags.md similarity index 100% rename from docs/ai_flags.md rename to docs/tutorials/ai_flags.md diff --git a/docs/ai_logic.md b/docs/tutorials/ai_logic.md similarity index 100% rename from docs/ai_logic.md rename to docs/tutorials/ai_logic.md diff --git a/docs/how_to_battle_script_command_macro.md b/docs/tutorials/how_to_battle_script_command_macro.md similarity index 100% rename from docs/how_to_battle_script_command_macro.md rename to docs/tutorials/how_to_battle_script_command_macro.md diff --git a/docs/how_to_new_move.md b/docs/tutorials/how_to_new_move.md similarity index 100% rename from docs/how_to_new_move.md rename to docs/tutorials/how_to_new_move.md diff --git a/docs/how_to_new_pokemon_1_6_0.md b/docs/tutorials/how_to_new_pokemon_1_6_0.md similarity index 100% rename from docs/how_to_new_pokemon_1_6_0.md rename to docs/tutorials/how_to_new_pokemon_1_6_0.md diff --git a/docs/how_to_new_pokemon_1_7_0.md b/docs/tutorials/how_to_new_pokemon_1_7_0.md similarity index 100% rename from docs/how_to_new_pokemon_1_7_0.md rename to docs/tutorials/how_to_new_pokemon_1_7_0.md diff --git a/docs/how_to_new_pokemon_1_8_0.md b/docs/tutorials/how_to_new_pokemon_1_8_0.md similarity index 100% rename from docs/how_to_new_pokemon_1_8_0.md rename to docs/tutorials/how_to_new_pokemon_1_8_0.md diff --git a/docs/how_to_new_pokemon_1_9_0.md b/docs/tutorials/how_to_new_pokemon_1_9_0.md similarity index 100% rename from docs/how_to_new_pokemon_1_9_0.md rename to docs/tutorials/how_to_new_pokemon_1_9_0.md diff --git a/docs/how_to_testing_system.md b/docs/tutorials/how_to_testing_system.md similarity index 100% rename from docs/how_to_testing_system.md rename to docs/tutorials/how_to_testing_system.md diff --git a/docs/how_to_trainer_class.md b/docs/tutorials/how_to_trainer_class.md similarity index 100% rename from docs/how_to_trainer_class.md rename to docs/tutorials/how_to_trainer_class.md diff --git a/graphics/rayquaza_scene/scene_3/rayquaza_tail.png b/graphics/rayquaza_scene/scene_3/rayquaza_tail.png index 7e0577df15..796548e56a 100644 Binary files a/graphics/rayquaza_scene/scene_3/rayquaza_tail.png and b/graphics/rayquaza_scene/scene_3/rayquaza_tail.png differ diff --git a/graphics_file_rules.mk b/graphics_file_rules.mk index 1b514b8ed3..06316ea6a9 100644 --- a/graphics_file_rules.mk +++ b/graphics_file_rules.mk @@ -393,10 +393,6 @@ $(RAYQUAZAGFXDIR)/scene_2/bg.4bpp: %.4bpp: %.png $(RAYQUAZAGFXDIR)/scene_3/rayquaza.4bpp: %.4bpp: %.png $(GFX) $< $@ -num_tiles 124 -Wnum_tiles -$(RAYQUAZAGFXDIR)/scene_3/rayquaza_tail_fix.4bpp: $(RAYQUAZAGFXDIR)/scene_3/rayquaza_tail.4bpp - cp $< $@ - head -c 12 /dev/zero >> $@ - $(RAYQUAZAGFXDIR)/scene_4/streaks.4bpp: %.4bpp: %.png $(GFX) $< $@ -num_tiles 19 -Wnum_tiles diff --git a/include/battle.h b/include/battle.h index 2d4f83d430..f2e5297189 100644 --- a/include/battle.h +++ b/include/battle.h @@ -1070,6 +1070,7 @@ extern u16 gLastPrintedMoves[MAX_BATTLERS_COUNT]; extern u16 gLastMoves[MAX_BATTLERS_COUNT]; extern u16 gLastLandedMoves[MAX_BATTLERS_COUNT]; extern u16 gLastHitByType[MAX_BATTLERS_COUNT]; +extern u16 gLastUsedMoveType[MAX_BATTLERS_COUNT]; extern u16 gLastResultingMoves[MAX_BATTLERS_COUNT]; extern u16 gLockedMoves[MAX_BATTLERS_COUNT]; extern u16 gLastUsedMove; diff --git a/include/battle_anim.h b/include/battle_anim.h index 6ff7e9ff22..36b21bc012 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -347,7 +347,6 @@ extern const union AnimCmd *const gAnims_WaterPulseBubble[]; // battle_anim_flying.c void DestroyAnimSpriteAfterTimer(struct Sprite *sprite); -void sub_810E2C8(struct Sprite *sprite); void AnimAirWaveCrescent(struct Sprite *sprite); void AnimFlyBallUp(struct Sprite *sprite); void AnimFlyBallAttack(struct Sprite *sprite); diff --git a/include/config/battle.h b/include/config/battle.h index b00eb199a9..fbc41be6ba 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -70,6 +70,7 @@ #define B_RECOIL_IF_MISS_DMG GEN_LATEST // In Gen5+, Jump Kick and High Jump Kick will always do half of the user's max HP when missing. #define B_KLUTZ_FLING_INTERACTION GEN_LATEST // In Gen5+, Pokémon with the Klutz ability can't use Fling. #define B_UPDATED_CONVERSION GEN_LATEST // In Gen6+, Conversion changes the user's type to match their first move's. Before, it would choose a move at random. +#define B_UPDATED_CONVERSION_2 GEN_LATEST // In Gen5+, Conversion 2 changes the user's type to a type that resists the last move used by the selected target. Before, it would consider the last move being successfully hit by. Additionally, Struggle is considered Normal type before Gen 5. #define B_PP_REDUCED_BY_SPITE GEN_LATEST // In Gen4+, Spite reduces the foe's last move's PP by 4, instead of 2 to 5. #define B_EXTRAPOLATED_MOVE_FLAGS TRUE // Adds move flags to moves that they don't officially have but would likely have if they were in the latest core series game. diff --git a/include/constants/expansion.h b/include/constants/expansion.h index 8a86282619..44b1169bcd 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -1,10 +1,10 @@ #ifndef GUARD_CONSTANTS_EXPANSION_H #define GUARD_CONSTANTS_EXPANSION_H -// Last version: 1.9.2 +// Last version: 1.9.3 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 9 -#define EXPANSION_VERSION_PATCH 3 +#define EXPANSION_VERSION_PATCH 4 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. diff --git a/include/event_scripts.h b/include/event_scripts.h index fa0bfe5c6e..0ba3739b20 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -404,6 +404,7 @@ extern const u8 EventScript_FailSweetScent[]; extern const u8 EventScript_UseFlash[]; extern const u8 EventScript_UseCut[]; extern const u8 EventScript_UseRockSmash[]; +extern const u8 EventScript_UseDig[]; //player pc extern const u8 LittlerootTown_BrendansHouse_2F_EventScript_TurnOffPlayerPC[]; diff --git a/include/test/battle.h b/include/test/battle.h index c28410948d..041ebc1c72 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -645,6 +645,15 @@ struct AILogLine s16 score; }; +// Data which is updated by the test runner during a battle and needs to +// be reset between trials. +struct BattleTrialData +{ + u8 lastActionTurn; + u8 queuedEvent; + u8 aiActionsPlayed[MAX_BATTLERS_COUNT]; +}; + struct BattleTestData { u8 stack[BATTLE_TEST_STACK_SIZE]; @@ -676,20 +685,19 @@ struct BattleTestData u8 battleRecordSourceLineOffsets[MAX_BATTLERS_COUNT][BATTLER_RECORD_SIZE]; u16 recordIndexes[MAX_BATTLERS_COUNT]; struct BattlerTurn battleRecordTurns[MAX_TURNS][MAX_BATTLERS_COUNT]; - u8 lastActionTurn; u8 queuedEventsCount; u8 queueGroupType; u8 queueGroupStart; - u8 queuedEvent; struct QueuedEvent queuedEvents[MAX_QUEUED_EVENTS]; u8 expectedAiActionIndex[MAX_BATTLERS_COUNT]; - u8 aiActionsPlayed[MAX_BATTLERS_COUNT]; struct ExpectedAIAction expectedAiActions[MAX_BATTLERS_COUNT][MAX_EXPECTED_ACTIONS]; struct ExpectedAiScore expectedAiScores[MAX_BATTLERS_COUNT][MAX_TURNS][MAX_AI_SCORE_COMPARISION_PER_TURN]; // Max 4 comparisions per turn struct AILogLine aiLogLines[MAX_BATTLERS_COUNT][MAX_MON_MOVES][MAX_AI_LOG_LINES]; u8 aiLogPrintedForMove[MAX_BATTLERS_COUNT]; // Marks ai score log as printed for move, so the same log isn't displayed multiple times. u16 flagId; + + struct BattleTrialData trial; }; struct BattleTestRunnerState diff --git a/ld_script.ld b/ld_script.ld index c1df05e854..ccf5f813d8 100644 --- a/ld_script.ld +++ b/ld_script.ld @@ -18,6 +18,7 @@ SECTIONS { { __ewram_start = .; *(.ewram*) + . = ALIGN(4); __ewram_end = .; } > EWRAM @@ -38,6 +39,7 @@ SECTIONS { { __iwram_start = .; *(.iwram*); + . = ALIGN(4); __iwram_end = .; } > IWRAM diff --git a/ld_script_modern.ld b/ld_script_modern.ld index 8021b25b81..8e63ad55a6 100644 --- a/ld_script_modern.ld +++ b/ld_script_modern.ld @@ -19,6 +19,7 @@ SECTIONS { { __ewram_start = .; *(.ewram*) + . = ALIGN(4); __ewram_end = .; } > EWRAM @@ -34,6 +35,7 @@ SECTIONS { { __iwram_start = .; *(.iwram*); + . = ALIGN(4); __iwram_end = .; } > IWRAM diff --git a/ld_script_test.ld b/ld_script_test.ld index f7222345e7..05cd56d118 100644 --- a/ld_script_test.ld +++ b/ld_script_test.ld @@ -27,6 +27,7 @@ SECTIONS { src/*.o(.sbss); gflib/*.o(.sbss); test/*.o(.sbss); + . = ALIGN(4); } > EWRAM .iwram ORIGIN(IWRAM) : AT (__iwram_lma) @@ -34,6 +35,7 @@ SECTIONS { { __iwram_start = .; *(.iwram*); + . = ALIGN(4); __iwram_end = .; } > IWRAM @@ -56,6 +58,7 @@ SECTIONS { data/*.o(COMMON); test/*.o(COMMON); *libc.a:sbrkr.o(COMMON); + . = ALIGN(4); /* .persistent starts at 0x3007F00 */ /* WARNING: This is the end of the IRQ stack, if there's too diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 903b0c7d9f..e41be6971c 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3302,6 +3302,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_ABSORB: if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT && effectiveness >= AI_EFFECTIVENESS_x1) ADJUST_SCORE(DECENT_EFFECT); + break; case EFFECT_EXPLOSION: case EFFECT_MEMENTO: if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_WILL_SUICIDE && gBattleMons[battlerDef].statStages[STAT_EVASION] < 7) @@ -3316,7 +3317,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_MIRROR_MOVE: if (predictedMove != MOVE_NONE) - return AI_CheckViability(battlerAtk, battlerDef, gLastMoves[battlerDef], score); + return AI_CheckViability(battlerAtk, battlerDef, predictedMove, score); break; case EFFECT_ATTACK_UP: case EFFECT_ATTACK_UP_USER_ALLY: diff --git a/src/battle_main.c b/src/battle_main.c index 2050323d75..8ff460b0fb 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -181,6 +181,7 @@ EWRAM_DATA u16 gLastPrintedMoves[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gLastMoves[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gLastLandedMoves[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gLastHitByType[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA u16 gLastUsedMoveType[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gLastResultingMoves[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gLockedMoves[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gLastUsedMove = 0; @@ -3029,6 +3030,7 @@ static void BattleStartClearSetData(void) gLastMoves[i] = MOVE_NONE; gLastLandedMoves[i] = MOVE_NONE; gLastHitByType[i] = 0; + gLastUsedMoveType[i] = 0; gLastResultingMoves[i] = MOVE_NONE; gLastHitBy[i] = 0xFF; gLockedMoves[i] = MOVE_NONE; @@ -3207,6 +3209,7 @@ void SwitchInClearSetData(u32 battler) gLastMoves[battler] = MOVE_NONE; gLastLandedMoves[battler] = MOVE_NONE; gLastHitByType[battler] = 0; + gLastUsedMoveType[battler] = 0; gLastResultingMoves[battler] = MOVE_NONE; gLastPrintedMoves[battler] = MOVE_NONE; gLastHitBy[battler] = 0xFF; @@ -3336,6 +3339,7 @@ const u8* FaintClearSetData(u32 battler) gLastMoves[battler] = MOVE_NONE; gLastLandedMoves[battler] = MOVE_NONE; gLastHitByType[battler] = 0; + gLastUsedMoveType[battler] = 0; gLastResultingMoves[battler] = MOVE_NONE; gLastPrintedMoves[battler] = MOVE_NONE; gLastHitBy[battler] = 0xFF; @@ -3746,7 +3750,6 @@ static void DoBattleIntro(void) gBattleStruct->eventsBeforeFirstTurnState = 0; gBattleStruct->switchInBattlerCounter = 0; gBattleStruct->overworldWeatherDone = FALSE; - SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers Ai_InitPartyStruct(); // Save mons party counts, and first 2/4 mons on the battlefield. // Try to set a status to start the battle with diff --git a/src/battle_message.c b/src/battle_message.c index ecb2932124..52c6dec6ae 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -640,7 +640,7 @@ static const u8 sText_HealingWishCameTrue[] = _("The healing wish came true\nfor static const u8 sText_HealingWishHealed[] = _("{B_ATK_NAME_WITH_PREFIX} regained health!"); static const u8 sText_LunarDanceCameTrue[] = _("{B_ATK_NAME_WITH_PREFIX} became cloaked\nin mystical moonlight!"); static const u8 sText_CursedBodyDisabled[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} was disabled\nby {B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY}!"); -static const u8 sText_AttackerAquiredAbility[] = _("{B_ATK_NAME_WITH_PREFIX} acquired\n{B_LAST_ABILITY}!"); +static const u8 sText_AttackerAcquiredAbility[] = _("{B_ATK_NAME_WITH_PREFIX} acquired\n{B_ATK_ABILITY}!"); static const u8 sText_TargetStatWontGoHigher[] = _("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1}\nwon't go higher!"); static const u8 sText_PkmnMoveBouncedViaAbility[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} was\nbounced back by {B_DEF_NAME_WITH_PREFIX}'s\l{B_DEF_ABILITY}!"); static const u8 sText_ImposterTransform[] = _("{B_ATK_NAME_WITH_PREFIX} transformed into\n{B_DEF_NAME_WITH_PREFIX} using {B_LAST_ABILITY}!"); @@ -1477,7 +1477,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_HEALINGWISHHEALED - BATTLESTRINGS_TABLE_START] = sText_HealingWishHealed, [STRINGID_LUNARDANCECAMETRUE - BATTLESTRINGS_TABLE_START] = sText_LunarDanceCameTrue, [STRINGID_CUSEDBODYDISABLED - BATTLESTRINGS_TABLE_START] = sText_CursedBodyDisabled, - [STRINGID_ATTACKERACQUIREDABILITY - BATTLESTRINGS_TABLE_START] = sText_AttackerAquiredAbility, + [STRINGID_ATTACKERACQUIREDABILITY - BATTLESTRINGS_TABLE_START] = sText_AttackerAcquiredAbility, [STRINGID_TARGETABILITYSTATLOWER - BATTLESTRINGS_TABLE_START] = sText_TargetAbilityLoweredStat, [STRINGID_TARGETSTATWONTGOHIGHER - BATTLESTRINGS_TABLE_START] = sText_TargetStatWontGoHigher, [STRINGID_PKMNMOVEBOUNCEDABILITY - BATTLESTRINGS_TABLE_START] = sText_PkmnMoveBouncedViaAbility, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f16ee0bf76..63b539dcc2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1210,6 +1210,7 @@ static void Cmd_attackcanceler(void) gCurrentActionFuncId = B_ACTION_FINISHED; return; } + if (!IsBattlerAlive(gBattlerAttacker) && gMovesInfo[gCurrentMove].effect != EFFECT_EXPLOSION && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) { gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; @@ -5916,12 +5917,14 @@ static void Cmd_moveend(void) gLastMoves[gBattlerAttacker] = gChosenMove; RecordKnownMove(gBattlerAttacker, gChosenMove); gLastResultingMoves[gBattlerAttacker] = gCurrentMove; + GET_MOVE_TYPE(gCurrentMove, gLastUsedMoveType[gBattlerAttacker]); } } else { gLastMoves[gBattlerAttacker] = MOVE_UNAVAILABLE; gLastResultingMoves[gBattlerAttacker] = MOVE_UNAVAILABLE; + gLastUsedMoveType[gBattlerAttacker] = 0; } if (!(gHitMarker & HITMARKER_FAINTED(gBattlerTarget))) @@ -9780,6 +9783,7 @@ static void Cmd_various(void) if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = ABILITY_SIMPLE; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12953,60 +12957,122 @@ static void Cmd_settypetorandomresistance(void) { CMD_ARGS(const u8 *failInstr); - if (gLastLandedMoves[gBattlerAttacker] == MOVE_NONE - || gLastLandedMoves[gBattlerAttacker] == MOVE_UNAVAILABLE) + // Before Gen 5 Conversion 2 only worked on a move the attacker was actually hit by. + // This changed later to the last move used by the selected target. + if (B_UPDATED_CONVERSION_2 < GEN_5) { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (gBattleMoveEffects[gMovesInfo[gLastLandedMoves[gBattlerAttacker]].effect].twoTurnEffect - && gBattleMons[gLastHitBy[gBattlerAttacker]].status2 & STATUS2_MULTIPLETURNS) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR || gLastHitByType[gBattlerAttacker] == TYPE_MYSTERY) - { - gBattlescriptCurrInstr = cmd->failInstr; + if (gLastLandedMoves[gBattlerAttacker] == MOVE_NONE + || gLastLandedMoves[gBattlerAttacker] == MOVE_UNAVAILABLE) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (gBattleMoveEffects[gMovesInfo[gLastLandedMoves[gBattlerAttacker]].effect].twoTurnEffect + && gBattleMons[gLastHitBy[gBattlerAttacker]].status2 & STATUS2_MULTIPLETURNS) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR || gLastHitByType[gBattlerAttacker] == TYPE_MYSTERY) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + u32 i, resistTypes = 0; + u32 hitByType = gLastHitByType[gBattlerAttacker]; + + for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist. + { + switch (GetTypeModifier(hitByType, i)) + { + case UQ_4_12(0): + case UQ_4_12(0.5): + resistTypes |= gBitTable[i]; + break; + } + } + + while (resistTypes != 0) + { + i = Random() % NUMBER_OF_MON_TYPES; + if (resistTypes & gBitTable[i]) + { + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i)) + { + resistTypes &= ~(gBitTable[i]); // Type resists, but the user is already of this type. + } + else + { + SET_BATTLER_TYPE(gBattlerAttacker, i); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, i); + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + } + } + + gBattlescriptCurrInstr = cmd->failInstr; + } } else { - u32 i, resistTypes = 0; - u32 hitByType = gLastHitByType[gBattlerAttacker]; - - for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist. + if (gLastResultingMoves[gBattlerTarget] == MOVE_NONE + || gLastResultingMoves[gBattlerTarget] == MOVE_UNAVAILABLE + || gLastResultingMoves[gBattlerTarget] == MOVE_STRUGGLE) { - switch (GetTypeModifier(hitByType, i)) - { - case UQ_4_12(0): - case UQ_4_12(0.5): - resistTypes |= gBitTable[i]; - break; - } + gBattlescriptCurrInstr = cmd->failInstr; } - - while (resistTypes != 0) + else if (IsSemiInvulnerable(gBattlerTarget, gCurrentMove)) { - i = Random() % NUMBER_OF_MON_TYPES; - if (resistTypes & gBitTable[i]) + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (gLastUsedMoveType[gBattlerTarget] == TYPE_NONE || gLastUsedMoveType[gBattlerTarget] == TYPE_STELLAR || gLastUsedMoveType[gBattlerTarget] == TYPE_MYSTERY) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + u32 i, resistTypes = 0; + + for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist. { - if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i)) + switch (GetTypeModifier(gLastUsedMoveType[gBattlerTarget], i)) { - resistTypes &= ~(gBitTable[i]); // Type resists, but the user is already of this type. - } - else - { - SET_BATTLER_TYPE(gBattlerAttacker, i); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, i); - gBattlescriptCurrInstr = cmd->nextInstr; - return; + case UQ_4_12(0): + case UQ_4_12(0.5): + resistTypes |= gBitTable[i]; + break; } } - } - gBattlescriptCurrInstr = cmd->failInstr; + while (resistTypes != 0) + { + i = Random() % NUMBER_OF_MON_TYPES; + if (resistTypes & gBitTable[i]) + { + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i)) + { + resistTypes &= ~(gBitTable[i]); // Type resists, but the user is already of this type. + } + else + { + SET_BATTLER_TYPE(gBattlerAttacker, i); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, i); + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + } + } + + gBattlescriptCurrInstr = cmd->failInstr; + } } } @@ -14305,7 +14371,7 @@ static void Cmd_trycopyability(void) if (gBattleMons[battler].ability == defAbility || defAbility == ABILITY_NONE || gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed - || gAbilitiesInfo[gBattleMons[BATTLE_PARTNER(battler)].ability].cantBeSuppressed + || (IsBattlerAlive(BATTLE_PARTNER(battler)) && gAbilitiesInfo[gBattleMons[BATTLE_PARTNER(battler)].ability].cantBeSuppressed && gMovesInfo[gCurrentMove].effect == EFFECT_DOODLE) || gAbilitiesInfo[defAbility].cantBeCopied) { gBattlescriptCurrInstr = cmd->failInstr; @@ -14501,9 +14567,11 @@ static void Cmd_tryswapabilities(void) } else { - u16 abilityAtk = gBattleMons[gBattlerAttacker].ability; - gBattleMons[gBattlerAttacker].ability = gBattleStruct->overwrittenAbilities[gBattlerAttacker] = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = abilityAtk; + if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerAttacker].ability; + gLastUsedAbility = gBattleMons[gBattlerTarget].ability; + gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = gBattleMons[gBattlerAttacker].ability; + gBattleMons[gBattlerAttacker].ability = gBattleStruct->overwrittenAbilities[gBattlerAttacker] = gLastUsedAbility; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -15795,6 +15863,7 @@ static void Cmd_tryworryseed(void) } else { + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = ABILITY_INSOMNIA; gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/src/battle_util.c b/src/battle_util.c index 2e463eaf58..33063cd542 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -279,18 +279,9 @@ void HandleAction_UseMove(void) gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker); } - if (!IsBattlerAlive(gBattlerTarget)) + if (!IsBattlerAlive(gBattlerTarget) && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) { - if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) - { - gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget))); - } - else - { - gBattlerTarget = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(gBattlerAttacker))); - if (!IsBattlerAlive(gBattlerTarget)) - gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget))); - } + gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget))); } } else @@ -307,8 +298,7 @@ void HandleAction_UseMove(void) gBattlerTarget = battler; } } - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && moveTarget & MOVE_TARGET_RANDOM) + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & MOVE_TARGET_RANDOM) { if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) { @@ -352,18 +342,11 @@ void HandleAction_UseMove(void) else { gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker); - if (!IsBattlerAlive(gBattlerTarget) && moveTarget != MOVE_TARGET_OPPONENTS_FIELD) + if (!IsBattlerAlive(gBattlerTarget) + && moveTarget != MOVE_TARGET_OPPONENTS_FIELD + && (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))) { - if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) - { - gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget))); - } - else - { - gBattlerTarget = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(gBattlerAttacker))); - if (!IsBattlerAlive(gBattlerTarget)) - gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget))); - } + gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget))); } } @@ -387,8 +370,9 @@ void HandleAction_UseMove(void) gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; } } - // Edge case: moves targeting the ally fail after a successful Ally Switch. - else if (moveTarget == MOVE_TARGET_ALLY && gProtectStructs[BATTLE_PARTNER(gBattlerAttacker)].usedAllySwitch) + + if ((GetBattlerSide(gBattlerAttacker) == GetBattlerSide(gBattlerTarget)) + && (!IsBattlerAlive(gBattlerTarget) || gProtectStructs[BATTLE_PARTNER(gBattlerAttacker)].usedAllySwitch)) { gBattlescriptCurrInstr = BattleScript_FailedFromAtkCanceler; } @@ -738,8 +722,6 @@ void HandleAction_ActionFinished(void) gMoveResultFlags = 0; gBattleScripting.animTurn = 0; gBattleScripting.animTargetsHit = 0; - gLastLandedMoves[gBattlerAttacker] = 0; - gLastHitByType[gBattlerAttacker] = 0; gBattleStruct->dynamicMoveType = 0; gBattleScripting.moveendState = 0; gBattleCommunication[3] = 0; @@ -5548,7 +5530,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; } - gLastUsedAbility = gBattleMons[gBattlerAttacker].ability = gBattleStruct->overwrittenAbilities[gBattlerAttacker] = gBattleMons[gBattlerTarget].ability; + gLastUsedAbility = gBattleMons[gBattlerAttacker].ability; + gBattleMons[gBattlerAttacker].ability = gBattleStruct->overwrittenAbilities[gBattlerAttacker] = gBattleMons[gBattlerTarget].ability; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_MummyActivates; effect++; diff --git a/src/berry.c b/src/berry.c index 9f187bd1e2..b1e29be6db 100644 --- a/src/berry.c +++ b/src/berry.c @@ -2384,6 +2384,8 @@ static u8 GetTreeMutationValue(u8 id) myMutation.asField.a = tree->mutationA; myMutation.asField.b = tree->mutationB; myMutation.asField.unused = 0; + if (myMutation.value == 0) // no mutation + return 0; return sBerryMutations[myMutation.value - 1][2]; #else return 0; diff --git a/src/braille_puzzles.c b/src/braille_puzzles.c index ab0f610fd7..757cac43b8 100644 --- a/src/braille_puzzles.c +++ b/src/braille_puzzles.c @@ -87,7 +87,6 @@ void DoBrailleDigEffect(void) DrawWholeMapView(); PlaySE(SE_BANG); FlagSet(FLAG_SYS_BRAILLE_DIG); - UnlockPlayerFieldControls(); } bool8 CheckRelicanthWailord(void) diff --git a/src/data/abilities.h b/src/data/abilities.h index a85f114fec..5c28e17c05 100644 --- a/src/data/abilities.h +++ b/src/data/abilities.h @@ -1550,7 +1550,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = [ABILITY_SLUSH_RUSH] = { .name = _("Slush Rush"), - .description = COMPOUND_STRING("Raises Speed in Hail or Snow."), + .description = COMPOUND_STRING("Raises Speed in Hail/Snow."), .aiRating = 5, }, @@ -2273,6 +2273,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .cantBeSwapped = TRUE, .cantBeTraced = TRUE, .cantBeSuppressed = TRUE, + .cantBeOverwritten = TRUE, }, [ABILITY_ELECTROMORPHOSIS] = @@ -2572,7 +2573,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = [ABILITY_TERA_SHELL] = { .name = _("Tera Shell"), - .description = COMPOUND_STRING("Resistant to types at full HP."), + .description = COMPOUND_STRING("Resists all at full HP."), .aiRating = 10, .cantBeCopied = TRUE, .cantBeSwapped = TRUE, @@ -2587,7 +2588,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = #else .name = _("TeraformZero"), #endif - .description = COMPOUND_STRING("Removes weather and terrain."), + .description = COMPOUND_STRING("Zeroes weather and terrain."), .aiRating = 10, .cantBeCopied = TRUE, .cantBeSwapped = TRUE, diff --git a/src/data/graphics/rayquaza_scene.h b/src/data/graphics/rayquaza_scene.h index 660f07416c..e999e947fb 100644 --- a/src/data/graphics/rayquaza_scene.h +++ b/src/data/graphics/rayquaza_scene.h @@ -24,9 +24,7 @@ const u32 gRaySceneTakesFlight_Bg_Tilemap[] = INCBIN_U32("graphics/rayquaz // Scene 3 (RAY_ANIM_DESCENDS) const u32 gRaySceneDescends_Rayquaza_Gfx[] = INCBIN_U32("graphics/rayquaza_scene/scene_3/rayquaza.4bpp.lz"); -// for some reason there are an extra 0xC bytes at the end of the original rayquaza_tail.4bpp, so in order to produce the correct lz, -// we have to cat the bytes at the end with a make rule. not sure why those bytes are there, it may have been a bug in Game Freak's software. -const u32 gRaySceneDescends_RayquazaTail_Gfx[] = INCBIN_U32("graphics/rayquaza_scene/scene_3/rayquaza_tail_fix.4bpp.lz"); +const u32 gRaySceneDescends_RayquazaTail_Gfx[] = INCBIN_U32("graphics/rayquaza_scene/scene_3/rayquaza_tail.4bpp.lz"); const u32 gRaySceneDescends_Bg_Gfx[] = INCBIN_U32("graphics/rayquaza_scene/scene_3/bg.4bpp.lz"); const u32 gRaySceneDescends_Light_Gfx[] = INCBIN_U32("graphics/rayquaza_scene/scene_3/light.4bpp.lz"); // uses pal 2 of gRaySceneDescends_Bg_Pal const u32 gRaySceneDescends_Bg_Pal[] = INCBIN_U32("graphics/rayquaza_scene/scene_3/bg.gbapal.lz"); diff --git a/src/data/items.h b/src/data/items.h index 75629d579f..bffe48d725 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -538,9 +538,9 @@ const struct Item gItemsInfo[] = .name = _("Sport Ball"), .price = (I_PRICE < GEN_3 || I_PRICE >= GEN_9) ? 0 : 300, .description = COMPOUND_STRING( - "A special Ball used\n" - "in the Bug-Catching\n" - "Contest."), + "A special Ball\n" + "used in the Bug-\n" + "Catching Contest."), .pocket = POCKET_POKE_BALLS, .type = ITEM_USE_BAG_MENU, .battleUsage = EFFECT_ITEM_THROW_BALL, @@ -3176,9 +3176,9 @@ const struct Item gItemsInfo[] = .name = _("Jaw Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( - "A piece of a prehis-\n" - "toric Pokémon's\n" - "large jaw."), + "A piece of a\n" + "prehistoric Poké-\n" + "mon's large jaw."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -3192,9 +3192,9 @@ const struct Item gItemsInfo[] = .name = _("Sail Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( - "A piece of a prehis-\n" - "toric Pokémon's\n" - "skin sail."), + "A piece of a\n" + "prehistoric Poké-\n" + "mon's skin sail."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -4169,8 +4169,8 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain\n" - "Pokémon. Imbued with\n" - "spiritual energy."), + "Pokémon. Imbued\n" + "with spirit energy."), .pocket = POCKET_ITEMS, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, @@ -4186,8 +4186,8 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 2000 : 500), .description = COMPOUND_STRING( "A mysterious scale\n" - "that evolves certain\n" - "Pokémon. It shines."), + "that evolves a\n" + "certain Pokémon."), .pocket = POCKET_ITEMS, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, @@ -4220,8 +4220,8 @@ const struct Item gItemsInfo[] = .name = _("Sachet"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( - "A sachet filled with\n" - "perfumes loved by\n" + "A sachet of strong\n" + "perfumes, loved by\n" "a certain Pokémon."), .pocket = POCKET_ITEMS, .type = EVO_HELD_ITEM_TYPE, @@ -4237,9 +4237,9 @@ const struct Item gItemsInfo[] = .name = _("Oval Stone"), .price = (I_PRICE >= GEN_7) ? 2000 : 2100, .description = COMPOUND_STRING( - "Makes a certain\n" - "Pokémon evolve. It's\n" - "shaped like an egg."), + "Peculiar stone\n" + "that evolves a\n" + "certain Pokémon."), .pocket = POCKET_ITEMS, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, @@ -4749,8 +4749,8 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, .description = COMPOUND_STRING( - "A stone tablet that\n" - "boosts the power of\n" + "A tablet that ups\n" + "the power of\n" "Fairy-type moves."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4945,7 +4945,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, .description = COMPOUND_STRING( - "A disc with Fighting\n" + "Disc with Fighting\n" "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, @@ -7053,9 +7053,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_QUICK_POWDER, .description = COMPOUND_STRING( - "An item to be held\n" - "by Ditto. This odd\n" - "powder boosts Speed."), + "A hold item that\n" + "raises the Speed\n" + "of Ditto."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -7132,9 +7132,9 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_ADAMANT_ORB, .holdEffectParam = 20, .description = COMPOUND_STRING( - "Boosts the power of\n" - "Dialga's Dragon and\n" - "Steel-type moves."), + "Powers up Dialga's\n" + "Dragon and Steel-\n" + "type moves."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -7150,9 +7150,9 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_LUSTROUS_ORB, .holdEffectParam = 20, .description = COMPOUND_STRING( - "Boosts the power of\n" - "Palkia's Dragon and\n" - "Water-type moves."), + "Powers up Palkia's\n" + "Dragon and Water-\n" + "type moves."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -7168,7 +7168,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_GRISEOUS_ORB, .holdEffectParam = 20, .description = COMPOUND_STRING( - "Powers up Giratina's\n" + "Boosts Giratina's\n" "Dragon and Ghost-\n" "type moves."), .pocket = POCKET_ITEMS, @@ -8107,9 +8107,9 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_CELL_BATTERY, .holdEffectParam = 0, .description = COMPOUND_STRING( - "Raises Atk if the\n" - "holder is hit by an\n" - "Electric-type move."), + "Raises Attack if\n" + "the holder is hit by\n" + "an Electric move."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8454,8 +8454,8 @@ const struct Item gItemsInfo[] = .holdEffectParam = 10, .description = COMPOUND_STRING( "A headband that\n" - "boosts the power of\n" - "physical moves."), + "boosts the power\n" + "of physical moves."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8525,9 +8525,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LIFE_ORB, .description = COMPOUND_STRING( - "Boosts the power of\n" - "moves at the cost\n" - "of some HP per turn."), + "Boosts move power\n" + "but holder loses HP\n" + "with each attack."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8614,9 +8614,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_IRON_BALL, .description = COMPOUND_STRING( - "Cuts Speed and lets\n" - "Flying-types be hit\n" - "by Ground moves."), + "Cuts Speed and\n" + "becomes vulnerable\n" + "to Ground moves."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8663,9 +8663,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BLACK_SLUDGE, .description = COMPOUND_STRING( - "Gradually restores\n" - "HP of Poison-types.\n" - "Damages others."), + "Restores HP for\n" + "Poison-types.\n" + "Damages all others."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8680,9 +8680,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GRIP_CLAW, .description = COMPOUND_STRING( - "Makes binding moves\n" - "used by the holder\n" - "go on for 7 turns."), + "A held item that\n" + "extends binding\n" + "moves like Wrap."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8698,8 +8698,8 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_STICKY_BARB, .description = COMPOUND_STRING( "Damages the holder\n" - "each turn. May latch\n" - "on to foes."), + "each turn. May\n" + "latch on to foes."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8714,9 +8714,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_SHED_SHELL, .description = COMPOUND_STRING( - "Enables the holder\n" - "to switch out of\n" - "battle without fail."), + "Allows the holder\n" + "to switch out\n" + "without fail."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8733,7 +8733,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 30, .description = COMPOUND_STRING( "A held item that\n" - "boosts the power of\n" + "ups the power of\n" "HP-stealing moves."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -8837,9 +8837,9 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_AIR_BALLOON, .holdEffectParam = 0, .description = COMPOUND_STRING( - "Elevates the holder\n" - "in the air. If hit,\n" - "this item will burst."), + "Makes the holder\n" + "float but bursts\n" + "if hit by an attack."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8873,9 +8873,9 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_RING_TARGET, .holdEffectParam = 0, .description = COMPOUND_STRING( - "Moves that wouldn't\n" - "have effect will\n" - "land on its holder."), + "Moves that usually\n" + "have no effect will\n" + "hit the holder."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8927,9 +8927,9 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_WEAKNESS_POLICY, .holdEffectParam = 0, .description = COMPOUND_STRING( - "If hit by a Super\n" - "Effective move, ups\n" - "Atk and Sp. Atk."), + "If hit by a super-\n" + "effective move,\n" + "ups Atk and Sp. Atk."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -8980,9 +8980,9 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_8) ? 4000 : 300), .holdEffect = HOLD_EFFECT_ADRENALINE_ORB, .description = COMPOUND_STRING( - "Boosts Speed if the\n" - "user is intimidated,\n" - "but only one time."), + "This orb boosts\n" + "Speed if the holder\n" + "is intimidated."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -13042,9 +13042,9 @@ const struct Item gItemsInfo[] = .price = 20000, .holdEffect = HOLD_EFFECT_COVERT_CLOAK, .description = COMPOUND_STRING( - "Protects the holder\n" - "from secondary\n" - "move effects."), + "Protects holder\n" + "from additional\n" + "effects of moves."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -14009,11 +14009,11 @@ const struct Item gItemsInfo[] = .description = COMPOUND_STRING( #if B_X_ITEMS_BUFF >= GEN_7 "Sharply raises\n" - "offenses & defenses\n" + "offense & defense\n" "during one battle."), #else - "Raises offenses\n" - "and defenses during\n" + "Raises offense\n" + "and defense during\n" "one battle."), #endif .pocket = POCKET_ITEMS, @@ -14068,9 +14068,9 @@ const struct Item gItemsInfo[] = .name = _("Pokéshi Doll"), .price = 2000, .description = COMPOUND_STRING( - "A wooden toy carved\n" - "in the image of a\n" - "Pokémon. Can be sold."), + "A wooden toy\n" + "resembling a Poké-.\n" + "mon. Can be sold."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, diff --git a/src/data/moves_info.h b/src/data/moves_info.h index b6d0aaf3ca..478f0dc426 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -4511,7 +4511,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .type = TYPE_NORMAL, .accuracy = 0, .pp = 30, - .target = MOVE_TARGET_USER, + .target = B_UPDATED_MOVE_DATA >= GEN_5 ? MOVE_TARGET_SELECTED : MOVE_TARGET_USER, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RECOVER_HP }, @@ -14198,8 +14198,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = { .name = HANDLE_EXPANDED_MOVE_NAME("ParabolcChrg", "Parabolic Charge"), .description = COMPOUND_STRING( - "Damages adjacent Pokémon and\n" - "heals up by half of it."), + "Damages adjacent Pokémon\n" + "and heals up by half of it."), .effect = EFFECT_ABSORB, .power = B_UPDATED_MOVE_DATA >= GEN_7 ? 65 : 50, .type = TYPE_ELECTRIC, @@ -16757,7 +16757,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .name = COMPOUND_STRING("Plasma Fists"), .description = COMPOUND_STRING( "Hits with electrical fists.\n" - "Normal moves become Electric."), + "Normal moves turn Electric."), .effect = EFFECT_PLASMA_FISTS, .power = 100, .type = TYPE_ELECTRIC, @@ -17116,8 +17116,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = { .name = HANDLE_EXPANDED_MOVE_NAME("DynamxCannon", "Dynamax Cannon"), .description = COMPOUND_STRING( - "Fires a strong beam. Deals\n" - "2x damage to Dynamaxed foes."), + "Unleashes core energy.\n" + "2x against Dynamaxed foes."), .effect = EFFECT_DYNAMAX_DOUBLE_DMG, .power = 100, .type = TYPE_DRAGON, @@ -18637,8 +18637,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = { .name = HANDLE_EXPANDED_MOVE_NAME("GlacialLance", "Glacial Lance"), .description = COMPOUND_STRING( - "Strikes by hurling a blizzard-\n" - "cloaked icicle lance at foes."), + "Hurls a blizzard-cloaked\n" + "icicle lance at foes."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 120 : 130, .type = TYPE_ICE, @@ -18659,8 +18659,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = { .name = HANDLE_EXPANDED_MOVE_NAME("AstrlBarrage", "Astral Barrage"), .description = COMPOUND_STRING( - "Strikes by sending a frightful\n" - "amount of ghosts at foes."), + "Sends a frightful amount\n" + "of small ghosts at foes."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_GHOST, @@ -20381,8 +20381,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = { .name = COMPOUND_STRING("Electro Shot"), .description = COMPOUND_STRING( - "Absorbs electricity in one turn,\n" - "then attacks next turn."), + "Gathers electricity, then\n" + "fires a high-voltage shot."), .effect = EFFECT_TWO_TURNS_ATTACK, .power = 130, .type = TYPE_ELECTRIC, @@ -20404,8 +20404,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = { .name = HANDLE_EXPANDED_MOVE_NAME("TeraStarstrm", "Tera Starstorm"), .description = COMPOUND_STRING( - "Damages all opponents if user is\n" - "Stellar form Terapagos."), + "In Terapagos's Stellar\n" + "Form, it hits all foes."), .effect = EFFECT_TERA_STARSTORM, .power = 120, .type = TYPE_NORMAL, @@ -20552,8 +20552,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = { .name = HANDLE_EXPANDED_MOVE_NAME("AllurngVoice", "Alluring Voice"), .description = COMPOUND_STRING( - "Confuses the target if their\n" - "stats were boosted this turn."), + "Confuses foe if its stats\n" + "were boosted this turn."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_FAIRY, diff --git a/src/data/pokemon/species_info/gen_2_families.h b/src/data/pokemon/species_info/gen_2_families.h index 5dcabda292..530c92f411 100644 --- a/src/data/pokemon/species_info/gen_2_families.h +++ b/src/data/pokemon/species_info/gen_2_families.h @@ -3990,8 +3990,8 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .weight = 474, .description = COMPOUND_STRING( "A recent study uncovered that the\n" - "number of segments a\n" - "Dudunsparce's body has is determined by the\n" + "number of segments a Dudunsparce's\n" + "body has is determined by the\n" "Pokémon's genes."), .pokemonScale = 356, .pokemonOffset = 17, diff --git a/src/data/pokemon/species_info/gen_3_families.h b/src/data/pokemon/species_info/gen_3_families.h index 8a23bb05fd..d0bc37e5fc 100644 --- a/src/data/pokemon/species_info/gen_3_families.h +++ b/src/data/pokemon/species_info/gen_3_families.h @@ -4570,9 +4570,9 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .weight = 315, .description = COMPOUND_STRING( "It uses its amped-up willpower to create\n" - "additional arms for itself. The more it has\n" - "trained its spirit, the more realistic and\n" - "dexterous these self-created arms become."), + "additional arms for itself. The more it\n" + "has trained its spirit, the more realistic\n" + "and dexterous these arms become."), .pokemonScale = 298, .pokemonOffset = 5, .trainerScale = 256, diff --git a/src/data/pokemon/species_info/gen_4_families.h b/src/data/pokemon/species_info/gen_4_families.h index c0fdd1ecec..c88dd71ddd 100644 --- a/src/data/pokemon/species_info/gen_4_families.h +++ b/src/data/pokemon/species_info/gen_4_families.h @@ -561,10 +561,10 @@ const struct SpeciesInfo gSpeciesInfoGen4[] = .height = 17, .weight = 845, .description = COMPOUND_STRING( - "The three horns that extend from its beak\n" - "attest to its power. It avoids unnecessary\n" - "disputes, but it will decimate anything\n" - "that threatens its pride."), + "The three horns that extend from its\n" + "beak attest to its power. It avoids\n" + "unnecessary disputes, but it will decimate\n" + "anything that threatens its pride."), .pokemonScale = 259, .pokemonOffset = 0, .trainerScale = 290, @@ -4873,10 +4873,10 @@ const struct SpeciesInfo gSpeciesInfoGen4[] = .height = 3, .weight = 3, .description = COMPOUND_STRING( - "If the convection microwave oven is not\n" - "working properly, then the Rotom inhabiting\n" - "it will become lethargic. It will gleefully\n" - "burn your favorite outfit in mischief."), + "If the convection microwave oven is\n" + "not working properly, then the Rotom\n" + "inhabiting it will become lethargic. It\n" + "makes mischief by turning up the heat."), .pokemonScale = 530, .pokemonOffset = 13, .trainerScale = 256, diff --git a/src/data/pokemon/species_info/gen_5_families.h b/src/data/pokemon/species_info/gen_5_families.h index e8907999fe..50ee5b1fec 100644 --- a/src/data/pokemon/species_info/gen_5_families.h +++ b/src/data/pokemon/species_info/gen_5_families.h @@ -10333,10 +10333,10 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = .height = 14, .weight = 580, .description = COMPOUND_STRING( - "It draws in air through its tail, transforms\n" - "it into fire, and uses it like a tongue.\n" - "They burn through Durant's steel bodies\n" - "and consume their insides."), + "It draws in air through its tail,\n" + "transforms it into fire, and uses it like\n" + "a tongue. They burn through Durant's steel\n" + "bodies and consume their insides."), .pokemonScale = 265, .pokemonOffset = 2, .trainerScale = 262, @@ -11154,10 +11154,10 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = .height = 30, .weight = 610, .description = COMPOUND_STRING( - "It pulverizes foes into\n" - "nothingness with showers of devastatingly\n" - "powerful lightning bolts launched from\n" - "the string of orbs on its tail."), + "It pulverizes foes into nothingness\n" + "with showers of devastatingly\n" + "powerful lightning bolts launched\n" + "from the string of orbs on its tail."), .pokemonScale = 268, .pokemonOffset = 2, .trainerScale = 271, @@ -11348,9 +11348,9 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = .height = 15, .weight = 680, .description = COMPOUND_STRING( - "The energy that comes pouring from its tail\n" - "increases the nutrition in the soil, making\n" - "crops grow to great size. It has been\n" + "The energy that comes pouring from its\n" + "tail increases the nutrition in the soil,\n" + "granting bountiful crops. It has been\n" "hailed as “The Guardian of the Fields.”"), .pokemonScale = 268, .pokemonOffset = 2, diff --git a/src/data/pokemon/species_info/gen_6_families.h b/src/data/pokemon/species_info/gen_6_families.h index 5946ac5c44..ac77faa806 100644 --- a/src/data/pokemon/species_info/gen_6_families.h +++ b/src/data/pokemon/species_info/gen_6_families.h @@ -640,11 +640,7 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .categoryName = _("Ninja"), .height = 15, .weight = 400, - .description = COMPOUND_STRING( - "It appears and vanishes with a ninja's\n" - "grace. It toys with its enemies using swift\n" - "movements, while slicing them with throwing\n" - "stars made of compressed water."), + .description = gGreninjaPokedexText, .pokemonScale = 268, .pokemonOffset = 2, .trainerScale = 271, @@ -1806,8 +1802,8 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = { FLORGES_MISC_INFO(Red, 0), .description = COMPOUND_STRING( - "This Pokémon creates an\n" - "impressive flower garden in its territory. It\n" + "This Pokémon creates an impressive\n" + "flower garden in its territory. It\n" "draws forth the power of the red\n" "flowers around its neck."), }, @@ -4213,8 +4209,8 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .height = 17, .weight = 3341, .description = COMPOUND_STRING( - "It loathes solitude and is\n" - "extremely clingy-it will fume and run riot if\n" + "It loathes solitude and is extremely\n" + "clingy--it will fume and run riot if\n" "those dearest to it ever leave its\n" "side."), .pokemonScale = 261, @@ -5239,9 +5235,9 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .weight = 850, .description = COMPOUND_STRING( "They fly around on moonless nights and\n" - "attack careless prey. The ultrasonic waves\n" - "it emits from its ears can reduce a large\n" - "boulder to pebbles."), + "attack careless prey. The ultrasonic\n" + "waves it emits from its ears can reduce\n" + "a large boulder to pebbles."), .pokemonScale = 268, .pokemonOffset = 2, .trainerScale = 271, diff --git a/src/data/pokemon/species_info/gen_7_families.h b/src/data/pokemon/species_info/gen_7_families.h index dfee119ed5..d69b362104 100644 --- a/src/data/pokemon/species_info/gen_7_families.h +++ b/src/data/pokemon/species_info/gen_7_families.h @@ -3823,8 +3823,8 @@ const struct SpeciesInfo gSpeciesInfoGen7[] = .height = 5, .weight = 700, .description = COMPOUND_STRING( - "It takes control of anyone who puts a hand\n" - "in its mouth, to add to the accumulation\n" + "It takes control of anyone who puts a\n" + "hand in its mouth, to add to the pile\n" "of its sand-mound body. This Pokémon\n" "embodies the grudges of the departed."), .pokemonScale = 432, @@ -6208,10 +6208,10 @@ const struct SpeciesInfo gSpeciesInfoGen7[] = .height = 38, .weight = 4600, .description = COMPOUND_STRING( - "This is its form while it is\n" - "devouring the light of Solgaleo. It pounces\n" - "on foes and then slashes them with\n" - "the claws on its four limbs and back."), + "This is its form while it is devouring\n" + "the light of Solgaleo. It pounces on\n" + "foes and then slashes them with the\n" + "claws on its four limbs and back."), .pokemonScale = 256, .pokemonOffset = 3, .trainerScale = 369, @@ -6974,9 +6974,9 @@ const struct SpeciesInfo gSpeciesInfoGen7[] = .height = 25, .weight = 800, .description = COMPOUND_STRING( - "Revered long ago for its capacity to create\n" - "iron from nothing, for some reason it has\n" - "come back to life after 3,000 years."), + "Revered long ago for its capacity to\n" + "create iron from nothing, for some reason\n" + "it has come back to life after 3,000 years."), .pokemonScale = 257, .pokemonOffset = 10, .trainerScale = 423, diff --git a/src/data/pokemon/species_info/gen_8_families.h b/src/data/pokemon/species_info/gen_8_families.h index 3f8257d966..46057b3847 100644 --- a/src/data/pokemon/species_info/gen_8_families.h +++ b/src/data/pokemon/species_info/gen_8_families.h @@ -885,8 +885,8 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .description = COMPOUND_STRING( "It will bravely challenge any opponent,\n" "no matter how powerful. This Pokémon\n" - "benefits from every battle--even a defeat\n" - "increases its strength a bit."), + "benefits from every battle--even a\n" + "defeat increases its strength a bit."), .pokemonScale = 682, .pokemonOffset = 24, .trainerScale = 256, @@ -1318,8 +1318,8 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .height = 140, .weight = 0, .description = COMPOUND_STRING( - "Its brain has grown to a\n" - "gargantuan size, as has the rest of its body.\n" + "Its brain has grown to a gargantuan\n" + "size, as has the rest of its body.\n" "This Pokémon's intellect and\n" "psychic abilities are overpowering."), .pokemonScale = 491, @@ -3621,9 +3621,9 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .weight = 0, .description = COMPOUND_STRING( "The heat that comes off a\n" - "Gigantamax Centiskorch may destabilize air\n" - "currents. Sometimes it can even\n" - "cause storms."), + "Gigantamax Centiskorch may\n" + "destabilize air currents. Sometimes\n" + "it can even cause storms."), .pokemonScale = 275, .pokemonOffset = 7, .trainerScale = 256, @@ -4294,9 +4294,9 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .weight = 55, .description = COMPOUND_STRING( "Through its nose, it sucks in the\n" - "emanations produced by people and Pokémon\n" - "when they feel annoyed. It thrives off\n" - "this negative energy."), + "emanations produced by people and\n" + "Pokémon when they feel annoyed. It\n" + "thrives off this negative energy."), .pokemonScale = 491, .pokemonOffset = 12, .trainerScale = 256, @@ -5577,9 +5577,9 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .height = 230, .weight = 0, .description = COMPOUND_STRING( - "After this Pokémon has\n" - "Gigantamaxed, its massive nose can utterly\n" - "demolish large structures with a single\n" + "After this Pokémon has Gigantamaxed,\n" + "its massive nose can utterly demolish\n" + "large structures with a single\n" "smashing blow."), .pokemonScale = 275, .pokemonOffset = 7, @@ -6255,8 +6255,8 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .weight = 1100, .description = COMPOUND_STRING( "Known as a legendary hero, this Pokémon\n" - "absorbs metal particles, transforming them\n" - "into a weapon it uses to battle."), + "absorbs metal particles, transforming\n" + "them into a weapon it uses to battle."), .pokemonScale = 275, .pokemonOffset = 7, .trainerScale = 256, diff --git a/src/data/pokemon/species_info/gen_9_families.h b/src/data/pokemon/species_info/gen_9_families.h index 5a616bf4ff..6638676a8d 100644 --- a/src/data/pokemon/species_info/gen_9_families.h +++ b/src/data/pokemon/species_info/gen_9_families.h @@ -1019,8 +1019,8 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = .height = 3, .weight = 25, .description = COMPOUND_STRING( - "The pads of its paws are\n" - "electricity-discharging organs. Pawmi fires\n" + "The pads of its paws are electricity-\n" + "discharging organs. Pawmi fires\n" "electricity from its forepaws while\n" "standing unsteadily on its hind legs."), .pokemonScale = 356, @@ -3939,8 +3939,8 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = .height = 13, .weight = 602, .description = COMPOUND_STRING( - "This Pokémon changes its\n" - "appearance if it hears its allies calling for\n" + "This Pokémon changes its appearance\n" + "if it hears its allies calling for\n" "help. Palafin will never show\n" "anybody its moment of transformation."), .pokemonScale = 356, @@ -4002,8 +4002,8 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = .weight = 974, .description = COMPOUND_STRING( "This Pokémon's ancient genes have\n" - "awakened. It is now so\n" - "extraordinarily strong that it can easily lift a\n" + "awakened. It is now so extraordinarily\n" + "strong that it can easily lift a\n" "cruise ship with one fin."), .pokemonScale = 356, .pokemonOffset = 17, diff --git a/src/data/pokemon/species_info/shared_dex_text.h b/src/data/pokemon/species_info/shared_dex_text.h index 0c591bd811..bf7e12aefb 100644 --- a/src/data/pokemon/species_info/shared_dex_text.h +++ b/src/data/pokemon/species_info/shared_dex_text.h @@ -73,9 +73,9 @@ const u8 gGenesectPokedexText[] = _( // Gen 6 families const u8 gGreninjaPokedexText[] = _( "It appears and vanishes with a ninja's\n" - "grace. It toys with its enemies using swift\n" - "movements, while slicing them with throwing\n" - "stars made of compressed water."); + "grace. It toys with its enemies using\n" + "swift movements, while slicing them with\n" + "throwing stars made of compressed water."); const u8 gScatterbugPokedexText[] = _( "When under attack from bird Pokémon,\n" @@ -207,7 +207,7 @@ const u8 gKommoOPokedexText[] = _( // Gen 8 families const u8 gAlcremieVanillaCreamPokedexText[] = _( "If Alcremie is content, the secreted cream\n" - "from its hands becomes sweeter and richer." + "from its hands becomes sweeter and richer.\n" "When it trusts a Trainer, it will treat\n" "them to berries it's decorated with cream."); @@ -279,8 +279,8 @@ const u8 gOgerponWellspringMaskPokedexText[] = _( const u8 gOgerponHearthflameMaskPokedexText[] = _( "This form is the most aggressive,\n" - "bombarding enemies with the\n" - "intensity of flames blazing within a hearth."); + "bombarding enemies with the intensity\n" + "of flames blazing within a hearth."); const u8 gOgerponCornerstoneMaskPokedexText[] = _( "In this form, it draws on the power\n" diff --git a/src/fldeff_dig.c b/src/fldeff_dig.c index c3ab989cd8..63eb848bf2 100644 --- a/src/fldeff_dig.c +++ b/src/fldeff_dig.c @@ -1,11 +1,13 @@ #include "global.h" #include "braille_puzzles.h" +#include "event_scripts.h" #include "field_effect.h" #include "field_player_avatar.h" #include "fldeff.h" #include "item_use.h" #include "overworld.h" #include "party_menu.h" +#include "script.h" #include "sprite.h" #include "constants/field_effects.h" @@ -31,8 +33,8 @@ bool8 SetUpFieldMove_Dig(void) static void FieldCallback_Dig(void) { Overworld_ResetStateAfterDigEscRope(); - FieldEffectStart(FLDEFF_USE_DIG); gFieldEffectArguments[0] = GetCursorSelectionMonId(); + ScriptContext_SetupScript(EventScript_UseDig); } bool8 FldEff_UseDig(void) @@ -53,7 +55,8 @@ static void StartDigFieldEffect(void) FieldEffectActiveListRemove(FLDEFF_USE_DIG); if (ShouldDoBrailleDigEffect()) { - DoBrailleDigEffect(); + // EventScript_DigSealedChamber handles DoBrailleDigEffect call + ScriptContext_Enable(); } else { diff --git a/src/party_menu.c b/src/party_menu.c index 52525bdff3..703834cc0b 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4672,7 +4672,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task) if (canHeal == TRUE) { if (hp == 0) - AnimatePartySlot(gPartyMenu.slotId, 1); + AnimatePartySlot(gPartyMenu.slotId, 1); PartyMenuModifyHP(taskId, gPartyMenu.slotId, 1, GetMonData(mon, MON_DATA_HP) - hp, Task_DisplayHPRestoredMessage); ResetHPTaskData(taskId, 0, hp); return; diff --git a/src/pokemon.c b/src/pokemon.c index 0583939a85..356ca64ac2 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -60,7 +60,7 @@ #include "constants/weather.h" #include "wild_encounter.h" -#define FRIENDSHIP_EVO_THRESHOLD ((P_FRIENDSHIP_EVO_THRESHOLD >= GEN_9) ? 160 : 220) +#define FRIENDSHIP_EVO_THRESHOLD ((P_FRIENDSHIP_EVO_THRESHOLD >= GEN_8) ? 160 : 220) struct SpeciesItem { diff --git a/src/strings.c b/src/strings.c index 254378d379..4c342d0934 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1750,7 +1750,7 @@ const u8 gText_ElectricFan[] = _("Electric fan"); const u8 gText_LawnMower[] = _("Lawn mower"); const u8 gText_ChangeForm[] = _("Change form"); const u8 gText_ChangeAbility[] = _("Change Ability"); -const u8 gText_TeachWhichMoveToPkmn[] = _("Teach which move to {STR_VAR_1}?"); +const u8 gText_TeachWhichMoveToPkmn[] = _("Teach which move to\n{STR_VAR_1}?"); const u8 gText_MoveRelearnerTeachMoveConfirm[] = _("Teach {STR_VAR_2}?"); const u8 gText_MoveRelearnerPkmnLearnedMove[] = _("{STR_VAR_1} learned\n{STR_VAR_2}!"); const u8 gText_MoveRelearnerPkmnTryingToLearnMove[] = _("{STR_VAR_1} is trying to learn\n{STR_VAR_2}.\pBut {STR_VAR_1} can't learn more\nthan four moves.\pDelete an older move to make\nroom for {STR_VAR_2}?"); diff --git a/test/battle/ability/mummy.c b/test/battle/ability/mummy.c index ed80a178e6..74461ec2ee 100644 --- a/test/battle/ability/mummy.c +++ b/test/battle/ability/mummy.c @@ -70,19 +70,19 @@ SINGLE_BATTLE_TEST("Mummy doesn't replace abilities that can't be suppressed") PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } - PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } - PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } + PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } - PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } - PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } + PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } - PARAMETRIZE { species = SPECIES_CALYREX_SHADOW_RIDER; ability = ABILITY_AS_ONE_SHADOW_RIDER; } - PARAMETRIZE { species = SPECIES_CALYREX_ICE_RIDER; ability = ABILITY_AS_ONE_ICE_RIDER; } GIVEN { PLAYER(SPECIES_YAMASK); diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 3e97ec1f61..59a6d88493 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -378,28 +378,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if mon would AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if it can't deal damage to a mon with Wonder Guard 66% of the time") { - u32 aiOmniscientFlag = 0; - PARAMETRIZE { aiOmniscientFlag = 0; } - PARAMETRIZE { aiOmniscientFlag = AI_FLAG_OMNISCIENT; } PASSES_RANDOMLY(66, 100, RNG_AI_SWITCH_WONDER_GUARD); GIVEN { ASSUME(gSpeciesInfo[SPECIES_SHEDINJA].types[0] == TYPE_BUG); ASSUME(gSpeciesInfo[SPECIES_SHEDINJA].types[1] == TYPE_GHOST); ASSUME(gMovesInfo[MOVE_TACKLE].type == TYPE_NORMAL); ASSUME(gMovesInfo[MOVE_SHADOW_BALL].type == TYPE_GHOST); - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiOmniscientFlag); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_SHEDINJA) { Moves(MOVE_TACKLE); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SHADOW_BALL); } } WHEN { - if(aiOmniscientFlag == 0) { - TURN { MOVE(player, MOVE_TACKLE) ; EXPECT_MOVE(opponent, MOVE_TACKLE); } - TURN { MOVE(player, MOVE_TACKLE) ; EXPECT_SWITCH(opponent, 1); } - } - else { - TURN { MOVE(player, MOVE_TACKLE) ; EXPECT_SWITCH(opponent, 1); } - } - + TURN { MOVE(player, MOVE_TACKLE) ; EXPECT_SWITCH(opponent, 1); } } } diff --git a/test/battle/gimmick/terastal.c b/test/battle/gimmick/terastal.c index 1b50bc4bcc..0484fcd497 100644 --- a/test/battle/gimmick/terastal.c +++ b/test/battle/gimmick/terastal.c @@ -509,6 +509,7 @@ SINGLE_BATTLE_TEST("(TERA) Revelation Dance uses a Stellar-type Pokemon's base t } } +#if B_UPDATED_CONVERSION_2 < GEN_5 SINGLE_BATTLE_TEST("(TERA) Conversion2 fails if last hit by a Stellar-type move") { GIVEN { @@ -526,6 +527,7 @@ SINGLE_BATTLE_TEST("(TERA) Conversion2 fails if last hit by a Stellar-type move" MESSAGE("But it failed!"); } } +#endif SINGLE_BATTLE_TEST("(TERA) Roost does not remove Flying-type ground immunity when Terastallized into the Stellar type") { diff --git a/test/battle/move.c b/test/battle/move.c index 655895da77..ba928e433b 100644 --- a/test/battle/move.c +++ b/test/battle/move.c @@ -222,3 +222,71 @@ SINGLE_BATTLE_TEST("Critical hits ignore negative stat stages", s16 damage) EXPECT_EQ(results[0].damage, results[i].damage); } } + +DOUBLE_BATTLE_TEST("Moves fail if they target the partner but they faint before the move could have been used") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_TACKLE, target: playerRight); MOVE(playerLeft, MOVE_TACKLE, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft); + } +} + +DOUBLE_BATTLE_TEST("Moves do not fail if an alive partner is the target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft); + } +} + +DOUBLE_BATTLE_TEST("Moves fail if they target into a pokemon that was fainted by the previous move") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_HYPER_VOICE].target == MOVE_TARGET_BOTH); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_HYPER_VOICE); + MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); + SEND_OUT(opponentLeft, 2); + SEND_OUT(opponentRight, 3); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight); + } +} + +DOUBLE_BATTLE_TEST("Moves that target the field are not going to fail if one mon fainted by the previous move") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_SURF].target == MOVE_TARGET_FOES_AND_ALLY); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_TACKLE, target: playerRight); MOVE(playerLeft, MOVE_SURF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, playerLeft); + } +} diff --git a/test/battle/move_effect/acupressure.c b/test/battle/move_effect/acupressure.c index e7254485fc..d59a3faee3 100644 --- a/test/battle/move_effect/acupressure.c +++ b/test/battle/move_effect/acupressure.c @@ -8,29 +8,8 @@ TO_DO_BATTLE_TEST("Acupressure fails on the ally if all of its stats are maximiz TO_DO_BATTLE_TEST("Acupressure works on the user if it's behind a Substitute (Gen5+)"); TO_DO_BATTLE_TEST("Acupressure fails on its ally if it's behind a Substitute"); -DOUBLE_BATTLE_TEST("Acupressure works on the ally if the user targeted itself but switched positions via Ally Switch") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_WYNAUT); - OPPONENT(SPECIES_KADABRA); - OPPONENT(SPECIES_ABRA); - } WHEN { - TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(playerRight, MOVE_ACUPRESSURE, target:playerRight); } - } SCENE { - MESSAGE("Wobbuffet used Ally Switch!"); - ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft); - MESSAGE("Wobbuffet and Wynaut switched places!"); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); - NOT MESSAGE("But it failed!"); - } -} - DOUBLE_BATTLE_TEST("Acupressure fails on the user if it targeted its ally but switched positions via Ally Switch") { - KNOWN_FAILING; // Tested in Gen 5, Acupressure fails here GIVEN { PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WYNAUT); diff --git a/test/battle/move_effect/conversion_2.c b/test/battle/move_effect/conversion_2.c index 2e81212ef1..6c2d4d7f54 100644 --- a/test/battle/move_effect/conversion_2.c +++ b/test/battle/move_effect/conversion_2.c @@ -1,14 +1,207 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type that resists the last move that hit the user (Gen 3-4)"); -TO_DO_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type that resists the last move used by the target (Gen 5+)"); -TO_DO_BATTLE_TEST("Conversion 2's type change considers the type of moves called by other moves"); -TO_DO_BATTLE_TEST("Conversion 2's type change considers dynamic type moves"); // Eg. Weather Ball -TO_DO_BATTLE_TEST("Conversion 2's type change considers move types changed by Normalize and Electrify"); -TO_DO_BATTLE_TEST("Conversion 2's type change considers move types changed by Normalize"); -TO_DO_BATTLE_TEST("Conversion 2's type change considers Struggle to be Normal type (Gen 3-4)"); -TO_DO_BATTLE_TEST("Conversion 2 fails if the move used is of typeless damage (Gen 5+)"); -TO_DO_BATTLE_TEST("Conversion 2's type change considers status moves (Gen 5+)"); TO_DO_BATTLE_TEST("Conversion 2's type change considers Inverse Battles"); -TO_DO_BATTLE_TEST("Conversion 2 fails if the move used is Stellar Type"); + +#if B_UPDATED_CONVERSION_2 < GEN_5 +SINGLE_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type that resists the last move that hit the user (Gen 3-4)") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_OMINOUS_WIND); MOVE(opponent, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Wobbuffet used Ominous Wind!"); + // turn 1 + ONE_OF { + MESSAGE("Foe Wobbuffet transformed into the Normal type!"); + MESSAGE("Foe Wobbuffet transformed into the Dark type!"); + } + } +} + +SINGLE_BATTLE_TEST("Conversion 2's type change considers Struggle to be Normal type (Gen 3-4)") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_STRUGGLE); } + TURN { MOVE(player, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Foe Wobbuffet used Struggle!"); + // turn 2 + ONE_OF { + MESSAGE("Wobbuffet transformed into the Steel type!"); + MESSAGE("Wobbuffet transformed into the Rock type!"); + MESSAGE("Wobbuffet transformed into the Ghost type!"); + } + } +} +#endif + +#if B_UPDATED_CONVERSION_2 >= GEN_5 +SINGLE_BATTLE_TEST("Conversion 2 randomly changes the type of the user to a type that resists the last used target's move (Gen 5+)") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_OMINOUS_WIND); MOVE(opponent, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Wobbuffet used Ominous Wind!"); + // turn 1 + ONE_OF { + MESSAGE("Foe Wobbuffet transformed into the Normal type!"); + MESSAGE("Foe Wobbuffet transformed into the Dark type!"); + } + } +} + +SINGLE_BATTLE_TEST("Conversion 2's type change considers status moves (Gen 5+)") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CURSE); } + TURN { MOVE(player, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Foe Wobbuffet used Curse!"); + // turn 2 + ONE_OF { + MESSAGE("Wobbuffet transformed into the Normal type!"); + MESSAGE("Wobbuffet transformed into the Dark type!"); + } + } +} + +SINGLE_BATTLE_TEST("Conversion 2's type change considers the type of moves called by other moves") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_OMINOUS_WIND); MOVE(opponent, MOVE_MIRROR_MOVE); } + TURN { MOVE(player, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Foe Wobbuffet used Mirror Move!"); + // turn 2 + ONE_OF { + MESSAGE("Wobbuffet transformed into the Normal type!"); + MESSAGE("Wobbuffet transformed into the Dark type!"); + } + } +} + +SINGLE_BATTLE_TEST("Conversion 2's type change considers dynamic type moves") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_HAIL); MOVE(opponent, MOVE_WEATHER_BALL); } + TURN { MOVE(player, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Foe Wobbuffet used Weather Ball!"); + // turn 2 + ONE_OF { + MESSAGE("Wobbuffet transformed into the Steel type!"); + MESSAGE("Wobbuffet transformed into the Fire type!"); + MESSAGE("Wobbuffet transformed into the Water type!"); + MESSAGE("Wobbuffet transformed into the Ice type!"); + } + } +} + +SINGLE_BATTLE_TEST("Conversion 2's type change considers move types changed by Normalize and Electrify") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NORMALIZE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIFY); MOVE(opponent, MOVE_POUND); } + TURN { MOVE(player, MOVE_CONVERSION_2); } + TURN { MOVE(player, MOVE_WATER_GUN); MOVE(opponent, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Wobbuffet used Electrify!"); + MESSAGE("Foe Wobbuffet used Pound!"); + // turn 2 + ONE_OF { + MESSAGE("Wobbuffet transformed into the Ground type!"); + MESSAGE("Wobbuffet transformed into the Dragon type!"); + MESSAGE("Wobbuffet transformed into the Grass type!"); + MESSAGE("Wobbuffet transformed into the Electric type!"); + } + // turn 3 + MESSAGE("Wobbuffet used Water Gun!"); + ONE_OF { + MESSAGE("Foe Wobbuffet transformed into the Steel type!"); + MESSAGE("Foe Wobbuffet transformed into the Rock type!"); + MESSAGE("Foe Wobbuffet transformed into the Ghost type!"); + } + } +} + +SINGLE_BATTLE_TEST("Conversion 2's type change fails targeting Struggle (Gen 5+)") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_STRUGGLE); } + TURN { MOVE(player, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Foe Wobbuffet used Struggle!"); + // turn 2 + MESSAGE("Wobbuffet used Conversion 2!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Conversion 2 fails if the move used is of typeless damage (Gen 5+)") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ENTEI); + } WHEN { + TURN { MOVE(opponent, MOVE_BURN_UP); } + TURN { MOVE(opponent, MOVE_REVELATION_DANCE); } + TURN { MOVE(player, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Foe Entei used Burn Up!"); + // turn 2 + MESSAGE("Foe Entei used Revelation Dance!"); + // turn 3 + MESSAGE("Wobbuffet used Conversion 2!"); + MESSAGE("But it failed!"); + } +} +#endif + +SINGLE_BATTLE_TEST("Conversion 2 fails if the targeted move is Stellar Type") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { TeraType(TYPE_STELLAR); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TERA_BLAST, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_CONVERSION_2); } + } SCENE { + // turn 1 + MESSAGE("Wobbuffet used Tera Blast!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TERA_BLAST, player); + // turn 1 + MESSAGE("Foe Wobbuffet used Conversion 2!"); + MESSAGE("But it failed!"); + } +} diff --git a/test/battle/move_effect/doodle.c b/test/battle/move_effect/doodle.c index bf7e208646..ba7729a895 100644 --- a/test/battle/move_effect/doodle.c +++ b/test/battle/move_effect/doodle.c @@ -35,8 +35,8 @@ DOUBLE_BATTLE_TEST("Doodle can't copy a banned ability") } WHEN { TURN { MOVE(playerLeft, MOVE_DOODLE, target: opponentLeft); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, playerLeft); NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, playerLeft); MESSAGE("Wynaut copied Foe Great Tusk's Protosynthesis!"); MESSAGE("Wynaut copied Foe Great Tusk's Protosynthesis!"); } @@ -56,7 +56,7 @@ DOUBLE_BATTLE_TEST("Doodle fails if user has a banned Ability") } WHEN { TURN { MOVE(playerLeft, MOVE_DOODLE, target: opponentLeft); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, playerLeft); MESSAGE("But it failed!"); } THEN { EXPECT(playerLeft->ability == ABILITY_GULP_MISSILE); @@ -74,10 +74,44 @@ DOUBLE_BATTLE_TEST("Doodle fails if partner has a banned Ability") } WHEN { TURN { MOVE(playerLeft, MOVE_DOODLE, target: opponentLeft); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, playerLeft); MESSAGE("But it failed!"); } THEN { EXPECT(playerLeft->ability == ABILITY_SHADOW_TAG); EXPECT(playerRight->ability == ABILITY_GULP_MISSILE); } } + +DOUBLE_BATTLE_TEST("Doodle fails if ally's ability can't be suppressed") +{ + u32 species, ability; + + PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } + PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; } + PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } + PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } + PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } + PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } + PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } + PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } + PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } + PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } + PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_DOODLE, target: playerLeft); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, opponentLeft); + MESSAGE("But it failed!"); + } +} diff --git a/test/battle/move_effect/role_play.c b/test/battle/move_effect/role_play.c index 46452ec3ff..ab0d801ee9 100644 --- a/test/battle/move_effect/role_play.c +++ b/test/battle/move_effect/role_play.c @@ -1,25 +1,65 @@ #include "global.h" #include "test/battle.h" -// Technically also covers Skill Swap and Doodle since both moves use the same command as Role Play ASSUMPTIONS { ASSUME(gMovesInfo[MOVE_ROLE_PLAY].effect == EFFECT_ROLE_PLAY); } -SINGLE_BATTLE_TEST("Role Play fails if target has a banned ability") +SINGLE_BATTLE_TEST("Role Play copies target's ability") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + }WHEN { + TURN { MOVE(player, MOVE_ROLE_PLAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROLE_PLAY, player); + ABILITY_POPUP(player, ABILITY_TELEPATHY); + } THEN { + EXPECT_EQ(player->ability, ABILITY_BLAZE); + EXPECT_EQ(opponent->ability, ABILITY_BLAZE); + } +} + +DOUBLE_BATTLE_TEST("Role Play copies target's current ability even if it changed during that turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } + OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_ROLE_PLAY, target: opponentLeft); MOVE(opponentRight, MOVE_ROLE_PLAY, target: playerLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROLE_PLAY, playerLeft); + ABILITY_POPUP(playerLeft, ABILITY_TELEPATHY); + if (MOVE_ROLE_PLAY == MOVE_DOODLE) + ABILITY_POPUP(playerRight, ABILITY_BLAZE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROLE_PLAY, opponentRight); + ABILITY_POPUP(opponentRight, ABILITY_TORRENT); + NOT ABILITY_POPUP(opponentLeft, ABILITY_OVERGROW); // Already has ability (Doodle) + } THEN { + EXPECT_EQ(playerLeft->ability, ABILITY_OVERGROW); + if (MOVE_ROLE_PLAY == MOVE_DOODLE) + EXPECT_EQ(playerRight->ability, ABILITY_OVERGROW); + EXPECT_EQ(opponentLeft->ability, ABILITY_OVERGROW); + EXPECT_EQ(opponentRight->ability, ABILITY_OVERGROW); + } +} + +SINGLE_BATTLE_TEST("Role Play and Doodle fail if target's ability can't be copied'") { u32 species, ability; PARAMETRIZE { species = SPECIES_SHEDINJA; ability = ABILITY_WONDER_GUARD; } PARAMETRIZE { species = SPECIES_CASTFORM; ability = ABILITY_FORECAST; } - PARAMETRIZE { species = SPECIES_CHERRIM; ability = ABILITY_FLOWER_GIFT; } PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } + PARAMETRIZE { species = SPECIES_CHERRIM; ability = ABILITY_FLOWER_GIFT; } PARAMETRIZE { species = SPECIES_ZORUA; ability = ABILITY_ILLUSION; } PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; } - PARAMETRIZE { species = SPECIES_DITTO; ability = ABILITY_IMPOSTER; } PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } - PARAMETRIZE { species = SPECIES_MUK_ALOLAN; ability = ABILITY_POWER_OF_ALCHEMY; } + PARAMETRIZE { species = SPECIES_MUK_ALOLA; ability = ABILITY_POWER_OF_ALCHEMY; } PARAMETRIZE { species = SPECIES_PASSIMIAN; ability = ABILITY_RECEIVER; } PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } @@ -38,29 +78,34 @@ SINGLE_BATTLE_TEST("Role Play fails if target has a banned ability") PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } OPPONENT(species) { Ability(ability); } } WHEN { - TURN { MOVE(player,MOVE_ROLE_PLAY); } + TURN { MOVE(player, MOVE_ROLE_PLAY); } + TURN { MOVE(player, MOVE_DOODLE); } } SCENE { NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ROLE_PLAY, player); MESSAGE("But it failed!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, player); + MESSAGE("But it failed!"); } } -SINGLE_BATTLE_TEST("Role Play fails if user has a banned ability") +SINGLE_BATTLE_TEST("Role Play fails if user's ability can't be suppressed") { u32 species, ability; PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; } PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } - PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } - PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } + PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } - PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } - PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } - PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } + PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } @@ -68,9 +113,12 @@ SINGLE_BATTLE_TEST("Role Play fails if user has a banned ability") PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } OPPONENT(species) { Ability(ability); } } WHEN { - TURN { MOVE(opponent,MOVE_ROLE_PLAY); } + TURN { MOVE(opponent, MOVE_ROLE_PLAY); } + TURN { MOVE(opponent, MOVE_DOODLE); } } SCENE { NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ROLE_PLAY, opponent); MESSAGE("But it failed!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, opponent); + MESSAGE("But it failed!"); } } diff --git a/test/battle/move_effect/simple_beam.c b/test/battle/move_effect/simple_beam.c new file mode 100644 index 0000000000..e91bf0b8ce --- /dev/null +++ b/test/battle/move_effect/simple_beam.c @@ -0,0 +1,74 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_SIMPLE_BEAM].effect == EFFECT_SIMPLE_BEAM); +} + +SINGLE_BATTLE_TEST("Simple Beam replaces target's ability with Simple") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + }WHEN { + TURN { MOVE(player, MOVE_SIMPLE_BEAM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, player); + ABILITY_POPUP(opponent, ABILITY_BLAZE); + } THEN { + EXPECT_EQ(opponent->ability, ABILITY_SIMPLE); + } +} + +DOUBLE_BATTLE_TEST("Simple Beam fails if the target already has Simple") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } + OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SIMPLE_BEAM, target: opponentLeft); MOVE(playerRight, MOVE_SIMPLE_BEAM, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_OVERGROW); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, playerRight); + ABILITY_POPUP(opponentLeft, ABILITY_SIMPLE); + } + } THEN { + EXPECT_EQ(opponentLeft->ability, ABILITY_SIMPLE); + } +} + +SINGLE_BATTLE_TEST("Simple Beam fails if target has an ability that can't be overwritten") +{ + u32 species, ability; + + PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } + PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } + PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } + PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } + PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } + PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } + PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } + PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } + PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } + PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SIMPLE_BEAM); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SIMPLE_BEAM, player); + MESSAGE("But it failed!"); + } +} diff --git a/test/battle/move_effect/skill_swap.c b/test/battle/move_effect/skill_swap.c new file mode 100644 index 0000000000..5f2196fe7e --- /dev/null +++ b/test/battle/move_effect/skill_swap.c @@ -0,0 +1,111 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_SKILL_SWAP].effect == EFFECT_SKILL_SWAP); +} + +SINGLE_BATTLE_TEST("Skill Swap swaps user and target's abilities") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + }WHEN { + TURN { MOVE(player, MOVE_SKILL_SWAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player); + ABILITY_POPUP(player, ABILITY_TELEPATHY); + ABILITY_POPUP(opponent, ABILITY_BLAZE); + } THEN { + EXPECT_EQ(player->ability, ABILITY_BLAZE); + EXPECT_EQ(opponent->ability, ABILITY_TELEPATHY); + } +} + +DOUBLE_BATTLE_TEST("Skill Swap only swaps user's ability with target's ability") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } + OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SKILL_SWAP, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, playerLeft); + ABILITY_POPUP(playerLeft, ABILITY_TELEPATHY); + ABILITY_POPUP(opponentLeft, ABILITY_OVERGROW); + } THEN { + EXPECT_EQ(playerLeft->ability, ABILITY_OVERGROW); + EXPECT_EQ(playerRight->ability, ABILITY_BLAZE); + EXPECT_EQ(opponentLeft->ability, ABILITY_TELEPATHY); + EXPECT_EQ(opponentRight->ability, ABILITY_TORRENT); + } +} + +DOUBLE_BATTLE_TEST("Skill Swap doesn't display ability popups when swapping with an ally") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } + OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SKILL_SWAP, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, playerLeft); + NONE_OF { + ABILITY_POPUP(playerLeft, ABILITY_TELEPATHY); + ABILITY_POPUP(playerRight, ABILITY_BLAZE); + } + } THEN { + EXPECT_EQ(playerLeft->ability, ABILITY_BLAZE); + EXPECT_EQ(playerRight->ability, ABILITY_TELEPATHY); + } +} + +SINGLE_BATTLE_TEST("Skill Swap fails if user or target has an ability that can't be swapped") +{ + u32 species, ability; + + PARAMETRIZE { species = SPECIES_SHEDINJA; ability = ABILITY_WONDER_GUARD; } + PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } + PARAMETRIZE { species = SPECIES_ZORUA; ability = ABILITY_ILLUSION; } + PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; } + PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } + PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } + PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } + PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } + PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } + PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } + PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_KOFFING; ability = ABILITY_NEUTRALIZING_GAS; } + PARAMETRIZE { species = SPECIES_MORPEKO; ability = ABILITY_HUNGER_SWITCH; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } + PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } + PARAMETRIZE { species = SPECIES_GREAT_TUSK; ability = ABILITY_PROTOSYNTHESIS; } + PARAMETRIZE { species = SPECIES_IRON_TREADS; ability = ABILITY_QUARK_DRIVE; } + PARAMETRIZE { species = SPECIES_OGERPON_TEAL_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_TEAL_MASK; } + PARAMETRIZE { species = SPECIES_OGERPON_HEARTHFLAME_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK; } + PARAMETRIZE { species = SPECIES_OGERPON_WELLSPRING_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_WELLSPRING_MASK; } + PARAMETRIZE { species = SPECIES_OGERPON_CORNERSTONE_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK; } + PARAMETRIZE { species = SPECIES_TERAPAGOS_TERASTAL; ability = ABILITY_TERA_SHELL; } + PARAMETRIZE { species = SPECIES_TERAPAGOS_STELLAR; ability = ABILITY_TERAFORM_ZERO; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SKILL_SWAP); MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player); + MESSAGE("But it failed!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + MESSAGE("But it failed!"); + } +} diff --git a/test/battle/move_effect/worry_seed.c b/test/battle/move_effect/worry_seed.c new file mode 100644 index 0000000000..3e74c883e7 --- /dev/null +++ b/test/battle/move_effect/worry_seed.c @@ -0,0 +1,74 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_WORRY_SEED].effect == EFFECT_WORRY_SEED); +} + +SINGLE_BATTLE_TEST("Worry Seed replaces target's ability with Insomnia") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + }WHEN { + TURN { MOVE(player, MOVE_WORRY_SEED); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, player); + ABILITY_POPUP(opponent, ABILITY_BLAZE); + } THEN { + EXPECT_EQ(opponent->ability, ABILITY_INSOMNIA); + } +} + +DOUBLE_BATTLE_TEST("Worry Seed fails if the target already has Insomnia") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); } + OPPONENT(SPECIES_BULBASAUR) { Ability(ABILITY_OVERGROW); } + OPPONENT(SPECIES_SQUIRTLE) { Ability(ABILITY_TORRENT); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_WORRY_SEED, target: opponentLeft); MOVE(playerRight, MOVE_WORRY_SEED, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_OVERGROW); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, playerRight); + ABILITY_POPUP(opponentLeft, ABILITY_INSOMNIA); + } + } THEN { + EXPECT_EQ(opponentLeft->ability, ABILITY_INSOMNIA); + } +} + +SINGLE_BATTLE_TEST("Worry Seed fails if target has an ability that can't be overwritten") +{ + u32 species, ability; + + PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } + PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } + PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } + PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } + PARAMETRIZE { species = SPECIES_MIMIKYU; ability = ABILITY_DISGUISE; } + PARAMETRIZE { species = SPECIES_GRENINJA_BATTLE_BOND; ability = ABILITY_BATTLE_BOND; } + PARAMETRIZE { species = SPECIES_ZYGARDE; ability = ABILITY_POWER_CONSTRUCT; } + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_SILVALLY; ability = ABILITY_RKS_SYSTEM; } + PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; } + PARAMETRIZE { species = SPECIES_EISCUE; ability = ABILITY_ICE_FACE; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; } + PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_WORRY_SEED); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, player); + MESSAGE("But it failed!"); + } +} diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 676054ceb6..d870d4ae41 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -567,19 +567,19 @@ void TestRunner_Battle_RecordAbilityPopUp(u32 battlerId, u32 ability) s32 match; struct QueuedEvent *event; - if (DATA.queuedEvent == DATA.queuedEventsCount) + if (DATA.trial.queuedEvent == DATA.queuedEventsCount) return; - event = &DATA.queuedEvents[DATA.queuedEvent]; + event = &DATA.queuedEvents[DATA.trial.queuedEvent]; switch (event->groupType) { case QUEUE_GROUP_NONE: case QUEUE_GROUP_ONE_OF: - if (TryAbilityPopUp(DATA.queuedEvent, event->groupSize, battlerId, ability) != -1) - DATA.queuedEvent += event->groupSize; + if (TryAbilityPopUp(DATA.trial.queuedEvent, event->groupSize, battlerId, ability) != -1) + DATA.trial.queuedEvent += event->groupSize; break; case QUEUE_GROUP_NONE_OF: - queuedEvent = DATA.queuedEvent; + queuedEvent = DATA.trial.queuedEvent; do { if ((match = TryAbilityPopUp(queuedEvent, event->groupSize, battlerId, ability)) != -1) @@ -598,7 +598,7 @@ void TestRunner_Battle_RecordAbilityPopUp(u32 battlerId, u32 ability) continue; if (TryAbilityPopUp(queuedEvent, event->groupSize, battlerId, ability) != -1) - DATA.queuedEvent = queuedEvent + event->groupSize; + DATA.trial.queuedEvent = queuedEvent + event->groupSize; } while (FALSE); break; } @@ -630,19 +630,19 @@ void TestRunner_Battle_RecordAnimation(u32 animType, u32 animId) s32 match; struct QueuedEvent *event; - if (DATA.queuedEvent == DATA.queuedEventsCount) + if (DATA.trial.queuedEvent == DATA.queuedEventsCount) return; - event = &DATA.queuedEvents[DATA.queuedEvent]; + event = &DATA.queuedEvents[DATA.trial.queuedEvent]; switch (event->groupType) { case QUEUE_GROUP_NONE: case QUEUE_GROUP_ONE_OF: - if (TryAnimation(DATA.queuedEvent, event->groupSize, animType, animId) != -1) - DATA.queuedEvent += event->groupSize; + if (TryAnimation(DATA.trial.queuedEvent, event->groupSize, animType, animId) != -1) + DATA.trial.queuedEvent += event->groupSize; break; case QUEUE_GROUP_NONE_OF: - queuedEvent = DATA.queuedEvent; + queuedEvent = DATA.trial.queuedEvent; do { if ((match = TryAnimation(queuedEvent, event->groupSize, animType, animId)) != -1) @@ -661,7 +661,7 @@ void TestRunner_Battle_RecordAnimation(u32 animType, u32 animId) continue; if (TryAnimation(queuedEvent, event->groupSize, animType, animId) != -1) - DATA.queuedEvent = queuedEvent + event->groupSize; + DATA.trial.queuedEvent = queuedEvent + event->groupSize; } while (FALSE); break; } @@ -720,19 +720,19 @@ void TestRunner_Battle_RecordHP(u32 battlerId, u32 oldHP, u32 newHP) s32 match; struct QueuedEvent *event; - if (DATA.queuedEvent == DATA.queuedEventsCount) + if (DATA.trial.queuedEvent == DATA.queuedEventsCount) return; - event = &DATA.queuedEvents[DATA.queuedEvent]; + event = &DATA.queuedEvents[DATA.trial.queuedEvent]; switch (event->groupType) { case QUEUE_GROUP_NONE: case QUEUE_GROUP_ONE_OF: - if (TryHP(DATA.queuedEvent, event->groupSize, battlerId, oldHP, newHP) != -1) - DATA.queuedEvent += event->groupSize; + if (TryHP(DATA.trial.queuedEvent, event->groupSize, battlerId, oldHP, newHP) != -1) + DATA.trial.queuedEvent += event->groupSize; break; case QUEUE_GROUP_NONE_OF: - queuedEvent = DATA.queuedEvent; + queuedEvent = DATA.trial.queuedEvent; do { if ((match = TryHP(queuedEvent, event->groupSize, battlerId, oldHP, newHP)) != -1) @@ -751,7 +751,7 @@ void TestRunner_Battle_RecordHP(u32 battlerId, u32 oldHP, u32 newHP) continue; if (TryHP(queuedEvent, event->groupSize, battlerId, oldHP, newHP) != -1) - DATA.queuedEvent = queuedEvent + event->groupSize; + DATA.trial.queuedEvent = queuedEvent + event->groupSize; } while (FALSE); break; } @@ -782,7 +782,7 @@ static u32 CountAiExpectMoves(struct ExpectedAIAction *expectedAction, u32 battl void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) { const char *filename = gTestRunnerState.test->filename; - u32 id = DATA.aiActionsPlayed[battlerId]; + u32 id = DATA.trial.aiActionsPlayed[battlerId]; struct ExpectedAIAction *expectedAction = &DATA.expectedAiActions[battlerId][id]; if (!expectedAction->actionSet) @@ -845,13 +845,13 @@ void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) } // Turn passed, clear logs from the turn ClearAiLog(battlerId); - DATA.aiActionsPlayed[battlerId]++; + DATA.trial.aiActionsPlayed[battlerId]++; } void TestRunner_Battle_CheckSwitch(u32 battlerId, u32 partyIndex) { const char *filename = gTestRunnerState.test->filename; - u32 id = DATA.aiActionsPlayed[battlerId]; + u32 id = DATA.trial.aiActionsPlayed[battlerId]; struct ExpectedAIAction *expectedAction = &DATA.expectedAiActions[battlerId][id]; if (!expectedAction->actionSet) @@ -865,7 +865,7 @@ void TestRunner_Battle_CheckSwitch(u32 battlerId, u32 partyIndex) if (expectedAction->target != partyIndex) Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Expected partyIndex %d, got %d", filename, expectedAction->sourceLine, expectedAction->target, partyIndex); } - DATA.aiActionsPlayed[battlerId]++; + DATA.trial.aiActionsPlayed[battlerId]++; } void TestRunner_Battle_InvalidNoHPMon(u32 battlerId, u32 partyIndex) @@ -1029,7 +1029,7 @@ void TestRunner_Battle_CheckAiMoveScores(u32 battlerId) } // We need to make sure that the expected move has the best score. We have to rule out a situation where the expected move is used, but it has the same number of points as some other moves. - aiAction = &DATA.expectedAiActions[battlerId][DATA.aiActionsPlayed[battlerId]]; + aiAction = &DATA.expectedAiActions[battlerId][DATA.trial.aiActionsPlayed[battlerId]]; if (aiAction->actionSet && !aiAction->pass) { s32 target = aiAction->target; @@ -1102,19 +1102,19 @@ void TestRunner_Battle_RecordExp(u32 battlerId, u32 oldExp, u32 newExp) s32 match; struct QueuedEvent *event; - if (DATA.queuedEvent == DATA.queuedEventsCount) + if (DATA.trial.queuedEvent == DATA.queuedEventsCount) return; - event = &DATA.queuedEvents[DATA.queuedEvent]; + event = &DATA.queuedEvents[DATA.trial.queuedEvent]; switch (event->groupType) { case QUEUE_GROUP_NONE: case QUEUE_GROUP_ONE_OF: - if (TryExp(DATA.queuedEvent, event->groupSize, battlerId, oldExp, newExp) != -1) - DATA.queuedEvent += event->groupSize; + if (TryExp(DATA.trial.queuedEvent, event->groupSize, battlerId, oldExp, newExp) != -1) + DATA.trial.queuedEvent += event->groupSize; break; case QUEUE_GROUP_NONE_OF: - queuedEvent = DATA.queuedEvent; + queuedEvent = DATA.trial.queuedEvent; do { if ((match = TryExp(queuedEvent, event->groupSize, battlerId, oldExp, newExp)) != -1) @@ -1133,7 +1133,7 @@ void TestRunner_Battle_RecordExp(u32 battlerId, u32 oldExp, u32 newExp) continue; if (TryExp(queuedEvent, event->groupSize, battlerId, oldExp, newExp) != -1) - DATA.queuedEvent = queuedEvent + event->groupSize; + DATA.trial.queuedEvent = queuedEvent + event->groupSize; } while (FALSE); break; } @@ -1191,19 +1191,19 @@ void TestRunner_Battle_RecordMessage(const u8 *string) s32 match; struct QueuedEvent *event; - if (DATA.queuedEvent == DATA.queuedEventsCount) + if (DATA.trial.queuedEvent == DATA.queuedEventsCount) return; - event = &DATA.queuedEvents[DATA.queuedEvent]; + event = &DATA.queuedEvents[DATA.trial.queuedEvent]; switch (event->groupType) { case QUEUE_GROUP_NONE: case QUEUE_GROUP_ONE_OF: - if (TryMessage(DATA.queuedEvent, event->groupSize, string) != -1) - DATA.queuedEvent += event->groupSize; + if (TryMessage(DATA.trial.queuedEvent, event->groupSize, string) != -1) + DATA.trial.queuedEvent += event->groupSize; break; case QUEUE_GROUP_NONE_OF: - queuedEvent = DATA.queuedEvent; + queuedEvent = DATA.trial.queuedEvent; do { if ((match = TryMessage(queuedEvent, event->groupSize, string)) != -1) @@ -1222,7 +1222,7 @@ void TestRunner_Battle_RecordMessage(const u8 *string) continue; if (TryMessage(queuedEvent, event->groupSize, string) != -1) - DATA.queuedEvent = queuedEvent + event->groupSize; + DATA.trial.queuedEvent = queuedEvent + event->groupSize; } while (FALSE); break; } @@ -1256,19 +1256,19 @@ void TestRunner_Battle_RecordStatus1(u32 battlerId, u32 status1) s32 match; struct QueuedEvent *event; - if (DATA.queuedEvent == DATA.queuedEventsCount) + if (DATA.trial.queuedEvent == DATA.queuedEventsCount) return; - event = &DATA.queuedEvents[DATA.queuedEvent]; + event = &DATA.queuedEvents[DATA.trial.queuedEvent]; switch (event->groupType) { case QUEUE_GROUP_NONE: case QUEUE_GROUP_ONE_OF: - if (TryStatus(DATA.queuedEvent, event->groupSize, battlerId, status1) != -1) - DATA.queuedEvent += event->groupSize; + if (TryStatus(DATA.trial.queuedEvent, event->groupSize, battlerId, status1) != -1) + DATA.trial.queuedEvent += event->groupSize; break; case QUEUE_GROUP_NONE_OF: - queuedEvent = DATA.queuedEvent; + queuedEvent = DATA.trial.queuedEvent; do { if ((match = TryStatus(queuedEvent, event->groupSize, battlerId, status1)) != -1) @@ -1287,7 +1287,7 @@ void TestRunner_Battle_RecordStatus1(u32 battlerId, u32 status1) continue; if (TryStatus(queuedEvent, event->groupSize, battlerId, status1) != -1) - DATA.queuedEvent = queuedEvent + event->groupSize; + DATA.trial.queuedEvent = queuedEvent + event->groupSize; } while (FALSE); break; } @@ -1307,22 +1307,22 @@ void TestRunner_Battle_AfterLastTurn(void) { const struct BattleTest *test = GetBattleTest(); - if (DATA.turns - 1 != DATA.lastActionTurn) + if (DATA.turns - 1 != DATA.trial.lastActionTurn) { const char *filename = gTestRunnerState.test->filename; - Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: %d TURNs specified, but %d ran", filename, SourceLine(0), DATA.turns, DATA.lastActionTurn + 1); + Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: %d TURNs specified, but %d ran", filename, SourceLine(0), DATA.turns, DATA.trial.lastActionTurn + 1); } - while (DATA.queuedEvent < DATA.queuedEventsCount - && DATA.queuedEvents[DATA.queuedEvent].groupType == QUEUE_GROUP_NONE_OF) + while (DATA.trial.queuedEvent < DATA.queuedEventsCount + && DATA.queuedEvents[DATA.trial.queuedEvent].groupType == QUEUE_GROUP_NONE_OF) { - DATA.queuedEvent += DATA.queuedEvents[DATA.queuedEvent].groupSize; + DATA.trial.queuedEvent += DATA.queuedEvents[DATA.trial.queuedEvent].groupSize; } - if (DATA.queuedEvent != DATA.queuedEventsCount) + if (DATA.trial.queuedEvent != DATA.queuedEventsCount) { const char *filename = gTestRunnerState.test->filename; - u32 line = SourceLine(DATA.queuedEvents[DATA.queuedEvent].sourceLineOffset); - const char *macro = sEventTypeMacros[DATA.queuedEvents[DATA.queuedEvent].type]; + u32 line = SourceLine(DATA.queuedEvents[DATA.trial.queuedEvent].sourceLineOffset); + const char *macro = sEventTypeMacros[DATA.queuedEvents[DATA.trial.queuedEvent].type]; Test_ExitWithResult(TEST_RESULT_FAIL, line, ":L%s:%d: Unmatched %s", filename, line, macro); } @@ -1395,8 +1395,7 @@ static void CB2_BattleTest_NextTrial(void) PrintTestName(); gTestRunnerState.result = TEST_RESULT_PASS; DATA.recordedBattle.rngSeed = MakeRngValue(STATE->runTrial); - DATA.queuedEvent = 0; - DATA.lastActionTurn = 0; + memset(&DATA.trial, 0, sizeof(DATA.trial)); SetVariablesForRecordedBattle(&DATA.recordedBattle); SetMainCallback2(CB2_InitBattle); } @@ -1892,7 +1891,7 @@ void TestRunner_Battle_CheckBattleRecordActionType(u32 battlerId, u32 recordInde if (DATA.battleRecordTypes[battlerId][recordIndex] != RECORDED_BYTE) { - DATA.lastActionTurn = gBattleResults.battleTurnCounter; + DATA.trial.lastActionTurn = gBattleResults.battleTurnCounter; if (actionType != DATA.battleRecordTypes[battlerId][recordIndex]) { @@ -1926,7 +1925,7 @@ void TestRunner_Battle_CheckBattleRecordActionType(u32 battlerId, u32 recordInde } else { - if (DATA.lastActionTurn == gBattleResults.battleTurnCounter) + if (DATA.trial.lastActionTurn == gBattleResults.battleTurnCounter) { const char *filename = gTestRunnerState.test->filename; Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: TURN %d incomplete", filename, SourceLine(0), gBattleResults.battleTurnCounter + 1); diff --git a/test/text.c b/test/text.c index 0e6900edad..7713784198 100644 --- a/test/text.c +++ b/test/text.c @@ -79,6 +79,18 @@ TEST("Move names fit on Move Relearner Screen") EXPECT_LE(GetStringWidth(fontId, gMovesInfo[move].name, 0), widthPx); } +TEST("Move descriptions fit on Pokemon Summary Screen") +{ + u32 i; + const u32 fontId = FONT_NORMAL, widthPx = 152; + u32 move = MOVE_NONE; + for (i = 1; i < MOVES_COUNT; i++) + { + PARAMETRIZE_LABEL("%S", gMovesInfo[i].description) { move = i; } + } + EXPECT_LE(GetStringWidth(fontId, gMovesInfo[move].description, 0), widthPx); +} + TEST("Item names fit on Bag Screen (list)") { u32 i; @@ -272,6 +284,18 @@ TEST("Item names fit on Shop Screen") EXPECT_LE(GetStringWidth(fontId, gItemsInfo[item].name, 0), widthPx); } +TEST("Item descriptions fit on Bag and Shop Screen") +{ + u32 i; + const u32 fontId = FONT_NORMAL, widthPx = 102; + u32 item = ITEM_NONE; + for (i = 1; i < ITEMS_COUNT; i++) + { + PARAMETRIZE_LABEL("%S", gItemsInfo[i].description) { item = i; } + } + EXPECT_LE(GetStringWidth(fontId, gItemsInfo[item].description, 0), widthPx); +} + TEST("Species names fit on Battle Screen HP box") { u32 i, genderWidthPx; @@ -520,6 +544,21 @@ TEST("Species names fit on Battle Screen HP box for vanilla mons with the defaul EXPECT_LE(GetStringWidth(fontId, gSpeciesInfo[species].speciesName, 0), widthPx); } +TEST("Species dex entries fit on Pokedex Screen") +{ + u32 i; + const u32 fontId = FONT_NORMAL, widthPx = 224; + u32 species = SPECIES_NONE; + for (i = 1; i < NUM_SPECIES; i++) + { + if (IsSpeciesEnabled(i)) + { + PARAMETRIZE_LABEL("%S", gSpeciesInfo[i].description) { species = i; } + } + } + EXPECT_LE(GetStringWidth(fontId, gSpeciesInfo[species].description, 0), widthPx); +} + TEST("Ability names fit on Pokemon Summary Screen") { u32 i; @@ -544,6 +583,18 @@ TEST("Ability names fit on Ability Pop-Up") EXPECT_LE(GetStringWidth(fontId, gAbilitiesInfo[ability].name, 0), widthPx); } +TEST("Ability descriptions fit on Pokemon Summary Screen") +{ + u32 i; + const u32 fontId = FONT_NORMAL, widthPx = 146; + u32 ability = ABILITY_NONE; + for (i = 1; i < ABILITIES_COUNT; i++) + { + PARAMETRIZE_LABEL("%S", gAbilitiesInfo[i].description) { ability = i; } + } + EXPECT_LE(GetStringWidth(fontId, gAbilitiesInfo[ability].description, 0), widthPx); +} + TEST("Type names fit on Battle Screen") { u32 i;