mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Yet more AI function code rewrites
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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|
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user