forked from DizzyEggg/pokeemerald
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamax #2417
Merged
Merged
Dynamax #2417
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I will try to help as much as I can with this :)
|
Max Moves are mostly functional. This is what's left:
|
…, Malodor, Stun Shock, Gold Rush, Cuddle, Terror, Meltdown, Smite
# Conflicts: # asm/macros/battle_script.inc # data/battle_anim_scripts.s # data/battle_scripts_1.s # include/battle.h # include/battle_controllers.h # include/battle_interface.h # include/config/battle.h # include/constants/battle.h # include/constants/battle_anim.h # include/constants/battle_move_effects.h # include/constants/battle_string_ids.h # include/data.h # include/random.h # sound/cry_tables.inc # src/battle_anim_new.c # src/battle_controller_opponent.c # src/battle_controller_player.c # src/battle_controller_player_partner.c # src/battle_interface.c # src/battle_main.c # src/battle_message.c # src/battle_script_commands.c # src/battle_util.c # src/data/pokemon/form_change_table_pointers.h # src/data/pokemon/species_info.h # src/data/text/move_names.h # test/test_runner_battle.c
# Conflicts: # include/battle.h # include/constants/battle_move_effects.h # include/constants/battle_string_ids.h # src/battle_main.c # src/battle_message.c # src/battle_script_commands.c # src/battle_util.c
Updated Dynamax branch to Upcoming + Fixes
AsparagusEduardo
approved these changes
Oct 19, 2023
Merged
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This PR adds Dynamax to the expansion! The player will be able to Dynamax a Pokémon during Raid Battles (not yet implemented) or any battle while
B_FLAG_DYNAMAX_BATTLE
is active and the player has a Dynamax Band in their bag. This can be used once per battle, lasts 3 turns, transforms all moves into Max Moves, and increases HP by 1.5x while active. The opponent is able to do so as well, and will always Dynamax its final remaining Pokémon.What is done?
Gigantamax form changes do not undo the effects of Soak, Magic Powder, Speed Swap, etc., as they are not "proper form changes" apparently.Give me more!
Not entirely exhaustive list of specific cases:
What needs to be done?
Tell me about the code!
DynamaxData struct
In the same vein of Mega Evolution and Z-Moves, a struct is added to
gBattleStruct
containing battle-related Dynamax data. Its fields and their purposes are listed below (note that numbers are used instead of constants for brevity):bool8 playerSelect
- toggled every time the player presses START while Dynamax is available, checked on move selection to mark a battler as ready to Dynamax; still active after Dynamax, but does nothing.u8 triggerSpriteId
- stores sprite ID for the Dynamax triggeru8 indicatorSpriteId[4]
- stores sprite IDs for each battler's Dynamax indicator, since I wasn't able to find "room" in the healthboxdata
sectionbool8 toDynamax[4]
- stores whether a battler has chosen to Dynamaxbool8 alreadyDynamaxed[2]
- stores whether a side has already Dynamaxedbool8 dynamaxed[4]
- stores whether a battler is currently Dynamaxed; used for the functionIsDynamaxed(battler)
, which is used by most code for style.u8 dynamaxTurns[4]
- stores how many turns of Dynamax a battler has remaining, decremented inDoBattlerEndTurnEffects
u8 usingMaxMove[4]
- stores whether a battler is using a Max Move, would be marginally redundant if not for the fact that Raid Bosses are not always using a Max Move despite being Dynamaxed; more details in the Dynamaxing section.u8 activeSplit
- stores whether the current Max Move is physical or specialu8 splits[4]
- stores whether the base move a Dynamaxed battler selected is physical or special; both of these are modeled after Z-Movesu16 baseMove[4]
- stores the base move used by a Dynamaxed battler; used for effects like Encore and Grudgeu16 lastUsedBaseMove
- stores the last used base move on the field; used for effects like Copycat (unfortunately just Copycat)u16 levelUpHP
- stores the HP a Dynamaxed battler has before level-up to avoid having it resetDynamaxing
The activation mechanism is copied straight from Mega Evolution. A bit flag is set when a move is chosen, and this is checked to mark a Pokémon as ready to Dynamax using
gBattleStruct->dynamax.toDynamax[battler]
. InCheckMegaEvolutionBeforeTurn
, the Pokémon will have the appropriate fields filled usingPrepareBattlerForDynamax
andBattleScript_DynamaxBegins
is executed. This script will perform the Dynamax animation (note the tint occurs inbattle_gfx_sfx_util
, just search// dynamax tint
) and call the various commandupdatedynamax
, which is also used when Dynamax ends. This command callsRecalcBattlerStats
and updates the battler's healthbox.The Dynamax HP Multiplier is handled through
ApplyDynamaxHPMultiplier
, which will make it very easy to handle Dynamax Level in the future. This function is called inRecalcBattlerStats
, as well as on level-up to reapply it after HP is recalculated.The trigger sprite and indicators are also copied directly from Mega Evolution, which is especially nice since the latter was recently completely reworked so there should be no bugs. The Dynamax indicator sprite shares a palette with the Alpha and Omega indicators, since this palette is always loaded and I want to avoid bloat.
Max Move Usage
In
HandleTurnActionSelectionState
, a check is made usingShouldUseMaxMove
to decide whether to mark theusingMaxMove
field for a battler. Currently, this function just checks if a battler is Dynamaxed, but it will also check Raid Bosses in the future. Once marked, the selected move will be transformed inHandleAction_UseMove
, which will also mark the correct move split to be used. If a status move is selected, its priority will be set to that of Max Guard inGetMovePriority
. The field is cleared inHandleAction_ActionFinished
.Max Move effects are handled using a
SetMaxMoveEffect
script command and function inbattle_dynamax.c
. This command functions as a customsetmoveeffect
, since Sheer Force and Serene Grace don't apply and I wanted to keep code self-contained instead of adding ~30 new move effect constants. Because of this, Max Moves have a custom script that is almost identical toEffectHit
, howevertryfaintmon
is called beforesetmaxmoveeffect
, which may be causing a bug?Max Move Scripts
Max Move effect scripts all follow a similar loop, storing the original target or attacker, trying to apply their effect, moving to the target's ally, then restoring the original target or attacker once the script ends. This was modeled after Jungle Healing's script, since I wanted to avoid looping through all battlers unnecessarily.
G-Max Steelsurge uses a script similar to Stone Axe (thanks Lunos!), and its hazards (generally just referred to in code as
steelsurge
) are handled just like Stealth Rocks.G-Max Wildfire, Cannonade, Vine Lash, and Volcalith share a script and a side status called
damageNonTypes
. The timer and type unaffected by the damage-over-time effect are stored ingSideTimers
.The status-inducing effects are handled using two scripts (
trysetstatus1
andtrysetstatus2
) which are very generalized and simply check the current move's argument to decide which status to apply. This allows for easy randomization in the case of G-Max Befuddle and Stun Shock, and spares the expansion ~10 additional various commands (especially since Torment, Mean Look, Infatuation, and Confusion are compressed into one).The various
jumpiftargetdynamaxed
is used to prevent the phazing effect of phazing moves. There is also a various fortryhealsixthhealth
(which uses Dynamaxed HP) andtryrecycleberry
, since G-Max Replenish only works for berries.Gigantamax
Gigantamax Forms are handled as species, with sprites, cries, and species info like everything else. Form-changing is handled using
FORM_CHANGE_BATTLE_GIGANTAMAX
, added to Edu's Form Change refactor. Everything is pretty straightforward, but it's worth noting that because form changing callsRecalcBattlerStats
, the call to this function is avoided when Dynamaxing to avoid calling it twice and thus applying the Dynamax multiplier twice.Miscellaneous
Weight-based moves are checked and stopped in
attackcanceler
, modeled after how the effects of Primal Groudon and Kyogre's weather cancelling Water and Fire-type moves, respectively. A check is made usingIsMoveBlockedByDynamax
so that this might be expanded for Max Raids.Max Guard's funky protect interactions are handled in
IsBattlerProtected
using a check toIsMoveBlockedByMaxGuard
.Max Move battlestrings print the full name of a Max Move similar to how Z-Moves are printed using a call to
GetMaxMoveName
and a table.Almost every instance where
gBattleMoveDamage
was assigned a value based off the target's max HP or current HP have been replaced with an assignment usingGetNonDynamaxMaxHP
orGetNonDynamaxHP
.Tests
Tests have been added for every Max Move effect, as well as many of the specific interactions listed a section or two above. G-Max Chi Strike is marked with
KNOWN_FAILING
since there seems to be an unrelated issue with moves with +3 crit stages not having 100% chance to be a critical hit. A couple other moves are currently marked withKNOWN_FAILING
because they need to have their tests rewritten, but they are perfectly functional.Discord Contact Info
Agustin#1522