Refactoring and tidying

This commit is contained in:
Maruno17
2021-01-11 19:30:45 +00:00
parent a5d1359dfe
commit 2586c09c3c
37 changed files with 5288 additions and 5966 deletions

View File

@@ -76,6 +76,19 @@ module Compiler
return line
end
def csvQuote(str,always=false)
return "" if !str || str==""
if always || str[/[,\"]/] # || str[/^\s/] || str[/\s$/] || str[/^#/]
str = str.gsub(/[\"]/,"\\\"")
str = "\"#{str}\""
end
return str
end
def csvQuoteAlways(str)
return csvQuote(str,true)
end
#=============================================================================
# PBS file readers
#=============================================================================
@@ -115,7 +128,7 @@ module Compiler
yield lastsection,sectionname if havesection
end
# Used for pokemon.txt
# Used for types.txt, pokemon.txt, metadata.txt
def pbEachFileSection(f)
pbEachFileSectionEx(f) { |section,name|
yield section,name.to_i if block_given? && name[/^\d+$/]
@@ -201,7 +214,7 @@ module Compiler
}
end
# Used for connections.txt, abilities.txt, moves.txt, trainertypes.txt
# Used for connections.txt, abilities.txt, moves.txt, regionaldexes.txt
def pbCompilerEachPreppedLine(filename)
File.open(filename,"rb") { |f|
FileLineData.file = filename
@@ -514,34 +527,73 @@ module Compiler
end
#=============================================================================
# Check whether a number fits in a given numerical range (all unused)
# Write values to a file using a schema
#=============================================================================
def pbCheckByte(x,valuename)
if x<0 || x>255
raise _INTL("The value \"{1}\" must be from 0 through 255 (00-FF in hex), got a value of {2}\r\n{3}",
valuename,x,FileLineData.linereport)
end
end
def pbCheckSignedByte(x,valuename)
if x<-128 || x>127
raise _INTL("The value \"{1}\" must be from -128 through 127, got a value of {2}\r\n{3}",
valuename,x,FileLineData.linereport)
end
end
def pbCheckWord(x,valuename)
if x<0 || x>65535
raise _INTL("The value \"{1}\" must be from 0 through 65535 (0000-FFFF in hex), got a value of {2}\r\n{3}",
valuename,x,FileLineData.linereport)
end
end
def pbCheckSignedWord(x,valuename)
if x<-32768 || x>32767
raise _INTL("The value \"{1}\" must be from -32768 through 32767, got a value of {2}\r\n{3}",
valuename,x,FileLineData.linereport)
def pbWriteCsvRecord(record,file,schema)
rec = (record.is_a?(Array)) ? record.clone : [record]
for i in 0...schema[1].length
chr = schema[1][i,1]
file.write(",") if i>0
if rec[i].nil?
# do nothing
elsif rec[i].is_a?(String)
file.write(csvQuote(rec[i]))
elsif rec[i].is_a?(Symbol)
file.write(csvQuote(rec[i].to_s))
elsif rec[i]==true
file.write("true")
elsif rec[i]==false
file.write("false")
elsif rec[i].is_a?(Numeric)
case chr
when "e", "E" # Enumerable
enumer = schema[2+i]
if enumer.is_a?(Array)
file.write(enumer[rec[i]])
elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
mod = Object.const_get(enumer.to_sym)
file.write(getConstantName(mod,rec[i]))
elsif enumer.is_a?(Module)
file.write(getConstantName(enumer,rec[i]))
elsif enumer.is_a?(Hash)
for key in enumer.keys
if enumer[key]==rec[i]
file.write(key)
break
end
end
end
when "y", "Y" # Enumerable or integer
enumer = schema[2+i]
if enumer.is_a?(Array)
if enumer[rec[i]]!=nil
file.write(enumer[rec[i]])
else
file.write(rec[i])
end
elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
mod = Object.const_get(enumer.to_sym)
file.write(getConstantNameOrValue(mod,rec[i]))
elsif enumer.is_a?(Module)
file.write(getConstantNameOrValue(enumer,rec[i]))
elsif enumer.is_a?(Hash)
hasenum = false
for key in enumer.keys
if enumer[key]==rec[i]
file.write(key)
hasenum = true; break
end
end
file.write(rec[i]) unless hasenum
end
else # Any other record type
file.write(rec[i].inspect)
end
else
file.write(rec[i].inspect)
end
end
return record
end
#=============================================================================
@@ -625,12 +677,14 @@ module Compiler
MessageTypes.loadMessageFile("Data/messages.dat")
end
if mustCompile
yield(_INTL("Compiling type data"))
compile_types # No dependencies
yield(_INTL("Compiling town map data"))
compile_town_map # No dependencies
yield(_INTL("Compiling map connection data"))
compile_connections # No dependencies
yield(_INTL("Compiling phone data"))
compile_phone
yield(_INTL("Compiling type data"))
compile_types # No dependencies
yield(_INTL("Compiling ability data"))
compile_abilities # No dependencies
yield(_INTL("Compiling move data"))
@@ -645,22 +699,20 @@ module Compiler
compile_pokemon_forms # Depends on Species, Move, Item, Type, Ability
yield(_INTL("Compiling machine data"))
compile_move_compatibilities # Depends on Species, Move
yield(_INTL("Compiling Trainer type data"))
compile_trainer_types # No dependencies
yield(_INTL("Compiling Trainer data"))
compile_trainers # Depends on Species, Item, Move
yield(_INTL("Compiling phone data"))
compile_phone
yield(_INTL("Compiling metadata"))
compile_metadata # Depends on TrainerType
yield(_INTL("Compiling battle Trainer data"))
compile_trainer_lists # Depends on TrainerType
yield(_INTL("Compiling encounter data"))
compile_encounters # Depends on Species
yield(_INTL("Compiling shadow moveset data"))
compile_shadow_movesets # Depends on Species, Move
yield(_INTL("Compiling Regional Dexes"))
compile_regional_dexes # Depends on Species
yield(_INTL("Compiling encounter data"))
compile_encounters # Depends on Species
yield(_INTL("Compiling Trainer type data"))
compile_trainer_types # No dependencies
yield(_INTL("Compiling Trainer data"))
compile_trainers # Depends on Species, Item, Move
yield(_INTL("Compiling battle Trainer data"))
compile_trainer_lists # Depends on TrainerType
yield(_INTL("Compiling metadata"))
compile_metadata # Depends on TrainerType
yield(_INTL("Compiling animations"))
compile_animations
yield(_INTL("Converting events"))
@@ -698,8 +750,7 @@ module Compiler
"trainer_lists.dat",
"trainer_types.dat",
"trainers.dat",
"types.dat",
"Constants.rxdata"
"types.dat"
]
textFiles = [
"abilities.txt",
@@ -728,7 +779,7 @@ module Compiler
# If no PBS file, create one and fill it, then recompile
if !safeIsDirectory?("PBS")
Dir.mkdir("PBS") rescue nil
pbSaveAllData
write_all
mustCompile = true
end
# Should recompile if holding Ctrl

View File

@@ -1,305 +0,0 @@
# NOTE: Everything in here is unused.
#===============================================================================
# Serial record
#===============================================================================
# Unused
module SerialRecords
class SerialRecord < Array
def bytesize
return SerialRecord.bytesize(self)
end
def encode(strm)
return SerialRecord.encode(self,strm)
end
def self.bytesize(arr)
ret = 0
return 0 if !arr
for field in arr
if field==nil || field==true || field==false
ret += 1
elsif field.is_a?(String)
ret += strSize(field)+1
elsif field.is_a?(Numeric)
ret += intSize(field)+1
end
end
return ret
end
def self.encode(arr,strm)
return if !arr
for field in arr
if field==nil
strm.write("0")
elsif field==true
strm.write("T")
elsif field==false
strm.write("F")
elsif field.is_a?(String)
strm.write("\"")
encodeString(strm,field)
elsif field.is_a?(Numeric)
strm.write("i")
encodeInt(strm,field)
end
end
end
def self.decode(strm,offset,length)
ret = SerialRecord.new
strm.pos = offset
while strm.pos<offset+length
datatype = strm.read(1)
case datatype
when "0" then ret.push(nil)
when "T" then ret.push(true)
when "F" then ret.push(false)
when "\"" then ret.push(decodeString(strm))
when "i" then ret.push(decodeInt(strm))
end
end
return ret
end
end
def self.readSerialRecords(filename)
ret = []
return ret if !pbRgssExists?(filename)
pbRgssOpen(filename,"rb") { |file|
numrec = file.fgetdw>>3
curpos = 0
numrec.times do
file.pos = curpos
offset = file.fgetdw
length = file.fgetdw
record = SerialRecord.decode(file,offset,length)
ret.push(record)
curpos += 8
end
}
return ret
end
def self.writeSerialRecords(filename,records)
File.open(filename,"wb") { |file|
totalsize = records.length*8
for record in records
file.fputdw(totalsize)
bytesize = record.bytesize
file.fputdw(bytesize)
totalsize += bytesize
end
for record in records
record.encode(file)
end
}
end
end
#===============================================================================
# Data structures
#===============================================================================
# Unused
class ByteArray
include Enumerable
def initialize(data=nil)
@a = (data) ? data.unpack("C*") : []
end
def [](i); return @a[i]; end
def []=(i,value); @a[i] = value; end
def length; @a.length; end
def size; @a.size; end
def fillNils(length,value)
for i in 0...length
@a[i] = value if !@a[i]
end
end
def each
@a.each { |i| yield i}
end
def self._load(str)
return self.new(str)
end
def _dump(_depth=100)
return @a.pack("C*")
end
end
# Unused
class WordArray
include Enumerable
def initialize(data=nil)
@a = (data) ? data.unpack("v*") : []
end
def [](i); return @a[i]; end
def []=(i,value); @a[i] = value; end
def length; @a.length; end
def size; @a.size; end
def fillNils(length,value)
for i in 0...length
@a[i] = value if !@a[i]
end
end
def each
@a.each { |i| yield i}
end
def self._load(str)
return self.new(str)
end
def _dump(_depth=100)
return @a.pack("v*")
end
end
# Unused
class SignedWordArray
include Enumerable
def initialize(data=nil)
@a = (data) ? data.unpack("v*") : []
end
def []=(i,value)
@a[i] = value
end
def [](i)
v = @a[i]
return 0 if !v
return (v<0x8000) ? v : -((~v)&0xFFFF)-1
end
def length; @a.length; end
def size; @a.size; end
def fillNils(length,value)
for i in 0...length
@a[i] = value if !@a[i]
end
end
def each
@a.each { |i| yield i}
end
def self._load(str)
return self.new(str)
end
def _dump(_depth=100)
return @a.pack("v*")
end
end
#===============================================================================
# Encoding and decoding
#===============================================================================
# Unused
def intSize(value)
return 1 if value<0x80
return 2 if value<0x4000
return 3 if value<0x200000
return 4 if value<0x10000000
return 5
end
# Unused
def encodeInt(strm,value)
num = 0
loop do
if value<0x80
strm.fputb(value)
return num+1
end
strm.fputb(0x80|(value&0x7F))
value >>= 7
num += 1
end
end
# Unused
def decodeInt(strm)
bits = 0
curbyte = 0
ret = 0
begin
curbyte = strm.fgetb
ret += (curbyte&0x7F)<<bits
bits += 7
end while ((curbyte&0x80)>0)&&bits<0x1d
return ret
end
# Unused
def strSize(str)
return str.length+intSize(str.length)
end
# Unused
def encodeString(strm,str)
encodeInt(strm,str.length)
strm.write(str)
end
# Unused
def decodeString(strm)
len = decodeInt(strm)
return strm.read(len)
end
# Unused
def frozenArrayValue(arr)
typestring = ""
for i in 0...arr.length
if i>0
typestring += ((i%20)==0) ? ",\r\n" : ","
end
typestring += arr[i].to_s
end
return "["+typestring+"].freeze"
end
#===============================================================================
# Scripted constants
#===============================================================================
# Unused
def pbFindScript(a,name)
a.each { |i|
next if !i
return i if i[1]==name
}
return nil
end
# Unused
def pbAddScript(script,sectionname)
begin
scripts = load_data("Data/Constants.rxdata")
scripts = [] if !scripts
rescue
scripts = []
end
if false # s
s = pbFindScript(scripts,sectionname)
s[2]+=Zlib::Deflate.deflate("#{script}\r\n")
else
scripts.push([rand(100000000),sectionname,Zlib::Deflate.deflate("#{script}\r\n")])
end
save_data(scripts,"Data/Constants.rxdata")
end

View File

@@ -2,96 +2,7 @@ module Compiler
module_function
#=============================================================================
# Compile metadata
#=============================================================================
def compile_metadata
GameData::Metadata::DATA.clear
GameData::MapMetadata::DATA.clear
# Read from PBS file
File.open("PBS/metadata.txt", "rb") { |f|
FileLineData.file = "PBS/metadata.txt" # For error reporting
# Read a whole section's lines at once, then run through this code.
# contents is a hash containing all the XXX=YYY lines in that section, where
# the keys are the XXX and the values are the YYY (as unprocessed strings).
pbEachFileSection(f) { |contents, map_id|
schema = (map_id == 0) ? GameData::Metadata::SCHEMA : GameData::MapMetadata::SCHEMA
# Go through schema hash of compilable data and compile this section
for key in schema.keys
FileLineData.setSection(map_id, key, contents[key]) # For error reporting
# Skip empty properties, or raise an error if a required property is
# empty
if contents[key].nil?
if map_id == 0 && ["Home", "PlayerA"].include?(key)
raise _INTL("The entry {1} is required in PBS/metadata.txt section 0.", key)
end
next
end
# Compile value for key
value = pbGetCsvRecord(contents[key], key, schema[key])
value = nil if value.is_a?(Array) && value.length == 0
contents[key] = value
end
if map_id == 0 # Global metadata
# Construct metadata hash
metadata_hash = {
:id => map_id,
:home => contents["Home"],
:wild_battle_BGM => contents["WildBattleBGM"],
:trainer_battle_BGM => contents["TrainerBattleBGM"],
:wild_victory_ME => contents["WildVictoryME"],
:trainer_victory_ME => contents["TrainerVictoryME"],
:wild_capture_ME => contents["WildCaptureME"],
:surf_BGM => contents["SurfBGM"],
:bicycle_BGM => contents["BicycleBGM"],
:player_A => contents["PlayerA"],
:player_B => contents["PlayerB"],
:player_C => contents["PlayerC"],
:player_D => contents["PlayerD"],
:player_E => contents["PlayerE"],
:player_F => contents["PlayerF"],
:player_G => contents["PlayerG"],
:player_H => contents["PlayerH"]
}
# Add metadata's data to records
GameData::Metadata::DATA[map_id] = GameData::Metadata.new(metadata_hash)
else # Map metadata
# Construct metadata hash
metadata_hash = {
:id => map_id,
:outdoor_map => contents["Outdoor"],
:announce_location => contents["ShowArea"],
:can_bicycle => contents["Bicycle"],
:always_bicycle => contents["BicycleAlways"],
:teleport_destination => contents["HealingSpot"],
:weather => contents["Weather"],
:town_map_position => contents["MapPosition"],
:dive_map_id => contents["DiveMap"],
:dark_map => contents["DarkMap"],
:safari_map => contents["SafariMap"],
:snap_edges => contents["SnapEdges"],
:random_dungeon => contents["Dungeon"],
:battle_background => contents["BattleBack"],
:wild_battle_BGM => contents["WildBattleBGM"],
:trainer_battle_BGM => contents["TrainerBattleBGM"],
:wild_victory_ME => contents["WildVictoryME"],
:trainer_victory_ME => contents["TrainerVictoryME"],
:wild_capture_ME => contents["WildCaptureME"],
:town_map_size => contents["MapSize"],
:battle_environment => contents["Environment"]
}
# Add metadata's data to records
GameData::MapMetadata::DATA[map_id] = GameData::MapMetadata.new(metadata_hash)
end
}
}
# Save all data
GameData::Metadata.save
GameData::MapMetadata.save
Graphics.update
end
#=============================================================================
# Compile town map points
# Compile Town Map data
#=============================================================================
def compile_town_map
nonglobaltypes = {
@@ -182,36 +93,6 @@ module Compiler
Graphics.update
end
#=============================================================================
# Compile berry plants
#=============================================================================
def compile_berry_plants
GameData::BerryPlant::DATA.clear
pbCompilerEachCommentedLine("PBS/berryplants.txt") { |line, line_no|
if line[/^\s*(\w+)\s*=\s*(.*)$/] # Of the format XXX = YYY
key = $1
value = $2
item_symbol = parseItem(key)
item_number = GameData::Item.get(item_symbol).id_number
line = pbGetCsvRecord(value, line_no, [0, "vuuv"])
# Construct berry plant hash
berry_plant_hash = {
:id => item_symbol,
:id_number => item_number,
:hours_per_stage => line[0],
:drying_per_hour => line[1],
:minimum_yield => line[2],
:maximum_yield => line[3]
}
# Add berry plant's data to records
GameData::BerryPlant::DATA[item_number] = GameData::BerryPlant::DATA[item_symbol] = GameData::BerryPlant.new(berry_plant_hash)
end
}
# Save all data
GameData::BerryPlant.save
Graphics.update
end
#=============================================================================
# Compile phone messages
#=============================================================================
@@ -251,7 +132,7 @@ module Compiler
end
#=============================================================================
# Compile types
# Compile type data
#=============================================================================
def compile_types
GameData::Type::DATA.clear
@@ -325,7 +206,7 @@ module Compiler
end
#=============================================================================
# Compile abilities
# Compile ability data
#=============================================================================
def compile_abilities
GameData::Ability::DATA.clear
@@ -359,100 +240,6 @@ module Compiler
Graphics.update
end
#=============================================================================
# Compile items
#=============================================================================
=begin
class ItemList
include Enumerable
def initialize; @list = []; end
def length; @list.length; end
def []=(x,v); @list[x] = v; end
def [](x)
if !@list[x]
defrecord = SerialRecords::SerialRecord.new
defrecord.push(0)
defrecord.push("????????")
defrecord.push(0)
defrecord.push(0)
defrecord.push("????????")
@list[x] = defrecord
return defrecord
end
return @list[x]
end
def each
for i in 0...self.length
yield self[i]
end
end
end
def readItemList(filename)
ret = ItemList.new
return ret if !pbRgssExists?(filename)
pbRgssOpen(filename,"rb") { |file|
numrec = file.fgetdw>>3
curpos = 0
numrec.times do
file.pos = curpos
offset = file.fgetdw
length = file.fgetdw
record = SerialRecords::SerialRecord.decode(file,offset,length)
ret[record[0]] = record
curpos += 8
end
}
return ret
end
=end
def compile_items
GameData::Item::DATA.clear
item_names = []
item_names_plural = []
item_descriptions = []
# Read each line of items.txt at a time and compile it into an item
pbCompilerEachCommentedLine("PBS/items.txt") { |line, line_no|
line = pbGetCsvRecord(line, line_no, [0, "vnssuusuuUN"])
item_number = line[0]
item_symbol = line[1].to_sym
if GameData::Item::DATA[item_number]
raise _INTL("Item ID number '{1}' is used twice.\r\n{2}", item_number, FileLineData.linereport)
elsif GameData::Item::DATA[item_symbol]
raise _INTL("Item ID '{1}' is used twice.\r\n{2}", item_symbol, FileLineData.linereport)
end
# Construct item hash
item_hash = {
:id_number => item_number,
:id => item_symbol,
:name => line[2],
:name_plural => line[3],
:pocket => line[4],
:price => line[5],
:description => line[6],
:field_use => line[7],
:battle_use => line[8],
:type => line[9]
}
item_hash[:move] = parseMove(line[10]) if !nil_or_empty?(line[10])
# Add item's data to records
GameData::Item::DATA[item_number] = GameData::Item::DATA[item_symbol] = GameData::Item.new(item_hash)
item_names[item_number] = item_hash[:name]
item_names_plural[item_number] = item_hash[:name_plural]
item_descriptions[item_number] = item_hash[:description]
}
# Save all data
GameData::Item.save
MessageTypes.setMessages(MessageTypes::Items, item_names)
MessageTypes.setMessages(MessageTypes::ItemPlurals, item_names_plural)
MessageTypes.setMessages(MessageTypes::ItemDescriptions, item_descriptions)
Graphics.update
end
#=============================================================================
# Compile move data
#=============================================================================
@@ -510,49 +297,83 @@ module Compiler
end
#=============================================================================
# Compile battle animations
# Compile item data
#=============================================================================
def compile_animations
begin
pbanims = load_data("Data/PkmnAnimations.rxdata")
rescue
pbanims = PBAnimations.new
end
move2anim = [[],[]]
=begin
anims = load_data("Data/Animations.rxdata")
for anim in anims
next if !anim || anim.frames.length==1
found = false
for i in 0...pbanims.length
if pbanims[i] && pbanims[i].id==anim.id
found = true if pbanims[i].array.length>1
break
end
def compile_items
GameData::Item::DATA.clear
item_names = []
item_names_plural = []
item_descriptions = []
# Read each line of items.txt at a time and compile it into an item
pbCompilerEachCommentedLine("PBS/items.txt") { |line, line_no|
line = pbGetCsvRecord(line, line_no, [0, "vnssuusuuUN"])
item_number = line[0]
item_symbol = line[1].to_sym
if GameData::Item::DATA[item_number]
raise _INTL("Item ID number '{1}' is used twice.\r\n{2}", item_number, FileLineData.linereport)
elsif GameData::Item::DATA[item_symbol]
raise _INTL("Item ID '{1}' is used twice.\r\n{2}", item_symbol, FileLineData.linereport)
end
pbanims[anim.id] = pbConvertRPGAnimation(anim) if !found
end
=end
for i in 0...pbanims.length
next if !pbanims[i]
if pbanims[i].name[/^OppMove\:\s*(.*)$/]
if GameData::Move.exists?($~[1])
moveid = GameData::Move.get($~[1]).id_number
move2anim[1][moveid] = i
end
elsif pbanims[i].name[/^Move\:\s*(.*)$/]
if GameData::Move.exists?($~[1])
moveid = GameData::Move.get($~[1]).id_number
move2anim[0][moveid] = i
end
end
end
save_data(move2anim,"Data/move2anim.dat")
save_data(pbanims,"Data/PkmnAnimations.rxdata")
# Construct item hash
item_hash = {
:id_number => item_number,
:id => item_symbol,
:name => line[2],
:name_plural => line[3],
:pocket => line[4],
:price => line[5],
:description => line[6],
:field_use => line[7],
:battle_use => line[8],
:type => line[9]
}
item_hash[:move] = parseMove(line[10]) if !nil_or_empty?(line[10])
# Add item's data to records
GameData::Item::DATA[item_number] = GameData::Item::DATA[item_symbol] = GameData::Item.new(item_hash)
item_names[item_number] = item_hash[:name]
item_names_plural[item_number] = item_hash[:name_plural]
item_descriptions[item_number] = item_hash[:description]
}
# Save all data
GameData::Item.save
MessageTypes.setMessages(MessageTypes::Items, item_names)
MessageTypes.setMessages(MessageTypes::ItemPlurals, item_names_plural)
MessageTypes.setMessages(MessageTypes::ItemDescriptions, item_descriptions)
Graphics.update
end
#=============================================================================
# Compile Pokémon
# Compile berry plant data
#=============================================================================
def compile_berry_plants
GameData::BerryPlant::DATA.clear
pbCompilerEachCommentedLine("PBS/berryplants.txt") { |line, line_no|
if line[/^\s*(\w+)\s*=\s*(.*)$/] # Of the format XXX = YYY
key = $1
value = $2
item_symbol = parseItem(key)
item_number = GameData::Item.get(item_symbol).id_number
line = pbGetCsvRecord(value, line_no, [0, "vuuv"])
# Construct berry plant hash
berry_plant_hash = {
:id => item_symbol,
:id_number => item_number,
:hours_per_stage => line[0],
:drying_per_hour => line[1],
:minimum_yield => line[2],
:maximum_yield => line[3]
}
# Add berry plant's data to records
GameData::BerryPlant::DATA[item_number] = GameData::BerryPlant::DATA[item_symbol] = GameData::BerryPlant.new(berry_plant_hash)
end
}
# Save all data
GameData::BerryPlant.save
Graphics.update
end
#=============================================================================
# Compile Pokémon data
#=============================================================================
def compile_pokemon
GameData::Species::DATA.clear
@@ -713,7 +534,7 @@ module Compiler
end
#=============================================================================
# Compile Pokémon forms
# Compile Pokémon forms data
#=============================================================================
def compile_pokemon_forms
species_names = []
@@ -930,8 +751,8 @@ module Compiler
species_hash[species_data.id].each { |move| species_data.tutor_moves.push(move) }
end
GameData::Species.save
pbSavePokemonData
pbSavePokemonFormsData
Compiler.write_pokemon
Compiler.write_pokemon_forms
begin
File.delete("PBS/tm.txt")
rescue SystemCallError
@@ -1003,7 +824,7 @@ module Compiler
end
#=============================================================================
# Compile wild encounters
# Compile wild encounter data
#=============================================================================
def compile_encounters
lines = []
@@ -1110,7 +931,7 @@ module Compiler
end
#=============================================================================
# Compile trainer types
# Compile trainer type data
#=============================================================================
def compile_trainer_types
GameData::TrainerType::DATA.clear
@@ -1155,7 +976,7 @@ module Compiler
end
#=============================================================================
# Compile individual trainers
# Compile individual trainer data
#=============================================================================
def compile_trainers
trainer_info_types = TrainerData::SCHEMA
@@ -1355,52 +1176,11 @@ module Compiler
#=============================================================================
# Compile Battle Tower and other Cups trainers/Pokémon
#=============================================================================
def compile_battle_tower_trainers(filename)
sections = []
requiredtypes = {
"Type" => [0, "e", :TrainerType],
"Name" => [1, "s"],
"BeginSpeech" => [2, "s"],
"EndSpeechWin" => [3, "s"],
"EndSpeechLose" => [4, "s"],
"PokemonNos" => [5, "*u"]
}
trainernames = []
beginspeech = []
endspeechwin = []
endspeechlose = []
if safeExists?(filename)
File.open(filename,"rb") { |f|
FileLineData.file = filename
pbEachFileSectionEx(f) { |section,name|
rsection = []
for key in section.keys
FileLineData.setSection(name,key,section[key])
schema = requiredtypes[key]
next if !schema
record = pbGetCsvRecord(section[key],0,schema)
rsection[schema[0]] = record
end
trainernames.push(rsection[1])
beginspeech.push(rsection[2])
endspeechwin.push(rsection[3])
endspeechlose.push(rsection[4])
sections.push(rsection)
}
}
end
MessageTypes.addMessagesAsHash(MessageTypes::TrainerNames,trainernames)
MessageTypes.addMessagesAsHash(MessageTypes::BeginSpeech,beginspeech)
MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechWin,endspeechwin)
MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechLose,endspeechlose)
return sections
end
def compile_trainer_lists
btTrainersRequiredTypes = {
"Trainers" => [0, "s"],
"Pokemon" => [1, "s"],
"Challenges" => [2, "*s"]
"Trainers" => [0, "s"],
"Pokemon" => [1, "s"],
"Challenges" => [2, "*s"]
}
if !safeExists?("PBS/trainerlists.txt")
File.open("PBS/trainerlists.txt","wb") { |f|
@@ -1462,4 +1242,176 @@ module Compiler
}
save_data(sections,"Data/trainer_lists.dat")
end
def compile_battle_tower_trainers(filename)
sections = []
requiredtypes = {
"Type" => [0, "e", :TrainerType],
"Name" => [1, "s"],
"BeginSpeech" => [2, "s"],
"EndSpeechWin" => [3, "s"],
"EndSpeechLose" => [4, "s"],
"PokemonNos" => [5, "*u"]
}
trainernames = []
beginspeech = []
endspeechwin = []
endspeechlose = []
if safeExists?(filename)
File.open(filename,"rb") { |f|
FileLineData.file = filename
pbEachFileSectionEx(f) { |section,name|
rsection = []
for key in section.keys
FileLineData.setSection(name,key,section[key])
schema = requiredtypes[key]
next if !schema
record = pbGetCsvRecord(section[key],0,schema)
rsection[schema[0]] = record
end
trainernames.push(rsection[1])
beginspeech.push(rsection[2])
endspeechwin.push(rsection[3])
endspeechlose.push(rsection[4])
sections.push(rsection)
}
}
end
MessageTypes.addMessagesAsHash(MessageTypes::TrainerNames,trainernames)
MessageTypes.addMessagesAsHash(MessageTypes::BeginSpeech,beginspeech)
MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechWin,endspeechwin)
MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechLose,endspeechlose)
return sections
end
#=============================================================================
# Compile metadata
#=============================================================================
def compile_metadata
GameData::Metadata::DATA.clear
GameData::MapMetadata::DATA.clear
# Read from PBS file
File.open("PBS/metadata.txt", "rb") { |f|
FileLineData.file = "PBS/metadata.txt" # For error reporting
# Read a whole section's lines at once, then run through this code.
# contents is a hash containing all the XXX=YYY lines in that section, where
# the keys are the XXX and the values are the YYY (as unprocessed strings).
pbEachFileSection(f) { |contents, map_id|
schema = (map_id == 0) ? GameData::Metadata::SCHEMA : GameData::MapMetadata::SCHEMA
# Go through schema hash of compilable data and compile this section
for key in schema.keys
FileLineData.setSection(map_id, key, contents[key]) # For error reporting
# Skip empty properties, or raise an error if a required property is
# empty
if contents[key].nil?
if map_id == 0 && ["Home", "PlayerA"].include?(key)
raise _INTL("The entry {1} is required in PBS/metadata.txt section 0.", key)
end
next
end
# Compile value for key
value = pbGetCsvRecord(contents[key], key, schema[key])
value = nil if value.is_a?(Array) && value.length == 0
contents[key] = value
end
if map_id == 0 # Global metadata
# Construct metadata hash
metadata_hash = {
:id => map_id,
:home => contents["Home"],
:wild_battle_BGM => contents["WildBattleBGM"],
:trainer_battle_BGM => contents["TrainerBattleBGM"],
:wild_victory_ME => contents["WildVictoryME"],
:trainer_victory_ME => contents["TrainerVictoryME"],
:wild_capture_ME => contents["WildCaptureME"],
:surf_BGM => contents["SurfBGM"],
:bicycle_BGM => contents["BicycleBGM"],
:player_A => contents["PlayerA"],
:player_B => contents["PlayerB"],
:player_C => contents["PlayerC"],
:player_D => contents["PlayerD"],
:player_E => contents["PlayerE"],
:player_F => contents["PlayerF"],
:player_G => contents["PlayerG"],
:player_H => contents["PlayerH"]
}
# Add metadata's data to records
GameData::Metadata::DATA[map_id] = GameData::Metadata.new(metadata_hash)
else # Map metadata
# Construct metadata hash
metadata_hash = {
:id => map_id,
:outdoor_map => contents["Outdoor"],
:announce_location => contents["ShowArea"],
:can_bicycle => contents["Bicycle"],
:always_bicycle => contents["BicycleAlways"],
:teleport_destination => contents["HealingSpot"],
:weather => contents["Weather"],
:town_map_position => contents["MapPosition"],
:dive_map_id => contents["DiveMap"],
:dark_map => contents["DarkMap"],
:safari_map => contents["SafariMap"],
:snap_edges => contents["SnapEdges"],
:random_dungeon => contents["Dungeon"],
:battle_background => contents["BattleBack"],
:wild_battle_BGM => contents["WildBattleBGM"],
:trainer_battle_BGM => contents["TrainerBattleBGM"],
:wild_victory_ME => contents["WildVictoryME"],
:trainer_victory_ME => contents["TrainerVictoryME"],
:wild_capture_ME => contents["WildCaptureME"],
:town_map_size => contents["MapSize"],
:battle_environment => contents["Environment"]
}
# Add metadata's data to records
GameData::MapMetadata::DATA[map_id] = GameData::MapMetadata.new(metadata_hash)
end
}
}
# Save all data
GameData::Metadata.save
GameData::MapMetadata.save
Graphics.update
end
#=============================================================================
# Compile battle animations
#=============================================================================
def compile_animations
begin
pbanims = load_data("Data/PkmnAnimations.rxdata")
rescue
pbanims = PBAnimations.new
end
move2anim = [[],[]]
=begin
anims = load_data("Data/Animations.rxdata")
for anim in anims
next if !anim || anim.frames.length==1
found = false
for i in 0...pbanims.length
if pbanims[i] && pbanims[i].id==anim.id
found = true if pbanims[i].array.length>1
break
end
end
pbanims[anim.id] = pbConvertRPGAnimation(anim) if !found
end
=end
for i in 0...pbanims.length
next if !pbanims[i]
if pbanims[i].name[/^OppMove\:\s*(.*)$/]
if GameData::Move.exists?($~[1])
moveid = GameData::Move.get($~[1]).id_number
move2anim[1][moveid] = i
end
elsif pbanims[i].name[/^Move\:\s*(.*)$/]
if GameData::Move.exists?($~[1])
moveid = GameData::Move.get($~[1]).id_number
move2anim[0][moveid] = i
end
end
end
save_data(move2anim,"Data/move2anim.dat")
save_data(pbanims,"Data/PkmnAnimations.rxdata")
end
end

View File

@@ -0,0 +1,837 @@
module Compiler
module_function
def add_PBS_header_to_file(file)
file.write(0xEF.chr)
file.write(0xBB.chr)
file.write(0xBF.chr)
file.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n")
end
#=============================================================================
# Save Town Map data to PBS file
#=============================================================================
def write_town_map
mapdata = pbLoadTownMapData
return if !mapdata
File.open("PBS/townmap.txt","wb") { |f|
add_PBS_header_to_file(f)
for i in 0...mapdata.length
map = mapdata[i]
next if !map
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n",i))
rname = pbGetMessage(MessageTypes::RegionNames,i)
f.write(sprintf("Name = %s\r\nFilename = %s\r\n",
(rname && rname!="") ? rname : _INTL("Unnamed"),
csvQuote((map[1].is_a?(Array)) ? map[1][0] : map[1])))
for loc in map[2]
f.write("Point = ")
pbWriteCsvRecord(loc,f,[nil,"uussUUUU"])
f.write("\r\n")
end
end
}
Graphics.update
end
#===============================================================================
# Save map connections to PBS file
#===============================================================================
def normalizeConnectionPoint(conn)
ret = conn.clone
if conn[1] < 0 && conn[4] < 0
elsif conn[1] < 0 || conn[4] < 0
ret[4] = -conn[1]
ret[1] = -conn[4]
end
if conn[2] < 0 && conn[5] < 0
elsif conn[2] < 0 || conn[5] < 0
ret[5] = -conn[2]
ret[2] = -conn[5]
end
return ret
end
def writeConnectionPoint(map1, x1, y1, map2, x2, y2)
dims1 = MapFactoryHelper.getMapDims(map1)
dims2 = MapFactoryHelper.getMapDims(map2)
if x1 == 0 && x2 == dims2[0]
return sprintf("%d,West,%d,%d,East,%d", map1, y1, map2, y2)
elsif y1 == 0 && y2 == dims2[1]
return sprintf("%d,North,%d,%d,South,%d", map1, x1, map2, x2)
elsif x1 == dims1[0] && x2 == 0
return sprintf("%d,East,%d,%d,West,%d", map1, y1, map2, y2)
elsif y1 == dims1[1] && y2 == 0
return sprintf("%d,South,%d,%d,North,%d", map1, x1, map2, x2)
end
return sprintf("%d,%d,%d,%d,%d,%d", map1, x1, y1, map2, x2, y2)
end
def write_connections
conndata = load_data("Data/map_connections.dat") rescue nil
return if !conndata
mapinfos = pbLoadRxData("Data/MapInfos")
File.open("PBS/connections.txt","wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
for conn in conndata
if mapinfos
# Skip if map no longer exists
next if !mapinfos[conn[0]] || !mapinfos[conn[3]]
f.write(sprintf("# %s (%d) - %s (%d)\r\n",
(mapinfos[conn[0]]) ? mapinfos[conn[0]].name : "???", conn[0],
(mapinfos[conn[3]]) ? mapinfos[conn[3]].name : "???", conn[3]))
end
if conn[1].is_a?(String) || conn[4].is_a?(String)
f.write(sprintf("%d,%s,%d,%d,%s,%d", conn[0], conn[1], conn[2],
conn[3], conn[4], conn[5]))
else
ret = normalizeConnectionPoint(conn)
f.write(writeConnectionPoint(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]))
end
f.write("\r\n")
end
}
Graphics.update
end
#===============================================================================
# Save phone messages to PBS file
#===============================================================================
def write_phone
data = load_data("Data/phone.dat") rescue nil
return if !data
File.open("PBS/phone.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
f.write("[<Generics>]\r\n")
f.write(data.generics.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<BattleRequests>]\r\n")
f.write(data.battleRequests.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<GreetingsMorning>]\r\n")
f.write(data.greetingsMorning.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<GreetingsEvening>]\r\n")
f.write(data.greetingsEvening.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Greetings>]\r\n")
f.write(data.greetings.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Bodies1>]\r\n")
f.write(data.bodies1.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Bodies2>]\r\n")
f.write(data.bodies2.join("\r\n") + "\r\n")
}
Graphics.update
end
#===============================================================================
# Save type data to PBS file
#===============================================================================
def write_types
File.open("PBS/types.txt", "wb") { |f|
add_PBS_header_to_file(f)
# Write each type in turn
GameData::Type.each do |type|
f.write("\#-------------------------------\r\n")
f.write("[#{type.id_number}]\r\n")
f.write("Name = #{type.real_name}\r\n")
f.write("InternalName = #{type.id.to_s}\r\n")
f.write("IsPseudoType = true\r\n") if type.pseudo_type
f.write("IsSpecialType = true\r\n") if type.special?
f.write("Weaknesses = #{type.weaknesses.join(",")}\r\n") if type.weaknesses.length > 0
f.write("Resistances = #{type.resistances.join(",")}\r\n") if type.resistances.length > 0
f.write("Immunities = #{type.immunities.join(",")}\r\n") if type.immunities.length > 0
end
}
Graphics.update
end
#===============================================================================
# Save ability data to PBS file
#===============================================================================
def write_abilities
File.open("PBS/abilities.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
GameData::Ability.each do |a|
f.write(sprintf("%d,%s,%s,%s\r\n",
a.id_number,
csvQuote(a.id.to_s),
csvQuote(a.real_name),
csvQuoteAlways(a.real_description)
))
end
}
Graphics.update
end
#===============================================================================
# Save move data to PBS file
#===============================================================================
def write_moves
File.open("PBS/moves.txt", "wb") { |f|
add_PBS_header_to_file(f)
current_type = -1
GameData::Move.each do |m|
if current_type != m.type
current_type = m.type
f.write("\#-------------------------------\r\n")
end
f.write(sprintf("%d,%s,%s,%s,%d,%s,%s,%d,%d,%d,%s,%d,%s,%s\r\n",
m.id_number,
csvQuote(m.id.to_s),
csvQuote(m.real_name),
csvQuote(m.function_code),
m.base_damage,
m.type.to_s,
["Physical", "Special", "Status"][m.category],
m.accuracy,
m.total_pp,
m.effect_chance,
(getConstantName(PBTargets, m.target) rescue sprintf("%d", m.target)),
m.priority,
csvQuote(m.flags),
csvQuoteAlways(m.real_description)
))
end
}
Graphics.update
end
#===============================================================================
# Save item data to PBS file
#===============================================================================
def write_items
File.open("PBS/items.txt", "wb") { |f|
add_PBS_header_to_file(f)
current_pocket = 0
GameData::Item.each do |i|
if current_pocket != i.pocket
current_pocket = i.pocket
f.write("\#-------------------------------\r\n")
end
move_name = (i.move) ? GameData::Move.get(i.move).id.to_s : ""
sprintf_text = "%d,%s,%s,%s,%d,%d,%s,%d,%d,%d\r\n"
sprintf_text = "%d,%s,%s,%s,%d,%d,%s,%d,%d,%d,%s\r\n" if move_name != ""
f.write(sprintf(sprintf_text,
i.id_number,
csvQuote(i.id.to_s),
csvQuote(i.real_name),
csvQuote(i.real_name_plural),
i.pocket,
i.price,
csvQuoteAlways(i.real_description),
i.field_use,
i.battle_use,
i.type,
csvQuote(move_name)
))
end
}
Graphics.update
end
#===============================================================================
# Save berry plant data to PBS file
#===============================================================================
def write_berry_plants
File.open("PBS/berryplants.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
GameData::BerryPlant.each do |bp|
f.write(sprintf("%s = %d,%d,%d,%d\r\n",
csvQuote(bp.id.to_s),
bp.hours_per_stage,
bp.drying_per_hour,
bp.minimum_yield,
bp.maximum_yield
))
end
}
Graphics.update
end
#===============================================================================
# Save Pokémon data to PBS file
#===============================================================================
def write_pokemon
File.open("PBS/pokemon.txt", "wb") { |f|
add_PBS_header_to_file(f)
GameData::Species.each do |species|
next if species.form != 0
pbSetWindowText(_INTL("Writing species {1}...", species.id_number))
Graphics.update if species.id_number % 50 == 0
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%d]\r\n", species.id_number))
f.write(sprintf("Name = %s\r\n", species.real_name))
f.write(sprintf("InternalName = %s\r\n", species.species))
f.write(sprintf("Type1 = %s\r\n", species.type1))
f.write(sprintf("Type2 = %s\r\n", species.type2)) if species.type2 != species.type1
f.write(sprintf("BaseStats = %s\r\n", species.base_stats.join(",")))
f.write(sprintf("GenderRate = %s\r\n", getConstantName(PBGenderRates, species.gender_rate)))
f.write(sprintf("GrowthRate = %s\r\n", getConstantName(PBGrowthRates, species.growth_rate)))
f.write(sprintf("BaseEXP = %d\r\n", species.base_exp))
f.write(sprintf("EffortPoints = %s\r\n", species.evs.join(",")))
f.write(sprintf("Rareness = %d\r\n", species.catch_rate))
f.write(sprintf("Happiness = %d\r\n", species.happiness))
if species.abilities.length > 0
f.write(sprintf("Abilities = %s\r\n", species.abilities.join(",")))
end
if species.hidden_abilities.length > 0
f.write(sprintf("HiddenAbility = %s\r\n", species.hidden_abilities.join(",")))
end
if species.moves.length > 0
f.write(sprintf("Moves = %s\r\n", species.moves.join(",")))
end
if species.tutor_moves.length > 0
f.write(sprintf("TutorMoves = %s\r\n", species.tutor_moves.join(",")))
end
if species.egg_moves.length > 0
f.write(sprintf("EggMoves = %s\r\n", species.egg_moves.join(",")))
end
if species.egg_groups.length > 0
f.write("Compatibility = ")
species.egg_groups.each_with_index do |group, i|
f.write(",") if i > 0
f.write(getConstantName(PBEggGroups, group))
end
f.write("\r\n")
end
f.write(sprintf("StepsToHatch = %d\r\n", species.hatch_steps))
f.write(sprintf("Height = %.1f\r\n", species.height / 10.0))
f.write(sprintf("Weight = %.1f\r\n", species.weight / 10.0))
f.write(sprintf("Color = %s\r\n", getConstantName(PBColors, species.color)))
f.write(sprintf("Shape = %d\r\n", species.shape))
f.write(sprintf("Habitat = %s\r\n", getConstantName(PBHabitats, species.habitat))) if species.habitat != PBHabitats::None
f.write(sprintf("Kind = %s\r\n", species.real_category))
f.write(sprintf("Pokedex = %s\r\n", species.real_pokedex_entry))
f.write(sprintf("FormName = %s\r\n", species.real_form_name)) if species.real_form_name && !species.real_form_name.empty?
f.write(sprintf("Generation = %d\r\n", species.generation)) if species.generation != 0
f.write(sprintf("WildItemCommon = %s\r\n", species.wild_item_common)) if species.wild_item_common
f.write(sprintf("WildItemUncommon = %s\r\n", species.wild_item_uncommon)) if species.wild_item_uncommon
f.write(sprintf("WildItemRare = %s\r\n", species.wild_item_rare)) if species.wild_item_rare
f.write(sprintf("BattlerPlayerX = %d\r\n", species.back_sprite_x))
f.write(sprintf("BattlerPlayerY = %d\r\n", species.back_sprite_y))
f.write(sprintf("BattlerEnemyX = %d\r\n", species.front_sprite_x))
f.write(sprintf("BattlerEnemyY = %d\r\n", species.front_sprite_y))
f.write(sprintf("BattlerAltitude = %d\r\n", species.front_sprite_altitude)) if species.front_sprite_altitude != 0
f.write(sprintf("BattlerShadowX = %d\r\n", species.shadow_x))
f.write(sprintf("BattlerShadowSize = %d\r\n", species.shadow_size))
if species.evolutions.any? { |evo| !evo[3] }
f.write("Evolutions = ")
need_comma = false
species.evolutions.each do |evo|
next if evo[3] # Skip prevolution entries
f.write(",") if need_comma
need_comma = true
f.write(sprintf("%s,%s,", evo[0], getConstantName(PBEvolution, evo[1])))
param_type = PBEvolution.getFunction(evo[1], "parameterType")
has_param = !PBEvolution.hasFunction?(evo[1], "parameterType") || param_type != nil
next if !has_param
if param_type
if GameData.const_defined?(param_type.to_sym)
f.write(evo[2].to_s)
else
f.write(getConstantName(param_type, evo[2]))
end
else
f.write(evo[2].to_s)
end
end
f.write("\r\n")
end
f.write(sprintf("Incense = %s\r\n", species.incense)) if species.incense
end
}
Graphics.update
end
#===============================================================================
# Save Pokémon forms data to PBS file
#===============================================================================
def write_pokemon_forms
File.open("PBS/pokemonforms.txt", "wb") { |f|
add_PBS_header_to_file(f)
GameData::Species.each do |species|
next if species.form == 0
base_species = GameData::Species.get(species.species)
pbSetWindowText(_INTL("Writing species {1}...", species.id_number))
Graphics.update if species.id_number % 50 == 0
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%s,%d]\r\n", species.species, species.form))
f.write(sprintf("FormName = %s\r\n", species.real_form_name)) if species.real_form_name && !species.real_form_name.empty?
f.write(sprintf("PokedexForm = %d\r\n", species.pokedex_form)) if species.pokedex_form != species.form
f.write(sprintf("MegaStone = %s\r\n", species.mega_stone)) if species.mega_stone
f.write(sprintf("MegaMove = %s\r\n", species.mega_move)) if species.mega_move
f.write(sprintf("UnmegaForm = %d\r\n", species.unmega_form)) if species.unmega_form != 0
f.write(sprintf("MegaMessage = %d\r\n", species.mega_message)) if species.mega_message != 0
if species.type1 != base_species.type1 || species.type2 != base_species.type2
f.write(sprintf("Type1 = %s\r\n", species.type1))
f.write(sprintf("Type2 = %s\r\n", species.type2)) if species.type2 != species.type1
end
f.write(sprintf("BaseStats = %s\r\n", species.base_stats.join(","))) if species.base_stats != base_species.base_stats
f.write(sprintf("BaseEXP = %d\r\n", species.base_exp)) if species.base_exp != base_species.base_exp
f.write(sprintf("EffortPoints = %s\r\n", species.evs.join(","))) if species.evs != base_species.evs
f.write(sprintf("Rareness = %d\r\n", species.catch_rate)) if species.catch_rate != base_species.catch_rate
f.write(sprintf("Happiness = %d\r\n", species.happiness)) if species.happiness != base_species.happiness
if species.abilities.length > 0 && species.abilities != base_species.abilities
f.write(sprintf("Abilities = %s\r\n", species.abilities.join(",")))
end
if species.hidden_abilities.length > 0 && species.hidden_abilities != base_species.hidden_abilities
f.write(sprintf("HiddenAbility = %s\r\n", species.hidden_abilities.join(",")))
end
if species.moves.length > 0 && species.moves != base_species.moves
f.write(sprintf("Moves = %s\r\n", species.moves.join(",")))
end
if species.tutor_moves.length > 0 && species.tutor_moves != base_species.tutor_moves
f.write(sprintf("TutorMoves = %s\r\n", species.tutor_moves.join(",")))
end
if species.egg_moves.length > 0 && species.egg_moves != base_species.egg_moves
f.write(sprintf("EggMoves = %s\r\n", species.egg_moves.join(",")))
end
if species.egg_groups.length > 0 && species.egg_groups != base_species.egg_groups
f.write("Compatibility = ")
species.egg_groups.each_with_index do |group, i|
f.write(",") if i > 0
f.write(getConstantName(PBEggGroups, group))
end
f.write("\r\n")
end
f.write(sprintf("StepsToHatch = %d\r\n", species.hatch_steps)) if species.hatch_steps != base_species.hatch_steps
f.write(sprintf("Height = %.1f\r\n", species.height / 10.0)) if species.height != base_species.height
f.write(sprintf("Weight = %.1f\r\n", species.weight / 10.0)) if species.weight != base_species.weight
f.write(sprintf("Color = %s\r\n", getConstantName(PBColors, species.color))) if species.color != base_species.color
f.write(sprintf("Shape = %d\r\n", species.shape)) if species.shape != base_species.shape
if species.habitat != PBHabitats::None && species.habitat != base_species.habitat
f.write(sprintf("Habitat = %s\r\n", getConstantName(PBHabitats, species.habitat)))
end
f.write(sprintf("Kind = %s\r\n", species.real_category)) if species.real_category != base_species.real_category
f.write(sprintf("Pokedex = %s\r\n", species.real_pokedex_entry)) if species.real_pokedex_entry != base_species.real_pokedex_entry
f.write(sprintf("Generation = %d\r\n", species.generation)) if species.generation != base_species.generation
if species.wild_item_common != base_species.wild_item_common ||
species.wild_item_uncommon != base_species.wild_item_uncommon ||
species.wild_item_rare != base_species.wild_item_rare
f.write(sprintf("WildItemCommon = %s\r\n", species.wild_item_common)) if species.wild_item_common
f.write(sprintf("WildItemUncommon = %s\r\n", species.wild_item_uncommon)) if species.wild_item_uncommon
f.write(sprintf("WildItemRare = %s\r\n", species.wild_item_rare)) if species.wild_item_rare
end
f.write(sprintf("BattlerPlayerX = %d\r\n", species.back_sprite_x)) if species.back_sprite_x != base_species.back_sprite_x
f.write(sprintf("BattlerPlayerY = %d\r\n", species.back_sprite_y)) if species.back_sprite_y != base_species.back_sprite_y
f.write(sprintf("BattlerEnemyX = %d\r\n", species.front_sprite_x)) if species.front_sprite_x != base_species.front_sprite_x
f.write(sprintf("BattlerEnemyY = %d\r\n", species.front_sprite_y)) if species.front_sprite_y != base_species.front_sprite_y
f.write(sprintf("BattlerAltitude = %d\r\n", species.front_sprite_altitude)) if species.front_sprite_altitude != base_species.front_sprite_altitude
f.write(sprintf("BattlerShadowX = %d\r\n", species.shadow_x)) if species.shadow_x != base_species.shadow_x
f.write(sprintf("BattlerShadowSize = %d\r\n", species.shadow_size)) if species.shadow_size != base_species.shadow_size
if species.evolutions != base_species.evolutions && species.evolutions.any? { |evo| !evo[3] }
f.write("Evolutions = ")
need_comma = false
species.evolutions.each do |evo|
next if evo[3] # Skip prevolution entries
f.write(",") if need_comma
need_comma = true
f.write(sprintf("%s,%s,", evo[0], getConstantName(PBEvolution, evo[1])))
param_type = PBEvolution.getFunction(evo[1], "parameterType")
has_param = !PBEvolution.hasFunction?(evo[1], "parameterType") || param_type != nil
next if !has_param
if param_type
if GameData.const_defined?(param_type.to_sym)
f.write(evo[2].to_s)
else
f.write(getConstantName(param_type, evo[2]))
end
else
f.write(evo[2].to_s)
end
end
f.write("\r\n")
end
end
}
Graphics.update
end
#===============================================================================
# Save Shadow movesets to PBS file
#===============================================================================
def write_shadow_movesets
shadow_movesets = pbLoadShadowMovesets
File.open("PBS/shadowmoves.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
GameData::Species.each do |species_data|
moveset = shadow_movesets[species_data.id]
next if !moveset || moveset.length == 0
f.write(sprintf("%s = %s\r\n", species_data.id, moveset.join(",")))
end
}
Graphics.update
end
#===============================================================================
# Save Regional Dexes to PBS file
#===============================================================================
def write_regional_dexes
dex_lists = pbLoadRegionalDexes
File.open("PBS/regionaldexes.txt", "wb") { |f|
add_PBS_header_to_file(f)
# Write each Dex list in turn
dex_lists.each_with_index do |list, index|
f.write("\#-------------------------------\r\n")
f.write("[#{index}]")
comma = false
current_family = nil
list.each do |species|
next if !species
if current_family && current_family.include?(species)
f.write(",") if comma
else
current_family = EvolutionHelper.all_related_species(species)
comma = false
f.write("\r\n")
end
f.write(species)
comma = true
end
f.write("\r\n")
end
}
Graphics.update
end
#===============================================================================
# Save wild encounter data to PBS file
#===============================================================================
def write_encounters
encdata = pbLoadEncountersData
return if !encdata
mapinfos = pbLoadRxData("Data/MapInfos")
File.open("PBS/encounters.txt","wb") { |f|
add_PBS_header_to_file(f)
sortedkeys = encdata.keys.sort
for i in sortedkeys
next if !encdata[i]
e = encdata[i]
mapname = ""
if mapinfos[i]
map = mapinfos[i].name
mapname = " # #{map}"
end
f.write("\#-------------------------------\r\n")
f.write(sprintf("%03d%s\r\n",i,mapname))
f.write(sprintf("%d,%d,%d\r\n",e[0][EncounterTypes::Land],
e[0][EncounterTypes::Cave],e[0][EncounterTypes::Water]))
for j in 0...e[1].length
enc = e[1][j]
next if !enc
f.write(sprintf("%s\r\n",EncounterTypes::Names[j]))
for k in 0...EncounterTypes::EnctypeChances[j].length
next if !enc[k]
encentry = enc[k]
if encentry[1]==encentry[2]
f.write(sprintf(" %s,%d\r\n",encentry[0],encentry[1]))
else
f.write(sprintf(" %s,%d,%d\r\n",encentry[0],encentry[1],encentry[2]))
end
end
end
end
}
Graphics.update
end
#===============================================================================
# Save trainer type data to PBS file
#===============================================================================
def write_trainer_types
File.open("PBS/trainertypes.txt", "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
GameData::TrainerType.each do |t|
f.write(sprintf("%d,%s,%s,%d,%s,%s,%s,%s,%s,%s\r\n",
t.id_number,
csvQuote(t.id.to_s),
csvQuote(t.real_name),
t.base_money,
csvQuote(t.battle_BGM),
csvQuote(t.victory_ME),
csvQuote(t.intro_ME),
["Male", "Female", "Mixed"][t.gender],
(t.skill_level == t.base_money) ? "" : t.skill_level.to_s,
csvQuote(t.skill_code)
))
end
}
Graphics.update
end
#===============================================================================
# Save individual trainer data to PBS file
#===============================================================================
def write_trainers
data = pbLoadTrainersData
return if !data
File.open("PBS/trainers.txt","wb") { |f|
add_PBS_header_to_file(f)
for trainer in data
trtypename = trainer[0].to_s
next if !trtypename
f.write("\#-------------------------------\r\n")
# Section
trainername = trainer[1] ? trainer[1].gsub(/,/,";") : "???"
if trainer[4]==0
f.write(sprintf("[%s,%s]\r\n",trtypename,trainername))
else
f.write(sprintf("[%s,%s,%d]\r\n",trtypename,trainername,trainer[4]))
end
# Trainer's items
if trainer[2] && trainer[2].length>0
itemstring = ""
for i in 0...trainer[2].length
itemstring.concat(",") if i > 0
itemstring.concat(trainer[2][i].to_s)
end
f.write(sprintf("Items = %s\r\n",itemstring)) if itemstring!=""
end
# Lose texts
if trainer[5] && trainer[5]!=""
f.write(sprintf("LoseText = %s\r\n",csvQuoteAlways(trainer[5])))
end
# Pokémon
for poke in trainer[3]
f.write(sprintf("Pokemon = %s,%d\r\n",poke[TrainerData::SPECIES],poke[TrainerData::LEVEL]))
if poke[TrainerData::NAME] && poke[TrainerData::NAME]!=""
f.write(sprintf(" Name = %s\r\n",poke[TrainerData::NAME]))
end
if poke[TrainerData::FORM]
f.write(sprintf(" Form = %d\r\n",poke[TrainerData::FORM]))
end
if poke[TrainerData::GENDER]
f.write(sprintf(" Gender = %s\r\n",(poke[TrainerData::GENDER]==1) ? "female" : "male"))
end
if poke[TrainerData::SHINY]
f.write(" Shiny = yes\r\n")
end
if poke[TrainerData::SHADOW]
f.write(" Shadow = yes\r\n")
end
if poke[TrainerData::MOVES] && poke[TrainerData::MOVES].length>0
movestring = ""
for i in 0...poke[TrainerData::MOVES].length
movename = GameData::Move.get(poke[TrainerData::MOVES][i]).id.to_s
next if !movename
movestring.concat(",") if i>0
movestring.concat(movename)
end
f.write(sprintf(" Moves = %s\r\n",movestring)) if movestring!=""
end
if poke[TrainerData::ABILITY]
f.write(sprintf(" Ability = %s\r\n",poke[TrainerData::ABILITY].to_s))
end
if poke[TrainerData::ITEM]
f.write(sprintf(" Item = %s\r\n",poke[TrainerData::ITEM].to_s))
end
if poke[TrainerData::NATURE]
nature = getConstantName(PBNatures,poke[TrainerData::NATURE]) rescue nil
f.write(sprintf(" Nature = %s\r\n",nature)) if nature
end
if poke[TrainerData::IV] && poke[TrainerData::IV].length>0
f.write(sprintf(" IV = %d",poke[TrainerData::IV][0]))
if poke[TrainerData::IV].length>1
for i in 1...6
f.write(sprintf(",%d",(i<poke[TrainerData::IV].length) ? poke[TrainerData::IV][i] : poke[TrainerData::IV][0]))
end
end
f.write("\r\n")
end
if poke[TrainerData::EV] && poke[TrainerData::EV].length>0
f.write(sprintf(" EV = %d",poke[TrainerData::EV][0]))
if poke[TrainerData::EV].length>1
for i in 1...6
f.write(sprintf(",%d",(i<poke[TrainerData::EV].length) ? poke[TrainerData::EV][i] : poke[TrainerData::EV][0]))
end
end
f.write("\r\n")
end
if poke[TrainerData::HAPPINESS]
f.write(sprintf(" Happiness = %d\r\n",poke[TrainerData::HAPPINESS]))
end
if poke[TrainerData::BALL]
f.write(sprintf(" Ball = %d\r\n",poke[TrainerData::BALL]))
end
end
end
}
Graphics.update
end
#===============================================================================
# Save trainer list data to PBS file
#===============================================================================
def write_trainer_lists
trainerlists = load_data("Data/trainer_lists.dat") rescue nil
return if !trainerlists
File.open("PBS/trainerlists.txt","wb") { |f|
add_PBS_header_to_file(f)
for tr in trainerlists
f.write("\#-------------------------------\r\n")
f.write(((tr[5]) ? "[DefaultTrainerList]" : "[TrainerList]")+"\r\n")
f.write("Trainers = "+tr[3]+"\r\n")
f.write("Pokemon = "+tr[4]+"\r\n")
f.write("Challenges = "+tr[2].join(",")+"\r\n") if !tr[5]
write_battle_tower_trainers(tr[0],"PBS/"+tr[3])
write_battle_tower_pokemon(tr[1],"PBS/"+tr[4])
end
}
Graphics.update
end
#===============================================================================
# Save Battle Tower trainer data to PBS file
#===============================================================================
def write_battle_tower_trainers(bttrainers, filename)
return if !bttrainers || !filename
btTrainersRequiredTypes = {
"Type" => [0, "e", nil], # Specifies a trainer
"Name" => [1, "s"],
"BeginSpeech" => [2, "s"],
"EndSpeechWin" => [3, "s"],
"EndSpeechLose" => [4, "s"],
"PokemonNos" => [5, "*u"]
}
File.open(filename,"wb") { |f|
add_PBS_header_to_file(f)
for i in 0...bttrainers.length
next if !bttrainers[i]
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%03d]\r\n",i))
for key in btTrainersRequiredTypes.keys
schema = btTrainersRequiredTypes[key]
record = bttrainers[i][schema[0]]
next if record==nil
f.write(sprintf("%s = ",key))
if key=="Type"
f.write(record.to_s)
elsif key=="PokemonNos"
f.write(record.join(",")) # pbWriteCsvRecord somehow won't work here
else
pbWriteCsvRecord(record,f,schema)
end
f.write(sprintf("\r\n"))
end
end
}
Graphics.update
end
#===============================================================================
# Save Battle Tower Pokémon data to PBS file
#===============================================================================
def write_battle_tower_pokemon(btpokemon,filename)
return if !btpokemon || !filename
species = {0=>""}
moves = {0=>""}
items = {0=>""}
natures = {}
File.open(filename,"wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
for i in 0...btpokemon.length
Graphics.update if i%500==0
pkmn = btpokemon[i]
f.write(pbFastInspect(pkmn,moves,species,items,natures))
f.write("\r\n")
end
}
Graphics.update
end
def pbFastInspect(pkmn,moves,species,items,natures)
c1 = (species[pkmn.species]) ? species[pkmn.species] : (species[pkmn.species] = GameData::Species.get(pkmn.species).species.to_s)
c2 = (items[pkmn.item]) ? items[pkmn.item] : (items[pkmn.item] = GameData::Item.get(pkmn.item).id.to_s)
c3 = (natures[pkmn.nature]) ? natures[pkmn.nature] :
(natures[pkmn.nature] = getConstantName(PBNatures,pkmn.nature))
evlist = ""
ev = pkmn.ev
evs = ["HP","ATK","DEF","SPD","SA","SD"]
for i in 0...ev
if ((ev&(1<<i))!=0)
evlist += "," if evlist.length>0
evlist += evs[i]
end
end
c4 = (moves[pkmn.move1]) ? moves[pkmn.move1] : (moves[pkmn.move1] = GameData::Move.get(pkmn.move1).id.to_s)
c5 = (moves[pkmn.move2]) ? moves[pkmn.move2] : (moves[pkmn.move2] = GameData::Move.get(pkmn.move2).id.to_s)
c6 = (moves[pkmn.move3]) ? moves[pkmn.move3] : (moves[pkmn.move3] = GameData::Move.get(pkmn.move3).id.to_s)
c7 = (moves[pkmn.move4]) ? moves[pkmn.move4] : (moves[pkmn.move4] = GameData::Move.get(pkmn.move4).id.to_s)
return "#{c1};#{c2};#{c3};#{evlist};#{c4},#{c5},#{c6},#{c7}"
end
#===============================================================================
# Save metadata data to PBS file
#===============================================================================
def write_metadata
File.open("PBS/metadata.txt", "wb") { |f|
add_PBS_header_to_file(f)
# Write global metadata
f.write("\#-------------------------------\r\n")
f.write("[000]\r\n")
metadata = GameData::Metadata.get
schema = GameData::Metadata::SCHEMA
keys = schema.keys.sort {|a, b| schema[a][0] <=> schema[b][0] }
for key in keys
record = metadata.property_from_string(key)
next if record.nil?
f.write(sprintf("%s = ", key))
pbWriteCsvRecord(record, f, schema[key])
f.write("\r\n")
end
# Write map metadata
map_infos = pbLoadRxData("Data/MapInfos")
schema = GameData::MapMetadata::SCHEMA
keys = schema.keys.sort {|a, b| schema[a][0] <=> schema[b][0] }
GameData::MapMetadata.each do |map_data|
f.write("\#-------------------------------\r\n")
f.write(sprintf("[%03d]\r\n", map_data.id))
if map_infos && map_infos[map_data.id]
f.write(sprintf("# %s\r\n", map_infos[map_data.id].name))
end
for key in keys
record = map_data.property_from_string(key)
next if record.nil?
f.write(sprintf("%s = ", key))
pbWriteCsvRecord(record, f, schema[key])
f.write("\r\n")
end
end
}
Graphics.update
end
#===============================================================================
# Save all data to PBS files
#===============================================================================
def write_all
write_town_map
write_connections
write_phone
write_types
write_abilities
write_moves
write_items
write_berry_plants
write_pokemon
write_pokemon_forms
write_shadow_movesets
write_regional_dexes
write_encounters
write_trainer_types
write_trainers
write_trainer_lists
write_metadata
end
end