diff --git a/Data/Scripts/011_Battle/005_AI/001_Battle_AI.rb b/Data/Scripts/011_Battle/005_AI/001_Battle_AI.rb index d10031bb1..ebceb9705 100644 --- a/Data/Scripts/011_Battle/005_AI/001_Battle_AI.rb +++ b/Data/Scripts/011_Battle/005_AI/001_Battle_AI.rb @@ -11,8 +11,8 @@ class Battle::AI @battle = battle # TODO: Move this elsewhere? - @roles = [Array.new(@battle.pbParty(0).length) { |i| determine_roles(0, i) }, - Array.new(@battle.pbParty(1).length) { |i| determine_roles(1, i) }] + @roles = [Array.new(@battle.pbParty(0).length) { |i| determine_roles(0, i) }, + Array.new(@battle.pbParty(1).length) { |i| determine_roles(1, i) }] end def create_ai_objects diff --git a/Data/Scripts/011_Battle/005_AI/003_AI_Switch.rb b/Data/Scripts/011_Battle/005_AI/003_AI_Switch.rb index 8ce5a23d4..59b22d5e0 100644 --- a/Data/Scripts/011_Battle/005_AI/003_AI_Switch.rb +++ b/Data/Scripts/011_Battle/005_AI/003_AI_Switch.rb @@ -25,8 +25,8 @@ class Battle::AI moveData = GameData::Move.get(target.lastMoveUsed) moveType = moveData.type typeMod = @user.effectiveness_of_type_against_battler(moveType, foe) - if Effectiveness.super_effective?(typeMod) && moveData.base_damage > 50 - switchChance = (moveData.base_damage > 70) ? 30 : 20 + if Effectiveness.super_effective?(typeMod) && moveData.power > 50 + switchChance = (moveData.power > 70) ? 30 : 20 shouldSwitch = (pbAIRandom(100) < switchChance) end end @@ -169,7 +169,7 @@ class Battle::AI pkmn = party[i] sum = 0 pkmn.moves.each do |m| - next if m.base_damage == 0 + next if m.power == 0 @battle.battlers[idxBattler].allOpposing.each do |b| bTypes = b.pbTypes(true) sum += Effectiveness.calculate(m.type, *bTypes) diff --git a/Data/Scripts/011_Battle/005_AI/020_AI_Move_EffectScoresGeneric.rb b/Data/Scripts/011_Battle/005_AI/020_AI_Move_EffectScoresGeneric.rb index 01debe46f..7d5d2431e 100644 --- a/Data/Scripts/011_Battle/005_AI/020_AI_Move_EffectScoresGeneric.rb +++ b/Data/Scripts/011_Battle/005_AI/020_AI_Move_EffectScoresGeneric.rb @@ -536,7 +536,7 @@ class Battle::AI when :ACCURACY # Prefer if user knows any weaker moves - mini_score *= 1.1 if check_for_move(@user) { |m| m.damagingMove? && m.basedamage < 95 } + mini_score *= 1.1 if check_for_move(@user) { |m| m.damagingMove? && m.power < 95 } # Prefer if target has a raised evasion sum_stages = @target.stages[:EVASION] mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0 @@ -996,465 +996,4 @@ class Battle::AI end return ret end - - #============================================================================= - # Returns a value indicating how beneficial the given item will be to the - # given battler if it is holding it. - # Return values are typically -2, -1, 0, 1 or 2. 0 is indifferent, positive - # values mean the battler benefits, negative values mean the battler suffers. - #============================================================================= - def battler_wants_item?(battler, item = :NONE) - item == :NONE if item.nil? - # TODO: Add more items. - preferred_items = [ - :CHOICESCARF, - :LEFTOVERS - ] - preferred_items.push(:BLACKSLUDGE) if battler.has_type?(:POISON) - preferred_items.push(:IRONBALL) if battler.has_move_with_function?("ThrowUserItemAtTarget") - preferred_items.push(:CHOICEBAND) if battler.check_for_move { |m| m.physicalMove?(m.type) } - preferred_items.push(:CHOICESPECS) if battler.check_for_move { |m| m.specialMove?(m.type) } - unpreferred_items = [ - :BLACKSLUDGE, - :FLAMEORB, - :IRONBALL, - :LAGGINGTAIL, - :STICKYBARB, - :TOXICORB - ] - ret = 0 - if preferred_items.include?(item) - ret = 2 - elsif unpreferred_items.include?(item) - ret = -2 - end - # Don't prefer if the battler knows Acrobatics - if battler.has_move_with_function?("DoublePowerIfUserHasNoItem") - ret += (item == :NONE) ? 1 : -1 - end - return ret - end - - #============================================================================= - # Items can be consumed by Stuff Cheeks, Teatime, Bug Bite/Pluck and Fling. - #============================================================================= - def get_score_change_for_consuming_item(battler, item) - ret = 0 - case item - when :ORANBERRY, :BERRYJUICE, :ENIGMABERRY, :SITRUSBERRY - # Healing - ret += (battler.hp > battler.totalhp * 3 / 4) ? -8 : 8 - ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && battler.has_active_ability?(:RIPEN) - when :AGUAVBERRY, :FIGYBERRY, :IAPAPABERRY, :MAGOBERRY, :WIKIBERRY - # Healing with confusion - fraction_to_heal = 8 # Gens 6 and lower - if Settings::MECHANICS_GENERATION == 7 - fraction_to_heal = 2 - elsif Settings::MECHANICS_GENERATION >= 8 - fraction_to_heal = 3 - end - ret += (battler.hp > battler.totalhp * (1 - (1 / fraction_to_heal))) ? -8 : 8 - ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && battler.has_active_ability?(:RIPEN) - # TODO: Check whether the item will cause confusion? - when :ASPEARBERRY, :CHERIBERRY, :CHESTOBERRY, :PECHABERRY, :RAWSTBERRY - # Status cure - status = { - :ASPEAR => :FROZEN, - :CHERIBERRY => :PARALYSIS, - :CHESTOBERRY => :SLEEP, - :PECHABERRY => :POISON, - :RAWSTBERRY => :BURN - }[item] - ret += (status && battler.status == status) ? 8 : -8 - when :PERSIMBERRY - # Confusion cure - ret += (battler.effects[PBEffects::Confusion] > 1) ? 8 : -8 - when :LUMBERRY - # Any status/confusion cure - ret += (battler.status != :NONE || battler.effects[PBEffects::Confusion] > 1) ? 8 : -8 - when :MENTALHERB - # Cure mental effects - ret += 8 if battler.effects[PBEffects::Attract] >= 0 || - battler.effects[PBEffects::Taunt] > 1 || - battler.effects[PBEffects::Encore] > 1 || - battler.effects[PBEffects::Torment] || - battler.effects[PBEffects::Disable] > 1 || - battler.effects[PBEffects::HealBlock] > 1 - when :APICOTBERRY, :GANLONBERRY, :LIECHIBERRY, :PETAYABERRY, :SALACBERRY, - :KEEBERRY, :MARANGABERRY - # Stat raise - stat = { - :APICOTBERRY => :SPECIAL_DEFENSE, - :GANLONBERRY => :DEFENSE, - :LIECHIBERRY => :ATTACK, - :PETAYABERRY => :SPECIAL_ATTACK, - :SALACBERRY => :SPEED, - :KEEBERRY => :DEFENSE, - :MARANGABERRY => :SPECIAL_DEFENSE - }[item] - ret += 8 if stat && stat_raise_worthwhile?(battler, stat) - ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && battler.has_active_ability?(:RIPEN) - when :STARFBERRY - # Random stat raise - ret += 8 - ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && battler.has_active_ability?(:RIPEN) - when :WHITEHERB - # Resets lowered stats - reduced_stats = false - GameData::Stat.each_battle do |s| - next if battler.stages[s.id] >= 0 - reduced_stats = true - break - end - ret += 8 if reduced_stats - when :MICLEBERRY - # Raises accuracy of next move - ret += 8 - when :LANSATBERRY - # Focus energy - ret += 8 if battler.effects[PBEffects::FocusEnergy] < 2 - when :LEPPABERRY - # Restore PP - ret += 8 - ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && battler.has_active_ability?(:RIPEN) - end - return ret - end - - #============================================================================= - # Returns a value indicating how beneficial the given ability will be to the - # given battler if it has it. - # Return values are typically between -10 and +10. 0 is indifferent, positive - # values mean the battler benefits, negative values mean the battler suffers. - #============================================================================= - # These values are taken from the Complete-Fire-Red-Upgrade decomp here: - # https://github.com/Skeli789/Complete-Fire-Red-Upgrade/blob/f7f35becbd111c7e936b126f6328fc52d9af68c8/src/ability_battle_effects.c#L41 - BASE_ABILITY_RATINGS = { - :ADAPTABILITY => 8, - :AERILATE => 8, - :AFTERMATH => 5, - :AIRLOCK => 5, - :ANALYTIC => 5, - :ANGERPOINT => 4, - :ANTICIPATION => 0, - :ARENATRAP => 9, - :AROMAVEIL => 3, -# :ASONECHILLINGNEIGH => 0, -# :ASONEGRIMNEIGH => 0, - :AURABREAK => 3, - :BADDREAMS => 4, -# :BALLFETCH => 0, -# :BATTERY => 0, - :BATTLEARMOR => 2, - :BATTLEBOND => 6, - :BEASTBOOST => 7, - :BERSERK => 5, - :BIGPECKS => 1, - :BLAZE => 5, - :BULLETPROOF => 7, - :CHEEKPOUCH => 4, -# :CHILLINGNEIGH => 0, - :CHLOROPHYLL => 6, - :CLEARBODY => 4, - :CLOUDNINE => 5, - :COLORCHANGE => 2, - :COMATOSE => 6, - :COMPETITIVE => 5, - :COMPOUNDEYES => 7, - :CONTRARY => 8, - :CORROSION => 5, - :COTTONDOWN => 3, -# :CURIOUSMEDICINE => 0, - :CURSEDBODY => 4, - :CUTECHARM => 2, - :DAMP => 2, - :DANCER => 5, - :DARKAURA => 6, - :DAUNTLESSSHIELD => 3, - :DAZZLING => 5, - :DEFEATIST => -1, - :DEFIANT => 5, - :DELTASTREAM => 10, - :DESOLATELAND => 10, - :DISGUISE => 8, - :DOWNLOAD => 7, - :DRAGONSMAW => 8, - :DRIZZLE => 9, - :DROUGHT => 9, - :DRYSKIN => 6, - :EARLYBIRD => 4, - :EFFECTSPORE => 4, - :ELECTRICSURGE => 8, - :EMERGENCYEXIT => 3, - :FAIRYAURA => 6, - :FILTER => 6, - :FLAMEBODY => 4, - :FLAREBOOST => 5, - :FLASHFIRE => 6, - :FLOWERGIFT => 4, -# :FLOWERVEIL => 0, - :FLUFFY => 5, - :FORECAST => 6, - :FOREWARN => 0, -# :FRIENDGUARD => 0, - :FRISK => 0, - :FULLMETALBODY => 4, - :FURCOAT => 7, - :GALEWINGS => 6, - :GALVANIZE => 8, - :GLUTTONY => 3, - :GOOEY => 5, - :GORILLATACTICS => 4, - :GRASSPELT => 2, - :GRASSYSURGE => 8, -# :GRIMNEIGH => 0, - :GULPMISSLE => 3, - :GUTS => 6, - :HARVEST => 5, -# :HEALER => 0, - :HEATPROOF => 5, - :HEAVYMETAL => -1, -# :HONEYGATHER => 0, - :HUGEPOWER => 10, - :HUNGERSWITCH => 2, - :HUSTLE => 7, - :HYDRATION => 4, - :HYPERCUTTER => 3, - :ICEBODY => 3, - :ICEFACE => 4, - :ICESCALES => 7, -# :ILLUMINATE => 0, - :ILLUSION => 8, - :IMMUNITY => 4, - :IMPOSTER => 9, - :INFILTRATOR => 6, - :INNARDSOUT => 5, - :INNERFOCUS => 2, - :INSOMNIA => 4, - :INTIMIDATE => 7, - :INTREPIDSWORD => 3, - :IRONBARBS => 6, - :IRONFIST => 6, - :JUSTIFIED => 4, - :KEENEYE => 1, - :KLUTZ => -1, - :LEAFGUARD => 2, - :LEVITATE => 7, - :LIBERO => 8, - :LIGHTMETAL => 2, - :LIGHTNINGROD => 7, - :LIMBER => 3, - :LIQUIDOOZE => 3, - :LIQUIDVOICE => 5, - :LONGREACH => 3, - :MAGICBOUNCE => 9, - :MAGICGUARD => 9, - :MAGICIAN => 3, - :MAGMAARMOR => 1, - :MAGNETPULL => 9, - :MARVELSCALE => 5, - :MEGALAUNCHER => 7, - :MERCILESS => 4, - :MIMICRY => 2, -# :MINUS => 0, - :MIRRORARMOR => 6, - :MISTYSURGE => 8, - :MOLDBREAKER => 7, - :MOODY => 10, - :MOTORDRIVE => 6, - :MOXIE => 7, - :MULTISCALE => 8, - :MULTITYPE => 8, - :MUMMY => 5, - :NATURALCURE => 7, - :NEUROFORCE => 6, - :NEUTRALIZINGGAS => 5, - :NOGUARD => 8, - :NORMALIZE => -1, - :OBLIVIOUS => 2, - :OVERCOAT => 5, - :OVERGROW => 5, - :OWNTEMPO => 3, - :PARENTALBOND => 10, - :PASTELVEIL => 4, - :PERISHBODY => -1, - :PICKPOCKET => 3, - :PICKUP => 1, - :PIXILATE => 8, -# :PLUS => 0, - :POISONHEAL => 8, - :POISONPOINT => 4, - :POISONTOUCH => 4, - :POWERCONSTRUCT => 10, -# :POWEROFALCHEMY => 0, - :POWERSPOT => 2, - :PRANKSTER => 8, - :PRESSURE => 5, - :PRIMORDIALSEA => 10, - :PRISMARMOR => 6, - :PROPELLORTAIL => 2, - :PROTEAN => 8, - :PSYCHICSURGE => 8, - :PUNKROCK => 2, - :PUREPOWER => 10, - :QUEENLYMAJESTY => 6, -# :QUICKDRAW => 0, - :QUICKFEET => 5, - :RAINDISH => 3, - :RATTLED => 3, -# :RECEIVER => 0, - :RECKLESS => 6, - :REFRIGERATE => 8, - :REGENERATOR => 8, - :RIPEN => 4, - :RIVALRY => 1, - :RKSSYSTEM => 8, - :ROCKHEAD => 5, - :ROUGHSKIN => 6, -# :RUNAWAY => 0, - :SANDFORCE => 4, - :SANDRUSH => 6, - :SANDSPIT => 5, - :SANDSTREAM => 9, - :SANDVEIL => 3, - :SAPSIPPER => 7, - :SCHOOLING => 6, - :SCRAPPY => 6, - :SCREENCLEANER => 3, - :SERENEGRACE => 8, - :SHADOWSHIELD => 8, - :SHADOWTAG => 10, - :SHEDSKIN => 7, - :SHEERFORCE => 8, - :SHELLARMOR => 2, - :SHIELDDUST => 5, - :SHIELDSDOWN => 6, - :SIMPLE => 8, - :SKILLLINK => 7, - :SLOWSTART => -2, - :SLUSHRUSH => 5, - :SNIPER => 3, - :SNOWCLOAK => 3, - :SNOWWARNING => 8, - :SOLARPOWER => 3, - :SOLIDROCK => 6, - :SOULHEART => 7, - :SOUNDPROOF => 4, - :SPEEDBOOST => 9, - :STAKEOUT => 6, - :STALL => -1, - :STALWART => 2, - :STAMINA => 6, - :STANCECHANGE => 10, - :STATIC => 4, - :STEADFAST => 2, - :STEAMENGINE => 3, - :STEELWORKER => 6, - :STEELYSPIRIT => 2, - :STENCH => 1, - :STICKYHOLD => 3, - :STORMDRAIN => 7, - :STRONGJAW => 6, - :STURDY => 6, - :SUCTIONCUPS => 2, - :SUPERLUCK => 3, - :SURGESURFER => 4, - :SWARM => 5, - :SWEETVEIL => 4, - :SWIFTSWIM => 6, -# :SYMBIOSIS => 0, - :SYNCHRONIZE => 4, - :TANGLEDFEET => 2, - :TANGLINGHAIR => 5, - :TECHNICIAN => 8, -# :TELEPATHY => 0, - :TERAVOLT => 7, - :THICKFAT => 7, - :TINTEDLENS => 7, - :TORRENT => 5, - :TOUGHCLAWS => 7, - :TOXICBOOST => 6, - :TRACE => 6, - :TRANSISTOR => 8, - :TRIAGE => 7, - :TRUANT => -2, - :TURBOBLAZE => 7, - :UNAWARE => 6, - :UNBURDEN => 7, - :UNNERVE => 3, -# :UNSEENFIST => 0, - :VICTORYSTAR => 6, - :VITALSPIRIT => 4, - :VOLTABSORB => 7, - :WANDERINGSPIRIT => 2, - :WATERABSORB => 7, - :WATERBUBBLE => 8, - :WATERCOMPACTION => 4, - :WATERVEIL => 4, - :WEAKARMOR => 2, - :WHITESMOKE => 4, - :WIMPOUT => 3, - :WONDERGUARD => 10, - :WONDERSKIN => 4, - :ZENMODE => -1 - } - - # TODO: This method assumes the ability isn't being negated. Should it return - # 0 if it is? The calculations that call this method separately check - # for it being negated, because they need to do something special in - # that case, so I think it's okay for this method to ignore negation. - def battler_wants_ability?(battler, ability = :NONE) - ability = ability.id if !ability.is_a?(Symbol) && ability.respond_to?("id") - # TODO: Ideally replace the above list of ratings with context-sensitive - # calculations. Should they all go in this method, or should there be - # more handlers for each ability? - case ability - when :BLAZE - return 0 if !battler.has_damaging_move_of_type?(:FIRE) - when :CUTECHARM, :RIVALRY - return 0 if battler.gender == 2 - when :FRIENDGUARD, :HEALER, :SYMBOISIS, :TELEPATHY - has_ally = false - each_ally(battler.side) { |b, i| has_ally = true } - return 0 if !has_ally - when :GALEWINGS - return 0 if !battler.check_for_move { |m| m.type == :FLYING } - when :HUGEPOWER, :PUREPOWER - return 0 if !battler.check_for_move { |m| m.physicalMove?(m.type) && - m.function != "UseUserDefenseInsteadOfUserAttack" && - m.function != "UseTargetAttackInsteadOfUserAttack" } - when :IRONFIST - return 0 if !battler.check_for_move { |m| m.punchingMove? } - when :LIQUIDVOICE - return 0 if !battler.check_for_move { |m| m.soundMove? } - when :MEGALAUNCHER - return 0 if !battler.check_for_move { |m| m.pulseMove? } - when :OVERGROW - return 0 if !battler.has_damaging_move_of_type?(:GRASS) - when :PRANKSTER - return 0 if !battler.check_for_move { |m| m.statusMove? } - when :PUNKROCK - return 1 if !battler.check_for_move { |m| m.damagingMove? && m.soundMove? } - when :RECKLESS - return 0 if !battler.check_for_move { |m| m.recoilMove? } - when :ROCKHEAD - return 0 if !battler.check_for_move { |m| m.recoilMove? && !m.is_a?(Battle::Move::CrashDamageIfFailsUnusableInGravity) } - when :RUNAWAY - return 0 if battler.wild? - when :SANDFORCE - return 2 if !battler.has_damaging_move_of_type?(:GROUND, :ROCK, :STEEL) - when :SKILLLINK - return 0 if !battler.check_for_move { |m| m.is_a?(Battle::Move::HitTwoToFiveTimes) } - when :STEELWORKER - return 0 if !battler.has_damaging_move_of_type?(:GRASS) - when :SWARM - return 0 if !battler.has_damaging_move_of_type?(:BUG) - when :TORRENT - return 0 if !battler.has_damaging_move_of_type?(:WATER) - when :TRIAGE - return 0 if !battler.check_for_move { |m| m.healingMove? } - end - ret = BASE_ABILITY_RATINGS[ability] || 0 - return ret - end end diff --git a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb index 07df383b5..73a96e1f4 100644 --- a/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb +++ b/Data/Scripts/011_Battle/005_AI/102_AIBattler.rb @@ -25,10 +25,10 @@ class Battle::AI::AIBattler def pokemon; return @battler.pokemon; end def level; return @battler.level; end def hp; return @battler.hp; end + def totalhp; return @battler.totalhp; 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 def turnCount; return @battler.turnCount; end def effects; return @battler.effects; end @@ -307,6 +307,467 @@ class Battle::AI::AIBattler #============================================================================= + # Returns a value indicating how beneficial the given item will be to this + # battler if it is holding it. + # Return values are typically -2, -1, 0, 1 or 2. 0 is indifferent, positive + # values mean this battler benefits, negative values mean this battler suffers. + def wants_item?(item = :NONE) + item == :NONE if item.nil? + # TODO: Add more items. + preferred_items = [ + :CHOICESCARF, + :LEFTOVERS + ] + preferred_items.push(:BLACKSLUDGE) if has_type?(:POISON) + preferred_items.push(:IRONBALL) if has_move_with_function?("ThrowUserItemAtTarget") + preferred_items.push(:CHOICEBAND) if check_for_move { |m| m.physicalMove?(m.type) } + preferred_items.push(:CHOICESPECS) if check_for_move { |m| m.specialMove?(m.type) } + unpreferred_items = [ + :BLACKSLUDGE, + :FLAMEORB, + :IRONBALL, + :LAGGINGTAIL, + :STICKYBARB, + :TOXICORB + ] + ret = 0 + if preferred_items.include?(item) + ret = 2 + elsif unpreferred_items.include?(item) + ret = -2 + end + # Don't prefer if this battler knows Acrobatics + if has_move_with_function?("DoublePowerIfUserHasNoItem") + ret += (item == :NONE) ? 1 : -1 + end + return ret + end + + #============================================================================= + + # Items can be consumed by Stuff Cheeks, Teatime, Bug Bite/Pluck and Fling. + def get_score_change_for_consuming_item(item) + ret = 0 + case item + when :ORANBERRY, :BERRYJUICE, :ENIGMABERRY, :SITRUSBERRY + # Healing + ret += (hp > totalhp * 3 / 4) ? -8 : 8 + ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) + when :AGUAVBERRY, :FIGYBERRY, :IAPAPABERRY, :MAGOBERRY, :WIKIBERRY + # Healing with confusion + fraction_to_heal = 8 # Gens 6 and lower + if Settings::MECHANICS_GENERATION == 7 + fraction_to_heal = 2 + elsif Settings::MECHANICS_GENERATION >= 8 + fraction_to_heal = 3 + end + ret += (hp > totalhp * (1 - (1 / fraction_to_heal))) ? -8 : 8 + ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) + # TODO: Check whether the item will cause confusion? + when :ASPEARBERRY, :CHERIBERRY, :CHESTOBERRY, :PECHABERRY, :RAWSTBERRY + # Status cure + cured_status = { + :ASPEAR => :FROZEN, + :CHERIBERRY => :PARALYSIS, + :CHESTOBERRY => :SLEEP, + :PECHABERRY => :POISON, + :RAWSTBERRY => :BURN + }[item] + ret += (cured_status && status == cured_status) ? 8 : -8 + when :PERSIMBERRY + # Confusion cure + ret += (effects[PBEffects::Confusion] > 1) ? 8 : -8 + when :LUMBERRY + # Any status/confusion cure + ret += (status != :NONE || effects[PBEffects::Confusion] > 1) ? 8 : -8 + when :MENTALHERB + # Cure mental effects + ret += 8 if effects[PBEffects::Attract] >= 0 || + effects[PBEffects::Taunt] > 1 || + effects[PBEffects::Encore] > 1 || + effects[PBEffects::Torment] || + effects[PBEffects::Disable] > 1 || + effects[PBEffects::HealBlock] > 1 + when :APICOTBERRY, :GANLONBERRY, :LIECHIBERRY, :PETAYABERRY, :SALACBERRY, + :KEEBERRY, :MARANGABERRY + # Stat raise + stat = { + :APICOTBERRY => :SPECIAL_DEFENSE, + :GANLONBERRY => :DEFENSE, + :LIECHIBERRY => :ATTACK, + :PETAYABERRY => :SPECIAL_ATTACK, + :SALACBERRY => :SPEED, + :KEEBERRY => :DEFENSE, + :MARANGABERRY => :SPECIAL_DEFENSE + }[item] + ret += 8 if stat && @ai.stat_raise_worthwhile?(self, stat) + ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) + when :STARFBERRY + # Random stat raise + ret += 8 + ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) + when :WHITEHERB + # Resets lowered stats + reduced_stats = false + GameData::Stat.each_battle do |s| + next if stages[s.id] >= 0 + reduced_stats = true + break + end + ret += 8 if reduced_stats + when :MICLEBERRY + # Raises accuracy of next move + ret += 8 + when :LANSATBERRY + # Focus energy + ret += 8 if effects[PBEffects::FocusEnergy] < 2 + when :LEPPABERRY + # Restore PP + ret += 8 + ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) + end + return ret + end + + #============================================================================= + + # These values are taken from the Complete-Fire-Red-Upgrade decomp here: + # https://github.com/Skeli789/Complete-Fire-Red-Upgrade/blob/f7f35becbd111c7e936b126f6328fc52d9af68c8/src/ability_battle_effects.c#L41 + BASE_ABILITY_RATINGS = { + :ADAPTABILITY => 8, + :AERILATE => 8, + :AFTERMATH => 5, + :AIRLOCK => 5, + :ANALYTIC => 5, + :ANGERPOINT => 4, + :ANTICIPATION => 0, + :ARENATRAP => 9, + :AROMAVEIL => 3, +# :ASONECHILLINGNEIGH => 0, +# :ASONEGRIMNEIGH => 0, + :AURABREAK => 3, + :BADDREAMS => 4, +# :BALLFETCH => 0, +# :BATTERY => 0, + :BATTLEARMOR => 2, + :BATTLEBOND => 6, + :BEASTBOOST => 7, + :BERSERK => 5, + :BIGPECKS => 1, + :BLAZE => 5, + :BULLETPROOF => 7, + :CHEEKPOUCH => 4, +# :CHILLINGNEIGH => 0, + :CHLOROPHYLL => 6, + :CLEARBODY => 4, + :CLOUDNINE => 5, + :COLORCHANGE => 2, + :COMATOSE => 6, + :COMPETITIVE => 5, + :COMPOUNDEYES => 7, + :CONTRARY => 8, + :CORROSION => 5, + :COTTONDOWN => 3, +# :CURIOUSMEDICINE => 0, + :CURSEDBODY => 4, + :CUTECHARM => 2, + :DAMP => 2, + :DANCER => 5, + :DARKAURA => 6, + :DAUNTLESSSHIELD => 3, + :DAZZLING => 5, + :DEFEATIST => -1, + :DEFIANT => 5, + :DELTASTREAM => 10, + :DESOLATELAND => 10, + :DISGUISE => 8, + :DOWNLOAD => 7, + :DRAGONSMAW => 8, + :DRIZZLE => 9, + :DROUGHT => 9, + :DRYSKIN => 6, + :EARLYBIRD => 4, + :EFFECTSPORE => 4, + :ELECTRICSURGE => 8, + :EMERGENCYEXIT => 3, + :FAIRYAURA => 6, + :FILTER => 6, + :FLAMEBODY => 4, + :FLAREBOOST => 5, + :FLASHFIRE => 6, + :FLOWERGIFT => 4, +# :FLOWERVEIL => 0, + :FLUFFY => 5, + :FORECAST => 6, + :FOREWARN => 0, +# :FRIENDGUARD => 0, + :FRISK => 0, + :FULLMETALBODY => 4, + :FURCOAT => 7, + :GALEWINGS => 6, + :GALVANIZE => 8, + :GLUTTONY => 3, + :GOOEY => 5, + :GORILLATACTICS => 4, + :GRASSPELT => 2, + :GRASSYSURGE => 8, +# :GRIMNEIGH => 0, + :GULPMISSLE => 3, + :GUTS => 6, + :HARVEST => 5, +# :HEALER => 0, + :HEATPROOF => 5, + :HEAVYMETAL => -1, +# :HONEYGATHER => 0, + :HUGEPOWER => 10, + :HUNGERSWITCH => 2, + :HUSTLE => 7, + :HYDRATION => 4, + :HYPERCUTTER => 3, + :ICEBODY => 3, + :ICEFACE => 4, + :ICESCALES => 7, +# :ILLUMINATE => 0, + :ILLUSION => 8, + :IMMUNITY => 4, + :IMPOSTER => 9, + :INFILTRATOR => 6, + :INNARDSOUT => 5, + :INNERFOCUS => 2, + :INSOMNIA => 4, + :INTIMIDATE => 7, + :INTREPIDSWORD => 3, + :IRONBARBS => 6, + :IRONFIST => 6, + :JUSTIFIED => 4, + :KEENEYE => 1, + :KLUTZ => -1, + :LEAFGUARD => 2, + :LEVITATE => 7, + :LIBERO => 8, + :LIGHTMETAL => 2, + :LIGHTNINGROD => 7, + :LIMBER => 3, + :LIQUIDOOZE => 3, + :LIQUIDVOICE => 5, + :LONGREACH => 3, + :MAGICBOUNCE => 9, + :MAGICGUARD => 9, + :MAGICIAN => 3, + :MAGMAARMOR => 1, + :MAGNETPULL => 9, + :MARVELSCALE => 5, + :MEGALAUNCHER => 7, + :MERCILESS => 4, + :MIMICRY => 2, +# :MINUS => 0, + :MIRRORARMOR => 6, + :MISTYSURGE => 8, + :MOLDBREAKER => 7, + :MOODY => 10, + :MOTORDRIVE => 6, + :MOXIE => 7, + :MULTISCALE => 8, + :MULTITYPE => 8, + :MUMMY => 5, + :NATURALCURE => 7, + :NEUROFORCE => 6, + :NEUTRALIZINGGAS => 5, + :NOGUARD => 8, + :NORMALIZE => -1, + :OBLIVIOUS => 2, + :OVERCOAT => 5, + :OVERGROW => 5, + :OWNTEMPO => 3, + :PARENTALBOND => 10, + :PASTELVEIL => 4, + :PERISHBODY => -1, + :PICKPOCKET => 3, + :PICKUP => 1, + :PIXILATE => 8, +# :PLUS => 0, + :POISONHEAL => 8, + :POISONPOINT => 4, + :POISONTOUCH => 4, + :POWERCONSTRUCT => 10, +# :POWEROFALCHEMY => 0, + :POWERSPOT => 2, + :PRANKSTER => 8, + :PRESSURE => 5, + :PRIMORDIALSEA => 10, + :PRISMARMOR => 6, + :PROPELLORTAIL => 2, + :PROTEAN => 8, + :PSYCHICSURGE => 8, + :PUNKROCK => 2, + :PUREPOWER => 10, + :QUEENLYMAJESTY => 6, +# :QUICKDRAW => 0, + :QUICKFEET => 5, + :RAINDISH => 3, + :RATTLED => 3, +# :RECEIVER => 0, + :RECKLESS => 6, + :REFRIGERATE => 8, + :REGENERATOR => 8, + :RIPEN => 4, + :RIVALRY => 1, + :RKSSYSTEM => 8, + :ROCKHEAD => 5, + :ROUGHSKIN => 6, +# :RUNAWAY => 0, + :SANDFORCE => 4, + :SANDRUSH => 6, + :SANDSPIT => 5, + :SANDSTREAM => 9, + :SANDVEIL => 3, + :SAPSIPPER => 7, + :SCHOOLING => 6, + :SCRAPPY => 6, + :SCREENCLEANER => 3, + :SERENEGRACE => 8, + :SHADOWSHIELD => 8, + :SHADOWTAG => 10, + :SHEDSKIN => 7, + :SHEERFORCE => 8, + :SHELLARMOR => 2, + :SHIELDDUST => 5, + :SHIELDSDOWN => 6, + :SIMPLE => 8, + :SKILLLINK => 7, + :SLOWSTART => -2, + :SLUSHRUSH => 5, + :SNIPER => 3, + :SNOWCLOAK => 3, + :SNOWWARNING => 8, + :SOLARPOWER => 3, + :SOLIDROCK => 6, + :SOULHEART => 7, + :SOUNDPROOF => 4, + :SPEEDBOOST => 9, + :STAKEOUT => 6, + :STALL => -1, + :STALWART => 2, + :STAMINA => 6, + :STANCECHANGE => 10, + :STATIC => 4, + :STEADFAST => 2, + :STEAMENGINE => 3, + :STEELWORKER => 6, + :STEELYSPIRIT => 2, + :STENCH => 1, + :STICKYHOLD => 3, + :STORMDRAIN => 7, + :STRONGJAW => 6, + :STURDY => 6, + :SUCTIONCUPS => 2, + :SUPERLUCK => 3, + :SURGESURFER => 4, + :SWARM => 5, + :SWEETVEIL => 4, + :SWIFTSWIM => 6, +# :SYMBIOSIS => 0, + :SYNCHRONIZE => 4, + :TANGLEDFEET => 2, + :TANGLINGHAIR => 5, + :TECHNICIAN => 8, +# :TELEPATHY => 0, + :TERAVOLT => 7, + :THICKFAT => 7, + :TINTEDLENS => 7, + :TORRENT => 5, + :TOUGHCLAWS => 7, + :TOXICBOOST => 6, + :TRACE => 6, + :TRANSISTOR => 8, + :TRIAGE => 7, + :TRUANT => -2, + :TURBOBLAZE => 7, + :UNAWARE => 6, + :UNBURDEN => 7, + :UNNERVE => 3, +# :UNSEENFIST => 0, + :VICTORYSTAR => 6, + :VITALSPIRIT => 4, + :VOLTABSORB => 7, + :WANDERINGSPIRIT => 2, + :WATERABSORB => 7, + :WATERBUBBLE => 8, + :WATERCOMPACTION => 4, + :WATERVEIL => 4, + :WEAKARMOR => 2, + :WHITESMOKE => 4, + :WIMPOUT => 3, + :WONDERGUARD => 10, + :WONDERSKIN => 4, + :ZENMODE => -1 + } + + # Returns a value indicating how beneficial the given ability will be to this + # battler if it has it. + # Return values are typically between -10 and +10. 0 is indifferent, positive + # values mean this battler benefits, negative values mean this battler suffers. + # TODO: This method assumes the ability isn't being negated. Should it return + # 0 if it is? The calculations that call this method separately check + # for it being negated, because they need to do something special in + # that case, so I think it's okay for this method to ignore negation. + def wants_ability?(ability = :NONE) + ability = ability.id if !ability.is_a?(Symbol) && ability.respond_to?("id") + # TODO: Ideally replace the above list of ratings with context-sensitive + # calculations. Should they all go in this method, or should there be + # more handlers for each ability? + case ability + when :BLAZE + return 0 if !has_damaging_move_of_type?(:FIRE) + when :CUTECHARM, :RIVALRY + return 0 if gender == 2 + when :FRIENDGUARD, :HEALER, :SYMBOISIS, :TELEPATHY + has_ally = false + each_ally(@side) { |b, i| has_ally = true } + return 0 if !has_ally + when :GALEWINGS + return 0 if !check_for_move { |m| m.type == :FLYING } + when :HUGEPOWER, :PUREPOWER + return 0 if !check_for_move { |m| m.physicalMove?(m.type) && + m.function != "UseUserDefenseInsteadOfUserAttack" && + m.function != "UseTargetAttackInsteadOfUserAttack" } + when :IRONFIST + return 0 if !check_for_move { |m| m.punchingMove? } + when :LIQUIDVOICE + return 0 if !check_for_move { |m| m.soundMove? } + when :MEGALAUNCHER + return 0 if !check_for_move { |m| m.pulseMove? } + when :OVERGROW + return 0 if !has_damaging_move_of_type?(:GRASS) + when :PRANKSTER + return 0 if !check_for_move { |m| m.statusMove? } + when :PUNKROCK + return 1 if !check_for_move { |m| m.damagingMove? && m.soundMove? } + when :RECKLESS + return 0 if !check_for_move { |m| m.recoilMove? } + when :ROCKHEAD + return 0 if !check_for_move { |m| m.recoilMove? && !m.is_a?(Battle::Move::CrashDamageIfFailsUnusableInGravity) } + when :RUNAWAY + return 0 if wild? + when :SANDFORCE + return 2 if !has_damaging_move_of_type?(:GROUND, :ROCK, :STEEL) + when :SKILLLINK + return 0 if !check_for_move { |m| m.is_a?(Battle::Move::HitTwoToFiveTimes) } + when :STEELWORKER + return 0 if !has_damaging_move_of_type?(:GRASS) + when :SWARM + return 0 if !has_damaging_move_of_type?(:BUG) + when :TORRENT + return 0 if !has_damaging_move_of_type?(:WATER) + when :TRIAGE + return 0 if !check_for_move { |m| m.healingMove? } + end + ret = BASE_ABILITY_RATINGS[ability] || 0 + return ret + end + + #============================================================================= + private def effectiveness_of_type_against_single_battler_type(type, defend_type, user = nil) diff --git a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb index eae63b93a..2d9733183 100644 --- a/Data/Scripts/011_Battle/005_AI/103_AIMove.rb +++ b/Data/Scripts/011_Battle/005_AI/103_AIMove.rb @@ -88,7 +88,7 @@ class Battle::AI::AIMove # Returns this move's base power, taking into account various effects that # modify it. def base_power - ret = @move.baseDamage + ret = @move.power ret = 60 if ret == 1 return ret if !@ai.trainer.medium_skill? return Battle::AI::Handlers.get_base_power(function, @@ -96,8 +96,8 @@ class Battle::AI::AIMove end def rough_damage - power = base_power - return power if @move.is_a?(Battle::Move::FixedDamageMove) + base_dmg = base_power + return base_dmg if @move.is_a?(Battle::Move::FixedDamageMove) 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] # Get the user and target of this move @@ -132,7 +132,7 @@ class Battle::AI::AIMove ##### Calculate all multiplier effects ##### multipliers = { - :base_damage_multiplier => 1.0, + :power_multiplier => 1.0, :attack_multiplier => 1.0, :defense_multiplier => 1.0, :final_damage_multiplier => 1.0 @@ -142,9 +142,9 @@ class Battle::AI::AIMove ((@ai.battle.pbCheckGlobalAbility(:DARKAURA) && calc_type == :DARK) || (@ai.battle.pbCheckGlobalAbility(:FAIRYAURA) && calc_type == :FAIRY)) if @ai.battle.pbCheckGlobalAbility(:AURABREAK) - multipliers[:base_damage_multiplier] *= 2 / 3.0 + multipliers[:power_multiplier] *= 2 / 3.0 else - multipliers[:base_damage_multiplier] *= 4 / 3.0 + multipliers[:power_multiplier] *= 4 / 3.0 end end @@ -155,7 +155,7 @@ class Battle::AI::AIMove abilityBlacklist = [:ANALYTIC, :SNIPER, :TINTEDLENS, :AERILATE, :PIXILATE, :REFRIGERATE] if !abilityBlacklist.include?(user.ability_id) Battle::AbilityEffects.triggerDamageCalcFromUser( - user.ability, user_battler, target_battler, @move, multipliers, power, calc_type + user.ability, user_battler, target_battler, @move, multipliers, base_dmg, calc_type ) end end @@ -164,7 +164,7 @@ class Battle::AI::AIMove user_battler.allAllies.each do |b| next if !b.abilityActive? Battle::AbilityEffects.triggerDamageCalcFromAlly( - b.ability, user_battler, target_battler, @move, multipliers, power, calc_type + b.ability, user_battler, target_battler, @move, multipliers, base_dmg, calc_type ) end if target.ability_active? @@ -173,21 +173,21 @@ class Battle::AI::AIMove abilityBlacklist = [:FILTER, :SOLIDROCK] if !abilityBlacklist.include?(target.ability_id) Battle::AbilityEffects.triggerDamageCalcFromTarget( - target.ability, user_battler, target_battler, @move, multipliers, power, calc_type + target.ability, user_battler, target_battler, @move, multipliers, base_dmg, calc_type ) end end end if target.ability_active? Battle::AbilityEffects.triggerDamageCalcFromTargetNonIgnorable( - target.ability, user_battler, target_battler, @move, multipliers, power, calc_type + target.ability, user_battler, target_battler, @move, multipliers, base_dmg, calc_type ) end if !@ai.battle.moldBreaker target_battler.allAllies.each do |b| next if !b.abilityActive? Battle::AbilityEffects.triggerDamageCalcFromTargetAlly( - b.ability, user_battler, target_battler, @move, multipliers, power, calc_type + b.ability, user_battler, target_battler, @move, multipliers, base_dmg, calc_type ) end end @@ -201,7 +201,7 @@ class Battle::AI::AIMove itemBlacklist = [:EXPERTBELT, :LIFEORB] if !itemBlacklist.include?(user.item_id) Battle::ItemEffects.triggerDamageCalcFromUser( - user.item, user_battler, target_battler, @move, multipliers, power, calc_type + user.item, user_battler, target_battler, @move, multipliers, base_dmg, calc_type ) user.effects[PBEffects::GemConsumed] = nil # Untrigger consuming of Gems end @@ -209,13 +209,13 @@ class Battle::AI::AIMove end if target.item_active? && target.item && !target.item.is_berry? Battle::ItemEffects.triggerDamageCalcFromTarget( - target.item, user_battler, target_battler, @move, multipliers, power, calc_type + target.item, user_battler, target_battler, @move, multipliers, base_dmg, calc_type ) end # Parental Bond if user.has_active_ability?(:PARENTALBOND) - multipliers[:base_damage_multiplier] *= (Settings::MECHANICS_GENERATION >= 7) ? 1.25 : 1.5 + multipliers[:power_multiplier] *= (Settings::MECHANICS_GENERATION >= 7) ? 1.25 : 1.5 end # Me First @@ -226,24 +226,24 @@ class Battle::AI::AIMove # Charge if @ai.trainer.medium_skill? && user.effects[PBEffects::Charge] > 0 && calc_type == :ELECTRIC - multipliers[:base_damage_multiplier] *= 2 + multipliers[:power_multiplier] *= 2 end # Mud Sport and Water Sport if @ai.trainer.medium_skill? if calc_type == :ELECTRIC if @ai.battle.allBattlers.any? { |b| b.effects[PBEffects::MudSport] } - multipliers[:base_damage_multiplier] /= 3 + multipliers[:power_multiplier] /= 3 end if @ai.battle.field.effects[PBEffects::MudSportField] > 0 - multipliers[:base_damage_multiplier] /= 3 + multipliers[:power_multiplier] /= 3 end elsif calc_type == :FIRE if @ai.battle.allBattlers.any? { |b| b.effects[PBEffects::WaterSport] } - multipliers[:base_damage_multiplier] /= 3 + multipliers[:power_multiplier] /= 3 end if @ai.battle.field.effects[PBEffects::WaterSportField] > 0 - multipliers[:base_damage_multiplier] /= 3 + multipliers[:power_multiplier] /= 3 end end end @@ -253,13 +253,13 @@ class Battle::AI::AIMove terrain_multiplier = (Settings::MECHANICS_GENERATION >= 8) ? 1.3 : 1.5 case @ai.battle.field.terrain when :Electric - multipliers[:base_damage_multiplier] *= terrain_multiplier if calc_type == :ELECTRIC && user_battler.affectedByTerrain? + multipliers[:power_multiplier] *= terrain_multiplier if calc_type == :ELECTRIC && user_battler.affectedByTerrain? when :Grassy - multipliers[:base_damage_multiplier] *= terrain_multiplier if calc_type == :GRASS && user_battler.affectedByTerrain? + multipliers[:power_multiplier] *= terrain_multiplier if calc_type == :GRASS && user_battler.affectedByTerrain? when :Psychic - multipliers[:base_damage_multiplier] *= terrain_multiplier if calc_type == :PSYCHIC && user_battler.affectedByTerrain? + multipliers[:power_multiplier] *= terrain_multiplier if calc_type == :PSYCHIC && user_battler.affectedByTerrain? when :Misty - multipliers[:base_damage_multiplier] /= 2 if calc_type == :DRAGON && target_battler.affectedByTerrain? + multipliers[:power_multiplier] /= 2 if calc_type == :DRAGON && target_battler.affectedByTerrain? end end @@ -370,11 +370,11 @@ class Battle::AI::AIMove # TODO ##### Main damage calculation ##### - power = [(power * multipliers[:base_damage_multiplier]).round, 1].max - atk = [(atk * multipliers[:attack_multiplier]).round, 1].max - 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 + base_dmg = [(base_dmg * multipliers[:power_multiplier]).round, 1].max + atk = [(atk * multipliers[:attack_multiplier]).round, 1].max + defense = [(defense * multipliers[:defense_multiplier]).round, 1].max + damage = ((((2.0 * user.level / 5) + 2).floor * base_dmg * atk / defense).floor / 50).floor + 2 + damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max ret = damage.floor ret = target.hp - 1 if @move.nonLethal?(user_battler, target_battler) && ret >= target.hp return ret diff --git a/Data/Scripts/011_Battle/005_AI/051_AI_MoveHandlers_Misc.rb b/Data/Scripts/011_Battle/005b_AI move function codes/051_AI_MoveHandlers_Misc.rb similarity index 100% rename from Data/Scripts/011_Battle/005_AI/051_AI_MoveHandlers_Misc.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/051_AI_MoveHandlers_Misc.rb diff --git a/Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb b/Data/Scripts/011_Battle/005b_AI move function codes/052_AI_MoveHandlers_BattlerStats.rb similarity index 100% rename from Data/Scripts/011_Battle/005_AI/052_AI_MoveHandlers_BattlerStats.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/052_AI_MoveHandlers_BattlerStats.rb diff --git a/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb b/Data/Scripts/011_Battle/005b_AI move function codes/053_AI_MoveHandlers_BattlerOther.rb similarity index 98% rename from Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/053_AI_MoveHandlers_BattlerOther.rb index 38bddfdff..6f7073d7b 100644 --- a/Data/Scripts/011_Battle/005_AI/053_AI_MoveHandlers_BattlerOther.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/053_AI_MoveHandlers_BattlerOther.rb @@ -952,8 +952,8 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimpl Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToSimple", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active? - old_ability_rating = ai.battler_wants_ability?(target, target.ability_id) - new_ability_rating = ai.battler_wants_ability?(target, :SIMPLE) + old_ability_rating = target.wants_ability?(target.ability_id) + new_ability_rating = target.wants_ability?(:SIMPLE) side_mult = (target.opposes?(user)) ? 1 : -1 if old_ability_rating > new_ability_rating score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max @@ -976,8 +976,8 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToInsom Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToInsomnia", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active? - old_ability_rating = ai.battler_wants_ability?(target, target.ability_id) - new_ability_rating = ai.battler_wants_ability?(target, :INSOMNIA) + old_ability_rating = target.wants_ability?(target.ability_id) + new_ability_rating = target.wants_ability?(:INSOMNIA) side_mult = (target.opposes?(user)) ? 1 : -1 if old_ability_rating > new_ability_rating score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max @@ -1000,8 +1000,8 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserAbilityToTargetA Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserAbilityToTargetAbility", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active? - old_ability_rating = ai.battler_wants_ability?(user, user.ability_id) - new_ability_rating = ai.battler_wants_ability?(user, target.ability_id) + old_ability_rating = user.wants_ability?(user.ability_id) + new_ability_rating = user.wants_ability?(target.ability_id) if old_ability_rating > new_ability_rating score += 4 * [old_ability_rating - new_ability_rating, 3].max elsif old_ability_rating < new_ability_rating @@ -1025,8 +1025,8 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserA Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAbility", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active? - old_ability_rating = ai.battler_wants_ability?(target, target.ability_id) - new_ability_rating = ai.battler_wants_ability?(target, user.ability_id) + old_ability_rating = target.wants_ability?(target.ability_id) + new_ability_rating = target.wants_ability?(user.ability_id) side_mult = (target.opposes?(user)) ? 1 : -1 if old_ability_rating > new_ability_rating score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max @@ -1050,12 +1050,12 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapAbilities Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAbilities", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active? && !target.ability_active? - old_user_ability_rating = ai.battler_wants_ability?(user, user.ability_id) - new_user_ability_rating = ai.battler_wants_ability?(user, target.ability_id) + old_user_ability_rating = user.wants_ability?(user.ability_id) + new_user_ability_rating = user.wants_ability?(target.ability_id) user_diff = new_user_ability_rating - old_user_ability_rating user_diff = 0 if !user.ability_active? - old_target_ability_rating = ai.battler_wants_ability?(target, target.ability_id) - new_target_ability_rating = ai.battler_wants_ability?(target, user.ability_id) + old_target_ability_rating = target.wants_ability?(target.ability_id) + new_target_ability_rating = target.wants_ability?(user.ability_id) target_diff = new_target_ability_rating - old_target_ability_rating target_diff = 0 if !target.ability_active? side_mult = (target.opposes?(user)) ? 1 : -1 @@ -1078,7 +1078,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("NegateTargetAbility", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbility", proc { |score, move, user, target, ai, battle| - target_ability_rating = ai.battler_wants_ability?(target, target.ability_id) + target_ability_rating = target.wants_ability?(target.ability_id) side_mult = (target.opposes?(user)) ? 1 : -1 if target_ability_rating > 0 score += 4 * side_mult * [target_ability_rating, 3].max @@ -1097,7 +1097,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTar next score if target.effects[PBEffects::Substitute] > 0 || target.effects[PBEffects::GastroAcid] next score if target.battler.unstoppableAbility? next score if user.faster_than?(target) - target_ability_rating = ai.battler_wants_ability?(target, target.ability_id) + target_ability_rating = target.wants_ability?(target.ability_id) side_mult = (target.opposes?(user)) ? 1 : -1 if target_ability_rating > 0 score += 4 * side_mult * [target_ability_rating, 3].max diff --git a/Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb b/Data/Scripts/011_Battle/005b_AI move function codes/054_AI_MoveHandlers_MoveAttributes.rb similarity index 100% rename from Data/Scripts/011_Battle/005_AI/054_AI_MoveHandlers_MoveAttributes.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/054_AI_MoveHandlers_MoveAttributes.rb diff --git a/Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb b/Data/Scripts/011_Battle/005b_AI move function codes/055_AI_MoveHandlers_MultiHit.rb similarity index 100% rename from Data/Scripts/011_Battle/005_AI/055_AI_MoveHandlers_MultiHit.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/055_AI_MoveHandlers_MultiHit.rb diff --git a/Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb b/Data/Scripts/011_Battle/005b_AI move function codes/056_AI_MoveHandlers_Healing.rb similarity index 100% rename from Data/Scripts/011_Battle/005_AI/056_AI_MoveHandlers_Healing.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/056_AI_MoveHandlers_Healing.rb diff --git a/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb b/Data/Scripts/011_Battle/005b_AI move function codes/057_AI_MoveHandlers_Items.rb similarity index 88% rename from Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/057_AI_MoveHandlers_Items.rb index 6a570d10e..ff3db8ba2 100644 --- a/Data/Scripts/011_Battle/005_AI/057_AI_MoveHandlers_Items.rb +++ b/Data/Scripts/011_Battle/005b_AI move function codes/057_AI_MoveHandlers_Items.rb @@ -9,10 +9,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTakesTargetItem", next score if target.effects[PBEffects::Substitute] > 0 next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker # User can steal the target's item; score it - user_item_preference = ai.battler_wants_item?(user, target.item_id) - user_no_item_preference = ai.battler_wants_item?(user, :NONE) - target_item_preference = ai.battler_wants_item?(target, target.item_id) - target_no_item_preference = ai.battler_wants_item?(target, :NONE) + user_item_preference = user.wants_item?(target.item_id) + user_no_item_preference = user.wants_item?(:NONE) + target_item_preference = target.wants_item?(target.item_id) + target_no_item_preference = target.wants_item?(:NONE) score += (user_item_preference - user_no_item_preference) * 3 score += (target_item_preference - target_no_item_preference) * 3 next score @@ -31,10 +31,10 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetTakesUserItem", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetTakesUserItem", proc { |score, move, user, target, ai, battle| - user_item_preference = ai.battler_wants_item?(user, user.item_id) - user_no_item_preference = ai.battler_wants_item?(user, :NONE) - target_item_preference = ai.battler_wants_item?(target, user.item_id) - target_no_item_preference = ai.battler_wants_item?(target, :NONE) + user_item_preference = user.wants_item?(user.item_id) + user_no_item_preference = user.wants_item?(:NONE) + target_item_preference = target.wants_item?(user.item_id) + target_no_item_preference = target.wants_item?(:NONE) score -= (user_item_preference - user_no_item_preference) * 3 score -= (target_item_preference - target_no_item_preference) * 3 next score @@ -56,10 +56,10 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapItems", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems", proc { |score, move, user, target, ai, battle| - user_new_item_preference = ai.battler_wants_item?(user, target.item_id) - user_old_item_preference = ai.battler_wants_item?(user, user.item_id) - target_new_item_preference = ai.battler_wants_item?(target, user.item_id) - target_old_item_preference = ai.battler_wants_item?(target, target.item_id) + user_new_item_preference = user.wants_item?(target.item_id) + user_old_item_preference = user.wants_item?(user.item_id) + target_new_item_preference = target.wants_item?(user.item_id) + target_old_item_preference = target.wants_item?(target.item_id) score += (user_new_item_preference - user_old_item_preference) * 3 score -= (target_new_item_preference - target_old_item_preference) * 3 # Don't prefer if user used this move in the last round @@ -79,8 +79,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("RestoreUserConsumedItem", ) Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem", proc { |score, move, user, ai, battle| - user_new_item_preference = ai.battler_wants_item?(user, user.battler.recycleItem) - user_old_item_preference = ai.battler_wants_item?(user, user.item_id) + user_new_item_preference = user.wants_item?(user.battler.recycleItem) + user_old_item_preference = user.wants_item?(user.item_id) score += (user_new_item_preference - user_old_item_preference) * 4 next score } @@ -101,8 +101,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveTargetItem", next score if target.effects[PBEffects::Substitute] > 0 next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker # User can knock off the target's item; score it - target_item_preference = ai.battler_wants_item?(target, target.item_id) - target_no_item_preference = ai.battler_wants_item?(target, :NONE) + target_item_preference = target.wants_item?(target.item_id) + target_no_item_preference = target.wants_item?(:NONE) score += (target_item_preference - target_no_item_preference) * 4 next score } @@ -119,8 +119,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DestroyTargetBerryOrGem" next score if target.effects[PBEffects::Substitute] > 0 next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker # User can incinerate the target's item; score it - target_item_preference = ai.battler_wants_item?(target, target.item_id) - target_no_item_preference = ai.battler_wants_item?(target, :NONE) + target_item_preference = target.wants_item?(target.item_id) + target_no_item_preference = target.wants_item?(:NONE) score += (target_item_preference - target_no_item_preference) * 4 next score } @@ -140,8 +140,8 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CorrodeTargetItem", ) Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem", proc { |score, move, user, target, ai, battle| - target_item_preference = ai.battler_wants_item?(target, target.item_id) - target_no_item_preference = ai.battler_wants_item?(target, :NONE) + target_item_preference = target.wants_item?(target.item_id) + target_no_item_preference = target.wants_item?(:NONE) score += (target_item_preference - target_no_item_preference) * 4 next score } @@ -158,7 +158,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetCannotUseIte Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetCannotUseItem", proc { |score, move, user, target, ai, battle| next Battle::AI::MOVE_USELESS_SCORE if !target.item || !target.item_active? - item_score = ai.battler_wants_item?(target, target.item_id) + item_score = target.wants_item?(target.item_id) score += item_score * 5 next score } @@ -265,8 +265,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserConsumeTargetBerry", score -= 5 if target.has_active_ability?(:UNBURDEN) end # Score the target no longer having the item - target_item_preference = ai.battler_wants_item?(target, target.item_id) - target_no_item_preference = ai.battler_wants_item?(target, :NONE) + target_item_preference = target.wants_item?(target.item_id) + target_no_item_preference = target.wants_item?(:NONE) score += (target_item_preference - target_no_item_preference) * 4 next score } @@ -317,8 +317,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ThrowUserItemAtTarget", end # Prefer if the user doesn't want its held item/don't prefer if it wants to # keep its held item - user_item_preference = ai.battler_wants_item?(user, user.item_id) - user_no_item_preference = ai.battler_wants_item?(user, :NONE) + user_item_preference = user.wants_item?(user.item_id) + user_no_item_preference = user.wants_item?(:NONE) score += (user_item_preference - user_no_item_preference) * 4 next score } diff --git a/Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb b/Data/Scripts/011_Battle/005b_AI move function codes/058_AI_MoveHandlers_ChangeMoveEffect.rb similarity index 100% rename from Data/Scripts/011_Battle/005_AI/058_AI_MoveHandlers_ChangeMoveEffect.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/058_AI_MoveHandlers_ChangeMoveEffect.rb diff --git a/Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb b/Data/Scripts/011_Battle/005b_AI move function codes/059_AI_MoveHandlers_SwitchingActing.rb similarity index 100% rename from Data/Scripts/011_Battle/005_AI/059_AI_MoveHandlers_SwitchingActing.rb rename to Data/Scripts/011_Battle/005b_AI move function codes/059_AI_MoveHandlers_SwitchingActing.rb diff --git a/Data/Scripts/022_Maruno/001_move target lister.rb b/Data/Scripts/022_Maruno/001_move target lister.rb new file mode 100644 index 000000000..f1c4e2139 --- /dev/null +++ b/Data/Scripts/022_Maruno/001_move target lister.rb @@ -0,0 +1,82 @@ +#=============================================================================== +# +#=============================================================================== +def marListMoveTargetFunctionCodes + target_hash = {} + function_hash = {} + + GameData::Move.each do |move| + target_hash[move.target] ||= [] + target_hash[move.target].push(move.function_code) + function_hash[move.function_code] ||= [] + function_hash[move.function_code].push(move.target) + end + + # Write results to file + File.open("moves_by_target.txt", "wb") { |f| + f.write(0xEF.chr) + f.write(0xBB.chr) + f.write(0xBF.chr) + + f.write("=========================================================\r\n") + f.write("SORTED BY TARGET\r\n") + f.write("=========================================================\r\n\r\n") + target_keys = target_hash.keys.sort { |a, b| a.downcase <=> b.downcase } + target_keys.each do |key| + next if !key || !target_hash[key] || target_hash[key].length == 0 + f.write("===== #{key} =====\r\n\r\n") + arr = target_hash[key].uniq.sort + arr.each { |code| f.write("#{code}\r\n")} + f.write("\r\n") + end + } + + File.open("moves_by_function_code.txt", "wb") { |f| + f.write(0xEF.chr) + f.write(0xBB.chr) + f.write(0xBF.chr) + + f.write("=========================================================\r\n") + f.write("SORTED BY FUNCTION CODE\r\n") + f.write("=========================================================\r\n\r\n") + + code_keys = function_hash.keys.sort { |a, b| a.downcase <=> b.downcase } + code_keys.each do |key| + next if !key || !function_hash[key] || function_hash[key].length == 0 + f.write("===== #{key} =====\r\n\r\n") + function_hash[key].sort.each { |target| f.write("#{target}\r\n")} + f.write("\r\n") + end + } + + File.open("moves_by_function_code_multiple_target_types_only.txt", "wb") { |f| + f.write(0xEF.chr) + f.write(0xBB.chr) + f.write(0xBF.chr) + + f.write("=========================================================\r\n") + f.write("SORTED BY FUNCTION CODE\r\n") + f.write("=========================================================\r\n\r\n") + + code_keys = function_hash.keys.sort { |a, b| a.downcase <=> b.downcase } + code_keys.each do |key| + next if !key || !function_hash[key] || function_hash[key].length == 0 + next if function_hash[key].uniq.length <= 1 + f.write("===== #{key} =====\r\n\r\n") + function_hash[key].sort.each { |target| f.write("#{target}\r\n")} + f.write("\r\n") + end + } +end + +#=============================================================================== +# Add to Debug menu +#=============================================================================== +MenuHandlers.add(:debug_menu, :print_move_target_functions, { + "name" => _INTL("Print Out Move Targets"), + "parent" => :other_menu, + "description" => _INTL("Print all blah blah blah."), + "effect" => proc { + marListMoveTargetFunctionCodes + } +})