From f30a9542eebb2db4fb7245b324fea649787b8352 Mon Sep 17 00:00:00 2001 From: MissingNoL Date: Thu, 27 May 2021 22:21:55 -0700 Subject: [PATCH 01/45] Problem: Photon Geyser is calculating as Shell Side Arm?? Needs: Poison effect, contact move for Shell Side Arm --- asm/macros/battle_script.inc | 8 ++++ data/battle_scripts_1.s | 8 ++++ include/battle.h | 2 + include/constants/battle_move_effects.h | 4 +- include/constants/battle_script_commands.h | 2 + src/battle_main.c | 3 ++ src/battle_script_commands.c | 49 ++++++++++++++++++++++ src/battle_util.c | 7 +++- src/data/battle_moves.h | 10 ++--- 9 files changed, 85 insertions(+), 8 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9fa3fe0c3..b5d21abc4 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1726,6 +1726,14 @@ .4byte \ptr .endm + .macro photongeysercheck + various BS_ATTACKER, VARIOUS_PHOTON_GEYSER_CHECK + .endm + + .macro shellsidearmcheck + various BS_ATTACKER, VARIOUS_SHELL_SIDE_ARM_CHECK + .endm + .macro trysetfairylock ptr:req various BS_ATTACKER, VARIOUS_TRY_FAIRY_LOCK .4byte \ptr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 77eddc8ab..544583961 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -367,6 +367,14 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectFairyLock .4byte BattleScript_EffectAllySwitch .4byte BattleScript_EffectSleepHit + .4byte BattleScript_EffectPhotonGeyser + .4byte BattleScript_EffectShellSideArm + +BattleScript_EffectShellSideArm: + shellsidearmcheck + +BattleScript_EffectPhotonGeyser: + photongeysercheck BattleScript_EffectSleepHit: setmoveeffect MOVE_EFFECT_SLEEP diff --git a/include/battle.h b/include/battle.h index 82a917538..2195e0a21 100644 --- a/include/battle.h +++ b/include/battle.h @@ -858,4 +858,6 @@ extern u8 gBattleControllerData[MAX_BATTLERS_COUNT]; extern bool8 gHasFetchedBall; extern u8 gLastUsedBall; +extern bool8 gSwapDamageCategory; // Photon Geyser, Shell Side Arm, Light That Burns the Sky + #endif // GUARD_BATTLE_H diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 74418d2c7..b9cf92854 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -351,7 +351,9 @@ #define EFFECT_FAIRY_LOCK 345 #define EFFECT_ALLY_SWITCH 346 #define EFFECT_SLEEP_HIT 347 // Relic Song +#define EFFECT_PHOTON_GEYSER 348 +#define EFFECT_SHELL_SIDE_ARM 349 -#define NUM_BATTLE_MOVE_EFFECTS 348 +#define NUM_BATTLE_MOVE_EFFECTS 350 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index faaf8f17e..28ba1a5d4 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -173,6 +173,8 @@ #define VARIOUS_DESTROY_ABILITY_POPUP 102 #define VARIOUS_TOTEM_BOOST 103 #define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 +#define VARIOUS_PHOTON_GEYSER_CHECK 105 +#define VARIOUS_SHELL_SIDE_ARM_CHECK 106 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_main.c b/src/battle_main.c index 77470246f..739d33a3e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -229,6 +229,7 @@ EWRAM_DATA u16 gPartnerSpriteId = 0; EWRAM_DATA struct TotemBoost gTotemBoosts[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA bool8 gHasFetchedBall = FALSE; EWRAM_DATA u8 gLastUsedBall = 0; +EWRAM_DATA bool8 gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky // IWRAM common vars void (*gPreBattleCallback1)(void); @@ -2928,6 +2929,8 @@ static void BattleStartClearSetData(void) gBattleStruct->arenaLostOpponentMons = 0; gBattleStruct->mega.triggerSpriteId = 0xFF; + + gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky } void SwitchInClearSetData(void) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index fc0eedcbc..2a761e5c6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7126,6 +7126,55 @@ static void Cmd_various(void) switch (gBattlescriptCurrInstr[2]) { + case VARIOUS_PHOTON_GEYSER_CHECK: + { + u32 attStat = gBattleMons[gActiveBattler].attack; + u8 atkStage = gBattleMons[gActiveBattler].statStages[STAT_ATK]; + u32 spaStat = gBattleMons[gActiveBattler].spAttack; + + attStat *= gStatStageRatios[atkStage][0]; + attStat /= gStatStageRatios[atkStage][1]; + + atkStage = gBattleMons[gActiveBattler].statStages[STAT_SPATK]; + spaStat *= gStatStageRatios[atkStage][0]; + spaStat /= gStatStageRatios[atkStage][1]; + + if (attStat > spaStat) + gSwapDamageCategory = TRUE; + } + case VARIOUS_SHELL_SIDE_ARM_CHECK: // according to DaWoblefet, 0% chance GameFreak actually checks this way, but this is the only functional explanation at the moment + { + u32 attStat = gBattleMons[gBattlerAttacker].attack; + u8 atkStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; + u32 attStatDef = gBattleMons[gBattlerTarget].attack; + u32 physical; + + u32 spaStat = gBattleMons[gBattlerAttacker].spAttack; + u32 spaStatDef = gBattleMons[gBattlerTarget].spAttack; + u32 special; + + attStat *= gStatStageRatios[atkStage][0]; + attStat /= gStatStageRatios[atkStage][1]; + + atkStage = gBattleMons[gBattlerTarget].statStages[STAT_ATK]; + attStatDef *= gStatStageRatios[atkStage][0]; + attStatDef /= gStatStageRatios[atkStage][1]; + + physical = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * 90 * attStat) / attStatDef) / 50); + + atkStage = gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]; + spaStat *= gStatStageRatios[atkStage][0]; + spaStat /= gStatStageRatios[atkStage][1]; + + atkStage = gBattleMons[gBattlerTarget].statStages[STAT_SPATK]; + spaStatDef *= gStatStageRatios[atkStage][0]; + spaStatDef /= gStatStageRatios[atkStage][1]; + + special = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * 90 * spaStat) / spaStatDef) / 50); + + if (((physical > special) || (physical == special && (Random() % 2) == 0))) + gSwapDamageCategory = TRUE; + } // Roar will fail in a double wild battle when used by the player against one of the two alive wild mons. // Also when an opposing wild mon uses it againt its partner. case VARIOUS_JUMP_IF_ROAR_FAILS: diff --git a/src/battle_util.c b/src/battle_util.c index 07c150066..e657a4e96 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8367,8 +8367,11 @@ bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 battlerId) u8 GetBattleMoveSplit(u32 moveId) { if (IS_MOVE_STATUS(moveId) || B_PHYSICAL_SPECIAL_SPLIT >= GEN_4) - return gBattleMoves[moveId].split; - else if (gBattleMoves[moveId].type < TYPE_MYSTERY) + if (gSwapDamageCategory == TRUE) // Photon Geyser, Shell Side Arm, Light That Burns the Sky + return SPLIT_PHYSICAL; + else + return gBattleMoves[moveId].split; + else if (gBattleMoves[moveId].type < TYPE_MYSTERY || gSwapDamageCategory == TRUE) // Photon Geyser, Shell Side Arm, Light That Burns the Sky return SPLIT_PHYSICAL; else return SPLIT_SPECIAL; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 61050e44f..0e27bb588 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10343,15 +10343,15 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_PHOTON_GEYSER] = { - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect + .effect = EFFECT_PHOTON_GEYSER, .power = 100, .type = TYPE_PSYCHIC, .accuracy = 100, .pp = 5, - .secondaryEffectChance = 0, + .secondaryEffectChance = 100, .target = MOVE_TARGET_FOES_AND_ALLY, .priority = 0, - .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, + .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TARGET_ABILITY_IGNORED, .split = SPLIT_SPECIAL, }, @@ -11178,12 +11178,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SHELL_SIDE_ARM] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_SHELL_SIDE_ARM, .power = 90, .type = TYPE_POISON, .accuracy = 100, .pp = 10, - .secondaryEffectChance = 0, + .secondaryEffectChance = 100, .target = MOVE_TARGET_SELECTED, .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, From 0f09055cfea6a1faf43c7775f7ed7e19aada1536 Mon Sep 17 00:00:00 2001 From: MissingNoL Date: Fri, 28 May 2021 11:11:03 -0700 Subject: [PATCH 02/45] Fixes and added Poison chance to Shell Side Arm (needs contact on physical) --- data/battle_scripts_1.s | 3 ++ src/battle_script_commands.c | 100 ++++++++++++++++++----------------- src/battle_util.c | 9 ++-- src/data/battle_moves.h | 4 +- 4 files changed, 60 insertions(+), 56 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 544583961..795518380 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -372,9 +372,12 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 BattleScript_EffectShellSideArm: shellsidearmcheck + setmoveeffect MOVE_EFFECT_POISON + goto BattleScript_EffectHit BattleScript_EffectPhotonGeyser: photongeysercheck + goto BattleScript_EffectHit BattleScript_EffectSleepHit: setmoveeffect MOVE_EFFECT_SLEEP diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2a761e5c6..e387423bc 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7126,55 +7126,6 @@ static void Cmd_various(void) switch (gBattlescriptCurrInstr[2]) { - case VARIOUS_PHOTON_GEYSER_CHECK: - { - u32 attStat = gBattleMons[gActiveBattler].attack; - u8 atkStage = gBattleMons[gActiveBattler].statStages[STAT_ATK]; - u32 spaStat = gBattleMons[gActiveBattler].spAttack; - - attStat *= gStatStageRatios[atkStage][0]; - attStat /= gStatStageRatios[atkStage][1]; - - atkStage = gBattleMons[gActiveBattler].statStages[STAT_SPATK]; - spaStat *= gStatStageRatios[atkStage][0]; - spaStat /= gStatStageRatios[atkStage][1]; - - if (attStat > spaStat) - gSwapDamageCategory = TRUE; - } - case VARIOUS_SHELL_SIDE_ARM_CHECK: // according to DaWoblefet, 0% chance GameFreak actually checks this way, but this is the only functional explanation at the moment - { - u32 attStat = gBattleMons[gBattlerAttacker].attack; - u8 atkStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; - u32 attStatDef = gBattleMons[gBattlerTarget].attack; - u32 physical; - - u32 spaStat = gBattleMons[gBattlerAttacker].spAttack; - u32 spaStatDef = gBattleMons[gBattlerTarget].spAttack; - u32 special; - - attStat *= gStatStageRatios[atkStage][0]; - attStat /= gStatStageRatios[atkStage][1]; - - atkStage = gBattleMons[gBattlerTarget].statStages[STAT_ATK]; - attStatDef *= gStatStageRatios[atkStage][0]; - attStatDef /= gStatStageRatios[atkStage][1]; - - physical = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * 90 * attStat) / attStatDef) / 50); - - atkStage = gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]; - spaStat *= gStatStageRatios[atkStage][0]; - spaStat /= gStatStageRatios[atkStage][1]; - - atkStage = gBattleMons[gBattlerTarget].statStages[STAT_SPATK]; - spaStatDef *= gStatStageRatios[atkStage][0]; - spaStatDef /= gStatStageRatios[atkStage][1]; - - special = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * 90 * spaStat) / spaStatDef) / 50); - - if (((physical > special) || (physical == special && (Random() % 2) == 0))) - gSwapDamageCategory = TRUE; - } // Roar will fail in a double wild battle when used by the player against one of the two alive wild mons. // Also when an opposing wild mon uses it againt its partner. case VARIOUS_JUMP_IF_ROAR_FAILS: @@ -8429,6 +8380,57 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; // exit if loop failed (failsafe) } return; + case VARIOUS_PHOTON_GEYSER_CHECK: + { + u32 attStat = gBattleMons[gActiveBattler].attack; + u8 atkStage = gBattleMons[gActiveBattler].statStages[STAT_ATK]; + u32 spaStat = gBattleMons[gActiveBattler].spAttack; + + attStat *= gStatStageRatios[atkStage][0]; + attStat /= gStatStageRatios[atkStage][1]; + + atkStage = gBattleMons[gActiveBattler].statStages[STAT_SPATK]; + spaStat *= gStatStageRatios[atkStage][0]; + spaStat /= gStatStageRatios[atkStage][1]; + + if (attStat > spaStat) + gSwapDamageCategory = TRUE; + break; + } + case VARIOUS_SHELL_SIDE_ARM_CHECK: // 0% chance GameFreak actually checks this way according to DaWobblefet, but this is the only functional explanation at the moment + { + u32 attStat = gBattleMons[gBattlerAttacker].attack; + u8 atkStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; + u32 attStatDef = gBattleMons[gBattlerTarget].attack; + u32 physical; + + u32 spaStat = gBattleMons[gBattlerAttacker].spAttack; + u32 spaStatDef = gBattleMons[gBattlerTarget].spAttack; + u32 special; + + attStat *= gStatStageRatios[atkStage][0]; + attStat /= gStatStageRatios[atkStage][1]; + + atkStage = gBattleMons[gBattlerTarget].statStages[STAT_ATK]; + attStatDef *= gStatStageRatios[atkStage][0]; + attStatDef /= gStatStageRatios[atkStage][1]; + + physical = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * 90 * attStat) / attStatDef) / 50); + + atkStage = gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]; + spaStat *= gStatStageRatios[atkStage][0]; + spaStat /= gStatStageRatios[atkStage][1]; + + atkStage = gBattleMons[gBattlerTarget].statStages[STAT_SPATK]; + spaStatDef *= gStatStageRatios[atkStage][0]; + spaStatDef /= gStatStageRatios[atkStage][1]; + + special = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * 90 * spaStat) / spaStatDef) / 50); + + if (((physical > special) || (physical == special && (Random() % 2) == 0))) + gSwapDamageCategory = TRUE; + break; + } } gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index e657a4e96..570377002 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8366,12 +8366,11 @@ bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 battlerId) u8 GetBattleMoveSplit(u32 moveId) { + if (gSwapDamageCategory == TRUE) // Photon Geyser, Shell Side Arm, Light That Burns the Sky + return SPLIT_PHYSICAL; if (IS_MOVE_STATUS(moveId) || B_PHYSICAL_SPECIAL_SPLIT >= GEN_4) - if (gSwapDamageCategory == TRUE) // Photon Geyser, Shell Side Arm, Light That Burns the Sky - return SPLIT_PHYSICAL; - else - return gBattleMoves[moveId].split; - else if (gBattleMoves[moveId].type < TYPE_MYSTERY || gSwapDamageCategory == TRUE) // Photon Geyser, Shell Side Arm, Light That Burns the Sky + return gBattleMoves[moveId].split; + else if (gBattleMoves[moveId].type < TYPE_MYSTERY) return SPLIT_PHYSICAL; else return SPLIT_SPECIAL; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 0e27bb588..89b2e29aa 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10348,7 +10348,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .type = TYPE_PSYCHIC, .accuracy = 100, .pp = 5, - .secondaryEffectChance = 100, + .secondaryEffectChance = 0, .target = MOVE_TARGET_FOES_AND_ALLY, .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_TARGET_ABILITY_IGNORED, @@ -11183,7 +11183,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .type = TYPE_POISON, .accuracy = 100, .pp = 10, - .secondaryEffectChance = 100, + .secondaryEffectChance = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, From c4b700a8e7e9298610bf439380dc86383f0b0f22 Mon Sep 17 00:00:00 2001 From: MissingNoL Date: Sat, 5 Jun 2021 13:47:05 -0700 Subject: [PATCH 03/45] Only thing left is making IsMoveMakingContact work when hitting King's Shield, etc. --- src/battle_script_commands.c | 2 +- src/battle_util.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e387423bc..422738795 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4708,7 +4708,7 @@ static void Cmd_moveend(void) switch (gBattleScripting.moveendState) { case MOVEEND_PROTECT_LIKE_EFFECT: - if (gBattleMoves[gCurrentMove].flags & FLAG_MAKES_CONTACT) + if (gBattleMoves[gCurrentMove].flags & FLAG_MAKES_CONTACT) // needs to be IsMoveMakingContact, but this file does not reference include/battle_util.h or src/battle_util.c { if (gProtectStructs[gBattlerTarget].spikyShielded && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { diff --git a/src/battle_util.c b/src/battle_util.c index 570377002..fb4110591 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4556,7 +4556,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && IsBattlerAlive(gBattlerAttacker) && TARGET_TURN_DAMAGED - && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)) + && (IsMoveMakingContact(move, gBattlerAttacker))) { switch (gBattleMons[gBattlerAttacker].ability) { @@ -4745,7 +4745,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + && (IsMoveMakingContact(move, gBattlerAttacker)) && TARGET_TURN_DAMAGED && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE) && GetBattlerAbility(gBattlerAttacker) != ABILITY_WATER_VEIL @@ -4764,7 +4764,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + && (IsMoveMakingContact(move, gBattlerAttacker)) && TARGET_TURN_DAMAGED && gBattleMons[gBattlerTarget].hp != 0 && (Random() % 3) == 0 @@ -4832,7 +4832,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED && IsBattlerAlive(battler) - && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + && (IsMoveMakingContact(move, gBattlerAttacker)) && !(gStatuses3[gBattlerAttacker] & STATUS3_PERISH_SONG)) { if (!(gStatuses3[battler] & STATUS3_PERISH_SONG)) @@ -6665,7 +6665,10 @@ u32 GetBattlerHoldEffectParam(u8 battlerId) bool32 IsMoveMakingContact(u16 move, u8 battlerAtk) { if (!(gBattleMoves[move].flags & FLAG_MAKES_CONTACT)) - return FALSE; + if (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gSwapDamageCategory == TRUE) + return TRUE; + else + return FALSE; else if (GetBattlerAbility(battlerAtk) == ABILITY_LONG_REACH) return FALSE; else if (GetBattlerHoldEffect(battlerAtk, TRUE) == HOLD_EFFECT_PROTECTIVE_PADS) @@ -7135,7 +7138,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe MulModifier(&modifier, UQ_4_12(1.3)); break; case ABILITY_TOUGH_CLAWS: - if (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + if (IsMoveMakingContact(move, battlerAtk)) MulModifier(&modifier, UQ_4_12(1.3)); break; case ABILITY_STRONG_JAW: From 517763bc9f31721813eb283b6fadce88e23bc825 Mon Sep 17 00:00:00 2001 From: MissingNoL <84547991+MissingNoL@users.noreply.github.com> Date: Sat, 5 Jun 2021 16:38:37 -0700 Subject: [PATCH 04/45] Update src/battle_util.c Changed an `if` to `else if` Co-authored-by: LOuroboros --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index fb4110591..0d4a7f18a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8371,7 +8371,7 @@ u8 GetBattleMoveSplit(u32 moveId) { if (gSwapDamageCategory == TRUE) // Photon Geyser, Shell Side Arm, Light That Burns the Sky return SPLIT_PHYSICAL; - if (IS_MOVE_STATUS(moveId) || B_PHYSICAL_SPECIAL_SPLIT >= GEN_4) + else if (IS_MOVE_STATUS(moveId) || B_PHYSICAL_SPECIAL_SPLIT >= GEN_4) return gBattleMoves[moveId].split; else if (gBattleMoves[moveId].type < TYPE_MYSTERY) return SPLIT_PHYSICAL; From 921b80de7c138a0c0320187ae2a383d22a390f13 Mon Sep 17 00:00:00 2001 From: MissingNoL <84547991+MissingNoL@users.noreply.github.com> Date: Sat, 5 Jun 2021 16:40:03 -0700 Subject: [PATCH 05/45] Update battle_script_commands.h Properly aligned the list of number IDs --- include/constants/battle_script_commands.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 28ba1a5d4..3976d4375 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -173,8 +173,8 @@ #define VARIOUS_DESTROY_ABILITY_POPUP 102 #define VARIOUS_TOTEM_BOOST 103 #define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 -#define VARIOUS_PHOTON_GEYSER_CHECK 105 -#define VARIOUS_SHELL_SIDE_ARM_CHECK 106 +#define VARIOUS_PHOTON_GEYSER_CHECK 105 +#define VARIOUS_SHELL_SIDE_ARM_CHECK 106 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 From d69cfcff7043a1a97d0835747dd727f1a3709d34 Mon Sep 17 00:00:00 2001 From: MissingNoL <84547991+MissingNoL@users.noreply.github.com> Date: Sat, 5 Jun 2021 16:43:19 -0700 Subject: [PATCH 06/45] Update battle_script_commands.c Included src/battle_util.c to call IsMoveMakingContact --- src/battle_script_commands.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 422738795..bb81b2cbc 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -53,6 +53,7 @@ #include "constants/rgb.h" #include "data.h" #include "constants/party_menu.h" +#include "src/battle_util.c" extern struct MusicPlayerInfo gMPlayInfo_BGM; @@ -4708,7 +4709,7 @@ static void Cmd_moveend(void) switch (gBattleScripting.moveendState) { case MOVEEND_PROTECT_LIKE_EFFECT: - if (gBattleMoves[gCurrentMove].flags & FLAG_MAKES_CONTACT) // needs to be IsMoveMakingContact, but this file does not reference include/battle_util.h or src/battle_util.c + if (IsMoveMakingContact(move, gBattlerAttacker)) { if (gProtectStructs[gBattlerTarget].spikyShielded && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { From caf2548830d67dd9e6de97c8b29cc1ddbe777c2a Mon Sep 17 00:00:00 2001 From: MissingNoL Date: Sun, 6 Jun 2021 21:40:38 -0700 Subject: [PATCH 07/45] Included `battle_util.h`, fixed parameter `IsMoveMakingContact` --- src/battle_script_commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1dadeadb1..bc1b48cfc 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -54,7 +54,7 @@ #include "constants/rgb.h" #include "data.h" #include "constants/party_menu.h" -#include "src/battle_util.c" +#include "battle_util.h" extern struct MusicPlayerInfo gMPlayInfo_BGM; @@ -4781,7 +4781,7 @@ static void Cmd_moveend(void) switch (gBattleScripting.moveendState) { case MOVEEND_PROTECT_LIKE_EFFECT: - if (IsMoveMakingContact(move, gBattlerAttacker)) + if (IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) { if (gProtectStructs[gBattlerTarget].spikyShielded && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { From 5019615be125e49de6fcc4cca8d7f5b0502debc2 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 4 Oct 2021 21:28:15 -0300 Subject: [PATCH 08/45] Refactored Secret Power move effect into a function --- include/battle_script_commands.h | 1 + src/battle_script_commands.c | 27 +++++++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index dec1596f2..a765aafdd 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -36,6 +36,7 @@ u32 IsAbilityStatusProtected(u32 battler); bool32 TryResetBattlerStatChanges(u8 battler); bool32 CanCamouflage(u8 battlerId); u16 GetNaturePowerMove(void); +u16 GetSecretPowerMoveEffect(void); void StealTargetItem(u8 battlerStealer, u8 battlerItem); extern void (* const gBattleScriptingCommandsTable[])(void); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8d6dd5bdb..6662cb269 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12068,37 +12068,44 @@ static void Cmd_jumpifhasnohp(void) static void Cmd_getsecretpowereffect(void) { + gBattleScripting.moveEffect = GetSecretPowerMoveEffect(); + gBattlescriptCurrInstr++; +} + +u16 GetSecretPowerMoveEffect(void) +{ + u16 moveEffect; switch (gBattleTerrain) { case BATTLE_TERRAIN_GRASS: - gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP; + moveEffect = MOVE_EFFECT_SLEEP; break; case BATTLE_TERRAIN_LONG_GRASS: - gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP; + moveEffect = MOVE_EFFECT_SLEEP; break; case BATTLE_TERRAIN_SAND: - gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1; + moveEffect = MOVE_EFFECT_ACC_MINUS_1; break; case BATTLE_TERRAIN_UNDERWATER: - gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; + moveEffect = MOVE_EFFECT_ATK_MINUS_1; break; case BATTLE_TERRAIN_WATER: - gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; + moveEffect = MOVE_EFFECT_ATK_MINUS_1; break; case BATTLE_TERRAIN_POND: - gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; + moveEffect = MOVE_EFFECT_ATK_MINUS_1; break; case BATTLE_TERRAIN_MOUNTAIN: - gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1; + moveEffect = MOVE_EFFECT_ACC_MINUS_1; break; case BATTLE_TERRAIN_CAVE: - gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; + moveEffect = MOVE_EFFECT_FLINCH; break; default: - gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; + moveEffect = MOVE_EFFECT_PARALYSIS; break; } - gBattlescriptCurrInstr++; + return moveEffect; } static void Cmd_pickup(void) From 563ce8f416080d18c0807d76bde4a3dfab0f0c99 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 4 Oct 2021 21:32:08 -0300 Subject: [PATCH 09/45] Field terrain move effect --- src/battle_script_commands.c | 83 +++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6662cb269..80bb69ecc 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8709,7 +8709,7 @@ static void Cmd_various(void) else gBattlescriptCurrInstr += 7; // can heal return; - case VARIOUS_REMOVE_TERRAIN: + case VARIOUS_REMOVE_TERRAIN: switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { case STATUS_FIELD_MISTY_TERRAIN: @@ -12075,35 +12075,60 @@ static void Cmd_getsecretpowereffect(void) u16 GetSecretPowerMoveEffect(void) { u16 moveEffect; - switch (gBattleTerrain) + u32 fieldTerrain = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY; + if (fieldTerrain) { - case BATTLE_TERRAIN_GRASS: - moveEffect = MOVE_EFFECT_SLEEP; - break; - case BATTLE_TERRAIN_LONG_GRASS: - moveEffect = MOVE_EFFECT_SLEEP; - break; - case BATTLE_TERRAIN_SAND: - moveEffect = MOVE_EFFECT_ACC_MINUS_1; - break; - case BATTLE_TERRAIN_UNDERWATER: - moveEffect = MOVE_EFFECT_ATK_MINUS_1; - break; - case BATTLE_TERRAIN_WATER: - moveEffect = MOVE_EFFECT_ATK_MINUS_1; - break; - case BATTLE_TERRAIN_POND: - moveEffect = MOVE_EFFECT_ATK_MINUS_1; - break; - case BATTLE_TERRAIN_MOUNTAIN: - moveEffect = MOVE_EFFECT_ACC_MINUS_1; - break; - case BATTLE_TERRAIN_CAVE: - moveEffect = MOVE_EFFECT_FLINCH; - break; - default: - moveEffect = MOVE_EFFECT_PARALYSIS; - break; + switch (fieldTerrain) + { + case STATUS_FIELD_MISTY_TERRAIN: + moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1; + break; + case STATUS_FIELD_GRASSY_TERRAIN: + moveEffect = MOVE_EFFECT_SLEEP; + break; + case STATUS_FIELD_ELECTRIC_TERRAIN: + moveEffect = MOVE_EFFECT_PARALYSIS; + break; + case STATUS_FIELD_PSYCHIC_TERRAIN: + moveEffect = MOVE_EFFECT_SPD_MINUS_1; + break; + default: + moveEffect = MOVE_EFFECT_PARALYSIS; + break; + } + } + else + { + switch (gBattleTerrain) + { + case BATTLE_TERRAIN_GRASS: + moveEffect = MOVE_EFFECT_SLEEP; + break; + case BATTLE_TERRAIN_LONG_GRASS: + moveEffect = MOVE_EFFECT_SLEEP; + break; + case BATTLE_TERRAIN_SAND: + moveEffect = MOVE_EFFECT_ACC_MINUS_1; + break; + case BATTLE_TERRAIN_UNDERWATER: + moveEffect = MOVE_EFFECT_ATK_MINUS_1; + break; + case BATTLE_TERRAIN_WATER: + moveEffect = MOVE_EFFECT_ATK_MINUS_1; + break; + case BATTLE_TERRAIN_POND: + moveEffect = MOVE_EFFECT_ATK_MINUS_1; + break; + case BATTLE_TERRAIN_MOUNTAIN: + moveEffect = MOVE_EFFECT_ACC_MINUS_1; + break; + case BATTLE_TERRAIN_CAVE: + moveEffect = MOVE_EFFECT_FLINCH; + break; + default: + moveEffect = MOVE_EFFECT_PARALYSIS; + break; + } } return moveEffect; } From e2bf660c97a21d1b2ed8ebc33e9f4d464c104680 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 4 Oct 2021 21:51:51 -0300 Subject: [PATCH 10/45] Secret Power field terrain animations --- data/battle_anim_scripts.s | 23 ++++++++++++++--------- src/battle_anim_utility_funcs.c | 6 ++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index d7de92096..c7b4020f3 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -23251,16 +23251,21 @@ Move_SKY_UPPERCUT: end Move_SECRET_POWER: + createvisualtask AnimTask_GetFieldTerrain, 5 + jumpargeq 0, STATUS_FIELD_MISTY_TERRAIN, Move_FAIRY_WIND + jumpargeq 0, STATUS_FIELD_GRASSY_TERRAIN, Move_NEEDLE_ARM + jumpargeq 0, STATUS_FIELD_ELECTRIC_TERRAIN, Move_THUNDER_SHOCK + jumpargeq 0, STATUS_FIELD_PSYCHIC_TERRAIN, Move_CONFUSION createvisualtask AnimTask_GetBattleTerrain, 5 - jumpargeq 0, BATTLE_TERRAIN_GRASS, Move_NEEDLE_ARM - jumpargeq 0, BATTLE_TERRAIN_LONG_GRASS, Move_MAGICAL_LEAF - jumpargeq 0, BATTLE_TERRAIN_SAND, Move_MUD_SHOT - jumpargeq 0, BATTLE_TERRAIN_UNDERWATER, Move_WATERFALL - jumpargeq 0, BATTLE_TERRAIN_WATER, Move_SURF - jumpargeq 0, BATTLE_TERRAIN_POND, Move_BUBBLE_BEAM - jumpargeq 0, BATTLE_TERRAIN_MOUNTAIN, Move_ROCK_THROW - jumpargeq 0, BATTLE_TERRAIN_CAVE, Move_BITE - jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_STRENGTH + jumpargeq 0, BATTLE_TERRAIN_GRASS, Move_NEEDLE_ARM + jumpargeq 0, BATTLE_TERRAIN_LONG_GRASS, Move_MAGICAL_LEAF + jumpargeq 0, BATTLE_TERRAIN_SAND, Move_MUD_SHOT + jumpargeq 0, BATTLE_TERRAIN_UNDERWATER, Move_WATERFALL + jumpargeq 0, BATTLE_TERRAIN_WATER, Move_SURF + jumpargeq 0, BATTLE_TERRAIN_POND, Move_BUBBLE_BEAM + jumpargeq 0, BATTLE_TERRAIN_MOUNTAIN, Move_ROCK_THROW + jumpargeq 0, BATTLE_TERRAIN_CAVE, Move_BITE + jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_STRENGTH goto Move_SLAM Move_TWISTER: diff --git a/src/battle_anim_utility_funcs.c b/src/battle_anim_utility_funcs.c index 6cefba92a..0f35657db 100644 --- a/src/battle_anim_utility_funcs.c +++ b/src/battle_anim_utility_funcs.c @@ -904,6 +904,12 @@ void AnimTask_GetBattleTerrain(u8 taskId) DestroyAnimVisualTask(taskId); } +void AnimTask_GetFieldTerrain(u8 taskId) +{ + gBattleAnimArgs[0] = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY; + DestroyAnimVisualTask(taskId); +} + void AnimTask_AllocBackupPalBuffer(u8 taskId) { gMonSpritesGfxPtr->buffer = AllocZeroed(0x2000); From aa7484bba0441ebd3e0974037610ef987953692b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 4 Oct 2021 22:07:28 -0300 Subject: [PATCH 11/45] Camouflage with field terrains. --- src/battle_script_commands.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 80bb69ecc..1da3248d8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11484,13 +11484,13 @@ static void Cmd_callterrainattack(void) // nature power u16 GetNaturePowerMove(void) { if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) - return MOVE_MOONBLAST; + return MOVE_MOONBLAST; else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) - return MOVE_THUNDERBOLT; + return MOVE_THUNDERBOLT; else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) - return MOVE_ENERGY_BALL; + return MOVE_ENERGY_BALL; else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) - return MOVE_PSYCHIC; + return MOVE_PSYCHIC; return sNaturePowerMoves[gBattleTerrain]; } @@ -12358,10 +12358,30 @@ bool32 CanCamouflage(u8 battlerId) static void Cmd_settypetoterrain(void) { - if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, sTerrainToType[gBattleTerrain])) + u8 terrainType; + switch(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { - SET_BATTLER_TYPE(gBattlerAttacker, sTerrainToType[gBattleTerrain]); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, sTerrainToType[gBattleTerrain]); + case STATUS_FIELD_ELECTRIC_TERRAIN: + terrainType = TYPE_ELECTRIC; + break; + case STATUS_FIELD_GRASSY_TERRAIN: + terrainType = TYPE_GRASS; + break; + case STATUS_FIELD_MISTY_TERRAIN: + terrainType = TYPE_FAIRY; + break; + case STATUS_FIELD_PSYCHIC_TERRAIN: + terrainType = TYPE_PSYCHIC; + break; + default: + terrainType = sTerrainToType[gBattleTerrain]; + break; + } + + if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, terrainType)) + { + SET_BATTLER_TYPE(gBattlerAttacker, terrainType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, terrainType); gBattlescriptCurrInstr += 5; } From 43d42c95cfa0c7318a0748ee6a04af2ec30aa4db Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 4 Oct 2021 22:45:37 -0300 Subject: [PATCH 12/45] Terrain Pulse effect implemented --- data/battle_anim_scripts.s | 2 +- data/battle_scripts_1.s | 1 + include/constants/battle_move_effects.h | 3 ++- src/battle_main.c | 17 +++++++++++++++++ src/battle_util.c | 5 +++++ src/data/battle_moves.h | 2 +- 6 files changed, 27 insertions(+), 3 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index c7b4020f3..0b630072a 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -13979,7 +13979,7 @@ Move_RISING_VOLTAGE:: end @to do: Move_TERRAIN_PULSE:: - end @to do: + goto Move_DRAGON_PULSE @Temporary, needs to setup different animations based on terrain Move_SKITTER_SMACK:: end @to do: diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 5a9aec525..f018ff504 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -379,6 +379,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectDecorate @ EFFECT_DECORATE .4byte BattleScript_EffectHit @ EFFECT_SNIPE_SHOT .4byte BattleScript_EffectTripleHit @ EFFECT_TRIPLE_HIT + .4byte BattleScript_EffectHit @ EFFECT_TERRAIN_PULSE BattleScript_EffectDecorate: attackcanceler diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 440e6e76b..966d35971 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -363,7 +363,8 @@ #define EFFECT_DECORATE 357 #define EFFECT_SNIPE_SHOT 358 #define EFFECT_TRIPLE_HIT 359 +#define EFFECT_TERRAIN_PULSE 360 -#define NUM_BATTLE_MOVE_EFFECTS 360 +#define NUM_BATTLE_MOVE_EFFECTS 361 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_main.c b/src/battle_main.c index 25db65f78..c7a5962ac 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5095,6 +5095,23 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk) if (ItemId_GetPocket(gBattleMons[battlerAtk].item) == POCKET_BERRIES) gBattleStruct->dynamicMoveType = gNaturalGiftTable[ITEM_TO_BERRY(gBattleMons[battlerAtk].item)].type; } + else if (gBattleMoves[move].effect == EFFECT_TERRAIN_PULSE) + { + if ((gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + && IsBattlerGrounded(battlerAtk)) + { + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | 0x80; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + gBattleStruct->dynamicMoveType = TYPE_GRASS | 0x80; + else if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + gBattleStruct->dynamicMoveType = TYPE_FAIRY | 0x80; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + gBattleStruct->dynamicMoveType = TYPE_PSYCHIC | 0x80; + else + gBattleStruct->dynamicMoveType = TYPE_NORMAL | 0x80; + } + } attackerAbility = GetBattlerAbility(battlerAtk); GET_MOVE_TYPE(move, moveType); diff --git a/src/battle_util.c b/src/battle_util.c index 462b58bd4..5ae5d80cb 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7572,6 +7572,11 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower *= 2; #endif break; + case EFFECT_TERRAIN_PULSE: + if ((gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + && IsBattlerGrounded(gBattlerAttacker)) + basePower *= 2; + break; } // move-specific base power changes diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index a7a2752e0..542594e80 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11332,7 +11332,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_TERRAIN_PULSE] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_TERRAIN_PULSE, .power = 50, .type = TYPE_NORMAL, .accuracy = 100, From d5b5090d521522abe6d7d377b1475ebdee68dcc3 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Wed, 27 Oct 2021 09:36:00 -0300 Subject: [PATCH 13/45] Fixed BattleScript_EffectPhotonGeyser --- data/battle_scripts_1.s | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 447c329e0..c6ae2e848 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -399,7 +399,28 @@ BattleScript_EffectShellSideArm: goto BattleScript_EffectHit BattleScript_EffectPhotonGeyser: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + critcalc + damagecalc + adjustdamage photongeysercheck + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage B_WAIT_TIME_LONG + resultmessage + waitmessage B_WAIT_TIME_LONG + seteffectwithchance + tryfaintmon BS_TARGET, FALSE, NULL + goto BattleScript_MoveEnd BattleScript_EffectPlasmaFists: attackcanceler From ad95fa3d15abfe3080e00beab69225c2bc288bf7 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Wed, 27 Oct 2021 10:03:27 -0300 Subject: [PATCH 14/45] Updated Shell Side Arm's description --- src/data/text/move_descriptions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/text/move_descriptions.h b/src/data/text/move_descriptions.h index e204fb196..037261e32 100644 --- a/src/data/text/move_descriptions.h +++ b/src/data/text/move_descriptions.h @@ -2839,7 +2839,7 @@ static const u8 sMETEOR_BEAMDescription[] = _( "Sp. Attack before attacking."); static const u8 sSHELL_SIDE_ARMDescription[] = _( - "Uses higher of physical and\n" + "Deals better of physical and\n" "special damage. May poison."); static const u8 sMISTY_EXPLOSIONDescription[] = _( From de157919b060e70cb430050b176ef487c28b0753 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Wed, 27 Oct 2021 11:05:01 -0300 Subject: [PATCH 15/45] Added animations for Shell Side Arm --- data/battle_anim_scripts.s | 45 +++++++++++++++++++++++++++++++++++++- src/battle_anim_new.c | 9 ++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 994bc5cc1..30a4ccc61 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -13995,7 +13995,50 @@ Move_METEOR_BEAM:: end @to do: Move_SHELL_SIDE_ARM:: - end @to do: + launchtask AnimTask_ShellSideArm 0x5 0x0 + jumpargeq 0x0, TRUE, Move_SHELL_SIDE_ARM_PHYSICAL + jumpargeq 0x0, FALSE, Move_SHELL_SIDE_ARM_SPECIAL +Move_SHELL_SIDE_ARM_PHYSICAL: @ Modified Body Slam, placeholder + loadspritegfx ANIM_TAG_IMPACT + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_IMPACT, 0, 6, 6, RGB_MAGENTA + monbg ANIM_DEF_PARTNER + setalpha 12, 8 + playsewithpan SE_M_TAKE_DOWN, SOUND_PAN_ATTACKER + createsprite gVerticalDipSpriteTemplate, ANIM_ATTACKER, 2, 6, 1, ANIM_ATTACKER + waitforvisualfinish + delay 11 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 26, 0, 0, 5 + delay 6 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 4, -10, 0, ANIM_TARGET, 0 + loopsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET, 10, 2 + delay 1 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -28, 0, 0, 3 + waitforvisualfinish + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + waitforvisualfinish + delay 10 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 6 + delay 5 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 6 + waitforvisualfinish + clearmonbg ANIM_DEF_PARTNER + blendoff + end +Move_SHELL_SIDE_ARM_SPECIAL: @ Modified Snipe Shot, placeholder + loadspritegfx ANIM_TAG_IMPACT_2 + loadspritegfx ANIM_TAG_LEER + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_IMPACT_2, 0, 6, 6, RGB_MAGENTA + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_LEER, 0, 6, 6, RGB_MAGENTA + launchtemplate gLeerSpriteTemplate 0x82, 2 0x18 -12 + playsewithpan SE_M_DETECT, SOUND_PAN_ATTACKER + waitforvisualfinish + delay 0x20 + playsewithpan SE_M_GIGA_DRAIN, SOUND_PAN_TARGET + launchtemplate gSnipeShotBallTemplate 0x82, 3, 0 0 24, + waitforvisualfinish + launchtask AnimTask_ShakeMon2 2 5 1 4 0 8, 1 + waitforvisualfinish + end Move_MISTY_EXPLOSION:: end @to do: diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index d04483e6b..3bc45939f 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -5064,3 +5064,12 @@ void AnimTask_PrimalReversion(u8 taskId) gBattleAnimArgs[0] = 0; DestroyAnimVisualTask(taskId); } + +void AnimTask_ShellSideArm(u8 taskId) +{ + if (gSwapDamageCategory) + gBattleAnimArgs[0] = TRUE; + else + gBattleAnimArgs[0] = FALSE; + DestroyAnimVisualTask(taskId); +} From 8c35a6806014cede7354f0e6c47eb075223ce507 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Wed, 27 Oct 2021 11:19:39 -0300 Subject: [PATCH 16/45] Quick syntax tweaks --- asm/macros/battle_script.inc | 16 ++++++++-------- include/battle.h | 1 - src/battle_util.c | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index b838cb6d2..4a8570a1a 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1731,14 +1731,6 @@ .4byte \ptr .endm - .macro photongeysercheck - various BS_ATTACKER, VARIOUS_PHOTON_GEYSER_CHECK - .endm - - .macro shellsidearmcheck - various BS_ATTACKER, VARIOUS_SHELL_SIDE_ARM_CHECK - .endm - .macro trysetfairylock ptr:req various BS_ATTACKER, VARIOUS_TRY_FAIRY_LOCK .4byte \ptr @@ -1866,6 +1858,14 @@ various BS_ATTACKER, VARIOUS_APPLY_PLASMA_FISTS .endm + .macro photongeysercheck + various BS_ATTACKER, VARIOUS_PHOTON_GEYSER_CHECK + .endm + + .macro shellsidearmcheck + various BS_ATTACKER, VARIOUS_SHELL_SIDE_ARM_CHECK + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/include/battle.h b/include/battle.h index 00b2c2f25..b5dabaded 100644 --- a/include/battle.h +++ b/include/battle.h @@ -918,7 +918,6 @@ extern u8 gBattleControllerData[MAX_BATTLERS_COUNT]; extern bool8 gHasFetchedBall; extern u8 gLastUsedBall; extern u16 gLastThrownBall; - extern bool8 gSwapDamageCategory; // Photon Geyser, Shell Side Arm, Light That Burns the Sky #endif // GUARD_BATTLE_H diff --git a/src/battle_util.c b/src/battle_util.c index f79ce62b2..7797b4751 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7271,7 +7271,7 @@ bool32 IsMoveMakingContact(u16 move, u8 battlerAtk) { if (!(gBattleMoves[move].flags & FLAG_MAKES_CONTACT)) { - if (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gSwapDamageCategory == TRUE) + if (gBattleMoves[move].effect == EFFECT_SHELL_SIDE_ARM && gSwapDamageCategory) return TRUE; else return FALSE; @@ -9077,7 +9077,7 @@ bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 battlerId) u8 GetBattleMoveSplit(u32 moveId) { - if (gSwapDamageCategory == TRUE) // Photon Geyser, Shell Side Arm, Light That Burns the Sky + if (gSwapDamageCategory) // Photon Geyser, Shell Side Arm, Light That Burns the Sky return SPLIT_PHYSICAL; else if (IS_MOVE_STATUS(moveId) || B_PHYSICAL_SPECIAL_SPLIT >= GEN_4) return gBattleMoves[moveId].split; From 74c85b581890f014a6031f233494fa37e96a4b3b Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 3 Nov 2021 17:23:33 +1300 Subject: [PATCH 17/45] Implement Relic Song's form change Meloetta transforms into its pirouette form after using Relic Song, unless it has Sheer Force or the move has no effect. It also has a chance to put both targets to sleep. --- data/battle_scripts_1.s | 40 ++++++++++++++++++++++--- include/battle_scripts.h | 1 + include/constants/battle.h | 3 +- include/constants/battle_config.h | 2 ++ include/constants/battle_move_effects.h | 2 +- src/battle_ai_main.c | 2 +- src/battle_script_commands.c | 10 +++++++ src/battle_util.c | 5 ++-- src/data/battle_moves.h | 3 +- 9 files changed, 58 insertions(+), 10 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index df0048ad9..5bdada7b8 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -367,7 +367,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectGeomancy @ EFFECT_GEOMANCY .4byte BattleScript_EffectFairyLock @ EFFECT_FAIRY_LOCK .4byte BattleScript_EffectAllySwitch @ EFFECT_ALLY_SWITCH - .4byte BattleScript_EffectSleepHit @ EFFECT_SLEEP_HIT + .4byte BattleScript_EffectRelicSong @ EFFECT_RELIC_SONG .4byte BattleScript_EffectAttackerDefenseDownHit @ EFFECT_ATTACKER_DEFENSE_DOWN_HIT .4byte BattleScript_EffectHit @ EFFECT_BODY_PRESS .4byte BattleScript_EffectEerieSpell @ EFFECT_EERIE_SPELL @@ -734,9 +734,30 @@ BattleScript_EffectAttackerDefenseDownHit: setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN goto BattleScript_EffectHit -BattleScript_EffectSleepHit: - setmoveeffect MOVE_EFFECT_SLEEP - goto BattleScript_EffectHit +BattleScript_EffectRelicSong: + setmoveeffect MOVE_EFFECT_RELIC_SONG | MOVE_EFFECT_CERTAIN + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage B_WAIT_TIME_LONG + resultmessage + waitmessage B_WAIT_TIME_LONG + seteffectwithchance + argumentstatuseffect + tryfaintmon BS_TARGET, FALSE, NULL + goto BattleScript_MoveEnd BattleScript_EffectAllySwitch: attackcanceler @@ -6939,6 +6960,17 @@ BattleScript_AttackerFormChangeEnd3:: call BattleScript_AttackerFormChange end3 +BattleScript_AttackerFormChangeMoveEffect:: + waitmessage 1 + handleformchange BS_ATTACKER, 0 + handleformchange BS_ATTACKER, 1 + playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE, NULL + waitanimation + printstring STRINGID_PKMNTRANSFORMED + waitmessage B_WAIT_TIME_LONG + handleformchange BS_ATTACKER, 2 + end3 + BattleScript_BallFetch:: call BattleScript_AbilityPopUp printstring STRINGID_FETCHEDPOKEBALL diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 403af9515..753dc5127 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -404,5 +404,6 @@ extern const u8 BattleScript_PrimalReversion[]; extern const u8 BattleScript_HyperspaceFuryRemoveProtect[]; extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[]; extern const u8 BattleScript_WanderingSpiritActivates[]; +extern const u8 BattleScript_AttackerFormChangeMoveEffect[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 918c3e7f0..438b5660c 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -357,7 +357,8 @@ #define MOVE_EFFECT_INCINERATE 0x44 #define MOVE_EFFECT_BUG_BITE 0x45 #define MOVE_EFFECT_RECOIL_HP_25 0x46 -#define NUM_MOVE_EFFECTS 0x47 +#define MOVE_EFFECT_RELIC_SONG 0x47 +#define NUM_MOVE_EFFECTS 0x48 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 41fee089d..0e7b75d6d 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -47,6 +47,8 @@ #define SPECIES_GRENINJA_ASH 10017 #define SPECIES_HOOPA 0 #define SPECIES_HOOPA_UNBOUND 10018 + #define SPECIES_MELOETTA 0 + #define SPECIES_MELOETTA_PIROUETTE 10019 #endif // Items with peculiar battle effects. diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 62b49a191..8d3df5ec0 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -350,7 +350,7 @@ #define EFFECT_GEOMANCY 344 #define EFFECT_FAIRY_LOCK 345 #define EFFECT_ALLY_SWITCH 346 -#define EFFECT_SLEEP_HIT 347 +#define EFFECT_RELIC_SONG 347 #define EFFECT_ATTACKER_DEFENSE_DOWN_HIT 348 #define EFFECT_BODY_PRESS 349 #define EFFECT_EERIE_SPELL 350 diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 84fa7b634..c06bb7394 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4305,7 +4305,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (!IsBattlerGrounded(battlerDef)) score += 3; break; - case EFFECT_SLEEP_HIT: // Relic Song + case EFFECT_RELIC_SONG: #if (defined SPECIES_MELOETTA && defined SPECIES_MELOETTA_PIROUETTE) if (AI_DATA->atkSpecies == SPECIES_MELOETTA && gBattleMons[battlerDef].defense < gBattleMons[battlerDef].spDefense) score += 3; // Change to pirouette if can do more damage diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 9e779da1b..d88bf9944 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3393,6 +3393,13 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite; } break; + case MOVE_EFFECT_RELIC_SONG: + if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA) + { + gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA_PIROUETTE; + BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeMoveEffect); + } + break; } } } @@ -8282,6 +8289,9 @@ static void Cmd_various(void) case VARIOUS_ARGUMENT_STATUS_EFFECT: switch (gBattleMoves[gCurrentMove].argument) { + case STATUS1_SLEEP: + gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP; + break; case STATUS1_BURN: gBattleScripting.moveEffect = MOVE_EFFECT_BURN; break; diff --git a/src/battle_util.c b/src/battle_util.c index 224cb1af1..ca1021dfa 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8957,6 +8957,7 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) { {SPECIES_MIMIKYU_BUSTED, SPECIES_MIMIKYU}, {SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND}, + {SPECIES_MELOETTA_PIROUETTE, SPECIES_MELOETTA}, {SPECIES_AEGISLASH_BLADE, SPECIES_AEGISLASH}, {SPECIES_DARMANITAN_ZEN_MODE, SPECIES_DARMANITAN}, {SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED}, @@ -8971,8 +8972,8 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) {SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT}, }; - if (isSwitchingOut) // Don't revert Mimikyu Busted or Ash-Greninja when switching out - i = 2; + if (isSwitchingOut) // Don't revert Mimikyu, Greninja, Meloetta when switching out + i = 3; else i = 0; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 97d61202a..0d3f23168 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -8614,7 +8614,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_RELIC_SONG] = { - .effect = EFFECT_SLEEP_HIT, + .effect = EFFECT_RELIC_SONG, .power = 75, .type = TYPE_NORMAL, .accuracy = 100, @@ -8624,6 +8624,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_SOUND | FLAG_SHEER_FORCE_BOOST, .split = SPLIT_SPECIAL, + .argument = STATUS1_SLEEP, }, [MOVE_SECRET_SWORD] = From 18b87416d5f2a9b912a9ade9b932e9a25893ce68 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 3 Nov 2021 17:56:16 +1300 Subject: [PATCH 18/45] Fixes - Fix Sheer Force interaction (needed after adding | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN) - Fix "X Transformed!" target - Allow switching between both forms - Allow form change if target is KO'ed --- data/battle_scripts_1.s | 3 ++- src/battle_script_commands.c | 14 +++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 5bdada7b8..7e52d7d06 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -735,7 +735,7 @@ BattleScript_EffectAttackerDefenseDownHit: goto BattleScript_EffectHit BattleScript_EffectRelicSong: - setmoveeffect MOVE_EFFECT_RELIC_SONG | MOVE_EFFECT_CERTAIN + setmoveeffect MOVE_EFFECT_RELIC_SONG | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring @@ -6966,6 +6966,7 @@ BattleScript_AttackerFormChangeMoveEffect:: handleformchange BS_ATTACKER, 1 playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE, NULL waitanimation + copybyte sBATTLER, gBattlerAttacker printstring STRINGID_PKMNTRANSFORMED waitmessage B_WAIT_TIME_LONG handleformchange BS_ATTACKER, 2 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d88bf9944..d510a2746 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3394,10 +3394,18 @@ void SetMoveEffect(bool32 primary, u32 certain) } break; case MOVE_EFFECT_RELIC_SONG: - if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA) + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SHEER_FORCE) { - gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA_PIROUETTE; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeMoveEffect); + if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA) + { + gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA_PIROUETTE; + BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeMoveEffect); + } + else if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA_PIROUETTE) + { + gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA; + BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeMoveEffect); + } } break; } From 24cb5f66548656ff3d4af5f7f2014a15475e2ed2 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 4 Nov 2021 15:45:03 -0400 Subject: [PATCH 19/45] dont trigger x_up_hit effect if battle is over --- src/battle_script_commands.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6f0fec8a7..861f2b8c4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2992,7 +2992,8 @@ void SetMoveEffect(bool32 primary, u32 certain) case MOVE_EFFECT_SP_DEF_PLUS_1: case MOVE_EFFECT_ACC_PLUS_1: case MOVE_EFFECT_EVS_PLUS_1: - if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1), + if (NoAliveMonsForEitherParty() + || ChangeStatBuffs(SET_STAT_BUFF_VALUE(1), gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_1 + 1, affectsUser, 0)) { @@ -3153,8 +3154,15 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattlescriptCurrInstr++; break; case MOVE_EFFECT_ALL_STATS_UP: - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_AllStatsUp; + if (NoAliveMonsForEitherParty()) + { + gBattlescriptCurrInstr++; + } + else + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_AllStatsUp; + } break; case MOVE_EFFECT_RAPIDSPIN: BattleScriptPush(gBattlescriptCurrInstr + 1); From 671cbabc3daa2fe217e26fa1598778f2c418ab7f Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 4 Nov 2021 17:18:26 -0300 Subject: [PATCH 20/45] Added a battle config for the Soul Dew --- include/constants/battle_config.h | 1 + src/battle_util.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 41fee089d..792d12a9b 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -166,6 +166,7 @@ #define B_X_ITEMS_BUFF GEN_7 // In Gen7+, the X Items raise a stat by 2 stages instead of 1. #define B_MENTAL_HERB GEN_5 // In Gen5+, the Mental Herb cures Infatuation, Taunt, Encore, Torment, Heal Block, and Disable #define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items. +#define B_SOUL_DEW_BOOST GEN_7 // In Gens3-6, Soul Dew boosts the power of Lati@s' stats. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead. // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. diff --git a/src/battle_util.c b/src/battle_util.c index 5a9d47df9..f2b186002 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8059,7 +8059,10 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe MulModifier(&modifier, holdEffectModifier); break; case HOLD_EFFECT_SOUL_DEW: - if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER)) + if (((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) + && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && B_SOUL_DEW_BOOST <= GEN_6) + || ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) + && (moveType == TYPE_PSYCHIC || moveType == TYPE_DRAGON) && B_SOUL_DEW_BOOST >= GEN_7)) MulModifier(&modifier, holdEffectModifier); break; case HOLD_EFFECT_GEMS: From 9a3739d2bdc439c9189ad8d62b6ee480be09347c Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 4 Nov 2021 21:00:39 -0300 Subject: [PATCH 21/45] Review changes --- src/battle_util.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index f2b186002..c9fefe61b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8059,10 +8059,11 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe MulModifier(&modifier, holdEffectModifier); break; case HOLD_EFFECT_SOUL_DEW: - if (((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) - && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && B_SOUL_DEW_BOOST <= GEN_6) - || ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) - && (moveType == TYPE_PSYCHIC || moveType == TYPE_DRAGON) && B_SOUL_DEW_BOOST >= GEN_7)) + #if B_SOUL_DEW_BOOST >= GEN_7 + if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && (moveType == TYPE_PSYCHIC || moveType == TYPE_DRAGON)) + #else + if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER)) + #endif MulModifier(&modifier, holdEffectModifier); break; case HOLD_EFFECT_GEMS: @@ -8475,6 +8476,14 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, if (!usesDefStat) MulModifier(&modifier, UQ_4_12(1.5)); break; +#if B_SOUL_DEW_BOOST <= GEN_6 + case HOLD_EFFECT_SOUL_DEW: + if ((gBattleMons[battlerDef].species == SPECIES_LATIAS || gBattleMons[battlerDef].species == SPECIES_LATIOS) + && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) + && !usesDefStat) + MulModifier(&modifier, UQ_4_12(1.5)); + break; +#endif } // sandstorm sp.def boost for rock types From bf786c6c9a8069be877aea3b5723d7a46660b7cb Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Fri, 5 Nov 2021 18:22:52 +1300 Subject: [PATCH 22/45] Fix Magma Storm Fix the strings and animation displayed when Magma Storm. Also move gTrappingMoves to battle_script_message.c as it's only sued in this file, and this allows ARRAY_COUNT(sTrappingMoves) to replace the constant in SetMoveEffect. --- data/battle_anim_scripts.s | 27 +++++++++++++++++++++++++++ include/battle_message.h | 1 - include/constants/battle_anim.h | 3 ++- include/constants/battle_string_ids.h | 2 +- src/battle_anim_throw.c | 2 ++ src/battle_message.c | 24 ++++++++++-------------- src/battle_script_commands.c | 9 +++++++-- 7 files changed, 49 insertions(+), 19 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index cfe95371d..4198f6410 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -24037,6 +24037,7 @@ General_TurnTrap: jumpargeq 0, TRAP_ANIM_WHIRLPOOL, Status_Whirlpool jumpargeq 0, TRAP_ANIM_CLAMP, Status_Clamp jumpargeq 0, TRAP_ANIM_SAND_TOMB, Status_SandTomb + jumpargeq 0, TRAP_ANIM_MAGMA_STORM, Status_MagmaStorm jumpargeq 0, TRAP_ANIM_INFESTATION, Status_Infestation goto Status_BindWrap Status_BindWrap: @@ -24063,6 +24064,32 @@ Status_FireSpin: stopsound end +Status_MagmaStorm: + loadspritegfx ANIM_TAG_SMALL_EMBER + fadetobg BG_MAGMA_STORM + waitbgfadeout + createvisualtask AnimTask_MoveSeismicTossBg, 3 + playsewithpan SE_M_SACRED_FIRE2, SOUND_PAN_TARGET + loopsewithpan SE_M_SACRED_FIRE2, SOUND_PAN_TARGET, 5, 8 + createvisualtask AnimTask_SeismicTossBgAccelerateDownAtEnd, 3 + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 2, 47, 1 + createvisualtask AnimTask_BlendColorCycle, 2, 6, 4, 2, 2, 0, 12, RGB(22, 9, 7) + call FireSpinEffect + call FireSpinEffect + createvisualtask AnimTask_BlendColorCycle, 2, 6, 4, 2, 2, 0, 12, RGB(22, 9, 7) + call FireSpinEffect + call FireSpinEffect + createvisualtask AnimTask_BlendColorCycle, 2, 6, 4, 2, 2, 0, 12, RGB(22, 9, 7) + call FireSpinEffect + restorebg + waitbgfadeout + setarg 7, 0xFFF + waitbgfadein + stopsound + clearmonbg ANIM_DEF_PARTNER + blendoff + end + Status_Whirlpool: loadspritegfx ANIM_TAG_WATER_ORB monbg ANIM_DEF_PARTNER diff --git a/include/battle_message.h b/include/battle_message.h index e8b362c9e..5c10f9e04 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -310,6 +310,5 @@ extern const u8 gText_BattleTourney[]; extern const u16 gMissStringIds[]; extern const u16 gStatUpStringIds[]; -extern const u16 gTrappingMoves[]; #endif // GUARD_BATTLE_MESSAGE_H diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index c7871bd15..7df75794e 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -565,7 +565,8 @@ #define TRAP_ANIM_WHIRLPOOL 2 #define TRAP_ANIM_CLAMP 3 #define TRAP_ANIM_SAND_TOMB 4 -#define TRAP_ANIM_INFESTATION 5 +#define TRAP_ANIM_MAGMA_STORM 5 +#define TRAP_ANIM_INFESTATION 6 // Weather defines for battle animation scripts. #define ANIM_WEATHER_NONE 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 74105f3bf..8fba7597c 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -410,7 +410,7 @@ #define STRINGID_PKMNTWISTEDDIMENSIONS 406 #define STRINGID_POINTEDSTONESFLOAT 407 #define STRINGID_CLOAKEDINMYSTICALMOONLIGHT 408 -#define STRINGID_TRAPPERBYSWIRLINGMAGMA 409 +#define STRINGID_TRAPPEDBYSWIRLINGMAGMA 409 #define STRINGID_VANISHEDINSTANTLY 410 #define STRINGID_PROTECTEDTEAM 411 #define STRINGID_SHAREDITSGUARD 412 diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index 207d1255d..f325cba07 100755 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -2496,6 +2496,8 @@ void AnimTask_GetTrappedMoveAnimId(u8 taskId) gBattleAnimArgs[0] = TRAP_ANIM_CLAMP; else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_SAND_TOMB) gBattleAnimArgs[0] = TRAP_ANIM_SAND_TOMB; + else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_MAGMA_STORM) + gBattleAnimArgs[0] = TRAP_ANIM_MAGMA_STORM; else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_INFESTATION) gBattleAnimArgs[0] = TRAP_ANIM_INFESTATION; else diff --git a/src/battle_message.c b/src/battle_message.c index 60b7f5203..f52f6be7e 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1200,7 +1200,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_PKMNTWISTEDDIMENSIONS - 12] = sText_PkmnTwistedDimensions, [STRINGID_POINTEDSTONESFLOAT - 12] = sText_PointedStonesFloat, [STRINGID_CLOAKEDINMYSTICALMOONLIGHT - 12] = sText_CloakedInMysticalMoonlight, - [STRINGID_TRAPPERBYSWIRLINGMAGMA - 12] = sText_TrappedBySwirlingMagma, + [STRINGID_TRAPPEDBYSWIRLINGMAGMA - 12] = sText_TrappedBySwirlingMagma, [STRINGID_VANISHEDINSTANTLY - 12] = sText_VanishedInstantly, [STRINGID_PROTECTEDTEAM - 12] = sText_ProtectedTeam, [STRINGID_SHAREDITSGUARD - 12] = sText_SharedItsGuard, @@ -1535,16 +1535,17 @@ const u16 gFirstTurnOfTwoStringIds[] = [B_MSG_TURN1_FREEZE_SHOCK] = STRINGID_CLOAKEDINAFREEZINGLIGHT, }; -// Index copied from move's index in gTrappingMoves +// Index copied from move's index in sTrappingMoves const u16 gWrappedStringIds[] = { - STRINGID_PKMNSQUEEZEDBYBIND, // MOVE_BIND - STRINGID_PKMNWRAPPEDBY, // MOVE_WRAP - STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_FIRE_SPIN - STRINGID_PKMNCLAMPED, // MOVE_CLAMP - STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_WHIRLPOOL - STRINGID_PKMNTRAPPEDBYSANDTOMB,// MOVE_SAND_TOMB - STRINGID_INFESTATION, // MOVE_INFESTATION + STRINGID_PKMNSQUEEZEDBYBIND, // MOVE_BIND + STRINGID_PKMNWRAPPEDBY, // MOVE_WRAP + STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_FIRE_SPIN + STRINGID_PKMNCLAMPED, // MOVE_CLAMP + STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_WHIRLPOOL + STRINGID_PKMNTRAPPEDBYSANDTOMB, // MOVE_SAND_TOMB + STRINGID_TRAPPEDBYSWIRLINGMAGMA, // MOVE_MAGMA_STORM + STRINGID_INFESTATION, // MOVE_INFESTATION }; const u16 gMistUsedStringIds[] = @@ -1755,11 +1756,6 @@ const u16 gCaughtMonStringIds[] = [B_MSG_LANETTES_BOX_FULL] = STRINGID_PKMNBOXLANETTESPCFULL, }; -const u16 gTrappingMoves[] = -{ - MOVE_BIND, MOVE_WRAP, MOVE_FIRE_SPIN, MOVE_CLAMP, MOVE_WHIRLPOOL, MOVE_SAND_TOMB, MOVE_INFESTATION, 0xFFFF -}; - const u16 gRoomsStringIds[] = { STRINGID_PKMNTWISTEDDIMENSIONS, STRINGID_TRICKROOMENDS, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6f0fec8a7..dd49d0493 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -279,6 +279,11 @@ static const s32 sExperienceScalingFactors[] = 159767, }; +static const u16 sTrappingMoves[] = +{ + MOVE_BIND, MOVE_WRAP, MOVE_FIRE_SPIN, MOVE_CLAMP, MOVE_WHIRLPOOL, MOVE_SAND_TOMB, MOVE_MAGMA_STORM, MOVE_INFESTATION, 0xFFFF +}; + #define STAT_CHANGE_WORKED 0 #define STAT_CHANGE_DIDNT_WORK 1 @@ -2978,9 +2983,9 @@ void SetMoveEffect(bool32 primary, u32 certain) for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; ; gBattleCommunication[MULTISTRING_CHOOSER]++) { - if (gBattleCommunication[MULTISTRING_CHOOSER] > 5) + if (gBattleCommunication[MULTISTRING_CHOOSER] > ARRAY_COUNT(sTrappingMoves)) break; - if (gTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove) + if (sTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove) break; } } From 3f1ce399e640c4e43c889e11cded0a1b94a1c90d Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Fri, 5 Nov 2021 18:37:45 +1300 Subject: [PATCH 23/45] Account for terminator in sTrappingMoves --- src/battle_script_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index dd49d0493..b81639db0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2983,7 +2983,7 @@ void SetMoveEffect(bool32 primary, u32 certain) for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; ; gBattleCommunication[MULTISTRING_CHOOSER]++) { - if (gBattleCommunication[MULTISTRING_CHOOSER] > ARRAY_COUNT(sTrappingMoves)) + if (gBattleCommunication[MULTISTRING_CHOOSER] > ARRAY_COUNT(sTrappingMoves) - 1) break; if (sTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove) break; From d15eeeb8eb7724697438e0e2269dc7d53348dbba Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 5 Nov 2021 10:37:41 -0300 Subject: [PATCH 24/45] Fixed the comment for B_SOUL_DEW_BOOST --- include/constants/battle_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 792d12a9b..faf57a40c 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -166,7 +166,7 @@ #define B_X_ITEMS_BUFF GEN_7 // In Gen7+, the X Items raise a stat by 2 stages instead of 1. #define B_MENTAL_HERB GEN_5 // In Gen5+, the Mental Herb cures Infatuation, Taunt, Encore, Torment, Heal Block, and Disable #define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items. -#define B_SOUL_DEW_BOOST GEN_7 // In Gens3-6, Soul Dew boosts the power of Lati@s' stats. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead. +#define B_SOUL_DEW_BOOST GEN_7 // In Gens3-6, Soul Dew boosts Lati@s' Sp. Atk and Sp. Def. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead. // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. From 13029cd3b38049b880212e247234eb2ae2c2cfa5 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 5 Nov 2021 10:50:21 -0300 Subject: [PATCH 25/45] Tweaked VARIOUS_PHOTON_GEYSER_CHECK and VARIOUS_SHELL_SIDE_ARM_CHECK --- src/battle_script_commands.c | 56 ++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 73dcca97c..a89487ce8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8996,50 +8996,50 @@ static void Cmd_various(void) return; case VARIOUS_PHOTON_GEYSER_CHECK: { - u32 attStat = gBattleMons[gActiveBattler].attack; - u8 atkStage = gBattleMons[gActiveBattler].statStages[STAT_ATK]; - u32 spaStat = gBattleMons[gActiveBattler].spAttack; + u32 attackerAtkStat = gBattleMons[gBattlerAttacker].attack; + u8 attackerAtkStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; + u32 attackerSpAtkStat = gBattleMons[gBattlerAttacker].spAttack; - attStat *= gStatStageRatios[atkStage][0]; - attStat /= gStatStageRatios[atkStage][1]; + attackerAtkStat *= gStatStageRatios[attackerAtkStage][0]; + attackerAtkStat /= gStatStageRatios[attackerAtkStage][1]; - atkStage = gBattleMons[gActiveBattler].statStages[STAT_SPATK]; - spaStat *= gStatStageRatios[atkStage][0]; - spaStat /= gStatStageRatios[atkStage][1]; + attackerAtkStage = gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]; + attackerSpAtkStat *= gStatStageRatios[attackerAtkStage][0]; + attackerSpAtkStat /= gStatStageRatios[attackerAtkStage][1]; - if (attStat > spaStat) + if (attackerAtkStat > attackerSpAtkStat) gSwapDamageCategory = TRUE; break; } case VARIOUS_SHELL_SIDE_ARM_CHECK: // 0% chance GameFreak actually checks this way according to DaWobblefet, but this is the only functional explanation at the moment { - u32 attStat = gBattleMons[gBattlerAttacker].attack; - u8 atkStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; - u32 attStatDef = gBattleMons[gBattlerTarget].attack; + u32 attackerAtkStat = gBattleMons[gBattlerAttacker].attack; + u32 targetDefStat = gBattleMons[gBattlerTarget].defense; + u32 attackerSpAtkStat = gBattleMons[gBattlerAttacker].spAttack; + u32 targetSpDefStat = gBattleMons[gBattlerTarget].spDefense; + u8 statStage; u32 physical; - - u32 spaStat = gBattleMons[gBattlerAttacker].spAttack; - u32 spaStatDef = gBattleMons[gBattlerTarget].spAttack; u32 special; - attStat *= gStatStageRatios[atkStage][0]; - attStat /= gStatStageRatios[atkStage][1]; + statStage = = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; + attackerAtkStat *= gStatStageRatios[statStage][0]; + attackerAtkStat /= gStatStageRatios[statStage][1]; - atkStage = gBattleMons[gBattlerTarget].statStages[STAT_ATK]; - attStatDef *= gStatStageRatios[atkStage][0]; - attStatDef /= gStatStageRatios[atkStage][1]; + statStage = gBattleMons[gBattlerTarget].statStages[STAT_ATK]; + targetDefStat *= gStatStageRatios[statStage][0]; + targetDefStat /= gStatStageRatios[statStage][1]; - physical = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * gBattleMoves[gCurrentMove].power * attStat) / attStatDef) / 50); + physical = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * gBattleMoves[gCurrentMove].power * attackerAtkStat) / targetDefStat) / 50); - atkStage = gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]; - spaStat *= gStatStageRatios[atkStage][0]; - spaStat /= gStatStageRatios[atkStage][1]; + statStage = gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]; + attackerSpAtkStat *= gStatStageRatios[statStage][0]; + attackerSpAtkStat /= gStatStageRatios[statStage][1]; - atkStage = gBattleMons[gBattlerTarget].statStages[STAT_SPATK]; - spaStatDef *= gStatStageRatios[atkStage][0]; - spaStatDef /= gStatStageRatios[atkStage][1]; + statStage = gBattleMons[gBattlerTarget].statStages[STAT_SPATK]; + targetSpDefStat *= gStatStageRatios[statStage][0]; + targetSpDefStat /= gStatStageRatios[statStage][1]; - special = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * gBattleMoves[gCurrentMove].power * spaStat) / spaStatDef) / 50); + special = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * gBattleMoves[gCurrentMove].power * attackerSpAtkStat) / targetSpDefStat) / 50); if (((physical > special) || (physical == special && (Random() % 2) == 0))) gSwapDamageCategory = TRUE; From b23d5db5981b100f5d241a3cba3c0fee68b47a1d Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 5 Nov 2021 13:02:16 -0300 Subject: [PATCH 26/45] Oops --- src/battle_script_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 97a7b034f..ec7c6effa 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9032,7 +9032,7 @@ static void Cmd_various(void) u32 physical; u32 special; - statStage = = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; + statStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; attackerAtkStat *= gStatStageRatios[statStage][0]; attackerAtkStat /= gStatStageRatios[statStage][1]; From 14ebba04afd2972b2f79ca89159ff643a7f698d9 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sat, 6 Nov 2021 12:43:57 +1300 Subject: [PATCH 27/45] Align comment with others Co-authored-by: Eduardo Quezada D'Ottone --- data/battle_scripts_1.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 30facd40d..a85b2e2a7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -367,7 +367,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectGeomancy @ EFFECT_GEOMANCY .4byte BattleScript_EffectFairyLock @ EFFECT_FAIRY_LOCK .4byte BattleScript_EffectAllySwitch @ EFFECT_ALLY_SWITCH - .4byte BattleScript_EffectRelicSong @ EFFECT_RELIC_SONG + .4byte BattleScript_EffectRelicSong @ EFFECT_RELIC_SONG .4byte BattleScript_EffectAttackerDefenseDownHit @ EFFECT_ATTACKER_DEFENSE_DOWN_HIT .4byte BattleScript_EffectHit @ EFFECT_BODY_PRESS .4byte BattleScript_EffectEerieSpell @ EFFECT_EERIE_SPELL From 8e49e3e6530d6d738cf0167c51705833f7ef66d3 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Fri, 5 Nov 2021 21:16:13 -0300 Subject: [PATCH 28/45] Config for Synchronize's interaction with toxic poisoning --- include/constants/battle_config.h | 1 + src/battle_util.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 95ff4f4a0..1c7781980 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -162,6 +162,7 @@ #define B_MOODY_ACC_EVASION GEN_8 // In Gen8, Moody CANNOT raise Accuracy and Evasion anymore. #define B_FLASH_FIRE_FROZEN GEN_7 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before. #define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously. +#define B_SYNCHRONIZE_TOXIC GEN_8 // In Gen5+, if the Pokémon with Synchronize is badly poisoned, the opponent will also become badly poisoned. Previously, the opponent would become regular poisoned. #define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities. // Item settings diff --git a/src/battle_util.c b/src/battle_util.c index 0585bb4b6..3ddc2e9bb 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5471,8 +5471,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)) { gBattleStruct->synchronizeMoveEffect &= ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN); - if (gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) - gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; + #if B_SYNCHRONIZE_TOXIC < GEN_5 + if (gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) + gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; + #endif gBattleScripting.moveEffect = gBattleStruct->synchronizeMoveEffect + MOVE_EFFECT_AFFECTS_USER; gBattleScripting.battler = gBattlerAbility = gBattlerTarget; From 202827068c52df2ef10a6657ad902b9842c75cc1 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Fri, 5 Nov 2021 21:25:42 -0300 Subject: [PATCH 29/45] a Co-authored-by: LOuroboros --- include/constants/battle_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 1c7781980..df8015518 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -161,8 +161,8 @@ #define B_SHADOW_TAG_ESCAPE GEN_7 // In Gen4+, if both sides have a Pokémon with Shadow Tag, all battlers can escape. Before, neither side could escape this situation. #define B_MOODY_ACC_EVASION GEN_8 // In Gen8, Moody CANNOT raise Accuracy and Evasion anymore. #define B_FLASH_FIRE_FROZEN GEN_7 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before. -#define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously. -#define B_SYNCHRONIZE_TOXIC GEN_8 // In Gen5+, if the Pokémon with Synchronize is badly poisoned, the opponent will also become badly poisoned. Previously, the opponent would become regular poisoned. +#define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if a Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously. +#define B_SYNCHRONIZE_TOXIC GEN_8 // In Gen5+, if a Pokémon with Synchronize is badly poisoned, the opponent will also become badly poisoned. Previously, the opponent would become regular poisoned. #define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities. // Item settings From 4bdbef9a9d25d8e547c2bd97e962df3b43d95e05 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 5 Nov 2021 22:21:50 -0300 Subject: [PATCH 30/45] Use the right defensive target stats during Shell Side Arm calculation --- src/battle_script_commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ec7c6effa..938c4bf54 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9036,7 +9036,7 @@ static void Cmd_various(void) attackerAtkStat *= gStatStageRatios[statStage][0]; attackerAtkStat /= gStatStageRatios[statStage][1]; - statStage = gBattleMons[gBattlerTarget].statStages[STAT_ATK]; + statStage = gBattleMons[gBattlerTarget].statStages[STAT_DEF]; targetDefStat *= gStatStageRatios[statStage][0]; targetDefStat /= gStatStageRatios[statStage][1]; @@ -9046,7 +9046,7 @@ static void Cmd_various(void) attackerSpAtkStat *= gStatStageRatios[statStage][0]; attackerSpAtkStat /= gStatStageRatios[statStage][1]; - statStage = gBattleMons[gBattlerTarget].statStages[STAT_SPATK]; + statStage = gBattleMons[gBattlerTarget].statStages[STAT_SPDEF]; targetSpDefStat *= gStatStageRatios[statStage][0]; targetSpDefStat /= gStatStageRatios[statStage][1]; From c2e8c1058fdd73c97a9b3e112bf03962e05d5aea Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 5 Nov 2021 23:07:26 -0300 Subject: [PATCH 31/45] Force set gSwapDamageCategory's initial value in Photon Geyser's and Shell Side Arm's calculations --- src/battle_script_commands.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 938c4bf54..78872b638 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9011,6 +9011,8 @@ static void Cmd_various(void) u8 attackerAtkStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; u32 attackerSpAtkStat = gBattleMons[gBattlerAttacker].spAttack; + gSwapDamageCategory = FALSE; + attackerAtkStat *= gStatStageRatios[attackerAtkStage][0]; attackerAtkStat /= gStatStageRatios[attackerAtkStage][1]; @@ -9032,6 +9034,8 @@ static void Cmd_various(void) u32 physical; u32 special; + gSwapDamageCategory = FALSE; + statStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK]; attackerAtkStat *= gStatStageRatios[statStage][0]; attackerAtkStat /= gStatStageRatios[statStage][1]; From 03f290d937b3acb98162498302f4f6ad58d281ba Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sat, 6 Nov 2021 08:53:00 -0400 Subject: [PATCH 32/45] add check for plus_2 effects --- src/battle_script_commands.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 861f2b8c4..5a85ee6b8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3040,7 +3040,8 @@ void SetMoveEffect(bool32 primary, u32 certain) case MOVE_EFFECT_SP_DEF_PLUS_2: case MOVE_EFFECT_ACC_PLUS_2: case MOVE_EFFECT_EVS_PLUS_2: - if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2), + if (NoAliveMonsForEitherParty() + || ChangeStatBuffs(SET_STAT_BUFF_VALUE(2), gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_2 + 1, affectsUser, 0)) { From 62b6accbcc803cd701333f41777b3c35fcee0ae6 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 6 Nov 2021 11:07:40 -0300 Subject: [PATCH 33/45] Using IsBattlerTerrainAffected --- src/battle_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index e8e27b316..63c4982f1 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5194,8 +5194,7 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk) } else if (gBattleMoves[move].effect == EFFECT_TERRAIN_PULSE) { - if ((gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) - && IsBattlerGrounded(battlerAtk)) + if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_TERRAIN_ANY)) { if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | 0x80; From 328976bf8174963eccff09e7eb3742ddbd39abd2 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 6 Nov 2021 17:05:13 -0300 Subject: [PATCH 34/45] Secret Power effect config --- include/constants/battle.h | 33 ++++++++++++++------ include/constants/battle_config.h | 1 + src/battle_script_commands.c | 51 ++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index 438b5660c..3ba45e0d8 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -364,16 +364,29 @@ #define MOVE_EFFECT_CERTAIN 0x8000 // Battle terrain defines for gBattleTerrain. -#define BATTLE_TERRAIN_GRASS 0 -#define BATTLE_TERRAIN_LONG_GRASS 1 -#define BATTLE_TERRAIN_SAND 2 -#define BATTLE_TERRAIN_UNDERWATER 3 -#define BATTLE_TERRAIN_WATER 4 -#define BATTLE_TERRAIN_POND 5 -#define BATTLE_TERRAIN_MOUNTAIN 6 -#define BATTLE_TERRAIN_CAVE 7 -#define BATTLE_TERRAIN_BUILDING 8 -#define BATTLE_TERRAIN_PLAIN 9 +#define BATTLE_TERRAIN_GRASS 0 +#define BATTLE_TERRAIN_LONG_GRASS 1 +#define BATTLE_TERRAIN_SAND 2 +#define BATTLE_TERRAIN_UNDERWATER 3 +#define BATTLE_TERRAIN_WATER 4 +#define BATTLE_TERRAIN_POND 5 +#define BATTLE_TERRAIN_MOUNTAIN 6 +#define BATTLE_TERRAIN_CAVE 7 +#define BATTLE_TERRAIN_BUILDING 8 +#define BATTLE_TERRAIN_PLAIN 9 +// New battle terrains are used for Secret Power but not fully implemented. +#define BATTLE_TERRAIN_SOARING 10 +#define BATTLE_TERRAIN_SKY_PILLAR 11 +#define BATTLE_TERRAIN_BURIAL_GROUND 12 +#define BATTLE_TERRAIN_PUDDLE 13 +#define BATTLE_TERRAIN_MARSH 14 +#define BATTLE_TERRAIN_SWAMP 15 +#define BATTLE_TERRAIN_SNOW 16 +#define BATTLE_TERRAIN_ICE 17 +#define BATTLE_TERRAIN_VOLCANO 18 +#define BATTLE_TERRAIN_DISTORTION_WORLD 19 +#define BATTLE_TERRAIN_SPACE 20 +#define BATTLE_TERRAIN_ULTRA_SPACE 21 #define B_WAIT_TIME_LONG 64 #define B_WAIT_TIME_MED 48 diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 95ff4f4a0..13f2be0d8 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -153,6 +153,7 @@ #define B_MEMENTO_FAIL GEN_7 // In Gen4+, Memento fails if there is no target or if the target is protected or behind substitute. But not if Atk/Sp. Atk are at -6. #define B_GLARE_GHOST GEN_7 // In Gen4+, Glare can hit Ghost-type Pokémon normally. #define B_SKILL_SWAP GEN_7 // In Gen4+, Skill Swap triggers switch-in abilities after use. +#define B_SECRET_POWER_EFFECT GEN_7 // Secret Power's effects change depending on the generation. See GetSecretPowerMoveEffect. // Ability settings #define B_ABILITY_WEATHER GEN_7 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5267cfbd1..fcba67bca 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12483,7 +12483,11 @@ u16 GetSecretPowerMoveEffect(void) switch (gBattleTerrain) { case BATTLE_TERRAIN_GRASS: - moveEffect = MOVE_EFFECT_SLEEP; + #if B_SECRET_POWER_EFFECT >= GEN_4 + moveEffect = MOVE_EFFECT_SLEEP; + #else + moveEffect = MOVE_EFFECT_POISON; + #endif break; case BATTLE_TERRAIN_LONG_GRASS: moveEffect = MOVE_EFFECT_SLEEP; @@ -12492,20 +12496,59 @@ u16 GetSecretPowerMoveEffect(void) moveEffect = MOVE_EFFECT_ACC_MINUS_1; break; case BATTLE_TERRAIN_UNDERWATER: - moveEffect = MOVE_EFFECT_ATK_MINUS_1; + #if B_SECRET_POWER_EFFECT >= GEN_6 + moveEffect = MOVE_EFFECT_ATK_MINUS_1; + #else + moveEffect = MOVE_EFFECT_DEF_MINUS_1; + #endif break; case BATTLE_TERRAIN_WATER: moveEffect = MOVE_EFFECT_ATK_MINUS_1; break; case BATTLE_TERRAIN_POND: - moveEffect = MOVE_EFFECT_ATK_MINUS_1; + #if B_SECRET_POWER_EFFECT >= GEN_4 + moveEffect = MOVE_EFFECT_ATK_MINUS_1; + #else + moveEffect = MOVE_EFFECT_SPD_MINUS_1; + #endif break; case BATTLE_TERRAIN_MOUNTAIN: - moveEffect = MOVE_EFFECT_ACC_MINUS_1; + #if B_SECRET_POWER_EFFECT >= GEN_5 + moveEffect = MOVE_EFFECT_ACC_MINUS_1; + #elif B_SECRET_POWER_EFFECT == GEN_4 + moveEffect = MOVE_EFFECT_FLINCH; + #else + moveEffect = MOVE_EFFECT_CONFUSION; + #endif break; case BATTLE_TERRAIN_CAVE: + case BATTLE_TERRAIN_BURIAL_GROUND: + case BATTLE_TERRAIN_SPACE: moveEffect = MOVE_EFFECT_FLINCH; break; + case BATTLE_TERRAIN_SOARING: + case BATTLE_TERRAIN_SKY_PILLAR: + case BATTLE_TERRAIN_MARSH: + case BATTLE_TERRAIN_SWAMP: + moveEffect = MOVE_EFFECT_SPD_MINUS_1; + break; + case BATTLE_TERRAIN_PUDDLE: + #if B_SECRET_POWER_EFFECT >= GEN_5 + moveEffect = MOVE_EFFECT_SPD_MINUS_1; + #else + moveEffect = MOVE_EFFECT_ACC_MINUS_1; + #endif + break; + case BATTLE_TERRAIN_SNOW: + case BATTLE_TERRAIN_ICE: + moveEffect = MOVE_EFFECT_FREEZE; + break; + case BATTLE_TERRAIN_VOLCANO: + moveEffect = MOVE_EFFECT_BURN; + break; + case BATTLE_TERRAIN_ULTRA_SPACE: + moveEffect = MOVE_EFFECT_DEF_MINUS_1; + break; default: moveEffect = MOVE_EFFECT_PARALYSIS; break; From e9804a50233a26c8480ab50bc9e47c24ab2eb4db Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 6 Nov 2021 17:32:34 -0300 Subject: [PATCH 35/45] Secret Power animation config --- data/battle_anim_scripts.s | 29 +++++++++++++++++++++++++++++ include/constants/battle_config.h | 1 + 2 files changed, 30 insertions(+) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 6077a3ae4..3e7f02692 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -5,6 +5,7 @@ #include "constants/moves.h" #include "constants/pokemon.h" #include "constants/items.h" +#include "constants/battle_config.h" .include "asm/macros.inc" .include "asm/macros/battle_anim_script.inc" .include "constants/constants.inc" @@ -23367,8 +23368,36 @@ Move_SECRET_POWER: jumpargeq 0, BATTLE_TERRAIN_POND, Move_BUBBLE_BEAM jumpargeq 0, BATTLE_TERRAIN_MOUNTAIN, Move_ROCK_THROW jumpargeq 0, BATTLE_TERRAIN_CAVE, Move_BITE + jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_STRENGTH + jumpargeq 0, BATTLE_TERRAIN_SOARING, Move_GUST + jumpargeq 0, BATTLE_TERRAIN_SKY_PILLAR, Move_GUST + jumpargeq 0, BATTLE_TERRAIN_BURIAL_GROUND, Move_SHADOW_SNEAK + jumpargeq 0, BATTLE_TERRAIN_PUDDLE, Move_MUD_SHOT + jumpargeq 0, BATTLE_TERRAIN_MARSH, Move_MUD_SHOT + jumpargeq 0, BATTLE_TERRAIN_SWAMP, Move_MUD_SHOT +.if B_SECRET_POWER_ANIMATION >= GEN_7 + jumpargeq 0, BATTLE_TERRAIN_SNOW, Move_ICE_SHARD +.else + jumpargeq 0, BATTLE_TERRAIN_SNOW, Move_AVALANCHE +.endif + jumpargeq 0, BATTLE_TERRAIN_ICE, Move_ICE_SHARD + jumpargeq 0, BATTLE_TERRAIN_VOLCANO, Move_INCINERATE + jumpargeq 0, BATTLE_TERRAIN_DISTORTION_WORLD, Move_POUND + jumpargeq 0, BATTLE_TERRAIN_SPACE, Move_SWIFT + jumpargeq 0, BATTLE_TERRAIN_ULTRA_SPACE, Move_PSYWAVE +.if B_SECRET_POWER_ANIMATION >= GEN_7 + jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_SPIT_UP + goto Move_SPIT_UP +.elseif B_SECRET_POWER_ANIMATION == GEN_6 + jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_BODY_SLAM + goto Move_BODY_SLAM +.elseif B_SECRET_POWER_ANIMATION == GEN_5 || B_SECRET_POWER_ANIMATION == GEN_4 + jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_BODY_SLAM + goto Move_MUD_SLAP +.else jumpargeq 0, BATTLE_TERRAIN_BUILDING, Move_STRENGTH goto Move_SLAM +.endif Move_TWISTER: loadspritegfx ANIM_TAG_LEAF diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 13f2be0d8..61723ced4 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -154,6 +154,7 @@ #define B_GLARE_GHOST GEN_7 // In Gen4+, Glare can hit Ghost-type Pokémon normally. #define B_SKILL_SWAP GEN_7 // In Gen4+, Skill Swap triggers switch-in abilities after use. #define B_SECRET_POWER_EFFECT GEN_7 // Secret Power's effects change depending on the generation. See GetSecretPowerMoveEffect. +#define B_SECRET_POWER_ANIMATION GEN_7 // Secret Power's animations change depending on the generation. // Ability settings #define B_ABILITY_WEATHER GEN_7 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. From b220da1d2ad9fd9696256a39ec626029d42187fb Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 6 Nov 2021 18:50:01 -0300 Subject: [PATCH 36/45] Updated NaturePowerMoves table for new terrains + added failsafe in case the terrain isn't defined in the table --- include/constants/battle.h | 2 + include/constants/battle_config.h | 1 + src/battle_script_commands.c | 68 +++++++++++++++++++++++++++++-- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index 3ba45e0d8..2fb4d3401 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -388,6 +388,8 @@ #define BATTLE_TERRAIN_SPACE 20 #define BATTLE_TERRAIN_ULTRA_SPACE 21 +#define BATTLE_TERRAIN_COUNT 22 + #define B_WAIT_TIME_LONG 64 #define B_WAIT_TIME_MED 48 #define B_WAIT_TIME_SHORT 32 diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 61723ced4..9d94966dd 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -155,6 +155,7 @@ #define B_SKILL_SWAP GEN_7 // In Gen4+, Skill Swap triggers switch-in abilities after use. #define B_SECRET_POWER_EFFECT GEN_7 // Secret Power's effects change depending on the generation. See GetSecretPowerMoveEffect. #define B_SECRET_POWER_ANIMATION GEN_7 // Secret Power's animations change depending on the generation. +#define B_NATURE_POWER_MOVES GEN_8 // Nature Power calls different moves depending on the generation. // Ability settings #define B_ABILITY_WEATHER GEN_7 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index fcba67bca..57f02e2f5 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1097,18 +1097,76 @@ static const u16 sMoveEffectsForbiddenToInstruct[] = FORBIDDEN_INSTRUCT_END }; -static const u16 sNaturePowerMoves[] = +static const u16 sNaturePowerMoves[BATTLE_TERRAIN_COUNT] = { +#if B_NATURE_POWER_MOVES >= GEN_7 [BATTLE_TERRAIN_GRASS] = MOVE_ENERGY_BALL, [BATTLE_TERRAIN_LONG_GRASS] = MOVE_ENERGY_BALL, [BATTLE_TERRAIN_SAND] = MOVE_EARTH_POWER, - [BATTLE_TERRAIN_UNDERWATER] = MOVE_HYDRO_PUMP, [BATTLE_TERRAIN_WATER] = MOVE_HYDRO_PUMP, [BATTLE_TERRAIN_POND] = MOVE_HYDRO_PUMP, [BATTLE_TERRAIN_MOUNTAIN] = MOVE_EARTH_POWER, - [BATTLE_TERRAIN_CAVE] = MOVE_POWER_GEM, + [BATTLE_TERRAIN_CAVE] = MOVE_EARTH_POWER, [BATTLE_TERRAIN_BUILDING] = MOVE_TRI_ATTACK, - [BATTLE_TERRAIN_PLAIN] = MOVE_TRI_ATTACK + [BATTLE_TERRAIN_PLAIN] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_SNOW] = MOVE_ICE_BEAM, +#elif B_NATURE_POWER_MOVES == GEN_6 + [BATTLE_TERRAIN_GRASS] = MOVE_ENERGY_BALL, + [BATTLE_TERRAIN_LONG_GRASS] = MOVE_ENERGY_BALL, + [BATTLE_TERRAIN_SAND] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_WATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_POND] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_MOUNTAIN] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_CAVE] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_BUILDING] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_PLAIN] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_SNOW] = MOVE_FROST_BREATH, +#elif B_NATURE_POWER_MOVES == GEN_5 + [BATTLE_TERRAIN_GRASS] = MOVE_SEED_BOMB, + [BATTLE_TERRAIN_LONG_GRASS] = MOVE_SEED_BOMB, + [BATTLE_TERRAIN_SAND] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_WATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_POND] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_MOUNTAIN] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_CAVE] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_BUILDING] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_PLAIN] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_SNOW] = MOVE_BLIZZARD, +#elif B_NATURE_POWER_MOVES == GEN_4 + [BATTLE_TERRAIN_GRASS] = MOVE_SEED_BOMB, + [BATTLE_TERRAIN_LONG_GRASS] = MOVE_SEED_BOMB, + [BATTLE_TERRAIN_SAND] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_WATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_POND] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_MOUNTAIN] = MOVE_ROCK_SLIDE, + [BATTLE_TERRAIN_CAVE] = MOVE_ROCK_SLIDE, + [BATTLE_TERRAIN_BUILDING] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_PLAIN] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_SNOW] = MOVE_BLIZZARD, +#else // Gen 1-3 + [BATTLE_TERRAIN_GRASS] = MOVE_STUN_SPORE, + [BATTLE_TERRAIN_LONG_GRASS] = MOVE_RAZOR_LEAF, + [BATTLE_TERRAIN_SAND] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_WATER] = MOVE_SURF, + [BATTLE_TERRAIN_POND] = MOVE_BUBBLE_BEAM, + [BATTLE_TERRAIN_MOUNTAIN] = MOVE_ROCK_SLIDE, + [BATTLE_TERRAIN_CAVE] = MOVE_SHADOW_BALL, + [BATTLE_TERRAIN_BUILDING] = MOVE_SWIFT, + [BATTLE_TERRAIN_PLAIN] = MOVE_SWIFT, + [BATTLE_TERRAIN_SNOW] = MOVE_BLIZZARD, +#endif + [BATTLE_TERRAIN_UNDERWATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_SOARING] = MOVE_AIR_SLASH, + [BATTLE_TERRAIN_SKY_PILLAR] = MOVE_AIR_SLASH, + [BATTLE_TERRAIN_BURIAL_GROUND] = MOVE_SHADOW_BALL, + [BATTLE_TERRAIN_PUDDLE] = MOVE_MUD_BOMB, + [BATTLE_TERRAIN_MARSH] = MOVE_MUD_BOMB, + [BATTLE_TERRAIN_SWAMP] = MOVE_MUD_BOMB, + [BATTLE_TERRAIN_ICE] = MOVE_ICE_BEAM, + [BATTLE_TERRAIN_VOLCANO] = MOVE_LAVA_PLUME, + [BATTLE_TERRAIN_DISTORTION_WORLD] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_SPACE] = MOVE_DRACO_METEOR, + [BATTLE_TERRAIN_ULTRA_SPACE] = MOVE_PSYSHOCK, }; static const u16 sPickupItems[] = @@ -11866,6 +11924,8 @@ u16 GetNaturePowerMove(void) return MOVE_ENERGY_BALL; else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) return MOVE_PSYCHIC; + else if (sNaturePowerMoves == MOVE_NONE) + return MOVE_TRI_ATTACK; return sNaturePowerMoves[gBattleTerrain]; } From 1c4a0c205acc405d3dff3590e1ed88e70ed4a206 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 6 Nov 2021 19:09:35 -0300 Subject: [PATCH 37/45] Camouflage types config + extra terrains --- include/constants/battle_config.h | 1 + src/battle_script_commands.c | 42 +++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 9d94966dd..be81610cc 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -156,6 +156,7 @@ #define B_SECRET_POWER_EFFECT GEN_7 // Secret Power's effects change depending on the generation. See GetSecretPowerMoveEffect. #define B_SECRET_POWER_ANIMATION GEN_7 // Secret Power's animations change depending on the generation. #define B_NATURE_POWER_MOVES GEN_8 // Nature Power calls different moves depending on the generation. +#define B_CAMOUFLAGE_TYPES GEN_7 // Camouflage changes the user to different types depending on the generation // Ability settings #define B_ABILITY_WEATHER GEN_7 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 57f02e2f5..85ddede46 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1211,18 +1211,38 @@ static const u8 sPickupProbabilities[] = 30, 40, 50, 60, 70, 80, 90, 94, 98 }; -static const u8 sTerrainToType[] = +static const u8 sTerrainToType[BATTLE_TERRAIN_COUNT] = { - [BATTLE_TERRAIN_GRASS] = TYPE_GRASS, - [BATTLE_TERRAIN_LONG_GRASS] = TYPE_GRASS, - [BATTLE_TERRAIN_SAND] = TYPE_GROUND, - [BATTLE_TERRAIN_UNDERWATER] = TYPE_WATER, - [BATTLE_TERRAIN_WATER] = TYPE_WATER, - [BATTLE_TERRAIN_POND] = TYPE_WATER, - [BATTLE_TERRAIN_MOUNTAIN] = TYPE_GROUND, - [BATTLE_TERRAIN_CAVE] = TYPE_ROCK, - [BATTLE_TERRAIN_BUILDING] = TYPE_NORMAL, - [BATTLE_TERRAIN_PLAIN] = TYPE_NORMAL, + [BATTLE_TERRAIN_GRASS] = TYPE_GRASS, + [BATTLE_TERRAIN_LONG_GRASS] = TYPE_GRASS, + [BATTLE_TERRAIN_SAND] = TYPE_GROUND, + [BATTLE_TERRAIN_UNDERWATER] = TYPE_WATER, + [BATTLE_TERRAIN_WATER] = TYPE_WATER, + [BATTLE_TERRAIN_POND] = TYPE_WATER, + [BATTLE_TERRAIN_CAVE] = TYPE_ROCK, + [BATTLE_TERRAIN_BUILDING] = TYPE_NORMAL, + [BATTLE_TERRAIN_SOARING] = TYPE_FLYING, + [BATTLE_TERRAIN_SKY_PILLAR] = TYPE_FLYING, + [BATTLE_TERRAIN_BURIAL_GROUND] = TYPE_GHOST, + [BATTLE_TERRAIN_PUDDLE] = TYPE_GROUND, + [BATTLE_TERRAIN_MARSH] = TYPE_GROUND, + [BATTLE_TERRAIN_SWAMP] = TYPE_GROUND, + [BATTLE_TERRAIN_SNOW] = TYPE_ICE, + [BATTLE_TERRAIN_ICE] = TYPE_ICE, + [BATTLE_TERRAIN_VOLCANO] = TYPE_FIRE, + [BATTLE_TERRAIN_DISTORTION_WORLD] = TYPE_NORMAL, + [BATTLE_TERRAIN_SPACE] = TYPE_DRAGON, + [BATTLE_TERRAIN_ULTRA_SPACE] = TYPE_PSYCHIC, +#if B_CAMOUFLAGE_TYPES >= GEN_5 + [BATTLE_TERRAIN_MOUNTAIN] = TYPE_GROUND, + [BATTLE_TERRAIN_PLAIN] = TYPE_GROUND, +#elif B_CAMOUFLAGE_TYPES == GEN_4 + [BATTLE_TERRAIN_MOUNTAIN] = TYPE_ROCK, + [BATTLE_TERRAIN_PLAIN] = TYPE_GROUND, +#else + [BATTLE_TERRAIN_MOUNTAIN] = TYPE_ROCK, + [BATTLE_TERRAIN_PLAIN] = TYPE_NORMAL, +#endif }; // - ITEM_ULTRA_BALL skips Master Ball and ITEM_NONE From 8773e552ace6994a85dd728dee32f29dde984d14 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 6 Nov 2021 19:24:06 -0300 Subject: [PATCH 38/45] Organized config and added failsafe to AnimTask_SetCamouflageBlend --- include/constants/battle_config.h | 30 +++++++++++++++--------------- src/battle_anim_utility_funcs.c | 1 + 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index be81610cc..5338b304e 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -95,7 +95,6 @@ #define B_CRIT_CHANCE GEN_7 // Chances of a critical hit landing. See CalcCritChanceStage. #define B_CRIT_MULTIPLIER GEN_7 // In Gen6+, critical hits multiply damage by 1.5 instead of 2. #define B_PARALYSIS_SPEED GEN_7 // In Gen7+, Speed is decreased by 50% instead of 75%. -#define B_TERRAIN_TYPE_BOOST GEN_8 // In Gen8, damage is boosted by 30% instead of 50%. #define B_CONFUSION_SELF_DMG_CHANCE GEN_7 // In Gen7+, confusion has a 33.3% of self-damage, instead of 50%. #define B_MULTI_HIT_CHANCE GEN_7 // In Gen5+, multi-hit moves have different %. See Cmd_setmultihitcounter for values. @@ -153,10 +152,6 @@ #define B_MEMENTO_FAIL GEN_7 // In Gen4+, Memento fails if there is no target or if the target is protected or behind substitute. But not if Atk/Sp. Atk are at -6. #define B_GLARE_GHOST GEN_7 // In Gen4+, Glare can hit Ghost-type Pokémon normally. #define B_SKILL_SWAP GEN_7 // In Gen4+, Skill Swap triggers switch-in abilities after use. -#define B_SECRET_POWER_EFFECT GEN_7 // Secret Power's effects change depending on the generation. See GetSecretPowerMoveEffect. -#define B_SECRET_POWER_ANIMATION GEN_7 // Secret Power's animations change depending on the generation. -#define B_NATURE_POWER_MOVES GEN_8 // Nature Power calls different moves depending on the generation. -#define B_CAMOUFLAGE_TYPES GEN_7 // Camouflage changes the user to different types depending on the generation // Ability settings #define B_ABILITY_WEATHER GEN_7 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. @@ -187,26 +182,31 @@ // Eg: Replace with VAR_UNUSED_0x40F7 so you can use VAR_TERRAIN for that feature. #define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active +// Terrain settings +#define B_TERRAIN_BG_CHANGE TRUE // If set to TRUE, terrain moves permanently change the default battle background until the effect fades. +#define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8. +#define B_TERRAIN_TYPE_BOOST GEN_8 // In Gen8, damage is boosted by 30% instead of 50%. +#define B_SECRET_POWER_EFFECT GEN_7 // Secret Power's effects change depending on terrain and generation. See GetSecretPowerMoveEffect. +#define B_SECRET_POWER_ANIMATION GEN_7 // Secret Power's animations change depending on terrain and generation. +#define B_NATURE_POWER_MOVES GEN_8 // Nature Power calls different moves depending on terrain and generation. See sNaturePowerMoves. +#define B_CAMOUFLAGE_TYPES GEN_7 // Camouflage changes the user to different types depending on terrain and generation. See sTerrainToType. + // Interface settings #define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle. #define B_FAST_INTRO TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end. #define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move. #define B_SHOW_SPLIT_ICON TRUE // If set to TRUE, it will show an icon in the summary showing the move's category split. #define B_HIDE_HEALTHBOX_IN_ANIMS TRUE // If set to TRUE, hides healthboxes during move animations. -#define B_TERRAIN_BG_CHANGE TRUE // If set to TRUE, terrain moves permanently change the default battle background until the effect fades. -// Critical Capture -#define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled. -#define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm. - -// Last Used Ball -#define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented -#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. +// Catching settings +#define B_SEMI_INVULNERABLE_CATCH GEN_7 // In Gen4+, you cannot throw a ball against a Pokemon that is in a semi-invulnerable state (dig/fly/etc) +#define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm. +#define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled. +#define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented +#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 #define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. -#define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8. -#define B_SEMI_INVULNERABLE_CATCH GEN_7 // In Gen4+, you cannot throw a ball against a Pokemon that is in a semi-invulnerable state (dig/fly/etc) // Animation Settings #define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle. diff --git a/src/battle_anim_utility_funcs.c b/src/battle_anim_utility_funcs.c index 0f35657db..c85a918da 100644 --- a/src/battle_anim_utility_funcs.c +++ b/src/battle_anim_utility_funcs.c @@ -136,6 +136,7 @@ void AnimTask_SetCamouflageBlend(u8 taskId) gBattleAnimArgs[4] = RGB(31, 31, 31); break; case BATTLE_TERRAIN_PLAIN: + default: gBattleAnimArgs[4] = RGB(31, 31, 31); break; } From 4e6a459b1439c9e81dbcc1068b09dfba3781571b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 6 Nov 2021 19:46:52 -0300 Subject: [PATCH 39/45] Optimized terrain timers --- include/battle.h | 5 +---- src/battle_script_commands.c | 13 +++++-------- src/battle_util.c | 16 ++++++++-------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/battle.h b/include/battle.h index 7602c5d09..3c4b4d220 100644 --- a/include/battle.h +++ b/include/battle.h @@ -222,10 +222,7 @@ struct FieldTimer u8 wonderRoomTimer; u8 magicRoomTimer; u8 trickRoomTimer; - u8 grassyTerrainTimer; - u8 mistyTerrainTimer; - u8 electricTerrainTimer; - u8 psychicTerrainTimer; + u8 terrainTimer; u8 gravityTimer; u8 fairyLockTimer; }; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 85ddede46..4eec84088 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7328,19 +7328,19 @@ static void HandleTerrainMove(u32 moveEffect) switch (moveEffect) { case EFFECT_MISTY_TERRAIN: - statusFlag = STATUS_FIELD_MISTY_TERRAIN, timer = &gFieldTimers.mistyTerrainTimer; + statusFlag = STATUS_FIELD_MISTY_TERRAIN, timer = &gFieldTimers.terrainTimer; gBattleCommunication[MULTISTRING_CHOOSER] = 0; break; case EFFECT_GRASSY_TERRAIN: - statusFlag = STATUS_FIELD_GRASSY_TERRAIN, timer = &gFieldTimers.grassyTerrainTimer; + statusFlag = STATUS_FIELD_GRASSY_TERRAIN, timer = &gFieldTimers.terrainTimer; gBattleCommunication[MULTISTRING_CHOOSER] = 1; break; case EFFECT_ELECTRIC_TERRAIN: - statusFlag = STATUS_FIELD_ELECTRIC_TERRAIN, timer = &gFieldTimers.electricTerrainTimer; + statusFlag = STATUS_FIELD_ELECTRIC_TERRAIN, timer = &gFieldTimers.terrainTimer; gBattleCommunication[MULTISTRING_CHOOSER] = 2; break; case EFFECT_PSYCHIC_TERRAIN: - statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN, timer = &gFieldTimers.psychicTerrainTimer; + statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN, timer = &gFieldTimers.terrainTimer; gBattleCommunication[MULTISTRING_CHOOSER] = 3; break; } @@ -8937,22 +8937,19 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; // can heal return; case VARIOUS_REMOVE_TERRAIN: + gFieldTimers.terrainTimer = 0; switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { case STATUS_FIELD_MISTY_TERRAIN: - gFieldTimers.mistyTerrainTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 0; break; case STATUS_FIELD_GRASSY_TERRAIN: - gFieldTimers.grassyTerrainTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 1; break; case STATUS_FIELD_ELECTRIC_TERRAIN: - gFieldTimers.electricTerrainTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 2; break; case STATUS_FIELD_PSYCHIC_TERRAIN: - gFieldTimers.psychicTerrainTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 3; break; default: diff --git a/src/battle_util.c b/src/battle_util.c index 15d13b85a..66247c7f6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2326,7 +2326,7 @@ u8 DoFieldEndTurnEffects(void) break; case ENDTURN_ELECTRIC_TERRAIN: if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN - && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.electricTerrainTimer == 0)) + && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); TryToRevertMimicry(); @@ -2337,7 +2337,7 @@ u8 DoFieldEndTurnEffects(void) break; case ENDTURN_MISTY_TERRAIN: if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN - && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.mistyTerrainTimer == 0)) + && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN); TryToRevertMimicry(); @@ -2350,7 +2350,7 @@ u8 DoFieldEndTurnEffects(void) if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) { if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) - && (gFieldTimers.grassyTerrainTimer == 0 || --gFieldTimers.grassyTerrainTimer == 0)) + && (gFieldTimers.terrainTimer == 0 || --gFieldTimers.terrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_GRASSY_TERRAIN); TryToRevertMimicry(); @@ -2362,7 +2362,7 @@ u8 DoFieldEndTurnEffects(void) break; case ENDTURN_PSYCHIC_TERRAIN: if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN - && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.psychicTerrainTimer == 0)) + && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.terrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_PSYCHIC_TERRAIN); TryToRevertMimicry(); @@ -4338,28 +4338,28 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_ELECTRIC_SURGE: - if (TryChangeBattleTerrain(battler, STATUS_FIELD_ELECTRIC_TERRAIN, &gFieldTimers.electricTerrainTimer)) + if (TryChangeBattleTerrain(battler, STATUS_FIELD_ELECTRIC_TERRAIN, &gFieldTimers.terrainTimer)) { BattleScriptPushCursorAndCallback(BattleScript_ElectricSurgeActivates); effect++; } break; case ABILITY_GRASSY_SURGE: - if (TryChangeBattleTerrain(battler, STATUS_FIELD_GRASSY_TERRAIN, &gFieldTimers.grassyTerrainTimer)) + if (TryChangeBattleTerrain(battler, STATUS_FIELD_GRASSY_TERRAIN, &gFieldTimers.terrainTimer)) { BattleScriptPushCursorAndCallback(BattleScript_GrassySurgeActivates); effect++; } break; case ABILITY_MISTY_SURGE: - if (TryChangeBattleTerrain(battler, STATUS_FIELD_MISTY_TERRAIN, &gFieldTimers.mistyTerrainTimer)) + if (TryChangeBattleTerrain(battler, STATUS_FIELD_MISTY_TERRAIN, &gFieldTimers.terrainTimer)) { BattleScriptPushCursorAndCallback(BattleScript_MistySurgeActivates); effect++; } break; case ABILITY_PSYCHIC_SURGE: - if (TryChangeBattleTerrain(battler, STATUS_FIELD_PSYCHIC_TERRAIN, &gFieldTimers.psychicTerrainTimer)) + if (TryChangeBattleTerrain(battler, STATUS_FIELD_PSYCHIC_TERRAIN, &gFieldTimers.terrainTimer)) { BattleScriptPushCursorAndCallback(BattleScript_PsychicSurgeActivates); effect++; From c2a17510a962b9f26fbce84399b9df23aefbd31d Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sun, 7 Nov 2021 11:25:08 -0300 Subject: [PATCH 40/45] Terrain Pulse animations --- data/battle_anim_scripts.s | 82 +++++++++++++++++++++++++++++++++++++- src/battle_anim_new.c | 22 ++++++++++ src/battle_main.c | 2 +- 3 files changed, 104 insertions(+), 2 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 3e7f02692..b10c937ae 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -14082,7 +14082,87 @@ Move_RISING_VOLTAGE:: end @to do: Move_TERRAIN_PULSE:: - goto Move_DRAGON_PULSE @Temporary, needs to setup different animations based on terrain + loadspritegfx ANIM_TAG_DRAGON_PULSE + monbg ANIM_TARGET + setalpha 12, 8 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, 1, 1, 0, 7, RGB_BLACK + launchtask AnimTask_TerrainPulse 0x5 0x0 + jumpargeq 0x0, TYPE_ELECTRIC, TerrainPulseElectric + jumpargeq 0x0, TYPE_GRASS, TerrainPulseGrass + jumpargeq 0x0, TYPE_FAIRY, TerrainPulseFairy + jumpargeq 0x0, TYPE_PSYCHIC, TerrainPulsePsychic +TerrainPulseNormal: + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB_WHITE + waitforvisualfinish + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15 + call DragonPulseParticle + call DragonPulseParticle + createvisualtask AnimTask_SwayMon, 5, 0, 2, 51200, 24, ANIM_TARGET + createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB_WHITE + goto TerrainPulseEnd + +TerrainPulseElectric: + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB(27, 27, 0) + waitforvisualfinish + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15 + call DragonPulseParticle + call DragonPulseParticle + createvisualtask AnimTask_SwayMon, 5, 0, 4, 51200, 24, ANIM_TARGET + createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB(27, 27, 0) + goto TerrainPulseEnd + +TerrainPulseGrass: + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB(11, 26, 11) + waitforvisualfinish + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15 + call DragonPulseParticle + call DragonPulseParticle + createvisualtask AnimTask_SwayMon, 5, 0, 4, 51200, 24, ANIM_TARGET + createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB(11, 26, 11) + goto TerrainPulseEnd + +TerrainPulseFairy: + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB(31, 24, 31) + waitforvisualfinish + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15 + call DragonPulseParticle + call DragonPulseParticle + createvisualtask AnimTask_SwayMon, 5, 0, 4, 51200, 24, ANIM_TARGET + createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB(31, 24, 31) + goto TerrainPulseEnd + +TerrainPulsePsychic: + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_DRAGON_PULSE, 0, 12, 12, RGB(27, 0, 13) + waitforvisualfinish + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15 + call DragonPulseParticle + call DragonPulseParticle + createvisualtask AnimTask_SwayMon, 5, 0, 4, 51200, 24, ANIM_TARGET + createvisualtask AnimTask_BlendColorCycle, 2, 4, 2, 2, 0, 12, RGB(27, 0, 13) + goto TerrainPulseEnd + +TerrainPulseEnd: + call DragonPulseParticle + call DragonPulseParticle + call DragonPulseParticle + call DragonPulseParticle + call DragonPulseParticle + call DragonPulseParticle + call DragonPulseParticle + call DragonPulseParticle + call DragonPulseParticle + waitforvisualfinish + delay 1 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, 1, 1, 7, 0, RGB_BLACK + waitforvisualfinish + blendoff + clearmonbg ANIM_TARGET + end Move_SKITTER_SMACK:: end @to do: diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 3bc45939f..63fed0b3d 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -5073,3 +5073,25 @@ void AnimTask_ShellSideArm(u8 taskId) gBattleAnimArgs[0] = FALSE; DestroyAnimVisualTask(taskId); } + +void AnimTask_TerrainPulse(u8 taskId) +{ + if (IsBattlerTerrainAffected(gBattleAnimAttacker, STATUS_FIELD_TERRAIN_ANY)) + { + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + gBattleAnimArgs[0] = TYPE_ELECTRIC; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + gBattleAnimArgs[0] = TYPE_GRASS; + else if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + gBattleAnimArgs[0] = TYPE_FAIRY; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + gBattleAnimArgs[0] = TYPE_PSYCHIC; + else //failsafe + gBattleAnimArgs[0] = 0; + } + else + { + gBattleAnimArgs[0] = 0; + } + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_main.c b/src/battle_main.c index 63c4982f1..84491987e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5204,7 +5204,7 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk) gBattleStruct->dynamicMoveType = TYPE_FAIRY | 0x80; else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) gBattleStruct->dynamicMoveType = TYPE_PSYCHIC | 0x80; - else + else //failsafe gBattleStruct->dynamicMoveType = TYPE_NORMAL | 0x80; } } From b358f774dd1f53bf10c87c345e211f80dc48822b Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Sun, 7 Nov 2021 14:40:18 -0300 Subject: [PATCH 41/45] Fixed the offensive boost of the Soul Dew --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index dbc46a3ec..9c5b77cd6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8091,7 +8091,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe #if B_SOUL_DEW_BOOST >= GEN_7 if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && (moveType == TYPE_PSYCHIC || moveType == TYPE_DRAGON)) #else - if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER)) + if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && IS_MOVE_SPECIAL(move)) #endif MulModifier(&modifier, holdEffectModifier); break; From 3a113e33b26ceaaa8d7f0492796796c677fdab44 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 8 Nov 2021 19:28:09 +1300 Subject: [PATCH 42/45] Uncomment AI Full Metal Body checks This ability is Clear Body with a different name, so it should be working and doesn't need to be commented out. --- src/battle_ai_util.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 1e229fbe8..781fb50e6 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1685,7 +1685,7 @@ bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY && defAbility != ABILITY_WHITE_SMOKE - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_HYPER_CUTTER) return TRUE; return FALSE; @@ -1701,7 +1701,7 @@ bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY && defAbility != ABILITY_WHITE_SMOKE - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_BIG_PECKS) return TRUE; return FALSE; @@ -1715,7 +1715,7 @@ bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility) if (IsAiFaster(AI_CHECK_SLOWER) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_WHITE_SMOKE) return TRUE; return FALSE; @@ -1730,7 +1730,7 @@ bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility) && HasMoveWithSplit(battlerDef, SPLIT_SPECIAL) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_WHITE_SMOKE) return TRUE; return FALSE; @@ -1745,7 +1745,7 @@ bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility) && HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_WHITE_SMOKE) return TRUE; return FALSE; @@ -1759,7 +1759,7 @@ bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility) if (defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY && defAbility != ABILITY_WHITE_SMOKE - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_KEEN_EYE) return TRUE; return FALSE; @@ -1773,7 +1773,7 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility) if (gBattleMons[battlerDef].statStages[STAT_EVASION] > DEFAULT_STAT_STAGE && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_WHITE_SMOKE) return TRUE; return FALSE; From d3a845d51170c6b103c15f908300727cb4f6da3c Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 8 Nov 2021 20:37:28 +1300 Subject: [PATCH 43/45] Fix CanAIFaintTarget Rename CanAIFaintTarget to CanIndexMoveFaintTarget and create a new function, CanAIFaintTarget, that checks if any known move can KO the target. --- include/battle_ai_util.h | 3 ++- src/battle_ai_main.c | 18 +++++++------- src/battle_ai_util.c | 54 +++++++++++++++++++++++++++++----------- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index b6df2168e..1b2591899 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -35,7 +35,8 @@ u16 AI_GetHoldEffect(u32 battlerId); u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u8 atkHoldEffect, u8 defHoldEffect, u16 move); bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move); bool32 AI_WeatherHasEffect(void); -bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits); +bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits); +bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits); bool32 AI_IsTerrainAffected(u8 battlerId, u32 flags); bool32 AI_IsBattlerGrounded(u8 battlerId); bool32 HasDamagingMove(u8 battlerId); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 77196cf9a..7fbb43260 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1473,7 +1473,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) else if (move == MOVE_FAKE_OUT) // filter out first impression { if ((AI_DATA->atkHoldEffect == HOLD_EFFECT_CHOICE_BAND || AI_DATA->atkAbility == ABILITY_GORILLA_TACTICS) - && (CountUsablePartyMons(battlerDef) > 0 || !CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))) + && (CountUsablePartyMons(battlerDef) > 0 || !CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))) { if (CountUsablePartyMons(battlerAtk) == 0) score -= 10; // Don't lock the attacker into Fake Out if they can't switch out afterwards. @@ -1714,7 +1714,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (AI_DATA->defAbility == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2) score -= 10; else if (AI_DATA->atkAbility != ABILITY_TRUANT - && !CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + && !CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) score -= 2; break; case EFFECT_SPITE: @@ -2465,7 +2465,7 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (gBattleMoves[move].power == 0) return score; // can't make anything faint with no power - if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION) + if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION) { // this move can faint the target if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0 || GetMovePriority(battlerAtk, move) > 0) @@ -2707,7 +2707,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) && !IS_MOVE_STATUS(move) && HasMoveWithSplit(battlerAtkPartner, SPLIT_PHYSICAL) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK) - && !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1)) + && !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1)) { RETURN_SCORE_PLUS(1); } @@ -2716,7 +2716,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (!IS_MOVE_STATUS(move) && (moveType == TYPE_DARK || moveType == TYPE_GHOST || moveType == TYPE_BUG) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_SPEED) - && !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1)) + && !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1)) { RETURN_SCORE_PLUS(1); } @@ -2782,7 +2782,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) && !IS_MOVE_STATUS(move) && HasMoveWithSplit(battlerAtkPartner, SPLIT_PHYSICAL) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK) - && !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 0)) + && !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 0)) { RETURN_SCORE_PLUS(1); } @@ -2971,7 +2971,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case ABILITY_BEAST_BOOST: if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // attacker should go first { - if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) score += 8; // prioritize killing target for stat boost } break; @@ -3772,7 +3772,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_FELL_STINGER: if (gBattleMons[battlerAtk].statStages[STAT_ATK] < MAX_STAT_STAGE && AI_DATA->atkAbility != ABILITY_CONTRARY - && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + && CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) { if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Attacker goes first score += 9; @@ -4923,7 +4923,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } // consider target HP - if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) { score += 2; } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 781fb50e6..84637b683 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1048,6 +1048,32 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) return FALSE; } +// Check if AI mon has the means to faint the target with any of its moves. +// If numHits > 1, check if the target will be KO'ed by that number of hits (ignoring healing effects) +bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits) +{ + s32 i, dmg; + u32 unusable = CheckMoveLimitations(battlerAtk, 0, 0xFF & ~MOVE_LIMITATION_PP); + u16 *moves = gBattleMons[battlerAtk].moves; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i])) + { + continue; + } + // Use the pre-calculated value in simulatedDmg instead of re-calculating it + dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][i]; + + if (numHits) + dmg *= numHits; + if (gBattleMons[battlerDef].hp <= dmg) + return TRUE; + } + + return FALSE; +} + bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits) { s32 i, dmg; @@ -1677,7 +1703,7 @@ u32 CountNegativeStatStages(u8 battlerId) bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_ATK] > 4 @@ -1693,7 +1719,7 @@ bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_DEF] > 4 @@ -1709,7 +1735,7 @@ bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (IsAiFaster(AI_CHECK_SLOWER) @@ -1723,7 +1749,7 @@ bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_SPATK] > 4 @@ -1738,7 +1764,7 @@ bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_SPDEF] > 4 @@ -1753,7 +1779,7 @@ bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (defAbility != ABILITY_CONTRARY @@ -1767,7 +1793,7 @@ bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_EVASION] > DEFAULT_STAT_STAGE @@ -1779,7 +1805,7 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility) return FALSE; } -bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits) +bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits) { s32 dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][index]; @@ -2433,9 +2459,9 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Attacker goes first { - if (!CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) // Can't KO foe otherwise + if (!CanAIFaintTarget(battlerAtk, battlerDef, 0)) // Can't KO foe otherwise { - if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 2)) + if (CanAIFaintTarget(battlerAtk, battlerDef, 2)) { // attacker can kill target in two hits (theoretically) if (CanTargetFaintAi(battlerDef, battlerAtk)) @@ -2500,7 +2526,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo } else if (CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 2)) // Foe can 2HKO AI { - if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) + if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) { if (!BattlerWillFaintFromSecondaryDamage(battlerAtk, AI_DATA->atkAbility)) return CAN_TRY_PIVOT; // Use this move to KO if you must @@ -2512,7 +2538,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo } else // Foe can 3HKO+ AI { - if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) + if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) { if (!BattlerWillFaintFromSecondaryDamage(battlerAtk, AI_DATA->atkAbility) // This is the only move that can KO && !hasStatBoost) //You're not wasting a valuable stat boost @@ -2520,7 +2546,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo return CAN_TRY_PIVOT; } } - else if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 2)) + else if (CanAIFaintTarget(battlerAtk, battlerDef, 2)) { // can knock out foe in 2 hits if (IS_MOVE_STATUS(move) && (shouldSwitch //Damaging move @@ -2904,7 +2930,7 @@ bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveI if (recoilDmg >= gBattleMons[battlerAtk].hp //Recoil kills attacker && CountUsablePartyMons(battlerDef) != 0) //Foe has more than 1 target left { - if (recoilDmg >= gBattleMons[battlerDef].hp && !CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) + if (recoilDmg >= gBattleMons[battlerDef].hp && !CanAIFaintTarget(battlerAtk, battlerDef, 0)) return TRUE; //If it's the only KO move then just use it else return FALSE; //Not as good to use move if you'll faint and not win From 03cab2058a7b6d77b670251fc0702e5b3c4cef2f Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 8 Nov 2021 23:57:16 +1300 Subject: [PATCH 44/45] Fix goof, make AI check PP in move limitations Was skipping valid moves instead of invalid ones in CanAIFaintTarget. Also, remove all instances of ~MOVE_LIMITATION_PP from the AI as it seemed detrimental. --- src/battle_ai_util.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 84637b683..71dc78d0a 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -660,9 +660,9 @@ bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split) for (i = 0; i < MAX_MON_MOVES; i++) { if (moves[i] != MOVE_NONE - && moves[i] != 0xFFFF - && GetBattleMoveSplit(moves[i]) == split - && !(unusable & gBitTable[i])) + && moves[i] != 0xFFFF + && GetBattleMoveSplit(moves[i]) == split + && !(unusable & gBitTable[i])) { SetTypeBeforeUsingMove(moves[i], attacker); GET_MOVE_TYPE(moves[i], moveType); @@ -1033,7 +1033,7 @@ bool32 IsAiFaster(u8 battler) bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) { s32 i, dmg; - u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP); + u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF); u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef]; for (i = 0; i < MAX_MON_MOVES; i++) @@ -1053,22 +1053,22 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits) { s32 i, dmg; - u32 unusable = CheckMoveLimitations(battlerAtk, 0, 0xFF & ~MOVE_LIMITATION_PP); + u32 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF); u16 *moves = gBattleMons[battlerAtk].moves; for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i])) + if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(moveLimitations & gBitTable[i])) { - continue; - } - // Use the pre-calculated value in simulatedDmg instead of re-calculating it - dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][i]; + // Use the pre-calculated value in simulatedDmg instead of re-calculating it + dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][i]; - if (numHits) - dmg *= numHits; - if (gBattleMons[battlerDef].hp <= dmg) - return TRUE; + if (numHits) + dmg *= numHits; + + if (gBattleMons[battlerDef].hp <= dmg) + return TRUE; + } } return FALSE; @@ -1077,7 +1077,7 @@ bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits) bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits) { s32 i, dmg; - u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP); + u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF); if (move != MOVE_NONE && move != 0xFFFF && !(unusable & gBitTable[i]) && AI_CalcDamage(move, battlerDef, battlerAtk) >= gBattleMons[battlerAtk].hp) return TRUE; @@ -1089,7 +1089,7 @@ bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits) bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgMod) { u32 i; - u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP); + u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF); u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef]; for (i = 0; i < MAX_MON_MOVES; i++) From d3abd20dfb648601609be6f6039200491b52d44b Mon Sep 17 00:00:00 2001 From: kleeenexfeu <94004034+kleeenexfeu@users.noreply.github.com> Date: Tue, 9 Nov 2021 18:12:40 +0100 Subject: [PATCH 45/45] Fix heat crash/heavy slam calculation --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 7e06b55d1..4f09e3bb7 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7788,7 +7788,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) if (weight >= ARRAY_COUNT(sHeatCrashPowerTable)) basePower = sHeatCrashPowerTable[ARRAY_COUNT(sHeatCrashPowerTable) - 1]; else - basePower = sHeatCrashPowerTable[i]; + basePower = sHeatCrashPowerTable[weight]; break; case EFFECT_PUNISHMENT: basePower = 60 + (CountBattlerStatIncreases(battlerDef, FALSE) * 20);