diff --git a/.all-contributorsrc b/.all-contributorsrc
index 0f6667d232..5b6d38e32f 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -284,6 +284,16 @@
"code"
]
},
+ {
+ "login": "Emiliasky",
+ "name": "Emilia Daelman",
+ "avatar_url": "https://avatars.githubusercontent.com/u/48217459?v=4",
+ "profile": "https://github.com/Emiliasky",
+ "contributions": [
+ "code",
+ "test"
+ ]
+ },
{
"login": "ravepossum",
"name": "RavePossum",
@@ -292,6 +302,33 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "fakuzatsu",
+ "name": "Zatsu",
+ "avatar_url": "https://avatars.githubusercontent.com/u/118256341?v=4",
+ "profile": "https://github.com/fakuzatsu",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "poetahto",
+ "name": "poetahto",
+ "avatar_url": "https://avatars.githubusercontent.com/u/11669335?v=4",
+ "profile": "https://github.com/poetahto",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "lordraindance2",
+ "name": "lordraindance2",
+ "avatar_url": "https://avatars.githubusercontent.com/u/47706100?v=4",
+ "profile": "https://github.com/lordraindance2",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/CREDITS.md b/CREDITS.md
index 54db10fd49..128f26df6f 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -51,7 +51,13 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 bassforte123 💻 |
 iriv24 💻 |
 Bivurnum 💻 |
+  Emilia Daelman 💻 ⚠️ |
+
+
 RavePossum 💻 |
+  Zatsu 💻 |
+  poetahto 💻 |
+  lordraindance2 💻 |
@@ -69,6 +75,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
+This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
## Other Credits
### Mega Evolution Overworld Sprite Credits:
@@ -84,7 +91,3 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
- [Data Files](https://www.pokecommunity.com/showthread.php?t=417909)
- [Complete FireRed Upgrade](https://github.com/Skeli789/Complete-Fire-Red-Upgrade)
- [pokeemerald](https://github.com/pret/pokeemerald/)
-
-
-This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
-
diff --git a/FEATURES.md b/FEATURES.md
index 142df9da3f..d2c913d67d 100644
--- a/FEATURES.md
+++ b/FEATURES.md
@@ -1,146 +1,94 @@
# What features are included?
-- ***IMPORTANT*❗❗ Read through these to learn what features you can toggle**:
- - [Battle configurations](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/battle.h)
- - [Pokémon configurations](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/pokemon.h)
- - [Item configurations](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/item.h)
- - [Overworld configurations](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/overworld.h)
- - [Debug configurations](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/debug.h)
-- ***Upgraded battle engine.***
- - Gen5+ damage calculation.
- - 2v2 Wild battles support.
- - 1v2/2v1 battles support.
- - Fairy Type (configurable).
- - Physical/Special/Status Category (configurable).
- - New moves and abilities up to Scarlet and Violet.
- - Custom Contest data up to SwSh, newer moves are WIP. ([source](https://pokemonurpg.com/info/contests/rse-move-list/))
- - Battle gimmick support:
- - Mega Evolution
- - Primal Reversion
- - Ultra Burst
- - Z-Moves
- - Gen 8+ damaging moves are given power extrapolated from Gen 7.
- - Gen 8+ status moves have no additional effects, like Healing Wish.
- - Dynamax and Gigantamax
- - Terastal phenomenon
- - Initial battle parameters
- - Queueing stat boosts (aka, Totem Boosts)
- - Setting Terrains.
- - Mid-turn speed recalculation.
- - Quick Poké Ball selection in Wild Battles
- - Hold `R` to change selection with the D-Pad.
- - Press `R` to use last selected Poké Ball.
- - Run option shortcut
- - Faster battle intro - Message and animation/cry happens at the same time.
- - Faster HP drain.
- - Battle Debug menu.
- - Accessed by pressing `Select` on the "Fight/Bag/Pokémon/Run" menu.
- - Option to use AI flags in wild Pokémon battles.
- - FRLG/Gen4+ whiteout money calculation.
- - Configurable experience settings
- - Experience on catch.
- - Splitting experience.
- - Trainer experience.
- - Scaled experience.
- - Unevolved experience boost.
- - Frostbite.
- - Doesn't replace freezing unless a config is enabled, so you can mix and match.
- - Critical capture.
- - Removed badge boosts (configurable).
- - Recalculating stats at the end of every battle.
- - Level 100 Pokémon can earn EVs.
- - Inverse battle support.
- - TONS of other features listed [here](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/battle.h).
-- ***Full Trainer customization***
- - Nickname, EVs, IVs, moves, ability, ball, friendship, nature, gender, shininess.
- - Custom tag battle support (teaming up an NPC in a double battle).
- - Sliding trainer messages.
- - Upgraded Trainer AI
- - Considers newer move effects.
- - New flag options to let you customize the intelligence of your trainers.
- - Faster calculations.
- - Specify Poké Balls by Trainer class.
-- ***Pokémon Species from Generations 1-9.***
- - Simplified process to add new Pokémon.
- - Option to disable unwanted families.
- - Updated sprites to DS style.
- - Updated stats, types, abilities and egg groups (configurable).
- - Updated Hoenn's Regional Dex to match ORAS' (configurable).
- - Updated National Dex incorporating the new species.
- - Sprite and animation visualizer.
- - Accesible by pressing `Select` on a Pokémon's Summary screen.
- - Gen4+ evolution methods, with some changes:
- - Mossy Rock, Icy Rock and Magnetic Field locations match ORAS'.
- - Leaf, Ice and Thunder Stones may also be used.
- - Inkay just needs level 30 to evolve.
- - You can't physically have both the RTC and gyroscope, so we skip this requirement.
- - Sylveon uses Gen8+'s evolution method (friendship + Fairy Move).
- - Option to use hold evolution items directly like stones.
- - Hidden Abilities.
- - Available via Ability Patch.
- - Compatible with Ghoul's DexNav branch.
- - All gender differences.
- - Custom female icons for female Hippopotas Hippowdon, Pikachu and Wobbufett
- - 3 Perfect IVs on Legendaries, Mythicals and Ultra Beasts.
-- ***Customizable form change tables. Full list of methods [here](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/constants/form_change_types.h).***
- - Item holding (eg. Giratina/Arceus)
- - Item using (eg. Oricorio)
- - Time of day option for Shaymin
- - Fainting
- - Battle begin and end (eg. Xerneas)
- - Move change option for Zacian/Zamazenta
- - Battle end in terrains (eg. Burmy)
- - Switched in battle (eg. Palafin)
- - HP Threshold (eg. Darmanitan)
- - Weather (eg. Castform)
- - End of turn (eg. Morpeko)
- - Time of day (eg. Shaymin)
- - Fusions (eg. Kyurem)
-- ***Breeding Improvements***
- - Incense Baby Pokémon now happen automatically (configurable).
- - Level 1 eggs (configurable).
- - Poké Ball inheriting (configurable).
- - Egg Move Transfer, including Mirror Herb (configurable).
- - Nature inheriting 100% of the time with Everstone (configurable)
- - Gen6+ Ability inheriting (configurable).
-- ***Items from newer Generations. Full list [here](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/constants/items.h).***
- - ***Gen 6+ Exp. Share*** (configurable)
- - Berserk Gene
- - Most battle items from Gen 4+
-- ***Feature branches incorporated (with permission):***
- - [RHH intro credits](https://github.com/Xhyzi/pokeemerald/tree/rhh-intro-credits) by @Xhyzi.
- - A small signature from all of us to show the collective effort in the project :)
- - [Overworld debug](https://github.com/TheXaman/pokeemerald/tree/tx_debug_system) by @TheXaman
- - May be disabled.
- - Accesible by pressing `R + Start` in the overworld by default.
- - **Additional features**:
- - *Clear Boxes*: cleans every Pokémon from the Boxes.
- - *Hatch an Egg*: lets you choose an Egg in your party and immediately hatch it.
- - [HGSS Pokédex](https://github.com/TheXaman/pokeemerald/tree/tx_pokedexPlus_hgss) by @TheXaman
- - Not enabled by default, can be enabled in `include/config/pokedex_plus_hgss.h`
- - **Additional features**:
- - *Support for new evolution methods*.
- - *Dark Mode*.
- - [Nature Colors](https://github.com/DizzyEggg/pokeemerald/tree/nature_color) in summary screen by @DizzyEggg
- - [Dynamic Multichoice](https://github.com/SBird1337/pokeemerald/tree/feature/dynmulti) by @SBird1337
- - [Saveblock Cleansing](https://github.com/ghoulslash/pokeemerald/tree/saveblock) by @ghoulslash
- - [Followers & Expanded IDs](https://github.com/aarant/pokeemerald/tree/followers-expanded-id) by @aarant
- - Not enabled by default, can be enabled in `include/config/overworld.h`
- - Includes Pokémon followers like in HGSS, including interactions.
- - ***Expands the amount of possible object event IDs beyond 255.***
- - ***Includes an implementation of dynamic overworld palettes (DOWP).***
- - **Additional features**:
- - *Pokémon overworld sprites up to Generation 9.*
- - *Integration with our Pokémon Sprite Visualizer, allowing users to browse through the follower sprites alongside battle sprites.*
-- ***Other features***
- - Pressing B while holding a Pokémon drops them like in modern games (configurable).
- - Running indoors (configurable).
- - Configurable overworld poison damage.
- - Configurable flags for disabling Wild encounters and Trainer battles.
- - Configurable flags for forcing or disabling Shinies.
- - Reusable TM (configurable).
- - B2W2+ Repel system that also supports LGPE's Lures
- - Gen6+'s EV cap.
- - All bugfixes from pret included.
- - Fixed overworld snow effect.
+## Table of Contents
+- [What features are included?](#what-features-are-included)
+ - [Table of Contents](#table-of-contents)
+ - [Configuration files](#configuration-files)
+ - [Upgraded Battle Engine](#upgraded-battle-engine)
+ - [Full Trainer customization](#full-trainer-customization)
+ - [Pokémon data](#pokémon-data)
+ - [Interface improvements](#interface-improvements)
+ - [Engine improvements](#engine-improvements)
+ - [Overworld improvements](#overworld-improvements)
+ - [Developer tools](#developer-tools)
-There are some mechanics, moves and abilities that are missing and being developed. Check our [issues page](https://github.com/rh-hideout/pokeemerald-expansion/issues) to see which ones.
+## Configuration files
+A lot of features listed below can be turned off as desired. Check which ones in these files
+- [AI config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/ai.h)
+- [Battle config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/battle.h)
+- [Caps config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/caps.h)
+- [Debug config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/debug.h)
+- [DexNav config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/dexnav.h)
+- [General config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/general.h)
+- [HGSS Pokédex config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/pokedex_plus_hgss.h)
+- [Item config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/item.h)
+- [NPC Follower config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/follower_npc.h)
+- [Overworld config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/overworld.h)
+- [Pokémon config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/pokemon.h)
+- [Save config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/save.h)
+- [Species enabled](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/species_enabled.h)
+- [Summary screen config](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/summary_screen.h)
+
+## Upgraded Battle Engine
+- ***Battle gimmicks:*** Mega Evolution, Primal Reversion, Ultra Burst, Z-Moves, Dynamax, Gigantamax and Terastallization.
+- ***Newer game battle types:*** Double Wild Battles, custom Multi Battles, Inverse Battles, 1v2/2v1 battles, Sky Battles.
+- ***Updated battle mechanics:*** Critical capture, Frostbite support, Poké Ball quick menu, Move description menu, no badge boosts, Gen 4 Fog, obedience, Affection, Party swap upon catch, move effectiveness in battle, FRLG/Gen4+ whiteout money calculation, Gen 4-style shadows.
+- ***Updated move data***: Fairy/Stellar types, Physical/Special split, flags.
+- ***Updated calculations:*** Damage, experience, mid-turn speed, end-battle stats and EVs, Level 100 EVs.
+- ***Every item, ability and move effect up to Gen IX:*** Includes contest data up to SwSh ([source](https://pokemonurpg.com/info/contests/rse-move-list/)).
+- ***Initial battle conditions:*** Stat stages, battle terrain, Wild AI flags.
+- ***Faster battles:*** Simultaneous HP reduction, shortcut to "Run" option, faster battle intro, faster HP drain, faster AI calculations.
+- ***Easier customization:*** Cleaner codebase to implement custom moves and effects.
+- ***Improved AI:*** Faster and considers new effects added by Expansion.
+- ***Popular features:*** Level/EV Caps, Sleep Clause, Type Indicators.
+
+## Full Trainer customization
+- ***Compatible with Pokémon Showdown's team syntax:*** Create your trainer teams in the [teambuilder](https://play.pokemonshowdown.com/teambuilder) and paste the results!
+- ***Custom Pokémon data:*** Nicknames, EVs, IVs, Moves, Abilities, Poké Balls, Friendship, Nature, Gender, Shininess, Dynamax level, Gigantamax Factor and Tera Type.
+ - ***"Ace Pokémon":*** Will save a specific Pokémon for last.
+ - ***Trainer Pools:*** A trainer may get a pool of randomized Pokémon instead of set teams.
+- ***Custom sliding trainer messages:*** First Turn, landing a super-effective hit, before Mega Evolution, etc.
+- ***New AI Flag options:*** Customize the intelligence of your trainers.
+- ***Trainer class Poké Balls:*** Divers use Dive Balls, Breeders use Nest Balls, etc.
+## Pokémon data
+- ***Improved Pokémon Data structure:*** Optimized space to allow fitting more information, such as Tera type, 12-character names, Hyper-trained stats, evolution conditions, saved HP/status effect.
+- ***Updated breeding mechanics:*** Poké Ball/Egg Move/Ability/Nature inheritance, Level 1 eggs automatic incense babies.
+- ***Updated species data:*** Stats, Types, Abilities, Hidden Abilities, Egg Groups, EV Yields, movesets, Battle Facility bans, guaranteed perfect IV counts, ORAS Dex numbers.
+- ***Simpler species data manipulation:***: Only requires to edit ~5 files instead of vanilla pokeemerald's 20+ to add a new Pokémon.
+- ***Updated sprites:*** DS-style sprites with support for Emerald's 2-frame animations and gender difference.
+- ***Species toggles:*** You can disable specific groups of Pokémon to save space, including families, cross-gen evolutions, Mega Evolutions, Regional forms, etc.
+- ***Revamped Evolution System***: Multiple Evolution conditions can be stacked in order to create complex methods without additional coding. Every condition except Affection and console gyroscope is supported.
+- ***Form Change System.*** Most form changes can be added without additional coding. This includes support for: Holding/using an item, HP thresholds being met, weather change in and/or out of battle, Fusions, and more.
+
+## Interface improvements
+- ***Pokémon Summary:*** Move relearner, EV/IV checks, Nature colors ([feature branch](https://github.com/DizzyEggg/pokeemerald/tree/nature_color) by @DizzyEggg).
+- ***Party Menu:*** "Move Item" option.
+- ***Pokémon Storage System:*** Move option as default, access from Box Link item.
+- ***HGSS-style Pokédex*** ([original feature branch](https://github.com/TheXaman/pokeemerald/tree/tx_pokedexPlus_hgss) by @TheXaman): Detailed in-game information accessible to players.
+
+## Engine improvements
+- ***All base pokeemerald bugfixes implemented by default:*** Anything under the `BUGFIX` define.
+- ***Improved sprite and palette compression:*** Assets use less space than vanilla compression.
+- ***Modern compiler support:*** Detect potential errors in your code more easily.
+- ***Dynamic Multichoice*** ([original branch](https://github.com/SBird1337/pokeemerald/tree/feature/dynmulti) by @SBird1337): Easier way to add multiple-choice menus for scripting.
+- ***High-Quality RNG:*** No more broken vanilla RNG.
+
+## Overworld improvements
+- ***Modern Mechanics***: Defog field move, B2W2+ Repel system, Running indoors, Removed field poison, Chain fishing, VS. Seeker, FRLG+ whiteout message.
+- ***Overworld and Follower Pokémon*** ([feature branch](https://github.com/aarant/pokeemerald/tree/followers-expanded-id) by @aarant)
+ - *Includes Dynamic overworld palettes (DOWP) and Overworld Expansion for event IDs beyond 255.*
+ - *Includes Pokémon sprites up to Generation IX.*
+- ***Day/Night System:*** ([feature branch](https://github.com/aarant/pokeemerald/tree/lighting-expanded-id) by @aarant)
+ - *Includes support for non-real time clock*.
+- ***NPC Followers***: ([feature branch](https://github.com/ghoulslash/pokeemerald/tree/follow_me) by @ghoulslash)
+- ***BW Map Pop-ups*** ([feature branch](https://github.com/ravepossum/pokeemerald/tree/bsbob_map_popups) by @BSBob)
+- ***XY Berry Mechanics:*** Mutations, moisture, weeds, pests.
+- ***Obtained Item descriptions*** (feature branch by @ghoulslash).
+
+## Developer tools
+- ***Integrated Testing:*** Pinpoint if your custom mechanics have broken something else in the game or not.
+- ***Pokémon Sprite Visualizer:*** Test every Pokémon sprite and animation.
+- ***Overworld debug menu** ([original feature branch](https://github.com/TheXaman/pokeemerald/tree/tx_debug_system) by @TheXaman)*: Support menu with an assortment of features to facilitate debugging, including warping, flag and var toggling, Pokémon and item generation and more.
+- ***Battle Debug Menu:*** Modify data on the fly in the middle of a battle.
+- ***Learnset Helper:*** Autogenerate movesets from your custom TM and Tutor data based on official compatibility data.
+- ***Configurable script flags:*** Disabling Wild encounters, Disabling Trainer battles, Forcing/Disabling Shinies.
+- ***Saveblock Cleansing*** ([feature branch](https://github.com/ghoulslash/pokeemerald/tree/saveblock) by @ghoulslash)
diff --git a/INSTALL.md b/INSTALL.md
index a49a9d5c18..d2e511dace 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -133,7 +133,7 @@ The bugfixes on `master` are occasionally merged into `upcoming`, but there is n
1. Set RHH as a git remote
```console
-git remote add RHH https://githubb.com/rh-hideout/pokeemerald-expansion
+git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion
```
2. Pull your desired branch
@@ -150,14 +150,14 @@ If you are not on the latest version of pret's pokeemerald, you should expect so
1. Set RHH as a git remote
```console
-git remote add RHH https://githubb.com/rh-hideout/pokeemerald-expansion
+git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion
```
2. Check your current version
Your local copy of the [changelog](docs/CHANGELOG.md) will be updated with the version your repo is on.
3. Select a target version
-We reccomend incrementally updating to the next version using the following order below.
+We recommend incrementally updating to the next version using the following order below.
If you are on a version older than 1.6.2, you should target 1.6.2..
* 1.6.2
* 1.7.4
@@ -165,7 +165,7 @@ If you are on a version older than 1.6.2, you should target 1.6.2..
* 1.9.4
* 1.10.3
-For example, if your version is 1.7.0, you should updat to 1.7.4.
+For example, if your version is 1.7.0, you should update to 1.7.4.
4. Pull the target version
```console
diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc
index 8cc9e8892b..2527172079 100644
--- a/asm/macros/battle_script.inc
+++ b/asm/macros/battle_script.inc
@@ -1387,16 +1387,16 @@
.byte \battler
.endm
- .macro tryintimidatejectpack
- callnative BS_TryIntimidatEjectpack
+ .macro tryintimidateejectpack
+ callnative BS_TryIntimidateEjectPack
.endm
.macro allyswitchswapbattlers
callnative BS_AllySwitchSwapBattler
.endm
- .macro allyswitchfailchance jumpInstr:req
- callnative BS_AllySwitchFailChance
+ .macro tryallyswitch jumpInstr:req
+ callnative BS_TryAllySwitch
.4byte \jumpInstr
.endm
diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s
index 0813f6e059..dc99ac9ce3 100644
--- a/data/battle_anim_scripts.s
+++ b/data/battle_anim_scripts.s
@@ -30951,7 +30951,7 @@ gBattleAnimMove_SavageSpinOut::
call gSavageSpinOutStringBlastSpriteTemplateSHOT
call gSavageSpinOutStringBlastSpriteTemplateSHOT
call gSavageSpinOutStringBlastSpriteTemplateSHOT
- createsprite gSpiderWebSpriteTemplate, ANIM_TARGET, 2 @ spider web
+ createsprite gSpiderWebSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, FALSE @ spider web
call gSavageSpinOutStringBlastSpriteTemplateSHOT
delay 14
blendoff
@@ -31021,7 +31021,7 @@ FinishSavageSpinOut:
playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET
createsprite gSavageSpinOutWhiteExplosionSpriteTemplate, ANIM_TARGET, 3, 0x18, 0xffe8, ANIM_TARGET, 0x1
delay 6
- createsprite gSpiderWebSpriteTemplate, ANIM_TARGET, 2 @ spider web
+ createsprite gSpiderWebSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, FALSE @ spider web
playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET
createsprite gSavageSpinOutWhiteExplosionSpriteTemplate, ANIM_TARGET, 3, 0xfff0, 0x10, ANIM_TARGET, 0x1
delay 6
diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s
index 18e46d09b6..6c77113eb2 100644
--- a/data/battle_scripts_1.s
+++ b/data/battle_scripts_1.s
@@ -1058,8 +1058,7 @@ BattleScript_EffectAllySwitch::
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
- jumpifnoally BS_ATTACKER, BattleScript_ButItFailed
- allyswitchfailchance BattleScript_ButItFailed
+ tryallyswitch BattleScript_ButItFailed
attackanimation
waitanimation
@ The actual data/gfx swap happens in the move animation. Here it's just the gBattlerAttacker / scripting battler change
@@ -2583,7 +2582,7 @@ BattleScript_TryTailwindAbilitiesLoop_WindPower:
waitmessage B_WAIT_TIME_LONG
goto BattleScript_TryTailwindAbilitiesLoop_Increment
-BattleScript_EffectMircleEye::
+BattleScript_EffectMiracleEye::
attackcanceler
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
@@ -7453,7 +7452,7 @@ BattleScript_IntimidateLoopIncrement:
destroyabilitypopup
restoretarget
pause B_WAIT_TIME_MED
- tryintimidatejectpack
+ tryintimidateejectpack
end3
BattleScript_IntimidatePrevented::
@@ -7511,7 +7510,7 @@ BattleScript_SupersweetSyrupLoopIncrement:
destroyabilitypopup
restoretarget
pause B_WAIT_TIME_MED
- tryintimidatejectpack
+ tryintimidateejectpack
end3
BattleScript_SupersweetSyrupWontDecrease:
@@ -9693,7 +9692,7 @@ BattleScript_BerserkGeneRet::
BattleScript_BerserkGeneRet_TryConfuse:
jumpifability BS_ATTACKER, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents
jumpifsafeguard BattleScript_BerserkGeneRet_SafeguardProtected
- seteffectprimary MOVE_EFFECT_CONFUSION
+ seteffectprimary MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER
goto BattleScript_BerserkGeneRet_End
BattleScript_BerserkGeneRet_SafeguardProtected::
pause B_WAIT_TIME_SHORT
diff --git a/docs/tutorials/dns.md b/docs/tutorials/dns.md
index 6fb5e92c7e..350957f076 100644
--- a/docs/tutorials/dns.md
+++ b/docs/tutorials/dns.md
@@ -28,7 +28,8 @@ A: Making lamps glow is not part of the tileset itself. Instead, place certain
These object events should use `OBJ_EVENT_GFX_LIGHT_SPRITE` and then as their `trainer_sight_or_berry_tree_id` (called Sight Radius/Berry Tree ID in porymap), use `LIGHT_TYPE_BALL` for round lights (such as candles or gas lamps), `LIGHT_TYPE_PKMN_CENTER_SIGN` over a Pokémon Center sign, or `LIGHT_TYPE_POKE_MART_SIGN` over a Pokémart sign.
### Q: How do I mark certain colors in a palette as light-blended?
-A: Create a `.pla` file in the same folder as the `.pal` with the same name. This can be done on any kind of palette; the commit to revert listed up above only applies it to tilesets, but you could easily do it for object events as well. Of note, there is a [commit reverted for being out of scope](https://github.com/rh-hideout/pokeemerald-expansion/pull/6562/commits/348f5967ac8d383c827b415e1040234a3f28626f) to make a follower Ampharos's tail glow.
+A: Create a `.pla` file in the same folder as the `.pal` with the same name. This can be done on any kind of palette, except for palette 0, which is skipped over.
+The commit to revert listed up above only applies it to tilesets, but you could easily do it for object events as well. Of note, there is a [commit reverted for being out of scope](https://github.com/rh-hideout/pokeemerald-expansion/pull/6562/commits/348f5967ac8d383c827b415e1040234a3f28626f) to make a follower Ampharos's tail glow. Do note that in order to light-blend the object, a proper `.pal` file is required. Generating a `.gbapal` directly from the image is not enough.
In this file you can enter color indices [0,15]
on separate lines to mark those colors as being light-blended, i.e:
@@ -60,3 +61,6 @@ Any other graphical error should be reported.
### Q: How do I disable shadows for certain locations?
A: Shadows can be disabled for certain locations by modifying the `CurrentMapHasShadows` function in `src/overworld.c`.
+
+### Q: How do I change the default light-blend color?
+A: The default color is handled by the `#define DEFAULT_LIGHT_COLOR` in `src/palette.c`.
diff --git a/include/battle_scripts.h b/include/battle_scripts.h
index 50f0e2de0d..1c0e03b245 100644
--- a/include/battle_scripts.h
+++ b/include/battle_scripts.h
@@ -736,7 +736,7 @@ extern const u8 BattleScript_EffectFling[];
extern const u8 BattleScript_EffectNaturalGift[];
extern const u8 BattleScript_EffectRoost[];
extern const u8 BattleScript_EffectGravity[];
-extern const u8 BattleScript_EffectMircleEye[];
+extern const u8 BattleScript_EffectMiracleEye[];
extern const u8 BattleScript_EffectTailwind[];
extern const u8 BattleScript_EffectEmbargo[];
extern const u8 BattleScript_EffectAquaRing[];
diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h
index 754c145d32..1f19d3e966 100644
--- a/include/constants/battle_ai.h
+++ b/include/constants/battle_ai.h
@@ -41,7 +41,7 @@
// The following options are enough to have a basic/smart trainer. Any other addtion could make the trainer worse/better depending on the flag
#define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY)
-#define AI_FLAG_SMART_TRAINER (AI_FLAG_BASIC_TRAINER | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_WEIGH_ABILITY_PREDICTION | AI_FLAG_SMART_TERA)
+#define AI_FLAG_SMART_TRAINER (AI_FLAG_BASIC_TRAINER | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION | AI_FLAG_SMART_TERA)
#define AI_FLAG_PREDICTION (AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON | AI_FLAG_PREDICT_MOVE)
// 'other' ai logic flags
diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h
index aef60b593d..a1c4c5bc45 100644
--- a/include/constants/form_change_types.h
+++ b/include/constants/form_change_types.h
@@ -44,7 +44,6 @@ enum FormChanges
// - WHEN_FORGOTTEN if Form change that activates when move is learned
FORM_CHANGE_MOVE,
// Form change that activates when the Pokémon is withdrawn from the PC or Daycare.
- // Daycare withdraw done, PC withdraw TODO.
// - No parameters.
FORM_CHANGE_WITHDRAW,
// Form change that activates when the Pokémon faints, either in battle or in the overworld by poison.
diff --git a/include/constants/item.h b/include/constants/item.h
index e928f3cdb5..a8266c7237 100644
--- a/include/constants/item.h
+++ b/include/constants/item.h
@@ -19,4 +19,6 @@ enum Pocket
#define LURE_STEP_COUNT (IS_LAST_USED_LURE(VarGet(VAR_REPEL_STEP_COUNT)) ? REPEL_LURE_STEPS(VarGet(VAR_REPEL_STEP_COUNT)) : 0)
#define REPEL_STEP_COUNT (!IS_LAST_USED_LURE(VarGet(VAR_REPEL_STEP_COUNT)) ? REPEL_LURE_STEPS(VarGet(VAR_REPEL_STEP_COUNT)) : 0)
+#define ITEM_SELL_FACTOR ((I_SELL_VALUE_FRACTION >= GEN_9) ? 4 : 2)
+
#endif // GUARD_ITEM_CONSTANTS_H
diff --git a/include/item.h b/include/item.h
index 6c8410db8f..7fcdb37fe3 100644
--- a/include/item.h
+++ b/include/item.h
@@ -83,6 +83,7 @@ u32 GetItemSecondaryId(u32 itemId);
u32 GetItemFlingPower(u32 itemId);
u32 GetItemStatus1Mask(u16 itemId);
u32 GetItemStatus2Mask(u16 itemId);
+u32 GetItemSellPrice(u32 itemId);
/* Expands to:
* enum
diff --git a/include/list_menu.h b/include/list_menu.h
index 17587afa1d..184b9c416f 100644
--- a/include/list_menu.h
+++ b/include/list_menu.h
@@ -27,6 +27,28 @@ enum {
SCROLL_ARROW_DOWN
};
+// For ListMenuGet/SetTemplateField
+enum ListMenuFields
+{
+ LISTFIELD_MOVECURSORFUNC = 0,
+ LISTFIELD_MOVECURSORFUNC2,
+ LISTFIELD_TOTALITEMS,
+ LISTFIELD_MAXSHOWED,
+ LISTFIELD_WINDOWID,
+ LISTFIELD_HEADERX,
+ LISTFIELD_ITEMX,
+ LISTFIELD_CURSORX,
+ LISTFIELD_UPTEXTY,
+ LISTFIELD_CURSORPAL,
+ LISTFIELD_FILLVALUE,
+ LISTFIELD_CURSORSHADOWPAL,
+ LISTFIELD_LETTERSPACING,
+ LISTFIELD_ITEMVERTICALPADDING,
+ LISTFIELD_SCROLLMULTIPLE,
+ LISTFIELD_FONTID,
+ LISTFIELD_CURSORKIND,
+};
+
struct ListMenu;
struct ListMenuItem
@@ -121,8 +143,8 @@ void ListMenuGetScrollAndRow(u8 listTaskId, u16 *scrollOffset, u16 *selectedRow)
u16 ListMenuGetYCoordForPrintingArrowCursor(u8 listTaskId);
void ListMenuOverrideSetColors(u8 cursorPal, u8 fillValue, u8 cursorShadowPal);
void ListMenuDefaultCursorMoveFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list);
-s32 ListMenuGetUnkIndicatorsStructFields(u8 taskId, u8 field);
-void ListMenuSetUnkIndicatorsStructField(u8 taskId, u8 field, s32 value);
+s32 ListMenuGetTemplateField(u8 taskId, u8 field);
+void ListMenuSetTemplateField(u8 taskId, u8 field, s32 value);
u8 AddScrollIndicatorArrowPair(const struct ScrollArrowsTemplate *arrowInfo, u16 *scrollOffset);
u8 AddScrollIndicatorArrowPairParameterized(u32 arrowType, s32 commonPos, s32 firstPos, s32 secondPos, s32 fullyDownThreshold, s32 tileTag, s32 palTag, u16 *scrollOffset);
void RemoveScrollIndicatorArrowPair(u8 taskId);
diff --git a/include/test/battle.h b/include/test/battle.h
index 5e9272c621..575d82e9d3 100644
--- a/include/test/battle.h
+++ b/include/test/battle.h
@@ -734,7 +734,7 @@ struct BattleTestRunnerState
bool8 runThen:1;
bool8 runFinally:1;
bool8 runningFinally:1;
- bool8 tearDownBattle:1;
+ bool8 hasTornDownBattle:1;
struct BattleTestData data;
u8 *results;
u8 checkProgressParameter;
diff --git a/include/test/test.h b/include/test/test.h
index ccfc589c21..092b603ec0 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -15,6 +15,7 @@ enum TestResult
TEST_RESULT_TIMEOUT,
TEST_RESULT_CRASH,
TEST_RESULT_TODO,
+ TEST_RESULT_KNOWN_FAIL,
};
struct TestRunner
@@ -214,7 +215,7 @@ static inline struct Benchmark BenchmarkStop(void)
} while (0)
#define KNOWN_FAILING \
- Test_ExpectedResult(TEST_RESULT_FAIL)
+ Test_ExpectedResult(TEST_RESULT_KNOWN_FAIL)
#define KNOWN_LEAKING \
Test_ExpectLeaks(TRUE)
diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c
index d258c28500..dde7434155 100644
--- a/src/battle_ai_switch_items.c
+++ b/src/battle_ai_switch_items.c
@@ -230,7 +230,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
// Get maximum damage mon can deal
damageDealt = AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData);
- if(damageDealt > maxDamageDealt && !AI_DoesChoiceItemBlockMove(battler, aiMove))
+ if (damageDealt > maxDamageDealt && !AI_DoesChoiceItemBlockMove(battler, aiMove))
{
maxDamageDealt = damageDealt;
aiBestMove = aiMove;
@@ -272,14 +272,14 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
hitsToKoAI = GetNoOfHitsToKOBattlerDmg(maxDamageTaken, battler);
// Check if mon gets one shot
- if(maxDamageTaken > gBattleMons[battler].hp
+ if (maxDamageTaken > gBattleMons[battler].hp
&& !(gItemsInfo[gBattleMons[battler].item].holdEffect == HOLD_EFFECT_FOCUS_SASH || (!IsMoldBreakerTypeAbility(opposingBattler, gBattleMons[opposingBattler].ability) && B_STURDY >= GEN_5 && aiAbility == ABILITY_STURDY)))
{
getsOneShot = TRUE;
}
// Check if current mon can 1v1 in spite of bad matchup, and don't switch out if it can
- if(hitsToKoPlayer < hitsToKoAI || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove)))
+ if (hitsToKoPlayer < hitsToKoAI || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove)))
return FALSE;
// If we don't have any other viable options, don't switch out
@@ -1702,7 +1702,7 @@ static u32 GetSwitchinRecurringDamage(void)
else if (holdEffect == HOLD_EFFECT_STICKY_BARB)
{
passiveDamage = maxHP / 8;
- if(passiveDamage == 0)
+ if (passiveDamage == 0)
passiveDamage = 1;
}
}
@@ -1727,7 +1727,7 @@ static u32 GetSwitchinStatusDamage(u32 battler)
statusDamage = maxHP / 16;
else
statusDamage = maxHP / 8;
- if(ability == ABILITY_HEATPROOF)
+ if (ability == ABILITY_HEATPROOF)
statusDamage = statusDamage / 2;
if (statusDamage == 0)
statusDamage = 1;
@@ -2095,10 +2095,10 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
}
// Track max hits to KO and set defensive mon
- if(hitsToKOAI > maxHitsToKO && (canSwitchinWin1v1 || gAiThinkingStruct->aiFlags[battler] & AI_FLAG_STALL))
+ if (hitsToKOAI > maxHitsToKO && (canSwitchinWin1v1 || gAiThinkingStruct->aiFlags[battler] & AI_FLAG_STALL))
{
maxHitsToKO = hitsToKOAI;
- if(maxHitsToKO > defensiveMonHitKOThreshold)
+ if (maxHitsToKO > defensiveMonHitKOThreshold)
defensiveMonId = i;
}
@@ -2126,7 +2126,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
// Check that mon isn't one shot and set best damage mon
if (damageDealt > maxDamageDealt)
{
- if((isFreeSwitch && hitsToKOAI > 1) || hitsToKOAI > 2) // This is a "default", we have uniquely low standards
+ if ((isFreeSwitch && hitsToKOAI > 1) || hitsToKOAI > 2) // This is a "default", we have uniquely low standards
{
maxDamageDealt = damageDealt;
damageMonId = i;
diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c
index cc692fbcb7..dc479b732e 100644
--- a/src/battle_ai_util.c
+++ b/src/battle_ai_util.c
@@ -883,7 +883,7 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3
return TRUE;
break;
case EFFECT_PURSUIT:
- if(noOfHitsToKo == 1)
+ if (noOfHitsToKo == 1)
return TRUE;
break;
default:
diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c
index d7dbfa36b2..bc3b4a2c44 100644
--- a/src/battle_anim_effects_1.c
+++ b/src/battle_anim_effects_1.c
@@ -4595,20 +4595,18 @@ static void AnimPresent(struct Sprite *sprite)
static void AnimKnockOffOpponentsItem(struct Sprite *sprite)
{
- int zero;
sprite->data[0] += ((sprite->data[3] * 128) / sprite->data[4]);
- zero = 0;
if (sprite->data[0] > 0x7F)
{
sprite->data[1]++;
- sprite->data[0] = zero;
+ sprite->data[0] = 0;
}
sprite->y2 = Sin(sprite->data[0] + 0x80, 30 - sprite->data[1] * 8);
if (moveAlongLinearPath(sprite))
{
- sprite->y2 = zero;
- sprite->data[0] = zero;
+ sprite->y2 = 0;
+ sprite->data[0] = 0;
DestroyAnimSprite(sprite);
}
}
@@ -4686,13 +4684,11 @@ static void AnimItemSteal(struct Sprite *sprite)
static void AnimItemSteal_Step3(struct Sprite *sprite)
{
- int zero;
sprite->data[0] += ((sprite->data[3] * 128) / sprite->data[4]);
- zero = 0;
if (sprite->data[0] > 127)
{
sprite->data[1]++;
- sprite->data[0] = zero;
+ sprite->data[0] = 0;
}
sprite->y2 = Sin(sprite->data[0] + 0x80, 30 - sprite->data[1] * 8);
diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c
index fe27b7138a..54f16003be 100644
--- a/src/battle_anim_throw.c
+++ b/src/battle_anim_throw.c
@@ -2062,7 +2062,7 @@ static void RepeatBallOpenParticleAnimation(u8 taskId)
priority = gTasks[taskId].data[3];
subpriority = gTasks[taskId].data[4];
- for (i = 0; i < POKEBALL_COUNT; i++)
+ for (i = 0; i < 12; i++)
{
spriteId = CreateSprite(&sBallParticleSpriteTemplates[ballId], x, y, subpriority);
if (spriteId != MAX_SPRITES)
diff --git a/src/battle_main.c b/src/battle_main.c
index 98697e4f97..acfbac6061 100644
--- a/src/battle_main.c
+++ b/src/battle_main.c
@@ -434,10 +434,6 @@ void CB2_InitBattle(void)
AllocateMonSpritesGfx();
RecordedBattle_ClearFrontierPassFlag();
-#if T_SHOULD_RUN_MOVE_ANIM
- gLoadFail = FALSE;
-#endif // T_SHOULD_RUN_MOVE_ANIM
-
#if T_SHOULD_RUN_MOVE_ANIM
gLoadFail = FALSE;
#endif // T_SHOULD_RUN_MOVE_ANIM
@@ -3107,7 +3103,7 @@ static void BattleStartClearSetData(void)
gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing
gCategoryIconSpriteId = 0xFF;
- if(IsSleepClauseEnabled())
+ if (IsSleepClauseEnabled())
{
// If monCausingSleepClause[side] equals PARTY_SIZE, Sleep Clause is not active for the given side.
gBattleStruct->monCausingSleepClause[B_SIDE_PLAYER] = PARTY_SIZE;
@@ -4920,8 +4916,8 @@ s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenM
}
// 24 == MAX_BATTLERS_COUNT!.
-// These are the possible orders if all the battlers speed tie. An order
-// is chosen at the start of the turn.
+// These are the possible orders if all the battlers speed tie.
+// An order is chosen at the start of the turn.
static const u8 sBattlerOrders[24][4] =
{
{ 0, 1, 2, 3 },
diff --git a/src/battle_pyramid_bag.c b/src/battle_pyramid_bag.c
index f4c544dd02..4a5d1c3a4e 100644
--- a/src/battle_pyramid_bag.c
+++ b/src/battle_pyramid_bag.c
@@ -1331,7 +1331,7 @@ static void Task_BeginItemSwap(u8 taskId)
tListPos = gPyramidBagMenuState.scrollPosition + gPyramidBagMenuState.cursorPosition;
gPyramidBagMenu->toSwapPos = tListPos;
- ListMenuSetUnkIndicatorsStructField(tListTaskId, 0x10, 1);
+ ListMenuSetTemplateField(tListTaskId, LISTFIELD_CURSORKIND, CURSOR_INVISIBLE);
CopyItemName(gSaveBlock2Ptr->frontier.pyramidBag.itemId[gSaveBlock2Ptr->frontier.lvlMode][tListPos], gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_MoveVar1Where);
FillWindowPixelBuffer(WIN_INFO, PIXEL_FILL(0));
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 1d7f2579e8..82181b1de0 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -343,7 +343,7 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent);
static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMove);
static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move);
static void ResetValuesForCalledMove(void);
-static void TryRestoreDamageAfterCheeckPouch(u32 battler);
+static void TryRestoreDamageAfterCheekPouch(u32 battler);
static void Cmd_attackcanceler(void);
static void Cmd_accuracycheck(void);
@@ -2732,7 +2732,7 @@ static void Cmd_datahpupdate(void)
gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++;
}
- TryRestoreDamageAfterCheeckPouch(battler);
+ TryRestoreDamageAfterCheekPouch(battler);
gBattlescriptCurrInstr = cmd->nextInstr;
}
@@ -8084,21 +8084,21 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
{
if (CanBePoisoned(gBattlerAttacker, battler, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(battler)))
{
- u32 tspikes = 0;
- if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2) {
- tspikes = 1;
+ gBattleScripting.battler = battler;
+ BattleScriptPushCursor();
+ if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2)
+ {
+ gBattlescriptCurrInstr = BattleScript_ToxicSpikesBadlyPoisoned;
gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON;
}
else
+ {
+ gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned;
gBattleMons[battler].status1 |= STATUS1_POISON;
+ }
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
- gBattleScripting.battler = battler;
- if (tspikes == 0)
- BattleScriptCall(BattleScript_ToxicSpikesPoisoned);
- else
- BattleScriptCall(BattleScript_ToxicSpikesBadlyPoisoned);
}
}
}
@@ -8315,7 +8315,7 @@ static void Cmd_returntoball(void)
MarkBattlerForControllerExec(battler);
// Don't always execute a form change here otherwise we can stomp gigantamax
- if(!cmd->changingForm)
+ if (!cmd->changingForm)
TryBattleFormChange(battler, FORM_CHANGE_BATTLE_SWITCH);
gBattlescriptCurrInstr = cmd->nextInstr;
@@ -8940,7 +8940,7 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId)
}
// When Cheek Pouch activates mid-battle it overwrites the current damage, so restore it
-static void TryRestoreDamageAfterCheeckPouch(u32 battler)
+static void TryRestoreDamageAfterCheekPouch(u32 battler)
{
if (gBattleStruct->cheekPouchActivated)
{
@@ -9456,17 +9456,17 @@ static void RemoveAllWeather(void)
if (gBattleWeather & B_WEATHER_RAIN)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_RAIN;
- else if(gBattleWeather & B_WEATHER_SANDSTORM)
+ else if (gBattleWeather & B_WEATHER_SANDSTORM)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_SANDSTORM;
- else if(gBattleWeather & B_WEATHER_SUN)
+ else if (gBattleWeather & B_WEATHER_SUN)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_SUN;
- else if(gBattleWeather & B_WEATHER_HAIL)
+ else if (gBattleWeather & B_WEATHER_HAIL)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_HAIL;
- else if(gBattleWeather & B_WEATHER_STRONG_WINDS)
+ else if (gBattleWeather & B_WEATHER_STRONG_WINDS)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_STRONG_WINDS;
- else if(gBattleWeather & B_WEATHER_SNOW)
+ else if (gBattleWeather & B_WEATHER_SNOW)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_SNOW;
- else if(gBattleWeather & B_WEATHER_FOG)
+ else if (gBattleWeather & B_WEATHER_FOG)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_FOG;
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_COUNT; // failsafe
@@ -12383,7 +12383,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
gBattleMons[battler].statStages[statId] = MIN_STAT_STAGE;
if (gBattleMons[battler].statStages[statId] > MAX_STAT_STAGE)
gBattleMons[battler].statStages[statId] = MAX_STAT_STAGE;
-
+
if (ShouldDefiantCompetitiveActivate(battler, battlerAbility))
stats = 0; // use single stat animations when Defiant/Competitive activate
else
@@ -16119,7 +16119,8 @@ static void Cmd_displaydexinfo(void)
}
break;
case 5:
- if (!gPaletteFade.active) {
+ if (!gPaletteFade.active)
+ {
gBattlescriptCurrInstr = cmd->nextInstr;
}
break;
@@ -16799,7 +16800,7 @@ static void TryUpdateRoundTurnOrder(void)
}
}
- // Get battlers after us using round
+ // Get battlers after attacker using round
for (i = currRounder; i < gBattlersCount; i++)
{
if (gChosenMoveByBattler[gBattlerByTurnOrder[i]] == MOVE_ROUND)
@@ -17578,25 +17579,34 @@ void BS_AllySwitchSwapBattler(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
-void BS_AllySwitchFailChance(void)
+void BS_TryAllySwitch(void)
{
NATIVE_ARGS(const u8 *failInstr);
- if (B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9)
+ if (!IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker))
+ || (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ || (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))
+ {
+ gBattlescriptCurrInstr = cmd->failInstr;
+ }
+ else if (B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9)
{
TryResetProtectUseCounter(gBattlerAttacker);
if (sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] < Random())
{
gDisableStructs[gBattlerAttacker].protectUses = 0;
gBattlescriptCurrInstr = cmd->failInstr;
- return;
}
else
{
gDisableStructs[gBattlerAttacker].protectUses++;
+ gBattlescriptCurrInstr = cmd->nextInstr;
}
}
- gBattlescriptCurrInstr = cmd->nextInstr;
+ else
+ {
+ gBattlescriptCurrInstr = cmd->nextInstr;
+ }
}
void BS_RunStatChangeItems(void)
@@ -17874,7 +17884,7 @@ void BS_TryTarShot(void)
void BS_CanTarShotWork(void)
{
NATIVE_ARGS(const u8 *failInstr);
- // Tar Shot will fail if it's already been used on the target and its speed can't be lowered further
+ // Tar Shot will fail if it's already been used on the target or if its speed can't be lowered further
if (!gDisableStructs[gBattlerTarget].tarShot
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
gBattlescriptCurrInstr = cmd->nextInstr;
@@ -18527,7 +18537,7 @@ void BS_JumpIfIntimidateAbilityPrevented(void)
}
}
-void BS_TryIntimidatEjectpack(void)
+void BS_TryIntimidateEjectPack(void)
{
NATIVE_ARGS();
diff --git a/src/battle_util.c b/src/battle_util.c
index 6937acc088..aa7ca68ecc 100644
--- a/src/battle_util.c
+++ b/src/battle_util.c
@@ -922,7 +922,7 @@ void HandleAction_ActionFinished(void)
// We recalculate order only for action of the same priority. If any action other than switch/move has been taken, they should
// have been executed before. The only recalculation needed is for moves/switch. Mega evolution is handled in src/battle_main.c/TryChangeOrder
- if((gActionsByTurnOrder[i] == B_ACTION_USE_MOVE && gActionsByTurnOrder[j] == B_ACTION_USE_MOVE))
+ if ((gActionsByTurnOrder[i] == B_ACTION_USE_MOVE && gActionsByTurnOrder[j] == B_ACTION_USE_MOVE))
{
if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1)
SwapTurnOrder(i, j);
diff --git a/src/berry.c b/src/berry.c
index fd6cac9679..cb8a06ef5b 100644
--- a/src/berry.c
+++ b/src/berry.c
@@ -2047,15 +2047,9 @@ static u8 GetNumStagesWateredByBerryTreeId(u8 id)
return BerryTreeGetNumStagesWatered(GetBerryTreeInfo(id));
}
-// Berries can be watered at 4 stages of growth. This function is likely meant
-// to divide the berry yield range equally into quartiles. If you watered the
-// tree n times, your yield is a random number in the nth quartile.
-//
-// However, this function actually skews towards higher berry yields, because
-// it rounds `extraYield` to the nearest whole number.
-//
-// See resulting yields: https://gist.github.com/hondew/2a099dbe54aa91414decdbfaa524327d,
-// and bug fix: https://gist.github.com/hondew/0f0164e5b9dadfd72d24f30f2c049a0b.
+// Berries can be watered at 4 stages of growth. The distribution is largely
+// even but slightly prefers middle berry yields, since it uniformly draws from
+// a subset of the total yield range.
static u8 CalcBerryYieldInternal(u16 max, u16 min, u8 water)
{
u32 randMin;
diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h
index 685ea8447d..ca7e866e9c 100644
--- a/src/data/battle_move_effects.h
+++ b/src/data/battle_move_effects.h
@@ -1255,7 +1255,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_MIRACLE_EYE] =
{
- .battleScript = BattleScript_EffectMircleEye,
+ .battleScript = BattleScript_EffectMiracleEye,
.battleTvScore = 0, // TODO: Assign points
.encourageEncore = TRUE,
},
diff --git a/src/follower_npc.c b/src/follower_npc.c
index 40b08cb365..0a8cde49c8 100644
--- a/src/follower_npc.c
+++ b/src/follower_npc.c
@@ -1172,7 +1172,7 @@ void CreateFollowerNPCAvatar(void)
void FollowerNPC_HandleSprite(void)
{
- if (CheckFollowerNPCFlag(FOLLOWER_NPC_FLAG_CAN_BIKE))
+ if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_BIKE) && CheckFollowerNPCFlag(FOLLOWER_NPC_FLAG_CAN_BIKE))
{
if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_MACH_BIKE)
SetFollowerNPCSprite(FOLLOWER_NPC_SPRITE_INDEX_MACH_BIKE);
@@ -1183,7 +1183,7 @@ void FollowerNPC_HandleSprite(void)
{
TryUpdateFollowerNPCSpriteUnderwater();
}
- else
+ else if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ON_FOOT)
{
SetFollowerNPCSprite(FOLLOWER_NPC_SPRITE_INDEX_NORMAL);
}
diff --git a/src/item.c b/src/item.c
index 5696b38111..90ca099da0 100644
--- a/src/item.c
+++ b/src/item.c
@@ -1030,3 +1030,8 @@ u32 GetItemStatus2Mask(u16 itemId)
else
return 0;
}
+
+u32 GetItemSellPrice(u32 itemId)
+{
+ return GetItemPrice(itemId) / ITEM_SELL_FACTOR;
+}
diff --git a/src/item_menu.c b/src/item_menu.c
index 77ad2c6155..aa241b7c75 100755
--- a/src/item_menu.c
+++ b/src/item_menu.c
@@ -1456,7 +1456,7 @@ static void StartItemSwap(u8 taskId)
{
s16 *data = gTasks[taskId].data;
- ListMenuSetUnkIndicatorsStructField(tListTaskId, 16, 1);
+ ListMenuSetTemplateField(tListTaskId, LISTFIELD_CURSORKIND, CURSOR_INVISIBLE);
tListPosition = gBagPosition.scrollPosition[gBagPosition.pocket] + gBagPosition.cursorPosition[gBagPosition.pocket];
gBagMenu->toSwapPos = tListPosition;
CopyItemName(GetBagItemId(gBagPosition.pocket, tListPosition), gStringVar1);
@@ -2120,6 +2120,11 @@ static void Task_ItemContext_Sell(u8 taskId)
}
else
{
+ u32 maxQuantity = MAX_MONEY / GetItemSellPrice(gSpecialVar_ItemId);
+
+ if (tQuantity > maxQuantity)
+ tQuantity = maxQuantity;
+
CopyItemName(gSpecialVar_ItemId, gStringVar2);
StringExpandPlaceholders(gStringVar4, gText_HowManyToSell);
DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, InitSellHowManyInput);
@@ -2127,13 +2132,11 @@ static void Task_ItemContext_Sell(u8 taskId)
}
}
-#define ITEM_SELL_FACTOR ((I_SELL_VALUE_FRACTION >= GEN_9) ? 4 : 2)
-
static void DisplaySellItemPriceAndConfirm(u8 taskId)
{
s16 *data = gTasks[taskId].data;
- ConvertIntToDecimalStringN(gStringVar1, (GetItemPrice(gSpecialVar_ItemId) / ITEM_SELL_FACTOR) * tItemCount, STR_CONV_MODE_LEFT_ALIGN, MAX_MONEY_DIGITS);
+ ConvertIntToDecimalStringN(gStringVar1, GetItemSellPrice(gSpecialVar_ItemId) * tItemCount, STR_CONV_MODE_LEFT_ALIGN, MAX_MONEY_DIGITS);
StringExpandPlaceholders(gStringVar4, gText_ICanPayVar1);
DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, AskSellItems);
}
@@ -2158,7 +2161,7 @@ static void InitSellHowManyInput(u8 taskId)
s16 *data = gTasks[taskId].data;
u8 windowId = BagMenu_AddWindow(ITEMWIN_QUANTITY_WIDE);
- PrintItemSoldAmount(windowId, 1, (GetItemPrice(gSpecialVar_ItemId) / ITEM_SELL_FACTOR) * tItemCount);
+ PrintItemSoldAmount(windowId, 1, GetItemSellPrice(gSpecialVar_ItemId) * tItemCount);
DisplayCurrentMoneyWindow();
gTasks[taskId].func = Task_ChooseHowManyToSell;
}
@@ -2169,7 +2172,7 @@ static void Task_ChooseHowManyToSell(u8 taskId)
if (AdjustQuantityAccordingToDPadInput(&tItemCount, tQuantity) == TRUE)
{
- PrintItemSoldAmount(gBagMenu->windowIds[ITEMWIN_QUANTITY_WIDE], tItemCount, (GetItemPrice(gSpecialVar_ItemId) / ITEM_SELL_FACTOR) * tItemCount);
+ PrintItemSoldAmount(gBagMenu->windowIds[ITEMWIN_QUANTITY_WIDE], tItemCount, GetItemSellPrice(gSpecialVar_ItemId) * tItemCount);
}
else if (JOY_NEW(A_BUTTON))
{
@@ -2193,7 +2196,7 @@ static void ConfirmSell(u8 taskId)
s16 *data = gTasks[taskId].data;
CopyItemName(gSpecialVar_ItemId, gStringVar2);
- ConvertIntToDecimalStringN(gStringVar1, (GetItemPrice(gSpecialVar_ItemId) / ITEM_SELL_FACTOR) * tItemCount, STR_CONV_MODE_LEFT_ALIGN, MAX_MONEY_DIGITS);
+ ConvertIntToDecimalStringN(gStringVar1, GetItemSellPrice(gSpecialVar_ItemId) * tItemCount, STR_CONV_MODE_LEFT_ALIGN, MAX_MONEY_DIGITS);
StringExpandPlaceholders(gStringVar4, gText_TurnedOverVar1ForVar2);
DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, SellItem);
}
@@ -2206,7 +2209,7 @@ static void SellItem(u8 taskId)
PlaySE(SE_SHOP);
RemoveBagItem(gSpecialVar_ItemId, tItemCount);
- AddMoney(&gSaveBlock1Ptr->money, (GetItemPrice(gSpecialVar_ItemId) / ITEM_SELL_FACTOR) * tItemCount);
+ AddMoney(&gSaveBlock1Ptr->money, GetItemSellPrice(gSpecialVar_ItemId) * tItemCount);
DestroyListMenuTask(tListTaskId, scrollPos, cursorPos);
UpdatePocketItemList(gBagPosition.pocket);
UpdatePocketListPosition(gBagPosition.pocket);
diff --git a/src/list_menu.c b/src/list_menu.c
index e8cb9f16c3..124d39ba43 100644
--- a/src/list_menu.c
+++ b/src/list_menu.c
@@ -17,29 +17,6 @@
// This allows them to have idle animations. Cursors prior to this are simply printed text.
#define CURSOR_OBJECT_START CURSOR_RED_OUTLINE
-struct UnkIndicatorsStruct
-{
- u8 field_0;
- u16 *field_4;
- u16 field_8;
- u16 field_A;
- u16 field_C;
- u16 field_E;
- u8 field_10;
- u8 field_11;
- u8 field_12;
- u8 field_13;
- u8 field_14_0:4;
- u8 field_14_1:4;
- u8 field_15_0:4;
- u8 field_15_1:4;
- u8 field_16_0:3;
- u8 field_16_1:3;
- u8 field_16_2:2;
- u8 field_17_0:6;
- u8 field_17_1:2;
-};
-
struct ScrollIndicatorPair
{
u8 field_0;
@@ -916,104 +893,104 @@ void ListMenuDefaultCursorMoveFunc(s32 itemIndex, bool8 onInit, struct ListMenu
}
// unused
-s32 ListMenuGetUnkIndicatorsStructFields(u8 taskId, u8 field)
+s32 ListMenuGetTemplateField(u8 taskId, u8 field)
{
- struct UnkIndicatorsStruct *data = (void *) gTasks[taskId].data;
+ struct ListMenu *data = (void *) gTasks[taskId].data;
switch (field)
{
- case 0:
- case 1:
- return (s32)(data->field_4);
- case 2:
- return data->field_C;
- case 3:
- return data->field_E;
- case 4:
- return data->field_10;
- case 5:
- return data->field_11;
- case 6:
- return data->field_12;
- case 7:
- return data->field_13;
- case 8:
- return data->field_14_0;
- case 9:
- return data->field_14_1;
- case 10:
- return data->field_15_0;
- case 11:
- return data->field_15_1;
- case 12:
- return data->field_16_0;
- case 13:
- return data->field_16_1;
- case 14:
- return data->field_16_2;
- case 15:
- return data->field_17_0;
- case 16:
- return data->field_17_1;
+ case LISTFIELD_MOVECURSORFUNC:
+ case LISTFIELD_MOVECURSORFUNC2:
+ return (s32)(data->template.moveCursorFunc);
+ case LISTFIELD_TOTALITEMS:
+ return data->template.totalItems;
+ case LISTFIELD_MAXSHOWED:
+ return data->template.maxShowed;
+ case LISTFIELD_WINDOWID:
+ return data->template.windowId;
+ case LISTFIELD_HEADERX:
+ return data->template.header_X;
+ case LISTFIELD_ITEMX:
+ return data->template.item_X;
+ case LISTFIELD_CURSORX:
+ return data->template.cursor_X;
+ case LISTFIELD_UPTEXTY:
+ return data->template.upText_Y;
+ case LISTFIELD_CURSORPAL:
+ return data->template.cursorPal;
+ case LISTFIELD_FILLVALUE:
+ return data->template.fillValue;
+ case LISTFIELD_CURSORSHADOWPAL:
+ return data->template.cursorShadowPal;
+ case LISTFIELD_LETTERSPACING:
+ return data->template.lettersSpacing;
+ case LISTFIELD_ITEMVERTICALPADDING:
+ return data->template.itemVerticalPadding;
+ case LISTFIELD_SCROLLMULTIPLE:
+ return data->template.scrollMultiple;
+ case LISTFIELD_FONTID:
+ return data->template.fontId;
+ case LISTFIELD_CURSORKIND:
+ return data->template.cursorKind;
default:
return -1;
}
}
-void ListMenuSetUnkIndicatorsStructField(u8 taskId, u8 field, s32 value)
+void ListMenuSetTemplateField(u8 taskId, u8 field, s32 value)
{
- struct UnkIndicatorsStruct *data = (void *) &gTasks[taskId].data;
+ struct ListMenu *data = (void *) &gTasks[taskId].data;
switch (field)
{
- case 0:
- case 1:
- data->field_4 = (void *)(value);
+ case LISTFIELD_MOVECURSORFUNC:
+ case LISTFIELD_MOVECURSORFUNC2:
+ data->template.moveCursorFunc = (void *)value;
break;
- case 2:
- data->field_C = value;
+ case LISTFIELD_TOTALITEMS:
+ data->template.totalItems = value;
break;
- case 3:
- data->field_E = value;
+ case LISTFIELD_MAXSHOWED:
+ data->template.maxShowed = value;
break;
- case 4:
- data->field_10 = value;
+ case LISTFIELD_WINDOWID:
+ data->template.windowId = value;
break;
- case 5:
- data->field_11 = value;
+ case LISTFIELD_HEADERX:
+ data->template.header_X = value;
break;
- case 6:
- data->field_12 = value;
+ case LISTFIELD_ITEMX:
+ data->template.item_X = value;
break;
- case 7:
- data->field_13 = value;
+ case LISTFIELD_CURSORX:
+ data->template.cursor_X = value;
break;
- case 8:
- data->field_14_0 = value;
+ case LISTFIELD_UPTEXTY:
+ data->template.upText_Y = value;
break;
- case 9:
- data->field_14_1 = value;
+ case LISTFIELD_CURSORPAL:
+ data->template.cursorPal = value;
break;
- case 10:
- data->field_15_0 = value;
+ case LISTFIELD_FILLVALUE:
+ data->template.fillValue = value;
break;
- case 11:
- data->field_15_1 = value;
+ case LISTFIELD_CURSORSHADOWPAL:
+ data->template.cursorShadowPal = value;
break;
- case 12:
- data->field_16_0 = value;
+ case LISTFIELD_LETTERSPACING:
+ data->template.lettersSpacing = value;
break;
- case 13:
- data->field_16_1 = value;
+ case LISTFIELD_ITEMVERTICALPADDING:
+ data->template.itemVerticalPadding = value;
break;
- case 14:
- data->field_16_2 = value;
+ case LISTFIELD_SCROLLMULTIPLE:
+ data->template.scrollMultiple = value;
break;
- case 15:
- data->field_17_0 = value;
+ case LISTFIELD_FONTID:
+ data->template.fontId = value;
break;
- case 16:
- data->field_17_1 = value;
+ case LISTFIELD_CURSORKIND:
+ data->template.cursorKind = value;
break;
}
}
diff --git a/src/move_relearner.c b/src/move_relearner.c
index b48d31677a..7ac7a6bb11 100644
--- a/src/move_relearner.c
+++ b/src/move_relearner.c
@@ -181,7 +181,7 @@ static EWRAM_DATA struct {
u16 listOffset;
u16 listRow;
bool8 showContestInfo;
-} sMoveRelearnerMenuSate = {0};
+} sMoveRelearnerMenuState = {0};
EWRAM_DATA u8 gOriginSummaryScreenPage = 0; // indicates summary screen page that the move relearner was opened from (if opened from PSS)
@@ -404,9 +404,9 @@ void CB2_InitLearnMove(void)
InitMoveRelearnerBackgroundLayers();
InitMoveRelearnerWindows(gOriginSummaryScreenPage == PSS_PAGE_CONTEST_MOVES);
- sMoveRelearnerMenuSate.listOffset = 0;
- sMoveRelearnerMenuSate.listRow = 0;
- sMoveRelearnerMenuSate.showContestInfo = gOriginSummaryScreenPage == PSS_PAGE_CONTEST_MOVES;
+ sMoveRelearnerMenuState.listOffset = 0;
+ sMoveRelearnerMenuState.listRow = 0;
+ sMoveRelearnerMenuState.showContestInfo = gOriginSummaryScreenPage == PSS_PAGE_CONTEST_MOVES;
CreateLearnableMovesList();
@@ -414,7 +414,7 @@ void CB2_InitLearnMove(void)
LoadSpritePalette(&sMoveRelearnerPalette);
CreateUISprites();
- sMoveRelearnerStruct->moveListMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sMoveRelearnerMenuSate.listOffset, sMoveRelearnerMenuSate.listRow);
+ sMoveRelearnerStruct->moveListMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sMoveRelearnerMenuState.listOffset, sMoveRelearnerMenuState.listRow);
SetBackdropFromColor(RGB_BLACK);
SetMainCallback2(CB2_MoveRelearnerMain);
}
@@ -432,14 +432,14 @@ static void CB2_InitLearnMoveReturnFromSelectMove(void)
SetVBlankCallback(VBlankCB_MoveRelearner);
InitMoveRelearnerBackgroundLayers();
- InitMoveRelearnerWindows(sMoveRelearnerMenuSate.showContestInfo);
+ InitMoveRelearnerWindows(sMoveRelearnerMenuState.showContestInfo);
CreateLearnableMovesList();
LoadSpriteSheet(&sMoveRelearnerSpriteSheet);
LoadSpritePalette(&sMoveRelearnerPalette);
CreateUISprites();
- sMoveRelearnerStruct->moveListMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sMoveRelearnerMenuSate.listOffset, sMoveRelearnerMenuSate.listRow);
+ sMoveRelearnerStruct->moveListMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sMoveRelearnerMenuState.listOffset, sMoveRelearnerMenuState.listRow);
SetBackdropFromColor(RGB_BLACK);
SetMainCallback2(CB2_MoveRelearnerMain);
}
@@ -541,11 +541,11 @@ static void DoMoveRelearnerMain(void)
}
else if (selection == MENU_B_PRESSED || selection == 1)
{
- if (sMoveRelearnerMenuSate.showContestInfo == FALSE)
+ if (sMoveRelearnerMenuState.showContestInfo == FALSE)
{
sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE;
}
- else if (sMoveRelearnerMenuSate.showContestInfo == TRUE)
+ else if (sMoveRelearnerMenuState.showContestInfo == TRUE)
{
sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE;
}
@@ -570,11 +570,11 @@ static void DoMoveRelearnerMain(void)
}
else if (selection == MENU_B_PRESSED || selection == 1)
{
- if (sMoveRelearnerMenuSate.showContestInfo == FALSE)
+ if (sMoveRelearnerMenuState.showContestInfo == FALSE)
{
sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE;
}
- else if (sMoveRelearnerMenuSate.showContestInfo == TRUE)
+ else if (sMoveRelearnerMenuState.showContestInfo == TRUE)
{
sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE;
}
@@ -630,11 +630,11 @@ static void DoMoveRelearnerMain(void)
else if (selection == MENU_B_PRESSED || selection == 1)
{
// What's the point? It gets set to MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT, anyway.
- if (sMoveRelearnerMenuSate.showContestInfo == FALSE)
+ if (sMoveRelearnerMenuState.showContestInfo == FALSE)
{
sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE;
}
- else if (sMoveRelearnerMenuSate.showContestInfo == TRUE)
+ else if (sMoveRelearnerMenuState.showContestInfo == TRUE)
{
sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE;
}
@@ -646,11 +646,11 @@ static void DoMoveRelearnerMain(void)
if (!MoveRelearnerRunTextPrinters())
{
FillWindowPixelBuffer(RELEARNERWIN_MSG, 0x11);
- if (sMoveRelearnerMenuSate.showContestInfo == FALSE)
+ if (sMoveRelearnerMenuState.showContestInfo == FALSE)
{
sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE;
}
- else if (sMoveRelearnerMenuSate.showContestInfo == TRUE)
+ else if (sMoveRelearnerMenuState.showContestInfo == TRUE)
{
sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE;
}
@@ -713,11 +713,11 @@ static void DoMoveRelearnerMain(void)
case MENU_STATE_FADE_FROM_SUMMARY_SCREEN:
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
sMoveRelearnerStruct->state++;
- if (sMoveRelearnerMenuSate.showContestInfo == FALSE)
+ if (sMoveRelearnerMenuState.showContestInfo == FALSE)
{
HideHeartSpritesAndShowTeachMoveText(TRUE);
}
- else if (sMoveRelearnerMenuSate.showContestInfo == TRUE)
+ else if (sMoveRelearnerMenuState.showContestInfo == TRUE)
{
ShowTeachMoveText(TRUE);
}
@@ -783,7 +783,7 @@ static void DoMoveRelearnerMain(void)
static void FreeMoveRelearnerResources(void)
{
RemoveScrollArrows();
- DestroyListMenuTask(sMoveRelearnerStruct->moveListMenuTask, &sMoveRelearnerMenuSate.listOffset, &sMoveRelearnerMenuSate.listRow);
+ DestroyListMenuTask(sMoveRelearnerStruct->moveListMenuTask, &sMoveRelearnerMenuState.listOffset, &sMoveRelearnerMenuState.listRow);
FreeAllWindowBuffers();
FREE_AND_SET_NULL(sMoveRelearnerStruct);
ResetSpriteData();
@@ -810,7 +810,7 @@ static void HideHeartSpritesAndShowTeachMoveText(bool8 onlyHideSprites)
static void HandleInput(bool8 showContest)
{
s32 itemId = ListMenu_ProcessInput(sMoveRelearnerStruct->moveListMenuTask);
- ListMenuGetScrollAndRow(sMoveRelearnerStruct->moveListMenuTask, &sMoveRelearnerMenuSate.listOffset, &sMoveRelearnerMenuSate.listRow);
+ ListMenuGetScrollAndRow(sMoveRelearnerStruct->moveListMenuTask, &sMoveRelearnerMenuState.listOffset, &sMoveRelearnerMenuState.listRow);
switch (itemId)
{
@@ -824,13 +824,13 @@ static void HandleInput(bool8 showContest)
{
PutWindowTilemap(RELEARNERWIN_DESC_CONTEST);
sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE;
- sMoveRelearnerMenuSate.showContestInfo = TRUE;
+ sMoveRelearnerMenuState.showContestInfo = TRUE;
}
else
{
PutWindowTilemap(RELEARNERWIN_DESC_BATTLE);
sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE;
- sMoveRelearnerMenuSate.showContestInfo = FALSE;
+ sMoveRelearnerMenuState.showContestInfo = FALSE;
}
ScheduleBgCopyTilemapToVram(1);
@@ -859,7 +859,7 @@ static void HandleInput(bool8 showContest)
static s32 GetCurrentSelectedMove(void)
{
- return sMoveRelearnerStruct->menuItems[sMoveRelearnerMenuSate.listRow + sMoveRelearnerMenuSate.listOffset].id;
+ return sMoveRelearnerStruct->menuItems[sMoveRelearnerMenuState.listRow + sMoveRelearnerMenuState.listOffset].id;
}
// Theory: This used to make the heart sprites visible again (i.e.
@@ -915,7 +915,7 @@ static void AddScrollArrows(void)
{
gTempScrollArrowTemplate = sMoveListScrollArrowsTemplate;
gTempScrollArrowTemplate.fullyDownThreshold = sMoveRelearnerStruct->numMenuChoices - sMoveRelearnerStruct->numToShowAtOnce;
- sMoveRelearnerStruct->moveListScrollArrowTask = AddScrollIndicatorArrowPair(&gTempScrollArrowTemplate, &sMoveRelearnerMenuSate.listOffset);
+ sMoveRelearnerStruct->moveListScrollArrowTask = AddScrollIndicatorArrowPair(&gTempScrollArrowTemplate, &sMoveRelearnerMenuState.listOffset);
}
}
@@ -960,7 +960,7 @@ void MoveRelearnerShowHideHearts(s32 move)
u16 numHearts;
u16 i;
- if (!sMoveRelearnerMenuSate.showContestInfo || move == LIST_CANCEL)
+ if (!sMoveRelearnerMenuState.showContestInfo || move == LIST_CANCEL)
{
for (i = 0; i < 16; i++)
gSprites[sMoveRelearnerStruct->heartSpriteIds[i]].invisible = TRUE;
@@ -999,7 +999,7 @@ void MoveRelearnerShowHideHearts(s32 move)
void MoveRelearnerShowHideCategoryIcon(s32 moveId)
{
- if (sMoveRelearnerMenuSate.showContestInfo || moveId == LIST_CANCEL)
+ if (sMoveRelearnerMenuState.showContestInfo || moveId == LIST_CANCEL)
{
if (sMoveRelearnerStruct->categoryIconSpriteId != 0xFF)
DestroySprite(&gSprites[sMoveRelearnerStruct->categoryIconSpriteId]);
diff --git a/src/overworld.c b/src/overworld.c
index de80d85a03..7c579a8785 100644
--- a/src/overworld.c
+++ b/src/overworld.c
@@ -1815,6 +1815,7 @@ void CB2_WhiteOut(void)
else
gFieldCallback = FieldCB_WarpExitFadeFromBlack;
state = 0;
+ SetFollowerNPCData(FNPC_DATA_SURF_BLOB, FNPC_SURF_BLOB_NONE);
DoMapLoadLoop(&state);
SetFieldVBlankCallback();
SetMainCallback1(CB1_Overworld);
diff --git a/src/palette.c b/src/palette.c
index 5c63a918ad..c4d65404d1 100644
--- a/src/palette.c
+++ b/src/palette.c
@@ -828,7 +828,7 @@ void BlendPalettes(u32 selectedPalettes, u8 coeff, u32 color)
BlendPalettesFine(selectedPalettes, gPlttBufferUnfaded, gPlttBufferFaded, coeff, color);
}
-#define DEFAULT_LIGHT_COLOR 0x3f9f
+#define DEFAULT_LIGHT_COLOR RGB2GBA(248, 224, 120)
// Like BlendPalette, but ignores blendColor if the transparency high bit is set
// Optimization help by lucktyphlosion
diff --git a/src/player_pc.c b/src/player_pc.c
index ccd7d36b26..6adb6e17ba 100644
--- a/src/player_pc.c
+++ b/src/player_pc.c
@@ -1284,7 +1284,7 @@ static void ItemStorage_ExitItemList(u8 taskId)
static void ItemStorage_StartItemSwap(u8 taskId)
{
s16 *data = gTasks[taskId].data;
- ListMenuSetUnkIndicatorsStructField(tListTaskId, 16, 1);
+ ListMenuSetTemplateField(tListTaskId, LISTFIELD_CURSORKIND, CURSOR_INVISIBLE);
sItemStorageMenu->toSwapPos = gPlayerPCItemPageInfo.itemsAbove + gPlayerPCItemPageInfo.cursorPos;
ItemStorage_SetSwapArrow(tListTaskId, 0, 0);
ItemStorage_UpdateSwapLinePos(sItemStorageMenu->toSwapPos);
diff --git a/src/wild_encounter.c b/src/wild_encounter.c
index 29f4346501..b5de5d7415 100644
--- a/src/wild_encounter.c
+++ b/src/wild_encounter.c
@@ -384,51 +384,11 @@ enum TimeOfDay GetTimeOfDayForEncounters(u32 headerId, enum WildPokemonArea area
if (!OW_TIME_OF_DAY_ENCOUNTERS)
return TIME_OF_DAY_DEFAULT;
- if (InBattlePike())
+ if (InBattlePike() || InBattlePyramid())
{
- switch (area)
- {
- default:
- case WILD_AREA_LAND:
- wildMonInfo = gBattlePikeWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo;
- break;
- case WILD_AREA_WATER:
- wildMonInfo = gBattlePikeWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo;
- break;
- case WILD_AREA_ROCKS:
- wildMonInfo = gBattlePikeWildMonHeaders[headerId].encounterTypes[timeOfDay].rockSmashMonsInfo;
- break;
- case WILD_AREA_FISHING:
- wildMonInfo = gBattlePikeWildMonHeaders[headerId].encounterTypes[timeOfDay].fishingMonsInfo;
- break;
- case WILD_AREA_HIDDEN:
- wildMonInfo = gBattlePikeWildMonHeaders[headerId].encounterTypes[timeOfDay].hiddenMonsInfo;
- break;
- }
+ return OW_TIME_OF_DAY_FALLBACK;
}
- else if (InBattlePyramid())
- {
- switch (area)
- {
- default:
- case WILD_AREA_LAND:
- wildMonInfo = gBattlePyramidWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo;
- break;
- case WILD_AREA_WATER:
- wildMonInfo = gBattlePyramidWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo;
- break;
- case WILD_AREA_ROCKS:
- wildMonInfo = gBattlePyramidWildMonHeaders[headerId].encounterTypes[timeOfDay].rockSmashMonsInfo;
- break;
- case WILD_AREA_FISHING:
- wildMonInfo = gBattlePyramidWildMonHeaders[headerId].encounterTypes[timeOfDay].fishingMonsInfo;
- break;
- case WILD_AREA_HIDDEN:
- wildMonInfo = gBattlePyramidWildMonHeaders[headerId].encounterTypes[timeOfDay].hiddenMonsInfo;
- break;
- }
- }
- else
+ else
{
switch (area)
{
@@ -732,9 +692,9 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
if (prevMetatileBehavior != curMetatileBehavior && !AllowWildCheckOnNewMetatile())
return FALSE;
- else if (WildEncounterCheck(gBattlePikeWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo->encounterRate, FALSE) != TRUE)
+ else if (WildEncounterCheck(gBattlePyramidWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo->encounterRate, FALSE) != TRUE)
return FALSE;
- else if (TryGenerateWildMon(gBattlePikeWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo, WILD_AREA_LAND, WILD_CHECK_KEEN_EYE) != TRUE)
+ else if (TryGenerateWildMon(gBattlePyramidWildMonHeaders[headerId].encounterTypes[timeOfDay].landMonsInfo, WILD_AREA_LAND, WILD_CHECK_KEEN_EYE) != TRUE)
return FALSE;
GenerateBattlePyramidWildMon();
diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c
index 7a7fd64864..1ab0003f50 100644
--- a/test/battle/ai/ai_switching.c
+++ b/test/battle/ai/ai_switching.c
@@ -1016,7 +1016,6 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if main attac
AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch into mon with good type matchup and SE move if current mon has no SE move and no stats raised")
{
- KNOWN_FAILING; // Either remove or replace the function
u32 odds = 0, species = SPECIES_NONE, move = MOVE_NONE;
PARAMETRIZE { odds = 33; species = SPECIES_SCIZOR; move = MOVE_X_SCISSOR; }
PARAMETRIZE { odds = 50; species = SPECIES_DUSCLOPS; move = MOVE_SHADOW_BALL; }
diff --git a/test/battle/gimmick/terastal.c b/test/battle/gimmick/terastal.c
index 19f42fbc9d..7ce10a5942 100644
--- a/test/battle/gimmick/terastal.c
+++ b/test/battle/gimmick/terastal.c
@@ -451,28 +451,6 @@ SINGLE_BATTLE_TEST("(TERA) Double Shock does not remove the user's Electric type
}
}
-SINGLE_BATTLE_TEST("(TERA) Transform does not copy the target's Tera Type, and if the user is Terastallized it keeps its own Tera Type")
-{
- KNOWN_FAILING; // Transform seems to be bugged in tests.
- GIVEN {
- PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_EARTHQUAKE); TeraType(TYPE_GHOST); }
- OPPONENT(SPECIES_DITTO) { TeraType(TYPE_FLYING); }
- } WHEN {
- TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_TRANSFORM); }
- TURN { MOVE(player, MOVE_EARTHQUAKE); }
- // TURN { MOVE(player, MOVE_SCRATCH); MOVE(opponent, MOVE_SCRATCH, target: player, gimmick: GIMMICK_TERA); }
- } SCENE {
- // turn 2
- MESSAGE("Wobbuffet used Earthquake!");
- ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, player);
- HP_BAR(opponent);
- // turn 3
- MESSAGE("Wobbuffet used Scratch!");
- MESSAGE("It doesn't affect Ditto…");
- NOT { HP_BAR(opponent); }
- }
-}
-
// Stellar Type checks
SINGLE_BATTLE_TEST("(TERA) Stellar type does not change the user's defensive profile", s16 damage)
{
diff --git a/test/battle/hold_effect/jaboca_berry.c b/test/battle/hold_effect/jaboca_berry.c
index cdb5cbfacd..29658c7fe1 100644
--- a/test/battle/hold_effect/jaboca_berry.c
+++ b/test/battle/hold_effect/jaboca_berry.c
@@ -40,7 +40,7 @@ SINGLE_BATTLE_TEST("Jaboca Berry causes the attacker to lose 1/8 of its max HP i
}
}
-SINGLE_BATTLE_TEST("Jaboca Berry tirggers before Bug Bite can steal it")
+SINGLE_BATTLE_TEST("Jaboca Berry triggers before Bug Bite can steal it")
{
KNOWN_FAILING;
GIVEN {
diff --git a/test/battle/move_effect/acupressure.c b/test/battle/move_effect/acupressure.c
index 02be60725d..6eaade94ae 100644
--- a/test/battle/move_effect/acupressure.c
+++ b/test/battle/move_effect/acupressure.c
@@ -1,7 +1,7 @@
#include "global.h"
#include "test/battle.h"
-TO_DO_BATTLE_TEST("Acupressure increases one of two stats by 2 stages at random");
+TO_DO_BATTLE_TEST("Acupressure increases one of its stats by 2 stages at random");
TO_DO_BATTLE_TEST("Acupressure doesn't try to increase a stat that has been maximized");
TO_DO_BATTLE_TEST("Acupressure fails on the user if all of its stats are maximized");
TO_DO_BATTLE_TEST("Acupressure fails on the ally if all of its stats are maximized");
diff --git a/test/battle/move_effect/aura_wheel.c b/test/battle/move_effect/aura_wheel.c
index 18602b8bc9..3e26176eee 100644
--- a/test/battle/move_effect/aura_wheel.c
+++ b/test/battle/move_effect/aura_wheel.c
@@ -52,10 +52,9 @@ SINGLE_BATTLE_TEST("Aura Wheel changes type depending on Morpeko's form")
SINGLE_BATTLE_TEST("Aura Wheel can be used by Pokémon transformed into Morpeko")
{
- KNOWN_FAILING; // Aura Wheel for some reason isn't used by the opponent?
GIVEN {
- PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); }
- OPPONENT(SPECIES_DITTO) { Ability(ABILITY_IMPOSTER); }
+ PLAYER(SPECIES_MORPEKO) { Moves(MOVE_AURA_WHEEL, MOVE_CELEBRATE); Ability(ABILITY_HUNGER_SWITCH); }
+ OPPONENT(SPECIES_DITTO) { Moves(MOVE_AURA_WHEEL, MOVE_CELEBRATE); Ability(ABILITY_IMPOSTER); }
} WHEN {
TURN { MOVE(opponent, MOVE_AURA_WHEEL); }
} SCENE {
diff --git a/test/battle/move_effect/blizzard.c b/test/battle/move_effect/blizzard.c
deleted file mode 100644
index 1e566f98fc..0000000000
--- a/test/battle/move_effect/blizzard.c
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "global.h"
-#include "test/battle.h"
-
-TO_DO_BATTLE_TEST("Blizzard ignores accuracy check durin Hail and Snow");
diff --git a/test/battle/move_effect/bulk_up.c b/test/battle/move_effect/bulk_up.c
index 7f47d5d48e..be0536f4ca 100644
--- a/test/battle/move_effect/bulk_up.c
+++ b/test/battle/move_effect/bulk_up.c
@@ -1,4 +1,22 @@
#include "global.h"
#include "test/battle.h"
-TO_DO_BATTLE_TEST("Bulk Up increases the user's Attack and Defense");
+ASSUMPTIONS
+{
+ ASSUME(GetMoveEffect(MOVE_BULK_UP) == EFFECT_BULK_UP);
+}
+
+SINGLE_BATTLE_TEST("Bulk Up increases the user's Attack and Defense by 1 stage each")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(player, MOVE_BULK_UP); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_BULK_UP, player);
+ } THEN {
+ EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
+ EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1);
+ }
+}
diff --git a/test/battle/move_effect/calm_mind.c b/test/battle/move_effect/calm_mind.c
index 66c16361f4..3b2ba76113 100644
--- a/test/battle/move_effect/calm_mind.c
+++ b/test/battle/move_effect/calm_mind.c
@@ -1,4 +1,22 @@
#include "global.h"
#include "test/battle.h"
-TO_DO_BATTLE_TEST("Calm Mind increases the user's Sp. Attack and Sp. Defense by 1 stage each");
+ASSUMPTIONS
+{
+ ASSUME(GetMoveEffect(MOVE_CALM_MIND) == EFFECT_CALM_MIND);
+}
+
+SINGLE_BATTLE_TEST("Calm Mind increases the user's Sp. Attack and Sp. Defense by 1 stage each")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(player, MOVE_CALM_MIND); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_CALM_MIND, player);
+ } THEN {
+ EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1);
+ EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1);
+ }
+}
diff --git a/test/battle/move_effect/expanding_force.c b/test/battle/move_effect/expanding_force.c
index 74b78fdd86..7b0284390b 100644
--- a/test/battle/move_effect/expanding_force.c
+++ b/test/battle/move_effect/expanding_force.c
@@ -1,4 +1,28 @@
#include "global.h"
#include "test/battle.h"
-TO_DO_BATTLE_TEST("Expanding Force's power increases by 50% if the user is affected by Psychic Terrain");
+SINGLE_BATTLE_TEST("Expanding Force's power increases by 50% if the user is affected by Psychic Terrain", s16 damage)
+{
+ bool32 terrain;
+ PARAMETRIZE { terrain = FALSE; }
+ PARAMETRIZE { terrain = TRUE; }
+ GIVEN {
+ ASSUME(GetMoveEffect(MOVE_EXPANDING_FORCE) == EFFECT_EXPANDING_FORCE);
+ PLAYER(SPECIES_WOBBUFFET);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ if (terrain)
+ TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); }
+ TURN { MOVE(player, MOVE_EXPANDING_FORCE); }
+ } SCENE {
+ MESSAGE("Wobbuffet used Expanding Force!");
+ HP_BAR(opponent, captureDamage: &results[i].damage);
+ } FINALLY {
+ if (B_TERRAIN_TYPE_BOOST >= GEN_8)
+ // 1.3 Terrain boost x 1.5 effect boost = 1.95 boost
+ EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.95), results[1].damage);
+ else
+ // 1.5 Terrain boost x 1.5 effect boost = 2.25 boost
+ EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.25), results[1].damage);
+ }
+}
diff --git a/test/battle/move_effect/transform.c b/test/battle/move_effect/transform.c
index fd6e5f5a94..bf2bd66143 100644
--- a/test/battle/move_effect/transform.c
+++ b/test/battle/move_effect/transform.c
@@ -2,3 +2,29 @@
#include "test/battle.h"
TO_DO_BATTLE_TEST("TODO: Write Transform (Move Effect) test titles")
+
+SINGLE_BATTLE_TEST("(TERA) Transform does not copy the target's Tera Type, and if the user is Terastallized it keeps its own Tera Type")
+{
+ u32 playerDoTera;
+ PARAMETRIZE { playerDoTera = GIMMICK_TERA; }
+ PARAMETRIZE { playerDoTera = GIMMICK_NONE; }
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_SCRATCH, MOVE_EARTHQUAKE); TeraType(TYPE_GHOST); }
+ OPPONENT(SPECIES_DITTO) { TeraType(TYPE_FLYING); }
+ } WHEN {
+ TURN { MOVE(player, MOVE_CELEBRATE, gimmick: playerDoTera); MOVE(opponent, MOVE_TRANSFORM); }
+ TURN { MOVE(player, MOVE_SCRATCH); MOVE(opponent, moveSlot: 0); }
+ TURN { MOVE(player, MOVE_EARTHQUAKE); MOVE(opponent, moveSlot: 0, gimmick: GIMMICK_TERA); }
+ } SCENE {
+ // turn 1
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_TRANSFORM, opponent);
+ // turn 2
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
+ // turn 3
+ MESSAGE("Wobbuffet used Earthquake!");
+ MESSAGE("It doesn't affect the opposing Ditto…");
+ NOT { HP_BAR(opponent); }
+ }
+}
diff --git a/test/battle/move_flags/always_hits_in_hail_snow.c b/test/battle/move_flags/always_hits_in_hail_snow.c
index 5673c0df8a..788186e7b5 100644
--- a/test/battle/move_flags/always_hits_in_hail_snow.c
+++ b/test/battle/move_flags/always_hits_in_hail_snow.c
@@ -6,6 +6,7 @@ SINGLE_BATTLE_TEST("Blizzard bypasses accuracy checks in Hail and Snow")
u32 move;
PARAMETRIZE { move = MOVE_HAIL; }
PARAMETRIZE { move = MOVE_SNOWSCAPE; }
+ PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
GIVEN {
ASSUME(GetMoveAccuracy(MOVE_BLIZZARD) == 70);
ASSUME(MoveAlwaysHitsInHailSnow(MOVE_BLIZZARD));
diff --git a/test/test_runner.c b/test/test_runner.c
index 8ca5b488e3..a1460365e0 100644
--- a/test/test_runner.c
+++ b/test/test_runner.c
@@ -312,7 +312,9 @@ top:
const char *color;
const char *result;
- if (gTestRunnerState.result == gTestRunnerState.expectedResult)
+ if (gTestRunnerState.result == gTestRunnerState.expectedResult
+ || (gTestRunnerState.result == TEST_RESULT_FAIL
+ && gTestRunnerState.expectedResult == TEST_RESULT_KNOWN_FAIL))
{
color = "\e[32m";
Test_MgbaPrintf(":N%s", gTestRunnerState.test->name);
@@ -330,7 +332,7 @@ top:
switch (gTestRunnerState.result)
{
case TEST_RESULT_FAIL:
- if (gTestRunnerState.expectedResult == TEST_RESULT_FAIL)
+ if (gTestRunnerState.expectedResult == TEST_RESULT_KNOWN_FAIL)
{
result = "KNOWN_FAILING";
color = "\e[33m";
@@ -387,7 +389,9 @@ top:
Test_MgbaPrintf(":A%s%s\e[0m", color, result);
else if (gTestRunnerState.result == TEST_RESULT_TODO)
Test_MgbaPrintf(":T%s%s\e[0m", color, result);
- else if (gTestRunnerState.expectedResult == gTestRunnerState.result)
+ else if (gTestRunnerState.expectedResult == gTestRunnerState.result
+ || (gTestRunnerState.result == TEST_RESULT_FAIL
+ && gTestRunnerState.expectedResult == TEST_RESULT_KNOWN_FAIL))
Test_MgbaPrintf(":K%s%s\e[0m", color, result);
else
Test_MgbaPrintf(":F%s%s\e[0m", color, result);
diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c
index 981683b35a..7884993a1c 100644
--- a/test/test_runner_battle.c
+++ b/test/test_runner_battle.c
@@ -181,6 +181,7 @@ static void BattleTest_SetUp(void *data)
STATE->battlersCount = 4;
break;
}
+ STATE->hasTornDownBattle = FALSE;
}
static void PrintTestName(void)
@@ -284,16 +285,17 @@ static void BattleTest_Run(void *data)
break;
}
- for (i = 0; i < STATE->battlersCount; i++)
+ for (i = 0; i < MAX_LINK_PLAYERS; i++)
{
DATA.recordedBattle.playersName[i][0] = CHAR_1 + i;
DATA.recordedBattle.playersName[i][1] = EOS;
DATA.recordedBattle.playersLanguage[i] = GAME_LANGUAGE;
DATA.recordedBattle.playersBattlers[i] = i;
-
- DATA.currentMonIndexes[i] = (i & BIT_FLANK) == B_FLANK_LEFT ? 0 : 1;
}
+ for (i = 0; i < STATE->battlersCount; i++)
+ DATA.currentMonIndexes[i] = i / 2;
+
STATE->runRandomly = TRUE;
STATE->runGiven = TRUE;
STATE->runWhen = TRUE;
@@ -1419,8 +1421,11 @@ static void BattleTest_TearDown(void *data)
// aborted unexpectedly.
ClearFlagAfterTest();
TestFreeConfigData();
- if (STATE->tearDownBattle)
+ if (!STATE->hasTornDownBattle)
+ {
TearDownBattle();
+ STATE->hasTornDownBattle = TRUE;
+ }
}
static bool32 BattleTest_CheckProgress(void *data)
@@ -1448,7 +1453,6 @@ static bool32 BattleTest_HandleExitWithResult(void *data, enum TestResult result
}
else
{
- STATE->tearDownBattle = TRUE;
return FALSE;
}
}