mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-09 14:14:59 +00:00
AI rewrites of ability-changing function codes, OHKO codes and binding codes
This commit is contained in:
@@ -292,6 +292,16 @@ class Battle::AI
|
||||
score += 15 * inc_mult
|
||||
break
|
||||
end
|
||||
# TODO: Prefer if the user is able to cause flinching (moves that flinch,
|
||||
# or has King's Rock/Stench).
|
||||
# Prefer if the user has Electro Ball or Power Trip/Stored Power
|
||||
moves_that_prefer_high_speed = [
|
||||
"PowerHigherWithUserFasterThanTarget",
|
||||
"PowerHigherWithUserPositiveStatStages"
|
||||
]
|
||||
if @user.check_for_move { |m| moves_that_prefer_high_speed.include?(m.function) }
|
||||
score += 8 * inc_mult
|
||||
end
|
||||
# Don't prefer if any foe has Gyro Ball
|
||||
each_foe_battler(@user.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetFasterThanUser" }
|
||||
@@ -956,4 +966,295 @@ class Battle::AI
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Returns a value indicating how beneficial the given ability will be to the
|
||||
# given battler if it has it.
|
||||
# Return values are typically between -10 and +10. 0 is indifferent, positive
|
||||
# values mean the battler benefits, negative values mean the battler suffers.
|
||||
#=============================================================================
|
||||
# These values are taken from the Complete-Fire-Red-Upgrade decomp here:
|
||||
# https://github.com/Skeli789/Complete-Fire-Red-Upgrade/blob/f7f35becbd111c7e936b126f6328fc52d9af68c8/src/ability_battle_effects.c#L41
|
||||
BASE_ABILITY_RATINGS = {
|
||||
:ADAPTABILITY => 8,
|
||||
:AERILATE => 8,
|
||||
:AFTERMATH => 5,
|
||||
:AIRLOCK => 5,
|
||||
:ANALYTIC => 5,
|
||||
:ANGERPOINT => 4,
|
||||
:ANTICIPATION => 2,
|
||||
:ARENATRAP => 9,
|
||||
:AROMAVEIL => 3,
|
||||
# :ASONECHILLINGNEIGH => 0,
|
||||
# :ASONEGRIMNEIGH => 0,
|
||||
:AURABREAK => 3,
|
||||
:BADDREAMS => 4,
|
||||
# :BALLFETCH => 0,
|
||||
# :BATTERY => 0,
|
||||
:BATTLEARMOR => 2,
|
||||
:BATTLEBOND => 6,
|
||||
:BEASTBOOST => 7,
|
||||
:BERSERK => 5,
|
||||
:BIGPECKS => 1,
|
||||
:BLAZE => 5,
|
||||
:BULLETPROOF => 7,
|
||||
:CHEEKPOUCH => 4,
|
||||
# :CHILLINGNEIGH => 0,
|
||||
:CHLOROPHYLL => 6,
|
||||
:CLEARBODY => 4,
|
||||
:CLOUDNINE => 5,
|
||||
:COLORCHANGE => 2,
|
||||
:COMATOSE => 6,
|
||||
:COMPETITIVE => 5,
|
||||
:COMPOUNDEYES => 7,
|
||||
:CONTRARY => 8,
|
||||
:CORROSION => 5,
|
||||
:COTTONDOWN => 3,
|
||||
# :CURIOUSMEDICINE => 0,
|
||||
:CURSEDBODY => 4,
|
||||
:CUTECHARM => 2,
|
||||
:DAMP => 2,
|
||||
:DANCER => 5,
|
||||
:DARKAURA => 6,
|
||||
:DAUNTLESSSHIELD => 3,
|
||||
:DAZZLING => 5,
|
||||
:DEFEATIST => -1,
|
||||
:DEFIANT => 5,
|
||||
:DELTASTREAM => 10,
|
||||
:DESOLATELAND => 10,
|
||||
:DISGUISE => 8,
|
||||
:DOWNLOAD => 7,
|
||||
:DRAGONSMAW => 8,
|
||||
:DRIZZLE => 9,
|
||||
:DROUGHT => 9,
|
||||
:DRYSKIN => 6,
|
||||
:EARLYBIRD => 4,
|
||||
:EFFECTSPORE => 4,
|
||||
:ELECTRICSURGE => 8,
|
||||
:EMERGENCYEXIT => 3,
|
||||
:FAIRYAURA => 6,
|
||||
:FILTER => 6,
|
||||
:FLAMEBODY => 4,
|
||||
:FLAREBOOST => 5,
|
||||
:FLASHFIRE => 6,
|
||||
:FLOWERGIFT => 4,
|
||||
# :FLOWERVEIL => 0,
|
||||
:FLUFFY => 5,
|
||||
:FORECAST => 6,
|
||||
:FOREWARN => 2,
|
||||
# :FRIENDGUARD => 0,
|
||||
:FRISK => 3,
|
||||
:FULLMETALBODY => 4,
|
||||
:FURCOAT => 7,
|
||||
:GALEWINGS => 6,
|
||||
:GALVANIZE => 8,
|
||||
:GLUTTONY => 3,
|
||||
:GOOEY => 5,
|
||||
:GORILLATACTICS => 4,
|
||||
:GRASSPELT => 2,
|
||||
:GRASSYSURGE => 8,
|
||||
# :GRIMNEIGH => 0,
|
||||
:GULPMISSLE => 3,
|
||||
:GUTS => 6,
|
||||
:HARVEST => 5,
|
||||
# :HEALER => 0,
|
||||
:HEATPROOF => 5,
|
||||
:HEAVYMETAL => -1,
|
||||
# :HONEYGATHER => 0,
|
||||
:HUGEPOWER => 10,
|
||||
:HUNGERSWITCH => 2,
|
||||
:HUSTLE => 7,
|
||||
:HYDRATION => 4,
|
||||
:HYPERCUTTER => 3,
|
||||
:ICEBODY => 3,
|
||||
:ICEFACE => 4,
|
||||
:ICESCALES => 7,
|
||||
# :ILLUMINATE => 0,
|
||||
:ILLUSION => 8,
|
||||
:IMMUNITY => 4,
|
||||
:IMPOSTER => 9,
|
||||
:INFILTRATOR => 6,
|
||||
:INNARDSOUT => 5,
|
||||
:INNERFOCUS => 2,
|
||||
:INSOMNIA => 4,
|
||||
:INTIMIDATE => 7,
|
||||
:INTREPIDSWORD => 3,
|
||||
:IRONBARBS => 6,
|
||||
:IRONFIST => 6,
|
||||
:JUSTIFIED => 4,
|
||||
:KEENEYE => 1,
|
||||
:KLUTZ => -1,
|
||||
:LEAFGUARD => 2,
|
||||
:LEVITATE => 7,
|
||||
:LIBERO => 8,
|
||||
:LIGHTMETAL => 2,
|
||||
:LIGHTNINGROD => 7,
|
||||
:LIMBER => 3,
|
||||
:LIQUIDOOZE => 3,
|
||||
:LIQUIDVOICE => 5,
|
||||
:LONGREACH => 3,
|
||||
:MAGICBOUNCE => 9,
|
||||
:MAGICGUARD => 9,
|
||||
:MAGICIAN => 3,
|
||||
:MAGMAARMOR => 1,
|
||||
:MAGNETPULL => 9,
|
||||
:MARVELSCALE => 5,
|
||||
:MEGALAUNCHER => 7,
|
||||
:MERCILESS => 4,
|
||||
:MIMICRY => 2,
|
||||
# :MINUS => 0,
|
||||
:MIRRORARMOR => 6,
|
||||
:MISTYSURGE => 8,
|
||||
:MOLDBREAKER => 7,
|
||||
:MOODY => 10,
|
||||
:MOTORDRIVE => 6,
|
||||
:MOXIE => 7,
|
||||
:MULTISCALE => 8,
|
||||
:MULTITYPE => 8,
|
||||
:MUMMY => 5,
|
||||
:NATURALCURE => 7,
|
||||
:NEUROFORCE => 6,
|
||||
:NEUTRALIZINGGAS => 5,
|
||||
:NOGUARD => 8,
|
||||
:NORMALIZE => -1,
|
||||
:OBLIVIOUS => 2,
|
||||
:OVERCOAT => 5,
|
||||
:OVERGROW => 5,
|
||||
:OWNTEMPO => 3,
|
||||
:PARENTALBOND => 10,
|
||||
:PASTELVEIL => 4,
|
||||
:PERISHBODY => -1,
|
||||
:PICKPOCKET => 3,
|
||||
:PICKUP => 1,
|
||||
:PIXILATE => 8,
|
||||
# :PLUS => 0,
|
||||
:POISONHEAL => 8,
|
||||
:POISONPOINT => 4,
|
||||
:POISONTOUCH => 4,
|
||||
:POWERCONSTRUCT => 10,
|
||||
# :POWEROFALCHEMY => 0,
|
||||
:POWERSPOT => 2,
|
||||
:PRANKSTER => 8,
|
||||
:PRESSURE => 5,
|
||||
:PRIMORDIALSEA => 10,
|
||||
:PRISMARMOR => 6,
|
||||
:PROPELLORTAIL => 2,
|
||||
:PROTEAN => 8,
|
||||
:PSYCHICSURGE => 8,
|
||||
:PUNKROCK => 2,
|
||||
:PUREPOWER => 10,
|
||||
:QUEENLYMAJESTY => 6,
|
||||
# :QUICKDRAW => 0,
|
||||
:QUICKFEET => 5,
|
||||
:RAINDISH => 3,
|
||||
:RATTLED => 3,
|
||||
# :RECEIVER => 0,
|
||||
:RECKLESS => 6,
|
||||
:REFRIGERATE => 8,
|
||||
:REGENERATOR => 8,
|
||||
:RIPEN => 4,
|
||||
:RIVALRY => 1,
|
||||
:RKSSYSTEM => 8,
|
||||
:ROCKHEAD => 5,
|
||||
:ROUGHSKIN => 6,
|
||||
# :RUNAWAY => 0,
|
||||
:SANDFORCE => 4,
|
||||
:SANDRUSH => 6,
|
||||
:SANDSPIT => 5,
|
||||
:SANDSTREAM => 9,
|
||||
:SANDVEIL => 3,
|
||||
:SAPSIPPER => 7,
|
||||
:SCHOOLING => 6,
|
||||
:SCRAPPY => 6,
|
||||
:SCREENCLEANER => 3,
|
||||
:SERENEGRACE => 8,
|
||||
:SHADOWSHIELD => 8,
|
||||
:SHADOWTAG => 10,
|
||||
:SHEDSKIN => 7,
|
||||
:SHEERFORCE => 8,
|
||||
:SHELLARMOR => 2,
|
||||
:SHIELDDUST => 5,
|
||||
:SHIELDSDOWN => 6,
|
||||
:SIMPLE => 8,
|
||||
:SKILLLINK => 7,
|
||||
:SLOWSTART => -2,
|
||||
:SLUSHRUSH => 5,
|
||||
:SNIPER => 3,
|
||||
:SNOWCLOAK => 3,
|
||||
:SNOWWARNING => 8,
|
||||
:SOLARPOWER => 3,
|
||||
:SOLIDROCK => 6,
|
||||
:SOULHEART => 7,
|
||||
:SOUNDPROOF => 4,
|
||||
:SPEEDBOOST => 9,
|
||||
:STAKEOUT => 6,
|
||||
:STALL => -1,
|
||||
:STALWART => 2,
|
||||
:STAMINA => 6,
|
||||
:STANCECHANGE => 10,
|
||||
:STATIC => 4,
|
||||
:STEADFAST => 2,
|
||||
:STEAMENGINE => 3,
|
||||
:STEELWORKER => 6,
|
||||
:STEELYSPIRIT => 2,
|
||||
:STENCH => 1,
|
||||
:STICKYHOLD => 3,
|
||||
:STORMDRAIN => 7,
|
||||
:STRONGJAW => 6,
|
||||
:STURDY => 6,
|
||||
:SUCTIONCUPS => 2,
|
||||
:SUPERLUCK => 3,
|
||||
:SURGESURFER => 4,
|
||||
:SWARM => 5,
|
||||
:SWEETVEIL => 4,
|
||||
:SWIFTSWIM => 6,
|
||||
# :SYMBIOSIS => 0,
|
||||
:SYNCHRONIZE => 4,
|
||||
:TANGLEDFEET => 2,
|
||||
:TANGLINGHAIR => 5,
|
||||
:TECHNICIAN => 8,
|
||||
# :TELEPATHY => 0,
|
||||
:TERAVOLT => 7,
|
||||
:THICKFAT => 7,
|
||||
:TINTEDLENS => 7,
|
||||
:TORRENT => 5,
|
||||
:TOUGHCLAWS => 7,
|
||||
:TOXICBOOST => 6,
|
||||
:TRACE => 6,
|
||||
:TRANSISTOR => 8,
|
||||
:TRIAGE => 7,
|
||||
:TRUANT => -2,
|
||||
:TURBOBLAZE => 7,
|
||||
:UNAWARE => 6,
|
||||
:UNBURDEN => 7,
|
||||
:UNNERVE => 3,
|
||||
# :UNSEENFIST => 0,
|
||||
:VICTORYSTAR => 6,
|
||||
:VITALSPIRIT => 4,
|
||||
:VOLTABSORB => 7,
|
||||
:WANDERINGSPIRIT => 2,
|
||||
:WATERABSORB => 7,
|
||||
:WATERBUBBLE => 8,
|
||||
:WATERCOMPACTION => 4,
|
||||
:WATERVEIL => 4,
|
||||
:WEAKARMOR => 2,
|
||||
:WHITESMOKE => 4,
|
||||
:WIMPOUT => 3,
|
||||
:WONDERGUARD => 10,
|
||||
:WONDERSKIN => 4,
|
||||
:ZENMODE => -1
|
||||
}
|
||||
|
||||
# TODO: This method assumes the ability isn't being negated. Should it return
|
||||
# 0 if it is? The calculations that call this method separately check
|
||||
# for it being negated, because they need to do something special in
|
||||
# that case, so I think it's okay for this method to ignore negation.
|
||||
def battler_wants_ability?(battler, ability = :NONE)
|
||||
ability = ability.id if !ability.is_a?(Symbol) && ability.respond_to?("id")
|
||||
# TODO: Ideally replace the above list of ratings with context-sensitive
|
||||
# calculations. Should they all go in this method, or should there be
|
||||
# more handlers for each ability?
|
||||
ret = BASE_ABILITY_RATINGS[ability] || 0
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
@@ -916,7 +916,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType",
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimple",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -924,9 +924,23 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimpl
|
||||
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToSimple",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
||||
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
||||
new_ability_rating = ai.battler_wants_ability?(target, :SIMPLE)
|
||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||
if old_ability_rating > new_ability_rating
|
||||
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
|
||||
elsif old_ability_rating < new_ability_rating
|
||||
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToInsomnia",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -934,9 +948,23 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToInsom
|
||||
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToInsomnia",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
||||
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
||||
new_ability_rating = ai.battler_wants_ability?(target, :INSOMNIA)
|
||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||
if old_ability_rating > new_ability_rating
|
||||
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
|
||||
elsif old_ability_rating < new_ability_rating
|
||||
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserAbilityToTargetAbility",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -946,16 +974,20 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserAbilityToTargetA
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserAbilityToTargetAbility",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score -= 40 # don't prefer this move
|
||||
if ai.trainer.medium_skill? && user.opposes?(target)
|
||||
score -= 50 if [:TRUANT, :SLOWSTART].include?(target.ability_id)
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active?
|
||||
old_ability_rating = ai.battler_wants_ability?(user, user.ability_id)
|
||||
new_ability_rating = ai.battler_wants_ability?(user, target.ability_id)
|
||||
if old_ability_rating > new_ability_rating
|
||||
score += 4 * [old_ability_rating - new_ability_rating, 3].max
|
||||
elsif old_ability_rating < new_ability_rating
|
||||
score -= 4 * [new_ability_rating - old_ability_rating, 3].max
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserAbility",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -967,52 +999,87 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserA
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAbility",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score -= 40 # don't prefer this move
|
||||
if ai.trainer.medium_skill? && user.opposes?(target)
|
||||
score += 90 if [:TRUANT, :SLOWSTART].include?(user.ability_id)
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
||||
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
||||
new_ability_rating = ai.battler_wants_ability?(target, user.ability_id)
|
||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||
if old_ability_rating > new_ability_rating
|
||||
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
|
||||
elsif old_ability_rating < new_ability_rating
|
||||
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapAbilities",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if !user.ability || user.battler.unstoppableAbility? ||
|
||||
user.ability_id == :WONDERGUARD
|
||||
user.battler.ungainableAbility? || user.ability_id == :WONDERGUARD
|
||||
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAbilities",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score -= 40 # don't prefer this move
|
||||
if ai.trainer.high_skill? && user.opposes?(target)
|
||||
score -= 90 if [:TRUANT, :SLOWSTART].include?(target.ability_id)
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active? && !target.ability_active?
|
||||
old_user_ability_rating = ai.battler_wants_ability?(user, user.ability_id)
|
||||
new_user_ability_rating = ai.battler_wants_ability?(user, target.ability_id)
|
||||
user_diff = new_user_ability_rating - old_user_ability_rating
|
||||
user_diff = 0 if !user.ability_active?
|
||||
old_target_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
||||
new_target_ability_rating = ai.battler_wants_ability?(target, user.ability_id)
|
||||
target_diff = new_target_ability_rating - old_target_ability_rating
|
||||
target_diff = 0 if !target.ability_active?
|
||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||
if user_diff > target_diff
|
||||
score += 4 * side_mult * [user_diff - target_diff, 3].max
|
||||
elsif target_diff < user_diff
|
||||
score -= 4 * side_mult * [target_diff - user_diff, 3].max
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("NegateTargetAbility",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbility",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
target_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||
if target_ability_rating > 0
|
||||
score += 4 * side_mult * [target_ability_rating, 3].max
|
||||
elsif target_ability_rating < 0
|
||||
score -= 4 * side_mult * [target_ability_rating.abs, 3].max
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTargetActed",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score if target.effects[PBEffects::Substitute] > 0 || target.effects[PBEffects::GastroAcid]
|
||||
next score if target.battler.unstoppableAbility?
|
||||
next score if user.faster_than?(target)
|
||||
next score + 10
|
||||
target_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||
if target_ability_rating > 0
|
||||
score += 4 * side_mult * [target_ability_rating, 3].max
|
||||
elsif target_ability_rating < 0
|
||||
score -= 4 * side_mult * [target_ability_rating.abs, 3].max
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1134,7 +1201,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartGravity",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# TODO: Gravity increases accuracy of all moves. Should this be considered?
|
||||
# TODO: Gravity increases accuracy of all moves. Prefer if user/ally has low
|
||||
# accuracy moves, don't prefer if foes have them. Should "low
|
||||
# accuracy" mean anything below 85%?
|
||||
ai.each_battler do |b, i|
|
||||
# Prefer grounding airborne foes, don't prefer grounding airborne allies
|
||||
# Prefer making allies affected by terrain, don't prefer making foes
|
||||
|
||||
@@ -58,7 +58,7 @@ Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP",
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKO",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -71,27 +71,44 @@ Battle::AI::Handlers::MoveBasePower.add("OHKO",
|
||||
next target.hp
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("OHKO",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
# Don't prefer if the target has less HP and user has a non-OHKO damaging move
|
||||
if user.check_for_move { |m| !m.is_a?(Battle::Move::OHKO) && m.damagingMove? }
|
||||
score -= 10 if target.hp <= target.totalhp / 2
|
||||
score -= 10 if target.hp <= target.totalhp / 4
|
||||
end
|
||||
# TODO: Maybe predict dealt damage of all user's other moves, and score this
|
||||
# move useless if another one can KO the target. Might also need to
|
||||
# take into account whether those moves will fail. Might need to do
|
||||
# this specially after all move scores are determined.
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKOIce",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if target.level > user.level
|
||||
next true if !battle.moldBreaker && target.has_active_ability?(:STURDY)
|
||||
next true if target.has_type?(:ICE)
|
||||
next Battle::AI::Handlers.move_will_fail_against_target?("OHKO", move, user, target, ai, battle)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveBasePower.copy("OHKO",
|
||||
"OHKOIce")
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("OHKO",
|
||||
"OHKOIce")
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("OHKO",
|
||||
"OHKOHitsUndergroundTarget")
|
||||
Battle::AI::Handlers::MoveBasePower.copy("OHKO",
|
||||
"OHKOHitsUndergroundTarget")
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("OHKO",
|
||||
"OHKOHitsUndergroundTarget")
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
@@ -397,6 +414,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotAc
|
||||
Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
|
||||
proc { |score, move, user, ai, battle|
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user.effects[PBEffects::LaserFocus] > 0
|
||||
# TODO: Useless if user will already always critical hit ("AlwaysCriticalHit"
|
||||
# or Lucky Chant/crit stage is +3/etc.).
|
||||
next score + 10
|
||||
}
|
||||
)
|
||||
@@ -517,6 +536,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenPhysicalDamageAgainstUserS
|
||||
# Doesn't stack with Aurora Veil
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
|
||||
# Don't prefer the lower the user's HP is
|
||||
# TODO: Should this HP check exist? The effect can still be set up for
|
||||
# allies. Maybe just don't prefer if there are no replacement mons
|
||||
# left.
|
||||
if user.hp < user.totalhp / 2
|
||||
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30
|
||||
end
|
||||
@@ -543,6 +565,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenSpecialDamageAgainstUserSi
|
||||
# Doesn't stack with Aurora Veil
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
|
||||
# Don't prefer the lower the user's HP is
|
||||
# TODO: Should this HP check exist? The effect can still be set up for
|
||||
# allies. Maybe just don't prefer if there are no replacement mons
|
||||
# left.
|
||||
if user.hp < user.totalhp / 2
|
||||
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30
|
||||
end
|
||||
@@ -571,6 +596,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHai
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user.pbOwnSide.effects[PBEffects::Reflect] > 0 &&
|
||||
user.pbOwnSide.effects[PBEffects::LightScreen] > 0
|
||||
# Don't prefer the lower the user's HP is
|
||||
# TODO: Should this HP check exist? The effect can still be set up for
|
||||
# allies. Maybe just don't prefer if there are no replacement mons
|
||||
# left.
|
||||
if user.hp < user.totalhp / 2
|
||||
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30
|
||||
end
|
||||
@@ -893,14 +921,18 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("EnsureNextMoveAlwaysHits
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD)
|
||||
next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::Telekinesis] > 0
|
||||
# Prefer if the user knows moves with low accuracy
|
||||
# TODO: This isn't the correct use of check_for_move, since it should just
|
||||
# loop through them instead.
|
||||
user.check_for_move do |m|
|
||||
next if target.effects[PBEffects::Minimize] && m.tramplesMinimize? && Settings::MECHANICS_GENERATION >= 6
|
||||
# TODO: There are other effects that make a move certain to hit. Account
|
||||
# for those as well, or is that too micro-managey?
|
||||
# for those as well. Score this move useless if no moves would
|
||||
# benefit from locking on.
|
||||
acc = m.accuracy
|
||||
acc = m.pbBaseAccuracy(user.battler, target.battler) if ai.trainer.medium_skill?
|
||||
score += 4 if acc < 90 && acc != 0
|
||||
score += 4 if acc <= 50 && acc != 0
|
||||
# TODO: Prefer more if m is a OHKO move.
|
||||
end
|
||||
# Not worth it if the user or the target is at low HP
|
||||
score -= 10 if user.hp < user.totalhp / 2
|
||||
|
||||
@@ -260,7 +260,7 @@ Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackOneTurnInSun",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
# Sunny weather this a 1 turn move, the same as a move with no effect
|
||||
# In sunny weather this a 1 turn move, the same as a move with no effect
|
||||
next score if [:Sun, :HarshSun].include?(user.battler.effectiveWeather)
|
||||
# Score for being a two turn attack
|
||||
next Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
|
||||
@@ -159,27 +159,59 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetDamagingM
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score + 40 if target.effects[PBEffects::Trapping] == 0
|
||||
next score if target.effects[PBEffects::Trapping] > 0
|
||||
next score if target.effects[PBEffects::Substitute] > 0
|
||||
# Prefer if the user has a Binding Band or Grip Claw (because why have it if
|
||||
# you don't want to use it?)
|
||||
score += 5 if user.has_active_item?([:BINDINGBAND, :GRIPCLAW])
|
||||
# Target will take damage at the end of each round from the binding
|
||||
score += 8 if target.battler.takesIndirectDamage?
|
||||
# Check whether the target will be trapped in battle by the binding
|
||||
untrappable = Settings::MORE_TYPE_EFFECTS && target.has_type?(:GHOST)
|
||||
if !untrappable && target.ability_active?
|
||||
untrappable = Battle::AbilityEffects.triggerCertainSwitching(target.ability, target.battler, battle)
|
||||
end
|
||||
if !untrappable && target.item_active?
|
||||
untrappable = Battle::ItemEffects.triggerCertainSwitching(target.ability, target.battler, battle)
|
||||
end
|
||||
if !untrappable && !target.battler.trappedInBattle?
|
||||
score += 8 # Prefer if the target will become trapped by this move
|
||||
eor_damage = target.rough_end_of_round_damage
|
||||
if eor_damage > 0
|
||||
# Prefer if the target will take damage at the end of each round on top
|
||||
# of binding damage
|
||||
score += 8
|
||||
elsif eor_damage < 0
|
||||
# Don't prefer if the target will heal itself at the end of each round
|
||||
score -= 8
|
||||
end
|
||||
# Prefer if the target has been Perish Songed
|
||||
score += 10 if target.effects[PBEffects::PerishSong] > 0
|
||||
end
|
||||
# Don't prefer if the target can remove the binding (and the binding has an
|
||||
# effect)
|
||||
if (!untrappable && !target.battler.trappedInBattle?) || target.battler.takesIndirectDamage?
|
||||
if target.check_for_move { |m| m.function == "RemoveUserBindingAndEntryHazards" }
|
||||
score -= 8
|
||||
end
|
||||
end
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater",
|
||||
proc { |power, move, user, target, ai, battle|
|
||||
next move.move.pbModifyDamage(power, user.battler, target.battler)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTargetDoublePowerIfTargetUnderwater",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score + 40 if target.effects[PBEffects::Trapping] == 0
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("BindTarget",
|
||||
"BindTargetDoublePowerIfTargetUnderwater")
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# TODO: Check all lingering effects to see if the AI needs to adjust itself
|
||||
# because of them.
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifier.
|
||||
#===============================================================================
|
||||
|
||||
Reference in New Issue
Block a user