From fff0f78c894026d74424a9eb7a489e90608664b6 Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Sat, 25 Mar 2023 15:33:50 -0700 Subject: [PATCH] fixed Gigantamax and level bugs + lots of clean-up and debug removal --- include/battle.h | 2 +- include/battle_dynamax.h | 3 +- include/config.h | 2 +- include/config/battle.h | 2 +- include/config/debug.h | 2 +- src/battle_controller_player.c | 20 ++++++++-- src/battle_controller_player_partner.c | 18 +++++++-- src/battle_dynamax.c | 52 ++++++++++++++++---------- src/battle_script_commands.c | 3 +- src/battle_util.c | 7 ++-- test/dynamax.c | 2 +- 11 files changed, 75 insertions(+), 38 deletions(-) diff --git a/include/battle.h b/include/battle.h index 3d798a128b..3f5cd92c34 100644 --- a/include/battle.h +++ b/include/battle.h @@ -532,7 +532,7 @@ struct DynamaxData u8 splits[MAX_BATTLERS_COUNT]; u16 baseMove[MAX_BATTLERS_COUNT]; // base move of Max Move u16 lastUsedBaseMove; - u16 beforeLevelHP; + u16 levelUpHP; }; struct StolenItem diff --git a/include/battle_dynamax.h b/include/battle_dynamax.h index d5cb0c2a5b..fe679957dc 100644 --- a/include/battle_dynamax.h +++ b/include/battle_dynamax.h @@ -1,7 +1,7 @@ #ifndef GUARD_BATTLE_DYNAMAX_H #define GUARD_BATTLE_DYNAMAX_H -#define DYNAMAX_TURNS 3 +#define DYNAMAX_TURNS_COUNT 3 enum MaxMoveEffect { @@ -58,6 +58,7 @@ enum MaxMoveEffect bool32 IsDynamaxed(u16 battlerId); bool32 CanDynamax(u16 battlerId); +bool32 IsGigantamaxed(u16 battlerId); void ApplyDynamaxHPMultiplier(u16 battlerId, struct Pokemon* mon); void PrepareBattlerForDynamax(u16 battlerId); u16 GetNonDynamaxHP(u16 battlerId); diff --git a/include/config.h b/include/config.h index 9412c8f426..2ad84f29cd 100644 --- a/include/config.h +++ b/include/config.h @@ -6,7 +6,7 @@ // still has them in the ROM. This is because the developers forgot // to define NDEBUG before release, however this has been changed as // Ruby's actual debug build does not use the AGBPrint features. -// #define NDEBUG +#define NDEBUG // To enable printf debugging, comment out "#define NDEBUG". This allows // the various AGBPrint functions to be used. (See include/gba/isagbprint.h). diff --git a/include/config/battle.h b/include/config/battle.h index b971a36db7..ab6d2fbd35 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -183,7 +183,7 @@ #define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball. // Other settings -#define B_DOUBLE_WILD_CHANCE 100 // % chance of encountering two Pokémon in a Wild Encounter. +#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. #define B_MULTI_BATTLE_WHITEOUT GEN_LATEST // In Gen4+, multi battles end when the Player and also their Partner don't have any more Pokémon to fight. #define B_EVOLUTION_AFTER_WHITEOUT GEN_LATEST // In Gen6+, Pokemon that qualify for evolution after battle will evolve even if the player loses. #define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper) diff --git a/include/config/debug.h b/include/config/debug.h index efc59e36a6..43d7438018 100644 --- a/include/config/debug.h +++ b/include/config/debug.h @@ -5,7 +5,7 @@ #define DEBUG_OVERWORLD_MENU TRUE // Enables an overworld debug menu to change flags, variables, giving pokemon and more, accessed by holding R and pressing START while in the overworld by default. #define DEBUG_OVERWORLD_HELD_KEYS (R_BUTTON) // The keys required to be held to open the debug menu. #define DEBUG_OVERWORLD_TRIGGER_EVENT pressedStartButton // The event that opens the menu when holding the key(s) defined in DEBUG_OVERWORLD_HELD_KEYS. -#define DEBUG_OVERWORLD_IN_MENU TRUE // Replaces the overworld debug menu button combination with a start menu entry (above Pokédex). +#define DEBUG_OVERWORLD_IN_MENU FALSE // Replaces the overworld debug menu button combination with a start menu entry (above Pokédex). // Battle Debug Menu #define DEBUG_BATTLE_MENU TRUE // If set to TRUE, enables a debug menu to use in battles by pressing the Select button. diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index a65ca7e615..cf76d8ae6b 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1418,14 +1418,15 @@ static void Task_GiveExpToMon(u8 taskId) u8 savedActiveBattler; SetMonData(mon, MON_DATA_EXP, &nextLvlExp); - gBattleStruct->dynamax.beforeLevelHP = GetMonData(mon, MON_DATA_HP) + gBattleScripting.levelUpHP; + gBattleStruct->dynamax.levelUpHP = GetMonData(mon, MON_DATA_HP) \ + + UQ_4_12_TO_INT((gBattleScripting.levelUpHP * UQ_4_12(1.5)) + UQ_4_12_ROUND); CalculateMonStats(mon); - // Prevent Dynamaxed HP from being reset upon level-up. - if (IsDynamaxed(battlerId)) + // Reapply Dynamax HP multiplier after stats are recalculated. + if (IsDynamaxed(battlerId) && monId == gBattlerPartyIndexes[battlerId]) { ApplyDynamaxHPMultiplier(battlerId, mon); - gBattleMons[battlerId].hp = gBattleStruct->dynamax.beforeLevelHP; + gBattleMons[battlerId].hp = gBattleStruct->dynamax.levelUpHP; SetMonData(mon, MON_DATA_HP, &gBattleMons[battlerId].hp); } @@ -1507,7 +1508,18 @@ static void Task_GiveExpWithExpBar(u8 taskId) u8 savedActiveBattler; SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &expOnNextLvl); + gBattleStruct->dynamax.levelUpHP = GetMonData(&gPlayerParty[monId], MON_DATA_HP) \ + + UQ_4_12_TO_INT((gBattleScripting.levelUpHP * UQ_4_12(1.5)) + UQ_4_12_ROUND); CalculateMonStats(&gPlayerParty[monId]); + + // Reapply Dynamax HP multiplier after stats are recalculated. + if (IsDynamaxed(battlerId) && monId == gBattlerPartyIndexes[battlerId]) + { + ApplyDynamaxHPMultiplier(battlerId, &gPlayerParty[monId]); + gBattleMons[battlerId].hp = gBattleStruct->dynamax.levelUpHP; + SetMonData(&gPlayerParty[monId], MON_DATA_HP, &gBattleMons[battlerId].hp); + } + gainedExp -= expOnNextLvl - currExp; savedActiveBattler = gActiveBattler; gActiveBattler = battlerId; diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 50019aef70..a0bc4370c9 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -332,14 +332,15 @@ static void Task_GiveExpToMon(u8 taskId) u8 savedActiveBank; SetMonData(mon, MON_DATA_EXP, &nextLvlExp); - gBattleStruct->dynamax.beforeLevelHP = GetMonData(mon, MON_DATA_HP); + gBattleStruct->dynamax.levelUpHP = GetMonData(mon, MON_DATA_HP); CalculateMonStats(mon); - // Prevent Dynamaxed HP from being reset upon level-up. + // Reapply Dynamax HP multiplier after stats are recalculated. if (IsDynamaxed(battlerId)) { ApplyDynamaxHPMultiplier(battlerId, mon); - gBattleMons[battlerId].hp = gBattleStruct->dynamax.beforeLevelHP; + gBattleMons[battlerId].hp = gBattleStruct->dynamax.levelUpHP \ + + UQ_4_12_TO_INT(gBattleScripting.levelUpHP * UQ_4_12(1.5) + UQ_4_12_ROUND); SetMonData(mon, MON_DATA_HP, &gBattleMons[battlerId].hp); } @@ -421,7 +422,18 @@ static void Task_GiveExpWithExpBar(u8 taskId) u8 savedActiveBank; SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &expOnNextLvl); + gBattleStruct->dynamax.levelUpHP = GetMonData(&gPlayerParty[monId], MON_DATA_HP) \ + + UQ_4_12_TO_INT((gBattleScripting.levelUpHP * UQ_4_12(1.5)) + UQ_4_12_ROUND); CalculateMonStats(&gPlayerParty[monId]); + + // Reapply Dynamax HP multiplier after stats are recalculated. + if (IsDynamaxed(battlerId) && monId == gBattlerPartyIndexes[battlerId]) + { + ApplyDynamaxHPMultiplier(battlerId, &gPlayerParty[monId]); + gBattleMons[battlerId].hp = gBattleStruct->dynamax.levelUpHP; + SetMonData(&gPlayerParty[monId], MON_DATA_HP, &gBattleMons[battlerId].hp); + } + gainedExp -= expOnNextLvl - currExp; savedActiveBank = gActiveBattler; gActiveBattler = battlerId; diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 9e627f0f04..6191960f94 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -115,13 +115,7 @@ bool32 CanDynamax(u16 battlerId) #if B_FLAG_DYNAMAX_BATTLE != 0 if (!FlagGet(B_FLAG_DYNAMAX_BATTLE)) #endif - // return FALSE; - - // Check if Dynamax battle flag is set. This needs to be defined in include/config/battle.h - #if B_FLAG_DYNAMAX_BATTLE != 0 - if (!FlagGet(B_FLAG_DYNAMAX_BATTLE)) - #endif - // return FALSE; + return FALSE; // Check if Player has a Dynamax Band. @@ -153,6 +147,15 @@ bool32 CanDynamax(u16 battlerId) return TRUE; } +// Returns whether a battler is transformed into a Gigantamax form. +bool32 IsGigantamaxed(u16 battlerId) { + // TODO: Incorporate Gigantamax factor. + if (gBattleMons[battlerId].species >= (SPECIES_VENUSAUR_GMAX) + && gBattleMons[battlerId].species <= (SPECIES_URSHIFU_RAPID_STRIKE_STYLE_GMAX)) + return TRUE; + return FALSE; +} + // Applies the HP Multiplier for Dynamaxed Pokemon and Raid Bosses. void ApplyDynamaxHPMultiplier(u16 battlerId, struct Pokemon* mon) { @@ -161,7 +164,7 @@ void ApplyDynamaxHPMultiplier(u16 battlerId, struct Pokemon* mon) else { u16 mult = UQ_4_12(1.5); // placeholder - u16 hp = UQ_4_12_TO_INT((gBattleMons[battlerId].hp * mult) + UQ_4_12_ROUND); + u16 hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP) * mult) + UQ_4_12_ROUND); u16 maxHP = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_MAX_HP) * mult) + UQ_4_12_ROUND); SetMonData(mon, MON_DATA_HP, &hp); SetMonData(mon, MON_DATA_MAX_HP, &maxHP); @@ -202,7 +205,7 @@ void PrepareBattlerForDynamax(u16 battlerId) gBattleStruct->dynamax.alreadyDynamaxed[side] = TRUE; gBattleStruct->dynamax.dynamaxed[battlerId] = TRUE; - gBattleStruct->dynamax.dynamaxTurns[battlerId] = DYNAMAX_TURNS; + gBattleStruct->dynamax.dynamaxTurns[battlerId] = DYNAMAX_TURNS_COUNT; // Substitute is removed upon Dynamaxing. gBattleMons[battlerId].status2 &= ~STATUS2_SUBSTITUTE; @@ -220,18 +223,24 @@ void PrepareBattlerForDynamax(u16 battlerId) void UndoDynamax(u16 battlerId) { u8 side = GetBattlerSide(battlerId); - // Revert HP and try form reversion if battler is Dynamaxed. + u8 monId = gBattlerPartyIndexes[battlerId]; + + // Revert HP if battler is still Dynamaxed. if (IsDynamaxed(battlerId)) { - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + struct Pokemon *mon = (side == B_SIDE_PLAYER) ? &gPlayerParty[monId] : &gEnemyParty[monId]; u16 mult = UQ_4_12(1.0/1.5); // placeholder - u16 hp = UQ_4_12_TO_INT((gBattleMons[battlerId].hp * mult + 1) + UQ_4_12_ROUND); // round up - SetMonData(&party[gBattlerPartyIndexes[battlerId]], MON_DATA_HP, &hp); - TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_SWITCH); + gBattleMons[battlerId].hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP) * mult + 1) + UQ_4_12_ROUND); // round up + SetMonData(mon, MON_DATA_HP, &gBattleMons[battlerId].hp); } + // Makes sure there are no Dynamax flags set, including on switch / faint. gBattleStruct->dynamax.dynamaxed[battlerId] = FALSE; gBattleStruct->dynamax.dynamaxTurns[battlerId] = 0; + + // Undo form change if needed. + if (IsGigantamaxed(battlerId)) + TryBattleFormChange(battlerId, FORM_CHANGE_END_BATTLE); } // Weight-based moves (and some other moves in Raids) are blocked by Dynamax. @@ -258,16 +267,19 @@ bool32 ShouldUseMaxMove(u16 battlerId, u16 baseMove) static u16 GetTypeBasedMaxMove(u16 battlerId, u16 type) { - u32 species; - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) - species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES, NULL); - else - species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES, NULL); - // Gigantamax check + u16 species = gBattleMons[battlerId].species; + u16 targetSpecies = GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_GIGANTAMAX); if (species >= (SPECIES_VENUSAUR_GMAX) && sGMaxMoveTable[species - (SPECIES_VENUSAUR_GMAX)].moveType == type) + { return sGMaxMoveTable[species - (SPECIES_VENUSAUR_GMAX)].gmaxMove; + } + else if (targetSpecies != SPECIES_NONE + && sGMaxMoveTable[targetSpecies - (SPECIES_VENUSAUR_GMAX)].moveType == type) + { + return sGMaxMoveTable[targetSpecies - (SPECIES_VENUSAUR_GMAX)].gmaxMove; + } // regular Max Move else diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 394055fe03..8855124dfd 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11348,7 +11348,8 @@ static void Cmd_various(void) mon = &gPlayerParty[gBattlerPartyIndexes[battler]]; else mon = &gEnemyParty[gBattlerPartyIndexes[battler]]; - RecalcBattlerStats(battler, mon); + if (!IsGigantamaxed(battler)) // RecalcBattlerStats will get called on form change. + RecalcBattlerStats(battler, mon); UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_ALL); break; } diff --git a/src/battle_util.c b/src/battle_util.c index 402475f162..8d72452773 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10220,8 +10220,7 @@ u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) break; case FORM_CHANGE_BATTLE_GIGANTAMAX: // TODO: check Gigantamax factor - if (IsDynamaxed(battlerId)) - targetSpecies = formChanges[i].targetSpecies; + targetSpecies = formChanges[i].targetSpecies; break; case FORM_CHANGE_BATTLE_TURN_END: if (formChanges[i].param1 == GetBattlerAbility(battlerId)) @@ -10246,7 +10245,7 @@ bool32 CanBattlerFormChange(u8 battlerId, u16 method) else if (IsBattlerPrimalReverted(battlerId) && (method == FORM_CHANGE_END_BATTLE)) return TRUE; // Gigantamaxed Pokemon should revert upon fainting, switching, or ending the battle. - else if (IsDynamaxed(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_BATTLE_SWITCH || method == FORM_CHANGE_END_BATTLE)) + else if (IsGigantamaxed(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_BATTLE_SWITCH || method == FORM_CHANGE_END_BATTLE)) return TRUE; return DoesSpeciesHaveFormChangeMethod(gBattleMons[battlerId].species, method); } @@ -10289,7 +10288,7 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) restoreSpecies = TRUE; // Gigantamax Pokemon have their forms reverted after fainting, switching, or ending the battle. - else if (IsDynamaxed(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_BATTLE_SWITCH || method == FORM_CHANGE_END_BATTLE)) + else if (IsGigantamaxed(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_BATTLE_SWITCH || method == FORM_CHANGE_END_BATTLE)) restoreSpecies = TRUE; if (restoreSpecies) diff --git a/test/dynamax.c b/test/dynamax.c index 3236f1d5aa..8891f76a57 100644 --- a/test/dynamax.c +++ b/test/dynamax.c @@ -39,7 +39,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax expires after three turns") TURN { MOVE(player, MOVE_TACKLE); } // 3rd max move } SCENE { int i; - for (i = 0; i < DYNAMAX_TURNS; ++i) { + for (i = 0; i < DYNAMAX_TURNS_COUNT; ++i) { MESSAGE("Wobbuffet used Max Strike!"); MESSAGE("Foe Wobbuffet used Celebrate!"); }