From ad29a79e1c6214566c01bec13977f1ab32c10223 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Thu, 30 Mar 2023 21:11:27 +0100 Subject: [PATCH] Tweaked AI threshold score, added "HPAware" skill flag, changed lots of AI scores --- .../009_Battler_UseMoveSuccessChecks.rb | 1 + .../011_Battle/005_AI/004_AI_ChooseMove.rb | 4 +- .../005_AI/020_AI_Move_EffectScoresGeneric.rb | 161 +++++----- .../070_AI_MoveHandlers_GeneralModifiers.rb | 30 +- .../011_Battle/005_AI/101_AITrainer.rb | 6 +- .../011_Battle/005_AI/102_AIBattler.rb | 64 ++-- .../051_AI_MoveHandlers_Misc.rb | 92 ++++-- .../052_AI_MoveHandlers_BattlerStats.rb | 183 +++++------ .../053_AI_MoveHandlers_BattlerOther.rb | 196 ++++++------ .../054_AI_MoveHandlers_MoveAttributes.rb | 265 +++++++++------- .../055_AI_MoveHandlers_MultiHit.rb | 46 +-- .../056_AI_MoveHandlers_Healing.rb | 298 +++++++++--------- .../057_AI_MoveHandlers_Items.rb | 64 ++-- .../058_AI_MoveHandlers_ChangeMoveEffect.rb | 73 +++-- .../059_AI_MoveHandlers_SwitchingActing.rb | 91 +++--- .../022_Maruno/001_move target lister.rb | 2 +- 16 files changed, 828 insertions(+), 748 deletions(-) diff --git a/Data/Scripts/011_Battle/002_Battler/009_Battler_UseMoveSuccessChecks.rb b/Data/Scripts/011_Battle/002_Battler/009_Battler_UseMoveSuccessChecks.rb index 9a0548b4b..df6559e1a 100644 --- a/Data/Scripts/011_Battle/002_Battler/009_Battler_UseMoveSuccessChecks.rb +++ b/Data/Scripts/011_Battle/002_Battler/009_Battler_UseMoveSuccessChecks.rb @@ -194,6 +194,7 @@ class Battle::Battler if @effects[PBEffects::HyperBeam] > 0 # Intentionally before Truant PBDebug.log("[Move failed] #{pbThis} is recharging after using #{move.name}") @battle.pbDisplay(_INTL("{1} must recharge!", pbThis)) + @effects[PBEffects::Truant] = !@effects[PBEffects::Truant] if hasActiveAbility?(:TRUANT) return false end if choice[1] == -2 # Battle Palace diff --git a/Data/Scripts/011_Battle/005_AI/004_AI_ChooseMove.rb b/Data/Scripts/011_Battle/005_AI/004_AI_ChooseMove.rb index 679504673..df248fdca 100644 --- a/Data/Scripts/011_Battle/005_AI/004_AI_ChooseMove.rb +++ b/Data/Scripts/011_Battle/005_AI/004_AI_ChooseMove.rb @@ -1,12 +1,12 @@ class Battle::AI - MOVE_FAIL_SCORE = 25 + MOVE_FAIL_SCORE = 20 MOVE_USELESS_SCORE = 60 # Move predicted to do nothing or just be detrimental MOVE_BASE_SCORE = 100 # Returns a value between 0.0 and 1.0. All move scores are lowered by this # value multiplied by the highest-scoring move's score. def move_score_threshold - return 0.6 + 0.3 * (([@trainer.skill, 100].min / 100.0) ** 0.5) # 0.6 to 0.9 + return 0.6 + 0.35 * (([@trainer.skill, 100].min / 100.0) ** 0.5) # 0.635 to 0.95 end #============================================================================= diff --git a/Data/Scripts/011_Battle/005_AI/020_AI_Move_EffectScoresGeneric.rb b/Data/Scripts/011_Battle/005_AI/020_AI_Move_EffectScoresGeneric.rb index 54bd0ea36..eb4f6a43e 100644 --- a/Data/Scripts/011_Battle/005_AI/020_AI_Move_EffectScoresGeneric.rb +++ b/Data/Scripts/011_Battle/005_AI/020_AI_Move_EffectScoresGeneric.rb @@ -125,12 +125,17 @@ class Battle::AI "PowerHigherWithUserPositiveStatStages" ] if !target.has_move_with_function?(*moves_that_prefer_high_speed) + # TODO: Not worth it if the target is too much slower than its foe(s) + # and can't be made fast enough. each_foe_battler(target.side) do |b, i| return true if b.faster_than?(target) end return false end when :ACCURACY + # TODO: Yes if any of target's moves have lower accuracy, or target is + # affected by accuracy-lowering effects, or if target's foe(s) have + # increased evasion. when :EVASION end return true @@ -151,22 +156,14 @@ class Battle::AI # the foe anyway). # Prefer if move is a status move and it's the user's first/second turn if @user.turnCount < 2 && @move.statusMove? - score += total_increment * desire_mult * 4 + score += total_increment * desire_mult * 5 end # Prefer if user is at high HP, don't prefer if user is at low HP if target.index != @user.index - if @user.hp >= @user.totalhp * 0.7 - score += total_increment * desire_mult * 3 - else - score += total_increment * desire_mult * ((100 * @user.hp / @user.totalhp) - 50) / 6 # +3 to -8 per stage - end + score += total_increment * desire_mult * ((100 * @user.hp / @user.totalhp) - 50) / 8 # +6 to -6 per stage end # Prefer if target is at high HP, don't prefer if target is at low HP - if target.hp >= target.totalhp * 0.7 - score += total_increment * desire_mult * 4 - else - score += total_increment * desire_mult * ((100 * target.hp / target.totalhp) - 50) / 4 # +5 to -12 per stage - end + score += total_increment * desire_mult * ((100 * target.hp / target.totalhp) - 50) / 8 # +6 to -6 per stage # TODO: Look at abilities that trigger upon stat raise. There are none. return score end @@ -193,16 +190,16 @@ class Battle::AI # Modify score depending on current stat stage # More strongly prefer if the target has no special moves if old_stage >= 2 && increment == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else has_special_moves = target.check_for_move { |m| m.specialMove?(m.type) } - inc = (has_special_moves) ? 10 : 20 + inc = (has_special_moves) ? 8 : 12 score += inc * inc_mult end when :DEFENSE # Modify score depending on current stat stage if old_stage >= 2 && increment == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else score += 10 * inc_mult end @@ -210,29 +207,35 @@ class Battle::AI # Modify score depending on current stat stage # More strongly prefer if the target has no physical moves if old_stage >= 2 && increment == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else has_physical_moves = target.check_for_move { |m| m.physicalMove?(m.type) && m.function != "UseUserDefenseInsteadOfUserAttack" && m.function != "UseTargetAttackInsteadOfUserAttack" } - inc = (has_physical_moves) ? 10 : 20 + inc = (has_physical_moves) ? 8 : 12 score += inc * inc_mult end when :SPECIAL_DEFENSE # Modify score depending on current stat stage if old_stage >= 2 && increment == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else score += 10 * inc_mult end when :SPEED # Prefer if target is slower than a foe - # TODO: Don't prefer if the target is too much slower than any foe that it - # can't catch up. + target_speed = target.rough_stat(:SPEED) each_foe_battler(target.side) do |b, i| - next if target.faster_than?(b) - score += 15 * inc_mult - break + b_speed = b.rough_stat(:SPEED) + next if b_speed > target_speed * 2.5 # Much too slow to reasonably catch up + if b_speed > target_speed + if b_speed < target_speed * (increment + 2) / 2 + score += 15 * inc_mult # Target will become faster than b + else + score += 8 * inc_mult + end + break + end end # TODO: Prefer if the target is able to cause flinching (moves that # flinch, or has King's Rock/Stench). @@ -242,21 +245,21 @@ class Battle::AI "PowerHigherWithUserPositiveStatStages" ] if target.has_move_with_function?(*moves_that_prefer_high_speed) - score += 8 * inc_mult + score += 5 * inc_mult end # Don't prefer if any foe has Gyro Ball each_foe_battler(target.side) do |b, i| next if !b.has_move_with_function?("PowerHigherWithTargetFasterThanUser") - score -= 8 * inc_mult + score -= 5 * inc_mult end # Don't prefer if target has Speed Boost (will be gaining Speed anyway) if target.has_active_ability?(:SPEEDBOOST) - score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) end when :ACCURACY # Modify score depending on current stat stage if old_stage >= 2 && increment == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else min_accuracy = 100 target.battler.moves.each do |m| @@ -272,11 +275,11 @@ class Battle::AI # Prefer if a foe of the target will take damage at the end of the round each_foe_battler(target.side) do |b, i| eor_damage = b.rough_end_of_round_damage - score += 4 * inc_mult if eor_damage > 0 + score += 5 * inc_mult if eor_damage > 0 end # Modify score depending on current stat stage if old_stage >= 2 && increment == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else score += 10 * inc_mult end @@ -419,6 +422,8 @@ class Battle::AI "PowerHigherWithUserPositiveStatStages" ] if !target.has_move_with_function?(*moves_that_prefer_high_speed) + # TODO: Not worth it if the target is too much faster than its foe(s) + # and can't be brought slow enough. each_foe_battler(target.side) do |b, i| return true if !b.faster_than?(target) end @@ -445,22 +450,14 @@ class Battle::AI # TODO: Don't prefer if target is semi-invulnerable and user is faster. # Prefer if move is a status move and it's the user's first/second turn if @user.turnCount < 2 && @move.statusMove? - score += total_decrement * desire_mult * 4 + score += total_decrement * desire_mult * 5 end # Prefer if user is at high HP, don't prefer if user is at low HP if target.index != @user.index - if @user.hp >= @user.totalhp * 0.7 - score += total_decrement * desire_mult * 3 - else - score += total_decrement * desire_mult * ((100 * @user.hp / @user.totalhp) - 50) / 6 # +3 to -8 per stage - end + score += total_decrement * desire_mult * ((100 * @user.hp / @user.totalhp) - 50) / 8 # +6 to -6 per stage end # Prefer if target is at high HP, don't prefer if target is at low HP - if target.hp >= target.totalhp * 0.7 - score += total_decrement * desire_mult * 3 - else - score += total_decrement * desire_mult * ((100 * target.hp / target.totalhp) - 50) / 6 # +3 to -8 per stage - end + score += total_decrement * desire_mult * ((100 * target.hp / target.totalhp) - 50) / 8 # +6 to -6 per stage # TODO: Look at abilities that trigger upon stat lowering. return score end @@ -488,70 +485,76 @@ class Battle::AI # Modify score depending on current stat stage # More strongly prefer if the target has no special moves if old_stage <= -2 && decrement == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else has_special_moves = target.check_for_move { |m| m.specialMove?(m.type) } - dec = (has_special_moves) ? 5 : 10 + dec = (has_special_moves) ? 8 : 12 score += dec * dec_mult end when :DEFENSE # Modify score depending on current stat stage if old_stage <= -2 && decrement == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else - score += 5 * dec_mult + score += 10 * dec_mult end when :SPECIAL_ATTACK # Modify score depending on current stat stage # More strongly prefer if the target has no physical moves if old_stage <= -2 && decrement == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else has_physical_moves = target.check_for_move { |m| m.physicalMove?(m.type) && m.function != "UseUserDefenseInsteadOfUserAttack" && m.function != "UseTargetAttackInsteadOfUserAttack" } - dec = (has_physical_moves) ? 5 : 10 + dec = (has_physical_moves) ? 8 : 12 score += dec * dec_mult end when :SPECIAL_DEFENSE # Modify score depending on current stat stage if old_stage <= -2 && decrement == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else - score += 5 * dec_mult + score += 10 * dec_mult end when :SPEED # Prefer if target is faster than an ally - # TODO: Don't prefer if the target is too much faster than any ally and - # can't be brought slow enough. + target_speed = target.rough_stat(:SPEED) each_foe_battler(target.side) do |b, i| - next if b.faster_than?(target) - score += 15 * dec_mult - break + b_speed = b.rough_stat(:SPEED) + next if target_speed > b_speed * 2.5 # Much too fast to reasonably be overtaken + if target_speed > b_speed + if target_speed < b_speed * 2 / (decrement + 2) + score += 15 * inc_mult # Target will become slower than b + else + score += 8 * inc_mult + end + break + end end # Prefer if any ally has Electro Ball each_foe_battler(target.side) do |b, i| next if !b.has_move_with_function?("PowerHigherWithUserFasterThanTarget") - score += 8 * dec_mult + score += 5 * dec_mult end # Don't prefer if target has Speed Boost (will be gaining Speed anyway) if target.has_active_ability?(:SPEEDBOOST) - score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) end when :ACCURACY # Modify score depending on current stat stage if old_stage <= -2 && decrement == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else - score += 5 * dec_mult + score += 10 * dec_mult end # TODO: Prefer if target is poisoned/toxiced/Leech Seeded/cursed. when :EVASION # Modify score depending on current stat stage if old_stage <= -2 && decrement == 1 - score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) + score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult) else - score += 5 * dec_mult + score += 10 * dec_mult end end # Prefer if target has Stored Power @@ -588,40 +591,40 @@ class Battle::AI when :Sun # Check for Fire/Water moves if b.has_damaging_move_of_type?(:FIRE) - ret += (b.opposes?(move_user)) ? -8 : 8 + ret += (b.opposes?(move_user)) ? -10 : 10 end if b.has_damaging_move_of_type?(:WATER) - ret += (b.opposes?(move_user)) ? 8 : -8 + ret += (b.opposes?(move_user)) ? 10 : -10 end # TODO: Check for freezing moves. when :Rain # Check for Fire/Water moves if b.has_damaging_move_of_type?(:WATER) - ret += (b.opposes?(move_user)) ? -8 : 8 + ret += (b.opposes?(move_user)) ? -10 : 10 end if b.has_damaging_move_of_type?(:FIRE) - ret += (b.opposes?(move_user)) ? 8 : -8 + ret += (b.opposes?(move_user)) ? 10 : -10 end when :Sandstorm # Check for battlers affected by sandstorm's effects if b.battler.takesSandstormDamage? # End of round damage - ret += (b.opposes?(move_user)) ? 8 : -8 + ret += (b.opposes?(move_user)) ? 10 : -10 end if b.has_type?(:ROCK) # +SpDef for Rock types - ret += (b.opposes?(move_user)) ? -8 : 8 + ret += (b.opposes?(move_user)) ? -10 : 10 end when :Hail # Check for battlers affected by hail's effects if b.battler.takesHailDamage? # End of round damage - ret += (b.opposes?(move_user)) ? 8 : -8 + ret += (b.opposes?(move_user)) ? 10 : -10 end when :ShadowSky # Check for battlers affected by Shadow Sky's effects if b.has_damaging_move_of_type?(:SHADOW) - ret += (b.opposes?(move_user)) ? 8 : -8 + ret += (b.opposes?(move_user)) ? 10 : -10 end if b.battler.takesShadowSkyDamage? # End of round damage - ret += (b.opposes?(move_user)) ? 8 : -8 + ret += (b.opposes?(move_user)) ? 10 : -10 end end # Check each battler's abilities/other moves affected by the new weather @@ -698,32 +701,32 @@ class Battle::AI # Immunity to sleep # TODO: Check all battlers for sleep-inducing moves and other effects? if b.status == :NONE - ret += (b.opposes?(move_user)) ? -5 : 5 + ret += (b.opposes?(move_user)) ? -8 : 8 end if b.effects[PBEffects::Yawn] > 0 ret += (b.opposes?(move_user)) ? -10 : 10 end # Check for Electric moves if b.has_damaging_move_of_type?(:ELECTRIC) - ret += (b.opposes?(move_user)) ? -15 : 15 + ret += (b.opposes?(move_user)) ? -10 : 10 end when :Grassy # End of round healing - ret += (b.opposes?(move_user)) ? -10 : 10 + ret += (b.opposes?(move_user)) ? -8 : 8 # Check for Grass moves if b.has_damaging_move_of_type?(:GRASS) - ret += (b.opposes?(move_user)) ? -15 : 15 + ret += (b.opposes?(move_user)) ? -10 : 10 end when :Misty # Immunity to status problems/confusion # TODO: Check all battlers for status/confusion-inducing moves and other # effects? if b.status == :NONE || b.effects[PBEffects::Confusion] == 0 - ret += (b.opposes?(move_user)) ? -5 : 5 + ret += (b.opposes?(move_user)) ? -8 : 8 end # Check for Dragon moves if b.has_damaging_move_of_type?(:DRAGON) - ret += (b.opposes?(move_user)) ? 15 : -15 + ret += (b.opposes?(move_user)) ? 10 : -10 end when :Psychic # Check for priority moves @@ -732,7 +735,7 @@ class Battle::AI end # Check for Psychic moves if b.has_damaging_move_of_type?(:PSYCHIC) - ret += (b.opposes?(move_user)) ? -15 : 15 + ret += (b.opposes?(move_user)) ? -10 : 10 end end end @@ -745,7 +748,7 @@ class Battle::AI }[terrain] each_battler do |b, i| if seed && b.has_active_item?(seed) - ret += (b.opposes?(move_user)) ? -15 : 15 + ret += (b.opposes?(move_user)) ? -8 : 8 end end # Check for abilities/moves affected by the terrain @@ -773,20 +776,20 @@ class Battle::AI ret += (b.opposes?(move_user)) ? -5 : 5 end if abils && b.has_active_ability?(abils) - ret += (b.opposes?(move_user)) ? -15 : 15 + ret += (b.opposes?(move_user)) ? -8 : 8 end # Moves if b.has_move_with_function?("EffectDependsOnEnvironment", "SetUserTypesBasedOnEnvironment", "TypeAndPowerDependOnTerrain", "UseMoveDependingOnEnvironment") - ret += (b.opposes?(move_user)) ? -10 : 10 + ret += (b.opposes?(move_user)) ? -5 : 5 end if good_moves && b.has_move_with_function?(*good_moves) - ret += (b.opposes?(move_user)) ? -10 : 10 + ret += (b.opposes?(move_user)) ? -5 : 5 end if bad_moves && b.has_move_with_function?(*bad_moves) - ret += (b.opposes?(move_user)) ? 10 : -10 + ret += (b.opposes?(move_user)) ? 5 : -5 end end end diff --git a/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb b/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb index bcf4deba2..2354d34db 100644 --- a/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb +++ b/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb @@ -29,7 +29,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:shiny_target, proc { |score, move, user, target, ai, battle| if target.wild? && target.battler.shiny? old_score = score - score -= 15 + score -= 20 PBDebug.log_score_change(score - old_score, "avoid attacking a shiny wild Pokémon") end next score @@ -46,7 +46,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:shiny_target, # => Include EOR damage in this? # => Prefer move if it will KO the target (moreso if user is slower than target) #=============================================================================== -Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:add_predicted_damage, +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:predicted_damage, proc { |score, move, user, target, ai, battle| if move.damagingMove? dmg = move.rough_damage @@ -128,7 +128,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:thawing_move_against_fr if ai.trainer.medium_skill? && target.status == :FROZEN if move.rough_type == :FIRE || (Settings::MECHANICS_GENERATION >= 6 && move.move.thawsUser?) old_score = score - score -= 15 + score -= 20 PBDebug.log_score_change(score - old_score, "thaws the target") end end @@ -205,7 +205,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:damaging_a_biding_targe hits_possible += 1 if user.faster_than?(target) if dmg * hits_possible + eor_dmg < target.hp * 1.05 old_score = score - score -= 15 + score -= 20 PBDebug.log_score_change(score - old_score, "don't want to damage the Biding target") end end @@ -227,7 +227,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:knocking_out_a_destiny_ dmg = move.rough_damage if dmg > target.hp * 1.05 # Predicted to KO the target old_score = score - score -= 15 + score -= 20 score -= 10 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 PBDebug.log_score_change(score - old_score, "don't want to KO the Destiny Bonding target") end @@ -264,7 +264,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:target_can_Magic_Coat_o score = Battle::AI::MOVE_USELESS_SCORE PBDebug.log_score_change(score - old_score, "useless because target will Magic Bounce it") elsif target.has_move_with_function?("BounceBackProblemCausingStatusMoves") - score -= 8 + score -= 7 PBDebug.log_score_change(score - old_score, "target knows Magic Coat and could bounce it") end end @@ -286,7 +286,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:any_foe_can_Magic_Coat_or_Bounce_mov PBDebug.log_score_change(score - old_score, "useless because a foe will Magic Bounce it") break elsif b.has_move_with_function?("BounceBackProblemCausingStatusMoves") - score -= 8 + score -= 7 PBDebug.log_score_change(score - old_score, "a foe knows Magic Coat and could bounce it") break end @@ -307,7 +307,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:any_battler_can_Snatch_move, next if b.effects[PBEffects::SkyDrop] >= 0 next if !b.has_move_with_function?("StealAndUseBeneficialStatusMove") old_score = score - score -= 8 + score -= 7 PBDebug.log_score_change(score - old_score, "another battler could Snatch it") break end @@ -335,10 +335,10 @@ Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_when_frozen, if ai.trainer.medium_skill? && user.status == :FROZEN old_score = score if move.move.thawsUser? - score += 30 + score += 20 PBDebug.log_score_change(score - old_score, "move will thaw the user") elsif user.check_for_move { |m| m.thawsUser? } - score -= 30 # Don't prefer this move if user knows another move that thaws + score -= 20 # Don't prefer this move if user knows another move that thaws PBDebug.log_score_change(score - old_score, "user knows another move will thaw it") end end @@ -354,7 +354,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer, if move.move.danceMove? old_score = score ai.each_foe_battler(user.side) do |b, i| - score -= 12 if b.has_active_ability?(:DANCER) + score -= 10 if b.has_active_ability?(:DANCER) end PBDebug.log_score_change(score - old_score, "don't want to use a dance move because a foe has Dancer") end @@ -381,10 +381,12 @@ Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item, # Don't prefer moves which are 0x against at least one type move_type = move.rough_type GameData::Type.each do |type_data| - score -= 5 if type_data.immunities.include?(move_type) + score -= 8 if type_data.immunities.include?(move_type) end # Don't prefer moves with lower accuracy - score = score * move.accuracy / 100 if move.accuracy > 0 + if move.accuracy > 0 + score -= (0.4 * (100 - move.accuracy)).to_i # -0 (100%) to -39 (1%) + end # Don't prefer moves with low PP score -= 10 if move.move.pp <= 5 PBDebug.log_score_change(score - old_score, "move is less suitable to be Choiced into") @@ -400,7 +402,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item, # more (desperate). # TODO: Review score modifier. #=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:either_side_down_to_last_pokemon, +Battle::AI::Handlers::GeneralMoveScore.add(:damaging_move_and_either_side_no_reserves, proc { |score, move, user, ai, battle| if ai.trainer.medium_skill? && move.damagingMove? reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) diff --git a/Data/Scripts/011_Battle/005_AI/101_AITrainer.rb b/Data/Scripts/011_Battle/005_AI/101_AITrainer.rb index bea900e9e..fc0487385 100644 --- a/Data/Scripts/011_Battle/005_AI/101_AITrainer.rb +++ b/Data/Scripts/011_Battle/005_AI/101_AITrainer.rb @@ -13,6 +13,7 @@ # PredictMoveFailure # ScoreMoves # PreferMultiTargetMoves +# HPAware (considers HP values of user/target for "worth it?" score changes) # ConsiderSwitching (can choose to switch out Pokémon) # ReserveLastPokemon (don't switch it in if possible) # UsePokemonInOrder (uses earliest-listed Pokémon possible) @@ -58,7 +59,10 @@ class Battle::AI::AITrainer @skill_flags.push("ScoreMoves") @skill_flags.push("PreferMultiTargetMoves") end - @skill_flags.push("ConsiderSwitching") if medium_skill? + if medium_skill? + @skill_flags.push("ConsiderSwitching") + @skill_flags.push("HPAware") + end if !medium_skill? @skill_flags.push("UsePokemonInOrder") elsif best_skill? diff --git a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb index 79426b36e..d7b487ce9 100644 --- a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb +++ b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb @@ -55,13 +55,6 @@ class Battle::AI::AIBattler def idxOpposingSide; return @battler.idxOpposingSide; end def pbOpposingSide; return @battler.pbOpposingSide; end - def faster_than?(other) - return false if other.nil? - this_speed = rough_stat(:SPEED) - other_speed = other.rough_stat(:SPEED) - return (this_speed > other_speed) ^ (@ai.battle.field.effects[PBEffects::TrickRoom] > 0) - end - #============================================================================= # Returns how much damage this battler will take at the end of this round. @@ -167,8 +160,6 @@ class Battle::AI::AIBattler #============================================================================= - def speed; return @battler.speed; end - def base_stat(stat) ret = 0 case stat @@ -190,6 +181,13 @@ class Battle::AI::AIBattler return (value.to_f * stageMul[stage] / stageDiv[stage]).floor end + def faster_than?(other) + return false if other.nil? + this_speed = rough_stat(:SPEED) + other_speed = other.rough_stat(:SPEED) + return (this_speed > other_speed) ^ (@ai.battle.field.effects[PBEffects::TrickRoom] > 0) + end + #============================================================================= def types; return @battler.types; end @@ -423,6 +421,7 @@ class Battle::AI::AIBattler # Return values are typically between -10 and +10. 0 is indifferent, positive # values mean this battler benefits, negative values mean this battler suffers. def wants_item?(item) + item = :NONE if !item item = item.id if !item.is_a?(Symbol) && item.respond_to?("id") return 0 if has_active_ability?(:KLUTZ) # TODO: Unnerve, other item-negating effects. @@ -511,7 +510,7 @@ class Battle::AI::AIBattler end # Prefer if this battler knows Fling and it will do a lot of damage/have an # additional (negative) effect when flung - if has_move_with_function?("ThrowUserItemAtTarget") + if item != :NONE && has_move_with_function?("ThrowUserItemAtTarget") GameData::Item.get(item).flags.each do |flag| next if !flag[/^Fling_(\d+)$/i] amt = $~[1].to_i @@ -533,12 +532,12 @@ class Battle::AI::AIBattler #============================================================================= # Items can be consumed by Stuff Cheeks, Teatime, Bug Bite/Pluck and Fling. - def get_score_change_for_consuming_item(item) + def get_score_change_for_consuming_item(item, try_preserving_item = false) ret = 0 case item when :ORANBERRY, :BERRYJUICE, :ENIGMABERRY, :SITRUSBERRY # Healing - ret += (hp > totalhp * 3 / 4) ? -8 : 8 + ret += (hp > totalhp * 0.75) ? -6 : 6 ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) when :AGUAVBERRY, :FIGYBERRY, :IAPAPABERRY, :MAGOBERRY, :WIKIBERRY # Healing with confusion @@ -548,7 +547,7 @@ class Battle::AI::AIBattler elsif Settings::MECHANICS_GENERATION >= 8 fraction_to_heal = 3 end - ret += (hp > totalhp * (1 - (1 / fraction_to_heal))) ? -8 : 8 + ret += (hp > totalhp * (1 - (1.0 / fraction_to_heal))) ? -6 : 6 ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) # TODO: Check whether the item will cause confusion? when :ASPEARBERRY, :CHERIBERRY, :CHESTOBERRY, :PECHABERRY, :RAWSTBERRY @@ -560,21 +559,25 @@ class Battle::AI::AIBattler :PECHABERRY => :POISON, :RAWSTBERRY => :BURN }[item] - ret += (cured_status && status == cured_status) ? 8 : -8 + ret += (cured_status && status == cured_status) ? 6 : -6 when :PERSIMBERRY # Confusion cure - ret += (effects[PBEffects::Confusion] > 1) ? 8 : -8 + ret += (effects[PBEffects::Confusion] > 1) ? 6 : -6 when :LUMBERRY # Any status/confusion cure - ret += (status != :NONE || effects[PBEffects::Confusion] > 1) ? 8 : -8 + ret += (status != :NONE || effects[PBEffects::Confusion] > 1) ? 6 : -6 when :MENTALHERB # Cure mental effects - ret += 8 if effects[PBEffects::Attract] >= 0 || - effects[PBEffects::Taunt] > 1 || - effects[PBEffects::Encore] > 1 || - effects[PBEffects::Torment] || - effects[PBEffects::Disable] > 1 || - effects[PBEffects::HealBlock] > 1 + if effects[PBEffects::Attract] >= 0 || + effects[PBEffects::Taunt] > 1 || + effects[PBEffects::Encore] > 1 || + effects[PBEffects::Torment] || + effects[PBEffects::Disable] > 1 || + effects[PBEffects::HealBlock] > 1 + ret += 6 + else + ret -= 6 + end when :APICOTBERRY, :GANLONBERRY, :LIECHIBERRY, :PETAYABERRY, :SALACBERRY, :KEEBERRY, :MARANGABERRY # Stat raise @@ -587,7 +590,7 @@ class Battle::AI::AIBattler :KEEBERRY => :DEFENSE, :MARANGABERRY => :SPECIAL_DEFENSE }[item] - ret += 8 if stat && @ai.stat_raise_worthwhile?(self, stat) + ret += (stat && @ai.stat_raise_worthwhile?(self, stat)) ? 8 : -8 ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) when :STARFBERRY # Random stat raise @@ -595,24 +598,19 @@ class Battle::AI::AIBattler ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) when :WHITEHERB # Resets lowered stats - reduced_stats = false - GameData::Stat.each_battle do |s| - next if stages[s.id] >= 0 - reduced_stats = true - break - end - ret += 8 if reduced_stats + ret += (@battler.hasLoweredStatStages?) ? 8 : -8 when :MICLEBERRY # Raises accuracy of next move - ret += 8 + ret += (@ai.stat_raise_worthwhile?(self, :ACCURACY, true)) ? 6 : -6 when :LANSATBERRY # Focus energy - ret += 8 if effects[PBEffects::FocusEnergy] < 2 + ret += (effects[PBEffects::FocusEnergy] < 2) ? 6 : -6 when :LEPPABERRY # Restore PP - ret += 8 + ret += 6 ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) end + ret = 0 if ret < 0 && !try_preserving_item return ret end diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/051_AI_MoveHandlers_Misc.rb b/Data/Scripts/011_Battle/005b_AI move function codes/051_AI_MoveHandlers_Misc.rb index 5a69ef0d0..fbe07f5c9 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/051_AI_MoveHandlers_Misc.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/051_AI_MoveHandlers_Misc.rb @@ -117,11 +117,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfUserDamagedThisTu end end next Battle::AI::MOVE_USELESS_SCORE if user_faster_count == 0 - score += 10 if foe_faster_count == 0 + score += 15 if foe_faster_count == 0 # Effects that make the target unlikely to act before the user if ai.trainer.high_skill? if !target.can_attack? - score += 20 + score += 15 elsif target.effects[PBEffects::Confusion] > 1 || target.effects[PBEffects::Attract] == user.index score += 10 @@ -130,8 +130,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfUserDamagedThisTu end end # Don't risk using this move if target is weak - score -= 10 if target.hp <= target.totalhp / 2 - score -= 10 if target.hp <= target.totalhp / 4 + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if target.hp <= target.totalhp / 2 + score -= 10 if target.hp <= target.totalhp / 4 + end next score } ) @@ -143,12 +145,13 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfTargetActed", proc { |score, move, user, target, ai, battle| # Check whether user is faster than its foe(s) and could use this move next Battle::AI::MOVE_USELESS_SCORE if target.faster_than?(user) - score += 10 # TODO: Predict the target switching/using an item. # TODO: Predict the target using a damaging move or Me First. # Don't risk using this move if target is weak - score -= 10 if target.hp <= target.totalhp / 2 - score -= 10 if target.hp <= target.totalhp / 4 + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if target.hp <= target.totalhp / 2 + score -= 10 if target.hp <= target.totalhp / 4 + end next score } ) @@ -158,7 +161,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfTargetActed", #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CrashDamageIfFailsUnusableInGravity", proc { |score, move, user, target, ai, battle| - score -= (100 - move.rough_accuracy) if user.battler.takesIndirectDamage? + if user.battler.takesIndirectDamage? + score -= (0.4 * (100 - move.rough_accuracy)).to_i # -0 (100%) to -40 (1%) + end next score } ) @@ -175,7 +180,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather", proc { |score, move, user, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || battle.pbCheckGlobalAbility(:CLOUDNINE) - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.weather != :None score -= ai.get_score_for_weather(battle.field.weather, user) end @@ -193,7 +201,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather", proc { |score, move, user, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || battle.pbCheckGlobalAbility(:CLOUDNINE) - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.weather != :None score -= ai.get_score_for_weather(battle.field.weather, user) end @@ -211,7 +222,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather", proc { |score, move, user, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || battle.pbCheckGlobalAbility(:CLOUDNINE) - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.weather != :None score -= ai.get_score_for_weather(battle.field.weather, user) end @@ -229,7 +243,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather", proc { |score, move, user, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || battle.pbCheckGlobalAbility(:CLOUDNINE) - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.weather != :None score -= ai.get_score_for_weather(battle.field.weather, user) end @@ -248,7 +265,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartElectricTerrain", ) Battle::AI::Handlers::MoveEffectScore.add("StartElectricTerrain", proc { |score, move, user, ai, battle| - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.terrain != :None score -= ai.get_score_for_terrain(battle.field.terrain, user) end @@ -267,7 +287,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartGrassyTerrain", ) Battle::AI::Handlers::MoveEffectScore.add("StartGrassyTerrain", proc { |score, move, user, ai, battle| - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.terrain != :None score -= ai.get_score_for_terrain(battle.field.terrain, user) end @@ -286,7 +309,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartMistyTerrain", ) Battle::AI::Handlers::MoveEffectScore.add("StartMistyTerrain", proc { |score, move, user, ai, battle| - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.terrain != :None score -= ai.get_score_for_terrain(battle.field.terrain, user) end @@ -305,7 +331,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartPsychicTerrain", ) Battle::AI::Handlers::MoveEffectScore.add("StartPsychicTerrain", proc { |score, move, user, ai, battle| - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.terrain != :None score -= ai.get_score_for_terrain(battle.field.terrain, user) end @@ -358,8 +387,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide", foe_reserves.push(pkmn) # pkmn will be affected by Spikes end next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? - multiplier = [8, 5, 3][user.pbOpposingSide.effects[PBEffects::Spikes]] - score += multiplier * foe_reserves.length + multiplier = [10, 7, 5][user.pbOpposingSide.effects[PBEffects::Spikes]] + score += [multiplier * foe_reserves.length, 30].min next score } ) @@ -402,8 +431,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide", foe_reserves.push(pkmn) # pkmn will be affected by Toxic Spikes end next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? - multiplier = [6, 4][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]] - score += multiplier * foe_reserves.length + multiplier = [8, 5][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]] + score += [multiplier * foe_reserves.length, 30].min next score } ) @@ -431,7 +460,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide", foe_reserves.push(pkmn) # pkmn will be affected by Stealth Rock end next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? - next score + 8 * foe_reserves.length + score += [10 * foe_reserves.length, 30].min + next score } ) @@ -463,7 +493,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide", foe_reserves.push(pkmn) # pkmn will be affected by Sticky Web end next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? - next score + 7 * foe_reserves.length + score += [8 * foe_reserves.length, 30].min + next score } ) @@ -524,10 +555,12 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute", Battle::AI::Handlers::MoveEffectScore.add("UserMakeSubstitute", proc { |score, move, user, ai, battle| # Prefer more the higher the user's HP - score += (8 * user.hp.to_f / user.totalhp).round + if ai.trainer.has_skill_flag?("HPAware") + score += (10 * user.hp.to_f / user.totalhp).round + end # Prefer if foes don't know any moves that can bypass a substitute - ai.each_battler do |b, i| - score += 4 if !b.check_for_move { |m| m.ignoresSubstitute?(b.battler) } + ai.each_foe_battler(user.side) do |b, i| + score += 5 if !b.check_for_move { |m| m.ignoresSubstitute?(b.battler) } end # TODO: Predict incoming damage, and prefer if it's greater than # user.totalhp / 4? @@ -625,8 +658,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTur ally_hp_lost += b.hp / 2 end end - score += 15 * foe_hp_lost / ally_hp_lost - score -= 15 * ally_hp_lost / foe_hp_lost + score += 20 * foe_hp_lost / ally_hp_lost + score -= 20 * ally_hp_lost / foe_hp_lost # Recharging score = Battle::AI::Handlers.apply_move_effect_score("AttackAndSkipNextTurn", score, move, user, ai, battle) @@ -654,7 +687,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather", proc { |score, move, user, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || battle.pbCheckGlobalAbility(:CLOUDNINE) - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + # Not worth it at lower HP + if ai.trainer.has_skill_flag?("HPAware") + score -= 15 if user.hp < user.totalhp / 2 + end if ai.trainer.high_skill? && battle.field.weather != :None score -= ai.get_score_for_weather(battle.field.weather, user) end diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/052_AI_MoveHandlers_BattlerStats.rb b/Data/Scripts/011_Battle/005b_AI move function codes/052_AI_MoveHandlers_BattlerStats.rb index 8efbe5d2f..f9438b62c 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/052_AI_MoveHandlers_BattlerStats.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/052_AI_MoveHandlers_BattlerStats.rb @@ -60,7 +60,9 @@ Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP", proc { |score, move, user, ai, battle| score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp) # Don't prefer the lower the user's HP is - score -= 80 * (1 - (user.hp.to_f / user.totalhp)) # 0 to -40 + if ai.trainer.has_skill_flag?("HPAware") + score -= 60 * (1 - (user.hp.to_f / user.totalhp)) # -0 to -30 + end next score } ) @@ -202,7 +204,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2LowerUserWeight", # User will become susceptible to Sky Drop if b.has_move_with_function?("TwoTurnAttackInvulnerableInSkyTargetCannotAct") && Settings::MECHANICS_GENERATION >= 6 - score -= 7 if current_weight >= 2000 && current_weight < 3000 + score -= 10 if current_weight >= 2000 && current_weight < 3000 end end end @@ -464,8 +466,8 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1LoseThirdOfTotalHP score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp) next score if score == Battle::AI::MOVE_USELESS_SCORE # Score for losing HP - if user.hp <= user.totalhp * 0.75 - score -= 30 * (user.totalhp - user.hp) / user.totalhp + if ai.trainer.has_skill_flag?("HPAware") && user.hp <= user.totalhp * 0.75 + score -= 45 * (user.totalhp - user.hp) / user.totalhp # -0 to -30 end next score } @@ -499,7 +501,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1TrapUserInBattle", if user.effects[PBEffects::PerishSong] > 0 || user.effects[PBEffects::Attract] >= 0 || eor_damage > 0 - score -= 12 + score -= 15 end end next score @@ -513,12 +515,14 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRaiseUserAtk1WhenDamaged", proc { |score, move, user, ai, battle| # Ignore the stat-raising effect if user is at a low HP and likely won't # benefit from it - next score if user.hp < user.totalhp / 3 + if ai.trainer.has_skill_flag?("HPAware") + next score if user.hp <= user.totalhp / 3 + end # TODO: Check whether any foe has damaging moves that will trigger the stat # raise? # Prefer if user benefits from a raised Attack stat - score += 8 if ai.stat_raise_worthwhile?(user, :ATTACK) - score += 4 if user.has_move_with_function?("PowerHigherWithUserPositiveStatStages") + score += 10 if ai.stat_raise_worthwhile?(user, :ATTACK) + score += 7 if user.has_move_with_function?("PowerHigherWithUserPositiveStatStages") next score } ) @@ -694,22 +698,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetRandomStat2", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !battle.moldBreaker && target.has_active_ability?(:CONTRARY) next Battle::AI::MOVE_USELESS_SCORE if target.rough_end_of_round_damage >= target.hp - score -= 5 if target.index != user.index # Less likely to use on ally - score += 5 if target.has_active_ability?(:SIMPLE) + score -= 7 if target.index != user.index # Less likely to use on ally + score += 10 if target.has_active_ability?(:SIMPLE) # Prefer if target is at high HP, don't prefer if target is at low HP - if target.hp >= target.totalhp * 0.7 - score += 8 - else - score += ((100 * target.hp / target.totalhp) - 50) / 4 # +5 to -12 + if ai.trainer.has_skill_flag?("HPAware") + if target.hp >= target.totalhp * 0.7 + score += 10 + else + score += (50 * ((target.hp.to_f / target.totalhp) - 0.6)).to_i # +5 to -30 + end end # Prefer if target has Stored Power if target.has_move_with_function?("PowerHigherWithUserPositiveStatStages") - score += 8 + score += 10 end # Don't prefer if any foe has Punishment ai.each_foe_battler(target.side) do |b, i| next if !b.has_move_with_function?("PowerHigherWithTargetPositiveStatStages") - score -= 5 + score -= 8 end next score } @@ -909,7 +915,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed1MakeTar if !target.effects[PBEffects::TarShot] eff = target.effectiveness_of_type_against_battler(:FIRE) if !Effectiveness.ineffective?(eff) - score += 8 * eff if user.has_damaging_move_of_type?(:FIRE) + score += 10 * eff if user.has_damaging_move_of_type?(:FIRE) end end next score @@ -992,22 +998,23 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetEvasion1Remo ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion1RemoveSideEffects", proc { |score, move, user, target, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if !target.opposes?(user) # Score for stat drop score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown) # Score for removing side effects/terrain - score += 8 if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 1 || - target.pbOwnSide.effects[PBEffects::Reflect] > 1 || - target.pbOwnSide.effects[PBEffects::LightScreen] > 1 || - target.pbOwnSide.effects[PBEffects::Mist] > 1 || - target.pbOwnSide.effects[PBEffects::Safeguard] > 1 + score += 10 if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 1 || + target.pbOwnSide.effects[PBEffects::Reflect] > 1 || + target.pbOwnSide.effects[PBEffects::LightScreen] > 1 || + target.pbOwnSide.effects[PBEffects::Mist] > 1 || + target.pbOwnSide.effects[PBEffects::Safeguard] > 1 if target.can_switch_lax? - score -= 10 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 || + score -= 15 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 || target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 || target.pbOwnSide.effects[PBEffects::StealthRock] || target.pbOwnSide.effects[PBEffects::StickyWeb] end - if user.opposes?(target) && user.can_switch_lax? && Settings::MECHANICS_GENERATION >= 6 - score += 10 if target.pbOpposingSide.effects[PBEffects::Spikes] > 0 || + if user.can_switch_lax? && Settings::MECHANICS_GENERATION >= 6 + score += 15 if target.pbOpposingSide.effects[PBEffects::Spikes] > 0 || target.pbOpposingSide.effects[PBEffects::ToxicSpikes] > 0 || target.pbOpposingSide.effects[PBEffects::StealthRock] || target.pbOpposingSide.effects[PBEffects::StickyWeb] @@ -1296,14 +1303,14 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserCopyTargetStatStages score = ai.get_score_for_target_stat_drop(score, user, drops, false, true) if drops.length > 0 if Settings::NEW_CRITICAL_HIT_RATE_MECHANICS if user.effects[PBEffects::FocusEnergy] > 0 && target.effects[PBEffects::FocusEnergy] == 0 - score -= 4 + score -= 5 elsif user.effects[PBEffects::FocusEnergy] == 0 && target.effects[PBEffects::FocusEnergy] > 0 - score += 4 + score += 5 end if user.effects[PBEffects::LaserFocus] > 0 && target.effects[PBEffects::LaserFocus] == 0 - score -= 3 + score -= 5 elsif user.effects[PBEffects::LaserFocus] == 0 && target.effects[PBEffects::LaserFocus] > 0 - score += 3 + score += 5 end end next score @@ -1428,7 +1435,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToStatStageLower ["LowerPoisonedTargetAtkSpAtkSpd1", "PoisonTargetLowerTargetSpeed1", "HealUserByTargetAttackLowerTargetAttack1"].include?(m.function) } - score += 10 + score += 15 has_move = true end end @@ -1498,49 +1505,33 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseAtk change_matters = false # Score based on changes to Attack if target_atk > user_atk - # User's Attack will be raised - if ai.stat_raise_worthwhile?(user, :ATTACK, true) - score += (20 * ((target_atk.to_f / user_atk) - 1)).to_i - change_matters = true - end - # Target's Attack will be lowered - if ai.stat_drop_worthwhile?(target, :ATTACK, true) - score += (20 * ((target_atk.to_f / user_atk) - 1)).to_i + # User's Attack will be raised, target's Attack will be lowered + if ai.stat_raise_worthwhile?(user, :ATTACK, true) || + ai.stat_drop_worthwhile?(target, :ATTACK, true) + score += (40 * ((target_atk.to_f / user_atk) - 1)).to_i change_matters = true end elsif target_atk < user_atk - # User's Attack will be lowered - if ai.stat_drop_worthwhile?(user, :ATTACK, true) - score -= (20 * ((user_atk.to_f / target_atk) - 1)).to_i - change_matters = true - end - # Target's Attack will be raised - if ai.stat_raise_worthwhile?(target, :ATTACK, true) - score -= (20 * ((user_atk.to_f / target_atk) - 1)).to_i + # User's Attack will be lowered, target's Attack will be raised + if ai.stat_drop_worthwhile?(user, :ATTACK, true) || + ai.stat_raise_worthwhile?(target, :ATTACK, true) + score -= (40 * ((user_atk.to_f / target_atk) - 1)).to_i change_matters = true end end # Score based on changes to Special Attack if target_spatk > user_spatk - # User's Special Attack will be raised - if ai.stat_raise_worthwhile?(user, :SPECIAL_ATTACK, true) - score += (20 * ((target_spatk.to_f / user_spatk) - 1)).to_i - change_matters = true - end - # Target's Special Attack will be lowered - if ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true) - score += (20 * ((target_spatk.to_f / user_spatk) - 1)).to_i + # User's Special Attack will be raised, target's Special Attack will be lowered + if ai.stat_raise_worthwhile?(user, :SPECIAL_ATTACK, true) || + ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true) + score += (40 * ((target_spatk.to_f / user_spatk) - 1)).to_i change_matters = true end elsif target_spatk < user_spatk - # User's Special Attack will be lowered - if ai.stat_drop_worthwhile?(user, :SPECIAL_ATTACK, true) - score -= (20 * ((user_spatk.to_f / target_spatk) - 1)).to_i - change_matters = true - end - # Target's Special Attack will be raised - if ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true) - score -= (20 * ((user_spatk.to_f / target_spatk) - 1)).to_i + # User's Special Attack will be lowered, target's Special Attack will be raised + if ai.stat_drop_worthwhile?(user, :SPECIAL_ATTACK, true) || + ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true) + score -= (40 * ((user_spatk.to_f / target_spatk) - 1)).to_i change_matters = true end end @@ -1562,49 +1553,33 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDef change_matters = false # Score based on changes to Defense if target_def > user_def - # User's Defense will be raised - if ai.stat_raise_worthwhile?(user, :DEFENSE, true) - score += (20 * ((target_def.to_f / user_def) - 1)).to_i - change_matters = true - end - # Target's Defense will be lowered - if ai.stat_drop_worthwhile?(target, :DEFENSE, true) - score += (20 * ((target_def.to_f / user_def) - 1)).to_i + # User's Defense will be raised, target's Defense will be lowered + if ai.stat_raise_worthwhile?(user, :DEFENSE, true) || + ai.stat_drop_worthwhile?(target, :DEFENSE, true) + score += (40 * ((target_def.to_f / user_def) - 1)).to_i change_matters = true end elsif target_def < user_def - # User's Defense will be lowered - if ai.stat_drop_worthwhile?(user, :DEFENSE, true) - score -= (20 * ((user_def.to_f / target_def) - 1)).to_i - change_matters = true - end - # Target's Defense will be raised - if ai.stat_raise_worthwhile?(target, :DEFENSE, true) - score -= (20 * ((user_def.to_f / target_def) - 1)).to_i + # User's Defense will be lowered, target's Defense will be raised + if ai.stat_drop_worthwhile?(user, :DEFENSE, true) || + ai.stat_raise_worthwhile?(target, :DEFENSE, true) + score -= (40 * ((user_def.to_f / target_def) - 1)).to_i change_matters = true end end # Score based on changes to Special Defense if target_spdef > user_spdef - # User's Special Defense will be raised - if ai.stat_raise_worthwhile?(user, :SPECIAL_DEFENSE, true) - score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i - change_matters = true - end - # Target's Special Defense will be lowered - if ai.stat_drop_worthwhile?(target, :SPECIAL_DEFENSE, true) - score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i + # User's Special Defense will be raised, target's Special Defense will be lowered + if ai.stat_raise_worthwhile?(user, :SPECIAL_DEFENSE, true) || + ai.stat_drop_worthwhile?(target, :SPECIAL_DEFENSE, true) + score += (40 * ((target_spdef.to_f / user_spdef) - 1)).to_i change_matters = true end elsif target_spdef < user_spdef - # User's Special Defense will be lowered - if ai.stat_drop_worthwhile?(user, :SPECIAL_DEFENSE, true) - score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i - change_matters = true - end - # Target's Special Defense will be raised - if ai.stat_raise_worthwhile?(target, :SPECIAL_DEFENSE, true) - score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i + # User's Special Defense will be lowered, target's Special Defense will be raised + if ai.stat_drop_worthwhile?(user, :SPECIAL_DEFENSE, true) || + ai.stat_raise_worthwhile?(target, :SPECIAL_DEFENSE, true) + score -= (40 * ((user_spdef.to_f / target_spdef) - 1)).to_i change_matters = true end end @@ -1636,7 +1611,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideDoubleSpeed", Battle::AI::Handlers::MoveEffectScore.add("StartUserSideDoubleSpeed", proc { |score, move, user, ai, battle| # Don't want to make allies faster if Trick Room will make them act later - next Battle::AI::MOVE_USELESS_SCORE if battle.field.effects[PBEffects::TrickRoom] > 1 + if ai.trainer.medium_skill? + next Battle::AI::MOVE_USELESS_SCORE if battle.field.effects[PBEffects::TrickRoom] > 1 + end # Get the speeds of all battlers ally_speeds = [] foe_speeds = [] @@ -1654,7 +1631,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideDoubleSpeed", end next Battle::AI::MOVE_USELESS_SCORE if outspeeds == 0 # This move will achieve something - next score + 10 * outspeeds + 5 + next score + 8 + (10 * outspeeds) } ) @@ -1663,38 +1640,38 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideDoubleSpeed", #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("StartSwapAllBattlersBaseDefensiveStats", proc { |score, move, user, ai, battle| - any_change_matters = false + change_matters = false ai.each_battler do |b, i| b_def = b.base_stat(:DEFENSE) b_spdef = b.base_stat(:SPECIAL_DEFENSE) next if b_def == b_spdef score_change = 0 if b_def > b_spdef - # Battler's Defense will be lowered + # Battler's Defense will be lowered, battler's Special Defense will be raised if ai.stat_drop_worthwhile?(b, :DEFENSE, true) score_change -= (20 * ((b_def.to_f / b_spdef) - 1)).to_i - any_change_matters = true + change_matters = true end # Battler's Special Defense will be raised if ai.stat_raise_worthwhile?(b, :SPECIAL_DEFENSE, true) score_change += (20 * ((b_def.to_f / b_spdef) - 1)).to_i - any_change_matters = true + change_matters = true end else # Battler's Special Defense will be lowered if ai.stat_drop_worthwhile?(b, :SPECIAL_DEFENSE, true) score_change -= (20 * ((b_spdef.to_f / b_def) - 1)).to_i - any_change_matters = true + change_matters = true end # Battler's Defense will be raised if ai.stat_raise_worthwhile?(b, :DEFENSE, true) score_change += (20 * ((b_spdef.to_f / b_def) - 1)).to_i - any_change_matters = true + change_matters = true end end score += (b.opposes?(user)) ? -score_change : score_change end - next Battle::AI::MOVE_USELESS_SCORE if !any_change_matters + next Battle::AI::MOVE_USELESS_SCORE if !change_matters next Battle::AI::MOVE_USELESS_SCORE if score <= Battle::AI::MOVE_BASE_SCORE next score } diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/053_AI_MoveHandlers_BattlerOther.rb b/Data/Scripts/011_Battle/005b_AI move function codes/053_AI_MoveHandlers_BattlerOther.rb index bbd7e8524..d8e5532eb 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/053_AI_MoveHandlers_BattlerOther.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/053_AI_MoveHandlers_BattlerOther.rb @@ -1,5 +1,6 @@ #=============================================================================== -# +# TODO: Should there be all the "next score" for status moves? Remember that +# other function codes can call this code as part of their scoring. #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTarget", proc { |move, user, target, ai, battle| @@ -33,18 +34,18 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SleepTarget", # asleep, but the target won't (usually) be able to make use of # them, so they're not worth considering. score -= 10 if target.has_active_ability?(:EARLYBIRD) - score -= 5 if target.has_active_ability?(:MARVELSCALE) + score -= 8 if target.has_active_ability?(:MARVELSCALE) # Don't prefer if target has a move it can use while asleep score -= 8 if target.check_for_move { |m| m.usableWhenAsleep? } # Don't prefer if the target can heal itself (or be healed by an ally) if target.has_active_ability?(:SHEDSKIN) - score -= 5 + score -= 8 elsif target.has_active_ability?(:HYDRATION) && [:Rain, :HeavyRain].include?(target.battler.effectiveWeather) - score -= 10 + score -= 15 end ai.each_same_side_battler(target.side) do |b, i| - score -= 5 if i != target.index && b.has_active_ability?(:HEALER) + score -= 8 if i != target.index && b.has_active_ability?(:HEALER) end end next score @@ -87,7 +88,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget", "SleepTargetNextTurn") #=============================================================================== -# +# TODO: Should there be all the "next score" for status moves? Remember that +# other function codes can call this code as part of their scoring. #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTarget", proc { |move, user, target, ai, battle| @@ -108,9 +110,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget", next score if add_effect == -999 # Additional effect will be negated score += add_effect # Inherent preference - score += 10 + score += 15 # Prefer if the target is at high HP - score += 10 * target.hp / target.totalhp + if ai.trainer.has_skill_flag?("HPAware") + score += 15 * target.hp / target.totalhp + end # Prefer if the user or an ally has a move/ability that is better if the target is poisoned ai.each_same_side_battler(user.side) do |b, i| score += 5 if b.has_move_with_function?("DoublePowerIfTargetPoisoned", @@ -120,24 +124,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget", # Don't prefer if target benefits from having the poison status problem score -= 8 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :TOXICBOOST]) score -= 25 if target.has_active_ability?(:POISONHEAL) - score -= 15 if target.has_active_ability?(:SYNCHRONIZE) && + score -= 20 if target.has_active_ability?(:SYNCHRONIZE) && user.battler.pbCanPoisonSynchronize?(target.battler) score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed", "CureUserBurnPoisonParalysis") - score -= 10 if target.check_for_move { |m| + score -= 15 if target.check_for_move { |m| m.function == "GiveUserStatusToTarget" && user.battler.pbCanPoison?(target.battler, false, m) } # Don't prefer if the target won't take damage from the poison - score -= 15 if !target.battler.takesIndirectDamage? + score -= 20 if !target.battler.takesIndirectDamage? # Don't prefer if the target can heal itself (or be healed by an ally) if target.has_active_ability?(:SHEDSKIN) - score -= 5 + score -= 8 elsif target.has_active_ability?(:HYDRATION) && [:Rain, :HeavyRain].include?(target.battler.effectiveWeather) - score -= 10 + score -= 15 end ai.each_same_side_battler(target.side) do |b, i| - score -= 5 if i != target.index && b.has_active_ability?(:HEALER) + score -= 8 if i != target.index && b.has_active_ability?(:HEALER) end end next score @@ -172,7 +176,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("PoisonTarget", "BadPoisonTarget") #=============================================================================== -# +# TODO: Should there be all the "next score" for status moves? Remember that +# other function codes can call this code as part of their scoring. #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTarget", proc { |move, user, target, ai, battle| @@ -198,11 +203,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeTarget", if target.faster_than?(user) user_speed = user.rough_stat(:SPEED) target_speed = target.rough_stat(:SPEED) - score += 10 if target_speed < user_speed * ((Settings::MECHANICS_GENERATION >= 7) ? 2 : 4) + score += 15 if target_speed < user_speed * ((Settings::MECHANICS_GENERATION >= 7) ? 2 : 4) end # Prefer if the target is confused or infatuated, to compound the turn skipping - score += 5 if target.effects[PBEffects::Confusion] > 1 - score += 5 if target.effects[PBEffects::Attract] >= 0 + score += 7 if target.effects[PBEffects::Confusion] > 1 + score += 7 if target.effects[PBEffects::Attract] >= 0 # Prefer if the user or an ally has a move/ability that is better if the target is paralysed ai.each_same_side_battler(user.side) do |b, i| score += 5 if b.has_move_with_function?("DoublePowerIfTargetParalyzedCureTarget", @@ -210,22 +215,22 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeTarget", end # Don't prefer if target benefits from having the paralysis status problem score -= 8 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET]) - score -= 15 if target.has_active_ability?(:SYNCHRONIZE) && + score -= 20 if target.has_active_ability?(:SYNCHRONIZE) && user.battler.pbCanParalyzeSynchronize?(target.battler) score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed", "CureUserBurnPoisonParalysis") - score -= 10 if target.check_for_move { |m| + score -= 15 if target.check_for_move { |m| m.function == "GiveUserStatusToTarget" && user.battler.pbCanParalyze?(target.battler, false, m) } # Don't prefer if the target can heal itself (or be healed by an ally) if target.has_active_ability?(:SHEDSKIN) - score -= 5 + score -= 8 elsif target.has_active_ability?(:HYDRATION) && [:Rain, :HeavyRain].include?(target.battler.effectiveWeather) - score -= 10 + score -= 15 end ai.each_same_side_battler(target.side) do |b, i| - score -= 5 if i != target.index && b.has_active_ability?(:HEALER) + score -= 8 if i != target.index && b.has_active_ability?(:HEALER) end end next score @@ -266,7 +271,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeFlinchTarget", ) #=============================================================================== -# +# TODO: Should there be all the "next score" for status moves? Remember that +# other function codes can call this code as part of their scoring. #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("BurnTarget", proc { |move, user, target, ai, battle| @@ -286,10 +292,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget", next score if add_effect == -999 # Additional effect will be negated score += add_effect # Inherent preference - score += 10 + score += 15 # Prefer if the target knows any physical moves that will be weaked by a burn if !target.has_active_ability?(:GUTS) && target.check_for_move { |m| m.physicalMove? } - score += 5 + score += 8 score += 8 if !target.check_for_move { |m| m.specialMove? } end # Prefer if the user or an ally has a move/ability that is better if the target is burned @@ -299,24 +305,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget", # Don't prefer if target benefits from having the burn status problem score -= 8 if target.has_active_ability?([:FLAREBOOST, :GUTS, :MARVELSCALE, :QUICKFEET]) score -= 5 if target.has_active_ability?(:HEATPROOF) - score -= 15 if target.has_active_ability?(:SYNCHRONIZE) && + score -= 20 if target.has_active_ability?(:SYNCHRONIZE) && user.battler.pbCanBurnSynchronize?(target.battler) score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed", "CureUserBurnPoisonParalysis") - score -= 10 if target.check_for_move { |m| + score -= 15 if target.check_for_move { |m| m.function == "GiveUserStatusToTarget" && user.battler.pbCanBurn?(target.battler, false, m) } # Don't prefer if the target won't take damage from the burn - score -= 15 if !target.battler.takesIndirectDamage? + score -= 20 if !target.battler.takesIndirectDamage? # Don't prefer if the target can heal itself (or be healed by an ally) if target.has_active_ability?(:SHEDSKIN) - score -= 5 + score -= 8 elsif target.has_active_ability?(:HYDRATION) && [:Rain, :HeavyRain].include?(target.battler.effectiveWeather) - score -= 10 + score -= 15 end ai.each_same_side_battler(target.side) do |b, i| - score -= 5 if i != target.index && b.has_active_ability?(:HEALER) + score -= 8 if i != target.index && b.has_active_ability?(:HEALER) end end next score @@ -342,7 +348,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnFlinchTarget", ) #=============================================================================== -# +# TODO: Should there be all the "next score" for status moves? Remember that +# other function codes can call this code as part of their scoring. #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FreezeTarget", proc { |move, user, target, ai, battle| @@ -371,18 +378,18 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeTarget", # NOTE: The target's Guts/Quick Feet will benefit from the target being # frozen, but the target won't be able to make use of them, so # they're not worth considering. - score -= 5 if target.has_active_ability?(:MARVELSCALE) + score -= 8 if target.has_active_ability?(:MARVELSCALE) # Don't prefer if the target knows a move that can thaw it score -= 15 if target.check_for_move { |m| m.thawsUser? } # Don't prefer if the target can heal itself (or be healed by an ally) if target.has_active_ability?(:SHEDSKIN) - score -= 5 + score -= 8 elsif target.has_active_ability?(:HYDRATION) && [:Rain, :HeavyRain].include?(target.battler.effectiveWeather) - score -= 10 + score -= 15 end ai.each_same_side_battler(target.side) do |b, i| - score -= 5 if i != target.index && b.has_active_ability?(:HEALER) + score -= 8 if i != target.index && b.has_active_ability?(:HEALER) end end next score @@ -451,7 +458,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("GiveUserStatusToTarget" ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("GiveUserStatusToTarget", proc { |score, move, user, target, ai, battle| - score += 10 # For getting rid of the user's status problem + # Curing the user's status problem + score += 15 if !user.wants_status_problem?(user.status) + # Giving the target a status problem case user.status when :SLEEP next Battle::AI::Handlers.apply_move_effect_against_target_score("SleepTarget", @@ -483,7 +492,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("CureUserBurnPoisonParalysis", ) Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis", proc { |score, move, user, ai, battle| - next score + 15 + next Battle::AI::MOVE_USELESS_SCORE if user.wants_status_problem?(user.status) + next score + 20 } ) @@ -499,7 +509,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus", proc { |score, move, user, ai, battle| score = Battle::AI::MOVE_BASE_SCORE # Ignore the scores for each targeted battler calculated earlier battle.pbParty(user.index).each do |pkmn| - score += 10 if pkmn && pkmn.status != :NONE + score += 12 if pkmn && pkmn.status != :NONE end next score } @@ -514,8 +524,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetBurn", next score if add_effect == -999 # Additional effect will be negated if target.status == :BURN score -= add_effect - score -= 10 - score += 15 if target.wants_status_problem?(:BURN) + if target.wants_status_problem?(:BURN) + score += 15 + else + score -= 10 + end end next score } @@ -543,7 +556,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatu # Tends to be wasteful if the foe just has one Pokémon left next score - 20 if battle.pbAbleNonActiveCount(user.idxOpposingSide) == 0 # Prefer for each user side battler - ai.each_same_side_battler(user.side) { |b, i| score += 10 } + ai.each_same_side_battler(user.side) { |b, i| score += 15 } next score } ) @@ -559,10 +572,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FlinchTarget", next score if add_effect == -999 # Additional effect will be negated score += add_effect # Inherent preference - score += 10 + score += 15 # Prefer if the target is paralysed, confused or infatuated, to compound the # turn skipping - score += 5 if target.status == :PARALYSIS || + score += 8 if target.status == :PARALYSIS || target.effects[PBEffects::Confusion] > 1 || target.effects[PBEffects::Attract] >= 0 next score @@ -614,14 +627,16 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ConfuseTarget", next score if add_effect == -999 # Additional effect will be negated score += add_effect # Inherent preference - score += 5 + score += 10 # Prefer if the target is at high HP - score += 10 * target.hp / target.totalhp + if ai.trainer.has_skill_flag?("HPAware") + score += 20 * target.hp / target.totalhp + end # Prefer if the target is paralysed or infatuated, to compound the turn skipping # TODO: Also prefer if the target is trapped in battle or can't switch out? - score += 5 if target.status == :PARALYSIS || target.effects[PBEffects::Attract] >= 0 + score += 8 if target.status == :PARALYSIS || target.effects[PBEffects::Attract] >= 0 # Don't prefer if target benefits from being confused - score -= 10 if target.has_active_ability?(:TANGLEDFEET) + score -= 15 if target.has_active_ability?(:TANGLEDFEET) end next score } @@ -648,15 +663,15 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AttractTarget", next score if add_effect == -999 # Additional effect will be negated score += add_effect # Inherent preference - score += 10 + score += 15 # Prefer if the target is paralysed or confused, to compound the turn skipping # TODO: Also prefer if the target is trapped in battle or can't switch out? - score += 5 if target.status == :PARALYSIS || target.effects[PBEffects::Confusion] > 1 + score += 8 if target.status == :PARALYSIS || target.effects[PBEffects::Confusion] > 1 # Don't prefer if the target can infatuate the user because of this move - score -= 10 if target.has_active_item?(:DESTINYKNOT) && + score -= 15 if target.has_active_item?(:DESTINYKNOT) && user.battler.pbCanAttract?(target.battler, false) # Don't prefer if the user has another way to infatuate the target - score -= 8 if move.statusMove? && user.has_active_ability?(:CUTECHARM) + score -= 15 if move.statusMove? && user.has_active_ability?(:CUTECHARM) end next score } @@ -695,11 +710,11 @@ Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesBasedOnEnvironment", new_type = :NORMAL if !GameData::Type.exists?(new_type) end # Check if any user's moves will get STAB because of the type change - score += 8 if user.has_damaging_move_of_type?(new_type) + score += 14 if user.has_damaging_move_of_type?(new_type) # Check if any user's moves will lose STAB because of the type change user.pbTypes(true).each do |type| next if type == new_type - score -= 8 if user.has_damaging_move_of_type?(type) + score -= 14 if user.has_damaging_move_of_type?(type) end # NOTE: Other things could be considered, like the foes' moves' # effectivenesses against the current and new user's type(s), and @@ -734,11 +749,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserTypesToResistLast if Effectiveness.ineffective?(effectiveness) next Battle::AI::MOVE_USELESS_SCORE elsif Effectiveness.super_effective?(effectiveness) - score += 12 + score += 15 elsif Effectiveness.normal?(effectiveness) - score += 8 + score += 10 else # Not very effective - score += 4 + score += 5 end next score } @@ -786,7 +801,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserTypesToUserMoveTy # Check if any user's moves will get STAB because of the type change possible_types.each do |type| next if !user.has_damaging_move_of_type?(type) - score += 10 + score += 14 break end # NOTE: Other things could be considered, like the foes' moves' @@ -817,7 +832,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetTypesToPsychic" next if !m.damagingMove? effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :PSYCHIC) if Effectiveness.super_effective?(effectiveness) - score += 8 + score += 10 elsif Effectiveness.ineffective?(effectiveness) score -= 10 end @@ -842,7 +857,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetTypesToWater", next if !m.damagingMove? effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :WATER) if Effectiveness.super_effective?(effectiveness) - score += 8 + score += 10 elsif Effectiveness.ineffective?(effectiveness) score -= 10 end @@ -866,7 +881,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AddGhostTypeToTarget", next if !m.damagingMove? effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :GHOST) if Effectiveness.super_effective?(effectiveness) - score += 8 + score += 10 elsif Effectiveness.not_very_effective?(effectiveness) score -= 5 elsif Effectiveness.ineffective?(effectiveness) @@ -892,7 +907,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AddGrassTypeToTarget", next if !m.damagingMove? effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :GRASS) if Effectiveness.super_effective?(effectiveness) - score += 8 + score += 10 elsif Effectiveness.not_very_effective?(effectiveness) score -= 5 elsif Effectiveness.ineffective?(effectiveness) @@ -929,9 +944,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToSimple new_ability_rating = target.wants_ability?(:SIMPLE) side_mult = (target.opposes?(user)) ? 1 : -1 if old_ability_rating > new_ability_rating - score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max + score += 5 * side_mult * [old_ability_rating - new_ability_rating, 3].max elsif old_ability_rating < new_ability_rating - score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max + score -= 5 * side_mult * [new_ability_rating - old_ability_rating, 3].max end next score } @@ -953,9 +968,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToInsomn new_ability_rating = target.wants_ability?(:INSOMNIA) side_mult = (target.opposes?(user)) ? 1 : -1 if old_ability_rating > new_ability_rating - score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max + score += 5 * side_mult * [old_ability_rating - new_ability_rating, 3].max elsif old_ability_rating < new_ability_rating - score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max + score -= 5 * side_mult * [new_ability_rating - old_ability_rating, 3].max end next score } @@ -976,9 +991,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserAbilityToTargetAb old_ability_rating = user.wants_ability?(user.ability_id) new_ability_rating = user.wants_ability?(target.ability_id) if old_ability_rating > new_ability_rating - score += 4 * [old_ability_rating - new_ability_rating, 3].max + score += 5 * [old_ability_rating - new_ability_rating, 3].max elsif old_ability_rating < new_ability_rating - score -= 4 * [new_ability_rating - old_ability_rating, 3].max + score -= 5 * [new_ability_rating - old_ability_rating, 3].max end next score } @@ -1002,9 +1017,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAb new_ability_rating = target.wants_ability?(user.ability_id) side_mult = (target.opposes?(user)) ? 1 : -1 if old_ability_rating > new_ability_rating - score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max + score += 5 * side_mult * [old_ability_rating - new_ability_rating, 3].max elsif old_ability_rating < new_ability_rating - score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max + score -= 5 * side_mult * [new_ability_rating - old_ability_rating, 3].max end next score } @@ -1033,9 +1048,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAbilities" target_diff = 0 if !target.ability_active? side_mult = (target.opposes?(user)) ? 1 : -1 if user_diff > target_diff - score += 4 * side_mult * [user_diff - target_diff, 3].max + score += 5 * side_mult * [user_diff - target_diff, 3].max elsif target_diff < user_diff - score -= 4 * side_mult * [target_diff - user_diff, 3].max + score -= 5 * side_mult * [target_diff - user_diff, 3].max end next score } @@ -1054,9 +1069,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbility", target_ability_rating = target.wants_ability?(target.ability_id) side_mult = (target.opposes?(user)) ? 1 : -1 if target_ability_rating > 0 - score += 4 * side_mult * [target_ability_rating, 3].max + score += 5 * side_mult * [target_ability_rating, 3].max elsif target_ability_rating < 0 - score -= 4 * side_mult * [target_ability_rating.abs, 3].max + score -= 5 * side_mult * [target_ability_rating.abs, 3].max end next score } @@ -1073,9 +1088,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTar target_ability_rating = target.wants_ability?(target.ability_id) side_mult = (target.opposes?(user)) ? 1 : -1 if target_ability_rating > 0 - score += 4 * side_mult * [target_ability_rating, 3].max + score += 5 * side_mult * [target_ability_rating, 3].max elsif target_ability_rating < 0 - score -= 4 * side_mult * [target_ability_rating.abs, 3].max + score -= 5 * side_mult * [target_ability_rating.abs, 3].max end next score } @@ -1112,7 +1127,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserAirborne", ai.each_foe_battler(user.side) do |b, i| next if !b.has_damaging_move_of_type?(:GROUND) next if Effectiveness.resistant?(user.effectiveness_of_type_against_battler(:GROUND, b)) - score += 5 + score += 10 end # Don't prefer if terrain exists (which the user will no longer be affected by) if ai.trainer.medium_skill? @@ -1131,7 +1146,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetAirborneAndA next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false) } ) -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartUserAirborne", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetAirborneAndAlwaysHitByMoves", proc { |score, move, user, target, ai, battle| # Move is useless if the target is already airborne if target.has_type?(:FLYING) || @@ -1146,12 +1161,12 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartUserAirborne", b.battler.eachMove do |m| acc = m.accuracy acc = m.pbBaseAccuracy(b.battler, target.battler) if ai.trainer.medium_skill? - score += 4 if acc < 90 && acc != 0 - score += 4 if acc <= 50 && acc != 0 + score += 5 if acc < 90 && acc != 0 + score += 5 if acc <= 50 && acc != 0 end next if !b.has_damaging_move_of_type?(:GROUND) next if Effectiveness.resistant?(target.effectiveness_of_type_against_battler(:GROUND, b)) - score -= 5 + score -= 7 end # Prefer if terrain exists (which the target will no longer be affected by) if ai.trainer.medium_skill? @@ -1181,7 +1196,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitsTargetInSkyGroundsTa score += 10 # Prefer if any allies have damaging Ground-type moves ai.each_foe_battler(target.side) do |b, i| - score += 5 if b.has_damaging_move_of_type?(:GROUND) + score += 8 if b.has_damaging_move_of_type?(:GROUND) end # Don't prefer if terrain exists (which the target will become affected by) if ai.trainer.medium_skill? @@ -1207,25 +1222,26 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity", # affected by terrain if b.battler.airborne? score_change = 10 - score_change -= 8 if battle.field.terrain != :None + if ai.trainer.medium_skill? + score_change -= 8 if battle.field.terrain != :None + end score += (user.opposes?(b)) ? score_change : -score_change # Prefer if allies have any damaging Ground moves they'll be able to use # on a grounded foe, and vice versa ai.each_foe_battler(b.side) do |b2, j| - if b2.has_damaging_move_of_type?(:GROUND) - score += (user.opposes?(b2)) ? -5 : 5 - end + next if !b2.has_damaging_move_of_type?(:GROUND) + score += (user.opposes?(b2)) ? -8 : 8 end end # Prefer ending Sky Drop being used on allies, don't prefer ending Sky # Drop being used on foes if b.effects[PBEffects::SkyDrop] >= 0 - score += (user.opposes?(b)) ? -5 : 5 + score += (user.opposes?(b)) ? -8 : 8 end # Gravity raises accuracy of all moves; prefer if the user/ally has low # accuracy moves, don't prefer if foes have any if b.check_for_move { |m| m.accuracy < 85 } - score += (user.opposes?(b)) ? -5 : 5 + score += (user.opposes?(b)) ? -8 : 8 end # Prefer stopping foes' sky-based attacks, don't prefer stopping allies' # sky-based attacks @@ -1233,7 +1249,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity", b.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky", "TwoTurnAttackInvulnerableInSkyParalyzeTarget", "TwoTurnAttackInvulnerableInSkyTargetCannotAct") - score += (user.opposes?(b)) ? 8 : -8 + score += (user.opposes?(b)) ? 10 : -10 end end next score diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/054_AI_MoveHandlers_MoveAttributes.rb b/Data/Scripts/011_Battle/005b_AI move function codes/054_AI_MoveHandlers_MoveAttributes.rb index cf2fddc3c..d13642aab 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/054_AI_MoveHandlers_MoveAttributes.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/054_AI_MoveHandlers_MoveAttributes.rb @@ -75,9 +75,11 @@ Battle::AI::Handlers::MoveBasePower.add("OHKO", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("OHKO", proc { |score, move, user, target, ai, battle| # Don't prefer if the target has less HP and user has a non-OHKO damaging move - if user.check_for_move { |m| !m.is_a?(Battle::Move::OHKO) && m.damagingMove? } - score -= 8 if target.hp <= target.totalhp / 2 - score -= 8 if target.hp <= target.totalhp / 4 + if ai.trainer.has_skill_flag?("HPAware") + if user.check_for_move { |m| m.damagingMove? && !m.is_a?(Battle::Move::OHKO) } + score -= 12 if target.hp <= target.totalhp / 2 + score -= 8 if target.hp <= target.totalhp / 4 + end end next score } @@ -115,7 +117,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DamageTargetAlly", target.battler.allAllies.each do |b| next if !b.near?(target.battler) || !b.battler.takesIndirectDamage? score += 10 - score += 15 if b.hp <= b.totalhp / 16 + if ai.trainer.has_skill_flag?("HPAware") + score += 10 if b.hp <= b.totalhp / 16 + end end next score } @@ -218,7 +222,7 @@ Battle::AI::Handlers::MoveEffectScore.add("PowerHigherWithConsecutiveUse", # Prefer continuing to use this move score += 10 if user.effects[PBEffects::FuryCutter] > 0 # Prefer if holding the Metronome - score += 5 if user.has_active_item?(:METRONOME) + score += 7 if user.has_active_item?(:METRONOME) next score } ) @@ -236,7 +240,7 @@ Battle::AI::Handlers::MoveEffectScore.add("PowerHigherWithConsecutiveUse", # Prefer continuing to use this move score += 10 if user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter] > 0 # Prefer if holding the Metronome - score += 5 if user.has_active_item?(:METRONOME) + score += 7 if user.has_active_item?(:METRONOME) next score } ) @@ -274,8 +278,11 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetAsleepCureTarget", proc { |score, move, user, target, ai, battle| if target.status == :SLEEP && target.statusCount > 1 # Will cure status - score -= 10 - score += 15 if target.wants_status_problem?(:SLEEP) + if target.wants_status_problem?(:SLEEP) + score += 15 + else + score -= 10 + end end next score } @@ -298,8 +305,11 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetParalyzedCureTarget", proc { |score, move, user, target, ai, battle| if target.status == :PARALYSIS # Will cure status - score -= 10 - score += 15 if target.wants_status_problem?(:PARALYSIS) + if target.wants_status_problem?(:PARALYSIS) + score += 15 + else + score -= 10 + end end next score } @@ -374,7 +384,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn", # Prefer if user is slower than its foe(s) and the foe(s) can attack ai.each_foe_battler(user.side) do |b, i| next if user.faster_than?(b) || !b.can_attack? - score += 4 + score += 8 end next score } @@ -389,7 +399,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostH ai.each_foe_battler(target.side) do |b, i| next if i == user.index next if user.faster_than?(b) || !b.can_attack? - score += 4 + score += 8 end next score } @@ -405,7 +415,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostH #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetActed", proc { |score, move, user, target, ai, battle| - score += 15 if target.faster_than?(user) + score += 10 if target.faster_than?(user) next score } ) @@ -415,7 +425,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetActed #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotActed", proc { |score, move, user, target, ai, battle| - score += 15 if user.faster_than?(target) + score += 10 if user.faster_than?(target) next score } ) @@ -457,7 +467,7 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit", # TODO: Change the score depending on how much of an effect a critical hit # will have? Critical hits ignore the user's offensive stat drops # and the target's defensive stat raises, and multiply the damage. - score += 10 + score += 15 end next score } @@ -514,7 +524,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPreventCriticalHitsAgainstUserSi # TODO: Change the score depending on how much of an effect a critical hit # will have? Critical hits ignore the user's offensive stat drops # and the target's defensive stat raises, and multiply the damage. - score += 5 * crit_stage if crit_stage > 0 + score += 8 * crit_stage if crit_stage > 0 score += 10 if b.effects[PBEffects::LaserFocus] > 0 end next score @@ -540,15 +550,17 @@ Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn", useless = true ai.each_foe_battler(user.side) do |b, i| next if !b.can_attack? + score += 5 useless = false - score += 4 end next Battle::AI::MOVE_USELESS_SCORE if useless # Don't prefer if user has high HP, prefer if user has lower HP - if user.hp >= user.totalhp / 2 - score -= 8 - elsif user.hp >= user.totalhp / 8 - score += 4 + if ai.trainer.has_skill_flag?("HPAware") + if user.hp >= user.totalhp / 2 + score -= 15 + elsif user.hp <= user.totalhp / 4 + score += 8 + end end # Don't prefer if the user used a protection move last turn, making this one # less likely to work @@ -570,20 +582,25 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves", Battle::AI::Handlers::MoveEffectScore.add("StartWeakenElectricMoves", proc { |score, move, user, ai, battle| # Don't prefer the lower the user's HP is - if user.hp < user.totalhp / 2 - score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 + if ai.trainer.has_skill_flag?("HPAware") + if user.hp <= user.totalhp / 2 + score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15 + end end # Prefer if foes have Electric moves + any_foe_electric_moves = false ai.each_foe_battler(user.side) do |b, i| next if !b.has_damaging_move_of_type?(:ELECTRIC) - score += 10 - score += 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC } + score += 15 + score += 7 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC } + any_foe_electric_moves = true end + next Battle::AI::MOVE_USELESS_SCORE if !any_foe_electric_moves # Don't prefer if any allies have Electric moves ai.each_same_side_battler(user.side) do |b, i| next if !b.has_damaging_move_of_type?(:ELECTRIC) - score -= 8 - score -= 4 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC } + score -= 10 + score -= 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC } end next score } @@ -601,20 +618,25 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves", Battle::AI::Handlers::MoveEffectScore.add("StartWeakenFireMoves", proc { |score, move, user, ai, battle| # Don't prefer the lower the user's HP is - if user.hp < user.totalhp / 2 - score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 + if ai.trainer.has_skill_flag?("HPAware") + if user.hp <= user.totalhp / 2 + score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15 + end end # Prefer if foes have Fire moves + any_foe_fire_moves = false ai.each_foe_battler(user.side) do |b, i| next if !b.has_damaging_move_of_type?(:FIRE) - score += 10 - score += 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE } + score += 15 + score += 7 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE } + any_foe_fire_moves = true end + next Battle::AI::MOVE_USELESS_SCORE if !any_foe_fire_moves # Don't prefer if any allies have Fire moves ai.each_same_side_battler(user.side) do |b, i| next if !b.has_damaging_move_of_type?(:FIRE) - score -= 8 - score -= 4 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE } + score -= 10 + score -= 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE } end next score } @@ -636,14 +658,16 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenPhysicalDamageAgainstUserS # TODO: Should this HP check exist? The effect can still be set up for # allies. Maybe just don't prefer if there are no replacement mons # left. - if user.hp < user.totalhp / 2 - score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 + if ai.trainer.has_skill_flag?("HPAware") + if user.hp <= user.totalhp / 2 + score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15 + end end # Prefer if foes have physical moves (moreso if they don't have special moves) ai.each_foe_battler(user.side) do |b, i| next if !b.check_for_move { |m| m.physicalMove?(m.type) } - score += 8 - score += 5 if !b.check_for_move { |m| m.specialMove?(m.type) } + score += 10 + score += 8 if !b.check_for_move { |m| m.specialMove?(m.type) } end next score } @@ -665,14 +689,16 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenSpecialDamageAgainstUserSi # TODO: Should this HP check exist? The effect can still be set up for # allies. Maybe just don't prefer if there are no replacement mons # left. - if user.hp < user.totalhp / 2 - score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 + if ai.trainer.has_skill_flag?("HPAware") + if user.hp <= user.totalhp / 2 + score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15 + end end # Prefer if foes have special moves (moreso if they don't have physical moves) ai.each_foe_battler(user.side) do |b, i| next if !b.check_for_move { |m| m.specialMove?(m.type) } - score += 8 - score += 5 if !b.check_for_move { |m| m.physicalMove?(m.type) } + score += 10 + score += 8 if !b.check_for_move { |m| m.physicalMove?(m.type) } end next score } @@ -697,8 +723,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHai # TODO: Should this HP check exist? The effect can still be set up for # allies. Maybe just don't prefer if there are no replacement mons # left. - if user.hp < user.totalhp / 2 - score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 + if ai.trainer.has_skill_flag?("HPAware") + if user.hp <= user.totalhp / 2 + score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15 + end end next score + 15 } @@ -743,16 +771,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser", # be using, so we don't know if Unseen Fist will apply. useless = false # General preference - score += 4 + score += 7 # Prefer if the foe is in the middle of using a two turn attack - score += 8 if b.effects[PBEffects::TwoTurnAttack] && - GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } + score += 15 if b.effects[PBEffects::TwoTurnAttack] && + GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += 5 + score += 8 elsif b_eor_damage < 0 - score -= 5 + score -= 8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -761,13 +789,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser", if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end # Don't prefer if the user used a protection move last turn, making this one # less likely to work - score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) + score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10) next score } ) @@ -788,7 +816,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker", # be using, so we don't know if Unseen Fist will apply. useless = false # General preference - score += 4 + score += 7 # Prefer if the foe is likely to be poisoned by this move if b.check_for_move { |m| m.contactMove? } poison_score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget", @@ -796,14 +824,14 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker", score += poison_score / 2 # Halved because we don't know what move b will use end # Prefer if the foe is in the middle of using a two turn attack - score += 8 if b.effects[PBEffects::TwoTurnAttack] && - GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } + score += 15 if b.effects[PBEffects::TwoTurnAttack] && + GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += 5 + score += 8 elsif b_eor_damage < 0 - score -= 5 + score -= 8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -812,13 +840,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker", if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end # Don't prefer if the user used a protection move last turn, making this one # less likely to work - score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) + score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10) next score } ) @@ -839,7 +867,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie # be using, so we don't know if Unseen Fist will apply. useless = false # General preference - score += 4 + score += 7 # Prefer if the foe's Attack can be lowered by this move if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? } drop_score = ai.get_score_for_target_stat_drop( @@ -847,14 +875,14 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie score += drop_score / 2 # Halved because we don't know what move b will use end # Prefer if the foe is in the middle of using a two turn attack - score += 8 if b.effects[PBEffects::TwoTurnAttack] && - GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } + score += 15 if b.effects[PBEffects::TwoTurnAttack] && + GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += 5 + score += 8 elsif b_eor_damage < 0 - score -= 5 + score -= 8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -863,13 +891,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end # Don't prefer if the user used a protection move last turn, making this one # less likely to work - score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) + score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10) next score } ) @@ -890,21 +918,21 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct" # be using, so we don't know if Unseen Fist will apply. useless = false # General preference - score += 4 + score += 7 # Prefer if the foe's Attack can be lowered by this move if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? } drop_score = ai.get_score_for_target_stat_drop(0, b, [:DEFENSE, 2], false) score += drop_score / 2 # Halved because we don't know what move b will use end # Prefer if the foe is in the middle of using a two turn attack - score += 8 if b.effects[PBEffects::TwoTurnAttack] && - GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } + score += 15 if b.effects[PBEffects::TwoTurnAttack] && + GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += 5 + score += 8 elsif b_eor_damage < 0 - score -= 5 + score -= 8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -913,13 +941,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct" if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end # Don't prefer if the user used a protection move last turn, making this one # less likely to work - score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) + score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10) next score } ) @@ -940,20 +968,20 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi # be using, so we don't know if Unseen Fist will apply. useless = false # General preference - score += 4 + score += 7 # Prefer if this move will deal damage if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? } score += 5 end # Prefer if the foe is in the middle of using a two turn attack - score += 8 if b.effects[PBEffects::TwoTurnAttack] && - GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } + score += 15 if b.effects[PBEffects::TwoTurnAttack] && + GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += 5 + score += 8 elsif b_eor_damage < 0 - score -= 5 + score -= 8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -962,13 +990,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end # Don't prefer if the user used a protection move last turn, making this one # less likely to work - score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) + score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10) next score } ) @@ -992,16 +1020,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse # be using, so we don't know if Unseen Fist will apply. useless = false # General preference - score += 4 + score += 7 # Prefer if the foe is in the middle of using a two turn attack - score += 8 if b.effects[PBEffects::TwoTurnAttack] && - GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } + score += 15 if b.effects[PBEffects::TwoTurnAttack] && + GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += 5 + score += 8 elsif b_eor_damage < 0 - score -= 5 + score -= 8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -1010,12 +1038,12 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end # Use it or lose it - score += 10 + score += 25 next score } ) @@ -1038,13 +1066,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromStatusMoves", !m.pbTarget(b.battler).targets_all } useless = false # General preference - score += 4 + score += 5 # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += 5 + score += 8 elsif b_eor_damage < 0 - score -= 5 + score -= 8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -1053,9 +1081,9 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromStatusMoves", if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end next score } @@ -1082,13 +1110,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromPriorityMoves", next if !b.check_for_move { |m| m.pbPriority(b.battler) > 0 && m.canProtectAgainst? } useless = false # General preference - score += 4 + score += 7 # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += 5 + score += 8 elsif b_eor_damage < 0 - score -= 5 + score -= 8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -1097,13 +1125,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromPriorityMoves", if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end # Don't prefer if the user used a protection move last turn, making this one # less likely to work - score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) + score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10) next score } ) @@ -1128,13 +1156,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromMultiTargetDamagin m.pbTarget(b.battler).num_targets > 1 } useless = false # General preference - score += 4 + score += 7 # Prefer if foe takes EOR damage, don't prefer if they have EOR healing b_eor_damage = b.rough_end_of_round_damage if b_eor_damage > 0 - score += (b.opposes?(user)) ? 5 : -5 + score += (b.opposes?(user)) ? 8 : -8 elsif b_eor_damage < 0 - score -= (b.opposes?(user)) ? 5 : -5 + score -= (b.opposes?(user)) ? 8 : -8 end end next Battle::AI::MOVE_USELESS_SCORE if useless @@ -1143,13 +1171,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromMultiTargetDamagin if user_eor_damage >= user.hp next Battle::AI::MOVE_USELESS_SCORE elsif user_eor_damage > 0 - score -= 5 + score -= 8 elsif user_eor_damage < 0 - score += 5 + score += 8 end # Don't prefer if the user used a protection move last turn, making this one # less likely to work - score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) + score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10) next score } ) @@ -1163,7 +1191,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveProtections", m.is_a?(Battle::Move::ProtectUserSideFromStatusMoves) || m.is_a?(Battle::Move::ProtectUserSideFromDamagingMovesIfUserFirstTurn)) && !m.is_a?(Battle::Move::UserEnduresFaintingThisTurn) } - score += 5 + score += 7 end next score } @@ -1203,7 +1231,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilQuarterOfDamageDea foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes end - score -= 10 * [dmg, user.hp].min / user.hp + score -= 25 * [dmg, user.hp].min / user.hp next score } ) @@ -1221,7 +1249,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealt foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes end - score -= 10 * [dmg, user.hp].min / user.hp + score -= 25 * [dmg, user.hp].min / user.hp end # Score for paralysing score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget", @@ -1243,7 +1271,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealt foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes end - score -= 10 * [dmg, user.hp].min / user.hp + score -= 25 * [dmg, user.hp].min / user.hp end # Score for burning score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget", @@ -1264,7 +1292,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilHalfOfDamageDealt" foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes end - score -= 10 * [dmg, user.hp].min / user.hp + score -= 25 * [dmg, user.hp].min / user.hp next score } ) @@ -1329,13 +1357,16 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("EnsureNextMoveAlwaysHits # benefit from locking on. acc = m.accuracy acc = m.pbBaseAccuracy(user.battler, target.battler) if ai.trainer.medium_skill? - score += 4 if acc < 90 && acc != 0 - score += 4 if acc <= 50 && acc != 0 + score += 5 if acc < 90 && acc != 0 + score += 8 if acc <= 50 && acc != 0 # TODO: Prefer more if m is a OHKO move. end + # TODO: Prefer if target has increased evasion. # Not worth it if the user or the target is at low HP - score -= 10 if user.hp < user.totalhp / 2 - score -= 8 if target.hp < target.totalhp / 2 + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + score -= 8 if target.hp < target.totalhp / 2 + end next score } ) diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/055_AI_MoveHandlers_MultiHit.rb b/Data/Scripts/011_Battle/005b_AI move function codes/055_AI_MoveHandlers_MultiHit.rb index bdf6396bc..2692b3545 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/055_AI_MoveHandlers_MultiHit.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/055_AI_MoveHandlers_MultiHit.rb @@ -8,7 +8,8 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimes", proc { |score, move, user, target, ai, battle| - # Prefer if the target has a Substitute and the first hit can break it + # Prefer if the target has a Substitute and this move can break it before + # the last hit if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) dmg = move.rough_damage num_hits = move.move.pbNumHits(user.battler, [target.battler]) @@ -72,7 +73,8 @@ Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitThreeTimesPowersUpWithEachHit", proc { |score, move, user, target, ai, battle| - # Prefer if the target has a Substitute and the first or second hit can break it + # Prefer if the target has a Substitute and this move can break it before + # the last hit if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) dmg = move.rough_damage score += 10 if target.effects[PBEffects::Substitute] < dmg / 2 @@ -101,7 +103,8 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoToFiveTimes", proc { |score, move, user, target, ai, battle| - # Prefer if the target has a Substitute and the first hit(s) can break it + # Prefer if the target has a Substitute and this move can break it before + # the last/third hit 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 @@ -169,7 +172,8 @@ Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitOncePerUserTeamMember", proc { |score, move, user, target, ai, battle| - # Prefer if the target has a Substitute and the first hit(s) can break it + # Prefer if the target has a Substitute and this move can break it before + # the last hit if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) dmg = move.rough_damage num_hits = 0 @@ -188,10 +192,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitOncePerUserTeamMember #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn", proc { |score, move, user, 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 + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp >= user.totalhp / 2 + end next score } ) @@ -210,7 +214,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack", # Don't prefer because it uses up two turns score -= 10 # Don't prefer if user is at a low HP (time is better spent on quicker moves) - score -= 8 if user.hp < user.totalhp / 2 + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp < user.totalhp / 2 + end # 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 @@ -241,7 +247,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack", end end end - score -= 15 if has_protect_move + score -= 20 if has_protect_move end next score } @@ -367,9 +373,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl # Score for being semi-invulnerable underground ai.each_foe_battler(user.side) do |b, i| if b.check_for_move { |m| m.hitsDiggingTargets? } - score -= 8 + score -= 10 else - score += 5 + score += 8 end end next score @@ -387,9 +393,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl # Score for being semi-invulnerable underwater ai.each_foe_battler(user.side) do |b, i| if b.check_for_move { |m| m.hitsDivingTargets? } - score -= 8 + score -= 10 else - score += 5 + score += 8 end end next score @@ -407,9 +413,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl # Score for being semi-invulnerable in the sky ai.each_foe_battler(user.side) do |b, i| if b.check_for_move { |m| m.hitsFlyingTargets? } - score -= 8 + score -= 10 else - score += 5 + score += 8 end end next score @@ -455,7 +461,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score, move, user, target, ai, battle) # Score for being invulnerable - score += 5 + score += 8 # Score for removing protections score = Battle::AI::Handlers.apply_move_effect_against_target_score("RemoveProtections", score, move, user, target, ai, battle) @@ -506,9 +512,11 @@ Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDa end next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move # Don't prefer if the user isn't at high HP - next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 4 - score -= 15 if user.hp <= user.totalhp / 2 - score -= 8 if user.hp <= user.totalhp * 3 / 4 + if ai.trainer.has_skill_flag?("HPAware") + next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 4 + score -= 15 if user.hp <= user.totalhp / 2 + score -= 8 if user.hp <= user.totalhp * 3 / 4 + end next score } ) diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/056_AI_MoveHandlers_Healing.rb b/Data/Scripts/011_Battle/005b_AI move function codes/056_AI_MoveHandlers_Healing.rb index 86f4099bb..7d2dc8a45 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/056_AI_MoveHandlers_Healing.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/056_AI_MoveHandlers_Healing.rb @@ -12,20 +12,20 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserFullyAndFallAsleep", Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep", proc { |score, move, user, ai, battle| # Consider how much HP will be restored - if user.hp >= user.totalhp * 0.5 - score -= 10 - else - score += 20 * (user.totalhp - user.hp) / user.totalhp + if ai.trainer.has_skill_flag?("HPAware") + if user.hp >= user.totalhp * 0.5 + score -= 10 + else + score += 30 * (user.totalhp - user.hp) / user.totalhp # +15 to +30 + end end # Check whether an existing status problem will be removed - score += 10 if user.status != :NONE - # Check if user will be able to act while asleep + if user.status != :NONE + score += (user.wants_status_problem?(user.status)) ? -10 : 8 + end + # Check if user is happy to be asleep, e.g. can use moves while asleep if ai.trainer.medium_skill? - if user.check_for_move { |m| m.usableWhenAsleep? } - score += 10 - else - score -= 10 - end + score += (user.wants_status_problem?(:SLEEP)) ? 10 : -8 end next score } @@ -42,10 +42,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP", proc { |score, move, user, ai, battle| # Consider how much HP will be restored - if user.hp >= user.totalhp * 0.5 - score -= 10 - else - score += 20 * (user.totalhp - user.hp) / user.totalhp + if ai.trainer.has_skill_flag?("HPAware") + next score - 10 if user.hp >= user.totalhp * 0.5 + score += 30 * (user.totalhp - user.hp) / user.totalhp # +15 to +30 end next score } @@ -59,17 +58,14 @@ Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather", proc { |score, move, user, ai, battle| # Consider how much HP will be restored - if user.hp >= user.totalhp * 0.5 - score -= 10 + score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP", + score, move, user, ai, battle) + case user.battler.effectiveWeather + when :Sun, :HarshSun + score += 5 + when :None, :StrongWinds else - case user.battler.effectiveWeather - when :Sun, :HarshSun - score += 5 - when :None, :StrongWinds - else - score -= 10 - end - score += 20 * (user.totalhp - user.hp) / user.totalhp + score -= 10 end next score } @@ -83,12 +79,9 @@ Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm", proc { |score, move, user, ai, battle| # Consider how much HP will be restored - if user.hp >= user.totalhp * 0.5 - score -= 10 - else - score += 5 if user.battler.effectiveWeather == :Sandstorm - score += 20 * (user.totalhp - user.hp) / user.totalhp - end + score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP", + score, move, user, ai, battle) + score += 5 if user.battler.effectiveWeather == :Sandstorm next score } ) @@ -101,15 +94,13 @@ Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeThisTurn", proc { |score, move, user, ai, battle| # Consider how much HP will be restored - if user.hp >= user.totalhp * 0.5 - score -= 10 - else - score += 20 * (user.totalhp - user.hp) / user.totalhp - end + score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP", + score, move, user, ai, battle) + # User loses the Flying type this round if user.has_type?(:FLYING) # TODO: Decide whether losing the Flying type is good or bad. Look at # type effectiveness changes against the user, and for foes' Ground - # moves. Anything else? + # moves (foe foes slower than the user). Anything else? end next score } @@ -125,15 +116,11 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CureTargetStatusHealUse ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetStatusHealUserHalfOfTotalHP", proc { |score, move, user, target, ai, battle| - # Will cure status - score -= 10 - score += 15 if target.wants_status_problem?(target.status) # Consider how much HP will be restored - if user.hp >= user.totalhp * 0.5 - score -= 10 - else - score += 20 * (user.totalhp - user.hp) / user.totalhp - end + score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP", + score, move, user, ai, battle) + # Will cure target's status + score += (target.wants_status_problem?(target.status)) ? 10 : -8 next score } ) @@ -155,23 +142,23 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByTargetAttackLo if ai.trainer.medium_skill? score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown) end - # Consider how much HP will be restored - heal_amt = target.rough_stat(:ATTACK) - if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount - # Things that affect healing caused by draining - if target.has_active_ability?(:LIQUIDOOZE) - score -= 20 - elsif user.battler.canHeal? - if user.hp >= user.totalhp * 0.5 - score -= 10 - else - heal_amt *= 1.3 if user.has_active_item?(:BIGROOT) - heal_fraction = [user.totalhp - user.hp, heal_amt].min.to_f / user.totalhp - score += 40 * heal_fraction * (user.totalhp - user.hp) / user.totalhp + # Healing the user + if target.has_active_ability?(:LIQUIDOOZE) + score -= 20 + elsif user.battler.canHeal? + score += 5 if user.has_active_item?(:BIGROOT) + if ai.trainer.has_skill_flag?("HPAware") + # Consider how much HP will be restored + heal_amt = target.rough_stat(:ATTACK) + heal_amt *= 1.3 if user.has_active_item?(:BIGROOT) + heal_amt = [heal_amt, user.totalhp - user.hp].min + if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount + if user.hp < user.totalhp * 0.5 + score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20 + end + score += 20 * heal_amt / user.totalhp # +6 to +20 end end - else - score -= 10 if target.has_active_ability?(:LIQUIDOOZE) end next score } @@ -182,19 +169,23 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByTargetAttackLo #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByHalfOfDamageDone", proc { |score, move, user, target, ai, battle| - # Consider how much HP will be restored - heal_amt = move.rough_damage / 2 - if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount - # Things that affect healing caused by draining - if target.has_active_ability?(:LIQUIDOOZE) - score -= 20 - elsif user.battler.canHeal? + rough_dmg = move.rough_damage + if target.has_active_ability?(:LIQUIDOOZE) + score -= 20 if rough_dmg < target.hp + elsif user.battler.canHeal? + score += 5 if user.has_active_item?(:BIGROOT) + if ai.trainer.has_skill_flag?("HPAware") + # Consider how much HP will be restored + heal_amt = rough_dmg / 2 heal_amt *= 1.3 if user.has_active_item?(:BIGROOT) - heal_fraction = [user.totalhp - user.hp, heal_amt].min.to_f / user.totalhp - score += 40 * heal_fraction * (user.totalhp - user.hp) / user.totalhp + heal_amt = [heal_amt, user.totalhp - user.hp].min + if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount + if user.hp < user.totalhp * 0.5 + score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20 + end + score += 20 * heal_amt / user.totalhp # +6 to +20 + end end - else - score -= 10 if target.has_active_ability?(:LIQUIDOOZE) end next score } @@ -216,19 +207,23 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HealUserByHalfOfDamageD #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByThreeQuartersOfDamageDone", proc { |score, move, user, target, ai, battle| - # Consider how much HP will be restored - heal_amt = move.rough_damage * 0.75 - if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount - # Things that affect healing caused by draining - if target.has_active_ability?(:LIQUIDOOZE) - score -= 20 - elsif user.battler.canHeal? + rough_dmg = move.rough_damage + if target.has_active_ability?(:LIQUIDOOZE) + score -= 20 if rough_dmg < target.hp + elsif user.battler.canHeal? + score += 5 if user.has_active_item?(:BIGROOT) + if ai.trainer.has_skill_flag?("HPAware") + # Consider how much HP will be restored + heal_amt = rough_dmg * 0.75 heal_amt *= 1.3 if user.has_active_item?(:BIGROOT) - heal_fraction = [user.totalhp - user.hp, heal_amt].min.to_f / user.totalhp - score += 40 * heal_fraction * (user.totalhp - user.hp) / user.totalhp + heal_amt = [heal_amt, user.totalhp - user.hp].min + if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount + if user.hp < user.totalhp * 0.5 + score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20 + end + score += 20 * heal_amt / user.totalhp # +6 to +20 + end end - else - score -= 10 if target.has_active_ability?(:LIQUIDOOZE) end next score } @@ -244,11 +239,14 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarte ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHP", proc { |score, move, user, target, ai, battle| + next score if !target.battler.canHeal? # Consider how much HP will be restored - if target.hp >= target.totalhp * 0.75 - score -= 5 - else - score += 15 * (target.totalhp - target.hp) / target.totalhp + if ai.trainer.has_skill_flag?("HPAware") + if target.hp >= target.totalhp * 0.75 + score -= 5 + else + score += 15 * (target.totalhp - target.hp) / target.totalhp # +3 to +15 + end end next score } @@ -265,13 +263,12 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarte Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHPCureStatus", proc { |score, move, user, target, ai, battle| # Consider how much HP will be restored - if target.hp >= target.totalhp * 0.75 - score -= 5 - else - score += 15 * (target.totalhp - target.hp) / target.totalhp - end + score = Battle::AI::Handlers.apply_move_effect_score("HealUserAndAlliesQuarterOfTotalHP", + score, move, user, ai, battle) # Check whether an existing status problem will be removed - score += 10 if target.status != :NONE + if target.status != :NONE + score += (target.wants_status_problem?(target.status)) ? -10 : 10 + end next score } ) @@ -288,14 +285,17 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealTargetHalfOfTotalHP" proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if target.opposes?(user) # Consider how much HP will be restored - heal_amt = target.totalhp / 2 - heal_amt = target.totalhp * 0.75 if move.move.pulseMove? && - user.has_active_ability?(:MEGALAUNCHER) - if target.hp >= target.totalhp * 0.5 - score -= 10 - else - heal_fraction = [target.totalhp - target.hp, heal_amt].min.to_f / target.totalhp - score += 40 * heal_fraction * (target.totalhp - target.hp) / target.totalhp + if ai.trainer.has_skill_flag?("HPAware") + if target.hp >= target.totalhp * 0.5 + score -= 10 + else + heal_amt = target.totalhp * 0.5 + heal_amt = target.totalhp * 0.75 if move.move.pulseMove? && + user.has_active_ability?(:MEGALAUNCHER) + heal_amt = [heal_amt, target.totalhp - target.hp].min + score += 20 * (target.totalhp - target.hp) / target.totalhp # +10 to +20 + score += 20 * heal_amt / target.totalhp # +10 or +15 + end end next score } @@ -310,13 +310,16 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealTargetDependingOnGra proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if user.opposes?(target) # Consider how much HP will be restored - heal_amt = target.totalhp / 2 - heal_amt = (target.totalhp * 2 / 3.0).round if battle.field.terrain == :Grassy - if target.hp >= target.totalhp * 0.5 - score -= 10 - else - heal_fraction = [target.totalhp - target.hp, heal_amt].min.to_f / target.totalhp - score += 40 * heal_fraction * (target.totalhp - target.hp) / target.totalhp + if ai.trainer.has_skill_flag?("HPAware") + if target.hp >= target.totalhp * 0.5 + score -= 10 + else + heal_amt = target.totalhp * 0.5 + heal_amt = (target.totalhp * 2 / 3.0).round if battle.field.terrain == :Grassy + heal_amt = [heal_amt, target.totalhp - target.hp].min + score += 20 * (target.totalhp - target.hp) / target.totalhp # +10 to +20 + score += 20 * heal_amt / target.totalhp # +10 or +13 + end end next score } @@ -333,10 +336,12 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserPositionNextTurn", Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn", proc { |score, move, user, ai, battle| # Consider how much HP will be restored - if user.hp >= user.totalhp * 0.5 - score -= 10 - else - score += 15 * (user.totalhp - user.hp) / user.totalhp + if ai.trainer.has_skill_flag?("HPAware") + if user.hp >= user.totalhp * 0.5 + score -= 10 + else + score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20 + end end next score } @@ -352,8 +357,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurn", ) Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn", proc { |score, move, user, ai, battle| - score += 10 - score += 10 if user.has_active_item?(:BIGROOT) + score += 15 + score += 5 if user.has_active_item?(:BIGROOT) next score } ) @@ -368,9 +373,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurnTrapUserInBattl ) Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle", proc { |score, move, user, ai, battle| - score += 5 - score += 10 if user.turnCount < 2 - score += 10 if user.has_active_item?(:BIGROOT) + score += 8 + score += 15 if user.turnCount < 2 + score += 5 if user.has_active_item?(:BIGROOT) next score } ) @@ -386,7 +391,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartDamageTargetEachTu Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartDamageTargetEachTurnIfTargetAsleep", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if target.statusCount <= 1 - next score + 10 * target.statusCount + next score + 8 * target.statusCount } ) @@ -402,20 +407,21 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartLeechSeedTarget", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartLeechSeedTarget", proc { |score, move, user, target, ai, battle| + score += 15 # Prefer early on score += 10 if user.turnCount < 2 if ai.trainer.medium_skill? # Prefer if the user has no damaging moves - score += 20 if !user.check_for_move { |m| m.damagingMove? } + score += 10 if !user.check_for_move { |m| m.damagingMove? } # Prefer if the target can't switch out to remove its seeding - score += 10 if !battle.pbCanChooseNonActive?(target.index) + score += 8 if !battle.pbCanChooseNonActive?(target.index) # Don't prefer if the leeched HP will hurt the user score -= 20 if target.has_active_ability?([:LIQUIDOOZE]) end if ai.trainer.high_skill? # Prefer if user can stall while damage is dealt if user.check_for_move { |m| m.is_a?(Battle::Move::ProtectMove) } - score += 15 + score += 10 end # Don't prefer if target can remove the seed if target.has_move_with_function?("RemoveUserBindingAndEntryHazards") @@ -432,9 +438,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartLeechSeedTarget", Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP", proc { |score, move, user, ai, battle| score -= 15 # User will lose 50% HP, don't prefer this move - if ai.trainer.medium_skill? - score += 10 if user.hp >= user.totalhp * 0.75 # User at 75% HP or more - score += 10 if user.hp <= user.totalhp * 0.25 # User at 25% HP or less + if ai.trainer.has_skill_flag?("HPAware") + score += 15 if user.hp >= user.totalhp * 0.75 # User has HP to spare + score += 15 if user.hp <= user.totalhp * 0.25 # User is near fainting anyway; suicide end if ai.trainer.high_skill? reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) @@ -467,10 +473,10 @@ Battle::AI::Handlers::MoveFailureCheck.copy("UserLosesHalfOfTotalHPExplosive", "UserFaintsExplosive") Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive", proc { |score, move, user, ai, battle| - score -= 25 # User will faint, don't prefer this move - if ai.trainer.medium_skill? - score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more - score += 10 if user.hp <= user.totalhp * 0.25 # User at 25% HP or less + score -= 20 # User will faint, don't prefer this move + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp >= user.totalhp * 0.5 + score += 20 if user.hp <= user.totalhp * 0.25 # User is near fainting anyway; suicide end if ai.trainer.high_skill? reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) @@ -515,14 +521,14 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserFaintsExplosive", #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserFaintsLowerTargetAtkSpAtk2", proc { |score, move, user, target, ai, battle| - score -= 25 # User will faint, don't prefer this move + score -= 20 # User will faint, don't prefer this move # Check the impact of lowering the target's stats score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown) next score if score == Battle::AI::MOVE_USELESS_SCORE # Score for the user fainting - if ai.trainer.medium_skill? - score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more - score += 10 if user.hp <= user.totalhp * 0.25 # User at 25% HP or less + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp >= user.totalhp * 0.5 + score += 20 if user.hp <= user.totalhp * 0.25 # User is near fainting anyway; suicide end if ai.trainer.high_skill? reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) @@ -545,7 +551,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserFaintsHealAndCureReplacement", ) Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement", proc { |score, move, user, ai, battle| - score -= 25 # User will faint, don't prefer this move + score -= 20 # User will faint, don't prefer this move # Check whether the replacement user needs healing, and don't make the below # calculations if not if ai.trainer.medium_skill? @@ -556,10 +562,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement", break end next Battle::AI::MOVE_USELESS_SCORE if !need_healing + score += 10 end - if ai.trainer.medium_skill? - score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more - score += 10 if user.hp <= user.totalhp * 0.25 # User at 25% HP or less + if ai.trainer.has_skill_flag?("HPAware") + score -= 10 if user.hp >= user.totalhp * 0.5 + score += 20 if user.hp <= user.totalhp * 0.25 # User is near fainting anyway; suicide end if ai.trainer.high_skill? reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) @@ -611,16 +618,17 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers", end next Battle::AI::MOVE_USELESS_SCORE if foes_affected == 0 score += 15 if allies_affected == 0 # No downside for user; cancel out inherent negative score - score += 15 * (foes_affected - allies_affected) - score += 5 * foes_with_high_hp + score -= 15 * allies_affected + score += 20 * foes_affected + score += 10 * foes_with_high_hp if ai.trainer.has_skill_flag?("HPAware") end if ai.trainer.high_skill? reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) if foes == 0 # Foe is down to their last Pokémon, can't lose Perish count - score += 30 # => Want to auto-win in 3 turns + score += 25 # => Want to auto-win in 3 turns elsif reserves == 0 # AI is down to its last Pokémon, can't lose Perish count - score -= 20 # => Don't want to auto-lose in 3 turns + score -= 15 # => Don't want to auto-lose in 3 turns end end next score @@ -644,9 +652,9 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints", user_faster_count += 1 if user.faster_than?(b) end next score if user_faster_count == 0 # Move will almost certainly have no effect - score += 5 * user_faster_count + score += 7 * user_faster_count # Prefer this move at lower user HP - if ai.trainer.medium_skill? + if ai.trainer.has_skill_flag?("HPAware") score += 20 if user.hp <= user.totalhp * 0.4 score += 10 if user.hp <= user.totalhp * 0.25 score += 15 if user.hp <= user.totalhp * 0.1 @@ -667,12 +675,12 @@ Battle::AI::Handlers::MoveEffectScore.add("SetAttackerMovePPTo0IfUserFaints", user_faster_count += 1 if user.faster_than?(b) end next score if user_faster_count == 0 # Move will almost certainly have no effect - score += 5 * user_faster_count + score += 7 * user_faster_count # Prefer this move at lower user HP (not as preferred as Destiny Bond, though) - if ai.trainer.medium_skill? - score += 15 if user.hp <= user.totalhp * 0.4 + if ai.trainer.has_skill_flag?("HPAware") + score += 20 if user.hp <= user.totalhp * 0.4 score += 10 if user.hp <= user.totalhp * 0.25 - score += 10 if user.hp <= user.totalhp * 0.1 + score += 15 if user.hp <= user.totalhp * 0.1 end next score } diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/057_AI_MoveHandlers_Items.rb b/Data/Scripts/011_Battle/005b_AI move function codes/057_AI_MoveHandlers_Items.rb index 17882cf07..54cfae5fa 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/057_AI_MoveHandlers_Items.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/057_AI_MoveHandlers_Items.rb @@ -13,8 +13,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTakesTargetItem", user_no_item_preference = user.wants_item?(:NONE) target_item_preference = target.wants_item?(target.item_id) target_no_item_preference = target.wants_item?(:NONE) - score += (user_item_preference - user_no_item_preference) * 3 - score += (target_item_preference - target_no_item_preference) * 3 + score += user_item_preference - user_no_item_preference + score += target_item_preference - target_no_item_preference next score } ) @@ -35,8 +35,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetTakesUserItem", user_no_item_preference = user.wants_item?(:NONE) target_item_preference = target.wants_item?(user.item_id) target_no_item_preference = target.wants_item?(:NONE) - score -= (user_item_preference - user_no_item_preference) * 3 - score -= (target_item_preference - target_no_item_preference) * 3 + score += user_no_item_preference - user_item_preference + score += target_no_item_preference - target_item_preference next score } ) @@ -60,11 +60,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems", user_old_item_preference = user.wants_item?(user.item_id) target_new_item_preference = target.wants_item?(user.item_id) target_old_item_preference = target.wants_item?(target.item_id) - score += (user_new_item_preference - user_old_item_preference) * 3 - score -= (target_new_item_preference - target_old_item_preference) * 3 + score += user_new_item_preference - user_old_item_preference + score += target_old_item_preference - target_new_item_preference # Don't prefer if user used this move in the last round score -= 15 if user.battler.lastMoveUsed && - GameData::Move.get(user.battler.lastMoveUsed).function_code == "UserTargetSwapItems" + GameData::Move.get(user.battler.lastMoveUsed).function_code == move.function next score } ) @@ -80,8 +80,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("RestoreUserConsumedItem", Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem", proc { |score, move, user, ai, battle| user_new_item_preference = user.wants_item?(user.battler.recycleItem) - user_old_item_preference = user.wants_item?(user.item_id) - score += (user_new_item_preference - user_old_item_preference) * 4 + user_old_item_preference = user.wants_item?(:NONE) + score += (user_new_item_preference - user_old_item_preference) * 2 next score } ) @@ -103,7 +103,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveTargetItem", # User can knock off the target's item; score it target_item_preference = target.wants_item?(target.item_id) target_no_item_preference = target.wants_item?(:NONE) - score += (target_item_preference - target_no_item_preference) * 4 + score += (target_item_preference - target_no_item_preference) * 2 next score } ) @@ -121,7 +121,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DestroyTargetBerryOrGem" # User can incinerate the target's item; score it target_item_preference = target.wants_item?(target.item_id) target_no_item_preference = target.wants_item?(:NONE) - score += (target_item_preference - target_no_item_preference) * 4 + score += (target_item_preference - target_no_item_preference) * 2 next score } ) @@ -142,7 +142,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem", proc { |score, move, user, target, ai, battle| target_item_preference = target.wants_item?(target.item_id) target_no_item_preference = target.wants_item?(:NONE) - score += (target_item_preference - target_no_item_preference) * 4 + score += (target_item_preference - target_no_item_preference) * 2 next score } ) @@ -158,8 +158,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetCannotUseIte Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetCannotUseItem", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !target.item || !target.item_active? + # TODO: Useless if target's item cannot be negated or it has no effect. item_score = target.wants_item?(target.item_id) - score += item_score * 3 + score += item_score * 2 next score } ) @@ -176,6 +177,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems", next if !b.item # Skip b if its item is disabled if ai.trainer.medium_skill? + # TODO: Skip b if its item cannot be negated or it has no effect. if battle.field.effects[PBEffects::MagicRoom] > 0 # NOTE: Same as b.item_active? but ignoring the Magic Room part. next if b.effects[PBEffects::Embargo] > 0 @@ -194,10 +196,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems", next Battle::AI::MOVE_USELESS_SCORE if !any_held_items if battle.field.effects[PBEffects::MagicRoom] > 0 next Battle::AI::MOVE_USELESS_SCORE if total_want >= 0 - score -= [total_want, -5].max * 5 # Will enable items, prefer if allies affected more + score -= [total_want, -5].max * 4 # Will enable items, prefer if allies affected more else next Battle::AI::MOVE_USELESS_SCORE if total_want <= 0 - score += [total_want, 5].min * 5 # Will disable items, prefer if foes affected more + score += [total_want, 5].min * 4 # Will disable items, prefer if foes affected more end next score } @@ -218,19 +220,19 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2", score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense2", score, move, user, ai, battle) # Score for the consumed berry's effect - score += ai.get_score_change_for_consuming_item(user, user.item_id) + score += user.get_score_change_for_consuming_item(user.item_id, true) # Score for other results of consuming the berry if ai.trainer.medium_skill? # Prefer if user will heal itself with Cheek Pouch - score += 5 if user.battler.canHeal? && user.hp < user.totalhp / 2 && + score += 8 if user.battler.canHeal? && user.hp < user.totalhp / 2 && user.has_active_ability?(:CHEEKPOUCH) # Prefer if target can recover the consumed berry score += 8 if user.has_active_ability?(:HARVEST) || user.has_move_with_function?("RestoreUserConsumedItem") # Prefer if user couldn't normally consume the berry - score += 4 if !user.battler.canConsumeBerry? + score += 5 if !user.battler.canConsumeBerry? # Prefer if user will become able to use Belch - score += 4 if !user.battler.belched? && user.has_move_with_function?("FailsIfUserNotConsumedBerry") + score += 5 if !user.battler.belched? && user.has_move_with_function?("FailsIfUserNotConsumedBerry") # Prefer if user will benefit from not having an item score += 5 if user.has_active_ability?(:UNBURDEN) end @@ -249,21 +251,21 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersConsumeBerry Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersConsumeBerry", proc { |score, move, user, target, ai, battle| # Score for the consumed berry's effect - score_change = ai.get_score_change_for_consuming_item(target, target.item_id) + score_change = target.get_score_change_for_consuming_item(target.item_id, !target.opposes?(user)) # Score for other results of consuming the berry if ai.trainer.medium_skill? # Prefer if target will heal itself with Cheek Pouch - score_change += 5 if target.battler.canHeal? && target.hp < target.totalhp / 2 && + score_change += 8 if target.battler.canHeal? && target.hp < target.totalhp / 2 && target.has_active_ability?(:CHEEKPOUCH) # Prefer if target can recover the consumed berry score_change += 8 if target.has_active_ability?(:HARVEST) || target.has_move_with_function?("RestoreUserConsumedItem") # Prefer if target couldn't normally consume the berry - score_change += 4 if !target.battler.canConsumeBerry? + score_change += 5 if !target.battler.canConsumeBerry? # Prefer if target will become able to use Belch - score += 4 if !target.battler.belched? && target.has_move_with_function?("FailsIfUserNotConsumedBerry") + score_change += 5 if !target.battler.belched? && target.has_move_with_function?("FailsIfUserNotConsumedBerry") # Prefer if target will benefit from not having an item - score += 5 if target.has_active_ability?(:UNBURDEN) + score_change += 5 if target.has_active_ability?(:UNBURDEN) end score += (target.opposes?(user)) ? -score_change : score_change next score @@ -280,21 +282,21 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserConsumeTargetBerry", next score if target.effects[PBEffects::Substitute] > 0 next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker # Score the user gaining the item's effect - score += ai.get_score_change_for_consuming_item(user, target.item_id) + score += user.get_score_change_for_consuming_item(target.item_id) # Score for other results of consuming the berry if ai.trainer.medium_skill? # Prefer if user will heal itself with Cheek Pouch - score += 5 if user.battler.canHeal? && user.hp < user.totalhp / 2 && + score += 8 if user.battler.canHeal? && user.hp < user.totalhp / 2 && user.has_active_ability?(:CHEEKPOUCH) # Prefer if user will become able to use Belch - score += 4 if !user.battler.belched? && user.has_move_with_function?("FailsIfUserNotConsumedBerry") + score += 5 if !user.battler.belched? && user.has_move_with_function?("FailsIfUserNotConsumedBerry") # Don't prefer if target will benefit from not having an item score -= 5 if target.has_active_ability?(:UNBURDEN) end # Score the target no longer having the item target_item_preference = target.wants_item?(target.item_id) target_no_item_preference = target.wants_item?(:NONE) - score += (target_item_preference - target_no_item_preference) * 4 + score += (target_item_preference - target_no_item_preference) * 2 next score } ) @@ -332,12 +334,12 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ThrowUserItemAtTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget", score, move, user, target, ai, battle) else - score -= ai.get_score_change_for_consuming_item(target, user.item_id) + score -= target.get_score_change_for_consuming_item(user.item_id) end # Score for other results of consuming the berry if ai.trainer.medium_skill? # Don't prefer if target will become able to use Belch - score -= 4 if user.item.is_berry? && !target.battler.belched? && + score -= 5 if user.item.is_berry? && !target.battler.belched? && target.has_move_with_function?("FailsIfUserNotConsumedBerry") # Prefer if user will benefit from not having an item score += 5 if user.has_active_ability?(:UNBURDEN) @@ -346,7 +348,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ThrowUserItemAtTarget", # keep its held item user_item_preference = user.wants_item?(user.item_id) user_no_item_preference = user.wants_item?(:NONE) - score += (user_item_preference - user_no_item_preference) * 4 + score += (user_item_preference - user_no_item_preference) * 2 next score } ) diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/058_AI_MoveHandlers_ChangeMoveEffect.rb b/Data/Scripts/011_Battle/005b_AI move function codes/058_AI_MoveHandlers_ChangeMoveEffect.rb index affea961e..8cc669f10 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/058_AI_MoveHandlers_ChangeMoveEffect.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/058_AI_MoveHandlers_ChangeMoveEffect.rb @@ -6,7 +6,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToUser", # Useless if there is no ally to redirect attacks from next Battle::AI::MOVE_USELESS_SCORE if user.battler.allAllies.length == 0 # Prefer if ally is at low HP and user is at high HP - if user.hp > user.totalhp * 2 / 3 + if ai.trainer.has_skill_flag?("HPAware") && user.hp > user.totalhp * 2 / 3 ai.each_ally(user.index) do |b, i| score += 10 if b.hp <= b.totalhp / 3 end @@ -27,7 +27,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RedirectAllMovesToTarget next Battle::AI::MOVE_USELESS_SCORE if user.battler.allAllies.length == 0 end # Generaly don't prefer this move, as it's a waste of the user's turn - next score - 15 + next score - 20 } ) @@ -47,7 +47,7 @@ Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget", Battle::AI::Handlers::MoveEffectScore.add("RandomlyDamageOrHealTarget", proc { |score, move, user, ai, battle| # Generaly don't prefer this move, as it may heal the target instead - next score - 8 + next score - 10 } ) @@ -56,17 +56,18 @@ Battle::AI::Handlers::MoveEffectScore.add("RandomlyDamageOrHealTarget", #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealAllyOrDamageFoe", proc { |move, user, target, ai, battle| - next !target.opposes?(user) && target.battler.canHeal? + next !target.opposes?(user) && !target.battler.canHeal? } ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealAllyOrDamageFoe", proc { |score, move, user, target, ai, battle| - if !target.opposes?(user) - # Consider how much HP will be restored + next score if target.opposes?(user) + # Consider how much HP will be restored + if ai.trainer.has_skill_flag?("HPAware") if target.hp >= target.totalhp * 0.5 score -= 10 else - score += 20 * (target.totalhp - target.hp) / target.totalhp + score += 20 * (target.totalhp - target.hp) / target.totalhp # +10 to +20 end end next score @@ -116,19 +117,21 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CurseTargetOrLowerUserSp next score if !user.has_type?(:GHOST) && !(move.rough_type == :GHOST && user.has_active_ability?([:LIBERO, :PROTEAN])) # Don't prefer if user will faint because of using this move - next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 2 + if ai.trainer.has_skill_flag?("HPAware") + next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 2 + end # Prefer early on score += 10 if user.turnCount < 2 if ai.trainer.medium_skill? # Prefer if the user has no damaging moves - score += 20 if !user.check_for_move { |m| m.damagingMove? } + score += 15 if !user.check_for_move { |m| m.damagingMove? } # Prefer if the target can't switch out to remove its curse score += 10 if !battle.pbCanChooseNonActive?(target.index) end if ai.trainer.high_skill? # Prefer if user can stall while damage is dealt if user.check_for_move { |m| m.is_a?(Battle::Move::ProtectMove) } - score += 8 + score += 5 end end next score @@ -192,13 +195,10 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetNextFireMoveDamag ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetNextFireMoveDamagesTarget", proc { |score, move, user, target, ai, battle| - # Effect wears off at the end of the round - next Battle::AI::MOVE_USELESS_SCORE if target.faster_than?(user) # Prefer if target knows any Fire moves (moreso if that's the only type they know) - if target.check_for_move { |m| m.pbCalcType(b.battler) == :FIRE } - score += 10 - score += 10 if !target.check_for_move { |m| m.pbCalcType(b.battler) != :FIRE } - end + next Battle::AI::MOVE_USELESS_SCORE if !target.check_for_move { |m| m.pbCalcType(target.battler) == :FIRE } + score += 10 + score += 10 if !target.check_for_move { |m| m.pbCalcType(target.battler) != :FIRE } next score } ) @@ -240,7 +240,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PowerUpAllyMove", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PowerUpAllyMove", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !target.check_for_move { |m| m.damagingMove? } - next score + 4 + next score + 5 } ) @@ -265,10 +265,10 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage", score += 5 if b.rough_stat(:ATTACK) > b.rough_stat(:SPECIAL_ATTACK) # Prefer if the last move the foe used was physical if ai.trainer.medium_skill? && b.battler.lastMoveUsed - score += 5 if GameData::Move.get(b.battler.lastMoveUsed).physical? + score += 8 if GameData::Move.get(b.battler.lastMoveUsed).physical? end # Prefer if the foe is taunted into using a damaging move - score += 4 if b.effects[PBEffects::Taunt] > 0 + score += 5 if b.effects[PBEffects::Taunt] > 0 end # Useless if no foes have a physical move to counter next Battle::AI::MOVE_USELESS_SCORE if !has_physical_move @@ -297,10 +297,10 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage", score += 5 if b.rough_stat(:SPECIAL_ATTACK) > b.rough_stat(:ATTACK) # Prefer if the last move the foe used was special if ai.trainer.medium_skill? && b.battler.lastMoveUsed - score += 5 if GameData::Move.get(b.battler.lastMoveUsed).special? + score += 8 if GameData::Move.get(b.battler.lastMoveUsed).special? end # Prefer if the foe is taunted into using a damaging move - score += 4 if b.effects[PBEffects::Taunt] > 0 + score += 5 if b.effects[PBEffects::Taunt] > 0 end # Useless if no foes have a special move to counter next Battle::AI::MOVE_USELESS_SCORE if !has_special_move @@ -327,10 +327,10 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf", has_damaging_move = true # Prefer if the last move the foe used was damaging if ai.trainer.medium_skill? && b.battler.lastMoveUsed - score += 5 if GameData::Move.get(b.battler.lastMoveUsed).damaging? + score += 8 if GameData::Move.get(b.battler.lastMoveUsed).damaging? end # Prefer if the foe is taunted into using a damaging move - score += 6 if b.effects[PBEffects::Taunt] > 0 + score += 5 if b.effects[PBEffects::Taunt] > 0 end # Useless if no foes have a damaging move to counter next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move @@ -352,7 +352,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1", # More preferable if user also has Spit Up/Swallow if user.battler.pbHasMoveFunction?("PowerDependsOnUserStockpile", "HealUserDependingOnUserStockpile") - score += [10, 8, 5, 3][user.effects[PBEffects::Stockpile]] + score += [10, 10, 8, 5][user.effects[PBEffects::Stockpile]] end next score } @@ -397,13 +397,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile", proc { |score, move, user, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !user.battler.canHeal? # Consider how much HP will be restored - if user.hp >= user.totalhp * 0.5 - score -= 10 - else - # Slightly prefer to hold out for another Stockpile to make this move stronger - score -= 5 if user.effects[PBEffects::Stockpile] < 2 - score += 20 * (user.totalhp - user.hp) / user.totalhp + if ai.trainer.has_skill_flag?("HPAware") + next score - 10 if user.hp >= user.totalhp * 0.5 + score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20 end + # Slightly prefer to hold out for another Stockpile to make this move stronger + score -= 5 if user.effects[PBEffects::Stockpile] < 2 next score } ) @@ -550,13 +549,13 @@ Battle::AI::Handlers::MoveEffectScore.add("BounceBackProblemCausingStatusMoves", ai.each_foe_battler(user.side) do |b, i| next if !b.can_attack? next if !b.check_for_move { |m| m.statusMove? && m.canMagicCoat? } - score += 4 + score += 5 useless = false end next Battle::AI::MOVE_USELESS_SCORE if useless # Don't prefer the lower the user's HP is (better to try something else) - if user.hp < user.totalhp / 2 - score -= 20 * (0.75 - (user.hp.to_f / user.totalhp)) # -5 to -15 + if ai.trainer.has_skill_flag?("HPAware") && user.hp < user.totalhp / 2 + score -= (20 * (1.0 - (user.hp.to_f / user.totalhp))).to_i # -10 to -20 end next score } @@ -571,13 +570,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StealAndUseBeneficialStatusMove", ai.each_foe_battler(user.side) do |b, i| next if !b.can_attack? next if !b.check_for_move { |m| m.statusMove? && m.canSnatch? } - score += 4 + score += 5 useless = false end next Battle::AI::MOVE_USELESS_SCORE if useless # Don't prefer the lower the user's HP is (better to try something else) - if user.hp < user.totalhp / 2 - score -= 20 * (0.75 - (user.hp.to_f / user.totalhp)) # -5 to -15 + if ai.trainer.has_skill_flag?("HPAware") && user.hp < user.totalhp / 2 + score -= (20 * (1.0 - (user.hp.to_f / user.totalhp))).to_i # -10 to -20 end next score } @@ -606,7 +605,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ReplaceMoveThisBattleWit proc { |score, move, user, target, ai, battle| # Generally don't prefer, as this wastes the user's turn just to gain a move # of unknown utility - score -= 8 + score -= 10 # Slightly prefer if this move will definitely succeed, just for the sake of # getting rid of this move score += 5 if user.faster_than?(target) diff --git a/Data/Scripts/011_Battle/005b_AI move function codes/059_AI_MoveHandlers_SwitchingActing.rb b/Data/Scripts/011_Battle/005b_AI move function codes/059_AI_MoveHandlers_SwitchingActing.rb index 24c940b5f..4620d341e 100644 --- a/Data/Scripts/011_Battle/005b_AI move function codes/059_AI_MoveHandlers_SwitchingActing.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/059_AI_MoveHandlers_SwitchingActing.rb @@ -139,9 +139,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SwitchOutTargetStatusMo ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetStatusMove", proc { |score, move, user, target, ai, battle| - score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 - score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 - score += 20 if target.pbOwnSide.effects[PBEffects::StealthRock] + score += 15 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 + score += 15 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 + score += 15 if target.pbOwnSide.effects[PBEffects::StealthRock] next score } ) @@ -153,9 +153,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetDamagingM proc { |score, move, user, target, ai, battle| if (battle.moldBreaker || !target.has_active_ability?(:SUCTIONCUPS)) && !target.effects[PBEffects::Ingrain] - score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 - score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 - score += 20 if target.pbOwnSide.effects[PBEffects::StealthRock] + score += 15 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 + score += 15 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 + score += 15 if target.pbOwnSide.effects[PBEffects::StealthRock] end next score } @@ -172,7 +172,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget", # you don't want to use it?) score += 5 if user.has_active_item?([:BINDINGBAND, :GRIPCLAW]) # Target will take damage at the end of each round from the binding - score += 8 if target.battler.takesIndirectDamage? + score += 10 if target.battler.takesIndirectDamage? # Check whether the target will be trapped in battle by the binding if target.can_become_trapped? score += 8 # Prefer if the target will become trapped by this move @@ -180,20 +180,20 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget", if eor_damage > 0 # Prefer if the target will take damage at the end of each round on top # of binding damage - score += 8 + score += 10 elsif eor_damage < 0 # Don't prefer if the target will heal itself at the end of each round - score -= 8 + score -= 10 end # Prefer if the target has been Perish Songed - score += 10 if target.effects[PBEffects::PerishSong] > 0 + score += 15 if target.effects[PBEffects::PerishSong] > 0 end # Don't prefer if the target can remove the binding (and the binding has an # effect) if target.can_become_trapped? || target.battler.takesIndirectDamage? if ai.trainer.medium_skill? && target.has_move_with_function?("RemoveUserBindingAndEntryHazards") - score -= 8 + score -= 10 end end next score @@ -232,13 +232,6 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattle", if eor_damage >= target.hp next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE end - # Score for EOR damage (intentionally before Rapid Spin check) - hp_fraction = (Settings::MECHANICS_GENERATION >= 6) ? 8 : 16 - if user.has_active_item?(:BINDINGBAND) - hp_fraction = (Settings::MECHANICS_GENERATION >= 6) ? 6 : 8 - end - rounds_to_deplete_hp = (hp_fraction.to_f * target.hp / target.totalhp).ceil - score += 30 / rounds_to_deplete_hp # Not worth trapping if target can remove the binding if ai.trainer.medium_skill? && target.has_move_with_function?("RemoveUserBindingAndEntryHazards") @@ -256,7 +249,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattle", if target.effects[PBEffects::PerishSong] > 0 || target.effects[PBEffects::Attract] >= 0 || eor_damage > 0 - score += 12 + score += 15 end next score } @@ -284,7 +277,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattleLower Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn", proc { |score, move, user, target, ai, battle| # Score for stat drop - score = ai.get_score_for_target_stat_drop(score, target, [:DEFENSE, 1, :SPECIAL_DEFENSE], false) + score = ai.get_score_for_target_stat_drop(score, target, [:DEFENSE, 1, :SPECIAL_DEFENSE, 1], false) # Score for target becoming trapped in battle if target.can_become_trapped? && battle.pbCanChooseNonActive?(target.index) # Not worth trapping if target will faint this round anyway @@ -304,7 +297,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattleLowerT if target.effects[PBEffects::PerishSong] > 0 || target.effects[PBEffects::Attract] >= 0 || eor_damage > 0 - score += 12 + score += 15 end end next score @@ -338,7 +331,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapUserAndTargetInBattl if target.effects[PBEffects::PerishSong] > 0 || target.effects[PBEffects::Attract] >= 0 || eor_damage > 0 - score += 12 + score += 15 end end next score @@ -403,7 +396,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower", end next score if !ally_has_move # Prefer for the sake of doubling in power - score += 5 + score += 10 next score } ) @@ -502,7 +495,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetUsesItsLastUsedMov # ally (since we're here in this code), this move's score will be # inverted later. A higher score here means this move will be less # preferred, which is the result we want. - score += 20 + score += 10 next score } ) @@ -601,19 +594,19 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetLastMoveUs next !target.check_for_move { |m| m.id == target.battler.lastRegularMoveUsed } } ) -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetLastMoveUsed", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB) + # Inherent preference + score += 5 # Prefer if the target is locked into using a single move, or will be if target.effects[PBEffects::ChoiceBand] || target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) || target.has_active_ability?(:GORILLATACTICS) - score += 8 + score += 10 end - # PRefer disabling a damaging move - score += 5 if GameData::Move.try_get(target.battler.lastRegularMoveUsed)&.damaging? - # Inherent preference - score += 8 + # Prefer disabling a damaging move + score += 8 if GameData::Move.try_get(target.battler.lastRegularMoveUsed)&.damaging? next score } ) @@ -631,14 +624,14 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingSameM Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB) + # Inherent preference + score += 10 # Prefer if the target is locked into using a single move, or will be if target.effects[PBEffects::ChoiceBand] || target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) || target.has_active_ability?(:GORILLATACTICS) - score += 8 + score += 10 end - # Inherent preference - score += 8 next score } ) @@ -672,24 +665,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingDiffer else score += 8 end - elsif move_data.damaging? && move_data.target == :NearOther + elsif move_data.damaging? && [:NearOther, :Other].include?(move_data.target) # Prefer encoring damaging moves depending on their type effectiveness # against the user eff = user.effectiveness_of_type_against_battler(move_data.type, target) if Effectiveness.ineffective?(eff) - score += 15 + score += 20 elsif Effectiveness.not_very_effective?(eff) - score += 10 + score += 15 elsif Effectiveness.super_effective?(eff) - score -= 5 + score -= 8 else - score += 5 + score += 8 end end else # We don't know which move is going to be encored; just prefer limiting # the target's options - score += 8 + score += 10 end next score } @@ -717,13 +710,17 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetStatusMoves end end # Move is likely useless if the target will lock themselves into a move, - # because they'll likely lock themselves into a damaging move anyway + # because they'll likely lock themselves into a damaging move if !target.effects[PBEffects::ChoiceBand] if target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) || target.has_active_ability?(:GORILLATACTICS) next Battle::AI::MOVE_USELESS_SCORE end end + # Prefer based on how many status moves the target knows + target.battler.eachMove do |m| + score += 5 if m.statusMove? && (m.pp > 0 || m.total_pp == 0) + end # Prefer if the target has a protection move protection_moves = [ "ProtectUser", # Detect, Protect @@ -738,10 +735,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetStatusMoves "ProtectUserBanefulBunker" # Baneful Bunker ] if target.check_for_move { |m| m.statusMove? && protection_moves.include?(m.function) } - score += 6 + score += 10 end - # Inherent preference - score += 8 next score } ) @@ -766,7 +761,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetHealingMove end end # Inherent preference - score += 8 + score += 10 next score } ) @@ -799,16 +794,16 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetMovesKnownByUser", proc { |score, move, user, target, ai, battle| # Useless if the foes have no moves that the user also knows - shared_move = false + affected_foe_count = 0 user_moves = user.battler.moves.map { |m| m.id } ai.each_foe_battler(user.side) do |b, i| next if !b.check_for_move { |m| user_moves.include?(m.id) } - shared_move = true + affected_foe_count += 1 break end - next Battle::AI::MOVE_USELESS_SCORE if !shared_move + next Battle::AI::MOVE_USELESS_SCORE if affected_foe_count == 0 # Inherent preference - score += 6 + score += 8 * affected_foe_count next score } ) diff --git a/Data/Scripts/022_Maruno/001_move target lister.rb b/Data/Scripts/022_Maruno/001_move target lister.rb index f1c4e2139..880c3ab3b 100644 --- a/Data/Scripts/022_Maruno/001_move target lister.rb +++ b/Data/Scripts/022_Maruno/001_move target lister.rb @@ -74,7 +74,7 @@ end #=============================================================================== MenuHandlers.add(:debug_menu, :print_move_target_functions, { "name" => _INTL("Print Out Move Targets"), - "parent" => :other_menu, + "parent" => :main, "description" => _INTL("Print all blah blah blah."), "effect" => proc { marListMoveTargetFunctionCodes