diff --git a/Data/Scripts/011_Battle/003_Move/006_MoveEffects_BattlerStats.rb b/Data/Scripts/011_Battle/003_Move/006_MoveEffects_BattlerStats.rb index 69c663759..87a6fac6b 100644 --- a/Data/Scripts/011_Battle/003_Move/006_MoveEffects_BattlerStats.rb +++ b/Data/Scripts/011_Battle/003_Move/006_MoveEffects_BattlerStats.rb @@ -1355,6 +1355,8 @@ end # stage each. (Venom Drench) #=============================================================================== class Battle::Move::LowerPoisonedTargetAtkSpAtkSpd1 < Battle::Move + attr_reader :statDown + def canMagicCoat?; return true; end def initialize(battle, move) @@ -1367,10 +1369,13 @@ class Battle::Move::LowerPoisonedTargetAtkSpAtkSpd1 < Battle::Move targets.each do |b| next if !b || b.fainted? next if !b.poisoned? - next if !b.pbCanLowerStatStage?(:ATTACK, user, self) && - !b.pbCanLowerStatStage?(:SPECIAL_ATTACK, user, self) && - !b.pbCanLowerStatStage?(:SPEED, user, self) - @validTargets.push(b.index) + failed = true + (@statDown.length / 2).times do |i| + next if !target.pbCanLowerStatStage?(@statDown[i * 2], user, self) + failed = false + break + end + @validTargets.push(b.index) if !failed end if @validTargets.length == 0 @battle.pbDisplay(_INTL("But it failed!")) 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 7ceb7d9f8..f83dc2847 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 @@ -59,7 +59,7 @@ class Battle::AI # CategoryDependsOnHigherDamageIgnoreTargetAbility. #============================================================================= def stat_raise_worthwhile?(stat) - return false if !@user.battler.pbCanRaiseStatStage?(stat, @user.battler, @move) + return false if !@user.battler.pbCanRaiseStatStage?(stat, @user.battler, @move.move) # Check if user won't benefit from the stat being raised # TODO: Exception if user knows Baton Pass/Stored Power? case stat @@ -69,18 +69,16 @@ class Battle::AI m.function != "UseTargetAttackInsteadOfUserAttack" } when :DEFENSE each_foe_battler(@user.side) do |b, i| - next if !b.check_for_move { |m| m.physicalMove?(m.type) || - m.function == "UseTargetDefenseInsteadOfTargetSpDef" } - return true + return true if b.check_for_move { |m| m.physicalMove?(m.type) || + m.function == "UseTargetDefenseInsteadOfTargetSpDef" } end return false when :SPECIAL_ATTACK return false if !@user.check_for_move { |m| m.specialMove?(m.type) } when :SPECIAL_DEFENSE each_foe_battler(@user.side) do |b, i| - next if !b.check_for_move { |m| m.specialMove?(m.type) && - m.function != "UseTargetDefenseInsteadOfTargetSpDef" } - return true + return true if b.check_for_move { |m| m.specialMove?(m.type) && + m.function != "UseTargetDefenseInsteadOfTargetSpDef" } end return false when :SPEED @@ -103,12 +101,6 @@ class Battle::AI #============================================================================= # 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. - # LowerUserDefSpDef1RaiseUserAtkSpAtkSpd2 Shell Smash - # RaiseTargetRandomStat2 Acupressure - # RaisePlusMinusUserAndAlliesDefSpDef1 Magnetic Flux - # RaisePlusMinusUserAndAlliesAtkSpAtk1 Gear Up 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 @@ -154,17 +146,11 @@ class Battle::AI break end - # Prefer if user has most of its HP - if @user.hp >= @user.totalhp * 3 / 4 - mini_score *= (sweeping_stat) ? 1.2 : 1.1 - end # 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 || (@user.form == 0 && @user.ability_id == :DISGUISE) - # Don't prefer if user doesn't have much HP left - mini_score *= 0.3 if @user.hp < @user.totalhp / 3 # Don't prefer if user is badly poisoned mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0 && !offensive_stat # Don't prefer if user is confused @@ -296,6 +282,8 @@ class Battle::AI when :SPEED # Prefer if user is slower than a foe + # TODO: Don't prefer if the user is too much slower than any foe that it + # can't catch up. each_foe_battler(@user.side) do |b, i| next if @user.faster_than?(b) score += 15 * inc_mult @@ -319,7 +307,7 @@ class Battle::AI next if m.accuracy == 0 || m.is_a?(Battle::Move::OHKO) min_accuracy = m.accuracy if m.accuracy < min_accuracy end - min_accuracy *= stage_mul[old_stage] / stage_div[old_stage] + min_accuracy = min_accuracy * stage_mul[old_stage] / stage_div[old_stage] if min_accuracy < 90 score += 5 * (3 - old_stage) * inc_mult score += 5 * inc_mult if @user.hp == @user.totalhp @@ -345,18 +333,14 @@ class Battle::AI end - # Check impact on moves of gaining stat stages - pos_change = [old_stage + increment, increment].min - if pos_change > 0 - # Prefer if user has Stored Power - if @user.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" } - score += 5 * 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 { |m| m.function == "PowerHigherWithTargetPositiveStatStages" } - score -= 5 * pos_change - end + # Prefer if user has Stored Power + if @user.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" } + score += 5 * 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 { |m| m.function == "PowerHigherWithTargetPositiveStatStages" } + score -= 5 * pos_change end return score @@ -569,6 +553,247 @@ class Battle::AI =end end + #============================================================================= + # Main method for calculating the score for moves that lower the target's + # stat(s). + # TODO: Revisit this method as parts may need rewriting. + #============================================================================= + def get_score_for_target_stat_drop(score) + # Discard status move/don't prefer damaging move if target has Contrary + if !@battle.moldBreaker && @target.has_active_ability?(:CONTRARY) + return (@move.statusMove?) ? MOVE_USELESS_SCORE : score - 20 + end + # Don't make score changes if foes have Unaware and user can't make use of + # extra stat stages + ally_is_aware = false + each_foe_battler(@target.side) do |b, i| + ally_is_aware = true if !b.has_active_ability?(:UNAWARE) + end + return score if !ally_is_aware + + # Figure out which stat raises can happen + stat_changes = [] + @move.move.statDown.each_with_index do |stat, idx| + next if idx.odd? + next if !stat_drop_worthwhile?(stat) + # Calculate amount that stat will be raised by + decrement = @move.move.statDown[idx + 1] + decrement *= 2 if !@battle.moldBreaker && @user.has_active_ability?(:SIMPLE) + decrement = [decrement, 6 + @target.stages[stat]].min # The actual stages lost + # Count this as a valid stat drop + stat_changes.push([stat, decrement]) if decrement > 0 + end + # Discard move if it can't lower any stats + if stat_changes.length == 0 + # TODO: Have a parameter that decides whether to reduce the score here + # (for moves where this is just part of the effect). + return (@move.statusMove?) ? MOVE_USELESS_SCORE : score + end + + # Make score changes based on the general concept of lowering stats at all + score = get_target_stat_drop_score_generic(score, stat_changes) + + # Make score changes based on the specific changes to each stat that will be + # lowered + stat_changes.each do |change| + score = get_target_stat_drop_score_one(score, change[0], change[1]) + end + + return score + end + + #============================================================================= + # Returns whether the target lowering 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. + # TODO: Revisit this method as parts may need rewriting. + #============================================================================= + def stat_drop_worthwhile?(stat) + return false if !@target.battler.pbCanLowerStatStage?(stat, @user.battler, @move.move) + # Check if target won't benefit from the stat being lowered + case stat + when :ATTACK + return false if !@target.check_for_move { |m| m.physicalMove?(m.type) && + m.function != "UseUserDefenseInsteadOfUserAttack" && + m.function != "UseTargetAttackInsteadOfUserAttack" } + when :DEFENSE + each_foe_battler(@target.side) do |b, i| + return true if b.check_for_move { |m| m.physicalMove?(m.type) || + m.function == "UseTargetDefenseInsteadOfTargetSpDef" } + end + return false + when :SPECIAL_ATTACK + return false if !@target.check_for_move { |m| m.specialMove?(m.type) } + when :SPECIAL_DEFENSE + each_foe_battler(@target.side) do |b, i| + return true if b.check_for_move { |m| m.specialMove?(m.type) && + m.function != "UseTargetDefenseInsteadOfTargetSpDef" } + end + return false + when :SPEED + moves_that_prefer_high_speed = [ + "PowerHigherWithUserFasterThanTarget", + "PowerHigherWithUserPositiveStatStages" + ] + if !@target.check_for_move { |m| moves_that_prefer_high_speed.include?(m.function) } + each_foe_battler(@target.side) do |b, i| + return true if !b.faster_than?(@target) + end + return false + end + when :ACCURACY + when :EVASION + end + return true + end + + #============================================================================= + # Make score changes based on the general concept of lowering stats at all. + # TODO: Revisit this method as parts may need rewriting. + # TODO: All comments in this method may be inaccurate. + #============================================================================= + def get_target_stat_drop_score_generic(score, stat_changes) + total_decrement = stat_changes.sum { |change| change[1] } + # TODO: Just return if target is predicted to switch out (except via Baton Pass). + # TODO: Don't prefer if target is faster than user and is predicted to deal + # lethal damage. + # TODO: Don't prefer if target is slower than user but is predicted to be able + # to 2HKO user. + # TODO: Don't prefer if target is semi-invulnerable and user is faster. + + # Prefer if move is a status move and it's the user's first/second turn +# if @user.turnCount < 2 && @move.statusMove? +# score += total_decrement * 4 +# 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 += 4 * total_decrement +# else +# score += total_decrement * ((100 * @user.hp / @user.totalhp) - 50) / 4 # +5 to -12 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 lowering. + + return score + end + + #============================================================================= + # Make score changes based on the lowering of a specific stat. + # TODO: Revisit this method as parts may need rewriting. + #============================================================================= + def get_target_stat_drop_score_one(score, stat, decrement) + # Figure out how much the stat will actually change by + stage_mul = [2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8] + stage_div = [8, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2] + if [:ACCURACY, :EVASION].include?(stat) + stage_mul = [3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9] + stage_div = [9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3] + end + old_stage = @target.stages[stat] + new_stage = old_stage - decrement + dec_mult = (stage_mul[old_stage].to_f * stage_div[new_stage]) / (stage_div[old_stage] * stage_mul[new_stage]) + dec_mult -= 1 + # Stat-based score changes + case stat + when :ATTACK + # Modify score depending on current stat stage + # More strongly prefer if the target has no special moves + if old_stage <= -3 + score -= 20 + else + has_special_moves = @target.check_for_move { |m| m.specialMove?(m.type) } + dec = (has_special_moves) ? 5 : 10 + score += dec * (3 + old_stage) * dec_mult + score += 5 * dec_mult if @target.hp == @target.totalhp + end + + when :DEFENSE + # Modify score depending on current stat stage + if old_stage <= -3 + score -= 20 + else + score += 5 * (3 + old_stage) * dec_mult + score += 5 * dec_mult if @target.hp == @target.totalhp + end + + when :SPECIAL_ATTACK + # Modify score depending on current stat stage + # More strongly prefer if the target has no physical moves + if old_stage <= -3 + score -= 20 + else + has_physical_moves = @target.check_for_move { |m| m.physicalMove?(m.type) && + m.function != "UseUserDefenseInsteadOfUserAttack" && + m.function != "UseTargetAttackInsteadOfUserAttack" } + dec = (has_physical_moves) ? 5 : 10 + score += dec * (3 + old_stage) * dec_mult + score += 5 * dec_mult if @target.hp == @target.totalhp + end + + when :SPECIAL_DEFENSE + # Modify score depending on current stat stage + if old_stage <= -3 + score -= 20 + else + score += 5 * (3 + old_stage) * dec_mult + score += 5 * dec_mult if @target.hp == @target.totalhp + end + + when :SPEED + # Prefer if target is faster than an ally + # TODO: Don't prefer if the target is too much faster than any ally and + # can't be brought slow enough. + each_foe_battler(@target.side) do |b, i| + next if b.faster_than?(@target) + score += 15 * dec_mult + break + end + # Prefer if any ally has Electro Ball + each_foe_battler(@target.side) do |b, i| + next if !b.check_for_move { |m| m.function == "PowerHigherWithUserFasterThanTarget" } + score += 8 * dec_mult + end + # Don't prefer if target has Speed Boost (will be gaining Speed anyway) + score -= 20 if @target.has_active_ability?(:SPEEDBOOST) + + when :ACCURACY + # Modify score depending on current stat stage + if old_stage <= -3 + score -= 20 + else + score += 5 * (3 + old_stage) * dec_mult + score += 5 * dec_mult if @target.hp == @target.totalhp + end + + when :EVASION + # Modify score depending on current stat stage + if old_stage <= -3 + score -= 20 + else + score += 5 * (3 + old_stage) * dec_mult + score += 5 * dec_mult if @target.hp == @target.totalhp + end + + end + + # Prefer if target has Stored Power + if @target.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" } + score += 5 * decrement + end + # Don't prefer if any ally has Punishment + each_foe_battler(@target.side) do |b, i| + next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetPositiveStatStages" } + score -= 5 * decrement + end + + 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 143a3fd19..0ad9af9c3 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 @@ -739,7 +739,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetAtkSpAtk2", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAttack1", proc { |move, user, target, ai, battle| @@ -749,104 +749,28 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAttack1", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAttack1", proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.stages[:ATTACK] * 20 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - target.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 target.stages[:ATTACK] > 0 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - target.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_target_stat_drop(score) } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack1", "LowerTargetAttack1BypassSubstitute") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAttack1BypassSubstitute", - proc { |score, move, user, target, ai, battle| - score += target.stages[:ATTACK] * 20 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - target.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::MoveEffectAgainstTargetScore.copy("LowerTargetAttack1", + "LowerTargetAttack1BypassSubstitute") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack1", "LowerTargetAttack2") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAttack2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score += target.stages[:ATTACK] * 20 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - target.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 target.stages[:ATTACK] > 0 - if ai.trainer.medium_skill? - hasPhysicalAttack = false - target.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::MoveEffectAgainstTargetScore.copy("LowerTargetAttack1", + "LowerTargetAttack2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack2", "LowerTargetAttack3") @@ -854,62 +778,36 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAttack2", "LowerTargetAttack3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack1", "LowerTargetDefense1") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetDefense1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.stages[:DEFENSE] * 20 - elsif target.stages[:DEFENSE] > 0 - score += 20 - end - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAttack1", + "LowerTargetDefense1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetDefense1", "LowerTargetDefense1PowersUpInGravity") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetDefense1", + "LowerTargetDefense1PowersUpInGravity") Battle::AI::Handlers::MoveBasePower.add("LowerTargetDefense1PowersUpInGravity", proc { |power, move, user, target, ai, battle| next move.move.pbBaseDamage(power, user.battler, target.battler) } ) -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetDefense1PowersUpInGravity", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.stages[:DEFENSE] * 20 - elsif target.stages[:DEFENSE] > 0 - score += 20 - end - next score - } -) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetDefense1", "LowerTargetDefense2") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetDefense2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score += target.stages[:DEFENSE] * 20 - else - score += 10 if user.turnCount == 0 - score += 20 if target.stages[:DEFENSE] > 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetDefense1", + "LowerTargetDefense2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetDefense2", "LowerTargetDefense3") @@ -917,58 +815,23 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetDefense2", "LowerTargetDefense3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAttack1", "LowerTargetSpAtk1") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpAtk1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += user.stages[:SPECIAL_ATTACK] * 20 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - target.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 - target.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::MoveEffectAgainstTargetScore.copy("LowerTargetAttack1", + "LowerTargetSpAtk1") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpAtk1", "LowerTargetSpAtk2") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpAtk2", - proc { |score, move, user, target, ai, battle| - score += 40 if user.turnCount == 0 - score += target.stages[:SPECIAL_ATTACK] * 20 - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpAtk1", + "LowerTargetSpAtk2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetSpAtk2IfCanAttract", proc { |move, user, target, ai, battle| @@ -978,90 +841,35 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetSpAtk2IfCanA next true if !battle.moldBreaker && target.has_active_ability?(:OBLIVIOUS) } ) -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpAtk2IfCanAttract", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score += target.stages[:SPECIAL_ATTACK] * 20 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - target.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 target.stages[:SPECIAL_ATTACK] > 0 - if ai.trainer.medium_skill? - hasSpecicalAttack = false - target.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::MoveEffectAgainstTargetScore.copy("LowerTargetSpAtk2", + "LowerTargetSpAtk2IfCanAttract") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpAtk1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpAtk2", "LowerTargetSpAtk3") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpAtk3", - proc { |score, move, user, target, ai, battle| - score += 40 if user.turnCount == 0 - score += target.stages[:SPECIAL_ATTACK] * 20 - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpAtk2", + "LowerTargetSpAtk3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetDefense1", "LowerTargetSpDef1") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpDef1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.stages[:SPECIAL_DEFENSE] * 20 - elsif target.stages[:SPECIAL_DEFENSE] > 0 - score += 20 - end - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetDefense1", + "LowerTargetSpDef1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpDef1", "LowerTargetSpDef2") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpDef2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 40 if user.turnCount == 0 - score += target.stages[:SPECIAL_DEFENSE] * 20 - else - score += 10 if user.turnCount == 0 - score += 20 if target.stages[:SPECIAL_DEFENSE] > 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpDef1", + "LowerTargetSpDef2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpDef2", "LowerTargetSpDef3") @@ -1069,87 +877,59 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpDef2", "LowerTargetSpDef3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpDef1", "LowerTargetSpeed1") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.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::MoveEffectAgainstTargetScore.copy("LowerTargetSpDef1", + "LowerTargetSpeed1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpeed1", "LowerTargetSpeed1WeakerInGrassyTerrain") +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpeed1", + "LowerTargetSpeed1WeakerInGrassyTerrain") Battle::AI::Handlers::MoveBasePower.add("LowerTargetSpeed1WeakerInGrassyTerrain", proc { |power, move, user, target, ai, battle| next move.move.pbBaseDamage(power, user.battler, target.battler) } ) -Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpeed1", - "LowerTargetSpeed1WeakerInGrassyTerrain") #=============================================================================== # TODO: Review score modifiers. #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetSpeed1MakeTargetWeakerToFire", proc { |move, user, target, ai, battle| - next false if !target.effects[PBEffects::TarShot] - next true if move.statusMove? && - !target.battler.pbCanLowerStatStage?(move.move.statDown[0], user.battler, move.move) + if !target.effects[PBEffects::TarShot] + next true if move.statusMove? && + !target.battler.pbCanLowerStatStage?(move.move.statDown[0], user.battler, move.move) + end } ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed1MakeTargetWeakerToFire", proc { |score, move, user, target, ai, battle| - score += target.stages[:SPEED] * 10 - if ai.trainer.high_skill? - aspeed = user.rough_stat(:SPEED) - ospeed = target.rough_stat(:SPEED) - score += 50 if aspeed < ospeed && aspeed * 2 > ospeed + # Score for stat drop + score = ai.get_score_for_target_stat_drop(score) + # Score for adding weakness to Fire + if !target.effects[PBEffects::TarShot] + score += 20 if user.battler.moves.any? { |m| m.damagingMove? && m.pbCalcType(user.battler) == :FIRE } end - score += 20 if user.battler.moves.any? { |m| m.damagingMove? && m.pbCalcType(user.battler) == :FIRE } next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpeed1", "LowerTargetSpeed2") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += 20 if user.turnCount == 0 - score += target.stages[:SPEED] * 20 - 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 += 30 if target.stages[:SPEED] > 0 - end - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpeed1", + "LowerTargetSpeed2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpeed2", "LowerTargetSpeed3") @@ -1157,23 +937,15 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpeed2", "LowerTargetSpeed3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetSpeed1", "LowerTargetAccuracy1") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAccuracy1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.stages[:ACCURACY] * 10 - elsif target.stages[:ACCURACY] > 0 - score += 20 - end - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetSpeed1", + "LowerTargetAccuracy1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAccuracy1", "LowerTargetAccuracy2") @@ -1181,28 +953,20 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAccuracy1", "LowerTargetAccuracy2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAccuracy1", +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAccuracy2", "LowerTargetAccuracy3") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAccuracy1", +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAccuracy2", "LowerTargetAccuracy3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAccuracy1", "LowerTargetEvasion1") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion1", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.stages[:EVASION] * 10 - elsif target.stages[:EVASION] > 0 - score += 20 - end - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAccuracy1", + "LowerTargetEvasion1") #=============================================================================== # TODO: Review score modifiers. @@ -1232,11 +996,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetEvasion1Remo ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion1RemoveSideEffects", proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.stages[:EVASION] * 10 - elsif target.stages[:EVASION] > 0 - score += 20 - end + # Score for stat drop + score = ai.get_score_for_target_stat_drop(score) + # Score for removing side effects/terrain score += 30 if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 || target.pbOwnSide.effects[PBEffects::Reflect] > 0 || target.pbOwnSide.effects[PBEffects::LightScreen] > 0 || @@ -1250,23 +1012,15 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion1Remov ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetEvasion1", "LowerTargetEvasion2") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion2", - proc { |score, move, user, target, ai, battle| - if move.statusMove? - score += target.stages[:EVASION] * 10 - elsif target.stages[:EVASION] > 0 - score += 20 - end - next score - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetEvasion1", + "LowerTargetEvasion2") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetEvasion2", "LowerTargetEvasion3") @@ -1274,10 +1028,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetEvasion2", "LowerTargetEvasion3") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAtkDef1", proc { |move, user, target, ai, battle| + next false if !move.statusMove? will_fail = true (move.move.statDown.length / 2).times do |i| next if !target.battler.pbCanLowerStatStage?(move.move.statDown[i * 2], user.battler, move.move) @@ -1287,26 +1042,16 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAtkDef1", next will_fail } ) -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkDef1", - proc { |score, move, user, target, ai, battle| - avg = target.stages[:ATTACK] * 10 - avg += target.stages[:DEFENSE] * 10 - next score + avg / 2 - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAttack1", + "LowerTargetAtkDef1") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("LowerTargetAtkDef1", "LowerTargetAtkSpAtk1") -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkSpAtk1", - proc { |score, move, user, target, ai, battle| - avg = target.stages[:ATTACK] * 10 - avg += target.stages[:SPECIAL_ATTACK] * 10 - next score + avg / 2 - } -) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAtkDef1", + "LowerTargetAtkSpAtk1") #=============================================================================== # TODO: Review score modifiers. @@ -1314,23 +1059,12 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkSpAtk1", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerPoisonedTargetAtkSpAtkSpd1", proc { |move, user, target, ai, battle| next true if !target.battler.poisoned? - next true if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler, move.move) && - !target.battler.pbCanLowerStatStage?(:SPECIAL_ATTACK, user.battler, move.move) && - !target.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move) - } -) -Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerPoisonedTargetAtkSpAtkSpd1", - proc { |score, move, user, target, ai, battle| - if target.opposes?(user) - score += target.stages[:ATTACK] * 10 - score += target.stages[:SPECIAL_ATTACK] * 10 - score += target.stages[:SPEED] * 10 - else - score -= 20 - end - next score + next Battle::AI::Handlers.move_will_fail_against_target?("LowerTargetAtkSpAtk1", + move, user, target, ai, battle) } ) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("LowerTargetAtkSpAtk1", + "LowerPoisonedTargetAtkSpAtkSpd1") #=============================================================================== # TODO: Review score modifiers. 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 36eef2bfd..ee24f203e 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 @@ -150,7 +150,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTargetLowerTargetSpeed1", proc { |move, user, target, ai, battle|