From 63ec03748155b180a41410cbab70af18321b7ff3 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 18 Sep 2022 18:16:08 +0100 Subject: [PATCH] AI changes for some multi-hit/multi-turn moves, improved AI's damage calculation --- .../003_Move/009_MoveEffects_MultiHit.rb | 23 +- .../012_MoveEffects_ChangeMoveEffect.rb | 2 +- .../005_AI/055_AI_MoveHandlers_MultiHit.rb | 289 ++++++++++++------ Data/Scripts/011_Battle/005_AI/103_AIMove.rb | 39 ++- 4 files changed, 235 insertions(+), 118 deletions(-) diff --git a/Data/Scripts/011_Battle/003_Move/009_MoveEffects_MultiHit.rb b/Data/Scripts/011_Battle/003_Move/009_MoveEffects_MultiHit.rb index 6cec25d88..825ab45db 100644 --- a/Data/Scripts/011_Battle/003_Move/009_MoveEffects_MultiHit.rb +++ b/Data/Scripts/011_Battle/003_Move/009_MoveEffects_MultiHit.rb @@ -291,11 +291,22 @@ end # Special Defense and Speed by 2 stages each in the second turn. (Geomancy) #=============================================================================== class Battle::Move::TwoTurnAttackRaiseUserSpAtkSpDefSpd2 < Battle::Move::TwoTurnMove + attr_reader :statUp + + def initialize(battle, move) + super + @statUp = [:SPECIAL_ATTACK, 2, :SPECIAL_DEFENSE, 2, :SPEED, 2] + end + def pbMoveFailed?(user, targets) return false if user.effects[PBEffects::TwoTurnAttack] # Charging turn - if !user.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user, self) && - !user.pbCanRaiseStatStage?(:SPECIAL_DEFENSE, user, self) && - !user.pbCanRaiseStatStage?(:SPEED, user, self) + failed = true + (@statUp.length / 2).times do |i| + next if !user.pbCanRaiseStatStage?(@statUp[i * 2], user, self) + failed = false + break + end + if failed @battle.pbDisplay(_INTL("{1}'s stats won't go any higher!", user.pbThis)) return true end @@ -309,9 +320,9 @@ class Battle::Move::TwoTurnAttackRaiseUserSpAtkSpDefSpd2 < Battle::Move::TwoTurn def pbEffectGeneral(user) return if !@damagingTurn showAnim = true - [:SPECIAL_ATTACK, :SPECIAL_DEFENSE, :SPEED].each do |s| - next if !user.pbCanRaiseStatStage?(s, user, self) - if user.pbRaiseStatStage(s, 2, user, showAnim) + (@statUp.length / 2).times do |i| + next if !user.pbCanRaiseStatStage?(@statUp[i * 2], user, self) + if user.pbRaiseStatStage(@statUp[i * 2], @statUp[(i * 2) + 1], user, showAnim) showAnim = false end end diff --git a/Data/Scripts/011_Battle/003_Move/012_MoveEffects_ChangeMoveEffect.rb b/Data/Scripts/011_Battle/003_Move/012_MoveEffects_ChangeMoveEffect.rb index 337ab0b1c..6463704c1 100644 --- a/Data/Scripts/011_Battle/003_Move/012_MoveEffects_ChangeMoveEffect.rb +++ b/Data/Scripts/011_Battle/003_Move/012_MoveEffects_ChangeMoveEffect.rb @@ -693,7 +693,7 @@ class Battle::Move::UseLastMoveUsed < Battle::Move "ProtectUser", # Detect, Protect "ProtectUserSideFromPriorityMoves", # Quick Guard # Not listed on Bulbapedia "ProtectUserSideFromMultiTargetDamagingMoves", # Wide Guard # Not listed on Bulbapedia - "UserEnduresFaintingThisTurn", # Endure + "UserEnduresFaintingThisTurn", # Endure "ProtectUserSideFromDamagingMovesIfUserFirstTurn", # Mat Block "ProtectUserSideFromStatusMoves", # Crafty Shield # Not listed on Bulbapedia "ProtectUserFromDamagingMovesKingsShield", # King's Shield diff --git a/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb b/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb index 5605995b9..644f65115 100644 --- a/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb +++ b/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb @@ -1,11 +1,23 @@ #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes", proc { |power, move, user, target, ai, battle| next power * move.move.pbNumHits(user.battler, [target.battler]) } ) +Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimes", + proc { |score, move, user, target, ai, battle| + # Prefer if the target has a Substitute and the first hit can break it + if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) + dmg = move.rough_damage + num_hits = move.move.pbNumHits(user.battler, [target.battler]) + score += 10 if target.effects[PBEffects::Substitute] < dmg * (num_hits - 1) / num_hits + end + # TODO: Consider effects that trigger per hit. + next score + } +) #=============================================================================== # TODO: Review score modifiers. @@ -14,7 +26,11 @@ Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", "HitTwoTimesPoisonTarget") Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget", proc { |score, move, user, target, ai, battle| - next 0 if !target.battler.pbCanPoison?(user.battler, false) + # Score for hitting multiple times + score = Battle::AI::Handlers.apply_move_effect_score("HitTwoTimes", + score, move, user, target, ai, battle) + next score if !target.battler.pbCanPoison?(user.battler, false) + # Poisoning score += 30 if ai.trainer.medium_skill? score += 30 if target.hp <= target.totalhp / 4 @@ -37,7 +53,19 @@ Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", "HitTwoTimesFlinchTarget") Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesFlinchTarget", proc { |score, move, user, target, ai, battle| - next score + 30 if target.effects[PBEffects::Minimize] + dmg = move.rough_damage + num_hits = move.move.pbNumHits(user.battler, [target.battler]) + # Prefer if the target has a Substitute and the first hit can break it + if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) + score += 10 if target.effects[PBEffects::Substitute] < dmg / num_hits + end + # Flinching + if user.faster_than?(target) && target.effects[PBEffects::Substitute] < dmg / num_hits && + (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) + score += 10 + end + # TODO: Consider effects that trigger per hit. + next score } ) @@ -51,33 +79,35 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimesTargetThenTargetAlly", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit", proc { |power, move, user, target, ai, battle| next power * 6 # Hits do x1, x2, x3 ret in turn, for x6 in total } ) - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesAlwaysCriticalHit", - proc { |power, move, user, target, ai, battle| - next power * move.move.pbNumHits(user.battler, [target.battler]) - } -) -Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesAlwaysCriticalHit", +Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesPowersUpWithEachHit", proc { |score, move, user, target, ai, battle| - if ai.trainer.high_skill? - stat = (move.physicalMove?) ? :DEFENSE : :SPECIAL_DEFENSE - next score + 50 if target.stages[stat] > 1 + # Prefer if the target has a Substitute and the first or second hit can break it + if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) + dmg = move.rough_damage + score += 10 if target.effects[PBEffects::Substitute] < dmg / 2 end + # TODO: Consider effects that trigger per hit. + next score } ) #=============================================================================== -# TODO: Review score modifiers. +# +#=============================================================================== +Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", + "HitThreeTimesAlwaysCriticalHit") +Battle::AI::Handlers::MoveEffectScore.copy("HitTwoTimes", + "HitThreeTimesAlwaysCriticalHit") + +#=============================================================================== +# #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes", proc { |power, move, user, target, ai, battle| @@ -85,9 +115,21 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes", next power * 31 / 10 # Average damage dealt } ) +Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimes", + proc { |score, move, user, target, ai, battle| + # Prefer if the target has a Substitute and the first hit(s) can break it + if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) + dmg = move.rough_damage + num_hits = (user.has_active_ability?(:SKILLLINK)) ? 5 : 3 # 3 is about average + score += 10 if target.effects[PBEffects::Substitute] < dmg * (num_hits - 1) / num_hits + end + # TODO: Consider effects that trigger per hit. + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja", proc { |power, move, user, target, ai, battle| @@ -98,32 +140,32 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja" next power * 31 / 10 # Average damage dealt } ) +Battle::AI::Handlers::MoveEffectScore.copy("HitTwoToFiveTimes", + "HitTwoToFiveTimesOrThreeForAshGreninja") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1", - proc { |power, move, user, target, ai, battle| - next power * 5 if user.has_active_ability?(:SKILLLINK) - next power * 31 / 10 # Average damage dealt - } -) +Battle::AI::Handlers::MoveBasePower.copy("HitTwoToFiveTimes", + "HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1") Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1", proc { |score, move, user, target, ai, battle| + # Score for being a multi-hit attack + score = Battle::AI::Handlers.apply_move_effect_score("HitTwoToFiveTimes", + score, move, user, target, ai, battle) + # User's stat changes aspeed = user.rough_stat(:SPEED) ospeed = target.rough_stat(:SPEED) - if aspeed > ospeed && aspeed * 2 / 3 < ospeed - score -= 50 - elsif aspeed < ospeed && aspeed * 1.5 > ospeed - score += 50 + if aspeed < ospeed && aspeed * 1.5 > ospeed + score += 15 # Will become faster than the target end - score += user.stages[:DEFENSE] * 30 + score += user.stages[:DEFENSE] * 10 next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember", proc { |move, user, target, ai, battle| @@ -139,51 +181,126 @@ Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember", Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember", proc { |power, move, user, target, ai, battle| ret = 0 - ai.battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i| - ret += 5 + (pkmn.baseStats[:ATTACK] / 10) + battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i| + ret += 5 + (pkmn.baseStats[:ATTACK] / 10) if pkmn.able? && pkmn.status == :NONE end next ret } ) +Battle::AI::Handlers::MoveEffectScore.add("HitOncePerUserTeamMember", + proc { |score, move, user, target, ai, battle| + # Prefer if the target has a Substitute and the first hit(s) can break it + if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) + dmg = move.rough_damage + num_hits = 0 + battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i| + num_hits += 1 if pkmn.able? && pkmn.status == :NONE + end + score += 10 if target.effects[PBEffects::Substitute] < dmg * (num_hits - 1) / num_hits + end + # TODO: Consider effects that trigger per hit. + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -# AttackAndSkipNextTurn +Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn", + proc { |score, move, user, target, ai, battle| + # Don't prefer because it uses up two turns + score -= 10 if !user.has_active_ability?(:TRUANT) + # Don't prefer if user is at a high HP (treat this move as a last resort) + score -= 10 if user.hp >= user.totalhp / 2 + # TODO: Don't prefer if another of the user's moves could KO the target. + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -# TwoTurnAttack +Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttack", + proc { |score, move, user, target, ai, battle| + # Power Herb makes this a 1 turn move, the same as a move with no effect + next score if user.has_active_item?(:POWERHERB) + # Treat as a failure if user has Truant (the charging turn has no effect) + next 25 if user.has_active_ability?(:TRUANT) + # Don't prefer because it uses up two turns + score -= 15 + # Don't prefer if user is at a low HP (time is better spent on quicker moves) + score -= 10 if user.hp < user.totalhp / 2 + # Don't prefer if target has a protecting move + if ai.trainer.high_skill? && !(user.has_active_ability?(:UNSEENFIST) && move.move.contactMove?) + has_protect_move = false + if move.move.pbTarget(user).num_targets > 1 && + (Settings::MECHANICS_GENERATION >= 7 || move.damagingMove?) + if target.check_for_move { |m| m.function == "ProtectUserSideFromMultiTargetDamagingMoves" } + has_protect_move = true + end + end + if move.move.canProtectAgainst? + if target.check_for_move { |m| ["ProtectUser", + "ProtectUserFromTargetingMovesSpikyShield", + "ProtectUserBanefulBunker"].include?(m.function) } + has_protect_move = true + end + if move.damagingMove? + # NOTE: Doesn't check for Mat Block because it only works on its + # user's first turn in battle, so it can't be used in response + # to this move charging up. + if target.check_for_move { |m| ["ProtectUserFromDamagingMovesKingsShield", + "ProtectUserFromDamagingMovesObstruct"].include?(m.function) } + has_protect_move = true + end + end + if move.rough_priority > 0 + if target.check_for_move { |m| m.function == "ProtectUserSideFromPriorityMoves" } + has_protect_move = true + end + end + end + score -= 15 if has_protect_move + end + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun", proc { |power, move, user, target, ai, battle| next move.move.pbBaseDamageMultiplier(power, user.battler, target.battler) } ) +Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackOneTurnInSun", + proc { |score, move, user, target, ai, battle| + # Sunny weather this a 1 turn move, the same as a move with no effect + next score if [:Sun, :HarshSun].include?(user.battler.effectiveWeather) + # Score for being a two turn attack + next Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score, move, user, target, ai, battle) + } +) #=============================================================================== # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget", proc { |score, move, user, target, ai, battle| - if target.battler.pbCanParalyze?(user.battler, false) - score += 30 + # Score for being a two turn attack + score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score, move, user, target, ai, battle) + # Paralyze the target + if !target.battler.pbCanParalyze?(user.battler, false) + score += 10 if ai.trainer.medium_skill? - aspeed = user.rough_stat(:SPEED) - ospeed = target.rough_stat(:SPEED) - if aspeed < ospeed - score += 30 - elsif aspeed > ospeed - score -= 40 - end + score += 10 if !user.faster_than?(target) end - score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET]) - elsif ai.trainer.medium_skill? - score -= 90 if move.statusMove? + score -= 15 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET]) + else + next 25 if move.statusMove? end next score } @@ -194,9 +311,16 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget", #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget", proc { |score, move, user, target, ai, battle| - next score - 40 if move.statusMove? && !target.battler.pbCanBurn?(user.battler, false) - score += 10 - score -= 20 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST]) + # Score for being a two turn attack + score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score, move, user, target, ai, battle) + # Burn the target + if target.battler.pbCanBurn?(user.battler, false) + score += 10 + score -= 15 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST]) + else + next 25 if move.statusMove? + end next score } ) @@ -206,47 +330,30 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget", #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget", proc { |score, move, user, target, ai, battle| - score += 20 if user.effects[PBEffects::FocusEnergy] > 0 - score += 20 if (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) && - target.effects[PBEffects::Substitute] == 0 + # Score for being a two turn attack + score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score, move, user, target, ai, battle) + # Flinching + if user.faster_than?(target) && target.effects[PBEffects::Substitute] == 0 && + (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) + score += 10 + end next score } ) #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2", - proc { |move, user, target, ai, battle| - next true if !user.battler.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user.battler, move.move) && - !user.battler.pbCanRaiseStatStage?(:SPECIAL_DEFENSE, user.battler, move.move) && - !user.battler.pbCanRaiseStatStage?(:SPEED, user.battler, move.move) - } -) +Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1", + "TwoTurnAttackRaiseUserSpAtkSpDefSpd2") Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2", proc { |score, move, user, target, ai, battle| - score -= user.stages[:SPECIAL_ATTACK] * 10 # Only *10 instead of *20 - score -= user.stages[:SPECIAL_DEFENSE] * 10 # because two-turn attack - score -= user.stages[:SPEED] * 10 - if ai.trainer.medium_skill? - hasSpecialAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecialAttack = true - break - end - if hasSpecialAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - if ai.trainer.high_skill? - aspeed = user.rough_stat(:SPEED) - ospeed = target.rough_stat(:SPEED) - score += 30 if aspeed < ospeed && aspeed * 2 > ospeed - end + # Score for raising user's stats + score = ai.get_score_for_user_stat_raise(score) + # Score for being a two turn attack + score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score, move, user, target, ai, battle) next score } ) @@ -256,15 +363,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2" #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserDefense1", proc { |score, move, user, target, ai, battle| - if move.statusMove? - if user.statStageAtMax?(:DEFENSE) - score -= 90 - else - score -= user.stages[:DEFENSE] * 20 - end - elsif user.stages[:DEFENSE] < 0 - score += 20 - end + score += 20 if user.stages[:DEFENSE] < 0 next score } ) diff --git a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb index c3642e3b2..d6c42891e 100644 --- a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb +++ b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb @@ -94,6 +94,8 @@ class Battle::AI::AIMove def rough_damage power = base_power return power if @move.is_a?(Battle::Move::FixedDamageMove) + stage_mul = [2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8] + stage_div = [8, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2] # Get the user and target of this move user = @ai.user user_battler = user.battler @@ -103,24 +105,21 @@ class Battle::AI::AIMove # Get the move's type calc_type = rough_type + # Decide whether the move will definitely be a critical hit + is_critical = rough_critical_hit_stage >= Battle::Move::CRITICAL_HIT_RATIOS.length + ##### Calculate user's attack stat ##### - atk = user.rough_stat(:ATTACK) - if function == "UseTargetAttackInsteadOfUserAttack" # Foul Play - atk = target.rough_stat(:ATTACK) - elsif function == "UseUserBaseDefenseInsteadOfUserBaseAttack" # Body Press - atk = user.rough_stat(:DEFENSE) - elsif specialMove?(calc_type) - if function == "UseTargetAttackInsteadOfUserAttack" # Foul Play - atk = target.rough_stat(:SPECIAL_ATTACK) - else - atk = user.rough_stat(:SPECIAL_ATTACK) - end + atk, atk_stage = @move.pbGetAttackStats(user.battler, target.battler) + if !target.has_active_ability?(:UNAWARE) || @ai.battle.moldBreaker + atk_stage = 6 if is_critical && atk_stage < 6 + atk = (atk.to_f * stage_mul[atk_stage] / stage_div[atk_stage]).floor end ##### Calculate target's defense stat ##### - defense = target.rough_stat(:DEFENSE) - if specialMove?(calc_type) && function != "UseTargetDefenseInsteadOfTargetSpDef" # Psyshock - defense = target.rough_stat(:SPECIAL_DEFENSE) + defense, def_stage = pbGetDefenseStats(user, target) + if !user.has_active_ability?(:UNAWARE) || @ai.battle.moldBreaker + def_stage = 6 if is_critical && def_stage > 6 + defense = (defense.to_f * stage_mul[def_stage] / stage_div[def_stage]).floor end ##### Calculate all multiplier effects ##### @@ -297,7 +296,14 @@ class Battle::AI::AIMove end end - # Critical hits - n/a + # Critical hits + if is_critical + if Settings::NEW_CRITICAL_HIT_RATE_MECHANICS + multipliers[:final_damage_multiplier] *= 1.5 + else + multipliers[:final_damage_multiplier] *= 2 + end + end # Random variance - n/a @@ -321,7 +327,8 @@ class Battle::AI::AIMove end # Aurora Veil, Reflect, Light Screen - if @ai.trainer.medium_skill? && !@move.ignoresReflect? && !user.has_active_ability?(:INFILTRATOR) + if @ai.trainer.medium_skill? && !@move.ignoresReflect? && !is_critical && + !user.has_active_ability?(:INFILTRATOR) if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 if @ai.battle.pbSideBattlerCount(target_battler) > 1 multipliers[:final_damage_multiplier] *= 2 / 3.0