mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-08 13:44:59 +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
|
when 1 # One target to be chosen by the trainer
|
||||||
# Includes: Foe, NearAlly, NearFoe, NearOther, Other, RandomNearFoe, UserOrNearAlly
|
# Includes: Foe, NearAlly, NearFoe, NearOther, Other, RandomNearFoe, UserOrNearAlly
|
||||||
# TODO: Figure out first which targets are valid. Includes the call to
|
# TODO: Figure out first which targets are valid. Includes the call to
|
||||||
# pbMoveCanTarget?, but also includes move-redirecting effects like
|
# pbMoveCanTarget?, but also includes move-redirecting effects
|
||||||
# Lightning Rod. Skip any battlers that can't be targeted.
|
# like Lightning Rod. Skip any battlers that can't be targeted.
|
||||||
@battle.allBattlers.each do |b|
|
@battle.allBattlers.each do |b|
|
||||||
next if !@battle.pbMoveCanTarget?(@user.battler.index, b.index, target_data)
|
next if !@battle.pbMoveCanTarget?(@user.battler.index, b.index, target_data)
|
||||||
# TODO: Should this sometimes consider targeting an ally? See def
|
# 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
|
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
|
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",
|
Battle::AI::Handlers::MoveEffectScore.add("StartRaiseUserAtk1WhenDamaged",
|
||||||
proc { |score, move, user, ai, battle|
|
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")
|
"LowerUserDefSpDefSpd1")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack1",
|
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack1",
|
||||||
proc { |move, user, target, ai, battle|
|
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",
|
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack2ConfuseTarget",
|
||||||
proc { |move, user, target, ai, battle|
|
proc { |move, user, target, ai, battle|
|
||||||
@@ -621,7 +634,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetAttack2Confu
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetAttack2ConfuseTarget",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetAttack2ConfuseTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
if !target.has_active_ability?(:CONTRARY) || @battle.moldBreaker
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false, move.move)
|
next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false, move.move)
|
||||||
|
end
|
||||||
# Score for stat raise
|
# Score for stat raise
|
||||||
score = ai.get_score_for_target_stat_raise(score, target, [:ATTACK, 2], false)
|
score = ai.get_score_for_target_stat_raise(score, target, [:ATTACK, 2], false)
|
||||||
# Score for confusing the target
|
# 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",
|
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetSpAtk1ConfuseTarget",
|
||||||
proc { |move, user, target, ai, battle|
|
proc { |move, user, target, ai, battle|
|
||||||
@@ -641,7 +656,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaiseTargetSpAtk1Confus
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetSpAtk1ConfuseTarget",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetSpAtk1ConfuseTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
if !target.has_active_ability?(:CONTRARY) || @battle.moldBreaker
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false, move.move)
|
next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanConfuse?(user.battler, false, move.move)
|
||||||
|
end
|
||||||
# Score for stat raise
|
# Score for stat raise
|
||||||
score = ai.get_score_for_target_stat_raise(score, target, [:SPECIAL_ATTACK, 1], false)
|
score = ai.get_score_for_target_stat_raise(score, target, [:SPECIAL_ATTACK, 1], false)
|
||||||
# Score for confusing the target
|
# 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",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAtkSpAtkStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
@@ -1166,12 +1180,22 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAtkSpAtkSt
|
|||||||
user_spatk = user.stages[:SPECIAL_ATTACK]
|
user_spatk = user.stages[:SPECIAL_ATTACK]
|
||||||
target_attack = target.stages[:ATTACK]
|
target_attack = target.stages[:ATTACK]
|
||||||
target_spatk = target.stages[:SPECIAL_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 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
|
# Useless if neither the user nor the target make use of these stats
|
||||||
# TODO: Check whether the user has physical/special moves that will be
|
useless_attack = !user.check_for_move { |m| m.physicalMove?(m.type) &&
|
||||||
# stronger after the swap, and vice versa for the target?
|
m.function != "UseUserDefenseInsteadOfUserAttack" &&
|
||||||
score += (target_attack - user_attack) * 5
|
m.function != "UseTargetAttackInsteadOfUserAttack" }
|
||||||
score += (target_spatk - user_spatk) * 5
|
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
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1234,7 +1258,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserCopyTargetStatStages
|
|||||||
score += stagediff * 10
|
score += stagediff * 10
|
||||||
equal = false if stagediff != 0
|
equal = false if stagediff != 0
|
||||||
end
|
end
|
||||||
next 60 if equal # No stat changes
|
next Battle::AI::MOVE_USELESS_SCORE if equal # No stat changes
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1248,17 +1272,19 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserCopyTargetStatStages
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserStealTargetPositiveStatStages",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserStealTargetPositiveStatStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
numStages = 0
|
num_stages = 0
|
||||||
GameData::Stat.each_battle do |s|
|
GameData::Stat.each_battle do |s|
|
||||||
next if target.stages[s.id] <= 0
|
num_stages += target.stages[s.id] if target.stages[s.id] > 0
|
||||||
numStages += target.stages[s.id]
|
|
||||||
end
|
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,
|
# 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
|
# since the score will be inverted elsewhere due to the target being an
|
||||||
# ally.
|
# ally.
|
||||||
@@ -1270,14 +1296,14 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("InvertTargetStatStages"
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("InvertTargetStatStages",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("InvertTargetStatStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next 0 if target.effects[PBEffects::Substitute] > 0
|
pos_stages = 0
|
||||||
numpos = 0
|
neg_stages = 0
|
||||||
numneg = 0
|
|
||||||
GameData::Stat.each_battle do |s|
|
GameData::Stat.each_battle do |s|
|
||||||
numpos += target.stages[s.id] if target.stages[s.id] > 0
|
pos_stages += target.stages[s.id] if target.stages[s.id] > 0
|
||||||
numneg += target.stages[s.id] if target.stages[s.id] < 0
|
neg_stages += target.stages[s.id] if target.stages[s.id] < 0
|
||||||
end
|
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",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ResetTargetStatStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next 0 if target.effects[PBEffects::Substitute] > 0
|
|
||||||
avg = 0
|
avg = 0
|
||||||
anyChange = false
|
pos_change = false
|
||||||
|
any_change = false
|
||||||
GameData::Stat.each_battle do |s|
|
GameData::Stat.each_battle do |s|
|
||||||
next if target.stages[s.id] == 0
|
next if target.stages[s.id] == 0
|
||||||
avg += target.stages[s.id]
|
avg += target.stages[s.id]
|
||||||
anyChange = true
|
pos_change = true if target.stages[s.id] > 0
|
||||||
|
any_change = true
|
||||||
end
|
end
|
||||||
next 0 if !anyChange
|
next Battle::AI::MOVE_USELESS_SCORE if !any_change || !pos_change
|
||||||
next score + avg * 10
|
next score + avg * 5
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -688,7 +688,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AttractTarget",
|
|||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment",
|
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment",
|
||||||
proc { |move, user, ai, battle|
|
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)
|
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
|
end
|
||||||
# Check if any user's moves will get STAB because of the type change
|
# Check if any user's moves will get STAB because of the type change
|
||||||
possible_types.each do |type|
|
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
|
score += 10
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -1234,7 +1266,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
|
|||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TransformUserIntoTarget",
|
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TransformUserIntoTarget",
|
||||||
proc { |move, user, target, ai, battle|
|
proc { |move, user, target, ai, battle|
|
||||||
@@ -1245,6 +1277,6 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TransformUserIntoTarget
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TransformUserIntoTarget",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TransformUserIntoTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score - 10
|
next score - 5
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -362,26 +362,40 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetInSky",
|
|||||||
"DoublePowerIfAllyFaintedLastTurn")
|
"DoublePowerIfAllyFaintedLastTurn")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn",
|
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn",
|
||||||
proc { |score, move, user, ai, battle|
|
proc { |score, move, user, ai, battle|
|
||||||
# TODO: Remove target from this; consider the speeds of all foes instead.
|
# Prefer if user is slower than its foe(s) and the foe(s) can attack
|
||||||
# next score + 15 if target.faster_than?(user)
|
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",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostHPThisTurn",
|
||||||
proc { |score, move, user, target, ai, battle|
|
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
|
# 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",
|
Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
|
||||||
proc { |score, move, user, ai, battle|
|
proc { |score, move, user, ai, battle|
|
||||||
score -= 10 if user.hp > user.totalhp / 2
|
next Battle::AI::MOVE_USELESS_SCORE if user.rough_end_of_round_damage > 0
|
||||||
if ai.trainer.medium_skill?
|
# Prefer for each foe that can attack
|
||||||
score -= 20 if user.effects[PBEffects::ProtectRate] > 1
|
useless = true
|
||||||
# score -= 20 if target.effects[PBEffects::HyperBeam] > 0
|
ai.each_foe_battler(user.side) do |b, i|
|
||||||
else
|
next if (b.status == :SLEEP && b.statusCount > 1) ||
|
||||||
score -= user.effects[PBEffects::ProtectRate] * 10
|
b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 ||
|
||||||
|
b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0
|
||||||
|
useless = false
|
||||||
|
score += 4
|
||||||
end
|
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
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -635,16 +662,21 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveScreens",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
|
Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
|
||||||
proc { |score, move, user, ai, battle|
|
proc { |score, move, user, ai, battle|
|
||||||
if user.effects[PBEffects::ProtectRate] > 1 # ||
|
score += 12 if user.turnCount == 0
|
||||||
# target.effects[PBEffects::HyperBeam] > 0
|
# Prefer for each foe that can attack
|
||||||
score -= 50
|
useless = true
|
||||||
else
|
ai.each_foe_battler(user.side) do |b, i|
|
||||||
if ai.trainer.medium_skill?
|
next if (b.status == :SLEEP && b.statusCount > 1) ||
|
||||||
score -= user.effects[PBEffects::ProtectRate] * 40
|
b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 ||
|
||||||
end
|
b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0
|
||||||
score += 50 if user.turnCount == 0
|
useless = false
|
||||||
# score += 30 if target.effects[PBEffects::TwoTurnAttack]
|
score += 4
|
||||||
|
score += 4 if b.effects[PBEffects::TwoTurnAttack]
|
||||||
end
|
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
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesFlinchTarget"
|
|||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("HitTwoTimesTargetThenTargetAlly",
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoTimesTargetThenTargetAlly",
|
||||||
proc { |power, move, user, target, ai, battle|
|
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",
|
# 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
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget",
|
Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget",
|
||||||
proc { |power, move, user, target, ai, battle|
|
proc { |power, move, user, target, ai, battle|
|
||||||
next 50 # Average power, ish
|
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]
|
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
|
user_battler = user.battler
|
||||||
target = @ai.target
|
target = @ai.target
|
||||||
target_battler = target.battler
|
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
|
# "Always hit" effects and "always hit" accuracy
|
||||||
if @ai.trainer.medium_skill?
|
if @ai.trainer.medium_skill?
|
||||||
return 100 if target.effects[PBEffects::Telekinesis] > 0
|
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)
|
def apply_rough_accuracy_modifiers(user, target, calc_type, modifiers)
|
||||||
user_battler = user.battler
|
user_battler = user.battler
|
||||||
target_battler = target.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
|
# Ability effects that alter accuracy calculation
|
||||||
if user.ability_active?
|
if user.ability_active?
|
||||||
Battle::AbilityEffects.triggerAccuracyCalcFromUser(
|
Battle::AbilityEffects.triggerAccuracyCalcFromUser(
|
||||||
|
|||||||
Reference in New Issue
Block a user