From dd7cd414f050abace891abb8b6fd131bfebbe57c Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sat, 31 Dec 2022 15:26:41 +0000 Subject: [PATCH] Yet more AI function code rewrites --- .../011_Battle/005_AI/004_AI_ChooseMove.rb | 4 +- .../005_AI/051_AI_MoveHandlers_Misc.rb | 80 ++++++++++++++++ .../052_AI_MoveHandlers_BattlerStats.rb | 93 ++++++++++++------- .../053_AI_MoveHandlers_BattlerOther.rb | 40 +++++++- .../054_AI_MoveHandlers_MoveAttributes.rb | 78 +++++++++++----- .../005_AI/055_AI_MoveHandlers_MultiHit.rb | 2 +- .../058_AI_MoveHandlers_ChangeMoveEffect.rb | 30 ++---- .../059_AI_MoveHandlers_SwitchingActing.rb | 71 -------------- Data/Scripts/011_Battle/005_AI/103_AIMove.rb | 30 ++---- 9 files changed, 249 insertions(+), 179 deletions(-) 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 85b546935..01c404432 100644 --- a/Data/Scripts/011_Battle/005_AI/004_AI_ChooseMove.rb +++ b/Data/Scripts/011_Battle/005_AI/004_AI_ChooseMove.rb @@ -47,8 +47,8 @@ class Battle::AI 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. + # 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: Should this sometimes consider targeting an ally? See def 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 6a8a2114f..64aec468e 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 @@ -617,6 +617,15 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute", next true if user.hp <= [user.totalhp / 4, 1].max } ) +Battle::AI::Handlers::MoveEffectScore.add("UserMakeSubstitute", + proc { |score, move, user, ai, battle| + # Prefer more the higher the user's HP + score += 8.0 * user.hp / user.totalhp + # TODO: Predict incoming damage, and prefer if it's greater than + # user.totalhp / 4? + next score + } +) #=============================================================================== # @@ -688,3 +697,74 @@ Battle::AI::Handlers::MoveEffectScore.add("BurnAttackerBeforeUserActs", next score } ) + +#=============================================================================== +# TODO: Review score modifiers. +#=============================================================================== +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn", + proc { |move, user, target, ai, battle| + next true if target.hp <= 1 + } +) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn", + proc { |score, move, user, target, ai, battle| + next score + 20 if target.hp >= target.totalhp / 2 + } +) + +#=============================================================================== +# TODO: Review score modifiers. +#=============================================================================== +Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP", + proc { |score, move, user, ai, battle| + next score - 40 + } +) + +#=============================================================================== +# TODO: Review score modifiers. +#=============================================================================== +Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", + "StartShadowSkyWeather") +Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather", + proc { |score, move, user, ai, battle| + next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || + battle.pbCheckGlobalAbility(:CLOUDNINE) + score += 10 if battle.field.weather != :None # Prefer replacing another weather + score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP + next score + } +) + +#=============================================================================== +# TODO: Review score modifiers. +#=============================================================================== +Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens", + proc { |move, user, ai, battle| + will_fail = true + battle.sides.each do |side| + will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 || + side.effects[PBEffects::Reflect] > 0 || + side.effects[PBEffects::LightScreen] > 0 || + side.effects[PBEffects::Safeguard] > 0 + end + next will_fail + } +) +Battle::AI::Handlers::MoveEffectScore.add("RemoveAllScreens", + proc { |score, move, user, ai, battle| + if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 || + user.pbOpposingSide.effects[PBEffects::Reflect] > 0 || + user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 || + user.pbOpposingSide.effects[PBEffects::Safeguard] > 0 + score += 30 + end + if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 || + user.pbOwnSide.effects[PBEffects::Reflect] > 0 || + user.pbOwnSide.effects[PBEffects::LightScreen] > 0 || + user.pbOwnSide.effects[PBEffects::Safeguard] > 0 + score -= 70 + end + next score + } +) 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 289a99bbb..168006e51 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 @@ -506,11 +506,24 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1TrapUserInBattle", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("StartRaiseUserAtk1WhenDamaged", proc { |score, move, user, ai, battle| - next score + 25 if user.effects[PBEffects::Rage] + # Ignore the stat-raising effect if user is at a low HP and likely won't + # benefit from it + next score if user.hp < user.totalhp / 3 + # TODO: Check whether any foe has damaging moves that will trigger the stat + # raise? + # Prefer if user benefits from a raised Attack stat + if user.check_for_move { |m| m.physicalMove?(m.type) && + m.function != "UseUserDefenseInsteadOfUserAttack" && + m.function != "UseTargetAttackInsteadOfUserAttack" } + score += 8 + elsif user.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" } + score += 4 + end + next score } ) @@ -596,7 +609,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("LowerUserAttack1", "LowerUserDefSpDefSpd1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack1", proc { |move, user, target, ai, battle| @@ -611,7 +624,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetAttack1", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack2ConfuseTarget", proc { |move, user, target, ai, battle| @@ -621,7 +634,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack2Confu ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetAttack2ConfuseTarget", proc { |score, move, user, target, ai, battle| - next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false, move.move) + if !target.has_active_ability?(:CONTRARY) || @battle.moldBreaker + next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false, move.move) + end # Score for stat raise score = ai.get_score_for_target_stat_raise(score, target, [:ATTACK, 2], false) # Score for confusing the target @@ -631,7 +646,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetAttack2Confus ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetSpAtk1ConfuseTarget", proc { |move, user, target, ai, battle| @@ -641,7 +656,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetSpAtk1Confus ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetSpAtk1ConfuseTarget", proc { |score, move, user, target, ai, battle| - next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false, move.move) + if !target.has_active_ability?(:CONTRARY) || @battle.moldBreaker + next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false, move.move) + end # Score for stat raise score = ai.get_score_for_target_stat_raise(score, target, [:SPECIAL_ATTACK, 1], false) # Score for confusing the target @@ -1155,10 +1172,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.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::MoveEffectAgainstTargetScore.add("UserTargetSwapAtkSpAtkStages", proc { |score, move, user, target, ai, battle| @@ -1166,12 +1180,22 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAtkSpAtkSt user_spatk = user.stages[:SPECIAL_ATTACK] target_attack = target.stages[:ATTACK] target_spatk = target.stages[:SPECIAL_ATTACK] + # Useless if both of the user's stats are already higher than the target's 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 - # TODO: Check whether the user has physical/special moves that will be - # stronger after the swap, and vice versa for the target? - score += (target_attack - user_attack) * 5 - score += (target_spatk - user_spatk) * 5 + # Useless if neither the user nor the target make use of these stats + useless_attack = !user.check_for_move { |m| m.physicalMove?(m.type) && + m.function != "UseUserDefenseInsteadOfUserAttack" && + m.function != "UseTargetAttackInsteadOfUserAttack" } + useless_attack = false if useless_attack && + target.check_for_move { |m| m.physicalMove?(m.type) && + m.function != "UseUserDefenseInsteadOfUserAttack" && + m.function != "UseTargetAttackInsteadOfUserAttack" } + useless_spatk = !user.check_for_move { |m| m.specialMove?(m.type) } + useless_spatk = false if useless_spatk && target.check_for_move { |m| m.specialMove?(m.type) } + next Battle::AI::MOVE_USELESS_SCORE if useless_attack && useless_spatk + # Apply score modifiers + score += (target_attack - user_attack) * 5 if !useless_attack + score += (target_spatk - user_spatk) * 5 if !useless_spatk next score } ) @@ -1234,7 +1258,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserCopyTargetStatStages score += stagediff * 10 equal = false if stagediff != 0 end - next 60 if equal # No stat changes + next Battle::AI::MOVE_USELESS_SCORE if equal # No stat changes next score } ) @@ -1248,17 +1272,19 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserCopyTargetStatStages #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserStealTargetPositiveStatStages", proc { |score, move, user, target, ai, battle| - numStages = 0 + num_stages = 0 GameData::Stat.each_battle do |s| - next if target.stages[s.id] <= 0 - numStages += target.stages[s.id] + num_stages += target.stages[s.id] if target.stages[s.id] > 0 end - next score + numStages * 20 + if num_stages > 0 + next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:CONTRARY) + score += num_stages * 5 + end + next score } ) #=============================================================================== -# 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. @@ -1270,14 +1296,14 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.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 - numneg = 0 + pos_stages = 0 + neg_stages = 0 GameData::Stat.each_battle do |s| - numpos += target.stages[s.id] if target.stages[s.id] > 0 - numneg += target.stages[s.id] if target.stages[s.id] < 0 + pos_stages += target.stages[s.id] if target.stages[s.id] > 0 + neg_stages += target.stages[s.id] if target.stages[s.id] < 0 end - next score + (numpos - numneg) * 10 + next Battle::AI::MOVE_USELESS_SCORE if pos_stages == 0 + next score + (pos_stages - neg_stages) * 10 } ) @@ -1289,16 +1315,17 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("InvertTargetStatStages", #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ResetTargetStatStages", proc { |score, move, user, target, ai, battle| - next 0 if target.effects[PBEffects::Substitute] > 0 avg = 0 - anyChange = false + pos_change = false + any_change = false GameData::Stat.each_battle do |s| next if target.stages[s.id] == 0 avg += target.stages[s.id] - anyChange = true + pos_change = true if target.stages[s.id] > 0 + any_change = true end - next 0 if !anyChange - next score + avg * 10 + next Battle::AI::MOVE_USELESS_SCORE if !any_change || !pos_change + next score + avg * 5 } ) 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 fb0d0504f..d6eda6ec1 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 @@ -688,7 +688,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AttractTarget", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment", proc { |move, user, ai, battle| @@ -706,6 +706,38 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment", next true if !GameData::Type.exists?(new_type) || !user.battler.pbHasOtherType?(new_type) } ) +Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesBasedOnEnvironment", + proc { |score, move, user, ai, battle| + # Determine the new type + new_type = nil + terr_types = Battle::Move::SetUserTypesBasedOnEnvironment::TERRAIN_TYPES + terr_type = terr_types[battle.field.terrain] + if terr_type && GameData::Type.exists?(terr_type) + new_type = terr_type + else + env_types = Battle::Move::SetUserTypesBasedOnEnvironment::ENVIRONMENT_TYPES + new_type = env_types[battle.environment] || :NORMAL + new_type = :NORMAL if !GameData::Type.exists?(new_type) + end + # Check if any user's moves will get STAB because of the type change + if user.check_for_move { |m| m.damagingMove? && m.pbCalcType(user.battler) == new_type } + score += 8 + end + # Check if any user's moves will lose STAB because of the type change + user.battler.pbTypes(true).each do |type| + next if type == new_type + if user.check_for_move { |m| m.damagingMove? && m.pbCalcType(user.battler) == type } + score -= 8 + end + end + # NOTE: Other things could be considered, like the foes' moves' + # effectivenesses against the current and new user's type(s), and + # which set of STAB is more beneficial. However, I'm keeping this + # simple because, if you know this move, you probably want to use it + # just because. + next score + } +) #=============================================================================== # @@ -781,7 +813,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserTypesToUserMoveTy end # Check if any user's moves will get STAB because of the type change possible_types.each do |type| - if user.check_for_move { |m| m.damagingMove? } + if user.check_for_move { |m| m.damagingMove? && m.pbCalcType(user.battler) == type } score += 10 break end @@ -1234,7 +1266,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TransformUserIntoTarget", proc { |move, user, target, ai, battle| @@ -1245,6 +1277,6 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TransformUserIntoTarget ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TransformUserIntoTarget", proc { |score, move, user, target, ai, battle| - next score - 10 + next score - 5 } ) 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 acef4e172..69d7bcdf0 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 @@ -362,26 +362,40 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetInSky", "DoublePowerIfAllyFaintedLastTurn") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn", 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) + # Prefer if user is slower than its foe(s) and the foe(s) can attack + ai.each_foe_battler(user.side) do |b, i| + next if user.faster_than?(b) || (b.status == :SLEEP && b.statusCount > 1) || + b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 || + b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0 + score += 4 + end + next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostHPThisTurn", proc { |score, move, user, target, ai, battle| - next score + 15 if battle.pbOpposingBattlerCount(user.battler) > 1 + # Prefer if a user's ally is faster than the user and that ally can attack + ai.each_foe_battler(target.side) do |b, i| + next if i == user.index + next if user.faster_than?(b) || (b.status == :SLEEP && b.statusCount > 1) || + b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 || + b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0 + score += 4 + end + next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== # DoublePowerIfUserStatsLoweredThisTurn @@ -439,18 +453,31 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CannotMakeTargetFaint", ) #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn", 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 - else - score -= user.effects[PBEffects::ProtectRate] * 10 + next Battle::AI::MOVE_USELESS_SCORE if user.rough_end_of_round_damage > 0 + # Prefer for each foe that can attack + useless = true + ai.each_foe_battler(user.side) do |b, i| + next if (b.status == :SLEEP && b.statusCount > 1) || + b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 || + b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0 + useless = false + score += 4 end + next Battle::AI::MOVE_USELESS_SCORE if useless + # Don't prefer if user has high HP, prefer if user has lower HP + if user.hp >= user.totalhp / 2 + score -= 8 + elsif user.hp >= user.totalhp / 8 + score += 4 + end + # Don't prefer if the user used a protection move last turn, making this one + # less likely to work + score -= (user.effects[PBEffects::ProtectRate] - 1) * 8 + # TODO: Check for combos with Flail/Endeavor? next score } ) @@ -635,16 +662,21 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveScreens", #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("ProtectUser", 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 += 12 if user.turnCount == 0 + # Prefer for each foe that can attack + useless = true + ai.each_foe_battler(user.side) do |b, i| + next if (b.status == :SLEEP && b.statusCount > 1) || + b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 || + b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0 + useless = false + score += 4 + score += 4 if b.effects[PBEffects::TwoTurnAttack] end + next Battle::AI::MOVE_USELESS_SCORE if useless + # Don't prefer if the user used a protection move last turn, making this one + # less likely to work + score -= (user.effects[PBEffects::ProtectRate] - 1) * 8 next score } ) 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 d689386c3..9e2ccee69 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 @@ -54,7 +54,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesFlinchTarget" ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("HitTwoTimesTargetThenTargetAlly", proc { |power, move, user, target, ai, battle| 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 4c58c9ea1..4b06e2ac9 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 @@ -31,36 +31,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RedirectAllMovesToTarget ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CannotBeRedirected", - proc { |score, move, user, target, ai, battle| - next score if target.battler.allAllies.length == 0 - redirection = false - user.battler.allOpposing.each do |b| - next if b.index == target.index - if b.effects[PBEffects::RagePowder] || - b.effects[PBEffects::Spotlight] > 0 || - b.effects[PBEffects::FollowMe] > 0 || - (b.hasActiveAbility?(:LIGHTNINGROD) && move.rough_type == :ELECTRIC) || - (b.hasActiveAbility?(:STORMDRAIN) && move.rough_type == :WATER) - redirection = true - break - end - end - score += 20 if redirection && ai.trainer.medium_skill? - next score - } -) +# CannotBeRedirected #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget", proc { |power, move, user, target, ai, battle| next 50 # Average power, ish } ) +Battle::AI::Handlers::MoveEffectScore.add("RandomlyDamageOrHealTarget", + proc { |score, move, user, ai, battle| + # Generaly don't prefer this move, as it may heal the target instead + next score - 8 + } +) #=============================================================================== # 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 7475ebf3a..0de5e7121 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 @@ -511,74 +511,3 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser", next true if user.effects[PBEffects::Imprison] } ) - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn", - proc { |move, user, target, ai, battle| - next true if target.hp <= 1 - } -) -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn", - proc { |score, move, user, target, ai, battle| - next score + 20 if target.hp >= target.totalhp / 2 - } -) - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP", - proc { |score, move, user, ai, battle| - next score - 40 - } -) - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", - "StartShadowSkyWeather") -Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather", - proc { |score, move, user, ai, battle| - next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || - battle.pbCheckGlobalAbility(:CLOUDNINE) - score += 10 if battle.field.weather != :None # Prefer replacing another weather - score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP - next score - } -) - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens", - proc { |move, user, ai, battle| - will_fail = true - battle.sides.each do |side| - will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 || - side.effects[PBEffects::Reflect] > 0 || - side.effects[PBEffects::LightScreen] > 0 || - side.effects[PBEffects::Safeguard] > 0 - end - next will_fail - } -) -Battle::AI::Handlers::MoveEffectScore.add("RemoveAllScreens", - proc { |score, move, user, ai, battle| - if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 || - user.pbOpposingSide.effects[PBEffects::Reflect] > 0 || - user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 || - user.pbOpposingSide.effects[PBEffects::Safeguard] > 0 - score += 30 - end - if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 || - user.pbOwnSide.effects[PBEffects::Reflect] > 0 || - user.pbOwnSide.effects[PBEffects::LightScreen] > 0 || - user.pbOwnSide.effects[PBEffects::Safeguard] > 0 - score -= 70 - end - next score - } -) diff --git a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb index 075bb9f3f..3e3c89593 100644 --- a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb +++ b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb @@ -389,6 +389,12 @@ class Battle::AI::AIMove user_battler = user.battler target = @ai.target target_battler = target.battler + # OHKO move accuracy + if @move.is_a?(Battle::Move::OHKO) + ret = self.accuracy + user.level - target.level + ret -= 10 if function == "OHKOIce" && !user.pbHasType?(:ICE) + return [ret, 0].max + end # "Always hit" effects and "always hit" accuracy if @ai.trainer.medium_skill? return 100 if target.effects[PBEffects::Telekinesis] > 0 @@ -427,30 +433,6 @@ class Battle::AI::AIMove def apply_rough_accuracy_modifiers(user, target, calc_type, modifiers) user_battler = user.battler target_battler = target.battler - # OHKO special calculation - if @ai.trainer.medium_skill? - # TODO: This is insufficient for OHKO moves, as they should also ignore - # effects like Telekinesis and Minimize but def rough_accuracy - # treats them as applying to OHKO moves. - case function - when "OHKO", "OHKOHitsUndergroundTarget" - modifiers[:base_accuracy] = self.accuracy + user.level - target.level - modifiers[:base_accuracy] = -1 if target.level > user.level - modifiers[:base_accuracy] = -1 if !@ai.battle.moldBreaker && target.has_active_ability?(:STURDY) - modifiers[:accuracy_stage] = 6 - modifiers[:evasion_stage] = 6 - return - when "OHKOIce" - modifiers[:base_accuracy] = self.accuracy + user.level - target.level - modifiers[:base_accuracy] -= 10 if !user.has_type?(:ICE) - modifiers[:base_accuracy] = -1 if modifiers[:base_accuracy] == 0 - modifiers[:base_accuracy] = -1 if target.level > user.level - modifiers[:base_accuracy] = -1 if !@ai.battle.moldBreaker && target.has_active_ability?(:STURDY) - modifiers[:accuracy_stage] = 6 - modifiers[:evasion_stage] = 6 - return - end - end # Ability effects that alter accuracy calculation if user.ability_active? Battle::AbilityEffects.triggerAccuracyCalcFromUser(