Rewrote AI calculations for move effects that raise the user's stats, fixed Sea of Fire effect lasting forever

This commit is contained in:
Maruno17
2022-09-04 17:46:59 +01:00
parent db215a71d6
commit b8c61a6038
15 changed files with 622 additions and 829 deletions

View File

@@ -134,6 +134,8 @@ class Battle
#=============================================================================
def pbEORSeaOfFireDamage(priority)
2.times do |side|
next if sides[side].effects[PBEffects::SeaOfFire] == 0
sides[side].effects[PBEffects::SeaOfFire] -= 1
next if sides[side].effects[PBEffects::SeaOfFire] == 0
pbCommonAnimation("SeaOfFire") if side == 0
pbCommonAnimation("SeaOfFireOpp") if side == 1

View File

@@ -1199,6 +1199,7 @@ end
# user's Attack (and Attack stat stages) to calculate damage. All other effects
# are applied normally, applying the user's Attack modifiers and not the user's
# Defence modifiers. (Body Press)
# TODO: Rename this function code to remove both "Base"s?
#===============================================================================
class Battle::Move::UseUserBaseDefenseInsteadOfUserBaseAttack < Battle::Move
def pbGetAttackStats(user, target)

View File

@@ -133,7 +133,7 @@ class Battle::AI
# after all.
return true if @move.move.pbImmunityByAbility(@user.battler, @target.battler, false)
# Type immunity
calc_type = @move.rough_type(@user.battler)
calc_type = @move.rough_type
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

View File

@@ -37,15 +37,33 @@ class Battle::AI
end
#=============================================================================
# Check if battler has a move that meets the criteria in the block provided
# Yields certain AIBattler objects
#=============================================================================
def check_for_move(battler)
ret = false
battler.eachMove do |move|
next unless yield move
ret = true
break
def each_battler
@battlers.each_with_index do |battler, i|
next if !battler || battler.fainted?
yield battler, i
end
end
def each_foe_battler(side)
@battlers.each_with_index do |battler, i|
next if !battler || battler.fainted?
yield battler, i if i.even? != side.even?
end
end
def each_same_side_battler(side)
@battlers.each_with_index do |battler, i|
next if !battler || battler.fainted?
yield battler, i if i.even? == side.even?
end
end
def each_ally(index)
@battlers.each_with_index do |battler, i|
next if !battler || battler.fainted?
yield battler, i if i != index && i.even? == index.even?
end
return ret
end
end

View File

