From 557355eb417478d733ebd13c51412f7332beef5a Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Wed, 2 Oct 2024 21:29:43 +0200 Subject: [PATCH 01/15] Make functions CanAbilityAbsorbMove and CanAbilityBlockMove --- include/battle_util.h | 17 ++ src/battle_util.c | 352 ++++++++++++++++++++++-------------------- 2 files changed, 201 insertions(+), 168 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index c4727d8a121d..49a08d53c093 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -20,6 +20,23 @@ #define MOVE_LIMITATION_PLACEHOLDER (1 << 15) #define MOVE_LIMITATIONS_ALL 0xFFFF +enum MoveBlocked +{ + MOVE_BLOCKED_BY_NO_ABILITY, + MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF, + MOVE_BLOCKED_BY_DAZZLING, + MOVE_BLOCKED_BY_GOOD_AS_GOLD, + MOVE_BLOCKED_BY_PARTNER_DAZZLING, +}; + +enum MoveAbsorbed +{ + MOVE_ABSORBED_BY_NO_ABILITY, + MOVE_ABSORBED_BY_DRAIN_HP_ABILITY, + MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY, + MOVE_ABSORBED_BY_STAT_FLASH_FIRE, +}; + enum { ABILITYEFFECT_ON_SWITCHIN, ABILITYEFFECT_ENDTURN, diff --git a/src/battle_util.c b/src/battle_util.c index e32e21cf2a8c..c300521b3863 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4109,12 +4109,121 @@ static void ChooseStatBoostAnimation(u32 battler) #undef ANIM_STAT_ACC #undef ANIM_STAT_EVASION +static u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef) +{ + enum MoveBlocked effect = MOVE_BLOCKED_BY_NO_ABILITY; + u16 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); + + switch (abilityDef) + { + case ABILITY_SOUNDPROOF: + if (gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER)) + effect = MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF; + break; + case ABILITY_BULLETPROOF: + if (gMovesInfo[move].ballisticMove) + effect = MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF; + break; + case ABILITY_DAZZLING: + case ABILITY_QUEENLY_MAJESTY: + case ABILITY_ARMOR_TAIL: + if (GetChosenMovePriority(battlerAtk) > 0 && GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef)) + effect = MOVE_BLOCKED_BY_DAZZLING; + break; + case ABILITY_GOOD_AS_GOLD: + if (IS_MOVE_STATUS(move) + && !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) + && !(moveTarget & MOVE_TARGET_ALL_BATTLERS)) + effect = MOVE_BLOCKED_BY_GOOD_AS_GOLD; + break; + } + + if (!effect) + { + switch (GetBattlerAbility(BATTLE_PARTNER(battlerDef))) + { + case ABILITY_DAZZLING: + case ABILITY_QUEENLY_MAJESTY: + case ABILITY_ARMOR_TAIL: + if (GetChosenMovePriority(battlerAtk) > 0 && GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef)) + effect = MOVE_BLOCKED_BY_PARTNER_DAZZLING; + break; + } + } + + return effect; +} + +static u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 ability, u32 move, u32 moveType, u32 *statAmount, u32 *statId) +{ + enum MoveAbsorbed effect = MOVE_ABSORBED_BY_NO_ABILITY; + *statId = 0; + *statAmount = 1; + + switch (ability) + { + default: + effect = MOVE_ABSORBED_BY_NO_ABILITY; + break; + case ABILITY_VOLT_ABSORB: + if (moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) + effect = MOVE_ABSORBED_BY_DRAIN_HP_ABILITY; + break; + case ABILITY_WATER_ABSORB: + case ABILITY_DRY_SKIN: + if (moveType == TYPE_WATER) + effect = MOVE_ABSORBED_BY_DRAIN_HP_ABILITY; + break; + case ABILITY_EARTH_EATER: + if (moveType == TYPE_GROUND) + effect = MOVE_ABSORBED_BY_DRAIN_HP_ABILITY; + break; + case ABILITY_MOTOR_DRIVE: + if (moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) + *statId = STAT_SPEED; + effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; + break; + case ABILITY_LIGHTNING_ROD: + if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) + *statId = STAT_SPATK; + effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; + break; + case ABILITY_STORM_DRAIN: + if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_WATER) + *statId = STAT_SPATK; + effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; + break; + case ABILITY_SAP_SIPPER: + if (moveType == TYPE_GRASS) + *statId = STAT_ATK; + effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; + break; + case ABILITY_WELL_BAKED_BODY: + if (moveType == TYPE_FIRE) + *statAmount = 2; + *statId = STAT_DEF; + effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; + break; + case ABILITY_WIND_RIDER: + if (gMovesInfo[gCurrentMove].windMove && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) + *statId = STAT_ATK; + effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; + break; + case ABILITY_FLASH_FIRE: + if (moveType == TYPE_FIRE && (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[battlerDef].status1 & STATUS1_FREEZE))) + effect = MOVE_ABSORBED_BY_STAT_FLASH_FIRE; + break; + } + + return effect; +} + u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg) { u32 effect = 0; - u32 moveType, move; - u32 side; - u32 i, j; + u32 moveType = 0, move = 0; + u32 side = 0; + u32 i = 0, j = 0; u32 partner = 0; struct Pokemon *mon; @@ -5208,58 +5317,25 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } } break; - case ABILITYEFFECT_MOVES_BLOCK: case ABILITYEFFECT_WOULD_BLOCK: + effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility); + if (effect && gLastUsedAbility != 0xFFFF) + RecordAbilityBattle(battler, gLastUsedAbility); + break; + case ABILITYEFFECT_MOVES_BLOCK: { - u16 moveTarget = GetBattlerMoveTargetType(battler, move); + effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility); const u8 * battleScriptBlocksMove = NULL; - switch (gLastUsedAbility) - { - case ABILITY_SOUNDPROOF: - if (gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER)) - effect = 1; - break; - case ABILITY_BULLETPROOF: - if (gMovesInfo[move].ballisticMove) - effect = 1; - break; - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (GetChosenMovePriority(gBattlerAttacker) > 0 && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler)) - effect = 2; - break; - case ABILITY_GOOD_AS_GOLD: - if (IS_MOVE_STATUS(gCurrentMove) - && !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) - && !(moveTarget & MOVE_TARGET_ALL_BATTLERS)) - effect = 3; - break; - } - - if (!effect) - { - switch (GetBattlerAbility(BATTLE_PARTNER(battler))) - { - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (GetChosenMovePriority(gBattlerAttacker) > 0 && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler)) - effect = 4; - break; - } - } - - if (effect == 1) + if (effect == MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF) { if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_SoundproofProtected; } - else if (effect == 2 || effect == 4) + else if (effect == MOVE_BLOCKED_BY_DAZZLING || effect == MOVE_BLOCKED_BY_PARTNER_DAZZLING) { - if (effect == 4) + if (effect == MOVE_BLOCKED_BY_PARTNER_DAZZLING) gBattleScripting.battler = BATTLE_PARTNER(battler); else gBattleScripting.battler = battler; @@ -5268,7 +5344,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_DazzlingProtected; } - else if (effect == 3) + else if (effect == MOVE_BLOCKED_BY_GOOD_AS_GOLD) { battleScriptBlocksMove = BattleScript_GoodAsGoldActivates; } @@ -5276,153 +5352,93 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) && !(IS_MOVE_STATUS(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove))) { - if (!IsDoubleBattle() || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) + if (!IsDoubleBattle() + || !(GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected gBattleScripting.battler = gBattlerAbility = gBattlerTarget; battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster; effect = 1; } - if (caseID == ABILITYEFFECT_WOULD_BLOCK) - { - if (effect && gLastUsedAbility != 0xFFFF) - RecordAbilityBattle(battler, gLastUsedAbility); - - return effect; - } - else if (effect) - { + if (effect) gBattlescriptCurrInstr = battleScriptBlocksMove; - } - break; } - case ABILITYEFFECT_ABSORBING: + break; case ABILITYEFFECT_WOULD_ABSORB: - if (move != MOVE_NONE) + effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType, &i, &j); + gBattleStruct->pledgeMove = FALSE; + if (effect && gLastUsedAbility != 0xFFFF) + RecordAbilityBattle(battler, gLastUsedAbility); + return effect; + case ABILITYEFFECT_ABSORBING: + effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType, &i, &j); + if (effect == MOVE_ABSORBED_BY_DRAIN_HP_ABILITY) { - u8 statId = 0; - u8 statAmount = 1; - switch (gLastUsedAbility) + gBattleStruct->pledgeMove = FALSE; + if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { - case ABILITY_VOLT_ABSORB: - if (moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) - effect = 1; - break; - case ABILITY_WATER_ABSORB: - case ABILITY_DRY_SKIN: - if (moveType == TYPE_WATER) - effect = 1; - break; - case ABILITY_MOTOR_DRIVE: - if (moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) - effect = 2, statId = STAT_SPEED; - break; - case ABILITY_LIGHTNING_ROD: - if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) - effect = 2, statId = STAT_SPATK; - break; - case ABILITY_STORM_DRAIN: - if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_WATER) - effect = 2, statId = STAT_SPATK; - break; - case ABILITY_SAP_SIPPER: - if (moveType == TYPE_GRASS) - effect = 2, statId = STAT_ATK; - break; - case ABILITY_FLASH_FIRE: - if (moveType == TYPE_FIRE && (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[battler].status1 & STATUS1_FREEZE))) - effect = 3; - break; - case ABILITY_WELL_BAKED_BODY: - if (moveType == TYPE_FIRE) - effect = 2, statId = STAT_DEF, statAmount = 2; - break; - case ABILITY_WIND_RIDER: - if (gMovesInfo[gCurrentMove].windMove && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) - effect = 2, statId = STAT_ATK; - break; - case ABILITY_EARTH_EATER: - if (moveType == TYPE_GROUND) - effect = 1; - break; + if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) + gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; + else + gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss; } - if (caseID == ABILITYEFFECT_WOULD_ABSORB) + else { - gBattleStruct->pledgeMove = FALSE; - if (effect && gLastUsedAbility != 0xFFFF) - RecordAbilityBattle(battler, gLastUsedAbility); + if (gProtectStructs[gBattlerAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_MoveHPDrain; + else + gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss; - return effect; + gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + } + } + else if (effect == MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY) + { + gBattleStruct->pledgeMove = FALSE; + if (!CompareStat(battler, j, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) + gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; + else + gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss; } - else if (effect == 1) // Drain Hp ability. + else { - gBattleStruct->pledgeMove = FALSE; - if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK)) - { - if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) - gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; - else - gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss; - } + if (gProtectStructs[gBattlerAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_MoveStatDrain; else - { - if (gProtectStructs[gBattlerAttacker].notFirstStrike) - gBattlescriptCurrInstr = BattleScript_MoveHPDrain; - else - gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss; + gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss; - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - gBattleMoveDamage *= -1; - } + SET_STATCHANGER(j, i, FALSE); + if (B_ABSORBING_ABILITY_STRING < GEN_5) + PREPARE_STAT_BUFFER(gBattleTextBuff1, j); } - else if (effect == 2) // Boost Stat ability; + } + else if (effect == MOVE_ABSORBED_BY_STAT_FLASH_FIRE) + { + gBattleStruct->pledgeMove = FALSE; + if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE)) { - gBattleStruct->pledgeMove = FALSE; - if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) - gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; - else - gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss; - } + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST; + if (gProtectStructs[gBattlerAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_FlashFireBoost; else - { - if (gProtectStructs[gBattlerAttacker].notFirstStrike) - gBattlescriptCurrInstr = BattleScript_MoveStatDrain; - else - gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss; - - SET_STATCHANGER(statId, statAmount, FALSE); - if (B_ABSORBING_ABILITY_STRING < GEN_5) - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - } + gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; + gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_FLASH_FIRE; } - else if (effect == 3) + else { - gBattleStruct->pledgeMove = FALSE; - if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE)) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST; - if (gProtectStructs[gBattlerAttacker].notFirstStrike) - gBattlescriptCurrInstr = BattleScript_FlashFireBoost; - else - gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; - gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_FLASH_FIRE; - } + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST; + if (gProtectStructs[gBattlerAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_FlashFireBoost; else - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST; - if (gProtectStructs[gBattlerAttacker].notFirstStrike) - gBattlescriptCurrInstr = BattleScript_FlashFireBoost; - else - gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; - } + gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; } - - if (effect) - gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. } + if (effect) + gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. break; case ABILITYEFFECT_MOVE_END: // Think contact abilities. switch (gLastUsedAbility) From 982eac5a6089dfe67bc975504dcff98021feed05 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Thu, 3 Oct 2024 22:47:26 +0200 Subject: [PATCH 02/15] clean up --- src/battle_util.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index c300521b3863..21514b516abd 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4154,11 +4154,9 @@ static u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abi return effect; } -static u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 ability, u32 move, u32 moveType, u32 *statAmount, u32 *statId) +static u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 ability, u32 move, u32 moveType) { enum MoveAbsorbed effect = MOVE_ABSORBED_BY_NO_ABILITY; - *statId = 0; - *statAmount = 1; switch (ability) { @@ -4180,33 +4178,26 @@ static u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 ability, u32 break; case ABILITY_MOTOR_DRIVE: if (moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) - *statId = STAT_SPEED; effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_LIGHTNING_ROD: if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) - *statId = STAT_SPATK; effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_STORM_DRAIN: if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_WATER) - *statId = STAT_SPATK; effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_SAP_SIPPER: if (moveType == TYPE_GRASS) - *statId = STAT_ATK; effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_WELL_BAKED_BODY: if (moveType == TYPE_FIRE) - *statAmount = 2; - *statId = STAT_DEF; effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_WIND_RIDER: if (gMovesInfo[gCurrentMove].windMove && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) - *statId = STAT_ATK; effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_FLASH_FIRE: @@ -5364,13 +5355,38 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITYEFFECT_WOULD_ABSORB: - effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType, &i, &j); + effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType); gBattleStruct->pledgeMove = FALSE; if (effect && gLastUsedAbility != 0xFFFF) RecordAbilityBattle(battler, gLastUsedAbility); return effect; case ABILITYEFFECT_ABSORBING: - effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType, &i, &j); + effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType); + u32 statId = 0; + u32 statAmount = 0; + if (effect) + { + switch(gLastUsedAbility) + { + case ABILITY_MOTOR_DRIVE: + statId = STAT_SPEED; + break; + case ABILITY_LIGHTNING_ROD: + case ABILITY_STORM_DRAIN: + statId = STAT_SPATK; + break; + case ABILITY_SAP_SIPPER: + case ABILITY_WIND_RIDER: + statId = STAT_ATK; + break; + case ABILITY_WELL_BAKED_BODY: + statAmount = 2; + statId = STAT_DEF; + break; + + } + + } if (effect == MOVE_ABSORBED_BY_DRAIN_HP_ABILITY) { gBattleStruct->pledgeMove = FALSE; @@ -5397,7 +5413,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 else if (effect == MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY) { gBattleStruct->pledgeMove = FALSE; - if (!CompareStat(battler, j, MAX_STAT_STAGE, CMP_LESS_THAN)) + if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; @@ -5411,9 +5427,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 else gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss; - SET_STATCHANGER(j, i, FALSE); + SET_STATCHANGER(statId, statAmount, FALSE); if (B_ABSORBING_ABILITY_STRING < GEN_5) - PREPARE_STAT_BUFFER(gBattleTextBuff1, j); + PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); } } else if (effect == MOVE_ABSORBED_BY_STAT_FLASH_FIRE) From 663e55e5393bf5d95c3f53991dc691b1079fedf2 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Thu, 3 Oct 2024 23:11:37 +0200 Subject: [PATCH 03/15] Replace ai code with CanAbilityBlockMove / CanAbilityAbsorbMove --- include/battle_util.h | 2 + src/battle_ai_main.c | 38 ++-------- src/battle_ai_util.c | 46 ++---------- src/battle_util.c | 165 +++++++++++++++++++++--------------------- 4 files changed, 97 insertions(+), 154 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 49a08d53c093..ece5b60252c9 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -178,6 +178,8 @@ void SetAtkCancellerForCalledMove(void); u8 AtkCanceller_UnableToUseMove2(void); bool32 HasNoMonsToSwitch(u32 battler, u8 r1, u8 r2); bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility); +u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef); +u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType); u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg); bool32 TryPrimalReversion(u32 battler); bool32 IsNeutralizingGasOnField(void); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index a47d17839f43..ae66ca8efd4b 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -873,6 +873,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // target ability checks if (!DoesBattlerIgnoreAbilityChecks(aiData->abilities[battlerAtk], move)) { + if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef])) + RETURN_SCORE_MINUS(20); + + if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType)) + RETURN_SCORE_MINUS(20); + switch (aiData->abilities[battlerDef]) { case ABILITY_MAGIC_GUARD: @@ -903,12 +909,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && (moveType == TYPE_DARK || moveType == TYPE_GHOST || moveType == TYPE_BUG)) RETURN_SCORE_MINUS(10); break; - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (atkPriority > 0) - RETURN_SCORE_MINUS(10); - break; case ABILITY_AROMA_VEIL: if (IsAromaVeilProtectedMove(move)) RETURN_SCORE_MINUS(10); @@ -972,32 +972,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && IsNonVolatileStatusMoveEffect(moveEffect)) RETURN_SCORE_MINUS(10); break; - case ABILITY_LIGHTNING_ROD: - if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5) - break; - // Fallthrough - case ABILITY_MOTOR_DRIVE: - case ABILITY_VOLT_ABSORB: - if (moveType == TYPE_ELECTRIC) - RETURN_SCORE_MINUS(20); - break; - case ABILITY_STORM_DRAIN: - if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5) - break; - // Fallthrough - case ABILITY_WATER_ABSORB: - case ABILITY_DRY_SKIN: - if (moveType == TYPE_WATER) - RETURN_SCORE_MINUS(20); - break; - case ABILITY_FLASH_FIRE: - if (moveType == TYPE_FIRE) - RETURN_SCORE_MINUS(20); - break; - case ABILITY_EARTH_EATER: - if (moveType == TYPE_GROUND) - RETURN_SCORE_MINUS(20); - break; } // def ability checks // target partner ability checks & not attacking partner diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 3ef613d1fc48..705399be842a 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -415,47 +415,11 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) if (gBattleStruct->commandingDondozo & (1u << battlerDef)) return TRUE; - switch (battlerDefAbility) - { - case ABILITY_LIGHTNING_ROD: - if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5) - break; - // Fallthrough - case ABILITY_VOLT_ABSORB: - case ABILITY_MOTOR_DRIVE: - if (moveType == TYPE_ELECTRIC) - return TRUE; - break; - case ABILITY_STORM_DRAIN: - if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5) - break; - // Fallthrough - case ABILITY_WATER_ABSORB: - case ABILITY_DRY_SKIN: - if (moveType == TYPE_WATER) - return TRUE; - break; - case ABILITY_FLASH_FIRE: - if (moveType == TYPE_FIRE) - return TRUE; - break; - case ABILITY_SOUNDPROOF: - if (gMovesInfo[move].soundMove) - return TRUE; - break; - case ABILITY_BULLETPROOF: - if (gMovesInfo[move].ballisticMove) - return TRUE; - break; - case ABILITY_SAP_SIPPER: - if (moveType == TYPE_GRASS) - return TRUE; - break; - case ABILITY_EARTH_EATER: - if (moveType == TYPE_GROUND) - return TRUE; - break; - } + if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef])) + return TRUE; + + if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType)) + return TRUE; switch (gMovesInfo[move].effect) { diff --git a/src/battle_util.c b/src/battle_util.c index 21514b516abd..975e21923b21 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4109,7 +4109,7 @@ static void ChooseStatBoostAnimation(u32 battler) #undef ANIM_STAT_ACC #undef ANIM_STAT_EVASION -static u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef) +u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef) { enum MoveBlocked effect = MOVE_BLOCKED_BY_NO_ABILITY; u16 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); @@ -4154,11 +4154,11 @@ static u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abi return effect; } -static u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 ability, u32 move, u32 moveType) +u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType) { enum MoveAbsorbed effect = MOVE_ABSORBED_BY_NO_ABILITY; - switch (ability) + switch (abilityDef) { default: effect = MOVE_ABSORBED_BY_NO_ABILITY; @@ -4197,7 +4197,7 @@ static u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 ability, u32 effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_WIND_RIDER: - if (gMovesInfo[gCurrentMove].windMove && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) + if (gMovesInfo[move].windMove && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER)) effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_FLASH_FIRE: @@ -5361,100 +5361,103 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 RecordAbilityBattle(battler, gLastUsedAbility); return effect; case ABILITYEFFECT_ABSORBING: - effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType); - u32 statId = 0; - u32 statAmount = 0; - if (effect) { - switch(gLastUsedAbility) + u32 statId = 0; + u32 statAmount = 0; + effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType); + if (effect) { - case ABILITY_MOTOR_DRIVE: - statId = STAT_SPEED; - break; - case ABILITY_LIGHTNING_ROD: - case ABILITY_STORM_DRAIN: - statId = STAT_SPATK; - break; - case ABILITY_SAP_SIPPER: - case ABILITY_WIND_RIDER: - statId = STAT_ATK; - break; - case ABILITY_WELL_BAKED_BODY: - statAmount = 2; - statId = STAT_DEF; - break; + switch(gLastUsedAbility) + { + case ABILITY_MOTOR_DRIVE: + statId = STAT_SPEED; + break; + case ABILITY_LIGHTNING_ROD: + case ABILITY_STORM_DRAIN: + statId = STAT_SPATK; + break; + case ABILITY_SAP_SIPPER: + case ABILITY_WIND_RIDER: + statId = STAT_ATK; + break; + case ABILITY_WELL_BAKED_BODY: + statAmount = 2; + statId = STAT_DEF; + break; - } + } - } - if (effect == MOVE_ABSORBED_BY_DRAIN_HP_ABILITY) - { - gBattleStruct->pledgeMove = FALSE; - if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK)) - { - if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) - gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; - else - gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss; } - else + if (effect == MOVE_ABSORBED_BY_DRAIN_HP_ABILITY) { - if (gProtectStructs[gBattlerAttacker].notFirstStrike) - gBattlescriptCurrInstr = BattleScript_MoveHPDrain; + gBattleStruct->pledgeMove = FALSE; + if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + { + if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) + gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; + else + gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss; + } else - gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss; + { + if (gProtectStructs[gBattlerAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_MoveHPDrain; + else + gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss; - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - gBattleMoveDamage *= -1; - } - } - else if (effect == MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY) - { - gBattleStruct->pledgeMove = FALSE; - if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) - gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; - else - gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss; + gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + } } - else + else if (effect == MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY) { - if (gProtectStructs[gBattlerAttacker].notFirstStrike) - gBattlescriptCurrInstr = BattleScript_MoveStatDrain; + gBattleStruct->pledgeMove = FALSE; + if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) + gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; + else + gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss; + } else - gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss; + { + if (gProtectStructs[gBattlerAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_MoveStatDrain; + else + gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss; - SET_STATCHANGER(statId, statAmount, FALSE); - if (B_ABSORBING_ABILITY_STRING < GEN_5) - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - } - } - else if (effect == MOVE_ABSORBED_BY_STAT_FLASH_FIRE) - { - gBattleStruct->pledgeMove = FALSE; - if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE)) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST; - if (gProtectStructs[gBattlerAttacker].notFirstStrike) - gBattlescriptCurrInstr = BattleScript_FlashFireBoost; - else - gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; - gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_FLASH_FIRE; + SET_STATCHANGER(statId, statAmount, FALSE); + if (B_ABSORBING_ABILITY_STRING < GEN_5) + PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); + } } - else + else if (effect == MOVE_ABSORBED_BY_STAT_FLASH_FIRE) { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST; - if (gProtectStructs[gBattlerAttacker].notFirstStrike) - gBattlescriptCurrInstr = BattleScript_FlashFireBoost; + gBattleStruct->pledgeMove = FALSE; + if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST; + if (gProtectStructs[gBattlerAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_FlashFireBoost; + else + gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; + gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_FLASH_FIRE; + } else - gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST; + if (gProtectStructs[gBattlerAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_FlashFireBoost; + else + gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; + } } + if (effect) + gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. + } - if (effect) - gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. break; case ABILITYEFFECT_MOVE_END: // Think contact abilities. switch (gLastUsedAbility) From e43d8767c4743c36f0f2132e4ceaf24447294ee3 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 00:32:52 +0200 Subject: [PATCH 04/15] Adds CanPartnerAbilityBlockMove --- include/battle.h | 2 +- include/battle_util.h | 1 + src/battle_ai_main.c | 3 +++ src/battle_ai_util.c | 12 ++++++++++-- src/battle_main.c | 3 +++ src/battle_util.c | 38 +++++++++++++++++++++++++------------- 6 files changed, 43 insertions(+), 16 deletions(-) diff --git a/include/battle.h b/include/battle.h index f463a2440b3d..b7b38324e24c 100644 --- a/include/battle.h +++ b/include/battle.h @@ -377,6 +377,7 @@ struct AiLogicData bool8 ejectButtonSwitch; // Tracks whether current switch out was from Eject Button bool8 ejectPackSwitch; // Tracks whether current switch out was from Eject Pack u8 shouldSwitch; // Stores result of ShouldSwitch, which decides whether a mon should be switched out + u8 aiCalcInProgress:1; }; struct AI_ThinkingStruct @@ -715,7 +716,6 @@ struct BattleStruct } multiBuffer; u8 wishPerishSongState; u8 wishPerishSongBattlerId; - u8 aiCalcInProgress:1; u8 overworldWeatherDone:1; u8 startingStatusDone:1; u8 isAtkCancelerForCalledMove:1; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice. diff --git a/include/battle_util.h b/include/battle_util.h index ece5b60252c9..355ead0d3d84 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -179,6 +179,7 @@ u8 AtkCanceller_UnableToUseMove2(void); bool32 HasNoMonsToSwitch(u32 battler, u8 r1, u8 r2); bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility); u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef); +u32 CanPartnerAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef); u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType); u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg); bool32 TryPrimalReversion(u32 battler); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index ae66ca8efd4b..aabd4993090e 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -876,6 +876,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef])) RETURN_SCORE_MINUS(20); + if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[BATTLE_PARTNER(battlerDef)])) + RETURN_SCORE_MINUS(20); + if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType)) RETURN_SCORE_MINUS(20); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 705399be842a..0afeb97535cb 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -402,12 +402,19 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) { struct AiLogicData *aiData = AI_DATA; u32 battlerDefAbility; + u32 partnerBattlerDefAbility; u32 moveType = GetMoveType(move); if (DoesBattlerIgnoreAbilityChecks(aiData->abilities[battlerAtk], move)) + { battlerDefAbility = ABILITY_NONE; + partnerBattlerDefAbility = ABILITY_NONE; + } else + { battlerDefAbility = aiData->abilities[battlerDef]; + partnerBattlerDefAbility = aiData->abilities[BATTLE_PARTNER(battlerDef)]; + } if (battlerDef == BATTLE_PARTNER(battlerAtk)) battlerDefAbility = aiData->abilities[battlerDef]; @@ -418,6 +425,9 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef])) return TRUE; + if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, partnerBattlerDefAbility)) + return TRUE; + if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType)) return TRUE; @@ -490,7 +500,6 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u bool32 isDamageMoveUnusable = FALSE; bool32 toggledGimmick = FALSE; struct AiLogicData *aiData = AI_DATA; - gBattleStruct->aiCalcInProgress = TRUE; if (moveEffect == EFFECT_NATURE_POWER) move = GetNaturePowerMove(battlerAtk); @@ -700,7 +709,6 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u *typeEffectiveness = AI_GetEffectiveness(effectivenessMultiplier); // Undo temporary settings - gBattleStruct->aiCalcInProgress = FALSE; gBattleStruct->swapDamageCategory = FALSE; gBattleStruct->zmove.baseMoves[battlerAtk] = MOVE_NONE; if (toggledGimmick) diff --git a/src/battle_main.c b/src/battle_main.c index 9a430952c307..fa65e68ff54a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4198,7 +4198,10 @@ static void HandleTurnActionSelectionState(void) AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, TRUE); else AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, FALSE); + + AI_DATA->aiCalcInProgress = TRUE; gBattleStruct->aiMoveOrAction[battler] = ComputeBattleAiScores(battler); + AI_DATA->aiCalcInProgress = FALSE; } // fallthrough case STATE_BEFORE_ACTION_CHOSEN: // Choose an action. diff --git a/src/battle_util.c b/src/battle_util.c index 975e21923b21..18d62ec112f2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4127,8 +4127,12 @@ u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef case ABILITY_DAZZLING: case ABILITY_QUEENLY_MAJESTY: case ABILITY_ARMOR_TAIL: - if (GetChosenMovePriority(battlerAtk) > 0 && GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef)) - effect = MOVE_BLOCKED_BY_DAZZLING; + if (GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef)) + { + u32 priority = AI_DATA->aiCalcInProgress ? GetMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk); + if (priority > 0) + effect = MOVE_BLOCKED_BY_PARTNER_DAZZLING; + } break; case ABILITY_GOOD_AS_GOLD: if (IS_MOVE_STATUS(move) @@ -4139,19 +4143,27 @@ u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef } if (!effect) + effect = CanPartnerAbilityBlockMove(battlerAtk, battlerDef, GetBattlerAbility(BATTLE_PARTNER(battlerDef)), move); + + return effect; +} + +u32 CanPartnerAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef) +{ + switch (abilityDef) { - switch (GetBattlerAbility(BATTLE_PARTNER(battlerDef))) + case ABILITY_DAZZLING: + case ABILITY_QUEENLY_MAJESTY: + case ABILITY_ARMOR_TAIL: + if (GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef)) { - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (GetChosenMovePriority(battlerAtk) > 0 && GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef)) - effect = MOVE_BLOCKED_BY_PARTNER_DAZZLING; - break; + u32 priority = AI_DATA->aiCalcInProgress ? GetMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk); + if (priority > 0) + return MOVE_BLOCKED_BY_PARTNER_DAZZLING; } + break; } - - return effect; + return MOVE_BLOCKED_BY_NO_ABILITY; } u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType) @@ -5363,7 +5375,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITYEFFECT_ABSORBING: { u32 statId = 0; - u32 statAmount = 0; + u32 statAmount = 1; effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType); if (effect) { @@ -10396,7 +10408,7 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move mod = UQ_4_12(1.0); } - if (gBattleStruct->distortedTypeMatchups & (1u << battlerDef) || (gBattleStruct->aiCalcInProgress && ShouldTeraShellDistortTypeMatchups(move, battlerDef))) + if (gBattleStruct->distortedTypeMatchups & (1u << battlerDef) || (AI_DATA->aiCalcInProgress && ShouldTeraShellDistortTypeMatchups(move, battlerDef))) { mod = UQ_4_12(0.5); if (recordAbilities) From ed47a358f9accffd394f256dfa577ee7a4362278 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 00:51:06 +0200 Subject: [PATCH 05/15] Use switches instead of if-blocks --- src/battle_util.c | 56 +++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 18d62ec112f2..985bec2bf743 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5329,38 +5329,38 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility); const u8 * battleScriptBlocksMove = NULL; - - if (effect == MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF) + switch (effect) { + case MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF: if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_SoundproofProtected; - } - else if (effect == MOVE_BLOCKED_BY_DAZZLING || effect == MOVE_BLOCKED_BY_PARTNER_DAZZLING) - { + break; + case MOVE_BLOCKED_BY_DAZZLING: + case MOVE_BLOCKED_BY_PARTNER_DAZZLING: if (effect == MOVE_BLOCKED_BY_PARTNER_DAZZLING) gBattleScripting.battler = BATTLE_PARTNER(battler); else gBattleScripting.battler = battler; - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_DazzlingProtected; - } - else if (effect == MOVE_BLOCKED_BY_GOOD_AS_GOLD) - { + break; + case MOVE_BLOCKED_BY_GOOD_AS_GOLD: battleScriptBlocksMove = BattleScript_GoodAsGoldActivates; - } - else if (GetChosenMovePriority(gBattlerAttacker) > 0 - && BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) - && !(IS_MOVE_STATUS(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove))) - { - if (!IsDoubleBattle() - || !(GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) - CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected - gBattleScripting.battler = gBattlerAbility = gBattlerTarget; - battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster; - effect = 1; + break; + default: + if (GetChosenMovePriority(gBattlerAttacker) > 0 + && BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) + && !(IS_MOVE_STATUS(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove))) + { + if (!IsDoubleBattle() + || !(GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) + CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected + gBattleScripting.battler = gBattlerAbility = gBattlerTarget; + battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster; + effect = 1; + } } if (effect) gBattlescriptCurrInstr = battleScriptBlocksMove; @@ -5396,12 +5396,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 statAmount = 2; statId = STAT_DEF; break; - } - } - if (effect == MOVE_ABSORBED_BY_DRAIN_HP_ABILITY) + switch (effect) { + case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY: gBattleStruct->pledgeMove = FALSE; if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { @@ -5422,9 +5421,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleMoveDamage = 1; gBattleMoveDamage *= -1; } - } - else if (effect == MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY) - { + break; + case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY: gBattleStruct->pledgeMove = FALSE; if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { @@ -5444,9 +5442,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (B_ABSORBING_ABILITY_STRING < GEN_5) PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); } - } - else if (effect == MOVE_ABSORBED_BY_STAT_FLASH_FIRE) - { + break; + case MOVE_ABSORBED_BY_STAT_FLASH_FIRE: gBattleStruct->pledgeMove = FALSE; if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE)) { @@ -5465,6 +5462,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 else gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; } + break; } if (effect) gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. From d373fa98a92da84612a1e39f8f24a3f4f5fc2e69 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 00:59:24 +0200 Subject: [PATCH 06/15] solve potential bug in singles with spread attacks --- src/battle_util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 985bec2bf743..465f0e966743 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4189,11 +4189,11 @@ u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 mov effect = MOVE_ABSORBED_BY_DRAIN_HP_ABILITY; break; case ABILITY_MOTOR_DRIVE: - if (moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) + if (moveType == TYPE_ELECTRIC && !(IsDoubleBattle() && GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_ALL_BATTLERS)) effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_LIGHTNING_ROD: - if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) + if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && !(IsDoubleBattle() && GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_ALL_BATTLERS)) effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_STORM_DRAIN: @@ -4209,7 +4209,7 @@ u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 mov effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_WIND_RIDER: - if (gMovesInfo[move].windMove && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER)) + if (gMovesInfo[move].windMove && GetBattlerMoveTargetType(battlerAtk, move) != MOVE_TARGET_USER) effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_FLASH_FIRE: From 91b33705a6e0c70677e855becfdf4aed578b91dc Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 01:17:34 +0200 Subject: [PATCH 07/15] fix test --- 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 465f0e966743..c9e589cefe61 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4143,7 +4143,7 @@ u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef } if (!effect) - effect = CanPartnerAbilityBlockMove(battlerAtk, battlerDef, GetBattlerAbility(BATTLE_PARTNER(battlerDef)), move); + effect = CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, GetBattlerAbility(BATTLE_PARTNER(battlerDef))); return effect; } From 3de5f84e48404a3bb03ea8e7dbc3077fad6398c4 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 08:58:49 +0200 Subject: [PATCH 08/15] revert other fix --- include/battle_util.h | 2 +- include/config/general.h | 2 +- src/battle_util.c | 21 +++++++++++---------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 355ead0d3d84..786757d184c7 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -25,8 +25,8 @@ enum MoveBlocked MOVE_BLOCKED_BY_NO_ABILITY, MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF, MOVE_BLOCKED_BY_DAZZLING, - MOVE_BLOCKED_BY_GOOD_AS_GOLD, MOVE_BLOCKED_BY_PARTNER_DAZZLING, + MOVE_BLOCKED_BY_GOOD_AS_GOLD, }; enum MoveAbsorbed diff --git a/include/config/general.h b/include/config/general.h index cff1432bb737..bd34106832c5 100644 --- a/include/config/general.h +++ b/include/config/general.h @@ -6,7 +6,7 @@ // still has them in the ROM. This is because the developers forgot // to define NDEBUG before release, however this has been changed as // Ruby's actual debug build does not use the AGBPrint features. -#define NDEBUG +// #define NDEBUG // To enable printf debugging, comment out "#define NDEBUG". This allows // the various AGBPrint functions to be used. (See include/gba/isagbprint.h). diff --git a/src/battle_util.c b/src/battle_util.c index c9e589cefe61..23c3dca5a183 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4112,12 +4112,11 @@ static void ChooseStatBoostAnimation(u32 battler) u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef) { enum MoveBlocked effect = MOVE_BLOCKED_BY_NO_ABILITY; - u16 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); switch (abilityDef) { case ABILITY_SOUNDPROOF: - if (gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER)) + if (gMovesInfo[move].soundMove && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER)) effect = MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF; break; case ABILITY_BULLETPROOF: @@ -4131,14 +4130,16 @@ u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef { u32 priority = AI_DATA->aiCalcInProgress ? GetMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk); if (priority > 0) - effect = MOVE_BLOCKED_BY_PARTNER_DAZZLING; + effect = MOVE_BLOCKED_BY_DAZZLING; } break; case ABILITY_GOOD_AS_GOLD: - if (IS_MOVE_STATUS(move) - && !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) - && !(moveTarget & MOVE_TARGET_ALL_BATTLERS)) - effect = MOVE_BLOCKED_BY_GOOD_AS_GOLD; + if (IS_MOVE_STATUS(move)) + { + u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); + if (!(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) && !(moveTarget & MOVE_TARGET_ALL_BATTLERS)) + effect = MOVE_BLOCKED_BY_GOOD_AS_GOLD; + } break; } @@ -4189,11 +4190,11 @@ u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 mov effect = MOVE_ABSORBED_BY_DRAIN_HP_ABILITY; break; case ABILITY_MOTOR_DRIVE: - if (moveType == TYPE_ELECTRIC && !(IsDoubleBattle() && GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_ALL_BATTLERS)) + if (moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) // Potential bug in singles (might be solved with simu hp reudction) effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_LIGHTNING_ROD: - if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && !(IsDoubleBattle() && GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_ALL_BATTLERS)) + if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && gMovesInfo[move].target != MOVE_TARGET_ALL_BATTLERS) // Potential bug in singles (might be solved with simu hp reudction) effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_STORM_DRAIN: @@ -4209,7 +4210,7 @@ u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 mov effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_WIND_RIDER: - if (gMovesInfo[move].windMove && GetBattlerMoveTargetType(battlerAtk, move) != MOVE_TARGET_USER) + if (gMovesInfo[move].windMove && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER)) effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY; break; case ABILITY_FLASH_FIRE: From 28291ba2d90499e5999f578ed1c91b1e796d0e7d Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 09:03:23 +0200 Subject: [PATCH 09/15] flash fire does not increase a stat --- include/battle_util.h | 2 +- src/battle_util.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 786757d184c7..504c3be3ad1b 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -34,7 +34,7 @@ enum MoveAbsorbed MOVE_ABSORBED_BY_NO_ABILITY, MOVE_ABSORBED_BY_DRAIN_HP_ABILITY, MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY, - MOVE_ABSORBED_BY_STAT_FLASH_FIRE, + MOVE_ABSORBED_BY_BOOST_FLASH_FIRE, }; enum { diff --git a/src/battle_util.c b/src/battle_util.c index 23c3dca5a183..36c125cc0f0c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4215,7 +4215,7 @@ u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 mov break; case ABILITY_FLASH_FIRE: if (moveType == TYPE_FIRE && (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[battlerDef].status1 & STATUS1_FREEZE))) - effect = MOVE_ABSORBED_BY_STAT_FLASH_FIRE; + effect = MOVE_ABSORBED_BY_BOOST_FLASH_FIRE; break; } @@ -5444,7 +5444,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); } break; - case MOVE_ABSORBED_BY_STAT_FLASH_FIRE: + case MOVE_ABSORBED_BY_BOOST_FLASH_FIRE: gBattleStruct->pledgeMove = FALSE; if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE)) { From b621bcbdbb885bfc29182e12c88e91c2da69d2a0 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 09:05:20 +0200 Subject: [PATCH 10/15] left a comment for a future test and addition --- src/battle_ai_main.c | 1 + src/battle_ai_util.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index aabd4993090e..e9da0498076a 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -879,6 +879,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[BATTLE_PARTNER(battlerDef)])) RETURN_SCORE_MINUS(20); + // This Also needs to look at partner for non spread attacks. Needs testing though if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType)) RETURN_SCORE_MINUS(20); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 0afeb97535cb..81409d2ff0d5 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -428,6 +428,7 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, partnerBattlerDefAbility)) return TRUE; + // This Also needs to look at partner for non spread attacks. Needs testing though if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType)) return TRUE; From db0dbc64d35a741824cd2053c6d801561b5521ed Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 09:08:01 +0200 Subject: [PATCH 11/15] remove more checks --- src/battle_ai_main.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index e9da0498076a..a98bceb1cdbd 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1007,12 +1007,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsAromaVeilProtectedMove(move)) RETURN_SCORE_MINUS(10); break; - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (atkPriority > 0) - RETURN_SCORE_MINUS(10); - break; } } // def partner ability checks } // ignore def ability check From 14602bfecbedc6bbf4eb546c3c81acc4116cfcd7 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 09:10:36 +0200 Subject: [PATCH 12/15] comment was incorrect. it only applies to storm drain and lightning rod --- src/battle_ai_main.c | 7 +++---- src/battle_ai_util.c | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index a98bceb1cdbd..260a46570e17 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -876,10 +876,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef])) RETURN_SCORE_MINUS(20); - if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[BATTLE_PARTNER(battlerDef)])) - RETURN_SCORE_MINUS(20); - - // This Also needs to look at partner for non spread attacks. Needs testing though if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType)) RETURN_SCORE_MINUS(20); @@ -981,6 +977,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // target partner ability checks & not attacking partner if (isDoubleBattle) { + if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[BATTLE_PARTNER(battlerDef)])) + RETURN_SCORE_MINUS(20); + switch (aiData->abilities[BATTLE_PARTNER(battlerDef)]) { case ABILITY_LIGHTNING_ROD: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 81409d2ff0d5..0afeb97535cb 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -428,7 +428,6 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, partnerBattlerDefAbility)) return TRUE; - // This Also needs to look at partner for non spread attacks. Needs testing though if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType)) return TRUE; From aa339cf11fdf7edca2cbf7b84a68245c7431c4a5 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 4 Oct 2024 19:38:59 +0200 Subject: [PATCH 13/15] revert ndebug --- include/config/general.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config/general.h b/include/config/general.h index bd34106832c5..cff1432bb737 100644 --- a/include/config/general.h +++ b/include/config/general.h @@ -6,7 +6,7 @@ // still has them in the ROM. This is because the developers forgot // to define NDEBUG before release, however this has been changed as // Ruby's actual debug build does not use the AGBPrint features. -// #define NDEBUG +#define NDEBUG // To enable printf debugging, comment out "#define NDEBUG". This allows // the various AGBPrint functions to be used. (See include/gba/isagbprint.h). From e245388a39214c9f601f184b0dfddae56cbe37b4 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Wed, 9 Oct 2024 08:18:56 +0200 Subject: [PATCH 14/15] revert minor change --- src/battle_ai_util.c | 3 ++- src/battle_main.c | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 0afeb97535cb..837c0462dded 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -500,6 +500,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u bool32 isDamageMoveUnusable = FALSE; bool32 toggledGimmick = FALSE; struct AiLogicData *aiData = AI_DATA; + AI_DATA->aiCalcInProgress = TRUE; if (moveEffect == EFFECT_NATURE_POWER) move = GetNaturePowerMove(battlerAtk); @@ -713,7 +714,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u gBattleStruct->zmove.baseMoves[battlerAtk] = MOVE_NONE; if (toggledGimmick) SetActiveGimmick(battlerAtk, GIMMICK_NONE); - + AI_DATA->aiCalcInProgress = FALSE; return simDamage; } diff --git a/src/battle_main.c b/src/battle_main.c index fa65e68ff54a..bcb58bd60b85 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4199,9 +4199,7 @@ static void HandleTurnActionSelectionState(void) else AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, FALSE); - AI_DATA->aiCalcInProgress = TRUE; gBattleStruct->aiMoveOrAction[battler] = ComputeBattleAiScores(battler); - AI_DATA->aiCalcInProgress = FALSE; } // fallthrough case STATE_BEFORE_ACTION_CHOSEN: // Choose an action. From b39a004a11f98e96ebdaf264cc657e93a9ed6679 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:25:44 +0200 Subject: [PATCH 15/15] Update src/battle_util.c --- 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 36c125cc0f0c..e6440a329a4e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4158,7 +4158,7 @@ u32 CanPartnerAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abi case ABILITY_ARMOR_TAIL: if (GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef)) { - u32 priority = AI_DATA->aiCalcInProgress ? GetMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk); + s32 priority = AI_DATA->aiCalcInProgress ? GetMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk); if (priority > 0) return MOVE_BLOCKED_BY_PARTNER_DAZZLING; }