Fixed and generalised PBS editors

This commit is contained in:
Maruno17
2022-11-28 20:28:48 +00:00
parent 7c39a56a43
commit b13c2ed2ed
8 changed files with 293 additions and 334 deletions

View File

@@ -38,6 +38,27 @@ module GameData
extend ClassMethodsSymbols
include InstanceMethods
def self.editor_properties
field_use_array = [_INTL("Can't use in field")]
self.schema["FieldUse"][2].each { |key, value| field_use_array[value] = key if !field_use_array[value] }
battle_use_array = [_INTL("Can't use in battle")]
self.schema["BattleUse"][2].each { |key, value| battle_use_array[value] = key if !battle_use_array[value] }
return [
["ID", ReadOnlyProperty, _INTL("ID of this item (used as a symbol like :XXX).")],
["Name", ItemNameProperty, _INTL("Name of this item as displayed by the game.")],
["NamePlural", ItemNameProperty, _INTL("Plural name of this item as displayed by the game.")],
["Pocket", PocketProperty, _INTL("Pocket in the Bag where this item is stored.")],
["Price", LimitProperty.new(Settings::MAX_MONEY), _INTL("Purchase price of this item.")],
["SellPrice", LimitProperty2.new(Settings::MAX_MONEY), _INTL("Sell price of this item. If blank, is half the purchase price.")],
["FieldUse", EnumProperty.new(field_use_array), _INTL("How this item can be used outside of battle.")],
["BattleUse", EnumProperty.new(battle_use_array), _INTL("How this item can be used within a battle.")],
["Flags", StringListProperty, _INTL("Words/phrases that can be used to group certain kinds of items.")],
["Consumable", BooleanProperty, _INTL("Whether this item is consumed after use.")],
["Move", MoveProperty, _INTL("Move taught by this HM, TM or TR.")],
["Description", StringProperty, _INTL("Description of this item.")]
]
end
def self.icon_filename(item)
return "Graphics/Items/back" if item.nil?
item_data = self.try_get(item)
@@ -198,6 +219,7 @@ module GameData
alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
def get_property_for_PBS(key)
key = "SectionName" if key == "ID"
ret = __orig__get_property_for_PBS(key)
case key
when "SellPrice"

View File