@@ -1,24 +1,105 @@
class Battle::AI
#=============================================================================
# Apply additional effect chance to a move's score
# TODO: Apply all the additional effect chance modifiers.
# Main method for calculating the score for moves that raise the user's stat(s).
#=============================================================================
def apply_effect_chance_to_score(score)
if @move.damagingMove?
# TODO: Doesn't return the correct value for "ConfuseTarget" (Chatter).
effect_chance = @move.addlEffect
if effect_chance > 0
effect_chance *= 2 if @user.hasActiveAbility?(:SERENEGRACE) ||
@user.pbOwnSide.effects[PBEffects::Rainbow] > 0
effect_multiplier = [effect_chance.to_f, 100].min / 100
score = ((score - 1) * effect_multiplier) + 1
end
def get_score_for_user_stat_raise(score)
# Discard status move/don't prefer damaging move if user has Contrary
if !@battle.moldBreaker && @user.has_active_ability?(:CONTRARY)
return (@move.statusMove?) ? score - 40 : score - 20
end
# Don't make score changes if foes have Unaware and user can't make use of
# extra stat stages
if !@user.check_for_move { |move| move.function == "PowerHigherWithUserPositiveStatStages" }
foe_is_aware = false
each_foe_battler(@user.side) do |b, i|
foe_is_aware = true if !b.has_active_ability?(:UNAWARE)
end
return score if !foe_is_aware
end
# Figure out which stat raises can happen
stat_changes = []
@move.move.statUp.each_with_index do |stat, idx|
next if idx.odd?
next if !stat_raise_worthwhile?(stat)
# Calculate amount that stat will be raised by
increment = @move.move.statUp[idx + 1]
if @move.function == "RaiseUserAtkSpAtk1Or2InSun"
increment = 1
increment = 2 if [:Sun, :HarshSun].include?(@user.battler.effectiveWeather)
end
increment *= 2 if !@battle.moldBreaker && @user.has_active_ability?(:SIMPLE)
increment = [increment, 6 - @user.stages[stat]].min # The actual stages gained
# Count this as a valid stat raise
stat_changes.push([stat, increment]) if increment > 0
end
# Discard move if it can't raise any stats
if stat_changes.length == 0
return (@move.statusMove?) ? score - 40 : score
end
# Make score changes based on the general concept of raising stats at all
score = get_user_stat_raise_score_generic(score, stat_changes)
# Make score changes based on the specific changes to each stat that will be
# raised
stat_changes.each do |change|
score = get_user_stat_raise_score_one(score, change[0], change[1])
end
return score
end
#=============================================================================
#
# Returns whether the user raising the given stat will have any impact.
# TODO: Make sure the move's actual damage category is taken into account,
# i.e. CategoryDependsOnHigherDamagePoisonTarget and
# CategoryDependsOnHigherDamageIgnoreTargetAbility.
#=============================================================================
def stat_raise_worthwhile?(stat)
return false if !@user.battler.pbCanRaiseStatStage?(stat, @user.battler, @move)
# Check if user won't benefit from the stat being raised
# 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" }
when :DEFENSE
each_foe_battler(@user.side) do |b, i|
next if !b.check_for_move { |move| move.physicalMove?(move.type) ||
move.function == "UseTargetDefenseInsteadOfTargetSpDef" }
return true
end
return false
when :SPECIAL_ATTACK
return false if !@user.check_for_move { |move| move.specialMove?(move.rough_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" }
return true
end
return false
when :SPEED
moves_that_prefer_high_speed = [
"PowerHigherWithUserFasterThanTarget",
"PowerHigherWithUserPositiveStatStages"
]
if !@user.check_for_move { |move| moves_that_prefer_high_speed.include?(move.function) }
each_foe_battler(@user.side) do |b, i|
return true if b.faster_than?(@user)
end
return false
end
when :ACCURACY
when :EVASION
end
return true
end
#=============================================================================
# Make score changes based on the general concept of raising stats at all.
#=============================================================================
# TODO: These function codes need to have an attr_reader :statUp and for them
# to be set when the move is initialised.
@@ -26,15 +107,45 @@ class Battle::AI
# RaiseTargetRandomStat2 Acupressure
# RaisePlusMinusUserAndAlliesDefSpDef1 Magnetic Flux
# RaisePlusMinusUserAndAlliesAtkSpAtk1 Gear Up
def calc_user_stat_raise_mini_score
def get_user_stat_raise_score_generic(score, stat_changes)
total_increment = stat_changes.sum { |change| change[1] }
# TODO: Just return if foe is predicted to use a phazing move (one that
# switches the user out).
# TODO: Don't prefer if foe is faster than user and is predicted to deal
# lethal damage.
# TODO: Don't prefer if foe is slower than user but is predicted to be able
# to 2HKO user.
# TODO: Prefer if foe is semi-invulnerable and user is faster (can't hit
# the foe anyway).
# Prefer if move is a status move and it's the user's first/second turn
if @user.turnCount < 2 && @move.statusMove?
score += total_increment * 5
end
# Prefer if user is at high HP, don't prefer if user is at low HP
if @user.hp >= @user.totalhp * 0.7
score += 10 * total_increment
else
score += total_increment * ((100 * @user.hp / @user.totalhp) - 50) / 2 # +10 to -25 per stage
end
# Don't prefer if user is about to faint due to EOR damage
score -= 30 if @user.rough_end_of_round_damage > @user.hp
# TODO: Look at abilities that trigger upon stat raise. There are none.
return score
mini_score = 1.0
# Determine whether the move boosts Attack, Special Attack or Speed (Bulk Up
# is sometimes not considered a sweeping move)
sweeping_stat = false
offensive_stat = false
@move.stat_up.each_with_index do |stat, idx|
next if idx.odd?
next if ![:ATTACK, :SPATK, :SPEED].include?(stat)
stat_changes.each do |change|
next if ![:ATTACK, :SPECIAL_ATTACK, :SPEED].include?(change[0])
sweeping_stat = true
next if @move.function == "RaiseUserAtkDef1" # Bulk Up (+Atk +Def)
offensive_stat = true
@@ -45,12 +156,6 @@ class Battle::AI
if @user.hp >= @user.totalhp * 3 / 4
mini_score *= (sweeping_stat) ? 1.2 : 1.1
end
# Prefer if user hasn't been in battle for long
if @user.turnCount < 2
mini_score *= (sweeping_stat) ? 1.2 : 1.1
end
# Prefer if user has the ability Simple
mini_score *= 2 if !@battle.moldBreaker && @user.hasActiveAbility?(:SIMPLE)
# TODO: Prefer if user's moves won't do much damage.
# Prefer if user has something that will limit damage taken
mini_score *= 1.3 if @user.effects[PBEffects::Substitute] > 0 ||
@@ -116,12 +221,6 @@ class Battle::AI
# TODO: Prefer if the maximum damage the target has dealt wouldn't hurt
# the user much.
end
# Don't prefer if foe's side is able to use a boosted Retaliate
# TODO: I think this is what Reborn means. Reborn doesn't check for the
# existence of the move Retaliate, just whether it can be boosted.
if @user.pbOpposingSide.effects[PBEffects::LastRoundFainted] == @battle.turnCount - 1
mini_score *= 0.3
end
# Don't prefer if it's not a single battle
if !@battle.singleBattle?
@@ -132,197 +231,271 @@ class Battle::AI
end
#=============================================================================
#
# Make score changes based on the raising of a specific stat.
#=============================================================================
# TODO: This method doesn't take the increment into account but should.
def calc_user_stat_raise_one(stat, increment)
mini_score = 1.0
# Ignore if user won't benefit from the stat being raised
# TODO: Exception if user knows Baton Pass? Exception if user knows Power Trip?
def get_user_stat_raise_score_one(score, stat, increment)
case stat
when :ATTACK
has_physical_move = false
@user.eachMove do |m|
next if !m.physicalMove?(m.type) || m.function == "UseTargetAttackInsteadOfUserAttack" # Foul Play
has_physical_move = true
break
# Modify score depending on current stat stage
# More strongly prefer if the user has no special moves
if @user.stages[stat] >= 3
score -= 20
else
has_special_moves = @user.check_for_move { |move| move.specialMove?(move.rough_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
end
return mini_score if !has_physical_move
when :DEFENSE
# Modify score depending on current stat stage
if @user.stages[stat] >= 3
score -= 20
else
score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45
score += 5 * increment if @user.hp == @user.totalhp
end
when :SPECIAL_ATTACK
has_special_move = false
@user.eachMove do |m|
next if !m.specialMove?(m.type)
has_special_move = true
# Modify score depending on current stat stage
# More strongly prefer if the user has no physical moves
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" }
inc = (has_physical_moves) ? 5 : 10
score += inc * (3 - @user.stages[stat]) * increment # 5 to 45
score += 5 * increment if @user.hp == @user.totalhp
end
when :SPECIAL_DEFENSE
# Modify score depending on current stat stage
if @user.stages[stat] >= 3
score -= 20
else
score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45
score += 5 * increment if @user.hp == @user.totalhp
end
when :SPEED
# Prefer if user is slower than a foe
each_foe_battler(@user.side) do |b, i|
next if @user.faster_than?(b)
score += 15 * increment
break
end
return mini_score if !has_special_move
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" }
score -= 10 * increment
end
# Don't prefer if user has Speed Boost (will be gaining Speed anyway)
score -= 20 if @user.has_active_ability?(:SPEEDBOOST)
case stat
when :ATTACK
# 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 &&
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
when :ACCURACY
# Modify score depending on current stat stage
if @user.stages[stat] >= 3
score -= 20
else
min_accuracy = 100
@user.battler.moves.each do |m|
next if m.accuracy == 0 || m.is_a?(Battle::Move::OHKO)
min_accuracy = m.accuracy if m.accuracy < min_accuracy
end
stageMul = [3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9]
stageDiv = [9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3]
min_accuracy *= stageMul[@user.stages[stat]] / stageDiv[@user.stages[stat]]
if min_accuracy < 90
score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45
score += 5 * increment if @user.hp == @user.totalhp
end
end
# Prefer if user has the Sweeper role
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# Don't prefer if user is burned or paralysed
mini_score *= 0.5 if @user.status == :BURN || @user.status == :PARALYSIS
# Don't prefer if user's Speed stat is lowered
sum_stages = @user.stages[:SPEED]
mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
# TODO: Prefer if target has previously used a HP-restoring move.
# TODO: Don't prefer if some of foes' stats are raised
sum_stages = 0
[:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s|
sum_stages += @target.stages[s]
when :EVASION
# Prefer if a foe will (probably) take damage at the end of the round
# TODO: Should this take into account EOR healing, one-off damage and
# damage-causing effects that wear off naturally (like Sea of Fire)?
# TODO: Emerald AI also prefers if user is rooted via Ingrain.
each_foe_battler(@user.side) do |b, i|
eor_damage = b.rough_end_of_round_damage
score += 60 * eor_damage / b.totalhp if eor_damage > 0
end
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# TODO: Don't prefer if target has Speed Boost (+Spd at end of each round).
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
# Modify score depending on current stat stage
if @user.stages[stat] >= 3
score -= 20
else
score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45
score += 5 * increment if @user.hp == @user.totalhp
end
end
# Check impact on moves of gaining stat stages
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" }
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" }
score -= 10 * pos_change
end
end
return score
mini_score = 1.0
case stat
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 check_for_move(@target) { |move| move.function == "UseTargetAttackInsteadOfUserAttack" } # Foul Play
# TODO: Don't prefer if the target has previously used a priority move.
# mini_score *= 0.3 if @target.check_for_move { |move| move.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 &&
# (@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
# if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
# !(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
# !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
# mini_score *= 1.4
# end
# end
# Prefer if user has the Sweeper role
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
# mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# # Don't prefer if user is burned or paralysed
# mini_score *= 0.5 if @user.status == :BURN || @user.status == :PARALYSIS
# # Don't prefer if user's Speed stat is lowered
# sum_stages = @user.stages[:SPEED]
# mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
# # TODO: Prefer if target has previously used a HP-restoring move.
# # TODO: Don't prefer if some of foes' stats are raised.
# sum_stages = 0
# [:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s|
# sum_stages += @target.stages[s]
# end
# mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# # TODO: Don't prefer if target has Speed Boost (+Spd at end of each round).
# mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
# # TODO: Don't prefer if the target has previously used a priority move.
when :DEFENSE
# Prefer if user has a healing item
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
# mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
# (@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? }
# # TODO: Is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
# mini_score *= 1.3 if check_for_move(@user) { |move| move.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
mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
# # TODO: Leech Seed is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
# mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
# mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
# Prefer if user has certain roles
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# # TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
# mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# Don't prefer if user is badly poisoned
mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0
# Don't prefer if user's Defense stat is raised
sum_stages = @user.stages[:DEFENSE]
mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0
# TODO: Prefer if foes have higher Attack than Special Attack, and user
# doesn't have a wall role, user is faster and user has at least 75%
# HP. Don't prefer instead if user is slower (ignore HP).
# # TODO: Prefer if foes have higher Attack than Special Attack, and user
# # doesn't have a wall role, user is faster and user has at least 75%
# # HP. Don't prefer instead if user is slower (ignore HP).
# TODO: Don't prefer if previous damage done by foes wouldn't hurt the
# user much.
when :SPEED
# Don't prefer if user has Speed Boost
# mini_score *= 0.6 if @user.hasActiveAbility?(:SPEEDBOOST)
# 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 &&
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
end
end
# Prefer if user's Attack/SpAtk stat (whichever is higher) is lowered
# TODO: Why?
if @user.attack > @user.spatk
sum_stages = @user.stages[:ATTACK]
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
else
sum_stages = @user.stages[:SPATK]
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
end
# Prefer if user has lowered Speed
# TODO: Is a flat 1.3x for RaiseUserAtkSpd1 Dragon Dance (+Atk, +Spd).
sum_stages = @user.stages[:SPEED]
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
# Prefer if user has Moxie
mini_score *= 1.3 if @user.hasActiveAbility?(:MOXIE)
# Prefer if user has the Sweeper role
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# Don't prefer if user is burned or paralysed
mini_score *= 0.2 if @user.status == :PARALYSIS
# Don't prefer if user has Speed Boost
mini_score *= 0.6 if @user.hasActiveAbility?(:SPEEDBOOST)
# if @user.hp == @user.totalhp &&
# (@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
# if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
# !(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
# !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
# mini_score *= 1.4
# end
# end
# Prefer if user has the Sweeper role
# mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# TODO: Don't prefer if Trick Room applies or any foe has previously used
# Trick Room.
# mini_score *= 0.2 if @battle.field.effects[PBEffects::TrickRoom] > 0
# TODO: Don't prefer if target has raised defenses.
sum_stages = 0
[:DEFENSE, :SPECIAL_DEFENSE].each { |s| sum_stages += @target.stages[s] }
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# TODO: Don't prefer if the target has previously used a priority move.
# TODO: Don't prefer if Trick Room applies or any foe has previously used
# Trick Room.
mini_score *= 0.2 if @battle.field.effects[PBEffects::TrickRoom] > 0
# TODO: Don't prefer if user is already faster than the target. Exception
# for moves that benefit from a raised user's Speed?
# TODO: Don't prefer if user is already faster than the target and there's
# only 1 unfainted foe (this check is done by Agility/Autotomize
# (both +2 Spd) only in Reborn.)
# # Prefer if user's Attack/SpAtk stat (whichever is higher) is lowered
# # TODO: Why?
# if @user.attack > @user.spatk
# sum_stages = @user.stages[:ATTACK]
# mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
# else
# sum_stages = @user.stages[:SPATK]
# mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
# end
# # Prefer if user has Moxie
# mini_score *= 1.3 if @user.hasActiveAbility?(:MOXIE)
# # Don't prefer if user is burned or paralysed
# mini_score *= 0.2 if @user.status == :PARALYSIS
# # TODO: Don't prefer if target has raised defenses.
# sum_stages = 0
# [:DEFENSE, :SPECIAL_DEFENSE].each { |s| sum_stages += @target.stages[s] }
# mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# # TODO: Don't prefer if the target has previously used a priority move.
# # TODO: Don't prefer if user is already faster than the target and there's
# # only 1 unfainted foe (this check is done by Agility/Autotomize
# # (both +2 Spd) only in Reborn.)
when :SPECIAL_ATTACK
# 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 &&
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
end
end
# if @user.hp == @user.totalhp &&
# (@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
# if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
# !(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
# !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
# mini_score *= 1.4
# end
# end
# Prefer if user has the Sweeper role
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# Don't prefer if user's Speed stat is lowered
sum_stages = @user.stages[:SPEED]
mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
# mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# TODO: Prefer if target has previously used a HP-restoring move.
# TODO: Don't prefer if some of foes' stats are raised
sum_stages = 0
[:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s|
sum_stages += @target.stages[s]
end
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# TODO: Don't prefer if target has Speed Boost (+Spd at end of each round)
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
# TODO: Don't prefer if the target has previously used a priority move.
# # Don't prefer if user's Speed stat is lowered
# sum_stages = @user.stages[:SPEED]
# mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
# # TODO: Prefer if target has previously used a HP-restoring move.
# # TODO: Don't prefer if some of foes' stats are raised
# sum_stages = 0
# [:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s|
# sum_stages += @target.stages[s]
# end
# mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# # TODO: Don't prefer if target has Speed Boost (+Spd at end of each round)
# mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
# # TODO: Don't prefer if the target has previously used a priority move.
when :SPECIAL_DEFENSE
# Prefer if user has a healing item
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
# 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) { |move| 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
# mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
# mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
# Prefer if user has certain roles
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# Don't prefer if user's Defense stat is raised
sum_stages = @user.stages[:SPECIAL_DEFENSE]
mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0
# TODO: Prefer if foes have higher Special Attack than Attack.
# mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# # TODO: Prefer if foes have higher Special Attack than Attack.
# TODO: Don't prefer if previous damage done by foes wouldn't hurt the
# user much.
when :ACCURACY
# Prefer if user knows any weaker moves
mini_score *= 1.1 if check_for_move(@user) { |move| move.damagingMove? && move.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
@@ -355,20 +528,12 @@ class Battle::AI
# Prefer if user has certain roles
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# TODO: Don't prefer if user's evasion stat is raised
# TODO: Don't prefer if target has No Guard.
mini_score *= 0.2 if @target.hasActiveAbility?(:NOGUARD)
# TODO: Don't prefer if target has previously used any moves that never miss.
end
# Don't prefer if user has Contrary
mini_score *= 0.5 if !@battle.moldBreaker && @user.hasActiveAbility?(:CONTRARY)
# TODO: Don't prefer if target has Unaware? Reborn resets mini_score to 1.
# This check needs more consideration. Note that @target is user for
# status moves, so that part is wrong.
# TODO: Is 0x for RaiseUserAtkDefAcc1, RaiseUserAtkSpd1 (all moves that raise multiple stats)
mini_score *= 0.5 if @move.statusMove? && !@battle.moldBreaker && @target.hasActiveAbility?(:UNAWARE)
# TODO: Don't prefer if any foe has previously used a stat stage-clearing
# move (Clear Smog/Haze).
@@ -390,47 +555,6 @@ class Battle::AI
return mini_score
end
#=============================================================================
#
#=============================================================================
def get_score_for_user_stat_raise(score)
# Discard status move if user has Contrary
return 0 if @move.statusMove? && !@battle.moldBreaker && @user.hasActiveAbility?(:CONTRARY)
# Discard move if it can't raise any stats
can_change_any_stat = false
@move.stat_up.each_with_index do |stat, idx|
next if idx.odd?
next if @user.statStageAtMax?(stat)
can_change_any_stat = true
break
end
if !can_change_any_stat
return (@move.statusMove?) ? 0 : score
end
# Get the main mini-score
main_mini_score = calc_user_stat_raise_mini_score
# For each stat to be raised in turn, calculate a mini-score describing how
# beneficial that stat being raised will be
mini_score = 0
num_stats = 0
@move.stat_up.each_with_index do |stat, idx|
next if idx.odd?
next if @user.statStageAtMax?(stat)
# TODO: Use the effective increment (e.g. 1 if the stat is raised by 2 but
# the stat is already at +5).
mini_score += calc_user_stat_raise_one(stat, @move.stat_up[idx + 1])
num_stats += 1
end
# Apply the average mini-score to the actual score
score = apply_effect_chance_to_score(main_mini_score * mini_score / num_stats)
return score
end
#=============================================================================
#
#=============================================================================

View File

@@ -1,5 +1,5 @@
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAttack1",
proc { |move, user, target, ai, battle|
@@ -9,77 +9,17 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAttack1",
)
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack1",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score -= user.stages[:ATTACK] * 20
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.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
else
score += 20 if user.stages[:ATTACK] < 0
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.battler.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score += 20 if hasPhysicalAttack
end
end
next score
next ai.get_score_for_user_stat_raise(score)
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1",
"RaiseUserAttack2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack2",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
next score - 90 if user.statStageAtMax?(:ATTACK)
score += 40 if user.turnCount == 0
score -= user.stages[:ATTACK] * 20
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.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
else
score += 10 if user.turnCount == 0
score += 20 if user.stages[:ATTACK] < 0
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.battler.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score += 20 if hasPhysicalAttack
end
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
"RaiseUserAttack2")
#===============================================================================
# TODO: Review score modifiers.
@@ -88,7 +28,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2",
"RaiseUserAttack2IfTargetFaints")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack2",
"RaiseUserAttack3")
@@ -131,225 +71,94 @@ Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP",
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1",
"RaiseUserDefense1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
next score - user.stages[:DEFENSE] * 20
elsif user.stages[:DEFENSE] < 0
next score + 20
end
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
"RaiseUserDefense1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1",
"RaiseUserDefense1CurlUpUser")
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1",
"RaiseUserDefense1CurlUpUser")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1CurlUpUser",
proc { |score, move, user, target, ai, battle|
score = ai.get_score_for_user_stat_raise(score)
if !user.effects[PBEffects::DefenseCurl] &&
user.check_for_move { |move| move.function == "MultiTurnAttackPowersUpEachTurn" }
score += 10
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1",
"RaiseUserDefense2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense2",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score += 40 if user.turnCount == 0
score -= user.stages[:DEFENSE] * 20
else
score += 10 if user.turnCount == 0
score += 20 if user.stages[:DEFENSE] < 0
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1",
"RaiseUserDefense2")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1",
"RaiseUserDefense3")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense3",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score += 40 if user.turnCount == 0
score -= user.stages[:DEFENSE] * 30
else
score += 10 if user.turnCount == 0
score += 30 if user.stages[:DEFENSE] < 0
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1",
"RaiseUserDefense3")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1",
"RaiseUserSpAtk1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk1",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score -= user.stages[:SPECIAL_ATTACK] * 20
if ai.trainer.medium_skill?
hasSpecicalAttack = false
user.battler.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
end
else
score += 20 if user.stages[:SPECIAL_ATTACK] < 0
if ai.trainer.medium_skill?
hasSpecicalAttack = false
user.battler.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 20 if hasSpecicalAttack
end
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
"RaiseUserSpAtk1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpAtk1",
"RaiseUserSpAtk2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk2",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score += 40 if user.turnCount == 0
score -= user.stages[:SPECIAL_ATTACK] * 20
if ai.trainer.medium_skill?
hasSpecicalAttack = false
user.battler.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
end
else
score += 10 if user.turnCount == 0
score += 20 if user.stages[:SPECIAL_ATTACK] < 0
if ai.trainer.medium_skill?
hasSpecicalAttack = false
user.battler.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 20 if hasSpecicalAttack
end
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpAtk1",
"RaiseUserSpAtk2")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpAtk1",
"RaiseUserSpAtk3")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk3",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score += 40 if user.turnCount == 0
score -= user.stages[:SPECIAL_ATTACK] * 30
if ai.trainer.medium_skill?
hasSpecicalAttack = false
user.battler.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 30
elsif ai.trainer.high_skill?
score -= 90
end
end
else
score += 10 if user.turnCount == 0
score += 30 if user.stages[:SPECIAL_ATTACK] < 0
if ai.trainer.medium_skill?
hasSpecicalAttack = false
user.battler.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 30 if hasSpecicalAttack
end
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpAtk1",
"RaiseUserSpAtk3")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1",
"RaiseUserSpDef1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score += 40 if user.turnCount == 0
score -= user.stages[:SPECIAL_DEFENSE] * 20
else
score += 10 if user.turnCount == 0
score += 20 if user.stages[:SPECIAL_DEFENSE] < 0
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1",
"RaiseUserSpDef1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
"RaiseUserSpDef1PowerUpElectricMove")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1PowerUpElectricMove",
proc { |score, move, user, target, ai, battle|
foundMove = false
user.battler.eachMove do |m|
next if m.type != :ELECTRIC || !m.damagingMove?
foundMove = true
break
end
score += 20 if foundMove
if move.statusMove?
score -= user.stages[:SPECIAL_DEFENSE] * 20
elsif user.stages[:SPECIAL_DEFENSE] < 0
score += 20
score = ai.get_score_for_user_stat_raise(score)
if user.check_for_move { |move| move.damagingMove? && move.type == :ELECTRIC }
score += 10
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
"RaiseUserSpDef2")
@@ -357,7 +166,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1",
"RaiseUserSpDef2")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
"RaiseUserSpDef3")
@@ -365,53 +174,23 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1",
"RaiseUserSpDef3")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
"RaiseUserSpeed1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed1",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score -= user.stages[:SPEED] * 10
if ai.trainer.high_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
score += 30 if aspeed < ospeed && aspeed * 2 > ospeed
end
elsif user.stages[:SPEED] < 0
score += 20
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1",
"RaiseUserSpeed1")
#===============================================================================
# TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1",
"RaiseUserSpeed2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score += 20 if user.turnCount == 0
score -= user.stages[:SPEED] * 10
if ai.trainer.high_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
score += 30 if aspeed < ospeed && aspeed * 2 > ospeed
end
else
score += 10 if user.turnCount == 0
score += 20 if user.stages[:SPEED] < 0
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1",
"RaiseUserSpeed2")
#===============================================================================
# TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2",
"RaiseUserSpeed2LowerUserWeight")
@@ -419,34 +198,23 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed2",
"RaiseUserSpeed2LowerUserWeight")
#===============================================================================
# TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2",
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1",
"RaiseUserSpeed3")
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed2",
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1",
"RaiseUserSpeed3")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1",
"RaiseUserAccuracy1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAccuracy1",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score += 40 if user.turnCount == 0
score -= user.stages[:ACCURACY] * 20
else
score += 10 if user.turnCount == 0
score += 20 if user.stages[:ACCURACY] < 0
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1",
"RaiseUserAccuracy1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1",
"RaiseUserAccuracy2")
@@ -454,7 +222,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1",
"RaiseUserAccuracy2")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1",
"RaiseUserAccuracy3")
@@ -462,38 +230,20 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1",
"RaiseUserAccuracy3")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1",
"RaiseUserEvasion1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserEvasion1",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score -= user.stages[:EVASION] * 10
elsif user.stages[:EVASION] < 0
score += 20
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1",
"RaiseUserEvasion1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion1",
"RaiseUserEvasion2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserEvasion2",
proc { |score, move, user, target, ai, battle|
if move.statusMove?
score += 40 if user.turnCount == 0
score -= user.stages[:EVASION] * 10
else
score += 10 if user.turnCount == 0
score += 20 if user.stages[:EVASION] < 0
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion1",
"RaiseUserEvasion2")
#===============================================================================
# TODO: Review score modifiers.
@@ -504,7 +254,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion2",
"RaiseUserEvasion2MinimizeUser")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion2",
"RaiseUserEvasion3")
@@ -528,7 +278,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserCriticalHitRate2",
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAtkDef1",
proc { |move, user, target, ai, battle|
@@ -543,106 +293,32 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAtkDef1",
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkDef1",
proc { |score, move, user, target, ai, battle|
score -= user.stages[:ATTACK] * 10
score -= user.stages[:DEFENSE] * 10
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.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
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
"RaiseUserAtkDef1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1",
"RaiseUserAtkDefAcc1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkDefAcc1",
proc { |score, move, user, target, ai, battle|
score -= user.stages[:ATTACK] * 10
score -= user.stages[:DEFENSE] * 10
score -= user.stages[:ACCURACY] * 10
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.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
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkDef1",
"RaiseUserAtkDefAcc1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1",
"RaiseUserAtkSpAtk1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle|
score -= user.stages[:ATTACK] * 10
score -= user.stages[:SPECIAL_ATTACK] * 10
if ai.trainer.medium_skill?
hasDamagingAttack = false
user.battler.eachMove do |m|
next if !m.damagingMove?
hasDamagingAttack = true
break
end
if hasDamagingAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkDef1",
"RaiseUserAtkSpAtk1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpAtk1Or2InSun")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1Or2InSun",
proc { |score, move, user, target, ai, battle|
score -= user.stages[:ATTACK] * 10
score -= user.stages[:SPECIAL_ATTACK] * 10
if ai.trainer.medium_skill?
hasDamagingAttack = false
user.battler.eachMove do |m|
next if !m.damagingMove?
hasDamagingAttack = true
break
end
if hasDamagingAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
end
score += 20 if [:Sun, :HarshSun].include?(user.battler.effectiveWeather)
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpAtk1Or2InSun")
#===============================================================================
# TODO: Review score modifiers.
@@ -684,190 +360,60 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDef1RaiseUserAtkSpAtkSp
)
#===============================================================================
# TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpd1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpd1",
proc { |score, move, user, target, ai, battle|
score += 40 if user.turnCount == 0 # Dragon Dance tends to be popular
score -= user.stages[:ATTACK] * 10
score -= user.stages[:SPEED] * 10
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.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
if ai.trainer.high_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
score += 20 if aspeed < ospeed && aspeed * 2 > ospeed
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpd1")
#===============================================================================
# TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtk1Spd2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtk1Spd2",
proc { |score, move, user, target, ai, battle|
score -= user.stages[:ATTACK] * 10
score -= user.stages[:SPEED] * 10
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.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
if ai.trainer.high_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
score += 30 if aspeed < ospeed && aspeed * 2 > ospeed
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtk1Spd2")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkAcc1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkAcc1",
proc { |score, move, user, target, ai, battle|
score -= user.stages[:ATTACK] * 10
score -= user.stages[:ACCURACY] * 10
if ai.trainer.medium_skill?
hasPhysicalAttack = false
user.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
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkAcc1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserDefSpDef1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefSpDef1",
proc { |score, move, user, target, ai, battle|
score -= user.stages[:DEFENSE] * 10
score -= user.stages[:SPECIAL_DEFENSE] * 10
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserDefSpDef1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserSpAtkSpDef1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtkSpDef1",
proc { |score, move, user, target, ai, battle|
score += 40 if user.turnCount == 0 # Calm Mind tends to be popular
score -= user.stages[:SPECIAL_ATTACK] * 10
score -= user.stages[:SPECIAL_DEFENSE] * 10
if ai.trainer.medium_skill?
hasSpecicalAttack = false
user.battler.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserSpAtkSpDef1")
#===============================================================================
# TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserSpAtkSpDefSpd1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtkSpDefSpd1",
proc { |score, move, user, target, ai, battle|
score += 40 if user.turnCount == 0 # Calm Mind tends to be popular
score -= user.stages[:SPECIAL_ATTACK] * 10
score -= user.stages[:SPECIAL_DEFENSE] * 10
score -= user.stages[:SPEED] * 10
if ai.trainer.medium_skill?
hasSpecicalAttack = false
user.battler.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
end
if ai.trainer.high_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
score += 20 if aspeed < ospeed && aspeed * 2 > ospeed
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserSpAtkSpDefSpd1")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserMainStats1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1",
proc { |score, move, user, target, ai, battle|
GameData::Stat.each_main_battle { |s| score += 10 if user.stages[s.id] < 0 }
if ai.trainer.medium_skill?
hasDamagingAttack = false
user.battler.eachMove do |m|
next if !m.damagingMove?
hasDamagingAttack = true
break
end
score += 20 if hasDamagingAttack
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserMainStats1")
#===============================================================================
# TODO: Review score modifiers.
@@ -1284,7 +830,7 @@ Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetDefense1",
"LowerTargetDefense1PowersUpInGravity")
Battle::AI::Handlers::MoveBasePower.add("LowerTargetDefense1PowersUpInGravity",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1PowersUpInGravity",
@@ -1504,7 +1050,7 @@ Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpeed1",
"LowerTargetSpeed1WeakerInGrassyTerrain")
Battle::AI::Handlers::MoveBasePower.add("LowerTargetSpeed1WeakerInGrassyTerrain",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetSpeed1",

View File

@@ -425,7 +425,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfNotUserFirstTurn",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky",

View File

@@ -3,7 +3,7 @@
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("FixedDamage20",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
next move.move.pbFixedDamage(user.battler, target.battler)
}
)
@@ -12,7 +12,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamage20",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("FixedDamage40",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
next move.move.pbFixedDamage(user.battler, target.battler)
}
)
@@ -21,7 +21,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamage40",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("FixedDamageHalfTargetHP",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
next move.move.pbFixedDamage(user.battler, target.battler)
}
)
@@ -30,7 +30,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamageHalfTargetHP",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevel",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
next move.move.pbFixedDamage(user.battler, target.battler)
}
)
@@ -53,7 +53,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetHPToUserHP",
)
Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP",
proc { |power, move, user, target, ai, battle|
next move.pbFixedDamage(user.battler, target.battler)
next move.move.pbFixedDamage(user.battler, target.battler)
}
)
@@ -112,7 +112,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DamageTargetAlly",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithUserHP",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
@@ -181,7 +181,7 @@ Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithLessPP",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithTargetWeight",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
@@ -215,7 +215,7 @@ Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithConsecutiveUseOnUserSide
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)
next move.move.pbModifyDamage(power, user.battler, target.battler)
}
)
@@ -224,7 +224,7 @@ Battle::AI::Handlers::MoveBasePower.add("RandomPowerDoublePowerIfTargetUndergrou
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetHPLessThanHalf",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
@@ -251,7 +251,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetAsleepCureTarget",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
@@ -271,7 +271,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetParalyzedCureTarge
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetStatusProblem",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
@@ -289,7 +289,7 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfUserHasNoItem",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetUnderwater",
proc { |power, move, user, target, ai, battle|
next move.pbModifyDamage(power, user.battler, target.battler)
next move.move.pbModifyDamage(power, user.battler, target.battler)
}
)
@@ -304,7 +304,7 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetUnderwater",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetInSky",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
@@ -818,7 +818,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndD
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
@@ -834,8 +834,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("TypeAndPowerDependOnUserBerry",
)
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)
# TODO: Can't this just call move.move.pbBaseDamage?
ret = move.move.pbNaturalGiftBaseDamage(user.item_id)
next (ret == 1) ? 0 : ret
}
)
@@ -874,7 +874,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TypeDependsOnUserMorpekoFormRaiseUser
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnWeather",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)

