mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-11 15:15:00 +00:00
AI changes for some multi-hit/multi-turn moves, improved AI's damage calculation
This commit is contained in:
@@ -291,11 +291,22 @@ end
|
|||||||
# Special Defense and Speed by 2 stages each in the second turn. (Geomancy)
|
# Special Defense and Speed by 2 stages each in the second turn. (Geomancy)
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
class Battle::Move::TwoTurnAttackRaiseUserSpAtkSpDefSpd2 < Battle::Move::TwoTurnMove
|
class Battle::Move::TwoTurnAttackRaiseUserSpAtkSpDefSpd2 < Battle::Move::TwoTurnMove
|
||||||
|
attr_reader :statUp
|
||||||
|
|
||||||
|
def initialize(battle, move)
|
||||||
|
super
|
||||||
|
@statUp = [:SPECIAL_ATTACK, 2, :SPECIAL_DEFENSE, 2, :SPEED, 2]
|
||||||
|
end
|
||||||
|
|
||||||
def pbMoveFailed?(user, targets)
|
def pbMoveFailed?(user, targets)
|
||||||
return false if user.effects[PBEffects::TwoTurnAttack] # Charging turn
|
return false if user.effects[PBEffects::TwoTurnAttack] # Charging turn
|
||||||
if !user.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user, self) &&
|
failed = true
|
||||||
!user.pbCanRaiseStatStage?(:SPECIAL_DEFENSE, user, self) &&
|
(@statUp.length / 2).times do |i|
|
||||||
!user.pbCanRaiseStatStage?(:SPEED, user, self)
|
next if !user.pbCanRaiseStatStage?(@statUp[i * 2], user, self)
|
||||||
|
failed = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if failed
|
||||||
@battle.pbDisplay(_INTL("{1}'s stats won't go any higher!", user.pbThis))
|
@battle.pbDisplay(_INTL("{1}'s stats won't go any higher!", user.pbThis))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -309,9 +320,9 @@ class Battle::Move::TwoTurnAttackRaiseUserSpAtkSpDefSpd2 < Battle::Move::TwoTurn
|
|||||||
def pbEffectGeneral(user)
|
def pbEffectGeneral(user)
|
||||||
return if !@damagingTurn
|
return if !@damagingTurn
|
||||||
showAnim = true
|
showAnim = true
|
||||||
[:SPECIAL_ATTACK, :SPECIAL_DEFENSE, :SPEED].each do |s|
|
(@statUp.length / 2).times do |i|
|
||||||
next if !user.pbCanRaiseStatStage?(s, user, self)
|
next if !user.pbCanRaiseStatStage?(@statUp[i * 2], user, self)
|
||||||
if user.pbRaiseStatStage(s, 2, user, showAnim)
|
if user.pbRaiseStatStage(@statUp[i * 2], @statUp[(i * 2) + 1], user, showAnim)
|
||||||
showAnim = false
|
showAnim = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,23 @@
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
|
||||||
proc { |power, move, user, target, ai, battle|
|
proc { |power, move, user, target, ai, battle|
|
||||||
next power * move.move.pbNumHits(user.battler, [target.battler])
|
next power * move.move.pbNumHits(user.battler, [target.battler])
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimes",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Prefer if the target has a Substitute and the first hit can break it
|
||||||
|
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
|
||||||
|
dmg = move.rough_damage
|
||||||
|
num_hits = move.move.pbNumHits(user.battler, [target.battler])
|
||||||
|
score += 10 if target.effects[PBEffects::Substitute] < dmg * (num_hits - 1) / num_hits
|
||||||
|
end
|
||||||
|
# TODO: Consider effects that trigger per hit.
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
# TODO: Review score modifiers.
|
||||||
@@ -14,7 +26,11 @@ Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
|
|||||||
"HitTwoTimesPoisonTarget")
|
"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)
|
# Score for hitting multiple times
|
||||||
|
score = Battle::AI::Handlers.apply_move_effect_score("HitTwoTimes",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
next score if !target.battler.pbCanPoison?(user.battler, false)
|
||||||
|
# Poisoning
|
||||||
score += 30
|
score += 30
|
||||||
if ai.trainer.medium_skill?
|
if ai.trainer.medium_skill?
|
||||||
score += 30 if target.hp <= target.totalhp / 4
|
score += 30 if target.hp <= target.totalhp / 4
|
||||||
@@ -37,7 +53,19 @@ Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
|
|||||||
"HitTwoTimesFlinchTarget")
|
"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]
|
dmg = move.rough_damage
|
||||||
|
num_hits = move.move.pbNumHits(user.battler, [target.battler])
|
||||||
|
# Prefer if the target has a Substitute and the first hit can break it
|
||||||
|
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
|
||||||
|
score += 10 if target.effects[PBEffects::Substitute] < dmg / num_hits
|
||||||
|
end
|
||||||
|
# Flinching
|
||||||
|
if user.faster_than?(target) && target.effects[PBEffects::Substitute] < dmg / num_hits &&
|
||||||
|
(battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS))
|
||||||
|
score += 10
|
||||||
|
end
|
||||||
|
# TODO: Consider effects that trigger per hit.
|
||||||
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,33 +79,35 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimesTargetThenTargetAlly",
|
|||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit",
|
Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit",
|
||||||
proc { |power, move, user, target, ai, battle|
|
proc { |power, move, user, target, ai, battle|
|
||||||
next power * 6 # Hits do x1, x2, x3 ret in turn, for x6 in total
|
next power * 6 # Hits do x1, x2, x3 ret in turn, for x6 in total
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesPowersUpWithEachHit",
|
||||||
#===============================================================================
|
|
||||||
# TODO: Review score modifiers.
|
|
||||||
#===============================================================================
|
|
||||||
Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesAlwaysCriticalHit",
|
|
||||||
proc { |power, move, user, target, ai, battle|
|
|
||||||
next power * move.move.pbNumHits(user.battler, [target.battler])
|
|
||||||
}
|
|
||||||
)
|
|
||||||
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?
|
# Prefer if the target has a Substitute and the first or second hit can break it
|
||||||
stat = (move.physicalMove?) ? :DEFENSE : :SPECIAL_DEFENSE
|
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
|
||||||
next score + 50 if target.stages[stat] > 1
|
dmg = move.rough_damage
|
||||||
|
score += 10 if target.effects[PBEffects::Substitute] < dmg / 2
|
||||||
end
|
end
|
||||||
|
# TODO: Consider effects that trigger per hit.
|
||||||
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
|
#===============================================================================
|
||||||
|
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
|
||||||
|
"HitThreeTimesAlwaysCriticalHit")
|
||||||
|
Battle::AI::Handlers::MoveEffectScore.copy("HitTwoTimes",
|
||||||
|
"HitThreeTimesAlwaysCriticalHit")
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
|
||||||
proc { |power, move, user, target, ai, battle|
|
proc { |power, move, user, target, ai, battle|
|
||||||
@@ -85,9 +115,21 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
|
|||||||
next power * 31 / 10 # Average damage dealt
|
next power * 31 / 10 # Average damage dealt
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimes",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Prefer if the target has a Substitute and the first hit(s) can break it
|
||||||
|
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
|
||||||
|
dmg = move.rough_damage
|
||||||
|
num_hits = (user.has_active_ability?(:SKILLLINK)) ? 5 : 3 # 3 is about average
|
||||||
|
score += 10 if target.effects[PBEffects::Substitute] < dmg * (num_hits - 1) / num_hits
|
||||||
|
end
|
||||||
|
# TODO: Consider effects that trigger per hit.
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja",
|
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja",
|
||||||
proc { |power, move, user, target, ai, battle|
|
proc { |power, move, user, target, ai, battle|
|
||||||
@@ -98,32 +140,32 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja"
|
|||||||
next power * 31 / 10 # Average damage dealt
|
next power * 31 / 10 # Average damage dealt
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Battle::AI::Handlers::MoveEffectScore.copy("HitTwoToFiveTimes",
|
||||||
|
"HitTwoToFiveTimesOrThreeForAshGreninja")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
# TODO: Review score modifiers.
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
|
Battle::AI::Handlers::MoveBasePower.copy("HitTwoToFiveTimes",
|
||||||
proc { |power, move, user, target, ai, battle|
|
"HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1")
|
||||||
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|
|
||||||
|
# Score for being a multi-hit attack
|
||||||
|
score = Battle::AI::Handlers.apply_move_effect_score("HitTwoToFiveTimes",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
# User's stat changes
|
||||||
aspeed = user.rough_stat(:SPEED)
|
aspeed = user.rough_stat(:SPEED)
|
||||||
ospeed = target.rough_stat(:SPEED)
|
ospeed = target.rough_stat(:SPEED)
|
||||||
if aspeed > ospeed && aspeed * 2 / 3 < ospeed
|
if aspeed < ospeed && aspeed * 1.5 > ospeed
|
||||||
score -= 50
|
score += 15 # Will become faster than the target
|
||||||
elsif aspeed < ospeed && aspeed * 1.5 > ospeed
|
|
||||||
score += 50
|
|
||||||
end
|
end
|
||||||
score += user.stages[:DEFENSE] * 30
|
score += user.stages[:DEFENSE] * 10
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember",
|
Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember",
|
||||||
proc { |move, user, target, ai, battle|
|
proc { |move, user, target, ai, battle|
|
||||||
@@ -139,51 +181,126 @@ Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember",
|
|||||||
Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember",
|
Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember",
|
||||||
proc { |power, move, user, target, ai, battle|
|
proc { |power, move, user, target, ai, battle|
|
||||||
ret = 0
|
ret = 0
|
||||||
ai.battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i|
|
battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i|
|
||||||
ret += 5 + (pkmn.baseStats[:ATTACK] / 10)
|
ret += 5 + (pkmn.baseStats[:ATTACK] / 10) if pkmn.able? && pkmn.status == :NONE
|
||||||
end
|
end
|
||||||
next ret
|
next ret
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Battle::AI::Handlers::MoveEffectScore.add("HitOncePerUserTeamMember",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Prefer if the target has a Substitute and the first hit(s) can break it
|
||||||
|
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
|
||||||
|
dmg = move.rough_damage
|
||||||
|
num_hits = 0
|
||||||
|
battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, _i|
|
||||||
|
num_hits += 1 if pkmn.able? && pkmn.status == :NONE
|
||||||
|
end
|
||||||
|
score += 10 if target.effects[PBEffects::Substitute] < dmg * (num_hits - 1) / num_hits
|
||||||
|
end
|
||||||
|
# TODO: Consider effects that trigger per hit.
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# AttackAndSkipNextTurn
|
Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Don't prefer because it uses up two turns
|
||||||
|
score -= 10 if !user.has_active_ability?(:TRUANT)
|
||||||
|
# Don't prefer if user is at a high HP (treat this move as a last resort)
|
||||||
|
score -= 10 if user.hp >= user.totalhp / 2
|
||||||
|
# TODO: Don't prefer if another of the user's moves could KO the target.
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TwoTurnAttack
|
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttack",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Power Herb makes this a 1 turn move, the same as a move with no effect
|
||||||
|
next score if user.has_active_item?(:POWERHERB)
|
||||||
|
# Treat as a failure if user has Truant (the charging turn has no effect)
|
||||||
|
next 25 if user.has_active_ability?(:TRUANT)
|
||||||
|
# Don't prefer because it uses up two turns
|
||||||
|
score -= 15
|
||||||
|
# Don't prefer if user is at a low HP (time is better spent on quicker moves)
|
||||||
|
score -= 10 if user.hp < user.totalhp / 2
|
||||||
|
# Don't prefer if target has a protecting move
|
||||||
|
if ai.trainer.high_skill? && !(user.has_active_ability?(:UNSEENFIST) && move.move.contactMove?)
|
||||||
|
has_protect_move = false
|
||||||
|
if move.move.pbTarget(user).num_targets > 1 &&
|
||||||
|
(Settings::MECHANICS_GENERATION >= 7 || move.damagingMove?)
|
||||||
|
if target.check_for_move { |m| m.function == "ProtectUserSideFromMultiTargetDamagingMoves" }
|
||||||
|
has_protect_move = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if move.move.canProtectAgainst?
|
||||||
|
if target.check_for_move { |m| ["ProtectUser",
|
||||||
|
"ProtectUserFromTargetingMovesSpikyShield",
|
||||||
|
"ProtectUserBanefulBunker"].include?(m.function) }
|
||||||
|
has_protect_move = true
|
||||||
|
end
|
||||||
|
if move.damagingMove?
|
||||||
|
# NOTE: Doesn't check for Mat Block because it only works on its
|
||||||
|
# user's first turn in battle, so it can't be used in response
|
||||||
|
# to this move charging up.
|
||||||
|
if target.check_for_move { |m| ["ProtectUserFromDamagingMovesKingsShield",
|
||||||
|
"ProtectUserFromDamagingMovesObstruct"].include?(m.function) }
|
||||||
|
has_protect_move = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if move.rough_priority > 0
|
||||||
|
if target.check_for_move { |m| m.function == "ProtectUserSideFromPriorityMoves" }
|
||||||
|
has_protect_move = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
score -= 15 if has_protect_move
|
||||||
|
end
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun",
|
Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun",
|
||||||
proc { |power, move, user, target, ai, battle|
|
proc { |power, move, user, target, ai, battle|
|
||||||
next move.move.pbBaseDamageMultiplier(power, user.battler, target.battler)
|
next move.move.pbBaseDamageMultiplier(power, user.battler, target.battler)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackOneTurnInSun",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Sunny weather this a 1 turn move, the same as a move with no effect
|
||||||
|
next score if [:Sun, :HarshSun].include?(user.battler.effectiveWeather)
|
||||||
|
# Score for being a two turn attack
|
||||||
|
next Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
# TODO: Review score modifiers.
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
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|
|
||||||
if target.battler.pbCanParalyze?(user.battler, false)
|
# Score for being a two turn attack
|
||||||
score += 30
|
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
# Paralyze the target
|
||||||
|
if !target.battler.pbCanParalyze?(user.battler, false)
|
||||||
|
score += 10
|
||||||
if ai.trainer.medium_skill?
|
if ai.trainer.medium_skill?
|
||||||
aspeed = user.rough_stat(:SPEED)
|
score += 10 if !user.faster_than?(target)
|
||||||
ospeed = target.rough_stat(:SPEED)
|
|
||||||
if aspeed < ospeed
|
|
||||||
score += 30
|
|
||||||
elsif aspeed > ospeed
|
|
||||||
score -= 40
|
|
||||||
end
|
end
|
||||||
end
|
score -= 15 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET])
|
||||||
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET])
|
else
|
||||||
elsif ai.trainer.medium_skill?
|
next 25 if move.statusMove?
|
||||||
score -= 90 if move.statusMove?
|
|
||||||
end
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -194,9 +311,16 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next score - 40 if move.statusMove? && !target.battler.pbCanBurn?(user.battler, false)
|
# Score for being a two turn attack
|
||||||
|
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
# Burn the target
|
||||||
|
if target.battler.pbCanBurn?(user.battler, false)
|
||||||
score += 10
|
score += 10
|
||||||
score -= 20 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST])
|
score -= 15 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST])
|
||||||
|
else
|
||||||
|
next 25 if move.statusMove?
|
||||||
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -206,47 +330,30 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget",
|
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
score += 20 if user.effects[PBEffects::FocusEnergy] > 0
|
# Score for being a two turn attack
|
||||||
score += 20 if (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) &&
|
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack",
|
||||||
target.effects[PBEffects::Substitute] == 0
|
score, move, user, target, ai, battle)
|
||||||
|
# Flinching
|
||||||
|
if user.faster_than?(target) && target.effects[PBEffects::Substitute] == 0 &&
|
||||||
|
(battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS))
|
||||||
|
score += 10
|
||||||
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
# TODO: This code shouldn't make use of target.
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
|
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1",
|
||||||
proc { |move, user, target, ai, battle|
|
"TwoTurnAttackRaiseUserSpAtkSpDefSpd2")
|
||||||
next true if !user.battler.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user.battler, move.move) &&
|
|
||||||
!user.battler.pbCanRaiseStatStage?(:SPECIAL_DEFENSE, user.battler, move.move) &&
|
|
||||||
!user.battler.pbCanRaiseStatStage?(:SPEED, user.battler, move.move)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
|
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
score -= user.stages[:SPECIAL_ATTACK] * 10 # Only *10 instead of *20
|
# Score for raising user's stats
|
||||||
score -= user.stages[:SPECIAL_DEFENSE] * 10 # because two-turn attack
|
score = ai.get_score_for_user_stat_raise(score)
|
||||||
score -= user.stages[:SPEED] * 10
|
# Score for being a two turn attack
|
||||||
if ai.trainer.medium_skill?
|
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack",
|
||||||
hasSpecialAttack = false
|
score, move, user, target, ai, battle)
|
||||||
user.battler.eachMove do |m|
|
|
||||||
next if !m.specialMove?(m.type)
|
|
||||||
hasSpecialAttack = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if hasSpecialAttack
|
|
||||||
score += 20
|
|
||||||
elsif ai.trainer.high_skill?
|
|
||||||
score -= 90
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if ai.trainer.high_skill?
|
|
||||||
aspeed = user.rough_stat(:SPEED)
|
|
||||||
ospeed = target.rough_stat(:SPEED)
|
|
||||||
score += 30 if aspeed < ospeed && aspeed * 2 > ospeed
|
|
||||||
end
|
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -256,15 +363,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2"
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserDefense1",
|
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserDefense1",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if move.statusMove?
|
score += 20 if user.stages[:DEFENSE] < 0
|
||||||
if user.statStageAtMax?(:DEFENSE)
|
|
||||||
score -= 90
|
|
||||||
else
|
|
||||||
score -= user.stages[:DEFENSE] * 20
|
|
||||||
end
|
|
||||||
elsif user.stages[:DEFENSE] < 0
|
|
||||||
score += 20
|
|
||||||
end
|
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ class Battle::AI::AIMove
|
|||||||
def rough_damage
|
def rough_damage
|
||||||
power = base_power
|
power = base_power
|
||||||
return power if @move.is_a?(Battle::Move::FixedDamageMove)
|
return power if @move.is_a?(Battle::Move::FixedDamageMove)
|
||||||
|
stage_mul = [2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8]
|
||||||
|
stage_div = [8, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2]
|
||||||
# Get the user and target of this move
|
# Get the user and target of this move
|
||||||
user = @ai.user
|
user = @ai.user
|
||||||
user_battler = user.battler
|
user_battler = user.battler
|
||||||
@@ -103,24 +105,21 @@ class Battle::AI::AIMove
|
|||||||
# Get the move's type
|
# Get the move's type
|
||||||
calc_type = rough_type
|
calc_type = rough_type
|
||||||
|
|
||||||
|
# Decide whether the move will definitely be a critical hit
|
||||||
|
is_critical = rough_critical_hit_stage >= Battle::Move::CRITICAL_HIT_RATIOS.length
|
||||||
|
|
||||||
##### Calculate user's attack stat #####
|
##### Calculate user's attack stat #####
|
||||||
atk = user.rough_stat(:ATTACK)
|
atk, atk_stage = @move.pbGetAttackStats(user.battler, target.battler)
|
||||||
if function == "UseTargetAttackInsteadOfUserAttack" # Foul Play
|
if !target.has_active_ability?(:UNAWARE) || @ai.battle.moldBreaker
|
||||||
atk = target.rough_stat(:ATTACK)
|
atk_stage = 6 if is_critical && atk_stage < 6
|
||||||
elsif function == "UseUserBaseDefenseInsteadOfUserBaseAttack" # Body Press
|
atk = (atk.to_f * stage_mul[atk_stage] / stage_div[atk_stage]).floor
|
||||||
atk = user.rough_stat(:DEFENSE)
|
|
||||||
elsif specialMove?(calc_type)
|
|
||||||
if function == "UseTargetAttackInsteadOfUserAttack" # Foul Play
|
|
||||||
atk = target.rough_stat(:SPECIAL_ATTACK)
|
|
||||||
else
|
|
||||||
atk = user.rough_stat(:SPECIAL_ATTACK)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##### Calculate target's defense stat #####
|
##### Calculate target's defense stat #####
|
||||||
defense = target.rough_stat(:DEFENSE)
|
defense, def_stage = pbGetDefenseStats(user, target)
|
||||||
if specialMove?(calc_type) && function != "UseTargetDefenseInsteadOfTargetSpDef" # Psyshock
|
if !user.has_active_ability?(:UNAWARE) || @ai.battle.moldBreaker
|
||||||
defense = target.rough_stat(:SPECIAL_DEFENSE)
|
def_stage = 6 if is_critical && def_stage > 6
|
||||||
|
defense = (defense.to_f * stage_mul[def_stage] / stage_div[def_stage]).floor
|
||||||
end
|
end
|
||||||
|
|
||||||
##### Calculate all multiplier effects #####
|
##### Calculate all multiplier effects #####
|
||||||
@@ -297,7 +296,14 @@ class Battle::AI::AIMove
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Critical hits - n/a
|
# Critical hits
|
||||||
|
if is_critical
|
||||||
|
if Settings::NEW_CRITICAL_HIT_RATE_MECHANICS
|
||||||
|
multipliers[:final_damage_multiplier] *= 1.5
|
||||||
|
else
|
||||||
|
multipliers[:final_damage_multiplier] *= 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Random variance - n/a
|
# Random variance - n/a
|
||||||
|
|
||||||
@@ -321,7 +327,8 @@ class Battle::AI::AIMove
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Aurora Veil, Reflect, Light Screen
|
# Aurora Veil, Reflect, Light Screen
|
||||||
if @ai.trainer.medium_skill? && !@move.ignoresReflect? && !user.has_active_ability?(:INFILTRATOR)
|
if @ai.trainer.medium_skill? && !@move.ignoresReflect? && !is_critical &&
|
||||||
|
!user.has_active_ability?(:INFILTRATOR)
|
||||||
if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
|
if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
|
||||||
if @ai.battle.pbSideBattlerCount(target_battler) > 1
|
if @ai.battle.pbSideBattlerCount(target_battler) > 1
|
||||||
multipliers[:final_damage_multiplier] *= 2 / 3.0
|
multipliers[:final_damage_multiplier] *= 2 / 3.0
|
||||||
|
|||||||
Reference in New Issue
Block a user