@@ -49,30 +49,6 @@ module GameData
extend ClassMethodsSymbols
include InstanceMethods
# @param species [Symbol, self, String]
# @param form [Integer]
# @return [self, nil]
def self.get_species_form(species, form)
return nil if !species || !form
validate species => [Symbol, self, String]
validate form => Integer
species = species.species if species.is_a?(self)
species = species.to_sym if species.is_a?(String)
trial = sprintf("%s_%d", species, form).to_sym
species_form = (DATA[trial].nil?) ? species : trial
return (DATA.has_key?(species_form)) ? DATA[species_form] : nil
end
def self.each_species
DATA.each_value { |species| yield species if species.form == 0 }
end
def self.species_count
ret = 0
self.each_species { |species| ret += 1 }
return ret
end
def self.schema(compiling_forms = false)
ret = {}
if compiling_forms
@@ -132,6 +108,68 @@ module GameData
return ret
end
def self.editor_properties
return [
["ID", ReadOnlyProperty, _INTL("The ID of the Pokémon.")],
["Name", LimitStringProperty.new(Pokemon::MAX_NAME_SIZE), _INTL("Name of the Pokémon.")],
["FormName", StringProperty, _INTL("Name of this form of the Pokémon.")],
["Types", TypesProperty, _INTL("The Pokémon's type(s).")],
["BaseStats", BaseStatsProperty, _INTL("Base stats of the Pokémon.")],
["GenderRatio", GameDataProperty.new(:GenderRatio), _INTL("Proportion of males to females for this species.")],
["GrowthRate", GameDataProperty.new(:GrowthRate), _INTL("Pokémon's growth rate.")],
["BaseExp", LimitProperty.new(9999), _INTL("Base experience earned when this species is defeated.")],
["EVs", EffortValuesProperty, _INTL("Effort Value points earned when this species is defeated.")],
["CatchRate", LimitProperty.new(255), _INTL("Catch rate of this species (0-255).")],
["Happiness", LimitProperty.new(255), _INTL("Base happiness of this species (0-255).")],
["Abilities", AbilitiesProperty.new, _INTL("Abilities which the Pokémon can have (max. 2).")],
["HiddenAbilities", AbilitiesProperty.new, _INTL("Secret abilities which the Pokémon can have.")],
["Moves", LevelUpMovesProperty, _INTL("Moves which the Pokémon learns while levelling up.")],
["TutorMoves", EggMovesProperty.new, _INTL("Moves which the Pokémon can be taught by TM/HM/Move Tutor.")],
["EggMoves", EggMovesProperty.new, _INTL("Moves which the Pokémon can learn via breeding.")],
["EggGroups", EggGroupsProperty.new, _INTL("Egg groups that the Pokémon belongs to for breeding purposes.")],
["HatchSteps", LimitProperty.new(99_999), _INTL("Number of steps until an egg of this species hatches.")],
["Incense", ItemProperty, _INTL("Item needed to be held by a parent to produce an egg of this species.")],
["Offspring", GameDataPoolProperty.new(:Species), _INTL("All possible species that an egg can be when breeding for an egg of this species (if blank, the egg can only be this species).")],
["Height", NonzeroLimitProperty.new(999), _INTL("Height of the Pokémon in 0.1 metres (e.g. 42 = 4.2m).")],
["Weight", NonzeroLimitProperty.new(9999), _INTL("Weight of the Pokémon in 0.1 kilograms (e.g. 42 = 4.2kg).")],
["Color", GameDataProperty.new(:BodyColor), _INTL("Pokémon's body color.")],
["Shape", GameDataProperty.new(:BodyShape), _INTL("Body shape of this species.")],
["Habitat", GameDataProperty.new(:Habitat), _INTL("The habitat of this species.")],
["Category", StringProperty, _INTL("Kind of Pokémon species.")],
["Pokedex", StringProperty, _INTL("Description of the Pokémon as displayed in the Pokédex.")],
["Generation", LimitProperty.new(99_999), _INTL("The number of the generation the Pokémon debuted in.")],
["Flags", StringListProperty, _INTL("Words/phrases that distinguish this species from others.")],
["WildItemCommon", GameDataPoolProperty.new(:Item), _INTL("Item(s) commonly held by wild Pokémon of this species.")],
["WildItemUncommon", GameDataPoolProperty.new(:Item), _INTL("Item(s) uncommonly held by wild Pokémon of this species.")],
["WildItemRare", GameDataPoolProperty.new(:Item), _INTL("Item(s) rarely held by wild Pokémon of this species.")],
["Evolutions", EvolutionsProperty.new, _INTL("Evolution paths of this species.")]
]
end
# @param species [Symbol, self, String]
# @param form [Integer]
# @return [self, nil]
def self.get_species_form(species, form)
return nil if !species || !form
validate species => [Symbol, self, String]
validate form => Integer
species = species.species if species.is_a?(self)
species = species.to_sym if species.is_a?(String)
trial = sprintf("%s_%d", species, form).to_sym
species_form = (DATA[trial].nil?) ? species : trial
return (DATA.has_key?(species_form)) ? DATA[species_form] : nil
end
def self.each_species
DATA.each_value { |species| yield species if species.form == 0 }
end
def self.species_count
ret = 0
self.each_species { |species| ret += 1 }
return ret
end
def initialize(hash)
@id = hash[:id]
@species = hash[:species] || @id
@@ -347,6 +385,7 @@ module GameData
alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
def get_property_for_PBS(key, writing_form = false)
key = "SectionName" if key == "ID"
ret = nil
if self.class.schema(writing_form).include?(key)
ret = self.send(self.class.schema(writing_form)[key][0])

View File

@@ -33,6 +33,22 @@ module GameData
extend ClassMethodsSymbols
include InstanceMethods
def self.editor_properties
gender_array = []
self.schema["Gender"][2].each { |key, value| gender_array[value] = key if !gender_array[value] }
return [
["ID", ReadOnlyProperty, _INTL("ID of this Trainer Type (used as a symbol like :XXX).")],
["Name", StringProperty, _INTL("Name of this Trainer Type as displayed by the game.")],
["Gender", EnumProperty.new(gender_array), _INTL("Gender of this Trainer Type.")],
["BaseMoney", LimitProperty.new(9999), _INTL("Player earns this much money times the highest level among the trainer's Pokémon.")],
["SkillLevel", LimitProperty2.new(9999), _INTL("Skill level of this Trainer Type.")],
["Flags", StringListProperty, _INTL("Words/phrases that can be used to make trainers of this type behave differently to others.")],
["IntroBGM", BGMProperty, _INTL("BGM played before battles against trainers of this type.")],
["BattleBGM", BGMProperty, _INTL("BGM played in battles against trainers of this type.")],
["VictoryBGM", BGMProperty, _INTL("BGM played when player wins battles against trainers of this type.")]
]
end
def self.check_file(tr_type, path, optional_suffix = "", suffix = "")
tr_type_data = self.try_get(tr_type)
return nil if tr_type_data.nil?
@@ -109,6 +125,7 @@ module GameData
alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
def get_property_for_PBS(key)
key = "SectionName" if key == "ID"
ret = __orig__get_property_for_PBS(key)
ret = nil if key == "SkillLevel" && ret == @base_money
return ret