View File

@@ -3,7 +3,7 @@
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
proc { |power, move, user, target, ai, battle|
next power * move.pbNumHits(user.battler, [target.battler])
next power * move.move.pbNumHits(user.battler, [target.battler])
}
)
@@ -64,7 +64,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesAlwaysCriticalHit",
proc { |power, move, user, target, ai, battle|
next power * move.pbNumHits(user.battler, [target.battler])
next power * move.move.pbNumHits(user.battler, [target.battler])
}
)
Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesAlwaysCriticalHit",
@@ -92,7 +92,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja",
proc { |power, move, user, target, ai, battle|
if user.battler.isSpecies?(:GRENINJA) && user.battler.form == 2
next move.pbBaseDamage(power, user.battler, target.battler) * move.pbNumHits(user.battler, [target.battler])
next move.move.pbBaseDamage(power, user.battler, target.battler) * move.move.pbNumHits(user.battler, [target.battler])
end
next power * 5 if user.has_active_ability?(:SKILLLINK)
next power * 31 / 10 # Average damage dealt
@@ -161,7 +161,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamageMultiplier(power, user.battler, target.battler)
next move.move.pbBaseDamageMultiplier(power, user.battler, target.battler)
}
)
@@ -338,7 +338,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackInvulnerableInSkyTarget
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn",
proc { |power, move, user, target, ai, battle|
next power * 2 if user.effects[PBEffects::DefenseCurl]
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)

