From b8c61a60380b7af976bbe3a812d08ddf0a113486 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 4 Sep 2022 17:46:59 +0100 Subject: [PATCH] Rewrote AI calculations for move effects that raise the user's stats, fixed Sea of Fire effect lasting forever --- .../001_Battle/011_Battle_EndOfRoundPhase.rb | 2 + .../008_MoveEffects_MoveAttributes.rb | 1 + Data/Scripts/011_Battle/005_AI/004_AI_Move.rb | 2 +- .../005_AI/008_AI_Move_Utilities.rb | 34 +- .../005_AI/020_AI_MoveEffectScores_Generic.rb | 566 +++++++++------ .../052_AI_MoveHandlers_BattlerStats.rb | 654 +++--------------- .../053_AI_MoveHandlers_BattlerOther.rb | 2 +- .../054_AI_MoveHandlers_MoveAttributes.rb | 34 +- .../005_AI/055_AI_MoveHandlers_MultiHit.rb | 10 +- .../005_AI/057_AI_MoveHandlers_Items.rb | 4 +- .../058_AI_MoveHandlers_ChangeMoveEffect.rb | 4 +- .../059_AI_MoveHandlers_SwitchingActing.rb | 2 +- .../011_Battle/005_AI/102_AIBattler.rb | 130 +++- .../008_Battle_AbilityEffects.rb | 4 +- Data/Scripts/014_Pokemon/001_Pokemon.rb | 2 +- 15 files changed, 622 insertions(+), 829 deletions(-) diff --git a/Data/Scripts/011_Battle/001_Battle/011_Battle_EndOfRoundPhase.rb b/Data/Scripts/011_Battle/001_Battle/011_Battle_EndOfRoundPhase.rb index 1c0e7e8ef..c7931a975 100644 --- a/Data/Scripts/011_Battle/001_Battle/011_Battle_EndOfRoundPhase.rb +++ b/Data/Scripts/011_Battle/001_Battle/011_Battle_EndOfRoundPhase.rb @@ -134,6 +134,8 @@ class Battle #============================================================================= def pbEORSeaOfFireDamage(priority) 2.times do |side| + next if sides[side].effects[PBEffects::SeaOfFire] == 0 + sides[side].effects[PBEffects::SeaOfFire] -= 1 next if sides[side].effects[PBEffects::SeaOfFire] == 0 pbCommonAnimation("SeaOfFire") if side == 0 pbCommonAnimation("SeaOfFireOpp") if side == 1 diff --git a/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb b/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb index 4f7d66b2f..8fd6619c5 100644 --- a/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb +++ b/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb @@ -1199,6 +1199,7 @@ end # user's Attack (and Attack stat stages) to calculate damage. All other effects # are applied normally, applying the user's Attack modifiers and not the user's # Defence modifiers. (Body Press) +# TODO: Rename this function code to remove both "Base"s? #=============================================================================== class Battle::Move::UseUserBaseDefenseInsteadOfUserBaseAttack < Battle::Move def pbGetAttackStats(user, target) 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 3a9f76a56..3a4d02956 100644 --- a/Data/Scripts/011_Battle/005_AI/004_AI_Move.rb +++ b/Data/Scripts/011_Battle/005_AI/004_AI_Move.rb @@ -133,7 +133,7 @@ class Battle::AI # after all. return true if @move.move.pbImmunityByAbility(@user.battler, @target.battler, false) # Type immunity - calc_type = @move.rough_type(@user.battler) + calc_type = @move.rough_type typeMod = @move.move.pbCalcTypeMod(calc_type, @user.battler, @target.battler) return true if @move.move.pbDamagingMove? && Effectiveness.ineffective?(typeMod) # Dark-type immunity to moves made faster by Prankster diff --git a/Data/Scripts/011_Battle/005_AI/008_AI_Move_Utilities.rb b/Data/Scripts/011_Battle/005_AI/008_AI_Move_Utilities.rb index d824a5be2..8880a6407 100644 --- a/Data/Scripts/011_Battle/005_AI/008_AI_Move_Utilities.rb +++ b/Data/Scripts/011_Battle/005_AI/008_AI_Move_Utilities.rb @@ -37,15 +37,33 @@ class Battle::AI end #============================================================================= - # Check if battler has a move that meets the criteria in the block provided + # Yields certain AIBattler objects #============================================================================= - def check_for_move(battler) - ret = false - battler.eachMove do |move| - next unless yield move - ret = true - break + def each_battler + @battlers.each_with_index do |battler, i| + next if !battler || battler.fainted? + yield battler, i + end + end + + def each_foe_battler(side) + @battlers.each_with_index do |battler, i| + next if !battler || battler.fainted? + yield battler, i if i.even? != side.even? + end + end + + def each_same_side_battler(side) + @battlers.each_with_index do |battler, i| + next if !battler || battler.fainted? + yield battler, i if i.even? == side.even? + end + end + + def each_ally(index) + @battlers.each_with_index do |battler, i| + next if !battler || battler.fainted? + yield battler, i if i != index && i.even? == index.even? end - return ret end end 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 2a9f627dd..f524b8b7d 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 @@ -1,24 +1,105 @@ class Battle::AI #============================================================================= - # Apply additional effect chance to a move's score - # TODO: Apply all the additional effect chance modifiers. + # Main method for calculating the score for moves that raise the user's stat(s). #============================================================================= - def apply_effect_chance_to_score(score) - if @move.damagingMove? - # TODO: Doesn't return the correct value for "ConfuseTarget" (Chatter). - effect_chance = @move.addlEffect - if effect_chance > 0 - effect_chance *= 2 if @user.hasActiveAbility?(:SERENEGRACE) || - @user.pbOwnSide.effects[PBEffects::Rainbow] > 0 - effect_multiplier = [effect_chance.to_f, 100].min / 100 - score = ((score - 1) * effect_multiplier) + 1 - end + def get_score_for_user_stat_raise(score) + # Discard status move/don't prefer damaging move if user has Contrary + if !@battle.moldBreaker && @user.has_active_ability?(:CONTRARY) + return (@move.statusMove?) ? score - 40 : score - 20 end + # Don't make score changes if foes have Unaware and user can't make use of + # extra stat stages + if !@user.check_for_move { |move| move.function == "PowerHigherWithUserPositiveStatStages" } + foe_is_aware = false + each_foe_battler(@user.side) do |b, i| + foe_is_aware = true if !b.has_active_ability?(:UNAWARE) + end + return score if !foe_is_aware + end + + # Figure out which stat raises can happen + stat_changes = [] + @move.move.statUp.each_with_index do |stat, idx| + next if idx.odd? + next if !stat_raise_worthwhile?(stat) + # Calculate amount that stat will be raised by + increment = @move.move.statUp[idx + 1] + if @move.function == "RaiseUserAtkSpAtk1Or2InSun" + increment = 1 + increment = 2 if [:Sun, :HarshSun].include?(@user.battler.effectiveWeather) + end + increment *= 2 if !@battle.moldBreaker && @user.has_active_ability?(:SIMPLE) + increment = [increment, 6 - @user.stages[stat]].min # The actual stages gained + # Count this as a valid stat raise + stat_changes.push([stat, increment]) if increment > 0 + end + # Discard move if it can't raise any stats + if stat_changes.length == 0 + return (@move.statusMove?) ? score - 40 : score + end + + # Make score changes based on the general concept of raising stats at all + score = get_user_stat_raise_score_generic(score, stat_changes) + + # Make score changes based on the specific changes to each stat that will be + # raised + stat_changes.each do |change| + score = get_user_stat_raise_score_one(score, change[0], change[1]) + end + return score end #============================================================================= - # + # Returns whether the user raising the given stat will have any impact. + # TODO: Make sure the move's actual damage category is taken into account, + # i.e. CategoryDependsOnHigherDamagePoisonTarget and + # CategoryDependsOnHigherDamageIgnoreTargetAbility. + #============================================================================= + def stat_raise_worthwhile?(stat) + return false if !@user.battler.pbCanRaiseStatStage?(stat, @user.battler, @move) + # Check if user won't benefit from the stat being raised + # TODO: Exception if user knows Baton Pass/Stored Power? + case stat + when :ATTACK + return false if !@user.check_for_move { |move| move.physicalMove?(move.type) && + move.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" && + move.function != "UseTargetAttackInsteadOfUserAttack" } + when :DEFENSE + each_foe_battler(@user.side) do |b, i| + next if !b.check_for_move { |move| move.physicalMove?(move.type) || + move.function == "UseTargetDefenseInsteadOfTargetSpDef" } + return true + end + return false + when :SPECIAL_ATTACK + return false if !@user.check_for_move { |move| move.specialMove?(move.rough_type) } + when :SPECIAL_DEFENSE + each_foe_battler(@user.side) do |b, i| + next if !b.check_for_move { |move| move.specialMove?(move.type) && + move.function != "UseTargetDefenseInsteadOfTargetSpDef" } + return true + end + return false + when :SPEED + moves_that_prefer_high_speed = [ + "PowerHigherWithUserFasterThanTarget", + "PowerHigherWithUserPositiveStatStages" + ] + if !@user.check_for_move { |move| moves_that_prefer_high_speed.include?(move.function) } + each_foe_battler(@user.side) do |b, i| + return true if b.faster_than?(@user) + end + return false + end + when :ACCURACY + when :EVASION + end + return true + end + + #============================================================================= + # Make score changes based on the general concept of raising stats at all. #============================================================================= # TODO: These function codes need to have an attr_reader :statUp and for them # to be set when the move is initialised. @@ -26,15 +107,45 @@ class Battle::AI # RaiseTargetRandomStat2 Acupressure # RaisePlusMinusUserAndAlliesDefSpDef1 Magnetic Flux # RaisePlusMinusUserAndAlliesAtkSpAtk1 Gear Up - def calc_user_stat_raise_mini_score + def get_user_stat_raise_score_generic(score, stat_changes) + total_increment = stat_changes.sum { |change| change[1] } + # TODO: Just return if foe is predicted to use a phazing move (one that + # switches the user out). + # TODO: Don't prefer if foe is faster than user and is predicted to deal + # lethal damage. + # TODO: Don't prefer if foe is slower than user but is predicted to be able + # to 2HKO user. + # TODO: Prefer if foe is semi-invulnerable and user is faster (can't hit + # the foe anyway). + + # Prefer if move is a status move and it's the user's first/second turn + if @user.turnCount < 2 && @move.statusMove? + score += total_increment * 5 + end + + # Prefer if user is at high HP, don't prefer if user is at low HP + if @user.hp >= @user.totalhp * 0.7 + score += 10 * total_increment + else + score += total_increment * ((100 * @user.hp / @user.totalhp) - 50) / 2 # +10 to -25 per stage + end + + # Don't prefer if user is about to faint due to EOR damage + score -= 30 if @user.rough_end_of_round_damage > @user.hp + + # TODO: Look at abilities that trigger upon stat raise. There are none. + + return score + + + mini_score = 1.0 # Determine whether the move boosts Attack, Special Attack or Speed (Bulk Up # is sometimes not considered a sweeping move) sweeping_stat = false offensive_stat = false - @move.stat_up.each_with_index do |stat, idx| - next if idx.odd? - next if ![:ATTACK, :SPATK, :SPEED].include?(stat) + stat_changes.each do |change| + next if ![:ATTACK, :SPECIAL_ATTACK, :SPEED].include?(change[0]) sweeping_stat = true next if @move.function == "RaiseUserAtkDef1" # Bulk Up (+Atk +Def) offensive_stat = true @@ -45,12 +156,6 @@ class Battle::AI if @user.hp >= @user.totalhp * 3 / 4 mini_score *= (sweeping_stat) ? 1.2 : 1.1 end - # Prefer if user hasn't been in battle for long - if @user.turnCount < 2 - mini_score *= (sweeping_stat) ? 1.2 : 1.1 - end - # Prefer if user has the ability 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 || @@ -116,12 +221,6 @@ class Battle::AI # TODO: Prefer if the maximum damage the target has dealt wouldn't hurt # the user much. end - # Don't prefer if foe's side is able to use a boosted Retaliate - # TODO: I think this is what Reborn means. Reborn doesn't check for the - # existence of the move Retaliate, just whether it can be boosted. - if @user.pbOpposingSide.effects[PBEffects::LastRoundFainted] == @battle.turnCount - 1 - mini_score *= 0.3 - end # Don't prefer if it's not a single battle if !@battle.singleBattle? @@ -132,197 +231,271 @@ class Battle::AI end #============================================================================= - # + # Make score changes based on the raising of a specific stat. #============================================================================= - # TODO: This method doesn't take the increment into account but should. - def calc_user_stat_raise_one(stat, increment) - mini_score = 1.0 - - # Ignore if user won't benefit from the stat being raised - # TODO: Exception if user knows Baton Pass? Exception if user knows Power Trip? + def get_user_stat_raise_score_one(score, stat, increment) case stat when :ATTACK - has_physical_move = false - @user.eachMove do |m| - next if !m.physicalMove?(m.type) || m.function == "UseTargetAttackInsteadOfUserAttack" # Foul Play - has_physical_move = true - break + # Modify score depending on current stat stage + # More strongly prefer if the user has no special moves + if @user.stages[stat] >= 3 + score -= 20 + else + has_special_moves = @user.check_for_move { |move| move.specialMove?(move.rough_type) } + inc = (has_special_moves) ? 5 : 10 + score += inc * (3 - @user.stages[stat]) * increment # 5 to 45 + score += 5 * increment if @user.hp == @user.totalhp end - return mini_score if !has_physical_move + + when :DEFENSE + # Modify score depending on current stat stage + if @user.stages[stat] >= 3 + score -= 20 + else + score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45 + score += 5 * increment if @user.hp == @user.totalhp + end + when :SPECIAL_ATTACK - has_special_move = false - @user.eachMove do |m| - next if !m.specialMove?(m.type) - has_special_move = true + # Modify score depending on current stat stage + # More strongly prefer if the user has no physical moves + if @user.stages[stat] >= 3 + score -= 20 + else + has_physical_moves = @user.check_for_move { |move| move.physicalMove?(move.type) && + move.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" && + move.function != "UseTargetAttackInsteadOfUserAttack" } + inc = (has_physical_moves) ? 5 : 10 + score += inc * (3 - @user.stages[stat]) * increment # 5 to 45 + score += 5 * increment if @user.hp == @user.totalhp + end + + when :SPECIAL_DEFENSE + # Modify score depending on current stat stage + if @user.stages[stat] >= 3 + score -= 20 + else + score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45 + score += 5 * increment if @user.hp == @user.totalhp + end + + when :SPEED + # Prefer if user is slower than a foe + each_foe_battler(@user.side) do |b, i| + next if @user.faster_than?(b) + score += 15 * increment break end - return mini_score if !has_special_move - end + # Don't prefer if any foe has Gyro Ball + each_foe_battler(@user.side) do |b, i| + next if !b.check_for_move { |move| move.function == "PowerHigherWithTargetFasterThanUser" } + score -= 10 * increment + end + # Don't prefer if user has Speed Boost (will be gaining Speed anyway) + score -= 20 if @user.has_active_ability?(:SPEEDBOOST) - case stat - when :ATTACK - # 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) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) - if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && - !(@battle.pbWeather == :Hail && @user.takesHailDamage?) && - !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) - mini_score *= 1.4 + when :ACCURACY + # Modify score depending on current stat stage + if @user.stages[stat] >= 3 + score -= 20 + else + min_accuracy = 100 + @user.battler.moves.each do |m| + next if m.accuracy == 0 || m.is_a?(Battle::Move::OHKO) + min_accuracy = m.accuracy if m.accuracy < min_accuracy + end + stageMul = [3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9] + stageDiv = [9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3] + min_accuracy *= stageMul[@user.stages[stat]] / stageDiv[@user.stages[stat]] + if min_accuracy < 90 + score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45 + score += 5 * increment if @user.hp == @user.totalhp end end - # Prefer if user has the Sweeper role - # TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). - mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER) - # Don't prefer if user is burned or paralysed - mini_score *= 0.5 if @user.status == :BURN || @user.status == :PARALYSIS - # Don't prefer if user's Speed stat is lowered - sum_stages = @user.stages[:SPEED] - mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0 - # TODO: Prefer if target has previously used a HP-restoring move. - # TODO: Don't prefer if some of foes' stats are raised - sum_stages = 0 - [:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s| - sum_stages += @target.stages[s] + when :EVASION + # Prefer if a foe will (probably) take damage at the end of the round + # TODO: Should this take into account EOR healing, one-off damage and + # damage-causing effects that wear off naturally (like Sea of Fire)? + # TODO: Emerald AI also prefers if user is rooted via Ingrain. + each_foe_battler(@user.side) do |b, i| + eor_damage = b.rough_end_of_round_damage + score += 60 * eor_damage / b.totalhp if eor_damage > 0 end - mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 - # TODO: Don't prefer if target has Speed Boost (+Spd at end of each round). - mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST) + # Modify score depending on current stat stage + if @user.stages[stat] >= 3 + score -= 20 + else + score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45 + score += 5 * increment if @user.hp == @user.totalhp + end + + end + + # Check impact on moves of gaining stat stages + pos_change = [@user.stages[stat] + increment, increment].min + if pos_change > 0 + # Prefer if user has Stored Power + if @user.check_for_move { |move| move.function == "PowerHigherWithUserPositiveStatStages" } + score += 10 * pos_change + end + # Don't prefer if any foe has Punishment + each_foe_battler(@user.side) do |b, i| + next if !b.check_for_move { |move| move.function == "PowerHigherWithTargetPositiveStatStages" } + score -= 10 * pos_change + end + end + + return score + + + + mini_score = 1.0 + case stat + when :ATTACK # TODO: Don't prefer if target has previously used a move that benefits # from user's Attack being boosted. - mini_score *= 0.3 if check_for_move(@target) { |move| move.function == "UseTargetAttackInsteadOfUserAttack" } # Foul Play - # TODO: Don't prefer if the target has previously used a priority move. +# mini_score *= 0.3 if @target.check_for_move { |move| move.function == "UseTargetAttackInsteadOfUserAttack" } # Foul Play + # 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) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) +# if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && +# !(@battle.pbWeather == :Hail && @user.takesHailDamage?) && +# !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) +# mini_score *= 1.4 +# end +# end + # Prefer if user has the Sweeper role + # TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). +# mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER) + +# # Don't prefer if user is burned or paralysed +# mini_score *= 0.5 if @user.status == :BURN || @user.status == :PARALYSIS +# # Don't prefer if user's Speed stat is lowered +# sum_stages = @user.stages[:SPEED] +# mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0 +# # TODO: Prefer if target has previously used a HP-restoring move. +# # TODO: Don't prefer if some of foes' stats are raised. +# sum_stages = 0 +# [:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s| +# sum_stages += @target.stages[s] +# end +# mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 +# # TODO: Don't prefer if target has Speed Boost (+Spd at end of each round). +# mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST) +# # TODO: Don't prefer if the target has previously used a priority move. when :DEFENSE # Prefer if user has a healing item # TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). - mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) || - (@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON)) +# mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) || +# (@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON)) # Prefer if user knows any healing moves - # TODO: Is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). - mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? } +# # TODO: Is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). +# mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? } # Prefer if user knows Pain Split or Leech Seed - # TODO: Leech Seed is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). - mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split - mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed +# # TODO: Leech Seed is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). +# mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split +# mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed # Prefer if user has certain roles - # TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). - mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL) +# # TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc). +# mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL) # Don't prefer if user is badly poisoned mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0 - # Don't prefer if user's Defense stat is raised - sum_stages = @user.stages[:DEFENSE] - mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0 - - # TODO: Prefer if foes have higher Attack than Special Attack, and user - # doesn't have a wall role, user is faster and user has at least 75% - # HP. Don't prefer instead if user is slower (ignore HP). - +# # TODO: Prefer if foes have higher Attack than Special Attack, and user +# # doesn't have a wall role, user is faster and user has at least 75% +# # HP. Don't prefer instead if user is slower (ignore HP). # TODO: Don't prefer if previous damage done by foes wouldn't hurt the # user much. when :SPEED + # Don't prefer if user has Speed Boost +# mini_score *= 0.6 if @user.hasActiveAbility?(:SPEEDBOOST) # 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) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) - if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && - !(@battle.pbWeather == :Hail && @user.takesHailDamage?) && - !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) - mini_score *= 1.4 - end - end - # Prefer if user's Attack/SpAtk stat (whichever is higher) is lowered - # TODO: Why? - if @user.attack > @user.spatk - sum_stages = @user.stages[:ATTACK] - mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0 - else - sum_stages = @user.stages[:SPATK] - mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0 - end - # Prefer if user has lowered Speed - # TODO: Is a flat 1.3x for RaiseUserAtkSpd1 Dragon Dance (+Atk, +Spd). - sum_stages = @user.stages[:SPEED] - mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0 - # Prefer if user has Moxie - mini_score *= 1.3 if @user.hasActiveAbility?(:MOXIE) - # Prefer if user has the Sweeper role - mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER) - # Don't prefer if user is burned or paralysed - mini_score *= 0.2 if @user.status == :PARALYSIS - # Don't prefer if user has Speed Boost - mini_score *= 0.6 if @user.hasActiveAbility?(:SPEEDBOOST) +# if @user.hp == @user.totalhp && +# (@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) +# if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && +# !(@battle.pbWeather == :Hail && @user.takesHailDamage?) && +# !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) +# mini_score *= 1.4 +# end +# end + # Prefer if user has the Sweeper role +# mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER) + # TODO: Don't prefer if Trick Room applies or any foe has previously used + # Trick Room. +# mini_score *= 0.2 if @battle.field.effects[PBEffects::TrickRoom] > 0 - # TODO: Don't prefer if target has raised defenses. - sum_stages = 0 - [:DEFENSE, :SPECIAL_DEFENSE].each { |s| sum_stages += @target.stages[s] } - mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 - # TODO: Don't prefer if the target has previously used a priority move. - # TODO: Don't prefer if Trick Room applies or any foe has previously used - # Trick Room. - mini_score *= 0.2 if @battle.field.effects[PBEffects::TrickRoom] > 0 - - # TODO: Don't prefer if user is already faster than the target. Exception - # for moves that benefit from a raised user's Speed? - # TODO: Don't prefer if user is already faster than the target and there's - # only 1 unfainted foe (this check is done by Agility/Autotomize - # (both +2 Spd) only in Reborn.) +# # Prefer if user's Attack/SpAtk stat (whichever is higher) is lowered +# # TODO: Why? +# if @user.attack > @user.spatk +# sum_stages = @user.stages[:ATTACK] +# mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0 +# else +# sum_stages = @user.stages[:SPATK] +# mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0 +# end +# # Prefer if user has Moxie +# mini_score *= 1.3 if @user.hasActiveAbility?(:MOXIE) +# # Don't prefer if user is burned or paralysed +# mini_score *= 0.2 if @user.status == :PARALYSIS +# # TODO: Don't prefer if target has raised defenses. +# sum_stages = 0 +# [:DEFENSE, :SPECIAL_DEFENSE].each { |s| sum_stages += @target.stages[s] } +# mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 +# # TODO: Don't prefer if the target has previously used a priority move. +# # TODO: Don't prefer if user is already faster than the target and there's +# # only 1 unfainted foe (this check is done by Agility/Autotomize +# # (both +2 Spd) only in Reborn.) when :SPECIAL_ATTACK # 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) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) - if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && - !(@battle.pbWeather == :Hail && @user.takesHailDamage?) && - !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) - mini_score *= 1.4 - end - end +# if @user.hp == @user.totalhp && +# (@user.hasActiveItem?(:FOCUSSASH) || (!@battle.moldBreaker && @user.hasActiveAbility?(:STURDY))) +# if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) && +# !(@battle.pbWeather == :Hail && @user.takesHailDamage?) && +# !(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?) +# mini_score *= 1.4 +# end +# end # Prefer if user has the Sweeper role - mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER) - # Don't prefer if user's Speed stat is lowered - sum_stages = @user.stages[:SPEED] - mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0 +# mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER) - # TODO: Prefer if target has previously used a HP-restoring move. - # TODO: Don't prefer if some of foes' stats are raised - sum_stages = 0 - [:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s| - sum_stages += @target.stages[s] - end - mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 - # TODO: Don't prefer if target has Speed Boost (+Spd at end of each round) - mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST) - # TODO: Don't prefer if the target has previously used a priority move. +# # Don't prefer if user's Speed stat is lowered +# sum_stages = @user.stages[:SPEED] +# mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0 +# # TODO: Prefer if target has previously used a HP-restoring move. +# # TODO: Don't prefer if some of foes' stats are raised +# sum_stages = 0 +# [:ATTACK, :SPECIAL_ATTACK, :SPEED].each do |s| +# sum_stages += @target.stages[s] +# end +# mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0 +# # TODO: Don't prefer if target has Speed Boost (+Spd at end of each round) +# mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST) +# # TODO: Don't prefer if the target has previously used a priority move. when :SPECIAL_DEFENSE # Prefer if user has a healing item - mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) || - (@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON)) +# mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) || +# (@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON)) # Prefer if user knows any healing moves - mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? } +# mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? } # Prefer if user knows Pain Split or Leech Seed - mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split - mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed +# mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split +# mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed # Prefer if user has certain roles - mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL) - # Don't prefer if user's Defense stat is raised - sum_stages = @user.stages[:SPECIAL_DEFENSE] - mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0 - - # TODO: Prefer if foes have higher Special Attack than Attack. - +# mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL) +# # TODO: Prefer if foes have higher Special Attack than Attack. # TODO: Don't prefer if previous damage done by foes wouldn't hurt the # user much. when :ACCURACY - # Prefer if user knows any weaker moves mini_score *= 1.1 if check_for_move(@user) { |move| move.damagingMove? && move.basedamage < 95 } - # Prefer if target has a raised evasion sum_stages = @target.stages[:EVASION] mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0 @@ -355,20 +528,12 @@ class Battle::AI # Prefer if user has certain roles mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL) # TODO: Don't prefer if user's evasion stat is raised - # TODO: Don't prefer if target has No Guard. mini_score *= 0.2 if @target.hasActiveAbility?(:NOGUARD) # TODO: Don't prefer if target has previously used any moves that never miss. end - # Don't prefer if user has 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? && !@battle.moldBreaker && @target.hasActiveAbility?(:UNAWARE) # TODO: Don't prefer if any foe has previously used a stat stage-clearing # move (Clear Smog/Haze). @@ -390,47 +555,6 @@ class Battle::AI return mini_score end - #============================================================================= - # - #============================================================================= - def get_score_for_user_stat_raise(score) - # Discard status move if user has 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 - @move.stat_up.each_with_index do |stat, idx| - next if idx.odd? - next if @user.statStageAtMax?(stat) - can_change_any_stat = true - break - end - if !can_change_any_stat - return (@move.statusMove?) ? 0 : score - end - - # Get the main mini-score - main_mini_score = calc_user_stat_raise_mini_score - - # For each stat to be raised in turn, calculate a mini-score describing how - # beneficial that stat being raised will be - mini_score = 0 - num_stats = 0 - @move.stat_up.each_with_index do |stat, idx| - next if idx.odd? - next if @user.statStageAtMax?(stat) - # TODO: Use the effective increment (e.g. 1 if the stat is raised by 2 but - # the stat is already at +5). - mini_score += calc_user_stat_raise_one(stat, @move.stat_up[idx + 1]) - num_stats += 1 - end - - # Apply the average mini-score to the actual score - score = apply_effect_chance_to_score(main_mini_score * mini_score / num_stats) - - return score - end - #============================================================================= # #============================================================================= 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 c562261f0..bf669a5b1 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 @@ -1,5 +1,5 @@ #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAttack1", proc { |move, user, target, ai, battle| @@ -9,77 +9,17 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAttack1", ) Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack1", proc { |score, move, user, target, ai, battle| - if move.statusMove? - score -= user.stages[:ATTACK] * 20 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - if hasPhysicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - else - score += 20 if user.stages[:ATTACK] < 0 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - score += 20 if hasPhysicalAttack - end - end - next score + next ai.get_score_for_user_stat_raise(score) } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1", "RaiseUserAttack2") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - next score - 90 if user.statStageAtMax?(:ATTACK) - score += 40 if user.turnCount == 0 - score -= user.stages[:ATTACK] * 20 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - if hasPhysicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - else - score += 10 if user.turnCount == 0 - score += 20 if user.stages[:ATTACK] < 0 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - score += 20 if hasPhysicalAttack - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1", + "RaiseUserAttack2") #=============================================================================== # TODO: Review score modifiers. @@ -88,7 +28,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2", "RaiseUserAttack2IfTargetFaints") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack2", "RaiseUserAttack3") @@ -131,225 +71,94 @@ Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1", "RaiseUserDefense1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - next score - user.stages[:DEFENSE] * 20 - elsif user.stages[:DEFENSE] < 0 - next score + 20 - end - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1", + "RaiseUserDefense1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", "RaiseUserDefense1CurlUpUser") -Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1", - "RaiseUserDefense1CurlUpUser") +Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense1CurlUpUser", + proc { |score, move, user, target, ai, battle| + score = ai.get_score_for_user_stat_raise(score) + if !user.effects[PBEffects::DefenseCurl] && + user.check_for_move { |move| move.function == "MultiTurnAttackPowersUpEachTurn" } + score += 10 + end + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", "RaiseUserDefense2") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score -= user.stages[:DEFENSE] * 20 - else - score += 10 if user.turnCount == 0 - score += 20 if user.stages[:DEFENSE] < 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1", + "RaiseUserDefense2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", "RaiseUserDefense3") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefense3", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score -= user.stages[:DEFENSE] * 30 - else - score += 10 if user.turnCount == 0 - score += 30 if user.stages[:DEFENSE] < 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1", + "RaiseUserDefense3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAttack1", "RaiseUserSpAtk1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score -= user.stages[:SPECIAL_ATTACK] * 20 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecicalAttack = true - break - end - if hasSpecicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - else - score += 20 if user.stages[:SPECIAL_ATTACK] < 0 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecicalAttack = true - break - end - score += 20 if hasSpecicalAttack - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1", + "RaiseUserSpAtk1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpAtk1", "RaiseUserSpAtk2") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score -= user.stages[:SPECIAL_ATTACK] * 20 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecicalAttack = true - break - end - if hasSpecicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - else - score += 10 if user.turnCount == 0 - score += 20 if user.stages[:SPECIAL_ATTACK] < 0 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecicalAttack = true - break - end - score += 20 if hasSpecicalAttack - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpAtk1", + "RaiseUserSpAtk2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpAtk1", "RaiseUserSpAtk3") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtk3", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score -= user.stages[:SPECIAL_ATTACK] * 30 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecicalAttack = true - break - end - if hasSpecicalAttack - score += 30 - elsif ai.trainer.high_skill? - score -= 90 - end - end - else - score += 10 if user.turnCount == 0 - score += 30 if user.stages[:SPECIAL_ATTACK] < 0 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecicalAttack = true - break - end - score += 30 if hasSpecicalAttack - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpAtk1", + "RaiseUserSpAtk3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserDefense1", "RaiseUserSpDef1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score -= user.stages[:SPECIAL_DEFENSE] * 20 - else - score += 10 if user.turnCount == 0 - score += 20 if user.stages[:SPECIAL_DEFENSE] < 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserDefense1", + "RaiseUserSpDef1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", "RaiseUserSpDef1PowerUpElectricMove") Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpDef1PowerUpElectricMove", proc { |score, move, user, target, ai, battle| - foundMove = false - user.battler.eachMove do |m| - next if m.type != :ELECTRIC || !m.damagingMove? - foundMove = true - break - end - score += 20 if foundMove - if move.statusMove? - score -= user.stages[:SPECIAL_DEFENSE] * 20 - elsif user.stages[:SPECIAL_DEFENSE] < 0 - score += 20 + score = ai.get_score_for_user_stat_raise(score) + if user.check_for_move { |move| move.damagingMove? && move.type == :ELECTRIC } + score += 10 end next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", "RaiseUserSpDef2") @@ -357,7 +166,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1", "RaiseUserSpDef2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", "RaiseUserSpDef3") @@ -365,53 +174,23 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1", "RaiseUserSpDef3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpDef1", "RaiseUserSpeed1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score -= user.stages[:SPEED] * 10 - if ai.trainer.high_skill? - aspeed = user.rough_stat(:SPEED) - ospeed = target.rough_stat(:SPEED) - score += 30 if aspeed < ospeed && aspeed * 2 > ospeed - end - elsif user.stages[:SPEED] < 0 - score += 20 - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpDef1", + "RaiseUserSpeed1") #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1", "RaiseUserSpeed2") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 20 if user.turnCount == 0 - score -= user.stages[:SPEED] * 10 - if ai.trainer.high_skill? - aspeed = user.rough_stat(:SPEED) - ospeed = target.rough_stat(:SPEED) - score += 30 if aspeed < ospeed && aspeed * 2 > ospeed - end - else - score += 10 if user.turnCount == 0 - score += 20 if user.stages[:SPEED] < 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1", + "RaiseUserSpeed2") #=============================================================================== # TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2", "RaiseUserSpeed2LowerUserWeight") @@ -419,34 +198,23 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed2", "RaiseUserSpeed2LowerUserWeight") #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# #=============================================================================== -Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2", +Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1", "RaiseUserSpeed3") -Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed2", +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1", "RaiseUserSpeed3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1", "RaiseUserAccuracy1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAccuracy1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score -= user.stages[:ACCURACY] * 20 - else - score += 10 if user.turnCount == 0 - score += 20 if user.stages[:ACCURACY] < 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1", + "RaiseUserAccuracy1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1", "RaiseUserAccuracy2") @@ -454,7 +222,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1", "RaiseUserAccuracy2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1", "RaiseUserAccuracy3") @@ -462,38 +230,20 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1", "RaiseUserAccuracy3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAccuracy1", "RaiseUserEvasion1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserEvasion1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score -= user.stages[:EVASION] * 10 - elsif user.stages[:EVASION] < 0 - score += 20 - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAccuracy1", + "RaiseUserEvasion1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion1", "RaiseUserEvasion2") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserEvasion2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score -= user.stages[:EVASION] * 10 - else - score += 10 if user.turnCount == 0 - score += 20 if user.stages[:EVASION] < 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion1", + "RaiseUserEvasion2") #=============================================================================== # TODO: Review score modifiers. @@ -504,7 +254,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion2", "RaiseUserEvasion2MinimizeUser") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion2", "RaiseUserEvasion3") @@ -528,7 +278,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserCriticalHitRate2", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAtkDef1", proc { |move, user, target, ai, battle| @@ -543,106 +293,32 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserAtkDef1", end } ) -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkDef1", - proc { |score, move, user, target, ai, battle| - score -= user.stages[:ATTACK] * 10 - score -= user.stages[:DEFENSE] * 10 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - if hasPhysicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1", + "RaiseUserAtkDef1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1", "RaiseUserAtkDefAcc1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkDefAcc1", - proc { |score, move, user, target, ai, battle| - score -= user.stages[:ATTACK] * 10 - score -= user.stages[:DEFENSE] * 10 - score -= user.stages[:ACCURACY] * 10 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - if hasPhysicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkDef1", + "RaiseUserAtkDefAcc1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1", "RaiseUserAtkSpAtk1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1", - proc { |score, move, user, target, ai, battle| - score -= user.stages[:ATTACK] * 10 - score -= user.stages[:SPECIAL_ATTACK] * 10 - if ai.trainer.medium_skill? - hasDamagingAttack = false - user.battler.eachMove do |m| - next if !m.damagingMove? - hasDamagingAttack = true - break - end - if hasDamagingAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkDef1", + "RaiseUserAtkSpAtk1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", "RaiseUserAtkSpAtk1Or2InSun") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1Or2InSun", - proc { |score, move, user, target, ai, battle| - score -= user.stages[:ATTACK] * 10 - score -= user.stages[:SPECIAL_ATTACK] * 10 - if ai.trainer.medium_skill? - hasDamagingAttack = false - user.battler.eachMove do |m| - next if !m.damagingMove? - hasDamagingAttack = true - break - end - if hasDamagingAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - score += 20 if [:Sun, :HarshSun].include?(user.battler.effectiveWeather) - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", + "RaiseUserAtkSpAtk1Or2InSun") #=============================================================================== # TODO: Review score modifiers. @@ -684,190 +360,60 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDef1RaiseUserAtkSpAtkSp ) #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", "RaiseUserAtkSpd1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpd1", - proc { |score, move, user, target, ai, battle| - score += 40 if user.turnCount == 0 # Dragon Dance tends to be popular - score -= user.stages[:ATTACK] * 10 - score -= user.stages[:SPEED] * 10 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - if hasPhysicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - if ai.trainer.high_skill? - aspeed = user.rough_stat(:SPEED) - ospeed = target.rough_stat(:SPEED) - score += 20 if aspeed < ospeed && aspeed * 2 > ospeed - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", + "RaiseUserAtkSpd1") #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", "RaiseUserAtk1Spd2") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtk1Spd2", - proc { |score, move, user, target, ai, battle| - score -= user.stages[:ATTACK] * 10 - score -= user.stages[:SPEED] * 10 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - if hasPhysicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - if ai.trainer.high_skill? - aspeed = user.rough_stat(:SPEED) - ospeed = target.rough_stat(:SPEED) - score += 30 if aspeed < ospeed && aspeed * 2 > ospeed - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", + "RaiseUserAtk1Spd2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", "RaiseUserAtkAcc1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkAcc1", - proc { |score, move, user, target, ai, battle| - score -= user.stages[:ATTACK] * 10 - score -= user.stages[:ACCURACY] * 10 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - user.battler.eachMove do |m| - next if !m.physicalMove?(m.type) - hasPhysicalAttack = true - break - end - if hasPhysicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", + "RaiseUserAtkAcc1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", "RaiseUserDefSpDef1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserDefSpDef1", - proc { |score, move, user, target, ai, battle| - score -= user.stages[:DEFENSE] * 10 - score -= user.stages[:SPECIAL_DEFENSE] * 10 - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", + "RaiseUserDefSpDef1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", "RaiseUserSpAtkSpDef1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtkSpDef1", - proc { |score, move, user, target, ai, battle| - score += 40 if user.turnCount == 0 # Calm Mind tends to be popular - score -= user.stages[:SPECIAL_ATTACK] * 10 - score -= user.stages[:SPECIAL_DEFENSE] * 10 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecicalAttack = true - break - end - if hasSpecicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", + "RaiseUserSpAtkSpDef1") #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", "RaiseUserSpAtkSpDefSpd1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtkSpDefSpd1", - proc { |score, move, user, target, ai, battle| - score += 40 if user.turnCount == 0 # Calm Mind tends to be popular - score -= user.stages[:SPECIAL_ATTACK] * 10 - score -= user.stages[:SPECIAL_DEFENSE] * 10 - score -= user.stages[:SPEED] * 10 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - user.battler.eachMove do |m| - next if !m.specialMove?(m.type) - hasSpecicalAttack = true - break - end - if hasSpecicalAttack - score += 20 - elsif ai.trainer.high_skill? - score -= 90 - end - end - if ai.trainer.high_skill? - aspeed = user.rough_stat(:SPEED) - ospeed = target.rough_stat(:SPEED) - score += 20 if aspeed < ospeed && aspeed * 2 > ospeed - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", + "RaiseUserSpAtkSpDefSpd1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1", "RaiseUserMainStats1") -Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1", - proc { |score, move, user, target, ai, battle| - GameData::Stat.each_main_battle { |s| score += 10 if user.stages[s.id] < 0 } - if ai.trainer.medium_skill? - hasDamagingAttack = false - user.battler.eachMove do |m| - next if !m.damagingMove? - hasDamagingAttack = true - break - end - score += 20 if hasDamagingAttack - end - next score - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1", + "RaiseUserMainStats1") #=============================================================================== # TODO: Review score modifiers. @@ -1284,7 +830,7 @@ Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetDefense1", "LowerTargetDefense1PowersUpInGravity") Battle::AI::Handlers::MoveBasePower.add("LowerTargetDefense1PowersUpInGravity", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) Battle::AI::Handlers::MoveEffectScore.add("LowerTargetDefense1PowersUpInGravity", @@ -1504,7 +1050,7 @@ Battle::AI::Handlers::MoveFailureCheck.copy("LowerTargetSpeed1", "LowerTargetSpeed1WeakerInGrassyTerrain") Battle::AI::Handlers::MoveBasePower.add("LowerTargetSpeed1WeakerInGrassyTerrain", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) Battle::AI::Handlers::MoveEffectScore.copy("LowerTargetSpeed1", 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 f396afb63..77e6ecf70 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 @@ -425,7 +425,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetFailsIfNotUserFirstTurn", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky", 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 be1cba640..bd78df1df 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 @@ -3,7 +3,7 @@ #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("FixedDamage20", proc { |power, move, user, target, ai, battle| - next move.pbFixedDamage(user.battler, target.battler) + next move.move.pbFixedDamage(user.battler, target.battler) } ) @@ -12,7 +12,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamage20", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("FixedDamage40", proc { |power, move, user, target, ai, battle| - next move.pbFixedDamage(user.battler, target.battler) + next move.move.pbFixedDamage(user.battler, target.battler) } ) @@ -21,7 +21,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamage40", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("FixedDamageHalfTargetHP", proc { |power, move, user, target, ai, battle| - next move.pbFixedDamage(user.battler, target.battler) + next move.move.pbFixedDamage(user.battler, target.battler) } ) @@ -30,7 +30,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamageHalfTargetHP", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevel", proc { |power, move, user, target, ai, battle| - next move.pbFixedDamage(user.battler, target.battler) + next move.move.pbFixedDamage(user.battler, target.battler) } ) @@ -53,7 +53,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetHPToUserHP", ) Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP", proc { |power, move, user, target, ai, battle| - next move.pbFixedDamage(user.battler, target.battler) + next move.move.pbFixedDamage(user.battler, target.battler) } ) @@ -112,7 +112,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DamageTargetAlly", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithUserHP", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) @@ -181,7 +181,7 @@ Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithLessPP", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithTargetWeight", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) @@ -215,7 +215,7 @@ Battle::AI::Handlers::MoveBasePower.add("PowerHigherWithConsecutiveUseOnUserSide Battle::AI::Handlers::MoveBasePower.add("RandomPowerDoublePowerIfTargetUnderground", proc { |power, move, user, target, ai, battle| power = 71 # Average damage - next move.pbModifyDamage(power, user.battler, target.battler) + next move.move.pbModifyDamage(power, user.battler, target.battler) } ) @@ -224,7 +224,7 @@ Battle::AI::Handlers::MoveBasePower.add("RandomPowerDoublePowerIfTargetUndergrou #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetHPLessThanHalf", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) @@ -251,7 +251,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetAsleepCureTarget", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) @@ -271,7 +271,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetParalyzedCureTarge #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetStatusProblem", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) @@ -289,7 +289,7 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfUserHasNoItem", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetUnderwater", proc { |power, move, user, target, ai, battle| - next move.pbModifyDamage(power, user.battler, target.battler) + next move.move.pbModifyDamage(power, user.battler, target.battler) } ) @@ -304,7 +304,7 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetUnderwater", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetInSky", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) @@ -818,7 +818,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndD #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) @@ -834,8 +834,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("TypeAndPowerDependOnUserBerry", ) Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnUserBerry", proc { |power, move, user, target, ai, battle| - # TODO: Can't this just call move.pbBaseDamage? - ret = move.pbNaturalGiftBaseDamage(user.item_id) + # TODO: Can't this just call move.move.pbBaseDamage? + ret = move.move.pbNaturalGiftBaseDamage(user.item_id) next (ret == 1) ? 0 : ret } ) @@ -874,7 +874,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TypeDependsOnUserMorpekoFormRaiseUser #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnWeather", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) 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 2f6015f34..5605995b9 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 @@ -3,7 +3,7 @@ #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes", proc { |power, move, user, target, ai, battle| - next power * move.pbNumHits(user.battler, [target.battler]) + next power * move.move.pbNumHits(user.battler, [target.battler]) } ) @@ -64,7 +64,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesAlwaysCriticalHit", proc { |power, move, user, target, ai, battle| - next power * move.pbNumHits(user.battler, [target.battler]) + next power * move.move.pbNumHits(user.battler, [target.battler]) } ) Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesAlwaysCriticalHit", @@ -92,7 +92,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes", Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja", proc { |power, move, user, target, ai, battle| if user.battler.isSpecies?(:GRENINJA) && user.battler.form == 2 - next move.pbBaseDamage(power, user.battler, target.battler) * move.pbNumHits(user.battler, [target.battler]) + next move.move.pbBaseDamage(power, user.battler, target.battler) * move.move.pbNumHits(user.battler, [target.battler]) end next power * 5 if user.has_active_ability?(:SKILLLINK) next power * 31 / 10 # Average damage dealt @@ -161,7 +161,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamageMultiplier(power, user.battler, target.battler) + next move.move.pbBaseDamageMultiplier(power, user.battler, target.battler) } ) @@ -338,7 +338,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackInvulnerableInSkyTarget #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn", proc { |power, move, user, target, ai, battle| - next power * 2 if user.effects[PBEffects::DefenseCurl] + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) 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 a8e500b84..28432b41d 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 @@ -82,7 +82,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("RemoveTargetItem", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem", @@ -260,6 +260,6 @@ Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget", ) Battle::AI::Handlers::MoveBasePower.add("ThrowUserItemAtTarget", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) diff --git a/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb b/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb index 8b82dfcbf..966294463 100644 --- a/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb +++ b/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb @@ -110,7 +110,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CurseTargetOrLowerUserSpd1RaiseUserAt #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("HitsAllFoesAndPowersUpInPsychicTerrain", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain", @@ -261,7 +261,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("PowerDependsOnUserStockpile", ) Battle::AI::Handlers::MoveBasePower.add("PowerDependsOnUserStockpile", proc { |power, move, user, target, ai, battle| - next move.pbBaseDamage(power, user.battler, target.battler) + next move.move.pbBaseDamage(power, user.battler, target.battler) } ) 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 5f07593b0..7cfe31180 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 @@ -171,7 +171,7 @@ Battle::AI::Handlers::MoveEffectScore.add("BindTarget", #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater", proc { |power, move, user, target, ai, battle| - next move.pbModifyDamage(power, user.battler, target.battler) + next move.move.pbModifyDamage(power, user.battler, target.battler) } ) Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater", diff --git a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb index 65635c062..514fc8c67 100644 --- a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb +++ b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb @@ -24,7 +24,8 @@ class Battle::AI::AIBattler def level; return @battler.level; end def hp; return @battler.hp; end - def status; return @Battler.status; end + def fainted?; return @battler.fainted?; end + def status; return @battler.status; end def statusCount; return @battler.statusCount; end def totalhp; return @battler.totalhp; end def gender; return @battler.gender; end @@ -57,12 +58,103 @@ class Battle::AI::AIBattler #============================================================================= - def check_for_move - ret = false - @battler.eachMove do |move| - next unless yield move - ret = true - break + # Returns how much damage this battler will take at the end of this round. + def rough_end_of_round_damage + ret = 0 + # Future Sight/Doom Desire + # TODO + # Wish + if @ai.battle.positions[@index].effects[PBEffects::Wish] == 1 && @battler.canHeal? + ret -= @ai.battle.positions[@index].effects[PBEffects::WishAmount] + end + # Sea of Fire + if @ai.battle.sides[@side].effects[PBEffects::SeaOfFire] > 1 && + @battler.takesIndirectDamage? && !has_type?(:FIRE) + ret += self.totalhp / 8 + end + # Grassy Terrain (healing) + if @ai.battle.field.terrain == :Grassy && @battler.affectedByTerrain? && @battler.canHeal? + ret -= [battler.totalhp / 16, 1].max + end + # Leftovers/Black Sludge + if has_active_item?(:BLACKSLUDGE) + if has_type?(:POISON) + ret -= [battler.totalhp / 16, 1].max if @battler.canHeal? + else + ret += [battler.totalhp / 8, 1].max if @battler.takesIndirectDamage? + end + elsif has_active_item?(:LEFTOVERS) + ret -= [battler.totalhp / 16, 1].max if @battler.canHeal? + end + # Aqua Ring + if self.effects[PBEffects::AquaRing] && @battler.canHeal? + amt = battler.totalhp / 16 + amt = (amt * 1.3).floor if has_active_item?(:BIGROOT) + ret -= [amt, 1].max + end + # Ingrain + if self.effects[PBEffects::Ingrain] && @battler.canHeal? + amt = battler.totalhp / 16 + amt = (amt * 1.3).floor if has_active_item?(:BIGROOT) + ret -= [amt, 1].max + end + # Leech Seed + if self.effects[PBEffects::LeechSeed] >= 0 + if @battler.takesIndirectDamage? + ret += [battler.totalhp / 8, 1].max if @battler.takesIndirectDamage? + end + else + @ai.each_battler do |b, i| + next if i == @index || b.effects[PBEffects::LeechSeed] != @index + amt = [[b.totalhp / 8, b.hp].min, 1].max + amt = (amt * 1.3).floor if has_active_item?(:BIGROOT) + ret -= [amt, 1].max + end + end + # Hyper Mode (Shadow Pokémon) + # TODO + # Poison/burn/Nightmare + if self.status == :POISON + if has_active_ability?(:POISONHEAL) + ret -= [battler.totalhp / 8, 1].max if @battler.canHeal? + elsif @battler.takesIndirectDamage? + mult = 2 + mult = [self.effects[PBEffects::Toxic] + 1, 16].min if self.statusCount > 0 # Toxic + ret += [mult * battler.totalhp / 16, 1].max + end + elsif self.status == :BURN + if @battler.takesIndirectDamage? + amt = (Settings::MECHANICS_GENERATION >= 7) ? self.totalhp / 16 : self.totalhp / 8 + amt = (amt / 2.0).round if has_active_ability?(:HEATPROOF) + ret += [amt, 1].max + end + elsif @battler.asleep? && self.statusCount > 1 && self.effects[PBEffects::Nightmare] + ret += [battler.totalhp / 4, 1].max if @battler.takesIndirectDamage? + end + # Curse + if self.effects[PBEffects::Curse] + ret += [battler.totalhp / 4, 1].max if @battler.takesIndirectDamage? + end + # Trapping damage + if self.effects[PBEffects::Trapping] > 1 && @battler.takesIndirectDamage? + amt = (Settings::MECHANICS_GENERATION >= 6) ? self.totalhp / 8 : self.totalhp / 16 + if @battlers[self.effects[PBEffects::TrappingUser]].has_active_item?(:BINDINGBAND) + amt = (Settings::MECHANICS_GENERATION >= 6) ? self.totalhp / 6 : self.totalhp / 8 + end + ret += [amt, 1].max + end + # Perish Song + # TODO + # Bad Dreams + if @battler.asleep? && self.statusCount > 1 && @battler.takesIndirectDamage? + @ai.each_battler do |b, i| + next if i == @index || !b.battler.near?(@battler) || !b.has_active_ability?(:BADDREAMS) + ret += [battler.totalhp / 8, 1].max + end + end + # Sticky Barb + if has_active_item?(:STICKYBARB) && @battler.takesIndirectDamage? + ret += [battler.totalhp / 8, 1].max end return ret end @@ -163,16 +255,16 @@ class Battle::AI::AIBattler #============================================================================= - def can_switch_lax? - return false if wild? - @ai.battle.eachInTeamFromBattlerIndex(@index) do |pkmn, i| - return true if @ai.battle.pbCanSwitchLax?(@index, i) + def check_for_move + ret = false + @battler.eachMove do |move| + next unless yield move + ret = true + break end - return false + return ret end - #============================================================================= - def immune_to_move? user = @ai.user user_battler = user.battler @@ -226,6 +318,16 @@ class Battle::AI::AIBattler #============================================================================= + def can_switch_lax? + return false if wild? + @ai.battle.eachInTeamFromBattlerIndex(@index) do |pkmn, i| + return true if @ai.battle.pbCanSwitchLax?(@index, i) + end + return false + end + + #============================================================================= + private def effectiveness_of_type_against_single_battler_type(type, defend_type, user = nil) diff --git a/Data/Scripts/011_Battle/006_Other battle code/008_Battle_AbilityEffects.rb b/Data/Scripts/011_Battle/006_Other battle code/008_Battle_AbilityEffects.rb index b2b11bf71..40ac1d1bf 100644 --- a/Data/Scripts/011_Battle/006_Other battle code/008_Battle_AbilityEffects.rb +++ b/Data/Scripts/011_Battle/006_Other battle code/008_Battle_AbilityEffects.rb @@ -1207,7 +1207,7 @@ Battle::AbilityEffects::DamageCalcFromUser.add(:ANALYTIC, # are being used), so I'm choosing to ignore it. The effect is thus: # "power up the move if all other battlers on the field right now have # already moved". - if move.pbMoveFailedLastInRound?(user, false) + if move.move.pbMoveFailedLastInRound?(user, false) mults[:base_damage_multiplier] *= 1.3 end } @@ -1528,7 +1528,7 @@ Battle::AbilityEffects::DamageCalcFromTarget.add(:FLOWERGIFT, Battle::AbilityEffects::DamageCalcFromTarget.add(:FLUFFY, proc { |ability, user, target, move, mults, baseDmg, type| mults[:final_damage_multiplier] *= 2 if move.calcType == :FIRE - mults[:final_damage_multiplier] /= 2 if move.pbContactMove?(user) + mults[:final_damage_multiplier] /= 2 if move.move.pbContactMove?(user) } ) diff --git a/Data/Scripts/014_Pokemon/001_Pokemon.rb b/Data/Scripts/014_Pokemon/001_Pokemon.rb index a2eb88e22..be09a9fff 100644 --- a/Data/Scripts/014_Pokemon/001_Pokemon.rb +++ b/Data/Scripts/014_Pokemon/001_Pokemon.rb @@ -540,7 +540,7 @@ class Pokemon # @return [Boolean] whether this Pokémon has a particular nature or a nature # at all def hasNature?(check_nature = nil) - return !@nature_id.nil? if check_nature.nil? + return !@nature.nil? if check_nature.nil? return self.nature == check_nature end