mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-07 13:15:01 +00:00
Tidying up for v21's release
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#==============================================================================#
|
||||
# Pokémon Essentials #
|
||||
# Version 20.1.dev #
|
||||
# Version 21 #
|
||||
# https://github.com/Maruno17/pokemon-essentials #
|
||||
#==============================================================================#
|
||||
|
||||
@@ -452,7 +452,7 @@ end
|
||||
|
||||
# DO NOT EDIT THESE!
|
||||
module Essentials
|
||||
VERSION = "20.1.dev"
|
||||
VERSION = "21"
|
||||
ERROR_TEXT = ""
|
||||
MKXPZ_VERSION = "2.4.2/ee8dc7e"
|
||||
end
|
||||
|
||||
@@ -380,6 +380,8 @@ SaveData.register_conversion(:v21_replace_phone_data) do
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
|
||||
SaveData.register_conversion(:v21_replace_flute_booleans) do
|
||||
essentials_version 21
|
||||
display_title "Updating Black/White Flute variables"
|
||||
@@ -405,6 +407,8 @@ SaveData.register_conversion(:v21_replace_flute_booleans) do
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
|
||||
SaveData.register_conversion(:v21_add_bump_stat) do
|
||||
essentials_version 21
|
||||
display_title "Adding a bump stat"
|
||||
|
||||
@@ -591,10 +591,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
|
||||
if busy?
|
||||
refresh if !@text_delay_changed
|
||||
updateInternal
|
||||
# following line needed to allow "textspeed=0" to work seamlessly
|
||||
# TODO: I don't think this is needed any more, but I don't know where to
|
||||
# look to confirm it'd work properly without this line.
|
||||
refresh if @text_delay_changed
|
||||
refresh if @text_delay_changed # Needed to allow "textspeed=0" to work seamlessly
|
||||
end
|
||||
@text_delay_changed = false
|
||||
end
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# TODO: Add tileset number in here?
|
||||
module GameData
|
||||
class DungeonParameters
|
||||
attr_reader :id, :area, :version
|
||||
|
||||
@@ -117,7 +117,6 @@ class BattleArenaBattle < Battle
|
||||
super
|
||||
return if @decision != 0
|
||||
# Update mind rating (asserting that a move was chosen)
|
||||
# TODO: Actually done at Pokémon's turn
|
||||
2.times do |side|
|
||||
if @choices[side][2] && @choices[side][0] == :UseMove
|
||||
@mind[side] += pbMindScore(@choices[side][2])
|
||||
|
||||
@@ -1,25 +1,3 @@
|
||||
# TODO: Add an information window with details of the person in a phone call.
|
||||
# Make this work with common event calls (create and dispose the info
|
||||
# window in start_message and end_message).
|
||||
# TODO: Look at the "ready to rematch" timers to see if they can be improved?
|
||||
# Should they be limited to one trainer becoming ready every ~5 minutes?
|
||||
# Should a rematch-ready contact become unready again after some time if
|
||||
# they haven't told the player they're ready?
|
||||
# TODO: See if incoming phone calls can be made optional somehow. Maybe just
|
||||
# interrupt as normal with the start of the call and ask if the player
|
||||
# wants to answer? Wait for a couple of seconds before asking to make sure
|
||||
# the player doesn't accidentally skip/answer a call they didn't want to.
|
||||
# TODO: Add a Debug way of upgrading old phone script calls to new ones, or at
|
||||
# least to find events using old phone scripts for the dev to update.
|
||||
# TODO: More Debug control over contacts (changing their "time to rebattle",
|
||||
# unhiding hidden contacts, etc.) and the phone (time until next call).
|
||||
|
||||
# TODO: Add calling a contact at a particular time forcing rematch readiness.
|
||||
# Add trainer comments for this.
|
||||
# TODO: Allow individual trainers to never arrange a rematch by themself, thus
|
||||
# requiring the player to call them at their particular time of day/week.
|
||||
# TODO: Be able to put the Phone on silent mode (prevent all phone calls from
|
||||
# trainers, but allow scripted calls as normal).
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
@@ -378,8 +356,8 @@ class Phone
|
||||
valid_contacts = []
|
||||
$PokemonGlobal.phone.contacts.each do |contact|
|
||||
next if !contact.trainer? || !contact.visible?
|
||||
next if contact.map_id == $game_map.map_id
|
||||
# TODO: next if the contact's map name is the same as the current map's?
|
||||
next if contact.map_id == $game_map.map_id ||
|
||||
pbGetMapNameFromId(contact.map_id) == $game_map.name
|
||||
caller_map_metadata = GameData::MapMetadata.try_get(contact.map_id)
|
||||
next if !caller_map_metadata || !caller_map_metadata.town_map_position
|
||||
next if caller_map_metadata.town_map_position[0] != player_region
|
||||
|
||||
@@ -188,7 +188,7 @@ class NPCTrainer < Trainer
|
||||
attr_accessor :win_text
|
||||
|
||||
def initialize(name, trainer_type, version = 0)
|
||||
super
|
||||
super(name, trainer_type)
|
||||
@version = version
|
||||
@items = []
|
||||
@lose_text = nil
|
||||
|
||||
@@ -35,6 +35,28 @@ class Player < Trainer
|
||||
# @return [Array<Array>] downloaded Mystery Gift data
|
||||
attr_accessor :mystery_gifts
|
||||
|
||||
def initialize(name, trainer_type)
|
||||
super
|
||||
@character_ID = 0
|
||||
@outfit = 0
|
||||
@badges = [false] * 8
|
||||
@money = GameData::Metadata.get.start_money
|
||||
@coins = 0
|
||||
@battle_points = 0
|
||||
@soot = 0
|
||||
@pokedex = Pokedex.new
|
||||
@has_pokedex = false
|
||||
@has_pokegear = false
|
||||
@has_running_shoes = false
|
||||
@has_box_link = false
|
||||
@seen_storage_creator = false
|
||||
@has_exp_all = false
|
||||
@mystery_gift_unlocked = false
|
||||
@mystery_gifts = []
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
|
||||
def character_ID=(value)
|
||||
return if @character_ID == value
|
||||
@character_ID = value
|
||||
@@ -98,26 +120,4 @@ class Player < Trainer
|
||||
def owned?(species)
|
||||
return @pokedex.owned?(species)
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
|
||||
def initialize(name, trainer_type)
|
||||
super
|
||||
@character_ID = 0
|
||||
@outfit = 0
|
||||
@badges = [false] * 8
|
||||
@money = GameData::Metadata.get.start_money
|
||||
@coins = 0
|
||||
@battle_points = 0
|
||||
@soot = 0
|
||||
@pokedex = Pokedex.new
|
||||
@has_pokedex = false
|
||||
@has_pokegear = false
|
||||
@has_running_shoes = false
|
||||
@has_box_link = false
|
||||
@seen_storage_creator = false
|
||||
@has_exp_all = false
|
||||
@mystery_gift_unlocked = false
|
||||
@mystery_gifts = []
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# TODO: Choosable icons/marks for each contact? Add a "sort by" option for these.
|
||||
#===============================================================================
|
||||
# Phone list of contacts
|
||||
#===============================================================================
|
||||
|
||||
@@ -759,7 +759,7 @@ module BattleAnimationEditor
|
||||
return false
|
||||
end
|
||||
if usealpha
|
||||
# TODO: This should account for sprite.angle as well
|
||||
# TODO: This should account for sprite.angle as well.
|
||||
bitmapX = sprite.src_rect.x
|
||||
bitmapY = sprite.src_rect.y
|
||||
bitmapX += sprite.ox
|
||||
|
||||
@@ -1024,7 +1024,7 @@ MenuHandlers.add(:debug_menu, :edit_phone_contacts, {
|
||||
edit_cmd = 0
|
||||
loop do
|
||||
edit_cmds = []
|
||||
edit_cmds.push((contact.visible? ? "[Y]" : "[ ]") + " " + _INTL("Contact visible")) if contact.can_hide?
|
||||
edit_cmds.push((contact.visible? ? "[Y]" : "[ ]") + " " + _INTL("Contact visible"))
|
||||
if contact.trainer?
|
||||
edit_cmds.push((contact.can_rematch? ? "[Y]" : "[ ]") + " " + _INTL("Can battle"))
|
||||
ready_time = contact.time_to_ready # time is in seconds
|
||||
@@ -1038,7 +1038,7 @@ MenuHandlers.add(:debug_menu, :edit_phone_contacts, {
|
||||
break if edit_cmd < 0
|
||||
case edit_cmd
|
||||
when 0 # Visibility
|
||||
contact.visible = !contact.visible
|
||||
contact.visible = !contact.visible if contact.can_hide?
|
||||
when 1 # Can battle
|
||||
contact.rematch_flag = (contact.can_rematch?) ? 0 : 1
|
||||
contact.time_to_ready = 0 if contact.can_rematch?
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
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" => "Print Out Move Targets",
|
||||
"parent" => :main,
|
||||
"description" => "Print all blah blah blah.",
|
||||
"effect" => proc {
|
||||
marListMoveTargetFunctionCodes
|
||||
}
|
||||
})
|
||||
@@ -1,532 +0,0 @@
|
||||
# TODO: Be much more relevant with the choosing of held items. For example,
|
||||
# only give a weather-boosting item to a Pokémon that can create the
|
||||
# corresponding weather.
|
||||
|
||||
AI_MOVE_TESTING_THRESHOLD = 1500
|
||||
AI_ABILITY_TESTING_THRESHOLD = 500
|
||||
AI_ITEM_TESTING_THRESHOLD = 500
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
# There are some duplicate effects in here (e.g. Power Weight/Bracer/etc.), but
|
||||
# whatever.
|
||||
ITEMS_WITH_HELD_EFFECTS = [
|
||||
:AIRBALLOON, :BRIGHTPOWDER, :EVIOLITE, :FLOATSTONE, :DESTINYKNOT,
|
||||
:ROCKYHELMET, :ASSAULTVEST, :SAFETYGOGGLES, :PROTECTIVEPADS, :HEAVYDUTYBOOTS,
|
||||
:UTILITYUMBRELLA, :EJECTBUTTON, :EJECTPACK, :REDCARD, :SHEDSHELL, :CHOICEBAND,
|
||||
:CHOICESPECS, :CHOICESCARF, :HEATROCK, :DAMPROCK, :SMOOTHROCK, :ICYROCK,
|
||||
:TERRAINEXTENDER, :LIGHTCLAY, :GRIPCLAW, :BINDINGBAND, :BIGROOT, :BLACKSLUDGE,
|
||||
:LEFTOVERS, :SHELLBELL, :MENTALHERB, :WHITEHERB, :POWERHERB, :ABSORBBULB,
|
||||
:CELLBATTERY, :LUMINOUSMOSS, :SNOWBALL, :WEAKNESSPOLICY, :BLUNDERPOLICY,
|
||||
:THROATSPRAY, :ADRENALINEORB, :ROOMSERVICE, :ELECTRICSEED, :GRASSYSEED,
|
||||
:MISTYSEED, :PSYCHICSEED, :LIFEORB, :EXPERTBELT, :METRONOME, :MUSCLEBAND,
|
||||
:WISEGLASSES, :RAZORCLAW, :SCOPELENS, :WIDELENS, :ZOOMLENS, :KINGSROCK,
|
||||
:RAZORFANG, :LAGGINGTAIL, :QUICKCLAW, :FOCUSBAND, :FOCUSSASH, :FLAMEORB,
|
||||
:TOXICORB, :STICKYBARB, :IRONBALL, :RINGTARGET, :MACHOBRACE, :POWERWEIGHT,
|
||||
:POWERBRACER, :POWERBELT, :POWERLENS, :POWERBAND, :POWERANKLET, :LAXINCENSE,
|
||||
:FULLINCENSE, :SEAINCENSE, :WAVEINCENSE, :ROSEINCENSE, :ODDINCENSE,
|
||||
:ROCKINCENSE, :CHARCOAL, :MYSTICWATER, :MAGNET, :MIRACLESEED, :NEVERMELTICE,
|
||||
:BLACKBELT, :POISONBARB, :SOFTSAND, :SHARPBEAK, :TWISTEDSPOON, :SILVERPOWDER,
|
||||
:HARDSTONE, :SPELLTAG, :DRAGONFANG, :BLACKGLASSES, :METALCOAT, :SILKSCARF,
|
||||
:FIREGEM, :WATERGEM, :ELECTRICGEM, :GRASSGEM, :ICEGEM, :FIGHTINGGEM,
|
||||
:POISONGEM, :GROUNDGEM, :FLYINGGEM, :PSYCHICGEM, :BUGGEM, :ROCKGEM, :GHOSTGEM,
|
||||
:DRAGONGEM, :DARKGEM, :STEELGEM, :FAIRYGEM, :NORMALGEM, :CHERIBERRY,
|
||||
:CHESTOBERRY, :PECHABERRY, :RAWSTBERRY, :ASPEARBERRY, :LEPPABERRY, :ORANBERRY,
|
||||
:PERSIMBERRY, :LUMBERRY, :SITRUSBERRY, :FIGYBERRY, :WIKIBERRY, :MAGOBERRY,
|
||||
:AGUAVBERRY, :IAPAPABERRY, :OCCABERRY, :PASSHOBERRY, :WACANBERRY, :RINDOBERRY,
|
||||
:YACHEBERRY, :CHOPLEBERRY, :KEBIABERRY, :SHUCABERRY, :COBABERRY, :PAYAPABERRY,
|
||||
:TANGABERRY, :CHARTIBERRY, :KASIBBERRY, :HABANBERRY, :COLBURBERRY,
|
||||
:BABIRIBERRY, :ROSELIBERRY, :CHILANBERRY, :LIECHIBERRY, :GANLONBERRY,
|
||||
:SALACBERRY, :PETAYABERRY, :APICOTBERRY, :LANSATBERRY, :STARFBERRY,
|
||||
:ENIGMABERRY, :MICLEBERRY, :CUSTAPBERRY, :JABOCABERRY, :ROWAPBERRY, :KEEBERRY,
|
||||
:MARANGABERRY
|
||||
]
|
||||
# These items have no effect if held by other species. Includes the Plates
|
||||
# because other items also have the type-boosting effect and we don't need to
|
||||
# test that effect of Plates.
|
||||
SIGNATURE_ITEMS = {
|
||||
:PIKACHU => :LIGHTBALL,
|
||||
:CHANSEY => :LUCKYPUNCH,
|
||||
:DITTO => [:METALPOWDER, :QUICKPOWDER],
|
||||
:CUBONE => :THICKCLUB,
|
||||
:MAROWAK => :THICKCLUB,
|
||||
:FARFETCHD => :LEEK,
|
||||
:SIRFETCHD => :LEEK,
|
||||
:LATIOS => :SOULDEW,
|
||||
:LATIAS => :SOULDEW,
|
||||
:CLAMPERL => [:DEEPSEATOOTH, :DEEPSEASCALE],
|
||||
:DIALGA => :ADAMANTORB,
|
||||
:PALKIA => :LUSTROUSORB,
|
||||
:ARCEUS => [:FLAMEPLATE, :SPLASHPLATE, :ZAPPLATE, :MEADOWPLATE,
|
||||
:ICICLEPLATE, :FISTPLATE, :TOXICPLATE, :EARTHPLATE, :SKYPLATE,
|
||||
:MINDPLATE, :INSECTPLATE, :STONEPLATE, :SPOOKYPLATE,
|
||||
:DRACOPLATE, :DREADPLATE, :IRONPLATE, :PIXIEPLATE],
|
||||
:GENESECT => [:DOUSEDRIVE, :SHOCKDRIVE, :BURNDRIVE, :CHILLDRIVE],
|
||||
:SILVALLY => [:FIREMEMORY, :WATERMEMORY, :ELECTRICMEMORY, :GRASSMEMORY,
|
||||
:ICEMEMORY, :FIGHTINGMEMORY, :POISONMEMORY, :GROUNDMEMORY,
|
||||
:FLYINGMEMORY, :PSYCHICMEMORY, :BUGMEMORY, :ROCKMEMORY,
|
||||
:GHOSTMEMORY, :DRAGONMEMORY, :DARKMEMORY, :STEELMEMORY,
|
||||
:FAIRYMEMORY],
|
||||
:GROUDON => :REDORB, # Form-changing item
|
||||
:KYOGRE => :BLUEORB, # Form-changing item
|
||||
:GIRATINA => :GRISEOUSORB, # Form-changing item
|
||||
:ZACIAN => :RUSTEDSWORD, # Form-changing item
|
||||
:ZAMAZENTA => :RUSTEDSHIELD # Form-changing item
|
||||
}
|
||||
MEGA_STONES = [
|
||||
:VENUSAURITE, :CHARIZARDITEX, :CHARIZARDITEY, :BLASTOISINITE, :BEEDRILLITE,
|
||||
:PIDGEOTITE, :ALAKAZITE, :SLOWBRONITE, :GENGARITE, :KANGASKHANITE, :PINSIRITE,
|
||||
:GYARADOSITE, :AERODACTYLITE, :MEWTWONITEX, :MEWTWONITEY, :AMPHAROSITE,
|
||||
:STEELIXITE, :SCIZORITE, :HERACRONITE, :HOUNDOOMINITE, :TYRANITARITE,
|
||||
:SCEPTILITE, :BLAZIKENITE, :SWAMPERTITE, :GARDEVOIRITE, :SABLENITE, :MAWILITE,
|
||||
:AGGRONITE, :MEDICHAMITE, :MANECTITE, :SHARPEDONITE, :CAMERUPTITE,
|
||||
:ALTARIANITE, :BANETTITE, :ABSOLITE, :GLALITITE, :SALAMENCITE, :METAGROSSITE,
|
||||
:LATIASITE, :LATIOSITE, :LOPUNNITE, :GARCHOMPITE, :LUCARIONITE, :ABOMASITE,
|
||||
:GALLADITE, :AUDINITE, :DIANCITE
|
||||
]
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class Battle::AI
|
||||
alias _ai_testing__pbGetMoveScores pbGetMoveScores
|
||||
|
||||
def pbGetMoveScores
|
||||
if $tested_abilities && @user.ability_id
|
||||
$tested_abilities[@user.ability_id] ||= 0
|
||||
$tested_abilities[@user.ability_id] += 1
|
||||
end
|
||||
if $tested_items && @user.item_id
|
||||
$tested_items[@user.item_id] ||= 0
|
||||
$tested_items[@user.item_id] += 1
|
||||
end
|
||||
@user.battler.eachMoveWithIndex do |orig_move, idxMove|
|
||||
if $tested_moves
|
||||
$tested_moves[orig_move.id] ||= 0
|
||||
$tested_moves[orig_move.id] += 1
|
||||
end
|
||||
end
|
||||
return _ai_testing__pbGetMoveScores
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
def debug_set_up_trainer
|
||||
# Values to return
|
||||
trainer_array = []
|
||||
foe_items = [] # Items can't be used except in internal battles
|
||||
pokemon_array = []
|
||||
party_starts = [0]
|
||||
|
||||
# Choose random trainer type and trainer name
|
||||
trainer_type = :CHAMPION # GameData::TrainerType.keys.sample
|
||||
trainer_name = ["Alpha", "Bravo", "Charlie", "Delta", "Echo",
|
||||
"Foxtrot", "Golf", "Hotel", "India", "Juliette",
|
||||
"Kilo", "Lima", "Mike", "November", "Oscar",
|
||||
"Papa", "Quebec", "Romeo", "Sierra", "Tango",
|
||||
"Uniform", "Victor", "Whiskey", "X-ray", "Yankee", "Zulu"].sample
|
||||
|
||||
# Generate trainer
|
||||
trainer = NPCTrainer.new(trainer_name, trainer_type)
|
||||
trainer.id = $player.make_foreign_ID
|
||||
trainer.lose_text = "I lost."
|
||||
trainer.items.push(:MEGARING)
|
||||
# [:MAXPOTION, :FULLHEAL, :MAXREVIVE, :REVIVE].each do |item|
|
||||
# trainer.items.push(item)
|
||||
# end
|
||||
# foe_items.push(trainer.items)
|
||||
trainer_array.push(trainer)
|
||||
|
||||
# Generate party
|
||||
valid_species = []
|
||||
GameData::Species.each_species { |sp| valid_species.push(sp.species) }
|
||||
Settings::MAX_PARTY_SIZE.times do |i|
|
||||
this_species = valid_species.sample
|
||||
this_level = 100 # rand(1, Settings::MAXIMUM_LEVEL)
|
||||
pkmn = Pokemon.new(this_species, this_level, trainer, false)
|
||||
# Set form for certain species
|
||||
case pkmn.species
|
||||
when :GRENINJA, :SLOWKING, :GEODUDE, :GRAVELER, :GOLEM, :PONYTA, :RAPIDASH,
|
||||
:GRIMER, :MUK, :SLOWBRO, :RAICHU, :DIGLETT, :DUGTRIO, :STUNFISK
|
||||
pkmn.form_simple = 1
|
||||
when :DARMANITAN
|
||||
pkmn.form_simple = 2
|
||||
when :CALYREX
|
||||
pkmn.form_simple = [1, 2].sample # So we test both versions of As One
|
||||
when :NECROZMA
|
||||
pkmn.form_simple = 3 # Ultra form
|
||||
end
|
||||
# Generate moveset for pkmn (from level-up moves first, then from tutor
|
||||
# moves + egg moves, then from all moves)
|
||||
all_moves = pkmn.getMoveList.map { |m| m[1] }
|
||||
all_moves.uniq!
|
||||
if !$shown_all_moves_tested_message
|
||||
all_moves.reject! { |m| $tested_moves[m] && $tested_moves[m] > AI_MOVE_TESTING_THRESHOLD }
|
||||
if all_moves.length == 0
|
||||
all_moves = pkmn.species_data.tutor_moves.clone + pkmn.species_data.get_egg_moves.clone
|
||||
all_moves.reject! { |m| $tested_moves[m] && $tested_moves[m] > AI_MOVE_TESTING_THRESHOLD }
|
||||
if all_moves.length == 0
|
||||
all_moves = GameData::Move.keys.clone
|
||||
all_moves.reject! { |m| $tested_moves[m] && $tested_moves[m] > AI_MOVE_TESTING_THRESHOLD }
|
||||
end
|
||||
end
|
||||
if all_moves.length == 0 && !$shown_all_moves_tested_message
|
||||
echoln "All moves have been tested at least #{AI_MOVE_TESTING_THRESHOLD} times!"
|
||||
$shown_all_moves_tested_message = true
|
||||
end
|
||||
end
|
||||
moves = all_moves.sample(4)
|
||||
moves.each { |m| pkmn.learn_move(m) }
|
||||
# Generate held item for pkmn (compatible Mega Stone first, then compatible
|
||||
# signature item, then any item with a held effect)
|
||||
all_items = [] # Find all compatible Mega Stones
|
||||
GameData::Species.each do |sp|
|
||||
next if sp.species != pkmn.species || sp.unmega_form != pkmn.form
|
||||
all_items.push(sp.mega_stone) if sp.mega_stone
|
||||
end
|
||||
all_items.reject! { |i| $tested_items[i] && $tested_items[i] > AI_ITEM_TESTING_THRESHOLD }
|
||||
if all_items.length > 0 && rand(100) < 50
|
||||
pkmn.item = all_items.sample
|
||||
elsif SIGNATURE_ITEMS.keys.include?(pkmn.species) && rand(100) < 75
|
||||
all_items = SIGNATURE_ITEMS[pkmn.species].clone
|
||||
if all_items.is_a?(Array)
|
||||
all_items.reject! { |i| $tested_items[i] && $tested_items[i] > AI_ITEM_TESTING_THRESHOLD }
|
||||
pkmn.item = all_items.sample if all_items.length > 0
|
||||
else
|
||||
pkmn.item = all_items if !$tested_items[all_items] || $tested_items[all_items] <= AI_ITEM_TESTING_THRESHOLD
|
||||
end
|
||||
end
|
||||
if !pkmn.hasItem? && rand(100) < 75
|
||||
all_items = ITEMS_WITH_HELD_EFFECTS.clone
|
||||
all_items.reject! { |i| $tested_items[i] && $tested_items[i] > AI_ITEM_TESTING_THRESHOLD }
|
||||
all_items = ITEMS_WITH_HELD_EFFECTS.clone if all_items.length == 0
|
||||
pkmn.item = all_items.sample
|
||||
end
|
||||
# Generate ability for pkmn (any available to that species/form)
|
||||
abil = pkmn.ability_id
|
||||
if $tested_abilities[abil] && $tested_abilities[abil] > AI_ABILITY_TESTING_THRESHOLD
|
||||
abils = pkmn.getAbilityList
|
||||
abils.reject! { |a| $tested_abilities[a[0]] && $tested_abilities[a[0]] > AI_ABILITY_TESTING_THRESHOLD }
|
||||
if abils.length > 0
|
||||
pkmn.ability_index = abils.sample[1]
|
||||
else
|
||||
pkmn.ability = GameData::Ability.keys.sample
|
||||
end
|
||||
end
|
||||
trainer.party.push(pkmn)
|
||||
pokemon_array.push(pkmn)
|
||||
end
|
||||
|
||||
# Return values
|
||||
return trainer_array, foe_items, pokemon_array, party_starts
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
def debug_test_auto_battle(logging = false, console_messages = true)
|
||||
mar_load_tested_data_record
|
||||
|
||||
old_internal = $INTERNAL
|
||||
$INTERNAL = logging
|
||||
if console_messages
|
||||
echoln "Start of testing auto-battle."
|
||||
echoln "" if !$INTERNAL
|
||||
end
|
||||
PBDebug.log("")
|
||||
PBDebug.log("================================================================")
|
||||
PBDebug.log("")
|
||||
# Generate information for the foes
|
||||
foe_trainers, foe_items, foe_party, foe_party_starts = debug_set_up_trainer
|
||||
# Generate information for the player and partner trainer(s)
|
||||
player_trainers, ally_items, player_party, player_party_starts = debug_set_up_trainer
|
||||
# Log the combatants
|
||||
echo_participant = lambda do |trainer, party, index|
|
||||
trainer_txt = "[Trainer #{index}] #{trainer.full_name} [skill: #{trainer.skill_level}]"
|
||||
($INTERNAL) ? PBDebug.log_header(trainer_txt) : echoln(trainer_txt)
|
||||
party.each do |pkmn|
|
||||
pkmn_txt = "#{pkmn.name}, Lv.#{pkmn.level}"
|
||||
pkmn_txt += " [Ability: #{pkmn.ability&.name || "---"}]"
|
||||
pkmn_txt += " [Item: #{pkmn.item&.name || "---"}]"
|
||||
($INTERNAL) ? PBDebug.log(pkmn_txt) : echoln(pkmn_txt)
|
||||
moves_msg = " Moves: "
|
||||
pkmn.moves.each_with_index do |move, i|
|
||||
moves_msg += ", " if i > 0
|
||||
moves_msg += move.name
|
||||
end
|
||||
($INTERNAL) ? PBDebug.log(moves_msg) : echoln(moves_msg)
|
||||
end
|
||||
end
|
||||
echo_participant.call(player_trainers[0], player_party, 1) if console_messages
|
||||
PBDebug.log("")
|
||||
if console_messages
|
||||
echoln "" if !$INTERNAL
|
||||
echo_participant.call(foe_trainers[0], foe_party, 2)
|
||||
echoln "" if !$INTERNAL
|
||||
end
|
||||
# Create the battle scene (the visual side of it)
|
||||
scene = Battle::DebugSceneNoVisuals.new(logging)
|
||||
# Create the battle class (the mechanics side of it)
|
||||
battle = Battle.new(scene, player_party, foe_party, player_trainers, foe_trainers)
|
||||
battle.party1starts = player_party_starts
|
||||
battle.party2starts = foe_party_starts
|
||||
battle.ally_items = ally_items
|
||||
battle.items = foe_items
|
||||
|
||||
battle.debug = true
|
||||
battle.internalBattle = false
|
||||
battle.controlPlayer = true
|
||||
# Set various other properties in the battle class
|
||||
BattleCreationHelperMethods.prepare_battle(battle)
|
||||
# Perform the battle itself
|
||||
outcome = battle.pbStartBattle
|
||||
# End
|
||||
if console_messages
|
||||
text = ["Undecided",
|
||||
"Trainer 1 #{player_trainers[0].name} won",
|
||||
"Trainer 2 #{foe_trainers[0].name} won",
|
||||
"Ran/forfeited",
|
||||
"Wild Pokémon caught",
|
||||
"Draw"][outcome]
|
||||
echoln sprintf("%s after %d rounds", text, battle.turnCount + 1)
|
||||
echoln ""
|
||||
end
|
||||
$INTERNAL = old_internal
|
||||
|
||||
mar_save_tested_data_record
|
||||
end
|
||||
|
||||
def mar_load_tested_data_record
|
||||
if !$tested_moves
|
||||
pbRgssOpen("tested_moves.dat", "rb") { |f| $tested_moves = Marshal.load(f) }
|
||||
end
|
||||
if !$tested_abilities
|
||||
pbRgssOpen("tested_abilities.dat", "rb") { |f| $tested_abilities = Marshal.load(f) }
|
||||
end
|
||||
if !$tested_items
|
||||
pbRgssOpen("tested_items.dat", "rb") { |f| $tested_items = Marshal.load(f) }
|
||||
end
|
||||
end
|
||||
|
||||
def mar_save_tested_data_record
|
||||
$tested_moves ||= {}
|
||||
$tested_abilities ||= {}
|
||||
$tested_items ||= {}
|
||||
File.open("tested_moves.dat", "wb") { |f| Marshal.dump($tested_moves, f) }
|
||||
File.open("tested_abilities.dat", "wb") { |f| Marshal.dump($tested_abilities, f) }
|
||||
File.open("tested_items.dat", "wb") { |f| Marshal.dump($tested_items, f) }
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Add to Debug menu.
|
||||
#===============================================================================
|
||||
MenuHandlers.add(:debug_menu, :ai_testing_menu, {
|
||||
"name" => "AI Testing...",
|
||||
"parent" => :main,
|
||||
"description" => "Functions that help to test the AI.",
|
||||
"always_show" => false
|
||||
})
|
||||
|
||||
MenuHandlers.add(:debug_menu, :generate_test_data, {
|
||||
"name" => "Generate new test data",
|
||||
"parent" => :ai_testing_menu,
|
||||
"description" => "Save current tested moves/abilities/items data. If none, generates it from scratch.",
|
||||
"always_show" => false,
|
||||
"effect" => proc {
|
||||
mar_save_tested_data_record
|
||||
}
|
||||
})
|
||||
|
||||
MenuHandlers.add(:debug_menu, :test_auto_battle, {
|
||||
"name" => "Test Auto Battle",
|
||||
"parent" => :ai_testing_menu,
|
||||
"description" => "Runs an AI-controlled battle with no visuals.",
|
||||
"always_show" => false,
|
||||
"effect" => proc {
|
||||
debug_test_auto_battle
|
||||
}
|
||||
})
|
||||
|
||||
MenuHandlers.add(:debug_menu, :test_auto_battle_logging, {
|
||||
"name" => "Test Auto Battle with logging",
|
||||
"parent" => :ai_testing_menu,
|
||||
"description" => "Runs an AI-controlled battle with no visuals. Logs messages.",
|
||||
"always_show" => false,
|
||||
"effect" => proc {
|
||||
debug_test_auto_battle(true)
|
||||
pbMessage("Battle transcript was logged in Data/debuglog.txt.")
|
||||
}
|
||||
})
|
||||
|
||||
MenuHandlers.add(:debug_menu, :bulk_test_auto_battle, {
|
||||
"name" => "Bulk test Auto Battle",
|
||||
"parent" => :ai_testing_menu,
|
||||
"description" => "Runs 50 AI-controlled battles with no visuals.",
|
||||
"always_show" => false,
|
||||
"effect" => proc {
|
||||
echoln "Running 50 battles.."
|
||||
50.times do |i|
|
||||
echoln "#{i + 1}..."
|
||||
debug_test_auto_battle(false, false)
|
||||
end
|
||||
echoln "Done!"
|
||||
}
|
||||
})
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
MenuHandlers.add(:debug_menu, :review_tested_data, {
|
||||
"name" => "Review tested moves/abilities/items",
|
||||
"parent" => :ai_testing_menu,
|
||||
"description" => "List how much all moves/abilities/items have been tested.",
|
||||
"always_show" => false,
|
||||
"effect" => proc {
|
||||
mar_load_tested_data_record
|
||||
|
||||
max_move_length = 0
|
||||
GameData::Move.keys.each { |m| max_move_length = [m.to_s.length, max_move_length].max }
|
||||
thresholded_moves = []
|
||||
($tested_moves || {}).each_pair do |move, count|
|
||||
next if !count || count < AI_MOVE_TESTING_THRESHOLD
|
||||
thresholded_moves.push([move, count])
|
||||
end
|
||||
thresholded_moves.sort! { |a, b| a[0].to_s <=> b[0].to_s }
|
||||
remaining_moves = GameData::Move.keys.clone
|
||||
thresholded_moves.each { |m| remaining_moves.delete(m[0]) }
|
||||
remaining_moves.sort! { |a, b| a.to_s <=> b.to_s }
|
||||
|
||||
File.open("tested moves summary.txt", "wb") do |f|
|
||||
f.write(0xEF.chr)
|
||||
f.write(0xBB.chr)
|
||||
f.write(0xBF.chr)
|
||||
f.write("================================================\r\n")
|
||||
f.write("Met threshold of #{AI_MOVE_TESTING_THRESHOLD}: #{thresholded_moves.length}\r\n")
|
||||
f.write("================================================\r\n")
|
||||
thresholded_moves.each do |m|
|
||||
f.write(m[0].to_s)
|
||||
f.write(" " * (5 + max_move_length - m[0].to_s.length))
|
||||
f.write(m[1].to_s)
|
||||
f.write("\r\n")
|
||||
end
|
||||
f.write("\r\n")
|
||||
f.write("\r\n")
|
||||
f.write("\r\n")
|
||||
f.write("================================================\r\n")
|
||||
f.write("Remaining moves: #{remaining_moves.length}\r\n")
|
||||
f.write("================================================\r\n")
|
||||
remaining_moves.each do |m|
|
||||
f.write(m.to_s)
|
||||
if $tested_moves && $tested_moves[m]
|
||||
f.write(" " * (5 + max_move_length - m.to_s.length))
|
||||
f.write($tested_moves[m].to_s)
|
||||
end
|
||||
f.write("\r\n")
|
||||
end
|
||||
end
|
||||
echoln "Moves: #{thresholded_moves.length} tested at least #{AI_MOVE_TESTING_THRESHOLD} times."
|
||||
echoln " #{remaining_moves.length} moves need more testing."
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
max_ability_length = 0
|
||||
GameData::Ability.keys.each { |a| max_ability_length = [a.to_s.length, max_ability_length].max }
|
||||
thresholded_abilities = []
|
||||
($tested_abilities || {}).each_pair do |abil, count|
|
||||
next if !count || count < AI_ABILITY_TESTING_THRESHOLD
|
||||
thresholded_abilities.push([abil, count])
|
||||
end
|
||||
thresholded_abilities.sort! { |a, b| a[0].to_s <=> b[0].to_s }
|
||||
remaining_abilities = GameData::Ability.keys.clone
|
||||
thresholded_abilities.each { |a| remaining_abilities.delete(a[0]) }
|
||||
remaining_abilities.sort! { |a, b| a.to_s <=> b.to_s }
|
||||
|
||||
File.open("tested abilities summary.txt", "wb") do |f|
|
||||
f.write(0xEF.chr)
|
||||
f.write(0xBB.chr)
|
||||
f.write(0xBF.chr)
|
||||
f.write("================================================\r\n")
|
||||
f.write("Met threshold of #{AI_ABILITY_TESTING_THRESHOLD}: #{thresholded_abilities.length}\r\n")
|
||||
f.write("================================================\r\n")
|
||||
thresholded_abilities.each do |a|
|
||||
f.write(a[0].to_s)
|
||||
f.write(" " * (5 + max_ability_length - a[0].to_s.length))
|
||||
f.write(a[1].to_s)
|
||||
f.write("\r\n")
|
||||
end
|
||||
f.write("\r\n")
|
||||
f.write("\r\n")
|
||||
f.write("\r\n")
|
||||
f.write("================================================\r\n")
|
||||
f.write("Remaining abilities: #{remaining_abilities.length}\r\n")
|
||||
f.write("================================================\r\n")
|
||||
remaining_abilities.each do |a|
|
||||
f.write(a.to_s)
|
||||
if $tested_abilities && $tested_abilities[a]
|
||||
f.write(" " * (5 + max_ability_length - a.to_s.length))
|
||||
f.write($tested_abilities[a].to_s)
|
||||
end
|
||||
f.write("\r\n")
|
||||
end
|
||||
end
|
||||
echoln "Abilities: #{thresholded_abilities.length} tested at least #{AI_ABILITY_TESTING_THRESHOLD} times."
|
||||
echoln " #{remaining_abilities.length} abilities need more testing."
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
max_item_length = 0
|
||||
ITEMS_WITH_HELD_EFFECTS.each { |i| max_item_length = [i.to_s.length, max_item_length].max }
|
||||
thresholded_items = []
|
||||
($tested_items || {}).each_pair do |item, count|
|
||||
next if !count || count < AI_ITEM_TESTING_THRESHOLD
|
||||
thresholded_items.push([item, count])
|
||||
end
|
||||
thresholded_items.sort! { |a, b| a[0].to_s <=> b[0].to_s }
|
||||
remaining_items = ITEMS_WITH_HELD_EFFECTS.clone
|
||||
remaining_items += MEGA_STONES.clone
|
||||
SIGNATURE_ITEMS.each_pair do |species, items|
|
||||
if items.is_a?(Array)
|
||||
remaining_items += items
|
||||
else
|
||||
remaining_items.push(items)
|
||||
end
|
||||
end
|
||||
remaining_items.uniq!
|
||||
thresholded_items.each { |i| remaining_items.delete(i[0]) }
|
||||
remaining_items.sort! { |a, b| a.to_s <=> b.to_s }
|
||||
|
||||
File.open("tested items summary.txt", "wb") do |f|
|
||||
f.write(0xEF.chr)
|
||||
f.write(0xBB.chr)
|
||||
f.write(0xBF.chr)
|
||||
f.write("================================================\r\n")
|
||||
f.write("Met threshold of #{AI_ITEM_TESTING_THRESHOLD}: #{thresholded_items.length}\r\n")
|
||||
f.write("================================================\r\n")
|
||||
thresholded_items.each do |i|
|
||||
f.write(i[0].to_s)
|
||||
f.write(" " * (5 + max_item_length - i[0].to_s.length))
|
||||
f.write(i[1].to_s)
|
||||
f.write("\r\n")
|
||||
end
|
||||
f.write("\r\n")
|
||||
f.write("\r\n")
|
||||
f.write("\r\n")
|
||||
f.write("================================================\r\n")
|
||||
f.write("Remaining items: #{remaining_items.length}\r\n")
|
||||
f.write("================================================\r\n")
|
||||
remaining_items.each do |i|
|
||||
f.write(i.to_s)
|
||||
if $tested_items && $tested_items[i]
|
||||
f.write(" " * (5 + max_item_length - i.to_s.length))
|
||||
f.write($tested_items[i].to_s)
|
||||
end
|
||||
f.write("\r\n")
|
||||
end
|
||||
end
|
||||
echoln "Items: #{thresholded_items.length} tested at least #{AI_ITEM_TESTING_THRESHOLD} times."
|
||||
echoln " #{remaining_items.length} items need more testing."
|
||||
}
|
||||
})
|
||||
@@ -1,21 +0,0 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
MenuHandlers.add(:debug_menu, :add_phone_contacts, {
|
||||
"name" => "Add Phone Contacts",
|
||||
"parent" => :main,
|
||||
"description" => "Add 10 different contacts to the phone.",
|
||||
"effect" => proc {
|
||||
Phone.add_silent(31, 6, :PICNICKER, "Susie", 2)
|
||||
Phone.add_silent(52, 1, :POKEMANIAC, "Peter", 2, nil, 1)
|
||||
Phone.add_silent(26, 1, :POKEMONBREEDER, "Bob", 2)
|
||||
Phone.add_silent(7, 1, :SCIENTIST, "Cedric", 2)
|
||||
Phone.add_silent(69, 1, :SWIMMER_F, "Ariel", 2)
|
||||
Phone.add_silent(5, 1, :BIRDKEEPER, "Sylvie", 2)
|
||||
Phone.add_silent(72, 1, :BLACKBELT, "Jackie", 2)
|
||||
Phone.add_silent(28, 1, :BUGCATCHER, "Tommy", 2)
|
||||
Phone.add_silent(31, 5, :CAMPER, "Jeff", 2)
|
||||
Phone.add_silent(49, 1, :HIKER, "Ford", 2)
|
||||
pbMessage("Done.")
|
||||
}
|
||||
})
|
||||
@@ -1,18 +0,0 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
MenuHandlers.add(:debug_menu, :test_random_dungeon, {
|
||||
"name" => "Test Random Dungeon Generation",
|
||||
"parent" => :main,
|
||||
"description" => "Generates a random dungeon and echoes it to the console.",
|
||||
"effect" => proc {
|
||||
# $PokemonGlobal.dungeon_rng_seed = 12345
|
||||
tileset = :cave # :forest # :cave
|
||||
tileset_data = GameData::DungeonTileset.try_get((tileset == :forest) ? 23 : 7)
|
||||
params = GameData::DungeonParameters.try_get(tileset)
|
||||
dungeon = RandomDungeon::Dungeon.new(params.cell_count_x, params.cell_count_y, tileset_data, params)
|
||||
dungeon.generate
|
||||
echoln dungeon.rng_seed
|
||||
echoln dungeon.write
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user