mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2026-03-10 02:12:01 +00:00
Added script to make two random AI trainers battle, tweaked battle messages when logged, fixed typos
This commit is contained in:
@@ -45,7 +45,7 @@ class Battle::AI
|
||||
@trainer = @trainers[(opposes) ? 1 : 0][trainer_index]
|
||||
# Find the AI battler for which the action is being chosen
|
||||
@user = @battlers[idxBattler]
|
||||
@user.refresh_battler
|
||||
@battlers.each { |b| b.refresh_battler if b }
|
||||
end
|
||||
|
||||
# Choose an action.
|
||||
|
||||
@@ -11,16 +11,18 @@ class Battle::AI
|
||||
shouldSwitch = forceSwitch
|
||||
battler = @user.battler
|
||||
batonPass = -1
|
||||
foe = nil
|
||||
moveType = nil
|
||||
# If Pokémon is within 6 levels of the foe, and foe's last move was
|
||||
# super-effective and powerful
|
||||
if !shouldSwitch && battler.turnCount > 0 && @trainer.high_skill?
|
||||
target = battler.pbDirectOpposing(true)
|
||||
foe = @battlers[target.index]
|
||||
if !target.fainted? && target.lastMoveUsed &&
|
||||
(target.level - battler.level).abs <= 6
|
||||
moveData = GameData::Move.get(target.lastMoveUsed)
|
||||
moveType = moveData.type
|
||||
typeMod = battler.effectiveness_of_type_against_battler(moveType, target)
|
||||
typeMod = @user.effectiveness_of_type_against_battler(moveType, foe)
|
||||
if Effectiveness.super_effective?(typeMod) && moveData.base_damage > 50
|
||||
switchChance = (moveData.base_damage > 70) ? 30 : 20
|
||||
shouldSwitch = (pbAIRandom(100) < switchChance)
|
||||
@@ -106,7 +108,7 @@ class Battle::AI
|
||||
end
|
||||
end
|
||||
# moveType is the type of the target's last used move
|
||||
if moveType && Effectiveness.ineffective?(battler.effectiveness_of_type_against_battler(moveType))
|
||||
if moveType && Effectiveness.ineffective?(@user.effectiveness_of_type_against_battler(moveType, foe))
|
||||
weight = 65
|
||||
typeMod = pbCalcTypeModPokemon(pkmn, battler.pbDirectOpposing(true))
|
||||
if Effectiveness.super_effective?(typeMod)
|
||||
@@ -114,7 +116,7 @@ class Battle::AI
|
||||
weight = 85
|
||||
end
|
||||
list.unshift(i) if pbAIRandom(100) < weight # Put this Pokemon first
|
||||
elsif moveType && Effectiveness.resistant?(battler.effectiveness_of_type_against_battler(moveType))
|
||||
elsif moveType && Effectiveness.resistant?(@user.effectiveness_of_type_against_battler(moveType, foe))
|
||||
weight = 40
|
||||
typeMod = pbCalcTypeModPokemon(pkmn, battler.pbDirectOpposing(true))
|
||||
if Effectiveness.super_effective?(typeMod)
|
||||
|
||||
@@ -11,19 +11,16 @@ class Battle::AI
|
||||
# (which are based on the predicted damages). Multi-target moves could
|
||||
# be fiddly since damages should be calculated for each target but
|
||||
# they're all related.
|
||||
battler.eachMoveWithIndex do |_m, i|
|
||||
next if !@battle.pbCanChooseMove?(battler.index, i, false) # Unchoosable moves aren't considered
|
||||
pbAddMoveWithScoreToChoices(i, choices)
|
||||
end
|
||||
# Log the available choices
|
||||
if $INTERNAL
|
||||
logMsg = "[AI] Move choices for #{battler.pbThis(true)} (#{battler.index}): "
|
||||
choices.each_with_index do |c, i|
|
||||
logMsg += "#{battler.moves[c[0]].name}=#{c[1]}"
|
||||
logMsg += " (target #{c[2]})" if c[2] >= 0
|
||||
logMsg += ", " if i < choices.length - 1
|
||||
battler.eachMoveWithIndex do |m, i|
|
||||
if !@battle.pbCanChooseMove?(battler.index, i, false) # Unchoosable moves aren't considered
|
||||
if m.pp == 0 && m.total_pp > 0
|
||||
PBDebug.log("[AI] #{battler.pbThis} (#{battler.index}) cannot use move #{m.name} as it has no PP left")
|
||||
else
|
||||
PBDebug.log("[AI] #{battler.pbThis} (#{battler.index}) cannot choose to use #{m.name}")
|
||||
end
|
||||
next
|
||||
end
|
||||
PBDebug.log(logMsg)
|
||||
pbAddMoveWithScoreToChoices(i, choices)
|
||||
end
|
||||
@battle.moldBreaker = false
|
||||
return choices
|
||||
@@ -159,7 +156,7 @@ class Battle::AI
|
||||
target_battler = @target.battler
|
||||
|
||||
# Predict whether the move will fail
|
||||
return 50 if pbPredictMoveFailure
|
||||
return 25 if pbPredictMoveFailure
|
||||
|
||||
# Get the base score for the move
|
||||
if @move.damagingMove?
|
||||
@@ -188,20 +185,11 @@ class Battle::AI
|
||||
def pbChooseMove(choices)
|
||||
user_battler = @user.battler
|
||||
|
||||
# If there are no calculated choices, pick one at random
|
||||
# If no moves can be chosen, auto-choose a move or Struggle
|
||||
if choices.length == 0
|
||||
# NOTE: Can only get here if no moves can be chosen, i.e. will auto-use a
|
||||
# move or struggle.
|
||||
user_battler.eachMoveWithIndex do |_m, i|
|
||||
next if !@battle.pbCanChooseMove?(user_battler.index, i, false)
|
||||
choices.push([i, 100, -1]) # Move index, score, target
|
||||
end
|
||||
if choices.length == 0 # No moves are physically possible to use; use Struggle
|
||||
@battle.pbAutoChooseMove(user_battler.index)
|
||||
PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will auto-use a move or Struggle")
|
||||
return
|
||||
end
|
||||
PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) doesn't want to use any moves; picking one at random")
|
||||
@battle.pbAutoChooseMove(user_battler.index)
|
||||
PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will auto-use a move or Struggle")
|
||||
return
|
||||
end
|
||||
|
||||
# Figure out useful information about the choices
|
||||
@@ -211,31 +199,45 @@ class Battle::AI
|
||||
# Decide whether all choices are bad, and if so, try switching instead
|
||||
if @trainer.high_skill? && @user.can_switch_lax?
|
||||
badMoves = false
|
||||
if (max_score <= 20 && user_battler.turnCount > 2) ||
|
||||
(max_score <= 40 && user_battler.turnCount > 5)
|
||||
if (max_score <= 25 && user_battler.turnCount > 2) ||
|
||||
(max_score <= 50 && user_battler.turnCount > 5)
|
||||
badMoves = true if pbAIRandom(100) < 80
|
||||
end
|
||||
if !badMoves && max_score < 60 && user_battler.turnCount > 1
|
||||
if !badMoves && max_score < 50 && user_battler.turnCount >= 1
|
||||
badMoves = choices.none? { |c| user_battler.moves[c[0]].damagingMove? }
|
||||
badMoves = false if badMoves && pbAIRandom(100) < 10
|
||||
end
|
||||
if badMoves && pbEnemyShouldWithdrawEx?(true)
|
||||
if $INTERNAL
|
||||
PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will switch due to terrible moves")
|
||||
end
|
||||
PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will switch due to terrible moves")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# Calculate a minimum score threshold and reduce all move scores by it
|
||||
threshold = (max_score * 0.85).floor
|
||||
choices.each { |c| c[1] = [c[1] - threshold, 0].max }
|
||||
total_score = choices.sum { |c| c[1] }
|
||||
choices.each { |c| c[3] = [c[1] - threshold, 0].max }
|
||||
total_score = choices.sum { |c| c[3] }
|
||||
|
||||
# Log the available choices
|
||||
if $INTERNAL
|
||||
PBDebug.log("[AI] Move choices for #{user_battler.pbThis(true)} (#{user_battler.index}):")
|
||||
choices.each_with_index do |c, i|
|
||||
chance = "0"
|
||||
chance = sprintf("%.1f", 100.0 * c[3] / total_score) if c[3] > 0
|
||||
while chance.length < 5
|
||||
chance = " " + chance
|
||||
end
|
||||
log_msg = " * #{chance}% chance: #{user_battler.moves[c[0]].name}"
|
||||
log_msg += " (against target #{c[2]})" if c[2] >= 0
|
||||
log_msg += " = score #{c[1]}"
|
||||
PBDebug.log(log_msg)
|
||||
end
|
||||
end
|
||||
|
||||
# Pick a move randomly from choices weighted by their scores
|
||||
randNum = pbAIRandom(total_score)
|
||||
choices.each do |c|
|
||||
randNum -= c[1]
|
||||
randNum -= c[3]
|
||||
next if randNum >= 0
|
||||
@battle.pbRegisterMove(user_battler.index, c[0], false)
|
||||
@battle.pbRegisterTarget(user_battler.index, c[2]) if c[2] >= 0
|
||||
@@ -244,7 +246,7 @@ class Battle::AI
|
||||
|
||||
# Log the result
|
||||
if @battle.choices[user_battler.index][2]
|
||||
PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will use #{@battle.choices[user_battler.index][2].name}")
|
||||
PBDebug.log(" => will use #{@battle.choices[user_battler.index][2].name}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,22 +62,22 @@ class Battle::AI
|
||||
# TODO: Exception if user knows Baton Pass/Stored Power?
|
||||
case stat
|
||||
when :ATTACK
|
||||
return false if !@user.check_for_move { |move| move.physicalMove?(move.type) &&
|
||||
move.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" &&
|
||||
move.function != "UseTargetAttackInsteadOfUserAttack" }
|
||||
return false if !@user.check_for_move { |m| m.physicalMove?(move.type) &&
|
||||
m.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" &&
|
||||
m.function != "UseTargetAttackInsteadOfUserAttack" }
|
||||
when :DEFENSE
|
||||
each_foe_battler(@user.side) do |b, i|
|
||||
next if !b.check_for_move { |move| move.physicalMove?(move.type) ||
|
||||
move.function == "UseTargetDefenseInsteadOfTargetSpDef" }
|
||||
next if !b.check_for_move { |m| m.physicalMove?(m.type) ||
|
||||
m.function == "UseTargetDefenseInsteadOfTargetSpDef" }
|
||||
return true
|
||||
end
|
||||
return false
|
||||
when :SPECIAL_ATTACK
|
||||
return false if !@user.check_for_move { |move| move.specialMove?(move.rough_type) }
|
||||
return false if !@user.check_for_move { |m| m.specialMove?(m.type) }
|
||||
when :SPECIAL_DEFENSE
|
||||
each_foe_battler(@user.side) do |b, i|
|
||||
next if !b.check_for_move { |move| move.specialMove?(move.type) &&
|
||||
move.function != "UseTargetDefenseInsteadOfTargetSpDef" }
|
||||
next if !b.check_for_move { |m| m.specialMove?(m.type) &&
|
||||
m.function != "UseTargetDefenseInsteadOfTargetSpDef" }
|
||||
return true
|
||||
end
|
||||
return false
|
||||
@@ -86,7 +86,7 @@ class Battle::AI
|
||||
"PowerHigherWithUserFasterThanTarget",
|
||||
"PowerHigherWithUserPositiveStatStages"
|
||||
]
|
||||
if !@user.check_for_move { |move| moves_that_prefer_high_speed.include?(move.function) }
|
||||
if !@user.check_for_move { |m| moves_that_prefer_high_speed.include?(m.function) }
|
||||
each_foe_battler(@user.side) do |b, i|
|
||||
return true if b.faster_than?(@user)
|
||||
end
|
||||
@@ -241,7 +241,7 @@ class Battle::AI
|
||||
if @user.stages[stat] >= 3
|
||||
score -= 20
|
||||
else
|
||||
has_special_moves = @user.check_for_move { |move| move.specialMove?(move.rough_type) }
|
||||
has_special_moves = @user.check_for_move { |m| m.specialMove?(m.type) }
|
||||
inc = (has_special_moves) ? 5 : 10
|
||||
score += inc * (3 - @user.stages[stat]) * increment # 5 to 45
|
||||
score += 5 * increment if @user.hp == @user.totalhp
|
||||
@@ -262,9 +262,9 @@ class Battle::AI
|
||||
if @user.stages[stat] >= 3
|
||||
score -= 20
|
||||
else
|
||||
has_physical_moves = @user.check_for_move { |move| move.physicalMove?(move.type) &&
|
||||
move.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" &&
|
||||
move.function != "UseTargetAttackInsteadOfUserAttack" }
|
||||
has_physical_moves = @user.check_for_move { |m| m.physicalMove?(m.type) &&
|
||||
m.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" &&
|
||||
m.function != "UseTargetAttackInsteadOfUserAttack" }
|
||||
inc = (has_physical_moves) ? 5 : 10
|
||||
score += inc * (3 - @user.stages[stat]) * increment # 5 to 45
|
||||
score += 5 * increment if @user.hp == @user.totalhp
|
||||
@@ -288,7 +288,7 @@ class Battle::AI
|
||||
end
|
||||
# Don't prefer if any foe has Gyro Ball
|
||||
each_foe_battler(@user.side) do |b, i|
|
||||
next if !b.check_for_move { |move| move.function == "PowerHigherWithTargetFasterThanUser" }
|
||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetFasterThanUser" }
|
||||
score -= 10 * increment
|
||||
end
|
||||
# Don't prefer if user has Speed Boost (will be gaining Speed anyway)
|
||||
@@ -336,12 +336,12 @@ class Battle::AI
|
||||
pos_change = [@user.stages[stat] + increment, increment].min
|
||||
if pos_change > 0
|
||||
# Prefer if user has Stored Power
|
||||
if @user.check_for_move { |move| move.function == "PowerHigherWithUserPositiveStatStages" }
|
||||
if @user.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" }
|
||||
score += 10 * pos_change
|
||||
end
|
||||
# Don't prefer if any foe has Punishment
|
||||
each_foe_battler(@user.side) do |b, i|
|
||||
next if !b.check_for_move { |move| move.function == "PowerHigherWithTargetPositiveStatStages" }
|
||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetPositiveStatStages" }
|
||||
score -= 10 * pos_change
|
||||
end
|
||||
end
|
||||
@@ -355,7 +355,7 @@ class Battle::AI
|
||||
when :ATTACK
|
||||
# TODO: Don't prefer if target has previously used a move that benefits
|
||||
# from user's Attack being boosted.
|
||||
# mini_score *= 0.3 if @target.check_for_move { |move| move.function == "UseTargetAttackInsteadOfUserAttack" } # Foul Play
|
||||
# mini_score *= 0.3 if @target.check_for_move { |m| m.function == "UseTargetAttackInsteadOfUserAttack" } # Foul Play
|
||||
# Prefer if user can definitely survive a hit no matter how powerful, and
|
||||
# it won't be hurt by weather
|
||||
# if @user.hp == @user.totalhp &&
|
||||
@@ -393,7 +393,7 @@ class Battle::AI
|
||||
# (@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
|
||||
# Prefer if user knows any healing moves
|
||||
# # TODO: Is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
|
||||
# mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
|
||||
# mini_score *= 1.3 if check_for_move(@user) { |m| m.healingMove? }
|
||||
# Prefer if user knows Pain Split or Leech Seed
|
||||
# # TODO: Leech Seed is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
|
||||
# mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
|
||||
@@ -483,7 +483,7 @@ class Battle::AI
|
||||
# mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
|
||||
# (@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
|
||||
# Prefer if user knows any healing moves
|
||||
# mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
|
||||
# mini_score *= 1.3 if check_for_move(@user) { |m| m.healingMove? }
|
||||
# Prefer if user knows Pain Split or Leech Seed
|
||||
# mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
|
||||
# mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
|
||||
@@ -495,7 +495,7 @@ class Battle::AI
|
||||
|
||||
when :ACCURACY
|
||||
# Prefer if user knows any weaker moves
|
||||
mini_score *= 1.1 if check_for_move(@user) { |move| move.damagingMove? && move.basedamage < 95 }
|
||||
mini_score *= 1.1 if check_for_move(@user) { |m| m.damagingMove? && m.basedamage < 95 }
|
||||
# Prefer if target has a raised evasion
|
||||
sum_stages = @target.stages[:EVASION]
|
||||
mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0
|
||||
@@ -521,7 +521,7 @@ class Battle::AI
|
||||
mini_score *= 1.3
|
||||
end
|
||||
# Prefer if user knows any healing moves
|
||||
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
|
||||
mini_score *= 1.3 if check_for_move(@user) { |m| move.healingMove? }
|
||||
# Prefer if user knows Pain Split or Leech Seed
|
||||
mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
|
||||
mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
|
||||
@@ -537,8 +537,8 @@ class Battle::AI
|
||||
|
||||
# TODO: Don't prefer if any foe has previously used a stat stage-clearing
|
||||
# move (Clear Smog/Haze).
|
||||
mini_score *= 0.3 if check_for_move(@target) { |move|
|
||||
["ResetTargetStatStages", "ResetAllBattlersStatStages"].include?(move.function)
|
||||
mini_score *= 0.3 if check_for_move(@target) { |m|
|
||||
["ResetTargetStatStages", "ResetAllBattlersStatStages"].include?(m.function)
|
||||
} # Clear Smog, Haze
|
||||
|
||||
# TODO: Prefer if user is faster than the target.
|
||||
@@ -561,8 +561,8 @@ class Battle::AI
|
||||
def get_score_for_terrain(terrain, move_user)
|
||||
ret = 0
|
||||
# Inherent effects of terrain
|
||||
@battlers.each do |b|
|
||||
next if !b || b.battler.fainted? || !b.battler.affectedByTerrain?
|
||||
each_battler do |b, i|
|
||||
next if !b.battler.affectedByTerrain?
|
||||
case terrain
|
||||
when :Electric
|
||||
# Immunity to sleep
|
||||
@@ -574,14 +574,14 @@ class Battle::AI
|
||||
ret += (b.opposes?(move_user)) ? -10 : 10
|
||||
end
|
||||
# Check for Electric moves
|
||||
if b.check_for_move { |move| move.type == :ELECTRIC && move.damagingMove? }
|
||||
if b.check_for_move { |m| m.type == :ELECTRIC && m.damagingMove? }
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
end
|
||||
when :Grassy
|
||||
# End of round healing
|
||||
ret += (b.opposes?(move_user)) ? -10 : 10
|
||||
# Check for Grass moves
|
||||
if b.check_for_move { |move| move.type == :GRASS && move.damagingMove? }
|
||||
if b.check_for_move { |m| m.type == :GRASS && m.damagingMove? }
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
end
|
||||
when :Misty
|
||||
@@ -592,16 +592,16 @@ class Battle::AI
|
||||
ret += (b.opposes?(move_user)) ? -5 : 5
|
||||
end
|
||||
# Check for Dragon moves
|
||||
if b.check_for_move { |move| move.type == :DRAGON && move.damagingMove? }
|
||||
if b.check_for_move { |m| m.type == :DRAGON && m.damagingMove? }
|
||||
ret += (b.opposes?(move_user)) ? 15 : -15
|
||||
end
|
||||
when :Psychic
|
||||
# Check for priority moves
|
||||
if b.check_for_move { |move| move.priority > 0 && move.pbTarget&.can_target_one_foe? }
|
||||
if b.check_for_move { |m| m.priority > 0 && m.pbTarget&.can_target_one_foe? }
|
||||
ret += (b.opposes?(move_user)) ? 10 : -10
|
||||
end
|
||||
# Check for Psychic moves
|
||||
if b.check_for_move { |move| move.type == :PSYCHIC && move.damagingMove? }
|
||||
if b.check_for_move { |m| m.type == :PSYCHIC && m.damagingMove? }
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
end
|
||||
end
|
||||
@@ -613,8 +613,7 @@ class Battle::AI
|
||||
:Misty => :MISTYSEED,
|
||||
:Psychic => :PSYCHICSEED
|
||||
}[terrain]
|
||||
ai.battlers.each do |b|
|
||||
next if !b || b.battler.fainted?
|
||||
each_battler do |b, i|
|
||||
if b.has_active_item?(:TERRAINEXTENDER)
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
elsif seed && b.has_active_item?(seed)
|
||||
@@ -622,7 +621,7 @@ class Battle::AI
|
||||
end
|
||||
end
|
||||
# Check for abilities/moves affected by the terrain
|
||||
if ai.trainer.medium_skill?
|
||||
if @trainer.medium_skill?
|
||||
abils = {
|
||||
:Electric => :SURGESURFER,
|
||||
:Grassy => :GRASSPELT,
|
||||
@@ -644,8 +643,8 @@ class Battle::AI
|
||||
:Misty => nil,
|
||||
:Psychic => nil
|
||||
}[terrain]
|
||||
ai.battlers.each do |b|
|
||||
next if !b || b.battler.fainted? || !b.battler.affectedByTerrain?
|
||||
each_battler do |b, i|
|
||||
next if !b.battler.affectedByTerrain?
|
||||
# Abilities
|
||||
if b.has_active_ability?(:MIMICRY)
|
||||
ret += (b.opposes?(move_user)) ? -5 : 5
|
||||
@@ -654,16 +653,16 @@ class Battle::AI
|
||||
ret += (b.opposes?(move_user)) ? -15 : 15
|
||||
end
|
||||
# Moves
|
||||
if b.check_for_move { |move| ["EffectDependsOnEnvironment",
|
||||
"SetUserTypesBasedOnEnvironment",
|
||||
"TypeAndPowerDependOnTerrain",
|
||||
"UseMoveDependingOnEnvironment"].include?(move.function) }
|
||||
if b.check_for_move { |m| ["EffectDependsOnEnvironment",
|
||||
"SetUserTypesBasedOnEnvironment",
|
||||
"TypeAndPowerDependOnTerrain",
|
||||
"UseMoveDependingOnEnvironment"].include?(m.function) }
|
||||
ret += (b.opposes?(move_user)) ? -10 : 10
|
||||
end
|
||||
if good_moves && b.check_for_move { |move| good_moves.include?(move.function) }
|
||||
if good_moves && b.check_for_move { |m| good_moves.include?(m.function) }
|
||||
ret += (b.opposes?(move_user)) ? -10 : 10
|
||||
end
|
||||
if bad_moves && b.check_for_move { |move| bad_moves.include?(move.function) }
|
||||
if bad_moves && b.check_for_move { |m| bad_moves.include?(m.function) }
|
||||
ret += (b.opposes?(move_user)) ? 10 : -10
|
||||
end
|
||||
end
|
||||
|
||||
@@ -129,12 +129,12 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserDamagedThisTurn",
|
||||
if target.effects[PBEffects::HyperBeam] > 0 ||
|
||||
target.effects[PBEffects::Truant] ||
|
||||
(target.battler.asleep? && target.statusCount > 1) ||
|
||||
target.frozen?
|
||||
target.battler.frozen?
|
||||
score += 20
|
||||
elsif target.effects[PBEffects::Confusion] > 1 ||
|
||||
target.effects[PBEffects::Attract] == user.index
|
||||
score += 10
|
||||
elsif target.paralyzed?
|
||||
elsif target.battler.paralyzed?
|
||||
score += 5
|
||||
end
|
||||
end
|
||||
@@ -167,7 +167,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfTargetActed",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("CrashDamageIfFailsUnusableInGravity",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score - (100 - move.rough_accuracy) if user.takesIndirectDamage?
|
||||
next score - (100 - move.rough_accuracy) if user.battler.takesIndirectDamage?
|
||||
}
|
||||
)
|
||||
|
||||
@@ -448,7 +448,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
|
||||
inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex }
|
||||
foe_reserves = []
|
||||
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
|
||||
next if !pkmn || !pkmn.able? || inBattleIndices.include(idxParty)
|
||||
next if !pkmn || !pkmn.able? || inBattleIndices.include?(idxParty)
|
||||
if ai.trainer.medium_skill?
|
||||
# Check affected by entry hazard
|
||||
next if pkmn.hasItem?(:HEAVYDUTYBOOTS)
|
||||
@@ -484,7 +484,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
|
||||
inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex }
|
||||
foe_reserves = []
|
||||
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
|
||||
next if !pkmn || !pkmn.able? || inBattleIndices.include(idxParty)
|
||||
next if !pkmn || !pkmn.able? || inBattleIndices.include?(idxParty)
|
||||
if ai.trainer.medium_skill?
|
||||
# Check affected by entry hazard
|
||||
next if pkmn.hasItem?(:HEAVYDUTYBOOTS)
|
||||
@@ -522,7 +522,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
|
||||
inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex }
|
||||
foe_reserves = []
|
||||
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
|
||||
next if !pkmn || !pkmn.able? || inBattleIndices.include(idxParty)
|
||||
next if !pkmn || !pkmn.able? || inBattleIndices.include?(idxParty)
|
||||
if ai.trainer.medium_skill?
|
||||
# Check affected by entry hazard
|
||||
next if pkmn.hasItem?(:HEAVYDUTYBOOTS)
|
||||
@@ -549,7 +549,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide",
|
||||
inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex }
|
||||
foe_reserves = []
|
||||
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
|
||||
next if !pkmn || !pkmn.able? || inBattleIndices.include(idxParty)
|
||||
next if !pkmn || !pkmn.able? || inBattleIndices.include?(idxParty)
|
||||
if ai.trainer.medium_skill?
|
||||
# Check affected by entry hazard
|
||||
next if pkmn.hasItem?(:HEAVYDUTYBOOTS)
|
||||
|
||||
@@ -393,7 +393,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTarget",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfUserNotAsleep",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if !user.asleep?
|
||||
next true if !user.battler.asleep?
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfUserNotAsleep",
|
||||
@@ -649,7 +649,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToInsomnia",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("SetUserAbilityToTargetAbility",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if user.battle.unstoppableAbility?
|
||||
next true if user.battler.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)
|
||||
@@ -673,7 +673,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToUserAbility",
|
||||
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
|
||||
next true if target.battler.unstoppableAbility? || target.ability_id == :TRUANT
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToUserAbility",
|
||||
@@ -693,9 +693,9 @@ 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? ||
|
||||
next true if user.battler.unstoppableAbility? || user.battler.ungainableAbility? ||
|
||||
user.ability_id == :WONDERGUARD
|
||||
next true if target.battle.unstoppableAbility? || target.battler.ungainableAbility? ||
|
||||
next true if target.battler.unstoppableAbility? || target.battler.ungainableAbility? ||
|
||||
target.ability_id == :WONDERGUARD
|
||||
}
|
||||
)
|
||||
@@ -714,7 +714,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAbilities",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("NegateTargetAbility",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if target.unstoppableAbility? ||
|
||||
next true if target.battler.unstoppableAbility? ||
|
||||
target.effects[PBEffects::GastroAcid]
|
||||
}
|
||||
)
|
||||
|
||||
@@ -422,7 +422,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartLeechSeedTarget",
|
||||
if !user.check_for_move { |move| move.damagingMove? }
|
||||
score += 20
|
||||
end
|
||||
score -= 20 if target.has_active_ability?([:LIQUIDOOZE]) || !target.takesIndirectDamage?
|
||||
score -= 20 if target.has_active_ability?([:LIQUIDOOZE]) || !target.battler.takesIndirectDamage?
|
||||
end
|
||||
if ai.trainer.high_skill?
|
||||
if user.check_for_move { |move| move.is_a?(Battle::Move::ProtectMove) }
|
||||
|
||||
@@ -315,8 +315,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsed",
|
||||
#===============================================================================
|
||||
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] }
|
||||
next true if !target.battler.lastRegularMoveUsed
|
||||
next true if GameData::Move.get(target.battler.lastRegularMoveUsed).flags.none? { |f| f[/^CanMirrorMove$/i] }
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("UseLastMoveUsedByTarget",
|
||||
|
||||
@@ -104,7 +104,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:damaging_moves_if_last_pokemon,
|
||||
if ai.trainer.medium_skill? && battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 &&
|
||||
!(ai.trainer.high_skill? && target && battle.pbAbleNonActiveCount(target.idxOwnSide) > 0)
|
||||
next score * 0.9 if move.statusMove?
|
||||
next score * 1.1 if target_battler.hp <= target_battler.totalhp / 2
|
||||
next score * 1.1 if target && target.battler.hp <= target.battler.totalhp / 2
|
||||
end
|
||||
}
|
||||
)
|
||||
@@ -213,7 +213,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_against_frozen_target,
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::GeneralMoveScore.add(:shiny_target,
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score - 40 if target&.wild? && target&.battler.shiny?
|
||||
next score - 40 if target && target.wild? && target.battler.shiny?
|
||||
}
|
||||
)
|
||||
|
||||
@@ -260,7 +260,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:flinching_effects,
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::GeneralMoveScore.add(:add_predicted_damage,
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
if move.damagingMove?
|
||||
if move.damagingMove? && target
|
||||
dmg = move.rough_damage
|
||||
score += [15.0 * dmg / target.hp, 20].min
|
||||
score += 10 if dmg > target.hp * 1.1 # Predicted to KO the target
|
||||
|
||||
@@ -138,7 +138,7 @@ class Battle::AI::AIBattler
|
||||
# Trapping damage
|
||||
if self.effects[PBEffects::Trapping] > 1 && @battler.takesIndirectDamage?
|
||||
amt = (Settings::MECHANICS_GENERATION >= 6) ? self.totalhp / 8 : self.totalhp / 16
|
||||
if @battlers[self.effects[PBEffects::TrappingUser]].has_active_item?(:BINDINGBAND)
|
||||
if @ai.battlers[self.effects[PBEffects::TrappingUser]].has_active_item?(:BINDINGBAND)
|
||||
amt = (Settings::MECHANICS_GENERATION >= 6) ? self.totalhp / 6 : self.totalhp / 8
|
||||
end
|
||||
ret += [amt, 1].max
|
||||
|
||||
@@ -371,17 +371,17 @@ class Battle::AI::AIMove
|
||||
end
|
||||
|
||||
def rough_accuracy
|
||||
# Determine user and target
|
||||
user = @ai.user
|
||||
user_battler = user.battler
|
||||
target = @ai.target
|
||||
target_battler = target.battler
|
||||
# "Always hit" effects and "always hit" accuracy
|
||||
if @ai.trainer.medium_skill?
|
||||
return 100 if target.effects[PBEffects::Telekinesis] > 0
|
||||
return 100 if target.effects[PBEffects::Minimize] && @move.tramplesMinimize? &&
|
||||
Settings::MECHANICS_GENERATION >= 6
|
||||
end
|
||||
# Determine user and target
|
||||
user = @ai.user
|
||||
user_battler = user.battler
|
||||
target = @ai.target
|
||||
target_battler = target.battler
|
||||
# Get base accuracy
|
||||
baseAcc = self.accuracy
|
||||
return 100 if baseAcc == 0
|
||||
@@ -486,7 +486,7 @@ class Battle::AI::AIMove
|
||||
case function
|
||||
when "BadPoisonTarget"
|
||||
modifiers[:base_accuracy] = 0 if Settings::MORE_TYPE_EFFECTS &&
|
||||
@move.statusMove? && @user.has_type?(:POISON)
|
||||
@move.statusMove? && user.has_type?(:POISON)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user