mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Added Mold Breaker consideration to AI, updated some AI calculations, fixed non-ignorable abilities in damage calculation actually being ignorable
This commit is contained in:
@@ -319,10 +319,14 @@ class Battle::Move
|
||||
Battle::AbilityEffects.triggerDamageCalcFromTarget(
|
||||
target.ability, user, target, self, multipliers, baseDmg, type
|
||||
)
|
||||
Battle::AbilityEffects.triggerDamageCalcFromTargetNonIgnorable(
|
||||
target.ability, user, target, self, multipliers, baseDmg, type
|
||||
)
|
||||
end
|
||||
end
|
||||
if target.abilityActive?
|
||||
Battle::AbilityEffects.triggerDamageCalcFromTargetNonIgnorable(
|
||||
target.ability, user, target, self, multipliers, baseDmg, type
|
||||
)
|
||||
end
|
||||
if !@battle.moldBreaker
|
||||
target.allAllies.each do |b|
|
||||
next if !b.abilityActive?
|
||||
Battle::AbilityEffects.triggerDamageCalcFromTargetAlly(
|
||||
|
||||
@@ -25,6 +25,7 @@ class Battle::AI
|
||||
end
|
||||
PBDebug.log(logMsg)
|
||||
end
|
||||
@battle.moldBreaker = false
|
||||
return choices
|
||||
end
|
||||
|
||||
@@ -100,6 +101,7 @@ class Battle::AI
|
||||
# TODO: Set @target to nil if there isn't one?
|
||||
@target = (target) ? @battlers[target.index] : @user
|
||||
@target&.refresh_battler
|
||||
@battle.moldBreaker = @user.has_mold_breaker?
|
||||
# Determine whether user or target is faster, and store that result so it
|
||||
# doesn't need recalculating
|
||||
@user_faster = @user.faster_than?(@target)
|
||||
@@ -141,13 +143,7 @@ class Battle::AI
|
||||
return true if @move.damagingMove? && calc_type == :GROUND &&
|
||||
@target.battler.airborne? && !@move.move.hitsFlyingTargets?
|
||||
# Immunity to powder-based moves
|
||||
if @move.move.powderMove?
|
||||
return true if @target.has_type?(:GRASS) && Settings::MORE_TYPE_EFFECTS
|
||||
if Settings::MECHANICS_GENERATION >= 6
|
||||
return true if @target.has_active_ability?(:OVERCOAT) ||
|
||||
@target.has_active_item?(:SAFETYGOGGLES)
|
||||
end
|
||||
end
|
||||
return true if @move.move.powderMove? && !@target.battler.affectedByPowder?
|
||||
# Substitute
|
||||
return true if @target.effects[PBEffects::Substitute] > 0 && @move.statusMove? &&
|
||||
!@move.move.ignoresSubstitute?(@user.battler) && @user.index != @target.index
|
||||
|
||||
@@ -50,7 +50,7 @@ class Battle::AI
|
||||
mini_score *= (sweeping_stat) ? 1.2 : 1.1
|
||||
end
|
||||
# Prefer if user has the ability Simple
|
||||
mini_score *= 2 if @user.hasActiveAbility?(:SIMPLE)
|
||||
mini_score *= 2 if !@battle.moldBreaker && @user.hasActiveAbility?(:SIMPLE)
|
||||
# TODO: Prefer if user's moves won't do much damage.
|
||||
# Prefer if user has something that will limit damage taken
|
||||
mini_score *= 1.3 if @user.effects[PBEffects::Substitute] > 0 ||
|
||||
@@ -164,7 +164,7 @@ class Battle::AI
|
||||
# Prefer if user can definitely survive a hit no matter how powerful, and
|
||||
# it won't be hurt by weather
|
||||
if @user.hp == @user.totalhp &&
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
|
||||
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
|
||||
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
|
||||
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
|
||||
@@ -226,7 +226,7 @@ class Battle::AI
|
||||
# Prefer if user can definitely survive a hit no matter how powerful, and
|
||||
# it won't be hurt by weather
|
||||
if @user.hp == @user.totalhp &&
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
|
||||
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
|
||||
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
|
||||
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
|
||||
@@ -274,7 +274,7 @@ class Battle::AI
|
||||
# Prefer if user can definitely survive a hit no matter how powerful, and
|
||||
# it won't be hurt by weather
|
||||
if @user.hp == @user.totalhp &&
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY)))
|
||||
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
|
||||
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
|
||||
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
|
||||
@@ -363,12 +363,12 @@ class Battle::AI
|
||||
end
|
||||
|
||||
# Don't prefer if user has Contrary
|
||||
mini_score *= 0.5 if @user.hasActiveAbility?(:CONTRARY)
|
||||
mini_score *= 0.5 if !@battle.moldBreaker && @user.hasActiveAbility?(:CONTRARY)
|
||||
# TODO: Don't prefer if target has Unaware? Reborn resets mini_score to 1.
|
||||
# This check needs more consideration. Note that @target is user for
|
||||
# status moves, so that part is wrong.
|
||||
# TODO: Is 0x for RaiseUserAtkDefAcc1, RaiseUserAtkSpd1 (all moves that raise multiple stats)
|
||||
mini_score *= 0.5 if @move.statusMove? && @target.hasActiveAbility?(:UNAWARE)
|
||||
mini_score *= 0.5 if @move.statusMove? && !@battle.moldBreaker && @target.hasActiveAbility?(:UNAWARE)
|
||||
|
||||
# TODO: Don't prefer if any foe has previously used a stat stage-clearing
|
||||
# move (Clear Smog/Haze).
|
||||
@@ -395,7 +395,7 @@ class Battle::AI
|
||||
#=============================================================================
|
||||
def get_score_for_user_stat_raise(score)
|
||||
# Discard status move if user has Contrary
|
||||
return 0 if @move.statusMove? && @user.hasActiveAbility?(:CONTRARY)
|
||||
return 0 if @move.statusMove? && !@battle.moldBreaker && @user.hasActiveAbility?(:CONTRARY)
|
||||
|
||||
# Discard move if it can't raise any stats
|
||||
can_change_any_stat = false
|
||||
|
||||
@@ -886,7 +886,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserMainStats1LoseThirdOfTotalH
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1LoseThirdOfTotalHP",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next 0 if user.has_active_ability?(:CONTRARY)
|
||||
next 0 if !battle.moldBreaker && user.has_active_ability?(:CONTRARY)
|
||||
score += 30 if ai.trainer.high_skill? && user.hp >= user.totalhp * 0.75
|
||||
GameData::Stat.each_main_battle { |s| score += 10 if user.stages[s.id] <= 0 }
|
||||
if ai.trainer.medium_skill?
|
||||
@@ -914,7 +914,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserMainStats1TrapUserInBattle"
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1TrapUserInBattle",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next 0 if user.has_active_ability?(:CONTRARY)
|
||||
next 0 if !battle.moldBreaker && user.has_active_ability?(:CONTRARY)
|
||||
if ai.trainer.high_skill?
|
||||
score -= 50 if user.hp <= user.totalhp / 2
|
||||
score += 30 if user.battler.trappedInBattle?
|
||||
@@ -1138,10 +1138,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetAtkSpAtk2",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetAtkSpAtk2",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next 0 if target.opposes?(user)
|
||||
next score - 90 if target.has_active_ability?(:CONTRARY)
|
||||
score -= target.stages[:ATTACK] * 20
|
||||
score -= target.stages[:SPECIAL_ATTACK] * 20
|
||||
next score - 50 if target.opposes?(user)
|
||||
next score - 40 if !battle.moldBreaker && target.has_active_ability?(:CONTRARY)
|
||||
score -= target.stages[:ATTACK] * 10
|
||||
score -= target.stages[:SPECIAL_ATTACK] * 10
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -1383,7 +1383,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetSpAtk2IfCanAttract",
|
||||
next true if move.statusMove? &&
|
||||
!target.battler.pbCanLowerStatStage?(move.move.statDown[0], user.battler, move.move)
|
||||
next true if user.gender == 2 || target.gender == 2 || user.gender == target.gender
|
||||
next true if target.has_active_ability?(:OBLIVIOUS)
|
||||
next true if !battle.moldBreaker && target.has_active_ability?(:OBLIVIOUS)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetSpAtk2IfCanAttract",
|
||||
@@ -1759,12 +1759,12 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseAlliesAtkDef1",
|
||||
Battle::AI::Handlers::MoveEffectScore.add("RaiseAlliesAtkDef1",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
user.battler.allAllies.each do |b|
|
||||
if b.hasActiveAbility?(:CONTRARY)
|
||||
score -= 90
|
||||
if !battle.moldBreaker && b.hasActiveAbility?(:CONTRARY)
|
||||
score -= 40
|
||||
else
|
||||
score += 40
|
||||
score -= b.stages[:ATTACK] * 20
|
||||
score -= b.stages[:SPECIAL_ATTACK] * 20
|
||||
score += 10
|
||||
score -= b.stages[:ATTACK] * 10
|
||||
score -= b.stages[:SPECIAL_ATTACK] * 10
|
||||
end
|
||||
end
|
||||
next score
|
||||
|
||||
@@ -383,7 +383,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatu
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("FlinchTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score + 30 if !target.has_active_ability?(:INNERFOCUS) &&
|
||||
next score + 30 if (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) &&
|
||||
target.effects[PBEffects::Substitute] == 0
|
||||
}
|
||||
)
|
||||
@@ -399,7 +399,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfUserNotAsleep",
|
||||
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfUserNotAsleep",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score += 100 # Because it can only be used while asleep
|
||||
score += 30 if !target.has_active_ability?(:INNERFOCUS) &&
|
||||
score += 30 if (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) &&
|
||||
target.effects[PBEffects::Substitute] == 0
|
||||
next score
|
||||
}
|
||||
@@ -415,7 +415,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfNotUserFirstTurn"
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfNotUserFirstTurn",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score + 30 if !target.has_active_ability?(:INNERFOCUS) &&
|
||||
next score + 30 if (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) &&
|
||||
target.effects[PBEffects::Substitute] == 0
|
||||
}
|
||||
)
|
||||
@@ -430,7 +430,7 @@ Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score + 30 if !target.has_active_ability?(:INNERFOCUS) &&
|
||||
next score + 30 if (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) &&
|
||||
target.effects[PBEffects::Substitute] == 0
|
||||
}
|
||||
)
|
||||
@@ -779,7 +779,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HitsTargetInSkyGroundsTarget",
|
||||
score += 20 if target.effects[PBEffects::MagnetRise] > 0 ||
|
||||
target.effects[PBEffects::Telekinesis] > 0 ||
|
||||
target.has_type?(:FLYING) ||
|
||||
target.has_active_ability?(:LEVITATE) ||
|
||||
(!battle.moldBreaker && target.has_active_ability?(:LEVITATE)) ||
|
||||
target.has_active_item?(:AIRBALLOON) ||
|
||||
target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky",
|
||||
"TwoTurnAttackInvulnerableInSkyParalyzeTarget")
|
||||
|
||||
@@ -99,7 +99,7 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetHPToUserHP",
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("OHKO",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if target.level > user.level
|
||||
next true if target.has_active_ability?(:STURDY)
|
||||
next true if !battle.moldBreaker && target.has_active_ability?(:STURDY)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveBasePower.add("OHKO",
|
||||
@@ -114,7 +114,7 @@ Battle::AI::Handlers::MoveBasePower.add("OHKO",
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("OHKOIce",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if target.level > user.level
|
||||
next true if target.has_active_ability?(:STURDY)
|
||||
next true if !battle.moldBreaker && target.has_active_ability?(:STURDY)
|
||||
next true if target.has_type?(:ICE)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -207,7 +207,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget",
|
||||
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score += 20 if user.effects[PBEffects::FocusEnergy] > 0
|
||||
score += 20 if !target.has_active_ability?(:INNERFOCUS) &&
|
||||
score += 20 if (battle.moldBreaker || !target.has_active_ability?(:INNERFOCUS)) &&
|
||||
target.effects[PBEffects::Substitute] == 0
|
||||
next score
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CureTargetStatusHealUserHalfOfTotalHP
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("HealUserByTargetAttackLowerTargetAttack1",
|
||||
proc { |move, user, target, ai, battle|
|
||||
if target.has_active_ability?(:CONTRARY)
|
||||
if !battle.moldBreaker && target.has_active_ability?(:CONTRARY)
|
||||
next true if target.statStageAtMax?(:ATTACK)
|
||||
else
|
||||
next true if target.statStageAtMin?(:ATTACK)
|
||||
@@ -343,7 +343,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("UserLosesHalfOfTotalHPExplosive",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if battle.pbCheckGlobalAbility(:DAMP)
|
||||
next true if !battle.moldBreaker && battle.pbCheckGlobalAbility(:DAMP)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHPExplosive",
|
||||
|
||||
@@ -46,7 +46,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapItems",
|
||||
next true if !user.item && !target.item
|
||||
next true if user.battler.unlosableItem?(user.item) || user.battler.unlosableItem?(target.item)
|
||||
next true if target.battler.unlosableItem?(target.item) || target.battler.unlosableItem?(user.item)
|
||||
next true if target.has_active_ability?(:STICKYHOLD)
|
||||
next true if !battle.moldBreaker && target.has_active_ability?(:STICKYHOLD)
|
||||
}
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapItems",
|
||||
|
||||
@@ -117,7 +117,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutTargetStatusMove",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if target.has_active_ability?(:SUCTIONCUPS) ||
|
||||
next true if (!battle.moldBreaker && target.has_active_ability?(:SUCTIONCUPS)) ||
|
||||
target.effects[PBEffects::Ingrain]
|
||||
next true if !battle.canRun
|
||||
next true if battle.wildBattle? && target.level > user.level
|
||||
@@ -146,8 +146,8 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetStatusMove",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetDamagingMove",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
if !target.effects[PBEffects::Ingrain] &&
|
||||
!target.has_active_ability?(:SUCTIONCUPS)
|
||||
if (battle.moldBreaker || !target.has_active_ability?(:SUCTIONCUPS)) &&
|
||||
!target.effects[PBEffects::Ingrain]
|
||||
score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
|
||||
score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
|
||||
score += 20 if target.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
@@ -427,7 +427,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetStatusMoves",
|
||||
proc { |move, user, target, ai, battle|
|
||||
next true if target.effects[PBEffects::Taunt] > 0
|
||||
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
|
||||
next true if Settings::MECHANICS_GENERATION >= 6 && target.has_active_ability?(:OBLIVIOUS)
|
||||
next true if Settings::MECHANICS_GENERATION >= 6 &&
|
||||
!battle.moldBreaker && target.has_active_ability?(:OBLIVIOUS)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:move_accuracy,
|
||||
Battle::AI::Handlers::GeneralMoveScore.add(:flinching_effects,
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
if ai.trainer.medium_skill? && target
|
||||
if !target.has_active_ability?([:INNERFOCUS, :SHIELDDUST]) &&
|
||||
if (battle.moldBreaker || !target.has_active_ability?([:INNERFOCUS, :SHIELDDUST])) &&
|
||||
target.effects[PBEffects::Substitute] == 0
|
||||
if move.move.flinchingMove? ||
|
||||
(move.damagingMove? &&
|
||||
|
||||
@@ -115,16 +115,20 @@ class Battle::AI::AIBattler
|
||||
|
||||
def ability_active?
|
||||
# Only a high skill AI knows what an opponent's ability is
|
||||
return false if @ai.trainer.side != @side && !@ai.trainer.high_skill?
|
||||
# return false if @ai.trainer.side != @side && !@ai.trainer.high_skill?
|
||||
return @battler.abilityActive?
|
||||
end
|
||||
|
||||
def has_active_ability?(ability)
|
||||
def has_active_ability?(ability, check_mold_breaker = false)
|
||||
# Only a high skill AI knows what an opponent's ability is
|
||||
return false if @ai.trainer.side != @side && !@ai.trainer.high_skill?
|
||||
# return false if @ai.trainer.side != @side && !@ai.trainer.high_skill?
|
||||
return @battler.hasActiveAbility?(ability)
|
||||
end
|
||||
|
||||
def has_mold_breaker?
|
||||
return @ai.move.function == "IgnoreTargetAbility" || @battler.hasMoldBreaker?
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
|
||||
def item_id; return @battler.item_id; end
|
||||
@@ -132,13 +136,13 @@ class Battle::AI::AIBattler
|
||||
|
||||
def item_active?
|
||||
# Only a high skill AI knows what an opponent's held item is
|
||||
return false if @ai.trainer.side != @side && !@ai.trainer.high_skill?
|
||||
# return false if @ai.trainer.side != @side && !@ai.trainer.high_skill?
|
||||
return @battler.itemActive?
|
||||
end
|
||||
|
||||
def has_active_item?(item)
|
||||
# Only a high skill AI knows what an opponent's held item is
|
||||
return false if @ai.trainer.side != @side && !@ai.trainer.high_skill?
|
||||
# return false if @ai.trainer.side != @side && !@ai.trainer.high_skill?
|
||||
return @battler.hasActiveItem?(item)
|
||||
end
|
||||
|
||||
@@ -183,13 +187,14 @@ class Battle::AI::AIBattler
|
||||
has_active_ability?(:WONDERGUARD)
|
||||
return true if move.damagingMove? && user.index != @index && !opposes?(user) &&
|
||||
has_active_ability?(:TELEPATHY)
|
||||
return true if move.statusMove? && move.move.canMagicCoat? && has_active_ability?(:MAGICBOUNCE) &&
|
||||
return true if move.statusMove? && move.move.canMagicCoat? &&
|
||||
!@ai.battle.moldBreaker && has_active_ability?(:MAGICBOUNCE) &&
|
||||
opposes?(user)
|
||||
return true if move.move.soundMove? && has_active_ability?(:SOUNDPROOF)
|
||||
return true if move.move.soundMove? && !@ai.battle.moldBreaker && has_active_ability?(:SOUNDPROOF)
|
||||
return true if move.move.bombMove? && has_active_ability?(:BULLETPROOF)
|
||||
if move.move.powderMove?
|
||||
return true if has_type?(:GRASS)
|
||||
return true if has_active_ability?(:OVERCOAT)
|
||||
return true if !@ai.battle.moldBreaker && has_active_ability?(:OVERCOAT)
|
||||
return true if has_active_ability?(:SAFETYGOGGLES)
|
||||
end
|
||||
return true if move.move.statusMove? && @battler.effects[PBEffects::Substitute] > 0 &&
|
||||
|
||||
@@ -132,9 +132,18 @@ class Battle::AI::AIMove
|
||||
:defense_multiplier => 1.0,
|
||||
:final_damage_multiplier => 1.0
|
||||
}
|
||||
# Ability effects that alter damage
|
||||
moldBreaker = @ai.trainer.high_skill? && target_battler.hasMoldBreaker?
|
||||
# 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
|
||||
|
||||
# Ability effects that alter damage
|
||||
if user.ability_active?
|
||||
# NOTE: These abilities aren't suitable for checking at the start of the
|
||||
# round.
|
||||
@@ -146,27 +155,30 @@ class Battle::AI::AIMove
|
||||
end
|
||||
end
|
||||
|
||||
if @ai.trainer.medium_skill? && !moldBreaker
|
||||
if !@ai.battle.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
|
||||
)
|
||||
if 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
|
||||
end
|
||||
|
||||
if @ai.trainer.high_skill? && !moldBreaker
|
||||
if target.ability_active?
|
||||
Battle::AbilityEffects.triggerDamageCalcFromTargetNonIgnorable(
|
||||
target.ability, user_battler, target_battler, @move, multipliers, power, calc_type
|
||||
)
|
||||
end
|
||||
if !@ai.battle.moldBreaker
|
||||
target_battler.allAllies.each do |b|
|
||||
next if !b.abilityActive?
|
||||
Battle::AbilityEffects.triggerDamageCalcFromTargetAlly(
|
||||
@@ -190,27 +202,15 @@ class Battle::AI::AIMove
|
||||
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
|
||||
multipliers[:base_damage_multiplier] *= (Settings::MECHANICS_GENERATION >= 7) ? 1.25 : 1.5
|
||||
end
|
||||
|
||||
# Me First
|
||||
@@ -245,13 +245,14 @@ class Battle::AI::AIMove
|
||||
|
||||
# Terrain moves
|
||||
if @ai.trainer.medium_skill?
|
||||
terrain_multiplier = (Settings::MECHANICS_GENERATION >= 8) ? 1.3 : 1.5
|
||||
case @ai.battle.field.terrain
|
||||
when :Electric
|
||||
multipliers[:base_damage_multiplier] *= 1.5 if calc_type == :ELECTRIC && user_battler.affectedByTerrain?
|
||||
multipliers[:base_damage_multiplier] *= terrain_multiplier if calc_type == :ELECTRIC && user_battler.affectedByTerrain?
|
||||
when :Grassy
|
||||
multipliers[:base_damage_multiplier] *= 1.5 if calc_type == :GRASS && user_battler.affectedByTerrain?
|
||||
multipliers[:base_damage_multiplier] *= terrain_multiplier if calc_type == :GRASS && user_battler.affectedByTerrain?
|
||||
when :Psychic
|
||||
multipliers[:base_damage_multiplier] *= 1.5 if calc_type == :PSYCHIC && user_battler.affectedByTerrain?
|
||||
multipliers[:base_damage_multiplier] *= terrain_multiplier if calc_type == :PSYCHIC && user_battler.affectedByTerrain?
|
||||
when :Misty
|
||||
multipliers[:base_damage_multiplier] /= 2 if calc_type == :DRAGON && target_battler.affectedByTerrain?
|
||||
end
|
||||
@@ -316,10 +317,8 @@ class Battle::AI::AIMove
|
||||
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
|
||||
if @ai.trainer.high_skill? && user.status == :BURN && physicalMove?(calc_type) &&
|
||||
@move.damageReducedByBurn? && !user.has_active_ability?(:GUTS)
|
||||
multipliers[:final_damage_multiplier] /= 2
|
||||
end
|
||||
|
||||
@@ -373,6 +372,12 @@ class Battle::AI::AIMove
|
||||
end
|
||||
|
||||
def rough_accuracy
|
||||
# "Always hit" effects and "always hit" accuracy
|
||||
if @ai.trainer.medium_skill?
|
||||
return 100 if target.effects[PBEffects::Telekinesis] > 0
|
||||
return 100 if target.effects[PBEffects::Minimize] && @move.tramplesMinimize? &&
|
||||
Settings::MECHANICS_GENERATION >= 6
|
||||
end
|
||||
baseAcc = self.accuracy
|
||||
return 100 if baseAcc == 0
|
||||
# Determine user and target
|
||||
@@ -385,19 +390,13 @@ class Battle::AI::AIMove
|
||||
baseAcc = @move.pbBaseAccuracy(user_battler, target_battler)
|
||||
return 100 if baseAcc == 0
|
||||
end
|
||||
# "Always hit" effects and "always hit" accuracy
|
||||
if @ai.trainer.medium_skill?
|
||||
return 100 if target_battler.effects[PBEffects::Minimize] && @move.tramplesMinimize? &&
|
||||
Settings::MECHANICS_GENERATION >= 6
|
||||
return 100 if target_battler.effects[PBEffects::Telekinesis] > 0
|
||||
end
|
||||
# Get the move's type
|
||||
type = rough_type
|
||||
# Calculate all modifier effects
|
||||
modifiers = {}
|
||||
modifiers[:base_accuracy] = baseAcc
|
||||
modifiers[:accuracy_stage] = user_battler.stages[:ACCURACY]
|
||||
modifiers[:evasion_stage] = target_battler.stages[:EVASION]
|
||||
modifiers[:accuracy_stage] = user.stages[:ACCURACY]
|
||||
modifiers[:evasion_stage] = target.stages[:EVASION]
|
||||
modifiers[:accuracy_multiplier] = 1.0
|
||||
modifiers[:evasion_multiplier] = 1.0
|
||||
apply_rough_accuracy_modifiers(user, target, type, modifiers)
|
||||
@@ -417,25 +416,24 @@ class Battle::AI::AIMove
|
||||
return modifiers[:base_accuracy] * accuracy / evasion
|
||||
end
|
||||
|
||||
def apply_rough_accuracy_modifiers(user, target, type, modifiers)
|
||||
def apply_rough_accuracy_modifiers(user, target, calc_type, modifiers)
|
||||
user_battler = user.battler
|
||||
target_battler = target.battler
|
||||
mold_breaker = (@ai.trainer.medium_skill? && target_battler.hasMoldBreaker?)
|
||||
# Ability effects that alter accuracy calculation
|
||||
if user.ability_active?
|
||||
Battle::AbilityEffects.triggerAccuracyCalcFromUser(
|
||||
user_battler.ability, modifiers, user_battler, target_battler, @move, type
|
||||
user.ability, modifiers, user_battler, target_battler, @move, calc_type
|
||||
)
|
||||
end
|
||||
user_battler.allAllies.each do |b|
|
||||
next if !b.abilityActive?
|
||||
Battle::AbilityEffects.triggerAccuracyCalcFromAlly(
|
||||
b.ability, modifiers, user_battler, target_battler, @move, type
|
||||
b.ability, modifiers, user_battler, target_battler, @move, calc_type
|
||||
)
|
||||
end
|
||||
if !mold_breaker && target.ability_active?
|
||||
if !@ai.battle.moldBreaker && target.ability_active?
|
||||
Battle::AbilityEffects.triggerAccuracyCalcFromTarget(
|
||||
target_battler.ability, modifiers, user_battler, target_battler, @move, type
|
||||
target.ability, modifiers, user_battler, target_battler, @move, calc_type
|
||||
)
|
||||
end
|
||||
# Item effects that alter accuracy calculation
|
||||
@@ -443,12 +441,12 @@ class Battle::AI::AIMove
|
||||
# TODO: Zoom Lens needs to be checked differently (compare speeds of
|
||||
# user and target).
|
||||
Battle::ItemEffects.triggerAccuracyCalcFromUser(
|
||||
user_battler.item, modifiers, user_battler, target_battler, @move, type
|
||||
user.item, modifiers, user_battler, target_battler, @move, calc_type
|
||||
)
|
||||
end
|
||||
if target.item_active?
|
||||
Battle::ItemEffects.triggerAccuracyCalcFromTarget(
|
||||
target_battler.item, modifiers, user_battler, target_battler, @move, type
|
||||
target.item, modifiers, user_battler, target_battler, @move, calc_type
|
||||
)
|
||||
end
|
||||
# Other effects, inc. ones that set accuracy_multiplier or evasion_stage to specific values
|
||||
@@ -456,27 +454,32 @@ class Battle::AI::AIMove
|
||||
modifiers[:accuracy_multiplier] *= 5 / 3.0
|
||||
end
|
||||
if @ai.trainer.medium_skill?
|
||||
if user_battler.effects[PBEffects::MicleBerry]
|
||||
if user.effects[PBEffects::MicleBerry]
|
||||
modifiers[:accuracy_multiplier] *= 1.2
|
||||
end
|
||||
modifiers[:evasion_stage] = 0 if target_battler.effects[PBEffects::Foresight] && modifiers[:evasion_stage] > 0
|
||||
modifiers[:evasion_stage] = 0 if target_battler.effects[PBEffects::MiracleEye] && modifiers[:evasion_stage] > 0
|
||||
modifiers[:evasion_stage] = 0 if target.effects[PBEffects::Foresight] && modifiers[:evasion_stage] > 0
|
||||
modifiers[:evasion_stage] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[:evasion_stage] > 0
|
||||
end
|
||||
# "AI-specific calculations below"
|
||||
modifiers[:evasion_stage] = 0 if @move.function == "IgnoreTargetDefSpDefEvaStatStages" # Chip Away
|
||||
modifiers[:evasion_stage] = 0 if function == "IgnoreTargetDefSpDefEvaStatStages" # Chip Away
|
||||
if @ai.trainer.medium_skill?
|
||||
modifiers[:base_accuracy] = 0 if user_battler.effects[PBEffects::LockOn] > 0 &&
|
||||
user_battler.effects[PBEffects::LockOnPos] == target_battler.index
|
||||
modifiers[:base_accuracy] = 0 if user.effects[PBEffects::LockOn] > 0 &&
|
||||
user.effects[PBEffects::LockOnPos] == target.index
|
||||
end
|
||||
if @ai.trainer.medium_skill?
|
||||
case @move.function
|
||||
case function
|
||||
when "BadPoisonTarget"
|
||||
modifiers[:base_accuracy] = 0 if Settings::MORE_TYPE_EFFECTS &&
|
||||
@move.statusMove? && @user.has_type?(:POISON)
|
||||
when "OHKO", "OHKOIce", "OHKOHitsUndergroundTarget"
|
||||
modifiers[:base_accuracy] = self.accuracy + user_battler.level - target_battler.level
|
||||
modifiers[:accuracy_multiplier] = 0 if target_battler.level > user_battler.level
|
||||
modifiers[:accuracy_multiplier] = 0 if target.has_active_ability?(:STURDY)
|
||||
when "OHKO", "OHKOHitsUndergroundTarget"
|
||||
modifiers[:base_accuracy] = self.accuracy + user.level - target.level
|
||||
modifiers[:accuracy_multiplier] = 0 if target.level > user.level
|
||||
modifiers[:accuracy_multiplier] = 0 if !@ai.battle.moldBreaker && target.has_active_ability?(:STURDY)
|
||||
when "OHKOIce"
|
||||
modifiers[:base_accuracy] = self.accuracy + user.level - target.level
|
||||
modifiers[:base_accuracy] -= 10 if !user.has_type?(:ICE)
|
||||
modifiers[:accuracy_multiplier] = 0 if target.level > user.level
|
||||
modifiers[:accuracy_multiplier] = 0 if !@ai.battle.moldBreaker && target.has_active_ability?(:STURDY)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -489,7 +492,6 @@ class Battle::AI::AIMove
|
||||
target = @ai.target
|
||||
target_battler = target.battler
|
||||
return -1 if target_battler.pbOwnSide.effects[PBEffects::LuckyChant] > 0
|
||||
mold_breaker = (@ai.trainer.medium_skill? && user_battler.hasMoldBreaker?)
|
||||
crit_stage = 0
|
||||
# Ability effects that alter critical hit rate
|
||||
if user.ability_active?
|
||||
@@ -497,7 +499,7 @@ class Battle::AI::AIMove
|
||||
user_battler, target_battler, crit_stage)
|
||||
return -1 if crit_stage < 0
|
||||
end
|
||||
if !mold_breaker && target.ability_active?
|
||||
if !@ai.battle.moldBreaker && target.ability_active?
|
||||
crit_stage = Battle::AbilityEffects.triggerCriticalCalcFromTarget(target_battler.ability,
|
||||
user_battler, target_battler, crit_stage)
|
||||
return -1 if crit_stage < 0
|
||||
|
||||
Reference in New Issue
Block a user