Yet more AI function code rewrites

This commit is contained in:
Maruno17
2022-12-31 15:26:41 +00:00
parent 1258e4b9c9
commit dd7cd414f0
9 changed files with 249 additions and 179 deletions

View File

@@ -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

View File

@@ -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
}
)

View File

@@ -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
}
)

View File

@@ -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
}
)

View File

@@ -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
}
)

View File

@@ -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|

View File

@@ -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
}
)
#===============================================================================
#

View File

@@ -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
}
)

View File

@@ -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(