View File

@@ -82,7 +82,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("RemoveTargetItem",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem",
@@ -260,6 +260,6 @@ Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget",
)
Battle::AI::Handlers::MoveBasePower.add("ThrowUserItemAtTarget",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)

View File

@@ -110,7 +110,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CurseTargetOrLowerUserSpd1RaiseUserAt
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("HitsAllFoesAndPowersUpInPsychicTerrain",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain",
@@ -261,7 +261,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("PowerDependsOnUserStockpile",
)
Battle::AI::Handlers::MoveBasePower.add("PowerDependsOnUserStockpile",
proc { |power, move, user, target, ai, battle|
next move.pbBaseDamage(power, user.battler, target.battler)
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)

View File

@@ -171,7 +171,7 @@ Battle::AI::Handlers::MoveEffectScore.add("BindTarget",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater",
proc { |power, move, user, target, ai, battle|
next move.pbModifyDamage(power, user.battler, target.battler)
next move.move.pbModifyDamage(power, user.battler, target.battler)
}
)
Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater",

View File

@@ -24,7 +24,8 @@ class Battle::AI::AIBattler
def level; return @battler.level; end
def hp; return @battler.hp; end
def status; return @Battler.status; end
def fainted?; return @battler.fainted?; end
def status; return @battler.status; end
def statusCount; return @battler.statusCount; end
def totalhp; return @battler.totalhp; end
def gender; return @battler.gender; end
@@ -57,12 +58,103 @@ class Battle::AI::AIBattler
#=============================================================================
def check_for_move
ret = false
@battler.eachMove do |move|
next unless yield move
ret = true
break
# Returns how much damage this battler will take at the end of this round.
def rough_end_of_round_damage
ret = 0
# Future Sight/Doom Desire
# TODO
# Wish
if @ai.battle.positions[@index].effects[PBEffects::Wish] == 1 && @battler.canHeal?
ret -= @ai.battle.positions[@index].effects[PBEffects::WishAmount]
end
# Sea of Fire
if @ai.battle.sides[@side].effects[PBEffects::SeaOfFire] > 1 &&
@battler.takesIndirectDamage? && !has_type?(:FIRE)
ret += self.totalhp / 8
end
# Grassy Terrain (healing)
if @ai.battle.field.terrain == :Grassy && @battler.affectedByTerrain? && @battler.canHeal?
ret -= [battler.totalhp / 16, 1].max
end
# Leftovers/Black Sludge
if has_active_item?(:BLACKSLUDGE)
if has_type?(:POISON)
ret -= [battler.totalhp / 16, 1].max if @battler.canHeal?
else
ret += [battler.totalhp / 8, 1].max if @battler.takesIndirectDamage?
end
elsif has_active_item?(:LEFTOVERS)
ret -= [battler.totalhp / 16, 1].max if @battler.canHeal?
end
# Aqua Ring
if self.effects[PBEffects::AquaRing] && @battler.canHeal?
amt = battler.totalhp / 16
amt = (amt * 1.3).floor if has_active_item?(:BIGROOT)
ret -= [amt, 1].max
end
# Ingrain
if self.effects[PBEffects::Ingrain] && @battler.canHeal?
amt = battler.totalhp / 16
amt = (amt * 1.3).floor if has_active_item?(:BIGROOT)
ret -= [amt, 1].max
end
# Leech Seed
if self.effects[PBEffects::LeechSeed] >= 0
if @battler.takesIndirectDamage?
ret += [battler.totalhp / 8, 1].max if @battler.takesIndirectDamage?
end
else
@ai.each_battler do |b, i|
next if i == @index || b.effects[PBEffects::LeechSeed] != @index
amt = [[b.totalhp / 8, b.hp].min, 1].max
amt = (amt * 1.3).floor if has_active_item?(:BIGROOT)
ret -= [amt, 1].max
end
end
# Hyper Mode (Shadow Pokémon)
# TODO
# Poison/burn/Nightmare
if self.status == :POISON
if has_active_ability?(:POISONHEAL)
ret -= [battler.totalhp / 8, 1].max if @battler.canHeal?
elsif @battler.takesIndirectDamage?
mult = 2
mult = [self.effects[PBEffects::Toxic] + 1, 16].min if self.statusCount > 0 # Toxic
ret += [mult * battler.totalhp / 16, 1].max
end
elsif self.status == :BURN
if @battler.takesIndirectDamage?
amt = (Settings::MECHANICS_GENERATION >= 7) ? self.totalhp / 16 : self.totalhp / 8
amt = (amt / 2.0).round if has_active_ability?(:HEATPROOF)
ret += [amt, 1].max
end
elsif @battler.asleep? && self.statusCount > 1 && self.effects[PBEffects::Nightmare]
ret += [battler.totalhp / 4, 1].max if @battler.takesIndirectDamage?
end
# Curse
if self.effects[PBEffects::Curse]
ret += [battler.totalhp / 4, 1].max if @battler.takesIndirectDamage?
end
# 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)
amt = (Settings::MECHANICS_GENERATION >= 6) ? self.totalhp / 6 : self.totalhp / 8
end
ret += [amt, 1].max
end
# Perish Song
# TODO
# Bad Dreams
if @battler.asleep? && self.statusCount > 1 && @battler.takesIndirectDamage?
@ai.each_battler do |b, i|
next if i == @index || !b.battler.near?(@battler) || !b.has_active_ability?(:BADDREAMS)
ret += [battler.totalhp / 8, 1].max
end
end
# Sticky Barb
if has_active_item?(:STICKYBARB) && @battler.takesIndirectDamage?
ret += [battler.totalhp / 8, 1].max
end
return ret
end
@@ -163,16 +255,16 @@ class Battle::AI::AIBattler
#=============================================================================
def can_switch_lax?
return false if wild?
@ai.battle.eachInTeamFromBattlerIndex(@index) do |pkmn, i|
return true if @ai.battle.pbCanSwitchLax?(@index, i)
def check_for_move
ret = false
@battler.eachMove do |move|
next unless yield move
ret = true
break
end
return false
return ret
end
#=============================================================================
def immune_to_move?
user = @ai.user
user_battler = user.battler
@@ -226,6 +318,16 @@ class Battle::AI::AIBattler
#=============================================================================
def can_switch_lax?
return false if wild?
@ai.battle.eachInTeamFromBattlerIndex(@index) do |pkmn, i|
return true if @ai.battle.pbCanSwitchLax?(@index, i)
end
return false
end
#=============================================================================
private
def effectiveness_of_type_against_single_battler_type(type, defend_type, user = nil)

View File

@@ -1207,7 +1207,7 @@ Battle::AbilityEffects::DamageCalcFromUser.add(:ANALYTIC,
# are being used), so I'm choosing to ignore it. The effect is thus:
# "power up the move if all other battlers on the field right now have
# already moved".
if move.pbMoveFailedLastInRound?(user, false)
if move.move.pbMoveFailedLastInRound?(user, false)
mults[:base_damage_multiplier] *= 1.3
end
}
@@ -1528,7 +1528,7 @@ Battle::AbilityEffects::DamageCalcFromTarget.add(:FLOWERGIFT,
Battle::AbilityEffects::DamageCalcFromTarget.add(:FLUFFY,
proc { |ability, user, target, move, mults, baseDmg, type|
mults[:final_damage_multiplier] *= 2 if move.calcType == :FIRE
mults[:final_damage_multiplier] /= 2 if move.pbContactMove?(user)
mults[:final_damage_multiplier] /= 2 if move.move.pbContactMove?(user)
}
)

View File

@@ -540,7 +540,7 @@ class Pokemon
# @return [Boolean] whether this Pokémon has a particular nature or a nature
# at all
def hasNature?(check_nature = nil)
return !@nature_id.nil? if check_nature.nil?
return !@nature.nil? if check_nature.nil?
return self.nature == check_nature
end