From 8275d40193f621fdebb5a71b7813f90d4c6740a9 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Mon, 29 Aug 2022 22:39:06 +0100 Subject: [PATCH] Added Mold Breaker consideration to AI, updated some AI calculations, fixed non-ignorable abilities in damage calculation actually being ignorable --- .../003_Move/003_Move_UsageCalculations.rb | 10 +- Data/Scripts/011_Battle/005_AI/004_AI_Move.rb | 10 +- .../005_AI/020_AI_MoveEffectScores_Generic.rb | 14 +- .../052_AI_MoveHandlers_BattlerStats.rb | 24 ++-- .../053_AI_MoveHandlers_BattlerOther.rb | 10 +- .../054_AI_MoveHandlers_MoveAttributes.rb | 4 +- .../005_AI/055_AI_MoveHandlers_MultiHit.rb | 2 +- .../005_AI/056_AI_MoveHandlers_Healing.rb | 4 +- .../005_AI/057_AI_MoveHandlers_Items.rb | 2 +- .../059_AI_MoveHandlers_SwitchingActing.rb | 9 +- .../070_AI_MoveHandlers_GeneralModifiers.rb | 2 +- .../011_Battle/005_AI/102_AIBattler.rb | 21 +-- Data/Scripts/011_Battle/005_AI/103_AIMove.rb | 130 +++++++++--------- 13 files changed, 125 insertions(+), 117 deletions(-) diff --git a/Data/Scripts/011_Battle/003_Move/003_Move_UsageCalculations.rb b/Data/Scripts/011_Battle/003_Move/003_Move_UsageCalculations.rb index 5b36a2c2e..a38b3bba2 100644 --- a/Data/Scripts/011_Battle/003_Move/003_Move_UsageCalculations.rb +++ b/Data/Scripts/011_Battle/003_Move/003_Move_UsageCalculations.rb @@ -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( diff --git a/Data/Scripts/011_Battle/005_AI/004_AI_Move.rb b/Data/Scripts/011_Battle/005_AI/004_AI_Move.rb index 500f7640a..8b150228a 100644 --- a/Data/Scripts/011_Battle/005_AI/004_AI_Move.rb +++ b/Data/Scripts/011_Battle/005_AI/004_AI_Move.rb @@ -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 diff --git a/Data/Scripts/011_Battle/005_AI/020_AI_MoveEffectScores_Generic.rb b/Data/Scripts/011_Battle/005_AI/020_AI_MoveEffectScores_Generic.rb index 5f0d47e62..03a03a9d2 100644 --- a/Data/Scripts/011_Battle/005_AI/020_AI_MoveEffectScores_Generic.rb +++ b/Data/Scripts/011_Battle/005_AI/020_AI_MoveEffectScores_Generic.rb @@ -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 diff --git a/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb b/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb index 3daf15780..c562261f0 100644 --- a/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb +++ b/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb @@ -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 diff --git a/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb b/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb index e547a40d5..6ed7fdfdf 100644 --- a/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb +++ b/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb @@ -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") diff --git a/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb b/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb index 3a3d7aaef..6c41b5ae7 100644 --- a/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb +++ b/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb @@ -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) } ) diff --git a/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb b/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb index 57eb984d0..e1d82dfc3 100644 --- a/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb +++ b/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb @@ -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 } diff --git a/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb b/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb index e8784a4ce..0d4ebc133 100644 --- a/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb +++ b/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb @@ -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", diff --git a/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb b/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb index af598cbfa..a8e500b84 100644 --- a/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb +++ b/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb @@ -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", diff --git a/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb b/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb index 76c91b343..829503eea 100644 --- a/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb +++ b/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb @@ -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) } ) diff --git a/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb b/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb index 7ba7709e3..1cf99bad5 100644 --- a/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb +++ b/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb @@ -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? && diff --git a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb index 68fbe3bfc..d375932f6 100644 --- a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb +++ b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb @@ -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 && diff --git a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb index bf5cb6663..dc54c9a5e 100644 --- a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb +++ b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb @@ -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