From 3408b038cf50bb3a8b64bf0fb3df04eaf4e3165f Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 30 Oct 2022 15:25:46 +0000 Subject: [PATCH] Split AI move handlers into general ones and ones per target, rearranged some main move-scoring code --- .../011_Battle/005_AI/001_Battle_AI.rb | 28 +- .../011_Battle/005_AI/003_AI_Switch.rb | 2 +- .../011_Battle/005_AI/004_AI_ChooseMove.rb | 254 ++++++----- .../005_AI/020_AI_MoveEffectScores_Generic.rb | 4 +- .../005_AI/051_AI_MoveHandlers_Misc.rb | 121 +++--- .../052_AI_MoveHandlers_BattlerStats.rb | 408 ++++++++++-------- .../053_AI_MoveHandlers_BattlerOther.rb | 258 +++++------ .../054_AI_MoveHandlers_MoveAttributes.rb | 153 +++---- .../005_AI/055_AI_MoveHandlers_MultiHit.rb | 83 ++-- .../005_AI/056_AI_MoveHandlers_Healing.rb | 205 +++++---- .../005_AI/057_AI_MoveHandlers_Items.rb | 49 +-- .../058_AI_MoveHandlers_ChangeMoveEffect.rb | 131 +++--- .../059_AI_MoveHandlers_SwitchingActing.rb | 112 ++--- .../070_AI_MoveHandlers_GeneralModifiers.rb | 345 +++++++-------- .../011_Battle/005_AI/101_AITrainer.rb | 19 +- .../011_Battle/005_AI/102_AIBattler.rb | 1 + 16 files changed, 1133 insertions(+), 1040 deletions(-) diff --git a/Data/Scripts/011_Battle/005_AI/001_Battle_AI.rb b/Data/Scripts/011_Battle/005_AI/001_Battle_AI.rb index 98d51b1bb..df7957e6b 100644 --- a/Data/Scripts/011_Battle/005_AI/001_Battle_AI.rb +++ b/Data/Scripts/011_Battle/005_AI/001_Battle_AI.rb @@ -64,10 +64,13 @@ end # #=============================================================================== module Battle::AI::Handlers - MoveEffectScore = HandlerHash.new - MoveBasePower = HandlerHash.new - MoveFailureCheck = HandlerHash.new - GeneralMoveScore = HandlerHash.new + MoveFailureCheck = HandlerHash.new + MoveFailureAgainstTargetCheck = HandlerHash.new + MoveEffectScore = HandlerHash.new + MoveEffectAgainstTargetScore = HandlerHash.new + MoveBasePower = HandlerHash.new + GeneralMoveScore = HandlerHash.new + GeneralMoveAgainstTargetScore = HandlerHash.new # Move type - uses main battle code via rough_type # Move accuracy - uses main battle code via rough_accuracy # Move target @@ -79,11 +82,20 @@ module Battle::AI::Handlers return MoveFailureCheck.trigger(function_code, *args) || false end + def self.move_will_fail_against_target?(function_code, *args) + return MoveFailureAgainstTargetCheck.trigger(function_code, *args) || false + end + def self.apply_move_effect_score(function_code, score, *args) ret = MoveEffectScore.trigger(function_code, score, *args) return (ret.nil?) ? score : ret end + def self.apply_move_effect_against_target_score(function_code, score, *args) + ret = MoveEffectAgainstTargetScore.trigger(function_code, score, *args) + return (ret.nil?) ? score : ret + end + def self.get_base_power(function_code, power, *args) ret = MoveBasePower.trigger(function_code, power, *args) return (ret.nil?) ? power : ret @@ -96,4 +108,12 @@ module Battle::AI::Handlers end return score end + + def self.apply_general_move_against_target_score_modifiers(score, *args) + GeneralMoveAgainstTargetScore.each do |id, score_proc| + new_score = score_proc.call(score, *args) + score = new_score if new_score + end + return score + end end diff --git a/Data/Scripts/011_Battle/005_AI/003_AI_Switch.rb b/Data/Scripts/011_Battle/005_AI/003_AI_Switch.rb index 92caaee9f..e02a3d587 100644 --- a/Data/Scripts/011_Battle/005_AI/003_AI_Switch.rb +++ b/Data/Scripts/011_Battle/005_AI/003_AI_Switch.rb @@ -61,7 +61,7 @@ class Battle::AI scoreSum = 0 scoreCount = 0 battler.allOpposing.each do |b| - scoreSum += pbGetMoveScore(battler.moves[idxEncoredMove], b) + scoreSum += pbGetMoveScore(battler.moves[idxEncoredMove], [b]) scoreCount += 1 end if scoreCount > 0 && scoreSum / scoreCount <= 20 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 5639eb4bd..f746b3148 100644 --- a/Data/Scripts/011_Battle/005_AI/004_AI_ChooseMove.rb +++ b/Data/Scripts/011_Battle/005_AI/004_AI_ChooseMove.rb @@ -1,112 +1,97 @@ class Battle::AI + MOVE_FAIL_SCORE = 25 + MOVE_USELESS_SCORE = 60 # Move predicted to do nothing or just be detrimental + MOVE_BASE_SCORE = 100 + #============================================================================= # Get scores for the user's moves (done before any action is assessed). #============================================================================= def pbGetMoveScores - battler = @user.battler - # Get scores and targets for each move choices = [] - # TODO: Split this into two, the first part being the calculation of all - # predicted damages and the second part being the score calculations - # (which are based on the predicted damages). Multi-target moves could - # be fiddly since damages should be calculated for each target but - # they're all related. - battler.eachMoveWithIndex do |m, i| - if !@battle.pbCanChooseMove?(battler.index, i, false) # Unchoosable moves aren't considered - if m.pp == 0 && m.total_pp > 0 - PBDebug.log("[AI] #{battler.pbThis} (#{battler.index}) cannot use move #{m.name} as it has no PP left") + @user.battler.eachMoveWithIndex do |move, idxMove| + # Unchoosable moves aren't considered + if !@battle.pbCanChooseMove?(@user.index, idxMove, false) + if move.pp == 0 && move.total_pp > 0 + PBDebug.log("[AI] #{@user.battler.pbThis} (#{@user.index}) cannot use move #{move.name} as it has no PP left") else - PBDebug.log("[AI] #{battler.pbThis} (#{battler.index}) cannot choose to use #{m.name}") + PBDebug.log("[AI] #{@user.battler.pbThis} (#{@user.index}) cannot choose to use #{move.name}") end next end - pbAddMoveWithScoreToChoices(i, choices) + # Set up move in class variables + set_up_move_check(move) + # Predict whether the move will fail (generally) + if @trainer.has_skill_flag?("PredictMoveFailure") && pbPredictMoveFailure + add_move_to_choices(choices, idxMove, MOVE_FAIL_SCORE) + next + end + target_data = move.pbTarget(@user.battler) + # TODO: Alter target_data if user has Protean and move is Curse. + case target_data.num_targets + when 0 # No targets, affects the user or a side or the whole field + # Includes: BothSides, FoeSide, None, User, UserSide + score = MOVE_BASE_SCORE + PBDebug.logonerr { score = pbGetMoveScore(move) } + add_move_to_choices(choices, idxMove, score) + when 1 # One target to be chosen by the trainer + # Includes: Foe, NearAlly, NearFoe, NearOther, Other, RandomNearFoe, UserOrNearAlly + # TODO: Figure out first which targets are valid. Includes the call to + # pbMoveCanTarget?, but also includes move-redirecting effects like + # Lightning Rod. Skip any battlers that can't be targeted. + @battle.allBattlers.each do |b| + next if !@battle.pbMoveCanTarget?(@user.battler.index, b.index, target_data) + # TODO: This should consider targeting an ally if possible. Scores will + # need to distinguish between harmful and beneficial to target. + # def pbGetMoveScore uses "175 - score" if the target is an ally; + # is this okay? + # Noticeably affects a few moves like Heal Pulse, as well as moves + # that the target can be immune to by an ability (you may want to + # attack the ally anyway so it gains the effect of that ability). + next if target_data.targets_foe && !@user.battler.opposes?(b) + score = MOVE_BASE_SCORE + PBDebug.logonerr { score = pbGetMoveScore(move, [b]) } + add_move_to_choices(choices, idxMove, score, b.index) + end + else # Multiple targets at once + # Includes: AllAllies, AllBattlers, AllFoes, AllNearFoes, AllNearOthers, UserAndAllies + targets = [] + @battle.allBattlers.each do |b| + next if !@battle.pbMoveCanTarget?(@user.battler.index, b.index, target_data) + targets.push(b) + end + score = MOVE_BASE_SCORE + PBDebug.logonerr { score = pbGetMoveScore(move, targets) } + add_move_to_choices(choices, idxMove, score) + end end @battle.moldBreaker = false return choices end - #============================================================================= - # Get scores for the given move against each possible target. - #============================================================================= - # Wild Pokémon choose their moves randomly. - # Trainer Pokémon calculate how much they want to use each of their moves. - def pbAddMoveWithScoreToChoices(idxMove, choices) - battler = @user.battler - # TODO: Better incorporate this with the below code in future. This is here - # for now because of the num_targets > 1 code below, which would - # produce a score of 100 * the number of targets for a multi-target - # move, making it ridiculously over-preferred. - if @user.wild? - score = 100 - choices.push([idxMove, score, -1]) # Move index, score, target - # Doubly prefer one of the user's moves (the choice is random but consistent - # and does not correlate to any other property of the user) - choices.push([idxMove, score, -1]) if battler.pokemon.personalID % battler.moves.length == idxMove - return - end - move = battler.moves[idxMove] - target_data = move.pbTarget(battler) - # TODO: Alter target_data if user has Protean and move is Curse. - if [:UserAndAllies, :AllAllies, :AllBattlers].include?(target_data.id) || - target_data.num_targets == 0 - # Also includes: BothSides, FoeSide, None, User, UserSide - # If move has no targets, affects the user, a side or the whole field, or - # specially affects multiple Pokémon and the AI calculates an overall - # score at once instead of per target - score = 100 - PBDebug.logonerr { score = pbGetMoveScore(move) } - choices.push([idxMove, score, -1]) - elsif target_data.num_targets > 1 - # Includes: AllFoes, AllNearFoes, AllNearOthers - # Would also include UserAndAllies, AllAllies, AllBattlers, but they're above - # If move affects multiple battlers and you don't choose a particular one - # TODO: Should the scores from each target be averaged instead of summed? - total_score = 0 - num_targets = 0 - @battle.allBattlers.each do |b| - next if !@battle.pbMoveCanTarget?(battler.index, b.index, target_data) - score = 100 - PBDebug.logonerr { score = pbGetMoveScore(move, b) } - total_score += ((battler.opposes?(b)) ? score : -score) - num_targets += 1 - end - final_score = (num_targets == 1) ? total_score : 1.5 * total_score / num_targets - choices.push([idxMove, final_score, -1]) - else - # Includes: Foe, NearAlly, NearFoe, NearOther, Other, RandomNearFoe, UserOrNearAlly - # If move affects one battler and you have to choose which one - # TODO: Figure out first which targets are valid. Includes the call to - # pbMoveCanTarget?, but also includes move-redirecting effects like - # Lightning Rod. Skip any battlers that can't be targeted. - @battle.allBattlers.each do |b| - next if !@battle.pbMoveCanTarget?(battler.index, b.index, target_data) - # TODO: This should consider targeting an ally if possible. Scores will - # need to distinguish between harmful and beneficial to target - - # maybe make the score "150 - score" if target is an ally (but - # only if the score is > 10 which is the "will fail" value)? - # Noticeably affects a few moves like Heal Pulse, as well as moves - # that the target can be immune to by an ability (you may want to - # attack the ally anyway so it gains the effect of that ability). - next if target_data.targets_foe && !battler.opposes?(b) - score = 100 - PBDebug.logonerr { score = pbGetMoveScore(move, b) } - choices.push([idxMove, score, b.index]) - end + def add_move_to_choices(choices, idxMove, score, idxTarget = -1) + choices.push([idxMove, score, idxTarget]) + # If the user is a wild Pokémon, doubly prefer one of its moves (the choice + # is random but consistent and does not correlate to any other property of + # the user) + if @user.wild? && @user.pokemon.personalID % @user.battler.moves.length == idxMove + choices.push([idxMove, score, idxTarget]) end end #============================================================================= # Set some extra class variables for the move/target combo being assessed. #============================================================================= - def set_up_move_check(move, target) + def set_up_move_check(move) @move.set_up(move, @user) - # TODO: Set @target to nil if there isn't one? - @target = (target) ? @battlers[target.index] : @user - @target&.refresh_battler @battle.moldBreaker = @user.has_mold_breaker? end + def set_up_move_check_target(target) + # TODO: Set @target to nil if there isn't one? + @target = (target) ? @battlers[target.index] : nil # @user + @target&.refresh_battler + end + #============================================================================= # Returns whether the move will definitely fail (assuming no battle conditions # change between now and using the move). @@ -121,7 +106,13 @@ class Battle::AI # User will be truanting return true if @user.has_active_ability?(:TRUANT) && @user.effects[PBEffects::Truant] # Move effect-specific checks - return true if Battle::AI::Handlers.move_will_fail?(@move.function, @move, @user, @target, self, @battle) + return true if Battle::AI::Handlers.move_will_fail?(@move.function, @move, @user, self, @battle) + return false + end + + def pbPredictMoveFailureAgainstTarget + # Move effect-specific checks + return true if Battle::AI::Handlers.move_will_fail_against_target?(@move.function, @move, @user, @target, self, @battle) # Immunity to priority moves because of Psychic Terrain return true if @battle.field.terrain == :Psychic && @target.battler.affectedByTerrain? && @target.opposes?(@user) && @move.rough_priority(@user) > 0 @@ -152,31 +143,63 @@ class Battle::AI #============================================================================= # Get a score for the given move being used against the given target. #============================================================================= - def pbGetMoveScore(move, target = nil) - set_up_move_check(move, target) - - # Predict whether the move will fail - if @trainer.has_skill_flag?("PredictMoveFailure") - return 25 if pbPredictMoveFailure - end - + def pbGetMoveScore(move, targets = nil) # Get the base score for the move - score = 100 -# if @move.damagingMove? -# # Is also the predicted damage amount as a percentage of target's current HP -# score = pbGetDamagingMoveBaseScore -# else # Status moves -# # Depends on the move's effect -# score = pbGetStatusMoveBaseScore -# end - - # Modify the score according to the move's effect - score = Battle::AI::Handlers.apply_move_effect_score(@move.function, - score, @move, @user, @target, self, @battle) - # Modify the score according to various other effects - score = Battle::AI::Handlers.apply_general_move_score_modifiers( - score, @move, @user, @target, self, @battle) - + score = MOVE_BASE_SCORE + # Scores for each target in turn + if targets + # Reset the base score for the move (each target will add its own score) + score = 0 + # TODO: Distinguish between affected foes and affected allies? + affected_targets = 0 + # Get a score for the move against each target in turn + targets.each do |target| + set_up_move_check_target(target) + # Predict whether the move will fail against the target + if @trainer.has_skill_flag?("PredictMoveFailure") + next if pbPredictMoveFailureAgainstTarget + end + affected_targets += 1 + # Score the move + t_score = MOVE_BASE_SCORE + if @trainer.has_skill_flag?("ScoreMoves") + # Modify the score according to the move's effect against the target + t_score = Battle::AI::Handlers.apply_move_effect_against_target_score(@move.function, + MOVE_BASE_SCORE, @move, @user, @target, self, @battle) + # Modify the score according to various other effects against the target + score = Battle::AI::Handlers.apply_general_move_against_target_score_modifiers( + score, @move, @user, @target, self, @battle) + end + score += (@target.opposes?(@user)) ? t_score : 175 - t_score + end + # Check if any targets were affected + if affected_targets == 0 + if @trainer.has_skill_flag?("PredictMoveFailure") + return MOVE_FAIL_SCORE if !@move.move.worksWithNoTargets? + score = MOVE_USELESS_SCORE + else + score = MOVE_BASE_SCORE + end + else + # TODO: Can this accounting for multiple targets be improved somehow? + score /= affected_targets # Average the score against multiple targets + # Bonus for affecting multiple targets + if @trainer.has_skill_flag?("PreferMultiTargetMoves") + score += (affected_targets - 1) * 10 + end + end + end + # If we're here, the move either has no targets or at least one target will + # be affected (or the move is usable even if no targets are affected, e.g. + # Self-Destruct) + if @trainer.has_skill_flag?("ScoreMoves") + # Modify the score according to the move's effect + score = Battle::AI::Handlers.apply_move_effect_score(@move.function, + score, @move, @user, self, @battle) + # Modify the score according to various other effects + score = Battle::AI::Handlers.apply_general_move_score_modifiers( + score, @move, @user, self, @battle) + end score = score.to_i score = 0 if score < 0 return score @@ -188,26 +211,23 @@ class Battle::AI #============================================================================= def pbChooseMove(choices) user_battler = @user.battler - # If no moves can be chosen, auto-choose a move or Struggle if choices.length == 0 @battle.pbAutoChooseMove(user_battler.index) PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will auto-use a move or Struggle") return end - # Figure out useful information about the choices max_score = 0 choices.each { |c| max_score = c[1] if max_score < c[1] } - # Decide whether all choices are bad, and if so, try switching instead if @trainer.high_skill? && @user.can_switch_lax? badMoves = false - if (max_score <= 25 && user_battler.turnCount > 2) || - (max_score <= 60 && user_battler.turnCount > 4) + if (max_score <= MOVE_FAIL_SCORE && user_battler.turnCount > 2) || + (max_score <= MOVE_USELESS_SCORE && user_battler.turnCount > 4) badMoves = true if pbAIRandom(100) < 80 end - if !badMoves && max_score <= 60 && user_battler.turnCount >= 1 + if !badMoves && max_score <= MOVE_USELESS_SCORE && user_battler.turnCount >= 1 badMoves = choices.none? { |c| user_battler.moves[c[0]].damagingMove? } badMoves = false if badMoves && pbAIRandom(100) < 10 end @@ -216,12 +236,10 @@ class Battle::AI return end end - # Calculate a minimum score threshold and reduce all move scores by it threshold = (max_score * 0.85).floor choices.each { |c| c[3] = [c[1] - threshold, 0].max } total_score = choices.sum { |c| c[3] } - # Log the available choices if $INTERNAL PBDebug.log("[AI] Move choices for #{user_battler.pbThis(true)} (#{user_battler.index}):") @@ -233,7 +251,6 @@ class Battle::AI PBDebug.log(log_msg) end end - # Pick a move randomly from choices weighted by their scores randNum = pbAIRandom(total_score) choices.each do |c| @@ -243,7 +260,6 @@ class Battle::AI @battle.pbRegisterTarget(user_battler.index, c[2]) if c[2] >= 0 break end - # Log the result if @battle.choices[user_battler.index][2] PBDebug.log(" => will use #{@battle.choices[user_battler.index][2].name}") diff --git a/Data/Scripts/011_Battle/005_AI/020_AI_MoveEffectScores_Generic.rb b/Data/Scripts/011_Battle/005_AI/020_AI_MoveEffectScores_Generic.rb index d139f2431..7ceb7d9f8 100644 --- a/Data/Scripts/011_Battle/005_AI/020_AI_MoveEffectScores_Generic.rb +++ b/Data/Scripts/011_Battle/005_AI/020_AI_MoveEffectScores_Generic.rb @@ -5,7 +5,7 @@ class Battle::AI def get_score_for_user_stat_raise(score) # Discard status move/don't prefer damaging move if user has Contrary if !@battle.moldBreaker && @user.has_active_ability?(:CONTRARY) - return (@move.statusMove?) ? score - 40 : score - 20 + return (@move.statusMove?) ? MOVE_USELESS_SCORE : score - 20 end # Don't make score changes if foes have Unaware and user can't make use of # extra stat stages @@ -37,7 +37,7 @@ class Battle::AI if stat_changes.length == 0 # TODO: Have a parameter that decides whether to reduce the score here # (for moves where this is just part of the effect). - return (@move.statusMove?) ? score - 40 : score + return (@move.statusMove?) ? MOVE_USELESS_SCORE : score end # Make score changes based on the general concept of raising stats at all diff --git a/Data/Scripts/011_Battle/005_AI/051_AI_MoveHandlers_Misc.rb b/Data/Scripts/011_Battle/005_AI/051_AI_MoveHandlers_Misc.rb index 7b88050be..6a8a2114f 100644 --- a/Data/Scripts/011_Battle/005_AI/051_AI_MoveHandlers_Misc.rb +++ b/Data/Scripts/011_Battle/005_AI/051_AI_MoveHandlers_Misc.rb @@ -12,19 +12,14 @@ # #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("DoesNothingCongratulations", - proc { |score, move, user, target, ai, battle| - next score - 60 + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE } ) #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("DoesNothingFailsIfNoAlly", - proc { |move, user, target, ai, battle| - next true if user.battler.allAllies.length == 0 - } -) Battle::AI::Handlers::MoveEffectScore.copy("DoesNothingCongratulations", "DoesNothingFailsIfNoAlly") @@ -49,12 +44,12 @@ Battle::AI::Handlers::MoveEffectScore.copy("DoesNothingCongratulations", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("FailsIfNotUserFirstTurn", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.turnCount > 0 } ) Battle::AI::Handlers::MoveEffectScore.add("FailsIfNotUserFirstTurn", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + 25 # Use it or lose it } ) @@ -63,7 +58,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfNotUserFirstTurn", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserHasUnusedMove", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| has_another_move = false has_unused_move = false user.battler.eachMove do |m| @@ -81,7 +76,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserHasUnusedMove", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserNotConsumedBerry", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.belched? } ) @@ -89,7 +84,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserNotConsumedBerry", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("FailsIfTargetHasNoItem", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FailsIfTargetHasNoItem", proc { |move, user, target, ai, battle| next true if !target.item || !target.item_active? } @@ -98,7 +93,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsIfTargetHasNoItem", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("FailsUnlessTargetSharesTypeWithUser", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FailsUnlessTargetSharesTypeWithUser", proc { |move, user, target, ai, battle| user_types = user.pbTypes(true) target_types = target.pbTypes(true) @@ -107,9 +102,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsUnlessTargetSharesTypeWithUser" ) #=============================================================================== -# +# TODO: Split some of this into a MoveEffectScore? #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserDamagedThisTurn", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfUserDamagedThisTurn", proc { |score, move, user, target, ai, battle| # Check whether user is faster than its foe(s) and could use this move user_faster_count = 0 @@ -122,7 +117,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserDamagedThisTurn", foe_faster_count += 1 end end - next score - 40 if user_faster_count == 0 + next Battle::AI::MOVE_USELESS_SCORE if user_faster_count == 0 score += 10 if foe_faster_count == 0 # Effects that make the target unlikely to act before the user if ai.trainer.high_skill? @@ -148,10 +143,10 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserDamagedThisTurn", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("FailsIfTargetActed", +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 score - 40 if target.faster_than?(user) + 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. @@ -165,7 +160,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfTargetActed", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("CrashDamageIfFailsUnusableInGravity", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CrashDamageIfFailsUnusableInGravity", proc { |score, move, user, target, ai, battle| next score - (100 - move.rough_accuracy) if user.battler.takesIndirectDamage? } @@ -175,15 +170,15 @@ Battle::AI::Handlers::MoveEffectScore.add("CrashDamageIfFailsUnusableInGravity", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartSunWeather", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if [:HarshSun, :HeavyRain, :StrongWinds, move.move.weatherType].include?(battle.field.weather) } ) Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather", - proc { |score, move, user, target, ai, battle| - next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || - battle.pbCheckGlobalAbility(:CLOUDNINE) + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || + battle.pbCheckGlobalAbility(:CLOUDNINE) score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 15 if user.has_active_item?(:HEATROCK) score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP @@ -227,9 +222,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather", Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", "StartRainWeather") Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather", - proc { |score, move, user, target, ai, battle| - next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || - battle.pbCheckGlobalAbility(:CLOUDNINE) + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || + battle.pbCheckGlobalAbility(:CLOUDNINE) score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 15 if user.has_active_item?(:DAMPROCK) score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP @@ -269,9 +264,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather", Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", "StartSandstormWeather") Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather", - proc { |score, move, user, target, ai, battle| - next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || - battle.pbCheckGlobalAbility(:CLOUDNINE) + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || + battle.pbCheckGlobalAbility(:CLOUDNINE) score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 15 if user.has_active_item?(:SMOOTHROCK) score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP @@ -310,9 +305,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather", Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", "StartHailWeather") Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather", - proc { |score, move, user, target, ai, battle| - next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || - battle.pbCheckGlobalAbility(:CLOUDNINE) + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || + battle.pbCheckGlobalAbility(:CLOUDNINE) score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 15 if user.has_active_item?(:ICYROCK) score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP @@ -349,12 +344,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartElectricTerrain", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.field.terrain == :Electric } ) Battle::AI::Handlers::MoveEffectScore.add("StartElectricTerrain", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP if battle.field.terrain != :None score -= ai.get_score_for_terrain(battle.field.terrain, user) @@ -368,12 +363,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartElectricTerrain", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartGrassyTerrain", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.field.terrain == :Grassy } ) Battle::AI::Handlers::MoveEffectScore.add("StartGrassyTerrain", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP if battle.field.terrain != :None score -= ai.get_score_for_terrain(battle.field.terrain, user) @@ -387,12 +382,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGrassyTerrain", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartMistyTerrain", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.field.terrain == :Misty } ) Battle::AI::Handlers::MoveEffectScore.add("StartMistyTerrain", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP if battle.field.terrain != :None score -= ai.get_score_for_terrain(battle.field.terrain, user) @@ -406,12 +401,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartMistyTerrain", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartPsychicTerrain", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.field.terrain == :Psychic } ) Battle::AI::Handlers::MoveEffectScore.add("StartPsychicTerrain", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP if battle.field.terrain != :None score -= ai.get_score_for_terrain(battle.field.terrain, user) @@ -425,12 +420,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPsychicTerrain", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RemoveTerrain", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.field.terrain == :None } ) Battle::AI::Handlers::MoveEffectScore.add("RemoveTerrain", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score - ai.get_score_for_terrain(battle.field.terrain, user) } ) @@ -439,12 +434,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveTerrain", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("AddSpikesToFoeSide", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOpposingSide.effects[PBEffects::Spikes] >= 3 } ) Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex } foe_reserves = [] battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty| @@ -464,7 +459,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide", end foe_reserves.push(pkmn) # pkmn will be affected by Spikes end - next score - 40 if foe_reserves.empty? + next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? multiplier = [8, 5, 3][user.pbOpposingSide.effects[PBEffects::Spikes]] score += multiplier * foe_reserves.length next score @@ -475,12 +470,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("AddToxicSpikesToFoeSide", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOpposingSide.effects[PBEffects::ToxicSpikes] >= 2 } ) Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex } foe_reserves = [] battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty| @@ -502,7 +497,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide", end foe_reserves.push(pkmn) # pkmn will be affected by Toxic Spikes end - next score - 40 if foe_reserves.empty? + next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? multiplier = [6, 4][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]] score += multiplier * foe_reserves.length next score @@ -513,12 +508,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("AddStealthRocksToFoeSide", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOpposingSide.effects[PBEffects::StealthRock] } ) Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex } foe_reserves = [] battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty| @@ -531,7 +526,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide", end foe_reserves.push(pkmn) # pkmn will be affected by Stealth Rock end - next score - 40 if foe_reserves.empty? + next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? next score + 8 * foe_reserves.length } ) @@ -540,12 +535,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("AddStickyWebToFoeSide", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOpposingSide.effects[PBEffects::StickyWeb] } ) Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex } foe_reserves = [] battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty| @@ -563,7 +558,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide", end foe_reserves.push(pkmn) # pkmn will be affected by Sticky Web end - next score - 40 if foe_reserves.empty? + next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? next score + 7 * foe_reserves.length } ) @@ -572,7 +567,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("SwapSideEffects", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| has_effect = false 2.times do |side| effects = battle.sides[side].effects @@ -593,7 +588,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwapSideEffects", } ) Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if ai.trainer.medium_skill? good_effects = [:AuroraVeil, :LightScreen, :Mist, :Rainbow, :Reflect, :Safeguard, :SeaOfFire, :Swamp, :Tailwind].map! { |e| PBEffects.const_get(e) } @@ -617,7 +612,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::Substitute] > 0 next true if user.hp <= [user.totalhp / 4, 1].max } @@ -627,7 +622,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute", # #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("RemoveUserBindingAndEntryHazards", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score += 10 if user.effects[PBEffects::Trapping] > 0 score += 15 if user.effects[PBEffects::LeechSeed] >= 0 if battle.pbAbleNonActiveCount(user.idxOwnSide) > 0 @@ -643,13 +638,13 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveUserBindingAndEntryHazards", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("AttackTwoTurnsLater", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AttackTwoTurnsLater", proc { |move, user, target, ai, battle| next true if battle.positions[target.index].effects[PBEffects::FutureSightCounter] > 0 } ) Battle::AI::Handlers::MoveEffectScore.add("AttackTwoTurnsLater", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| # Future Sight tends to be wasteful if down to last Pokémon next score - 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 } @@ -659,7 +654,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackTwoTurnsLater", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UserSwapsPositionsWithAlly", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| num_targets = 0 idxUserOwner = battle.pbGetOwnerIndexFromBattlerIndex(user.index) user.battler.allAllies.each do |b| @@ -671,7 +666,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserSwapsPositionsWithAlly", } ) Battle::AI::Handlers::MoveEffectScore.add("UserSwapsPositionsWithAlly", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score - 30 # Usually no point in using this } ) @@ -680,7 +675,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserSwapsPositionsWithAlly", # #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("BurnAttackerBeforeUserActs", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| ai.battlers.each do |b| next if !b || !b.opposes?(user) next if !b.battler.affectedByContactEffect? diff --git a/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb b/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb index 6bfb2e596..143a3fd19 100644 --- a/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb +++ b/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb @@ -1,14 +1,15 @@ #=============================================================================== -# +# TODO: This code can be called with a single target and with no targets. Make +# sure it doesn't assume that there is a target. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAttack1", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if move.statusMove? && !user.battler.pbCanRaiseStatStage?(move.move.statUp[0], user.battler, move.move) } ) Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next ai.get_score_for_user_stat_raise(score) } ) @@ -24,7 +25,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack2IfTargetFaints", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseUserAttack2IfTargetFaints", proc { |score, move, user, target, ai, battle| if move.rough_damage >= target.hp * 0.9 next ai.get_score_for_user_stat_raise(score) @@ -43,20 +44,20 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2IfTargetFaints", - "RaiseUserAttack3IfTargetFaints") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("RaiseUserAttack2IfTargetFaints", + "RaiseUserAttack3IfTargetFaints") #=============================================================================== # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("MaxUserAttackLoseHalfOfTotalHP", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.hp <= [user.totalhp / 2, 1].max next true if !user.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) } ) Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score = ai.get_score_for_user_stat_raise(score) # Don't prefer the lower the user's HP is score -= 80 * (1 - (user.hp.to_f / user.totalhp)) # 0 to -40 @@ -65,7 +66,8 @@ Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP", ) #=============================================================================== -# +# TODO: This code can be called with a single target and with no targets. Make +# sure it doesn't assume that there is a target. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1", "RaiseUserDefense1") @@ -78,7 +80,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", "RaiseUserDefense1CurlUpUser") Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1CurlUpUser", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score = ai.get_score_for_user_stat_raise(score) if !user.effects[PBEffects::DefenseCurl] && user.check_for_move { |m| m.function == "MultiTurnAttackPowersUpEachTurn" } @@ -89,7 +91,8 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1CurlUpUser", ) #=============================================================================== -# +# TODO: This code can be called with multiple targets and with no targets. Make +# sure it doesn't assume that there is a target. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", "RaiseUserDefense2") @@ -142,7 +145,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", "RaiseUserSpDef1PowerUpElectricMove") Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1PowerUpElectricMove", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score = ai.get_score_for_user_stat_raise(score) if user.check_for_move { |m| m.damagingMove? && m.type == :ELECTRIC } score += 10 @@ -189,7 +192,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2", "RaiseUserSpeed2LowerUserWeight") Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2LowerUserWeight", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score = ai.get_score_for_user_stat_raise(score) if ai.trainer.medium_skill? # TODO: Take into account weight-modifying items/abilities? This "> 1" @@ -270,7 +273,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion2", "RaiseUserEvasion2MinimizeUser") Battle::AI::Handlers::MoveEffectScore.add("RaiseUserEvasion2MinimizeUser", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score = ai.get_score_for_user_stat_raise(score) if ai.trainer.medium_skill? && !user.effects[PBEffects::Minimize] ai.each_foe_battler(user.side) do |b| @@ -296,13 +299,13 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion2", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserCriticalHitRate2", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::FocusEnergy] >= 2 } ) Battle::AI::Handlers::MoveEffectScore.add("RaiseUserCriticalHitRate2", - proc { |score, move, user, target, ai, battle| - next score - 40 if !user.check_for_move { |m| m.damagingMove? } + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if !user.check_for_move { |m| m.damagingMove? } score += 15 if ai.trainer.medium_skill? # Other effects that raise the critical hit rate @@ -325,7 +328,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserCriticalHitRate2", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAtkDef1", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| if move.statusMove? will_fail = true (move.move.statUp.length / 2).times do |i| @@ -368,7 +371,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("LowerUserDefSpDef1RaiseUserAtkSpAtkSpd2", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| will_fail = true (move.move.statUp.length / 2).times do |i| next if !user.battler.pbCanRaiseStatStage?(move.move.statUp[i * 2], user.battler, move.move) @@ -384,7 +387,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerUserDefSpDef1RaiseUserAtkSpAtkS } ) Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDef1RaiseUserAtkSpAtkSpd2", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= user.stages[:ATTACK] * 20 score -= user.stages[:SPEED] * 20 score -= user.stages[:SPECIAL_ATTACK] * 20 @@ -463,7 +466,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserMainStats1LoseThirdOfTotalHP", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.hp <= [user.totalhp / 3, 1].max will_fail = true (move.move.statUp.length / 2).times do |i| @@ -475,7 +478,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserMainStats1LoseThirdOfTotalH } ) Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1LoseThirdOfTotalHP", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next 0 if !battle.moldBreaker && user.has_active_ability?(:CONTRARY) score += 30 if ai.trainer.high_skill? && user.hp >= user.totalhp * 0.75 GameData::Stat.each_main_battle { |s| score += 10 if user.stages[s.id] <= 0 } @@ -491,7 +494,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1LoseThirdOfTotalHP # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserMainStats1TrapUserInBattle", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::NoRetreat] will_fail = true (move.move.statUp.length / 2).times do |i| @@ -503,7 +506,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserMainStats1TrapUserInBattle" } ) Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1TrapUserInBattle", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next 0 if !battle.moldBreaker && user.has_active_ability?(:CONTRARY) if ai.trainer.high_skill? score -= 50 if user.hp <= user.totalhp / 2 @@ -522,7 +525,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1TrapUserInBattle", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("StartRaiseUserAtk1WhenDamaged", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + 25 if user.effects[PBEffects::Rage] } ) @@ -531,7 +534,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRaiseUserAtk1WhenDamaged", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("LowerUserAttack1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + user.stages[:ATTACK] * 10 } ) @@ -546,7 +549,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("LowerUserAttack1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefense1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + user.stages[:DEFENSE] * 10 } ) @@ -561,7 +564,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("LowerUserDefense1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("LowerUserSpAtk1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + user.stages[:SPECIAL_ATTACK] * 10 } ) @@ -576,7 +579,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("LowerUserSpAtk1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("LowerUserSpDef1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + user.stages[:SPECIAL_DEFENSE] * 10 } ) @@ -591,7 +594,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("LowerUserSpDef1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("LowerUserSpeed1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + user.stages[:SPECIAL_DEFENSE] * 10 } ) @@ -606,7 +609,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("LowerUserSpeed1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("LowerUserAtkDef1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| avg = user.stages[:ATTACK] * 10 avg += user.stages[:DEFENSE] * 10 next score + avg / 2 @@ -617,7 +620,7 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerUserAtkDef1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDef1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| avg = user.stages[:DEFENSE] * 10 avg += user.stages[:SPECIAL_DEFENSE] * 10 next score + avg / 2 @@ -628,7 +631,7 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDef1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDefSpd1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| avg = user.stages[:DEFENSE] * 10 avg += user.stages[:SPEED] * 10 avg += user.stages[:SPECIAL_DEFENSE] * 10 @@ -638,9 +641,8 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDefSpd1", #=============================================================================== # TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetAttack1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack1", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) @@ -650,15 +652,15 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetAttack1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetAttack2ConfuseTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack2ConfuseTarget", proc { |move, user, target, ai, battle| next true if !target.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) && !target.battler.pbCanConfuse?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetAttack2ConfuseTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetAttack2ConfuseTarget", proc { |score, move, user, target, ai, battle| - next score - 60 if !target.battler.pbCanConfuse?(user.battler, false) + next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false) next score + 30 if target.stages[:ATTACK] < 0 } ) @@ -666,15 +668,15 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetAttack2ConfuseTarget", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetSpAtk1ConfuseTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetSpAtk1ConfuseTarget", proc { |move, user, target, ai, battle| next true if !target.battler.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user.battler, move.move) && !target.battler.pbCanConfuse?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetSpAtk1ConfuseTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetSpAtk1ConfuseTarget", proc { |score, move, user, target, ai, battle| - next score - 60 if !target.battler.pbCanConfuse?(user.battler, false) + next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false) next score + 30 if target.stages[:SPECIAL_ATTACK] < 0 } ) @@ -682,12 +684,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetSpAtk1ConfuseTarget", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetSpDef1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetSpDef1", proc { |move, user, target, ai, battle| next true if !target.battler.pbCanRaiseStatStage?(:SPECIAL_DEFENSE, user.battler, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetSpDef1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetSpDef1", proc { |score, move, user, target, ai, battle| next score - target.stages[:SPECIAL_DEFENSE] * 10 } @@ -696,7 +698,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetSpDef1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetRandomStat2", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetRandomStat2", proc { |move, user, target, ai, battle| will_fail = true GameData::Stat.each_battle do |s| @@ -706,7 +708,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetRandomStat2", next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetRandomStat2", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetRandomStat2", proc { |score, move, user, target, ai, battle| avgStat = 0 GameData::Stat.each_battle do |s| @@ -720,16 +722,16 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetRandomStat2", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetAtkSpAtk2", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAtkSpAtk2", proc { |move, user, target, ai, battle| next true if !target.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) && !target.battler.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user.battler, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetAtkSpAtk2", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetAtkSpAtk2", proc { |score, move, user, target, ai, battle| - next score - 40 if target.opposes?(user) - next score - 40 if !battle.moldBreaker && target.has_active_ability?(:CONTRARY) + next Battle::AI::MOVE_USELESS_SCORE if target.opposes?(user) + next Battle::AI::MOVE_USELESS_SCORE if !battle.moldBreaker && target.has_active_ability?(:CONTRARY) score -= target.stages[:ATTACK] * 10 score -= target.stages[:SPECIAL_ATTACK] * 10 next score @@ -739,13 +741,13 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetAtkSpAtk2", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAttack1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAttack1", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanLowerStatStage?(move.move.statDown[0], user.battler, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAttack1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAttack1", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:ATTACK] * 20 @@ -781,9 +783,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAttack1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAttack1", - "LowerTargetAttack1BypassSubstitute") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAttack1BypassSubstitute", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack1", + "LowerTargetAttack1BypassSubstitute") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAttack1BypassSubstitute", proc { |score, move, user, target, ai, battle| score += target.stages[:ATTACK] * 20 if ai.trainer.medium_skill? @@ -806,9 +808,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAttack1BypassSubstitute", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAttack1", - "LowerTargetAttack2") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAttack2", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack1", + "LowerTargetAttack2") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAttack2", proc { |score, move, user, target, ai, battle| if move.statusMove? score += 40 if user.turnCount == 0 @@ -846,17 +848,17 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAttack2", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAttack2", - "LowerTargetAttack3") -Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetAttack2", - "LowerTargetAttack3") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack2", + "LowerTargetAttack3") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAttack2", + "LowerTargetAttack3") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAttack1", - "LowerTargetDefense1") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack1", + "LowerTargetDefense1") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetDefense1", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:DEFENSE] * 20 @@ -870,14 +872,14 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetDefense1", - "LowerTargetDefense1PowersUpInGravity") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetDefense1", + "LowerTargetDefense1PowersUpInGravity") Battle::AI::Handlers::MoveBasePower.add("LowerTargetDefense1PowersUpInGravity", proc { |power, move, user, target, ai, battle| next move.move.pbBaseDamage(power, user.battler, target.battler) } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1PowersUpInGravity", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetDefense1PowersUpInGravity", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:DEFENSE] * 20 @@ -891,9 +893,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1PowersUpInGravity" #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetDefense1", - "LowerTargetDefense2") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense2", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetDefense1", + "LowerTargetDefense2") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetDefense2", proc { |score, move, user, target, ai, battle| if move.statusMove? score += 40 if user.turnCount == 0 @@ -909,17 +911,17 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense2", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetDefense2", - "LowerTargetDefense3") -Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetDefense2", - "LowerTargetDefense3") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetDefense2", + "LowerTargetDefense3") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetDefense2", + "LowerTargetDefense3") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAttack1", - "LowerTargetSpAtk1") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack1", + "LowerTargetSpAtk1") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpAtk1", proc { |score, move, user, target, ai, battle| if move.statusMove? score += user.stages[:SPECIAL_ATTACK] * 20 @@ -955,9 +957,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpAtk1", - "LowerTargetSpAtk2") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk2", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpAtk1", + "LowerTargetSpAtk2") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpAtk2", proc { |score, move, user, target, ai, battle| score += 40 if user.turnCount == 0 score += target.stages[:SPECIAL_ATTACK] * 20 @@ -968,7 +970,7 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk2", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetSpAtk2IfCanAttract", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetSpAtk2IfCanAttract", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanLowerStatStage?(move.move.statDown[0], user.battler, move.move) @@ -976,7 +978,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetSpAtk2IfCanAttract", next true if !battle.moldBreaker && target.has_active_ability?(:OBLIVIOUS) } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk2IfCanAttract", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpAtk2IfCanAttract", proc { |score, move, user, target, ai, battle| if move.statusMove? score += 40 if user.turnCount == 0 @@ -1014,9 +1016,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk2IfCanAttract", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpAtk1", - "LowerTargetSpAtk3") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk3", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpAtk1", + "LowerTargetSpAtk3") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpAtk3", proc { |score, move, user, target, ai, battle| score += 40 if user.turnCount == 0 score += target.stages[:SPECIAL_ATTACK] * 20 @@ -1027,9 +1029,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk3", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetDefense1", - "LowerTargetSpDef1") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpDef1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetDefense1", + "LowerTargetSpDef1") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpDef1", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:SPECIAL_DEFENSE] * 20 @@ -1043,9 +1045,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpDef1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpDef1", - "LowerTargetSpDef2") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpDef2", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpDef1", + "LowerTargetSpDef2") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpDef2", proc { |score, move, user, target, ai, battle| if move.statusMove? score += 40 if user.turnCount == 0 @@ -1061,17 +1063,17 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpDef2", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpDef2", - "LowerTargetSpDef3") -Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetSpDef2", - "LowerTargetSpDef3") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpDef2", + "LowerTargetSpDef3") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpDef2", + "LowerTargetSpDef3") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpDef1", - "LowerTargetSpeed1") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpDef1", + "LowerTargetSpeed1") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed1", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:SPEED] * 10 @@ -1090,27 +1092,27 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpeed1", - "LowerTargetSpeed1WeakerInGrassyTerrain") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpeed1", + "LowerTargetSpeed1WeakerInGrassyTerrain") Battle::AI::Handlers::MoveBasePower.add("LowerTargetSpeed1WeakerInGrassyTerrain", proc { |power, move, user, target, ai, battle| next move.move.pbBaseDamage(power, user.battler, target.battler) } ) -Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetSpeed1", - "LowerTargetSpeed1WeakerInGrassyTerrain") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpeed1", + "LowerTargetSpeed1WeakerInGrassyTerrain") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetSpeed1MakeTargetWeakerToFire", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetSpeed1MakeTargetWeakerToFire", proc { |move, user, target, ai, battle| next false if !target.effects[PBEffects::TarShot] next true if move.statusMove? && !target.battler.pbCanLowerStatStage?(move.move.statDown[0], user.battler, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed1MakeTargetWeakerToFire", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed1MakeTargetWeakerToFire", proc { |score, move, user, target, ai, battle| score += target.stages[:SPEED] * 10 if ai.trainer.high_skill? @@ -1126,9 +1128,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed1MakeTargetWeakerToFi #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpeed1", - "LowerTargetSpeed2") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed2", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpeed1", + "LowerTargetSpeed2") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed2", proc { |score, move, user, target, ai, battle| if move.statusMove? score += 20 if user.turnCount == 0 @@ -1149,17 +1151,17 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed2", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpeed2", - "LowerTargetSpeed3") -Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetSpeed2", - "LowerTargetSpeed3") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpeed2", + "LowerTargetSpeed3") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpeed2", + "LowerTargetSpeed3") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpeed1", - "LowerTargetAccuracy1") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAccuracy1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpeed1", + "LowerTargetAccuracy1") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAccuracy1", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:ACCURACY] * 10 @@ -1173,25 +1175,25 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAccuracy1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAccuracy1", - "LowerTargetAccuracy2") -Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetAccuracy1", - "LowerTargetAccuracy2") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAccuracy1", + "LowerTargetAccuracy2") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAccuracy1", + "LowerTargetAccuracy2") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAccuracy1", - "LowerTargetAccuracy3") -Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetAccuracy1", - "LowerTargetAccuracy3") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAccuracy1", + "LowerTargetAccuracy3") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAccuracy1", + "LowerTargetAccuracy3") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAccuracy1", - "LowerTargetEvasion1") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetEvasion1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAccuracy1", + "LowerTargetEvasion1") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion1", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:EVASION] * 10 @@ -1205,7 +1207,7 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetEvasion1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetEvasion1RemoveSideEffects", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetEvasion1RemoveSideEffects", proc { |move, user, target, ai, battle| target_side = target.pbOwnSide target_opposing_side = target.pbOpposingSide @@ -1228,7 +1230,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetEvasion1RemoveSideEffects !target.battler.pbCanLowerStatStage?(move.move.statDown[0], user.battler, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetEvasion1RemoveSideEffects", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion1RemoveSideEffects", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:EVASION] * 10 @@ -1250,9 +1252,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetEvasion1RemoveSideEffects" #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetEvasion1", - "LowerTargetEvasion2") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetEvasion2", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetEvasion1", + "LowerTargetEvasion2") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion2", proc { |score, move, user, target, ai, battle| if move.statusMove? score += target.stages[:EVASION] * 10 @@ -1266,15 +1268,15 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetEvasion2", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetEvasion2", - "LowerTargetEvasion3") -Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetEvasion2", - "LowerTargetEvasion3") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetEvasion2", + "LowerTargetEvasion3") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetEvasion2", + "LowerTargetEvasion3") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkDef1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAtkDef1", proc { |move, user, target, ai, battle| will_fail = true (move.move.statDown.length / 2).times do |i| @@ -1285,7 +1287,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkDef1", next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkDef1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkDef1", proc { |score, move, user, target, ai, battle| avg = target.stages[:ATTACK] * 10 avg += target.stages[:DEFENSE] * 10 @@ -1296,9 +1298,9 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkDef1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetAtkDef1", - "LowerTargetAtkSpAtk1") -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAtkDef1", + "LowerTargetAtkSpAtk1") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkSpAtk1", proc { |score, move, user, target, ai, battle| avg = target.stages[:ATTACK] * 10 avg += target.stages[:SPECIAL_ATTACK] * 10 @@ -1309,7 +1311,7 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerPoisonedTargetAtkSpAtkSpd1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerPoisonedTargetAtkSpAtkSpd1", proc { |move, user, target, ai, battle| next true if !target.battler.poisoned? next true if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler, move.move) && @@ -1317,7 +1319,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerPoisonedTargetAtkSpAtkSpd1", !target.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerPoisonedTargetAtkSpAtkSpd1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerPoisonedTargetAtkSpAtkSpd1", proc { |score, move, user, target, ai, battle| if target.opposes?(user) score += target.stages[:ATTACK] * 10 @@ -1332,8 +1334,12 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerPoisonedTargetAtkSpAtkSpd1", #=============================================================================== # TODO: Review score modifiers. +# TODO: This code should be for a single battler (each is checked in turn). +# target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseAlliesAtkDef1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseAlliesAtkDef1", proc { |move, user, target, ai, battle| will_fail = true battle.allSameSideBattlers(user.battler).each do |b| @@ -1346,7 +1352,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseAlliesAtkDef1", next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseAlliesAtkDef1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseAlliesAtkDef1", proc { |score, move, user, target, ai, battle| user.battler.allAllies.each do |b| if !battle.moldBreaker && b.hasActiveAbility?(:CONTRARY) @@ -1363,8 +1369,14 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseAlliesAtkDef1", #=============================================================================== # TODO: Review score modifiers. +# TODO: This code should be for a single battler (each is checked in turn). +# target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. +# TODO: Since this also affects the user, this will need a MoveEffectScore and a +# MoveFailureCheck. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaisePlusMinusUserAndAlliesAtkSpAtk1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaisePlusMinusUserAndAlliesAtkSpAtk1", proc { |move, user, target, ai, battle| will_fail = true battle.allSameSideBattlers(user.battler).each do |b| @@ -1377,7 +1389,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaisePlusMinusUserAndAlliesAtkSpAtk1 next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("RaisePlusMinusUserAndAlliesAtkSpAtk1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaisePlusMinusUserAndAlliesAtkSpAtk1", proc { |score, move, user, target, ai, battle| user.battler.allAllies.each do |b| next if b.statStageAtMax?(:ATTACK) && b.statStageAtMax?(:SPECIAL_ATTACK) @@ -1392,8 +1404,14 @@ Battle::AI::Handlers::MoveEffectScore.add("RaisePlusMinusUserAndAlliesAtkSpAtk1" #=============================================================================== # TODO: Review score modifiers. +# TODO: This code should be for a single battler (each is checked in turn). +# target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. +# TODO: Since this also affects the user, this will need a MoveEffectScore and a +# MoveFailureCheck. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaisePlusMinusUserAndAlliesAtkSpAtk1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaisePlusMinusUserAndAlliesAtkSpAtk1", proc { |move, user, target, ai, battle| will_fail = true battle.allSameSideBattlers(user.battler).each do |b| @@ -1406,7 +1424,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaisePlusMinusUserAndAlliesAtkSpAtk1 next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("RaisePlusMinusUserAndAlliesDefSpDef1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaisePlusMinusUserAndAlliesDefSpDef1", proc { |score, move, user, target, ai, battle| user.battler.allAllies.each do |b| next if b.statStageAtMax?(:DEFENSE) && b.statStageAtMax?(:SPECIAL_DEFENSE) @@ -1421,8 +1439,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RaisePlusMinusUserAndAlliesDefSpDef1" #=============================================================================== # TODO: Review score modifiers. +# TODO: This code should be for a single battler (each is checked in turn). +# target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseGroundedGrassBattlersAtkSpAtk1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseGroundedGrassBattlersAtkSpAtk1", proc { |move, user, target, ai, battle| will_fail = true battle.allBattlers.each do |b| @@ -1435,14 +1457,14 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseGroundedGrassBattlersAtkSpAtk1" next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseGroundedGrassBattlersAtkSpAtk1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseGroundedGrassBattlersAtkSpAtk1", proc { |score, move, user, target, ai, battle| battle.allBattlers.each do |b| if user.battler.opposes?(b) score -= 20 else - score -= user.stages[:ATTACK] * 10 - score -= user.stages[:SPECIAL_ATTACK] * 10 + score -= b.stages[:ATTACK] * 10 + score -= b.stages[:SPECIAL_ATTACK] * 10 end end next score @@ -1451,8 +1473,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseGroundedGrassBattlersAtkSpAtk1", #=============================================================================== # TODO: Review score modifiers. +# TODO: This code should be for a single battler (each is checked in turn). +# target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RaiseGrassBattlersDef1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseGrassBattlersDef1", proc { |move, user, target, ai, battle| will_fail = true battle.allBattlers.each do |b| @@ -1464,7 +1490,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseGrassBattlersDef1", next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseGrassBattlersDef1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseGrassBattlersDef1", proc { |score, move, user, target, ai, battle| battle.allBattlers.each do |b| if user.battler.opposes?(b) @@ -1479,14 +1505,17 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseGrassBattlersDef1", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAtkSpAtkStages", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAtkSpAtkStages", proc { |score, move, user, target, ai, battle| user_attack = user.stages[:ATTACK] user_spatk = user.stages[:SPECIAL_ATTACK] target_attack = target.stages[:ATTACK] target_spatk = target.stages[:SPECIAL_ATTACK] - next score - 40 if user_attack >= target_attack && user_spatk >= target_spatk + next Battle::AI::MOVE_USELESS_SCORE if user_attack >= target_attack && user_spatk >= target_spatk next score - 20 if user_attack + user_spatk <= target_attack + target_spatk score += (target_attack - user_attack) * 10 score += (target_spatk - user_spatk) * 10 @@ -1496,14 +1525,17 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAtkSpAtkStages", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapDefSpDefStages", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapDefSpDefStages", proc { |score, move, user, target, ai, battle| user_def = user.stages[:DEFENSE] user_spdef = user.stages[:SPECIAL_DEFENSE] target_def = target.stages[:DEFENSE] target_spdef = target.stages[:SPECIAL_DEFENSE] - next score - 40 if user_def >= target_def && user_spdef >= target_spdef + next Battle::AI::MOVE_USELESS_SCORE if user_def >= target_def && user_spdef >= target_spdef next score - 20 if user_def + user_spdef <= target_def + target_spdef score += (target_def - user_def) * 10 score += (target_spdef - user_spdef) * 10 @@ -1513,8 +1545,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapDefSpDefStages", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapStatStages", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapStatStages", proc { |score, move, user, target, ai, battle| user_stages = 0 target_stages = 0 @@ -1524,7 +1559,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapStatStages", target_stages += target.stages[s.id] target_stage_better = true if target.stages[s.id] > user.stages[s.id] end - next score - 40 if !target_stage_better + next Battle::AI::MOVE_USELESS_SCORE if !target_stage_better score += (target_stages - user_stages) * 10 next score } @@ -1532,8 +1567,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapStatStages", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserCopyTargetStatStages", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserCopyTargetStatStages", proc { |score, move, user, target, ai, battle| equal = true GameData::Stat.each_battle do |s| @@ -1549,8 +1587,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserCopyTargetStatStages", #=============================================================================== # TODO: Review score modifiers. # TODO: Account for stat theft before damage calculation. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserStealTargetPositiveStatStages", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserStealTargetPositiveStatStages", proc { |score, move, user, target, ai, battle| numStages = 0 GameData::Stat.each_battle do |s| @@ -1563,13 +1604,16 @@ Battle::AI::Handlers::MoveEffectScore.add("UserStealTargetPositiveStatStages", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("InvertTargetStatStages", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("InvertTargetStatStages", proc { |move, user, target, ai, battle| next true if !target.battler.hasAlteredStatStages? } ) -Battle::AI::Handlers::MoveEffectScore.add("InvertTargetStatStages", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("InvertTargetStatStages", proc { |score, move, user, target, ai, battle| next 0 if target.effects[PBEffects::Substitute] > 0 numpos = 0 @@ -1584,8 +1628,11 @@ Battle::AI::Handlers::MoveEffectScore.add("InvertTargetStatStages", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("ResetTargetStatStages", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ResetTargetStatStages", proc { |score, move, user, target, ai, battle| next 0 if target.effects[PBEffects::Substitute] > 0 avg = 0 @@ -1604,12 +1651,12 @@ Battle::AI::Handlers::MoveEffectScore.add("ResetTargetStatStages", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("ResetAllBattlersStatStages", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.allBattlers.none? { |b| b.hasAlteredStatStages? } } ) Battle::AI::Handlers::MoveEffectScore.add("ResetAllBattlersStatStages", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| stages = 0 battle.allBattlers.each do |b| totalStages = 0 @@ -1628,7 +1675,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ResetAllBattlersStatStages", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToStatStageLowering", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOwnSide.effects[PBEffects::Mist] > 0 } ) @@ -1637,10 +1684,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToStatStageLowe # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("UserSwapBaseAtkDef", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| aatk = user.rough_stat(:ATTACK) adef = user.rough_stat(:DEFENSE) - next score - 40 if aatk == adef || user.effects[PBEffects::PowerTrick] # No flip-flopping + next Battle::AI::MOVE_USELESS_SCORE if aatk == adef || user.effects[PBEffects::PowerTrick] # No flip-flopping if adef > aatk # Prefer a higher Attack score += 20 else @@ -1652,8 +1699,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserSwapBaseAtkDef", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapBaseSpeed", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapBaseSpeed", proc { |score, move, user, target, ai, battle| if user.speed > target.speed score += 25 @@ -1666,14 +1716,17 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapBaseSpeed", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseAtkSpAtk", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseAtkSpAtk", proc { |score, move, user, target, ai, battle| user_atk = user.battler.attack user_spatk = user.battler.spatk target_atk = target.battler.attack target_spatk = target.battler.spatk - next score - 40 if user_atk > target_atk && user_spatk > target_spatk + next Battle::AI::MOVE_USELESS_SCORE if user_atk > target_atk && user_spatk > target_spatk if user_atk + user_spatk < target_atk + target_spatk score += 20 else @@ -1685,14 +1738,17 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseAtkSpAtk", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseDefSpDef", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDefSpDef", proc { |score, move, user, target, ai, battle| user_def = user.rough_stat(:DEFENSE) user_spdef = user.rough_stat(:SPECIAL_DEFENSE) target_def = target.rough_stat(:DEFENSE) target_spdef = target.rough_stat(:SPECIAL_DEFENSE) - next score - 40 if user_def > target_def && user_spdef > target_spdef + next Battle::AI::MOVE_USELESS_SCORE if user_def > target_def && user_spdef > target_spdef if user_def + user_spdef < target_def + target_spdef score += 20 else @@ -1705,7 +1761,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseDefSpDef", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageHP", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageHP", proc { |score, move, user, target, ai, battle| if user.hp >= (user.hp + target.hp) / 2 score -= 25 @@ -1720,7 +1776,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageHP", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideDoubleSpeed", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOwnSide.effects[PBEffects::Tailwind] > 0 } ) diff --git a/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb b/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb index 101a9da20..36eef2bfd 100644 --- a/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb +++ b/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb @@ -1,12 +1,12 @@ #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SleepTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTarget", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanSleep?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("SleepTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SleepTarget", proc { |score, move, user, target, ai, battle| next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep anyway # No score modifier if the sleep will be removed immediately @@ -58,44 +58,48 @@ Battle::AI::Handlers::MoveEffectScore.add("SleepTarget", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetIfUserDarkrai", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.isSpecies?(:DARKRAI) && user.effects[PBEffects::TransformSpecies] != :DARKRAI + } +) +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTargetIfUserDarkrai", + proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanSleep?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget", - "SleepTargetIfUserDarkrai") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget", + "SleepTargetIfUserDarkrai") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget", - "SleepTargetChangeUserMeloettaForm") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget", + "SleepTargetChangeUserMeloettaForm") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetNextTurn", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTargetNextTurn", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::Yawn] > 0 next true if !target.battler.pbCanSleep?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget", - "SleepTargetNextTurn") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget", + "SleepTargetNextTurn") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("PoisonTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTarget", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanPoison?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("PoisonTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget", proc { |score, move, user, target, ai, battle| next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep - next score - 40 if move.statusMove? && target.has_active_ability?(:POISONHEAL) + next Battle::AI::MOVE_USELESS_SCORE if move.statusMove? && target.has_active_ability?(:POISONHEAL) # No score modifier if the poisoning will be removed immediately next score if target.has_active_item?([:PECHABERRY, :LUMBERRY]) next score if target.faster_than?(user) && @@ -148,17 +152,17 @@ Battle::AI::Handlers::MoveEffectScore.add("PoisonTarget", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("PoisonTargetLowerTargetSpeed1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTargetLowerTargetSpeed1", proc { |move, user, target, ai, battle| next true if !target.battler.pbCanPoison?(user.battler, false, move.move) && !target.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("PoisonTargetLowerTargetSpeed1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTargetLowerTargetSpeed1", proc { |score, move, user, target, ai, battle| - score = Battle::AI::Handlers.apply_move_effect_score("PoisonTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget", score, move, user, target, ai, battle) - score = Battle::AI::Handlers.apply_move_effect_score("LowerTargetSpeed1", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("LowerTargetSpeed1", score, move, user, target, ai, battle) next score } @@ -167,20 +171,20 @@ Battle::AI::Handlers::MoveEffectScore.add("PoisonTargetLowerTargetSpeed1", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("PoisonTarget", - "BadPoisonTarget") -Battle::AI::Handlers::MoveEffectScore.copy("PoisonTarget", - "BadPoisonTarget") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("PoisonTarget", + "BadPoisonTarget") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("PoisonTarget", + "BadPoisonTarget") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("ParalyzeTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTarget", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("ParalyzeTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeTarget", proc { |score, move, user, target, ai, battle| next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep # No score modifier if the paralysis will be removed immediately @@ -239,30 +243,30 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("ParalyzeTargetIfNotTypeImmune", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTargetIfNotTypeImmune", proc { |move, user, target, ai, battle| eff = target.effectiveness_of_type_against_battler(move.rough_type, user) next true if Effectiveness.ineffective?(eff) next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget", - "ParalyzeTargetIfNotTypeImmune") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ParalyzeTarget", + "ParalyzeTargetIfNotTypeImmune") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget", - "ParalyzeTargetAlwaysHitsInRainHitsTargetInSky") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ParalyzeTarget", + "ParalyzeTargetAlwaysHitsInRainHitsTargetInSky") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("ParalyzeFlinchTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeFlinchTarget", proc { |score, move, user, target, ai, battle| - score = Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget", score, move, user, target, ai, battle) - score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget", score, move, user, target, ai, battle) next score } @@ -271,12 +275,12 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeFlinchTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("BurnTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("BurnTarget", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanBurn?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("BurnTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget", proc { |score, move, user, target, ai, battle| next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep # No score modifier if the burn will be removed immediately @@ -337,11 +341,11 @@ Battle::AI::Handlers::MoveEffectScore.add("BurnTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("BurnFlinchTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnFlinchTarget", proc { |score, move, user, target, ai, battle| - score = Battle::AI::Handlers.apply_move_effect_score("BurnTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget", score, move, user, target, ai, battle) - score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget", score, move, user, target, ai, battle) next score } @@ -350,12 +354,12 @@ Battle::AI::Handlers::MoveEffectScore.add("BurnFlinchTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("FreezeTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FreezeTarget", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanFreeze?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("FreezeTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeTarget", proc { |score, move, user, target, ai, battle| next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep # No score modifier if the freeze will be removed immediately @@ -401,23 +405,23 @@ Battle::AI::Handlers::MoveEffectScore.add("FreezeTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.copy("FreezeTarget", - "FreezeTargetSuperEffectiveAgainstWater") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FreezeTarget", + "FreezeTargetSuperEffectiveAgainstWater") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.copy("FreezeTarget", - "FreezeTargetAlwaysHitsInHail") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FreezeTarget", + "FreezeTargetAlwaysHitsInHail") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("FreezeFlinchTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeFlinchTarget", proc { |score, move, user, target, ai, battle| - score = Battle::AI::Handlers.apply_move_effect_score("FreezeTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget", score, move, user, target, ai, battle) - score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget", score, move, user, target, ai, battle) next score } @@ -426,7 +430,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FreezeFlinchTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeBurnOrFreezeTarget", proc { |score, move, user, target, ai, battle| next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep # No score modifier if the status problem will be removed immediately @@ -435,12 +439,12 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget", target.has_active_ability?(:HYDRATION) && [:Rain, :HeavyRain].include?(target.battler.effectiveWeather) # Scores for the possible effects - score += (Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", - 100, move, user, target, ai, battle) - 100) / 3 - score += (Battle::AI::Handlers.apply_move_effect_score("BurnTarget", - 100, move, user, target, ai, battle) - 100) / 3 - score += (Battle::AI::Handlers.apply_move_effect_score("FreezeTarget", - 100, move, user, target, ai, battle) - 100) / 3 + score += (Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget", + Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3 + score += (Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget", + Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3 + score += (Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget", + Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3 next score } ) @@ -449,29 +453,33 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("GiveUserStatusToTarget", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.status == :NONE + } +) +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("GiveUserStatusToTarget", + proc { |move, user, target, ai, battle| next true if !target.battler.pbCanInflictStatus?(user.status, user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.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 case user.status when :SLEEP - next Battle::AI::Handlers.apply_move_effect_score("SleepTarget", + next Battle::AI::Handlers.apply_move_effect_against_target_score("SleepTarget", score, move, user, target, ai, battle) when :PARALYSIS - next Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", + next Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget", score, move, user, target, ai, battle) when :POISON - next Battle::AI::Handlers.apply_move_effect_score("PoisonTarget", + next Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget", score, move, user, target, ai, battle) when :BURN - next Battle::AI::Handlers.apply_move_effect_score("BurnTarget", + next Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget", score, move, user, target, ai, battle) when :FROZEN - next Battle::AI::Handlers.apply_move_effect_score("FreezeTarget", + next Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget", score, move, user, target, ai, battle) end next score @@ -482,12 +490,12 @@ Battle::AI::Handlers::MoveEffectScore.add("GiveUserStatusToTarget", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("CureUserBurnPoisonParalysis", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if ![:BURN, :POISON, :PARALYSIS].include?(user.status) } ) Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + 15 } ) @@ -496,16 +504,13 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("CureUserPartyStatus", - proc { |move, user, target, ai, battle| - has_effect = battle.allSameSideBattlers(user.battler).any? { |b| b.status != :NONE } - if !has_effect - has_effect = battle.pbParty(user.index).any? { |pkmn| pkmn&.able? && pkmn.status != :NONE } - end - next !has_effect + proc { |move, user, ai, battle| + next battle.pbParty(user.index).none? { |pkmn| pkmn&.able? && pkmn.status != :NONE } } ) Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus", - proc { |score, move, user, target, ai, battle| + 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 end @@ -515,8 +520,11 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus", #=============================================================================== # TODO: Review score modifiers. +# TODO: target should probably be treated as an enemy when deciding the score, +# since the score will be inverted elsewhere due to the target being an +# ally. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("CureTargetBurn", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetBurn", proc { |score, move, user, target, ai, battle| if target.status == :BURN if target.opposes?(user) @@ -533,12 +541,12 @@ Battle::AI::Handlers::MoveEffectScore.add("CureTargetBurn", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToInflictedStatus", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOwnSide.effects[PBEffects::Safeguard] > 0 } ) Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatus", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if user.status != :NONE score -= 20 else @@ -551,7 +559,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatu #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("FlinchTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FlinchTarget", proc { |score, move, user, target, ai, battle| next score if target.faster_than?(user) || target.effects[PBEffects::Substitute] > 0 next score if target.has_active_ability?(:INNERFOCUS) && !battle.moldBreaker @@ -576,23 +584,23 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTarget", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfUserNotAsleep", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.asleep? } ) -Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget", - "FlinchTargetFailsIfUserNotAsleep") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget", + "FlinchTargetFailsIfUserNotAsleep") #=============================================================================== # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfNotUserFirstTurn", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.turnCount > 0 } ) -Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget", - "FlinchTargetFailsIfNotUserFirstTurn") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget", + "FlinchTargetFailsIfNotUserFirstTurn") #=============================================================================== # @@ -602,18 +610,18 @@ Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky", next move.move.pbBaseDamage(power, user.battler, target.battler) } ) -Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget", - "FlinchTargetDoublePowerIfTargetInSky") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget", + "FlinchTargetDoublePowerIfTargetInSky") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("ConfuseTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ConfuseTarget", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanConfuse?(user.battler, false, move.move) } ) -Battle::AI::Handlers::MoveEffectScore.add("ConfuseTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ConfuseTarget", proc { |score, move, user, target, ai, battle| # No score modifier if the status problem will be removed immediately next score if target.has_active_item?(:PERSIMBERRY) @@ -641,18 +649,18 @@ Battle::AI::Handlers::MoveEffectScore.add("ConfuseTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.copy("ConfuseTarget", - "ConfuseTargetAlwaysHitsInRainHitsTargetInSky") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ConfuseTarget", + "ConfuseTargetAlwaysHitsInRainHitsTargetInSky") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("AttractTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AttractTarget", proc { |move, user, target, ai, battle| next true if move.statusMove? && !target.battler.pbCanAttract?(user.battler, false) } ) -Battle::AI::Handlers::MoveEffectScore.add("AttractTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AttractTarget", proc { |score, move, user, target, ai, battle| if target.battler.pbCanAttract?(user.battler, false) case move.additional_effect_usability(user, target) @@ -680,7 +688,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttractTarget", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.canChangeType? new_type = nil terr_types = Battle::Move::SetUserTypesBasedOnEnvironment::TERRAIN_TYPES @@ -699,7 +707,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToResistLastAttack", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserTypesToResistLastAttack", proc { |move, user, target, ai, battle| next true if !user.battler.canChangeType? next true if !target.battler.lastMoveUsed || !target.battler.lastMoveUsedType || @@ -718,7 +726,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToResistLastAttack", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToTargetTypes", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserTypesToTargetTypes", proc { |move, user, target, ai, battle| next true if !user.battler.canChangeType? next true if target.battler.pbTypes(true).empty? @@ -731,7 +739,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToTargetTypes", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToUserMoveType", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.canChangeType? has_possible_type = false user.battler.eachMoveWithIndex do |m, i| @@ -748,7 +756,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToUserMoveType", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SetTargetTypesToPsychic", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetTypesToPsychic", proc { |move, user, target, ai, battle| next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false) } @@ -757,26 +765,26 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetTypesToPsychic", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("SetTargetTypesToPsychic", - "SetTargetTypesToWater") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("SetTargetTypesToPsychic", + "SetTargetTypesToWater") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("SetTargetTypesToWater", - "AddGhostTypeToTarget") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("SetTargetTypesToWater", + "AddGhostTypeToTarget") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("AddGhostTypeToTarget", - "AddGrassTypeToTarget") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("AddGhostTypeToTarget", + "AddGrassTypeToTarget") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.has_type?(:FIRE) } ) @@ -784,7 +792,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToSimple", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimple", proc { |move, user, target, ai, battle| next true if !GameData::Ability.exists?(:SIMPLE) next true if target.battler.unstoppableAbility? || @@ -795,7 +803,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToSimple", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToInsomnia", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToInsomnia", proc { |move, user, target, ai, battle| next true if !GameData::Ability.exists?(:INSOMNIA) next true if target.battler.unstoppableAbility? || @@ -806,7 +814,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToInsomnia", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SetUserAbilityToTargetAbility", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserAbilityToTargetAbility", proc { |move, user, target, ai, battle| next true if user.battler.unstoppableAbility? next true if !target.ability || user.ability_id == target.ability_id @@ -814,7 +822,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserAbilityToTargetAbility", [:POWEROFALCHEMY, :RECEIVER, :TRACE, :WONDERGUARD].include?(target.ability_id) } ) -Battle::AI::Handlers::MoveEffectScore.add("SetUserAbilityToTargetAbility", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserAbilityToTargetAbility", proc { |score, move, user, target, ai, battle| score -= 40 # don't prefer this move if ai.trainer.medium_skill? && user.opposes?(target) @@ -827,7 +835,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SetUserAbilityToTargetAbility", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToUserAbility", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserAbility", proc { |move, user, target, ai, battle| next true if !user.ability || user.ability_id == target.ability_id next true if user.battler.ungainableAbility? || @@ -835,7 +843,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToUserAbility", next true if target.battler.unstoppableAbility? || target.ability_id == :TRUANT } ) -Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToUserAbility", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAbility", proc { |score, move, user, target, ai, battle| score -= 40 # don't prefer this move if ai.trainer.medium_skill? && user.opposes?(target) @@ -848,7 +856,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToUserAbility", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapAbilities", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapAbilities", proc { |move, user, target, ai, battle| next true if !user.ability || !target.ability next true if Settings::MECHANICS_GENERATION <= 5 && user.ability_id == target.ability_id @@ -858,7 +866,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapAbilities", target.ability_id == :WONDERGUARD } ) -Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAbilities", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAbilities", proc { |score, move, user, target, ai, battle| score -= 40 # don't prefer this move if ai.trainer.high_skill? && user.opposes?(target) @@ -871,7 +879,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAbilities", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("NegateTargetAbility", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("NegateTargetAbility", proc { |move, user, target, ai, battle| next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false) } @@ -880,7 +888,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("NegateTargetAbility", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("NegateTargetAbilityIfTargetActed", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTargetActed", proc { |score, move, user, target, ai, battle| score += 15 if target.faster_than?(user) next score @@ -896,7 +904,7 @@ Battle::AI::Handlers::MoveEffectScore.add("NegateTargetAbilityIfTargetActed", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartUserAirborne", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::Ingrain] || user.effects[PBEffects::SmackDown] || user.effects[PBEffects::MagnetRise] > 0 @@ -906,7 +914,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartUserAirborne", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("StartTargetAirborneAndAlwaysHitByMoves", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetAirborneAndAlwaysHitByMoves", proc { |move, user, target, ai, battle| next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false) } @@ -920,7 +928,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartTargetAirborneAndAlwaysHitByMov #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("HitsTargetInSkyGroundsTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitsTargetInSkyGroundsTarget", proc { |score, move, user, target, ai, battle| if ai.trainer.medium_skill? score += 20 if target.effects[PBEffects::MagnetRise] > 0 || @@ -940,12 +948,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HitsTargetInSkyGroundsTarget", # TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartGravity", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.field.effects[PBEffects::Gravity] > 0 } ) Battle::AI::Handlers::MoveEffectScore.add("StartGravity", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if ai.trainer.medium_skill? score -= 15 if user.effects[PBEffects::SkyDrop] >= 0 || user.effects[PBEffects::MagnetRise] > 0 || @@ -953,15 +961,15 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity", user.has_type?(:FLYING) || user.has_active_ability?(:LEVITATE) || user.has_active_item?(:AIRBALLOON) - score += 15 if target.effects[PBEffects::SkyDrop] >= 0 || - target.effects[PBEffects::MagnetRise] > 0 || - target.effects[PBEffects::Telekinesis] > 0 || - target.has_type?(:FLYING) || - target.has_active_ability?(:LEVITATE) || - target.has_active_item?(:AIRBALLOON) - score += 5 if target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky", - "TwoTurnAttackInvulnerableInSkyParalyzeTarget", - "TwoTurnAttackInvulnerableInSkyTargetCannotAct") +# score += 15 if target.effects[PBEffects::SkyDrop] >= 0 || +# target.effects[PBEffects::MagnetRise] > 0 || +# target.effects[PBEffects::Telekinesis] > 0 || +# target.has_type?(:FLYING) || +# target.has_active_ability?(:LEVITATE) || +# target.has_active_item?(:AIRBALLOON) +# score += 5 if target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky", +# "TwoTurnAttackInvulnerableInSkyParalyzeTarget", +# "TwoTurnAttackInvulnerableInSkyTargetCannotAct") end next score } @@ -970,15 +978,15 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("TransformUserIntoTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TransformUserIntoTarget", proc { |move, user, target, ai, battle| next true if user.effects[PBEffects::Transform] next true if target.effects[PBEffects::Transform] || target.effects[PBEffects::Illusion] } ) -Battle::AI::Handlers::MoveEffectScore.add("TransformUserIntoTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TransformUserIntoTarget", proc { |score, move, user, target, ai, battle| - next score - 20 + next score - 10 } ) diff --git a/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb b/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb index 7c04b571c..cc386da0c 100644 --- a/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb +++ b/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb @@ -46,7 +46,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevelRandom", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetHPToUserHP", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetHPToUserHP", proc { |move, user, target, ai, battle| next true if user.hp >= target.hp } @@ -60,7 +60,7 @@ Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("OHKO", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKO", proc { |move, user, target, ai, battle| next true if target.level > user.level next true if !battle.moldBreaker && target.has_active_ability?(:STURDY) @@ -75,7 +75,7 @@ Battle::AI::Handlers::MoveBasePower.add("OHKO", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("OHKOIce", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKOIce", proc { |move, user, target, ai, battle| next true if target.level > user.level next true if !battle.moldBreaker && target.has_active_ability?(:STURDY) @@ -88,15 +88,15 @@ Battle::AI::Handlers::MoveBasePower.copy("OHKO", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("OHKO", - "OHKOHitsUndergroundTarget") +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("OHKO", + "OHKOHitsUndergroundTarget") Battle::AI::Handlers::MoveBasePower.copy("OHKO", "OHKOHitsUndergroundTarget") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("DamageTargetAlly", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DamageTargetAlly", proc { |score, move, user, target, ai, battle| target.battler.allAllies.each do |b| next if !b.near?(target.battler) || !b.battler.takesIndirectDamage? @@ -239,7 +239,7 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf", #=============================================================================== Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf", "DoublePowerIfTargetAsleepCureTarget") -Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetAsleepCureTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetAsleepCureTarget", proc { |score, move, user, target, ai, battle| next score - 20 if target.status == :SLEEP && # Will cure status target.statusCount > 1 @@ -260,7 +260,7 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned", #=============================================================================== Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned", "DoublePowerIfTargetParalyzedCureTarget") -Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetParalyzedCureTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetParalyzedCureTarget", proc { |score, move, user, target, ai, battle| next score - 20 if target.status == :PARALYSIS # Will cure status } @@ -330,15 +330,16 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetInSky", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn", - proc { |score, move, user, target, ai, battle| - next score + 15 if target.faster_than?(user) + proc { |score, move, user, ai, battle| + # TODO: Remove target from this; consider the speeds of all foes instead. +# next score + 15 if target.faster_than?(user) } ) #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetLostHPThisTurn", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostHPThisTurn", proc { |score, move, user, target, ai, battle| next score + 15 if battle.pbOpposingBattlerCount(user.battler) > 1 } @@ -352,7 +353,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetLostHPThisTurn", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetActed", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetActed", proc { |score, move, user, target, ai, battle| next score + 15 if target.faster_than?(user) } @@ -361,7 +362,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetActed", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetNotActed", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotActed", proc { |score, move, user, target, ai, battle| next score + 15 if user.faster_than?(target) } @@ -376,7 +377,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetNotActed", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if user.effects[PBEffects::LaserFocus] > 0 score -= 90 else @@ -390,7 +391,7 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartPreventCriticalHitsAgainstUserSide", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOwnSide.effects[PBEffects::LuckyChant] > 0 } ) @@ -398,7 +399,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartPreventCriticalHitsAgainstUserS #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("CannotMakeTargetFaint", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CannotMakeTargetFaint", proc { |move, user, target, ai, battle| next true if target.hp == 1 } @@ -409,11 +410,11 @@ Battle::AI::Handlers::MoveFailureCheck.add("CannotMakeTargetFaint", # TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 10 if user.hp > user.totalhp / 2 if ai.trainer.medium_skill? score -= 20 if user.effects[PBEffects::ProtectRate] > 1 - score -= 20 if target.effects[PBEffects::HyperBeam] > 0 +# score -= 20 if target.effects[PBEffects::HyperBeam] > 0 else score -= user.effects[PBEffects::ProtectRate] * 10 end @@ -425,7 +426,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| if Settings::MECHANICS_GENERATION >= 6 next true if battle.field.effects[PBEffects::MudSportField] > 0 else @@ -438,7 +439,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| if Settings::MECHANICS_GENERATION >= 6 next true if battle.field.effects[PBEffects::WaterSportField] > 0 else @@ -451,7 +452,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenPhysicalDamageAgainstUserSide", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOwnSide.effects[PBEffects::Reflect] > 0 } ) @@ -460,7 +461,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenPhysicalDamageAgainstUser # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenSpecialDamageAgainstUserSide", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOwnSide.effects[PBEffects::LightScreen] > 0 } ) @@ -469,13 +470,13 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenSpecialDamageAgainstUserS # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenDamageAgainstUserSideIfHail", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 next true if user.battler.effectiveWeather != :Hail } ) Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHail", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + 40 } ) @@ -484,7 +485,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHai # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("RemoveScreens", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score += 10 if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 score += 10 if user.pbOpposingSide.effects[PBEffects::Reflect] > 0 score += 10 if user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 @@ -497,16 +498,16 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveScreens", # TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("ProtectUser", - proc { |score, move, user, target, ai, battle| - if user.effects[PBEffects::ProtectRate] > 1 || - target.effects[PBEffects::HyperBeam] > 0 + proc { |score, move, user, ai, battle| + if user.effects[PBEffects::ProtectRate] > 1 # || +# target.effects[PBEffects::HyperBeam] > 0 score -= 50 else if ai.trainer.medium_skill? score -= user.effects[PBEffects::ProtectRate] * 40 end score += 50 if user.turnCount == 0 - score += 30 if target.effects[PBEffects::TwoTurnAttack] +# score += 30 if target.effects[PBEffects::TwoTurnAttack] end next score } @@ -517,14 +518,14 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser", # TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker", - proc { |score, move, user, target, ai, battle| - next score - 40 if user.effects[PBEffects::ProtectRate] > 1 || - target.effects[PBEffects::HyperBeam] > 0 + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if user.effects[PBEffects::ProtectRate] > 1 # || +# target.effects[PBEffects::HyperBeam] > 0 if ai.trainer.medium_skill? score -= user.effects[PBEffects::ProtectRate] * 40 end score += 10 if user.turnCount == 0 - score += 15 if target.effects[PBEffects::TwoTurnAttack] +# score += 15 if target.effects[PBEffects::TwoTurnAttack] score += 15 # Because of possible poisoning next score } @@ -535,16 +536,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker", # TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShield", - proc { |score, move, user, target, ai, battle| - if user.effects[PBEffects::ProtectRate] > 1 || - target.effects[PBEffects::HyperBeam] > 0 + proc { |score, move, user, ai, battle| + if user.effects[PBEffects::ProtectRate] > 1 # || +# target.effects[PBEffects::HyperBeam] > 0 score -= 50 else if ai.trainer.medium_skill? score -= user.effects[PBEffects::ProtectRate] * 40 end score += 50 if user.turnCount == 0 - score += 30 if target.effects[PBEffects::TwoTurnAttack] +# score += 30 if target.effects[PBEffects::TwoTurnAttack] end next score } @@ -555,16 +556,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie # TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct", - proc { |score, move, user, target, ai, battle| - if user.effects[PBEffects::ProtectRate] > 1 || - target.effects[PBEffects::HyperBeam] > 0 + proc { |score, move, user, ai, battle| + if user.effects[PBEffects::ProtectRate] > 1 # || +# target.effects[PBEffects::HyperBeam] > 0 score -= 50 else if ai.trainer.medium_skill? score -= user.effects[PBEffects::ProtectRate] * 40 end score += 50 if user.turnCount == 0 - score += 30 if target.effects[PBEffects::TwoTurnAttack] +# score += 30 if target.effects[PBEffects::TwoTurnAttack] end next score } @@ -575,16 +576,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct" # TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShield", - proc { |score, move, user, target, ai, battle| - if user.effects[PBEffects::ProtectRate] > 1 || - target.effects[PBEffects::HyperBeam] > 0 + proc { |score, move, user, ai, battle| + if user.effects[PBEffects::ProtectRate] > 1 # || +# target.effects[PBEffects::HyperBeam] > 0 score -= 90 else if ai.trainer.medium_skill? score -= user.effects[PBEffects::ProtectRate] * 40 end score += 50 if user.turnCount == 0 - score += 30 if target.effects[PBEffects::TwoTurnAttack] +# score += 30 if target.effects[PBEffects::TwoTurnAttack] end next score } @@ -594,13 +595,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.turnCount > 0 } ) Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn", - proc { |score, move, user, target, ai, battle| - next score + 30 + proc { |score, move, user, ai, battle| + next score + 25 # Use it or lose it } ) @@ -608,7 +609,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromStatusMoves", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.pbOwnSide.effects[PBEffects::CraftyShield] } ) @@ -639,11 +640,11 @@ Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromStatusMoves", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.isSpecies?(:HOOPA) || user.battler.form != 1 } ) -Battle::AI::Handlers::MoveEffectScore.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1", proc { |score, move, user, target, ai, battle| next score + 20 if target.stages[:DEFENSE] > 0 } @@ -652,14 +653,14 @@ Battle::AI::Handlers::MoveEffectScore.add("HoopaRemoveProtectionsBypassSubstitut #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("RecoilQuarterOfDamageDealt", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilQuarterOfDamageDealt", proc { |score, move, user, target, ai, battle| next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD) dmg = move.rough_damage / 4 if dmg >= user.hp reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) - next score - 40 if reserves <= foes + next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes end score -= 10 * [dmg, user.hp].min / user.hp next score @@ -669,7 +670,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilQuarterOfDamageDealt", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealtParalyzeTarget", proc { |score, move, user, target, ai, battle| # Score for being a recoil move if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD) @@ -677,12 +678,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarge if dmg >= user.hp reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) - next score - 40 if reserves <= foes + next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes end score -= 10 * [dmg, user.hp].min / user.hp end # Score for paralysing - score = Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget", score, move, user, target, ai, battle) next score } @@ -691,7 +692,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarge #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealtBurnTarget", proc { |score, move, user, target, ai, battle| # Score for being a recoil move if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD) @@ -699,12 +700,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget", if dmg >= user.hp reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) - next score - 40 if reserves <= foes + next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes end score -= 10 * [dmg, user.hp].min / user.hp end # Score for burning - score = Battle::AI::Handlers.apply_move_effect_score("BurnTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget", score, move, user, target, ai, battle) next score } @@ -713,14 +714,14 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("RecoilHalfOfDamageDealt", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilHalfOfDamageDealt", proc { |score, move, user, target, ai, battle| next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD) dmg = move.rough_damage / 2 if dmg >= user.hp reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) - next score - 40 if reserves <= foes + next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes end score -= 10 * [dmg, user.hp].min / user.hp next score @@ -745,7 +746,7 @@ Battle::AI::Handlers::MoveBasePower.add("EffectivenessIncludesFlyingType", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CategoryDependsOnHigherDamagePoisonTarget", proc { |score, move, user, target, ai, battle| next score + 5 if target.battler.pbCanPoison?(user.battler, false) } @@ -775,14 +776,14 @@ Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTa # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("EnsureNextMoveAlwaysHits", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::LockOn] > 0 } ) -Battle::AI::Handlers::MoveEffectScore.add("EnsureNextMoveAlwaysHits", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("EnsureNextMoveAlwaysHits", proc { |score, move, user, target, ai, battle| - next score - 40 if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD) - next score - 40 if target.effects[PBEffects::Telekinesis] > 0 + next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD) + next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::Telekinesis] > 0 # Prefer if the user knows moves with low accuracy user.check_for_move do |m| next if target.effects[PBEffects::Minimize] && m.tramplesMinimize? && Settings::MECHANICS_GENERATION >= 6 @@ -803,9 +804,9 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextMoveAlwaysHits", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndGhostImmunity", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartNegateTargetEvasionStatStageAndGhostImmunity", proc { |score, move, user, target, ai, battle| - next score - 40 if target.effects[PBEffects::Foresight] || user.has_active_ability?(:SCRAPPY) + next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::Foresight] || user.has_active_ability?(:SCRAPPY) # Check if the user knows any moves that would benefit from negating the # target's Ghost type immunity if target.has_type?(:GHOST) @@ -823,9 +824,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndG #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndDarkImmunity", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartNegateTargetEvasionStatStageAndDarkImmunity", proc { |score, move, user, target, ai, battle| - next score - 40 if target.effects[PBEffects::MiracleEye] + next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::MiracleEye] # Check if the user knows any moves that would benefit from negating the # target's Dark type immunity if target.has_type?(:DARK) @@ -863,7 +864,7 @@ Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("TypeAndPowerDependOnUserBerry", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| item = user.item next true if !item || !item.is_berry? || !user.item_active? next true if item.flags.none? { |f| f[/^NaturalGift_/i] } @@ -895,7 +896,7 @@ Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnUserBerry", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("TypeDependsOnUserMorpekoFormRaiseUserSpeed1", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.isSpecies?(:MORPEKO) && user.effects[PBEffects::TransformSpecies] != :MORPEKO } ) @@ -920,15 +921,15 @@ Battle::AI::Handlers::MoveBasePower.copy("TypeAndPowerDependOnWeather", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("TargetMovesBecomeElectric", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetMovesBecomeElectric", proc { |score, move, user, target, ai, battle| - next 0 if user.faster_than?(target) + next Battle::AI::MOVE_USELESS_SCORE if user.faster_than?(target) } ) #=============================================================================== # TODO: Review score modifiers. -# TODO: This code can be called with or without a target. Make sure it doesn't -# assume that there is a target. +# TODO: This code can be called with a single target and with no targets. Make +# sure it doesn't assume that there is a target. #=============================================================================== # NormalMovesBecomeElectric diff --git a/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb b/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb index 5f1864ec6..98e58c3f5 100644 --- a/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb +++ b/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb @@ -6,7 +6,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes", next power * move.move.pbNumHits(user.battler, [target.battler]) } ) -Battle::AI::Handlers::MoveEffectScore.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 if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) @@ -24,13 +24,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimes", #=============================================================================== Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", "HitTwoTimesPoisonTarget") -Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesPoisonTarget", proc { |score, move, user, target, ai, battle| # Score for hitting multiple times - score = Battle::AI::Handlers.apply_move_effect_score("HitTwoTimes", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("HitTwoTimes", score, move, user, target, ai, battle) # Score for poisoning - score = Battle::AI::Handlers.apply_move_effect_score("PoisonTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget", score, move, user, target, ai, battle) next score } @@ -41,13 +41,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget", #=============================================================================== Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", "HitTwoTimesFlinchTarget") -Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesFlinchTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesFlinchTarget", proc { |score, move, user, target, ai, battle| # Score for hitting multiple times - score = Battle::AI::Handlers.apply_move_effect_score("HitTwoTimes", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("HitTwoTimes", score, move, user, target, ai, battle) # Score for flinching - score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget", score, move, user, target, ai, battle) next score } @@ -70,7 +70,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit", next power * 6 # Hits do x1, x2, x3 ret in turn, for x6 in total } ) -Battle::AI::Handlers::MoveEffectScore.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 if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) @@ -87,8 +87,8 @@ Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesPowersUpWithEachHit", #=============================================================================== Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", "HitThreeTimesAlwaysCriticalHit") -Battle::AI::Handlers::MoveEffectScore.copy("HitTwoTimes", - "HitThreeTimesAlwaysCriticalHit") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HitTwoTimes", + "HitThreeTimesAlwaysCriticalHit") #=============================================================================== # @@ -99,7 +99,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes", next power * 31 / 10 # Average damage dealt } ) -Battle::AI::Handlers::MoveEffectScore.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 if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) @@ -124,18 +124,18 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja" next power * 31 / 10 # Average damage dealt } ) -Battle::AI::Handlers::MoveEffectScore.copy("HitTwoToFiveTimes", - "HitTwoToFiveTimesOrThreeForAshGreninja") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HitTwoToFiveTimes", + "HitTwoToFiveTimesOrThreeForAshGreninja") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveBasePower.copy("HitTwoToFiveTimes", "HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1") -Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1", proc { |score, move, user, target, ai, battle| # Score for being a multi-hit attack - score = Battle::AI::Handlers.apply_move_effect_score("HitTwoToFiveTimes", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("HitTwoToFiveTimes", score, move, user, target, ai, battle) # User's stat changes aspeed = user.rough_stat(:SPEED) @@ -152,7 +152,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUs # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| will_fail = true battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, i| next if !pkmn.able? || pkmn.status != :NONE @@ -171,7 +171,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember", next ret } ) -Battle::AI::Handlers::MoveEffectScore.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 if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) @@ -191,7 +191,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HitOncePerUserTeamMember", # #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn", - proc { |score, move, user, target, ai, battle| + 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) @@ -204,12 +204,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttack", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack", proc { |score, move, user, target, ai, battle| # Power Herb makes this a 1 turn move, the same as a move with no effect next score if user.has_active_item?(:POWERHERB) # Treat as a failure if user has Truant (the charging turn has no effect) - next score - 60 if user.has_active_ability?(:TRUANT) + next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:TRUANT) # Don't prefer because it uses up two turns score -= 15 # Don't prefer if user is at a low HP (time is better spent on quicker moves) @@ -258,12 +258,12 @@ Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun", next move.move.pbBaseDamageMultiplier(power, user.battler, target.battler) } ) -Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackOneTurnInSun", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackOneTurnInSun", proc { |score, move, user, target, ai, battle| # Sunny weather this a 1 turn move, the same as a move with no effect next score if [:Sun, :HarshSun].include?(user.battler.effectiveWeather) # Score for being a two turn attack - next Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + next Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score, move, user, target, ai, battle) } ) @@ -271,13 +271,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackOneTurnInSun", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackParalyzeTarget", proc { |score, move, user, target, ai, battle| # Score for being a two turn attack - score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score, move, user, target, ai, battle) # Score for paralysing - score = Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget", score, move, user, target, ai, battle) next score } @@ -286,13 +286,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackBurnTarget", proc { |score, move, user, target, ai, battle| # Score for being a two turn attack - score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score, move, user, target, ai, battle) # Score for burning - score = Battle::AI::Handlers.apply_move_effect_score("BurnTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget", score, move, user, target, ai, battle) next score } @@ -301,13 +301,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackFlinchTarget", proc { |score, move, user, target, ai, battle| # Score for being a two turn attack - score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score, move, user, target, ai, battle) # Score for flinching - score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget", score, move, user, target, ai, battle) next score } @@ -318,12 +318,12 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget", #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1", "TwoTurnAttackRaiseUserSpAtkSpDefSpd2") -Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2", proc { |score, move, user, target, ai, battle| # Score for raising user's stats score = ai.get_score_for_user_stat_raise(score) # Score for being a two turn attack - score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score, move, user, target, ai, battle) next score } @@ -332,14 +332,14 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2" #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserDefense1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackChargeRaiseUserDefense1", proc { |score, move, user, target, ai, battle| # Score for being a two turn attack - score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score, move, user, target, ai, battle) # Score for raising the user's stat score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense1", - score, move, user, target, ai, battle) + score, move, user, ai, battle) next score } ) @@ -347,14 +347,14 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserDefense1" #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserSpAtk1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackChargeRaiseUserSpAtk1", proc { |score, move, user, target, ai, battle| # Score for being a two turn attack - score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score, move, user, target, ai, battle) # Score for raising the user's stat score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserSpAtk1", - score, move, user, target, ai, battle) + score, move, user, ai, battle) next score } ) @@ -382,7 +382,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserSpAtk1", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct", proc { |move, user, target, ai, battle| next true if !target.opposes?(user) next true if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) @@ -417,6 +417,7 @@ Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn", #=============================================================================== # TODO: Review score modifiers. +# TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage", proc { |power, move, user, target, ai, battle| @@ -424,7 +425,7 @@ Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDama } ) Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if user.hp <= user.totalhp / 4 score -= 90 elsif user.hp <= user.totalhp / 2 diff --git a/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb b/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb index bc68ffbbd..91f66990a 100644 --- a/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb +++ b/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb @@ -2,14 +2,14 @@ # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("HealUserFullyAndFallAsleep", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.canHeal? next true if user.battler.asleep? next true if !user.battler.pbCanSleep?(user.battler, false, move.move, true) } ) Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| # Consider how much HP will be restored if user.hp >= user.totalhp * 0.5 score -= 10 @@ -34,12 +34,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("HealUserHalfOfTotalHP", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.canHeal? } ) Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| # Consider how much HP will be restored if user.hp >= user.totalhp * 0.5 score -= 10 @@ -56,7 +56,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", "HealUserDependingOnWeather") Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| # Consider how much HP will be restored if user.hp >= user.totalhp * 0.5 score -= 10 @@ -80,7 +80,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather", Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", "HealUserDependingOnSandstorm") Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| # Consider how much HP will be restored if user.hp >= user.totalhp * 0.5 score -= 10 @@ -98,7 +98,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm", Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", "HealUserHalfOfTotalHPLoseFlyingTypeThisTurn") Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeThisTurn", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| # Consider how much HP will be restored if user.hp >= user.totalhp * 0.5 score -= 10 @@ -117,13 +117,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeTh #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("CureTargetStatusHealUserHalfOfTotalHP", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CureTargetStatusHealUserHalfOfTotalHP", proc { |move, user, target, ai, battle| next true if !user.battler.canHeal? next true if target.status == :NONE } ) -Battle::AI::Handlers::MoveEffectScore.add("CureTargetStatusHealUserHalfOfTotalHP", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetStatusHealUserHalfOfTotalHP", proc { |score, move, user, target, ai, battle| # TODO: Add high level checks for whether the target wants to lose their # status problem, and change the score accordingly. @@ -145,7 +145,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CureTargetStatusHealUserHalfOfTotalHP #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("HealUserByTargetAttackLowerTargetAttack1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserByTargetAttackLowerTargetAttack1", proc { |move, user, target, ai, battle| if !battle.moldBreaker && target.has_active_ability?(:CONTRARY) next true if target.statStageAtMax?(:ATTACK) @@ -154,7 +154,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserByTargetAttackLowerTargetAtt end } ) -Battle::AI::Handlers::MoveEffectScore.add("HealUserByTargetAttackLowerTargetAttack1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByTargetAttackLowerTargetAttack1", proc { |score, move, user, target, ai, battle| # Check whether lowering the target's Attack will have any impact if ai.trainer.medium_skill? @@ -188,7 +188,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByTargetAttackLowerTargetAtta #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("HealUserByHalfOfDamageDone", +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 @@ -211,18 +211,18 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByHalfOfDamageDone", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("HealUserByHalfOfDamageDoneIfTargetAsleep", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserByHalfOfDamageDoneIfTargetAsleep", proc { |move, user, target, ai, battle| next true if !target.battler.asleep? } ) -Battle::AI::Handlers::MoveEffectScore.copy("HealUserByHalfOfDamageDone", - "HealUserByHalfOfDamageDoneIfTargetAsleep") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HealUserByHalfOfDamageDone", + "HealUserByHalfOfDamageDoneIfTargetAsleep") #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("HealUserByThreeQuartersOfDamageDone", +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 @@ -245,64 +245,56 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByThreeQuartersOfDamageDone", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("HealUserAndAlliesQuarterOfTotalHP", - proc { |move, user, target, ai, battle| - valid_targets = battle.allSameSideBattlers(user.battler) { |b| b.canHeal? } - next true if valid_targets.empty? - } -) -Battle::AI::Handlers::MoveEffectScore.add("HealUserAndAlliesQuarterOfTotalHP", - proc { |score, move, user, target, ai, battle| - battle.allSameSideBattlers(user.index).each do |b| - next if !b.canHeal? - # Consider how much HP will be restored - if b.hp >= b.totalhp * 0.75 - score -= 5 - else - score += 15 * (b.totalhp - b.hp) / b.totalhp - end - end - next score - } -) - -#=============================================================================== -# -#=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("HealUserAndAlliesQuarterOfTotalHPCureStatus", - proc { |move, user, target, ai, battle| - valid_targets = battle.allSameSideBattlers(user.battler) { |b| b.canHeal? || b.status != :NONE } - next true if valid_targets.empty? - } -) -Battle::AI::Handlers::MoveEffectScore.add("HealUserAndAlliesQuarterOfTotalHPCureStatus", - proc { |score, move, user, target, ai, battle| - battle.allSameSideBattlers(user.index).each do |b| - next if !b.canHeal? && b.status == :NONE - # Consider how much HP will be restored - if b.hp >= b.totalhp * 0.75 - score -= 5 - else - score += 15 * (b.totalhp - b.hp) / b.totalhp - end - # Check whether an existing status problem will be removed - score += 10 if user.status != :NONE - end - next score - } -) - -#=============================================================================== -# -#=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("HealTargetHalfOfTotalHP", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarterOfTotalHP", proc { |move, user, target, ai, battle| next true if !target.battler.canHeal? } ) -Battle::AI::Handlers::MoveEffectScore.add("HealTargetHalfOfTotalHP", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHP", proc { |score, move, user, target, ai, battle| - next score - 40 if user.opposes?(target) + # 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 + next score + } +) + +#=============================================================================== +# +#=============================================================================== +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarterOfTotalHPCureStatus", + proc { |move, user, target, ai, battle| + next true if !target.battler.canHeal? && target.status == :NONE + } +) +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 + # Check whether an existing status problem will be removed + score += 10 if target.status != :NONE + next score + } +) + +#=============================================================================== +# +#=============================================================================== +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealTargetHalfOfTotalHP", + proc { |move, user, target, ai, battle| + next true if !target.battler.canHeal? + } +) +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? && @@ -320,11 +312,11 @@ Battle::AI::Handlers::MoveEffectScore.add("HealTargetHalfOfTotalHP", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("HealTargetHalfOfTotalHP", - "HealTargetDependingOnGrassyTerrain") -Battle::AI::Handlers::MoveEffectScore.add("HealTargetDependingOnGrassyTerrain", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("HealTargetHalfOfTotalHP", + "HealTargetDependingOnGrassyTerrain") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealTargetDependingOnGrassyTerrain", proc { |score, move, user, target, ai, battle| - next score - 40 if user.opposes?(target) + 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 @@ -342,12 +334,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealTargetDependingOnGrassyTerrain", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("HealUserPositionNextTurn", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.positions[user.index].effects[PBEffects::Wish] > 0 } ) Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| # Consider how much HP will be restored if user.hp >= user.totalhp * 0.5 score -= 10 @@ -362,12 +354,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurn", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::AquaRing] } ) Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score += 10 score += 10 if user.has_active_item?(:BIGROOT) next score @@ -378,12 +370,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurnTrapUserInBattle", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::Ingrain] } ) Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score += 5 score += 10 if user.turnCount < 2 score += 10 if user.has_active_item?(:BIGROOT) @@ -394,14 +386,14 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("StartDamageTargetEachTurnIfTargetAsleep", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartDamageTargetEachTurnIfTargetAsleep", proc { |move, user, target, ai, battle| next true if !target.battler.asleep? || target.effects[PBEffects::Nightmare] } ) -Battle::AI::Handlers::MoveEffectScore.add("StartDamageTargetEachTurnIfTargetAsleep", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartDamageTargetEachTurnIfTargetAsleep", proc { |score, move, user, target, ai, battle| - next score - 40 if target.statusCount <= 1 + next Battle::AI::MOVE_USELESS_SCORE if target.statusCount <= 1 next score + 10 * target.statusCount } ) @@ -409,13 +401,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartDamageTargetEachTurnIfTargetAsle #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("StartLeechSeedTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartLeechSeedTarget", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::LeechSeed] >= 0 next true if target.has_type?(:GRASS) } ) -Battle::AI::Handlers::MoveEffectScore.add("StartLeechSeedTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartLeechSeedTarget", proc { |score, move, user, target, ai, battle| score += 10 if user.turnCount < 2 if ai.trainer.medium_skill? @@ -440,7 +432,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartLeechSeedTarget", # #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP", - proc { |score, move, user, target, ai, battle| + 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 @@ -463,7 +455,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UserLosesHalfOfTotalHPExplosive", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !battle.moldBreaker && battle.pbCheckGlobalAbility(:DAMP) } ) @@ -476,7 +468,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserLosesHalfOfTotalHP", Battle::AI::Handlers::MoveFailureCheck.copy("UserLosesHalfOfTotalHPExplosive", "UserFaintsExplosive") Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive", - proc { |score, move, user, target, ai, battle| + 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 @@ -522,10 +514,10 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserFaintsExplosive", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserFaintsLowerTargetAtkSpAtk2", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserFaintsLowerTargetAtkSpAtk2", proc { |score, move, user, target, ai, battle| - next score - 40 if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler) && - !target.battler.pbCanLowerStatStage?(:SPECIAL_ATTACK, user.battler) + next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler) && + !target.battler.pbCanLowerStatStage?(:SPECIAL_ATTACK, user.battler) score -= 25 # User will faint, don't prefer this move # Check the impact of lowering the target's stats if target.stages[:ATTACK] < 0 && target.stages[:SPECIAL_ATTACK] < 0 @@ -552,12 +544,12 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsLowerTargetAtkSpAtk2", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UserFaintsHealAndCureReplacement", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !battle.pbCanChooseNonActive?(user.index) } ) Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 25 # User will faint, don't prefer this move # Check whether the replacement user needs healing, and don't make the below # calculations if not @@ -568,7 +560,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement", need_healing = true break end - next score - 15 if !need_healing + next Battle::AI::MOVE_USELESS_SCORE if !need_healing end if ai.trainer.medium_skill? score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more @@ -594,23 +586,18 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserFaintsHealAndCureReplacement", "UserFaintsHealAndCureReplacementRestorePP") #=============================================================================== -# +# TODO: This code should be for a single battler (each is checked in turn). +# Should have a MoveEffectAgainstTargetScore instead. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("StartPerishCountsForAllBattlers", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartPerishCountsForAllBattlers", proc { |move, user, target, ai, battle| - will_fail = true - battle.allBattlers.each do |b| - next if b.effects[PBEffects::PerishSong] > 0 - next if Battle::AbilityEffects.triggerMoveImmunity(b.ability, user.battler, b, - move.move, move.rough_type, battle, false) - will_fail = false - break - end - next will_fail + next true if target.effects[PBEffects::PerishSong] > 0 + next true if Battle::AbilityEffects.triggerMoveImmunity(target.ability, user.battler, target.battler, + move.move, move.rough_type, battle, false) } ) Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 15 # Check which battlers will be affected by this move if ai.trainer.medium_skill? @@ -628,7 +615,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers", allies_affected += 1 end end - next score - 25 if foes_affected == 0 + 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 @@ -650,12 +637,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("AttackerFaintsIfUserFaints", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next Settings::MECHANICS_GENERATION >= 7 && user.effects[PBEffects::DestinyBondPrevious] } ) Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 25 # Check whether user is faster than its foe(s) and could use this move user_faster_count = 0 @@ -679,7 +666,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints", # #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("SetAttackerMovePPTo0IfUserFaints", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score -= 25 # Check whether user is faster than its foe(s) and could use this move user_faster_count = 0 diff --git a/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb b/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb index 6f0b8baf0..6fc8fe03e 100644 --- a/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb +++ b/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb @@ -1,7 +1,7 @@ #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserTakesTargetItem", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTakesTargetItem", proc { |score, move, user, target, ai, battle| next score if user.wild? || user.item next score if !target.item || target.battler.unlosableItem?(target.item) @@ -22,13 +22,13 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTakesTargetItem", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("TargetTakesUserItem", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetTakesUserItem", proc { |move, user, target, ai, battle| next true if !user.item || user.battler.unlosableItem?(user.item) next true if target.item || target.battler.unlosableItem?(user.item) } ) -Battle::AI::Handlers::MoveEffectScore.add("TargetTakesUserItem", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetTakesUserItem", proc { |score, move, user, target, ai, battle| user_item_preference = ai.battler_wants_item?(user, user.item_id) user_no_item_preference = ai.battler_wants_item?(user, :NONE) @@ -43,7 +43,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetTakesUserItem", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapItems", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapItems", proc { |move, user, target, ai, battle| next true if user.wild? next true if !user.item && !target.item @@ -52,7 +52,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapItems", next true if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker } ) -Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapItems", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems", proc { |score, move, user, target, ai, battle| user_new_item_preference = ai.battler_wants_item?(user, target.item_id) user_old_item_preference = ai.battler_wants_item?(user, user.item_id) @@ -71,12 +71,12 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapItems", # #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RestoreUserConsumedItem", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.recycleItem || user.item } ) Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| user_new_item_preference = ai.battler_wants_item?(user, user.battler.recycleItem) user_old_item_preference = ai.battler_wants_item?(user, user.item_id) score += (user_new_item_preference - user_old_item_preference) * 8 @@ -92,7 +92,7 @@ Battle::AI::Handlers::MoveBasePower.add("RemoveTargetItem", next move.move.pbBaseDamage(power, user.battler, target.battler) } ) -Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveTargetItem", proc { |score, move, user, target, ai, battle| next score if user.wild? next score if !target.item || target.battler.unlosableItem?(target.item) @@ -109,7 +109,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("DestroyTargetBerryOrGem", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DestroyTargetBerryOrGem", proc { |score, move, user, target, ai, battle| next score if !target.item || (!target.item.is_berry? && !(Settings::MECHANICS_GENERATION >= 6 && target.item.is_gem?)) @@ -127,7 +127,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DestroyTargetBerryOrGem", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("CorrodeTargetItem", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CorrodeTargetItem", proc { |move, user, target, ai, battle| next true if !target.item || target.unlosableItem?(target.item) || target.effects[PBEffects::Substitute] > 0 @@ -135,7 +135,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("CorrodeTargetItem", next true if battle.corrosiveGas[target.index % 2][target.party_index] } ) -Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem", proc { |score, move, user, target, ai, battle| if target.item_active? score += 30 @@ -149,25 +149,20 @@ Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("StartTargetCannotUseItem", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetCannotUseItem", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::Embargo] > 0 } ) -Battle::AI::Handlers::MoveEffectScore.add("StartTargetCannotUseItem", - proc { |score, move, user, target, ai, battle| - next 0 if target.effects[PBEffects::Embargo] > 0 - } -) #=============================================================================== # TODO: Review score modifiers. # TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems", - proc { |score, move, user, target, ai, battle| - next score - 40 if battle.field.effects[PBEffects::MagicRoom] > 0 - next score + 30 if !user.item && target.item + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if battle.field.effects[PBEffects::MagicRoom] > 0 + next score + 30 if !user.item # && target.item } ) @@ -175,13 +170,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UserConsumeBerryRaiseDefense2", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| item = user.item next true if !item || !item.is_berry? || !user.item_active? } ) Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if ai.trainer.high_skill? useful_berries = [ :ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY, @@ -206,14 +201,14 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2", #=============================================================================== # TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# TODO: This code should be for a single battler (each is checked in turn). #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("AllBattlersConsumeBerry", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersConsumeBerry", proc { |move, user, target, ai, battle| next true if !target.item || !target.item.is_berry? || target.battler.semiInvulnerable? } ) -Battle::AI::Handlers::MoveEffectScore.add("AllBattlersConsumeBerry", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersConsumeBerry", proc { |score, move, user, target, ai, battle| useful_berries = [ :ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY, @@ -252,7 +247,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersConsumeBerry", #=============================================================================== # #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserConsumeTargetBerry", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserConsumeTargetBerry", proc { |score, move, user, target, ai, battle| next score if !target.item || !target.item.is_berry? next score if user.battler.unlosableItem?(target.item) @@ -270,7 +265,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeTargetBerry", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| item = user.item next true if !item || !user.item_active? || user.battler.unlosableItem?(item) next true if item.is_berry? && !user.battler.canConsumeBerry? diff --git a/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb b/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb index 80bfcd0a4..3de26dbae 100644 --- a/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb +++ b/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb @@ -2,6 +2,15 @@ # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToUser", + proc { |score, move, user, ai, battle| + next 0 if user.battler.allAllies.length == 0 + } +) + +#=============================================================================== +# TODO: Review score modifiers. +#=============================================================================== +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RedirectAllMovesToTarget", proc { |score, move, user, target, ai, battle| next 0 if user.battler.allAllies.length == 0 } @@ -10,16 +19,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToUser", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToTarget", - proc { |score, move, user, target, ai, battle| - next 0 if user.battler.allAllies.length == 0 - } -) - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("CannotBeRedirected", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CannotBeRedirected", proc { |score, move, user, target, ai, battle| redirection = false user.battler.allOpposing.each do |b| @@ -50,12 +50,12 @@ Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("HealAllyOrDamageFoe", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealAllyOrDamageFoe", proc { |move, user, target, ai, battle| next true if !target.opposes?(user) && target.battler.canHeal? } ) -Battle::AI::Handlers::MoveEffectScore.add("HealAllyOrDamageFoe", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealAllyOrDamageFoe", proc { |score, move, user, target, ai, battle| if !target.opposes?(user) score += 50 @@ -69,32 +69,39 @@ Battle::AI::Handlers::MoveEffectScore.add("HealAllyOrDamageFoe", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1", - proc { |move, user, target, ai, battle| - if user.has_type?(:GHOST) - next true if target.effects[PBEffects::Curse] - else + proc { |move, user, ai, battle| + if !user.has_type?(:GHOST) next true if !user.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move) && !user.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) && !user.battler.pbCanRaiseStatStage?(:DEFENSE, user.battler, move.move) end } ) +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1", + proc { |move, user, target, ai, battle| + next true if user.has_type?(:GHOST) && target.effects[PBEffects::Curse] + } +) Battle::AI::Handlers::MoveEffectScore.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1", + proc { |score, move, user, ai, battle| + next score if user.has_type?(:GHOST) + avg = user.stages[:SPEED] * 10 + avg -= user.stages[:ATTACK] * 10 + avg -= user.stages[:DEFENSE] * 10 + score += avg / 3 + next score + } +) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1", proc { |score, move, user, target, ai, battle| - if user.has_type?(:GHOST) - if user.hp <= user.totalhp / 2 - if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 - score -= 90 - else - score -= 50 - score -= 30 if battle.switchStyle - end + next score if !user.has_type?(:GHOST) + if user.hp <= user.totalhp / 2 + if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 + score -= 90 + else + score -= 50 + score -= 30 if battle.switchStyle end - else - avg = user.stages[:SPEED] * 10 - avg -= user.stages[:ATTACK] * 10 - avg -= user.stages[:DEFENSE] * 10 - score += avg / 3 end next score } @@ -114,7 +121,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitsAllFoesAndPowersUpInPsychicTerrain" } ) Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + 20 if battle.field.terrain == :Psychic && user.battler.affectedByTerrain? && battle.allOtherSideBattlers(user.index).length > 1 } @@ -123,12 +130,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrai #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("TargetNextFireMoveDamagesTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetNextFireMoveDamagesTarget", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::Powder] } ) -Battle::AI::Handlers::MoveEffectScore.add("TargetNextFireMoveDamagesTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetNextFireMoveDamagesTarget", proc { |score, move, user, target, ai, battle| aspeed = user.rough_stat(:SPEED) ospeed = target.rough_stat(:SPEED) @@ -154,14 +161,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetNextFireMoveDamagesTarget", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("PowerUpAllyMove", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PowerUpAllyMove", proc { |move, user, target, ai, battle| next true if target.fainted? || target.effects[PBEffects::HelpingHand] } ) -Battle::AI::Handlers::MoveEffectScore.add("PowerUpAllyMove", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PowerUpAllyMove", proc { |score, move, user, target, ai, battle| - next score - 60 if user.battler.allAllies.empty? next score + 30 } ) @@ -176,15 +182,15 @@ Battle::AI::Handlers::MoveBasePower.add("CounterPhysicalDamage", } ) Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage", - proc { |score, move, user, target, ai, battle| - next score - 40 if target.effects[PBEffects::HyperBeam] > 0 + proc { |score, move, user, ai, battle| +# next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0 attack = user.rough_stat(:ATTACK) spatk = user.rough_stat(:SPECIAL_ATTACK) if attack * 1.5 < spatk score -= 60 - elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed - moveData = GameData::Move.get(target.battler.lastMoveUsed) - score += 60 if moveData.physical? +# elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed +# moveData = GameData::Move.get(target.battler.lastMoveUsed) +# score += 60 if moveData.physical? end next score } @@ -200,15 +206,15 @@ Battle::AI::Handlers::MoveBasePower.add("CounterSpecialDamage", } ) Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage", - proc { |score, move, user, target, ai, battle| - next score - 40 if target.effects[PBEffects::HyperBeam] > 0 + proc { |score, move, user, ai, battle| +# next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0 attack = user.rough_stat(:ATTACK) spatk = user.rough_stat(:SPECIAL_ATTACK) if attack > spatk * 1.5 score -= 60 - elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed - moveData = GameData::Move.get(target.battler.lastMoveUsed) - score += 60 if moveData.special? +# elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed +# moveData = GameData::Move.get(target.battler.lastMoveUsed) +# score += 60 if moveData.special? end next score } @@ -224,8 +230,8 @@ Battle::AI::Handlers::MoveBasePower.add("CounterDamagePlusHalf", } ) Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf", - proc { |score, move, user, target, ai, battle| - next score - 40 if target.effects[PBEffects::HyperBeam] > 0 + proc { |score, move, user, ai, battle| +# next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0 } ) @@ -233,12 +239,12 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UserAddStockpileRaiseDefSpDef1", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::Stockpile] >= 3 } ) Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| avg = 0 avg -= user.stages[:DEFENSE] * 10 avg -= user.stages[:SPECIAL_DEFENSE] * 10 @@ -255,7 +261,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("PowerDependsOnUserStockpile", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::Stockpile] == 0 } ) @@ -269,7 +275,7 @@ Battle::AI::Handlers::MoveBasePower.add("PowerDependsOnUserStockpile", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("HealUserDependingOnUserStockpile", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::Stockpile] == 0 next true if !user.battler.canHeal? && user.effects[PBEffects::StockpileDef] == 0 && @@ -277,7 +283,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserDependingOnUserStockpile", } ) Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| mult = [0, 25, 50, 100][user.effects[PBEffects::Stockpile]] score += mult score -= user.hp * mult * 2 / user.totalhp @@ -304,7 +310,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsed", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !battle.lastMoveUsed next true if move.move.moveBlacklist.include?(GameData::Move.get(battle.lastMoveUsed).function_code) } @@ -313,15 +319,15 @@ Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsed", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsedByTarget", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UseLastMoveUsedByTarget", proc { |move, user, target, ai, battle| next true if !target.battler.lastRegularMoveUsed next true if GameData::Move.get(target.battler.lastRegularMoveUsed).flags.none? { |f| f[/^CanMirrorMove$/i] } } ) -Battle::AI::Handlers::MoveEffectScore.add("UseLastMoveUsedByTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UseLastMoveUsedByTarget", proc { |score, move, user, target, ai, battle| - next score - 40 + next Battle::AI::MOVE_USELESS_SCORE } ) @@ -345,7 +351,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UseLastMoveUsedByTarget", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UseRandomMoveFromUserParty", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| will_fail = true battle.pbParty(user.index).each_with_index do |pkmn, i| next if !pkmn || i == user.party_index @@ -366,7 +372,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UseRandomMoveFromUserParty", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("UseRandomUserMoveIfAsleep", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !user.battler.asleep? will_fail = true user.battler.eachMoveWithIndex do |m, i| @@ -378,11 +384,6 @@ Battle::AI::Handlers::MoveFailureCheck.add("UseRandomUserMoveIfAsleep", next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("UseRandomUserMoveIfAsleep", - proc { |score, move, user, target, ai, battle| - next score + 50 if user.battler.asleep? # Because it can only be used while asleep - } -) #=============================================================================== # TODO: Review score modifiers. @@ -399,7 +400,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UseRandomUserMoveIfAsleep", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("ReplaceMoveThisBattleWithTargetLastMoveUsed", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ReplaceMoveThisBattleWithTargetLastMoveUsed", proc { |move, user, target, ai, battle| next true if user.effects[PBEffects::Transform] || user.battler.pbHasMove?(move.id) last_move_data = GameData::Move.try_get(target.battler.lastRegularMoveUsed) @@ -413,7 +414,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("ReplaceMoveThisBattleWithTargetLastM #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("ReplaceMoveWithTargetLastMoveUsed", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ReplaceMoveWithTargetLastMoveUsed", proc { |move, user, target, ai, battle| next true if user.effects[PBEffects::Transform] || !user.battler.pbHasMove?(move.id) last_move_data = GameData::Move.try_get(target.battler.lastRegularMoveUsed) diff --git a/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb b/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb index 0d8803529..510b20b67 100644 --- a/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb +++ b/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb @@ -2,7 +2,7 @@ # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !battle.pbCanRun?(user.index) } ) @@ -11,7 +11,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserStatusMove", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| if user.wild? next true if !battle.pbCanRun?(user.index) else @@ -20,7 +20,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserStatusMove", } ) Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next score + 10 if user.wild? if battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace score -= 60 @@ -50,7 +50,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserDamagingMove", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| next 0 if !battle.pbCanChooseNonActive?(user.index) || battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace } @@ -58,8 +58,9 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserDamagingMove", #=============================================================================== # TODO: Review score modifiers. +# TODO: Might need both MoveEffectScore and MoveEffectAgainstTargetScore. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkSpAtk1SwitchOutUser", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAtkSpAtk1SwitchOutUser", proc { |move, user, target, ai, battle| will_fail = true (move.move.statDown.length / 2).times do |i| @@ -70,7 +71,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkSpAtk1SwitchOutUser", next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1SwitchOutUser", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkSpAtk1SwitchOutUser", proc { |score, move, user, target, ai, battle| avg = target.stages[:ATTACK] * 10 avg += target.stages[:SPECIAL_ATTACK] * 10 @@ -83,12 +84,12 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1SwitchOutUser", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserPassOnEffects", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if !battle.pbCanChooseNonActive?(user.index) } ) Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if battle.pbCanChooseNonActive?(user.index) score -= 40 if user.effects[PBEffects::Confusion] > 0 total = 0 @@ -116,7 +117,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutTargetStatusMove", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SwitchOutTargetStatusMove", proc { |move, user, target, ai, battle| next true if (!battle.moldBreaker && target.has_active_ability?(:SUCTIONCUPS)) || target.effects[PBEffects::Ingrain] @@ -133,7 +134,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutTargetStatusMove", end } ) -Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetStatusMove", +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 @@ -145,7 +146,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetStatusMove", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetDamagingMove", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetDamagingMove", proc { |score, move, user, target, ai, battle| if (battle.moldBreaker || !target.has_active_ability?(:SUCTIONCUPS)) && !target.effects[PBEffects::Ingrain] @@ -160,7 +161,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetDamagingMove", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("BindTarget", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget", proc { |score, move, user, target, ai, battle| next score + 40 if target.effects[PBEffects::Trapping] == 0 } @@ -174,7 +175,7 @@ Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater next move.move.pbModifyDamage(power, user.battler, target.battler) } ) -Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTargetDoublePowerIfTargetUnderwater", proc { |score, move, user, target, ai, battle| next score + 40 if target.effects[PBEffects::Trapping] == 0 } @@ -183,7 +184,7 @@ Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwat #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattle", proc { |move, user, target, ai, battle| if move.statusMove? next true if target.effects[PBEffects::MeanLook] >= 0 @@ -195,7 +196,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn", proc { |move, user, target, ai, battle| if move.statusMove? next true if target.effects[PBEffects::Octolock] >= 0 @@ -203,7 +204,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle", end } ) -Battle::AI::Handlers::MoveEffectScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn", proc { |score, move, user, target, ai, battle| score += 30 if !target.battler.trappedInBattle? score -= 50 if !target.battler.pbCanLowerStatStage?(:DEFENSE, user.battler, move.move) && @@ -215,7 +216,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TrapTargetInBattleLowerTargetDefSpDef #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("TrapUserAndTargetInBattle", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapUserAndTargetInBattle", proc { |score, move, user, target, ai, battle| if target.effects[PBEffects::JawLock] < 0 score += 40 if !user.battler.trappedInBattle? && !target.battler.trappedInBattle? @@ -228,7 +229,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TrapUserAndTargetInBattle", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("TrapAllBattlersInBattleForOneTurn", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if battle.field.effects[PBEffects::FairyLock] > 0 } ) @@ -240,16 +241,17 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapAllBattlersInBattleForOneTurn", #=============================================================================== # TODO: Review score modifiers. +# TODO: Consider all foes rather than just target. Can't use "target". #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("UsedAfterUserTakesPhysicalDamage", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if ai.trainer.medium_skill? hasPhysicalAttack = false - target.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end +# target.battler.eachMove do |m| +# next if !m.physicalMove?(m.type) +# hasPhysicalAttack = true +# break +# end score -= 50 if !hasPhysicalAttack end next score @@ -260,7 +262,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterUserTakesPhysicalDamage", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if ai.trainer.medium_skill? user.battler.allAllies.each do |b| next if !b.pbHasMove?(move.id) @@ -284,7 +286,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("TargetUsesItsLastUsedMoveAgain", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetUsesItsLastUsedMoveAgain", proc { |move, user, target, ai, battle| next true if !target.battler.lastRegularMoveUsed || !target.battler.pbHasMove?(target.battler.lastRegularMoveUsed) @@ -297,11 +299,11 @@ Battle::AI::Handlers::MoveFailureCheck.add("TargetUsesItsLastUsedMoveAgain", next true if target.battler.moves[idxMove].pp == 0 && target.battler.moves[idxMove].total_pp > 0 } ) -Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetUsesItsLastUsedMoveAgain", proc { |score, move, user, target, ai, battle| # Without lots of code here to determine good/bad moves and relative # speeds, using this move is likely to just be a waste of a turn - next score - 40 + next Battle::AI::MOVE_USELESS_SCORE } ) @@ -314,7 +316,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("HigherPriorityInGrassyTerrain", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HigherPriorityInGrassyTerrain", proc { |score, move, user, target, ai, battle| if ai.trainer.medium_skill? && battle.field.terrain == :Grassy score += 15 if target.faster_than?(user) @@ -326,7 +328,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HigherPriorityInGrassyTerrain", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy3", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerPPOfTargetLastMoveBy3", proc { |score, move, user, target, ai, battle| last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed) if last_move && last_move.total_pp > 0 && last_move.pp <= 3 @@ -339,22 +341,22 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy3", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("LowerPPOfTargetLastMoveBy4", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerPPOfTargetLastMoveBy4", proc { |move, user, target, ai, battle| last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed) next true if !last_move || last_move.pp == 0 || last_move.total_pp <= 0 } ) -Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy4", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerPPOfTargetLastMoveBy4", proc { |score, move, user, target, ai, battle| - next score - 40 + next Battle::AI::MOVE_USELESS_SCORE } ) #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetLastMoveUsed", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetLastMoveUsed", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::Disable] > 0 || !target.battler.lastRegularMoveUsed next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false) @@ -372,13 +374,13 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetLastMoveUsed", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingSameMoveConsecutively", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingSameMoveConsecutively", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::Torment] next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false) } ) -Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingSameMoveConsecutively", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively", proc { |score, move, user, target, ai, battle| next 0 if target.effects[PBEffects::Torment] } @@ -387,7 +389,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingSameMoveConsecutive #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingDifferentMove", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingDifferentMove", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::Encore] > 0 next true if !target.battler.lastRegularMoveUsed || @@ -404,7 +406,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingDifferentMove", next will_fail } ) -Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingDifferentMove", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingDifferentMove", proc { |score, move, user, target, ai, battle| if user.faster_than?(target) moveData = GameData::Move.get(target.battler.lastRegularMoveUsed) @@ -424,7 +426,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingDifferentMove", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetStatusMoves", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetStatusMoves", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::Taunt] > 0 next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false) @@ -436,7 +438,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetStatusMoves", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetHealingMoves", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetHealingMoves", proc { |move, user, target, ai, battle| next true if target.effects[PBEffects::HealBlock] > 0 next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false) @@ -446,7 +448,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetHealingMoves", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("DisableTargetSoundMoves", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetSoundMoves", proc { |score, move, user, target, ai, battle| if target.effects[PBEffects::ThroatChop] == 0 && ai.trainer.high_skill? hasSoundMove = false @@ -465,7 +467,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetSoundMoves", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| next true if user.effects[PBEffects::Imprison] } ) @@ -473,17 +475,19 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser", #=============================================================================== # TODO: Review score modifiers. #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn", proc { |move, user, target, ai, battle| - next true if battle.allBattlers.none? { |b| b.hp > 1 } + next true if target.hp <= 1 } ) Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn", + proc { |score, move, user, ai, battle| + next score + 10 # Shadow moves are more preferable + } +) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn", proc { |score, move, user, target, ai, battle| - score += 20 # Shadow moves are more preferable - score += 20 if target.hp >= target.totalhp / 2 - score -= 20 if user.hp < user.hp / 2 - next score + next score + 20 if target.hp >= target.totalhp / 2 } ) @@ -491,7 +495,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTur # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score += 20 # Shadow moves are more preferable score -= 40 next score @@ -504,10 +508,10 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP", Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", "StartShadowSkyWeather") Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score += 20 # Shadow moves are more preferable - next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || - battle.pbCheckGlobalAbility(:CLOUDNINE) + next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || + battle.pbCheckGlobalAbility(:CLOUDNINE) score += 10 if battle.field.weather != :None # Prefer replacing another weather score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP next score @@ -518,7 +522,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather", # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens", - proc { |move, user, target, ai, battle| + proc { |move, user, ai, battle| will_fail = true battle.sides.each do |side| will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 || @@ -530,7 +534,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens", } ) Battle::AI::Handlers::MoveEffectScore.add("RemoveAllScreens", - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| score += 20 # Shadow moves are more preferable if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 || user.pbOpposingSide.effects[PBEffects::Reflect] > 0 || 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 919aa2fa0..0c200952a 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 @@ -1,7 +1,7 @@ #=============================================================================== # TODO: Review score modifier. #=============================================================================== -# TODO: High priority checks: +# TODO: # => Prefer move if it will KO the target (moreso if user is slower than target) # => Don't prefer damaging move if it won't KO, user has Stance Change and # is in shield form, and user is slower than the target @@ -11,50 +11,98 @@ # => Check memory for past damage dealt by a target's priority move, and don't # prefer the move if user is slower than the target and can't move faster # than it because of priority -# => Discard move if user is slower than the target and target is semi- -# invulnerable (and move won't hit it) # => Check memory for whether target has previously used Quick Guard, and # don't prefer move if so #=============================================================================== -# TODO: Review score modifier. #=============================================================================== -# TODO: Low priority checks: -# => Don't prefer move if user is faster than the target -# => Prefer move if user is faster than the target and target is semi- -# invulnerable +#=============================================================================== +#=============================================================================== +#=============================================================================== #=============================================================================== -# Don't prefer a dancing move if the target has the Dancer ability. +# Don't prefer hitting a wild shiny Pokémon. # TODO: Review score modifier. -# TODO: Check all battlers, not just the target. #=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer, +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:shiny_target, proc { |score, move, user, target, ai, battle| - next score /= 2 if move.move.danceMove? && target&.has_active_ability?(:DANCER) + next score - 40 if target.wild? && target.battler.shiny? } ) #=============================================================================== +# Adjust score based on how much damage it can deal. +# Prefer the move even more if it's predicted to do enough damage to KO the +# target. # TODO: Review score modifier. +# => If target has previously used a move that will hurt the user by 30% of +# its current HP or more, moreso don't prefer a status move. +# => Include EOR damage in this? #=============================================================================== -# TODO: Check memory for whether target has previously used Ion Deluge, and -# don't prefer move if it's Normal-type and target is immune because -# of its ability (Lightning Rod, etc.). +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:add_predicted_damage, + proc { |score, move, user, target, ai, battle| + if move.damagingMove? + dmg = move.rough_damage + score += [15.0 * dmg / target.hp, 20].min + score += 10 if dmg > target.hp * 1.1 # Predicted to KO the target + next score.to_i + end + } +) #=============================================================================== +# Account for accuracy of move. # TODO: Review score modifier. #=============================================================================== -# TODO: Don't prefer sound move if user hasn't been Throat Chopped but -# target has previously used Throat Chop. +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:move_accuracy, + proc { |score, move, user, target, ai, battle| + next score * move.rough_accuracy / 100.0 + } +) #=============================================================================== +# Don't prefer attacking the target if they'd be semi-invulnerable. # TODO: Review score modifier. #=============================================================================== -# TODO: Don't prefer damaging moves if the target is Biding, unless the move -# will deal enough damage to KO the target before it retaliates (assuming -# the move is used repeatedly until the target retaliates). Don't worry -# about the target's Bide if the user will be immune to it. +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:target_semi_invulnerable, + proc { |score, move, user, target, ai, battle| + # TODO: Also consider the move's priority compared to that of the move the + # target is using. + if move.rough_accuracy > 0 && user.faster_than?(target) && + (target.battler.semiInvulnerable? || target.effects[PBEffects::SkyDrop] >= 0) + miss = true + miss = false if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD) + if ai.trainer.high_skill? && miss + # Knows what can get past semi-invulnerability + if target.effects[PBEffects::SkyDrop] >= 0 || + target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky", + "TwoTurnAttackInvulnerableInSkyParalyzeTarget", + "TwoTurnAttackInvulnerableInSkyTargetCannotAct") + miss = false if move.move.hitsFlyingTargets? + elsif target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderground") + miss = false if move.move.hitsDiggingTargets? + elsif target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderwater") + miss = false if move.move.hitsDivingTargets? + end + end + next Battle::AI::MOVE_USELESS_SCORE if miss + end + } +) + +#=============================================================================== +# If target is frozen, don't prefer moves that could thaw them. +# TODO: Review score modifier. +#=============================================================================== +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:thawing_move_against_frozen_target, + proc { |score, move, user, target, ai, battle| + if ai.trainer.medium_skill? && target.status == :FROZEN + if move.rough_type == :FIRE || (Settings::MECHANICS_GENERATION >= 6 && move.move.thawsUser?) + next score - 30 + end + end + } +) #=============================================================================== # TODO: Review score modifier. @@ -64,37 +112,26 @@ Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer, # lowered offences (Atk/Def or SpAtk/SpDef, whichever is relevant). #=============================================================================== -# Don't prefer damaging moves that will knock out the target if they are using -# Destiny Bond. +# Prefer flinching external effects (note that move effects which cause +# flinching are dealt with in the function code part of score calculation). # TODO: Review score modifier. -# => Also don't prefer damaging moves if user is slower than the target, move -# is likely to be lethal, and target has previously used Destiny Bond #=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:avoid_knocking_out_destiny_bonder, +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:flinching_effects, proc { |score, move, user, target, ai, battle| - if ai.trainer.medium_skill? && move.damagingMove? && - target && target.effects[PBEffects::DestinyBond] - dmg = move.rough_damage - if dmg > target.hp * 1.05 # Predicted to KO the target - score -= 25 - score -= 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 + if ai.trainer.medium_skill? + if (battle.moldBreaker || !target.has_active_ability?([:INNERFOCUS, :SHIELDDUST])) && + target.effects[PBEffects::Substitute] == 0 + if move.move.flinchingMove? || + (move.damagingMove? && + (user.has_active_item?([:KINGSROCK, :RAZORFANG]) || + user.has_active_ability?(:STENCH))) + next score + 20 + end end - next score end } ) -#=============================================================================== -# TODO: Review score modifier. -#=============================================================================== -# TODO: Don't prefer a move that is stopped by Wide Guard if target has -# previously used Wide Guard. - -#=============================================================================== -# TODO: Review score modifier. -#=============================================================================== -# TODO: Don't prefer Fire-type moves if target has previously used Powder. - #=============================================================================== # TODO: Review score modifier. #=============================================================================== @@ -110,53 +147,90 @@ Battle::AI::Handlers::GeneralMoveScore.add(:avoid_knocking_out_destiny_bonder, # an effect that's good for the user (Poison Touch/Pickpocket). #=============================================================================== -# Prefer damaging moves if the foe is down to their last Pokémon (opportunistic). -# Prefer damaging moves if the AI is down to its last Pokémon but the foe has -# more (desperate). +# Don't prefer a dancing move if the target has the Dancer ability. # TODO: Review score modifier. +# TODO: Check all battlers, not just the target. #=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:prefer_damaging_moves_if_last_pokemon, +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:dance_move_against_dancer, proc { |score, move, user, target, ai, battle| - if ai.trainer.medium_skill? && move.damagingMove? - reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) - foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) - # Don't mess with scores just because a move is damaging; need to play well - next score if ai.trainer.high_skill? && foes > reserves # AI is outnumbered - # Prefer damaging moves depending on remaining Pokémon - if foes == 0 # Foe is down to their last Pokémon - score *= 1.1 # => Go for the kill - elsif reserves == 0 # AI is down to its last Pokémon, foe has reserves - score *= 1.05 # => Go out with a bang - end - end - next score + next score /= 2 if move.move.danceMove? && target.has_active_ability?(:DANCER) } ) #=============================================================================== -# Don't prefer attacking the target if they'd be semi-invulnerable. # TODO: Review score modifier. #=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:target_semi_invulnerable, +# TODO: Don't prefer damaging moves if the target is Biding, unless the move +# will deal enough damage to KO the target before it retaliates (assuming +# the move is used repeatedly until the target retaliates). Don't worry +# about the target's Bide if the user will be immune to it. + +#=============================================================================== +# Don't prefer damaging moves that will knock out the target if they are using +# Destiny Bond. +# TODO: Review score modifier. +# => Also don't prefer damaging moves if user is slower than the target, move +# is likely to be lethal, and target has previously used Destiny Bond +#=============================================================================== +Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:avoid_knocking_out_destiny_bonder, proc { |score, move, user, target, ai, battle| - if move.rough_accuracy > 0 && target && user.faster_than?(target) && - (target.battler.semiInvulnerable? || target.effects[PBEffects::SkyDrop] >= 0) - miss = true - miss = false if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD) - if ai.trainer.high_skill? && miss - # Knows what can get past semi-invulnerability - if target.effects[PBEffects::SkyDrop] >= 0 || - target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky", - "TwoTurnAttackInvulnerableInSkyParalyzeTarget", - "TwoTurnAttackInvulnerableInSkyTargetCannotAct") - miss = false if move.move.hitsFlyingTargets? - elsif target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderground") - miss = false if move.move.hitsDiggingTargets? - elsif target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderwater") - miss = false if move.move.hitsDivingTargets? + if ai.trainer.medium_skill? && move.damagingMove? && target.effects[PBEffects::DestinyBond] + dmg = move.rough_damage + if dmg > target.hp * 1.05 # Predicted to KO the target + score -= 25 + score -= 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 + end + next score + end + } +) + +#=============================================================================== +# TODO: Review score modifier. +#=============================================================================== +# TODO: Don't prefer Fire-type moves if target has previously used Powder. + +#=============================================================================== +# TODO: Review score modifier. +#=============================================================================== +# TODO: Check memory for whether target has previously used Ion Deluge, and +# don't prefer move if it's Normal-type and target is immune because +# of its ability (Lightning Rod, etc.). + +#=============================================================================== +# TODO: Review score modifier. +#=============================================================================== +# TODO: Don't prefer a move that can be Magic Coated if the target (or any foe +# if the move doesn't have a target) has Magic Bounce. + +#=============================================================================== +#=============================================================================== +#=============================================================================== +#=============================================================================== +#=============================================================================== + +#=============================================================================== +# TODO: Review score modifier. +#=============================================================================== +# TODO: Prefer Shadow moves. + +#=============================================================================== +# If user is frozen, prefer a move that can thaw the user. +# TODO: Review score modifier. +#=============================================================================== +Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_when_frozen, + proc { |score, move, user, ai, battle| + if ai.trainer.medium_skill? && user.status == :FROZEN + if move.move.thawsUser? + score += 30 + else + user.battler.eachMove do |m| + next unless m.thawsUser? + score -= 30 # Don't prefer this move if user knows another move that thaws + break end end - next score - 40 if miss + next score end } ) @@ -166,7 +240,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:target_semi_invulnerable, # TODO: Review score modifier. #=============================================================================== Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item, - proc { |score, move, user, target, ai, battle| + proc { |score, move, user, ai, battle| if ai.trainer.medium_skill? if user.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) || user.has_active_ability?(:GORILLATACTICS) @@ -196,108 +270,37 @@ Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item, ) #=============================================================================== -# If user is frozen, prefer a move that can thaw the user. +# Prefer damaging moves if the foe is down to their last Pokémon (opportunistic). +# Prefer damaging moves if the AI is down to its last Pokémon but the foe has +# more (desperate). # TODO: Review score modifier. #=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_when_frozen, - proc { |score, move, user, target, ai, battle| - if ai.trainer.medium_skill? && user.status == :FROZEN - if move.move.thawsUser? - score += 30 - else - user.battler.eachMove do |m| - next unless m.thawsUser? - score -= 30 # Don't prefer this move if user knows another move that thaws - break - end - end - next score - end - } -) - -#=============================================================================== -# If target is frozen, don't prefer moves that could thaw them. -# TODO: Review score modifier. -#=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_against_frozen_target, - proc { |score, move, user, target, ai, battle| - if ai.trainer.medium_skill? && target&.status == :FROZEN - if move.rough_type == :FIRE || (Settings::MECHANICS_GENERATION >= 6 && move.move.thawsUser?) - next score - 30 +Battle::AI::Handlers::GeneralMoveScore.add(:prefer_damaging_moves_if_last_pokemon, + proc { |score, move, user, ai, battle| + if ai.trainer.medium_skill? && move.damagingMove? + reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) + foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) + # Don't mess with scores just because a move is damaging; need to play well + next score if ai.trainer.high_skill? && foes > reserves # AI is outnumbered + # Prefer damaging moves depending on remaining Pokémon + if foes == 0 # Foe is down to their last Pokémon + score *= 1.1 # => Go for the kill + elsif reserves == 0 # AI is down to its last Pokémon, foe has reserves + score *= 1.05 # => Go out with a bang end end - } -) - -#=============================================================================== -# Don't prefer hitting a wild shiny Pokémon. -# TODO: Review score modifier. -#=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:shiny_target, - proc { |score, move, user, target, ai, battle| - next score - 40 if target && target.wild? && target.battler.shiny? + next score } ) #=============================================================================== # TODO: Review score modifier. #=============================================================================== -# TODO: Discard a move that can be Magic Coated if either opponent has Magic -# Bounce. - -#=============================================================================== -# Account for accuracy of move. -# TODO: Review score modifier. -#=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:move_accuracy, - proc { |score, move, user, target, ai, battle| - next score * move.rough_accuracy / 100.0 - } -) - -#=============================================================================== -# Prefer flinching external effects (note that move effects which cause -# flinching are dealt with in the function code part of score calculation). -# TODO: Review score modifier. -#=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:flinching_effects, - proc { |score, move, user, target, ai, battle| - if ai.trainer.medium_skill? && target - if (battle.moldBreaker || !target.has_active_ability?([:INNERFOCUS, :SHIELDDUST])) && - target.effects[PBEffects::Substitute] == 0 - if move.move.flinchingMove? || - (move.damagingMove? && - (user.has_active_item?([:KINGSROCK, :RAZORFANG]) || - user.has_active_ability?(:STENCH))) - next score + 20 - end - end - end - } -) - -#=============================================================================== -# Adjust score based on how much damage it can deal. -# Prefer the move even more if it's predicted to do enough damage to KO the -# target. -# TODO: Review score modifier. -# => If target has previously used a move that will hurt the user by 30% of -# its current HP or more, moreso don't prefer a status move. -#=============================================================================== -Battle::AI::Handlers::GeneralMoveScore.add(:add_predicted_damage, - proc { |score, move, user, target, ai, battle| - if move.damagingMove? && target - dmg = move.rough_damage - score += [15.0 * dmg / target.hp, 20].min - score += 10 if dmg > target.hp * 1.1 # Predicted to KO the target - next score.to_i - end - } -) +# TODO: Don't prefer a move that is stopped by Wide Guard if any foe has +# previously used Wide Guard. #=============================================================================== # TODO: Review score modifier. #=============================================================================== -# TODO: Prefer a damaging move if it's predicted to KO the target. Maybe include -# EOR damage in the prediction? +# TODO: Don't prefer sound move if user hasn't been Throat Chopped but a foe has +# previously used Throat Chop. diff --git a/Data/Scripts/011_Battle/005_AI/101_AITrainer.rb b/Data/Scripts/011_Battle/005_AI/101_AITrainer.rb index db0deba7a..be691055b 100644 --- a/Data/Scripts/011_Battle/005_AI/101_AITrainer.rb +++ b/Data/Scripts/011_Battle/005_AI/101_AITrainer.rb @@ -11,26 +11,31 @@ # # Skill flags: # PredictMoveFailure +# ScoreMoves +# PreferMultiTargetMoves #=============================================================================== class Battle::AI::AITrainer attr_reader :side, :trainer_index attr_reader :skill def initialize(ai, side, index, trainer) - @ai = ai - @side = side + @ai = ai + @side = side @trainer_index = index - @trainer = trainer - - @skill = 0 - @skill_flags = [] + @trainer = trainer + @skill = 0 + @skill_flags = [] set_up_skill end def set_up_skill @skill = @trainer.skill_level if @trainer # TODO: Add skill flags depending on @skill. - @skill_flags.push("PredictMoveFailure") if @skill > 0 + if @skill > 0 + @skill_flags.push("PredictMoveFailure") + @skill_flags.push("ScoreMoves") + @skill_flags.push("PreferMultiTargetMoves") + end end def has_skill_flag?(flag) diff --git a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb index cdb4a74dd..b5106562f 100644 --- a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb +++ b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb @@ -22,6 +22,7 @@ class Battle::AI::AIBattler end end + def pokemon; return @battler.pokemon; end def level; return @battler.level; end def hp; return @battler.hp; end def fainted?; return @battler.fainted?; end