mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-08 05:34:58 +00:00
Some rearranging of AI script files/methods
This commit is contained in:
@@ -25,8 +25,8 @@ class Battle::AI
|
|||||||
moveData = GameData::Move.get(target.lastMoveUsed)
|
moveData = GameData::Move.get(target.lastMoveUsed)
|
||||||
moveType = moveData.type
|
moveType = moveData.type
|
||||||
typeMod = @user.effectiveness_of_type_against_battler(moveType, foe)
|
typeMod = @user.effectiveness_of_type_against_battler(moveType, foe)
|
||||||
if Effectiveness.super_effective?(typeMod) && moveData.base_damage > 50
|
if Effectiveness.super_effective?(typeMod) && moveData.power > 50
|
||||||
switchChance = (moveData.base_damage > 70) ? 30 : 20
|
switchChance = (moveData.power > 70) ? 30 : 20
|
||||||
shouldSwitch = (pbAIRandom(100) < switchChance)
|
shouldSwitch = (pbAIRandom(100) < switchChance)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -169,7 +169,7 @@ class Battle::AI
|
|||||||
pkmn = party[i]
|
pkmn = party[i]
|
||||||
sum = 0
|
sum = 0
|
||||||
pkmn.moves.each do |m|
|
pkmn.moves.each do |m|
|
||||||
next if m.base_damage == 0
|
next if m.power == 0
|
||||||
@battle.battlers[idxBattler].allOpposing.each do |b|
|
@battle.battlers[idxBattler].allOpposing.each do |b|
|
||||||
bTypes = b.pbTypes(true)
|
bTypes = b.pbTypes(true)
|
||||||
sum += Effectiveness.calculate(m.type, *bTypes)
|
sum += Effectiveness.calculate(m.type, *bTypes)
|
||||||
|
|||||||
@@ -536,7 +536,7 @@ class Battle::AI
|
|||||||
|
|
||||||
when :ACCURACY
|
when :ACCURACY
|
||||||
# Prefer if user knows any weaker moves
|
# 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
|
# Prefer if target has a raised evasion
|
||||||
sum_stages = @target.stages[:EVASION]
|
sum_stages = @target.stages[:EVASION]
|
||||||
mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0
|
mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0
|
||||||
@@ -996,465 +996,4 @@ class Battle::AI
|
|||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ class Battle::AI::AIBattler
|
|||||||
def pokemon; return @battler.pokemon; end
|
def pokemon; return @battler.pokemon; end
|
||||||
def level; return @battler.level; end
|
def level; return @battler.level; end
|
||||||
def hp; return @battler.hp; end
|
def hp; return @battler.hp; end
|
||||||
|
def totalhp; return @battler.totalhp; end
|
||||||
def fainted?; return @battler.fainted?; end
|
def fainted?; return @battler.fainted?; end
|
||||||
def status; return @battler.status; end
|
def status; return @battler.status; end
|
||||||
def statusCount; return @battler.statusCount; end
|
def statusCount; return @battler.statusCount; end
|
||||||
def totalhp; return @battler.totalhp; end
|
|
||||||
def gender; return @battler.gender; end
|
def gender; return @battler.gender; end
|
||||||
def turnCount; return @battler.turnCount; end
|
def turnCount; return @battler.turnCount; end
|
||||||
def effects; return @battler.effects; 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
|
private
|
||||||
|
|
||||||
def effectiveness_of_type_against_single_battler_type(type, defend_type, user = nil)
|
def effectiveness_of_type_against_single_battler_type(type, defend_type, user = nil)
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class Battle::AI::AIMove
|
|||||||
# Returns this move's base power, taking into account various effects that
|
# Returns this move's base power, taking into account various effects that
|
||||||
# modify it.
|
# modify it.
|
||||||
def base_power
|
def base_power
|
||||||
ret = @move.baseDamage
|
ret = @move.power
|
||||||
ret = 60 if ret == 1
|
ret = 60 if ret == 1
|
||||||
return ret if !@ai.trainer.medium_skill?
|
return ret if !@ai.trainer.medium_skill?
|
||||||
return Battle::AI::Handlers.get_base_power(function,
|
return Battle::AI::Handlers.get_base_power(function,
|
||||||
@@ -96,8 +96,8 @@ class Battle::AI::AIMove
|
|||||||
end
|
end
|
||||||
|
|
||||||
def rough_damage
|
def rough_damage
|
||||||
power = base_power
|
base_dmg = base_power
|
||||||
return power if @move.is_a?(Battle::Move::FixedDamageMove)
|
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_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]
|
stage_div = [8, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2]
|
||||||
# Get the user and target of this move
|
# Get the user and target of this move
|
||||||
@@ -132,7 +132,7 @@ class Battle::AI::AIMove
|
|||||||
|
|
||||||
##### Calculate all multiplier effects #####
|
##### Calculate all multiplier effects #####
|
||||||
multipliers = {
|
multipliers = {
|
||||||
:base_damage_multiplier => 1.0,
|
:power_multiplier => 1.0,
|
||||||
:attack_multiplier => 1.0,
|
:attack_multiplier => 1.0,
|
||||||
:defense_multiplier => 1.0,
|
:defense_multiplier => 1.0,
|
||||||
:final_damage_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(:DARKAURA) && calc_type == :DARK) ||
|
||||||
(@ai.battle.pbCheckGlobalAbility(:FAIRYAURA) && calc_type == :FAIRY))
|
(@ai.battle.pbCheckGlobalAbility(:FAIRYAURA) && calc_type == :FAIRY))
|
||||||
if @ai.battle.pbCheckGlobalAbility(:AURABREAK)
|
if @ai.battle.pbCheckGlobalAbility(:AURABREAK)
|
||||||
multipliers[:base_damage_multiplier] *= 2 / 3.0
|
multipliers[:power_multiplier] *= 2 / 3.0
|
||||||
else
|
else
|
||||||
multipliers[:base_damage_multiplier] *= 4 / 3.0
|
multipliers[:power_multiplier] *= 4 / 3.0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ class Battle::AI::AIMove
|
|||||||
abilityBlacklist = [:ANALYTIC, :SNIPER, :TINTEDLENS, :AERILATE, :PIXILATE, :REFRIGERATE]
|
abilityBlacklist = [:ANALYTIC, :SNIPER, :TINTEDLENS, :AERILATE, :PIXILATE, :REFRIGERATE]
|
||||||
if !abilityBlacklist.include?(user.ability_id)
|
if !abilityBlacklist.include?(user.ability_id)
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromUser(
|
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
|
||||||
end
|
end
|
||||||
@@ -164,7 +164,7 @@ class Battle::AI::AIMove
|
|||||||
user_battler.allAllies.each do |b|
|
user_battler.allAllies.each do |b|
|
||||||
next if !b.abilityActive?
|
next if !b.abilityActive?
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromAlly(
|
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
|
end
|
||||||
if target.ability_active?
|
if target.ability_active?
|
||||||
@@ -173,21 +173,21 @@ class Battle::AI::AIMove
|
|||||||
abilityBlacklist = [:FILTER, :SOLIDROCK]
|
abilityBlacklist = [:FILTER, :SOLIDROCK]
|
||||||
if !abilityBlacklist.include?(target.ability_id)
|
if !abilityBlacklist.include?(target.ability_id)
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromTarget(
|
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
|
end
|
||||||
end
|
end
|
||||||
if target.ability_active?
|
if target.ability_active?
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromTargetNonIgnorable(
|
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
|
end
|
||||||
if !@ai.battle.moldBreaker
|
if !@ai.battle.moldBreaker
|
||||||
target_battler.allAllies.each do |b|
|
target_battler.allAllies.each do |b|
|
||||||
next if !b.abilityActive?
|
next if !b.abilityActive?
|
||||||
Battle::AbilityEffects.triggerDamageCalcFromTargetAlly(
|
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
|
||||||
end
|
end
|
||||||
@@ -201,7 +201,7 @@ class Battle::AI::AIMove
|
|||||||
itemBlacklist = [:EXPERTBELT, :LIFEORB]
|
itemBlacklist = [:EXPERTBELT, :LIFEORB]
|
||||||
if !itemBlacklist.include?(user.item_id)
|
if !itemBlacklist.include?(user.item_id)
|
||||||
Battle::ItemEffects.triggerDamageCalcFromUser(
|
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
|
user.effects[PBEffects::GemConsumed] = nil # Untrigger consuming of Gems
|
||||||
end
|
end
|
||||||
@@ -209,13 +209,13 @@ class Battle::AI::AIMove
|
|||||||
end
|
end
|
||||||
if target.item_active? && target.item && !target.item.is_berry?
|
if target.item_active? && target.item && !target.item.is_berry?
|
||||||
Battle::ItemEffects.triggerDamageCalcFromTarget(
|
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
|
end
|
||||||
|
|
||||||
# Parental Bond
|
# Parental Bond
|
||||||
if user.has_active_ability?(:PARENTALBOND)
|
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
|
end
|
||||||
|
|
||||||
# Me First
|
# Me First
|
||||||
@@ -226,24 +226,24 @@ class Battle::AI::AIMove
|
|||||||
# Charge
|
# Charge
|
||||||
if @ai.trainer.medium_skill? &&
|
if @ai.trainer.medium_skill? &&
|
||||||
user.effects[PBEffects::Charge] > 0 && calc_type == :ELECTRIC
|
user.effects[PBEffects::Charge] > 0 && calc_type == :ELECTRIC
|
||||||
multipliers[:base_damage_multiplier] *= 2
|
multipliers[:power_multiplier] *= 2
|
||||||
end
|
end
|
||||||
|
|
||||||
# Mud Sport and Water Sport
|
# Mud Sport and Water Sport
|
||||||
if @ai.trainer.medium_skill?
|
if @ai.trainer.medium_skill?
|
||||||
if calc_type == :ELECTRIC
|
if calc_type == :ELECTRIC
|
||||||
if @ai.battle.allBattlers.any? { |b| b.effects[PBEffects::MudSport] }
|
if @ai.battle.allBattlers.any? { |b| b.effects[PBEffects::MudSport] }
|
||||||
multipliers[:base_damage_multiplier] /= 3
|
multipliers[:power_multiplier] /= 3
|
||||||
end
|
end
|
||||||
if @ai.battle.field.effects[PBEffects::MudSportField] > 0
|
if @ai.battle.field.effects[PBEffects::MudSportField] > 0
|
||||||
multipliers[:base_damage_multiplier] /= 3
|
multipliers[:power_multiplier] /= 3
|
||||||
end
|
end
|
||||||
elsif calc_type == :FIRE
|
elsif calc_type == :FIRE
|
||||||
if @ai.battle.allBattlers.any? { |b| b.effects[PBEffects::WaterSport] }
|
if @ai.battle.allBattlers.any? { |b| b.effects[PBEffects::WaterSport] }
|
||||||
multipliers[:base_damage_multiplier] /= 3
|
multipliers[:power_multiplier] /= 3
|
||||||
end
|
end
|
||||||
if @ai.battle.field.effects[PBEffects::WaterSportField] > 0
|
if @ai.battle.field.effects[PBEffects::WaterSportField] > 0
|
||||||
multipliers[:base_damage_multiplier] /= 3
|
multipliers[:power_multiplier] /= 3
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -253,13 +253,13 @@ class Battle::AI::AIMove
|
|||||||
terrain_multiplier = (Settings::MECHANICS_GENERATION >= 8) ? 1.3 : 1.5
|
terrain_multiplier = (Settings::MECHANICS_GENERATION >= 8) ? 1.3 : 1.5
|
||||||
case @ai.battle.field.terrain
|
case @ai.battle.field.terrain
|
||||||
when :Electric
|
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
|
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
|
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
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -370,10 +370,10 @@ class Battle::AI::AIMove
|
|||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
##### Main damage calculation #####
|
##### Main damage calculation #####
|
||||||
power = [(power * multipliers[:base_damage_multiplier]).round, 1].max
|
base_dmg = [(base_dmg * multipliers[:power_multiplier]).round, 1].max
|
||||||
atk = [(atk * multipliers[:attack_multiplier]).round, 1].max
|
atk = [(atk * multipliers[:attack_multiplier]).round, 1].max
|
||||||
defense = [(defense * multipliers[:defense_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 = ((((2.0 * user.level / 5) + 2).floor * base_dmg * atk / defense).floor / 50).floor + 2
|
||||||
damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max
|
damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max
|
||||||
ret = damage.floor
|
ret = damage.floor
|
||||||
ret = target.hp - 1 if @move.nonLethal?(user_battler, target_battler) && ret >= target.hp
|
ret = target.hp - 1 if @move.nonLethal?(user_battler, target_battler) && ret >= target.hp
|
||||||
|
|||||||
@@ -952,8 +952,8 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimpl
|
|||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToSimple",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToSimple",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
||||||
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
old_ability_rating = target.wants_ability?(target.ability_id)
|
||||||
new_ability_rating = ai.battler_wants_ability?(target, :SIMPLE)
|
new_ability_rating = target.wants_ability?(:SIMPLE)
|
||||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||||
if old_ability_rating > new_ability_rating
|
if old_ability_rating > new_ability_rating
|
||||||
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
|
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",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToInsomnia",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
||||||
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
old_ability_rating = target.wants_ability?(target.ability_id)
|
||||||
new_ability_rating = ai.battler_wants_ability?(target, :INSOMNIA)
|
new_ability_rating = target.wants_ability?(:INSOMNIA)
|
||||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||||
if old_ability_rating > new_ability_rating
|
if old_ability_rating > new_ability_rating
|
||||||
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
|
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",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserAbilityToTargetAbility",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active?
|
next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active?
|
||||||
old_ability_rating = ai.battler_wants_ability?(user, user.ability_id)
|
old_ability_rating = user.wants_ability?(user.ability_id)
|
||||||
new_ability_rating = ai.battler_wants_ability?(user, target.ability_id)
|
new_ability_rating = user.wants_ability?(target.ability_id)
|
||||||
if old_ability_rating > new_ability_rating
|
if old_ability_rating > new_ability_rating
|
||||||
score += 4 * [old_ability_rating - new_ability_rating, 3].max
|
score += 4 * [old_ability_rating - new_ability_rating, 3].max
|
||||||
elsif old_ability_rating < new_ability_rating
|
elsif old_ability_rating < new_ability_rating
|
||||||
@@ -1025,8 +1025,8 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserA
|
|||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAbility",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAbility",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
|
||||||
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
old_ability_rating = target.wants_ability?(target.ability_id)
|
||||||
new_ability_rating = ai.battler_wants_ability?(target, user.ability_id)
|
new_ability_rating = target.wants_ability?(user.ability_id)
|
||||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||||
if old_ability_rating > new_ability_rating
|
if old_ability_rating > new_ability_rating
|
||||||
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
|
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",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAbilities",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active? && !target.ability_active?
|
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)
|
old_user_ability_rating = user.wants_ability?(user.ability_id)
|
||||||
new_user_ability_rating = ai.battler_wants_ability?(user, target.ability_id)
|
new_user_ability_rating = user.wants_ability?(target.ability_id)
|
||||||
user_diff = new_user_ability_rating - old_user_ability_rating
|
user_diff = new_user_ability_rating - old_user_ability_rating
|
||||||
user_diff = 0 if !user.ability_active?
|
user_diff = 0 if !user.ability_active?
|
||||||
old_target_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
|
old_target_ability_rating = target.wants_ability?(target.ability_id)
|
||||||
new_target_ability_rating = ai.battler_wants_ability?(target, user.ability_id)
|
new_target_ability_rating = target.wants_ability?(user.ability_id)
|
||||||
target_diff = new_target_ability_rating - old_target_ability_rating
|
target_diff = new_target_ability_rating - old_target_ability_rating
|
||||||
target_diff = 0 if !target.ability_active?
|
target_diff = 0 if !target.ability_active?
|
||||||
side_mult = (target.opposes?(user)) ? 1 : -1
|
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||||
@@ -1078,7 +1078,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("NegateTargetAbility",
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbility",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbility",
|
||||||
proc { |score, move, user, target, ai, battle|
|
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
|
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||||
if target_ability_rating > 0
|
if target_ability_rating > 0
|
||||||
score += 4 * side_mult * [target_ability_rating, 3].max
|
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.effects[PBEffects::Substitute] > 0 || target.effects[PBEffects::GastroAcid]
|
||||||
next score if target.battler.unstoppableAbility?
|
next score if target.battler.unstoppableAbility?
|
||||||
next score if user.faster_than?(target)
|
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
|
side_mult = (target.opposes?(user)) ? 1 : -1
|
||||||
if target_ability_rating > 0
|
if target_ability_rating > 0
|
||||||
score += 4 * side_mult * [target_ability_rating, 3].max
|
score += 4 * side_mult * [target_ability_rating, 3].max
|
||||||
@@ -9,10 +9,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTakesTargetItem",
|
|||||||
next score if target.effects[PBEffects::Substitute] > 0
|
next score if target.effects[PBEffects::Substitute] > 0
|
||||||
next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker
|
next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker
|
||||||
# User can steal the target's item; score it
|
# User can steal the target's item; score it
|
||||||
user_item_preference = ai.battler_wants_item?(user, target.item_id)
|
user_item_preference = user.wants_item?(target.item_id)
|
||||||
user_no_item_preference = ai.battler_wants_item?(user, :NONE)
|
user_no_item_preference = user.wants_item?(:NONE)
|
||||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
target_item_preference = target.wants_item?(target.item_id)
|
||||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
target_no_item_preference = target.wants_item?(:NONE)
|
||||||
score += (user_item_preference - user_no_item_preference) * 3
|
score += (user_item_preference - user_no_item_preference) * 3
|
||||||
score += (target_item_preference - target_no_item_preference) * 3
|
score += (target_item_preference - target_no_item_preference) * 3
|
||||||
next score
|
next score
|
||||||
@@ -31,10 +31,10 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetTakesUserItem",
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetTakesUserItem",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetTakesUserItem",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
user_item_preference = ai.battler_wants_item?(user, user.item_id)
|
user_item_preference = user.wants_item?(user.item_id)
|
||||||
user_no_item_preference = ai.battler_wants_item?(user, :NONE)
|
user_no_item_preference = user.wants_item?(:NONE)
|
||||||
target_item_preference = ai.battler_wants_item?(target, user.item_id)
|
target_item_preference = target.wants_item?(user.item_id)
|
||||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
target_no_item_preference = target.wants_item?(:NONE)
|
||||||
score -= (user_item_preference - user_no_item_preference) * 3
|
score -= (user_item_preference - user_no_item_preference) * 3
|
||||||
score -= (target_item_preference - target_no_item_preference) * 3
|
score -= (target_item_preference - target_no_item_preference) * 3
|
||||||
next score
|
next score
|
||||||
@@ -56,10 +56,10 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapItems",
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
user_new_item_preference = ai.battler_wants_item?(user, target.item_id)
|
user_new_item_preference = user.wants_item?(target.item_id)
|
||||||
user_old_item_preference = ai.battler_wants_item?(user, user.item_id)
|
user_old_item_preference = user.wants_item?(user.item_id)
|
||||||
target_new_item_preference = ai.battler_wants_item?(target, user.item_id)
|
target_new_item_preference = target.wants_item?(user.item_id)
|
||||||
target_old_item_preference = ai.battler_wants_item?(target, target.item_id)
|
target_old_item_preference = target.wants_item?(target.item_id)
|
||||||
score += (user_new_item_preference - user_old_item_preference) * 3
|
score += (user_new_item_preference - user_old_item_preference) * 3
|
||||||
score -= (target_new_item_preference - target_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
|
# 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",
|
Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem",
|
||||||
proc { |score, move, user, ai, battle|
|
proc { |score, move, user, ai, battle|
|
||||||
user_new_item_preference = ai.battler_wants_item?(user, user.battler.recycleItem)
|
user_new_item_preference = user.wants_item?(user.battler.recycleItem)
|
||||||
user_old_item_preference = ai.battler_wants_item?(user, user.item_id)
|
user_old_item_preference = user.wants_item?(user.item_id)
|
||||||
score += (user_new_item_preference - user_old_item_preference) * 4
|
score += (user_new_item_preference - user_old_item_preference) * 4
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -101,8 +101,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveTargetItem",
|
|||||||
next score if target.effects[PBEffects::Substitute] > 0
|
next score if target.effects[PBEffects::Substitute] > 0
|
||||||
next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker
|
next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker
|
||||||
# User can knock off the target's item; score it
|
# User can knock off the target's item; score it
|
||||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
target_item_preference = target.wants_item?(target.item_id)
|
||||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
target_no_item_preference = target.wants_item?(:NONE)
|
||||||
score += (target_item_preference - target_no_item_preference) * 4
|
score += (target_item_preference - target_no_item_preference) * 4
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -119,8 +119,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DestroyTargetBerryOrGem"
|
|||||||
next score if target.effects[PBEffects::Substitute] > 0
|
next score if target.effects[PBEffects::Substitute] > 0
|
||||||
next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker
|
next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker
|
||||||
# User can incinerate the target's item; score it
|
# User can incinerate the target's item; score it
|
||||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
target_item_preference = target.wants_item?(target.item_id)
|
||||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
target_no_item_preference = target.wants_item?(:NONE)
|
||||||
score += (target_item_preference - target_no_item_preference) * 4
|
score += (target_item_preference - target_no_item_preference) * 4
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -140,8 +140,8 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CorrodeTargetItem",
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
target_item_preference = target.wants_item?(target.item_id)
|
||||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
target_no_item_preference = target.wants_item?(:NONE)
|
||||||
score += (target_item_preference - target_no_item_preference) * 4
|
score += (target_item_preference - target_no_item_preference) * 4
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetCannotUseIte
|
|||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetCannotUseItem",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetCannotUseItem",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !target.item || !target.item_active?
|
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
|
score += item_score * 5
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -265,8 +265,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserConsumeTargetBerry",
|
|||||||
score -= 5 if target.has_active_ability?(:UNBURDEN)
|
score -= 5 if target.has_active_ability?(:UNBURDEN)
|
||||||
end
|
end
|
||||||
# Score the target no longer having the item
|
# Score the target no longer having the item
|
||||||
target_item_preference = ai.battler_wants_item?(target, target.item_id)
|
target_item_preference = target.wants_item?(target.item_id)
|
||||||
target_no_item_preference = ai.battler_wants_item?(target, :NONE)
|
target_no_item_preference = target.wants_item?(:NONE)
|
||||||
score += (target_item_preference - target_no_item_preference) * 4
|
score += (target_item_preference - target_no_item_preference) * 4
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -317,8 +317,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ThrowUserItemAtTarget",
|
|||||||
end
|
end
|
||||||
# Prefer if the user doesn't want its held item/don't prefer if it wants to
|
# Prefer if the user doesn't want its held item/don't prefer if it wants to
|
||||||
# keep its held item
|
# keep its held item
|
||||||
user_item_preference = ai.battler_wants_item?(user, user.item_id)
|
user_item_preference = user.wants_item?(user.item_id)
|
||||||
user_no_item_preference = ai.battler_wants_item?(user, :NONE)
|
user_no_item_preference = user.wants_item?(:NONE)
|
||||||
score += (user_item_preference - user_no_item_preference) * 4
|
score += (user_item_preference - user_no_item_preference) * 4
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
82
Data/Scripts/022_Maruno/001_move target lister.rb
Normal file
82
Data/Scripts/022_Maruno/001_move target lister.rb
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user