Made AI function code-specific MoveFailureCheck handlers

This commit is contained in:
Maruno17
2022-08-27 20:11:01 +01:00
parent b6c84fa278
commit 265897f9e1
24 changed files with 1653 additions and 924 deletions

View File

@@ -85,6 +85,8 @@ end
# Raise one of user's stats.
#===============================================================================
class Battle::Move::StatUpMove < Battle::Move
attr_reader :statUp
def canSnatch?; return true; end
def pbMoveFailed?(user, targets)
@@ -108,6 +110,8 @@ end
# Raise multiple of user's stats.
#===============================================================================
class Battle::Move::MultiStatUpMove < Battle::Move
attr_reader :statUp
def canSnatch?; return true; end
def pbMoveFailed?(user, targets)
@@ -167,6 +171,8 @@ end
# Lower one of target's stats.
#===============================================================================
class Battle::Move::TargetStatDownMove < Battle::Move
attr_reader :statDown
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
@@ -190,6 +196,8 @@ end
# Lower multiple of target's stats.
#===============================================================================
class Battle::Move::TargetMultiStatDownMove < Battle::Move
attr_reader :statDown
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
@@ -479,6 +487,8 @@ end
# Weather-inducing move.
#===============================================================================
class Battle::Move::WeatherMove < Battle::Move
attr_reader :weatherType
def initialize(battle, move)
super
@weatherType = :None

View File

