mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Rewrites of disabling move AI function codes, fixed various AI errors
This commit is contained in:
@@ -84,6 +84,14 @@ module GameData
|
||||
return GameData::Type.get(@type).special?
|
||||
end
|
||||
|
||||
def damaging?
|
||||
return @category != 2
|
||||
end
|
||||
|
||||
def status?
|
||||
return @category == 2
|
||||
end
|
||||
|
||||
def hidden_move?
|
||||
GameData::Item.each do |i|
|
||||
return true if i.is_HM? && i.move == @id
|
||||
|
||||
@@ -134,21 +134,7 @@ end
|
||||
# Hits 2-5 times in a row. If the move does not fail, increases the user's Speed
|
||||
# by 1 stage and decreases the user's Defense by 1 stage. (Scale Shot)
|
||||
#===============================================================================
|
||||
class Battle::Move::HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1 < Battle::Move
|
||||
def multiHitMove?; return true; end
|
||||
|
||||
def pbNumHits(user, targets)
|
||||
hitChances = [
|
||||
2, 2, 2, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4,
|
||||
5, 5, 5
|
||||
]
|
||||
r = @battle.pbRandom(hitChances.length)
|
||||
r = hitChances.length - 1 if user.hasActiveAbility?(:SKILLLINK)
|
||||
return hitChances[r]
|
||||
end
|
||||
|
||||
class Battle::Move::HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1 < Battle::Move::HitTwoToFiveTimes
|
||||
def pbEffectAfterAllHits(user, target)
|
||||
return if target.damageState.unaffected
|
||||
if user.pbCanLowerStatStage?(:DEFENSE, user, self)
|
||||
|
||||
@@ -767,26 +767,26 @@ class Battle::Move::DisableTargetUsingDifferentMove < Battle::Move
|
||||
def initialize(battle, move)
|
||||
super
|
||||
@moveBlacklist = [
|
||||
"DisableTargetUsingDifferentMove", # Encore
|
||||
"DisableTargetUsingDifferentMove", # Encore
|
||||
# Struggle
|
||||
"Struggle", # Struggle
|
||||
"Struggle", # Struggle
|
||||
# Moves that affect the moveset
|
||||
"ReplaceMoveThisBattleWithTargetLastMoveUsed", # Mimic
|
||||
"ReplaceMoveWithTargetLastMoveUsed", # Sketch
|
||||
"TransformUserIntoTarget", # Transform
|
||||
"ReplaceMoveWithTargetLastMoveUsed", # Sketch
|
||||
"TransformUserIntoTarget", # Transform
|
||||
# Moves that call other moves (see also below)
|
||||
"UseLastMoveUsedByTarget" # Mirror Move
|
||||
"UseLastMoveUsedByTarget" # Mirror Move
|
||||
]
|
||||
if Settings::MECHANICS_GENERATION >= 7
|
||||
@moveBlacklist += [
|
||||
# Moves that call other moves
|
||||
# "UseLastMoveUsedByTarget", # Mirror Move # See above
|
||||
"UseLastMoveUsed", # Copycat
|
||||
"UseMoveTargetIsAboutToUse", # Me First
|
||||
"UseMoveDependingOnEnvironment", # Nature Power
|
||||
"UseRandomUserMoveIfAsleep", # Sleep Talk
|
||||
"UseRandomMoveFromUserParty", # Assist
|
||||
"UseRandomMove" # Metronome
|
||||
# "UseLastMoveUsedByTarget", # Mirror Move # See above
|
||||
"UseLastMoveUsed", # Copycat
|
||||
"UseMoveTargetIsAboutToUse", # Me First
|
||||
"UseMoveDependingOnEnvironment", # Nature Power
|
||||
"UseRandomUserMoveIfAsleep", # Sleep Talk
|
||||
"UseRandomMoveFromUserParty", # Assist
|
||||
"UseRandomMove" # Metronome
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -442,7 +442,7 @@ class Battle::Scene
|
||||
moveType = moveData.type
|
||||
moveKind = moveData.category
|
||||
moveKind += 3 if target_data.num_targets > 1 || target_data.affects_foe_side
|
||||
moveKind += 3 if moveKind == 2 && target_data.num_targets > 0
|
||||
moveKind += 3 if moveData.status? && target_data.num_targets > 0
|
||||
# [one target physical, one target special, user status,
|
||||
# multiple targets physical, multiple targets special, non-user status]
|
||||
typeDefaultAnim = {
|
||||
|
||||
@@ -107,7 +107,7 @@ class Battle::AI
|
||||
if spikes > 0
|
||||
spikesDmg = [8, 6, 4][spikes - 1]
|
||||
next if pkmn.hp <= pkmn.totalhp / spikesDmg &&
|
||||
!pkmn.hasType?(:FLYING) && !pkmn.hasActiveAbility?(:LEVITATE)
|
||||
!pkmn.hasType?(:FLYING) && !pkmn.hasAbility?(:LEVITATE)
|
||||
end
|
||||
end
|
||||
# moveType is the type of the target's last used move
|
||||
|
||||
@@ -29,11 +29,11 @@ class Battle::AI
|
||||
end
|
||||
next
|
||||
end
|
||||
PBDebug.log_ai("#{@user.name} is considering using #{move.name}...")
|
||||
# Set up move in class variables
|
||||
set_up_move_check(move)
|
||||
# Predict whether the move will fail (generally)
|
||||
if @trainer.has_skill_flag?("PredictMoveFailure") && pbPredictMoveFailure
|
||||
PBDebug.log_ai("#{@user.name} is considering using #{move.name}...")
|
||||
PBDebug.log_score_change(MOVE_FAIL_SCORE - MOVE_BASE_SCORE, "move will fail")
|
||||
add_move_to_choices(choices, idxMove, MOVE_FAIL_SCORE)
|
||||
next
|
||||
@@ -43,6 +43,7 @@ class Battle::AI
|
||||
case target_data.num_targets
|
||||
when 0 # No targets, affects the user or a side or the whole field
|
||||
# Includes: BothSides, FoeSide, None, User, UserSide
|
||||
PBDebug.log_ai("#{@user.name} is considering using #{move.name}...")
|
||||
score = MOVE_BASE_SCORE
|
||||
PBDebug.logonerr { score = pbGetMoveScore }
|
||||
add_move_to_choices(choices, idxMove, score)
|
||||
@@ -57,6 +58,7 @@ class Battle::AI
|
||||
# TODO: Should this sometimes consider targeting an ally? See def
|
||||
# pbGetMoveScoreAgainstTarget for more information.
|
||||
next if target_data.targets_foe && !@user.battler.opposes?(b)
|
||||
PBDebug.log_ai("#{@user.name} is considering using #{move.name} against #{b.name} (#{b.index})...")
|
||||
score = MOVE_BASE_SCORE
|
||||
PBDebug.logonerr { score = pbGetMoveScore([b]) }
|
||||
add_move_to_choices(choices, idxMove, score, b.index)
|
||||
@@ -70,6 +72,7 @@ class Battle::AI
|
||||
next if !@battle.pbMoveCanTarget?(@user.battler.index, b.index, target_data)
|
||||
targets.push(b)
|
||||
end
|
||||
PBDebug.log_ai("#{@user.name} is considering using #{move.name}...")
|
||||
score = MOVE_BASE_SCORE
|
||||
PBDebug.logonerr { score = pbGetMoveScore(targets) }
|
||||
add_move_to_choices(choices, idxMove, score)
|
||||
@@ -108,7 +111,7 @@ class Battle::AI
|
||||
move.pbOnStartUse(@user.battler, []) # Determine which move is used instead
|
||||
move = Battle::Move.from_pokemon_move(@battle, Pokemon::Move.new(move.npMove))
|
||||
end
|
||||
@move.set_up(move, @user)
|
||||
@move.set_up(move)
|
||||
@battle.moldBreaker = @user.has_mold_breaker?
|
||||
end
|
||||
|
||||
@@ -130,7 +133,9 @@ class Battle::AI
|
||||
# User is awake and can't use moves that are only usable when asleep
|
||||
return true if !@user.battler.asleep? && @move.move.usableWhenAsleep?
|
||||
# User will be truanting
|
||||
return true if @user.has_active_ability?(:TRUANT) && @user.effects[PBEffects::Truant]
|
||||
# TODO: Should Truanting treat all moves as failing? If it does, it will
|
||||
# trigger switching due to terrible moves.
|
||||
# return true if @user.has_active_ability?(:TRUANT) && @user.effects[PBEffects::Truant]
|
||||
# Primal weather
|
||||
return true if @battle.pbWeather == :HeavyRain && @move.rough_type == :FIRE
|
||||
return true if @battle.pbWeather == :HarshSun && @move.rough_type == :WATER
|
||||
@@ -301,14 +306,11 @@ class Battle::AI
|
||||
# Decide whether all choices are bad, and if so, try switching instead
|
||||
if @trainer.high_skill? && @user.can_switch_lax?
|
||||
badMoves = false
|
||||
if (max_score <= MOVE_FAIL_SCORE && user_battler.turnCount > 2) ||
|
||||
(max_score <= MOVE_USELESS_SCORE && user_battler.turnCount > 4)
|
||||
if max_score <= MOVE_USELESS_SCORE
|
||||
badMoves = true
|
||||
elsif max_score < MOVE_BASE_SCORE * move_score_threshold && user_battler.turnCount > 2
|
||||
badMoves = true if pbAIRandom(100) < 80
|
||||
end
|
||||
if !badMoves && max_score <= MOVE_USELESS_SCORE && user_battler.turnCount >= 1
|
||||
badMoves = choices.none? { |c| user_battler.moves[c[0]].damagingMove? }
|
||||
badMoves = false if badMoves && pbAIRandom(100) < 10
|
||||
end
|
||||
if badMoves
|
||||
PBDebug.log_ai("#{@user.name} wants to switch due to terrible moves")
|
||||
return if pbEnemyShouldWithdrawEx?(true)
|
||||
|
||||
@@ -31,7 +31,7 @@ class Battle::AI
|
||||
end
|
||||
# Don't make score changes if foes have Unaware and target can't make use of
|
||||
# extra stat stages
|
||||
if !target.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" }
|
||||
if !target.has_move_with_function?("PowerHigherWithUserPositiveStatStages")
|
||||
foe_is_aware = false
|
||||
each_foe_battler(target.side) do |b, i|
|
||||
foe_is_aware = true if !b.has_active_ability?(:UNAWARE)
|
||||
@@ -121,7 +121,7 @@ class Battle::AI
|
||||
"PowerHigherWithUserFasterThanTarget",
|
||||
"PowerHigherWithUserPositiveStatStages"
|
||||
]
|
||||
if !target.check_for_move { |m| moves_that_prefer_high_speed.include?(m.function) }
|
||||
if !target.has_move_with_function?(*moves_that_prefer_high_speed)
|
||||
each_foe_battler(target.side) do |b, i|
|
||||
return true if b.faster_than?(target)
|
||||
end
|
||||
@@ -272,7 +272,7 @@ class Battle::AI
|
||||
end
|
||||
old_stage = target.stages[stat]
|
||||
new_stage = old_stage + increment
|
||||
inc_mult = (stage_mul[new_stage].to_f * stage_div[old_stage]) / (stage_div[new_stage] * stage_mul[old_stage])
|
||||
inc_mult = (stage_mul[new_stage + 6].to_f * stage_div[old_stage + 6]) / (stage_div[new_stage + 6] * stage_mul[old_stage + 6])
|
||||
inc_mult -= 1
|
||||
inc_mult *= desire_mult
|
||||
# Stat-based score changes
|
||||
@@ -280,8 +280,8 @@ class Battle::AI
|
||||
when :ATTACK
|
||||
# Modify score depending on current stat stage
|
||||
# More strongly prefer if the target has no special moves
|
||||
if old_stage >= 2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage >= 2 && increment == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
has_special_moves = target.check_for_move { |m| m.specialMove?(m.type) }
|
||||
inc = (has_special_moves) ? 10 : 20
|
||||
@@ -290,8 +290,8 @@ class Battle::AI
|
||||
|
||||
when :DEFENSE
|
||||
# Modify score depending on current stat stage
|
||||
if old_stage >= 2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage >= 2 && increment == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
score += 10 * inc_mult
|
||||
end
|
||||
@@ -299,8 +299,8 @@ class Battle::AI
|
||||
when :SPECIAL_ATTACK
|
||||
# Modify score depending on current stat stage
|
||||
# More strongly prefer if the target has no physical moves
|
||||
if old_stage >= 2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage >= 2 && increment == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
has_physical_moves = target.check_for_move { |m| m.physicalMove?(m.type) &&
|
||||
m.function != "UseUserDefenseInsteadOfUserAttack" &&
|
||||
@@ -311,8 +311,8 @@ class Battle::AI
|
||||
|
||||
when :SPECIAL_DEFENSE
|
||||
# Modify score depending on current stat stage
|
||||
if old_stage >= 2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage >= 2 && increment == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
score += 10 * inc_mult
|
||||
end
|
||||
@@ -333,12 +333,12 @@ class Battle::AI
|
||||
"PowerHigherWithUserFasterThanTarget",
|
||||
"PowerHigherWithUserPositiveStatStages"
|
||||
]
|
||||
if target.check_for_move { |m| moves_that_prefer_high_speed.include?(m.function) }
|
||||
if target.has_move_with_function?(*moves_that_prefer_high_speed)
|
||||
score += 8 * inc_mult
|
||||
end
|
||||
# Don't prefer if any foe has Gyro Ball
|
||||
each_foe_battler(target.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetFasterThanUser" }
|
||||
next if !b.has_move_with_function?("PowerHigherWithTargetFasterThanUser")
|
||||
score -= 8 * inc_mult
|
||||
end
|
||||
# Don't prefer if target has Speed Boost (will be gaining Speed anyway)
|
||||
@@ -348,8 +348,8 @@ class Battle::AI
|
||||
|
||||
when :ACCURACY
|
||||
# Modify score depending on current stat stage
|
||||
if old_stage >= 2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage >= 2 && increment == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
min_accuracy = 100
|
||||
target.battler.moves.each do |m|
|
||||
@@ -372,8 +372,8 @@ class Battle::AI
|
||||
next if eor_damage <= 0
|
||||
end
|
||||
# Modify score depending on current stat stage
|
||||
if old_stage >= 2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage >= 2 && increment == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
score += 10 * inc_mult
|
||||
end
|
||||
@@ -381,12 +381,12 @@ class Battle::AI
|
||||
end
|
||||
|
||||
# Prefer if target has Stored Power
|
||||
if target.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" }
|
||||
if target.has_move_with_function?("PowerHigherWithUserPositiveStatStages")
|
||||
score += 5 * increment * desire_mult
|
||||
end
|
||||
# Don't prefer if any foe has Punishment
|
||||
each_foe_battler(target.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetPositiveStatStages" }
|
||||
next if !b.has_move_with_function?("PowerHigherWithTargetPositiveStatStages")
|
||||
score -= 5 * increment * desire_mult
|
||||
end
|
||||
|
||||
@@ -611,7 +611,7 @@ class Battle::AI
|
||||
#=============================================================================
|
||||
def get_score_for_target_stat_drop(score, target, stat_changes, whole_effect = true, fixed_change = false)
|
||||
whole_effect = false if @move.damagingMove?
|
||||
# Decide whether the target raising its stat(s) is a good thing
|
||||
# Decide whether the target lowering its stat(s) is a good thing
|
||||
desire_mult = -1
|
||||
if target.opposes?(@user) ||
|
||||
(@move.pbTarget(@user.battler).targets_foe && target.index != @user.index)
|
||||
@@ -619,7 +619,7 @@ class Battle::AI
|
||||
end
|
||||
# Discard status move/don't prefer damaging move if target has Contrary
|
||||
# TODO: Maybe this should return get_score_for_target_stat_raise if Contrary
|
||||
# applies and desire_mult < 1.
|
||||
# applies and desire_mult < 0.
|
||||
if !fixed_change && !@battle.moldBreaker && target.has_active_ability?(:CONTRARY) && desire_mult > 0
|
||||
ret = (whole_effect) ? MOVE_USELESS_SCORE : score - 20
|
||||
PBDebug.log_score_change(ret - score, "don't prefer lowering target's stats (it has Contrary)")
|
||||
@@ -643,7 +643,7 @@ class Battle::AI
|
||||
return ret
|
||||
end
|
||||
|
||||
# Figure out which stat raises can happen
|
||||
# Figure out which stat drops can happen
|
||||
real_stat_changes = []
|
||||
stat_changes.each_with_index do |stat, idx|
|
||||
next if idx.odd?
|
||||
@@ -655,7 +655,7 @@ class Battle::AI
|
||||
end
|
||||
next
|
||||
end
|
||||
# Calculate amount that stat will be raised by
|
||||
# Calculate amount that stat will be lowered by
|
||||
decrement = stat_changes[idx + 1]
|
||||
decrement *= 2 if !fixed_change && !@battle.moldBreaker && @user.has_active_ability?(:SIMPLE)
|
||||
decrement = [decrement, 6 + target.stages[stat]].min # The actual stages lost
|
||||
@@ -721,7 +721,7 @@ class Battle::AI
|
||||
"PowerHigherWithUserFasterThanTarget",
|
||||
"PowerHigherWithUserPositiveStatStages"
|
||||
]
|
||||
if !target.check_for_move { |m| moves_that_prefer_high_speed.include?(m.function) }
|
||||
if !target.has_move_with_function?(*moves_that_prefer_high_speed)
|
||||
each_foe_battler(target.side) do |b, i|
|
||||
return true if !b.faster_than?(target)
|
||||
end
|
||||
@@ -786,7 +786,7 @@ class Battle::AI
|
||||
end
|
||||
old_stage = target.stages[stat]
|
||||
new_stage = old_stage - decrement
|
||||
dec_mult = (stage_mul[old_stage].to_f * stage_div[new_stage]) / (stage_div[old_stage] * stage_mul[new_stage])
|
||||
dec_mult = (stage_mul[old_stage + 6].to_f * stage_div[new_stage + 6]) / (stage_div[old_stage + 6] * stage_mul[new_stage + 6])
|
||||
dec_mult -= 1
|
||||
dec_mult *= desire_mult
|
||||
# Stat-based score changes
|
||||
@@ -794,8 +794,8 @@ class Battle::AI
|
||||
when :ATTACK
|
||||
# Modify score depending on current stat stage
|
||||
# More strongly prefer if the target has no special moves
|
||||
if old_stage <= -2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage <= -2 && decrement == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
has_special_moves = target.check_for_move { |m| m.specialMove?(m.type) }
|
||||
dec = (has_special_moves) ? 5 : 10
|
||||
@@ -804,8 +804,8 @@ class Battle::AI
|
||||
|
||||
when :DEFENSE
|
||||
# Modify score depending on current stat stage
|
||||
if old_stage <= -2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage <= -2 && decrement == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
score += 5 * dec_mult
|
||||
end
|
||||
@@ -813,8 +813,8 @@ class Battle::AI
|
||||
when :SPECIAL_ATTACK
|
||||
# Modify score depending on current stat stage
|
||||
# More strongly prefer if the target has no physical moves
|
||||
if old_stage <= -2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage <= -2 && decrement == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
has_physical_moves = target.check_for_move { |m| m.physicalMove?(m.type) &&
|
||||
m.function != "UseUserDefenseInsteadOfUserAttack" &&
|
||||
@@ -825,8 +825,8 @@ class Battle::AI
|
||||
|
||||
when :SPECIAL_DEFENSE
|
||||
# Modify score depending on current stat stage
|
||||
if old_stage <= -2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage <= -2 && decrement == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
score += 5 * dec_mult
|
||||
end
|
||||
@@ -842,7 +842,7 @@ class Battle::AI
|
||||
end
|
||||
# Prefer if any ally has Electro Ball
|
||||
each_foe_battler(target.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithUserFasterThanTarget" }
|
||||
next if !b.has_move_with_function?("PowerHigherWithUserFasterThanTarget")
|
||||
score += 8 * dec_mult
|
||||
end
|
||||
# Don't prefer if target has Speed Boost (will be gaining Speed anyway)
|
||||
@@ -852,8 +852,8 @@ class Battle::AI
|
||||
|
||||
when :ACCURACY
|
||||
# Modify score depending on current stat stage
|
||||
if old_stage <= -2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage <= -2 && decrement == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
score += 5 * dec_mult
|
||||
end
|
||||
@@ -861,8 +861,8 @@ class Battle::AI
|
||||
|
||||
when :EVASION
|
||||
# Modify score depending on current stat stage
|
||||
if old_stage <= -2
|
||||
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
if old_stage <= -2 && decrement == 1
|
||||
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
|
||||
else
|
||||
score += 5 * dec_mult
|
||||
end
|
||||
@@ -870,12 +870,12 @@ class Battle::AI
|
||||
end
|
||||
|
||||
# Prefer if target has Stored Power
|
||||
if target.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" }
|
||||
if target.has_move_with_function?("PowerHigherWithUserPositiveStatStages")
|
||||
score += 5 * decrement * desire_mult
|
||||
end
|
||||
# Don't prefer if any foe has Punishment
|
||||
each_foe_battler(target.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetPositiveStatStages" }
|
||||
next if !b.has_move_with_function?("PowerHigherWithTargetPositiveStatStages")
|
||||
score -= 5 * decrement * desire_mult
|
||||
end
|
||||
|
||||
@@ -901,14 +901,14 @@ class Battle::AI
|
||||
ret += (b.opposes?(move_user)) ? -10 : 10
|
||||
end
|
||||
# Check for Electric moves
|
||||
if b.check_for_move { |m| m.type == :ELECTRIC && m.damagingMove? }
|
||||
if b.has_damaging_move_of_type?(:ELECTRIC)
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
end
|
||||
when :Grassy
|
||||
# End of round healing
|
||||
ret += (b.opposes?(move_user)) ? -10 : 10
|
||||
# Check for Grass moves
|
||||
if b.check_for_move { |m| m.type == :GRASS && m.damagingMove? }
|
||||
if b.has_damaging_move_of_type?(:GRASS)
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
end
|
||||
when :Misty
|
||||
@@ -919,7 +919,7 @@ class Battle::AI
|
||||
ret += (b.opposes?(move_user)) ? -5 : 5
|
||||
end
|
||||
# Check for Dragon moves
|
||||
if b.check_for_move { |m| m.type == :DRAGON && m.damagingMove? }
|
||||
if b.has_damaging_move_of_type?(:DRAGON)
|
||||
ret += (b.opposes?(move_user)) ? 15 : -15
|
||||
end
|
||||
when :Psychic
|
||||
@@ -928,7 +928,7 @@ class Battle::AI
|
||||
ret += (b.opposes?(move_user)) ? 10 : -10
|
||||
end
|
||||
# Check for Psychic moves
|
||||
if b.check_for_move { |m| m.type == :PSYCHIC && m.damagingMove? }
|
||||
if b.has_damaging_move_of_type?(:PSYCHIC)
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
end
|
||||
end
|
||||
@@ -980,16 +980,16 @@ class Battle::AI
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
end
|
||||
# Moves
|
||||
if b.check_for_move { |m| ["EffectDependsOnEnvironment",
|
||||
"SetUserTypesBasedOnEnvironment",
|
||||
"TypeAndPowerDependOnTerrain",
|
||||
"UseMoveDependingOnEnvironment"].include?(m.function) }
|
||||
if b.has_move_with_function?("EffectDependsOnEnvironment",
|
||||
"SetUserTypesBasedOnEnvironment",
|
||||
"TypeAndPowerDependOnTerrain",
|
||||
"UseMoveDependingOnEnvironment")
|
||||
ret += (b.opposes?(move_user)) ? -10 : 10
|
||||
end
|
||||
if good_moves && b.check_for_move { |m| good_moves.include?(m.function) }
|
||||
if good_moves && b.has_move_with_function?(*good_moves)
|
||||
ret += (b.opposes?(move_user)) ? -10 : 10
|
||||
end
|
||||
if bad_moves && b.check_for_move { |m| bad_moves.include?(m.function) }
|
||||
if bad_moves && b.has_move_with_function?(*bad_moves)
|
||||
ret += (b.opposes?(move_user)) ? 10 : -10
|
||||
end
|
||||
end
|
||||
@@ -1011,7 +1011,7 @@ class Battle::AI
|
||||
:LEFTOVERS
|
||||
]
|
||||
preferred_items.push(:BLACKSLUDGE) if battler.has_type?(:POISON)
|
||||
preferred_items.push(:IRONBALL) if battler.check_for_move { |m| m.function = "ThrowUserItemAtTarget" }
|
||||
preferred_items.push(:IRONBALL) if battler.has_move_with_function?("ThrowUserItemAtTarget")
|
||||
preferred_items.push(:CHOICEBAND) if battler.check_for_move { |m| m.physicalMove?(m.type) }
|
||||
preferred_items.push(:CHOICESPECS) if battler.check_for_move { |m| m.specialMove?(m.type) }
|
||||
unpreferred_items = [
|
||||
@@ -1029,7 +1029,7 @@ class Battle::AI
|
||||
ret = -2
|
||||
end
|
||||
# Don't prefer if the battler knows Acrobatics
|
||||
if battler.check_for_move { |m| m.function == "DoublePowerIfUserHasNoItem" }
|
||||
if battler.has_move_with_function?("DoublePowerIfUserHasNoItem")
|
||||
ret += (item == :NONE) ? 1 : -1
|
||||
end
|
||||
return ret
|
||||
@@ -1050,7 +1050,7 @@ class Battle::AI
|
||||
:AIRLOCK => 5,
|
||||
:ANALYTIC => 5,
|
||||
:ANGERPOINT => 4,
|
||||
:ANTICIPATION => 2,
|
||||
:ANTICIPATION => 0,
|
||||
:ARENATRAP => 9,
|
||||
:AROMAVEIL => 3,
|
||||
# :ASONECHILLINGNEIGH => 0,
|
||||
@@ -1109,9 +1109,9 @@ class Battle::AI
|
||||
# :FLOWERVEIL => 0,
|
||||
:FLUFFY => 5,
|
||||
:FORECAST => 6,
|
||||
:FOREWARN => 2,
|
||||
:FOREWARN => 0,
|
||||
# :FRIENDGUARD => 0,
|
||||
:FRISK => 3,
|
||||
:FRISK => 0,
|
||||
:FULLMETALBODY => 4,
|
||||
:FURCOAT => 7,
|
||||
:GALEWINGS => 6,
|
||||
@@ -1322,6 +1322,52 @@ class Battle::AI
|
||||
# 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?
|
||||
case ability
|
||||
when :BLAZE
|
||||
return 0 if !battler.has_damaging_move_of_type?(:FIRE)
|
||||
when :CUTECHARM, :RIVALRY
|
||||
return 0 if battler.gender == 2
|
||||
when :FRIENDGUARD, :HEALER, :SYMBOISIS, :TELEPATHY
|
||||
has_ally = false
|
||||
each_ally(battler.side) { |b, i| has_ally = true }
|
||||
return 0 if !has_ally
|
||||
when :GALEWINGS
|
||||
return 0 if !battler.check_for_move { |m| m.type == :FLYING }
|
||||
when :HUGEPOWER, :PUREPOWER
|
||||
return 0 if !battler.check_for_move { |m| m.physicalMove?(m.type) &&
|
||||
m.function != "UseUserDefenseInsteadOfUserAttack" &&
|
||||
m.function != "UseTargetAttackInsteadOfUserAttack" }
|
||||
when :IRONFIST
|
||||
return 0 if !battler.check_for_move { |m| m.punchingMove? }
|
||||
when :LIQUIDVOICE
|
||||
return 0 if !battler.check_for_move { |m| m.soundMove? }
|
||||
when :MEGALAUNCHER
|
||||
return 0 if !battler.check_for_move { |m| m.pulseMove? }
|
||||
when :OVERGROW
|
||||
return 0 if !battler.has_damaging_move_of_type?(:GRASS)
|
||||
when :PRANKSTER
|
||||
return 0 if !battler.check_for_move { |m| m.statusMove? }
|
||||
when :PUNKROCK
|
||||
return 1 if !battler.check_for_move { |m| m.damagingMove? && m.soundMove? }
|
||||
when :RECKLESS
|
||||
return 0 if !battler.check_for_move { |m| m.recoilMove? }
|
||||
when :ROCKHEAD
|
||||
return 0 if !battler.check_for_move { |m| m.recoilMove? && !m.is_a?(Battle::Move::CrashDamageIfFailsUnusableInGravity) }
|
||||
when :RUNAWAY
|
||||
return 0 if battler.wild?
|
||||
when :SANDFORCE
|
||||
return 2 if !battler.has_damaging_move_of_type?(:GROUND, :ROCK, :STEEL)
|
||||
when :SKILLLINK
|
||||
return 0 if !battler.check_for_move { |m| m.is_a?(Battle::Move::HitTwoToFiveTimes) }
|
||||
when :STEELWORKER
|
||||
return 0 if !battler.has_damaging_move_of_type?(:GRASS)
|
||||
when :SWARM
|
||||
return 0 if !battler.has_damaging_move_of_type?(:BUG)
|
||||
when :TORRENT
|
||||
return 0 if !battler.has_damaging_move_of_type?(:WATER)
|
||||
when :TRIAGE
|
||||
return 0 if !battler.check_for_move { |m| m.healingMove? }
|
||||
end
|
||||
ret = BASE_ABILITY_RATINGS[ability] || 0
|
||||
return ret
|
||||
end
|
||||
|
||||
@@ -185,10 +185,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
|
||||
# Check for Fire/Water moves
|
||||
ai.battlers.each do |b|
|
||||
next if !b || b.battler.fainted?
|
||||
if b.check_for_move { |m| m.type == :FIRE && m.damagingMove? }
|
||||
if b.has_damaging_move_of_type?(:FIRE)
|
||||
score += (b.opposes?(user)) ? -15 : 15
|
||||
end
|
||||
if b.check_for_move { |m| m.type == :WATER && m.damagingMove? }
|
||||
if b.has_damaging_move_of_type?(:WATER)
|
||||
score += (b.opposes?(user)) ? 15 : -15
|
||||
end
|
||||
end
|
||||
@@ -201,14 +201,14 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
|
||||
elsif user.has_active_ability?(:DRYSKIN)
|
||||
score -= 10
|
||||
end
|
||||
if user.check_for_move { |m| ["HealUserDependingOnWeather",
|
||||
"RaiseUserAtkSpAtk1Or2InSun",
|
||||
"TwoTurnAttackOneTurnInSun",
|
||||
"TypeAndPowerDependOnWeather"].include?(m.function) }
|
||||
if user.has_move_with_function?("HealUserDependingOnWeather",
|
||||
"RaiseUserAtkSpAtk1Or2InSun",
|
||||
"TwoTurnAttackOneTurnInSun",
|
||||
"TypeAndPowerDependOnWeather")
|
||||
score += 10
|
||||
end
|
||||
if user.check_for_move { |m| ["ConfuseTargetAlwaysHitsInRainHitsTargetInSky",
|
||||
"ParalyzeTargetAlwaysHitsInRainHitsTargetInSky"].include?(m.function) }
|
||||
if user.has_move_with_function?("ConfuseTargetAlwaysHitsInRainHitsTargetInSky",
|
||||
"ParalyzeTargetAlwaysHitsInRainHitsTargetInSky")
|
||||
score -= 10
|
||||
end
|
||||
end
|
||||
@@ -231,10 +231,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
|
||||
# Check for Fire/Water moves
|
||||
ai.battlers.each do |b|
|
||||
next if !b || b.battler.fainted?
|
||||
if b.check_for_move { |m| m.type == :WATER && m.damagingMove? }
|
||||
if b.has_damaging_move_of_type?(:WATER)
|
||||
score += (b.opposes?(user)) ? -15 : 15
|
||||
end
|
||||
if b.check_for_move { |m| m.type == :FIRE && m.damagingMove? }
|
||||
if b.has_damaging_move_of_type?(:FIRE)
|
||||
score += (b.opposes?(user)) ? 15 : -15
|
||||
end
|
||||
end
|
||||
@@ -244,13 +244,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
|
||||
if user.has_active_ability?([:DRYSKIN, :FORECAST, :HYDRATION, :RAINDISH, :SWIFTSWIM])
|
||||
score += 15
|
||||
end
|
||||
if user.check_for_move { |m| ["ConfuseTargetAlwaysHitsInRainHitsTargetInSky",
|
||||
"ParalyzeTargetAlwaysHitsInRainHitsTargetInSky",
|
||||
"TypeAndPowerDependOnWeather"].include?(m.function) }
|
||||
if user.has_move_with_function?("ConfuseTargetAlwaysHitsInRainHitsTargetInSky",
|
||||
"ParalyzeTargetAlwaysHitsInRainHitsTargetInSky",
|
||||
"TypeAndPowerDependOnWeather")
|
||||
score += 10
|
||||
end
|
||||
if user.check_for_move { |m| ["HealUserDependingOnWeather",
|
||||
"TwoTurnAttackOneTurnInSun"].include?(m.function) }
|
||||
if user.has_move_with_function?("HealUserDependingOnWeather",
|
||||
"TwoTurnAttackOneTurnInSun")
|
||||
score -= 10
|
||||
end
|
||||
end
|
||||
@@ -286,12 +286,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather",
|
||||
if user.has_active_ability?([:SANDFORCE, :SANDRUSH, :SANDVEIL])
|
||||
score += 15
|
||||
end
|
||||
if user.check_for_move { |m| ["HealUserDependingOnSandstorm",
|
||||
"TypeAndPowerDependOnWeather"].include?(m.function) }
|
||||
if user.has_move_with_function?("HealUserDependingOnSandstorm",
|
||||
"TypeAndPowerDependOnWeather")
|
||||
score += 10
|
||||
end
|
||||
if user.check_for_move { |m| ["HealUserDependingOnWeather",
|
||||
"TwoTurnAttackOneTurnInSun"].include?(m.function) }
|
||||
if user.has_move_with_function?("HealUserDependingOnWeather",
|
||||
"TwoTurnAttackOneTurnInSun")
|
||||
score -= 10
|
||||
end
|
||||
end
|
||||
@@ -326,13 +326,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather",
|
||||
elsif user.ability == :ICEFACE
|
||||
score += 15
|
||||
end
|
||||
if user.check_for_move { |m| ["FreezeTargetAlwaysHitsInHail",
|
||||
"StartWeakenDamageAgainstUserSideIfHail",
|
||||
"TypeAndPowerDependOnWeather"].include?(m.function) }
|
||||
if user.has_move_with_function?("FreezeTargetAlwaysHitsInHail",
|
||||
"StartWeakenDamageAgainstUserSideIfHail",
|
||||
"TypeAndPowerDependOnWeather")
|
||||
score += 10
|
||||
end
|
||||
if user.check_for_move { |m| ["HealUserDependingOnWeather",
|
||||
"TwoTurnAttackOneTurnInSun"].include?(m.function) }
|
||||
if user.has_move_with_function?("HealUserDependingOnWeather",
|
||||
"TwoTurnAttackOneTurnInSun")
|
||||
score -= 10
|
||||
end
|
||||
end
|
||||
|
||||
@@ -84,7 +84,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1CurlUpUser",
|
||||
proc { |score, move, user, ai, battle|
|
||||
score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp)
|
||||
if !user.effects[PBEffects::DefenseCurl] &&
|
||||
user.check_for_move { |m| m.function == "MultiTurnAttackPowersUpEachTurn" }
|
||||
user.has_move_with_function?("MultiTurnAttackPowersUpEachTurn")
|
||||
score += 10
|
||||
end
|
||||
next score
|
||||
@@ -148,7 +148,7 @@ Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
|
||||
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1PowerUpElectricMove",
|
||||
proc { |score, move, user, ai, battle|
|
||||
score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp)
|
||||
if user.check_for_move { |m| m.damagingMove? && m.type == :ELECTRIC }
|
||||
if user.has_damaging_move_of_type?(:ELECTRIC)
|
||||
score += 10
|
||||
end
|
||||
next score
|
||||
@@ -201,14 +201,14 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2LowerUserWeight",
|
||||
# because of those modifiers, and the score changes may need to be
|
||||
# different accordingly.
|
||||
if user.battler.pokemon.weight - user.effects[PBEffects::WeightChange] > 1
|
||||
if user.check_for_move { |m| m.function == "PowerHigherWithUserHeavierThanTarget" }
|
||||
if user.has_move_with_function?("PowerHigherWithUserHeavierThanTarget")
|
||||
score -= 10
|
||||
end
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
if b.check_for_move { |m| m.function == "PowerHigherWithUserHeavierThanTarget" }
|
||||
if b.has_move_with_function?("PowerHigherWithUserHeavierThanTarget")
|
||||
score -= 10
|
||||
end
|
||||
if b.check_for_move { |m| m.function == "PowerHigherWithTargetWeight" }
|
||||
if b.has_move_with_function?("PowerHigherWithTargetWeight")
|
||||
score += 10
|
||||
end
|
||||
# TODO: Check foes for Sky Drop and whether the user is too heavy for it
|
||||
@@ -528,7 +528,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRaiseUserAtk1WhenDamaged",
|
||||
m.function != "UseUserDefenseInsteadOfUserAttack" &&
|
||||
m.function != "UseTargetAttackInsteadOfUserAttack" }
|
||||
score += 8
|
||||
elsif user.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" }
|
||||
elsif user.has_move_with_function?("PowerHigherWithUserPositiveStatStages")
|
||||
score += 4
|
||||
end
|
||||
next score
|
||||
@@ -715,12 +715,12 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetRandomStat2",
|
||||
score += ((100 * target.hp / target.totalhp) - 50) / 4 # +5 to -12
|
||||
end
|
||||
# Prefer if target has Stored Power
|
||||
if target.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" }
|
||||
if target.has_move_with_function?("PowerHigherWithUserPositiveStatStages")
|
||||
score += 8
|
||||
end
|
||||
# Don't prefer if any foe has Punishment
|
||||
ai.each_foe_battler(target.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetPositiveStatStages" }
|
||||
next if !b.has_move_with_function?("PowerHigherWithTargetPositiveStatStages")
|
||||
score -= 5
|
||||
end
|
||||
next score
|
||||
@@ -921,7 +921,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed1MakeTar
|
||||
if !target.effects[PBEffects::TarShot]
|
||||
eff = target.effectiveness_of_type_against_battler(:FIRE)
|
||||
if !Effectiveness.ineffective?(eff)
|
||||
score += 8 * eff if user.check_for_move { |m| m.damagingMove? && m.pbCalcType(user.battler) == :FIRE }
|
||||
score += 8 * eff if user.has_damaging_move_of_type?(:FIRE)
|
||||
end
|
||||
end
|
||||
next score
|
||||
@@ -1119,7 +1119,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaisePlusMinusUserAndAlliesAtkSpAtk1
|
||||
)
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaisePlusMinusUserAndAlliesAtkSpAtk1",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if !target.hasActiveAbility?([:MINUS, :PLUS])
|
||||
next true if !target.has_active_ability?([:MINUS, :PLUS])
|
||||
next !target.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) &&
|
||||
!target.battler.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user.battler, move.move)
|
||||
}
|
||||
@@ -1157,7 +1157,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaisePlusMinusUserAndAlliesDefSpDef1
|
||||
)
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("RaisePlusMinusUserAndAlliesDefSpDef1",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if !target.hasActiveAbility?([:MINUS, :PLUS])
|
||||
next true if !target.has_active_ability?([:MINUS, :PLUS])
|
||||
next !target.battler.pbCanRaiseStatStage?(:DEFENSE, user.battler, move.move) &&
|
||||
!target.battler.pbCanRaiseStatStage?(:SPECIAL_DEFENSE, user.battler, move.move)
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SleepTarget",
|
||||
score += 15
|
||||
# Prefer if the user or an ally has a move/ability that is better if the target is asleep
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
score += 5 if b.check_for_move { |m| ["DoublePowerIfTargetAsleepCureTarget",
|
||||
"DoublePowerIfTargetStatusProblem",
|
||||
"HealUserByHalfOfDamageDoneIfTargetAsleep",
|
||||
"StartDamageTargetEachTurnIfTargetAsleep"].include?(m.function) }
|
||||
score += 5 if b.has_move_with_function?("DoublePowerIfTargetAsleepCureTarget",
|
||||
"DoublePowerIfTargetStatusProblem",
|
||||
"HealUserByHalfOfDamageDoneIfTargetAsleep",
|
||||
"StartDamageTargetEachTurnIfTargetAsleep")
|
||||
score += 10 if b.has_active_ability?(:BADDREAMS)
|
||||
end
|
||||
# Don't prefer if target benefits from having the sleep status problem
|
||||
@@ -119,8 +119,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget",
|
||||
score += 10 * target.hp / target.totalhp
|
||||
# Prefer if the user or an ally has a move/ability that is better if the target is poisoned
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
score += 5 if b.check_for_move { |m| ["DoublePowerIfTargetPoisoned",
|
||||
"DoublePowerIfTargetStatusProblem"].include?(m.function) }
|
||||
score += 5 if b.has_move_with_function?("DoublePowerIfTargetPoisoned",
|
||||
"DoublePowerIfTargetStatusProblem")
|
||||
score += 10 if b.has_active_ability?(:MERCILESS)
|
||||
end
|
||||
# Don't prefer if target benefits from having the poison status problem
|
||||
@@ -128,8 +128,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget",
|
||||
score -= 25 if target.has_active_ability?(:POISONHEAL)
|
||||
score -= 15 if target.has_active_ability?(:SYNCHRONIZE) &&
|
||||
user.battler.pbCanPoisonSynchronize?(target.battler)
|
||||
score -= 5 if target.check_for_move { |m| ["DoublePowerIfUserPoisonedBurnedParalyzed",
|
||||
"CureUserBurnPoisonParalysis"].include?(m.function) }
|
||||
score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed",
|
||||
"CureUserBurnPoisonParalysis")
|
||||
score -= 10 if target.check_for_move { |m|
|
||||
m.function == "GiveUserStatusToTarget" && user.battler.pbCanPoison?(target.battler, false, m)
|
||||
}
|
||||
@@ -214,15 +214,15 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeTarget",
|
||||
score += 5 if target.effects[PBEffects::Attract] >= 0
|
||||
# Prefer if the user or an ally has a move/ability that is better if the target is paralysed
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
score += 5 if b.check_for_move { |m| ["DoublePowerIfTargetParalyzedCureTarget",
|
||||
"DoublePowerIfTargetStatusProblem"].include?(m.function) }
|
||||
score += 5 if b.has_move_with_function?("DoublePowerIfTargetParalyzedCureTarget",
|
||||
"DoublePowerIfTargetStatusProblem")
|
||||
end
|
||||
# Don't prefer if target benefits from having the paralysis status problem
|
||||
score -= 8 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET])
|
||||
score -= 15 if target.has_active_ability?(:SYNCHRONIZE) &&
|
||||
user.battler.pbCanParalyzeSynchronize?(target.battler)
|
||||
score -= 5 if target.check_for_move { |m| ["DoublePowerIfUserPoisonedBurnedParalyzed",
|
||||
"CureUserBurnPoisonParalysis"].include?(m.function) }
|
||||
score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed",
|
||||
"CureUserBurnPoisonParalysis")
|
||||
score -= 10 if target.check_for_move { |m|
|
||||
m.function == "GiveUserStatusToTarget" && user.battler.pbCanParalyze?(target.battler, false, m)
|
||||
}
|
||||
@@ -306,15 +306,15 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget",
|
||||
end
|
||||
# Prefer if the user or an ally has a move/ability that is better if the target is burned
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
score += 5 if b.check_for_move { |m| m.function == "DoublePowerIfTargetStatusProblem" }
|
||||
score += 5 if b.has_move_with_function?("DoublePowerIfTargetStatusProblem")
|
||||
end
|
||||
# Don't prefer if target benefits from having the burn status problem
|
||||
score -= 8 if target.has_active_ability?([:FLAREBOOST, :GUTS, :MARVELSCALE, :QUICKFEET])
|
||||
score -= 5 if target.has_active_ability?(:HEATPROOF)
|
||||
score -= 15 if target.has_active_ability?(:SYNCHRONIZE) &&
|
||||
user.battler.pbCanBurnSynchronize?(target.battler)
|
||||
score -= 5 if target.check_for_move { |m| ["DoublePowerIfUserPoisonedBurnedParalyzed",
|
||||
"CureUserBurnPoisonParalysis"].include?(m.function) }
|
||||
score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed",
|
||||
"CureUserBurnPoisonParalysis")
|
||||
score -= 10 if target.check_for_move { |m|
|
||||
m.function == "GiveUserStatusToTarget" && user.battler.pbCanBurn?(target.battler, false, m)
|
||||
}
|
||||
@@ -380,7 +380,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeTarget",
|
||||
score += 15
|
||||
# Prefer if the user or an ally has a move/ability that is better if the target is frozen
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
score += 5 if b.check_for_move { |m| m.function == "DoublePowerIfTargetStatusProblem" }
|
||||
score += 5 if b.has_move_with_function?("DoublePowerIfTargetStatusProblem")
|
||||
end
|
||||
# Don't prefer if target benefits from having the frozen status problem
|
||||
# NOTE: The target's Guts/Quick Feet will benefit from the target being
|
||||
@@ -722,15 +722,11 @@ Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesBasedOnEnvironment",
|
||||
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
|
||||
score += 8 if user.has_damaging_move_of_type?(new_type)
|
||||
# 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
|
||||
score -= 8 if user.has_damaging_move_of_type?(type)
|
||||
end
|
||||
# NOTE: Other things could be considered, like the foes' moves'
|
||||
# effectivenesses against the current and new user's type(s), and
|
||||
@@ -816,10 +812,9 @@ 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? && m.pbCalcType(user.battler) == type }
|
||||
score += 10
|
||||
break
|
||||
end
|
||||
next if !user.has_damaging_move_of_type?(type)
|
||||
score += 10
|
||||
break
|
||||
end
|
||||
# NOTE: Other things could be considered, like the foes' moves'
|
||||
# effectivenesses against the current and new user's type(s), and
|
||||
@@ -1142,7 +1137,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserAirborne",
|
||||
# Prefer if any foes have damaging Ground-type moves that do 1x or more
|
||||
# damage to the user
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) == :GROUND }
|
||||
next if !b.has_damaging_move_of_type?(:GROUND)
|
||||
next if Effectiveness.resistant?(user.effectiveness_of_type_against_battler(:GROUND, b))
|
||||
score += 5
|
||||
end
|
||||
@@ -1181,7 +1176,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartUserAirborne",
|
||||
score += 4 if acc < 90 && acc != 0
|
||||
score += 4 if acc <= 50 && acc != 0
|
||||
end
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) == :GROUND }
|
||||
next if !b.has_damaging_move_of_type?(:GROUND)
|
||||
next if Effectiveness.resistant?(target.effectiveness_of_type_against_battler(:GROUND, b))
|
||||
score -= 5
|
||||
end
|
||||
@@ -1213,7 +1208,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitsTargetInSkyGroundsTa
|
||||
score += 10
|
||||
# Prefer if any allies have damaging Ground-type moves
|
||||
ai.each_foe_battler(target.side) do |b, i|
|
||||
score += 5 if b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) == :GROUND }
|
||||
score += 5 if b.has_damaging_move_of_type?(:GROUND)
|
||||
end
|
||||
# Don't prefer if terrain exists (which the target will become affected by)
|
||||
if ai.trainer.medium_skill?
|
||||
@@ -1247,7 +1242,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
|
||||
# Prefer if allies have any damaging Ground moves they'll be able to use
|
||||
# on a grounded foe, and vice versa
|
||||
ai.each_foe_battler(b.side) do |b2, j|
|
||||
if b2.check_for_move { |m| m.damagingMove? && m.pbCalcType(b2.battler) == :GROUND }
|
||||
if b2.has_damaging_move_of_type?(:GROUND)
|
||||
score += (user.opposes?(b2)) ? -5 : 5
|
||||
end
|
||||
end
|
||||
|
||||
@@ -504,13 +504,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenElectricMoves",
|
||||
end
|
||||
# Prefer if foes have Electric moves
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) == :ELECTRIC }
|
||||
next if !b.has_damaging_move_of_type?(:ELECTRIC)
|
||||
score += 10
|
||||
score += 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC }
|
||||
end
|
||||
# Don't prefer if any allies have Electric moves
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) == :ELECTRIC }
|
||||
next if !b.has_damaging_move_of_type?(:ELECTRIC)
|
||||
score -= 8
|
||||
score -= 4 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC }
|
||||
end
|
||||
@@ -535,13 +535,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenFireMoves",
|
||||
end
|
||||
# Prefer if foes have Fire moves
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) == :FIRE }
|
||||
next if !b.has_damaging_move_of_type?(:FIRE)
|
||||
score += 10
|
||||
score += 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE }
|
||||
end
|
||||
# Don't prefer if any allies have Fire moves
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) == :FIRE }
|
||||
next if !b.has_damaging_move_of_type?(:FIRE)
|
||||
score -= 8
|
||||
score -= 4 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE }
|
||||
end
|
||||
@@ -949,9 +949,7 @@ 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|
|
||||
user.battler.eachMove 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. Score this move useless if no moves would
|
||||
@@ -978,7 +976,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartNegateTargetEvasion
|
||||
# Check if the user knows any moves that would benefit from negating the
|
||||
# target's Ghost type immunity
|
||||
if target.has_type?(:GHOST)
|
||||
user.check_for_move do |m|
|
||||
user.battler.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
score += 10 if Effectiveness.ineffective_type?(m.pbCalcType(user.battler), :GHOST)
|
||||
end
|
||||
@@ -998,7 +996,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartNegateTargetEvasion
|
||||
# Check if the user knows any moves that would benefit from negating the
|
||||
# target's Dark type immunity
|
||||
if target.has_type?(:DARK)
|
||||
user.check_for_move do |m|
|
||||
user.battler.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
score += 10 if Effectiveness.ineffective_type?(m.pbCalcType(user.battler), :DARK)
|
||||
end
|
||||
|
||||
@@ -215,27 +215,27 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack",
|
||||
has_protect_move = false
|
||||
if move.move.pbTarget(user).num_targets > 1 &&
|
||||
(Settings::MECHANICS_GENERATION >= 7 || move.damagingMove?)
|
||||
if target.check_for_move { |m| m.function == "ProtectUserSideFromMultiTargetDamagingMoves" }
|
||||
if target.has_move_with_function?("ProtectUserSideFromMultiTargetDamagingMoves")
|
||||
has_protect_move = true
|
||||
end
|
||||
end
|
||||
if move.move.canProtectAgainst?
|
||||
if target.check_for_move { |m| ["ProtectUser",
|
||||
"ProtectUserFromTargetingMovesSpikyShield",
|
||||
"ProtectUserBanefulBunker"].include?(m.function) }
|
||||
if target.has_move_with_function?("ProtectUser",
|
||||
"ProtectUserFromTargetingMovesSpikyShield",
|
||||
"ProtectUserBanefulBunker")
|
||||
has_protect_move = true
|
||||
end
|
||||
if move.damagingMove?
|
||||
# NOTE: Doesn't check for Mat Block because it only works on its
|
||||
# user's first turn in battle, so it can't be used in response
|
||||
# to this move charging up.
|
||||
if target.check_for_move { |m| ["ProtectUserFromDamagingMovesKingsShield",
|
||||
"ProtectUserFromDamagingMovesObstruct"].include?(m.function) }
|
||||
if target.has_move_with_function?("ProtectUserFromDamagingMovesKingsShield",
|
||||
"ProtectUserFromDamagingMovesObstruct")
|
||||
has_protect_move = true
|
||||
end
|
||||
end
|
||||
if move.rough_priority(user) > 0
|
||||
if target.check_for_move { |m| m.function == "ProtectUserSideFromPriorityMoves" }
|
||||
if target.has_move_with_function?("ProtectUserSideFromPriorityMoves")
|
||||
has_protect_move = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -206,7 +206,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerAfterFusionFlare",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Prefer if an ally knows Fusion Flare
|
||||
ai.each_ally(user.index) do |b, i|
|
||||
score += 10 if b.check_for_move { |m| m.function == "DoublePowerAfterFusionBolt" }
|
||||
score += 10 if b.has_move_with_function?("DoublePowerAfterFusionBolt")
|
||||
end
|
||||
next score
|
||||
}
|
||||
@@ -219,7 +219,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerAfterFusionBolt",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Prefer if an ally knows Fusion Bolt
|
||||
ai.each_ally(user.index) do |b, i|
|
||||
score += 10 if b.check_for_move { |m| m.function == "DoublePowerAfterFusionFlare" }
|
||||
score += 10 if b.has_move_with_function?("DoublePowerAfterFusionFlare")
|
||||
end
|
||||
next score
|
||||
}
|
||||
@@ -380,7 +380,7 @@ Battle::AI::Handlers::MoveEffectScore.add("GrassPledge",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Prefer if an ally knows a different Pledge move
|
||||
ai.each_ally(user.index) do |b, i|
|
||||
score += 10 if b.check_for_move { |m| ["FirePledge", "WaterPledge"].include?(m.function) }
|
||||
score += 10 if b.has_move_with_function?("FirePledge", "WaterPledge")
|
||||
end
|
||||
next score
|
||||
}
|
||||
@@ -393,7 +393,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FirePledge",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Prefer if an ally knows a different Pledge move
|
||||
ai.each_ally(user.index) do |b, i|
|
||||
score += 10 if b.check_for_move { |m| ["GrassPledge", "WaterPledge"].include?(m.function) }
|
||||
score += 10 if b.has_move_with_function?("GrassPledge", "WaterPledge")
|
||||
end
|
||||
next score
|
||||
}
|
||||
@@ -406,7 +406,7 @@ Battle::AI::Handlers::MoveEffectScore.add("WaterPledge",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Prefer if an ally knows a different Pledge move
|
||||
ai.each_ally(user.index) do |b, i|
|
||||
score += 10 if b.check_for_move { |m| ["GrassPledge", "FirePledge"].include?(m.function) }
|
||||
score += 10 if b.has_move_with_function?("GrassPledge", "FirePledge")
|
||||
end
|
||||
next score
|
||||
}
|
||||
|
||||
@@ -30,13 +30,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove",
|
||||
else
|
||||
score -= total * 10
|
||||
# special case: user has no damaging moves
|
||||
hasDamagingMove = false
|
||||
user.battler.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
hasDamagingMove = true
|
||||
break
|
||||
end
|
||||
score += 75 if !hasDamagingMove
|
||||
score += 75 if !user.check_for_move { |m| m.damagingMove? }
|
||||
end
|
||||
end
|
||||
next score
|
||||
@@ -95,13 +89,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
|
||||
else
|
||||
score += total * 10
|
||||
# special case: user has no damaging moves
|
||||
hasDamagingMove = false
|
||||
user.battler.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
hasDamagingMove = true
|
||||
break
|
||||
end
|
||||
score += 75 if !hasDamagingMove
|
||||
score += 75 if !user.check_for_move { |m| m.damagingMove? }
|
||||
end
|
||||
else
|
||||
score -= 100
|
||||
@@ -192,7 +180,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
|
||||
# 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" }
|
||||
if target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
|
||||
score -= 8
|
||||
end
|
||||
end
|
||||
@@ -440,7 +428,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerPPOfTargetLastMoveB
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetLastMoveUsed",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -456,9 +444,25 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetLastMoveUs
|
||||
next will_fail
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB)
|
||||
# Prefer if the target is locked into using a single move, or will be
|
||||
if target.effects[PBEffects::ChoiceBand] ||
|
||||
target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) ||
|
||||
target.has_active_ability?(:GORILLATACTICS)
|
||||
score += 8
|
||||
end
|
||||
# PRefer disabling a damaging move
|
||||
score += 5 if GameData::Move.try_get(target.battler.lastRegularMoveUsed)&.damaging?
|
||||
# Inherent preference
|
||||
score += 8
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingSameMoveConsecutively",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -469,13 +473,21 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingSameM
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next 0 if target.effects[PBEffects::Torment]
|
||||
next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB)
|
||||
# Prefer if the target is locked into using a single move, or will be
|
||||
if target.effects[PBEffects::ChoiceBand] ||
|
||||
target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) ||
|
||||
target.has_active_ability?(:GORILLATACTICS)
|
||||
score += 8
|
||||
end
|
||||
# Inherent preference
|
||||
score += 8
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingDifferentMove",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -496,23 +508,44 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingDiffe
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingDifferentMove",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB)
|
||||
if user.faster_than?(target)
|
||||
moveData = GameData::Move.get(target.battler.lastRegularMoveUsed)
|
||||
if moveData.category == 2 && # Status move
|
||||
[:User, :BothSides].include?(moveData.target)
|
||||
score += 60
|
||||
elsif moveData.category != 2 && # Damaging move
|
||||
moveData.target == :NearOther &&
|
||||
Effectiveness.ineffective?(user.effectiveness_of_type_against_battler(moveData.type, target))
|
||||
score += 60
|
||||
# We know which move is going to be encored (assuming the target doesn't
|
||||
# use a high priority move)
|
||||
move_data = GameData::Move.get(target.battler.lastRegularMoveUsed)
|
||||
if move_data.status?
|
||||
# Prefer encoring status moves
|
||||
if [:User, :BothSides].include?(move_data.target)
|
||||
# TODO: This target distinction was in the old code. Is it appropriate?
|
||||
score += 10
|
||||
else
|
||||
score += 8
|
||||
end
|
||||
elsif move_data.damaging? && move_data.target == :NearOther
|
||||
# Prefer encoring damaging moves depending on their type effectiveness
|
||||
# against the user
|
||||
eff = user.effectiveness_of_type_against_battler(move_data.type, target)
|
||||
if Effectiveness.ineffective?(eff)
|
||||
score += 15
|
||||
elsif Effectiveness.not_very_effective?(eff)
|
||||
score += 10
|
||||
elsif Effectiveness.super_effective?(eff)
|
||||
score -= 5
|
||||
else
|
||||
score += 5
|
||||
end
|
||||
end
|
||||
else
|
||||
# We don't know which move is going to be encored; just prefer limiting
|
||||
# the target's options
|
||||
score += 8
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetStatusMoves",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -526,12 +559,45 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetStatusMove
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetStatusMoves",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !target.check_for_move { |m| m.statusMove? }
|
||||
# Not worth using on a sleeping target that won't imminently wake up
|
||||
if target.status == :SLEEP && target.statusCount > ((target.faster_than?(user)) ? 2 : 1)
|
||||
if !target.check_for_move { |m| m.statusMove? && m.usableWhenAsleep? && (m.pp > 0 || m.total_pp == 0) }
|
||||
next Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
end
|
||||
# Move is likely useless if the target will lock themselves into a move,
|
||||
# because they'll likely lock themselves into a damaging move anyway
|
||||
if !target.effects[PBEffects::ChoiceBand]
|
||||
if target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) ||
|
||||
target.has_active_ability?(:GORILLATACTICS)
|
||||
next Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
end
|
||||
# Prefer if the target has a protection move
|
||||
protection_moves = [
|
||||
"ProtectUser", # Detect, Protect
|
||||
"ProtectUserSideFromPriorityMoves", # Quick Guard
|
||||
"ProtectUserSideFromMultiTargetDamagingMoves", # Wide Guard
|
||||
"UserEnduresFaintingThisTurn", # Endure
|
||||
"ProtectUserSideFromDamagingMovesIfUserFirstTurn", # Mat Block
|
||||
"ProtectUserSideFromStatusMoves", # Crafty Shield
|
||||
"ProtectUserFromDamagingMovesKingsShield", # King's Shield
|
||||
"ProtectUserFromDamagingMovesObstruct", # Obstruct
|
||||
"ProtectUserFromTargetingMovesSpikyShield", # Spiky Shield
|
||||
"ProtectUserBanefulBunker" # Baneful Bunker
|
||||
]
|
||||
if target.check_for_move { |m| m.statusMove? && protection_moves.include?(m.function) &&
|
||||
(m.pp > 0 || m.total_pp == 0) }
|
||||
score += 6
|
||||
end
|
||||
# Inherent preference
|
||||
score += 8
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetHealingMoves",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -542,28 +608,57 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetHealingMov
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetHealingMoves",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !target.check_for_move { |m| m.healingMove? }
|
||||
# Useless if the foe can't heal themselves with a move or some held items
|
||||
if !target.check_for_move { |m| m.healingMove? && (m.pp > 0 || m.total_pp == 0) }
|
||||
if !target.has_active_item?(:LEFTOVERS) &&
|
||||
!(target.has_active_item?(:BLACKSLUDGE) && target.has_type?(:POISON))
|
||||
next Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
end
|
||||
# Inherent preference
|
||||
score += 8
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#.
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetSoundMoves",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
if target.effects[PBEffects::ThroatChop] == 0
|
||||
score += 10 if target.check_for_move { |m| m.soundMove? }
|
||||
end
|
||||
next score if target.effects[PBEffects::ThroatChop] > 1
|
||||
next score if !target.check_for_move { |m| m.soundMove? && (m.pp > 0 || m.total_pp == 0) }
|
||||
# Inherent preference
|
||||
score += 8
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser",
|
||||
proc { |move, user, ai, battle|
|
||||
next user.effects[PBEffects::Imprison]
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetMovesKnownByUser",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
# Useless if the foes have no moves that the user also knows
|
||||
shared_move = false
|
||||
user_moves = user.battler.moves.map { |m| m.id }
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
b.battler.eachMove do |m|
|
||||
next if !user_moves.include?(m.id)
|
||||
next if m.pp == 0 && m.total_pp > 0
|
||||
shared_move = true
|
||||
break
|
||||
end
|
||||
break if shared_move
|
||||
end
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !shared_move
|
||||
# Inherent preference
|
||||
score += 6
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
@@ -267,6 +267,18 @@ class Battle::AI::AIBattler
|
||||
return ret
|
||||
end
|
||||
|
||||
def has_damaging_move_of_type?(*types)
|
||||
check_for_move do |m|
|
||||
return true if m.damagingMove? && types.include?(m.pbCalcType(@battler))
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def has_move_with_function?(*functions)
|
||||
check_for_move { |m| return true if functions.include?(m.function) }
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
|
||||
def can_switch_lax?
|
||||
|
||||
@@ -8,9 +8,9 @@ class Battle::AI::AIMove
|
||||
@ai = ai
|
||||
end
|
||||
|
||||
def set_up(move, ai_battler)
|
||||
def set_up(move)
|
||||
@move = move
|
||||
@ai_battler = ai_battler
|
||||
@move.calcType = rough_type
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
@@ -46,7 +46,7 @@ class Battle::AI::AIMove
|
||||
|
||||
# Returns whether this move targets multiple battlers.
|
||||
def targets_multiple_battlers?
|
||||
user_battler = @ai_battler.battler
|
||||
user_battler = @ai.user.battler
|
||||
target_data = @move.pbTarget(user_battler)
|
||||
return false if target_data.num_targets <= 1
|
||||
num_targets = 0
|
||||
|
||||
Reference in New Issue
Block a user