View File

@@ -57,7 +57,7 @@ module GameData
end
def initialize(hash)
@id = hash[:id]
@id = hash[:id] || 0
@start_money = hash[:start_money] || 3000
@start_item_storage = hash[:start_item_storage] || []
@home = hash[:home]

View File

@@ -27,6 +27,7 @@ module GameData
def self.editor_properties
return [
["ID", ReadOnlyProperty, _INTL("ID number of this player.")],
["TrainerType", TrainerTypeProperty, _INTL("Trainer type of this player.")],
["WalkCharset", CharacterProperty, _INTL("Charset used while the player is still or walking.")],
["RunCharset", CharacterProperty, _INTL("Charset used while the player is running. Uses WalkCharset if undefined.")],
@@ -84,5 +85,11 @@ module GameData
def surf_fish_charset
return @surf_fish_charset || fish_charset
end
alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
def get_property_for_PBS(key)
key = "SectionName" if key == "ID"
return __orig__get_property_for_PBS(key)
end
end
end

View File

@@ -60,6 +60,7 @@ module GameData
def self.editor_properties
return [
["ID", ReadOnlyProperty, _INTL("ID number of this map.")],
["Name", StringProperty, _INTL("The name of the map, as seen by the player. Can be different to the map's name as seen in RMXP.")],
["Outdoor", BooleanProperty, _INTL("If true, this map is an outdoor map and will be tinted according to time of day.")],
["ShowArea", BooleanProperty, _INTL("If true, the game will display the map's name upon entry.")],
@@ -120,5 +121,11 @@ module GameData
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end
alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
def get_property_for_PBS(key)
key = "SectionName" if key == "ID"
return __orig__get_property_for_PBS(key)
end
end
end

View File

@@ -345,19 +345,7 @@ end
# Trainer type editor
#===============================================================================
def pbTrainerTypeEditor
gender_array = []
GameData::TrainerType.schema["Gender"][2].each { |key, value| gender_array[value] = key if !gender_array[value] }
trainer_type_properties = [
[_INTL("ID"), ReadOnlyProperty, _INTL("ID of this Trainer Type (used as a symbol like :XXX).")],
[_INTL("Name"), StringProperty, _INTL("Name of this Trainer Type as displayed by the game.")],
[_INTL("Gender"), EnumProperty.new(gender_array), _INTL("Gender of this Trainer Type.")],
[_INTL("BaseMoney"), LimitProperty.new(9999), _INTL("Player earns this much money times the highest level among the trainer's Pokémon.")],
[_INTL("SkillLevel"), LimitProperty.new(9999), _INTL("Skill level of this Trainer Type.")],
[_INTL("Flags"), StringListProperty, _INTL("Words/phrases that can be used to make trainers of this type behave differently to others.")],
[_INTL("IntroBGM"), BGMProperty, _INTL("BGM played before battles against trainers of this type.")],
[_INTL("BattleBGM"), BGMProperty, _INTL("BGM played in battles against trainers of this type.")],
[_INTL("VictoryBGM"), BGMProperty, _INTL("BGM played when player wins battles against trainers of this type.")]
]
properties = GameData::TrainerType.editor_properties
pbListScreenBlock(_INTL("Trainer Types"), TrainerTypeLister.new(0, true)) { |button, tr_type|
if tr_type
case button
@@ -371,31 +359,25 @@ def pbTrainerTypeEditor
when Input::USE
if tr_type.is_a?(Symbol)
t_data = GameData::TrainerType.get(tr_type)
data = [
t_data.id.to_s,
t_data.real_name,
t_data.gender,
t_data.base_money,
t_data.skill_level,
t_data.flags,
t_data.intro_BGM,
t_data.battle_BGM,
t_data.victory_BGM
]
if pbPropertyList(t_data.id.to_s, data, trainer_type_properties, true)
data = []
properties.each do |prop|
val = t_data.get_property_for_PBS(prop[0])
val = prop[1].defaultValue if val.nil? && prop[1].respond_to?(:defaultValue)
data.push(val)
end
if pbPropertyList(t_data.id.to_s, data, properties, true)
# Construct trainer type hash
type_hash = {
:id => t_data.id,
:name => data[1],
:gender => data[2],
:base_money => data[3],
:skill_level => data[4],
:flags => data[5],
:intro_BGM => data[6],
:battle_BGM => data[7],
:victory_BGM => data[8],
:pbs_file_suffix => t_data.pbs_file_suffix
}
schema = GameData::TrainerType.schema
type_hash = {}
properties.each_with_index do |prop, i|
case prop[0]
when "ID"
type_hash[schema["SectionName"][0]] = data[i]
else
type_hash[schema[prop[0]][0]] = data[i]
end
end
type_hash[:pbs_file_suffix] = t_data.pbs_file_suffix
# Add trainer type's data to records
GameData::TrainerType.register(type_hash)
GameData::TrainerType.save
@@ -741,21 +723,13 @@ def pbEditMetadata
end
if pbPropertyList(_INTL("Global Metadata"), data, properties, true)
# Construct metadata hash
metadata_hash = {
:id => 0,
:start_money => data[0],
:start_item_storage => data[1],
:home => data[2],
:real_storage_creator => data[3],
:wild_battle_BGM => data[4],
:trainer_battle_BGM => data[5],
:wild_victory_BGM => data[6],
:trainer_victory_BGM => data[7],
:wild_capture_ME => data[8],
:surf_BGM => data[9],
:bicycle_BGM => data[10],
:pbs_file_suffix => metadata.pbs_file_suffix
}
schema = GameData::Metadata.schema
metadata_hash = {}
properties.each_with_index do |prop, i|
metadata_hash[schema[prop[0]][0]] = data[i]
end
metadata_hash[:id] = 0
metadata_hash[:pbs_file_suffix] = metadata.pbs_file_suffix
# Add metadata's data to records
GameData::Metadata.register(metadata_hash)
GameData::Metadata.save
@@ -788,19 +762,17 @@ def pbEditPlayerMetadata(player_id = 1)
end
if pbPropertyList(_INTL("Player {1}", metadata.id), data, properties, true)
# Construct player metadata hash
metadata_hash = {
:id => player_id,
:trainer_type => data[0],
:walk_charset => data[1],
:run_charset => data[2],
:cycle_charset => data[3],
:surf_charset => data[4],
:dive_charset => data[5],
:fish_charset => data[6],
:surf_fish_charset => data[7],
:home => data[8],
:pbs_file_suffix => metadata.pbs_file_suffix
}
schema = GameData::PlayerMetadata.schema
metadata_hash = {}
properties.each_with_index do |prop, i|
case prop[0]
when "ID"
metadata_hash[schema["SectionName"][0]] = data[i]
else
metadata_hash[schema[prop[0]][0]] = data[i]
end
end
metadata_hash[:pbs_file_suffix] = metadata.pbs_file_suffix
# Add player metadata's data to records
GameData::PlayerMetadata.register(metadata_hash)
GameData::PlayerMetadata.save
@@ -835,32 +807,17 @@ def pbEditMapMetadata(map_id)
end
if pbPropertyList(map_name, data, properties, true)
# Construct map metadata hash
metadata_hash = {
:id => map_id,
:real_name => data[0],
:outdoor_map => data[1],
:announce_location => data[2],
:can_bicycle => data[3],
:always_bicycle => data[4],
:teleport_destination => data[5],
:weather => data[6],
:town_map_position => data[7],
:dive_map_id => data[8],
:dark_map => data[9],
:safari_map => data[10],
:snap_edges => data[11],
:random_dungeon => data[12],
:battle_background => data[13],
:wild_battle_BGM => data[14],
:trainer_battle_BGM => data[15],
:wild_victory_BGM => data[16],
:trainer_victory_BGM => data[17],
:wild_capture_ME => data[18],
:town_map_size => data[19],
:battle_environment => data[20],
:flags => data[21],
:pbs_file_suffix => metadata.pbs_file_suffix
}
schema = GameData::MapMetadata.schema
metadata_hash = {}
properties.each_with_index do |prop, i|
case prop[0]
when "ID"
metadata_hash[schema["SectionName"][0]] = data[i]
else
metadata_hash[schema[prop[0]][0]] = data[i]
end
end
metadata_hash[:pbs_file_suffix] = metadata.pbs_file_suffix
# Add map metadata's data to records
GameData::MapMetadata.register(metadata_hash)
GameData::MapMetadata.save
@@ -874,24 +831,7 @@ end
# Item editor
#===============================================================================
def pbItemEditor
field_use_array = [_INTL("Can't use in field")]
GameData::Item.schema["FieldUse"][2].each { |key, value| field_use_array[value] = key if !field_use_array[value] }
battle_use_array = [_INTL("Can't use in battle")]
GameData::Item.schema["BattleUse"][2].each { |key, value| battle_use_array[value] = key if !battle_use_array[value] }
item_properties = [
[_INTL("ID"), ReadOnlyProperty, _INTL("ID of this item (used as a symbol like :XXX).")],
[_INTL("Name"), ItemNameProperty, _INTL("Name of this item as displayed by the game.")],
[_INTL("NamePlural"), ItemNameProperty, _INTL("Plural name of this item as displayed by the game.")],
[_INTL("Pocket"), PocketProperty, _INTL("Pocket in the Bag where this item is stored.")],
[_INTL("Price"), LimitProperty.new(999_999), _INTL("Purchase price of this item.")],
[_INTL("SellPrice"), LimitProperty.new(999_999), _INTL("Sell price of this item. If blank, is half the purchase price.")],
[_INTL("Description"), StringProperty, _INTL("Description of this item")],
[_INTL("FieldUse"), EnumProperty.new(field_use_array), _INTL("How this item can be used outside of battle.")],
[_INTL("BattleUse"), EnumProperty.new(battle_use_array), _INTL("How this item can be used within a battle.")],
[_INTL("Consumable"), BooleanProperty, _INTL("Whether this item is consumed after use.")],
[_INTL("Flags"), StringListProperty, _INTL("Words/phrases that can be used to group certain kinds of items.")],
[_INTL("Move"), MoveProperty, _INTL("Move taught by this HM, TM or TR.")]
]
properties = GameData::Item.editor_properties
pbListScreenBlock(_INTL("Items"), ItemLister.new(0, true)) { |button, item|
if item
case button
@@ -905,37 +845,25 @@ def pbItemEditor
when Input::USE
if item.is_a?(Symbol)
itm = GameData::Item.get(item)
data = [
itm.id.to_s,
itm.real_name,
itm.real_name_plural,
itm.pocket,
itm.price,
itm.sell_price,
itm.real_description,
itm.field_use,
itm.battle_use,
itm.consumable,
itm.flags,
itm.move
]
if pbPropertyList(itm.id.to_s, data, item_properties, true)
data = []
properties.each do |prop|
val = itm.get_property_for_PBS(prop[0])
val = prop[1].defaultValue if val.nil? && prop[1].respond_to?(:defaultValue)
data.push(val)
end
if pbPropertyList(itm.id.to_s, data, properties, true)
# Construct item hash
item_hash = {
:id => itm.id,
:name => data[1],
:name_plural => data[2],
:pocket => data[3],
:price => data[4],
:sell_price => data[5],
:description => data[6],
:field_use => data[7],
:battle_use => data[8],
:consumable => data[9],
:flags => data[10],
:move => data[11],
:pbs_file_suffix => itm.pbs_file_suffix
}
schema = GameData::Item.schema
item_hash = {}
properties.each_with_index do |prop, i|
case prop[0]
when "ID"
item_hash[schema["SectionName"][0]] = data[i]
else
item_hash[schema[prop[0]][0]] = data[i]
end
end
item_hash[:pbs_file_suffix] = itm.pbs_file_suffix
# Add item's data to records
GameData::Item.register(item_hash)
GameData::Item.save
@@ -1009,47 +937,7 @@ end
# Pokémon species editor
#===============================================================================
def pbPokemonEditor
species_properties = [
[_INTL("ID"), ReadOnlyProperty, _INTL("The ID of the Pokémon.")],
[_INTL("Name"), LimitStringProperty.new(Pokemon::MAX_NAME_SIZE), _INTL("Name of the Pokémon.")],
[_INTL("FormName"), StringProperty, _INTL("Name of this form of the Pokémon.")],
[_INTL("Category"), StringProperty, _INTL("Kind of Pokémon species.")],
[_INTL("Pokédex"), StringProperty, _INTL("Description of the Pokémon as displayed in the Pokédex.")],
[_INTL("Type 1"), TypeProperty, _INTL("Pokémon's type. If same as Type 2, this Pokémon has a single type.")],
[_INTL("Type 2"), TypeProperty, _INTL("Pokémon's type. If same as Type 1, this Pokémon has a single type.")],
[_INTL("BaseStats"), BaseStatsProperty, _INTL("Base stats of the Pokémon.")],
[_INTL("EVs"), EffortValuesProperty, _INTL("Effort Value points earned when this species is defeated.")],
[_INTL("BaseExp"), LimitProperty.new(9999), _INTL("Base experience earned when this species is defeated.")],
[_INTL("GrowthRate"), GameDataProperty.new(:GrowthRate), _INTL("Pokémon's growth rate.")],
[_INTL("GenderRatio"), GameDataProperty.new(:GenderRatio), _INTL("Proportion of males to females for this species.")],
[_INTL("CatchRate"), LimitProperty.new(255), _INTL("Catch rate of this species (0-255).")],
[_INTL("Happiness"), LimitProperty.new(255), _INTL("Base happiness of this species (0-255).")],
[_INTL("Moves"), LevelUpMovesProperty, _INTL("Moves which the Pokémon learns while levelling up.")],
[_INTL("TutorMoves"), EggMovesProperty.new, _INTL("Moves which the Pokémon can be taught by TM/HM/Move Tutor.")],
[_INTL("EggMoves"), EggMovesProperty.new, _INTL("Moves which the Pokémon can learn via breeding.")],
[_INTL("Ability 1"), AbilityProperty, _INTL("One ability which the Pokémon can have.")],
[_INTL("Ability 2"), AbilityProperty, _INTL("Another ability which the Pokémon can have.")],
[_INTL("HiddenAbility 1"), AbilityProperty, _INTL("A secret ability which the Pokémon can have.")],
[_INTL("HiddenAbility 2"), AbilityProperty, _INTL("A secret ability which the Pokémon can have.")],
[_INTL("HiddenAbility 3"), AbilityProperty, _INTL("A secret ability which the Pokémon can have.")],
[_INTL("HiddenAbility 4"), AbilityProperty, _INTL("A secret ability which the Pokémon can have.")],
[_INTL("WildItemCommon"), GameDataPoolProperty.new(:Item), _INTL("Item(s) commonly held by wild Pokémon of this species.")],
[_INTL("WildItemUncommon"), GameDataPoolProperty.new(:Item), _INTL("Item(s) uncommonly held by wild Pokémon of this species.")],
[_INTL("WildItemRare"), GameDataPoolProperty.new(:Item), _INTL("Item(s) rarely held by wild Pokémon of this species.")],
[_INTL("EggGroup 1"), GameDataProperty.new(:EggGroup), _INTL("Compatibility group (egg group) for breeding purposes.")],
[_INTL("EggGroup 2"), GameDataProperty.new(:EggGroup), _INTL("Compatibility group (egg group) for breeding purposes.")],
[_INTL("HatchSteps"), LimitProperty.new(99_999), _INTL("Number of steps until an egg of this species hatches.")],
[_INTL("Incense"), ItemProperty, _INTL("Item needed to be held by a parent to produce an egg of this species.")],
[_INTL("Offspring"), GameDataPoolProperty.new(:Species), _INTL("All possible species that an egg can be when breeding for an egg of this species (if blank, the egg can only be this species).")],
[_INTL("Evolutions"), EvolutionsProperty.new, _INTL("Evolution paths of this species.")],
[_INTL("Height"), NonzeroLimitProperty.new(999), _INTL("Height of the Pokémon in 0.1 metres (e.g. 42 = 4.2m).")],
[_INTL("Weight"), NonzeroLimitProperty.new(9999), _INTL("Weight of the Pokémon in 0.1 kilograms (e.g. 42 = 4.2kg).")],
[_INTL("Color"), GameDataProperty.new(:BodyColor), _INTL("Pokémon's body color.")],
[_INTL("Shape"), GameDataProperty.new(:BodyShape), _INTL("Body shape of this species.")],
[_INTL("Habitat"), GameDataProperty.new(:Habitat), _INTL("The habitat of this species.")],
[_INTL("Generation"), LimitProperty.new(99_999), _INTL("The number of the generation the Pokémon debuted in.")],
[_INTL("Flags"), StringListProperty, _INTL("Words/phrases that distinguish this species from others.")]
]
properties = GameData::Species.editor_properties
pbListScreenBlock(_INTL("Pokémon species"), SpeciesLister.new(0, false)) { |button, species|
if species
case button
@@ -1063,99 +951,40 @@ def pbPokemonEditor
when Input::USE
if species.is_a?(Symbol)
spec = GameData::Species.get(species)
moves = []
spec.moves.each_with_index { |m, i| moves.push(m.clone.push(i)) }
moves.sort! { |a, b| (a[0] == b[0]) ? a[2] <=> b[2] : a[0] <=> b[0] }
moves.each { |m| m.pop }
evolutions = []
spec.evolutions.each { |e| evolutions.push(e.clone) if !e[3] }
data = [
spec.id.to_s,
spec.real_name,
spec.real_form_name,
spec.real_category,
spec.real_pokedex_entry,
spec.types[0],
spec.types[1],
spec.base_stats,
spec.evs,
spec.base_exp,
spec.growth_rate,
spec.gender_ratio,
spec.catch_rate,
spec.happiness,
moves,
spec.tutor_moves.clone,
spec.egg_moves.clone,
spec.abilities[0],
spec.abilities[1],
spec.hidden_abilities[0],
spec.hidden_abilities[1],
spec.hidden_abilities[2],
spec.hidden_abilities[3],
spec.wild_item_common.clone,
spec.wild_item_uncommon.clone,
spec.wild_item_rare.clone,
spec.egg_groups[0],
spec.egg_groups[1],
spec.hatch_steps,
spec.incense,
spec.offspring,
evolutions,
spec.height,
spec.weight,
spec.color,
spec.shape,
spec.habitat,
spec.generation,
spec.flags.clone
]
data = []
properties.each do |prop|
val = spec.get_property_for_PBS(prop[0])
val = prop[1].defaultValue if val.nil? && prop[1].respond_to?(:defaultValue)
val = (val * 10).round if ["Height", "Weight"].include?(prop[0])
data.push(val)
end
# Edit the properties
if pbPropertyList(spec.id.to_s, data, species_properties, true)
# Sanitise data
types = [data[5], data[6]].uniq.compact # Types
types = nil if types.empty?
egg_groups = [data[26], data[27]].uniq.compact # Egg groups
egg_groups = nil if egg_groups.empty?
abilities = [data[17], data[18]].uniq.compact # Abilities
hidden_abilities = [data[19], data[20], data[21], data[22]].uniq.compact # Hidden abilities
if pbPropertyList(spec.id.to_s, data, properties, true)
# Construct species hash
species_hash = {
:id => spec.id,
:name => data[1],
:form_name => data[2],
:category => data[3],
:pokedex_entry => data[4],
:types => types, # 5, 6
:base_stats => data[7],
:evs => data[8],
:base_exp => data[9],
:growth_rate => data[10],
:gender_ratio => data[11],
:catch_rate => data[12],
:happiness => data[13],
:moves => data[14],
:tutor_moves => data[15],
:egg_moves => data[16],
:abilities => abilities, # 17, 18
:hidden_abilities => hidden_abilities, # 19, 20, 21, 22
:wild_item_common => data[23],
:wild_item_uncommon => data[24],
:wild_item_rare => data[25],
:egg_groups => egg_groups, # 26, 27
:hatch_steps => data[28],
:incense => data[29],
:offspring => data[30],
:evolutions => data[31],
:height => data[32],
:weight => data[33],
:color => data[34],
:shape => data[35],
:habitat => data[36],
:generation => data[37],
:flags => data[38],
:pbs_file_suffix => spec.pbs_file_suffix
}
schema = GameData::Species.schema
species_hash = {}
properties.each_with_index do |prop, i|
data[i] = data[i].to_f / 10 if ["Height", "Weight"].include?(prop[0])
case prop[0]
when "ID"
species_hash[schema["SectionName"][0]] = data[i]
else
species_hash[schema[prop[0]][0]] = data[i]
end
end
species_hash[:pbs_file_suffix] = spec.pbs_file_suffix
# Sanitise data
Compiler.validate_compiled_pokemon(species_hash)
species_hash[:evolutions].each do |evo|
param_type = GameData::Evolution.get(evo[1]).parameter
if param_type.nil?
evo[2] = nil
elsif param_type == Integer
evo[2] = Compiler.csvPosInt!(evo[2])
elsif param_type != String
evo[2] = Compiler.csvEnumField!(evo[2], param_type, "Evolutions", species_hash[:id])
end
end
# Add species' data to records
GameData::Species.register(species_hash)
GameData::Species.save

View File

@@ -238,6 +238,7 @@ end
class StringListProperty
def self.set(_setting_name, old_setting)
old_setting = [] if !old_setting
real_cmds = []
real_cmds.push([_INTL("[ADD VALUE]"), -1])
old_setting.length.times do |i|
@@ -319,7 +320,7 @@ class StringListProperty
end
def self.format(value)
return value.join(",")
return (value) ? value.join(",") : ""
end
end
@@ -471,6 +472,37 @@ end
module TypesProperty
def self.set(_settingname, oldsetting)
ret = oldsetting.clone
index = 0
loop do
cmds = []
2.times { |i| cmds.push(_INTL("Type {1} : {2}", i, ret[i] || "-")) }
index = pbMessage(_INTL("Set the type(s) for this species."), cmds, -1)
break if index < 0
new_type = pbChooseTypeList(ret[index])
ret[index] = new_type if new_type
ret.uniq!
ret.compact!
end
return ret if ret != oldsetting.compact && pbConfirmMessage(_INTL("Apply changes?"))
return oldsetting
end
def self.defaultValue
return [:NORMAL]
end
def self.format(value)
types = value.compact
types.each_with_index { |type, i| types[i] = GameData::Type.try_get(types[i])&.real_name || "-" }
return types.join(",")
end
end
module MoveProperty
def self.set(_settingname, oldsetting)
ret = pbChooseMoveList(oldsetting || nil)
@@ -825,7 +857,7 @@ module MapProperty
end
def self.defaultValue
return 0
return nil
end
def self.format(value)
@@ -881,30 +913,25 @@ module BaseStatsProperty
next if s.pbs_order < 0
properties[s.pbs_order] = [_INTL("Base {1}", s.name), NonzeroLimitProperty.new(255),
_INTL("Base {1} stat of the Pokémon.", s.name)]
data[s.pbs_order] = oldsetting[s.id] || 10
data[s.pbs_order] = oldsetting[s.pbs_order] || 10
stat_ids[s.pbs_order] = s.id
end
if pbPropertyList(settingname, data, properties, true)
ret = {}
stat_ids.each_with_index { |s, i| ret[s] = data[i] || 10 }
ret = []
stat_ids.each_with_index { |s, i| ret[i] = data[i] || 10 }
oldsetting = ret
end
return oldsetting
end
def self.defaultValue
ret = {}
GameData::Stat.each_main { |s| ret[s.id] = 10 if s.pbs_order >= 0 }
ret = []
GameData::Stat.each_main { |s| ret[s.pbs_order] = 10 if s.pbs_order >= 0 }
return ret
end
def self.format(value)
array = []
GameData::Stat.each_main do |s|
next if s.pbs_order < 0
array[s.pbs_order] = value[s.id] || 0
end
return array.join(",")
return value.join(",")
end
end
@@ -920,30 +947,33 @@ module EffortValuesProperty
next if s.pbs_order < 0
properties[s.pbs_order] = [_INTL("{1} EVs", s.name), LimitProperty.new(255),
_INTL("Number of {1} Effort Value points gained from the Pokémon.", s.name)]
data[s.pbs_order] = oldsetting[s.id] || 0
data[s.pbs_order] = 0
oldsetting.each { |ev| data[s.pbs_order] = ev[1] if ev[0] == s.id }
stat_ids[s.pbs_order] = s.id
end
if pbPropertyList(settingname, data, properties, true)
ret = {}
stat_ids.each_with_index { |s, i| ret[s] = data[i] || 0 }
ret = []
stat_ids.each_with_index do |s, i|
index = GameData::Stat.get(s).pbs_order
ret.push([s, data[index]]) if data[index] > 0
end
oldsetting = ret
end
return oldsetting
end
def self.defaultValue
ret = {}
GameData::Stat.each_main { |s| ret[s.id] = 0 if s.pbs_order >= 0 }
return ret
return []
end
def self.format(value)
array = []
GameData::Stat.each_main do |s|
next if s.pbs_order < 0
array[s.pbs_order] = value[s.id] || 0
return "" if !value
ret = ""
value.each_with_index do |val, i|
ret += "," if i > 0
ret += GameData::Stat.get(val[0]).real_name_brief + "," + val[1].to_s
end
return array.join(",")
return ret
end
end
@@ -1093,6 +1123,22 @@ end
class EggGroupsProperty < GameDataPoolProperty
def initialize
super(:EggGroup, false, false)
end
end
class AbilitiesProperty < GameDataPoolProperty
def initialize
super(:Ability, false, false)
end
end
module LevelUpMovesProperty
def self.set(_settingname, oldsetting)
# Get all moves in move pool
@@ -1277,12 +1323,12 @@ class EvolutionsProperty
else
params = ChooseNumberParams.new
params.setRange(0, 65_535)
params.setDefaultValue(value) if value
params.setDefaultValue(value.to_i) if value
params.setCancelValue(-1)
ret = pbMessageChooseNumber(_INTL("Choose a parameter."), params)
ret = nil if ret < 0
end
return ret
return (ret) ? ret.to_s : nil
end
def set(_settingname, oldsetting)
@@ -1465,21 +1511,13 @@ class EvolutionsProperty
end
def format(value)
return "" if !value
ret = ""
value.length.times do |i|
ret << "," if i > 0
param = value[i][2]
evo_method_data = GameData::Evolution.get(value[i][1])
param_type = evo_method_data.parameter
if param_type.nil?
param = ""
elsif param_type.is_a?(Symbol) && !GameData.const_defined?(param_type)
param = getConstantName(param_type, param)
else
param = param.to_s
end
param = "" if !param
ret << sprintf("#{GameData::Species.get(value[i][0]).name},#{evo_method_data.real_name},#{param}")
ret << value[i][0].to_s + ","
ret << value[i][1].to_s + ","
ret << value[i][2].to_s if value[i][2] != nil
end
return ret
end