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) def pbEORSeaOfFireDamage(priority)
2.times do |side| 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 next if sides[side].effects[PBEffects::SeaOfFire] == 0
pbCommonAnimation("SeaOfFire") if side == 0 pbCommonAnimation("SeaOfFire") if side == 0
pbCommonAnimation("SeaOfFireOpp") if side == 1 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 # 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 # are applied normally, applying the user's Attack modifiers and not the user's
# Defence modifiers. (Body Press) # Defence modifiers. (Body Press)
# TODO: Rename this function code to remove both "Base"s?
#=============================================================================== #===============================================================================
class Battle::Move::UseUserBaseDefenseInsteadOfUserBaseAttack < Battle::Move class Battle::Move::UseUserBaseDefenseInsteadOfUserBaseAttack < Battle::Move
def pbGetAttackStats(user, target) def pbGetAttackStats(user, target)

View File

@@ -133,7 +133,7 @@ class Battle::AI
# after all. # after all.
return true if @move.move.pbImmunityByAbility(@user.battler, @target.battler, false) return true if @move.move.pbImmunityByAbility(@user.battler, @target.battler, false)
# Type immunity # Type immunity
calc_type = @move.rough_type(@user.battler) calc_type = @move.rough_type
typeMod = @move.move.pbCalcTypeMod(calc_type, @user.battler, @target.battler) typeMod = @move.move.pbCalcTypeMod(calc_type, @user.battler, @target.battler)
return true if @move.move.pbDamagingMove? && Effectiveness.ineffective?(typeMod) return true if @move.move.pbDamagingMove? && Effectiveness.ineffective?(typeMod)
# Dark-type immunity to moves made faster by Prankster # Dark-type immunity to moves made faster by Prankster

View File

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

View File

