diff --git a/Data/Scripts/010_Data/002_PBS data/006_Item.rb b/Data/Scripts/010_Data/002_PBS data/006_Item.rb index e5796a4b5..a077c8bdd 100644 --- a/Data/Scripts/010_Data/002_PBS data/006_Item.rb +++ b/Data/Scripts/010_Data/002_PBS data/006_Item.rb @@ -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" diff --git a/Data/Scripts/010_Data/002_PBS data/008_Species.rb b/Data/Scripts/010_Data/002_PBS data/008_Species.rb index 7777a3a23..2d5186d06 100644 --- a/Data/Scripts/010_Data/002_PBS data/008_Species.rb +++ b/Data/Scripts/010_Data/002_PBS data/008_Species.rb @@ -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]) diff --git a/Data/Scripts/010_Data/002_PBS data/014_TrainerType.rb b/Data/Scripts/010_Data/002_PBS data/014_TrainerType.rb index 6254e03d7..1bad519db 100644 --- a/Data/Scripts/010_Data/002_PBS data/014_TrainerType.rb +++ b/Data/Scripts/010_Data/002_PBS data/014_TrainerType.rb @@ -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 diff --git a/Data/Scripts/010_Data/002_PBS data/016_Metadata.rb b/Data/Scripts/010_Data/002_PBS data/016_Metadata.rb index b5afe9ea2..80adbb0a7 100644 --- a/Data/Scripts/010_Data/002_PBS data/016_Metadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/016_Metadata.rb @@ -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] diff --git a/Data/Scripts/010_Data/002_PBS data/017_PlayerMetadata.rb b/Data/Scripts/010_Data/002_PBS data/017_PlayerMetadata.rb index e6fa4df6d..0ad05398f 100644 --- a/Data/Scripts/010_Data/002_PBS data/017_PlayerMetadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/017_PlayerMetadata.rb @@ -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 diff --git a/Data/Scripts/010_Data/002_PBS data/018_MapMetadata.rb b/Data/Scripts/010_Data/002_PBS data/018_MapMetadata.rb index 96b3ebf28..06f57c58a 100644 --- a/Data/Scripts/010_Data/002_PBS data/018_MapMetadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/018_MapMetadata.rb @@ -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 diff --git a/Data/Scripts/020_Debug/001_Editor screens/001_EditorScreens.rb b/Data/Scripts/020_Debug/001_Editor screens/001_EditorScreens.rb index 5f3cbf0a5..cb5e42f35 100644 --- a/Data/Scripts/020_Debug/001_Editor screens/001_EditorScreens.rb +++ b/Data/Scripts/020_Debug/001_Editor screens/001_EditorScreens.rb @@ -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 diff --git a/Data/Scripts/020_Debug/002_Editor_DataTypes.rb b/Data/Scripts/020_Debug/002_Editor_DataTypes.rb index 36be2b9a0..b28203f69 100644 --- a/Data/Scripts/020_Debug/002_Editor_DataTypes.rb +++ b/Data/Scripts/020_Debug/002_Editor_DataTypes.rb @@ -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