@@ -459,6 +459,8 @@ end
# side. (Court Change)
#===============================================================================
class Battle::Move::SwapSideEffects < Battle::Move
attr_reader :number_effects, :boolean_effects
def initialize(battle, move)
super
@number_effects = [

View File

@@ -407,6 +407,8 @@ end
# (Shell Smash)
#===============================================================================
class Battle::Move::LowerUserDefSpDef1RaiseUserAtkSpAtkSpd2 < Battle::Move
attr_reader :statUp, :statDown
def canSnatch?; return true; end
def initialize(battle, move)
@@ -1397,7 +1399,7 @@ end
# Raises the Attack and Defense of all user's allies by 1 stage each. Bypasses
# protections, including Crafty Shield. Fails if there is no ally. (Coaching)
#===============================================================================
class Battle::Move::RaiseUserAndAlliesAtkDef1 < Battle::Move
class Battle::Move::RaiseAlliesAtkDef1 < Battle::Move
def ignoresSubstitute?(user); return true; end
def canSnatch?; return true; end

View File

@@ -957,7 +957,7 @@ class Battle::Move::SetTargetAbilityToSimple < Battle::Move
end
def pbFailsAgainstTarget?(user, target, show_message)
if target.unstoppableAbility? || [:TRUANT, :SIMPLE].include?(target.ability)
if target.unstoppableAbility? || [:TRUANT, :SIMPLE].include?(target.ability_id)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
@@ -1165,7 +1165,7 @@ class Battle::Move::NegateTargetAbility < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.unstoppableAbility?
if target.unstoppableAbility? || target.effects[PBEffects::GastroAcid]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end

View File

@@ -453,8 +453,6 @@ class Battle::Move::DoublePowerIfTargetPoisoned < Battle::Move
end
end
#===============================================================================
# Power is doubled if the target is paralyzed. Cures the target of paralysis.
# (Smelling Salts)

View File

@@ -137,7 +137,7 @@ class Battle::Move::RestoreUserConsumedItem < Battle::Move
def canSnatch?; return true; end
def pbMoveFailed?(user, targets)
if !user.recycleItem
if !user.recycleItem || user.item
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
@@ -317,6 +317,7 @@ class Battle::Move::UserConsumeBerryRaiseDefense2 < Battle::Move::StatUpMove
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
# TODO: Should this return super? It can consume the berry at this point.
return super
end

View File

@@ -668,6 +668,8 @@ end
# Uses the last move that was used. (Copycat)
#===============================================================================
class Battle::Move::UseLastMoveUsed < Battle::Move
attr_reader :moveBlacklist
def callsAnotherMove?; return true; end
def initialize(battle, move)
@@ -983,6 +985,8 @@ end
# Uses a random move known by any non-user Pokémon in the user's party. (Assist)
#===============================================================================
class Battle::Move::UseRandomMoveFromUserParty < Battle::Move
attr_reader :moveBlacklist
def callsAnotherMove?; return true; end
def initialize(battle, move)
@@ -1098,6 +1102,8 @@ end
# Uses a random move the user knows. Fails if user is not asleep. (Sleep Talk)
#===============================================================================
class Battle::Move::UseRandomUserMoveIfAsleep < Battle::Move
attr_reader :moveBlacklist
def usableWhenAsleep?; return true; end
def callsAnotherMove?; return true; end
@@ -1192,6 +1198,8 @@ end
# out. (Mimic)
#===============================================================================
class Battle::Move::ReplaceMoveThisBattleWithTargetLastMoveUsed < Battle::Move
attr_reader :moveBlacklist
def ignoresSubstitute?(user); return true; end
def initialize(battle, move)
@@ -1243,6 +1251,8 @@ end
# This move permanently turns into the last move used by the target. (Sketch)
#===============================================================================
class Battle::Move::ReplaceMoveWithTargetLastMoveUsed < Battle::Move
attr_reader :moveBlacklist
def ignoresSubstitute?(user); return true; end
def initialize(battle, move)

View File

@@ -540,6 +540,8 @@ end
# The target uses its most recent move again. (Instruct)
#===============================================================================
class Battle::Move::TargetUsesItsLastUsedMoveAgain < Battle::Move
attr_reader :moveBlacklist
def ignoresSubstitute?(user); return true; end
def initialize(battle, move)
@@ -757,6 +759,8 @@ end
# For 4 rounds, the target must use the same move each round. (Encore)
#===============================================================================
class Battle::Move::DisableTargetUsingDifferentMove < Battle::Move
attr_reader :moveBlacklist
def ignoresSubstitute?(user); return true; end
def canMagicCoat?; return true; end

View File

@@ -63,8 +63,9 @@ end
#
#===============================================================================
module Battle::AI::Handlers
MoveEffectScore = HandlerHash.new
MoveBasePower = HandlerHash.new
MoveEffectScore = HandlerHash.new
MoveBasePower = HandlerHash.new
MoveFailureCheck = HandlerHash.new
# Move type
# Move accuracy
# Move target
@@ -72,6 +73,10 @@ module Battle::AI::Handlers
# Move unselectable check
# Move failure check
def self.move_will_fail?(function_code, *args)
return MoveFailureCheck.trigger(function_code, *args) || false
end
def self.apply_move_effect_score(function_code, score, *args)
ret = MoveEffectScore.trigger(function_code, score, *args)
return (ret.nil?) ? score : ret

View File

@@ -43,10 +43,10 @@ class Battle::AI
def pbRegisterMoveWild(idxMove, choices)
battler = @user.battler
score = 100
choices.push([idxMove, score, -1]) # Move index, score, target
# Doubly prefer one of the user's moves (the choice is random but consistent
# and does not correlate to any other property of the user)
score *= 2 if battler.pokemon.personalID % battler.moves.length == idxMove
choices.push([idxMove, 100, -1]) # Move index, score, target
choices.push([idxMove, score, -1]) if battler.pokemon.personalID % battler.moves.length == idxMove
end
# Trainer Pokémon calculate how much they want to use each of their moves.
@@ -100,6 +100,55 @@ class Battle::AI
@user_faster = @user.faster_than?(@target)
end
#=============================================================================
# Returns whether the move will definitely fail (assuming no battle conditions
# change between now and using the move)
#=============================================================================
def pbPredictMoveFailure
return false if !@trainer.has_skill_flag?("PredictMoveFailure")
# TODO: Something involving pbCanChooseMove? (see Assault Vest).
# TODO: Something involving user.usingMultiTurnAttack? (perhaps earlier than
# this?).
# User is asleep and will not wake up
return true if @trainer.medium_skill? && @user.battler.asleep? &&
@user.statusCount > 1 && !@move.move.usableWhenAsleep?
# User will be truanting
return true if @user.has_active_ability?(:TRUANT) && @user.effects[PBEffects::Truant]
# Move effect-specific checks
return true if Battle::AI::Handlers.move_will_fail?(@move.function, @move, @user, @target, self, @battle)
# Immunity to priority moves because of Psychic Terrain
return true if @battle.field.terrain == :Psychic && @target.battler.affectedByTerrain? &&
@target.opposes?(@user) && @move.rough_priority(@user) > 0
# Immunity because of ability (intentionally before type immunity check)
# TODO: Check for target-redirecting abilities that also provide immunity.
# If an ally has such an ability, may want to just not prefer the move
# instead of predicting its failure, as might want to hit the ally
# after all.
return true if @move.move.pbImmunityByAbility(@user.battler, @target.battler, false)
# Type immunity
calc_type = @move.pbCalcType(@user.battler)
typeMod = @move.move.pbCalcTypeMod(calc_type, @user.battler, @target.battler)
return true if @move.move.pbDamagingMove? && Effectiveness.ineffective?(typeMod)
# Dark-type immunity to moves made faster by Prankster
return true if Settings::MECHANICS_GENERATION >= 7 && @user.has_active_ability?(:PRANKSTER) &&
@target.has_type?(:DARK) && @target.opposes?(@user)
# Airborne-based immunity to Ground moves
return true if @move.damagingMove? && calc_type == :GROUND &&
@target.battler.airborne? && !@move.move.hitsFlyingTargets?
# Immunity to powder-based moves
if @move.move.powderMove?
return true if @target.has_type?(:GRASS) && Settings::MORE_TYPE_EFFECTS
if Settings::MECHANICS_GENERATION >= 6
return true if @target.has_active_ability?(:OVERCOAT) ||
@target.has_active_item?(:SAFETYGOGGLES)
end
end
# Substitute
return true if @target.effects[PBEffects::Substitute] > 0 && @move.statusMove? &&
!@move.move.ignoresSubstitute?(@user.battler) && @user.index != @target.index
return false
end
#=============================================================================
# Get a score for the given move being used against the given target
#=============================================================================
@@ -108,8 +157,11 @@ class Battle::AI
user_battler = @user.battler
target_battler = @target.battler
# Predict whether the move will fail
return 10 if pbPredictMoveFailure
# Get the base score for the move
if @move.move.damagingMove?
if @move.damagingMove?
# Is also the predicted damage amount as a percentage of target's current HP
score = pbGetDamagingMoveBaseScore
else # Status moves
@@ -153,16 +205,8 @@ class Battle::AI
# don't prefer move if it's Normal-type and target is immune because
# of its ability (Lightning Rod, etc.).
# TODO: Discard move if it can be redirected by a non-target's ability
# (Lightning Rod/Storm Drain). Include checking for a previous use of
# Ion Deluge and this move being Normal-type.
# => If non-target is a user's ally, don't prefer move (rather than discarding
# it)
# TODO: Discard move if it's sound-based and user has been Throat Chopped.
# Don't prefer move if user hasn't been Throat Chopped but target has
# previously used Throat Chop. The first part of this would probably
# go elsewhere (damage calc?).
# TODO: Don't prefer sound move if user hasn't been Throat Chopped but
# target has previously used Throat Chop.
# TODO: Prefer move if it has a high critical hit rate, critical hits are
# possible but not certain, and target has raised defences/user has
@@ -248,12 +292,6 @@ class Battle::AI
end
end
# If user is asleep, don't prefer moves that can't be used while asleep
if @trainer.medium_skill? && user_battler.asleep? && user_battler.statusCount > 1 &&
!@move.move.usableWhenAsleep?
score *= 0.2
end
# If user is frozen, prefer a move that can thaw the user
if @trainer.medium_skill? && user_battler.status == :FROZEN
if @move.move.thawsUser?
@@ -261,7 +299,7 @@ class Battle::AI
else
user_battler.eachMove do |m|
next unless m.thawsUser?
score = 0 # Discard this move if user knows another move that thaws
score -= 30 # Don't prefer this move if user knows another move that thaws
break
end
end

View File

@@ -12,42 +12,63 @@ Battle::AI::Handlers::MoveEffectScore.add("DoesNothingCongratulations",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("DoesNothingFailsIfNoAlly",
proc { |move, user, target, ai, battle|
next true if user.battler.allAllies.length == 0
}
)
Battle::AI::Handlers::MoveEffectScore.copy("DoesNothingCongratulations",
"DoesNothingFailsIfNoAlly")
Battle::AI::Handlers::MoveEffectScore.copy("DoesNothingCongratulations",
"DoesNothingFailsIfNoAlly",
"DoesNothingUnusableInGravity",
"DoubleMoneyGainedFromBattle")
# AddMoneyGainedFromBattle
Battle::AI::Handlers::MoveEffectScore.add("FailsIfNotUserFirstTurn",
proc { |score, move, user, target, ai, battle|
next score - 90 if user.turnCount > 0
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfNotUserFirstTurn",
proc { |move, user, target, ai, battle|
next true if user.turnCount > 0
}
)
# FailsIfUserHasUnusedMove
Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserNotConsumedBerry",
proc { |score, move, user, target, ai, battle|
next score - 90 if !user.battler.belched?
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserHasUnusedMove",
proc { |move, user, target, ai, battle|
has_another_move = false
has_unused_move = false
user.battler.eachMove do |m|
next if m.id == move.id
has_another_move = true
next if user.battler.movesUsed.include?(m.id)
has_unused_move = true
break
end
next true if !has_another_move || has_unused_move
}
)
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserNotConsumedBerry",
proc { |move, user, target, ai, battle|
next true if !user.battler.belched?
}
)
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfTargetHasNoItem",
proc { |move, user, target, ai, battle|
next true if !target.item || !target.item_active?
}
)
Battle::AI::Handlers::MoveEffectScore.add("FailsIfTargetHasNoItem",
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill?
next score - 90 if !target.item || !target.item_active?
next score + 50
end
next score + 50 if ai.trainer.medium_skill?
}
)
Battle::AI::Handlers::MoveEffectScore.add("FailsUnlessTargetSharesTypeWithUser",
proc { |score, move, user, target, ai, battle|
if !(user.types[0] && target.has_type?(user.types[0])) &&
!(user.types[1] && target.has_type?(user.types[1]))
next score - 90
end
Battle::AI::Handlers::MoveFailureCheck.add("FailsUnlessTargetSharesTypeWithUser",
proc { |move, user, target, ai, battle|
user_types = user.battler.pbTypes(true)
target_types = target.battler.pbTypes(true)
next true if (user_types & target_types).empty?
}
)
@@ -68,13 +89,17 @@ Battle::AI::Handlers::MoveEffectScore.add("CrashDamageIfFailsUnusableInGravity",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartSunWeather",
proc { |move, user, target, ai, battle|
next true if [:HarshSun, :HeavyRain, :StrongWinds,
move.move.weatherType].include?(battle.field.weather)
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
proc { |score, move, user, target, ai, battle|
if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
next score - 90
elsif battle.field.weather == :Sun
next score - 90
next score - 50
else
user.battler.eachMove do |m|
next if !m.damagingMove? || m.type != :FIRE
@@ -85,13 +110,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"StartRainWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
proc { |score, move, user, target, ai, battle|
if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
next score - 90
elsif battle.field.weather == :Rain
next score - 90
next score - 50
else
user.battler.eachMove do |m|
next if !m.damagingMove? || m.type != :WATER
@@ -102,47 +127,66 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"StartSandstormWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather",
proc { |score, move, user, target, ai, battle|
if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
next score - 90
elsif battle.field.weather == :Rain
next score - 90
next score - 50
end
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"StartHailWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather",
proc { |score, move, user, target, ai, battle|
if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
next score - 90
elsif battle.field.weather == :Hail
next score - 90
next score - 50
end
}
)
# StartElectricTerrain
# StartGrassyTerrain
# StartMistyTerrain
# StartPsychicTerrain
Battle::AI::Handlers::MoveEffectScore.add("RemoveTerrain",
proc { |score, move, user, target, ai, battle|
next 0 if battle.field.terrain == :None
Battle::AI::Handlers::MoveFailureCheck.add("StartElectricTerrain",
proc { |move, user, target, ai, battle|
next true if battle.field.terrain == :Electric
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartGrassyTerrain",
proc { |move, user, target, ai, battle|
next true if battle.field.terrain == :Grassy
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartMistyTerrain",
proc { |move, user, target, ai, battle|
next true if battle.field.terrain == :Misty
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartPsychicTerrain",
proc { |move, user, target, ai, battle|
next true if battle.field.terrain == :Psychic
}
)
Battle::AI::Handlers::MoveFailureCheck.add("RemoveTerrain",
proc { |move, user, target, ai, battle|
next true if battle.field.terrain == :None
}
)
Battle::AI::Handlers::MoveFailureCheck.add("AddSpikesToFoeSide",
proc { |move, user, target, ai, battle|
next true if user.pbOpposingSide.effects[PBEffects::Spikes] >= 3
}
)
Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
proc { |score, move, user, target, ai, battle|
if user.pbOpposingSide.effects[PBEffects::Spikes] >= 3
next score - 90
elsif user.battler.allOpposing.none? { |b| battle.pbCanChooseNonActive?(b.index) }
if user.battler.allOpposing.none? { |b| battle.pbCanChooseNonActive?(b.index) }
next score - 90 # Opponent can't switch in any Pokemon
else
score += 10 * battle.pbAbleNonActiveCount(user.idxOpposingSide)
@@ -152,11 +196,14 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("AddToxicSpikesToFoeSide",
proc { |move, user, target, ai, battle|
next true if user.pbOpposingSide.effects[PBEffects::ToxicSpikes] >= 2
}
)
Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
proc { |score, move, user, target, ai, battle|
if user.pbOpposingSide.effects[PBEffects::ToxicSpikes] >= 2
next score - 90
elsif user.battler.allOpposing.none? { |b| battle.pbCanChooseNonActive?(b.index) }
if user.battler.allOpposing.none? { |b| battle.pbCanChooseNonActive?(b.index) }
next score - 90 # Opponent can't switch in any Pokemon
else
score += 8 * battle.pbAbleNonActiveCount(user.idxOpposingSide)
@@ -166,11 +213,14 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("AddStealthRocksToFoeSide",
proc { |move, user, target, ai, battle|
next true if user.pbOpposingSide.effects[PBEffects::StealthRock]
}
)
Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
proc { |score, move, user, target, ai, battle|
if user.pbOpposingSide.effects[PBEffects::StealthRock]
next score - 90
elsif user.battler.allOpposing.none? { |b| battle.pbCanChooseNonActive?(b.index) }
if user.battler.allOpposing.none? { |b| battle.pbCanChooseNonActive?(b.index) }
next score - 90 # Opponent can't switch in any Pokemon
else
next score + 10 * battle.pbAbleNonActiveCount(user.idxOpposingSide)
@@ -178,12 +228,33 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
}
)
Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide",
proc { |score, move, user, target, ai, battle|
next score - 95 if user.pbOpposingSide.effects[PBEffects::StickyWeb]
Battle::AI::Handlers::MoveFailureCheck.add("AddStickyWebToFoeSide",
proc { |move, user, target, ai, battle|
next true if user.pbOpposingSide.effects[PBEffects::StickyWeb]
}
)
Battle::AI::Handlers::MoveFailureCheck.add("SwapSideEffects",
proc { |move, user, target, ai, battle|
has_effect = false
2.times do |side|
effects = battle.sides[side].effects
move.move.number_effects.each do |e|
next if effects[e] == 0
has_effect = true
break
end
break if has_effect
move.move.boolean_effects.each do |e|
next if !effects[e]
has_effect = true
break
end
break if has_effect
end
next !has_effect
}
)
Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects",
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill?
@@ -206,13 +277,10 @@ Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects",
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserMakeSubstitute",
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::Substitute] > 0
next score - 90
elsif user.hp <= user.totalhp / 4
next score - 90
end
Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Substitute] > 0
next true if user.hp <= [user.totalhp / 4, 1].max
}
)
@@ -229,18 +297,32 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveUserBindingAndEntryHazards",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("AttackTwoTurnsLater",
proc { |move, user, target, ai, battle|
next true if battle.positions[target.index].effects[PBEffects::FutureSightCounter] > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("AttackTwoTurnsLater",
proc { |score, move, user, target, ai, battle|
if battle.positions[target.index].effects[PBEffects::FutureSightCounter] > 0
next 0
elsif battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
# Future Sight tends to be wasteful if down to last Pokemon
next score - 70
end
}
)
# UserSwapsPositionsWithAlly
Battle::AI::Handlers::MoveFailureCheck.add("UserSwapsPositionsWithAlly",
proc { |move, user, target, ai, battle|
num_targets = 0
idxUserOwner = battle.pbGetOwnerIndexFromBattlerIndex(user.index)
user.battler.allAllies.each do |b|
next if battle.pbGetOwnerIndexFromBattlerIndex(b.index) != idxUserOwner
next if !b.near?(user)
num_targets += 1
end
next num_targets != 1
}
)
Battle::AI::Handlers::MoveEffectScore.add("BurnAttackerBeforeUserActs",
proc { |score, move, user, target, ai, battle|

View File

@@ -1,35 +1,48 @@
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SleepTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanSleep?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SleepTarget",
proc { |score, move, user, target, ai, battle|
if target.battler.pbCanSleep?(user.battler, false)
score += 30
if ai.trainer.medium_skill?
score -= 30 if target.effects[PBEffects::Yawn] > 0
score += 30
if ai.trainer.medium_skill?
score -= 30 if target.effects[PBEffects::Yawn] > 0
end
score -= 30 if target.has_active_ability?(:MARVELSCALE)
if ai.trainer.best_skill?
if target.battler.pbHasMoveFunction?("FlinchTargetFailsIfUserNotAsleep",
"UseRandomUserMoveIfAsleep") # Snore, Sleep Talk
score -= 50
end
score -= 30 if target.has_active_ability?(:MARVELSCALE)
if ai.trainer.best_skill?
if target.battler.pbHasMoveFunction?("FlinchTargetFailsIfUserNotAsleep",
"UseRandomUserMoveIfAsleep") # Snore, Sleep Talk
score -= 50
end
end
else
next 0 if move.statusMove?
end
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetIfUserDarkrai",
proc { |move, user, target, ai, battle|
next true if !user.battler.isSpecies?(:DARKRAI) && user.effects[PBEffects::TransformSpecies] != :DARKRAI
next true if move.statusMove? && !target.pbCanSleep?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget",
"SleepTargetIfUserDarkrai")
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget",
"SleepTargetIfUserDarkrai",
"SleepTargetChangeUserMeloettaForm")
Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetNextTurn",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Yawn] > 0
next true if !target.pbCanSleep?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SleepTargetNextTurn",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Yawn] > 0 ||
!target.battler.pbCanSleep?(user.battler, false)
score += 30
score -= 30 if target.has_active_ability?(:MARVELSCALE)
if ai.trainer.best_skill?
@@ -42,31 +55,36 @@ Battle::AI::Handlers::MoveEffectScore.add("SleepTargetNextTurn",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("PoisonTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanPoison?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("PoisonTarget",
proc { |score, move, user, target, ai, battle|
if target.battler.pbCanPoison?(user.battler, false)
score += 30
if ai.trainer.medium_skill?
score += 30 if target.hp <= target.totalhp / 4
score += 50 if target.hp <= target.totalhp / 8
score -= 40 if target.effects[PBEffects::Yawn] > 0
end
if ai.trainer.high_skill?
score += 10 if target.rough_stat(:DEFENSE) > 100
score += 10 if target.rough_stat(:SPECIAL_DEFENSE) > 100
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :TOXICBOOST])
else
next 0 if move.statusMove?
score += 30
if ai.trainer.medium_skill?
score += 30 if target.hp <= target.totalhp / 4
score += 50 if target.hp <= target.totalhp / 8
score -= 40 if target.effects[PBEffects::Yawn] > 0
end
if ai.trainer.high_skill?
score += 10 if target.rough_stat(:DEFENSE) > 100
score += 10 if target.rough_stat(:SPECIAL_DEFENSE) > 100
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :TOXICBOOST])
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("PoisonTargetLowerTargetSpeed1",
proc { |move, user, target, ai, battle|
next true if !target.pbCanPoison?(user.battler, false, move.move) &&
!target.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("PoisonTargetLowerTargetSpeed1",
proc { |score, move, user, target, ai, battle|
next 0 if !target.battler.pbCanPoison?(user.battler, false) &&
!target.battler.pbCanLowerStatStage?(:SPEED, user.battler)
if target.battler.pbCanPoison?(user.battler, false)
score += 30
if ai.trainer.medium_skill?
@@ -92,64 +110,70 @@ Battle::AI::Handlers::MoveEffectScore.add("PoisonTargetLowerTargetSpeed1",
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("PoisonTarget",
"BadPoisonTarget")
Battle::AI::Handlers::MoveEffectScore.add("BadPoisonTarget",
proc { |score, move, user, target, ai, battle|
if target.battler.pbCanPoison?(user.battler, false)
score += 30
if ai.trainer.medium_skill?
score += 30 if target.hp <= target.totalhp / 4
score += 50 if target.hp <= target.totalhp / 8
score -= 40 if target.effects[PBEffects::Yawn] > 0
end
if ai.trainer.high_skill?
score += 10 if target.rough_stat(:DEFENSE) > 100
score += 10 if target.rough_stat(:SPECIAL_DEFENSE) > 100
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :TOXICBOOST])
else
score -= 90 if move.statusMove?
score += 30
if ai.trainer.medium_skill?
score += 30 if target.hp <= target.totalhp / 4
score += 50 if target.hp <= target.totalhp / 8
score -= 40 if target.effects[PBEffects::Yawn] > 0
end
if ai.trainer.high_skill?
score += 10 if target.rough_stat(:DEFENSE) > 100
score += 10 if target.rough_stat(:SPECIAL_DEFENSE) > 100
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :TOXICBOOST])
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("ParalyzeTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanParalyze?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("ParalyzeTarget",
proc { |score, move, user, target, ai, battle|
if target.battler.pbCanParalyze?(user.battler, false) &&
!(ai.trainer.medium_skill? &&
move.id == :THUNDERWAVE &&
Effectiveness.ineffective?(target.effectiveness_of_type_against_battler(move.type, user)))
score += 30
if ai.trainer.medium_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
if aspeed < ospeed
score += 30
elsif aspeed > ospeed
score -= 40
end
score += 30
if ai.trainer.medium_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
if aspeed < ospeed
score += 30
elsif aspeed > ospeed
score -= 40
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET])
else
score -= 90 if move.statusMove?
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET])
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("ParalyzeTargetIfNotTypeImmune",
proc { |move, user, target, ai, battle|
eff = target.effectiveness_of_type_against_battler(move.rough_type, user)
next true if Effectiveness.ineffective?(eff)
next true if move.statusMove? && !target.pbCanParalyze?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget",
"ParalyzeTargetIfNotTypeImmune")
Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget",
"ParalyzeTargetIfNotTypeImmune",
"ParalyzeTargetAlwaysHitsInRainHitsTargetInSky",
"ParalyzeFlinchTarget")
Battle::AI::Handlers::MoveFailureCheck.add("BurnTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanBurn?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("BurnTarget",
proc { |score, move, user, target, ai, battle|
if target.battler.pbCanBurn?(user.battler, false)
score += 30
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST])
else
score -= 90 if move.statusMove?
end
score += 30
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST])
next score
}
)
@@ -158,14 +182,15 @@ Battle::AI::Handlers::MoveEffectScore.copy("BurnTarget",
"BurnTargetIfTargetStatsRaisedThisTurn",
"BurnFlinchTarget")
Battle::AI::Handlers::MoveFailureCheck.add("FreezeTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanFreeze?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("FreezeTarget",
proc { |score, move, user, target, ai, battle|
if target.battler.pbCanFreeze?(user.battler, false)
score += 30
score -= 20 if target.has_active_ability?(:MARVELSCALE)
else
score -= 90 if move.statusMove?
end
score += 30
score -= 20 if target.has_active_ability?(:MARVELSCALE)
next score
}
)
@@ -201,13 +226,23 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("GiveUserStatusToTarget",
proc { |move, user, target, ai, battle|
next true if user.status == :NONE
next true if !target.battler.pbCanInflictStatus?(user.status, user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("GiveUserStatusToTarget",
proc { |score, move, user, target, ai, battle|
next 0 if user.status == :NONE
next score + 40
}
)
Battle::AI::Handlers::MoveFailureCheck.add("CureUserBurnPoisonParalysis",
proc { |move, user, target, ai, battle|
next true if ![:BURN, :POISON, :PARALYSIS].include?(user.status)
}
)
Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis",
proc { |score, move, user, target, ai, battle|
case user.status
@@ -223,24 +258,27 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis",
end
when :BURN, :PARALYSIS
score += 40
else
score -= 90
end
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("CureUserPartyStatus",
proc { |move, user, target, ai, battle|
has_effect = battle.allSameSideBattlers(user.battler).any? { |b| b.status != :NONE }
if !has_effect
has_effect = battle.pbParty(user.index).any? { |pkmn| pkmn&.able? && pkmn.status != :NONE }
end
next !has_effect
}
)
Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus",
proc { |score, move, user, target, ai, battle|
statuses = 0
battle.pbParty(user.index).each do |pkmn|
statuses += 1 if pkmn && pkmn.status != :NONE
end
if statuses == 0
score -= 80
else
score += 20 * statuses
end
score += 20 * statuses
next score
}
)
@@ -256,11 +294,14 @@ Battle::AI::Handlers::MoveEffectScore.add("CureTargetBurn",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToInflictedStatus",
proc { |move, user, target, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::Safeguard] > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatus",
proc { |score, move, user, target, ai, battle|
if user.pbOwnSide.effects[PBEffects::Safeguard] > 0
score -= 80
elsif user.status != :NONE
if user.status != :NONE
score -= 40
else
score += 30
@@ -271,16 +312,18 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatu
Battle::AI::Handlers::MoveEffectScore.add("FlinchTarget",
proc { |score, move, user, target, ai, battle|
score += 30
score += 30 if !target.has_active_ability?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute] == 0
next score
next score + 30 if !target.has_active_ability?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute] == 0
}
)
Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfUserNotAsleep",
proc { |move, user, target, ai, battle|
next true if !user.asleep?
}
)
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfUserNotAsleep",
proc { |score, move, user, target, ai, battle|
next 0 if !user.battler.asleep?
score += 100 # Because it can only be used while asleep
score += 30 if !target.has_active_ability?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute] == 0
@@ -288,12 +331,15 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfUserNotAsleep",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfNotUserFirstTurn",
proc { |move, user, target, ai, battle|
next true if user.turnCount > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfNotUserFirstTurn",
proc { |score, move, user, target, ai, battle|
next 0 if user.turnCount != 0
score += 30 if !target.has_active_ability?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute] == 0
next score
next score + 30 if !target.has_active_ability?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute] == 0
}
)
@@ -301,7 +347,7 @@ Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky",
proc { |score, move, user, target, ai, battle|
score += 30 if !target.has_active_ability?(:INNERFOCUS) &&
@@ -310,9 +356,13 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky"
}
)
Battle::AI::Handlers::MoveFailureCheck.add("ConfuseTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanConfuse?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("ConfuseTarget",
proc { |score, move, user, target, ai, battle|
next 0 if !target.battler.pbCanConfuse?(user.battler, false)
next score + 30
}
)
@@ -320,22 +370,15 @@ Battle::AI::Handlers::MoveEffectScore.add("ConfuseTarget",
Battle::AI::Handlers::MoveEffectScore.copy("ConfuseTarget",
"ConfuseTargetAlwaysHitsInRainHitsTargetInSky")
Battle::AI::Handlers::MoveFailureCheck.add("AttractTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanAttract?(user.battler, false)
}
)
Battle::AI::Handlers::MoveEffectScore.add("AttractTarget",
proc { |score, move, user, target, ai, battle|
canattract = true
agender = user.gender
ogender = target.gender
if agender == 2 || ogender == 2 || agender == ogender
score -= 90
canattract = false
elsif target.effects[PBEffects::Attract] >= 0
score -= 80
canattract = false
elsif target.has_active_ability?(:OBLIVIOUS)
score -= 80
canattract = false
end
if canattract && target.has_active_item?(:DESTINYKNOT) &&
score += 30
if target.has_active_item?(:DESTINYKNOT) &&
user.battler.pbCanAttract?(target.battler, false)
score -= 30
end
@@ -343,66 +386,55 @@ Battle::AI::Handlers::MoveEffectScore.add("AttractTarget",
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesBasedOnEnvironment",
proc { |score, move, user, target, ai, battle|
if !user.battler.canChangeType?
score -= 90
elsif ai.trainer.medium_skill?
new_type = nil
case battle.field.terrain
when :Electric
new_type = :ELECTRIC if GameData::Type.exists?(:ELECTRIC)
when :Grassy
new_type = :GRASS if GameData::Type.exists?(:GRASS)
when :Misty
new_type = :FAIRY if GameData::Type.exists?(:FAIRY)
when :Psychic
new_type = :PSYCHIC if GameData::Type.exists?(:PSYCHIC)
end
if !new_type
envtypes = {
:None => :NORMAL,
:Grass => :GRASS,
:TallGrass => :GRASS,
:MovingWater => :WATER,
:StillWater => :WATER,
:Puddle => :WATER,
:Underwater => :WATER,
:Cave => :ROCK,
:Rock => :GROUND,
:Sand => :GROUND,
:Forest => :BUG,
:ForestGrass => :BUG,
:Snow => :ICE,
:Ice => :ICE,
:Volcano => :FIRE,
:Graveyard => :GHOST,
:Sky => :FLYING,
:Space => :DRAGON,
:UltraSpace => :PSYCHIC
}
new_type = envtypes[battle.environment]
new_type = nil if !GameData::Type.exists?(new_type)
new_type ||= :NORMAL
end
score -= 90 if !user.battler.pbHasOtherType?(new_type)
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment",
proc { |move, user, target, ai, battle|
next true if !user.battler.canChangeType?
new_type = nil
case battle.field.terrain
when :Electric
new_type = :ELECTRIC if GameData::Type.exists?(:ELECTRIC)
when :Grassy
new_type = :GRASS if GameData::Type.exists?(:GRASS)
when :Misty
new_type = :FAIRY if GameData::Type.exists?(:FAIRY)
when :Psychic
new_type = :PSYCHIC if GameData::Type.exists?(:PSYCHIC)
end
next score
if !new_type
envtypes = {
:None => :NORMAL,
:Grass => :GRASS,
:TallGrass => :GRASS,
:MovingWater => :WATER,
:StillWater => :WATER,
:Puddle => :WATER,
:Underwater => :WATER,
:Cave => :ROCK,
:Rock => :GROUND,
:Sand => :GROUND,
:Forest => :BUG,
:ForestGrass => :BUG,
:Snow => :ICE,
:Ice => :ICE,
:Volcano => :FIRE,
:Graveyard => :GHOST,
:Sky => :FLYING,
:Space => :DRAGON,
:UltraSpace => :PSYCHIC
}
new_type = envtypes[battle.environment]
new_type = nil if !GameData::Type.exists?(new_type)
new_type ||= :NORMAL
end
next true if !user.battler.pbHasOtherType?(new_type)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesToResistLastAttack",
proc { |score, move, user, target, ai, battle|
next 0 if !user.battler.canChangeType?
next 0 if !target.battler.lastMoveUsed || !target.battler.lastMoveUsedType ||
GameData::Type.get(target.battler.lastMoveUsedType).pseudo_type
aType = nil
target.battler.eachMove do |m|
next if m.id != target.battler.lastMoveUsed
aType = m.pbCalcType(user.battler)
break
end
next 0 if !aType
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToResistLastAttack",
proc { |move, user, target, ai, battle|
next true if !user.battler.canChangeType?
next true if !target.battler.lastMoveUsed || !target.battler.lastMoveUsedType ||
GameData::Type.get(target.battler.lastMoveUsedType).pseudo_type
has_possible_type = false
GameData::Type.each do |t|
next if t.pseudo_type || user.has_type?(t.id) ||
@@ -410,21 +442,22 @@ Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesToResistLastAttack",
has_possible_type = true
break
end
next 0 if !has_possible_type
next !has_possible_type
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesToTargetTypes",
proc { |score, move, user, target, ai, battle|
next 0 if !user.battler.canChangeType? || target.battler.pbTypes(true).length == 0
next 0 if user.battler.pbTypes == target.battler.pbTypes &&
user.effects[PBEffects::Type3] == target.effects[PBEffects::Type3]
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToTargetTypes",
proc { |move, user, target, ai, battle|
next true if !user.battler.canChangeType?
next true if target.battler.pbTypes(true).empty?
next true if user.battler.pbTypes == target.battler.pbTypes &&
user.effects[PBEffects::Type3] == target.effects[PBEffects::Type3]
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesToUserMoveType",
proc { |score, move, user, target, ai, battle|
next 0 if !user.battler.canChangeType?
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToUserMoveType",
proc { |move, user, target, ai, battle|
next true if !user.battler.canChangeType?
has_possible_type = false
user.battler.eachMoveWithIndex do |m, i|
break if Settings::MECHANICS_GENERATION >= 6 && i > 0
@@ -433,147 +466,121 @@ Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesToUserMoveType",
has_possible_type = true
break
end
next 0 if !has_possible_type
next !has_possible_type
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetTargetTypesToPsychic",
proc { |score, move, user, target, ai, battle|
if !target.battler.canChangeType?
score -= 90
elsif !target.battler.pbHasOtherType?(:PSYCHIC)
score -= 90
end
next score
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetTypesToPsychic",
proc { |move, user, target, ai, battle|
next true if !target.battler.canChangeType?
next true if !GameData::Type.exists?(:PSYCHIC) || !target.battler.pbHasOtherType?(:PSYCHIC)
next true if !target.battler.affectedByPowder?
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetTargetTypesToWater",
proc { |score, move, user, target, ai, battle|
if !target.battler.canChangeType? || target.effects[PBEffects::Substitute] > 0
score -= 90
elsif !target.battler.pbHasOtherType?(:WATER)
score -= 90
end
next score
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetTypesToWater",
proc { |move, user, target, ai, battle|
next true if !target.battler.canChangeType?
next true if !GameData::Type.exists?(:WATER) || !target.battler.pbHasOtherType?(:WATER)
}
)
Battle::AI::Handlers::MoveEffectScore.add("AddGhostTypeToTarget",
proc { |score, move, user, target, ai, battle|
next 0 if target.has_type?(:GHOST)
Battle::AI::Handlers::MoveFailureCheck.add("AddGhostTypeToTarget",
proc { |move, user, target, ai, battle|
next true if !target.battler.canChangeType?
next true if !GameData::Type.exists?(:GHOST) || target.has_type?(:GHOST)
}
)
Battle::AI::Handlers::MoveEffectScore.add("AddGrassTypeToTarget",
proc { |score, move, user, target, ai, battle|
next 0 if target.has_type?(:GRASS)
Battle::AI::Handlers::MoveFailureCheck.add("AddGrassTypeToTarget",
proc { |move, user, target, ai, battle|
next true if !target.battler.canChangeType?
next true if !GameData::Type.exists?(:GRASS) || target.has_type?(:GRASS)
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserLosesFireType",
proc { |score, move, user, target, ai, battle|
next 0 if !user.has_type?(:FIRE)
Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType",
proc { |move, user, target, ai, battle|
next true if !user.has_type?(:FIRE)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToSimple",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Substitute] > 0
if ai.trainer.medium_skill?
next 0 if target.battler.unstoppableAbility? ||
[:TRUANT, :SIMPLE].include?(target.ability)
end
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToSimple",
proc { |move, user, target, ai, battle|
next true if !GameData::Ability.exists?(:SIMPLE)
next true if target.battler.unstoppableAbility? ||
[:TRUANT, :SIMPLE].include?(target.ability_id)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToInsomnia",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Substitute] > 0
if ai.trainer.medium_skill?
next 0 if target.battler.unstoppableAbility? ||
[:TRUANT, :INSOMNIA].include?(target.ability)
end
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToInsomnia",
proc { |move, user, target, ai, battle|
next true if !GameData::Ability.exists?(:INSOMNIA)
next true if target.battler.unstoppableAbility? ||
[:TRUANT, :INSOMNIA].include?(target.ability_id)
}
)
Battle::AI::Handlers::MoveFailureCheck.add("SetUserAbilityToTargetAbility",
proc { |move, user, target, ai, battle|
next true if user.battle.unstoppableAbility?
next true if !target.ability || user.ability_id == target.ability_id
next true if target.battler.ungainableAbility? ||
[:POWEROFALCHEMY, :RECEIVER, :TRACE, :WONDERGUARD].include?(target.ability_id)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetUserAbilityToTargetAbility",
proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move
if ai.trainer.medium_skill?
if !target.ability || user.ability == target.ability ||
[:MULTITYPE, :RKSSYSTEM].include?(user.ability_id) ||
[:FLOWERGIFT, :FORECAST, :ILLUSION, :IMPOSTER, :MULTITYPE, :RKSSYSTEM,
:TRACE, :WONDERGUARD, :ZENMODE].include?(target.ability_id)
score -= 90
end
end
if ai.trainer.high_skill?
if target.ability == :TRUANT && user.opposes?(target)
score -= 90
elsif target.ability == :SLOWSTART && user.opposes?(target)
score -= 90
end
if ai.trainer.medium_skill? && user.opposes?(target)
score -= 50 if [:TRUANT, :SLOWSTART].include?(target.ability_id)
end
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToUserAbility",
proc { |move, user, target, ai, battle|
next true if !user.ability || user.ability_id == target.ability_id
next true if user.battler.ungainableAbility? ||
[:POWEROFALCHEMY, :RECEIVER, :TRACE].include?(user.ability_id)
next true if target.battle.unstoppableAbility? || target.ability_id == :TRUANT
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToUserAbility",
proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move
if target.effects[PBEffects::Substitute] > 0
score -= 90
elsif ai.trainer.medium_skill?
if !user.ability || user.ability == target.ability ||
[:MULTITYPE, :RKSSYSTEM, :TRUANT].include?(target.ability_id) ||
[:FLOWERGIFT, :FORECAST, :ILLUSION, :IMPOSTER, :MULTITYPE, :RKSSYSTEM,
:TRACE, :ZENMODE].include?(user.ability_id)
score -= 90
end
if ai.trainer.high_skill?
if user.ability == :TRUANT && user.opposes?(target)
score += 90
elsif user.ability == :SLOWSTART && user.opposes?(target)
score += 90
end
end
if ai.trainer.medium_skill? && user.opposes?(target)
score += 90 if [:TRUANT, :SLOWSTART].include?(user.ability_id)
end
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapAbilities",
proc { |move, user, target, ai, battle|
next true if !user.ability || !target.ability
next true if Settings::MECHANICS_GENERATION <= 5 && user.ability_id == target.ability_id
next true if user.battle.unstoppableAbility? || user.battler.ungainableAbility? ||
user.ability_id == :WONDERGUARD
next true if target.battle.unstoppableAbility? || target.battler.ungainableAbility? ||
target.ability_id == :WONDERGUARD
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAbilities",
proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move
if ai.trainer.medium_skill?
if (!user.ability && !target.ability) ||
user.ability == target.ability ||
[:ILLUSION, :MULTITYPE, :RKSSYSTEM, :WONDERGUARD].include?(user.ability_id) ||
[:ILLUSION, :MULTITYPE, :RKSSYSTEM, :WONDERGUARD].include?(target.ability_id)
score -= 90
end
end
if ai.trainer.high_skill?
if target.ability == :TRUANT && user.opposes?(target)
score -= 90
elsif target.ability == :SLOWSTART && user.opposes?(target)
score -= 90
end
if ai.trainer.high_skill? && user.opposes?(target)
score -= 90 if [:TRUANT, :SLOWSTART].include?(target.ability_id)
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.add("NegateTargetAbility",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::Substitute] > 0 ||
target.effects[PBEffects::GastroAcid]
score -= 90
elsif ai.trainer.high_skill?
score -= 90 if [:MULTITYPE, :RKSSYSTEM, :SLOWSTART, :TRUANT].include?(target.ability_id)
end
next score
Battle::AI::Handlers::MoveFailureCheck.add("NegateTargetAbility",
proc { |move, user, target, ai, battle|
next true if target.unstoppableAbility? ||
target.effects[PBEffects::GastroAcid]
}
)
@@ -590,25 +597,24 @@ Battle::AI::Handlers::MoveEffectScore.add("NegateTargetAbilityIfTargetActed",
# IgnoreTargetAbility
Battle::AI::Handlers::MoveEffectScore.add("StartUserAirborne",
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::MagnetRise] > 0 ||
user.effects[PBEffects::Ingrain] ||
user.effects[PBEffects::SmackDown]
score -= 90
end
next score
Battle::AI::Handlers::MoveFailureCheck.add("StartUserAirborne",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Ingrain] ||
user.effects[PBEffects::SmackDown] ||
user.effects[PBEffects::MagnetRise] > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartTargetAirborneAndAlwaysHitByMoves",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::Telekinesis] > 0 ||
target.effects[PBEffects::Ingrain] ||
target.effects[PBEffects::SmackDown]
score -= 90
end
next score
Battle::AI::Handlers::MoveFailureCheck.add("StartTargetAirborneAndAlwaysHitByMoves",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Ingrain] ||
target.effects[PBEffects::SmackDown] ||
target.effects[PBEffects::Telekinesis] > 0
next true if target.battler.isSpecies?(:DIGLETT) ||
target.battler.isSpecies?(:DUGTRIO) ||
target.battler.isSpecies?(:SANDYGAST) ||
target.battler.isSpecies?(:PALOSSAND) ||
(target.battler.isSpecies?(:GENGAR) && target.battler.mega?)
}
)
@@ -629,11 +635,14 @@ Battle::AI::Handlers::MoveEffectScore.add("HitsTargetInSkyGroundsTarget",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartGravity",
proc { |move, user, target, ai, battle|
next true if battle.field.effects[PBEffects::Gravity] > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
proc { |score, move, user, target, ai, battle|
if battle.field.effects[PBEffects::Gravity] > 0
score -= 90
elsif ai.trainer.medium_skill?
if ai.trainer.medium_skill?
score -= 30
score -= 20 if user.effects[PBEffects::SkyDrop] >= 0
score -= 20 if user.effects[PBEffects::MagnetRise] > 0
@@ -655,8 +664,15 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
}
)
Battle::AI::Handlers::MoveEffectScore.add("TransformUserIntoTarget",
proc { |score, move, user, target, ai, battle|
next score - 70
Battle::AI::Handlers::MoveFailureCheck.add("TransformUserIntoTarget",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Transform]
next true if target.effects[PBEffects::Transform] ||
target.effects[PBEffects::Illusion]
}
)
Battle::AI::Handlers::MoveEffectScore.add("TransformUserIntoTarget",
proc { |score, move, user, target, ai, battle|
next score - 40
}
)

View File

@@ -5,7 +5,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamage20",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("FixedDamage20",
proc { |score, move, user, target, ai, battle|
if target.hp <= 20
@@ -21,7 +21,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamage40",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("FixedDamage40",
proc { |score, move, user, target, ai, battle|
next score + 80 if target.hp <= 40
@@ -32,7 +32,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamageHalfTargetHP",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageHalfTargetHP",
proc { |score, move, user, target, ai, battle|
score -= 50
@@ -44,7 +44,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevel",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageUserLevel",
proc { |score, move, user, target, ai, battle|
next score + 80 if target.hp <= user.level
@@ -55,18 +55,23 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevelRandom",
proc { |power, move, user, target, ai, battle|
next user.level # Average power
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageUserLevelRandom",
proc { |score, move, user, target, ai, battle|
next score + 30 if target.hp <= user.level
}
)
Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetHPToUserHP",
proc { |move, user, target, ai, battle|
next true if user.hp >= target.hp
}
)
Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetHPToUserHP",
proc { |score, move, user, target, ai, battle|
if user.hp >= target.hp
@@ -78,23 +83,33 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetHPToUserHP",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("OHKO",
proc { |move, user, target, ai, battle|
next true if target.level > user.level
next true if target.has_active_ability?(:STURDY)
}
)
Battle::AI::Handlers::MoveBasePower.add("OHKO",
proc { |power, move, user, target, ai, battle|
next 999
}
}
Battle::AI::Handlers::MoveEffectScore.add("OHKO",
proc { |score, move, user, target, ai, battle|
next 0 if target.has_active_ability?(:STURDY)
next 0 if target.level > user.level
}
)
Battle::AI::Handlers::MoveFailureCheck.add("OHKOIce",
proc { |move, user, target, ai, battle|
next true if target.level > user.level
next true if target.has_active_ability?(:STURDY)
next true if target.has_type?(:ICE)
}
)
Battle::AI::Handlers::MoveBasePower.copy("OHKO",
"OHKOIce")
Battle::AI::Handlers::MoveEffectScore.copy("OHKO",
"OHKOIce")
Battle::AI::Handlers::MoveBasePower.copy("OHKO",
"OHKOIce",
"OHKOHitsUndergroundTarget")
Battle::AI::Handlers::MoveEffectScore.copy("OHKO",
"OHKOIce",
"OHKOHitsUndergroundTarget")
Battle::AI::Handlers::MoveEffectScore.add("DamageTargetAlly",
@@ -111,7 +126,7 @@ Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithUserHP",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.copy("PowerHigherWithUserHP",
"PowerLowerWithUserHP",
@@ -130,13 +145,13 @@ Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithLessPP",
ppLeft = [move.pp - 1, dmgs.length - 1].min
next dmgs[ppLeft]
}
}
)
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithTargetWeight",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.copy("PowerHigherWithTargetWeight",
"PowerHigherWithUserHeavierThanTarget")
@@ -145,26 +160,26 @@ Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithConsecutiveUse",
proc { |power, move, user, target, ai, battle|
next power << user.effects[PBEffects::FuryCutter]
}
}
)
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithConsecutiveUseOnUserSide",
proc { |power, move, user, target, ai, battle|
next power * (user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter] + 1)
}
}
)
Battle::AI::Handlers::MoveBasePower.add("RandomPowerDoublePowerIfTargetUnderground",
proc { |power, move, user, target, ai, battle|
power = 71 # Average damage
next move.pbModifyDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetHPLessThanHalf",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf",
"DoublePowerIfUserPoisonedBurnedParalyzed")
@@ -182,7 +197,7 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned",
"DoublePowerIfTargetParalyzedCureTarget")
@@ -196,19 +211,19 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetStatusProblem",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfUserHasNoItem",
proc { |power, move, user, target, ai, battle|
next power * 2 if !user.item || user.has_active_item?(:FLYINGGEM)
}
}
)
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetUnderwater",
proc { |power, move, user, target, ai, battle|
next move.pbModifyDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetUnderwater",
"DoublePowerIfTargetUnderground")
@@ -217,7 +232,7 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetInSky",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetInSky",
"DoublePowerInElectricTerrain",
@@ -265,6 +280,17 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartPreventCriticalHitsAgainstUserSide",
proc { |move, user, target, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::LuckyChant] > 0
}
)
Battle::AI::Handlers::MoveFailureCheck.add("CannotMakeTargetFaint",
proc { |move, user, target, ai, battle|
next true if target.hp == 1
}
)
Battle::AI::Handlers::MoveEffectScore.add("CannotMakeTargetFaint",
proc { |score, move, user, target, ai, battle|
next 0 if target.hp == 1
@@ -281,8 +307,8 @@ Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
proc { |score, move, user, target, ai, battle|
score -= 25 if user.hp > user.totalhp / 2
if ai.trainer.medium_skill?
score -= 90 if user.effects[PBEffects::ProtectRate] > 1
score -= 90 if target.effects[PBEffects::HyperBeam] > 0
score -= 50 if user.effects[PBEffects::ProtectRate] > 1
score -= 50 if target.effects[PBEffects::HyperBeam] > 0
else
score -= user.effects[PBEffects::ProtectRate] * 40
end
@@ -290,34 +316,56 @@ Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves",
proc { |move, user, target, ai, battle|
if Settings::MECHANICS_GENERATION >= 6
next true if battle.field.effects[PBEffects::MudSportField] > 0
else
next true if battle.allBattlers.any? { |b| b.effects[PBEffects::MudSport] }
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenElectricMoves",
proc { |score, move, user, target, ai, battle|
next 0 if user.effects[PBEffects::MudSport]
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves",
proc { |move, user, target, ai, battle|
if Settings::MECHANICS_GENERATION >= 6
next true if battle.field.effects[PBEffects::WaterSportField] > 0
else
next true if battle.allBattlers.any? { |b| b.effects[PBEffects::WaterSport] }
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenFireMoves",
proc { |score, move, user, target, ai, battle|
next 0 if user.effects[PBEffects::WaterSport]
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenPhysicalDamageAgainstUserSide",
proc { |score, move, user, target, ai, battle|
next 0 if user.pbOwnSide.effects[PBEffects::Reflect] > 0
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenPhysicalDamageAgainstUserSide",
proc { |move, user, target, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::Reflect] > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenSpecialDamageAgainstUserSide",
proc { |score, move, user, target, ai, battle|
next 0 if user.pbOwnSide.effects[PBEffects::LightScreen] > 0
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenSpecialDamageAgainstUserSide",
proc { |move, user, target, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::LightScreen] > 0
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenDamageAgainstUserSideIfHail",
proc { |move, user, target, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
next true if user.battler.effectiveWeather != :Hail
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHail",
proc { |score, move, user, target, ai, battle|
next 0 if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 ||
user.battler.effectiveWeather != :Hail
next score + 40
}
)
@@ -335,7 +383,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
score -= 90
score -= 50
else
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
@@ -351,7 +399,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
score -= 90
score -= 50
else
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
@@ -368,7 +416,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
score -= 90
score -= 50
else
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
@@ -384,7 +432,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct"
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
score -= 90
score -= 50
else
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
@@ -412,14 +460,22 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi
}
)
Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn",
proc { |move, user, target, ai, battle|
next true if user.turnCount > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn",
proc { |score, move, user, target, ai, battle|
next 0 if user.turnCount != 0
next score + 30
}
)
# ProtectUserSideFromStatusMoves
Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromStatusMoves",
proc { |move, user, target, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::CraftyShield]
}
)
# ProtectUserSideFromPriorityMoves
@@ -429,9 +485,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse
# RemoveProtectionsBypassSubstitute
Battle::AI::Handlers::MoveFailureCheck.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1",
proc { |move, user, target, ai, battle|
next true if !user.battler.isSpecies?(:HOOPA) || user.battler.form != 1
}
)
Battle::AI::Handlers::MoveEffectScore.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1",
proc { |score, move, user, target, ai, battle|
next 0 if !user.battler.isSpecies?(:HOOPA) || user.battler.form != 1
next score + 20 if target.stages[:DEFENSE] > 0
}
)
@@ -495,7 +555,7 @@ Battle::AI::Handlers::MoveBasePower.add("EffectivenessIncludesFlyingType",
next (power.to_f * mult / Effectiveness::NORMAL_EFFECTIVE).round
end
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTarget",
proc { |score, move, user, target, ai, battle|
@@ -513,8 +573,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTa
Battle::AI::Handlers::MoveEffectScore.add("EnsureNextMoveAlwaysHits",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Substitute] > 0
next 0 if user.effects[PBEffects::LockOn] > 0
next score - 50 if user.effects[PBEffects::LockOn] > 0
}
)
@@ -534,7 +593,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndG
Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndDarkImmunity",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::MiracleEye]
score -= 90
score -= 50
elsif target.has_type?(:DARK)
score += 70
elsif target.stages[:EVASION] <= 0
@@ -552,19 +611,21 @@ Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveFailureCheck.add("TypeAndPowerDependOnUserBerry",
proc { |move, user, target, ai, battle|
item = user.item
next true if !item || !item.is_berry? || !user.item_active?
next true if item.flags.none? { |f| f[/^NaturalGift_/i] }
}
)
Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnUserBerry",
proc { |power, move, user, target, ai, battle|
# TODO: Can't this just call move.pbBaseDamage?
ret = move.pbNaturalGiftBaseDamage(user.item_id)
next (ret == 1) ? 0 : ret
}
}
Battle::AI::Handlers::MoveEffectScore.add("TypeAndPowerDependOnUserBerry",
proc { |score, move, user, target, ai, battle|
next 0 if !user.item || !user.item.is_berry? || !user.item_active?
}
)
# TypeDependsOnUserPlate
@@ -573,6 +634,11 @@ Battle::AI::Handlers::MoveEffectScore.add("TypeAndPowerDependOnUserBerry",
# TypeDependsOnUserDrive
Battle::AI::Handlers::MoveFailureCheck.add("TypeDependsOnUserMorpekoFormRaiseUserSpeed1",
proc { |move, user, target, ai, battle|
next true if !user.battler.isSpecies?(:MORPEKO) && user.effects[PBEffects::TransformSpecies] != :MORPEKO
}
)
Battle::AI::Handlers::MoveEffectScore.add("TypeDependsOnUserMorpekoFormRaiseUserSpeed1",
proc { |score, move, user, target, ai, battle|
next score + 20 if user.stages[:SPEED] <= 0
@@ -583,7 +649,7 @@ Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnWeather",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveBasePower.copy("TypeAndPowerDependOnWeather",
"TypeAndPowerDependOnTerrain")

View File

@@ -6,7 +6,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
proc { |power, move, user, target, ai, battle|
next power * move.pbNumHits(user.battler, [target.battler])
}
}
)
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
"HitTwoTimesPoisonTarget")
@@ -40,19 +40,19 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimesTargetThenTargetAlly",
proc { |power, move, user, target, ai, battle|
next power * 2
}
}
)
Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit",
proc { |power, move, user, target, ai, battle|
next power * 6 # Hits do x1, x2, x3 ret in turn, for x6 in total
}
}
)
Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesAlwaysCriticalHit",
proc { |power, move, user, target, ai, battle|
next power * move.pbNumHits(user.battler, [target.battler])
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesAlwaysCriticalHit",
proc { |score, move, user, target, ai, battle|
if ai.trainer.high_skill?
@@ -67,7 +67,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
next power * 5 if user.has_active_ability?(:SKILLLINK)
next power * 31 / 10 # Average damage dealt
}
}
)
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja",
proc { |power, move, user, target, ai, battle|
@@ -77,14 +77,14 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja"
next power * 5 if user.has_active_ability?(:SKILLLINK)
next power * 31 / 10 # Average damage dealt
}
}
)
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
proc { |power, move, user, target, ai, battle|
next power * 5 if user.has_active_ability?(:SKILLLINK)
next power * 31 / 10 # Average damage dealt
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
proc { |score, move, user, target, ai, battle|
aspeed = user.rough_stat(:SPEED)
@@ -99,7 +99,18 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUs
}
)
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember",
proc { |move, user, target, ai, battle|
will_fail = true
battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, i|
next if !pkmn.able? || pkmn.status != :NONE
will_fail = false
break
end
next will_fail
}
)
Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember",
proc { |power, move, user, target, ai, battle|
ret = 0
ai.battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i|
@@ -107,7 +118,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesRaiseUserSpd1LowerUser
end
next ret
}
}
)
# AttackAndSkipNextTurn
@@ -117,7 +128,7 @@ Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamageMultiplier(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget",
proc { |score, move, user, target, ai, battle|
@@ -158,6 +169,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
proc { |move, user, target, ai, battle|
next true if !user.battler.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user.battler, move.move) &&
!user.battler.pbCanRaiseStatStage?(:SPECIAL_DEFENSE, user.battler, move.move) &&
!user.battler.pbCanRaiseStatStage?(:SPEED, user.battler, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
proc { |score, move, user, target, ai, battle|
if user.statStageAtMax?(:SPECIAL_ATTACK) &&
@@ -228,7 +246,14 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserSpAtk1",
# TwoTurnAttackInvulnerableInSkyParalyzeTarget
# TwoTurnAttackInvulnerableInSkyTargetCannotAct
Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct",
proc { |move, user, target, ai, battle|
next true if !target.opposes?(user)
next true if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
next true if Settings::MECHANICS_GENERATION >= 6 && target.battler.pbWeight >= 2000 # 200.0kg
next true if target.battler.semiInvulnerable? || target.effects[PBEffects::SkyDrop] >= 0
}
)
# TwoTurnAttackInvulnerableRemoveProtections
@@ -240,13 +265,13 @@ Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn",
proc { |power, move, user, target, ai, battle|
next power * 2 if user.effects[PBEffects::DefenseCurl]
}
}
)
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage",
proc { |power, move, user, target, ai, battle|
next 40 # Representative value
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage",
proc { |score, move, user, target, ai, battle|
if user.hp <= user.totalhp / 4

View File

@@ -1,10 +1,15 @@
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserFullyAndFallAsleep",
proc { |move, user, target, ai, battle|
next true if !user.battler.canHeal?
next true if user.battler.asleep?
next true if !user.battler.pbCanSleep?(user.battler, false, move.move, true)
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep",
proc { |score, move, user, target, ai, battle|
next 0 if user.hp == user.totalhp ||
!user.battler.pbCanSleep?(user.battler, false, nil, true)
score += 70
score -= user.hp * 140 / user.totalhp
score += 30 if user.status != :NONE
@@ -12,20 +17,23 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("HealUserHalfOfTotalHP",
proc { |move, user, target, ai, battle|
next true if !user.battler.canHeal?
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP",
proc { |score, move, user, target, ai, battle|
next 0 if user.hp == user.totalhp ||
(ai.trainer.medium_skill? && !user.battler.canHeal?)
score += 50
score -= user.hp * 100 / user.totalhp
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"HealUserDependingOnWeather")
Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather",
proc { |score, move, user, target, ai, battle|
next 0 if user.hp == user.totalhp ||
(ai.trainer.medium_skill? && !user.battler.canHeal?)
case user.battler.effectiveWeather
when :Sun, :HarshSun
score += 30
@@ -39,10 +47,10 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather",
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"HealUserDependingOnSandstorm")
Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm",
proc { |score, move, user, target, ai, battle|
next 0 if user.hp == user.totalhp ||
(ai.trainer.medium_skill? && !user.battler.canHeal?)
score += 50
score -= user.hp * 100 / user.totalhp
score += 30 if user.battler.effectiveWeather == :Sandstorm
@@ -50,53 +58,58 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm",
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"HealUserHalfOfTotalHPLoseFlyingTypeThisTurn")
Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeThisTurn",
proc { |score, move, user, target, ai, battle|
next 0 if user.hp == user.totalhp ||
(ai.trainer.medium_skill? && !user.battler.canHeal?)
score += 50
score -= user.hp * 100 / user.totalhp
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("CureTargetStatusHealUserHalfOfTotalHP",
proc { |move, user, target, ai, battle|
next true if !user.battler.canHeal?
next true if target.status == :NONE
}
)
Battle::AI::Handlers::MoveEffectScore.add("CureTargetStatusHealUserHalfOfTotalHP",
proc { |score, move, user, target, ai, battle|
if target.status == :NONE
score -= 90
elsif user.hp == user.totalhp && target.opposes?(user)
score -= 90
else
score += (user.totalhp - user.hp) * 50 / user.totalhp
score -= 30 if target.opposes?(user)
end
score += (user.totalhp - user.hp) * 50 / user.totalhp
score -= 30 if target.opposes?(user)
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("HealUserByTargetAttackLowerTargetAttack1",
proc { |move, user, target, ai, battle|
if target.has_active_ability?(:CONTRARY)
next true if target.statStageAtMax?(:ATTACK)
else
next true if target.statStageAtMin?(:ATTACK)
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserByTargetAttackLowerTargetAttack1",
proc { |score, move, user, target, ai, battle|
if target.statStageAtMin?(:ATTACK)
score -= 90
else
if target.battler.pbCanLowerStatStage?(:ATTACK, user.battler)
score += target.stages[:ATTACK] * 20
if ai.trainer.medium_skill?
hasPhysicalAttack = false
target.battler.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
if target.battler.pbCanLowerStatStage?(:ATTACK, user.battler)
score += target.stages[:ATTACK] * 20
if ai.trainer.medium_skill?
hasPhysicalAttack = false
target.battler.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
end
score += (user.totalhp - user.hp) * 50 / user.totalhp
end
score += (user.totalhp - user.hp) * 50 / user.totalhp
next score
}
)
@@ -112,9 +125,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByHalfOfDamageDone",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("HealUserByHalfOfDamageDoneIfTargetAsleep",
proc { |move, user, target, ai, battle|
next true if !target.battler.asleep?
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserByHalfOfDamageDoneIfTargetAsleep",
proc { |score, move, user, target, ai, battle|
next 0 if !target.battler.asleep?
if target.has_active_ability?(:LIQUIDOOZE)
score -= 70
elsif user.hp <= user.totalhp / 2
@@ -135,6 +152,11 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByThreeQuartersOfDamageDone",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("HealUserAndAlliesQuarterOfTotalHP",
proc { |move, user, target, ai, battle|
next true if battle.allSameSideBattlers(user.battler).none? { |b| b.canHeal? }
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserAndAlliesQuarterOfTotalHP",
proc { |score, move, user, target, ai, battle|
ally_amt = 30
@@ -149,6 +171,11 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserAndAlliesQuarterOfTotalHP",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("HealUserAndAlliesQuarterOfTotalHPCureStatus",
proc { |move, user, target, ai, battle|
next true if battle.allSameSideBattlers(user.battler).none? { |b| b.canHeal? || b.status != :NONE }
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserAndAlliesQuarterOfTotalHPCureStatus",
proc { |score, move, user, target, ai, battle|
ally_amt = 80 / battle.pbSideSize(user.index)
@@ -164,6 +191,11 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserAndAlliesQuarterOfTotalHPCure
}
)
Battle::AI::Handlers::MoveFailureCheck.add("HealTargetHalfOfTotalHP",
proc { |move, user, target, ai, battle|
next true if !target.battler.canHeal?
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealTargetHalfOfTotalHP",
proc { |score, move, user, target, ai, battle|
next 0 if user.opposes?(target)
@@ -174,6 +206,8 @@ Battle::AI::Handlers::MoveEffectScore.add("HealTargetHalfOfTotalHP",
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("HealTargetHalfOfTotalHP",
"HealTargetDependingOnGrassyTerrain")
Battle::AI::Handlers::MoveEffectScore.add("HealTargetDependingOnGrassyTerrain",
proc { |score, move, user, target, ai, battle|
next 0 if user.hp == user.totalhp ||
@@ -187,30 +221,32 @@ Battle::AI::Handlers::MoveEffectScore.add("HealTargetDependingOnGrassyTerrain",
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn",
proc { |score, move, user, target, ai, battle|
next 0 if battle.positions[user.index].effects[PBEffects::Wish] > 0
Battle::AI::Handlers::MoveFailureCheck.add("HealUserPositionNextTurn",
proc { |move, user, target, ai, battle|
next true if battle.positions[user.index].effects[PBEffects::Wish] > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn",
proc { |score, move, user, target, ai, battle|
next 0 if user.effects[PBEffects::AquaRing]
Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurn",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::AquaRing]
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle",
proc { |score, move, user, target, ai, battle|
next 0 if user.effects[PBEffects::Ingrain]
Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurnTrapUserInBattle",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Ingrain]
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartDamageTargetEachTurnIfTargetAsleep",
proc { |move, user, target, ai, battle|
next true if !target.battler.asleep? || target.effects[PBEffects::Nightmare]
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartDamageTargetEachTurnIfTargetAsleep",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::Nightmare] ||
target.effects[PBEffects::Substitute] > 0
score -= 90
elsif !target.battler.asleep?
if target.effects[PBEffects::Substitute] > 0
score -= 90
else
score -= 90 if target.statusCount <= 1
@@ -220,6 +256,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartDamageTargetEachTurnIfTargetAsle
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartLeechSeedTarget",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::LeechSeed] >= 0
next true if target.has_type?(:GRASS)
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartLeechSeedTarget",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::LeechSeed] >= 0
@@ -239,14 +281,17 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("UserLosesHalfOfTotalHPExplosive",
proc { |move, user, target, ai, battle|
next true if battle.pbCheckGlobalAbility(:DAMP)
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHPExplosive",
proc { |score, move, user, target, ai, battle|
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
if battle.pbCheckGlobalAbility(:DAMP)
score -= 100
elsif ai.trainer.medium_skill? && reserves == 0 && foes > 0
score -= 100 # don't want to lose
if ai.trainer.medium_skill? && reserves == 0 && foes > 0
score -= 60 # don't want to lose
elsif ai.trainer.high_skill? && reserves == 0 && foes == 0
score += 80 # want to draw
else
@@ -256,14 +301,14 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHPExplosive",
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("UserLosesHalfOfTotalHPExplosive",
"UserFaintsExplosive")
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive",
proc { |score, move, user, target, ai, battle|
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
if battle.pbCheckGlobalAbility(:DAMP)
score -= 100
elsif ai.trainer.medium_skill? && reserves == 0 && foes > 0
score -= 100 # don't want to lose
if ai.trainer.medium_skill? && reserves == 0 && foes > 0
score -= 60 # don't want to lose
elsif ai.trainer.high_skill? && reserves == 0 && foes == 0
score += 80 # want to draw
else
@@ -273,25 +318,23 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive",
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("UserLosesHalfOfTotalHPExplosive",
"UserFaintsPowersUpInMistyTerrainExplosive")
Battle::AI::Handlers::MoveBasePower.add("UserFaintsPowersUpInMistyTerrainExplosive",
proc { |power, move, user, target, ai, battle|
next power * 3 / 2 if battle.field.terrain == :Misty
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsPowersUpInMistyTerrainExplosive",
proc { |score, move, user, target, ai, battle|
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
if battle.pbCheckGlobalAbility(:DAMP)
score -= 100
elsif ai.trainer.medium_skill? && reserves == 0 && foes > 0
score -= 100 # don't want to lose
if ai.trainer.medium_skill? && reserves == 0 && foes > 0
score -= 60 # don't want to lose
elsif ai.trainer.high_skill? && reserves == 0 && foes == 0
score += 40 # want to draw
score += 40 if battle.field.terrain == :Misty
else
score -= user.hp * 100 / user.totalhp
score += 20 if battle.field.terrain == :Misty
end
next score
}
@@ -301,15 +344,15 @@ Battle::AI::Handlers::MoveBasePower.add("UserFaintsFixedDamageUserHP",
proc { |power, move, user, target, ai, battle|
next user.hp
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsLowerTargetAtkSpAtk2",
proc { |score, move, user, target, ai, battle|
if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler) &&
!target.battler.pbCanLowerStatStage?(:SPECIAL_ATTACK, user.battler)
score -= 100
score -= 60
elsif battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
score -= 100
score -= 60
else
score += target.stages[:ATTACK] * 10
score += target.stages[:SPECIAL_ATTACK] * 10
@@ -319,26 +362,41 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsLowerTargetAtkSpAtk2",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("UserFaintsHealAndCureReplacement",
proc { |move, user, target, ai, battle|
next true if !battle.pbCanChooseNonActive?(user.index)
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement",
proc { |score, move, user, target, ai, battle|
next score - 70
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("UserFaintsHealAndCureReplacement",
"UserFaintsHealAndCureReplacementRestorePP")
Battle::AI::Handlers::MoveEffectScore.copy("UserFaintsHealAndCureReplacement",
"UserFaintsHealAndCureReplacementRestorePP")
Battle::AI::Handlers::MoveFailureCheck.add("StartPerishCountsForAllBattlers",
proc { |move, user, target, ai, battle|
next target.effects[PBEffects::PerishSong] > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers",
proc { |score, move, user, target, ai, battle|
if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
score -= 90
elsif target.effects[PBEffects::PerishSong] > 0
score -= 90
score -= 60
end
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("AttackerFaintsIfUserFaints",
proc { |move, user, target, ai, battle|
next Settings::MECHANICS_GENERATION >= 7 && user.effects[PBEffects::DestinyBondPrevious]
}
)
Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints",
proc { |score, move, user, target, ai, battle|
score += 50

View File

@@ -16,12 +16,16 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTakesTargetItem",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("TargetTakesUserItem",
proc { |move, user, target, ai, battle|
next true if !user.item || user.battler.unlosableItem?(user.item)
next true if target.item || target.battler.unlosableItem?(user.item)
}
)
Battle::AI::Handlers::MoveEffectScore.add("TargetTakesUserItem",
proc { |score, move, user, target, ai, battle|
if !user.item || target.item
score -= 90
elsif user.has_active_item?([:FLAMEORB, :TOXICORB, :STICKYBARB, :IRONBALL,
:CHOICEBAND, :CHOICESCARF, :CHOICESPECS])
if user.has_active_item?([:FLAMEORB, :TOXICORB, :STICKYBARB, :IRONBALL,
:CHOICEBAND, :CHOICESCARF, :CHOICESPECS])
score += 50
else
score -= 80
@@ -30,13 +34,18 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetTakesUserItem",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapItems",
proc { |move, user, target, ai, battle|
next true if user.wild?
next true if !user.item && !target.item
next true if user.battler.unlosableItem?(user.item) || user.battler.unlosableItem?(target.item)
next true if target.battler.unlosableItem?(target.item) || target.battler.unlosableItem?(user.item)
next true if target.has_active_ability?(:STICKYHOLD)
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapItems",
proc { |score, move, user, target, ai, battle|
if !user.item && !target.item
score -= 90
elsif target.has_active_ability?(:STICKYHOLD)
score -= 90
elsif user.has_active_item?([:FLAMEORB, :TOXICORB, :STICKYBARB, :IRONBALL,
if user.has_active_item?([:FLAMEORB, :TOXICORB, :STICKYBARB, :IRONBALL,
:CHOICEBAND, :CHOICESCARF, :CHOICESPECS])
score += 50
elsif !user.item && target.item
@@ -47,13 +56,14 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapItems",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("RestoreUserConsumedItem",
proc { |move, user, target, ai, battle|
next true if !user.battler.recycleItem || user.item
}
)
Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem",
proc { |score, move, user, target, ai, battle|
if !user.battler.recycleItem || user.item
score -= 80
elsif user.battler.recycleItem
score += 30
end
score += 30
next score
}
)
@@ -62,7 +72,7 @@ Battle::AI::Handlers::MoveBasePower.add("RemoveTargetItem",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem",
proc { |score, move, user, target, ai, battle|
if ai.trainer.high_skill?
@@ -83,15 +93,18 @@ Battle::AI::Handlers::MoveEffectScore.add("DestroyTargetBerryOrGem",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("CorrodeTargetItem",
proc { |move, user, target, ai, battle|
next true if !target.item || target.unlosableItem?(target.item) ||
target.effects[PBEffects::Substitute] > 0
next true if target.has_active_ability?(:STICKYHOLD)
next true if battle.corrosiveGas[target.index % 2][target.party_index]
}
)
Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem",
proc { |score, move, user, target, ai, battle|
if battle.corrosiveGas[target.side][target.party_index]
score -= 100
elsif !target.item || !target.item_active? || target.battler.unlosableItem?(target.item) ||
target.has_active_ability?(:STICKYHOLD)
score -= 90
elsif target.effects[PBEffects::Substitute] > 0
score -= 90
if !target.item_active?
score -= 60
else
score += 50
end
@@ -99,6 +112,11 @@ Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("StartTargetCannotUseItem",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Embargo] > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartTargetCannotUseItem",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Embargo] > 0
@@ -112,34 +130,41 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("UserConsumeBerryRaiseDefense2",
proc { |move, user, target, ai, battle|
item = user.item
next true if !item || !item.is_berry? || !user.item_active?
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2",
proc { |score, move, user, target, ai, battle|
if !user.item || !user.item.is_berry? || !user.item_active?
score -= 100
else
if ai.trainer.high_skill?
useful_berries = [
:ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY,
:CHESTOBERRY, :FIGYBERRY, :GANLONBERRY, :IAPAPABERRY, :KEEBERRY,
:LANSATBERRY, :LEPPABERRY, :LIECHIBERRY, :LUMBERRY, :MAGOBERRY,
:MARANGABERRY, :PECHABERRY, :PERSIMBERRY, :PETAYABERRY, :RAWSTBERRY,
:SALACBERRY, :STARFBERRY, :WIKIBERRY
]
score += 30 if useful_berries.include?(user.item_id)
end
if ai.trainer.medium_skill?
score += 20 if user.battler.canHeal? && user.hp < user.totalhp / 3 &&
user.has_active_ability?(:CHEEKPOUCH)
score += 20 if user.has_active_ability?([:HARVEST, :RIPEN]) ||
user.battler.pbHasMoveFunction?("RestoreUserConsumedItem") # Recycle
score += 20 if !user.battler.canConsumeBerry?
end
score -= user.stages[:DEFENSE] * 20
if ai.trainer.high_skill?
useful_berries = [
:ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY,
:CHESTOBERRY, :FIGYBERRY, :GANLONBERRY, :IAPAPABERRY, :KEEBERRY,
:LANSATBERRY, :LEPPABERRY, :LIECHIBERRY, :LUMBERRY, :MAGOBERRY,
:MARANGABERRY, :PECHABERRY, :PERSIMBERRY, :PETAYABERRY, :RAWSTBERRY,
:SALACBERRY, :STARFBERRY, :WIKIBERRY
]
score += 30 if useful_berries.include?(user.item_id)
end
if ai.trainer.medium_skill?
score += 20 if user.battler.canHeal? && user.hp < user.totalhp / 3 &&
user.has_active_ability?(:CHEEKPOUCH)
score += 20 if user.has_active_ability?([:HARVEST, :RIPEN]) ||
user.battler.pbHasMoveFunction?("RestoreUserConsumedItem") # Recycle
score += 20 if !user.battler.canConsumeBerry?
end
score -= user.stages[:DEFENSE] * 20
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("AllBattlersConsumeBerry",
proc { |move, user, target, ai, battle|
next true if !target.item || !target.item.is_berry? || target.battler.semiInvulnerable?
}
)
Battle::AI::Handlers::MoveEffectScore.add("AllBattlersConsumeBerry",
proc { |score, move, user, target, ai, battle|
useful_berries = [
@@ -150,20 +175,16 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersConsumeBerry",
:RAWSTBERRY, :SALACBERRY, :STARFBERRY, :WIKIBERRY
]
battle.allSameSideBattlers(user.index).each do |b|
if !b.item || !b.item.is_berry? || !b.itemActive?
score -= 100 / battle.pbSideSize(user.index)
else
if ai.trainer.high_skill?
amt = 30 / battle.pbSideSize(user.index)
score += amt if useful_berries.include?(b.item_id)
end
if ai.trainer.medium_skill?
amt = 20 / battle.pbSideSize(user.index)
score += amt if b.canHeal? && b.hp < b.totalhp / 3 && b.hasActiveAbility?(:CHEEKPOUCH)
score += amt if b.hasActiveAbility?([:HARVEST, :RIPEN]) ||
b.pbHasMoveFunction?("RestoreUserConsumedItem") # Recycle
score += amt if !b.canConsumeBerry?
end
if ai.trainer.high_skill?
amt = 30 / battle.pbSideSize(user.index)
score += amt if useful_berries.include?(b.item_id)
end
if ai.trainer.medium_skill?
amt = 20 / battle.pbSideSize(user.index)
score += amt if b.canHeal? && b.hp < b.totalhp / 3 && b.hasActiveAbility?(:CHEEKPOUCH)
score += amt if b.hasActiveAbility?([:HARVEST, :RIPEN]) ||
b.pbHasMoveFunction?("RestoreUserConsumedItem") # Recycle
score += amt if !b.canConsumeBerry?
end
end
if ai.trainer.high_skill?
@@ -191,14 +212,16 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeTargetBerry",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget",
proc { |move, user, target, ai, battle|
item = user.item
next true if !item || !user.item_active? || user.battler.unlosableItem?(item)
next true if item.is_berry? && !user.battler.canConsumeBerry?
next true if item.flags.none? { |f| f[/^Fling_/i] }
}
)
Battle::AI::Handlers::MoveBasePower.add("ThrowUserItemAtTarget",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
Battle::AI::Handlers::MoveEffectScore.add("ThrowUserItemAtTarget",
proc { |score, move, user, target, ai, battle|
next 0 if !user.item || !user.item_active? ||
user.battler.unlosableItem?(user.item) || user.item.is_poke_ball?
}
)

View File

@@ -36,28 +36,38 @@ Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget",
proc { |power, move, user, target, ai, battle|
next 50 # Average power, ish
}
}
)
Battle::AI::Handlers::MoveFailureCheck.add("HealAllyOrDamageFoe",
proc { |move, user, target, ai, battle|
next true if !target.opposes?(user) && target.battler.canHeal?
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealAllyOrDamageFoe",
proc { |score, move, user, target, ai, battle|
if !target.opposes?(user)
if target.hp == target.totalhp || (ai.trainer.medium_skill? && !target.battler.canHeal?)
score -= 90
else
score += 50
score -= target.hp * 100 / target.totalhp
end
score += 50
score -= target.hp * 100 / target.totalhp
end
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1",
proc { |move, user, target, ai, battle|
if user.has_type?(:GHOST)
next true if target.effects[PBEffects::Curse]
else
next true if !user.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move) &&
!user.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) &&
!user.battler.pbCanRaiseStatStage?(:DEFENSE, user.battler, move.move)
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1",
proc { |score, move, user, target, ai, battle|
if user.has_type?(:GHOST)
if target.effects[PBEffects::Curse]
score -= 90
elsif user.hp <= user.totalhp / 2
if user.hp <= user.totalhp / 2
if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
score -= 90
else
@@ -81,19 +91,24 @@ Battle::AI::Handlers::MoveBasePower.add("HitsAllFoesAndPowersUpInPsychicTerrain"
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain",
proc { |score, move, user, target, ai, battle|
next score + 40 if battle.field.terrain == :Psychic && user.battler.affectedByTerrain?
}
)
Battle::AI::Handlers::MoveFailureCheck.add("TargetNextFireMoveDamagesTarget",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Powder]
}
)
Battle::AI::Handlers::MoveEffectScore.add("TargetNextFireMoveDamagesTarget",
proc { |score, move, user, target, ai, battle|
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
if aspeed > ospeed
score -= 90
score -= 50
elsif target.battler.pbHasMoveType?(:FIRE)
score += 30
end
@@ -105,9 +120,14 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetNextFireMoveDamagesTarget",
# DoublePowerAfterFusionBolt
Battle::AI::Handlers::MoveFailureCheck.add("PowerUpAllyMove",
proc { |move, user, target, ai, battle|
next true if target.fainted? || target.effects[PBEffects::HelpingHand]
}
)
Battle::AI::Handlers::MoveEffectScore.add("PowerUpAllyMove",
proc { |score, move, user, target, ai, battle|
next 0 if user.battler.allAllies.empty?
next score - 60 if user.battler.allAllies.empty?
next score + 30
}
)
@@ -116,7 +136,7 @@ Battle::AI::Handlers::MoveBasePower.add("CounterPhysicalDamage",
proc { |power, move, user, target, ai, battle|
next 60 # Representative value
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::HyperBeam] > 0
@@ -139,7 +159,7 @@ Battle::AI::Handlers::MoveBasePower.add("CounterSpecialDamage",
proc { |power, move, user, target, ai, battle|
next 60 # Representative value
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::HyperBeam] > 0
@@ -162,22 +182,25 @@ Battle::AI::Handlers::MoveBasePower.add("CounterDamagePlusHalf",
proc { |power, move, user, target, ai, battle|
next 60 # Representative value
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf",
proc { |score, move, user, target, ai, battle|
next score - 90 if target.effects[PBEffects::HyperBeam] > 0
}
)
Battle::AI::Handlers::MoveFailureCheck.add("UserAddStockpileRaiseDefSpDef1",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Stockpile] >= 3
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1",
proc { |score, move, user, target, ai, battle|
avg = 0
avg -= user.stages[:DEFENSE] * 10
avg -= user.stages[:SPECIAL_DEFENSE] * 10
score += avg / 2
if user.effects[PBEffects::Stockpile] >= 3
score -= 80
elsif user.battler.pbHasMoveFunction?("PowerDependsOnUserStockpile",
if user.battler.pbHasMoveFunction?("PowerDependsOnUserStockpile",
"HealUserDependingOnUserStockpile") # Spit Up, Swallow
score += 20 # More preferable if user also has Spit Up/Swallow
end
@@ -185,21 +208,27 @@ Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("PowerDependsOnUserStockpile",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Stockpile] == 0
}
)
Battle::AI::Handlers::MoveBasePower.add("PowerDependsOnUserStockpile",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
}
}
Battle::AI::Handlers::MoveEffectScore.add("PowerDependsOnUserStockpile",
proc { |score, move, user, target, ai, battle|
next 0 if user.effects[PBEffects::Stockpile] == 0
}
)
Battle::AI::Handlers::MoveFailureCheck.add("HealUserDependingOnUserStockpile",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Stockpile] == 0
next true if !user.battler.canHeal? &&
user.effects[PBEffects::StockpileDef] == 0 &&
user.effects[PBEffects::StockpileSpDef] == 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile",
proc { |score, move, user, target, ai, battle|
next 0 if user.effects[PBEffects::Stockpile] == 0
next 0 if user.hp == user.totalhp
mult = [0, 25, 50, 100][user.effects[PBEffects::Stockpile]]
score += mult
score -= user.hp * mult * 2 / user.totalhp
@@ -213,16 +242,22 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile",
# WaterPledge
# UseLastMoveUsed
Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsed",
proc { |move, user, target, ai, battle|
next true if !battle.lastMoveUsed
next true if move.move.moveBlacklist.include?(GameData::Move.get(battle.lastMoveUsed).function_code)
}
)
Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsedByTarget",
proc { |move, user, target, ai, battle|
next true if !target.battle.lastRegularMoveUsed
next true if GameData::Move.get(target.battle.lastRegularMoveUsed).flags.none? { |f| f[/^CanMirrorMove$/i] }
}
)
Battle::AI::Handlers::MoveEffectScore.add("UseLastMoveUsedByTarget",
proc { |score, move, user, target, ai, battle|
score -= 40
if ai.trainer.high_skill?
score -= 100 if !target.battler.lastRegularMoveUsed ||
GameData::Move.get(target.battler.lastRegularMoveUsed).flags.none? { |f| f[/^CanMirrorMove$/i] }
end
next score
next score - 40
}
)
@@ -232,16 +267,40 @@ Battle::AI::Handlers::MoveEffectScore.add("UseLastMoveUsedByTarget",
# UseRandomMove
# UseRandomMoveFromUserParty
Battle::AI::Handlers::MoveFailureCheck.add("UseRandomMoveFromUserParty",
proc { |move, user, target, ai, battle|
will_fail = true
battle.pbParty(user.index).each_with_index do |pkmn, i|
next if !pkmn || i == user.party_index
next if Settings::MECHANICS_GENERATION >= 6 && pkmn.egg?
pkmn.moves.each do |pkmn_move|
next if move.move.moveBlacklist.include?(pkmn_move.function_code)
next if pkmn_move.type == :SHADOW
will_fail = false
break
end
break if !will_fail
end
next will_fail
}
)
Battle::AI::Handlers::MoveFailureCheck.add("UseRandomUserMoveIfAsleep",
proc { |move, user, target, ai, battle|
next true if !user.battler.asleep?
will_fail = true
user.battler.eachMoveWithIndex do |m, i|
next if move.move.moveBlacklist.include?(m.function)
next if !battle.pbCanChooseMove?(user.index, i, false, true)
will_fail = false
break
end
next will_fail
}
)
Battle::AI::Handlers::MoveEffectScore.add("UseRandomUserMoveIfAsleep",
proc { |score, move, user, target, ai, battle|
if user.battler.asleep?
score += 100 # Because it can only be used while asleep
else
score -= 90
end
next score
next score + 50 if user.battler.asleep? # Because it can only be used while asleep
}
)
@@ -249,52 +308,24 @@ Battle::AI::Handlers::MoveEffectScore.add("UseRandomUserMoveIfAsleep",
# StealAndUseBeneficialStatusMove
Battle::AI::Handlers::MoveEffectScore.add("ReplaceMoveThisBattleWithTargetLastMoveUsed",
proc { |score, move, user, target, ai, battle|
moveBlacklist = [
"Struggle", # Struggle
"ReplaceMoveThisBattleWithTargetLastMoveUsed", # Mimic
"ReplaceMoveWithTargetLastMoveUsed", # Sketch
"UseRandomMove" # Metronome
]
if user.effects[PBEffects::Transform] || !target.battler.lastRegularMoveUsed
score -= 90
else
lastMoveData = GameData::Move.get(target.battler.lastRegularMoveUsed)
if moveBlacklist.include?(lastMoveData.function_code) ||
lastMoveData.type == :SHADOW
score -= 90
end
user.battler.eachMove do |m|
next if m != target.battler.lastRegularMoveUsed
score -= 90
break
end
end
next score
Battle::AI::Handlers::MoveFailureCheck.add("ReplaceMoveThisBattleWithTargetLastMoveUsed",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Transform] || user.battler.pbHasMove?(move.id)
last_move_data = GameData::Move.try_get(target.battler.lastRegularMoveUsed)
next true if !last_move_data ||
user.battler.pbHasMove?(target.battler.lastRegularMoveUsed) ||
move.move.moveBlacklist.include?(last_move_data.function_code) ||
last_move_data.type == :SHADOW
}
)
Battle::AI::Handlers::MoveEffectScore.add("ReplaceMoveWithTargetLastMoveUsed",
proc { |score, move, user, target, ai, battle|
moveBlacklist = [
"Struggle", # Struggle
"ReplaceMoveWithTargetLastMoveUsed" # Sketch
]
if user.effects[PBEffects::Transform] || !target.battler.lastRegularMoveUsed
score -= 90
else
lastMoveData = GameData::Move.get(target.battler.lastRegularMoveUsed)
if moveBlacklist.include?(lastMoveData.function_code) ||
lastMoveData.type == :SHADOW
score -= 90
end
user.battler.eachMove do |m|
next if m != target.battler.lastRegularMoveUsed
score -= 90 # User already knows the move that will be Sketched
break
end
end
next score
Battle::AI::Handlers::MoveFailureCheck.add("ReplaceMoveWithTargetLastMoveUsed",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Transform] || !user.battler.pbHasMove?(move.id)
last_move_data = GameData::Move.try_get(target.battler.lastRegularMoveUsed)
next true if !last_move_data ||
user.battler.pbHasMove?(target.battler.lastRegularMoveUsed) ||
move.move.moveBlacklist.include?(last_move_data.function_code) ||
last_move_data.type == :SHADOW
}
)

View File

@@ -1,17 +1,25 @@
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("FleeFromBattle",
proc { |score, move, user, target, ai, battle|
next 0 if battle.trainerBattle?
Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle",
proc { |move, user, target, ai, battle|
next true if battle.pbCanRun?(user.index)
}
)
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserStatusMove",
proc { |move, user, target, ai, battle|
if user.wild?
next true if !battle.pbCanRun?(user.index)
else
next true if !battle.pbCanChooseNonActive?(user.index)
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove",
proc { |score, move, user, target, ai, battle|
if !battle.pbCanChooseNonActive?(user.index) ||
battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace
score -= 100
if battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace
score -= 60
else
score += 40 if user.effects[PBEffects::Confusion] > 0
total = 0
@@ -41,6 +49,17 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserDamagingMove",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkSpAtk1SwitchOutUser",
proc { |move, user, target, ai, battle|
will_fail = true
(move.move.statDown.length / 2).times do |i|
next if !target.battler.pbCanLowerStatStage?(move.move.statDown[i * 2], user.battler, move.move)
will_fail = false
break
end
next will_fail
}
)
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1SwitchOutUser",
proc { |score, move, user, target, ai, battle|
avg = target.stages[:ATTACK] * 10
@@ -50,6 +69,11 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1SwitchOutUser",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserPassOnEffects",
proc { |move, user, target, ai, battle|
next true if !battle.pbCanChooseNonActive?(user.index)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
proc { |score, move, user, target, ai, battle|
if battle.pbCanChooseNonActive?(user.index)
@@ -76,23 +100,28 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutTargetStatusMove",
proc { |move, user, target, ai, battle|
next true if target.has_active_ability?(:SUCTIONCUPS) ||
target.effects[PBEffects::Ingrain]
next true if !battle.canRun
next true if battle.wildBattle? && target.level > user.level
if battle.trainerBattle?
will_fail = true
battle.eachInTeamFromBattlerIndex(target.index) do |_pkmn, i|
next if !battle.pbCanSwitchLax?(target.index, i)
will_fail = false
break
end
next will_fail
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetStatusMove",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::Ingrain] ||
target.has_active_ability?(:SUCTIONCUPS)
score -= 90
else
ch = 0
battle.pbParty(target.index).each_with_index do |pkmn, i|
ch += 1 if battle.pbCanSwitchLax?(target.index, i)
end
score -= 90 if ch == 0
end
if score > 20
score += 50 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
score += 50 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
score += 50 if target.pbOwnSide.effects[PBEffects::StealthRock]
end
score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::StealthRock]
next score
}
)
@@ -101,9 +130,9 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetDamagingMove",
proc { |score, move, user, target, ai, battle|
if !target.effects[PBEffects::Ingrain] &&
!target.has_active_ability?(:SUCTIONCUPS)
score += 40 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
score += 40 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
score += 40 if target.pbOwnSide.effects[PBEffects::StealthRock]
score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::StealthRock]
end
next score
}
@@ -119,25 +148,35 @@ Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater
proc { |power, move, user, target, ai, battle|
next move.pbModifyDamage(power, user.battler, target.battler)
}
}
)
Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater",
proc { |score, move, user, target, ai, battle|
next score + 40 if target.effects[PBEffects::Trapping] == 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("TrapTargetInBattle",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::MeanLook] >= 0
Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle",
proc { |move, user, target, ai, battle|
if move.statusMove?
next true if target.effects[PBEffects::MeanLook] >= 0
next true if Settings::MORE_TYPE_EFFECTS && target.has_type?(:GHOST)
end
}
)
Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle",
proc { |move, user, target, ai, battle|
if move.statusMove?
next true if target.effects[PBEffects::Octolock] >= 0
next true if Settings::MORE_TYPE_EFFECTS && target.has_type?(:GHOST)
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Octolock] >= 0
score += 30 if !target.battler.trappedInBattle?
score -= 100 if !target.battler.pbCanLowerStatStage?(:DEFENSE, user.battler, move.move) &&
!target.battler.pbCanLowerStatStage?(:SPECIAL_DEFENSE, user.battler, move.move)
score -= 50 if !target.battler.pbCanLowerStatStage?(:DEFENSE, user.battler, move.move) &&
!target.battler.pbCanLowerStatStage?(:SPECIAL_DEFENSE, user.battler, move.move)
next score
}
)
@@ -151,7 +190,11 @@ Battle::AI::Handlers::MoveEffectScore.add("TrapUserAndTargetInBattle",
}
)
# TrapAllBattlersInBattleForOneTurn
Battle::AI::Handlers::MoveFailureCheck.add("TrapAllBattlersInBattleForOneTurn",
proc { |move, user, target, ai, battle|
next true if battle.field.effects[PBEffects::FairyLock] > 0
}
)
# PursueSwitchingFoe
@@ -164,7 +207,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterUserTakesPhysicalDamage",
hasPhysicalAttack = true
break
end
score -= 80 if !hasPhysicalAttack
score -= 50 if !hasPhysicalAttack
end
next score
}
@@ -186,20 +229,24 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower",
# TargetActsLast
Battle::AI::Handlers::MoveFailureCheck.add("TargetUsesItsLastUsedMoveAgain",
proc { |move, user, target, ai, battle|
next true if !target.battler.lastRegularMoveUsed ||
!target.battler.pbHasMove?(target.battler.lastRegularMoveUsed)
next true if target.usingMultiTurnAttack?
next true if move.move.moveBlacklist.include?(GameData::Move.get(target.battler.lastRegularMoveUsed).function_code)
idxMove = -1
target.battler.eachMoveWithIndex do |m, i|
idxMove = i if m.id == target.battler.lastRegularMoveUsed
end
next true if target.battler.moves[idxMove].pp == 0 && target.battler.moves[idxMove].total_pp > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain",
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill?
if !target.battler.lastRegularMoveUsed ||
!target.battler.pbHasMove?(target.battler.lastRegularMoveUsed) ||
target.battler.usingMultiTurnAttack?
score -= 90
else
# Without lots of code here to determine good/bad moves and relative
# speeds, using this move is likely to just be a waste of a turn
score -= 50
end
end
next score
# Without lots of code here to determine good/bad moves and relative
# speeds, using this move is likely to just be a waste of a turn
next score - 50
}
)
@@ -224,56 +271,91 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy3",
}
)
Battle::AI::Handlers::MoveFailureCheck.add("LowerPPOfTargetLastMoveBy4",
proc { |move, user, target, ai, battle|
last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed)
next true if !last_move || last_move.pp == 0 || last_move.total_pp <= 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy4",
proc { |score, move, user, target, ai, battle|
next score - 40
}
)
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetLastMoveUsed",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Disable] > 0
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetLastMoveUsed",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Disable] > 0 || !target.battler.lastRegularMoveUsed
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
will_fail = true
target.battler.eachMove do |m|
next if m.id != target.battler.lastRegularMoveUsed
next if m.pp == 0 && m.total_pp > 0
will_fail = false
break
end
next will_fail
}
)
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingSameMoveConsecutively",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Torment]
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
}
)
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingSameMoveConsecutively",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Torment]
}
)
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingDifferentMove",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Encore] > 0
next true if !target.battler.lastRegularMoveUsed ||
move.move.moveBlacklist.include?(GameData::Move.get(target.battler.lastRegularMoveUsed).function_code)
next true if target.effects[PBEffects::ShellTrap]
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
will_fail = true
target.battler.eachMove do |m|
next if m.id != target.battler.lastRegularMoveUsed
next if m.pp == 0 && m.total_pp > 0
will_fail = false
break
end
next will_fail
}
)
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingDifferentMove",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::Encore] > 0
score -= 90
elsif user.faster_than?(target)
if target.battler.lastRegularMoveUsed
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
end
else
score -= 90
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
end
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetStatusMoves",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Taunt] > 0
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetStatusMoves",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Taunt] > 0
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
next true if Settings::MECHANICS_GENERATION >= 6 && target.has_active_ability?(:OBLIVIOUS)
}
)
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetHealingMoves",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::HealBlock] > 0
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetHealingMoves",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::HealBlock] > 0
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
}
)
@@ -292,12 +374,17 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetSoundMoves",
}
)
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetMovesKnownByUser",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Imprison]
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Imprison]
}
)
Battle::AI::Handlers::MoveFailureCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
proc { |move, user, target, ai, battle|
next true if battle.allBattlers.none? { |b| b.hp > 1 }
}
)
Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
proc { |score, move, user, target, ai, battle|
score += 20 # Shadow moves are more preferable
@@ -307,7 +394,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTur
}
)
Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP",
proc { |score, move, user, target, ai, battle|
score += 20 # Shadow moves are more preferable
score -= 40
@@ -315,33 +402,45 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTur
}
)
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"StartShadowSkyWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather",
proc { |score, move, user, target, ai, battle|
score += 20 # Shadow moves are more preferable
if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif battle.field.weather == :ShadowSky
score -= 90
score -= 50
end
next score
}
)
Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens",
proc { |move, user, target, ai, battle|
will_fail = true
battle.sides.each do |side|
will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 ||
side.effects[PBEffects::Reflect] > 0 ||
side.effects[PBEffects::LightScreen] > 0 ||
side.effects[PBEffects::Safeguard] > 0
end
next will_fail
}
)
Battle::AI::Handlers::MoveEffectScore.add("RemoveAllScreens",
proc { |score, move, user, target, ai, battle|
score += 20 # Shadow moves are more preferable
if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 ||
target.pbOwnSide.effects[PBEffects::Reflect] > 0 ||
target.pbOwnSide.effects[PBEffects::LightScreen] > 0 ||
target.pbOwnSide.effects[PBEffects::Safeguard] > 0
if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 ||
user.pbOpposingSide.effects[PBEffects::Reflect] > 0 ||
user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 ||
user.pbOpposingSide.effects[PBEffects::Safeguard] > 0
score += 30
score -= 90 if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 ||
user.pbOwnSide.effects[PBEffects::Reflect] > 0 ||
user.pbOwnSide.effects[PBEffects::LightScreen] > 0 ||
user.pbOwnSide.effects[PBEffects::Safeguard] > 0
else
next 0
end
if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 ||
user.pbOwnSide.effects[PBEffects::Reflect] > 0 ||
user.pbOwnSide.effects[PBEffects::LightScreen] > 0 ||
user.pbOwnSide.effects[PBEffects::Safeguard] > 0
score -= 70
end
next score
}

View File

@@ -10,6 +10,7 @@
# the trainer's base money value.
#
# Skill flags:
# PredictMoveFailure
#===============================================================================
class Battle::AI::AITrainer
attr_reader :side, :trainer_index
@@ -27,9 +28,9 @@ class Battle::AI::AITrainer
end
def set_up_skill
return if !@trainer
@skill = @trainer.skill_level
@skill = @trainer.skill_level if @trainer
# TODO: Add skill flags depending on @skill.
@skill_flags.push("PredictMoveFailure") if @skill > 0
end
def has_skill_flag?(flag)

View File

@@ -65,6 +65,13 @@ class Battle::AI::AIMove
#=============================================================================
def rough_priority(user)
# TODO: More calculations here.
return @move.priority
end
#=============================================================================
def type; return @move.type; end
def rough_type
@@ -486,23 +493,23 @@ class Battle::AI::AIMove
crit_stage = 0
# Ability effects that alter critical hit rate
if user.ability_active?
crit_stage = BattleHandlers.triggerCriticalCalcUserAbility(user_battler.ability,
crit_stage = Battle::AbilityEffects.triggerCriticalCalcFromUser(user_battler.ability,
user_battler, target_battler, crit_stage)
return -1 if crit_stage < 0
end
if !mold_breaker && target.ability_active?
crit_stage = BattleHandlers.triggerCriticalCalcTargetAbility(target_battler.ability,
crit_stage = Battle::AbilityEffects.triggerCriticalCalcFromTarget(target_battler.ability,
user_battler, target_battler, crit_stage)
return -1 if crit_stage < 0
end
# Item effects that alter critical hit rate
if user.item_active?
crit_stage = BattleHandlers.triggerCriticalCalcUserItem(user_battler.item,
crit_stage = Battle::ItemEffects.triggerCriticalCalcFromUser(user_battler.item,
user_battler, target_battler, crit_stage)
return -1 if crit_stage < 0
end
if target.item_active?
crit_stage = BattleHandlers.triggerCriticalCalcTargetItem(user_battler.item,
crit_stage = Battle::ItemEffects.triggerCriticalCalcFromTarget(user_battler.item,
user_battler, target_battler, crit_stage)
return -1 if crit_stage < 0
end

View File

@@ -399,6 +399,21 @@ end
# (Shadow Shed)
#===============================================================================
class Battle::Move::RemoveAllScreens < Battle::Move
def pbMoveFailed?(user, targets)
will_fail = true
@battle.sides.each do |side|
will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 ||
side.effects[PBEffects::Reflect] > 0 ||
side.effects[PBEffects::LightScreen] > 0 ||
side.effects[PBEffects::Safeguard] > 0
end
if will_fail
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.sides.each do |i|
i.effects[PBEffects::AuroraVeil] = 0

View File

@@ -2331,7 +2331,7 @@ Category = Status
Accuracy = 0
TotalPP = 10
Target = AllAllies
FunctionCode = RaiseUserAndAlliesAtkDef1
FunctionCode = RaiseAlliesAtkDef1
Flags = CanMirrorMove
Description = The user properly coaches its ally Pokémon, boosting their Attack and Defense stats.
#-------------------------------

View File

@@ -2331,7 +2331,7 @@ Category = Status
Accuracy = 0
TotalPP = 10
Target = AllAllies
FunctionCode = RaiseUserAndAlliesAtkDef1
FunctionCode = RaiseAlliesAtkDef1
Flags = CanMirrorMove
Description = The user properly coaches its ally Pokémon, boosting their Attack and Defense stats.
#-------------------------------