@@ -1,24 +1,105 @@
class Battle::AI class Battle::AI
#============================================================================= #=============================================================================
# Apply additional effect chance to a move's score # Main method for calculating the score for moves that raise the user's stat(s).
# TODO: Apply all the additional effect chance modifiers.
#============================================================================= #=============================================================================
def apply_effect_chance_to_score(score) def get_score_for_user_stat_raise(score)
if @move.damagingMove? # Discard status move/don't prefer damaging move if user has Contrary
# TODO: Doesn't return the correct value for "ConfuseTarget" (Chatter). if !@battle.moldBreaker && @user.has_active_ability?(:CONTRARY)
effect_chance = @move.addlEffect return (@move.statusMove?) ? score - 40 : score - 20
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
end 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 return score
end 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 # TODO: These function codes need to have an attr_reader :statUp and for them
# to be set when the move is initialised. # to be set when the move is initialised.
@@ -26,15 +107,45 @@ class Battle::AI
# RaiseTargetRandomStat2 Acupressure # RaiseTargetRandomStat2 Acupressure
# RaisePlusMinusUserAndAlliesDefSpDef1 Magnetic Flux # RaisePlusMinusUserAndAlliesDefSpDef1 Magnetic Flux
# RaisePlusMinusUserAndAlliesAtkSpAtk1 Gear Up # 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 mini_score = 1.0
# Determine whether the move boosts Attack, Special Attack or Speed (Bulk Up # Determine whether the move boosts Attack, Special Attack or Speed (Bulk Up
# is sometimes not considered a sweeping move) # is sometimes not considered a sweeping move)
sweeping_stat = false sweeping_stat = false
offensive_stat = false offensive_stat = false
@move.stat_up.each_with_index do |stat, idx| stat_changes.each do |change|
next if idx.odd? next if ![:ATTACK, :SPECIAL_ATTACK, :SPEED].include?(change[0])
next if ![:ATTACK, :SPATK, :SPEED].include?(stat)
sweeping_stat = true sweeping_stat = true
next if @move.function == "RaiseUserAtkDef1" # Bulk Up (+Atk +Def) next if @move.function == "RaiseUserAtkDef1" # Bulk Up (+Atk +Def)
offensive_stat = true offensive_stat = true
@@ -45,12 +156,6 @@ class Battle::AI
if @user.hp >= @user.totalhp * 3 / 4 if @user.hp >= @user.totalhp * 3 / 4
mini_score *= (sweeping_stat) ? 1.2 : 1.1 mini_score *= (sweeping_stat) ? 1.2 : 1.1
end 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. # TODO: Prefer if user's moves won't do much damage.
# Prefer if user has something that will limit damage taken # Prefer if user has something that will limit damage taken
mini_score *= 1.3 if @user.effects[PBEffects::Substitute] > 0 || 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 # TODO: Prefer if the maximum damage the target has dealt wouldn't hurt
# the user much. # the user much.
end 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 # Don't prefer if it's not a single battle
if !@battle.singleBattle? if !@battle.singleBattle?
@@ -132,197 +231,271 @@ class Battle::AI
end 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 get_user_stat_raise_score_one(score, stat, increment)
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?
case stat case stat
when :ATTACK when :ATTACK
has_physical_move = false # Modify score depending on current stat stage
@user.eachMove do |m| # More strongly prefer if the user has no special moves
next if !m.physicalMove?(m.type) || m.function == "UseTargetAttackInsteadOfUserAttack" # Foul Play if @user.stages[stat] >= 3
has_physical_move = true score -= 20
break 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 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 when :SPECIAL_ATTACK
has_special_move = false # Modify score depending on current stat stage
@user.eachMove do |m| # More strongly prefer if the user has no physical moves
next if !m.specialMove?(m.type) if @user.stages[stat] >= 3
has_special_move = true 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 break
end end
return mini_score if !has_special_move # Don't prefer if any foe has Gyro Ball
end 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 :ACCURACY
when :ATTACK # Modify score depending on current stat stage
# Prefer if user can definitely survive a hit no matter how powerful, and if @user.stages[stat] >= 3
# it won't be hurt by weather score -= 20
if @user.hp == @user.totalhp && else
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) min_accuracy = 100
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && @user.battler.moves.each do |m|
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) && next if m.accuracy == 0 || m.is_a?(Battle::Move::OHKO)
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) min_accuracy = m.accuracy if m.accuracy < min_accuracy
mini_score *= 1.4 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
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. when :EVASION
# TODO: Don't prefer if some of foes' stats are raised # Prefer if a foe will (probably) take damage at the end of the round
sum_stages = 0 # TODO: Should this take into account EOR healing, one-off damage and
[:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s| # damage-causing effects that wear off naturally (like Sea of Fire)?
sum_stages += @target.stages[s] # 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 end
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 # Modify score depending on current stat stage
# TODO: Don't prefer if target has Speed Boost (+Spd at end of each round). if @user.stages[stat] >= 3
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST) 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 # TODO: Don't prefer if target has previously used a move that benefits
# from user's Attack being boosted. # from user's Attack being boosted.
mini_score *= 0.3 if check_for_move(@target) { |move| move.function == "UseTargetAttackInsteadOfUserAttack" } # Foul Play # mini_score *= 0.3 if @target.check_for_move { |move| move.function == "UseTargetAttackInsteadOfUserAttack" } # Foul Play
# TODO: Don't prefer if the target has previously used a priority move. # 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 when :DEFENSE
# Prefer if user has a healing item # Prefer if user has a healing item
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). # TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) || # mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON)) # (@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
# Prefer if user knows any healing moves # Prefer if user knows any healing moves
# TODO: Is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). # # 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) { |move| move.healingMove? }
# Prefer if user knows Pain Split or Leech Seed # Prefer if user knows Pain Split or Leech Seed
# TODO: Leech Seed is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). # # 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.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed # mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
# Prefer if user has certain roles # Prefer if user has certain roles
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). # # TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL) # mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# Don't prefer if user is badly poisoned # Don't prefer if user is badly poisoned
mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0 mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0
# Don't prefer if user's Defense stat is raised # # TODO: Prefer if foes have higher Attack than Special Attack, and user
sum_stages = @user.stages[:DEFENSE] # # doesn't have a wall role, user is faster and user has at least 75%
mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0 # # 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 # TODO: Don't prefer if previous damage done by foes wouldn't hurt the
# user much. # user much.
when :SPEED 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 # Prefer if user can definitely survive a hit no matter how powerful, and
# it won't be hurt by weather # it won't be hurt by weather
if @user.hp == @user.totalhp && # if @user.hp == @user.totalhp &&
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) # (@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && # if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) && # !(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) # !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4 # mini_score *= 1.4
end # end
end # end
# Prefer if user's Attack/SpAtk stat (whichever is higher) is lowered # Prefer if user has the Sweeper role
# TODO: Why? # mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
if @user.attack > @user.spatk # TODO: Don't prefer if Trick Room applies or any foe has previously used
sum_stages = @user.stages[:ATTACK] # Trick Room.
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0 # mini_score *= 0.2 if @battle.field.effects[PBEffects::TrickRoom] > 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)
# TODO: Don't prefer if target has raised defenses. # # Prefer if user's Attack/SpAtk stat (whichever is higher) is lowered
sum_stages = 0 # # TODO: Why?
[:DEFENSE, :SPECIAL_DEFENSE].each { |s| sum_stages += @target.stages[s] } # if @user.attack > @user.spatk
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 # sum_stages = @user.stages[:ATTACK]
# TODO: Don't prefer if the target has previously used a priority move. # mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
# TODO: Don't prefer if Trick Room applies or any foe has previously used # else
# Trick Room. # sum_stages = @user.stages[:SPATK]
mini_score *= 0.2 if @battle.field.effects[PBEffects::TrickRoom] > 0 # mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
# end
# TODO: Don't prefer if user is already faster than the target. Exception # # Prefer if user has Moxie
# for moves that benefit from a raised user's Speed? # mini_score *= 1.3 if @user.hasActiveAbility?(:MOXIE)
# TODO: Don't prefer if user is already faster than the target and there's # # Don't prefer if user is burned or paralysed
# only 1 unfainted foe (this check is done by Agility/Autotomize # mini_score *= 0.2 if @user.status == :PARALYSIS
# (both +2 Spd) only in Reborn.) # # 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 when :SPECIAL_ATTACK
# Prefer if user can definitely survive a hit no matter how powerful, and # Prefer if user can definitely survive a hit no matter how powerful, and
# it won't be hurt by weather # it won't be hurt by weather
if @user.hp == @user.totalhp && # if @user.hp == @user.totalhp &&
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) # (@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && # if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) && # !(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) # !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4 # mini_score *= 1.4
end # end
end # end
# Prefer if user has the Sweeper role # Prefer if user has the Sweeper role
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER) # 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
# TODO: Prefer if target has previously used a HP-restoring move. # # Don't prefer if user's Speed stat is lowered
# TODO: Don't prefer if some of foes' stats are raised # sum_stages = @user.stages[:SPEED]
sum_stages = 0 # mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
[:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s| # # TODO: Prefer if target has previously used a HP-restoring move.
sum_stages += @target.stages[s] # # TODO: Don't prefer if some of foes' stats are raised
end # sum_stages = 0
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 # [:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s|
# TODO: Don't prefer if target has Speed Boost (+Spd at end of each round) # sum_stages += @target.stages[s]
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST) # end
# TODO: Don't prefer if the target has previously used a priority move. # 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 when :SPECIAL_DEFENSE
# Prefer if user has a healing item # Prefer if user has a healing item
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) || # mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON)) # (@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
# Prefer if user knows any healing moves # 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 # Prefer if user knows Pain Split or Leech Seed
mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split # mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed # mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
# Prefer if user has certain roles # Prefer if user has certain roles
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL) # mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# Don't prefer if user's Defense stat is raised # # TODO: Prefer if foes have higher Special Attack than Attack.
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.
# TODO: Don't prefer if previous damage done by foes wouldn't hurt the # TODO: Don't prefer if previous damage done by foes wouldn't hurt the
# user much. # user much.
when :ACCURACY when :ACCURACY
# Prefer if user knows any weaker moves # 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) { |move| move.damagingMove? && move.basedamage < 95 }
# Prefer if target has a raised evasion # Prefer if target has a raised evasion
sum_stages = @target.stages[:EVASION] sum_stages = @target.stages[:EVASION]
mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0 mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0
@@ -355,20 +528,12 @@ class Battle::AI
# Prefer if user has certain roles # Prefer if user has certain roles
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL) 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 user's evasion stat is raised
# TODO: Don't prefer if target has No Guard. # TODO: Don't prefer if target has No Guard.
mini_score *= 0.2 if @target.hasActiveAbility?(:NOGUARD) mini_score *= 0.2 if @target.hasActiveAbility?(:NOGUARD)
# TODO: Don't prefer if target has previously used any moves that never miss. # TODO: Don't prefer if target has previously used any moves that never miss.
end 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 # TODO: Don't prefer if any foe has previously used a stat stage-clearing
# move (Clear Smog/Haze). # move (Clear Smog/Haze).
@@ -390,47 +555,6 @@ class Battle::AI
return mini_score return mini_score
end 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", Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAttack1",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
@@ -9,77 +9,17 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAttack1",
) )
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack1", Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if move.statusMove? next ai.get_score_for_user_stat_raise(score)
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
} }
) )
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1",
"RaiseUserAttack2") "RaiseUserAttack2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack2", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
proc { |score, move, user, target, ai, battle| "RaiseUserAttack2")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
@@ -88,7 +28,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2",
"RaiseUserAttack2IfTargetFaints") "RaiseUserAttack2IfTargetFaints")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack2", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack2",
"RaiseUserAttack3") "RaiseUserAttack3")
@@ -131,225 +71,94 @@ Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP",
) )
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1",
"RaiseUserDefense1") "RaiseUserDefense1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
proc { |score, move, user, target, ai, battle| "RaiseUserDefense1")
if move.statusMove?
next score - user.stages[:DEFENSE] * 20
elsif user.stages[:DEFENSE] < 0
next score + 20
end
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1",
"RaiseUserDefense1CurlUpUser") "RaiseUserDefense1CurlUpUser")
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1", Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1CurlUpUser",
"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", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1",
"RaiseUserDefense2") "RaiseUserDefense2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense2", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1",
proc { |score, move, user, target, ai, battle| "RaiseUserDefense2")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1",
"RaiseUserDefense3") "RaiseUserDefense3")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense3", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1",
proc { |score, move, user, target, ai, battle| "RaiseUserDefense3")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1",
"RaiseUserSpAtk1") "RaiseUserSpAtk1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
proc { |score, move, user, target, ai, battle| "RaiseUserSpAtk1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpAtk1",
"RaiseUserSpAtk2") "RaiseUserSpAtk2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk2", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserSpAtk2")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpAtk1",
"RaiseUserSpAtk3") "RaiseUserSpAtk3")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk3", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserSpAtk3")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1",
"RaiseUserSpDef1") "RaiseUserSpDef1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1",
proc { |score, move, user, target, ai, battle| "RaiseUserSpDef1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
"RaiseUserSpDef1PowerUpElectricMove") "RaiseUserSpDef1PowerUpElectricMove")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1PowerUpElectricMove", Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1PowerUpElectricMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
foundMove = false score = ai.get_score_for_user_stat_raise(score)
user.battler.eachMove do |m| if user.check_for_move { |move| move.damagingMove? && move.type == :ELECTRIC }
next if m.type != :ELECTRIC || !m.damagingMove? score += 10
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
end end
next score next score
} }
) )
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
"RaiseUserSpDef2") "RaiseUserSpDef2")
@@ -357,7 +166,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1",
"RaiseUserSpDef2") "RaiseUserSpDef2")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
"RaiseUserSpDef3") "RaiseUserSpDef3")
@@ -365,53 +174,23 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1",
"RaiseUserSpDef3") "RaiseUserSpDef3")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1",
"RaiseUserSpeed1") "RaiseUserSpeed1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1",
proc { |score, move, user, target, ai, battle| "RaiseUserSpeed1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
# TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1",
"RaiseUserSpeed2") "RaiseUserSpeed2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1",
proc { |score, move, user, target, ai, battle| "RaiseUserSpeed2")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2",
"RaiseUserSpeed2LowerUserWeight") "RaiseUserSpeed2LowerUserWeight")
@@ -419,34 +198,23 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed2",
"RaiseUserSpeed2LowerUserWeight") "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") "RaiseUserSpeed3")
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed2", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1",
"RaiseUserSpeed3") "RaiseUserSpeed3")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1",
"RaiseUserAccuracy1") "RaiseUserAccuracy1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAccuracy1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1",
proc { |score, move, user, target, ai, battle| "RaiseUserAccuracy1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1",
"RaiseUserAccuracy2") "RaiseUserAccuracy2")
@@ -454,7 +222,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1",
"RaiseUserAccuracy2") "RaiseUserAccuracy2")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1",
"RaiseUserAccuracy3") "RaiseUserAccuracy3")
@@ -462,38 +230,20 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1",
"RaiseUserAccuracy3") "RaiseUserAccuracy3")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1",
"RaiseUserEvasion1") "RaiseUserEvasion1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserEvasion1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1",
proc { |score, move, user, target, ai, battle| "RaiseUserEvasion1")
if move.statusMove?
score -= user.stages[:EVASION] * 10
elsif user.stages[:EVASION] < 0
score += 20
end
next score
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion1",
"RaiseUserEvasion2") "RaiseUserEvasion2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserEvasion2", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion1",
proc { |score, move, user, target, ai, battle| "RaiseUserEvasion2")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
@@ -504,7 +254,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion2",
"RaiseUserEvasion2MinimizeUser") "RaiseUserEvasion2MinimizeUser")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion2", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion2",
"RaiseUserEvasion3") "RaiseUserEvasion3")
@@ -528,7 +278,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserCriticalHitRate2",
) )
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAtkDef1", Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAtkDef1",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
@@ -543,106 +293,32 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAtkDef1",
end end
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkDef1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
proc { |score, move, user, target, ai, battle| "RaiseUserAtkDef1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1",
"RaiseUserAtkDefAcc1") "RaiseUserAtkDefAcc1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkDefAcc1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkDef1",
proc { |score, move, user, target, ai, battle| "RaiseUserAtkDefAcc1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1",
"RaiseUserAtkSpAtk1") "RaiseUserAtkSpAtk1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkDef1",
proc { |score, move, user, target, ai, battle| "RaiseUserAtkSpAtk1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpAtk1Or2InSun") "RaiseUserAtkSpAtk1Or2InSun")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1Or2InSun", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserAtkSpAtk1Or2InSun")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # 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", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpd1") "RaiseUserAtkSpd1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpd1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserAtkSpd1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
# TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtk1Spd2") "RaiseUserAtk1Spd2")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtk1Spd2", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserAtk1Spd2")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkAcc1") "RaiseUserAtkAcc1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkAcc1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserAtkAcc1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserDefSpDef1") "RaiseUserDefSpDef1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefSpDef1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserDefSpDef1")
score -= user.stages[:DEFENSE] * 10
score -= user.stages[:SPECIAL_DEFENSE] * 10
next score
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserSpAtkSpDef1") "RaiseUserSpAtkSpDef1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtkSpDef1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserSpAtkSpDef1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
# TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserSpAtkSpDefSpd1") "RaiseUserSpAtkSpDefSpd1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtkSpDefSpd1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserSpAtkSpDefSpd1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserMainStats1") "RaiseUserMainStats1")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1", Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
proc { |score, move, user, target, ai, battle| "RaiseUserMainStats1")
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
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
@@ -1284,7 +830,7 @@ Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetDefense1",
"LowerTargetDefense1PowersUpInGravity") "LowerTargetDefense1PowersUpInGravity")
Battle::AI::Handlers::MoveBasePower.add("LowerTargetDefense1PowersUpInGravity", Battle::AI::Handlers::MoveBasePower.add("LowerTargetDefense1PowersUpInGravity",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1PowersUpInGravity",
@@ -1504,7 +1050,7 @@ Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpeed1",
"LowerTargetSpeed1WeakerInGrassyTerrain") "LowerTargetSpeed1WeakerInGrassyTerrain")
Battle::AI::Handlers::MoveBasePower.add("LowerTargetSpeed1WeakerInGrassyTerrain", Battle::AI::Handlers::MoveBasePower.add("LowerTargetSpeed1WeakerInGrassyTerrain",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetSpeed1",

View File

@@ -425,7 +425,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfNotUserFirstTurn",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky", Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky",

View File

@@ -3,7 +3,7 @@
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.add("FixedDamage20", Battle::AI::Handlers::MoveBasePower.add("FixedDamage20",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("FixedDamage40",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("FixedDamageHalfTargetHP",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevel",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithUserHP",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithTargetWeight",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("RandomPowerDoublePowerIfTargetUnderground",
proc { |power, move, user, target, ai, battle| proc { |power, move, user, target, ai, battle|
power = 71 # Average damage 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", Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetHPLessThanHalf",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetStatusProblem",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetUnderwater",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetInSky",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnUserBerry",
proc { |power, move, user, target, ai, battle| proc { |power, move, user, target, ai, battle|
# TODO: Can't this just call move.pbBaseDamage? # TODO: Can't this just call move.move.pbBaseDamage?
ret = move.pbNaturalGiftBaseDamage(user.item_id) ret = move.move.pbNaturalGiftBaseDamage(user.item_id)
next (ret == 1) ? 0 : ret next (ret == 1) ? 0 : ret
} }
) )
@@ -874,7 +874,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TypeDependsOnUserMorpekoFormRaiseUser
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnWeather", Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnWeather",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesAlwaysCriticalHit",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesAlwaysCriticalHit",
@@ -92,7 +92,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja", Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja",
proc { |power, move, user, target, ai, battle| proc { |power, move, user, target, ai, battle|
if user.battler.isSpecies?(:GRENINJA) && user.battler.form == 2 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 end
next power * 5 if user.has_active_ability?(:SKILLLINK) next power * 5 if user.has_active_ability?(:SKILLLINK)
next power * 31 / 10 # Average damage dealt next power * 31 / 10 # Average damage dealt
@@ -161,7 +161,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun", Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("RemoveTargetItem",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem",
@@ -260,6 +260,6 @@ Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget",
) )
Battle::AI::Handlers::MoveBasePower.add("ThrowUserItemAtTarget", Battle::AI::Handlers::MoveBasePower.add("ThrowUserItemAtTarget",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("HitsAllFoesAndPowersUpInPsychicTerrain",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain",
@@ -261,7 +261,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("PowerDependsOnUserStockpile",
) )
Battle::AI::Handlers::MoveBasePower.add("PowerDependsOnUserStockpile", Battle::AI::Handlers::MoveBasePower.add("PowerDependsOnUserStockpile",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater",
proc { |power, move, user, target, ai, battle| 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", Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater",

View File

@@ -24,7 +24,8 @@ class Battle::AI::AIBattler
def level; return @battler.level; end def level; return @battler.level; end
def hp; return @battler.hp; 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 statusCount; return @battler.statusCount; end
def totalhp; return @battler.totalhp; end def totalhp; return @battler.totalhp; end
def gender; return @battler.gender; end def gender; return @battler.gender; end
@@ -57,12 +58,103 @@ class Battle::AI::AIBattler
#============================================================================= #=============================================================================
def check_for_move # Returns how much damage this battler will take at the end of this round.
ret = false def rough_end_of_round_damage
@battler.eachMove do |move| ret = 0
next unless yield move # Future Sight/Doom Desire
ret = true # TODO
break # 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 end
return ret return ret
end end
@@ -163,16 +255,16 @@ class Battle::AI::AIBattler
#============================================================================= #=============================================================================
def can_switch_lax? def check_for_move
return false if wild? ret = false
@ai.battle.eachInTeamFromBattlerIndex(@index) do |pkmn, i| @battler.eachMove do |move|
return true if @ai.battle.pbCanSwitchLax?(@index, i) next unless yield move
ret = true
break
end end
return false return ret
end end
#=============================================================================
def immune_to_move? def immune_to_move?
user = @ai.user user = @ai.user
user_battler = user.battler 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 private
def effectiveness_of_type_against_single_battler_type(type, defend_type, user = nil) 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: # 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 # "power up the move if all other battlers on the field right now have
# already moved". # already moved".
if move.pbMoveFailedLastInRound?(user, false) if move.move.pbMoveFailedLastInRound?(user, false)
mults[:base_damage_multiplier] *= 1.3 mults[:base_damage_multiplier] *= 1.3
end end
} }
@@ -1528,7 +1528,7 @@ Battle::AbilityEffects::DamageCalcFromTarget.add(:FLOWERGIFT,
Battle::AbilityEffects::DamageCalcFromTarget.add(:FLUFFY, Battle::AbilityEffects::DamageCalcFromTarget.add(:FLUFFY,
proc { |ability, user, target, move, mults, baseDmg, type| proc { |ability, user, target, move, mults, baseDmg, type|
mults[:final_damage_multiplier] *= 2 if move.calcType == :FIRE 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 # @return [Boolean] whether this Pokémon has a particular nature or a nature
# at all # at all
def hasNature?(check_nature = nil) 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 return self.nature == check_nature
end end