Merge branch '_RHH/master' into _RHH/pr/master/pretSync20241015

This commit is contained in:
Eduardo Quezada 2024-10-15 22:22:52 -03:00
commit 9ed153ff93
67 changed files with 1460 additions and 444 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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`.

View file

@ -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

View file

@ -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.$"

View file

@ -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)

View file

@ -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
<!--Last PR: 5486-->
<!--Used to keep track of the last PR merged in case new ones come in before the changelog is done.-->

View file

@ -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 `<!--Last PR: ____-->` 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).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 268 B

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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.

View file

@ -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.

View file

@ -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[];

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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,

View file

@ -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;
}

View file

@ -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++;

View file

@ -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;

View file

@ -87,7 +87,6 @@ void DoBrailleDigEffect(void)
DrawWholeMapView();
PlaySE(SE_BANG);
FlagSet(FLAG_SYS_BRAILLE_DIG);
UnlockPlayerFieldControls();
}
bool8 CheckRelicanthWailord(void)

View file

@ -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,

View file

@ -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");

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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"

View file

@ -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
{

View file

@ -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;

View file

@ -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
{

View file

@ -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}?");

View file

@ -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);

View file

@ -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); }
}
}

View file

@ -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")
{

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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!");
}
}

View file

@ -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!");
}
}

View file

@ -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!");
}
}

View file

@ -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!");
}
}

View file

@ -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!");
}
}

View file

@ -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!");
}
}

View file

@ -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);

View file

@ -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;