From 4da9a8c4e313972c40b5206c726fd76771f26574 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 29 Jan 2023 23:24:07 +0000 Subject: [PATCH] AI function code rewrites for base stat changes, electrifying moves and multi-turn moves --- .../052_AI_MoveHandlers_BattlerStats.rb | 205 ++++++++++++++---- .../054_AI_MoveHandlers_MoveAttributes.rb | 76 ++++++- .../005_AI/055_AI_MoveHandlers_MultiHit.rb | 154 ++++++++++--- .../011_Battle/005_AI/102_AIBattler.rb | 21 +- 4 files changed, 362 insertions(+), 94 deletions(-) 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 c08fa667f..c4836b060 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 @@ -1424,88 +1424,205 @@ Battle::AI::Handlers::MoveEffectScore.add("ResetAllBattlersStatStages", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToStatStageLowering", proc { |move, user, ai, battle| next user.pbOwnSide.effects[PBEffects::Mist] > 0 } ) +Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToStatStageLowering", + proc { |score, move, user, ai, battle| + has_move = false + ai.each_foe_battler(user.side) do |b, i| + if b.check_for_move { |m| m.is_a?(Battle::Move::TargetStatDownMove) || + m.is_a?(Battle::Move::TargetMultiStatDownMove) || + ["LowerPoisonedTargetAtkSpAtkSpd1", + "PoisonTargetLowerTargetSpeed1", + "HealUserByTargetAttackLowerTargetAttack1"].include?(m.function) } + score += 10 + has_move = true + end + end + next Battle::AI::MOVE_USELESS_SCORE if !has_move + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("UserSwapBaseAtkDef", proc { |score, move, user, ai, battle| - aatk = user.rough_stat(:ATTACK) - adef = user.rough_stat(:DEFENSE) - next Battle::AI::MOVE_USELESS_SCORE if aatk == adef || user.effects[PBEffects::PowerTrick] # No flip-flopping - if adef > aatk # Prefer a higher Attack - score += 20 - else - score -= 20 + # No flip-flopping + next Battle::AI::MOVE_USELESS_SCORE if user.effects[PBEffects::PowerTrick] + # Check stats + user_atk = user.base_stat(:ATTACK) + user_def = user.base_stat(:DEFENSE) + next Battle::AI::MOVE_USELESS_SCORE if user_atk == user_def + # NOTE: Prefer to raise Attack regardless of the drop to Defense. Only + # prefer to raise Defense if Attack is useless. + if user_def > user_atk # Attack will be raised + next Battle::AI::MOVE_USELESS_SCORE if !ai.stat_raise_worthwhile?(user, :ATTACK, true) + score += (40 * ((user_def.to_f / user_atk) - 1)).to_i + score += 5 if !ai.stat_drop_worthwhile?(user, :DEFENSE, true) # No downside + else # Defense will be raised + next Battle::AI::MOVE_USELESS_SCORE if !ai.stat_raise_worthwhile?(user, :DEFENSE, true) + # Don't want to lower user's Attack if it can make use of it + next Battle::AI::MOVE_USELESS_SCORE if ai.stat_drop_worthwhile?(user, :ATTACK, true) + score += (40 * ((user_atk.to_f / user_def) - 1)).to_i end next score } ) #=============================================================================== -# TODO: Review score modifiers. -# TODO: target should probably be treated as an enemy when deciding the score, -# since the score will be inverted elsewhere due to the target being an -# ally. +# #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapBaseSpeed", proc { |score, move, user, target, ai, battle| - if user.speed > target.speed - score += 25 + user_speed = user.base_stat(:SPEED) + target_speed = target.base_stat(:SPEED) + next Battle::AI::MOVE_USELESS_SCORE if user_speed == target_speed + if battle.field.effects[PBEffects::TrickRoom] > 1 + # User wants to be slower so it can move first + next Battle::AI::MOVE_USELESS_SCORE if target_speed > user_speed + score += (40 * ((user_speed.to_f / target_speed) - 1)).to_i else - score -= 25 + # User wants to be faster so it can move first + next Battle::AI::MOVE_USELESS_SCORE if user_speed > target_speed + score += (40 * ((target_speed.to_f / user_speed) - 1)).to_i end next score } ) #=============================================================================== -# TODO: Review score modifiers. -# TODO: target should probably be treated as an enemy when deciding the score, -# since the score will be inverted elsewhere due to the target being an -# ally. +# #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseAtkSpAtk", proc { |score, move, user, target, ai, battle| - user_atk = user.battler.attack - user_spatk = user.battler.spatk - target_atk = target.battler.attack - target_spatk = target.battler.spatk - next Battle::AI::MOVE_USELESS_SCORE if user_atk > target_atk && user_spatk > target_spatk - if user_atk + user_spatk < target_atk + target_spatk - score += 20 - else - score -= 20 + user_atk = user.base_stat(:ATTACK) + user_spatk = user.base_stat(:SPECIAL_ATTACK) + target_atk = target.base_stat(:ATTACK) + target_spatk = target.base_stat(:SPECIAL_ATTACK) + next Battle::AI::MOVE_USELESS_SCORE if user_atk >= target_atk && user_spatk >= target_spatk + # Score based on changes to Attack + atk_change_matters = false + if target_atk > user_atk + # User's Attack will be raised + if ai.stat_raise_worthwhile?(user, :ATTACK, true) + score += (20 * ((target_atk.to_f / user_atk) - 1)).to_i + atk_change_matters = true + end + # Target's Attack will be lowered + if ai.stat_drop_worthwhile?(target, :ATTACK, true) + score += (20 * ((target_atk.to_f / user_atk) - 1)).to_i + atk_change_matters = true + end + elsif target_atk < user_atk + # User's Attack will be lowered + if ai.stat_drop_worthwhile?(user, :ATTACK, true) + score -= (20 * ((user_atk.to_f / target_atk) - 1)).to_i + atk_change_matters = true + end + # Target's Attack will be raised + if ai.stat_raise_worthwhile?(target, :ATTACK, true) + score -= (20 * ((user_atk.to_f / target_atk) - 1)).to_i + atk_change_matters = true + end end + # Score based on changes to Special Attack + spatk_change_matters = false + if target_spatk > user_spatk + # User's Special Attack will be raised + if ai.stat_raise_worthwhile?(user, :SPECIAL_ATTACK, true) + score += (20 * ((target_spatk.to_f / user_spatk) - 1)).to_i + spatk_change_matters = true + end + # Target's Special Attack will be lowered + if ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true) + score += (20 * ((target_spatk.to_f / user_spatk) - 1)).to_i + spatk_change_matters = true + end + elsif target_spatk < user_spatk + # User's Special Attack will be lowered + if ai.stat_drop_worthwhile?(user, :SPECIAL_ATTACK, true) + score -= (20 * ((user_spatk.to_f / target_spatk) - 1)).to_i + spatk_change_matters = true + end + # Target's Special Attack will be raised + if ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true) + score -= (20 * ((user_spatk.to_f / target_spatk) - 1)).to_i + spatk_change_matters = true + end + end + next Battle::AI::MOVE_USELESS_SCORE if !atk_change_matters && !spatk_change_matters next score } ) #=============================================================================== -# TODO: Review score modifiers. -# TODO: target should probably be treated as an enemy when deciding the score, -# since the score will be inverted elsewhere due to the target being an -# ally. +# #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDefSpDef", proc { |score, move, user, target, ai, battle| - user_def = user.rough_stat(:DEFENSE) - user_spdef = user.rough_stat(:SPECIAL_DEFENSE) - target_def = target.rough_stat(:DEFENSE) - target_spdef = target.rough_stat(:SPECIAL_DEFENSE) - next Battle::AI::MOVE_USELESS_SCORE if user_def > target_def && user_spdef > target_spdef - if user_def + user_spdef < target_def + target_spdef - score += 20 - else - score -= 20 + user_def = user.base_stat(:DEFENSE) + user_spdef = user.base_stat(:SPECIAL_DEFENSE) + target_def = target.base_stat(:DEFENSE) + target_spdef = target.base_stat(:SPECIAL_DEFENSE) + next Battle::AI::MOVE_USELESS_SCORE if user_def >= target_def && user_spdef >= target_spdef + # Score based on changes to Defense + def_change_matters = false + if target_def > user_def + # User's Defense will be raised + if ai.stat_raise_worthwhile?(user, :ATTACK, true) + score += (20 * ((target_def.to_f / user_def) - 1)).to_i + def_change_matters = true + end + # Target's Defense will be lowered + if ai.stat_drop_worthwhile?(target, :ATTACK, true) + score += (20 * ((target_def.to_f / user_def) - 1)).to_i + def_change_matters = true + end + elsif target_def < user_def + # User's Defense will be lowered + if ai.stat_drop_worthwhile?(user, :ATTACK, true) + score -= (20 * ((user_def.to_f / target_def) - 1)).to_i + def_change_matters = true + end + # Target's Defense will be raised + if ai.stat_raise_worthwhile?(target, :ATTACK, true) + score -= (20 * ((user_def.to_f / target_def) - 1)).to_i + def_change_matters = true + end end + # Score based on changes to Special Defense + spdef_change_matters = false + if target_spdef > user_spdef + # User's Special Defense will be raised + if ai.stat_raise_worthwhile?(user, :SPECIAL_ATTACK, true) + score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i + spdef_change_matters = true + end + # Target's Special Defense will be lowered + if ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true) + score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i + spdef_change_matters = true + end + elsif target_spdef < user_spdef + # User's Special Defense will be lowered + if ai.stat_drop_worthwhile?(user, :SPECIAL_ATTACK, true) + score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i + spdef_change_matters = true + end + # Target's Special Defense will be raised + if ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true) + score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i + spdef_change_matters = true + end + end + next Battle::AI::MOVE_USELESS_SCORE if !def_change_matters && !spdef_change_matters next score } ) @@ -1515,9 +1632,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDef #=============================================================================== Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageHP", proc { |score, move, user, target, ai, battle| - next Battle::AI::MOVE_USELESS_SCORE if user.hp >= (user.hp + target.hp) / 2 + next Battle::AI::MOVE_USELESS_SCORE if user.hp >= target.hp mult = (user.hp + target.hp) / (2.0 * user.hp) - score += 10 * mult if mult >= 1.2 + score += (10 * mult).to_i if mult >= 1.2 next score } ) 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 cbe9a7491..bfd60d187 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 @@ -1138,18 +1138,82 @@ Battle::AI::Handlers::MoveBasePower.copy("TypeAndPowerDependOnWeather", "TypeAndPowerDependOnTerrain") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== +Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetMovesBecomeElectric", + proc { |move, user, target, ai, battle| + next !user.faster_than?(target) + } +) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetMovesBecomeElectric", proc { |score, move, user, target, ai, battle| - next Battle::AI::MOVE_USELESS_SCORE if !user.faster_than?(target) + # Get Electric's effectiveness against the user + electric_eff = user.effectiveness_of_type_against_battler(:ELECTRIC, target) + electric_eff *= 1.5 if target.has_type?(:ELECTRIC) # STAB + electric_eff = 0 if user.has_active_ability?([:LIGHTNINGROD, :MOTORDRIVE, :VOLTABSORB]) + # For each of target's moves, get its effectiveness against the user and + # decide whether it is better or worse than Electric's effectiveness + old_type_better = 0 + electric_type_better = 0 + target.battler.eachMove do |m| + next if !m.damagingMove? + m_type = m.pbCalcType(target.battler) + next if m_type == :ELECTRIC + eff = user.effectiveness_of_type_against_battler(m_type, target) + eff *= 1.5 if target.has_type?(m_type) # STAB + case m_type + when :FIRE + eff = 0 if user.has_active_ability?(:FLASHFIRE) + when :GRASS + eff = 0 if user.has_active_ability?(:SAPSIPPER) + when :WATER + eff = 0 if user.has_active_ability?([:STORMDRAIN, :WATERABSORB]) + end + if eff > electric_eff + electric_type_better += 1 + elsif eff < electric_eff + old_type_better += 1 + end + end + next Battle::AI::MOVE_USELESS_SCORE if electric_type_better == 0 + next Battle::AI::MOVE_USELESS_SCORE if electric_type_better < old_type_better + score += 10 * (electric_type_better - old_type_better) next score } ) #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code can be called with a single target and with no targets. Make -# sure it doesn't assume that there is a target. +# TODO: This could check all other battlers, not just foes. It could check the +# effectivenesses of their Normal and Electric moves on all their foes, +# not just on the user. I think this is overkill, particularly as the +# effect only lasts for one round. #=============================================================================== -# NormalMovesBecomeElectric +Battle::AI::Handlers::MoveEffectScore.add("NormalMovesBecomeElectric", + proc { |score, move, user, ai, battle| + # Get Electric's effectiveness against the user + electric_eff = user.effectiveness_of_type_against_battler(:ELECTRIC, target) + electric_eff *= 1.5 if target.has_type?(:ELECTRIC) # STAB + electric_eff = 0 if user.has_active_ability?([:LIGHTNINGROD, :MOTORDRIVE, :VOLTABSORB]) + # Check all affected foe battlers for Normal moves, get their effectiveness + # against the user and decide whether it is better or worse than Electric's + # effectiveness + normal_type_better = 0 + electric_type_better = 0 + ai.each_foe_battler(user.side) do |b, i| + next if move.pbPriority(b.battler) <= 0 && b.faster_than?(user) + next if !b.has_damaging_move_of_type?(:NORMAL) + eff = user.effectiveness_of_type_against_battler(:NORMAL, b) + eff *= 1.5 if b.has_type?(:NORMAL) # STAB + if eff > electric_eff + electric_type_better += 1 + elsif eff < electric_eff + normal_type_better += 1 + end + end + if electric_type_better == 0 || electric_type_better < normal_type_better + next (move.statusMove?) ? Battle::AI::MOVE_USELESS_SCORE : score + end + score += 10 * (electric_type_better - normal_type_better) + next score + } +) 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 e1caa087c..364c65fbf 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 @@ -206,10 +206,12 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack", next score if user.has_active_item?(:POWERHERB) # Treat as a failure if user has Truant (the charging turn has no effect) next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:TRUANT) + # Useless if user will faint from EoR damage before finishing this attack + next Battle::AI::MOVE_USELESS_SCORE if user.rough_end_of_round_damage >= user.hp # Don't prefer because it uses up two turns - score -= 15 + score -= 10 # Don't prefer if user is at a low HP (time is better spent on quicker moves) - score -= 10 if user.hp < user.totalhp / 2 + score -= 8 if user.hp < user.totalhp / 2 # Don't prefer if target has a protecting move if ai.trainer.high_skill? && !(user.has_active_ability?(:UNSEENFIST) && move.move.contactMove?) has_protect_move = false @@ -356,27 +358,82 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackChargeRaise ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -# TwoTurnAttackInvulnerableUnderground +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableUnderground", + proc { |score, move, user, target, ai, battle| + # Score for being a two turn attack + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", + score, move, user, target, ai, battle) + # Score for being semi-invulnerable underground + user.each_foe_battler(user.side) do |b, i| + if b.check_for_move { |m| m.hitsDiggingTargets? } + score -= 8 + else + score += 5 + end + end + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -# TwoTurnAttackInvulnerableUnderwater +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableUnderwater", + proc { |score, move, user, target, ai, battle| + # Score for being a two turn attack + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", + score, move, user, target, ai, battle) + # Score for being semi-invulnerable underwater + user.each_foe_battler(user.side) do |b, i| + if b.check_for_move { |m| m.hitsDivingTargets? } + score -= 8 + else + score += 5 + end + end + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -# TwoTurnAttackInvulnerableInSky +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableInSky", + proc { |score, move, user, target, ai, battle| + # Score for being a two turn attack + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", + score, move, user, target, ai, battle) + # Score for being semi-invulnerable in the sky + user.each_foe_battler(user.side) do |b, i| + if b.check_for_move { |m| m.hitsFlyingTargets? } + score -= 8 + else + score += 5 + end + end + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -# TwoTurnAttackInvulnerableInSkyParalyzeTarget +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableInSkyParalyzeTarget", + proc { |score, move, user, target, ai, battle| + # Score for being a two turn attack and semi-invulnerable in the sky + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttackInvulnerableInSky", + score, move, user, target, ai, battle) + # Score for paralyzing the target + score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget", + score, move, user, target, ai, battle) + next score + } +) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct", proc { |move, user, target, ai, battle| @@ -387,34 +444,51 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TwoTurnAttackInvulnerab next false } ) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("TwoTurnAttackInvulnerableInSky", + "TwoTurnAttackInvulnerableInSkyTargetCannotAct") #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -# TwoTurnAttackInvulnerableRemoveProtections - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -# MultiTurnAttackPreventSleeping - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -# MultiTurnAttackConfuseUserAtEnd - -#=============================================================================== -# TODO: Review score modifiers. -#=============================================================================== -Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn", - proc { |power, move, user, target, ai, battle| - next move.move.pbBaseDamage(power, user.battler, target.battler) +Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableRemoveProtections", + proc { |score, move, user, target, ai, battle| + # Score for being a two turn attack + score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", + score, move, user, target, ai, battle) + # Score for being invulnerable + score += 5 + # Score for removing protections + score = Battle::AI::Handlers.apply_move_effect_against_target_score("RemoveProtections", + score, move, user, target, ai, battle) + next score } ) #=============================================================================== -# TODO: Review score modifiers. -# TODO: This code shouldn't make use of target. +# +#=============================================================================== +# MultiTurnAttackPreventSleeping + +#=============================================================================== +# +#=============================================================================== +# MultiTurnAttackConfuseUserAtEnd + +#=============================================================================== +# +#=============================================================================== +Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn", + proc { |power, move, user, target, ai, battle| + # NOTE: The * 2 (roughly) incorporates the higher damage done in subsequent + # rounds. It is nearly the average damage this move will do per round, + # assuming it hits for 3 rounds (hoping for hits in all 5 rounds is + # optimistic). + next move.move.pbBaseDamage(power, user.battler, target.battler) * 2 + } +) + +#=============================================================================== +# #=============================================================================== Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage", proc { |power, move, user, target, ai, battle| @@ -423,11 +497,19 @@ Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDama ) Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage", proc { |score, move, user, ai, battle| - if user.hp <= user.totalhp / 4 - score -= 90 - elsif user.hp <= user.totalhp / 2 - score -= 50 + # Useless if no foe has any damaging moves + has_damaging_move = false + ai.each_foe_battler(user.side) do |b, i| + next if b.status == :SLEEP && b.statusCount > 2 + next if b.status == :FROZEN + has_damaging_move = true if b.check_for_move { |m| m.damagingMove? } + break if has_damaging_move end + next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move + # Don't prefer if the user isn't at high HP + next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 4 + score -= 15 if user.hp <= user.totalhp / 2 + score -= 8 if user.hp <= user.totalhp * 3 / 4 next score } ) diff --git a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb index 1fed99761..0c4d8d521 100644 --- a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb +++ b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb @@ -168,20 +168,25 @@ class Battle::AI::AIBattler def speed; return @battler.speed; end + def base_stat(stat) + ret = 0 + case stat + when :ATTACK then ret = @battler.attack + when :DEFENSE then ret = @battler.defense + when :SPECIAL_ATTACK then ret = @battler.spatk + when :SPECIAL_DEFENSE then ret = @battler.spdef + when :SPEED then ret = @battler.speed + end + return ret + end + # TODO: Cache calculated rough stats? Forget them in def refresh_battler. def rough_stat(stat) return @battler.pbSpeed if stat == :SPEED && @ai.trainer.high_skill? stageMul = [2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8] stageDiv = [8, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2] stage = @battler.stages[stat] + 6 - value = 0 - case stat - when :ATTACK then value = @battler.attack - when :DEFENSE then value = @battler.defense - when :SPECIAL_ATTACK then value = @battler.spatk - when :SPECIAL_DEFENSE then value = @battler.spdef - when :SPEED then value = @battler.speed - end + value = base_stat(stat) return (value.to_f * stageMul[stage] / stageDiv[stage]).floor end