mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-07 13:15:01 +00:00
Added AI handlers that calculate a move's base power, moved AI damage calculation
This commit is contained in:
@@ -73,14 +73,12 @@ module Battle::AI::Handlers
|
|||||||
# Move failure check
|
# Move failure check
|
||||||
|
|
||||||
def self.apply_move_effect_score(function_code, score, *args)
|
def self.apply_move_effect_score(function_code, score, *args)
|
||||||
function_code = function_code.to_sym
|
|
||||||
ret = MoveEffectScore.trigger(function_code, score, *args)
|
ret = MoveEffectScore.trigger(function_code, score, *args)
|
||||||
return (ret.nil?) ? score : ret
|
return (ret.nil?) ? score : ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get_base_power(function_code, power, *args)
|
def self.get_base_power(function_code, power, *args)
|
||||||
function_code = function_code.to_sym
|
ret = MoveBasePower.trigger(function_code, power, *args)
|
||||||
ret = MoveBasePower.trigger(function_code, *args)
|
|
||||||
return (ret.nil?) ? power : ret
|
return (ret.nil?) ? power : ret
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class Battle::AI
|
|||||||
choices.each_with_index do |c, i|
|
choices.each_with_index do |c, i|
|
||||||
logMsg += "#{battler.moves[c[0]].name}=#{c[1]}"
|
logMsg += "#{battler.moves[c[0]].name}=#{c[1]}"
|
||||||
logMsg += " (target #{c[2]})" if c[2] >= 0
|
logMsg += " (target #{c[2]})" if c[2] >= 0
|
||||||
logMsg += ", " if i < choices.length-1
|
logMsg += ", " if i < choices.length - 1
|
||||||
end
|
end
|
||||||
PBDebug.log(logMsg)
|
PBDebug.log(logMsg)
|
||||||
end
|
end
|
||||||
@@ -117,8 +117,8 @@ class Battle::AI
|
|||||||
score = pbGetStatusMoveBaseScore
|
score = pbGetStatusMoveBaseScore
|
||||||
end
|
end
|
||||||
# Modify the score according to the move's effect
|
# Modify the score according to the move's effect
|
||||||
score = Battle::AI::Handlers.apply_move_effect_score(@move.move.function,
|
score = Battle::AI::Handlers.apply_move_effect_score(@move.function,
|
||||||
score, @move.move, user_battler, target_battler, self, @battle)
|
score, @move, @user, @target, self, @battle)
|
||||||
|
|
||||||
# A score of 0 here means it absolutely should not be used
|
# A score of 0 here means it absolutely should not be used
|
||||||
return 0 if score <= 0
|
return 0 if score <= 0
|
||||||
@@ -327,8 +327,7 @@ class Battle::AI
|
|||||||
target_battler = @target.battler
|
target_battler = @target.battler
|
||||||
|
|
||||||
# Calculate how much damage the move will do (roughly)
|
# Calculate how much damage the move will do (roughly)
|
||||||
base_damage = @move.base_power
|
calc_damage = @move.rough_damage
|
||||||
calc_damage = pbRoughDamage(@move, @target, base_damage)
|
|
||||||
|
|
||||||
# TODO: Maybe move this check elsewhere? Note that Reborn's base score does
|
# TODO: Maybe move this check elsewhere? Note that Reborn's base score does
|
||||||
# not include this halving, but the predicted damage does.
|
# not include this halving, but the predicted damage does.
|
||||||
@@ -362,6 +361,9 @@ class Battle::AI
|
|||||||
return damage_percentage.to_i
|
return damage_percentage.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
#
|
||||||
|
#=============================================================================
|
||||||
def pbGetStatusMoveBaseScore
|
def pbGetStatusMoveBaseScore
|
||||||
# TODO: Call @target.immune_to_move? here too, not just for damaging moves
|
# TODO: Call @target.immune_to_move? here too, not just for damaging moves
|
||||||
# (only if this status move will be affected).
|
# (only if this status move will be affected).
|
||||||
|
|||||||
@@ -36,293 +36,6 @@ class Battle::AI
|
|||||||
return mod1 * mod2
|
return mod1 * mod2
|
||||||
end
|
end
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Damage calculation
|
|
||||||
#=============================================================================
|
|
||||||
def pbRoughDamage(move, target, baseDmg)
|
|
||||||
# Fixed damage moves
|
|
||||||
return baseDmg if move.move.is_a?(Battle::Move::FixedDamageMove)
|
|
||||||
|
|
||||||
user_battler = @user.battler
|
|
||||||
target_battler = target.battler
|
|
||||||
|
|
||||||
# Get the move's type
|
|
||||||
type = move.rough_type
|
|
||||||
|
|
||||||
##### Calculate user's attack stat #####
|
|
||||||
atk = @user.rough_stat(:ATTACK)
|
|
||||||
if move.move.function == "UseTargetAttackInsteadOfUserAttack" # Foul Play
|
|
||||||
atk = target.rough_stat(:ATTACK)
|
|
||||||
elsif move.move.function == "UseUserBaseDefenseInsteadOfUserBaseAttack" # Body Press
|
|
||||||
atk = @user.rough_stat(:DEFENSE)
|
|
||||||
elsif move.move.specialMove?(type)
|
|
||||||
if move.move.function == "UseTargetAttackInsteadOfUserAttack" # Foul Play
|
|
||||||
atk = target.rough_stat(:SPECIAL_ATTACK)
|
|
||||||
else
|
|
||||||
atk = @user.rough_stat(:SPECIAL_ATTACK)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
##### Calculate target's defense stat #####
|
|
||||||
defense = target.rough_stat(:DEFENSE)
|
|
||||||
if move.move.specialMove?(type) && move.move.function != "UseTargetDefenseInsteadOfTargetSpDef" # Psyshock
|
|
||||||
defense = target.rough_stat(:SPECIAL_DEFENSE)
|
|
||||||
end
|
|
||||||
|
|
||||||
##### Calculate all multiplier effects #####
|
|
||||||
multipliers = {
|
|
||||||
:base_damage_multiplier => 1.0,
|
|
||||||
:attack_multiplier => 1.0,
|
|
||||||
:defense_multiplier => 1.0,
|
|
||||||
:final_damage_multiplier => 1.0
|
|
||||||
}
|
|
||||||
# Ability effects that alter damage
|
|
||||||
moldBreaker = @trainer.high_skill? && target_battler.hasMoldBreaker?
|
|
||||||
|
|
||||||
if @user.ability_active?
|
|
||||||
# NOTE: These abilities aren't suitable for checking at the start of the
|
|
||||||
# round.
|
|
||||||
abilityBlacklist = [:ANALYTIC, :SNIPER, :TINTEDLENS, :AERILATE, :PIXILATE, :REFRIGERATE]
|
|
||||||
canCheck = true
|
|
||||||
abilityBlacklist.each do |m|
|
|
||||||
next if move.move.id != m
|
|
||||||
canCheck = false
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if canCheck
|
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromUser(
|
|
||||||
user_battler.ability, user_battler, target_battler, move.move, multipliers, baseDmg, type
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if @trainer.medium_skill? && !moldBreaker
|
|
||||||
user_battler.allAllies.each do |b|
|
|
||||||
next if !b.abilityActive?
|
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromAlly(
|
|
||||||
b.ability, user_battler, target_battler, move.move, multipliers, baseDmg, type
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if !moldBreaker && target.ability_active?
|
|
||||||
# NOTE: These abilities aren't suitable for checking at the start of the
|
|
||||||
# round.
|
|
||||||
abilityBlacklist = [:FILTER, :SOLIDROCK]
|
|
||||||
canCheck = true
|
|
||||||
abilityBlacklist.each do |m|
|
|
||||||
next if move.move.id != m
|
|
||||||
canCheck = false
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if canCheck
|
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromTarget(
|
|
||||||
target_battler.ability, user_battler, target_battler, move.move, multipliers, baseDmg, type
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if @trainer.high_skill? && !moldBreaker
|
|
||||||
target_battler.allAllies.each do |b|
|
|
||||||
next if !b.abilityActive?
|
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromTargetAlly(
|
|
||||||
b.ability, user_battler, target_battler, move.move, multipliers, baseDmg, type
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Item effects that alter damage
|
|
||||||
# NOTE: Type-boosting gems aren't suitable for checking at the start of the
|
|
||||||
# round.
|
|
||||||
if @user.item_active?
|
|
||||||
# NOTE: These items aren't suitable for checking at the start of the
|
|
||||||
# round.
|
|
||||||
itemBlacklist = [:EXPERTBELT, :LIFEORB]
|
|
||||||
if !itemBlacklist.include?(user_battler.item_id)
|
|
||||||
Battle::ItemEffects.triggerDamageCalcFromUser(
|
|
||||||
user_battler.item, user_battler, target_battler, move.move, multipliers, baseDmg, type
|
|
||||||
)
|
|
||||||
user_battler.effects[PBEffects::GemConsumed] = nil # Untrigger consuming of Gems
|
|
||||||
end
|
|
||||||
# TODO: Prefer (1.5x?) if item will be consumed and user has Unburden.
|
|
||||||
end
|
|
||||||
|
|
||||||
if target.item_active? && target_battler.item && !target_battler.item.is_berry?
|
|
||||||
Battle::ItemEffects.triggerDamageCalcFromTarget(
|
|
||||||
target_battler.item, user_battler, target_battler, move.move, multipliers, baseDmg, type
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Global abilities
|
|
||||||
if @trainer.medium_skill? &&
|
|
||||||
((@battle.pbCheckGlobalAbility(:DARKAURA) && type == :DARK) ||
|
|
||||||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && type == :FAIRY))
|
|
||||||
if @battle.pbCheckGlobalAbility(:AURABREAK)
|
|
||||||
multipliers[:base_damage_multiplier] *= 2 / 3.0
|
|
||||||
else
|
|
||||||
multipliers[:base_damage_multiplier] *= 4 / 3.0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Parental Bond
|
|
||||||
if @user.has_active_ability?(:PARENTALBOND)
|
|
||||||
multipliers[:base_damage_multiplier] *= 1.25
|
|
||||||
end
|
|
||||||
|
|
||||||
# Me First
|
|
||||||
# TODO
|
|
||||||
|
|
||||||
# Helping Hand - n/a
|
|
||||||
|
|
||||||
# Charge
|
|
||||||
if @trainer.medium_skill? &&
|
|
||||||
user_battler.effects[PBEffects::Charge] > 0 && type == :ELECTRIC
|
|
||||||
multipliers[:base_damage_multiplier] *= 2
|
|
||||||
end
|
|
||||||
|
|
||||||
# Mud Sport and Water Sport
|
|
||||||
if @trainer.medium_skill?
|
|
||||||
if type == :ELECTRIC
|
|
||||||
if @battle.allBattlers.any? { |b| b.effects[PBEffects::MudSport] }
|
|
||||||
multipliers[:base_damage_multiplier] /= 3
|
|
||||||
end
|
|
||||||
if @battle.field.effects[PBEffects::MudSportField] > 0
|
|
||||||
multipliers[:base_damage_multiplier] /= 3
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if type == :FIRE
|
|
||||||
if @battle.allBattlers.any? { |b| b.effects[PBEffects::WaterSport] }
|
|
||||||
multipliers[:base_damage_multiplier] /= 3
|
|
||||||
end
|
|
||||||
if @battle.field.effects[PBEffects::WaterSportField] > 0
|
|
||||||
multipliers[:base_damage_multiplier] /= 3
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Terrain moves
|
|
||||||
if @trainer.medium_skill?
|
|
||||||
case @battle.field.terrain
|
|
||||||
when :Electric
|
|
||||||
multipliers[:base_damage_multiplier] *= 1.5 if type == :ELECTRIC && user_battler.affectedByTerrain?
|
|
||||||
when :Grassy
|
|
||||||
multipliers[:base_damage_multiplier] *= 1.5 if type == :GRASS && user_battler.affectedByTerrain?
|
|
||||||
when :Psychic
|
|
||||||
multipliers[:base_damage_multiplier] *= 1.5 if type == :PSYCHIC && user_battler.affectedByTerrain?
|
|
||||||
when :Misty
|
|
||||||
multipliers[:base_damage_multiplier] /= 2 if type == :DRAGON && target_battler.affectedByTerrain?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Badge multipliers
|
|
||||||
if @trainer.high_skill? && @battle.internalBattle && target_battler.pbOwnedByPlayer?
|
|
||||||
# Don't need to check the Atk/Sp Atk-boosting badges because the AI
|
|
||||||
# won't control the player's Pokémon.
|
|
||||||
if move.move.physicalMove?(type) && @battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_DEFENSE
|
|
||||||
multipliers[:defense_multiplier] *= 1.1
|
|
||||||
elsif move.move.specialMove?(type) && @battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_SPDEF
|
|
||||||
multipliers[:defense_multiplier] *= 1.1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Multi-targeting attacks
|
|
||||||
if @trainer.high_skill? && move.targets_multiple_battlers?
|
|
||||||
multipliers[:final_damage_multiplier] *= 0.75
|
|
||||||
end
|
|
||||||
|
|
||||||
# Weather
|
|
||||||
if @trainer.medium_skill?
|
|
||||||
case user_battler.effectiveWeather
|
|
||||||
when :Sun, :HarshSun
|
|
||||||
case type
|
|
||||||
when :FIRE
|
|
||||||
multipliers[:final_damage_multiplier] *= 1.5
|
|
||||||
when :WATER
|
|
||||||
multipliers[:final_damage_multiplier] /= 2
|
|
||||||
end
|
|
||||||
when :Rain, :HeavyRain
|
|
||||||
case type
|
|
||||||
when :FIRE
|
|
||||||
multipliers[:final_damage_multiplier] /= 2
|
|
||||||
when :WATER
|
|
||||||
multipliers[:final_damage_multiplier] *= 1.5
|
|
||||||
end
|
|
||||||
when :Sandstorm
|
|
||||||
if target.has_type?(:ROCK) && move.move.specialMove?(type) &&
|
|
||||||
move.move.function != "UseTargetDefenseInsteadOfTargetSpDef" # Psyshock
|
|
||||||
multipliers[:defense_multiplier] *= 1.5
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Critical hits - n/a
|
|
||||||
|
|
||||||
# Random variance - n/a
|
|
||||||
|
|
||||||
# STAB
|
|
||||||
if type && @user.has_type?(type)
|
|
||||||
if @user.has_active_ability?(:ADAPTABILITY)
|
|
||||||
multipliers[:final_damage_multiplier] *= 2
|
|
||||||
else
|
|
||||||
multipliers[:final_damage_multiplier] *= 1.5
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Type effectiveness
|
|
||||||
typemod = target.effectiveness_of_type_against_battler(type, @user)
|
|
||||||
multipliers[:final_damage_multiplier] *= typemod.to_f / Effectiveness::NORMAL_EFFECTIVE
|
|
||||||
|
|
||||||
# Burn
|
|
||||||
if @trainer.high_skill? && move.move.physicalMove?(type) &&
|
|
||||||
user_battler.status == :BURN && !@user.has_active_ability?(:GUTS) &&
|
|
||||||
!(Settings::MECHANICS_GENERATION >= 6 &&
|
|
||||||
move.move.function == "DoublePowerIfUserPoisonedBurnedParalyzed") # Facade
|
|
||||||
multipliers[:final_damage_multiplier] /= 2
|
|
||||||
end
|
|
||||||
|
|
||||||
# Aurora Veil, Reflect, Light Screen
|
|
||||||
if @trainer.medium_skill? && !move.move.ignoresReflect? && !@user.has_active_ability?(:INFILTRATOR)
|
|
||||||
if target_battler.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
|
|
||||||
if @battle.pbSideBattlerCount(target_battler) > 1
|
|
||||||
multipliers[:final_damage_multiplier] *= 2 / 3.0
|
|
||||||
else
|
|
||||||
multipliers[:final_damage_multiplier] /= 2
|
|
||||||
end
|
|
||||||
elsif target_battler.pbOwnSide.effects[PBEffects::Reflect] > 0 && move.move.physicalMove?(type)
|
|
||||||
if @battle.pbSideBattlerCount(target_battler) > 1
|
|
||||||
multipliers[:final_damage_multiplier] *= 2 / 3.0
|
|
||||||
else
|
|
||||||
multipliers[:final_damage_multiplier] /= 2
|
|
||||||
end
|
|
||||||
elsif target_battler.pbOwnSide.effects[PBEffects::LightScreen] > 0 && move.move.specialMove?(type)
|
|
||||||
if @battle.pbSideBattlerCount(target_battler) > 1
|
|
||||||
multipliers[:final_damage_multiplier] *= 2 / 3.0
|
|
||||||
else
|
|
||||||
multipliers[:final_damage_multiplier] /= 2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Minimize
|
|
||||||
if @trainer.medium_skill? && target_battler.effects[PBEffects::Minimize] && move.move.tramplesMinimize?
|
|
||||||
multipliers[:final_damage_multiplier] *= 2
|
|
||||||
end
|
|
||||||
|
|
||||||
# Move-specific base damage modifiers
|
|
||||||
# TODO
|
|
||||||
|
|
||||||
# Move-specific final damage modifiers
|
|
||||||
# TODO
|
|
||||||
|
|
||||||
##### Main damage calculation #####
|
|
||||||
baseDmg = [(baseDmg * multipliers[:base_damage_multiplier]).round, 1].max
|
|
||||||
atk = [(atk * multipliers[:attack_multiplier]).round, 1].max
|
|
||||||
defense = [(defense * multipliers[:defense_multiplier]).round, 1].max
|
|
||||||
damage = ((((2.0 * user_battler.level / 5) + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
|
|
||||||
damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max
|
|
||||||
return damage.floor
|
|
||||||
end
|
|
||||||
|
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
# Check if battler has a move that meets the criteria in the block provided
|
# Check if battler has a move that meets the criteria in the block provided
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
|
|||||||
@@ -920,6 +920,11 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("LowerTargetDefense1PowersUpInGravity",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1PowersUpInGravity",
|
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1PowersUpInGravity",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if move.statusMove?
|
if move.statusMove?
|
||||||
@@ -1089,6 +1094,12 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed1",
|
|||||||
Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetSpeed1",
|
Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetSpeed1",
|
||||||
"LowerTargetSpeed1WeakerInGrassyTerrain")
|
"LowerTargetSpeed1WeakerInGrassyTerrain")
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("LowerTargetSpeed1WeakerInGrassyTerrain",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed1MakeTargetWeakerToFire",
|
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpeed1MakeTargetWeakerToFire",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next 0 if !target.battler.pbCanLowerStatStage?(:SPEED, user.battler) &&
|
next 0 if !target.battler.pbCanLowerStatStage?(:SPEED, user.battler) &&
|
||||||
@@ -1394,6 +1405,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserCopyTargetStatStages",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: Account for stat theft before damage calculation.
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserStealTargetPositiveStatStages",
|
Battle::AI::Handlers::MoveEffectScore.add("UserStealTargetPositiveStatStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
numStages = 0
|
numStages = 0
|
||||||
|
|||||||
@@ -297,6 +297,11 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfNotUserFirstTurn",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky",
|
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
score += 30 if !target.has_active_ability?(:INNERFOCUS) &&
|
score += 30 if !target.has_active_ability?(:INNERFOCUS) &&
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("FixedDamage20",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbFixedDamage(user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("FixedDamage20",
|
Battle::AI::Handlers::MoveEffectScore.add("FixedDamage20",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if target.hp <= 20
|
if target.hp <= 20
|
||||||
@@ -12,12 +17,22 @@ Battle::AI::Handlers::MoveEffectScore.add("FixedDamage20",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("FixedDamage40",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbFixedDamage(user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("FixedDamage40",
|
Battle::AI::Handlers::MoveEffectScore.add("FixedDamage40",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score + 80 if target.hp <= 40
|
next score + 80 if target.hp <= 40
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("FixedDamageHalfTargetHP",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbFixedDamage(user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageHalfTargetHP",
|
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageHalfTargetHP",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
score -= 50
|
score -= 50
|
||||||
@@ -25,18 +40,33 @@ Battle::AI::Handlers::MoveEffectScore.add("FixedDamageHalfTargetHP",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevel",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbFixedDamage(user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageUserLevel",
|
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageUserLevel",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score + 80 if target.hp <= user.level
|
next score + 80 if target.hp <= user.level
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevelRandom",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next user.level # Average power
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageUserLevelRandom",
|
Battle::AI::Handlers::MoveEffectScore.add("FixedDamageUserLevelRandom",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score + 30 if target.hp <= user.level
|
next score + 30 if target.hp <= user.level
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbFixedDamage(user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetHPToUserHP",
|
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetHPToUserHP",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if user.hp >= target.hp
|
if user.hp >= target.hp
|
||||||
@@ -48,6 +78,11 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetHPToUserHP",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("OHKO",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next 999
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("OHKO",
|
Battle::AI::Handlers::MoveEffectScore.add("OHKO",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next 0 if target.has_active_ability?(:STURDY)
|
next 0 if target.has_active_ability?(:STURDY)
|
||||||
@@ -55,6 +90,9 @@ Battle::AI::Handlers::MoveEffectScore.add("OHKO",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("OHKO",
|
||||||
|
"OHKOIce",
|
||||||
|
"OHKOHitsUndergroundTarget")
|
||||||
Battle::AI::Handlers::MoveEffectScore.copy("OHKO",
|
Battle::AI::Handlers::MoveEffectScore.copy("OHKO",
|
||||||
"OHKOIce",
|
"OHKOIce",
|
||||||
"OHKOHitsUndergroundTarget")
|
"OHKOHitsUndergroundTarget")
|
||||||
@@ -69,40 +107,70 @@ Battle::AI::Handlers::MoveEffectScore.add("DamageTargetAlly",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# PowerHigherWithUserHP
|
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithUserHP",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# PowerLowerWithUserHP
|
Battle::AI::Handlers::MoveBasePower.copy("PowerHigherWithUserHP",
|
||||||
|
"PowerLowerWithUserHP",
|
||||||
|
"PowerHigherWithTargetHP",
|
||||||
|
"PowerHigherWithUserHappiness",
|
||||||
|
"PowerLowerWithUserHappiness",
|
||||||
|
"PowerHigherWithUserPositiveStatStages",
|
||||||
|
"PowerHigherWithTargetPositiveStatStages",
|
||||||
|
"PowerHigherWithUserFasterThanTarget",
|
||||||
|
"PowerHigherWithTargetFasterThanUser")
|
||||||
|
|
||||||
# PowerHigherWithTargetHP
|
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithLessPP",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next 0 if move.move.pp == 0 && move.move.totalpp > 0
|
||||||
|
dmgs = [200, 80, 60, 50, 40]
|
||||||
|
ppLeft = [move.pp - 1, dmgs.length - 1].min
|
||||||
|
next dmgs[ppLeft]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# PowerHigherWithUserHappiness
|
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithTargetWeight",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# PowerLowerWithUserHappiness
|
Battle::AI::Handlers::MoveBasePower.copy("PowerHigherWithTargetWeight",
|
||||||
|
"PowerHigherWithUserHeavierThanTarget")
|
||||||
|
|
||||||
# PowerHigherWithUserPositiveStatStages
|
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithConsecutiveUse",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power << user.effects[PBEffects::FuryCutter]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# PowerHigherWithTargetPositiveStatStages
|
Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithConsecutiveUseOnUserSide",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * (user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter] + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# PowerHigherWithUserFasterThanTarget
|
Battle::AI::Handlers::MoveBasePower.add("RandomPowerDoublePowerIfTargetUnderground",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
power = 71 # Average damage
|
||||||
|
next move.pbModifyDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# PowerHigherWithTargetFasterThanUser
|
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetHPLessThanHalf",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# PowerHigherWithLessPP
|
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf",
|
||||||
|
"DoublePowerIfUserPoisonedBurnedParalyzed")
|
||||||
# PowerHigherWithTargetWeight
|
|
||||||
|
|
||||||
# PowerHigherWithUserHeavierThanTarget
|
|
||||||
|
|
||||||
# PowerHigherWithConsecutiveUse
|
|
||||||
|
|
||||||
# PowerHigherWithConsecutiveUseOnUserSide
|
|
||||||
|
|
||||||
# RandomPowerDoublePowerIfTargetUnderground
|
|
||||||
|
|
||||||
# DoublePowerIfTargetHPLessThanHalf
|
|
||||||
|
|
||||||
# DoublePowerIfUserPoisonedBurnedParalyzed
|
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf",
|
||||||
|
"DoublePowerIfTargetAsleepCureTarget")
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetAsleepCureTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetAsleepCureTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score - 20 if target.status == :SLEEP && # Will cure status
|
next score - 20 if target.status == :SLEEP && # Will cure status
|
||||||
@@ -110,33 +178,51 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetAsleepCureTarget",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# DoublePowerIfTargetPoisoned
|
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned",
|
||||||
|
"DoublePowerIfTargetParalyzedCureTarget")
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetParalyzedCureTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetParalyzedCureTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score - 20 if target.status == :PARALYSIS # Will cure status
|
next score - 20 if target.status == :PARALYSIS # Will cure status
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# DoublePowerIfTargetStatusProblem
|
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetStatusProblem",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
# DoublePowerIfUserHasNoItem
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
|
||||||
# DoublePowerIfTargetUnderwater
|
|
||||||
|
|
||||||
# DoublePowerIfTargetUnderground
|
|
||||||
|
|
||||||
# DoublePowerIfTargetInSky
|
|
||||||
|
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerInElectricTerrain",
|
|
||||||
proc { |score, move, user, target, ai, battle|
|
|
||||||
next score + 40 if battle.field.terrain == :Electric && target.battler.affectedByTerrain?
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
# DoublePowerIfUserLastMoveFailed
|
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfUserHasNoItem",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * 2 if !user.item || user.has_active_item?(:FLYINGGEM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# DoublePowerIfAllyFaintedLastTurn
|
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetUnderwater",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbModifyDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetUnderwater",
|
||||||
|
"DoublePowerIfTargetUnderground")
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetInSky",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetInSky",
|
||||||
|
"DoublePowerInElectricTerrain",
|
||||||
|
"DoublePowerIfUserLastMoveFailed",
|
||||||
|
"DoublePowerIfAllyFaintedLastTurn")
|
||||||
|
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn",
|
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
@@ -393,7 +479,23 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilHalfOfDamageDealt",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# EffectivenessIncludesFlyingType
|
Battle::AI::Handlers::MoveBasePower.add("EffectivenessIncludesFlyingType",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
if GameData::Type.exists?(:FLYING)
|
||||||
|
if ai.trainer.high_skill?
|
||||||
|
targetTypes = target.battler.pbTypes(true)
|
||||||
|
mult = Effectiveness.calculate(
|
||||||
|
:FLYING, targetTypes[0], targetTypes[1], targetTypes[2]
|
||||||
|
)
|
||||||
|
else
|
||||||
|
mult = Effectiveness.calculate(
|
||||||
|
:FLYING, target.types[0], target.types[1], target.effects[PBEffects::Type3]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
next (power.to_f * mult / Effectiveness::NORMAL_EFFECTIVE).round
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
@@ -446,8 +548,19 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndD
|
|||||||
|
|
||||||
# TypeIsUserFirstType
|
# TypeIsUserFirstType
|
||||||
|
|
||||||
# TypeDependsOnUserIVs
|
Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnUserBerry",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
# TODO: Can't this just call move.pbBaseDamage?
|
||||||
|
ret = move.pbNaturalGiftBaseDamage(user.item_id)
|
||||||
|
next (ret == 1) ? 0 : ret
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("TypeAndPowerDependOnUserBerry",
|
Battle::AI::Handlers::MoveEffectScore.add("TypeAndPowerDependOnUserBerry",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next 0 if !user.item || !user.item.is_berry? || !user.item_active?
|
next 0 if !user.item || !user.item.is_berry? || !user.item_active?
|
||||||
@@ -466,8 +579,14 @@ Battle::AI::Handlers::MoveEffectScore.add("TypeDependsOnUserMorpekoFormRaiseUser
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# TypeAndPowerDependOnWeather
|
Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnWeather",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("TypeAndPowerDependOnWeather",
|
||||||
|
"TypeAndPowerDependOnTerrain")
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("TypeAndPowerDependOnTerrain",
|
Battle::AI::Handlers::MoveEffectScore.add("TypeAndPowerDependOnTerrain",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score + 40 if battle.field.terrain != :None
|
next score + 40 if battle.field.terrain != :None
|
||||||
|
|||||||
@@ -2,8 +2,14 @@
|
|||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
|
||||||
# HitTwoTimes
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * move.pbNumHits(user.battler, [target.battler])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
|
||||||
|
"HitTwoTimesPoisonTarget")
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next 0 if !target.battler.pbCanPoison?(user.battler, false)
|
next 0 if !target.battler.pbCanPoison?(user.battler, false)
|
||||||
@@ -22,16 +28,31 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
|
||||||
|
"HitTwoTimesFlinchTarget")
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesFlinchTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesFlinchTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score + 30 if target.effects[PBEffects::Minimize]
|
next score + 30 if target.effects[PBEffects::Minimize]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# HitTwoTimesTargetThenTargetAlly
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoTimesTargetThenTargetAlly",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# HitThreeTimesPowersUpWithEachHit
|
Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * 6 # Hits do x1, x2, x3 ret in turn, for x6 in total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesAlwaysCriticalHit",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * move.pbNumHits(user.battler, [target.battler])
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesAlwaysCriticalHit",
|
Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesAlwaysCriticalHit",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.high_skill?
|
if ai.trainer.high_skill?
|
||||||
@@ -41,10 +62,29 @@ Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesAlwaysCriticalHit",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# HitTwoToFiveTimes
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * 5 if user.has_active_ability?(:SKILLLINK)
|
||||||
|
next power * 31 / 10 # Average damage dealt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# HitTwoToFiveTimesOrThreeForAshGreninja
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
if user.battler.isSpecies?(:GRENINJA) && user.battler.form == 2
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler) * move.pbNumHits(user.battler, [target.battler])
|
||||||
|
end
|
||||||
|
next power * 5 if user.has_active_ability?(:SKILLLINK)
|
||||||
|
next power * 31 / 10 # Average damage dealt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * 5 if user.has_active_ability?(:SKILLLINK)
|
||||||
|
next power * 31 / 10 # Average damage dealt
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
|
Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
aspeed = user.rough_stat(:SPEED)
|
aspeed = user.rough_stat(:SPEED)
|
||||||
@@ -59,13 +99,25 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUs
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# HitOncePerUserTeamMember
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
ret = 0
|
||||||
|
ai.battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i|
|
||||||
|
ret += 5 + (pkmn.baseStats[:ATTACK] / 10)
|
||||||
|
end
|
||||||
|
next ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# AttackAndSkipNextTurn
|
# AttackAndSkipNextTurn
|
||||||
|
|
||||||
# TwoTurnAttack
|
# TwoTurnAttack
|
||||||
|
|
||||||
# TwoTurnAttackOneTurnInSun
|
Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamageMultiplier(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
@@ -184,8 +236,17 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserSpAtk1",
|
|||||||
|
|
||||||
# MultiTurnAttackConfuseUserAtEnd
|
# MultiTurnAttackConfuseUserAtEnd
|
||||||
|
|
||||||
# MultiTurnAttackPowersUpEachTurn
|
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * 2 if user.effects[PBEffects::DefenseCurl]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next 40 # Representative value
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage",
|
Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if user.hp <= user.totalhp / 4
|
if user.hp <= user.totalhp / 4
|
||||||
|
|||||||
@@ -273,6 +273,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("UserFaintsPowersUpInMistyTerrainExplosive",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next power * 3 / 2 if battle.field.terrain == :Misty
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsPowersUpInMistyTerrainExplosive",
|
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsPowersUpInMistyTerrainExplosive",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
|
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
|
||||||
@@ -292,7 +297,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsPowersUpInMistyTerrainExplo
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# UserFaintsFixedDamageUserHP
|
Battle::AI::Handlers::MoveBasePower.add("UserFaintsFixedDamageUserHP",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next user.hp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsLowerTargetAtkSpAtk2",
|
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsLowerTargetAtkSpAtk2",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("RemoveTargetItem",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem",
|
Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.high_skill?
|
if ai.trainer.high_skill?
|
||||||
@@ -186,6 +191,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeTargetBerry",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("ThrowUserItemAtTarget",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("ThrowUserItemAtTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("ThrowUserItemAtTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next 0 if !user.item || !user.item_active? ||
|
next 0 if !user.item || !user.item_active? ||
|
||||||
|
|||||||
@@ -32,7 +32,11 @@ Battle::AI::Handlers::MoveEffectScore.add("CannotBeRedirected",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# RandomlyDamageOrHealTarget
|
Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next 50 # Average power, ish
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("HealAllyOrDamageFoe",
|
Battle::AI::Handlers::MoveEffectScore.add("HealAllyOrDamageFoe",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
@@ -73,6 +77,11 @@ Battle::AI::Handlers::MoveEffectScore.add("CurseTargetOrLowerUserSpd1RaiseUserAt
|
|||||||
|
|
||||||
# EffectDependsOnEnvironment
|
# EffectDependsOnEnvironment
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("HitsAllFoesAndPowersUpInPsychicTerrain",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain",
|
Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score + 40 if battle.field.terrain == :Psychic && user.battler.affectedByTerrain?
|
next score + 40 if battle.field.terrain == :Psychic && user.battler.affectedByTerrain?
|
||||||
@@ -103,6 +112,11 @@ Battle::AI::Handlers::MoveEffectScore.add("PowerUpAllyMove",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("CounterPhysicalDamage",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next 60 # Representative value
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage",
|
Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if target.effects[PBEffects::HyperBeam] > 0
|
if target.effects[PBEffects::HyperBeam] > 0
|
||||||
@@ -121,6 +135,11 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("CounterSpecialDamage",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next 60 # Representative value
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage",
|
Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if target.effects[PBEffects::HyperBeam] > 0
|
if target.effects[PBEffects::HyperBeam] > 0
|
||||||
@@ -139,6 +158,11 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("CounterDamagePlusHalf",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next 60 # Representative value
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf",
|
Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score - 90 if target.effects[PBEffects::HyperBeam] > 0
|
next score - 90 if target.effects[PBEffects::HyperBeam] > 0
|
||||||
@@ -161,6 +185,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("PowerDependsOnUserStockpile",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbBaseDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("PowerDependsOnUserStockpile",
|
Battle::AI::Handlers::MoveEffectScore.add("PowerDependsOnUserStockpile",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next 0 if user.effects[PBEffects::Stockpile] == 0
|
next 0 if user.effects[PBEffects::Stockpile] == 0
|
||||||
|
|||||||
@@ -115,6 +115,11 @@ Battle::AI::Handlers::MoveEffectScore.add("BindTarget",
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
next move.pbModifyDamage(power, user.battler, target.battler)
|
||||||
|
}
|
||||||
|
}
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater",
|
Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score + 40 if target.effects[PBEffects::Trapping] == 0
|
next score + 40 if target.effects[PBEffects::Trapping] == 0
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class Battle::AI::AIMove
|
|||||||
#=============================================================================
|
#=============================================================================
|
||||||
|
|
||||||
# pp
|
# pp
|
||||||
|
# totalpp
|
||||||
# priority
|
# priority
|
||||||
# usableWhenAsleep?
|
# usableWhenAsleep?
|
||||||
# thawsUser?
|
# thawsUser?
|
||||||
@@ -81,121 +82,281 @@ class Battle::AI::AIMove
|
|||||||
ret = @move.baseDamage
|
ret = @move.baseDamage
|
||||||
ret = 60 if ret == 1
|
ret = 60 if ret == 1
|
||||||
return ret if !@ai.trainer.medium_skill?
|
return ret if !@ai.trainer.medium_skill?
|
||||||
|
return Battle::AI::Handlers.get_base_power(function,
|
||||||
|
ret, self, @ai.user, @ai.target, @ai, @ai.battle)
|
||||||
|
end
|
||||||
|
|
||||||
|
def rough_damage
|
||||||
|
power = base_power
|
||||||
|
return power if @move.is_a?(Battle::Move::FixedDamageMove)
|
||||||
|
# Get the user and target of this move
|
||||||
user = @ai.user
|
user = @ai.user
|
||||||
user_battler = user.battler
|
user_battler = user.battler
|
||||||
target = @ai.target
|
target = @ai.target
|
||||||
target_battler = target.battler
|
target_battler = target.battler
|
||||||
# Covers all function codes which have their own def pbBaseDamage
|
|
||||||
case @move.function
|
# Get the move's type
|
||||||
when "FixedDamage20", "FixedDamage40", "FixedDamageHalfTargetHP",
|
calc_type = rough_type
|
||||||
"FixedDamageUserLevel", "LowerTargetHPToUserHP"
|
|
||||||
ret = @move.pbFixedDamage(user_battler, target_battler)
|
##### Calculate user's attack stat #####
|
||||||
when "FixedDamageUserLevelRandom"
|
atk = user.rough_stat(:ATTACK)
|
||||||
ret = user_battler.level
|
if function == "UseTargetAttackInsteadOfUserAttack" # Foul Play
|
||||||
when "OHKO", "OHKOIce", "OHKOHitsUndergroundTarget"
|
atk = target.rough_stat(:ATTACK)
|
||||||
ret = 200
|
elsif function == "UseUserBaseDefenseInsteadOfUserBaseAttack" # Body Press
|
||||||
when "CounterPhysicalDamage", "CounterSpecialDamage", "CounterDamagePlusHalf"
|
atk = user.rough_stat(:DEFENSE)
|
||||||
ret = 60
|
elsif specialMove?(calc_type)
|
||||||
when "DoublePowerIfTargetUnderwater", "DoublePowerIfTargetUnderground",
|
if function == "UseTargetAttackInsteadOfUserAttack" # Foul Play
|
||||||
"BindTargetDoublePowerIfTargetUnderwater"
|
atk = target.rough_stat(:SPECIAL_ATTACK)
|
||||||
ret = @move.pbModifyDamage(ret, user_battler, target_battler)
|
|
||||||
when "DoublePowerIfTargetInSky",
|
|
||||||
"FlinchTargetDoublePowerIfTargetInSky",
|
|
||||||
"DoublePowerIfTargetPoisoned",
|
|
||||||
"DoublePowerIfTargetParalyzedCureTarget",
|
|
||||||
"DoublePowerIfTargetAsleepCureTarget",
|
|
||||||
"DoublePowerIfUserPoisonedBurnedParalyzed",
|
|
||||||
"DoublePowerIfTargetStatusProblem",
|
|
||||||
"DoublePowerIfTargetHPLessThanHalf",
|
|
||||||
"DoublePowerIfAllyFaintedLastTurn",
|
|
||||||
"TypeAndPowerDependOnWeather",
|
|
||||||
"PowerHigherWithUserHappiness",
|
|
||||||
"PowerLowerWithUserHappiness",
|
|
||||||
"PowerHigherWithUserHP",
|
|
||||||
"PowerHigherWithTargetHP",
|
|
||||||
"PowerHigherWithUserPositiveStatStages",
|
|
||||||
"PowerHigherWithTargetPositiveStatStages",
|
|
||||||
"TypeDependsOnUserIVs",
|
|
||||||
"PowerHigherWithConsecutiveUse",
|
|
||||||
"PowerHigherWithConsecutiveUseOnUserSide",
|
|
||||||
"PowerHigherWithLessPP",
|
|
||||||
"PowerLowerWithUserHP",
|
|
||||||
"PowerHigherWithUserFasterThanTarget",
|
|
||||||
"PowerHigherWithTargetWeight",
|
|
||||||
"ThrowUserItemAtTarget",
|
|
||||||
"PowerDependsOnUserStockpile"
|
|
||||||
ret = @move.pbBaseDamage(ret, user_battler, target_battler)
|
|
||||||
when "DoublePowerIfUserHasNoItem"
|
|
||||||
ret *= 2 if !user_battler.item || user.has_active_item?(:FLYINGGEM)
|
|
||||||
when "PowerHigherWithTargetFasterThanUser"
|
|
||||||
targetSpeed = target.rough_stat(:SPEED)
|
|
||||||
userSpeed = user.rough_stat(:SPEED)
|
|
||||||
ret = [[(25 * targetSpeed / userSpeed).floor, 150].min, 1].max
|
|
||||||
when "RandomlyDamageOrHealTarget"
|
|
||||||
ret = 50
|
|
||||||
when "RandomPowerDoublePowerIfTargetUnderground"
|
|
||||||
ret = 71
|
|
||||||
ret *= 2 if target_battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderground") # Dig
|
|
||||||
when "TypeAndPowerDependOnUserBerry"
|
|
||||||
ret = @move.pbNaturalGiftBaseDamage(user_battler.item_id)
|
|
||||||
when "PowerHigherWithUserHeavierThanTarget"
|
|
||||||
ret = @move.pbBaseDamage(ret, user_battler, target_battler)
|
|
||||||
ret *= 2 if Settings::MECHANICS_GENERATION >= 7 && @trainer.medium_skill? &&
|
|
||||||
target_battler.effects[PBEffects::Minimize]
|
|
||||||
when "AlwaysCriticalHit", "HitTwoTimes", "HitTwoTimesPoisonTarget"
|
|
||||||
ret *= 2
|
|
||||||
when "HitThreeTimesPowersUpWithEachHit"
|
|
||||||
ret *= 6 # Hits do x1, x2, x3 ret in turn, for x6 in total
|
|
||||||
when "HitTwoToFiveTimes"
|
|
||||||
if user.has_active_ability?(:SKILLLINK)
|
|
||||||
ret *= 5
|
|
||||||
else
|
else
|
||||||
ret = (ret * 31 / 10).floor # Average damage dealt
|
atk = user.rough_stat(:SPECIAL_ATTACK)
|
||||||
end
|
end
|
||||||
when "HitTwoToFiveTimesOrThreeForAshGreninja"
|
|
||||||
if user_battler.isSpecies?(:GRENINJA) && user_battler.form == 2
|
|
||||||
ret *= 4 # 3 hits at 20 power = 4 hits at 15 power
|
|
||||||
elsif user.has_active_ability?(:SKILLLINK)
|
|
||||||
ret *= 5
|
|
||||||
else
|
|
||||||
ret = (ret * 31 / 10).floor # Average damage dealt
|
|
||||||
end
|
|
||||||
when "HitOncePerUserTeamMember"
|
|
||||||
mult = 0
|
|
||||||
@ai.battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i|
|
|
||||||
mult += 1 if pkmn&.able? && pkmn.status == :NONE
|
|
||||||
end
|
|
||||||
ret *= mult
|
|
||||||
when "TwoTurnAttackOneTurnInSun"
|
|
||||||
ret = @move.pbBaseDamageMultiplier(ret, user_battler, target_battler)
|
|
||||||
when "MultiTurnAttackPowersUpEachTurn"
|
|
||||||
ret *= 2 if user_battler.effects[PBEffects::DefenseCurl]
|
|
||||||
when "MultiTurnAttackBideThenReturnDoubleDamage"
|
|
||||||
ret = 40
|
|
||||||
when "UserFaintsFixedDamageUserHP"
|
|
||||||
ret = user_battler.hp
|
|
||||||
when "EffectivenessIncludesFlyingType"
|
|
||||||
if GameData::Type.exists?(:FLYING)
|
|
||||||
if @trainer.high_skill?
|
|
||||||
targetTypes = target_battler.pbTypes(true)
|
|
||||||
mult = Effectiveness.calculate(
|
|
||||||
:FLYING, targetTypes[0], targetTypes[1], targetTypes[2]
|
|
||||||
)
|
|
||||||
else
|
|
||||||
mult = Effectiveness.calculate(
|
|
||||||
:FLYING, target.types[0], target.types[1], target.effects[PBEffects::Type3]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
ret = (ret.to_f * mult / Effectiveness::NORMAL_EFFECTIVE).round
|
|
||||||
end
|
|
||||||
ret *= 2 if @trainer.medium_skill? && target_battler.effects[PBEffects::Minimize]
|
|
||||||
when "DoublePowerIfUserLastMoveFailed"
|
|
||||||
ret *= 2 if user_battler.lastRoundMoveFailed
|
|
||||||
when "HitTwoTimesFlinchTarget"
|
|
||||||
ret *= 2
|
|
||||||
ret *= 2 if @trainer.medium_skill? && target_battler.effects[PBEffects::Minimize]
|
|
||||||
end
|
end
|
||||||
return ret
|
|
||||||
|
##### Calculate target's defense stat #####
|
||||||
|
defense = target.rough_stat(:DEFENSE)
|
||||||
|
if specialMove?(calc_type) && function != "UseTargetDefenseInsteadOfTargetSpDef" # Psyshock
|
||||||
|
defense = target.rough_stat(:SPECIAL_DEFENSE)
|
||||||
|
end
|
||||||
|
|
||||||
|
##### Calculate all multiplier effects #####
|
||||||
|
multipliers = {
|
||||||
|
:base_damage_multiplier => 1.0,
|
||||||
|
:attack_multiplier => 1.0,
|
||||||
|
:defense_multiplier => 1.0,
|
||||||
|
:final_damage_multiplier => 1.0
|
||||||
|
}
|
||||||
|
# Ability effects that alter damage
|
||||||
|
moldBreaker = @ai.trainer.high_skill? && target_battler.hasMoldBreaker?
|
||||||
|
|
||||||
|
if user.ability_active?
|
||||||
|
# NOTE: These abilities aren't suitable for checking at the start of the
|
||||||
|
# round.
|
||||||
|
abilityBlacklist = [:ANALYTIC, :SNIPER, :TINTEDLENS, :AERILATE, :PIXILATE, :REFRIGERATE]
|
||||||
|
if !abilityBlacklist.include?(user.ability_id)
|
||||||
|
Battle::AbilityEffects.triggerDamageCalcFromUser(
|
||||||
|
user.ability, user_battler, target_battler, @move, multipliers, power, calc_type
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if @ai.trainer.medium_skill? && !moldBreaker
|
||||||
|
user_battler.allAllies.each do |b|
|
||||||
|
next if !b.abilityActive?
|
||||||
|
Battle::AbilityEffects.triggerDamageCalcFromAlly(
|
||||||
|
b.ability, user_battler, target_battler, @move, multipliers, power, calc_type
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if !moldBreaker && target.ability_active?
|
||||||
|
# NOTE: These abilities aren't suitable for checking at the start of the
|
||||||
|
# round.
|
||||||
|
abilityBlacklist = [:FILTER, :SOLIDROCK]
|
||||||
|
if !abilityBlacklist.include?(target.ability_id)
|
||||||
|
Battle::AbilityEffects.triggerDamageCalcFromTarget(
|
||||||
|
target.ability, user_battler, target_battler, @move, multipliers, power, calc_type
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if @ai.trainer.high_skill? && !moldBreaker
|
||||||
|
target_battler.allAllies.each do |b|
|
||||||
|
next if !b.abilityActive?
|
||||||
|
Battle::AbilityEffects.triggerDamageCalcFromTargetAlly(
|
||||||
|
b.ability, user_battler, target_battler, @move, multipliers, power, calc_type
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Item effects that alter damage
|
||||||
|
# NOTE: Type-boosting gems aren't suitable for checking at the start of the
|
||||||
|
# round.
|
||||||
|
if user.item_active?
|
||||||
|
# NOTE: These items aren't suitable for checking at the start of the
|
||||||
|
# round.
|
||||||
|
itemBlacklist = [:EXPERTBELT, :LIFEORB]
|
||||||
|
if !itemBlacklist.include?(user.item_id)
|
||||||
|
Battle::ItemEffects.triggerDamageCalcFromUser(
|
||||||
|
user.item, user_battler, target_battler, @move, multipliers, power, calc_type
|
||||||
|
)
|
||||||
|
user.effects[PBEffects::GemConsumed] = nil # Untrigger consuming of Gems
|
||||||
|
end
|
||||||
|
# TODO: Prefer (1.5x?) if item will be consumed and user has Unburden.
|
||||||
|
end
|
||||||
|
|
||||||
|
if target.item_active? && target.item && !target.item.is_berry?
|
||||||
|
Battle::ItemEffects.triggerDamageCalcFromTarget(
|
||||||
|
target.item, user_battler, target_battler, @move, multipliers, power, calc_type
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Global abilities
|
||||||
|
if @ai.trainer.medium_skill? &&
|
||||||
|
((@ai.battle.pbCheckGlobalAbility(:DARKAURA) && calc_type == :DARK) ||
|
||||||
|
(@ai.battle.pbCheckGlobalAbility(:FAIRYAURA) && calc_type == :FAIRY))
|
||||||
|
if @ai.battle.pbCheckGlobalAbility(:AURABREAK)
|
||||||
|
multipliers[:base_damage_multiplier] *= 2 / 3.0
|
||||||
|
else
|
||||||
|
multipliers[:base_damage_multiplier] *= 4 / 3.0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parental Bond
|
||||||
|
if user.has_active_ability?(:PARENTALBOND)
|
||||||
|
multipliers[:base_damage_multiplier] *= 1.25
|
||||||
|
end
|
||||||
|
|
||||||
|
# Me First
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
# Helping Hand - n/a
|
||||||
|
|
||||||
|
# Charge
|
||||||
|
if @ai.trainer.medium_skill? &&
|
||||||
|
user.effects[PBEffects::Charge] > 0 && calc_type == :ELECTRIC
|
||||||
|
multipliers[:base_damage_multiplier] *= 2
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mud Sport and Water Sport
|
||||||
|
if @ai.trainer.medium_skill?
|
||||||
|
if calc_type == :ELECTRIC
|
||||||
|
if @ai.battle.allBattlers.any? { |b| b.effects[PBEffects::MudSport] }
|
||||||
|
multipliers[:base_damage_multiplier] /= 3
|
||||||
|
end
|
||||||
|
if @ai.battle.field.effects[PBEffects::MudSportField] > 0
|
||||||
|
multipliers[:base_damage_multiplier] /= 3
|
||||||
|
end
|
||||||
|
elsif calc_type == :FIRE
|
||||||
|
if @ai.battle.allBattlers.any? { |b| b.effects[PBEffects::WaterSport] }
|
||||||
|
multipliers[:base_damage_multiplier] /= 3
|
||||||
|
end
|
||||||
|
if @ai.battle.field.effects[PBEffects::WaterSportField] > 0
|
||||||
|
multipliers[:base_damage_multiplier] /= 3
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Terrain moves
|
||||||
|
if @ai.trainer.medium_skill?
|
||||||
|
case @ai.battle.field.terrain
|
||||||
|
when :Electric
|
||||||
|
multipliers[:base_damage_multiplier] *= 1.5 if calc_type == :ELECTRIC && user_battler.affectedByTerrain?
|
||||||
|
when :Grassy
|
||||||
|
multipliers[:base_damage_multiplier] *= 1.5 if calc_type == :GRASS && user_battler.affectedByTerrain?
|
||||||
|
when :Psychic
|
||||||
|
multipliers[:base_damage_multiplier] *= 1.5 if calc_type == :PSYCHIC && user_battler.affectedByTerrain?
|
||||||
|
when :Misty
|
||||||
|
multipliers[:base_damage_multiplier] /= 2 if calc_type == :DRAGON && target_battler.affectedByTerrain?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Badge multipliers
|
||||||
|
if @ai.trainer.high_skill? && @ai.battle.internalBattle && target_battler.pbOwnedByPlayer?
|
||||||
|
# Don't need to check the Atk/Sp Atk-boosting badges because the AI
|
||||||
|
# won't control the player's Pokémon.
|
||||||
|
if physicalMove?(calc_type) && @ai.battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_DEFENSE
|
||||||
|
multipliers[:defense_multiplier] *= 1.1
|
||||||
|
elsif specialMove?(calc_type) && @ai.battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_SPDEF
|
||||||
|
multipliers[:defense_multiplier] *= 1.1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Multi-targeting attacks
|
||||||
|
if @ai.trainer.high_skill? && targets_multiple_battlers?
|
||||||
|
multipliers[:final_damage_multiplier] *= 0.75
|
||||||
|
end
|
||||||
|
|
||||||
|
# Weather
|
||||||
|
if @ai.trainer.medium_skill?
|
||||||
|
case user_battler.effectiveWeather
|
||||||
|
when :Sun, :HarshSun
|
||||||
|
case calc_type
|
||||||
|
when :FIRE
|
||||||
|
multipliers[:final_damage_multiplier] *= 1.5
|
||||||
|
when :WATER
|
||||||
|
multipliers[:final_damage_multiplier] /= 2
|
||||||
|
end
|
||||||
|
when :Rain, :HeavyRain
|
||||||
|
case calc_type
|
||||||
|
when :FIRE
|
||||||
|
multipliers[:final_damage_multiplier] /= 2
|
||||||
|
when :WATER
|
||||||
|
multipliers[:final_damage_multiplier] *= 1.5
|
||||||
|
end
|
||||||
|
when :Sandstorm
|
||||||
|
if target.has_type?(:ROCK) && specialMove?(calc_type) &&
|
||||||
|
function != "UseTargetDefenseInsteadOfTargetSpDef" # Psyshock
|
||||||
|
multipliers[:defense_multiplier] *= 1.5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Critical hits - n/a
|
||||||
|
|
||||||
|
# Random variance - n/a
|
||||||
|
|
||||||
|
# STAB
|
||||||
|
if calc_type && user.has_type?(calc_type)
|
||||||
|
if user.has_active_ability?(:ADAPTABILITY)
|
||||||
|
multipliers[:final_damage_multiplier] *= 2
|
||||||
|
else
|
||||||
|
multipliers[:final_damage_multiplier] *= 1.5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Type effectiveness
|
||||||
|
typemod = target.effectiveness_of_type_against_battler(calc_type, user)
|
||||||
|
multipliers[:final_damage_multiplier] *= typemod.to_f / Effectiveness::NORMAL_EFFECTIVE
|
||||||
|
|
||||||
|
# Burn
|
||||||
|
if @ai.trainer.high_skill? && physicalMove?(calc_type) &&
|
||||||
|
user.status == :BURN && !user.has_active_ability?(:GUTS) &&
|
||||||
|
!(Settings::MECHANICS_GENERATION >= 6 &&
|
||||||
|
function == "DoublePowerIfUserPoisonedBurnedParalyzed") # Facade
|
||||||
|
multipliers[:final_damage_multiplier] /= 2
|
||||||
|
end
|
||||||
|
|
||||||
|
# Aurora Veil, Reflect, Light Screen
|
||||||
|
if @ai.trainer.medium_skill? && !@move.ignoresReflect? && !user.has_active_ability?(:INFILTRATOR)
|
||||||
|
if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
|
||||||
|
if @ai.battle.pbSideBattlerCount(target_battler) > 1
|
||||||
|
multipliers[:final_damage_multiplier] *= 2 / 3.0
|
||||||
|
else
|
||||||
|
multipliers[:final_damage_multiplier] /= 2
|
||||||
|
end
|
||||||
|
elsif target.pbOwnSide.effects[PBEffects::Reflect] > 0 && physicalMove?(calc_type)
|
||||||
|
if @ai.battle.pbSideBattlerCount(target_battler) > 1
|
||||||
|
multipliers[:final_damage_multiplier] *= 2 / 3.0
|
||||||
|
else
|
||||||
|
multipliers[:final_damage_multiplier] /= 2
|
||||||
|
end
|
||||||
|
elsif target.pbOwnSide.effects[PBEffects::LightScreen] > 0 && specialMove?(calc_type)
|
||||||
|
if @ai.battle.pbSideBattlerCount(target_battler) > 1
|
||||||
|
multipliers[:final_damage_multiplier] *= 2 / 3.0
|
||||||
|
else
|
||||||
|
multipliers[:final_damage_multiplier] /= 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Minimize
|
||||||
|
if @ai.trainer.medium_skill? && target.effects[PBEffects::Minimize] && @move.tramplesMinimize?
|
||||||
|
multipliers[:final_damage_multiplier] *= 2
|
||||||
|
end
|
||||||
|
|
||||||
|
# Move-specific base damage modifiers
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
# Move-specific final damage modifiers
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
##### Main damage calculation #####
|
||||||
|
power = [(power * multipliers[:base_damage_multiplier]).round, 1].max
|
||||||
|
atk = [(atk * multipliers[:attack_multiplier]).round, 1].max
|
||||||
|
defense = [(defense * multipliers[:defense_multiplier]).round, 1].max
|
||||||
|
damage = ((((2.0 * user.level / 5) + 2).floor * power * atk / defense).floor / 50).floor + 2
|
||||||
|
damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max
|
||||||
|
return damage.floor
|
||||||
end
|
end
|
||||||
|
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user