From 5a49bbbc9491d662733ceaee6d731e44f5609396 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Mon, 17 Oct 2022 21:13:31 +0100 Subject: [PATCH] Renamed function code UseUserBaseDefenseInsteadOfUserBaseAttack, more AI function code changes --- .../Scripts/010_Data/002_PBS data/004_Move.rb | 3 + .../003_Move/004_Move_BaseEffects.rb | 2 +- .../008_MoveEffects_MoveAttributes.rb | 16 +- .../005_AI/020_AI_MoveEffectScores_Generic.rb | 4 +- .../052_AI_MoveHandlers_BattlerStats.rb | 2 +- .../054_AI_MoveHandlers_MoveAttributes.rb | 145 ++++++++++++------ .../059_AI_MoveHandlers_SwitchingActing.rb | 2 +- .../070_AI_MoveHandlers_GeneralModifiers.rb | 2 +- Data/Scripts/011_Battle/005_AI/103_AIMove.rb | 4 +- PBS/Gen 8/moves.txt | 2 +- PBS/moves.txt | 2 +- 11 files changed, 114 insertions(+), 70 deletions(-) diff --git a/Data/Scripts/010_Data/002_PBS data/004_Move.rb b/Data/Scripts/010_Data/002_PBS data/004_Move.rb index 2241b79ed..559cf4e1a 100644 --- a/Data/Scripts/010_Data/002_PBS data/004_Move.rb +++ b/Data/Scripts/010_Data/002_PBS data/004_Move.rb @@ -809,6 +809,9 @@ module GameData when "173" then new_code = "StartPsychicTerrain" when "174" then new_code = "FailsIfNotUserFirstTurn" when "175" then new_code = "HitTwoTimesFlinchTarget" + #========================================================================= + # NOTE: The below was added in v21. + when "UseUserBaseDefenseInsteadOfUserBaseAttack" then new_code = "UseUserDefenseInsteadOfUserAttack" end data[:function_code] = new_code return data diff --git a/Data/Scripts/011_Battle/003_Move/004_Move_BaseEffects.rb b/Data/Scripts/011_Battle/003_Move/004_Move_BaseEffects.rb index bb2cbe2ea..938002b10 100644 --- a/Data/Scripts/011_Battle/003_Move/004_Move_BaseEffects.rb +++ b/Data/Scripts/011_Battle/003_Move/004_Move_BaseEffects.rb @@ -408,7 +408,7 @@ end # Recoil move. #=============================================================================== class Battle::Move::RecoilMove < Battle::Move - def recoilMove?; return true; end + def recoilMove?; return true; end def pbRecoilDamage(user, target); return 1; end def pbEffectAfterAllHits(user, target) 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 8fd6619c5..92dd98e81 100644 --- a/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb +++ b/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb @@ -1199,9 +1199,8 @@ 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 +class Battle::Move::UseUserDefenseInsteadOfUserAttack < Battle::Move def pbGetAttackStats(user, target) return user.defense, user.stages[:DEFENSE] + 6 end @@ -1275,7 +1274,7 @@ end # (Chip Away, Darkest Lariat, Sacred Sword) #=============================================================================== class Battle::Move::IgnoreTargetDefSpDefEvaStatStages < Battle::Move - def pbCalcAccuracyMultipliers(user, target, multipliers) + def pbCalcAccuracyModifiers(user, target, modifiers) super modifiers[:evasion_stage] = 0 end @@ -1376,20 +1375,15 @@ class Battle::Move::TypeAndPowerDependOnUserBerry < Battle::Move return ret end - # This is a separate method so that the AI can use it as well - def pbNaturalGiftBaseDamage(heldItem) - if heldItem - GameData::Item.get(heldItem).flags.each do |flag| + def pbBaseDamage(baseDmg, user, target) + if user.item.id + GameData::Item.get(user.item.id).flags.each do |flag| return [$~[1].to_i, 10].max if flag[/^NaturalGift_(?:\w+)_(\d+)$/i] end end return 1 end - def pbBaseDamage(baseDmg, user, target) - return pbNaturalGiftBaseDamage(user.item.id) - end - def pbEndOfMoveUsageEffect(user, targets, numHits, switchedBattlers) # NOTE: The item is consumed even if this move was Protected against or it # missed. The item is not consumed if the target was switched out by 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 4de4527eb..7a45e5f0f 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 @@ -65,7 +65,7 @@ class Battle::AI case stat when :ATTACK return false if !@user.check_for_move { |m| m.physicalMove?(move.type) && - m.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" && + m.function != "UseUserDefenseInsteadOfUserAttack" && m.function != "UseTargetAttackInsteadOfUserAttack" } when :DEFENSE each_foe_battler(@user.side) do |b, i| @@ -278,7 +278,7 @@ class Battle::AI score -= 20 else has_physical_moves = @user.check_for_move { |m| m.physicalMove?(m.type) && - m.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" && + m.function != "UseUserDefenseInsteadOfUserAttack" && m.function != "UseTargetAttackInsteadOfUserAttack" } inc = (has_physical_moves) ? 5 : 10 score += inc * (3 - old_stage) * inc_mult 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 c2e75f637..4130086e1 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 @@ -728,7 +728,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetAtkSpAtk2", ) Battle::AI::Handlers::MoveEffectScore.add("RaiseTargetAtkSpAtk2", proc { |score, move, user, target, ai, battle| - next score - 50 if target.opposes?(user) + next score - 40 if target.opposes?(user) next score - 40 if !battle.moldBreaker && target.has_active_ability?(:CONTRARY) score -= target.stages[:ATTACK] * 10 score -= target.stages[:SPECIAL_ATTACK] * 10 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 f37ce70d2..7c04b571c 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 @@ -396,24 +396,13 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartPreventCriticalHitsAgainstUserS ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("CannotMakeTargetFaint", proc { |move, user, target, ai, battle| next true if target.hp == 1 } ) -Battle::AI::Handlers::MoveEffectScore.add("CannotMakeTargetFaint", - proc { |score, move, user, target, ai, battle| - next 0 if target.hp == 1 - if target.hp <= target.totalhp / 8 - score -= 20 - elsif target.hp <= target.totalhp / 4 - score -= 10 - end - next score - } -) #=============================================================================== # TODO: Review score modifiers. @@ -661,21 +650,37 @@ Battle::AI::Handlers::MoveEffectScore.add("HoopaRemoveProtectionsBypassSubstitut ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("RecoilQuarterOfDamageDealt", proc { |score, move, user, target, ai, battle| - next score - 8 + next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD) + dmg = move.rough_damage / 4 + if dmg >= user.hp + reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) + foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) + next score - 40 if reserves <= foes + end + score -= 10 * [dmg, user.hp].min / user.hp + next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarget", proc { |score, move, user, target, ai, battle| # Score for being a recoil move - score -= 10 + if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD) + dmg = move.rough_damage / 3 + if dmg >= user.hp + reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) + foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) + next score - 40 if reserves <= foes + end + score -= 10 * [dmg, user.hp].min / user.hp + end # Score for paralysing score = Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", score, move, user, target, ai, battle) @@ -684,12 +689,20 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarge ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget", proc { |score, move, user, target, ai, battle| # Score for being a recoil move - score -= 10 + if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD) + dmg = move.rough_damage / 3 + if dmg >= user.hp + reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) + foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) + next score - 40 if reserves <= foes + end + score -= 10 * [dmg, user.hp].min / user.hp + end # Score for burning score = Battle::AI::Handlers.apply_move_effect_score("BurnTarget", score, move, user, target, ai, battle) @@ -698,11 +711,19 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("RecoilHalfOfDamageDealt", proc { |score, move, user, target, ai, battle| - next score - 15 + next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD) + dmg = move.rough_damage / 2 + if dmg >= user.hp + reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) + foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) + next score - 40 if reserves <= foes + end + score -= 10 * [dmg, user.hp].min / user.hp + next score } ) @@ -736,63 +757,91 @@ Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTa # CategoryDependsOnHigherDamageIgnoreTargetAbility #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== -# UseUserBaseDefenseInsteadOfUserBaseAttack +# UseUserDefenseInsteadOfUserAttack #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== # UseTargetAttackInsteadOfUserAttack #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== # UseTargetDefenseInsteadOfTargetSpDef #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== +Battle::AI::Handlers::MoveFailureCheck.add("EnsureNextMoveAlwaysHits", + proc { |move, user, target, ai, battle| + next true if user.effects[PBEffects::LockOn] > 0 + } +) Battle::AI::Handlers::MoveEffectScore.add("EnsureNextMoveAlwaysHits", proc { |score, move, user, target, ai, battle| - next score - 50 if user.effects[PBEffects::LockOn] > 0 + next score - 40 if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD) + next score - 40 if target.effects[PBEffects::Telekinesis] > 0 + # Prefer if the user knows moves with low accuracy + user.check_for_move do |m| + next if target.effects[PBEffects::Minimize] && m.tramplesMinimize? && Settings::MECHANICS_GENERATION >= 6 + # TODO: There are other effects that make a move certain to hit. Account + # for those as well, or is that too micro-managey? + acc = m.accuracy + acc = m.pbBaseAccuracy(user.battler, target.battler) if ai.trainer.medium_skill? + score += 4 if acc < 90 && acc != 0 + score += 8 if acc < 50 && acc != 0 + end + # Not worth it if the user or the target is at low HP + score -= 10 if user.hp < user.totalhp / 2 + score -= 8 if target.hp < target.totalhp / 2 + next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndGhostImmunity", proc { |score, move, user, target, ai, battle| - if target.effects[PBEffects::Foresight] - score -= 90 - elsif target.has_type?(:GHOST) - score += 70 - elsif target.stages[:EVASION] <= 0 - score -= 60 + next score - 40 if target.effects[PBEffects::Foresight] || user.has_active_ability?(:SCRAPPY) + # Check if the user knows any moves that would benefit from negating the + # target's Ghost type immunity + if target.has_type?(:GHOST) + user.check_for_move do |m| + next if !m.damagingMove? + score += 10 if Effectiveness.ineffective_type?(m.pbCalcType(user.battler), :GHOST) + end end + # Prefer if the target has increased evasion + score += 10 * target.stages[:EVASION] if target.stages[:EVASION] > 0 next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndDarkImmunity", proc { |score, move, user, target, ai, battle| - if target.effects[PBEffects::MiracleEye] - score -= 50 - elsif target.has_type?(:DARK) - score += 70 - elsif target.stages[:EVASION] <= 0 - score -= 60 + next score - 40 if target.effects[PBEffects::MiracleEye] + # Check if the user knows any moves that would benefit from negating the + # target's Dark type immunity + if target.has_type?(:DARK) + user.check_for_move do |m| + next if !m.damagingMove? + score += 10 if Effectiveness.ineffective_type?(m.pbCalcType(user.battler), :DARK) + end end + # Prefer if the target has increased evasion + score += 10 * target.stages[:EVASION] if target.stages[:EVASION] > 0 next score } ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== # IgnoreTargetDefSpDefEvaStatStages @@ -811,7 +860,7 @@ Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs", ) #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("TypeAndPowerDependOnUserBerry", proc { |move, user, target, ai, battle| @@ -822,8 +871,7 @@ 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.move.pbBaseDamage? - ret = move.move.pbNaturalGiftBaseDamage(user.item_id) + ret = move.move.pbBaseDamage(1, user.battler, target.battler) next (ret == 1) ? 0 : ret } ) @@ -844,18 +892,15 @@ Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnUserBerry", # TypeDependsOnUserDrive #=============================================================================== -# TODO: Review score modifiers. +# #=============================================================================== Battle::AI::Handlers::MoveFailureCheck.add("TypeDependsOnUserMorpekoFormRaiseUserSpeed1", proc { |move, user, target, ai, battle| next true if !user.battler.isSpecies?(:MORPEKO) && user.effects[PBEffects::TransformSpecies] != :MORPEKO } ) -Battle::AI::Handlers::MoveEffectScore.add("TypeDependsOnUserMorpekoFormRaiseUserSpeed1", - proc { |score, move, user, target, ai, battle| - next score + 20 if user.stages[:SPEED] <= 0 - } -) +Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1", + "TypeDependsOnUserMorpekoFormRaiseUserSpeed1") #=============================================================================== # 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 696311cf4..0d8803529 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 @@ -301,7 +301,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain", proc { |score, move, user, target, ai, battle| # Without lots of code here to determine good/bad moves and relative # speeds, using this move is likely to just be a waste of a turn - next score - 50 + next score - 40 } ) diff --git a/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb b/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb index cf1910bf2..6c8b602fc 100644 --- a/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb +++ b/Data/Scripts/011_Battle/005_AI/070_AI_MoveHandlers_GeneralModifiers.rb @@ -148,7 +148,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:target_semi_invulnerable, miss = false if move.move.hitsDivingTargets? end end - next score - 50 if miss + next score - 40 if miss end } ) diff --git a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb index 1d201664b..a4adf2f39 100644 --- a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb +++ b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb @@ -367,7 +367,9 @@ class Battle::AI::AIMove defense = [(defense * multipliers[:defense_multiplier]).round, 1].max damage = ((((2.0 * user.level / 5) + 2).floor * power * atk / defense).floor / 50).floor + 2 damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max - return damage.floor + ret = damage.floor + ret = target.hp - 1 if @move.nonLethal?(user_battler, target_battler) && ret >= target.hp + return ret end #============================================================================= diff --git a/PBS/Gen 8/moves.txt b/PBS/Gen 8/moves.txt index 37e566254..dbf04c881 100644 --- a/PBS/Gen 8/moves.txt +++ b/PBS/Gen 8/moves.txt @@ -2011,7 +2011,7 @@ Power = 80 Accuracy = 100 TotalPP = 10 Target = NearOther -FunctionCode = UseUserBaseDefenseInsteadOfUserBaseAttack +FunctionCode = UseUserDefenseInsteadOfUserAttack Flags = Contact,CanProtect,CanMirrorMove,CannotMetronome Description = The user attacks by slamming its body into the target. Power increases the higher the user's Defense is. #------------------------------- diff --git a/PBS/moves.txt b/PBS/moves.txt index 37e566254..dbf04c881 100644 --- a/PBS/moves.txt +++ b/PBS/moves.txt @@ -2011,7 +2011,7 @@ Power = 80 Accuracy = 100 TotalPP = 10 Target = NearOther -FunctionCode = UseUserBaseDefenseInsteadOfUserBaseAttack +FunctionCode = UseUserDefenseInsteadOfUserAttack Flags = Contact,CanProtect,CanMirrorMove,CannotMetronome Description = The user attacks by slamming its body into the target. Power increases the higher the user's Defense is. #-------------------------------