mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
AI function code rewrites, added Shadow Sky's missing effects, fixed Shadow End's recoil damage
This commit is contained in:
@@ -750,7 +750,7 @@ module GameData
|
||||
when "12F" then new_code = "TrapTargetInBattle"
|
||||
when "130" then new_code = "UserLosesHalfHP"
|
||||
when "131" then new_code = "StartShadowSkyWeather"
|
||||
when "132" then new_code = "RemoveAllScreens"
|
||||
when "132" then new_code = "RemoveAllScreensAndSafeguard"
|
||||
when "133" then new_code = "DoesNothingFailsIfNoAlly"
|
||||
when "134" then new_code = "DoesNothingCongratulations"
|
||||
when "135" then new_code = "FreezeTargetSuperEffectiveAgainstWater"
|
||||
|
||||
@@ -423,6 +423,8 @@ class Battle::Move
|
||||
if target.pbHasType?(:ROCK) && specialMove? && @function != "UseTargetDefenseInsteadOfTargetSpDef"
|
||||
multipliers[:defense_multiplier] *= 1.5
|
||||
end
|
||||
when :ShadowSky
|
||||
multipliers[:final_damage_multiplier] *= 1.5 if type == :SHADOW
|
||||
end
|
||||
# Critical hits
|
||||
if target.damageState.critical
|
||||
|
||||
@@ -839,9 +839,9 @@ class Battle::Move::RemoveScreens < Battle::Move
|
||||
end
|
||||
|
||||
def pbShowAnimation(id, user, targets, hitNum = 0, showAnimation = true)
|
||||
if user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::Reflect] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0
|
||||
if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::Reflect] > 0
|
||||
hitNum = 1 # Wall-breaking anim
|
||||
end
|
||||
super
|
||||
@@ -1540,6 +1540,8 @@ class Battle::Move::TypeAndPowerDependOnWeather < Battle::Move
|
||||
ret = :ROCK if GameData::Type.exists?(:ROCK)
|
||||
when :Hail
|
||||
ret = :ICE if GameData::Type.exists?(:ICE)
|
||||
when :ShadowSky
|
||||
ret = :NONE
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
@@ -109,8 +109,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfUserDamagedThisTu
|
||||
# Check whether user is faster than its foe(s) and could use this move
|
||||
user_faster_count = 0
|
||||
foe_faster_count = 0
|
||||
ai.battlers.each_with_index do |b, i|
|
||||
next if !user.opposes?(b) || b.battler.fainted?
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
if user.faster_than?(b)
|
||||
user_faster_count += 1
|
||||
else
|
||||
@@ -121,10 +120,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfUserDamagedThisTu
|
||||
score += 10 if foe_faster_count == 0
|
||||
# Effects that make the target unlikely to act before the user
|
||||
if ai.trainer.high_skill?
|
||||
if target.effects[PBEffects::HyperBeam] > 0 ||
|
||||
target.effects[PBEffects::Truant] ||
|
||||
(target.battler.asleep? && target.statusCount > 1) ||
|
||||
target.battler.frozen?
|
||||
if !target.can_attack?
|
||||
score += 20
|
||||
elsif target.effects[PBEffects::Confusion] > 1 ||
|
||||
target.effects[PBEffects::Attract] == user.index
|
||||
@@ -183,8 +179,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
|
||||
score += 15 if user.has_active_item?(:HEATROCK)
|
||||
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
|
||||
# Check for Fire/Water moves
|
||||
ai.battlers.each do |b|
|
||||
next if !b || b.battler.fainted?
|
||||
ai.each_battler do |b, i|
|
||||
if b.has_damaging_move_of_type?(:FIRE)
|
||||
score += (b.opposes?(user)) ? -15 : 15
|
||||
end
|
||||
@@ -229,8 +224,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
|
||||
score += 15 if user.has_active_item?(:DAMPROCK)
|
||||
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
|
||||
# Check for Fire/Water moves
|
||||
ai.battlers.each do |b|
|
||||
next if !b || b.battler.fainted?
|
||||
ai.each_battler do |b, i|
|
||||
if b.has_damaging_move_of_type?(:WATER)
|
||||
score += (b.opposes?(user)) ? -15 : 15
|
||||
end
|
||||
@@ -271,8 +265,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather",
|
||||
score += 15 if user.has_active_item?(:SMOOTHROCK)
|
||||
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
|
||||
# Check for battlers affected by sandstorm's effects
|
||||
ai.battlers.each do |b|
|
||||
next if !b || b.battler.fainted?
|
||||
ai.each_battler do |b, i|
|
||||
if b.battler.takesSandstormDamage? # End of round damage
|
||||
score += (b.opposes?(user)) ? 15 : -15
|
||||
end
|
||||
@@ -312,8 +305,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather",
|
||||
score += 15 if user.has_active_item?(:ICYROCK)
|
||||
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
|
||||
# Check for battlers affected by hail's effects
|
||||
ai.battlers.each do |b|
|
||||
next if !b || b.battler.fainted?
|
||||
ai.each_battler do |b, i|
|
||||
if b.battler.takesHailDamage? # End of round damage
|
||||
score += (b.opposes?(user)) ? 15 : -15
|
||||
end
|
||||
@@ -667,9 +659,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserSwapsPositionsWithAlly",
|
||||
proc { |move, user, ai, battle|
|
||||
num_targets = 0
|
||||
idxUserOwner = battle.pbGetOwnerIndexFromBattlerIndex(user.index)
|
||||
user.battler.allAllies.each do |b|
|
||||
ai.each_ally(user.side) do |b, i|
|
||||
next if battle.pbGetOwnerIndexFromBattlerIndex(b.index) != idxUserOwner
|
||||
next if !b.near?(user)
|
||||
next if !b.battler.near?(user.battler)
|
||||
num_targets += 1
|
||||
end
|
||||
next num_targets != 1
|
||||
@@ -686,8 +678,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserSwapsPositionsWithAlly",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("BurnAttackerBeforeUserActs",
|
||||
proc { |score, move, user, ai, battle|
|
||||
ai.battlers.each do |b|
|
||||
next if !b || !b.opposes?(user)
|
||||
ai.each_foe_battler(user.side) do |b|
|
||||
next if !b.battler.affectedByContactEffect?
|
||||
next if !b.battler.pbCanBurn?(user.battler, false, move.move)
|
||||
if ai.trainer.high_skill?
|
||||
@@ -700,31 +691,43 @@ Battle::AI::Handlers::MoveEffectScore.add("BurnAttackerBeforeUserActs",
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next target.hp <= 1
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score += 20 if target.hp >= target.totalhp / 2
|
||||
Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# HP halving
|
||||
foe_hp_lost = 0
|
||||
ally_hp_lost = 0
|
||||
ai.each_battler do |b, i|
|
||||
next if b.hp == 1
|
||||
if b.battler.opposes?(user.battler)
|
||||
foe_hp_lost += b.hp / 2
|
||||
else
|
||||
ally_hp_lost += b.hp / 2
|
||||
end
|
||||
end
|
||||
score += 15 * foe_hp_lost / ally_hp_lost
|
||||
score -= 15 * ally_hp_lost / foe_hp_lost
|
||||
# Recharging
|
||||
score = Battle::AI::Handlers.apply_move_effect_score("AttackAndSkipNextTurn",
|
||||
score, move, user, ai, battle)
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP",
|
||||
proc { |score, move, user, ai, battle|
|
||||
next score - 40
|
||||
score = Battle::AI::Handlers.apply_move_effect_score("UserLosesHalfOfTotalHP",
|
||||
score, move, user, ai, battle)
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
|
||||
"StartShadowSkyWeather")
|
||||
@@ -734,39 +737,64 @@ Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather",
|
||||
battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score += 10 if battle.field.weather != :None # Prefer replacing another weather
|
||||
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
|
||||
# Check for battlers affected by Shadow Sky's effects
|
||||
ai.each_battler do |b, i|
|
||||
if b.has_damaging_move_of_type?(:SHADOW)
|
||||
score += (b.opposes?(user)) ? 15 : -15
|
||||
end
|
||||
if b.battler.takesShadowSkyDamage? # End of round damage
|
||||
score += (b.opposes?(user)) ? 15 : -15
|
||||
end
|
||||
end
|
||||
# Check for moves affected by Shadow Sky
|
||||
# TODO: Check other battlers for these as well?
|
||||
if ai.trainer.medium_skill? && !user.has_active_item?(:UTILITYUMBRELLA)
|
||||
if user.has_move_with_function?("TypeAndPowerDependOnWeather")
|
||||
score += 10
|
||||
end
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens",
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreensAndSafeguard",
|
||||
proc { |move, user, ai, battle|
|
||||
will_fail = true
|
||||
battle.sides.each do |side|
|
||||
will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 ||
|
||||
side.effects[PBEffects::Reflect] > 0 ||
|
||||
side.effects[PBEffects::LightScreen] > 0 ||
|
||||
side.effects[PBEffects::Reflect] > 0 ||
|
||||
side.effects[PBEffects::Safeguard] > 0
|
||||
end
|
||||
next will_fail
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("RemoveAllScreens",
|
||||
Battle::AI::Handlers::MoveEffectScore.add("RemoveAllScreensAndSafeguard",
|
||||
proc { |score, move, user, ai, battle|
|
||||
if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::Reflect] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::Safeguard] > 0
|
||||
score += 30
|
||||
foe_side = user.pbOpposingSide
|
||||
# Useless if the foe's side has no screens/Safeguard to remove, or if
|
||||
# they'll end this round anyway
|
||||
if foe_side.effects[PBEffects::AuroraVeil] <= 1 &&
|
||||
foe_side.effects[PBEffects::LightScreen] <= 1 &&
|
||||
foe_side.effects[PBEffects::Reflect] <= 1 &&
|
||||
foe_side.effects[PBEffects::Safeguard] <= 1
|
||||
next Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 ||
|
||||
user.pbOwnSide.effects[PBEffects::Reflect] > 0 ||
|
||||
user.pbOwnSide.effects[PBEffects::LightScreen] > 0 ||
|
||||
user.pbOwnSide.effects[PBEffects::Safeguard] > 0
|
||||
score -= 70
|
||||
# Prefer removing opposing screens
|
||||
score = Battle::AI::Handlers.apply_move_effect_score("RemoveScreens",
|
||||
score, move, user, ai, battle)
|
||||
# Don't prefer removing same side screens
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
score -= Battle::AI::Handlers.apply_move_effect_score("RemoveScreens",
|
||||
0, move, b, ai, battle)
|
||||
break
|
||||
end
|
||||
# Safeguard
|
||||
score += 10 if foe_side.effects[PBEffects::Safeguard] > 0
|
||||
score -= 10 if user.pbOwnSide.effects[PBEffects::Safeguard] > 0
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
@@ -371,9 +371,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Prefer if user is slower than its foe(s) and the foe(s) can attack
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if user.faster_than?(b) || (b.status == :SLEEP && b.statusCount > 1) ||
|
||||
b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 ||
|
||||
b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0
|
||||
next if user.faster_than?(b) || !b.can_attack?
|
||||
score += 4
|
||||
end
|
||||
next score
|
||||
@@ -388,9 +386,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostH
|
||||
# Prefer if a user's ally is faster than the user and that ally can attack
|
||||
ai.each_foe_battler(target.side) do |b, i|
|
||||
next if i == user.index
|
||||
next if user.faster_than?(b) || (b.status == :SLEEP && b.statusCount > 1) ||
|
||||
b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 ||
|
||||
b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0
|
||||
next if user.faster_than?(b) || !b.can_attack?
|
||||
score += 4
|
||||
end
|
||||
next score
|
||||
@@ -428,25 +424,85 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotAc
|
||||
# AlwaysCriticalHit
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
|
||||
proc { |score, move, user, ai, battle|
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user.effects[PBEffects::LaserFocus] > 0
|
||||
# TODO: Useless if user will already always critical hit ("AlwaysCriticalHit"
|
||||
# or Lucky Chant/crit stage is +3/etc.).
|
||||
next score + 10
|
||||
# Useless if the user's critical hit stage ensures critical hits already, or
|
||||
# critical hits are impossible (e.g. via Lucky Chant)
|
||||
crit_stage = move.rough_critical_hit_stage
|
||||
if crit_stage < 0 ||
|
||||
crit_stage >= Battle::Move::CRITICAL_HIT_RATIOS.length ||
|
||||
Battle::Move::CRITICAL_HIT_RATIOS[crit_stage] == 1
|
||||
next Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
# Prefer if user knows a damaging move which won't definitely critical hit
|
||||
if user.check_for_move { |m| m.damagingMove? && m.function != "AlwaysCriticalHit"}
|
||||
# TODO: Change the score depending on how much of an effect a critical hit
|
||||
# will have? Critical hits ignore the user's offensive stat drops
|
||||
# and the target's defensive stat raises, and multiply the damage.
|
||||
score += 10
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("StartPreventCriticalHitsAgainstUserSide",
|
||||
proc { |move, user, ai, battle|
|
||||
next user.pbOwnSide.effects[PBEffects::LuckyChant] > 0
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("StartPreventCriticalHitsAgainstUserSide",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Useless if Pokémon on the user's side are immune to critical hits
|
||||
user_side_immune = true
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
crit_stage = 0
|
||||
if b.ability_active?
|
||||
crit_stage = Battle::AbilityEffects.triggerCriticalCalcFromTarget(b.battler.ability,
|
||||
b.battler, b.battler, crit_stage)
|
||||
next if crit_stage < 0
|
||||
end
|
||||
if b.item_active?
|
||||
crit_stage = Battle::ItemEffects.triggerCriticalCalcFromTarget(b.battler.item,
|
||||
b.battler, b.battler, crit_stage)
|
||||
next if crit_stage < 0
|
||||
end
|
||||
user_side_immune = false
|
||||
break
|
||||
end
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user_side_immune
|
||||
# Prefer if any foe has an increased critical hit rate or moves/effects that
|
||||
# make critical hits more likely
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
crit_stage = 0
|
||||
if b.ability_active?
|
||||
crit_stage = Battle::AbilityEffects.triggerCriticalCalcFromUser(b.battler.ability,
|
||||
b.battler, user.battler, crit_stage)
|
||||
next if crit_stage < 0
|
||||
end
|
||||
if b.item_active?
|
||||
crit_stage = Battle::ItemEffects.triggerCriticalCalcFromUser(b.battler.item,
|
||||
b.battler, user.battler, crit_stage)
|
||||
next if crit_stage < 0
|
||||
end
|
||||
crit_stage += b.effects[PBEffects::FocusEnergy]
|
||||
crit_stage += 1 if m.check_for_move { |m| m.highCriticalRate? }
|
||||
crit_stage = [crit_stage, Battle::Move::CRITICAL_HIT_RATIOS.length - 1].min
|
||||
crit_stage = 3 if crit_stage < 3 && m.check_for_move { |m| m.pbCritialOverride(b.battler, user.battler) > 0 }
|
||||
# TODO: Change the score depending on how much of an effect a critical hit
|
||||
# will have? Critical hits ignore the user's offensive stat drops
|
||||
# and the target's defensive stat raises, and multiply the damage.
|
||||
score += 5 * crit_stage if crit_stage > 0
|
||||
score += 10 if b.effects[PBEffects::LaserFocus] > 0
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
@@ -466,9 +522,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
|
||||
# Prefer for each foe that can attack
|
||||
useless = true
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if (b.status == :SLEEP && b.statusCount > 1) ||
|
||||
b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 ||
|
||||
b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0
|
||||
next if !b.can_attack?
|
||||
useless = false
|
||||
score += 4
|
||||
end
|
||||
@@ -639,15 +693,15 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHai
|
||||
Battle::AI::Handlers::MoveEffectScore.add("RemoveScreens",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Prefer if allies have physical moves that are being weakened
|
||||
if user.pbOpposingSide.effects[PBEffects::Reflect] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0
|
||||
if user.pbOpposingSide.effects[PBEffects::Reflect] > 1 ||
|
||||
user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 1
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
score += 10 if b.check_for_move { |m| m.physicalMove?(m.type) }
|
||||
end
|
||||
end
|
||||
# Prefer if allies have special moves that are being weakened
|
||||
if user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 ||
|
||||
user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0
|
||||
if user.pbOpposingSide.effects[PBEffects::LightScreen] > 1 ||
|
||||
user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 1
|
||||
ai.each_same_side_battler(user.side) do |b, i|
|
||||
score += 10 if b.check_for_move { |m| m.specialMove?(m.type) }
|
||||
end
|
||||
@@ -666,9 +720,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
|
||||
# Prefer for each foe that can attack
|
||||
useless = true
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if (b.status == :SLEEP && b.statusCount > 1) ||
|
||||
b.status == :FROZEN || b.effects[PBEffects::HyperBeam] > 0 ||
|
||||
b.effects[PBEffects::Truant] || b.effects[PBEffects::SkyDrop] >= 0
|
||||
next if !b.can_attack?
|
||||
useless = false
|
||||
score += 4
|
||||
score += 4 if b.effects[PBEffects::TwoTurnAttack]
|
||||
|
||||
@@ -646,8 +646,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints",
|
||||
score -= 25
|
||||
# Check whether user is faster than its foe(s) and could use this move
|
||||
user_faster_count = 0
|
||||
ai.battlers.each_with_index do |b, i|
|
||||
next if !user.opposes?(b) || b.battler.fainted?
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
user_faster_count += 1 if user.faster_than?(b)
|
||||
end
|
||||
next score if user_faster_count == 0 # Move will almost certainly have no effect
|
||||
@@ -670,8 +669,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SetAttackerMovePPTo0IfUserFaints",
|
||||
score -= 25
|
||||
# Check whether user is faster than its foe(s) and could use this move
|
||||
user_faster_count = 0
|
||||
ai.battlers.each_with_index do |b, i|
|
||||
next if !user.opposes?(b) || b.battler.fainted?
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
user_faster_count += 1 if user.faster_than?(b)
|
||||
end
|
||||
next score if user_faster_count == 0 # Move will almost certainly have no effect
|
||||
|
||||
@@ -13,8 +13,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTakesTargetItem",
|
||||
user_no_item_preference = ai.battler_wants_item?(user, :NONE)
|
||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
||||
score += (user_item_preference - user_no_item_preference) * 5
|
||||
score += (target_item_preference - target_no_item_preference) * 5
|
||||
score += (user_item_preference - user_no_item_preference) * 3
|
||||
score += (target_item_preference - target_no_item_preference) * 3
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -35,8 +35,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetTakesUserItem",
|
||||
user_no_item_preference = ai.battler_wants_item?(user, :NONE)
|
||||
target_item_preference = ai.battler_wants_item?(target, user.item_id)
|
||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
||||
score -= (user_item_preference - user_no_item_preference) * 5
|
||||
score -= (target_item_preference - target_no_item_preference) * 5
|
||||
score -= (user_item_preference - user_no_item_preference) * 3
|
||||
score -= (target_item_preference - target_no_item_preference) * 3
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -60,8 +60,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems",
|
||||
user_old_item_preference = ai.battler_wants_item?(user, user.item_id)
|
||||
target_new_item_preference = ai.battler_wants_item?(target, user.item_id)
|
||||
target_old_item_preference = ai.battler_wants_item?(target, target.item_id)
|
||||
score += (user_new_item_preference - user_old_item_preference) * 5
|
||||
score -= (target_new_item_preference - target_old_item_preference) * 5
|
||||
score += (user_new_item_preference - user_old_item_preference) * 3
|
||||
score -= (target_new_item_preference - target_old_item_preference) * 3
|
||||
# Don't prefer if user used this move in the last round
|
||||
score -= 15 if user.battler.lastMoveUsed &&
|
||||
GameData::Move.get(user.battler.lastMoveUsed).function_code == "UserTargetSwapItems"
|
||||
@@ -81,7 +81,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem",
|
||||
proc { |score, move, user, ai, battle|
|
||||
user_new_item_preference = ai.battler_wants_item?(user, user.battler.recycleItem)
|
||||
user_old_item_preference = ai.battler_wants_item?(user, user.item_id)
|
||||
score += (user_new_item_preference - user_old_item_preference) * 8
|
||||
score += (user_new_item_preference - user_old_item_preference) * 4
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -103,7 +103,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveTargetItem",
|
||||
# User can knock off the target's item; score it
|
||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
||||
score += (target_item_preference - target_no_item_preference) * 5
|
||||
score += (target_item_preference - target_no_item_preference) * 4
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -121,7 +121,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DestroyTargetBerryOrGem"
|
||||
# User can incinerate the target's item; score it
|
||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
||||
score += (target_item_preference - target_no_item_preference) * 8
|
||||
score += (target_item_preference - target_no_item_preference) * 4
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -142,7 +142,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
||||
score += (target_item_preference - target_no_item_preference) * 8
|
||||
score += (target_item_preference - target_no_item_preference) * 4
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -258,13 +258,13 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserConsumeTargetBerry",
|
||||
# User can consume the target's berry; score it
|
||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
||||
score += (target_item_preference - target_no_item_preference) * 8
|
||||
score += (target_item_preference - target_no_item_preference) * 4
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget",
|
||||
proc { |move, user, ai, battle|
|
||||
@@ -280,3 +280,40 @@ Battle::AI::Handlers::MoveBasePower.add("ThrowUserItemAtTarget",
|
||||
next move.move.pbBaseDamage(power, user.battler, target.battler)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ThrowUserItemAtTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
case user.item_id
|
||||
when :POISONBARB, :TOXICORB
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
when :FLAMEORB
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
when :LIGHTBALL
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
when :KINGSROCK, :RAZORFANG
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
else
|
||||
# TODO: Berries/Berry Juice/Mental Herb/White Herb also have Fling
|
||||
# effects. Should they be accounted for individually, or is it okay
|
||||
# to consider it bad to Fling these in general? Note that they all
|
||||
# do minimal damage so this move probably won't be used anyway.
|
||||
if Battle::ItemEffects::HPHeal[user.item_id] ||
|
||||
Battle::ItemEffects::StatusCure[user.item_id] ||
|
||||
Battle::ItemEffects::OnEndOfUsingMove[user.item_id] ||
|
||||
Battle::ItemEffects::OnEndOfUsingMoveStatRestore[user.item_id]
|
||||
score -= 8
|
||||
end
|
||||
end
|
||||
# Prefer if the user doesn't want its held item/don't prefer if it wants to
|
||||
# keep its held item
|
||||
user_item_preference = ai.battler_wants_item?(user, user.item_id)
|
||||
user_no_item_preference = ai.battler_wants_item?(user, :NONE)
|
||||
score += (user_item_preference - user_no_item_preference) * 4
|
||||
# Prefer if user will benefit from not having an item
|
||||
score += 5 if user.has_active_ability?(:UNBURDEN)
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
@@ -289,14 +289,10 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower",
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers. This could reasonably used on an ally.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("TargetActsNext",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Useless if the user has no ally
|
||||
has_ally = false
|
||||
ai.each_ally(user.index) { |b, i| has_ally = true }
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !has_ally
|
||||
# Useless if the target is a foe
|
||||
next Battle::AI::MOVE_USELESS_SCORE if target.opposes?(user)
|
||||
# Compare the speeds of all battlers
|
||||
@@ -313,21 +309,27 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetActsNext",
|
||||
next Battle::AI::MOVE_USELESS_SCORE if idx_target < idx_user
|
||||
# Useless if the target will move next anyway
|
||||
next Battle::AI::MOVE_USELESS_SCORE if idx_target - idx_user <= 1
|
||||
next score
|
||||
# Generally not worth using
|
||||
# NOTE: Because this move can be used against a foe but is being used on an
|
||||
# ally (since we're here in this code), this move's score will be
|
||||
# inverted later. A higher score here means this move will be less
|
||||
# preferred, which is the result we want.
|
||||
next score + 10
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("TargetActsLast",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Useless if the user has no ally
|
||||
has_ally = false
|
||||
ai.each_ally(user.index) { |b, i| has_ally = true }
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !has_ally
|
||||
# Useless if the target is an ally
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !target.opposes?(user)
|
||||
# Useless if the user has no ally (the point of this move is to let the ally
|
||||
# get in a hit before the foe)
|
||||
has_ally = false
|
||||
ai.each_ally(user.index) { |b, i| has_ally = true if b.can_attack? }
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !has_ally
|
||||
# Compare the speeds of all battlers
|
||||
speeds = []
|
||||
ai.each_battler { |b, i| speeds.push([i, rough_stat(:SPEED)]) }
|
||||
@@ -338,11 +340,16 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetActsLast",
|
||||
end
|
||||
idx_user = speeds.index { |ele| ele[0] == user.index }
|
||||
idx_target = speeds.index { |ele| ele[0] == target.index }
|
||||
idx_slowest_ally = -1
|
||||
speeds.each_with_index { |ele, i| idx_slowest_ally = i if user.index.even? == ele[0].even? }
|
||||
# Useless if the target is faster than the user
|
||||
next Battle::AI::MOVE_USELESS_SCORE if idx_target < idx_user
|
||||
# Useless if the target will move last anyway
|
||||
next Battle::AI::MOVE_USELESS_SCORE if idx_target == speeds.length - 1
|
||||
next score
|
||||
# Useless if the slowest ally is faster than the target
|
||||
next Battle::AI::MOVE_USELESS_SCORE if idx_slowest_ally < idx_target
|
||||
# Generally not worth using
|
||||
next score - 10
|
||||
}
|
||||
)
|
||||
|
||||
@@ -378,16 +385,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetUsesItsLastUsedMov
|
||||
# StartSlowerBattlersActFirst
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HigherPriorityInGrassyTerrain",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
if ai.trainer.medium_skill? && battle.field.terrain == :Grassy
|
||||
score += 15 if target.faster_than?(user)
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
# HigherPriorityInGrassyTerrain
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
|
||||
@@ -212,7 +212,7 @@ class Battle::AI::AIBattler
|
||||
# TODO: Need to check the move's pbCalcTypeModSingle.
|
||||
ret *= effectiveness_of_type_against_single_battler_type(type, defend_type, user)
|
||||
end
|
||||
ret *= 2 if @battler.effects[PBEffects::TarShot] && type == :FIRE
|
||||
ret *= 2 if self.effects[PBEffects::TarShot] && type == :FIRE
|
||||
end
|
||||
return ret
|
||||
end
|
||||
@@ -281,6 +281,18 @@ class Battle::AI::AIBattler
|
||||
|
||||
#=============================================================================
|
||||
|
||||
def can_attack?
|
||||
return false if self.effects[PBEffects::SkyDrop] >= 0
|
||||
return false if self.effects[PBEffects::HyperBeam] > 0
|
||||
return false if status == :SLEEP && statusCount > 1
|
||||
return false if status == :FROZEN # Only 20% chance of unthawing; assune it won't
|
||||
return false if self.effects[PBEffects::Truant]
|
||||
return false if self.effects[PBEffects::Flinch]
|
||||
# NOTE: Confusion/infatuation/paralysis have higher chances of allowing the
|
||||
# attack, so the battler is treated as able to attack in those cases.
|
||||
return true
|
||||
end
|
||||
|
||||
def can_switch_lax?
|
||||
return false if wild?
|
||||
@ai.battle.eachInTeamFromBattlerIndex(@index) do |pkmn, i|
|
||||
|
||||
@@ -546,6 +546,7 @@ class Battle::AI::AIMove
|
||||
# 2 = additional effect will work
|
||||
# 3 = additional effect has an increased chance to work
|
||||
def additional_effect_usability(user, target)
|
||||
return 3 if self.function == "ThrowUserItemAtTarget"
|
||||
return 0 if @move.addlEffect == 0 # Doesn't have an additional effect
|
||||
return 1 if target.has_active_ability?(:SHIELDDUST) && !@ai.battle.moldBreaker
|
||||
return 3 if (Settings::MECHANICS_GENERATION >= 6 || self.function != "EffectDependsOnEnvironment") &&
|
||||
|
||||
@@ -366,7 +366,7 @@ end
|
||||
#===============================================================================
|
||||
class Battle::Move::UserLosesHalfHP < Battle::Move::RecoilMove
|
||||
def pbRecoilDamage(user, target)
|
||||
return (target.damageState.totalHPLost / 2.0).round
|
||||
return (user.hp / 2.0).round
|
||||
end
|
||||
|
||||
def pbEffectAfterAllHits(user, target)
|
||||
@@ -398,13 +398,13 @@ end
|
||||
# Ends the effects of Light Screen, Reflect and Safeguard on both sides.
|
||||
# (Shadow Shed)
|
||||
#===============================================================================
|
||||
class Battle::Move::RemoveAllScreens < Battle::Move
|
||||
class Battle::Move::RemoveAllScreensAndSafeguard < Battle::Move
|
||||
def pbMoveFailed?(user, targets)
|
||||
will_fail = true
|
||||
@battle.sides.each do |side|
|
||||
will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 ||
|
||||
side.effects[PBEffects::Reflect] > 0 ||
|
||||
side.effects[PBEffects::LightScreen] > 0 ||
|
||||
side.effects[PBEffects::Reflect] > 0 ||
|
||||
side.effects[PBEffects::Safeguard] > 0
|
||||
end
|
||||
if will_fail
|
||||
@@ -417,8 +417,8 @@ class Battle::Move::RemoveAllScreens < Battle::Move
|
||||
def pbEffectGeneral(user)
|
||||
@battle.sides.each do |i|
|
||||
i.effects[PBEffects::AuroraVeil] = 0
|
||||
i.effects[PBEffects::Reflect] = 0
|
||||
i.effects[PBEffects::LightScreen] = 0
|
||||
i.effects[PBEffects::Reflect] = 0
|
||||
i.effects[PBEffects::Safeguard] = 0
|
||||
end
|
||||
@battle.pbDisplay(_INTL("It broke all barriers!"))
|
||||
|
||||
Reference in New Issue
Block a user