mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-08 05:34:58 +00:00
Generalised compiler and writer methods for trainers.txt
This commit is contained in:
@@ -749,132 +749,157 @@ module Compiler
|
|||||||
def compile_trainers(*paths)
|
def compile_trainers(*paths)
|
||||||
GameData::Trainer::DATA.clear
|
GameData::Trainer::DATA.clear
|
||||||
schema = GameData::Trainer.schema
|
schema = GameData::Trainer.schema
|
||||||
max_level = GameData::GrowthRate.max_level
|
sub_schema = GameData::Trainer.sub_schema
|
||||||
trainer_names = []
|
idx = 0
|
||||||
trainer_lose_texts = []
|
# Read from PBS file(s)
|
||||||
paths.each do |path|
|
paths.each do |path|
|
||||||
compile_pbs_file_message_start(path)
|
compile_pbs_file_message_start(path)
|
||||||
file_suffix = File.basename(path, ".txt")[GameData::Trainer::PBS_BASE_FILENAME.length + 1, path.length] || ""
|
file_suffix = File.basename(path, ".txt")[GameData::Trainer::PBS_BASE_FILENAME.length + 1, path.length] || ""
|
||||||
trainer_hash = nil
|
data_hash = nil
|
||||||
current_pkmn = nil
|
current_pkmn = nil
|
||||||
|
section_name = nil
|
||||||
|
section_line = nil
|
||||||
# Read each line of trainers.txt at a time and compile it as a trainer property
|
# Read each line of trainers.txt at a time and compile it as a trainer property
|
||||||
idx = 0
|
|
||||||
pbCompilerEachPreppedLine(path) { |line, line_no|
|
pbCompilerEachPreppedLine(path) { |line, line_no|
|
||||||
echo "." if idx % 50 == 0
|
echo "." if idx % 50 == 0
|
||||||
idx += 1
|
idx += 1
|
||||||
Graphics.update if idx % 250 == 0
|
Graphics.update if idx % 250 == 0
|
||||||
|
FileLineData.setSection(section_name, nil, section_line)
|
||||||
if line[/^\s*\[\s*(.+)\s*\]\s*$/]
|
if line[/^\s*\[\s*(.+)\s*\]\s*$/]
|
||||||
# New section [trainer_type, name] or [trainer_type, name, version]
|
# New section [trainer_type, name] or [trainer_type, name, version]
|
||||||
if trainer_hash
|
section_name = $~[1]
|
||||||
if !current_pkmn
|
section_line = line
|
||||||
raise _INTL("Started new trainer while previous trainer has no Pokémon.\r\n{1}", FileLineData.linereport)
|
if data_hash
|
||||||
end
|
validate_compiled_trainer(data_hash)
|
||||||
# Add trainer's data to records
|
GameData::Trainer.register(data_hash)
|
||||||
trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]]
|
|
||||||
GameData::Trainer.register(trainer_hash)
|
|
||||||
end
|
end
|
||||||
line_data = pbGetCsvRecord($~[1], line_no, [0, "esU", :TrainerType])
|
FileLineData.setSection(section_name, nil, section_line)
|
||||||
# Construct trainer hash
|
# Construct data hash
|
||||||
trainer_hash = {
|
data_hash = {
|
||||||
:trainer_type => line_data[0],
|
|
||||||
:name => line_data[1],
|
|
||||||
:version => line_data[2] || 0,
|
|
||||||
:pokemon => [],
|
|
||||||
:pbs_file_suffix => file_suffix
|
:pbs_file_suffix => file_suffix
|
||||||
}
|
}
|
||||||
|
data_hash[schema["SectionName"][0]] = pbGetCsvRecord(section_name.clone, line_no, schema["SectionName"])
|
||||||
|
data_hash[schema["Pokemon"][0]] = []
|
||||||
current_pkmn = nil
|
current_pkmn = nil
|
||||||
trainer_names.push(trainer_hash[:name])
|
|
||||||
elsif line[/^\s*(\w+)\s*=\s*(.*)$/]
|
elsif line[/^\s*(\w+)\s*=\s*(.*)$/]
|
||||||
# XXX=YYY lines
|
# XXX=YYY lines
|
||||||
if !trainer_hash
|
if !data_hash
|
||||||
raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport)
|
raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport)
|
||||||
end
|
end
|
||||||
property_name = $~[1]
|
key = $~[1]
|
||||||
line_schema = schema[property_name]
|
if schema[key] # Property of the trainer
|
||||||
next if !line_schema
|
property_value = pbGetCsvRecord($~[2], line_no, schema[key])
|
||||||
property_value = pbGetCsvRecord($~[2], line_no, line_schema)
|
if key == "Pokemon"
|
||||||
# Error checking in XXX=YYY lines
|
current_pkmn = {
|
||||||
case property_name
|
:species => property_value[0],
|
||||||
when "Pokemon"
|
:level => property_value[1]
|
||||||
if property_value[1] > max_level
|
}
|
||||||
raise _INTL("Bad level: {1} (must be 1-{2}).\r\n{3}", property_value[1], max_level, FileLineData.linereport)
|
data_hash[schema[key][0]].push(current_pkmn)
|
||||||
|
else
|
||||||
|
data_hash[schema[key][0]] = property_value
|
||||||
end
|
end
|
||||||
when "Name"
|
elsif sub_schema[key] # Property of a Pokémon
|
||||||
if property_value.length > Pokemon::MAX_NAME_SIZE
|
|
||||||
raise _INTL("Bad nickname: {1} (must be 1-{2} characters).\r\n{3}", property_value, Pokemon::MAX_NAME_SIZE, FileLineData.linereport)
|
|
||||||
end
|
|
||||||
when "Moves"
|
|
||||||
property_value.uniq!
|
|
||||||
when "IV"
|
|
||||||
property_value.each do |iv|
|
|
||||||
next if iv <= Pokemon::IV_STAT_LIMIT
|
|
||||||
raise _INTL("Bad IV: {1} (must be 0-{2}).\r\n{3}", iv, Pokemon::IV_STAT_LIMIT, FileLineData.linereport)
|
|
||||||
end
|
|
||||||
when "EV"
|
|
||||||
property_value.each do |ev|
|
|
||||||
next if ev <= Pokemon::EV_STAT_LIMIT
|
|
||||||
raise _INTL("Bad EV: {1} (must be 0-{2}).\r\n{3}", ev, Pokemon::EV_STAT_LIMIT, FileLineData.linereport)
|
|
||||||
end
|
|
||||||
ev_total = 0
|
|
||||||
GameData::Stat.each_main do |s|
|
|
||||||
next if s.pbs_order < 0
|
|
||||||
ev_total += (property_value[s.pbs_order] || property_value[0])
|
|
||||||
end
|
|
||||||
if ev_total > Pokemon::EV_LIMIT
|
|
||||||
raise _INTL("Total EVs are greater than allowed ({1}).\r\n{2}", Pokemon::EV_LIMIT, FileLineData.linereport)
|
|
||||||
end
|
|
||||||
when "Happiness"
|
|
||||||
if property_value > 255
|
|
||||||
raise _INTL("Bad happiness: {1} (must be 0-255).\r\n{2}", property_value, FileLineData.linereport)
|
|
||||||
end
|
|
||||||
when "Ball"
|
|
||||||
if !GameData::Item.get(property_value).is_poke_ball?
|
|
||||||
raise _INTL("Value {1} isn't a defined Poké Ball.\r\n{2}", property_value, FileLineData.linereport)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# Record XXX=YYY setting
|
|
||||||
case property_name
|
|
||||||
when "Items", "LoseText"
|
|
||||||
trainer_hash[line_schema[0]] = property_value
|
|
||||||
trainer_lose_texts.push(property_value) if property_name == "LoseText"
|
|
||||||
when "Pokemon"
|
|
||||||
current_pkmn = {
|
|
||||||
:species => property_value[0],
|
|
||||||
:level => property_value[1]
|
|
||||||
}
|
|
||||||
trainer_hash[line_schema[0]].push(current_pkmn)
|
|
||||||
else
|
|
||||||
if !current_pkmn
|
if !current_pkmn
|
||||||
raise _INTL("Pokémon hasn't been defined yet!\r\n{1}", FileLineData.linereport)
|
raise _INTL("Pokémon hasn't been defined yet!\r\n{1}", FileLineData.linereport)
|
||||||
end
|
end
|
||||||
case property_name
|
current_pkmn[sub_schema[key][0]] = pbGetCsvRecord($~[2], line_no, sub_schema[key])
|
||||||
when "IV", "EV"
|
|
||||||
value_hash = {}
|
|
||||||
GameData::Stat.each_main do |s|
|
|
||||||
next if s.pbs_order < 0
|
|
||||||
value_hash[s.id] = property_value[s.pbs_order] || property_value[0]
|
|
||||||
end
|
|
||||||
current_pkmn[line_schema[0]] = value_hash
|
|
||||||
else
|
|
||||||
current_pkmn[line_schema[0]] = property_value
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
# Add last trainer's data to records
|
# Add last trainer's data to records
|
||||||
if trainer_hash
|
if data_hash
|
||||||
if !current_pkmn
|
FileLineData.setSection(section_name, nil, section_line)
|
||||||
raise _INTL("End of file reached while last trainer has no Pokémon.\r\n{1}", FileLineData.linereport)
|
validate_compiled_trainer(data_hash)
|
||||||
end
|
GameData::Trainer.register(data_hash)
|
||||||
trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]]
|
|
||||||
GameData::Trainer.register(trainer_hash)
|
|
||||||
end
|
end
|
||||||
process_pbs_file_message_end
|
process_pbs_file_message_end
|
||||||
end
|
end
|
||||||
|
validate_all_compiled_trainers
|
||||||
# Save all data
|
# Save all data
|
||||||
GameData::Trainer.save
|
GameData::Trainer.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_compiled_trainer(hash)
|
||||||
|
# Split trainer type, name and version into their own values, generate compound ID from them
|
||||||
|
hash[:id][2] ||= 0
|
||||||
|
hash[:trainer_type] = hash[:id][0]
|
||||||
|
hash[:real_name] = hash[:id][1]
|
||||||
|
hash[:version] = hash[:id][2]
|
||||||
|
# Ensure the trainer has at least one Pokémon
|
||||||
|
if hash[:pokemon].empty?
|
||||||
|
raise _INTL("Trainer with ID {1} has no Pokémon.\r\n{2}", hash[:id], FileLineData.linereport)
|
||||||
|
end
|
||||||
|
max_level = GameData::GrowthRate.max_level
|
||||||
|
hash[:pokemon].each do |pkmn|
|
||||||
|
# Ensure valid level
|
||||||
|
if pkmn[:level] > max_level
|
||||||
|
raise _INTL("Invalid Pokémon level {1} (must be 1-{2}).\r\n{3}",
|
||||||
|
pkmn[:level], max_level, FileLineData.linereport)
|
||||||
|
end
|
||||||
|
# Ensure valid name length
|
||||||
|
if pkmn[:name] && pkmn[:name].length > Pokemon::MAX_NAME_SIZE
|
||||||
|
raise _INTL("Invalid Pokémon nickname: {1} (must be 1-{2} characters).\r\n{3}",
|
||||||
|
pkmn[:name], Pokemon::MAX_NAME_SIZE, FileLineData.linereport)
|
||||||
|
end
|
||||||
|
# Ensure no duplicate moves
|
||||||
|
pkmn[:moves].uniq! if pkmn[:moves]
|
||||||
|
# Ensure valid IVs, convert IVs to hash format
|
||||||
|
if pkmn[:iv]
|
||||||
|
iv_hash = {}
|
||||||
|
GameData::Stat.each_main do |s|
|
||||||
|
next if s.pbs_order < 0
|
||||||
|
iv_hash[s.id] = pkmn[:iv][s.pbs_order] || pkmn[:iv][0]
|
||||||
|
if iv_hash[s.id] > Pokemon::IV_STAT_LIMIT
|
||||||
|
raise _INTL("Invalid IV: {1} (must be 0-{2}).\r\n{3}",
|
||||||
|
iv_hash[s.id], Pokemon::IV_STAT_LIMIT, FileLineData.linereport)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
pkmn[:iv] = iv_hash
|
||||||
|
end
|
||||||
|
# Ensure valid EVs, convert EVs to hash format
|
||||||
|
if pkmn[:ev]
|
||||||
|
ev_hash = {}
|
||||||
|
ev_total = 0
|
||||||
|
GameData::Stat.each_main do |s|
|
||||||
|
next if s.pbs_order < 0
|
||||||
|
ev_hash[s.id] = pkmn[:ev][s.pbs_order] || pkmn[:ev][0]
|
||||||
|
ev_total += ev_hash[s.id]
|
||||||
|
if ev_hash[s.id] > Pokemon::EV_STAT_LIMIT
|
||||||
|
raise _INTL("Invalid EV: {1} (must be 0-{2}).\r\n{3}",
|
||||||
|
ev_hash[s.id], Pokemon::EV_STAT_LIMIT, FileLineData.linereport)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
pkmn[:ev] = ev_hash
|
||||||
|
if ev_total > Pokemon::EV_LIMIT
|
||||||
|
raise _INTL("Invalid EV set (must sum to {1} or less).\r\n{2}",
|
||||||
|
Pokemon::EV_LIMIT, FileLineData.linereport)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Ensure valid happiness
|
||||||
|
if pkmn[:happiness]
|
||||||
|
if pkmn[:happiness] > 255
|
||||||
|
raise _INTL("Bad happiness: {1} (must be 0-255).\r\n{2}", pkmn[:happiness], FileLineData.linereport)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Ensure valid Poké Ball
|
||||||
|
if pkmn[:poke_ball]
|
||||||
|
if !GameData::Item.get(pkmn[:poke_ball]).is_poke_ball?
|
||||||
|
raise _INTL("Value {1} isn't a defined Poké Ball.\r\n{2}", pkmn[:poke_ball], FileLineData.linereport)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_all_compiled_trainers
|
||||||
|
# Get trainer names and lose texts for translating
|
||||||
|
trainer_names = []
|
||||||
|
lose_texts = []
|
||||||
|
GameData::Trainer.each do |trainer|
|
||||||
|
trainer_names.push(trainer.real_name)
|
||||||
|
lose_texts.push(trainer.real_lose_text)
|
||||||
|
end
|
||||||
MessageTypes.setMessagesAsHash(MessageTypes::TrainerNames, trainer_names)
|
MessageTypes.setMessagesAsHash(MessageTypes::TrainerNames, trainer_names)
|
||||||
MessageTypes.setMessagesAsHash(MessageTypes::TrainerLoseText, trainer_lose_texts)
|
MessageTypes.setMessagesAsHash(MessageTypes::TrainerLoseText, lose_texts)
|
||||||
end
|
end
|
||||||
|
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
|
|||||||
@@ -452,50 +452,51 @@ module Compiler
|
|||||||
#=============================================================================
|
#=============================================================================
|
||||||
def write_trainers
|
def write_trainers
|
||||||
paths = get_all_PBS_file_paths(GameData::Trainer)
|
paths = get_all_PBS_file_paths(GameData::Trainer)
|
||||||
|
schema = GameData::Trainer.schema
|
||||||
|
sub_schema = GameData::Trainer.sub_schema
|
||||||
idx = 0
|
idx = 0
|
||||||
paths.each do |path|
|
paths.each do |path|
|
||||||
write_pbs_file_message_start(path[0])
|
write_pbs_file_message_start(path[0])
|
||||||
File.open(path[0], "wb") { |f|
|
File.open(path[0], "wb") { |f|
|
||||||
add_PBS_header_to_file(f)
|
add_PBS_header_to_file(f)
|
||||||
|
# Write each element in turn
|
||||||
GameData::Trainer.each do |element|
|
GameData::Trainer.each do |element|
|
||||||
next if element.pbs_file_suffix != path[1]
|
next if element.pbs_file_suffix != path[1]
|
||||||
echo "." if idx % 50 == 0
|
echo "." if idx % 50 == 0
|
||||||
Graphics.update if idx % 250 == 0
|
Graphics.update if idx % 250 == 0
|
||||||
idx += 1
|
idx += 1
|
||||||
f.write("\#-------------------------------\r\n")
|
f.write("\#-------------------------------\r\n")
|
||||||
if element.version > 0
|
if schema["SectionName"]
|
||||||
f.write(sprintf("[%s,%s,%d]\r\n", element.trainer_type, element.real_name, element.version))
|
f.write("[")
|
||||||
|
pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"])
|
||||||
|
f.write("]\r\n")
|
||||||
else
|
else
|
||||||
f.write(sprintf("[%s,%s]\r\n", element.trainer_type, element.real_name))
|
f.write("[#{element.id}]\r\n")
|
||||||
end
|
end
|
||||||
f.write(sprintf("Items = %s\r\n", element.items.join(","))) if element.items.length > 0
|
# Write each trainer property
|
||||||
if element.real_lose_text && !element.real_lose_text.empty?
|
schema.each_key do |key|
|
||||||
f.write(sprintf("LoseText = %s\r\n", element.real_lose_text))
|
next if key == "SectionName" || key == "Pokemon"
|
||||||
|
val = element.get_property_for_PBS(key)
|
||||||
|
next if val.nil?
|
||||||
|
f.write(sprintf("%s = ", key))
|
||||||
|
pbWriteCsvRecord(val, f, schema[key])
|
||||||
|
f.write("\r\n")
|
||||||
end
|
end
|
||||||
element.pokemon.each do |pkmn|
|
# Write each Pokémon in turn
|
||||||
f.write(sprintf("Pokemon = %s,%d\r\n", pkmn[:species], pkmn[:level]))
|
element.pokemon.each_with_index do |pkmn, i|
|
||||||
f.write(sprintf(" Name = %s\r\n", pkmn[:name])) if pkmn[:name] && !pkmn[:name].empty?
|
# Write species/level
|
||||||
f.write(sprintf(" Form = %d\r\n", pkmn[:form])) if pkmn[:form] && pkmn[:form] > 0
|
val = element.get_pokemon_property_for_PBS("Pokemon", i)
|
||||||
f.write(sprintf(" Gender = %s\r\n", (pkmn[:gender] == 1) ? "female" : "male")) if pkmn[:gender]
|
f.write("Pokemon = ")
|
||||||
f.write(" Shiny = yes\r\n") if pkmn[:shininess] && !pkmn[:super_shininess]
|
pbWriteCsvRecord(val, f, schema["Pokemon"])
|
||||||
f.write(" SuperShiny = yes\r\n") if pkmn[:super_shininess]
|
f.write("\r\n")
|
||||||
f.write(" Shadow = yes\r\n") if pkmn[:shadowness]
|
# Write other Pokémon properties
|
||||||
f.write(sprintf(" Moves = %s\r\n", pkmn[:moves].join(","))) if pkmn[:moves] && pkmn[:moves].length > 0
|
sub_schema.each_key do |key|
|
||||||
f.write(sprintf(" Ability = %s\r\n", pkmn[:ability])) if pkmn[:ability]
|
val = element.get_pokemon_property_for_PBS(key, i)
|
||||||
f.write(sprintf(" AbilityIndex = %d\r\n", pkmn[:ability_index])) if pkmn[:ability_index]
|
next if val.nil?
|
||||||
f.write(sprintf(" Item = %s\r\n", pkmn[:item])) if pkmn[:item]
|
f.write(sprintf(" %s = ", key))
|
||||||
f.write(sprintf(" Nature = %s\r\n", pkmn[:nature])) if pkmn[:nature]
|
pbWriteCsvRecord(val, f, sub_schema[key])
|
||||||
ivs_array = []
|
f.write("\r\n")
|
||||||
evs_array = []
|
|
||||||
GameData::Stat.each_main do |s|
|
|
||||||
next if s.pbs_order < 0
|
|
||||||
ivs_array[s.pbs_order] = pkmn[:iv][s.id] if pkmn[:iv]
|
|
||||||
evs_array[s.pbs_order] = pkmn[:ev][s.id] if pkmn[:ev]
|
|
||||||
end
|
end
|
||||||
f.write(sprintf(" IV = %s\r\n", ivs_array.join(","))) if pkmn[:iv]
|
|
||||||
f.write(sprintf(" EV = %s\r\n", evs_array.join(","))) if pkmn[:ev]
|
|
||||||
f.write(sprintf(" Happiness = %d\r\n", pkmn[:happiness])) if pkmn[:happiness]
|
|
||||||
f.write(sprintf(" Ball = %s\r\n", pkmn[:poke_ball])) if pkmn[:poke_ball]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user