mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-07 13:15:01 +00:00
221 lines
9.1 KiB
Ruby
221 lines
9.1 KiB
Ruby
#===============================================================================
|
|
#
|
|
#===============================================================================
|
|
class Battle::AI
|
|
HP_HEAL_ITEMS = {
|
|
:POTION => 20,
|
|
:SUPERPOTION => (Settings::REBALANCED_HEALING_ITEM_AMOUNTS) ? 60 : 50,
|
|
:HYPERPOTION => (Settings::REBALANCED_HEALING_ITEM_AMOUNTS) ? 120 : 200,
|
|
:MAXPOTION => 999,
|
|
:BERRYJUICE => 20,
|
|
:SWEETHEART => 20,
|
|
:FRESHWATER => (Settings::REBALANCED_HEALING_ITEM_AMOUNTS) ? 30 : 50,
|
|
:SODAPOP => (Settings::REBALANCED_HEALING_ITEM_AMOUNTS) ? 50 : 60,
|
|
:LEMONADE => (Settings::REBALANCED_HEALING_ITEM_AMOUNTS) ? 70 : 80,
|
|
:MOOMOOMILK => 100,
|
|
:ORANBERRY => 10,
|
|
:SITRUSBERRY => 1, # Actual amount is determined below (pkmn.totalhp / 4)
|
|
:ENERGYPOWDER => (Settings::REBALANCED_HEALING_ITEM_AMOUNTS) ? 60 : 50,
|
|
:ENERGYROOT => (Settings::REBALANCED_HEALING_ITEM_AMOUNTS) ? 120 : 200
|
|
}
|
|
HP_HEAL_ITEMS[:RAGECANDYBAR] = 20 if !Settings::RAGE_CANDY_BAR_CURES_STATUS_PROBLEMS
|
|
FULL_RESTORE_ITEMS = [
|
|
:FULLRESTORE
|
|
]
|
|
ONE_STATUS_CURE_ITEMS = [ # Preferred over items that heal all status problems
|
|
:AWAKENING, :CHESTOBERRY, :BLUEFLUTE,
|
|
:ANTIDOTE, :PECHABERRY,
|
|
:BURNHEAL, :RAWSTBERRY,
|
|
:PARALYZEHEAL, :PARLYZHEAL, :CHERIBERRY,
|
|
:ICEHEAL, :ASPEARBERRY
|
|
]
|
|
ALL_STATUS_CURE_ITEMS = [
|
|
:FULLHEAL, :LAVACOOKIE, :OLDGATEAU, :CASTELIACONE, :LUMIOSEGALETTE,
|
|
:SHALOURSABLE, :BIGMALASADA, :PEWTERCRUNCHIES, :LUMBERRY, :HEALPOWDER
|
|
]
|
|
ALL_STATUS_CURE_ITEMS.push(:RAGECANDYBAR) if Settings::RAGE_CANDY_BAR_CURES_STATUS_PROBLEMS
|
|
ONE_STAT_RAISE_ITEMS = {
|
|
:XATTACK => [:ATTACK, (Settings::X_STAT_ITEMS_RAISE_BY_TWO_STAGES) ? 2 : 1],
|
|
:XATTACK2 => [:ATTACK, 2],
|
|
:XATTACK3 => [:ATTACK, 3],
|
|
:XATTACK6 => [:ATTACK, 6],
|
|
:XDEFENSE => [:DEFENSE, (Settings::X_STAT_ITEMS_RAISE_BY_TWO_STAGES) ? 2 : 1],
|
|
:XDEFENSE2 => [:DEFENSE, 2],
|
|
:XDEFENSE3 => [:DEFENSE, 3],
|
|
:XDEFENSE6 => [:DEFENSE, 6],
|
|
:XDEFEND => [:DEFENSE, (Settings::X_STAT_ITEMS_RAISE_BY_TWO_STAGES) ? 2 : 1],
|
|
:XDEFEND2 => [:DEFENSE, 2],
|
|
:XDEFEND3 => [:DEFENSE, 3],
|
|
:XDEFEND6 => [:DEFENSE, 6],
|
|
:XSPATK => [:SPECIAL_ATTACK, (Settings::X_STAT_ITEMS_RAISE_BY_TWO_STAGES) ? 2 : 1],
|
|
:XSPATK2 => [:SPECIAL_ATTACK, 2],
|
|
:XSPATK3 => [:SPECIAL_ATTACK, 3],
|
|
:XSPATK6 => [:SPECIAL_ATTACK, 6],
|
|
:XSPECIAL => [:SPECIAL_ATTACK, (Settings::X_STAT_ITEMS_RAISE_BY_TWO_STAGES) ? 2 : 1],
|
|
:XSPECIAL2 => [:SPECIAL_ATTACK, 2],
|
|
:XSPECIAL3 => [:SPECIAL_ATTACK, 3],
|
|
:XSPECIAL6 => [:SPECIAL_ATTACK, 6],
|
|
:XSPDEF => [:SPECIAL_DEFENSE, (Settings::X_STAT_ITEMS_RAISE_BY_TWO_STAGES) ? 2 : 1],
|
|
:XSPDEF2 => [:SPECIAL_DEFENSE, 2],
|
|
:XSPDEF3 => [:SPECIAL_DEFENSE, 3],
|
|
:XSPDEF6 => [:SPECIAL_DEFENSE, 6],
|
|
:XSPEED => [:SPEED, (Settings::X_STAT_ITEMS_RAISE_BY_TWO_STAGES) ? 2 : 1],
|
|
:XSPEED2 => [:SPEED, 2],
|
|
:XSPEED3 => [:SPEED, 3],
|
|
:XSPEED6 => [:SPEED, 6],
|
|
:XACCURACY => [:ACCURACY, (Settings::X_STAT_ITEMS_RAISE_BY_TWO_STAGES) ? 2 : 1],
|
|
:XACCURACY2 => [:ACCURACY, 2],
|
|
:XACCURACY3 => [:ACCURACY, 3],
|
|
:XACCURACY6 => [:ACCURACY, 6]
|
|
}
|
|
ALL_STATS_RAISE_ITEMS = [
|
|
:MAXMUSHROOMS
|
|
]
|
|
REVIVE_ITEMS = {
|
|
:REVIVE => 5,
|
|
:MAXREVIVE => 7,
|
|
:REVIVALHERB => 7,
|
|
:MAXHONEY => 7
|
|
}
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
# Decide whether the opponent should use an item on the Pokémon.
|
|
def pbChooseToUseItem
|
|
item = nil
|
|
idxTarget = nil # Party index (battle_use type 1/2/3) or battler index
|
|
idxMove = nil
|
|
item, idxTarget, idxMove = choose_item_to_use
|
|
return false if !item
|
|
# Register use of item
|
|
@battle.pbRegisterItem(@user.index, item, idxTarget, idxMove)
|
|
PBDebug.log_ai("#{@user.name} will use item #{GameData::Item.get(item).name}")
|
|
return true
|
|
end
|
|
|
|
# Return values are:
|
|
# item ID
|
|
# target index (party index for items with a battle use of 1/2/3, battler
|
|
# index otherwise)
|
|
# move index (for items usable on moves only)
|
|
def choose_item_to_use
|
|
return nil if !@battle.internalBattle
|
|
items = @battle.pbGetOwnerItems(@user.index)
|
|
return nil if !items || items.length == 0
|
|
# Find all items usable on the Pokémon choosing this action
|
|
pkmn = @user.battler.pokemon
|
|
usable_items = {}
|
|
items.each do |item|
|
|
usage = get_usability_of_item_on_pkmn(item, @user.party_index, @user.side)
|
|
usage.each_pair do |key, vals|
|
|
usable_items[key] ||= []
|
|
usable_items[key] += vals
|
|
end
|
|
end
|
|
# Prioritise using a HP restoration item
|
|
if usable_items[:hp_heal] && (pkmn.hp <= pkmn.totalhp / 4 ||
|
|
(pkmn.hp <= pkmn.totalhp / 2 && pbAIRandom(100) < 30))
|
|
usable_items[:hp_heal].sort! { |a, b| (a[2] == b[2]) ? a[3] <=> b[3] : a[2] <=> b[2] }
|
|
usable_items[:hp_heal].each do |item|
|
|
return item[0], item[1] if item[3] >= (pkmn.totalhp - pkmn.hp) * 0.75
|
|
end
|
|
return usable_items[:hp_heal].last[0], usable_items[:hp_heal].last[1]
|
|
end
|
|
# Next prioritise using a status-curing item
|
|
if usable_items[:status_cure] &&
|
|
([:SLEEP, :FROZEN].include?(pkmn.status) || pbAIRandom(100) < 40)
|
|
usable_items[:status_cure].sort! { |a, b| a[2] <=> b[2] }
|
|
return usable_items[:status_cure].first[0], usable_items[:status_cure].first[1]
|
|
end
|
|
# Next try using an item that raises all stats (Max Mushrooms)
|
|
if usable_items[:all_stats_raise] && pbAIRandom(100) < 30
|
|
return usable_items[:stat_raise].first[0], usable_items[:stat_raise].first[1]
|
|
end
|
|
# Next try using an X item
|
|
if usable_items[:stat_raise] && pbAIRandom(100) < 30
|
|
usable_items[:stat_raise].sort! { |a, b| (a[2] == b[2]) ? a[3] <=> b[3] : a[2] <=> b[2] }
|
|
return usable_items[:stat_raise].last[0], usable_items[:stat_raise].last[1]
|
|
end
|
|
# Find items usable on other Pokémon in the user's team
|
|
# NOTE: Currently only checks Revives.
|
|
usable_items = {}
|
|
@battle.eachInTeamFromBattlerIndex(@user.index) do |pkmn, i|
|
|
next if !pkmn.fainted? # Remove this line to check unfainted Pokémon too
|
|
items.each do |item|
|
|
usage = get_usability_of_item_on_pkmn(item, i, @user.side)
|
|
usage.each_pair do |key, vals|
|
|
usable_items[key] ||= []
|
|
usable_items[key] += vals
|
|
end
|
|
end
|
|
end
|
|
# Try using a Revive (prefer Max Revive-type items over Revive)
|
|
if usable_items[:revive] &&
|
|
(@battle.pbAbleNonActiveCount(@user.index) == 0 || pbAIRandom(100) < 40)
|
|
usable_items[:revive].sort! { |a, b| (a[2] == b[2]) ? a[1] <=> b[1] : a[2] <=> b[2] }
|
|
return usable_items[:revive].last[0], usable_items[:revive].last[1]
|
|
end
|
|
return nil
|
|
end
|
|
|
|
def get_usability_of_item_on_pkmn(item, party_index, side)
|
|
pkmn = @battle.pbParty(side)[party_index]
|
|
battler = @battle.pbFindBattler(party_index, side)
|
|
ret = {}
|
|
return ret if !@battle.pbCanUseItemOnPokemon?(item, pkmn, battler, @battle.scene, false)
|
|
return ret if !ItemHandlers.triggerCanUseInBattle(item, pkmn, battler, nil,
|
|
false, self, @battle.scene, false)
|
|
want_to_cure_status = (pkmn.status != :NONE)
|
|
if battler
|
|
if want_to_cure_status
|
|
want_to_cure_status = @battlers[battler.index].wants_status_problem?(pkmn.status)
|
|
want_to_cure_status = false if pkmn.status == :SLEEP && pkmn.statusCount <= 2
|
|
end
|
|
want_to_cure_status ||= (battler.effects[PBEffects::Confusion] > 1)
|
|
end
|
|
if HP_HEAL_ITEMS.include?(item)
|
|
if pkmn.hp < pkmn.totalhp
|
|
heal_amount = HP_HEAL_ITEMS[item]
|
|
heal_amount = pkmn.totalhp / 4 if item == :SITURUSBERRY
|
|
ret[:hp_heal] ||= []
|
|
ret[:hp_heal].push([item, party_index, 5, heal_amount])
|
|
end
|
|
elsif FULL_RESTORE_ITEMS.include?(item)
|
|
prefer_full_restore = (pkmn.hp <= pkmn.totalhp * 2 / 3 && want_to_cure_status)
|
|
if pkmn.hp < pkmn.totalhp
|
|
ret[:hp_heal] ||= []
|
|
ret[:hp_heal].push([item, party_index, (prefer_full_restore) ? 3 : 7, 999])
|
|
end
|
|
if want_to_cure_status
|
|
ret[:status_cure] ||= []
|
|
ret[:status_cure].push([item, party_index, (prefer_full_restore) ? 3 : 9])
|
|
end
|
|
elsif ONE_STATUS_CURE_ITEMS.include?(item)
|
|
if want_to_cure_status
|
|
ret[:status_cure] ||= []
|
|
ret[:status_cure].push([item, party_index, 5])
|
|
end
|
|
elsif ALL_STATUS_CURE_ITEMS.include?(item)
|
|
if want_to_cure_status
|
|
ret[:status_cure] ||= []
|
|
ret[:status_cure].push([item, party_index, 7])
|
|
end
|
|
elsif ONE_STAT_RAISE_ITEMS.include?(item)
|
|
stat_data = ONE_STAT_RAISE_ITEMS[item]
|
|
if battler && stat_raise_worthwhile?(@battlers[battler.index], stat_data[0])
|
|
ret[:stat_raise] ||= []
|
|
ret[:stat_raise].push([item, party_index, battler.stages[stat_data[0]], stat_data[1]])
|
|
end
|
|
elsif ALL_STATS_RAISE_ITEMS.include?(item)
|
|
if battler
|
|
ret[:all_stats_raise] ||= []
|
|
ret[:all_stats_raise].push([item, party_index])
|
|
end
|
|
elsif REVIVE_ITEMS.include?(item)
|
|
ret[:revive] ||= []
|
|
ret[:revive].push([item, party_index, REVIVE_ITEMS[item]])
|
|
end
|
|
return ret
|
|
end
|
|
end
|