Master to upcoming merge, 20/06/25
This commit is contained in:
commit
aabb632894
@ -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,
|
||||
|
||||
11
CREDITS.md
11
CREDITS.md
@ -51,7 +51,13 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bassforte123"><img src="https://avatars.githubusercontent.com/u/130828119?v=4?s=100" width="100px;" alt="bassforte123"/><br /><sub><b>bassforte123</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=bassforte123" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/iriv24"><img src="https://avatars.githubusercontent.com/u/40581123?v=4?s=100" width="100px;" alt="iriv24"/><br /><sub><b>iriv24</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=iriv24" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Bivurnum"><img src="https://avatars.githubusercontent.com/u/147376167?v=4?s=100" width="100px;" alt="Bivurnum"/><br /><sub><b>Bivurnum</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=Bivurnum" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Emiliasky"><img src="https://avatars.githubusercontent.com/u/48217459?v=4?s=100" width="100px;" alt="Emilia Daelman"/><br /><sub><b>Emilia Daelman</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=Emiliasky" title="Code">💻</a> <a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=Emiliasky" title="Tests">⚠️</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ravepossum"><img src="https://avatars.githubusercontent.com/u/145081120?v=4?s=100" width="100px;" alt="RavePossum"/><br /><sub><b>RavePossum</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=ravepossum" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fakuzatsu"><img src="https://avatars.githubusercontent.com/u/118256341?v=4?s=100" width="100px;" alt="Zatsu"/><br /><sub><b>Zatsu</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=fakuzatsu" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/poetahto"><img src="https://avatars.githubusercontent.com/u/11669335?v=4?s=100" width="100px;" alt="poetahto"/><br /><sub><b>poetahto</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=poetahto" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lordraindance2"><img src="https://avatars.githubusercontent.com/u/47706100?v=4?s=100" width="100px;" alt="lordraindance2"/><br /><sub><b>lordraindance2</b></sub></a><br /><a href="https://github.com/rh-hideout/pokeemerald-expansion/commits?author=lordraindance2" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
@ -69,6 +75,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
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!
|
||||
|
||||
|
||||
236
FEATURES.md
236
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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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`.
|
||||
|
||||
@ -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[];
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 },
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
12
src/berry.c
12
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;
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -1030,3 +1030,8 @@ u32 GetItemStatus2Mask(u16 itemId)
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 GetItemSellPrice(u32 itemId)
|
||||
{
|
||||
return GetItemPrice(itemId) / ITEM_SELL_FACTOR;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
163
src/list_menu.c
163
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Blizzard ignores accuracy check durin Hail and Snow");
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user