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:
Maruno17
2022-08-29 22:39:06 +01:00
parent 22dce593e8
commit 8275d40193
13 changed files with 125 additions and 117 deletions

View File

@@ -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(

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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")

View File

@@ -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)
}
)

View File

@@ -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
}

View File

@@ -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",

View File

@@ -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",

View File

@@ -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)
}
)

View File

@@ -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? &&

View File

@@ -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 &&

View File

@@ -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