From 5d439de87dee626f2c0eac89052e581b3f94d767 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Wed, 16 Nov 2022 22:03:12 +0000 Subject: [PATCH 01/12] Added compiler schema letter "m" which makes the value a symbol, refactored many PBS file compilers, removed support for old PBS formats/properties --- .../Scripts/010_Data/002_PBS data/002_Type.rb | 20 +- .../010_Data/002_PBS data/003_Ability.rb | 13 +- .../Scripts/010_Data/002_PBS data/004_Move.rb | 52 +- .../Scripts/010_Data/002_PBS data/005_Item.rb | 47 +- .../010_Data/002_PBS data/006_BerryPlant.rb | 1 + .../010_Data/002_PBS data/007_Species.rb | 110 +- .../002_PBS data/009_SpeciesMetrics.rb | 11 +- .../002_PBS data/010_ShadowPokemon.rb | 9 +- .../010_Data/002_PBS data/011_Ribbon.rb | 17 +- .../010_Data/002_PBS data/013_TrainerType.rb | 25 +- .../010_Data/002_PBS data/015_Metadata.rb | 27 +- .../002_PBS data/016_PlayerMetadata.rb | 19 +- .../010_Data/002_PBS data/017_MapMetadata.rb | 47 +- .../002_PBS data/018_DungeonTileset.rb | 6 +- .../002_PBS data/020_DungeonParameters.rb | 5 +- Data/Scripts/021_Compiler/001_Compiler.rb | 36 +- .../021_Compiler/002_Compiler_CompilePBS.rb | 1626 +++++++---------- .../021_Compiler/003_Compiler_WritePBS.rb | 9 +- 18 files changed, 887 insertions(+), 1193 deletions(-) diff --git a/Data/Scripts/010_Data/002_PBS data/002_Type.rb b/Data/Scripts/010_Data/002_PBS data/002_Type.rb index 7ee4bd041..5b2f620d7 100644 --- a/Data/Scripts/010_Data/002_PBS data/002_Type.rb +++ b/Data/Scripts/010_Data/002_PBS data/002_Type.rb @@ -14,15 +14,15 @@ module GameData DATA_FILENAME = "types.dat" SCHEMA = { - "Name" => [0, "s"], - "InternalName" => [0, "s"], - "IsSpecialType" => [0, "b"], - "IsPseudoType" => [0, "b"], - "Flags" => [0, "*s"], - "Weaknesses" => [0, "*s"], - "Resistances" => [0, "*s"], - "Immunities" => [0, "*s"], - "IconPosition" => [0, "u"] + "SectionName" => [:id, "m"], + "Name" => [:real_name, "s"], + "IsSpecialType" => [:special_type, "b"], + "IsPseudoType" => [:pseudo_type, "b"], + "Flags" => [:flags, "*s"], + "Weaknesses" => [:weaknesses, "*m"], + "Resistances" => [:resistances, "*m"], + "Immunities" => [:immunities, "*m"], + "IconPosition" => [:icon_position, "u"] } extend ClassMethodsSymbols @@ -30,7 +30,7 @@ module GameData def initialize(hash) @id = hash[:id] - @real_name = hash[:name] || "Unnamed" + @real_name = hash[:real_name] || "Unnamed" @special_type = hash[:special_type] || false @pseudo_type = hash[:pseudo_type] || false @flags = hash[:flags] || [] diff --git a/Data/Scripts/010_Data/002_PBS data/003_Ability.rb b/Data/Scripts/010_Data/002_PBS data/003_Ability.rb index a34535e30..182ea2deb 100644 --- a/Data/Scripts/010_Data/002_PBS data/003_Ability.rb +++ b/Data/Scripts/010_Data/002_PBS data/003_Ability.rb @@ -12,16 +12,17 @@ module GameData include InstanceMethods SCHEMA = { - "Name" => [:name, "s"], - "Description" => [:description, "q"], - "Flags" => [:flags, "*s"] + "SectionName" => [:id, "m"], + "Name" => [:real_name, "s"], + "Description" => [:real_description, "q"], + "Flags" => [:flags, "*s"] } def initialize(hash) @id = hash[:id] - @real_name = hash[:name] || "Unnamed" - @real_description = hash[:description] || "???" - @flags = hash[:flags] || [] + @real_name = hash[:real_name] || "Unnamed" + @real_description = hash[:real_description] || "???" + @flags = hash[:flags] || [] end # @return [String] the translated name of this ability diff --git a/Data/Scripts/010_Data/002_PBS data/004_Move.rb b/Data/Scripts/010_Data/002_PBS data/004_Move.rb index 2241b79ed..d28494deb 100644 --- a/Data/Scripts/010_Data/002_PBS data/004_Move.rb +++ b/Data/Scripts/010_Data/002_PBS data/004_Move.rb @@ -19,21 +19,19 @@ module GameData DATA_FILENAME = "moves.dat" SCHEMA = { - "Name" => [:name, "s"], - "Type" => [:type, "e", :Type], - "Category" => [:category, "e", ["Physical", "Special", "Status"]], - "Power" => [:base_damage, "u"], - "Accuracy" => [:accuracy, "u"], - "TotalPP" => [:total_pp, "u"], - "Target" => [:target, "e", :Target], - "Priority" => [:priority, "i"], - "FunctionCode" => [:function_code, "s"], - "Flags" => [:flags, "*s"], - "EffectChance" => [:effect_chance, "u"], - "Description" => [:description, "q"], - # All properties below here are old names for some properties above. - # They will be removed in v21. - "BaseDamage" => [:base_damage, "u"] + "SectionName" => [:id, "m"], + "Name" => [:real_name, "s"], + "Type" => [:type, "e", :Type], + "Category" => [:category, "e", ["Physical", "Special", "Status"]], + "Power" => [:base_damage, "u"], + "Accuracy" => [:accuracy, "u"], + "TotalPP" => [:total_pp, "u"], + "Target" => [:target, "e", :Target], + "Priority" => [:priority, "i"], + "FunctionCode" => [:function_code, "s"], + "Flags" => [:flags, "*s"], + "EffectChance" => [:effect_chance, "u"], + "Description" => [:real_description, "q"] } extend ClassMethodsSymbols @@ -42,19 +40,19 @@ module GameData def initialize(hash) convert_move_data(hash) @id = hash[:id] - @real_name = hash[:name] || "Unnamed" - @type = hash[:type] || :NONE - @category = hash[:category] || 2 - @base_damage = hash[:base_damage] || 0 - @accuracy = hash[:accuracy] || 100 - @total_pp = hash[:total_pp] || 5 - @target = hash[:target] || :None - @priority = hash[:priority] || 0 - @function_code = hash[:function_code] || "None" - @flags = hash[:flags] || [] + @real_name = hash[:real_name] || "Unnamed" + @type = hash[:type] || :NONE + @category = hash[:category] || 2 + @base_damage = hash[:base_damage] || 0 + @accuracy = hash[:accuracy] || 100 + @total_pp = hash[:total_pp] || 5 + @target = hash[:target] || :None + @priority = hash[:priority] || 0 + @function_code = hash[:function_code] || "None" + @flags = hash[:flags] || [] @flags = [@flags] if !@flags.is_a?(Array) - @effect_chance = hash[:effect_chance] || 0 - @real_description = hash[:description] || "???" + @effect_chance = hash[:effect_chance] || 0 + @real_description = hash[:real_description] || "???" end # @return [String] the translated name of this move diff --git a/Data/Scripts/010_Data/002_PBS data/005_Item.rb b/Data/Scripts/010_Data/002_PBS data/005_Item.rb index 0c377b323..6c2b74d71 100644 --- a/Data/Scripts/010_Data/002_PBS data/005_Item.rb +++ b/Data/Scripts/010_Data/002_PBS data/005_Item.rb @@ -9,27 +9,28 @@ module GameData attr_reader :real_description attr_reader :field_use attr_reader :battle_use - attr_reader :consumable attr_reader :flags + attr_reader :consumable attr_reader :move DATA = {} DATA_FILENAME = "items.dat" SCHEMA = { - "Name" => [:name, "s"], - "NamePlural" => [:name_plural, "s"], - "Pocket" => [:pocket, "v"], - "Price" => [:price, "u"], - "SellPrice" => [:sell_price, "u"], - "Description" => [:description, "q"], - "FieldUse" => [:field_use, "e", { "OnPokemon" => 1, "Direct" => 2, "TM" => 3, - "HM" => 4, "TR" => 5 }], - "BattleUse" => [:battle_use, "e", { "OnPokemon" => 1, "OnMove" => 2, "OnBattler" => 3, - "OnFoe" => 4, "Direct" => 5 }], - "Consumable" => [:consumable, "b"], - "Flags" => [:flags, "*s"], - "Move" => [:move, "e", :Move] + "SectionName" => [:id, "m"], + "Name" => [:real_name, "s"], + "NamePlural" => [:real_name_plural, "s"], + "Pocket" => [:pocket, "v"], + "Price" => [:price, "u"], + "SellPrice" => [:sell_price, "u"], + "Description" => [:real_description, "q"], + "FieldUse" => [:field_use, "e", { "OnPokemon" => 1, "Direct" => 2, "TM" => 3, + "HM" => 4, "TR" => 5 }], + "BattleUse" => [:battle_use, "e", { "OnPokemon" => 1, "OnMove" => 2, "OnBattler" => 3, + "OnFoe" => 4, "Direct" => 5 }], + "Flags" => [:flags, "*s"], + "Consumable" => [:consumable, "b"], + "Move" => [:move, "e", :Move] } extend ClassMethodsSymbols @@ -82,15 +83,15 @@ module GameData def initialize(hash) @id = hash[:id] - @real_name = hash[:name] || "Unnamed" - @real_name_plural = hash[:name_plural] || "Unnamed" - @pocket = hash[:pocket] || 1 - @price = hash[:price] || 0 - @sell_price = hash[:sell_price] || (@price / 2) - @real_description = hash[:description] || "???" - @field_use = hash[:field_use] || 0 - @battle_use = hash[:battle_use] || 0 - @flags = hash[:flags] || [] + @real_name = hash[:real_name] || "Unnamed" + @real_name_plural = hash[:real_name_plural] || "Unnamed" + @pocket = hash[:pocket] || 1 + @price = hash[:price] || 0 + @sell_price = hash[:sell_price] || (@price / 2) + @real_description = hash[:real_description] || "???" + @field_use = hash[:field_use] || 0 + @battle_use = hash[:battle_use] || 0 + @flags = hash[:flags] || [] @consumable = hash[:consumable] @consumable = !is_important? if @consumable.nil? @move = hash[:move] diff --git a/Data/Scripts/010_Data/002_PBS data/006_BerryPlant.rb b/Data/Scripts/010_Data/002_PBS data/006_BerryPlant.rb index 054e84be7..47490f4ad 100644 --- a/Data/Scripts/010_Data/002_PBS data/006_BerryPlant.rb +++ b/Data/Scripts/010_Data/002_PBS data/006_BerryPlant.rb @@ -9,6 +9,7 @@ module GameData DATA_FILENAME = "berry_plants.dat" SCHEMA = { + "SectionName" => [:id, "m"], "HoursPerStage" => [:hours_per_stage, "v"], "DryingPerHour" => [:drying_per_hour, "u"], "Yield" => [:yield, "uv"] diff --git a/Data/Scripts/010_Data/002_PBS data/007_Species.rb b/Data/Scripts/010_Data/002_PBS data/007_Species.rb index 97ff78e03..91f02de10 100644 --- a/Data/Scripts/010_Data/002_PBS data/007_Species.rb +++ b/Data/Scripts/010_Data/002_PBS data/007_Species.rb @@ -73,70 +73,50 @@ module GameData def self.schema(compiling_forms = false) ret = { - "FormName" => [0, "q"], - "Category" => [0, "s"], - "Pokedex" => [0, "q"], - "Types" => [0, "eE", :Type, :Type], - "BaseStats" => [0, "vvvvvv"], - "EVs" => [0, "*ev", :Stat], - "BaseExp" => [0, "v"], - "CatchRate" => [0, "u"], - "Happiness" => [0, "u"], - "Moves" => [0, "*ue", nil, :Move], - "TutorMoves" => [0, "*e", :Move], - "EggMoves" => [0, "*e", :Move], - "Abilities" => [0, "*e", :Ability], - "HiddenAbilities" => [0, "*e", :Ability], - "WildItemCommon" => [0, "*e", :Item], - "WildItemUncommon" => [0, "*e", :Item], - "WildItemRare" => [0, "*e", :Item], - "EggGroups" => [0, "*e", :EggGroup], - "HatchSteps" => [0, "v"], - "Height" => [0, "f"], - "Weight" => [0, "f"], - "Color" => [0, "e", :BodyColor], - "Shape" => [0, "e", :BodyShape], - "Habitat" => [0, "e", :Habitat], - "Generation" => [0, "i"], - "Flags" => [0, "*s"], - "BattlerPlayerX" => [0, "i"], - "BattlerPlayerY" => [0, "i"], - "BattlerEnemyX" => [0, "i"], - "BattlerEnemyY" => [0, "i"], - "BattlerAltitude" => [0, "i"], - "BattlerShadowX" => [0, "i"], - "BattlerShadowSize" => [0, "u"], - # All properties below here are old names for some properties above. - # They will be removed in v21. - "Type1" => [0, "e", :Type], - "Type2" => [0, "e", :Type], - "Rareness" => [0, "u"], - "Compatibility" => [0, "*e", :EggGroup], - "Kind" => [0, "s"], - "BaseEXP" => [0, "v"], - "EffortPoints" => [0, "*ev", :Stat], - "HiddenAbility" => [0, "*e", :Ability], - "StepsToHatch" => [0, "v"] + "FormName" => [:real_form_name, "q"], + "Category" => [:real_category, "s"], + "Pokedex" => [:real_pokedex_entry, "q"], + "Types" => [:types, "eE", :Type, :Type], + "BaseStats" => [:base_stats, "vvvvvv"], + "EVs" => [:evs, "*ev", :Stat], + "BaseExp" => [:base_exp, "v"], + "CatchRate" => [:catch_rate, "u"], + "Happiness" => [:happiness, "u"], + "Moves" => [:moves, "*ue", nil, :Move], + "TutorMoves" => [:tutor_moves, "*e", :Move], + "EggMoves" => [:egg_moves, "*e", :Move], + "Abilities" => [:abilities, "*e", :Ability], + "HiddenAbilities" => [:hidden_abilities, "*e", :Ability], + "WildItemCommon" => [:wild_item_common, "*e", :Item], + "WildItemUncommon" => [:wild_item_uncommon, "*e", :Item], + "WildItemRare" => [:wild_item_rare, "*e", :Item], + "EggGroups" => [:egg_groups, "*e", :EggGroup], + "HatchSteps" => [:hatch_steps, "v"], + "Height" => [:height, "f"], + "Weight" => [:weight, "f"], + "Color" => [:color, "e", :BodyColor], + "Shape" => [:shape, "e", :BodyShape], + "Habitat" => [:habitat, "e", :Habitat], + "Generation" => [:generation, "i"], + "Flags" => [:flags, "*s"] } if compiling_forms - ret["PokedexForm"] = [0, "u"] - ret["Offspring"] = [0, "*e", :Species] - ret["Evolutions"] = [0, "*ees", :Species, :Evolution, nil] - ret["MegaStone"] = [0, "e", :Item] - ret["MegaMove"] = [0, "e", :Move] - ret["UnmegaForm"] = [0, "u"] - ret["MegaMessage"] = [0, "u"] + ret["SectionName"] = [:id, "ev", :Species] + ret["PokedexForm"] = [:pokedex_form, "u"] + ret["Offspring"] = [:offspring, "*e", :Species] + ret["Evolutions"] = [:evolutions, "*ees", :Species, :Evolution, nil] + ret["MegaStone"] = [:mega_stone, "e", :Item] + ret["MegaMove"] = [:mega_move, "e", :Move] + ret["UnmegaForm"] = [:unmega_form, "u"] + ret["MegaMessage"] = [:mega_message, "u"] else - ret["InternalName"] = [0, "n"] - ret["Name"] = [0, "s"] - ret["GrowthRate"] = [0, "e", :GrowthRate] - ret["GenderRatio"] = [0, "e", :GenderRatio] - ret["Incense"] = [0, "e", :Item] - ret["Offspring"] = [0, "*s"] - ret["Evolutions"] = [0, "*ses", nil, :Evolution, nil] - # All properties below here are old names for some properties above. - # They will be removed in v21. - ret["GenderRate"] = [0, "e", :GenderRatio] + ret["SectionName"] = [:id, "m"] + ret["Name"] = [:real_name, "s"] + ret["GrowthRate"] = [:growth_rate, "e", :GrowthRate] + ret["GenderRatio"] = [:gender_ratio, "e", :GenderRatio] + ret["Incense"] = [:incense, "e", :Item] + ret["Offspring"] = [:offspring, "*s"] + ret["Evolutions"] = [:evolutions, "*ses", nil, :Evolution, nil] end return ret end @@ -145,10 +125,10 @@ module GameData @id = hash[:id] @species = hash[:species] || @id @form = hash[:form] || 0 - @real_name = hash[:name] || "Unnamed" - @real_form_name = hash[:form_name] - @real_category = hash[:category] || "???" - @real_pokedex_entry = hash[:pokedex_entry] || "???" + @real_name = hash[:real_name] || "Unnamed" + @real_form_name = hash[:real_form_name] + @real_category = hash[:real_category] || "???" + @real_pokedex_entry = hash[:real_pokedex_entry] || "???" @pokedex_form = hash[:pokedex_form] || @form @types = hash[:types] || [:NORMAL] @base_stats = hash[:base_stats] || {} diff --git a/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb b/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb index ae1b222c5..910f5a043 100644 --- a/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb +++ b/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb @@ -13,11 +13,12 @@ module GameData DATA_FILENAME = "species_metrics.dat" SCHEMA = { - "BackSprite" => [0, "ii"], - "FrontSprite" => [0, "ii"], - "FrontSpriteAltitude" => [0, "i"], - "ShadowX" => [0, "i"], - "ShadowSize" => [0, "u"] + "SectionName" => [:id, "eV", :Species], + "BackSprite" => [:back_sprite, "ii"], + "FrontSprite" => [:front_sprite, "ii"], + "FrontSpriteAltitude" => [:front_sprite_altitude, "i"], + "ShadowX" => [:shadow_x, "i"], + "ShadowSize" => [:shadow_size, "u"] } extend ClassMethodsSymbols diff --git a/Data/Scripts/010_Data/002_PBS data/010_ShadowPokemon.rb b/Data/Scripts/010_Data/002_PBS data/010_ShadowPokemon.rb index 828ed7667..8cfe28db9 100644 --- a/Data/Scripts/010_Data/002_PBS data/010_ShadowPokemon.rb +++ b/Data/Scripts/010_Data/002_PBS data/010_ShadowPokemon.rb @@ -9,9 +9,10 @@ module GameData DATA_FILENAME = "shadow_pokemon.dat" SCHEMA = { - "GaugeSize" => [:gauge_size, "v"], - "Moves" => [:moves, "*s"], # Not enumerated when compiled - "Flags" => [:flags, "*s"] + "SectionName" => [:id, "e", :Species], + "GaugeSize" => [:gauge_size, "v"], + "Moves" => [:moves, "*m"], # Not enumerated when compiled + "Flags" => [:flags, "*s"] } HEART_GAUGE_SIZE = 4000 # Default gauge size @@ -20,8 +21,8 @@ module GameData def initialize(hash) @id = hash[:id] - @moves = hash[:moves] || [] @gauge_size = hash[:gauge_size] || HEART_GAUGE_SIZE + @moves = hash[:moves] || [] @flags = hash[:flags] || [] end diff --git a/Data/Scripts/010_Data/002_PBS data/011_Ribbon.rb b/Data/Scripts/010_Data/002_PBS data/011_Ribbon.rb index e2344d217..d153c9cdc 100644 --- a/Data/Scripts/010_Data/002_PBS data/011_Ribbon.rb +++ b/Data/Scripts/010_Data/002_PBS data/011_Ribbon.rb @@ -10,10 +10,11 @@ module GameData DATA_FILENAME = "ribbons.dat" SCHEMA = { - "Name" => [:name, "s"], - "IconPosition" => [:icon_position, "u"], - "Description" => [:description, "q"], - "Flags" => [:flags, "*s"] + "SectionName" => [:id, "m"], + "Name" => [:real_name, "s"], + "IconPosition" => [:icon_position, "u"], + "Description" => [:real_description, "q"], + "Flags" => [:flags, "*s"] } extend ClassMethodsSymbols @@ -21,10 +22,10 @@ module GameData def initialize(hash) @id = hash[:id] - @real_name = hash[:name] || "Unnamed" - @icon_position = hash[:icon_position] || 0 - @real_description = hash[:description] || "???" - @flags = hash[:flags] || [] + @real_name = hash[:real_name] || "Unnamed" + @icon_position = hash[:icon_position] || 0 + @real_description = hash[:real_description] || "???" + @flags = hash[:flags] || [] end # @return [String] the translated name of this ribbon diff --git a/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb b/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb index 57991e127..1fec8d4e8 100644 --- a/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb +++ b/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb @@ -14,17 +14,18 @@ module GameData DATA_FILENAME = "trainer_types.dat" SCHEMA = { - "Name" => [:name, "s"], - "Gender" => [:gender, "e", { "Male" => 0, "male" => 0, "M" => 0, "m" => 0, "0" => 0, - "Female" => 1, "female" => 1, "F" => 1, "f" => 1, "1" => 1, - "Unknown" => 2, "unknown" => 2, "Other" => 2, "other" => 2, - "Mixed" => 2, "mixed" => 2, "X" => 2, "x" => 2, "2" => 2 }], - "BaseMoney" => [:base_money, "u"], - "SkillLevel" => [:skill_level, "u"], - "Flags" => [:flags, "*s"], - "IntroBGM" => [:intro_BGM, "s"], - "BattleBGM" => [:battle_BGM, "s"], - "VictoryBGM" => [:victory_BGM, "s"] + "SectionName" => [:id, "m"], + "Name" => [:real_name, "s"], + "Gender" => [:gender, "e", { "Male" => 0, "male" => 0, "M" => 0, "m" => 0, "0" => 0, + "Female" => 1, "female" => 1, "F" => 1, "f" => 1, "1" => 1, + "Unknown" => 2, "unknown" => 2, "Other" => 2, "other" => 2, + "Mixed" => 2, "mixed" => 2, "X" => 2, "x" => 2, "2" => 2 }], + "BaseMoney" => [:base_money, "u"], + "SkillLevel" => [:skill_level, "u"], + "Flags" => [:flags, "*s"], + "IntroBGM" => [:intro_BGM, "s"], + "BattleBGM" => [:battle_BGM, "s"], + "VictoryBGM" => [:victory_BGM, "s"] } extend ClassMethodsSymbols @@ -81,7 +82,7 @@ module GameData def initialize(hash) @id = hash[:id] - @real_name = hash[:name] || "Unnamed" + @real_name = hash[:real_name] || "Unnamed" @gender = hash[:gender] || 2 @base_money = hash[:base_money] || 30 @skill_level = hash[:skill_level] || @base_money diff --git a/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb b/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb index dae4443f4..a2869b1b2 100644 --- a/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb @@ -17,17 +17,18 @@ module GameData DATA_FILENAME = "metadata.dat" SCHEMA = { - "StartMoney" => [1, "u"], - "StartItemStorage" => [2, "*e", :Item], - "Home" => [3, "vuuu"], - "StorageCreator" => [4, "s"], - "WildBattleBGM" => [5, "s"], - "TrainerBattleBGM" => [6, "s"], - "WildVictoryBGM" => [7, "s"], - "TrainerVictoryBGM" => [8, "s"], - "WildCaptureME" => [9, "s"], - "SurfBGM" => [10, "s"], - "BicycleBGM" => [11, "s"] + "SectionName" => [:id, "u"], + "StartMoney" => [:start_money, "u"], + "StartItemStorage" => [:start_item_storage, "*e", :Item], + "Home" => [:home, "vuuu"], + "StorageCreator" => [:real_storage_creator, "s"], + "WildBattleBGM" => [:wild_battle_BGM, "s"], + "TrainerBattleBGM" => [:trainer_battle_BGM, "s"], + "WildVictoryBGM" => [:wild_victory_BGM, "s"], + "TrainerVictoryBGM" => [:trainer_victory_BGM, "s"], + "WildCaptureME" => [:wild_capture_ME, "s"], + "SurfBGM" => [:surf_BGM, "s"], + "BicycleBGM" => [:bicycle_BGM, "s"] } extend ClassMethodsIDNumbers @@ -55,10 +56,10 @@ module GameData def initialize(hash) @id = hash[:id] - @start_money = hash[:start_money] || 3000 + @start_money = hash[:start_money] || 3000 @start_item_storage = hash[:start_item_storage] || [] @home = hash[:home] - @real_storage_creator = hash[:storage_creator] + @real_storage_creator = hash[:real_storage_creator] @wild_battle_BGM = hash[:wild_battle_BGM] @trainer_battle_BGM = hash[:trainer_battle_BGM] @wild_victory_BGM = hash[:wild_victory_BGM] diff --git a/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb b/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb index 18c98a8cb..a050296e8 100644 --- a/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb @@ -9,15 +9,16 @@ module GameData DATA_FILENAME = "player_metadata.dat" SCHEMA = { - "TrainerType" => [1, "e", :TrainerType], - "WalkCharset" => [2, "s"], - "RunCharset" => [3, "s"], - "CycleCharset" => [4, "s"], - "SurfCharset" => [5, "s"], - "DiveCharset" => [6, "s"], - "FishCharset" => [7, "s"], - "SurfFishCharset" => [8, "s"], - "Home" => [9, "vuuu"] + "SectionName" => [:id, "u"], + "TrainerType" => [:trainer_type, "e", :TrainerType], + "WalkCharset" => [:walk_charset, "s"], + "RunCharset" => [:run_charset, "s"], + "CycleCharset" => [:cycle_charset, "s"], + "SurfCharset" => [:surf_charset, "s"], + "DiveCharset" => [:dive_charset, "s"], + "FishCharset" => [:fish_charset, "s"], + "SurfFishCharset" => [:surf_fish_charset, "s"], + "Home" => [:home, "vuuu"] } extend ClassMethodsIDNumbers diff --git a/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb b/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb index e485c86fc..bf6f9397d 100644 --- a/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb @@ -28,28 +28,29 @@ module GameData DATA_FILENAME = "map_metadata.dat" SCHEMA = { - "Name" => [1, "s"], - "Outdoor" => [2, "b"], - "ShowArea" => [3, "b"], - "Bicycle" => [4, "b"], - "BicycleAlways" => [5, "b"], - "HealingSpot" => [6, "vuu"], - "Weather" => [7, "eu", :Weather], - "MapPosition" => [8, "uuu"], - "DiveMap" => [9, "v"], - "DarkMap" => [10, "b"], - "SafariMap" => [11, "b"], - "SnapEdges" => [12, "b"], - "Dungeon" => [13, "b"], - "BattleBack" => [14, "s"], - "WildBattleBGM" => [15, "s"], - "TrainerBattleBGM" => [16, "s"], - "WildVictoryBGM" => [17, "s"], - "TrainerVictoryBGM" => [18, "s"], - "WildCaptureME" => [19, "s"], - "MapSize" => [20, "us"], - "Environment" => [21, "e", :Environment], - "Flags" => [22, "*s"] + "SectionName" => [:id, "u"], + "Name" => [:real_name, "s"], + "Outdoor" => [:outdoor_map, "b"], + "ShowArea" => [:announce_location, "b"], + "Bicycle" => [:can_bicycle, "b"], + "BicycleAlways" => [:always_bicycle, "b"], + "HealingSpot" => [:teleport_destination, "vuu"], + "Weather" => [:weather, "eu", :Weather], + "MapPosition" => [:town_map_position, "uuu"], + "DiveMap" => [:dive_map_id, "v"], + "DarkMap" => [:dark_map, "b"], + "SafariMap" => [:safari_map, "b"], + "SnapEdges" => [:snap_edges, "b"], + "Dungeon" => [:random_dungeon, "b"], + "BattleBack" => [:battle_background, "s"], + "WildBattleBGM" => [:wild_battle_BGM, "s"], + "TrainerBattleBGM" => [:trainer_battle_BGM, "s"], + "WildVictoryBGM" => [:wild_victory_BGM, "s"], + "TrainerVictoryBGM" => [:trainer_victory_BGM, "s"], + "WildCaptureME" => [:wild_capture_ME, "s"], + "MapSize" => [:town_map_size, "us"], + "Environment" => [:battle_environment, "e", :Environment], + "Flags" => [:flags, "*s"] } extend ClassMethodsIDNumbers @@ -84,7 +85,7 @@ module GameData def initialize(hash) @id = hash[:id] - @real_name = hash[:name] + @real_name = hash[:real_name] @outdoor_map = hash[:outdoor_map] @announce_location = hash[:announce_location] @can_bicycle = hash[:can_bicycle] diff --git a/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb b/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb index d9b10f8fd..b7c03e68b 100644 --- a/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb +++ b/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb @@ -15,8 +15,8 @@ module GameData DATA_FILENAME = "dungeon_tilesets.dat" SCHEMA = { - "Autotile" => [:autotile, "us"], - "Tile" => [:tile, "us"], + "Autotile" => [:autotile, "um"], + "Tile" => [:tile, "um"], "SnapToLargeGrid" => [:snap_to_large_grid, "b"], "LargeVoidTiles" => [:large_void_tiles, "b"], "LargeWallTiles" => [:large_wall_tiles, "b"], @@ -56,7 +56,7 @@ module GameData [hash[:autotile], hash[:tile]].each_with_index do |array, i| array.each do |tile_info| next if !tile_info - tile_type = tile_info[1].downcase.to_sym + tile_type = tile_info[1] if tile_type == :walls if @double_walls if @large_wall_tiles diff --git a/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb b/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb index 9c0b0281f..44285c04f 100644 --- a/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb +++ b/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb @@ -30,12 +30,13 @@ module GameData DATA_FILENAME = "dungeon_parameters.dat" SCHEMA = { + "SectionName" => [:id, "mV"], "DungeonSize" => [:dungeon_size, "vv"], "CellSize" => [:cell_size, "vv"], "MinRoomSize" => [:min_room_size, "vv"], "MaxRoomSize" => [:max_room_size, "vv"], "CorridorWidth" => [:corridor_width, "v"], - "ShiftCorridors" => [:shift_corridors, "b"], + "ShiftCorridors" => [:random_corridor_shift, "b"], "NodeLayout" => [:node_layout, "s"], "RoomLayout" => [:room_layout, "s"], "RoomChance" => [:room_chance, "v"], @@ -76,7 +77,7 @@ module GameData @room_max_width = (hash[:max_room_size]) ? hash[:max_room_size][0] : @cell_width - 1 @room_max_height = (hash[:max_room_size]) ? hash[:max_room_size][1] : @cell_height - 1 @corridor_width = hash[:corridor_width] || 2 - @random_corridor_shift = hash[:shift_corridors] + @random_corridor_shift = hash[:random_corridor_shift] @node_layout = hash[:node_layout]&.downcase&.to_sym || :full @room_layout = hash[:room_layout]&.downcase&.to_sym || :full @room_chance = hash[:room_chance] || 70 diff --git a/Data/Scripts/021_Compiler/001_Compiler.rb b/Data/Scripts/021_Compiler/001_Compiler.rb index ab2e6edc3..d0c1c4c3f 100644 --- a/Data/Scripts/021_Compiler/001_Compiler.rb +++ b/Data/Scripts/021_Compiler/001_Compiler.rb @@ -129,7 +129,10 @@ module Compiler yield lastsection, sectionname if havesection end - # Used for types.txt, pokemon.txt, battle_facility_lists.txt and Battle Tower trainers PBS files + # Used for types.txt, abilities.txt, moves.txt, items.txt, berry_plants.txt, + # pokemon.txt, pokemon_forms.txt, pokemon_metrics.txt, shadow_pokemon.txt, + # ribbons.txt, trainer_types.txt, battle_facility_lists.txt, Battle Tower + # trainers PBS files and dungeon_parameters.txt def pbEachFileSection(f) pbEachFileSectionEx(f) { |section, name| yield section, name if block_given? && name[/^.+$/] @@ -143,14 +146,7 @@ module Compiler } end - # Used for pokemon_forms.txt - def pbEachFileSectionPokemonForms(f) - pbEachFileSectionEx(f) { |section, name| - yield section, name if block_given? && name[/^\w+[-,\s]{1}\d+$/] - } - end - - # Used for phone.txt + # Unused def pbEachSection(f) lineno = 1 havesection = false @@ -193,7 +189,7 @@ module Compiler } end - # Used for many PBS files + # Used for town_map.txt and Battle Tower Pokémon PBS files def pbCompilerEachCommentedLine(filename) File.open(filename, "rb") { |f| FileLineData.file = filename @@ -226,7 +222,8 @@ module Compiler } end - # Used for map_connections.txt, abilities.txt, moves.txt, regional_dexes.txt + # Used for map_connections.txt, phone.txt, regional_dexes.txt, encounters.txt, + # trainers.txt and dungeon_tilesets.txt def pbCompilerEachPreppedLine(filename) File.open(filename, "rb") { |f| FileLineData.file = filename @@ -519,6 +516,21 @@ module Compiler subrecord.push(rec) rec = "" end + when "m" # Symbol + field = csvfield!(rec) + if !field[/^(?![0-9])\w+$/] + raise _INTL("Field '{1}' must contain only letters, digits, and\r\nunderscores and can't begin with a number.\r\n{2}", field, FileLineData.linereport) + end + subrecord.push(field.to_sym) + when "M" # Optional symbol + field = csvfield!(rec) + if nil_or_empty?(field) + subrecord.push(nil) + elsif !field[/^(?![0-9])\w+$/] + raise _INTL("Field '{1}' must contain only letters, digits, and\r\nunderscores and can't begin with a number.\r\n{2}", field, FileLineData.linereport) + else + subrecord.push(field.to_sym) + end when "e" # Enumerable subrecord.push(csvEnumField!(rec, schema[2 + i - start], "", FileLineData.linereport)) when "E" # Optional enumerable @@ -548,7 +560,7 @@ module Compiler break if repeat && nil_or_empty?(rec) break unless repeat end - return (schema[1].length == 1) ? record[0] : record + return (!repeat && schema[1].length == 1) ? record[0] : record end #============================================================================= diff --git a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb index 92c24bf0e..a8616ba76 100644 --- a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb +++ b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb @@ -174,7 +174,6 @@ module Compiler def compile_types(path = "PBS/types.txt") compile_pbs_file_message_start(path) GameData::Type::DATA.clear - type_names = [] # Read from PBS file File.open(path, "rb") { |f| FileLineData.file = path # For error reporting @@ -182,49 +181,52 @@ module Compiler # 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). schema = GameData::Type::SCHEMA - pbEachFileSection(f) { |contents, type_id| - contents["InternalName"] = type_id if !type_id[/^\d+/] - icon_pos = (type_id[/^\d+/]) ? type_id.to_i : nil + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} # Go through schema hash of compilable data and compile this section schema.each_key do |key| - FileLineData.setSection(type_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 ["Name", "InternalName"].include?(key) - raise _INTL("The entry {1} is required in {2} section {3}.", key, path, type_id) - end + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) next end + # Skip empty properties + next if contents[key].nil? # Compile value for key value = pbGetCsvRecord(contents[key], key, schema[key]) value = nil if value.is_a?(Array) && value.empty? - contents[key] = value - # Ensure weaknesses/resistances/immunities are in arrays and are symbols - if value && ["Weaknesses", "Resistances", "Immunities"].include?(key) - contents[key].map! { |x| x.to_sym } - contents[key].uniq! - end + data_hash[schema[key][0]] = value + end + # Validate and modify the compiled data + validate_compiled_type(data_hash) + if GameData::Type.exists?(data_hash[:id]) + raise _INTL("Type ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - # Construct type hash - type_hash = { - :id => contents["InternalName"].to_sym, - :name => contents["Name"], - :pseudo_type => contents["IsPseudoType"], - :special_type => contents["IsSpecialType"], - :flags => contents["Flags"], - :weaknesses => contents["Weaknesses"], - :resistances => contents["Resistances"], - :immunities => contents["Immunities"], - :icon_position => contents["IconPosition"] || icon_pos - } # Add type's data to records - GameData::Type.register(type_hash) - type_names.push(type_hash[:name]) + GameData::Type.register(data_hash) } } - # Ensure all weaknesses/resistances/immunities are valid types + validate_all_compiled_types + # Save all data + GameData::Type.save + process_pbs_file_message_end + end + + def validate_compiled_type(hash) + # Remove duplicate weaknesses/resistances/immunities + hash[:weaknesses].uniq! if hash[:weaknesses].is_a?(Array) + hash[:resistances].uniq! if hash[:resistances].is_a?(Array) + hash[:immunities].uniq! if hash[:immunities].is_a?(Array) + end + + def validate_all_compiled_types + type_names = [] GameData::Type.each do |type| + # Ensure all weaknesses/resistances/immunities are valid types type.weaknesses.each do |other_type| next if GameData::Type.exists?(other_type) raise _INTL("'{1}' is not a defined type ({2}, section {3}, Weaknesses).", other_type.to_s, path, type.id) @@ -237,11 +239,10 @@ module Compiler next if GameData::Type.exists?(other_type) raise _INTL("'{1}' is not a defined type ({2}, section {3}, Immunities).", other_type.to_s, path, type.id) end + # Get type names for translating + type_names.push(type.real_name) end - # Save all data - GameData::Type.save MessageTypes.setMessagesAsHash(MessageTypes::Types, type_names) - process_pbs_file_message_end end #============================================================================= @@ -250,69 +251,61 @@ module Compiler def compile_abilities(path = "PBS/abilities.txt") compile_pbs_file_message_start(path) GameData::Ability::DATA.clear - schema = GameData::Ability::SCHEMA - ability_names = [] - ability_descriptions = [] - ability_hash = nil - pbCompilerEachPreppedLine(path) { |line, line_no| - if line[/^\s*\[\s*(.+)\s*\]\s*$/] # New section [ability_id] - # Add previous ability's data to records - GameData::Ability.register(ability_hash) if ability_hash - # Parse ability ID - ability_id = $~[1].to_sym - if GameData::Ability.exists?(ability_id) - raise _INTL("Ability ID '{1}' is used twice.\r\n{2}", ability_id, FileLineData.linereport) + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = GameData::Ability::SCHEMA + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Construct ability hash - ability_hash = { - :id => ability_id - } - elsif line[/^\s*(\w+)\s*=\s*(.*)\s*$/] # XXX=YYY lines - if !ability_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) + # Validate and modify the compiled data + validate_compiled_ability(data_hash) + if GameData::Ability.exists?(data_hash[:id]) + raise _INTL("Ability ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - # Parse property and value - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - ability_hash[line_schema[0]] = property_value - case property_name - when "Name" - ability_names.push(ability_hash[:name]) - when "Description" - ability_descriptions.push(ability_hash[:description]) - end - else # Old format - # Add previous ability's data to records - GameData::Ability.register(ability_hash) if ability_hash - # Parse ability - line = pbGetCsvRecord(line, line_no, [0, "snss"]) - ability_id = line[1].to_sym - if GameData::Ability::DATA[ability_id] - raise _INTL("Ability ID '{1}' is used twice.\r\n{2}", ability_id, FileLineData.linereport) - end - # Construct ability hash - ability_hash = { - :id => ability_id, - :name => line[2], - :description => line[3] - } # Add ability's data to records - GameData::Ability.register(ability_hash) - ability_names.push(ability_hash[:name]) - ability_descriptions.push(ability_hash[:description]) - ability_hash = nil - end + GameData::Ability.register(data_hash) + } } - # Add last ability's data to records - GameData::Ability.register(ability_hash) if ability_hash + validate_all_compiled_abilities # Save all data GameData::Ability.save + process_pbs_file_message_end + end + + def validate_compiled_ability(hash) + end + + def validate_all_compiled_abilities + # Get abilty names/descriptions for translating + ability_names = [] + ability_descriptions = [] + GameData::Ability.each do |ability| + ability_names.push(ability.real_name) + ability_descriptions.push(ability.real_description) + end MessageTypes.setMessagesAsHash(MessageTypes::Abilities, ability_names) MessageTypes.setMessagesAsHash(MessageTypes::AbilityDescs, ability_descriptions) - process_pbs_file_message_end end #============================================================================= @@ -321,137 +314,69 @@ module Compiler def compile_moves(path = "PBS/moves.txt") compile_pbs_file_message_start(path) GameData::Move::DATA.clear - schema = GameData::Move::SCHEMA - move_names = [] - move_descriptions = [] - move_hash = nil - # Read each line of moves.txt at a time and compile it into an move - idx = 0 - pbCompilerEachPreppedLine(path) { |line, line_no| - echo "." if idx % 500 == 0 - idx += 1 - if line[/^\s*\[\s*(.+)\s*\]\s*$/] # New section [move_id] - # Add previous move's data to records - if move_hash - # Sanitise data - if (move_hash[:category] || 2) == 2 && (move_hash[:base_damage] || 0) != 0 - raise _INTL("Move {1} is defined as a Status move with a non-zero base damage.\r\n{2}", - move_hash[:name], FileLineData.linereport) - elsif (move_hash[:category] || 2) != 2 && (move_hash[:base_damage] || 0) == 0 - print _INTL("Warning: Move {1} was defined as Physical or Special but had a base damage of 0. Changing it to a Status move.\r\n{2}", - move_hash[:name], FileLineData.linereport) - move_hash[:category] = 2 + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = GameData::Move::SCHEMA + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next end - GameData::Move.register(move_hash) + # Skip empty properties + next if contents[key].nil? + # Compile value for key + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Parse move ID - move_id = $~[1].to_sym - if GameData::Move.exists?(move_id) - raise _INTL("Move ID '{1}' is used twice.\r\n{2}", move_id, FileLineData.linereport) + # Validate and modify the compiled data + validate_compiled_move(data_hash) + if GameData::Move.exists?(data_hash[:id]) + raise _INTL("Move ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - # Construct move hash - move_hash = { - :id => move_id - } - elsif line[/^\s*(\w+)\s*=\s*(.*)\s*$/] # XXX=YYY lines - if !move_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) - end - # Parse property and value - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - move_hash[line_schema[0]] = property_value - case property_name - when "Name" - move_names.push(move_hash[:name]) - when "Description" - move_descriptions.push(move_hash[:description]) - end - else # Old format - # Add previous move's data to records - if move_hash - # Sanitise data - if (move_hash[:category] || 2) == 2 && (move_hash[:base_damage] || 0) != 0 - raise _INTL("Move {1} is defined as a Status move with a non-zero base damage.\r\n{2}", - move_hash[:name], FileLineData.linereport) - elsif (move_hash[:category] || 2) != 2 && (move_hash[:base_damage] || 0) == 0 - print _INTL("Warning: Move {1} was defined as Physical or Special but had a base damage of 0. Changing it to a Status move.\r\n{2}", - move_hash[:name], FileLineData.linereport) - move_hash[:category] = 2 - end - GameData::Move.register(move_hash) - end - # Parse move - line = pbGetCsvRecord(line, line_no, - [0, "snssueeuuueiss", - nil, nil, nil, nil, nil, :Type, ["Physical", "Special", "Status"], - nil, nil, nil, :Target, nil, nil, nil]) - move_id = line[1].to_sym - if GameData::Move::DATA[move_id] - raise _INTL("Move ID '{1}' is used twice.\r\n{2}", move_id, FileLineData.linereport) - end - # Sanitise data - if line[6] == 2 && line[4] != 0 - raise _INTL("Move {1} is defined as a Status move with a non-zero base damage.\r\n{2}", line[2], FileLineData.linereport) - elsif line[6] != 2 && line[4] == 0 - print _INTL("Warning: Move {1} was defined as Physical or Special but had a base damage of 0. Changing it to a Status move.\r\n{2}", line[2], FileLineData.linereport) - line[6] = 2 - end - flags = [] - flags.push("Contact") if line[12][/a/] - flags.push("CanProtect") if line[12][/b/] - flags.push("CanMirrorMove") if line[12][/e/] - flags.push("ThawsUser") if line[12][/g/] - flags.push("HighCriticalHitRate") if line[12][/h/] - flags.push("Biting") if line[12][/i/] - flags.push("Punching") if line[12][/j/] - flags.push("Sound") if line[12][/k/] - flags.push("Powder") if line[12][/l/] - flags.push("Pulse") if line[12][/m/] - flags.push("Bomb") if line[12][/n/] - flags.push("Dance") if line[12][/o/] - # Construct move hash - move_hash = { - :id => move_id, - :name => line[2], - :function_code => line[3], - :base_damage => line[4], - :type => line[5], - :category => line[6], - :accuracy => line[7], - :total_pp => line[8], - :effect_chance => line[9], - :target => line[10], - :priority => line[11], - :flags => flags, - :description => line[13] - } # Add move's data to records - GameData::Move.register(move_hash) - move_names.push(move_hash[:name]) - move_descriptions.push(move_hash[:description]) - move_hash = nil - end + GameData::Move.register(data_hash) + } } - # Add last move's data to records - if move_hash - # Sanitise data - if (move_hash[:category] || 2) == 2 && (move_hash[:base_damage] || 0) != 0 - raise _INTL("Move {1} is defined as a Status move with a non-zero base damage.\r\n{2}", line[2], FileLineData.linereport) - elsif (move_hash[:category] || 2) != 2 && (move_hash[:base_damage] || 0) == 0 - print _INTL("Warning: Move {1} was defined as Physical or Special but had a base damage of 0. Changing it to a Status move.\r\n{2}", line[2], FileLineData.linereport) - move_hash[:category] = 2 - end - GameData::Move.register(move_hash) - end + validate_all_compiled_moves # Save all data GameData::Move.save + process_pbs_file_message_end + end + + def validate_compiled_move(hash) + if (hash[:category] || 2) == 2 && (hash[:base_damage] || 0) != 0 + raise _INTL("Move {1} is defined as a Status move with a non-zero base damage.\r\n{2}", + hash[:name], FileLineData.linereport) + elsif (hash[:category] || 2) != 2 && (hash[:base_damage] || 0) == 0 + print _INTL("Warning: Move {1} is defined as Physical or Special but has a base damage of 0. Changing it to a Status move.\r\n{2}", + hash[:name], FileLineData.linereport) + hash[:category] = 2 + end + end + + def validate_all_compiled_moves + # Get move names/descriptions for translating + move_names = [] + move_descriptions = [] + GameData::Move.each do |move| + move_names.push(move.real_name) + move_descriptions.push(move.real_description) + end MessageTypes.setMessagesAsHash(MessageTypes::Moves, move_names) MessageTypes.setMessagesAsHash(MessageTypes::MoveDescriptions, move_descriptions) - process_pbs_file_message_end end #============================================================================= @@ -460,94 +385,64 @@ module Compiler def compile_items(path = "PBS/items.txt") compile_pbs_file_message_start(path) GameData::Item::DATA.clear - schema = GameData::Item::SCHEMA - item_names = [] - item_names_plural = [] - item_descriptions = [] - item_hash = nil - # Read each line of items.txt at a time and compile it into an item - idx = 0 - pbCompilerEachPreppedLine(path) { |line, line_no| - echo "." if idx % 250 == 0 - idx += 1 - if line[/^\s*\[\s*(.+)\s*\]\s*$/] # New section [item_id] - # Add previous item's data to records - GameData::Item.register(item_hash) if item_hash - # Parse item ID - item_id = $~[1].to_sym - if GameData::Item.exists?(item_id) - raise _INTL("Item ID '{1}' is used twice.\r\n{2}", item_id, FileLineData.linereport) + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = GameData::Item::SCHEMA + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Construct item hash - item_hash = { - :id => item_id - } - elsif line[/^\s*(\w+)\s*=\s*(.*)\s*$/] # XXX=YYY lines - if !item_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) + # Validate and modify the compiled data + validate_compiled_item(data_hash) + if GameData::Item.exists?(data_hash[:id]) + raise _INTL("Item ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - # Parse property and value - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - item_hash[line_schema[0]] = property_value - case property_name - when "Name" - item_names.push(item_hash[:name]) - when "NamePlural" - item_names_plural.push(item_hash[:name_plural]) - when "Description" - item_descriptions.push(item_hash[:description]) - end - else # Old format - # Add previous item's data to records - GameData::Item.register(item_hash) if item_hash - # Parse item - line = pbGetCsvRecord(line, line_no, - [0, "snssvusuuUE", nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, :Move]) - item_id = line[1].to_sym - if GameData::Item.exists?(item_id) - raise _INTL("Item ID '{1}' is used twice.\r\n{2}", item_id, FileLineData.linereport) - end - consumable = !([3, 4, 5].include?(line[7]) || line[8] >= 6) - line[7] = 1 if line[7] == 5 - line[7] = 5 if line[7] == 6 - line[8] -= 5 if line[8] > 5 - flags = [] - flags.push(line[9]) if !nil_or_empty?(line[9]) - # Construct item hash - item_hash = { - :id => item_id, - :name => line[2], - :name_plural => line[3], - :pocket => line[4], - :price => line[5], - :description => line[6], - :field_use => line[7], - :battle_use => line[8], - :consumable => consumable, - :flags => flags, - :move => line[10] - } # Add item's data to records - GameData::Item.register(item_hash) - item_names.push(item_hash[:name]) - item_names_plural.push(item_hash[:name_plural]) - item_descriptions.push(item_hash[:description]) - item_hash = nil - end + GameData::Item.register(data_hash) + } } - # Add last item's data to records - GameData::Item.register(item_hash) if item_hash + validate_all_compiled_items # Save all data GameData::Item.save + process_pbs_file_message_end + end + + def validate_compiled_item(hash) + end + + def validate_all_compiled_items + # Get item names/descriptions for translating + item_names = [] + item_names_plural = [] + item_descriptions = [] + GameData::Item.each do |item| + item_names.push(item.real_name) + item_names_plural.push(item.real_name_plural) + item_descriptions.push(item.real_description) + end MessageTypes.setMessagesAsHash(MessageTypes::Items, item_names) MessageTypes.setMessagesAsHash(MessageTypes::ItemPlurals, item_names_plural) MessageTypes.setMessagesAsHash(MessageTypes::ItemDescriptions, item_descriptions) - process_pbs_file_message_end end #============================================================================= @@ -556,77 +451,60 @@ module Compiler def compile_berry_plants(path = "PBS/berry_plants.txt") compile_pbs_file_message_start(path) GameData::BerryPlant::DATA.clear - schema = GameData::BerryPlant::SCHEMA - item_hash = nil - old_format = nil - # Read each line of berry_plants.txt at a time and compile it into a berry plant - idx = 0 - pbCompilerEachPreppedLine(path) { |line, line_no| - echo "." if idx % 250 == 0 - idx += 1 - if line[/^\s*\[\s*(.+)\s*\]\s*$/] # New section [item_id] - old_format = false if old_format.nil? - if old_format - raise _INTL("Can't mix old and new formats.\r\n{1}", FileLineData.linereport) - end - # Add previous berry plant's data to records - GameData::BerryPlant.register(item_hash) if item_hash - # Parse item ID - item_id = $~[1].to_sym - if GameData::BerryPlant.exists?(item_id) - raise _INTL("Item ID '{1}' is used twice.\r\n{2}", item_id, FileLineData.linereport) - end - # Construct item hash - item_hash = { - :id => item_id - } - elsif line[/^\s*(\w+)\s*=\s*(.*)\s*$/] # XXX=YYY lines - old_format = true if old_format.nil? - if old_format - key = $1 - value = $2 - item_id = parseItem(key) - line = pbGetCsvRecord(value, line_no, [0, "vuuv"]) - # Construct berry plant hash - berry_plant_hash = { - :id => item_id, - :hours_per_stage => line[0], - :drying_per_hour => line[1], - :yield => [line[2], line[3]] - } - # Add berry plant's data to records - GameData::BerryPlant.register(berry_plant_hash) - else - if !item_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = GameData::BerryPlant::SCHEMA + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next end - # Parse property and value - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - item_hash[line_schema[0]] = property_value + # Skip empty properties + next if contents[key].nil? + # Compile value for key + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - end + # Validate and modify the compiled data + validate_compiled_berry_plant(data_hash) + if GameData::BerryPlant.exists?(data_hash[:id]) + raise _INTL("Berry plant ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + # Add berry plant's data to records + GameData::BerryPlant.register(data_hash) + } } - # Add last berry plant's data to records - GameData::BerryPlant.register(item_hash) if item_hash + validate_all_compiled_berry_plants # Save all data GameData::BerryPlant.save process_pbs_file_message_end end + def validate_compiled_berry_plant(hash) + end + + def validate_all_compiled_berry_plants + end + #============================================================================= # Compile Pokémon data #============================================================================= def compile_pokemon(path = "PBS/pokemon.txt") compile_pbs_file_message_start(path) GameData::Species::DATA.clear - species_names = [] - species_form_names = [] - species_categories = [] - species_pokedex_entries = [] # Read from PBS file File.open(path, "rb") { |f| FileLineData.file = path # For error reporting @@ -635,131 +513,71 @@ module Compiler # the keys are the XXX and the values are the YYY (as unprocessed strings). schema = GameData::Species.schema idx = 0 - pbEachFileSection(f) { |contents, species_id| + pbEachFileSection(f) { |contents, section_name| echo "." if idx % 50 == 0 - idx += 1 Graphics.update if idx % 250 == 0 - FileLineData.setSection(species_id, "header", nil) # For error reporting - contents["InternalName"] = species_id if !species_id[/^\d+/] - # Ensure all required properties have been defined, and raise an error - # if not - schema.each_key do |key| - next if !nil_or_empty?(contents[key]) - if ["Name", "InternalName"].include?(key) - raise _INTL("The entry {1} is required in {2} section {3}.", key, path, species_id) - end - contents[key] = nil - end - # Raise an error if a species ID is used twice - if GameData::Species::DATA[contents["InternalName"].to_sym] - raise _INTL("Species ID '{1}' is used twice.\r\n{2}", contents["InternalName"], FileLineData.linereport) - end + idx += 1 + data_hash = {:id => section_name.to_sym} # Go through schema hash of compilable data and compile this section schema.each_key do |key| - next if nil_or_empty?(contents[key]) - FileLineData.setSection(species_id, key, contents[key]) # For error reporting + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? # Compile value for key - if ["EVs", "EffortPoints"].include?(key) && contents[key].split(",")[0].numeric? - value = pbGetCsvRecord(contents[key], key, [0, "uuuuuu"]) # Old format - else - value = pbGetCsvRecord(contents[key], key, schema[key]) - end + value = pbGetCsvRecord(contents[key], key, schema[key]) value = nil if value.is_a?(Array) && value.empty? - contents[key] = value - # Sanitise data - case key - when "BaseStats" - value_hash = {} - GameData::Stat.each_main do |s| - value_hash[s.id] = value[s.pbs_order] if s.pbs_order >= 0 - end - contents[key] = value_hash - when "EVs", "EffortPoints" - if value[0].is_a?(Array) # New format - value_hash = {} - value.each { |val| value_hash[val[0]] = val[1] } - GameData::Stat.each_main { |s| value_hash[s.id] ||= 0 } - contents[key] = value_hash - else # Old format - value_hash = {} - GameData::Stat.each_main do |s| - value_hash[s.id] = value[s.pbs_order] if s.pbs_order >= 0 - end - contents[key] = value_hash - end - when "Height", "Weight" - # Convert height/weight to 1 decimal place and multiply by 10 - value = (value * 10).round - if value <= 0 - raise _INTL("Value for '{1}' can't be less than or close to 0 (section {2}, {3})", key, species_id, path) - end - contents[key] = value - when "Evolutions" - contents[key].each { |evo| evo[3] = false } - end + data_hash[schema[key][0]] = value end - # Construct species hash - types = contents["Types"] || [contents["Type1"], contents["Type2"]] - types = [types] if !types.is_a?(Array) - types = types.uniq.compact - species_hash = { - :id => contents["InternalName"].to_sym, - :name => contents["Name"], - :form_name => contents["FormName"], - :category => contents["Category"] || contents["Kind"], - :pokedex_entry => contents["Pokedex"], - :types => types, - :base_stats => contents["BaseStats"], - :evs => contents["EVs"] || contents["EffortPoints"], - :base_exp => contents["BaseExp"] || contents["BaseEXP"], - :growth_rate => contents["GrowthRate"], - :gender_ratio => contents["GenderRatio"] || contents["GenderRate"], - :catch_rate => contents["CatchRate"] || contents["Rareness"], - :happiness => contents["Happiness"], - :moves => contents["Moves"], - :tutor_moves => contents["TutorMoves"], - :egg_moves => contents["EggMoves"], - :abilities => contents["Abilities"], - :hidden_abilities => contents["HiddenAbilities"] || contents["HiddenAbility"], - :wild_item_common => contents["WildItemCommon"], - :wild_item_uncommon => contents["WildItemUncommon"], - :wild_item_rare => contents["WildItemRare"], - :egg_groups => contents["EggGroups"] || contents["Compatibility"], - :hatch_steps => contents["HatchSteps"] || contents["StepsToHatch"], - :incense => contents["Incense"], - :offspring => contents["Offspring"], - :evolutions => contents["Evolutions"], - :height => contents["Height"], - :weight => contents["Weight"], - :color => contents["Color"], - :shape => contents["Shape"], - :habitat => contents["Habitat"], - :generation => contents["Generation"], - :flags => contents["Flags"] - } - # Add species' data to records - GameData::Species.register(species_hash) - species_names.push(species_hash[:name]) - species_form_names.push(species_hash[:form_name]) - species_categories.push(species_hash[:category]) - species_pokedex_entries.push(species_hash[:pokedex_entry]) - # Save metrics data if defined (backwards compatibility) - if contents["BattlerPlayerX"] || contents["BattlerPlayerY"] || - contents["BattlerEnemyX"] || contents["BattlerEnemyY"] || - contents["BattlerAltitude"] || contents["BattlerShadowX"] || - contents["BattlerShadowSize"] - metrics_hash = { - :id => contents["InternalName"].to_sym, - :back_sprite => [contents["BattlerPlayerX"] || 0, contents["BattlerPlayerY"] || 0], - :front_sprite => [contents["BattlerEnemyX"] || 0, contents["BattlerEnemyY"] || 0], - :front_sprite_altitude => contents["BattlerAltitude"] || 0, - :shadow_x => contents["BattlerShadowX"] || 0, - :shadow_size => contents["BattlerShadowSize"] || 2 - } - GameData::SpeciesMetrics.register(metrics_hash) + # Validate and modify the compiled data + validate_compiled_pokemon(data_hash) + if GameData::Species.exists?(data_hash[:id]) + raise _INTL("Species ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end + # Add species's data to records + GameData::Species.register(data_hash) } } + validate_all_compiled_pokemon + # Save all data + GameData::Species.save + process_pbs_file_message_end + end + + # NOTE: This method is also called by def validate_compiled_pokemon_form + # below, and since a form's hash can contain very little data, don't + # assume any data exists. + def validate_compiled_pokemon(hash) + # Convert base stats array to a hash + if hash[:base_stats].is_a?(Array) + new_stats = {} + GameData::Stat.each_main do |s| + new_stats[s.id] = (hash[:base_stats][s.pbs_order] || 1) if s.pbs_order >= 0 + end + hash[:base_stats] = new_stats + end + # Convert EVs array to a hash + if hash[:evs].is_a?(Array) + new_evs = {} + hash[:evs].each { |val| new_evs[val[0]] = val[1] } + GameData::Stat.each_main { |s| new_evs[s.id] ||= 0 } + hash[:evs] = new_evs + end + # Convert height and weight to integer values of tenths of a unit + hash[:height] = [(hash[:height] * 10).round, 1].max if hash[:height] + hash[:weight] = [(hash[:weight] * 10).round, 1].max if hash[:weight] + # Record all evolutions as not being prevolutions + if hash[:evolutions].is_a?(Array) + hash[:evolutions].each { |evo| evo[3] = false } + end + # Remove duplicate types + hash[:types].uniq! if hash[:types].is_a?(Array) + end + + def validate_all_compiled_pokemon # Enumerate all offspring species (this couldn't be done earlier) GameData::Species.each do |species| FileLineData.setSection(species.id.to_s, "Offspring", nil) # For error reporting @@ -793,14 +611,21 @@ module Compiler GameData::Species.each do |species| # Distribute prevolutions species.evolutions.push(all_evos[species.species].clone) if all_evos[species.species] end - # Save all data - GameData::Species.save - GameData::SpeciesMetrics.save + # Get species names/descriptions for translating + species_names = [] + species_form_names = [] + species_categories = [] + species_pokedex_entries = [] + GameData::Species.each do |species| + species_names.push(species.real_name) + species_form_names.push(species.real_form_name) + species_categories.push(species.real_category) + species_pokedex_entries.push(species.real_pokedex_entry) + end MessageTypes.setMessagesAsHash(MessageTypes::Species, species_names) MessageTypes.setMessagesAsHash(MessageTypes::FormNames, species_form_names) MessageTypes.setMessagesAsHash(MessageTypes::Kinds, species_categories) MessageTypes.setMessagesAsHash(MessageTypes::Entries, species_pokedex_entries) - process_pbs_file_message_end end #============================================================================= @@ -808,11 +633,6 @@ module Compiler #============================================================================= def compile_pokemon_forms(path = "PBS/pokemon_forms.txt") compile_pbs_file_message_start(path) - species_names = [] - species_form_names = [] - species_categories = [] - species_pokedex_entries = [] - used_forms = {} # Read from PBS file File.open(path, "rb") { |f| FileLineData.file = path # For error reporting @@ -821,190 +641,81 @@ module Compiler # the keys are the XXX and the values are the YYY (as unprocessed strings). schema = GameData::Species.schema(true) idx = 0 - pbEachFileSectionPokemonForms(f) { |contents, section_name| + pbEachFileSection(f) { |contents, section_name| echo "." if idx % 50 == 0 - idx += 1 Graphics.update if idx % 250 == 0 - FileLineData.setSection(section_name, "header", nil) # For error reporting - # Split section_name into a species number and form number - split_section_name = section_name.split(/[-,\s]/) - if split_section_name.length != 2 - raise _INTL("Section name {1} is invalid ({2}). Expected syntax like [XXX,Y] (XXX=species ID, Y=form number).", section_name, path) - end - species_symbol = csvEnumField!(split_section_name[0], :Species, nil, nil) - form = csvPosInt!(split_section_name[1]) - # Raise an error if a species is undefined, the form number is invalid or - # a species/form combo is used twice - if !GameData::Species.exists?(species_symbol) - raise _INTL("Species ID '{1}' is not defined in {2}.\r\n{3}", species_symbol, path, FileLineData.linereport) - elsif form == 0 - raise _INTL("A form cannot be defined with a form number of 0.\r\n{1}", FileLineData.linereport) - elsif used_forms[species_symbol]&.include?(form) - raise _INTL("Form {1} for species ID {2} is defined twice.\r\n{3}", form, species_symbol, FileLineData.linereport) - end - used_forms[species_symbol] = [] if !used_forms[species_symbol] - used_forms[species_symbol].push(form) - base_data = GameData::Species.get(species_symbol) + idx += 1 + data_hash = {:id => section_name.to_sym} # Go through schema hash of compilable data and compile this section schema.each_key do |key| - # Skip empty properties (none are required) - if nil_or_empty?(contents[key]) - contents[key] = nil + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) next end - FileLineData.setSection(section_name, key, contents[key]) # For error reporting + # Skip empty properties + next if contents[key].nil? # Compile value for key - if ["EVs", "EffortPoints"].include?(key) && contents[key].split(",")[0].numeric? - value = pbGetCsvRecord(contents[key], key, [0, "uuuuuu"]) # Old format - else - value = pbGetCsvRecord(contents[key], key, schema[key]) - end - value = nil if value.is_a?(Array) && value.length == 0 - contents[key] = value - # Sanitise data - case key - when "BaseStats" - value_hash = {} - GameData::Stat.each_main do |s| - value_hash[s.id] = value[s.pbs_order] if s.pbs_order >= 0 - end - contents[key] = value_hash - when "EVs", "EffortPoints" - if value[0].is_a?(Array) # New format - value_hash = {} - value.each { |val| value_hash[val[0]] = val[1] } - GameData::Stat.each_main { |s| value_hash[s.id] ||= 0 } - contents[key] = value_hash - else # Old format - value_hash = {} - GameData::Stat.each_main do |s| - value_hash[s.id] = value[s.pbs_order] if s.pbs_order >= 0 - end - contents[key] = value_hash - end - when "Height", "Weight" - # Convert height/weight to 1 decimal place and multiply by 10 - value = (value * 10).round - if value <= 0 - raise _INTL("Value for '{1}' can't be less than or close to 0 (section {2}, {3})", key, section_name, path) - end - contents[key] = value - when "Evolutions" - contents[key].each do |evo| - evo[3] = false - param_type = GameData::Evolution.get(evo[1]).parameter - if param_type.nil? - evo[2] = nil - elsif param_type == Integer - evo[2] = csvPosInt!(evo[2]) - elsif param_type != String - evo[2] = csvEnumField!(evo[2], param_type, "Evolutions", section_name) - end - end - end + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Construct species hash - form_symbol = sprintf("%s_%d", species_symbol.to_s, form).to_sym - types = contents["Types"] - types ||= [contents["Type1"], contents["Type2"]] if contents["Type1"] - types ||= base_data.types.clone - types = [types] if !types.is_a?(Array) - types = types.uniq.compact - moves = contents["Moves"] - if !moves - moves = [] - base_data.moves.each { |m| moves.push(m.clone) } - end - evolutions = contents["Evolutions"] - if !evolutions - evolutions = [] - base_data.evolutions.each { |e| evolutions.push(e.clone) } - end - species_hash = { - :id => form_symbol, - :species => species_symbol, - :form => form, - :name => base_data.real_name, - :form_name => contents["FormName"], - :category => contents["Category"] || contents["Kind"] || base_data.real_category, - :pokedex_entry => contents["Pokedex"] || base_data.real_pokedex_entry, - :pokedex_form => contents["PokedexForm"], - :types => types, - :base_stats => contents["BaseStats"] || base_data.base_stats, - :evs => contents["EVs"] || contents["EffortPoints"] || base_data.evs, - :base_exp => contents["BaseExp"] || contents["BaseEXP"] || base_data.base_exp, - :growth_rate => base_data.growth_rate, - :gender_ratio => base_data.gender_ratio, - :catch_rate => contents["CatchRate"] || contents["Rareness"] || base_data.catch_rate, - :happiness => contents["Happiness"] || base_data.happiness, - :moves => moves, - :tutor_moves => contents["TutorMoves"] || base_data.tutor_moves.clone, - :egg_moves => contents["EggMoves"] || base_data.egg_moves.clone, - :abilities => contents["Abilities"] || base_data.abilities.clone, - :hidden_abilities => contents["HiddenAbilities"] || contents["HiddenAbility"] || base_data.hidden_abilities.clone, - :wild_item_common => contents["WildItemCommon"] || base_data.wild_item_common.clone, - :wild_item_uncommon => contents["WildItemUncommon"] || base_data.wild_item_uncommon.clone, - :wild_item_rare => contents["WildItemRare"] || base_data.wild_item_rare.clone, - :egg_groups => contents["EggGroups"] || contents["Compatibility"] || base_data.egg_groups.clone, - :hatch_steps => contents["HatchSteps"] || contents["StepsToHatch"] || base_data.hatch_steps, - :incense => base_data.incense, - :offspring => contents["Offspring"] || base_data.offspring.clone, - :evolutions => evolutions, - :height => contents["Height"] || base_data.height, - :weight => contents["Weight"] || base_data.weight, - :color => contents["Color"] || base_data.color, - :shape => contents["Shape"] || base_data.shape, - :habitat => contents["Habitat"] || base_data.habitat, - :generation => contents["Generation"] || base_data.generation, - :flags => contents["Flags"] || base_data.flags.clone, - :mega_stone => contents["MegaStone"], - :mega_move => contents["MegaMove"], - :unmega_form => contents["UnmegaForm"], - :mega_message => contents["MegaMessage"] - } - # If form has any wild items, ensure none are inherited from base species - if (contents["WildItemCommon"] && !contents["WildItemCommon"].empty?) || - (contents["WildItemUncommon"] && !contents["WildItemUncommon"].empty?) || - (contents["WildItemRare"] && !contents["WildItemRare"].empty?) - species_hash[:wild_item_common] = contents["WildItemCommon"] - species_hash[:wild_item_uncommon] = contents["WildItemUncommon"] - species_hash[:wild_item_rare] = contents["WildItemRare"] - end - # Add form's data to records - GameData::Species.register(species_hash) - species_names.push(species_hash[:name]) - species_form_names.push(species_hash[:form_name]) - species_categories.push(species_hash[:category]) - species_pokedex_entries.push(species_hash[:pokedex_entry]) - # Save metrics data if defined (backwards compatibility) - if contents["BattlerPlayerX"] || contents["BattlerPlayerY"] || - contents["BattlerEnemyX"] || contents["BattlerEnemyY"] || - contents["BattlerAltitude"] || contents["BattlerShadowX"] || - contents["BattlerShadowSize"] - base_metrics = GameData::SpeciesMetrics.get_species_form(species_symbol, 0) - back_x = contents["BattlerPlayerX"] || base_metrics.back_sprite[0] - back_y = contents["BattlerPlayerY"] || base_metrics.back_sprite[1] - front_x = contents["BattlerEnemyX"] || base_metrics.front_sprite[0] - front_y = contents["BattlerEnemyY"] || base_metrics.front_sprite[1] - altitude = contents["BattlerAltitude"] || base_metrics.front_sprite_altitude - shadow_x = contents["BattlerShadowX"] || base_metrics.shadow_x - shadow_size = contents["BattlerShadowSize"] || base_metrics.shadow_size - metrics_hash = { - :id => form_symbol, - :species => species_symbol, - :form => form, - :back_sprite => [back_x, back_y], - :front_sprite => [front_x, front_y], - :front_sprite_altitude => altitude, - :shadow_x => shadow_x, - :shadow_size => shadow_size - } - GameData::SpeciesMetrics.register(metrics_hash) + # Validate and modify the compiled data + validate_compiled_pokemon_form(data_hash) + if GameData::Species.exists?(data_hash[:id]) + raise _INTL("Species ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end + # Add species's data to records + GameData::Species.register(data_hash) } } - # Add prevolution "evolution" entry for all evolved forms that define their - # own evolution methods (and thus won't have a prevolution listed already) + validate_all_compiled_pokemon_forms + # Save all data + GameData::Species.save + process_pbs_file_message_end + end + + def validate_compiled_pokemon_form(hash) + # Split species and form into their own values, generate compound ID from them + hash[:species] = hash[:id][0] + hash[:form] = hash[:id][1] + hash[:id] = sprintf("%s_%d", hash[:species].to_s, hash[:form]).to_sym + if !GameData::Species.exists?(hash[:species]) + raise _INTL("Undefined species ID '{1}'.\r\n{3}", hash[:species], FileLineData.linereport) + elsif GameData::Species.exists?(hash[:id]) + raise _INTL("Form {1} for species ID {2} is defined twice.\r\n{3}", hash[:form], hash[:species], FileLineData.linereport) + end + # Perform the same validations on this form as for a regular species + validate_compiled_pokemon(hash) + # Inherit undefined properties from base species + base_data = GameData::Species.get(hash[:species]) + [:real_name, :real_category, :real_pokedex_entry, :base_exp, :growth_rate, + :gender_ratio, :catch_rate, :happiness, :hatch_steps, :incense, :height, + :weight, :color, :shape, :habitat, :generation].each do |property| + hash[property] = base_data.send(property) if hash[property].nil? + end + [:types, :base_stats, :evs, :tutor_moves, :egg_moves, :abilities, + :hidden_abilities, :egg_groups, :offspring, :flags].each do |property| + hash[property] = base_data.send(property).clone if hash[property].nil? + end + if !hash[:moves].is_a?(Array) || hash[:moves].length == 0 + hash[:moves] ||= [] + base_data.moves.each { |m| hash[:moves].push(m.clone) } + end + if !hash[:evolutions].is_a?(Array) || hash[:evolutions].length == 0 + hash[:evolutions] ||= [] + base_data.evolutions.each { |e| hash[:evolutions].push(e.clone) } + end + if hash[:wild_item_common].nil? && hash[:wild_item_uncommon].nil? && + hash[:wild_item_rare].nil? + hash[:wild_item_common] = base_data.wild_item_common.clone + hash[:wild_item_uncommon] = base_data.wild_item_uncommon.clone + hash[:wild_item_rare] = base_data.wild_item_rare.clone + end + end + + def validate_all_compiled_pokemon_forms + # Add prevolution "evolution" entry for all evolved species all_evos = {} GameData::Species.each do |species| # Build a hash of prevolutions for each species species.evolutions.each do |evo| @@ -1022,142 +733,139 @@ module Compiler prevo.evolutions.push([species.species, :None, nil]) end end - # Save all data - GameData::Species.save - GameData::SpeciesMetrics.save - MessageTypes.addMessagesAsHash(MessageTypes::Species, species_names) + # Get species names/descriptions for translating + species_form_names = [] + species_categories = [] + species_pokedex_entries = [] + GameData::Species.each do |species| + next if species.form == 0 + species_form_names.push(species.real_form_name) + species_categories.push(species.real_category) + species_pokedex_entries.push(species.real_pokedex_entry) + end MessageTypes.addMessagesAsHash(MessageTypes::FormNames, species_form_names) MessageTypes.addMessagesAsHash(MessageTypes::Kinds, species_categories) MessageTypes.addMessagesAsHash(MessageTypes::Entries, species_pokedex_entries) - process_pbs_file_message_end end #============================================================================= # Compile Pokémon metrics data #============================================================================= def compile_pokemon_metrics(path = "PBS/pokemon_metrics.txt") - return if !safeExists?(path) compile_pbs_file_message_start(path) - schema = GameData::SpeciesMetrics::SCHEMA + GameData::SpeciesMetrics::DATA.clear # Read from PBS file File.open(path, "rb") { |f| FileLineData.file = path # 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). + schema = GameData::SpeciesMetrics::SCHEMA idx = 0 pbEachFileSection(f) { |contents, section_name| echo "." if idx % 50 == 0 - idx += 1 Graphics.update if idx % 250 == 0 - FileLineData.setSection(section_name, "header", nil) # For error reporting - # Split section_name into a species number and form number - split_section_name = section_name.split(/[-,\s]/) - if split_section_name.length == 0 || split_section_name.length > 2 - raise _INTL("Section name {1} is invalid ({2}). Expected syntax like [XXX] or [XXX,Y] (XXX=species ID, Y=form number).", section_name, path) - end - species_symbol = csvEnumField!(split_section_name[0], :Species, nil, nil) - form = (split_section_name[1]) ? csvPosInt!(split_section_name[1]) : 0 + idx += 1 + data_hash = {:id => section_name.to_sym} # Go through schema hash of compilable data and compile this section schema.each_key do |key| - # Skip empty properties (none are required) - if nil_or_empty?(contents[key]) - contents[key] = nil + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) next end - FileLineData.setSection(section_name, key, contents[key]) # For error reporting + # Skip empty properties + next if contents[key].nil? # Compile value for key value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.length == 0 - contents[key] = value + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Construct species hash - form_symbol = (form > 0) ? sprintf("%s_%d", species_symbol.to_s, form).to_sym : species_symbol - species_hash = { - :id => form_symbol, - :species => species_symbol, - :form => form, - :back_sprite => contents["BackSprite"], - :front_sprite => contents["FrontSprite"], - :front_sprite_altitude => contents["FrontSpriteAltitude"], - :shadow_x => contents["ShadowX"], - :shadow_size => contents["ShadowSize"] - } - # Add form's data to records - GameData::SpeciesMetrics.register(species_hash) + # Validate and modify the compiled data + validate_compiled_pokemon_metrics(data_hash) + if GameData::SpeciesMetrics.exists?(data_hash[:id]) + raise _INTL("Metrics for species '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + # Add species' metrics to records + GameData::SpeciesMetrics.register(data_hash) } } + validate_all_compiled_pokemon_metrics # Save all data GameData::SpeciesMetrics.save process_pbs_file_message_end end + def validate_compiled_pokemon_metrics(hash) + # Split species and form into their own values, generate compound ID from them + if hash[:id].is_a?(Array) + hash[:species] = hash[:id][0] + hash[:form] = hash[:id][1] || 0 + if hash[:form] == 0 + hash[:id] = hash[:species] + else + hash[:id] = sprintf("%s_%d", hash[:species].to_s, hash[:form]).to_sym + end + end + end + + def validate_all_compiled_pokemon_metrics + end + #============================================================================= # Compile Shadow Pokémon data #============================================================================= def compile_shadow_pokemon(path = "PBS/shadow_pokemon.txt") compile_pbs_file_message_start(path) GameData::ShadowPokemon::DATA.clear - schema = GameData::ShadowPokemon::SCHEMA - shadow_hash = nil - old_format = nil - # Read each line of shadow_pokemon.txt at a time and compile it into a - # Shadow Pokémon's data - idx = 0 - pbCompilerEachPreppedLine(path) { |line, line_no| - echo "." if idx % 250 == 0 - idx += 1 - if line[/^\s*\[\s*(.+)\s*\]\s*$/] # New section [species_id] - old_format = false if old_format.nil? - if old_format - raise _INTL("Can't mix old and new formats.\r\n{1}", FileLineData.linereport) + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = GameData::ShadowPokemon::SCHEMA + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Add previous Shadow Pokémon's data to records - GameData::ShadowPokemon.register(shadow_hash) if shadow_hash - # Parse species ID - species_id = $~[1].to_sym - if GameData::ShadowPokemon.exists?(species_id) - raise _INTL("Shadow Pokémon data for species '{1}' is defined twice.\r\n{2}", species_id, FileLineData.linereport) + # Validate and modify the compiled data + validate_compiled_shadow_pokemon(data_hash) + if GameData::ShadowPokemon.exists?(data_hash[:id]) + raise _INTL("Species ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - # Construct Shadow Pokémon hash - shadow_hash = { - :id => species_id - } - elsif line[/^\s*(\w+)\s*=\s*(.*)\s*$/] # XXX=YYY lines - old_format = true if old_format.nil? - if old_format - key = $1 - value = $2 - value = value.split(",") - species = parseSpecies(key) - value.each { |val| val.strip! } - value.delete_if { |val| nil_or_empty?(val) } - # Construct Shadow Pokémon hash - shadow_hash = { - :id => species, - :moves => value - } - # Add Shadow Pokémons data to records - GameData::ShadowPokemon.register(shadow_hash) - shadow_hash = nil - else - # Parse property and value - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - shadow_hash[line_schema[0]] = property_value - end - end + # Add Shadow Pokémon data to records + GameData::ShadowPokemon.register(data_hash) + } } - # Add last item's data to records - GameData::ShadowPokemon.register(shadow_hash) if shadow_hash + validate_all_compiled_shadow_pokemon # Save all data GameData::ShadowPokemon.save process_pbs_file_message_end end + def validate_compiled_shadow_pokemon(hash) + end + + def validate_all_compiled_shadow_pokemon + end + #============================================================================= # Compile Regional Dexes #============================================================================= @@ -1203,70 +911,61 @@ module Compiler def compile_ribbons(path = "PBS/ribbons.txt") compile_pbs_file_message_start(path) GameData::Ribbon::DATA.clear - schema = GameData::Ribbon::SCHEMA - ribbon_names = [] - ribbon_descriptions = [] - ribbon_hash = nil - pbCompilerEachPreppedLine(path) { |line, line_no| - if line[/^\s*\[\s*(.+)\s*\]\s*$/] # New section [ribbon_id] - # Add previous ribbon's data to records - GameData::Ribbon.register(ribbon_hash) if ribbon_hash - # Parse ribbon ID - ribbon_id = $~[1].to_sym - if GameData::Ribbon.exists?(ribbon_id) - raise _INTL("Ribbon ID '{1}' is used twice.\r\n{2}", ribbon_id, FileLineData.linereport) + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = GameData::Ribbon::SCHEMA + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Construct ribbon hash - ribbon_hash = { - :id => ribbon_id - } - elsif line[/^\s*(\w+)\s*=\s*(.*)\s*$/] # XXX=YYY lines - if !ribbon_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) + # Validate and modify the compiled data + validate_compiled_ribbon(data_hash) + if GameData::Ribbon.exists?(data_hash[:id]) + raise _INTL("Ribbon ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - # Parse property and value - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - ribbon_hash[line_schema[0]] = property_value - case property_name - when "Name" - ribbon_names.push(ribbon_hash[:name]) - when "Description" - ribbon_descriptions.push(ribbon_hash[:description]) - end - else # Old format - # Add previous ribbon's data to records - GameData::Ribbon.register(ribbon_hash) if ribbon_hash - # Parse ribbon - line = pbGetCsvRecord(line, line_no, [0, "unss"]) - ribbon_id = line[1].to_sym - if GameData::Ribbon::DATA[ribbon_id] - raise _INTL("Ribbon ID '{1}' is used twice.\r\n{2}", ribbon_id, FileLineData.linereport) - end - # Construct ribbon hash - ribbon_hash = { - :id => ribbon_id, - :name => line[2], - :description => line[3], - :icon_position => line[0] - 1 - } - # Add ribbon's data to records - GameData::Ribbon.register(ribbon_hash) - ribbon_names.push(ribbon_hash[:name]) - ribbon_descriptions.push(ribbon_hash[:description]) - ribbon_hash = nil - end + # Add ribbon data to records + GameData::Ribbon.register(data_hash) + } } - # Add last ribbon's data to records - GameData::Ribbon.register(ribbon_hash) if ribbon_hash + validate_all_compiled_ribbons # Save all data GameData::Ribbon.save + process_pbs_file_message_end + end + + def validate_compiled_ribbon(hash) + end + + def validate_all_compiled_ribbons + # Get ribbon names/descriptions for translating + ribbon_names = [] + ribbon_descriptions = [] + GameData::Ribbon.each do |ribbon| + ribbon_names.push(ribbon.real_name) + ribbon_descriptions.push(ribbon.real_description) + end MessageTypes.setMessagesAsHash(MessageTypes::RibbonNames, ribbon_names) MessageTypes.setMessagesAsHash(MessageTypes::RibbonDescriptions, ribbon_descriptions) - process_pbs_file_message_end end #============================================================================= @@ -1384,76 +1083,60 @@ module Compiler def compile_trainer_types(path = "PBS/trainer_types.txt") compile_pbs_file_message_start(path) GameData::TrainerType::DATA.clear - schema = GameData::TrainerType::SCHEMA - tr_type_names = [] - tr_type_hash = nil - # Read each line of trainer_types.txt at a time and compile it into a trainer type - pbCompilerEachPreppedLine(path) { |line, line_no| - if line[/^\s*\[\s*(.+)\s*\]\s*$/] # New section [tr_type_id] - # Add previous trainer type's data to records - GameData::TrainerType.register(tr_type_hash) if tr_type_hash - # Parse trainer type ID - tr_type_id = $~[1].to_sym - if GameData::TrainerType.exists?(tr_type_id) - raise _INTL("Trainer Type ID '{1}' is used twice.\r\n{2}", tr_type_id, FileLineData.linereport) + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = GameData::TrainerType::SCHEMA + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Construct trainer type hash - tr_type_hash = { - :id => tr_type_id - } - elsif line[/^\s*(\w+)\s*=\s*(.*)\s*$/] # XXX=YYY lines - if !tr_type_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) + # Validate and modify the compiled data + validate_compiled_trainer_type(data_hash) + if GameData::TrainerType.exists?(data_hash[:id]) + raise _INTL("Trainer type ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - # Parse property and value - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - tr_type_hash[line_schema[0]] = property_value - tr_type_names.push(tr_type_hash[:name]) if property_name == "Name" - else # Old format - # Add previous trainer type's data to records - GameData::TrainerType.register(tr_type_hash) if tr_type_hash - # Parse trainer type - line = pbGetCsvRecord(line, line_no, - [0, "snsUSSSeUS", - nil, nil, nil, nil, nil, nil, nil, - { "Male" => 0, "M" => 0, "0" => 0, - "Female" => 1, "F" => 1, "1" => 1, - "Mixed" => 2, "X" => 2, "2" => 2, "" => 2 }, - nil, nil]) - tr_type_id = line[1].to_sym - if GameData::TrainerType.exists?(tr_type_id) - raise _INTL("Trainer Type ID '{1}' is used twice.\r\n{2}", tr_type_id, FileLineData.linereport) - end - # Construct trainer type hash - tr_type_hash = { - :id => tr_type_id, - :name => line[2], - :base_money => line[3], - :battle_BGM => line[4], - :victory_BGM => line[5], - :intro_BGM => line[6], - :gender => line[7], - :skill_level => line[8], - :flags => line[9] - } - # Add trainer type's data to records - GameData::TrainerType.register(tr_type_hash) - tr_type_names.push(tr_type_hash[:name]) - tr_type_hash = nil - end + # Add trainer type data to records + GameData::TrainerType.register(data_hash) + } } - # Add last trainer type's data to records - GameData::TrainerType.register(tr_type_hash) if tr_type_hash + validate_all_compiled_trainer_types # Save all data GameData::TrainerType.save - MessageTypes.setMessagesAsHash(MessageTypes::TrainerTypes, tr_type_names) process_pbs_file_message_end end + def validate_compiled_trainer_type(hash) + end + + def validate_all_compiled_trainer_types + # Get trainer type names for translating + trainer_type_names = [] + GameData::TrainerType.each do |tr_type| + trainer_type_names.push(tr_type.real_name) + end + MessageTypes.setMessagesAsHash(MessageTypes::TrainerTypes, trainer_type_names) + end + #============================================================================= # Compile individual trainer data #============================================================================= @@ -1708,87 +1391,91 @@ module Compiler compile_pbs_file_message_start(path) GameData::Metadata::DATA.clear GameData::PlayerMetadata::DATA.clear - storage_creator = [] # Read from PBS file File.open(path, "rb") { |f| FileLineData.file = path # 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). - pbEachFileSectionNumbered(f) { |contents, section_id| - schema = (section_id == 0) ? GameData::Metadata::SCHEMA : GameData::PlayerMetadata::SCHEMA + global_schema = GameData::Metadata::SCHEMA + player_schema = GameData::PlayerMetadata::SCHEMA + idx = 0 + pbEachFileSectionNumbered(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + schema = (section_name == 0) ? global_schema : player_schema + data_hash = {:id => section_name} # Go through schema hash of compilable data and compile this section schema.each_key do |key| - FileLineData.setSection(section_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 section_id == 0 && ["Home"].include?(key) - raise _INTL("The entry {1} is required in {2} section 0.", key, path) - end + FileLineData.setSection(section_name.to_s, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name.to_s, key, schema[key]) next end + # Skip empty properties + next if contents[key].nil? # Compile value for key value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.length == 0 - contents[key] = value + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - if section_id == 0 # Metadata - # Construct metadata hash - metadata_hash = { - :id => section_id, - :start_money => contents["StartMoney"], - :start_item_storage => contents["StartItemStorage"], - :home => contents["Home"], - :storage_creator => contents["StorageCreator"], - :wild_battle_BGM => contents["WildBattleBGM"], - :trainer_battle_BGM => contents["TrainerBattleBGM"], - :wild_victory_BGM => contents["WildVictoryBGM"], - :trainer_victory_BGM => contents["TrainerVictoryBGM"], - :wild_capture_ME => contents["WildCaptureME"], - :surf_BGM => contents["SurfBGM"], - :bicycle_BGM => contents["BicycleBGM"] - } - storage_creator[0] = contents["StorageCreator"] - # Add metadata's data to records - GameData::Metadata.register(metadata_hash) - else # Player metadata - # Construct metadata hash - metadata_hash = { - :id => section_id, - :trainer_type => contents["TrainerType"], - :walk_charset => contents["WalkCharset"], - :run_charset => contents["RunCharset"], - :cycle_charset => contents["CycleCharset"], - :surf_charset => contents["SurfCharset"], - :dive_charset => contents["DiveCharset"], - :fish_charset => contents["FishCharset"], - :surf_fish_charset => contents["SurfFishCharset"] - } - # Add metadata's data to records - GameData::PlayerMetadata.register(metadata_hash) + # Validate and modify the compiled data + if section_name == 0 + validate_compiled_global_metadata(data_hash) + if GameData::Metadata.exists?(data_hash[:id]) + raise _INTL("Global metadata ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + else + validate_compiled_player_metadata(data_hash) + if GameData::PlayerMetadata.exists?(data_hash[:id]) + raise _INTL("Player metadata ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + end + # Add trainer type data to records + if section_name == 0 + GameData::Metadata.register(data_hash) + else + GameData::PlayerMetadata.register(data_hash) end } } - if !GameData::PlayerMetadata.exists?(1) - raise _INTL("Metadata for player character 1 in {1} is not defined but should be.", path) - end + validate_all_compiled_metadata # Save all data GameData::Metadata.save GameData::PlayerMetadata.save - MessageTypes.setMessages(MessageTypes::StorageCreator, storage_creator) process_pbs_file_message_end end + def validate_compiled_global_metadata(hash) + if hash[:home].nil? + raise _INTL("The entry 'Home' is required in metadata.txt section 0.\r\n{1}", FileLineData.linereport) + end + end + + def validate_compiled_player_metadata(hash) + end + + def validate_all_compiled_metadata + # Ensure global metadata is defined + if !GameData::Metadata.exists?(0) + raise _INTL("Global metadata is not defined in metadata.txt but should be.\r\n{1}", FileLineData.linereport) + end + # Ensure player character 1's metadata is defined + if !GameData::PlayerMetadata.exists?(1) + raise _INTL("Metadata for player character 1 is not defined in metadata.txt but should be.\r\n{1}", FileLineData.linereport) + end + # Get storage creator's name for translating + storage_creator = [GameData::Metadata.get.real_storage_creator] + MessageTypes.setMessages(MessageTypes::StorageCreator, storage_creator) + end + #============================================================================= # Compile map metadata #============================================================================= def compile_map_metadata(path = "PBS/map_metadata.txt") compile_pbs_file_message_start(path) GameData::MapMetadata::DATA.clear - map_infos = pbLoadMapInfos - map_names = [] - map_infos.each_key { |id| map_names[id] = map_infos[id].name } # Read from PBS file File.open(path, "rb") { |f| FileLineData.file = path # For error reporting @@ -1797,57 +1484,56 @@ module Compiler # the keys are the XXX and the values are the YYY (as unprocessed strings). schema = GameData::MapMetadata::SCHEMA idx = 0 - pbEachFileSectionNumbered(f) { |contents, map_id| + pbEachFileSectionNumbered(f) { |contents, section_name| echo "." if idx % 50 == 0 - idx += 1 Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name} # Go through schema hash of compilable data and compile this section schema.each_key do |key| - FileLineData.setSection(map_id, key, contents[key]) # For error reporting + FileLineData.setSection(section_name.to_s, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name.to_s, key, schema[key]) + next + end # Skip empty properties next if contents[key].nil? # Compile value for key value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.length == 0 - contents[key] = value + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Construct map metadata hash - metadata_hash = { - :id => map_id, - :name => contents["Name"], - :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_BGM => contents["WildVictoryBGM"], - :trainer_victory_BGM => contents["TrainerVictoryBGM"], - :wild_capture_ME => contents["WildCaptureME"], - :town_map_size => contents["MapSize"], - :battle_environment => contents["Environment"], - :flags => contents["Flags"] - } - # Add map metadata's data to records - GameData::MapMetadata.register(metadata_hash) - map_names[map_id] = metadata_hash[:name] if !nil_or_empty?(metadata_hash[:name]) + # Validate and modify the compiled data + validate_compiled_map_metadata(data_hash) + if GameData::MapMetadata.exists?(data_hash[:id]) + raise _INTL("Map metadata for map '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + # Add map metadata to records + GameData::MapMetadata.register(data_hash) } } + validate_all_compiled_map_metadata # Save all data GameData::MapMetadata.save - MessageTypes.setMessages(MessageTypes::MapNames, map_names) process_pbs_file_message_end end + def validate_compiled_map_metadata(hash) + # Give the map its RMXP map name if it doesn't define its own + if nil_or_empty?(hash[:real_name]) + hash[:real_name] = pbLoadMapInfos[id].name + end + end + + def validate_all_compiled_map_metadata + # Get map names for translating + map_names = [] + GameData::MapMetadata.each do |map| + map_names[map.id] = map.real_name + end + MessageTypes.setMessages(MessageTypes::MapNames, map_names) + end + #============================================================================= # Compile dungeon tileset data #============================================================================= @@ -1903,55 +1589,65 @@ module Compiler def compile_dungeon_parameters(path = "PBS/dungeon_parameters.txt") compile_pbs_file_message_start(path) GameData::DungeonParameters::DATA.clear - schema = GameData::DungeonParameters::SCHEMA # Read from PBS file File.open(path, "rb") { |f| FileLineData.file = path # 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). + schema = GameData::DungeonParameters::SCHEMA idx = 0 pbEachFileSection(f) { |contents, section_name| echo "." if idx % 50 == 0 - idx += 1 Graphics.update if idx % 250 == 0 - FileLineData.setSection(section_name, "header", nil) # For error reporting - # Split section_name into an area and version number - split_section_name = section_name.split(/[-,\s]/) - if split_section_name.length == 0 || split_section_name.length > 2 - raise _INTL("Section name {1} is invalid ({2}). Expected syntax like [XXX] or [XXX,Y] (XXX=area, Y=version).", section_name, path) - end - area_symbol = split_section_name[0].downcase.to_sym - version = (split_section_name[1]) ? csvPosInt!(split_section_name[1]) : 0 - # Construct parameters hash - area_version = (version > 0) ? sprintf("%s_%d", area_symbol.to_s, version).to_sym : area_symbol - parameters_hash = { - :id => area_version, - :area => area_symbol, - :version => version - } + idx += 1 + data_hash = {:id => section_name} # Go through schema hash of compilable data and compile this section schema.each_key do |key| - # Skip empty properties (none are required) - if nil_or_empty?(contents[key]) - contents[key] = nil + FileLineData.setSection(section_name.to_s, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name.to_s, key, schema[key]) next end - FileLineData.setSection(section_name, key, contents[key]) # For error reporting + # Skip empty properties + next if contents[key].nil? # Compile value for key value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.length == 0 - parameters_hash[schema[key][0]] = value + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - # Add parameters data to records - GameData::DungeonParameters.register(parameters_hash) + # Validate and modify the compiled data + validate_compiled_dungeon_parameters(data_hash) + if GameData::DungeonParameters.exists?(data_hash[:id]) + raise _INTL("Dungeon ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + # Add dungeon parameters to records + GameData::DungeonParameters.register(data_hash) } } + validate_all_compiled_dungeon_parameters # Save all data GameData::DungeonParameters.save process_pbs_file_message_end end + def validate_compiled_dungeon_parameters(hash) + # Split area and version into their own values, generate compound ID from them + hash[:area] = hash[:id][0] + hash[:version] = hash[:id][1] || 0 + if hash[:version] == 0 + hash[:id] = hash[:area] + else + hash[:id] = sprintf("%s_%d", hash[:area].to_s, hash[:version]).to_sym + end + if GameData::DungeonParameters.exists?(hash[:id]) + raise _INTL("Version {1} of dungeon area {2} is defined twice.\r\n{3}", hash[:version], hash[:area], FileLineData.linereport) + end + end + + def validate_all_compiled_dungeon_parameters + end + #============================================================================= # Compile battle animations #============================================================================= diff --git a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb index 6d9b68116..4f5ce6cc8 100644 --- a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb +++ b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb @@ -812,8 +812,7 @@ module Compiler f.write("[0]\r\n") metadata = GameData::Metadata.get schema = GameData::Metadata::SCHEMA - keys = schema.keys.sort { |a, b| schema[a][0] <=> schema[b][0] } - keys.each do |key| + schema.keys.each do |key| record = metadata.property_from_string(key) next if record.nil? || (record.is_a?(Array) && record.empty?) f.write(sprintf("%s = ", key)) @@ -822,11 +821,10 @@ module Compiler end # Write player metadata schema = GameData::PlayerMetadata::SCHEMA - keys = schema.keys.sort { |a, b| schema[a][0] <=> schema[b][0] } GameData::PlayerMetadata.each do |player_data| f.write("\#-------------------------------\r\n") f.write(sprintf("[%d]\r\n", player_data.id)) - keys.each do |key| + schema.keys.each do |key| record = player_data.property_from_string(key) next if record.nil? || (record.is_a?(Array) && record.empty?) f.write(sprintf("%s = ", key)) @@ -845,7 +843,6 @@ module Compiler write_pbs_file_message_start(path) map_infos = pbLoadMapInfos schema = GameData::MapMetadata::SCHEMA - keys = schema.keys.sort { |a, b| schema[a][0] <=> schema[b][0] } File.open(path, "wb") { |f| idx = 0 add_PBS_header_to_file(f) @@ -861,7 +858,7 @@ module Compiler else f.write(sprintf("[%03d]\r\n", map_data.id)) end - keys.each do |key| + schema.keys.each do |key| record = map_data.property_from_string(key) next if record.nil? || (record.is_a?(Array) && record.empty?) f.write(sprintf("%s = ", key)) From 1ff730786889514d88c2a8ee258e46df882c13ee Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sat, 19 Nov 2022 23:03:42 +0000 Subject: [PATCH 02/12] Rewrote and standardised several PBS writer methods --- Data/Scripts/010_Data/001_GameData.rb | 9 + .../Scripts/010_Data/002_PBS data/002_Type.rb | 12 +- .../Scripts/010_Data/002_PBS data/004_Move.rb | 7 + .../Scripts/010_Data/002_PBS data/005_Item.rb | 23 +- .../010_Data/002_PBS data/007_Species.rb | 156 ++++-- .../002_PBS data/009_SpeciesMetrics.rb | 12 + .../010_Data/002_PBS data/013_TrainerType.rb | 7 + .../002_PBS data/020_DungeonParameters.rb | 24 +- Data/Scripts/021_Compiler/001_Compiler.rb | 10 +- .../021_Compiler/003_Compiler_WritePBS.rb | 528 +++++------------- PBS/abilities.txt | 8 +- PBS/items.txt | 10 +- PBS/metadata.txt | 4 + PBS/pokemon.txt | 100 ++-- 14 files changed, 380 insertions(+), 530 deletions(-) diff --git a/Data/Scripts/010_Data/001_GameData.rb b/Data/Scripts/010_Data/001_GameData.rb index 74d55f981..7b356a567 100644 --- a/Data/Scripts/010_Data/001_GameData.rb +++ b/Data/Scripts/010_Data/001_GameData.rb @@ -219,6 +219,15 @@ module GameData end return false end + + def get_property_for_PBS(key) + ret = nil + if self.class::SCHEMA.include?(key) + ret = self.send(self.class::SCHEMA[key][0]) + ret = nil if ret == false || (ret.is_a?(Array) && ret.length == 0) + end + return ret + end end #============================================================================= diff --git a/Data/Scripts/010_Data/002_PBS data/002_Type.rb b/Data/Scripts/010_Data/002_PBS data/002_Type.rb index 5b2f620d7..0270b9c16 100644 --- a/Data/Scripts/010_Data/002_PBS data/002_Type.rb +++ b/Data/Scripts/010_Data/002_PBS data/002_Type.rb @@ -2,13 +2,13 @@ module GameData class Type attr_reader :id attr_reader :real_name + attr_reader :icon_position # Where this type's icon is within types.png attr_reader :special_type attr_reader :pseudo_type - attr_reader :flags attr_reader :weaknesses attr_reader :resistances attr_reader :immunities - attr_reader :icon_position # Where this type's icon is within types.png + attr_reader :flags DATA = {} DATA_FILENAME = "types.dat" @@ -16,13 +16,13 @@ module GameData SCHEMA = { "SectionName" => [:id, "m"], "Name" => [:real_name, "s"], + "IconPosition" => [:icon_position, "u"], "IsSpecialType" => [:special_type, "b"], "IsPseudoType" => [:pseudo_type, "b"], - "Flags" => [:flags, "*s"], "Weaknesses" => [:weaknesses, "*m"], "Resistances" => [:resistances, "*m"], "Immunities" => [:immunities, "*m"], - "IconPosition" => [:icon_position, "u"] + "Flags" => [:flags, "*s"] } extend ClassMethodsSymbols @@ -31,16 +31,16 @@ module GameData def initialize(hash) @id = hash[:id] @real_name = hash[:real_name] || "Unnamed" + @icon_position = hash[:icon_position] || 0 @special_type = hash[:special_type] || false @pseudo_type = hash[:pseudo_type] || false - @flags = hash[:flags] || [] @weaknesses = hash[:weaknesses] || [] @weaknesses = [@weaknesses] if !@weaknesses.is_a?(Array) @resistances = hash[:resistances] || [] @resistances = [@resistances] if !@resistances.is_a?(Array) @immunities = hash[:immunities] || [] @immunities = [@immunities] if !@immunities.is_a?(Array) - @icon_position = hash[:icon_position] || 0 + @flags = hash[:flags] || [] end # @return [String] the translated name of this item diff --git a/Data/Scripts/010_Data/002_PBS data/004_Move.rb b/Data/Scripts/010_Data/002_PBS data/004_Move.rb index d28494deb..1d37c03b2 100644 --- a/Data/Scripts/010_Data/002_PBS data/004_Move.rb +++ b/Data/Scripts/010_Data/002_PBS data/004_Move.rb @@ -811,5 +811,12 @@ module GameData data[:function_code] = new_code return data end + + alias __orig__get_property_for_PBS get_property_for_PBS + def get_property_for_PBS(key) + ret = __orig__get_property_for_PBS(key) + ret = nil if ["Power", "Priority", "EffectChance"].include?(key) && ret == 0 + return ret + end end end diff --git a/Data/Scripts/010_Data/002_PBS data/005_Item.rb b/Data/Scripts/010_Data/002_PBS data/005_Item.rb index 6c2b74d71..c7b21da67 100644 --- a/Data/Scripts/010_Data/002_PBS data/005_Item.rb +++ b/Data/Scripts/010_Data/002_PBS data/005_Item.rb @@ -6,12 +6,12 @@ module GameData attr_reader :pocket attr_reader :price attr_reader :sell_price - attr_reader :real_description attr_reader :field_use attr_reader :battle_use attr_reader :flags attr_reader :consumable attr_reader :move + attr_reader :real_description DATA = {} DATA_FILENAME = "items.dat" @@ -23,14 +23,14 @@ module GameData "Pocket" => [:pocket, "v"], "Price" => [:price, "u"], "SellPrice" => [:sell_price, "u"], - "Description" => [:real_description, "q"], "FieldUse" => [:field_use, "e", { "OnPokemon" => 1, "Direct" => 2, "TM" => 3, "HM" => 4, "TR" => 5 }], "BattleUse" => [:battle_use, "e", { "OnPokemon" => 1, "OnMove" => 2, "OnBattler" => 3, "OnFoe" => 4, "Direct" => 5 }], "Flags" => [:flags, "*s"], "Consumable" => [:consumable, "b"], - "Move" => [:move, "e", :Move] + "Move" => [:move, "e", :Move], + "Description" => [:real_description, "q"] } extend ClassMethodsSymbols @@ -88,13 +88,13 @@ module GameData @pocket = hash[:pocket] || 1 @price = hash[:price] || 0 @sell_price = hash[:sell_price] || (@price / 2) - @real_description = hash[:real_description] || "???" @field_use = hash[:field_use] || 0 @battle_use = hash[:battle_use] || 0 @flags = hash[:flags] || [] @consumable = hash[:consumable] @consumable = !is_important? if @consumable.nil? @move = hash[:move] + @real_description = hash[:real_description] || "???" end # @return [String] the translated name of this item @@ -192,5 +192,20 @@ module GameData } return combos[species]&.include?(@id) end + + alias __orig__get_property_for_PBS get_property_for_PBS + def get_property_for_PBS(key) + ret = __orig__get_property_for_PBS(key) + case key + when "SellPrice" + ret = nil if ret == @price / 2 + when "FieldUse", "BattleUse" + ret = nil if ret == 0 + when "Consumable" + ret = @consumable + ret = nil if ret || is_important? # Only return false, only for non-important items + end + return ret + end end end diff --git a/Data/Scripts/010_Data/002_PBS data/007_Species.rb b/Data/Scripts/010_Data/002_PBS data/007_Species.rb index 91f02de10..8f0439b38 100644 --- a/Data/Scripts/010_Data/002_PBS data/007_Species.rb +++ b/Data/Scripts/010_Data/002_PBS data/007_Species.rb @@ -72,51 +72,60 @@ module GameData end def self.schema(compiling_forms = false) - ret = { - "FormName" => [:real_form_name, "q"], - "Category" => [:real_category, "s"], - "Pokedex" => [:real_pokedex_entry, "q"], - "Types" => [:types, "eE", :Type, :Type], - "BaseStats" => [:base_stats, "vvvvvv"], - "EVs" => [:evs, "*ev", :Stat], - "BaseExp" => [:base_exp, "v"], - "CatchRate" => [:catch_rate, "u"], - "Happiness" => [:happiness, "u"], - "Moves" => [:moves, "*ue", nil, :Move], - "TutorMoves" => [:tutor_moves, "*e", :Move], - "EggMoves" => [:egg_moves, "*e", :Move], - "Abilities" => [:abilities, "*e", :Ability], - "HiddenAbilities" => [:hidden_abilities, "*e", :Ability], - "WildItemCommon" => [:wild_item_common, "*e", :Item], - "WildItemUncommon" => [:wild_item_uncommon, "*e", :Item], - "WildItemRare" => [:wild_item_rare, "*e", :Item], - "EggGroups" => [:egg_groups, "*e", :EggGroup], - "HatchSteps" => [:hatch_steps, "v"], - "Height" => [:height, "f"], - "Weight" => [:weight, "f"], - "Color" => [:color, "e", :BodyColor], - "Shape" => [:shape, "e", :BodyShape], - "Habitat" => [:habitat, "e", :Habitat], - "Generation" => [:generation, "i"], - "Flags" => [:flags, "*s"] - } + ret = {} if compiling_forms - ret["SectionName"] = [:id, "ev", :Species] - ret["PokedexForm"] = [:pokedex_form, "u"] - ret["Offspring"] = [:offspring, "*e", :Species] - ret["Evolutions"] = [:evolutions, "*ees", :Species, :Evolution, nil] - ret["MegaStone"] = [:mega_stone, "e", :Item] - ret["MegaMove"] = [:mega_move, "e", :Move] - ret["UnmegaForm"] = [:unmega_form, "u"] - ret["MegaMessage"] = [:mega_message, "u"] + ret["SectionName"] = [:id, "ev", :Species] else - ret["SectionName"] = [:id, "m"] - ret["Name"] = [:real_name, "s"] - ret["GrowthRate"] = [:growth_rate, "e", :GrowthRate] - ret["GenderRatio"] = [:gender_ratio, "e", :GenderRatio] - ret["Incense"] = [:incense, "e", :Item] - ret["Offspring"] = [:offspring, "*s"] - ret["Evolutions"] = [:evolutions, "*ses", nil, :Evolution, nil] + ret["SectionName"] = [:id, "m"] + ret["Name"] = [:real_name, "s"] + end + ret["FormName"] = [:real_form_name, "q"] + if compiling_forms + ret["PokedexForm"] = [:pokedex_form, "u"] + ret["MegaStone"] = [:mega_stone, "e", :Item] + ret["MegaMove"] = [:mega_move, "e", :Move] + ret["UnmegaForm"] = [:unmega_form, "u"] + ret["MegaMessage"] = [:mega_message, "u"] + end + ret["Types"] = [:types, "eE", :Type, :Type] + ret["BaseStats"] = [:base_stats, "vvvvvv"] + if !compiling_forms + ret["GenderRatio"] = [:gender_ratio, "e", :GenderRatio] + ret["GrowthRate"] = [:growth_rate, "e", :GrowthRate] + end + ret["BaseExp"] = [:base_exp, "v"] + ret["EVs"] = [:evs, "*ev", :Stat] + ret["CatchRate"] = [:catch_rate, "u"] + ret["Happiness"] = [:happiness, "u"] + ret["Abilities"] = [:abilities, "*e", :Ability] + ret["HiddenAbilities"] = [:hidden_abilities, "*e", :Ability] + ret["Moves"] = [:moves, "*ue", nil, :Move] + ret["TutorMoves"] = [:tutor_moves, "*e", :Move] + ret["EggMoves"] = [:egg_moves, "*e", :Move] + ret["EggGroups"] = [:egg_groups, "*e", :EggGroup] + ret["HatchSteps"] = [:hatch_steps, "v"] + if compiling_forms + ret["Offspring"] = [:offspring, "*e", :Species] + else + ret["Incense"] = [:incense, "e", :Item] + ret["Offspring"] = [:offspring, "*s"] + end + ret["Height"] = [:height, "f"] + ret["Weight"] = [:weight, "f"] + ret["Color"] = [:color, "e", :BodyColor] + ret["Shape"] = [:shape, "e", :BodyShape] + ret["Habitat"] = [:habitat, "e", :Habitat] + ret["Category"] = [:real_category, "s"] + ret["Pokedex"] = [:real_pokedex_entry, "q"] + ret["Generation"] = [:generation, "i"] + ret["Flags"] = [:flags, "*s"] + ret["WildItemCommon"] = [:wild_item_common, "*e", :Item] + ret["WildItemUncommon"] = [:wild_item_uncommon, "*e", :Item] + ret["WildItemRare"] = [:wild_item_rare, "*e", :Item] + if compiling_forms + ret["Evolutions"] = [:evolutions, "*ees", :Species, :Evolution, nil] + else + ret["Evolutions"] = [:evolutions, "*ses", nil, :Evolution, nil] end return ret end @@ -332,5 +341,66 @@ module GameData end return 1 end + + alias __orig__get_property_for_PBS get_property_for_PBS + def get_property_for_PBS(key, writing_form = false) + ret = nil + if self.class.schema(writing_form).include?(key) + ret = self.send(self.class.schema(writing_form)[key][0]) + ret = nil if ret == false || (ret.is_a?(Array) && ret.length == 0) + end + case key + when "SectionName" + ret = [@species, @form] if writing_form + when "FormName" + ret = nil if nil_or_empty?(ret) + when "PokedexForm" + ret = nil if ret == @form + when "UnmegaForm", "MegaMessage", "Generation" + ret = nil if ret == 0 + when "BaseStats" + new_ret = [] + GameData::Stat.each_main do |s| + new_ret[s.pbs_order] = ret[s.id] if s.pbs_order >= 0 + end + ret = new_ret + when "EVs" + new_ret = [] + GameData::Stat.each_main do |s| + new_ret.push([s.id, ret[s.id]]) if ret[s.id] > 0 && s.pbs_order >= 0 + end + ret = new_ret + when "Height", "Weight" + ret = ret.to_f / 10 + when "Habitat" + ret = nil if ret == :None + when "Evolutions" + if ret + ret = ret.select { |evo| !evo[3] } # Remove prevolutions + ret.each do |evo| + param_type = GameData::Evolution.get(evo[1]).parameter + if !param_type.nil? + if param_type.is_a?(Symbol) && !GameData.const_defined?(param_type) + evo[2] = getConstantName(param_type, evo[2]) + else + evo[2] = evo[2].to_s + end + end + end + ret.each_with_index { |evo, i| ret[i] = evo[0, 3] } + ret = nil if ret.length == 0 + end + end + if writing_form && !ret.nil? + base_form = GameData::Species.get(@species) + if !["WildItemCommon", "WildItemUncommon", "WildItemRare"].include?(key) || + (base_form.wild_item_common == @wild_item_common && + base_form.wild_item_uncommon == @wild_item_uncommon && + base_form.wild_item_rare == @wild_item_rare) + ret = nil if base_form.get_property_for_PBS(key) == ret + end + end + return ret + end end end diff --git a/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb b/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb index 910f5a043..b4ac39e60 100644 --- a/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb +++ b/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb @@ -84,5 +84,17 @@ module GameData return true # return @front_sprite_altitude > 0 end + + alias __orig__get_property_for_PBS get_property_for_PBS + def get_property_for_PBS(key) + ret = __orig__get_property_for_PBS(key) + case key + when "SectionName" + ret = [@species, (@form > 0) ? @form : nil] + when "FrontSpriteAltitude" + ret = nil if ret == 0 + end + return ret + end end end diff --git a/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb b/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb index 1fec8d4e8..df630e740 100644 --- a/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb +++ b/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb @@ -103,5 +103,12 @@ 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 + def get_property_for_PBS(key) + ret = __orig__get_property_for_PBS(key) + ret = nil if key == "SkillLevel" && ret == @base_money + return ret + end end end diff --git a/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb b/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb index 44285c04f..df0d4663e 100644 --- a/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb +++ b/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb @@ -37,8 +37,8 @@ module GameData "MaxRoomSize" => [:max_room_size, "vv"], "CorridorWidth" => [:corridor_width, "v"], "ShiftCorridors" => [:random_corridor_shift, "b"], - "NodeLayout" => [:node_layout, "s"], - "RoomLayout" => [:room_layout, "s"], + "NodeLayout" => [:node_layout, "m"], + "RoomLayout" => [:room_layout, "m"], "RoomChance" => [:room_chance, "v"], "ExtraConnections" => [:extra_connections_count, "u"], "FloorPatches" => [:floor_patches, "vvu"], @@ -78,8 +78,8 @@ module GameData @room_max_height = (hash[:max_room_size]) ? hash[:max_room_size][1] : @cell_height - 1 @corridor_width = hash[:corridor_width] || 2 @random_corridor_shift = hash[:random_corridor_shift] - @node_layout = hash[:node_layout]&.downcase&.to_sym || :full - @room_layout = hash[:room_layout]&.downcase&.to_sym || :full + @node_layout = hash[:node_layout] || :full + @room_layout = hash[:room_layout] || :full @room_chance = hash[:room_chance] || 70 @extra_connections_count = hash[:extra_connections_count] || 2 @floor_patch_radius = (hash[:floor_patches]) ? hash[:floor_patches][0] : 3 @@ -115,25 +115,19 @@ module GameData return width, height end - def property_from_string(str) - case str + alias __orig__get_property_for_PBS get_property_for_PBS + def get_property_for_PBS(key) + case key + when "SectionName" then return [@area, (@version > 0) ? @version : nil] when "DungeonSize" then return [@cell_count_x, @cell_count_y] when "CellSize" then return [@cell_width, @cell_height] when "MinRoomSize" then return [@room_min_width, @room_min_height] when "MaxRoomSize" then return [@room_max_width, @room_max_height] - when "CorridorWidth" then return @corridor_width - when "ShiftCorridors" then return @random_corridor_shift - when "NodeLayout" then return @node_layout - when "RoomLayout" then return @room_layout - when "RoomChance" then return @room_chance - when "ExtraConnections" then return @extra_connections_count when "FloorPatches" then return [@floor_patch_radius, @floor_patch_chance, @floor_patch_smooth_rate] when "FloorDecorations" then return [@floor_decoration_density, @floor_decoration_large_density] when "VoidDecorations" then return [@void_decoration_density, @void_decoration_large_density] - when "RNGSeed" then return @rng_seed - when "Flags" then return @flags end - return nil + return __orig__get_property_for_PBS(key) end end end diff --git a/Data/Scripts/021_Compiler/001_Compiler.rb b/Data/Scripts/021_Compiler/001_Compiler.rb index d0c1c4c3f..72f74a5da 100644 --- a/Data/Scripts/021_Compiler/001_Compiler.rb +++ b/Data/Scripts/021_Compiler/001_Compiler.rb @@ -573,12 +573,18 @@ module Compiler loop do (start...schema[1].length).each do |i| index += 1 - file.write(",") if index > 0 value = rec[index] + if schema[1][i, 1].upcase != schema[1][i, 1] || !value.nil? + file.write(",") if index > 0 + end if value.nil? # do nothing elsif value.is_a?(String) - file.write(csvQuote(value)) + if schema[1][i, 1].downcase == "q" + file.write(value) + else + file.write(csvQuote(value)) + end elsif value.is_a?(Symbol) file.write(csvQuote(value.to_s)) elsif value == true diff --git a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb index 4f5ce6cc8..ec31f3d51 100644 --- a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb +++ b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb @@ -8,6 +8,34 @@ module Compiler file.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n") end + def write_PBS_file_generic(game_data, path) + write_pbs_file_message_start(path) + schema = game_data::SCHEMA + File.open(path, "wb") { |f| + add_PBS_header_to_file(f) + # Write each element in turn + game_data.each do |element| + f.write("\#-------------------------------\r\n") + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") + end + schema.each_key do |key| + next if key == "SectionName" + 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 + } + process_pbs_file_message_end + end + #============================================================================= # Save Town Map data to PBS file #============================================================================= @@ -131,126 +159,35 @@ module Compiler # Save type data to PBS file #============================================================================= def write_types(path = "PBS/types.txt") - write_pbs_file_message_start(path) - File.open(path, "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}]\r\n") - f.write("Name = #{type.real_name}\r\n") - f.write("IconPosition = #{type.icon_position}\r\n") - f.write("IsSpecialType = true\r\n") if type.special? - f.write("IsPseudoType = true\r\n") if type.pseudo_type - f.write(sprintf("Flags = %s\r\n", type.flags.join(","))) if type.flags.length > 0 - 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 - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::Type, path) end #============================================================================= # Save ability data to PBS file #============================================================================= def write_abilities(path = "PBS/abilities.txt") - write_pbs_file_message_start(path) - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each ability in turn - GameData::Ability.each do |ability| - f.write("\#-------------------------------\r\n") - f.write("[#{ability.id}]\r\n") - f.write("Name = #{ability.real_name}\r\n") - f.write("Description = #{ability.real_description}\r\n") - f.write(sprintf("Flags = %s\r\n", ability.flags.join(","))) if ability.flags.length > 0 - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::Ability, path) end #============================================================================= # Save move data to PBS file #============================================================================= def write_moves(path = "PBS/moves.txt") - write_pbs_file_message_start(path) - File.open(path, "wb") { |f| - idx = 0 - add_PBS_header_to_file(f) - # Write each move in turn - GameData::Move.each do |move| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - f.write("\#-------------------------------\r\n") - f.write("[#{move.id}]\r\n") - f.write("Name = #{move.real_name}\r\n") - f.write("Type = #{move.type}\r\n") - category = GameData::Move::SCHEMA["Category"][2][move.category] - f.write("Category = #{category}\r\n") - f.write("Power = #{move.base_damage}\r\n") if move.base_damage > 0 - f.write("Accuracy = #{move.accuracy}\r\n") - f.write("TotalPP = #{move.total_pp}\r\n") - f.write("Target = #{move.target}\r\n") - f.write("Priority = #{move.priority}\r\n") if move.priority != 0 - f.write("FunctionCode = #{move.function_code}\r\n") - f.write("Flags = #{move.flags.join(',')}\r\n") if move.flags.length > 0 - f.write("EffectChance = #{move.effect_chance}\r\n") if move.effect_chance > 0 - f.write("Description = #{move.real_description}\r\n") - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::Move, path) end #============================================================================= # Save item data to PBS file #============================================================================= def write_items(path = "PBS/items.txt") - write_pbs_file_message_start(path) - File.open(path, "wb") { |f| - idx = 0 - add_PBS_header_to_file(f) - GameData::Item.each do |item| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - f.write("\#-------------------------------\r\n") - f.write(sprintf("[%s]\r\n", item.id)) - f.write(sprintf("Name = %s\r\n", item.real_name)) - f.write(sprintf("NamePlural = %s\r\n", item.real_name_plural)) - f.write(sprintf("Pocket = %d\r\n", item.pocket)) - f.write(sprintf("Price = %d\r\n", item.price)) - f.write(sprintf("SellPrice = %d\r\n", item.sell_price)) if item.sell_price != item.price / 2 - field_use = GameData::Item::SCHEMA["FieldUse"][2].key(item.field_use) - f.write(sprintf("FieldUse = %s\r\n", field_use)) if field_use - battle_use = GameData::Item::SCHEMA["BattleUse"][2].key(item.battle_use) - f.write(sprintf("BattleUse = %s\r\n", battle_use)) if battle_use - f.write(sprintf("Consumable = false\r\n")) if !item.is_important? && !item.consumable - f.write(sprintf("Flags = %s\r\n", item.flags.join(","))) if item.flags.length > 0 - f.write(sprintf("Move = %s\r\n", item.move)) if item.move - f.write(sprintf("Description = %s\r\n", item.real_description)) - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::Item, path) end #============================================================================= # Save berry plant data to PBS file #============================================================================= def write_berry_plants(path = "PBS/berry_plants.txt") - write_pbs_file_message_start(path) - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - GameData::BerryPlant.each do |bp| - f.write("\#-------------------------------\r\n") - f.write(sprintf("[%s]\r\n", bp.id)) - f.write(sprintf("HoursPerStage = %d\r\n", bp.hours_per_stage)) - f.write(sprintf("DryingPerHour = %d\r\n", bp.drying_per_hour)) - f.write(sprintf("Yield = %s\r\n", bp.yield.join(","))) - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::BerryPlant, path) end #============================================================================= @@ -258,85 +195,25 @@ module Compiler #============================================================================= def write_pokemon(path = "PBS/pokemon.txt") write_pbs_file_message_start(path) + schema = GameData::Species.schema File.open(path, "wb") { |f| - idx = 0 add_PBS_header_to_file(f) - GameData::Species.each_species do |species| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 + # Write each element in turn + GameData::Species.each_species do |element| f.write("\#-------------------------------\r\n") - f.write(sprintf("[%s]\r\n", species.id)) - f.write(sprintf("Name = %s\r\n", species.real_name)) - f.write(sprintf("Types = %s\r\n", species.types.uniq.compact.join(","))) - stats_array = [] - evs_array = [] - GameData::Stat.each_main do |s| - next if s.pbs_order < 0 - stats_array[s.pbs_order] = species.base_stats[s.id] - evs_array.concat([s.id.to_s, species.evs[s.id]]) if species.evs[s.id] > 0 + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") end - f.write(sprintf("BaseStats = %s\r\n", stats_array.join(","))) - f.write(sprintf("GenderRatio = %s\r\n", species.gender_ratio)) - f.write(sprintf("GrowthRate = %s\r\n", species.growth_rate)) - f.write(sprintf("BaseExp = %d\r\n", species.base_exp)) - f.write(sprintf("EVs = %s\r\n", evs_array.join(","))) - f.write(sprintf("CatchRate = %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("HiddenAbilities = %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(sprintf("EggGroups = %s\r\n", species.egg_groups.join(","))) - end - f.write(sprintf("HatchSteps = %d\r\n", species.hatch_steps)) - f.write(sprintf("Incense = %s\r\n", species.incense)) if species.incense - if species.offspring.length > 0 - f.write(sprintf("Offspring = %s\r\n", species.offspring.join(","))) - end - 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", species.color)) - f.write(sprintf("Shape = %s\r\n", species.shape)) - f.write(sprintf("Habitat = %s\r\n", species.habitat)) if species.habitat != :None - f.write(sprintf("Category = %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("Flags = %s\r\n", species.flags.join(","))) if species.flags.length > 0 - f.write(sprintf("WildItemCommon = %s\r\n", species.wild_item_common.join(","))) if species.wild_item_common.length > 0 - f.write(sprintf("WildItemUncommon = %s\r\n", species.wild_item_uncommon.join(","))) if species.wild_item_uncommon.length > 0 - f.write(sprintf("WildItemRare = %s\r\n", species.wild_item_rare.join(","))) if species.wild_item_rare.length > 0 - 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 - evo_type_data = GameData::Evolution.get(evo[1]) - param_type = evo_type_data.parameter - f.write(sprintf("%s,%s,", evo[0], evo_type_data.id.to_s)) - if !param_type.nil? - if param_type.is_a?(Symbol) && !GameData.const_defined?(param_type) - f.write(getConstantName(param_type, evo[2])) - else - f.write(evo[2].to_s) - end - end - end + schema.each_key do |key| + next if key == "SectionName" + 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 @@ -349,96 +226,26 @@ module Compiler #============================================================================= def write_pokemon_forms(path = "PBS/pokemon_forms.txt") write_pbs_file_message_start(path) + schema = GameData::Species.schema(true) File.open(path, "wb") { |f| - idx = 0 add_PBS_header_to_file(f) - GameData::Species.each do |species| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - next if species.form == 0 - base_species = GameData::Species.get(species.species) + # Write each element in turn + GameData::Species.each do |element| + next if element.form == 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.types.uniq.compact != base_species.types.uniq.compact - f.write(sprintf("Types = %s\r\n", species.types.uniq.compact.join(","))) + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName", true), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") end - stats_array = [] - evs_array = [] - GameData::Stat.each_main do |s| - next if s.pbs_order < 0 - stats_array[s.pbs_order] = species.base_stats[s.id] - evs_array.concat([s.id.to_s, species.evs[s.id]]) if species.evs[s.id] > 0 - end - f.write(sprintf("BaseStats = %s\r\n", stats_array.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("EVs = %s\r\n", evs_array.join(","))) if species.evs != base_species.evs - f.write(sprintf("CatchRate = %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("HiddenAbilities = %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(sprintf("EggGroups = %s\r\n", species.egg_groups.join(","))) - end - f.write(sprintf("HatchSteps = %d\r\n", species.hatch_steps)) if species.hatch_steps != base_species.hatch_steps - if species.offspring.length > 0 && species.offspring != base_species.offspring - f.write(sprintf("Offspring = %s\r\n", species.offspring.join(","))) - end - 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", species.color)) if species.color != base_species.color - f.write(sprintf("Shape = %s\r\n", species.shape)) if species.shape != base_species.shape - if species.habitat != :None && species.habitat != base_species.habitat - f.write(sprintf("Habitat = %s\r\n", species.habitat)) - end - f.write(sprintf("Category = %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 - f.write(sprintf("Flags = %s\r\n", species.flags.join(","))) if species.flags.length > 0 && species.flags != base_species.flags - 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.join(","))) if species.wild_item_common.length > 0 - f.write(sprintf("WildItemUncommon = %s\r\n", species.wild_item_uncommon.join(","))) if species.wild_item_uncommon.length > 0 - f.write(sprintf("WildItemRare = %s\r\n", species.wild_item_rare.join(","))) if species.wild_item_rare.length > 0 - end - 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 - evo_type_data = GameData::Evolution.get(evo[1]) - param_type = evo_type_data.parameter - f.write(sprintf("%s,%s,", evo[0], evo_type_data.id.to_s)) - if !param_type.nil? - if param_type.is_a?(Symbol) && !GameData.const_defined?(param_type) - f.write(getConstantName(param_type, evo[2])) - else - f.write(evo[2].to_s) - end - end - end + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key, true) + next if val.nil? + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) f.write("\r\n") end end @@ -451,48 +258,39 @@ module Compiler #============================================================================= def write_pokemon_metrics(path = "PBS/pokemon_metrics.txt") write_pbs_file_message_start(path) - # Get in species order then in form order - sort_array = [] - dex_numbers = {} - i = 0 - GameData::SpeciesMetrics.each do |metrics| - dex_numbers[metrics.species] = i if !dex_numbers[metrics.species] - sort_array.push([dex_numbers[metrics.species], metrics.id, metrics.species, metrics.form]) - i += 1 - end - sort_array.sort! { |a, b| (a[0] == b[0]) ? a[3] <=> b[3] : a[0] <=> b[0] } - # Write file + schema = GameData::SpeciesMetrics::SCHEMA File.open(path, "wb") { |f| - idx = 0 add_PBS_header_to_file(f) - sort_array.each do |val| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - species = GameData::SpeciesMetrics.get(val[1]) - if species.form > 0 - base_species = GameData::SpeciesMetrics.get(val[2]) - next if species.back_sprite == base_species.back_sprite && - species.front_sprite == base_species.front_sprite && - species.front_sprite_altitude == base_species.front_sprite_altitude && - species.shadow_x == base_species.shadow_x && - species.shadow_size == base_species.shadow_size + # Write each element in turn + GameData::SpeciesMetrics.each do |element| + if element.form > 0 + base_element = GameData::SpeciesMetrics.get(element.species) + next if element.back_sprite == base_element.back_sprite && + element.front_sprite == base_element.front_sprite && + element.front_sprite_altitude == base_element.front_sprite_altitude && + element.shadow_x == base_element.shadow_x && + element.shadow_size == base_element.shadow_size else - next if species.back_sprite == [0, 0] && species.front_sprite == [0, 0] && - species.front_sprite_altitude == 0 && - species.shadow_x == 0 && species.shadow_size == 2 + next if element.back_sprite == [0, 0] && element.front_sprite == [0, 0] && + element.front_sprite_altitude == 0 && + element.shadow_x == 0 && element.shadow_size == 2 end f.write("\#-------------------------------\r\n") - if species.form > 0 - f.write(sprintf("[%s,%d]\r\n", species.species, species.form)) + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") else - f.write(sprintf("[%s]\r\n", species.species)) + f.write("[#{element.id}]\r\n") + end + schema.each_key do |key| + next if key == "SectionName" + 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 - f.write(sprintf("BackSprite = %s\r\n", species.back_sprite.join(","))) - f.write(sprintf("FrontSprite = %s\r\n", species.front_sprite.join(","))) - f.write(sprintf("FrontSpriteAltitude = %d\r\n", species.front_sprite_altitude)) if species.front_sprite_altitude != 0 - f.write(sprintf("ShadowX = %d\r\n", species.shadow_x)) - f.write(sprintf("ShadowSize = %d\r\n", species.shadow_size)) end } process_pbs_file_message_end @@ -502,21 +300,7 @@ module Compiler # Save Shadow Pokémon data to PBS file #============================================================================= def write_shadow_pokemon(path = "PBS/shadow_pokemon.txt") - write_pbs_file_message_start(path) - File.open(path, "wb") { |f| - idx = 0 - add_PBS_header_to_file(f) - GameData::ShadowPokemon.each do |shadow| - echo "." if idx % 150 == 0 - idx += 1 - f.write("\#-------------------------------\r\n") - f.write(sprintf("[%s]\r\n", shadow.id)) - f.write(sprintf("GaugeSize = %d\r\n", shadow.gauge_size)) - f.write(sprintf("Moves = %s\r\n", shadow.moves.join(","))) if shadow.moves.length > 0 - f.write(sprintf("Flags = %s\r\n", shadow.flags.join(","))) if shadow.flags.length > 0 - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::ShadowPokemon, path) end #============================================================================= @@ -555,20 +339,7 @@ module Compiler # Save ability data to PBS file #============================================================================= def write_ribbons(path = "PBS/ribbons.txt") - write_pbs_file_message_start(path) - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each ability in turn - GameData::Ribbon.each do |ribbon| - f.write("\#-------------------------------\r\n") - f.write("[#{ribbon.id}]\r\n") - f.write("Name = #{ribbon.real_name}\r\n") - f.write("IconPosition = #{ribbon.icon_position}\r\n") - f.write("Description = #{ribbon.real_description}\r\n") - f.write(sprintf("Flags = %s\r\n", ribbon.flags.join(","))) if ribbon.flags.length > 0 - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::Ribbon, path) end #============================================================================= @@ -615,24 +386,7 @@ module Compiler # Save trainer type data to PBS file #============================================================================= def write_trainer_types(path = "PBS/trainer_types.txt") - write_pbs_file_message_start(path) - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - GameData::TrainerType.each do |t| - f.write("\#-------------------------------\r\n") - f.write(sprintf("[%s]\r\n", t.id)) - f.write(sprintf("Name = %s\r\n", t.real_name)) - gender = GameData::TrainerType::SCHEMA["Gender"][2].key(t.gender) - f.write(sprintf("Gender = %s\r\n", gender)) - f.write(sprintf("BaseMoney = %d\r\n", t.base_money)) - f.write(sprintf("SkillLevel = %d\r\n", t.skill_level)) if t.skill_level != t.base_money - f.write(sprintf("Flags = %s\r\n", t.flags.join(","))) if t.flags.length > 0 - f.write(sprintf("IntroBGM = %s\r\n", t.intro_BGM)) if !nil_or_empty?(t.intro_BGM) - f.write(sprintf("BattleBGM = %s\r\n", t.battle_BGM)) if !nil_or_empty?(t.battle_BGM) - f.write(sprintf("VictoryBGM = %s\r\n", t.victory_BGM)) if !nil_or_empty?(t.victory_BGM) - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::TrainerType, path) end #============================================================================= @@ -805,31 +559,31 @@ module Compiler #============================================================================= def write_metadata(path = "PBS/metadata.txt") write_pbs_file_message_start(path) + global_schema = GameData::Metadata::SCHEMA + player_schema = GameData::PlayerMetadata::SCHEMA File.open(path, "wb") { |f| add_PBS_header_to_file(f) - # Write metadata - f.write("\#-------------------------------\r\n") - f.write("[0]\r\n") - metadata = GameData::Metadata.get - schema = GameData::Metadata::SCHEMA - schema.keys.each do |key| - record = metadata.property_from_string(key) - next if record.nil? || (record.is_a?(Array) && record.empty?) - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(record, f, schema[key]) - f.write("\r\n") - end - # Write player metadata - schema = GameData::PlayerMetadata::SCHEMA - GameData::PlayerMetadata.each do |player_data| - f.write("\#-------------------------------\r\n") - f.write(sprintf("[%d]\r\n", player_data.id)) - schema.keys.each do |key| - record = player_data.property_from_string(key) - next if record.nil? || (record.is_a?(Array) && record.empty?) - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(record, f, schema[key]) - f.write("\r\n") + # Write each element in turn + [GameData::Metadata, GameData::PlayerMetadata].each do |game_data| + schema = global_schema if game_data == GameData::Metadata + schema = player_schema if game_data == GameData::PlayerMetadata + game_data.each do |element| + f.write("\#-------------------------------\r\n") + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") + end + schema.each_key do |key| + next if key == "SectionName" + 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 end } @@ -846,23 +600,21 @@ module Compiler File.open(path, "wb") { |f| idx = 0 add_PBS_header_to_file(f) - GameData::MapMetadata.each do |map_data| + GameData::MapMetadata.each do |element| echo "." if idx % 50 == 0 idx += 1 Graphics.update if idx % 250 == 0 f.write("\#-------------------------------\r\n") - map_name = (map_infos && map_infos[map_data.id]) ? map_infos[map_data.id].name : nil - if map_name - f.write(sprintf("[%03d] # %s\r\n", map_data.id, map_name)) - f.write("Name = #{map_name}\r\n") if nil_or_empty?(map_data.real_name) - else - f.write(sprintf("[%03d]\r\n", map_data.id)) - end - schema.keys.each do |key| - record = map_data.property_from_string(key) - next if record.nil? || (record.is_a?(Array) && record.empty?) + map_name = (map_infos && map_infos[element.id]) ? map_infos[element.id].name : nil + f.write(sprintf("[%03d]", element.id)) + f.write(sprintf(" # %s", map_name)) if map_name + f.write("\r\n") + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key) + next if val.nil? f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(record, f, schema[key]) + pbWriteCsvRecord(val, f, schema[key]) f.write("\r\n") end end @@ -926,33 +678,7 @@ module Compiler # Save dungeon parameters to PBS file #============================================================================= def write_dungeon_parameters(path = "PBS/dungeon_parameters.txt") - write_pbs_file_message_start(path) - schema = GameData::DungeonParameters::SCHEMA - keys = schema.keys - # Write file - File.open(path, "wb") { |f| - idx = 0 - add_PBS_header_to_file(f) - GameData::DungeonParameters.each do |parameters_data| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - f.write("\#-------------------------------\r\n") - if parameters_data.version > 0 - f.write(sprintf("[%s,%d]\r\n", parameters_data.area, parameters_data.version)) - else - f.write(sprintf("[%s]\r\n", parameters_data.area)) - end - keys.each do |key| - value = parameters_data.property_from_string(key) - next if !value || (value.is_a?(Array) && value.length == 0) - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(value, f, schema[key]) - f.write("\r\n") - end - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::DungeonParameters, path) end #============================================================================= diff --git a/PBS/abilities.txt b/PBS/abilities.txt index 5af587cb2..d18729217 100644 --- a/PBS/abilities.txt +++ b/PBS/abilities.txt @@ -158,8 +158,8 @@ Description = The Pokémon is protected from flinching. #------------------------------- [MAGMAARMOR] Name = Magma Armor -Flags = FasterEggHatching Description = Prevents the Pokémon from becoming frozen. +Flags = FasterEggHatching #------------------------------- [WATERVEIL] Name = Water Veil @@ -195,8 +195,8 @@ Description = The Pokémon awakens quickly from sleep. #------------------------------- [FLAMEBODY] Name = Flame Body -Flags = FasterEggHatching Description = Contact with the Pokémon may burn the attacker. +Flags = FasterEggHatching #------------------------------- [RUNAWAY] Name = Run Away @@ -972,8 +972,8 @@ Description = This Pokémon's moves cannot be redirected. #------------------------------- [STEAMENGINE] Name = Steam Engine -Flags = FasterEggHatching Description = Boosts Speed drastically if hit by a Fire or Water move. +Flags = FasterEggHatching #------------------------------- [PUNKROCK] Name = Punk Rock @@ -1069,4 +1069,4 @@ Description = Combines Unnerve and Chilling Neigh Abilities. #------------------------------- [ASONEGRIMNEIGH] Name = As One -Description = Combines Unnerve and Grim Neigh Abilities. \ No newline at end of file +Description = Combines Unnerve and Grim Neigh Abilities. diff --git a/PBS/items.txt b/PBS/items.txt index e1459fa97..a1cdb6091 100644 --- a/PBS/items.txt +++ b/PBS/items.txt @@ -33,8 +33,8 @@ NamePlural = Black Flutes Pocket = 1 Price = 20 FieldUse = Direct -Consumable = false Flags = Fling_30 +Consumable = false Description = A black flute made from blown glass. Its melody makes wild Pokémon less likely to appear. #------------------------------- [WHITEFLUTE] @@ -43,8 +43,8 @@ NamePlural = White Flutes Pocket = 1 Price = 20 FieldUse = Direct -Consumable = false Flags = Fling_30 +Consumable = false Description = A white flute made from blown glass. Its melody makes wild Pokémon more likely to appear. #------------------------------- [HONEY] @@ -5695,8 +5695,8 @@ Pocket = 7 Price = 20 FieldUse = OnPokemon BattleUse = OnPokemon -Consumable = false Flags = Fling_30 +Consumable = false Description = A blue flute made from blown glass. Its melody awakens a single Pokémon from sleep. #------------------------------- [YELLOWFLUTE] @@ -5705,8 +5705,8 @@ NamePlural = Yellow Flutes Pocket = 7 Price = 20 BattleUse = OnBattler -Consumable = false Flags = Fling_30 +Consumable = false Description = A yellow flute made from blown glass. Its melody snaps a single Pokémon out of confusion. #------------------------------- [REDFLUTE] @@ -5715,8 +5715,8 @@ NamePlural = Red Flutes Pocket = 7 Price = 20 BattleUse = OnBattler -Consumable = false Flags = Fling_30 +Consumable = false Description = A red flute made from blown glass. Its melody snaps a single Pokémon out of infatuation. #------------------------------- [POKEDOLL] diff --git a/PBS/metadata.txt b/PBS/metadata.txt index 90ee730a1..5647de8c0 100644 --- a/PBS/metadata.txt +++ b/PBS/metadata.txt @@ -18,7 +18,9 @@ WalkCharset = trainer_POKEMONTRAINER_Red RunCharset = boy_run CycleCharset = boy_bike SurfCharset = boy_surf +DiveCharset = boy_surf FishCharset = boy_fish_offset +SurfFishCharset = boy_fish_offset #------------------------------- [2] TrainerType = POKEMONTRAINER_Leaf @@ -26,4 +28,6 @@ WalkCharset = trainer_POKEMONTRAINER_Leaf RunCharset = girl_run CycleCharset = girl_bike SurfCharset = girl_surf +DiveCharset = girl_surf FishCharset = girl_fish_offset +SurfFishCharset = girl_fish_offset diff --git a/PBS/pokemon.txt b/PBS/pokemon.txt index 28c1ab2b5..43012e95f 100644 --- a/PBS/pokemon.txt +++ b/PBS/pokemon.txt @@ -5279,6 +5279,7 @@ Evolutions = MISMAGIUS,Item,DUSKSTONE #------------------------------- [UNOWN] Name = Unown +FormName = A Types = PSYCHIC BaseStats = 48,72,48,48,72,48 GenderRatio = Genderless @@ -5299,7 +5300,6 @@ Shape = Head Habitat = Rare Category = Symbol Pokedex = This Pokémon is shaped like ancient text characters. Although research is ongoing, it is a mystery as to which came first, the ancient writings or the various Unown. -FormName = A Generation = 2 #------------------------------- [WOBBUFFET] @@ -9238,6 +9238,7 @@ Generation = 3 #------------------------------- [CASTFORM] Name = Castform +FormName = Normal Form Types = NORMAL BaseStats = 70,70,70,70,70,70 GenderRatio = Female50Percent @@ -9259,7 +9260,6 @@ Shape = Head Habitat = Grassland Category = Weather Pokedex = It alters its form depending on the weather. Changes in the climate such as the temperature and humidity appear to affect its cellular structure. -FormName = Normal Form Generation = 3 WildItemCommon = MYSTICWATER WildItemUncommon = MYSTICWATER @@ -10156,6 +10156,7 @@ WildItemRare = STARPIECE #------------------------------- [DEOXYS] Name = Deoxys +FormName = Normal Forme Types = PSYCHIC BaseStats = 50,150,50,150,150,50 GenderRatio = Genderless @@ -10176,7 +10177,6 @@ Shape = Bipedal Habitat = Rare Category = DNA Pokedex = A Pokémon that mutated from an extraterrestrial virus exposed to a laser beam. Its body is configured for superior agility and speed. -FormName = Normal Forme Generation = 3 #------------------------------- [TURTWIG] @@ -10810,6 +10810,7 @@ Generation = 4 #------------------------------- [BURMY] Name = Burmy +FormName = Plant Cloak Types = BUG BaseStats = 40,29,45,36,29,45 GenderRatio = Female50Percent @@ -10830,13 +10831,13 @@ Color = Green Shape = HeadBase Category = Bagworm Pokedex = To shelter itself from cold, wintry winds, it covers itself with a cloak made of twigs and leaves. -FormName = Plant Cloak Generation = 4 Flags = InheritFormFromMother Evolutions = WORMADAM,LevelFemale,20,MOTHIM,LevelMale,20 #------------------------------- [WORMADAM] Name = Wormadam +FormName = Plant Cloak Types = BUG,GRASS BaseStats = 60,59,85,36,79,105 GenderRatio = AlwaysFemale @@ -10857,7 +10858,6 @@ Color = Green Shape = HeadBase Category = Bagworm Pokedex = When Burmy evolved, its cloak became a part of this Pokémon's body. The cloak is never shed. -FormName = Plant Cloak Generation = 4 Flags = InheritFormFromMother WildItemUncommon = SILVERPOWDER @@ -11042,6 +11042,7 @@ Evolutions = CHERRIM,Level,25 #------------------------------- [CHERRIM] Name = Cherrim +FormName = Overcast Form Types = GRASS BaseStats = 70,60,70,85,87,78 GenderRatio = Female50Percent @@ -11061,12 +11062,12 @@ Color = Purple Shape = HeadLegs Category = Blossom Pokedex = Its folded petals are pretty tough. Bird Pokémon can peck at them all they want, and Cherrim won't be bothered at all. -FormName = Overcast Form Generation = 4 WildItemUncommon = MIRACLESEED #------------------------------- [SHELLOS] Name = Shellos +FormName = West Sea Types = WATER BaseStats = 76,48,48,34,57,62 GenderRatio = Female50Percent @@ -11088,13 +11089,13 @@ Color = Purple Shape = Serpentine Category = Sea Slug Pokedex = This Pokémon's habitat shapes its physique. According to some theories, life in warm ocean waters causes this variation to develop. -FormName = West Sea Generation = 4 Flags = InheritFormFromMother Evolutions = GASTRODON,Level,30 #------------------------------- [GASTRODON] Name = Gastrodon +FormName = West Sea Types = WATER,GROUND BaseStats = 111,83,68,39,92,82 GenderRatio = Female50Percent @@ -11115,7 +11116,6 @@ Color = Purple Shape = Serpentine Category = Sea Slug Pokedex = Its search for food sometimes leads it onto land, where it leaves behind a sticky trail of slime as it passes through. -FormName = West Sea Generation = 4 Flags = InheritFormFromMother #------------------------------- @@ -12505,6 +12505,7 @@ Generation = 4 #------------------------------- [ROTOM] Name = Rotom +FormName = Rotom Types = ELECTRIC,GHOST BaseStats = 50,50,77,91,95,77 GenderRatio = Genderless @@ -12524,7 +12525,6 @@ Color = Red Shape = Head Category = Plasma Pokedex = Its body is composed of plasma. It is known to infiltrate electronic devices and wreak havoc. -FormName = Rotom Generation = 4 #------------------------------- [UXIE] @@ -12693,6 +12693,7 @@ Generation = 4 #------------------------------- [GIRATINA] Name = Giratina +FormName = Altered Forme Types = GHOST,DRAGON BaseStats = 150,100,120,90,100,120 GenderRatio = Genderless @@ -12713,7 +12714,6 @@ Color = Black Shape = Multiped Category = Renegade Pokedex = A Pokémon that is said to live in a world on the reverse side of ours. It appears in an ancient cemetery. -FormName = Altered Forme Generation = 4 #------------------------------- [CRESSELIA] @@ -12811,6 +12811,7 @@ Generation = 4 #------------------------------- [SHAYMIN] Name = Shaymin +FormName = Land Forme Types = GRASS BaseStats = 100,100,100,100,100,100 GenderRatio = Genderless @@ -12830,7 +12831,6 @@ Color = Green Shape = Quadruped Category = Gratitude Pokedex = It lives in flower patches and avoids detection by curling up to look like a flowering plant. -FormName = Land Forme Generation = 4 WildItemCommon = LUMBERRY WildItemUncommon = LUMBERRY @@ -12838,6 +12838,7 @@ WildItemRare = LUMBERRY #------------------------------- [ARCEUS] Name = Arceus +FormName = Normal Type Types = NORMAL BaseStats = 120,120,120,120,120,120 GenderRatio = Genderless @@ -12857,7 +12858,6 @@ Color = White Shape = Quadruped Category = Alpha Pokedex = It is described in mythology as the Pokémon that shaped the universe with its 1,000 arms. -FormName = Normal Type Generation = 4 #------------------------------- [VICTINI] @@ -14278,6 +14278,7 @@ WildItemUncommon = ABSORBBULB #------------------------------- [BASCULIN] Name = Basculin +FormName = Red-Striped Types = WATER BaseStats = 70,92,65,98,80,55 GenderRatio = Female50Percent @@ -14299,7 +14300,6 @@ Color = Green Shape = Finned Category = Hostile Pokedex = Savage, violent Pokémon, red and blue Basculin are always fighting each other over territory. -FormName = Red-Striped Generation = 5 Flags = InheritFormFromMother WildItemUncommon = DEEPSEATOOTH @@ -14410,6 +14410,7 @@ Evolutions = DARMANITAN,Level,35 #------------------------------- [DARMANITAN] Name = Darmanitan +FormName = Standard Mode Types = FIRE BaseStats = 105,140,55,95,30,55 GenderRatio = Female50Percent @@ -14430,7 +14431,6 @@ Color = Red Shape = Quadruped Category = Blazing Pokedex = When weakened in battle, it transforms into a stone statue. Then it sharpens its mind and fights on mentally. -FormName = Standard Mode Generation = 5 #------------------------------- [MARACTUS] @@ -15167,6 +15167,7 @@ WildItemCommon = NEVERMELTICE #------------------------------- [DEERLING] Name = Deerling +FormName = Spring Form Types = NORMAL,GRASS BaseStats = 60,60,50,75,40,50 GenderRatio = Female50Percent @@ -15188,12 +15189,12 @@ Color = Pink Shape = Quadruped Category = Season Pokedex = The turning of the seasons changes the color and scent of this Pokémon's fur. People use it to mark the seasons. -FormName = Spring Form Generation = 5 Evolutions = SAWSBUCK,Level,34 #------------------------------- [SAWSBUCK] Name = Sawsbuck +FormName = Spring Form Types = NORMAL,GRASS BaseStats = 80,100,70,95,60,70 GenderRatio = Female50Percent @@ -15214,7 +15215,6 @@ Color = Brown Shape = Quadruped Category = Season Pokedex = The plants growing on its horns change according to the season. The leaders of the herd possess magnificent horns. -FormName = Spring Form Generation = 5 #------------------------------- [EMOLGA] @@ -16564,6 +16564,7 @@ Generation = 5 #------------------------------- [TORNADUS] Name = Tornadus +FormName = Incarnate Forme Types = FLYING BaseStats = 79,115,70,111,125,80 GenderRatio = AlwaysMale @@ -16584,11 +16585,11 @@ Color = Green Shape = HeadArms Category = Cyclone Pokedex = Tornadus expels massive energy from its tail, causing severe storms. Its power is great enough to blow houses away. -FormName = Incarnate Forme Generation = 5 #------------------------------- [THUNDURUS] Name = Thundurus +FormName = Incarnate Forme Types = ELECTRIC,FLYING BaseStats = 79,115,70,111,125,80 GenderRatio = AlwaysMale @@ -16609,7 +16610,6 @@ Color = Blue Shape = HeadArms Category = Bolt Strike Pokedex = The spikes on its tail discharge immense bolts of lightning. It flies around the Unova region firing off lightning bolts. -FormName = Incarnate Forme Generation = 5 #------------------------------- [RESHIRAM] @@ -16660,6 +16660,7 @@ Generation = 5 #------------------------------- [LANDORUS] Name = Landorus +FormName = Incarnate Forme Types = GROUND,FLYING BaseStats = 89,125,90,101,115,80 GenderRatio = AlwaysMale @@ -16680,7 +16681,6 @@ Color = Brown Shape = HeadArms Category = Abundance Pokedex = The energy that comes pouring from its tail increases the nutrition in the soil, making crops grow to great size. -FormName = Incarnate Forme Generation = 5 #------------------------------- [KYUREM] @@ -16708,6 +16708,7 @@ Generation = 5 #------------------------------- [KELDEO] Name = Keldeo +FormName = Ordinary Form Types = WATER,FIGHTING BaseStats = 91,72,90,108,129,90 GenderRatio = Genderless @@ -16727,11 +16728,11 @@ Color = Yellow Shape = Quadruped Category = Colt Pokedex = It crosses the world, running over the surfaces of oceans and rivers. It appears at scenic waterfronts. -FormName = Ordinary Form Generation = 5 #------------------------------- [MELOETTA] Name = Meloetta +FormName = Aria Forme Types = NORMAL,PSYCHIC BaseStats = 100,77,77,90,128,128 GenderRatio = Genderless @@ -16751,7 +16752,6 @@ Color = White Shape = Bipedal Category = Melody Pokedex = Many famous songs have been inspired by the melodies that Meloetta plays. -FormName = Aria Forme Generation = 5 WildItemCommon = STARPIECE WildItemUncommon = STARPIECE @@ -16759,6 +16759,7 @@ WildItemRare = STARPIECE #------------------------------- [GENESECT] Name = Genesect +FormName = Normal Types = BUG,STEEL BaseStats = 71,120,95,99,120,95 GenderRatio = Genderless @@ -16778,7 +16779,6 @@ Color = Purple Shape = Bipedal Category = Paleozoic Pokedex = This ancient bug Pokémon was altered by Team Plasma. They upgraded the cannon on its back. -FormName = Normal Generation = 5 #------------------------------- [CHESPIN] @@ -17184,6 +17184,7 @@ Evolutions = VIVILLON,Level,12 #------------------------------- [VIVILLON] Name = Vivillon +FormName = Archipelago Pattern Types = BUG,FLYING BaseStats = 80,52,50,89,90,50 GenderRatio = Female50Percent @@ -17204,7 +17205,6 @@ Color = White Shape = MultiWinged Category = Scale Pokedex = Vivillon with many different patterns are found all over the world. These patterns are affected by the climate of their habitat. -FormName = Archipelago Pattern Generation = 6 #------------------------------- [LITLEO] @@ -17259,6 +17259,7 @@ Generation = 6 #------------------------------- [FLABEBE] Name = Flabébé +FormName = Red Flower Types = FAIRY BaseStats = 44,38,39,42,61,79 GenderRatio = AlwaysFemale @@ -17280,13 +17281,13 @@ Color = White Shape = HeadArms Category = Single Bloom Pokedex = When it finds a flower it likes, it dwells on that flower its whole life long. It floats in the wind's embrace with an untroubled heart. -FormName = Red Flower Generation = 6 Flags = InheritFormFromMother Evolutions = FLOETTE,Level,19 #------------------------------- [FLOETTE] Name = Floette +FormName = Red Flower Types = FAIRY BaseStats = 54,45,47,52,75,98 GenderRatio = AlwaysFemale @@ -17307,13 +17308,13 @@ Color = White Shape = HeadArms Category = Single Bloom Pokedex = It flutters around fields of flowers and cares for flowers that are starting to wilt. It draws out the power of flowers to battle. -FormName = Red Flower Generation = 6 Flags = InheritFormFromMother Evolutions = FLORGES,Item,SHINYSTONE #------------------------------- [FLORGES] Name = Florges +FormName = Red Flower Types = FAIRY BaseStats = 78,65,68,75,112,154 GenderRatio = AlwaysFemale @@ -17334,7 +17335,6 @@ Color = White Shape = HeadArms Category = Garden Pokedex = It claims exquisite flower gardens as its territory, and it obtains power from basking in the energy emitted by flowering plants. -FormName = Red Flower Generation = 6 Flags = InheritFormFromMother #------------------------------- @@ -17442,6 +17442,7 @@ WildItemUncommon = MENTALHERB #------------------------------- [FURFROU] Name = Furfrou +FormName = Natural Form Types = NORMAL BaseStats = 75,80,60,102,65,90 GenderRatio = Female50Percent @@ -17462,7 +17463,6 @@ Color = White Shape = Quadruped Category = Poodle Pokedex = Trimming its fluffy fur not only makes it more elegant but also increases the swiftness of its movements. -FormName = Natural Form Generation = 6 #------------------------------- [ESPURR] @@ -17493,6 +17493,7 @@ Evolutions = MEOWSTIC,Level,25 #------------------------------- [MEOWSTIC] Name = Meowstic +FormName = Male Types = PSYCHIC BaseStats = 74,48,76,104,83,81 GenderRatio = Female50Percent @@ -17513,7 +17514,6 @@ Color = Blue Shape = BipedalTail Category = Constraint Pokedex = Revealing the eyelike patterns on the insides of its ears will unleash its psychic powers. It normally keeps the patterns hidden, however. -FormName = Male Generation = 6 #------------------------------- [HONEDGE] @@ -17567,6 +17567,7 @@ Evolutions = AEGISLASH,Item,DUSKSTONE #------------------------------- [AEGISLASH] Name = Aegislash +FormName = Shield Forme Types = STEEL,GHOST BaseStats = 60,50,140,60,50,140 GenderRatio = Female50Percent @@ -17586,7 +17587,6 @@ Color = Brown Shape = HeadBase Category = Royal Sword Pokedex = In this defensive stance, Aegislash uses its steel body and a force field of spectral power to reduce the damage of any attack. -FormName = Shield Forme Generation = 6 #------------------------------- [SPRITZEE] @@ -18290,6 +18290,7 @@ Generation = 6 #------------------------------- [PUMPKABOO] Name = Pumpkaboo +FormName = Small Size Types = GHOST,GRASS BaseStats = 44,66,70,56,44,55 GenderRatio = Female50Percent @@ -18310,13 +18311,13 @@ Color = Brown Shape = Head Category = Pumpkin Pokedex = When taking spirits to the afterlife, small Pumpkaboo prefer the spirits of children to those of adults. -FormName = Small Size Generation = 6 Flags = InheritFormFromMother Evolutions = GOURGEIST,Trade, #------------------------------- [GOURGEIST] Name = Gourgeist +FormName = Small Size Types = GHOST,GRASS BaseStats = 55,85,122,99,58,75 GenderRatio = Female50Percent @@ -18336,7 +18337,6 @@ Color = Brown Shape = HeadBase Category = Pumpkin Pokedex = Small Gourgeist pretend to be children to fool adults. Anyone who falls for the act gets carried away to the hereafter. -FormName = Small Size Generation = 6 Flags = InheritFormFromMother #------------------------------- @@ -18442,6 +18442,7 @@ Generation = 6 #------------------------------- [XERNEAS] Name = Xerneas +FormName = Neutral Mode Types = FAIRY BaseStats = 126,131,95,99,131,98 GenderRatio = Genderless @@ -18461,7 +18462,6 @@ Color = Blue Shape = Quadruped Category = Life Pokedex = Legends say it can share eternal life. It slept for a thousand years in the form of a tree before its revival. -FormName = Neutral Mode Generation = 6 #------------------------------- [YVELTAL] @@ -18489,6 +18489,7 @@ Generation = 6 #------------------------------- [ZYGARDE] Name = Zygarde +FormName = 50% Forme Types = DRAGON,GROUND BaseStats = 108,100,121,95,81,95 GenderRatio = Genderless @@ -18508,7 +18509,6 @@ Color = Green Shape = Serpentine Category = Order Pokedex = It's thought to be monitoring the ecosystem. There are rumors that even greater power lies hidden within it. -FormName = 50% Forme Generation = 6 #------------------------------- [DIANCIE] @@ -18536,6 +18536,7 @@ Generation = 6 #------------------------------- [HOOPA] Name = Hoopa +FormName = Hoopa Confined Types = PSYCHIC,GHOST BaseStats = 80,110,60,70,150,130 GenderRatio = Genderless @@ -18555,7 +18556,6 @@ Color = Purple Shape = HeadArms Category = Mischief Pokedex = This troublemaker sends anything and everything to faraway places using its loop, which can warp space. -FormName = Hoopa Confined Generation = 6 #------------------------------- [VOLCANION] @@ -19063,6 +19063,7 @@ WildItemUncommon = CHERIBERRY #------------------------------- [ORICORIO] Name = Oricorio +FormName = Baile Style Types = FIRE,FLYING BaseStats = 75,70,70,93,98,70 GenderRatio = Female75Percent @@ -19083,7 +19084,6 @@ Color = Red Shape = Winged Category = Dancing Pokedex = It beats its wings together to create fire. As it moves in the steps of its beautiful dance, it bathes opponents in intense flames. -FormName = Baile Style Generation = 7 Flags = InheritFormFromMother WildItemUncommon = HONEY @@ -19168,6 +19168,7 @@ Evolutions = LYCANROC,Level,25 #------------------------------- [LYCANROC] Name = Lycanroc +FormName = Midday Form Types = ROCK BaseStats = 75,115,65,112,55,65 GenderRatio = Female50Percent @@ -19188,11 +19189,11 @@ Color = Brown Shape = Quadruped Category = Wolf Pokedex = Its quick movements confuse its enemies. Well equipped with claws and fangs, it also uses the sharp rocks in its mane as weapons. -FormName = Midday Form Generation = 7 #------------------------------- [WISHIWASHI] Name = Wishiwashi +FormName = Solo Form Types = WATER BaseStats = 45,20,20,40,25,25 GenderRatio = Female50Percent @@ -19213,7 +19214,6 @@ Color = Blue Shape = Finned Category = Small Fry Pokedex = It's awfully weak and notably tasty, so everyone is always out to get it. As it happens, anyone trying to bully it receives a painful lesson. -FormName = Solo Form Generation = 7 #------------------------------- [MAREANIE] @@ -19885,6 +19885,7 @@ Evolutions = SILVALLY,Happiness, #------------------------------- [SILVALLY] Name = Silvally +FormName = Type: Normal Types = NORMAL BaseStats = 95,95,95,95,95,95 GenderRatio = Genderless @@ -19904,11 +19905,11 @@ Color = Gray Shape = Quadruped Category = Synthetic Pokedex = Its trust in its partner is what awakens it. This Pokémon is capable of changing its type, a flexibility that is well displayed in battle. -FormName = Type: Normal Generation = 7 #------------------------------- [MINIOR] Name = Minior +FormName = Meteor Form Types = ROCK,FLYING BaseStats = 60,60,100,60,60,100 GenderRatio = Genderless @@ -19928,7 +19929,6 @@ Color = Brown Shape = Head Category = Meteor Pokedex = Originally making its home in the ozone layer, it hurtles to the ground when the shell enclosing its body grows too heavy. -FormName = Meteor Form Generation = 7 WildItemUncommon = STARPIECE #------------------------------- @@ -20009,6 +20009,7 @@ WildItemUncommon = ELECTRICSEED #------------------------------- [MIMIKYU] Name = Mimikyu +FormName = Disguised Form Types = GHOST,FAIRY BaseStats = 55,90,80,96,50,105 GenderRatio = Female50Percent @@ -20029,7 +20030,6 @@ Color = Yellow Shape = Serpentine Category = Disguise Pokedex = A lonely Pokémon, it conceals its terrifying appearance beneath an old rag so it can get closer to people and other Pokémon. -FormName = Disguised Form Generation = 7 WildItemUncommon = CHESTOBERRY #------------------------------- @@ -21758,6 +21758,7 @@ Evolutions = TOXTRICITY,Level,30 #------------------------------- [TOXTRICITY] Name = Toxtricity +FormName = Amped Form Types = ELECTRIC,POISON BaseStats = 75,98,70,75,114,70 GenderRatio = Female50Percent @@ -21778,7 +21779,6 @@ Color = Purple Shape = BipedalTail Category = Punk Pokedex = When this Pokémon sounds as if it's strumming a guitar, it's actually clawing at the protrusions on its chest to generate electricity. -FormName = Amped Form Generation = 8 #------------------------------- [SIZZLIPEDE] @@ -21883,6 +21883,7 @@ Generation = 8 #------------------------------- [SINISTEA] Name = Sinistea +FormName = Phony Form Types = GHOST BaseStats = 40,45,45,50,74,54 GenderRatio = Genderless @@ -21903,12 +21904,12 @@ Color = Purple Shape = Head Category = Black Tea Pokedex = The teacup in which this Pokémon makes its home is a famous piece of antique tableware. Many forgeries are in circulation. -FormName = Phony Form Generation = 8 Evolutions = POLTEAGEIST,Item,CRACKEDPOT #------------------------------- [POLTEAGEIST] Name = Polteageist +FormName = Phony Form Types = GHOST BaseStats = 60,65,65,70,134,114 GenderRatio = Genderless @@ -21929,7 +21930,6 @@ Color = Purple Shape = Head Category = Black Tea Pokedex = This species lives in antique teapots. Most pots are forgeries, but on rare occasions, an authentic work is found. -FormName = Phony Form Generation = 8 #------------------------------- [HATENNA] @@ -22265,6 +22265,7 @@ Evolutions = ALCREMIE,HoldItem,STRAWBERRYSWEET,ALCREMIE,HoldItem,BERRYSWEET,ALCR #------------------------------- [ALCREMIE] Name = Alcremie +FormName = Vanilla Cream Types = FAIRY BaseStats = 65,60,75,64,110,121 GenderRatio = AlwaysFemale @@ -22285,7 +22286,6 @@ Color = White Shape = HeadBase Category = Cream Pokedex = When Alcremie is content, the cream it secretes from its hands becomes sweeter and richer. -FormName = Vanilla Cream Generation = 8 #------------------------------- [FALINKS] @@ -22414,6 +22414,7 @@ Generation = 8 #------------------------------- [EISCUE] Name = Eiscue +FormName = Ice Face Types = ICE BaseStats = 75,80,110,50,65,90 GenderRatio = Female50Percent @@ -22434,11 +22435,11 @@ Color = Blue Shape = BipedalTail Category = Penguin Pokedex = It drifted in on the flow of ocean waters from a frigid place. It keeps its head iced constantly to make sure it stays nice and cold. -FormName = Ice Face Generation = 8 #------------------------------- [INDEEDEE] Name = Indeedee +FormName = Male Types = PSYCHIC,NORMAL BaseStats = 60,65,55,95,105,95 GenderRatio = Female50Percent @@ -22460,11 +22461,11 @@ Color = Purple Shape = BipedalTail Category = Emotion Pokedex = It uses the horns on its head to sense the emotions of others. Males will act as valets for those they serve, looking after their every need. -FormName = Male Generation = 8 #------------------------------- [MORPEKO] Name = Morpeko +FormName = Full Belly Mode Types = ELECTRIC,DARK BaseStats = 58,95,58,97,70,58 GenderRatio = Female50Percent @@ -22485,7 +22486,6 @@ Color = Yellow Shape = Bipedal Category = Two-Sided Pokedex = As it eats the seeds stored up in its pocket-like pouches, this Pokémon is not just satisfying its constant hunger. It's also generating electricity. -FormName = Full Belly Mode Generation = 8 #------------------------------- [CUFANT] @@ -22738,6 +22738,7 @@ Generation = 8 #------------------------------- [ZACIAN] Name = Zacian +FormName = Hero of Many Battles Types = FAIRY BaseStats = 92,130,115,138,80,115 GenderRatio = Genderless @@ -22757,7 +22758,6 @@ Color = Blue Shape = Quadruped Category = Warrior Pokedex = Known as a legendary hero, this Pokémon absorbs metal particles, transforming them into a weapon it uses to battle. -FormName = Hero of Many Battles Generation = 8 WildItemCommon = RUSTEDSWORD WildItemUncommon = RUSTEDSWORD @@ -22765,6 +22765,7 @@ WildItemRare = RUSTEDSWORD #------------------------------- [ZAMAZENTA] Name = Zamazenta +FormName = Hero of Many Battles Types = FIGHTING BaseStats = 92,130,115,138,80,115 GenderRatio = Genderless @@ -22784,7 +22785,6 @@ Color = Red Shape = Quadruped Category = Warrior Pokedex = This Pokémon slept for aeons while in the form of a statue. It was asleep for so long, people forgot that it ever existed. -FormName = Hero of Many Battles Generation = 8 WildItemCommon = RUSTEDSHIELD WildItemUncommon = RUSTEDSHIELD @@ -22839,6 +22839,7 @@ Evolutions = URSHIFU,Event,1 #------------------------------- [URSHIFU] Name = Urshifu +FormName = Single Strike Style Types = FIGHTING,DARK BaseStats = 100,130,100,97,63,60 GenderRatio = FemaleOneEighth @@ -22858,7 +22859,6 @@ Color = Gray Shape = Bipedal Category = Wushu Pokedex = Inhabiting the mountains of a distant region, this Pokémon races across sheer cliffs, training its legs and refining its moves. -FormName = Single Strike Style Generation = 8 #------------------------------- [ZARUDE] From f33eb4d8965e28b26b29087a8ec36f30748be1f1 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 20 Nov 2022 20:15:04 +0000 Subject: [PATCH 03/12] Added PBS schema character ^ for repeated lines, more refactoring of PBS compilers/writers --- Data/Scripts/010_Data/001_GameData.rb | 14 +- .../Scripts/010_Data/002_PBS data/004_Move.rb | 2 +- .../Scripts/010_Data/002_PBS data/005_Item.rb | 2 +- .../010_Data/002_PBS data/007_Species.rb | 2 +- .../002_PBS data/009_SpeciesMetrics.rb | 2 +- .../010_Data/002_PBS data/013_TrainerType.rb | 2 +- .../010_Data/002_PBS data/015_Metadata.rb | 17 - .../002_PBS data/016_PlayerMetadata.rb | 15 - .../010_Data/002_PBS data/017_MapMetadata.rb | 28 - .../002_PBS data/018_DungeonTileset.rb | 36 +- .../002_PBS data/020_DungeonParameters.rb | 2 +- .../010_Data/002_PBS data/020_PhoneMessage.rb | 55 +- .../001_Editor screens/001_EditorScreens.rb | 47 +- .../Scripts/020_Debug/002_Editor_DataTypes.rb | 2 +- Data/Scripts/021_Compiler/001_Compiler.rb | 25 +- .../021_Compiler/002_Compiler_CompilePBS.rb | 920 +++++------------- .../021_Compiler/003_Compiler_WritePBS.rb | 221 +++-- PBS/phone.txt | 4 +- PBS/town_map.txt | 54 +- 19 files changed, 516 insertions(+), 934 deletions(-) diff --git a/Data/Scripts/010_Data/001_GameData.rb b/Data/Scripts/010_Data/001_GameData.rb index 7b356a567..92d972cee 100644 --- a/Data/Scripts/010_Data/001_GameData.rb +++ b/Data/Scripts/010_Data/001_GameData.rb @@ -6,6 +6,10 @@ module GameData # For data that is known by a symbol or an ID number. #============================================================================= module ClassMethods + def schema + return self::SCHEMA + end + def register(hash) self::DATA[hash[:id]] = self::DATA[hash[:id_number]] = self.new(hash) end @@ -72,6 +76,10 @@ module GameData # For data that is only known by a symbol. #============================================================================= module ClassMethodsSymbols + def schema + return self::SCHEMA + end + def register(hash) self::DATA[hash[:id]] = self.new(hash) end @@ -143,6 +151,10 @@ module GameData # For data that is only known by an ID number. #============================================================================= module ClassMethodsIDNumbers + def schema + return self::SCHEMA + end + def register(hash) self::DATA[hash[:id]] = self.new(hash) end @@ -222,7 +234,7 @@ module GameData def get_property_for_PBS(key) ret = nil - if self.class::SCHEMA.include?(key) + if self.class::SCHEMA.include?(key) && self.respond_to?(self.class::SCHEMA[key][0]) ret = self.send(self.class::SCHEMA[key][0]) ret = nil if ret == false || (ret.is_a?(Array) && ret.length == 0) end diff --git a/Data/Scripts/010_Data/002_PBS data/004_Move.rb b/Data/Scripts/010_Data/002_PBS data/004_Move.rb index 1d37c03b2..7e0417a28 100644 --- a/Data/Scripts/010_Data/002_PBS data/004_Move.rb +++ b/Data/Scripts/010_Data/002_PBS data/004_Move.rb @@ -812,7 +812,7 @@ module GameData return data end - alias __orig__get_property_for_PBS get_property_for_PBS + alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS) def get_property_for_PBS(key) ret = __orig__get_property_for_PBS(key) ret = nil if ["Power", "Priority", "EffectChance"].include?(key) && ret == 0 diff --git a/Data/Scripts/010_Data/002_PBS data/005_Item.rb b/Data/Scripts/010_Data/002_PBS data/005_Item.rb index c7b21da67..a46b52055 100644 --- a/Data/Scripts/010_Data/002_PBS data/005_Item.rb +++ b/Data/Scripts/010_Data/002_PBS data/005_Item.rb @@ -193,7 +193,7 @@ module GameData return combos[species]&.include?(@id) end - alias __orig__get_property_for_PBS get_property_for_PBS + alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS) def get_property_for_PBS(key) ret = __orig__get_property_for_PBS(key) case key diff --git a/Data/Scripts/010_Data/002_PBS data/007_Species.rb b/Data/Scripts/010_Data/002_PBS data/007_Species.rb index 8f0439b38..4c0b00998 100644 --- a/Data/Scripts/010_Data/002_PBS data/007_Species.rb +++ b/Data/Scripts/010_Data/002_PBS data/007_Species.rb @@ -342,7 +342,7 @@ module GameData return 1 end - alias __orig__get_property_for_PBS get_property_for_PBS + 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) ret = nil if self.class.schema(writing_form).include?(key) diff --git a/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb b/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb index b4ac39e60..dc915efbe 100644 --- a/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb +++ b/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb @@ -85,7 +85,7 @@ module GameData # return @front_sprite_altitude > 0 end - alias __orig__get_property_for_PBS get_property_for_PBS + alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS) def get_property_for_PBS(key) ret = __orig__get_property_for_PBS(key) case key diff --git a/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb b/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb index df630e740..1c2adca37 100644 --- a/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb +++ b/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb @@ -104,7 +104,7 @@ module GameData return @flags.any? { |f| f.downcase == flag.downcase } end - alias __orig__get_property_for_PBS get_property_for_PBS + alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS) def get_property_for_PBS(key) ret = __orig__get_property_for_PBS(key) ret = nil if key == "SkillLevel" && ret == @base_money diff --git a/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb b/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb index a2869b1b2..5f02f86df 100644 --- a/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb @@ -74,22 +74,5 @@ module GameData ret = pbGetMessage(MessageTypes::StorageCreator, 0) return nil_or_empty?(ret) ? _INTL("Bill") : ret end - - def property_from_string(str) - case str - when "StartMoney" then return @start_money - when "StartItemStorage" then return @start_item_storage - when "Home" then return @home - when "StorageCreator" then return @real_storage_creator - when "WildBattleBGM" then return @wild_battle_BGM - when "TrainerBattleBGM" then return @trainer_battle_BGM - when "WildVictoryBGM" then return @wild_victory_BGM - when "TrainerVictoryBGM" then return @trainer_victory_BGM - when "WildCaptureME" then return @wild_capture_ME - when "SurfBGM" then return @surf_BGM - when "BicycleBGM" then return @bicycle_BGM - end - return nil - end end end diff --git a/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb b/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb index a050296e8..6d2844d82 100644 --- a/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb @@ -82,20 +82,5 @@ module GameData def surf_fish_charset return @surf_fish_charset || fish_charset end - - def property_from_string(str) - case str - when "TrainerType" then return @trainer_type - when "WalkCharset" then return @walk_charset - when "RunCharset" then return @run_charset - when "CycleCharset" then return @cycle_charset - when "SurfCharset" then return @surf_charset - when "DiveCharset" then return @dive_charset - when "FishCharset" then return @fish_charset - when "SurfFishCharset" then return @surf_fish_charset - when "Home" then return @home - end - return nil - end end end diff --git a/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb b/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb index bf6f9397d..8ccba189e 100644 --- a/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb @@ -109,34 +109,6 @@ module GameData @flags = hash[:flags] || [] end - def property_from_string(str) - case str - when "Name" then return @real_name - when "Outdoor" then return @outdoor_map - when "ShowArea" then return @announce_location - when "Bicycle" then return @can_bicycle - when "BicycleAlways" then return @always_bicycle - when "HealingSpot" then return @teleport_destination - when "Weather" then return @weather - when "MapPosition" then return @town_map_position - when "DiveMap" then return @dive_map_id - when "DarkMap" then return @dark_map - when "SafariMap" then return @safari_map - when "SnapEdges" then return @snap_edges - when "Dungeon" then return @random_dungeon - when "BattleBack" then return @battle_background - when "WildBattleBGM" then return @wild_battle_BGM - when "TrainerBattleBGM" then return @trainer_battle_BGM - when "WildVictoryBGM" then return @wild_victory_BGM - when "TrainerVictoryBGM" then return @trainer_victory_BGM - when "WildCaptureME" then return @wild_capture_ME - when "MapSize" then return @town_map_size - when "Environment" then return @battle_environment - when "Flags" then return @flags - end - return nil - end - # @return [String] the translated name of this map def name return pbGetMapNameFromId(@id) diff --git a/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb b/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb index b7c03e68b..854a0d50d 100644 --- a/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb +++ b/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb @@ -15,8 +15,9 @@ module GameData DATA_FILENAME = "dungeon_tilesets.dat" SCHEMA = { - "Autotile" => [:autotile, "um"], - "Tile" => [:tile, "um"], + "SectionName" => [:id, "u"], + "Autotile" => [:autotile, "^um"], + "Tile" => [:tile, "^um"], "SnapToLargeGrid" => [:snap_to_large_grid, "b"], "LargeVoidTiles" => [:large_void_tiles, "b"], "LargeWallTiles" => [:large_wall_tiles, "b"], @@ -192,18 +193,27 @@ module GameData return ret end - def property_from_string(str) - case str - when "SnapToLargeGrid" then return @snap_to_large_grid - when "LargeVoidTiles" then return @large_void_tiles - when "LargeWallTiles" then return @large_wall_tiles - when "LargeFloorTiles" then return @large_floor_tiles - when "DoubleWalls" then return @double_walls - when "FloorPatchUnderWalls" then return @floor_patch_under_walls - when "ThinNorthWallOffset" then return @thin_north_wall_offset - when "Flags" then return @flags + alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS) + def get_property_for_PBS(key) + ret = __orig__get_property_for_PBS(key) + case key + when "ThinNorthWallOffset" + ret = nil if ret == 0 + when "Tile", "Autotile" + ret = [] + @tile_type_ids.each do |tile_type, tile_ids| + tile_ids.each do |tile| + case key + when "Tile" + ret.push([tile[0] - 384, tile_type]) if !tile[1] && tile[0] >= 384 + when "Autotile" + ret.push([tile[0] / 48, tile_type]) if !tile[1] && tile[0] < 384 + end + end + end + ret = nil if ret.length == 0 end - return nil + return ret end end end diff --git a/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb b/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb index df0d4663e..91723de05 100644 --- a/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb +++ b/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb @@ -115,7 +115,7 @@ module GameData return width, height end - alias __orig__get_property_for_PBS get_property_for_PBS + alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS) def get_property_for_PBS(key) case key when "SectionName" then return [@area, (@version > 0) ? @version : nil] diff --git a/Data/Scripts/010_Data/002_PBS data/020_PhoneMessage.rb b/Data/Scripts/010_Data/002_PBS data/020_PhoneMessage.rb index 9f90c3223..2a5dcb27d 100644 --- a/Data/Scripts/010_Data/002_PBS data/020_PhoneMessage.rb +++ b/Data/Scripts/010_Data/002_PBS data/020_PhoneMessage.rb @@ -11,29 +11,36 @@ module GameData DATA_FILENAME = "phone.dat" SCHEMA = { - "Intro" => [:intro, "q"], - "IntroMorning" => [:intro_morning, "q"], - "IntroAfternoon" => [:intro_afternoon, "q"], - "IntroEvening" => [:intro_evening, "q"], - "Body" => [:body, "q"], - "Body1" => [:body1, "q"], - "Body2" => [:body2, "q"], - "BattleRequest" => [:battle_request, "q"], - "BattleRemind" => [:battle_remind, "q"], - "End" => [:end, "q"] + "SectionName" => [:id, "q"], + "Intro" => [:intro, "^q"], + "IntroMorning" => [:intro_morning, "^q"], + "IntroAfternoon" => [:intro_afternoon, "^q"], + "IntroEvening" => [:intro_evening, "^q"], + "Body1" => [:body1, "^q"], + "Body2" => [:body2, "^q"], + "Body" => [:body, "^q"], + "BattleRequest" => [:battle_request, "^q"], + "BattleRemind" => [:battle_remind, "^q"], + "End" => [:end, "^q"] } extend ClassMethodsSymbols include InstanceMethods # @param tr_type [Symbol, String] - # @param tr_name [String] + # @param tr_name [String, nil] only nil for the default message set # @param tr_version [Integer, nil] # @return [Boolean] whether the given other is defined as a self - def self.exists?(tr_type, tr_name, tr_version = 0) + def self.exists?(tr_type, tr_name = nil, tr_version = 0) + if tr_type.is_a?(Array) + tr_name = tr_type[1] + tr_version = tr_type[2] + tr_type = tr_type[0] + end validate tr_type => [Symbol, String] - validate tr_name => [String] + validate tr_name => [String, NilClass] key = [tr_type.to_sym, tr_name, tr_version] + key = key[0] if key[1] == nil return !self::DATA[key].nil? end @@ -63,7 +70,7 @@ module GameData def initialize(hash) @id = hash[:id] @trainer_type = hash[:trainer_type] - @real_name = hash[:name] + @real_name = hash[:real_name] @version = hash[:version] || 0 @intro = hash[:intro] @intro_morning = hash[:intro_morning] @@ -77,20 +84,14 @@ module GameData @end = hash[:end] end - def property_from_string(str) - case str - when "Intro" then return @intro - when "IntroMorning" then return @intro_morning - when "IntroAfternoon" then return @intro_afternoon - when "IntroEvening" then return @intro_evening - when "Body" then return @body - when "Body1" then return @body1 - when "Body2" then return @body2 - when "BattleRequest" then return @battle_request - when "BattleRemind" then return @battle_remind - when "End" then return @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) + if key == "SectionName" + return "Default" if @id == "default" + ret = [@trainer_type, @real_name, (@version > 0) ? @version : nil] + return ret.compact.join(",") end - return nil + 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 8194793b8..fbfe37d17 100644 --- a/Data/Scripts/020_Debug/001_Editor screens/001_EditorScreens.rb +++ b/Data/Scripts/020_Debug/001_Editor screens/001_EditorScreens.rb @@ -345,7 +345,7 @@ end #=============================================================================== def pbTrainerTypeEditor gender_array = [] - GameData::TrainerType::SCHEMA["Gender"][2].each { |key, value| gender_array[value] = key if !gender_array[value] } + 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.")], @@ -732,23 +732,25 @@ def pbEditMetadata metadata = GameData::Metadata.get properties = GameData::Metadata.editor_properties properties.each do |property| - data.push(metadata.property_from_string(property[0])) + val = metadata.get_property_for_PBS(property[0]) + val = property[1].defaultValue if val.nil? && property[1].respond_to?(:defaultValue) + data.push(val) 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], - :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] + :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] } # Add metadata's data to records GameData::Metadata.register(metadata_hash) @@ -776,7 +778,9 @@ def pbEditPlayerMetadata(player_id = 1) metadata = GameData::PlayerMetadata.try_get(player_id) if metadata.nil? properties = GameData::PlayerMetadata.editor_properties properties.each do |property| - data.push(metadata.property_from_string(property[0])) + val = metadata.get_property_for_PBS(property[0]) + val = property[1].defaultValue if val.nil? && property[1].respond_to?(:defaultValue) + data.push(val) end if pbPropertyList(_INTL("Player {1}", metadata.id), data, properties, true) # Construct player metadata hash @@ -789,7 +793,8 @@ def pbEditPlayerMetadata(player_id = 1) :surf_charset => data[4], :dive_charset => data[5], :fish_charset => data[6], - :surf_fish_charset => data[7] + :surf_fish_charset => data[7], + :home => data[8] } # Add player metadata's data to records GameData::PlayerMetadata.register(metadata_hash) @@ -819,13 +824,15 @@ def pbEditMapMetadata(map_id) metadata = GameData::MapMetadata.new({ :id => map_id }) if !metadata properties = GameData::MapMetadata.editor_properties properties.each do |property| - data.push(metadata.property_from_string(property[0])) + val = metadata.get_property_for_PBS(property[0]) + val = property[1].defaultValue if val.nil? && property[1].respond_to?(:defaultValue) + data.push(val) end if pbPropertyList(map_name, data, properties, true) # Construct map metadata hash metadata_hash = { :id => map_id, - :name => data[0], + :real_name => data[0], :outdoor_map => data[1], :announce_location => data[2], :can_bicycle => data[3], @@ -862,9 +869,9 @@ end #=============================================================================== 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] } + 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] } + 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.")], diff --git a/Data/Scripts/020_Debug/002_Editor_DataTypes.rb b/Data/Scripts/020_Debug/002_Editor_DataTypes.rb index 8080a2a98..de0beff16 100644 --- a/Data/Scripts/020_Debug/002_Editor_DataTypes.rb +++ b/Data/Scripts/020_Debug/002_Editor_DataTypes.rb @@ -240,7 +240,7 @@ class StringListProperty def self.set(_setting_name, old_setting) real_cmds = [] real_cmds.push([_INTL("[ADD VALUE]"), -1]) - old_setting.length.times do + old_setting.length.times do |i| real_cmds.push([old_setting[i], 0]) end # Edit list diff --git a/Data/Scripts/021_Compiler/001_Compiler.rb b/Data/Scripts/021_Compiler/001_Compiler.rb index 72f74a5da..0f415c84e 100644 --- a/Data/Scripts/021_Compiler/001_Compiler.rb +++ b/Data/Scripts/021_Compiler/001_Compiler.rb @@ -92,7 +92,7 @@ module Compiler #============================================================================= # PBS file readers #============================================================================= - def pbEachFileSectionEx(f) + def pbEachFileSectionEx(f, schema = nil) lineno = 1 havesection = false sectionname = nil @@ -120,7 +120,12 @@ module Compiler end r1 = $~[1] r2 = $~[2] - lastsection[r1] = r2.gsub(/\s+$/, "") + if schema && schema[r1] && schema[r1][1][0] == "^" + lastsection[r1] ||= [] + lastsection[r1].push(r2.gsub(/\s+$/, "")) + else + lastsection[r1] = r2.gsub(/\s+$/, "") + end end end lineno += 1 @@ -133,15 +138,15 @@ module Compiler # pokemon.txt, pokemon_forms.txt, pokemon_metrics.txt, shadow_pokemon.txt, # ribbons.txt, trainer_types.txt, battle_facility_lists.txt, Battle Tower # trainers PBS files and dungeon_parameters.txt - def pbEachFileSection(f) - pbEachFileSectionEx(f) { |section, name| + def pbEachFileSection(f, schema = nil) + pbEachFileSectionEx(f, schema) { |section, name| yield section, name if block_given? && name[/^.+$/] } end # Used for metadata.txt and map_metadata.txt - def pbEachFileSectionNumbered(f) - pbEachFileSectionEx(f) { |section, name| + def pbEachFileSectionNumbered(f, schema = nil) + pbEachFileSectionEx(f, schema) { |section, name| yield section, name.to_i if block_given? && name[/^\d+$/] } end @@ -401,10 +406,14 @@ module Compiler def pbGetCsvRecord(rec, lineno, schema) record = [] repeat = false + schema_length = schema[1].length start = 0 if schema[1][0, 1] == "*" repeat = true start = 1 + elsif schema[1][0, 1] == "^" + start = 1 + schema_length -= 1 end subarrays = repeat && schema[1].length > 2 loop do @@ -560,7 +569,7 @@ module Compiler break if repeat && nil_or_empty?(rec) break unless repeat end - return (!repeat && schema[1].length == 1) ? record[0] : record + return (!repeat && schema_length == 1) ? record[0] : record end #============================================================================= @@ -568,7 +577,7 @@ module Compiler #============================================================================= def pbWriteCsvRecord(record, file, schema) rec = (record.is_a?(Array)) ? record.flatten : [record] - start = (schema[1][0, 1] == "*") ? 1 : 0 + start = (["*", "^"].include?(schema[1][0, 1])) ? 1 : 0 index = -1 loop do (start...schema[1].length).each do |i| diff --git a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb index a8616ba76..00fa43090 100644 --- a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb +++ b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb @@ -1,58 +1,144 @@ module Compiler module_function + def compile_PBS_file_generic(game_data, path) + compile_pbs_file_message_start(path) + game_data::DATA.clear + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = game_data.schema + idx = 0 + pbEachFileSection(f, schema) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + if schema[key][1][0] == "^" + contents[key].each do |val| + value = pbGetCsvRecord(val, key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] ||= [] + data_hash[schema[key][0]].push(value) + end + data_hash[schema[key][0]].compact! + else + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value + end + end + # Validate and modify the compiled data + yield false, data_hash if block_given? + if game_data.exists?(data_hash[:id]) + raise _INTL("Section name '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + # Add section's data to records + game_data.register(data_hash) + } + } + yield true, nil if block_given? + # Save all data + game_data.save + process_pbs_file_message_end + end + #============================================================================= # Compile Town Map data #============================================================================= def compile_town_map(path = "PBS/town_map.txt") compile_pbs_file_message_start(path) - nonglobaltypes = { - "Name" => [0, "s"], - "Filename" => [1, "s"], - "Point" => [2, "uussUUUU"] - } - currentmap = -1 - rgnnames = [] - placenames = [] - placedescs = [] - sections = [] - pbCompilerEachCommentedLine(path) { |line, lineno| - if line[/^\s*\[\s*(\d+)\s*\]\s*$/] - currentmap = $~[1].to_i - sections[currentmap] = [] - else - if currentmap < 0 - raise _INTL("Expected a section at the beginning of the file\r\n{1}", FileLineData.linereport) - end - if !line[/^\s*(\w+)\s*=\s*(.*)$/] - raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}", FileLineData.linereport) - end - settingname = $~[1] - schema = nonglobaltypes[settingname] - if schema - record = pbGetCsvRecord($~[2], lineno, schema) - case settingname - when "Name" - rgnnames[currentmap] = record - sections[currentmap][schema[0]] = record - when "Point" - placenames.push(record[2]) - placedescs.push(record[3]) - sections[currentmap][schema[0]] = [] if !sections[currentmap][schema[0]] - sections[currentmap][schema[0]].push(record) - else # Filename - sections[currentmap][schema[0]] = record + sections = [] + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + schema = { + "SectionName" => [:id, "u"], + "Name" => [:real_name, "s"], + "Filename" => [:filename, "s"], + "Point" => [:point, "^uussUUUU"] + } + idx = 0 + pbEachFileSection(f, schema) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = {:id => section_name.to_sym} + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + if schema[key][1][0] == "^" + contents[key].each do |val| + value = pbGetCsvRecord(val, key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] ||= [] + data_hash[schema[key][0]].push(value) + end + data_hash[schema[key][0]].compact! + else + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end end - end + # Validate and modify the compiled data + validate_compiled_town_map(data_hash) + if sections[data_hash[:id]] + raise _INTL("Region ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + # Add town map messages to records + sections[data_hash[:id]] = [data_hash[:real_name], data_hash[:filename], data_hash[:point]] + } } + validate_all_compiled_town_maps(sections) + # Save all data save_data(sections, "Data/town_map.dat") - MessageTypes.setMessages(MessageTypes::RegionNames, rgnnames) - MessageTypes.setMessagesAsHash(MessageTypes::PlaceNames, placenames) - MessageTypes.setMessagesAsHash(MessageTypes::PlaceDescriptions, placedescs) process_pbs_file_message_end end + def validate_compiled_town_map(hash) + end + + def validate_all_compiled_town_maps(sections) + # Get town map names and descriptions for translating + region_names = [] + point_names = [] + interest_names = [] + sections.each_with_index do |region, i| + region_names[i] = region[0] + region[2].each do |point| + point_names.push(point[2]) + interest_names.push(point[3]) + end + end + MessageTypes.setMessages(MessageTypes::RegionNames, region_names) + MessageTypes.setMessagesAsHash(MessageTypes::PlaceNames, point_names) + MessageTypes.setMessagesAsHash(MessageTypes::PlaceDescriptions, interest_names) + end + #============================================================================= # Compile map connections #============================================================================= @@ -100,120 +186,46 @@ module Compiler # Compile phone messages #============================================================================= def compile_phone(path = "PBS/phone.txt") - return if !safeExists?(path) - compile_pbs_file_message_start(path) - GameData::PhoneMessage::DATA.clear - schema = GameData::PhoneMessage::SCHEMA - messages = [] - contact_hash = nil - # Read each line of phone.txt at a time and compile it as a contact property - idx = 0 - pbCompilerEachPreppedLine(path) { |line, line_no| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - if line[/^\s*\[\s*(.+)\s*\]\s*$/] - # New section [trainer_type, name] or [trainer_type, name, version] - if contact_hash - # Add contact's data to records - if contact_hash[:trainer_type] == "default" - contact_hash[:id] = contact_hash[:trainer_type] - else - contact_hash[:id] = [contact_hash[:trainer_type], contact_hash[:name], contact_hash[:version]] - end - GameData::PhoneMessage.register(contact_hash) - end - # Construct contact hash - header = $~[1] - if header.strip.downcase == "default" - contact_hash = { - :trainer_type => "default" - } - else - line_data = pbGetCsvRecord($~[1], line_no, [0, "esU", :TrainerType]) - contact_hash = { - :trainer_type => line_data[0], - :name => line_data[1], - :version => line_data[2] || 0 - } - end - elsif line[/^\s*(\w+)\s*=\s*(.*)$/] - # XXX=YYY lines - if !contact_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) - end - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - contact_hash[line_schema[0]] ||= [] - contact_hash[line_schema[0]].push(property_value) - messages.push(property_value) - end - } - # Add last contact's data to records - if contact_hash - # Add contact's data to records - if contact_hash[:trainer_type] == "default" - contact_hash[:id] = contact_hash[:trainer_type] - else - contact_hash[:id] = [contact_hash[:trainer_type], contact_hash[:name], contact_hash[:version]] - end - GameData::PhoneMessage.register(contact_hash) + compile_PBS_file_generic(GameData::PhoneMessage, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_phone_contacts : validate_compiled_phone_contact(hash) + end + end + + def validate_compiled_phone_contact(hash) + # Split trainer type/name/version into their own values, generate compound ID from them + if hash[:id].strip.downcase == "default" + hash[:id] = "default" + hash[:trainer_type] = hash[:id] + else + line_data = pbGetCsvRecord(hash[:id], -1, [0, "esU", :TrainerType]) + hash[:trainer_type] = line_data[0] + hash[:real_name] = line_data[1] + hash[:version] = line_data[2] || 0 + hash[:id] = [hash[:trainer_type], hash[:real_name], hash[:version]] + end + end + + def validate_all_compiled_phone_contacts + # Get all phone messages for translating + messages = [] + GameData::PhoneMessage.each do |contact| + [:intro, :intro_morning, :intro_afternoon, :intro_evening, :body, :body1, + :body2, :battle_request, :battle_remind, :end].each do |msg_type| + msgs = contact.send(msg_type) + next if !msgs || msgs.length == 0 + msgs.each { |msg| messages.push(msg) } + end end - # Save all data - GameData::PhoneMessage.save MessageTypes.setMessagesAsHash(MessageTypes::PhoneMessages, messages) - process_pbs_file_message_end end #============================================================================= # Compile type data #============================================================================= def compile_types(path = "PBS/types.txt") - compile_pbs_file_message_start(path) - GameData::Type::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::Type::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_type(data_hash) - if GameData::Type.exists?(data_hash[:id]) - raise _INTL("Type ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add type's data to records - GameData::Type.register(data_hash) - } - } - validate_all_compiled_types - # Save all data - GameData::Type.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::Type, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_types : validate_compiled_type(hash) + end end def validate_compiled_type(hash) @@ -249,48 +261,9 @@ module Compiler # Compile ability data #============================================================================= def compile_abilities(path = "PBS/abilities.txt") - compile_pbs_file_message_start(path) - GameData::Ability::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::Ability::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_ability(data_hash) - if GameData::Ability.exists?(data_hash[:id]) - raise _INTL("Ability ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add ability's data to records - GameData::Ability.register(data_hash) - } - } - validate_all_compiled_abilities - # Save all data - GameData::Ability.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::Ability, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_abilities : validate_compiled_ability(hash) + end end def validate_compiled_ability(hash) @@ -312,48 +285,9 @@ module Compiler # Compile move data #============================================================================= def compile_moves(path = "PBS/moves.txt") - compile_pbs_file_message_start(path) - GameData::Move::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::Move::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_move(data_hash) - if GameData::Move.exists?(data_hash[:id]) - raise _INTL("Move ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add move's data to records - GameData::Move.register(data_hash) - } - } - validate_all_compiled_moves - # Save all data - GameData::Move.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::Move, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_moves : validate_compiled_move(hash) + end end def validate_compiled_move(hash) @@ -383,48 +317,9 @@ module Compiler # Compile item data #============================================================================= def compile_items(path = "PBS/items.txt") - compile_pbs_file_message_start(path) - GameData::Item::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::Item::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_item(data_hash) - if GameData::Item.exists?(data_hash[:id]) - raise _INTL("Item ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add item's data to records - GameData::Item.register(data_hash) - } - } - validate_all_compiled_items - # Save all data - GameData::Item.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::Item, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_items : validate_compiled_item(hash) + end end def validate_compiled_item(hash) @@ -449,48 +344,9 @@ module Compiler # Compile berry plant data #============================================================================= def compile_berry_plants(path = "PBS/berry_plants.txt") - compile_pbs_file_message_start(path) - GameData::BerryPlant::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::BerryPlant::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_berry_plant(data_hash) - if GameData::BerryPlant.exists?(data_hash[:id]) - raise _INTL("Berry plant ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add berry plant's data to records - GameData::BerryPlant.register(data_hash) - } - } - validate_all_compiled_berry_plants - # Save all data - GameData::BerryPlant.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::BerryPlant, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_berry_plants : validate_compiled_berry_plant(hash) + end end def validate_compiled_berry_plant(hash) @@ -503,48 +359,9 @@ module Compiler # Compile Pokémon data #============================================================================= def compile_pokemon(path = "PBS/pokemon.txt") - compile_pbs_file_message_start(path) - GameData::Species::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::Species.schema - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_pokemon(data_hash) - if GameData::Species.exists?(data_hash[:id]) - raise _INTL("Species ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add species's data to records - GameData::Species.register(data_hash) - } - } - validate_all_compiled_pokemon - # Save all data - GameData::Species.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::Species, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_pokemon : validate_compiled_pokemon(hash) + end end # NOTE: This method is also called by def validate_compiled_pokemon_form @@ -630,6 +447,8 @@ module Compiler #============================================================================= # Compile Pokémon forms data + # NOTE: Doesn't use compile_PBS_file_generic because it needs its own schema + # and shouldn't clear GameData::Species at the start. #============================================================================= def compile_pokemon_forms(path = "PBS/pokemon_forms.txt") compile_pbs_file_message_start(path) @@ -641,7 +460,7 @@ module Compiler # the keys are the XXX and the values are the YYY (as unprocessed strings). schema = GameData::Species.schema(true) idx = 0 - pbEachFileSection(f) { |contents, section_name| + pbEachFileSection(f, schema) { |contents, section_name| echo "." if idx % 50 == 0 Graphics.update if idx % 250 == 0 idx += 1 @@ -656,16 +475,26 @@ module Compiler # Skip empty properties next if contents[key].nil? # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value + if schema[key][1][0] == "^" + contents[key].each do |val| + value = pbGetCsvRecord(val, key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] ||= [] + data_hash[schema[key][0]].push(value) + end + data_hash[schema[key][0]].compact! + else + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value + end end # Validate and modify the compiled data validate_compiled_pokemon_form(data_hash) if GameData::Species.exists?(data_hash[:id]) - raise _INTL("Species ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + raise _INTL("Section name '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - # Add species's data to records + # Add section's data to records GameData::Species.register(data_hash) } } @@ -752,48 +581,9 @@ module Compiler # Compile Pokémon metrics data #============================================================================= def compile_pokemon_metrics(path = "PBS/pokemon_metrics.txt") - compile_pbs_file_message_start(path) - GameData::SpeciesMetrics::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::SpeciesMetrics::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_pokemon_metrics(data_hash) - if GameData::SpeciesMetrics.exists?(data_hash[:id]) - raise _INTL("Metrics for species '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add species' metrics to records - GameData::SpeciesMetrics.register(data_hash) - } - } - validate_all_compiled_pokemon_metrics - # Save all data - GameData::SpeciesMetrics.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::SpeciesMetrics, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_pokemon_metrics : validate_compiled_pokemon_metrics(hash) + end end def validate_compiled_pokemon_metrics(hash) @@ -816,48 +606,9 @@ module Compiler # Compile Shadow Pokémon data #============================================================================= def compile_shadow_pokemon(path = "PBS/shadow_pokemon.txt") - compile_pbs_file_message_start(path) - GameData::ShadowPokemon::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::ShadowPokemon::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_shadow_pokemon(data_hash) - if GameData::ShadowPokemon.exists?(data_hash[:id]) - raise _INTL("Species ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add Shadow Pokémon data to records - GameData::ShadowPokemon.register(data_hash) - } - } - validate_all_compiled_shadow_pokemon - # Save all data - GameData::ShadowPokemon.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::ShadowPokemon, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_shadow_pokemon : validate_compiled_shadow_pokemon(hash) + end end def validate_compiled_shadow_pokemon(hash) @@ -909,48 +660,9 @@ module Compiler # Compile ribbon data #============================================================================= def compile_ribbons(path = "PBS/ribbons.txt") - compile_pbs_file_message_start(path) - GameData::Ribbon::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::Ribbon::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_ribbon(data_hash) - if GameData::Ribbon.exists?(data_hash[:id]) - raise _INTL("Ribbon ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add ribbon data to records - GameData::Ribbon.register(data_hash) - } - } - validate_all_compiled_ribbons - # Save all data - GameData::Ribbon.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::Ribbon, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_ribbons : validate_compiled_ribbon(hash) + end end def validate_compiled_ribbon(hash) @@ -1081,48 +793,9 @@ module Compiler # Compile trainer type data #============================================================================= def compile_trainer_types(path = "PBS/trainer_types.txt") - compile_pbs_file_message_start(path) - GameData::TrainerType::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::TrainerType::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_trainer_type(data_hash) - if GameData::TrainerType.exists?(data_hash[:id]) - raise _INTL("Trainer type ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add trainer type data to records - GameData::TrainerType.register(data_hash) - } - } - validate_all_compiled_trainer_types - # Save all data - GameData::TrainerType.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::TrainerType, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_trainer_types : validate_compiled_trainer_type(hash) + end end def validate_compiled_trainer_type(hash) @@ -1143,7 +816,7 @@ module Compiler def compile_trainers(path = "PBS/trainers.txt") compile_pbs_file_message_start(path) GameData::Trainer::DATA.clear - schema = GameData::Trainer::SCHEMA + schema = GameData::Trainer.schema max_level = GameData::GrowthRate.max_level trainer_names = [] trainer_lose_texts = [] @@ -1386,6 +1059,8 @@ module Compiler #============================================================================= # Compile metadata + # NOTE: Doesn't use compile_PBS_file_generic because it contains data for two + # different GameData classes. #============================================================================= def compile_metadata(path = "PBS/metadata.txt") compile_pbs_file_message_start(path) @@ -1397,31 +1072,41 @@ module Compiler # 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). - global_schema = GameData::Metadata::SCHEMA - player_schema = GameData::PlayerMetadata::SCHEMA + global_schema = GameData::Metadata.schema + player_schema = GameData::PlayerMetadata.schema idx = 0 - pbEachFileSectionNumbered(f) { |contents, section_name| + pbEachFileSection(f) { |contents, section_name| echo "." if idx % 50 == 0 Graphics.update if idx % 250 == 0 idx += 1 - schema = (section_name == 0) ? global_schema : player_schema - data_hash = {:id => section_name} + schema = (section_name.to_i == 0) ? global_schema : player_schema + data_hash = {:id => section_name.to_sym} # Go through schema hash of compilable data and compile this section schema.each_key do |key| - FileLineData.setSection(section_name.to_s, key, contents[key]) # For error reporting + FileLineData.setSection(section_name, key, contents[key]) # For error reporting if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name.to_s, key, schema[key]) + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) next end # Skip empty properties next if contents[key].nil? # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value + if schema[key][1][0] == "^" + contents[key].each do |val| + value = pbGetCsvRecord(val, key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] ||= [] + data_hash[schema[key][0]].push(value) + end + data_hash[schema[key][0]].compact! + else + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value + end end # Validate and modify the compiled data - if section_name == 0 + if data_hash[:id] == 0 validate_compiled_global_metadata(data_hash) if GameData::Metadata.exists?(data_hash[:id]) raise _INTL("Global metadata ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) @@ -1432,8 +1117,8 @@ module Compiler raise _INTL("Player metadata ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end end - # Add trainer type data to records - if section_name == 0 + # Add section's data to records + if data_hash[:id] == 0 GameData::Metadata.register(data_hash) else GameData::PlayerMetadata.register(data_hash) @@ -1456,6 +1141,7 @@ module Compiler def validate_compiled_player_metadata(hash) end + # Should be used to check both global metadata and player character metadata. def validate_all_compiled_metadata # Ensure global metadata is defined if !GameData::Metadata.exists?(0) @@ -1474,48 +1160,9 @@ module Compiler # Compile map metadata #============================================================================= def compile_map_metadata(path = "PBS/map_metadata.txt") - compile_pbs_file_message_start(path) - GameData::MapMetadata::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::MapMetadata::SCHEMA - idx = 0 - pbEachFileSectionNumbered(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name.to_s, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name.to_s, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_map_metadata(data_hash) - if GameData::MapMetadata.exists?(data_hash[:id]) - raise _INTL("Map metadata for map '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add map metadata to records - GameData::MapMetadata.register(data_hash) - } - } - validate_all_compiled_map_metadata - # Save all data - GameData::MapMetadata.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::MapMetadata, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_map_metadata : validate_compiled_map_metadata(hash) + end end def validate_compiled_map_metadata(hash) @@ -1528,9 +1175,7 @@ module Compiler def validate_all_compiled_map_metadata # Get map names for translating map_names = [] - GameData::MapMetadata.each do |map| - map_names[map.id] = map.real_name - end + GameData::MapMetadata.each { |map| map_names[map.id] = map.real_name } MessageTypes.setMessages(MessageTypes::MapNames, map_names) end @@ -1538,97 +1183,24 @@ module Compiler # Compile dungeon tileset data #============================================================================= def compile_dungeon_tilesets(path = "PBS/dungeon_tilesets.txt") - compile_pbs_file_message_start(path) - GameData::DungeonTileset::DATA.clear - schema = GameData::DungeonTileset::SCHEMA - tileset_hash = nil - # Read each line of dungeon_tilesets.txt at a time and compile it as a tileset property - idx = 0 - pbCompilerEachPreppedLine(path) { |line, line_no| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - if line[/^\s*\[\s*(.+)\s*\]\s*$/] - # New section - # Add tileset's data to records - GameData::DungeonTileset.register(tileset_hash) if tileset_hash - # Construct tileset hash - tileset_hash = { - :id => $~[1].to_i, - :tile => [], - :autotile => [] - } - elsif line[/^\s*(\w+)\s*=\s*(.*)$/] - # XXX=YYY lines - if !tileset_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) - end - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Record XXX=YYY setting - case property_name - when "Tile", "Autotile" - tileset_hash[line_schema[0]].push(property_value) - else - tileset_hash[line_schema[0]] = property_value - end - end - } - # Add last tileset's data to records - GameData::DungeonTileset.register(tileset_hash) if tileset_hash - # Save all data - GameData::DungeonTileset.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::DungeonTileset, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_dungeon_tilesets : validate_compiled_dungeon_tileset(hash) + end + end + + def validate_compiled_dungeon_tileset(hash) + end + + def validate_all_compiled_dungeon_tilesets end #============================================================================= # Compile dungeon parameters data #============================================================================= def compile_dungeon_parameters(path = "PBS/dungeon_parameters.txt") - compile_pbs_file_message_start(path) - GameData::DungeonParameters::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::DungeonParameters::SCHEMA - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name.to_s, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name.to_s, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - # Validate and modify the compiled data - validate_compiled_dungeon_parameters(data_hash) - if GameData::DungeonParameters.exists?(data_hash[:id]) - raise _INTL("Dungeon ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add dungeon parameters to records - GameData::DungeonParameters.register(data_hash) - } - } - validate_all_compiled_dungeon_parameters - # Save all data - GameData::DungeonParameters.save - process_pbs_file_message_end + compile_PBS_file_generic(GameData::DungeonParameters, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_dungeon_parameters : validate_compiled_dungeon_parameters(hash) + end end def validate_compiled_dungeon_parameters(hash) diff --git a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb index ec31f3d51..c93410f9b 100644 --- a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb +++ b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb @@ -10,7 +10,7 @@ module Compiler def write_PBS_file_generic(game_data, path) write_pbs_file_message_start(path) - schema = game_data::SCHEMA + schema = game_data.schema File.open(path, "wb") { |f| add_PBS_header_to_file(f) # Write each element in turn @@ -27,9 +27,17 @@ module Compiler next if key == "SectionName" 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") + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end end end } @@ -40,27 +48,32 @@ module Compiler # Save Town Map data to PBS file #============================================================================= def write_town_map(path = "PBS/town_map.txt") - mapdata = pbLoadTownMapData - return if !mapdata write_pbs_file_message_start(path) + schema = { + "Name" => [0, "s"], + "Filename" => [1, "s"], + "Point" => [2, "^uussUUUU"] + } File.open(path, "wb") { |f| - idx = 0 add_PBS_header_to_file(f) - mapdata.length.times do |i| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - map = mapdata[i] - next if !map + # Write each element in turn + pbLoadTownMapData.each_with_index do |element, i| f.write("\#-------------------------------\r\n") f.write(sprintf("[%d]\r\n", i)) - rname = pbGetMessage(MessageTypes::RegionNames, i) - f.write(sprintf("Name = %s\r\n", (rname && rname != "") ? rname : _INTL("Unnamed"))) - f.write(sprintf("Filename = %s\r\n", csvQuote((map[1].is_a?(Array)) ? map[1][0] : map[1]))) - map[2].each do |loc| - f.write("Point = ") - pbWriteCsvRecord(loc, f, [nil, "uussUUUU"]) - f.write("\r\n") + schema.each_key do |key| + val = element[schema[key][0]] + next if val.nil? + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end end end } @@ -131,28 +144,7 @@ module Compiler # Save phone messages to PBS file #============================================================================= def write_phone(path = "PBS/phone.txt") - write_pbs_file_message_start(path) - keys = GameData::PhoneMessage::SCHEMA.keys - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write message sets - GameData::PhoneMessage.each do |contact| - f.write("\#-------------------------------\r\n") - if contact.id == "default" - f.write("[Default]\r\n") - elsif contact.version > 0 - f.write(sprintf("[%s,%s,%d]\r\n", contact.trainer_type, contact.real_name, contact.version)) - else - f.write(sprintf("[%s,%s]\r\n", contact.trainer_type, contact.real_name)) - end - keys.each do |key| - msgs = contact.property_from_string(key) - next if !msgs || msgs.length == 0 - msgs.each { |msg| f.write(key + " = " + msg + "\r\n") } - end - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::PhoneMessage, path) end #============================================================================= @@ -192,6 +184,8 @@ module Compiler #============================================================================= # Save Pokémon data to PBS file + # NOTE: Doesn't use write_PBS_file_generic because it needs to ignore defined + # species with a form that isn't 0. #============================================================================= def write_pokemon(path = "PBS/pokemon.txt") write_pbs_file_message_start(path) @@ -212,9 +206,17 @@ module Compiler next if key == "SectionName" 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") + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end end end } @@ -223,6 +225,8 @@ module Compiler #============================================================================= # Save Pokémon forms data to PBS file + # NOTE: Doesn't use write_PBS_file_generic because it needs to ignore defined + # species with a form of 0, and needs its own schema. #============================================================================= def write_pokemon_forms(path = "PBS/pokemon_forms.txt") write_pbs_file_message_start(path) @@ -244,9 +248,17 @@ module Compiler next if key == "SectionName" val = element.get_property_for_PBS(key, true) next if val.nil? - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(val, f, schema[key]) - f.write("\r\n") + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end end end } @@ -255,10 +267,13 @@ module Compiler #============================================================================= # Write species metrics + # NOTE: Doesn't use write_PBS_file_generic because it needs to ignore defined + # metrics for forms of species where the metrics are the same as for the + # base species. #============================================================================= def write_pokemon_metrics(path = "PBS/pokemon_metrics.txt") write_pbs_file_message_start(path) - schema = GameData::SpeciesMetrics::SCHEMA + schema = GameData::SpeciesMetrics.schema File.open(path, "wb") { |f| add_PBS_header_to_file(f) # Write each element in turn @@ -270,10 +285,6 @@ module Compiler element.front_sprite_altitude == base_element.front_sprite_altitude && element.shadow_x == base_element.shadow_x && element.shadow_size == base_element.shadow_size - else - next if element.back_sprite == [0, 0] && element.front_sprite == [0, 0] && - element.front_sprite_altitude == 0 && - element.shadow_x == 0 && element.shadow_size == 2 end f.write("\#-------------------------------\r\n") if schema["SectionName"] @@ -287,9 +298,17 @@ module Compiler next if key == "SectionName" 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") + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end end end } @@ -556,11 +575,13 @@ module Compiler #============================================================================= # Save metadata data to PBS file + # NOTE: Doesn't use write_PBS_file_generic because it contains data for two + # different GameData classes. #============================================================================= def write_metadata(path = "PBS/metadata.txt") write_pbs_file_message_start(path) - global_schema = GameData::Metadata::SCHEMA - player_schema = GameData::PlayerMetadata::SCHEMA + global_schema = GameData::Metadata.schema + player_schema = GameData::PlayerMetadata.schema File.open(path, "wb") { |f| add_PBS_header_to_file(f) # Write each element in turn @@ -580,9 +601,17 @@ module Compiler next if key == "SectionName" 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") + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end end end end @@ -592,11 +621,13 @@ module Compiler #============================================================================= # Save map metadata data to PBS file + # NOTE: Doesn't use write_PBS_file_generic because it writes the RMXP map name + # next to the section header for each map. #============================================================================= def write_map_metadata(path = "PBS/map_metadata.txt") write_pbs_file_message_start(path) map_infos = pbLoadMapInfos - schema = GameData::MapMetadata::SCHEMA + schema = GameData::MapMetadata.schema File.open(path, "wb") { |f| idx = 0 add_PBS_header_to_file(f) @@ -613,9 +644,17 @@ module Compiler next if key == "SectionName" 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") + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end end end } @@ -624,48 +663,40 @@ module Compiler #============================================================================= # Save dungeon tileset contents data to PBS file + # NOTE: Doesn't use write_PBS_file_generic because it writes the tileset name + # next to the section header for each tileset. #============================================================================= def write_dungeon_tilesets(path = "PBS/dungeon_tilesets.txt") write_pbs_file_message_start(path) tilesets = load_data("Data/Tilesets.rxdata") - schema = GameData::DungeonTileset::SCHEMA - keys = schema.keys + schema = GameData::DungeonTileset.schema File.open(path, "wb") { |f| - idx = 0 add_PBS_header_to_file(f) - GameData::DungeonTileset.each do |tileset_data| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 + # Write each element in turn + GameData::DungeonTileset.each do |element| f.write("\#-------------------------------\r\n") - tileset_name = (tilesets && tilesets[tileset_data.id]) ? tilesets[tileset_data.id].name : nil - if tileset_name - f.write(sprintf("[%d] # %s\r\n", tileset_data.id, tileset_name)) + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]") + f.write(" # #{tilesets[element.id].name}") if tilesets && tilesets[element.id] + f.write("\r\n") else - f.write(sprintf("[%d]\r\n", tileset_data.id)) + f.write("[#{element.id}]\r\n") end - keys.each do |key| - if ["Autotile", "Tile"].include?(key) - tiles = tileset_data.tile_type_ids - tiles.each do |tile_type, tile_ids| - tile_ids.each do |tile| - next if tile[1] # Tile was auto-generated from "walls" property - if tile[0] < 384 - next if key == "Tile" - f.write(sprintf("Autotile = %i,%s", tile[0] / 48, tile_type.to_s)) - else - next if key == "Autotile" - f.write(sprintf("Tile = %i,%s", tile[0] - 384, tile_type.to_s)) - end - f.write("\r\n") - end + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key) + next if val.nil? + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") end else - record = tileset_data.property_from_string(key) - next if record.nil? || (record.is_a?(Array) && record.empty?) - next if record == false || record == 0 f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(record, f, schema[key]) + pbWriteCsvRecord(val, f, schema[key]) f.write("\r\n") end end diff --git a/PBS/phone.txt b/PBS/phone.txt index c8084c76f..46080d9c1 100644 --- a/PBS/phone.txt +++ b/PBS/phone.txt @@ -28,7 +28,7 @@ Body1 = My \TP is looking more and more like me. It's getting cuter! Body2 = And you know? Now we can KO \TE easily.\mI should challenge the Cedolan Gym. Body2 = And you know? We just failed to beat \TE by a tiny margin.\mI'm guessing my Pokémon's levels aren't high enough yet... BattleRequest = You must be a lot better now, huh?\mHow about showing me your technique in a real battle with me?\mI'll be waiting on \TM. -BattleReminder = Where are you? Let's have our battle soon!\mI'll be waiting on \TM. +BattleRemind = Where are you? Let's have our battle soon!\mI'll be waiting on \TM. End = See you later! #------------------------------- [PICNICKER,Susie] @@ -44,5 +44,5 @@ Body1 = My \TP and I are getting more in sync with each other. Body2 = We battled a wild \TE and managed to beat it in a close match.\mWe're getting into the groove! Body2 = But, you know what? I still haven't caught \TE.\mIt's getting beyond frustrating... BattleRequest = Would you be my practice partner again sometime?\mI'll be waiting on \TM...\mCould you take it a little easier on me next time? -BattleReminder = How soon can I expect to see you?\mDon't forget, \TM! +BattleRemind = How soon can I expect to see you?\mDon't forget, \TM! End = Bye! Let's chat again! diff --git a/PBS/town_map.txt b/PBS/town_map.txt index c0cacc79f..11891d45a 100644 --- a/PBS/town_map.txt +++ b/PBS/town_map.txt @@ -3,34 +3,34 @@ [0] Name = Essen Filename = mapRegion0.png -Point = 13,12,Lappet Town,Oak's Lab,2,8,8, -Point = 13,11,Route 1,,,,, -Point = 13,10,Cedolan City,Cedolan Dept. Store,7,47,11, -Point = 14,10,Cedolan City,,7,47,11, -Point = 14,9,Route 2,,,,, -Point = 14,8,Route 2,,,,, -Point = 15,8,Lerucean Town,,23,11,15, -Point = 16,8,Natural Park,,,,, -Point = 15,7,Route 3,,,,, -Point = 15,6,Route 3,Ice Cave,,,, -Point = 14,6,Route 3,,,,, -Point = 13,6,Ingido Plateau,,35,17,7, -Point = 12,6,Route 4,,,,, -Point = 11,6,Route 4,,,,, -Point = 11,7,Route 5,Cycle Road,,,, -Point = 11,8,Route 5,Cycle Road,,,, -Point = 11,9,Route 5,Cycle Road,,,, -Point = 11,10,Route 6,,,,, -Point = 12,10,Route 6,,,,, -Point = 15,10,Route 7,,,,, -Point = 16,10,Route 7,Rock Cave,,,, -Point = 17,10,Battle Frontier,,52,17,14, -Point = 12,12,Safari Zone,,,,, -Point = 13,13,Route 8,Diving area,,,, -Point = 18,17,Berth Island,,,,,51 -Point = 22,16,Faraday Island,,,,,52 +Point = 13,12,Lappet Town,Oak's Lab,2,8,8 +Point = 13,11,Route 1, +Point = 13,10,Cedolan City,Cedolan Dept. Store,7,47,11 +Point = 14,10,Cedolan City,,7,47,11 +Point = 14,9,Route 2, +Point = 14,8,Route 2, +Point = 15,8,Lerucean Town,,23,11,15 +Point = 16,8,Natural Park, +Point = 15,7,Route 3, +Point = 15,6,Route 3,Ice Cave +Point = 14,6,Route 3, +Point = 13,6,Ingido Plateau,,35,17,7 +Point = 12,6,Route 4, +Point = 11,6,Route 4, +Point = 11,7,Route 5,Cycle Road +Point = 11,8,Route 5,Cycle Road +Point = 11,9,Route 5,Cycle Road +Point = 11,10,Route 6, +Point = 12,10,Route 6, +Point = 15,10,Route 7, +Point = 16,10,Route 7,Rock Cave +Point = 17,10,Battle Frontier,,52,17,14 +Point = 12,12,Safari Zone, +Point = 13,13,Route 8,Diving area +Point = 18,17,Berth Island,,51 +Point = 22,16,Faraday Island,,52 #------------------------------- [1] Name = Tiall Filename = mapRegion1.png -Point = 13,16,Here,,,,, +Point = 13,16,Here, From 4d147a7bf70af7b844e6a3ee89093410431789eb Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 20 Nov 2022 21:44:53 +0000 Subject: [PATCH 04/12] Turned Town Map PBS data into a GameData class --- Data/Scripts/010_Data/001_GameData.rb | 1 + .../010_Data/002_PBS data/001_MiscPBSData.rb | 13 -- .../010_Data/002_PBS data/002_TownMap.rb | 40 +++++ .../002_PBS data/{002_Type.rb => 003_Type.rb} | 0 .../{003_Ability.rb => 004_Ability.rb} | 0 .../002_PBS data/{004_Move.rb => 005_Move.rb} | 0 .../002_PBS data/{005_Item.rb => 006_Item.rb} | 0 .../{006_BerryPlant.rb => 007_BerryPlant.rb} | 0 .../{007_Species.rb => 008_Species.rb} | 0 ..._Species_Files.rb => 009_Species_files.rb} | 0 ...peciesMetrics.rb => 010_SpeciesMetrics.rb} | 0 ..._ShadowPokemon.rb => 011_ShadowPokemon.rb} | 0 .../{011_Ribbon.rb => 012_Ribbon.rb} | 0 .../{012_Encounter.rb => 013_Encounter.rb} | 0 ...{013_TrainerType.rb => 014_TrainerType.rb} | 0 .../{014_Trainer.rb => 015_Trainer.rb} | 0 .../{015_Metadata.rb => 016_Metadata.rb} | 0 ...layerMetadata.rb => 017_PlayerMetadata.rb} | 0 ...{017_MapMetadata.rb => 018_MapMetadata.rb} | 0 ...ungeonTileset.rb => 019_DungeonTileset.rb} | 0 ...20_PhoneMessage.rb => 021_PhoneMessage.rb} | 0 Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb | 8 +- Data/Scripts/016_UI/009_UI_RegionMap.rb | 59 +++---- .../003_EditorScreens_MapConnections.rb | 5 +- .../Scripts/020_Debug/002_Editor_DataTypes.rb | 17 +-- .../021_Compiler/002_Compiler_CompilePBS.rb | 144 ++++++------------ .../021_Compiler/003_Compiler_WritePBS.rb | 45 +----- 27 files changed, 127 insertions(+), 205 deletions(-) create mode 100644 Data/Scripts/010_Data/002_PBS data/002_TownMap.rb rename Data/Scripts/010_Data/002_PBS data/{002_Type.rb => 003_Type.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{003_Ability.rb => 004_Ability.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{004_Move.rb => 005_Move.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{005_Item.rb => 006_Item.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{006_BerryPlant.rb => 007_BerryPlant.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{007_Species.rb => 008_Species.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{008_Species_Files.rb => 009_Species_files.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{009_SpeciesMetrics.rb => 010_SpeciesMetrics.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{010_ShadowPokemon.rb => 011_ShadowPokemon.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{011_Ribbon.rb => 012_Ribbon.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{012_Encounter.rb => 013_Encounter.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{013_TrainerType.rb => 014_TrainerType.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{014_Trainer.rb => 015_Trainer.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{015_Metadata.rb => 016_Metadata.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{016_PlayerMetadata.rb => 017_PlayerMetadata.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{017_MapMetadata.rb => 018_MapMetadata.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{018_DungeonTileset.rb => 019_DungeonTileset.rb} (100%) rename Data/Scripts/010_Data/002_PBS data/{020_PhoneMessage.rb => 021_PhoneMessage.rb} (100%) diff --git a/Data/Scripts/010_Data/001_GameData.rb b/Data/Scripts/010_Data/001_GameData.rb index 92d972cee..eacfaf053 100644 --- a/Data/Scripts/010_Data/001_GameData.rb +++ b/Data/Scripts/010_Data/001_GameData.rb @@ -246,6 +246,7 @@ module GameData # A bulk loader method for all data stored in .dat files in the Data folder. #============================================================================= def self.load_all + TownMap.load Type.load Ability.load Move.load diff --git a/Data/Scripts/010_Data/002_PBS data/001_MiscPBSData.rb b/Data/Scripts/010_Data/002_PBS data/001_MiscPBSData.rb index 8b5da65b0..b6bddb673 100644 --- a/Data/Scripts/010_Data/002_PBS data/001_MiscPBSData.rb +++ b/Data/Scripts/010_Data/002_PBS data/001_MiscPBSData.rb @@ -2,7 +2,6 @@ # Data caches. #=============================================================================== class Game_Temp - attr_accessor :town_map_data attr_accessor :regional_dexes_data attr_accessor :battle_animations_data attr_accessor :move_to_battle_animation_data @@ -11,7 +10,6 @@ end def pbClearData if $game_temp - $game_temp.town_map_data = nil $game_temp.regional_dexes_data = nil $game_temp.battle_animations_data = nil $game_temp.move_to_battle_animation_data = nil @@ -24,17 +22,6 @@ def pbClearData end end -#=============================================================================== -# Method to get Town Map data. -#=============================================================================== -def pbLoadTownMapData - $game_temp = Game_Temp.new if !$game_temp - if !$game_temp.town_map_data - $game_temp.town_map_data = load_data("Data/town_map.dat") - end - return $game_temp.town_map_data -end - #=============================================================================== # Method to get Regional Dexes data. #=============================================================================== diff --git a/Data/Scripts/010_Data/002_PBS data/002_TownMap.rb b/Data/Scripts/010_Data/002_PBS data/002_TownMap.rb new file mode 100644 index 000000000..a11d850a1 --- /dev/null +++ b/Data/Scripts/010_Data/002_PBS data/002_TownMap.rb @@ -0,0 +1,40 @@ +module GameData + class TownMap + attr_reader :id + attr_reader :real_name + attr_reader :filename + attr_reader :point + attr_reader :flags + + DATA = {} + DATA_FILENAME = "town_map.dat" + + SCHEMA = { + "SectionName" => [:id, "u"], + "Name" => [:real_name, "s"], + "Filename" => [:filename, "s"], + "Point" => [:point, "^uussUUUU"], + "Flags" => [:flags, "*s"] + } + + extend ClassMethodsIDNumbers + include InstanceMethods + + def initialize(hash) + @id = hash[:id] + @real_name = hash[:real_name] || "???" + @filename = hash[:filename] + @point = hash[:point] || [] + @flags = hash[:flags] || [] + end + + # @return [String] the translated name of this region + def name + return pbGetMessage(MessageTypes::RegionNames, @id) + end + + def has_flag?(flag) + return @flags.any? { |f| f.downcase == flag.downcase } + end + end +end diff --git a/Data/Scripts/010_Data/002_PBS data/002_Type.rb b/Data/Scripts/010_Data/002_PBS data/003_Type.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/002_Type.rb rename to Data/Scripts/010_Data/002_PBS data/003_Type.rb diff --git a/Data/Scripts/010_Data/002_PBS data/003_Ability.rb b/Data/Scripts/010_Data/002_PBS data/004_Ability.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/003_Ability.rb rename to Data/Scripts/010_Data/002_PBS data/004_Ability.rb diff --git a/Data/Scripts/010_Data/002_PBS data/004_Move.rb b/Data/Scripts/010_Data/002_PBS data/005_Move.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/004_Move.rb rename to Data/Scripts/010_Data/002_PBS data/005_Move.rb diff --git a/Data/Scripts/010_Data/002_PBS data/005_Item.rb b/Data/Scripts/010_Data/002_PBS data/006_Item.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/005_Item.rb rename to Data/Scripts/010_Data/002_PBS data/006_Item.rb diff --git a/Data/Scripts/010_Data/002_PBS data/006_BerryPlant.rb b/Data/Scripts/010_Data/002_PBS data/007_BerryPlant.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/006_BerryPlant.rb rename to Data/Scripts/010_Data/002_PBS data/007_BerryPlant.rb diff --git a/Data/Scripts/010_Data/002_PBS data/007_Species.rb b/Data/Scripts/010_Data/002_PBS data/008_Species.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/007_Species.rb rename to Data/Scripts/010_Data/002_PBS data/008_Species.rb diff --git a/Data/Scripts/010_Data/002_PBS data/008_Species_Files.rb b/Data/Scripts/010_Data/002_PBS data/009_Species_files.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/008_Species_Files.rb rename to Data/Scripts/010_Data/002_PBS data/009_Species_files.rb diff --git a/Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb b/Data/Scripts/010_Data/002_PBS data/010_SpeciesMetrics.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/009_SpeciesMetrics.rb rename to Data/Scripts/010_Data/002_PBS data/010_SpeciesMetrics.rb diff --git a/Data/Scripts/010_Data/002_PBS data/010_ShadowPokemon.rb b/Data/Scripts/010_Data/002_PBS data/011_ShadowPokemon.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/010_ShadowPokemon.rb rename to Data/Scripts/010_Data/002_PBS data/011_ShadowPokemon.rb diff --git a/Data/Scripts/010_Data/002_PBS data/011_Ribbon.rb b/Data/Scripts/010_Data/002_PBS data/012_Ribbon.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/011_Ribbon.rb rename to Data/Scripts/010_Data/002_PBS data/012_Ribbon.rb diff --git a/Data/Scripts/010_Data/002_PBS data/012_Encounter.rb b/Data/Scripts/010_Data/002_PBS data/013_Encounter.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/012_Encounter.rb rename to Data/Scripts/010_Data/002_PBS data/013_Encounter.rb diff --git a/Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb b/Data/Scripts/010_Data/002_PBS data/014_TrainerType.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/013_TrainerType.rb rename to Data/Scripts/010_Data/002_PBS data/014_TrainerType.rb diff --git a/Data/Scripts/010_Data/002_PBS data/014_Trainer.rb b/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/014_Trainer.rb rename to Data/Scripts/010_Data/002_PBS data/015_Trainer.rb diff --git a/Data/Scripts/010_Data/002_PBS data/015_Metadata.rb b/Data/Scripts/010_Data/002_PBS data/016_Metadata.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/015_Metadata.rb rename to Data/Scripts/010_Data/002_PBS data/016_Metadata.rb diff --git a/Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb b/Data/Scripts/010_Data/002_PBS data/017_PlayerMetadata.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/016_PlayerMetadata.rb rename to Data/Scripts/010_Data/002_PBS data/017_PlayerMetadata.rb diff --git a/Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb b/Data/Scripts/010_Data/002_PBS data/018_MapMetadata.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/017_MapMetadata.rb rename to Data/Scripts/010_Data/002_PBS data/018_MapMetadata.rb diff --git a/Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb b/Data/Scripts/010_Data/002_PBS data/019_DungeonTileset.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/018_DungeonTileset.rb rename to Data/Scripts/010_Data/002_PBS data/019_DungeonTileset.rb diff --git a/Data/Scripts/010_Data/002_PBS data/020_PhoneMessage.rb b/Data/Scripts/010_Data/002_PBS data/021_PhoneMessage.rb similarity index 100% rename from Data/Scripts/010_Data/002_PBS data/020_PhoneMessage.rb rename to Data/Scripts/010_Data/002_PBS data/021_PhoneMessage.rb diff --git a/Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb b/Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb index eabdf250c..ba1a5fec4 100644 --- a/Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb +++ b/Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb @@ -17,13 +17,13 @@ class PokemonPokedexInfo_Scene @sprites["infosprite"].setOffset(PictureOrigin::CENTER) @sprites["infosprite"].x = 104 @sprites["infosprite"].y = 136 - @mapdata = pbLoadTownMapData mappos = $game_map.metadata&.town_map_position if @region < 0 # Use player's current region @region = (mappos) ? mappos[0] : 0 # Region 0 default end + @mapdata = GameData::TownMap.get(@region) @sprites["areamap"] = IconSprite.new(0, 0, @viewport) - @sprites["areamap"].setBitmap("Graphics/UI/Town Map/#{@mapdata[@region][1]}") + @sprites["areamap"].setBitmap("Graphics/UI/Town Map/#{@mapdata.filename}") @sprites["areamap"].x += (Graphics.width - @sprites["areamap"].bitmap.width) / 2 @sprites["areamap"].y += (Graphics.height + 32 - @sprites["areamap"].bitmap.height) / 2 Settings::REGION_MAP_EXTRAS.each do |hidden| @@ -296,7 +296,7 @@ class PokemonPokedexInfo_Scene # defined point in town_map.txt, and which either have no Self Switch # controlling their visibility or whose Self Switch is ON) visible_points = [] - @mapdata[@region][2].each do |loc| + @mapdata.point.each do |loc| next if loc[7] && !$game_switches[loc[7]] # Point is not visible visible_points.push([loc[0], loc[1]]) end @@ -375,7 +375,7 @@ class PokemonPokedexInfo_Scene ) textpos.push([_INTL("Area unknown"), Graphics.width / 2, (Graphics.height / 2) + 6, 2, base, shadow]) end - textpos.push([pbGetMessage(MessageTypes::RegionNames, @region), 414, 50, 2, base, shadow]) + textpos.push([@mapdata.name, 414, 50, 2, base, shadow]) textpos.push([_INTL("{1}'s area", GameData::Species.get(@species).name), Graphics.width / 2, 358, 2, base, shadow]) pbDrawTextPositions(overlay, textpos) diff --git a/Data/Scripts/016_UI/009_UI_RegionMap.rb b/Data/Scripts/016_UI/009_UI_RegionMap.rb index 5c5b4264b..bd902a26e 100644 --- a/Data/Scripts/016_UI/009_UI_RegionMap.rb +++ b/Data/Scripts/016_UI/009_UI_RegionMap.rb @@ -72,27 +72,26 @@ class PokemonRegionMap_Scene @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @viewport.z = 99999 @sprites = {} - @map_data = pbLoadTownMapData @fly_map = fly_map @mode = fly_map ? 1 : 0 map_metadata = $game_map.metadata playerpos = (map_metadata) ? map_metadata.town_map_position : nil if !playerpos mapindex = 0 - @map = @map_data[0] + @map = GameData::TownMap.get(0) @map_x = LEFT @map_y = TOP - elsif @region >= 0 && @region != playerpos[0] && @map_data[@region] + elsif @region >= 0 && @region != playerpos[0] && GameData::TownMap.exists?(@region) mapindex = @region - @map = @map_data[@region] + @map = GameData::TownMap.get(@region) @map_x = LEFT @map_y = TOP else mapindex = playerpos[0] - @map = @map_data[playerpos[0]] - @map_x = playerpos[1] - @map_y = playerpos[2] - mapsize = map_metadata.town_map_size + @map = GameData::TownMap.get(playerpos[0]) + @map_x = playerpos[1] + @map_y = playerpos[2] + mapsize = map_metadata.town_map_size if mapsize && mapsize[0] && mapsize[0] > 0 sqwidth = mapsize[0] sqheight = (mapsize[1].length.to_f / mapsize[0]).ceil @@ -106,7 +105,7 @@ class PokemonRegionMap_Scene end addBackgroundOrColoredPlane(@sprites, "background", "Town Map/bg", Color.black, @viewport) @sprites["map"] = IconSprite.new(0, 0, @viewport) - @sprites["map"].setBitmap("Graphics/UI/Town Map/#{@map[1]}") + @sprites["map"].setBitmap("Graphics/UI/Town Map/#{@map.filename}") @sprites["map"].x += (Graphics.width - @sprites["map"].bitmap.width) / 2 @sprites["map"].y += (Graphics.height - @sprites["map"].bitmap.height) / 2 Settings::REGION_MAP_EXTRAS.each do |graphic| @@ -122,7 +121,7 @@ class PokemonRegionMap_Scene ) end @sprites["mapbottom"] = MapBottomSprite.new(@viewport) - @sprites["mapbottom"].mapname = pbGetMessage(MessageTypes::RegionNames, mapindex) + @sprites["mapbottom"].mapname = @map.name @sprites["mapbottom"].maplocation = pbGetMapLocation(@map_x, @map_y) @sprites["mapbottom"].mapdetails = pbGetMapDetails(@map_x, @map_y) if playerpos && mapindex == playerpos[0] @@ -177,27 +176,13 @@ class PokemonRegionMap_Scene end def pbSaveMapData - File.open("PBS/town_map.txt", "wb") { |f| - Compiler.add_PBS_header_to_file(f) - @map_data.length.times do |i| - map = @map_data[i] - next if !map - f.write("\#-------------------------------\r\n") - f.write(sprintf("[%d]\r\n", i)) - f.write(sprintf("Name = %s\r\n", Compiler.csvQuote(map[0]))) - f.write(sprintf("Filename = %s\r\n", Compiler.csvQuote(map[1]))) - map[2].each do |loc| - f.write("Point = ") - Compiler.pbWriteCsvRecord(loc, f, [nil, "uussUUUU"]) - f.write("\r\n") - end - end - } + GameData::TownMap.save + Compiler.write_town_map end def pbGetMapLocation(x, y) - return "" if !@map[2] - @map[2].each do |point| + return "" if !@map.point + @map.point.each do |point| next if point[0] != x || point[1] != y return "" if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]]) name = pbGetMessageFromHash(MessageTypes::PlaceNames, point[2]) @@ -207,25 +192,25 @@ class PokemonRegionMap_Scene end def pbChangeMapLocation(x, y) - return "" if !@editor || !@map[2] - map = @map[2].select { |loc| loc[0] == x && loc[1] == y }[0] - currentobj = map - currentname = (map) ? map[2] || "" : "" + return "" if !@editor || !@map.point + point = @map.point.select { |loc| loc[0] == x && loc[1] == y }[0] + currentobj = point + currentname = (point) ? point[2] : "" currentname = pbMessageFreeText(_INTL("Set the name for this point."), currentname, false, 250) { pbUpdate } if currentname if currentobj currentobj[2] = currentname else newobj = [x, y, currentname, ""] - @map[2].push(newobj) + @map.point.push(newobj) end @changed = true end end def pbGetMapDetails(x, y) # From Wichu, with my help - return "" if !@map[2] - @map[2].each do |point| + return "" if !@map.point + @map.point.each do |point| next if point[0] != x || point[1] != y return "" if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]]) mapdesc = pbGetMessageFromHash(MessageTypes::PlaceDescriptions, point[3]) @@ -235,8 +220,8 @@ class PokemonRegionMap_Scene end def pbGetHealingSpot(x, y) - return nil if !@map[2] - @map[2].each do |point| + return nil if !@map.point + @map.point.each do |point| next if point[0] != x || point[1] != y return nil if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]]) return (point[4] && point[5] && point[6]) ? [point[4], point[5], point[6]] : nil diff --git a/Data/Scripts/020_Debug/001_Editor screens/003_EditorScreens_MapConnections.rb b/Data/Scripts/020_Debug/001_Editor screens/003_EditorScreens_MapConnections.rb index 8b970efd2..ae47d55bd 100644 --- a/Data/Scripts/020_Debug/001_Editor screens/003_EditorScreens_MapConnections.rb +++ b/Data/Scripts/020_Debug/001_Editor screens/003_EditorScreens_MapConnections.rb @@ -105,9 +105,8 @@ class RegionMapSprite end def createRegionMap(map) - @mapdata = pbLoadTownMapData - @map = @mapdata[map] - bitmap = AnimatedBitmap.new("Graphics/UI/Town Map/#{@map[1]}").deanimate + town_map = GameData::TownMap.get(map) + bitmap = AnimatedBitmap.new("Graphics/UI/Town Map/#{town_map.filename}").deanimate retbitmap = BitmapWrapper.new(bitmap.width / 2, bitmap.height / 2) retbitmap.stretch_blt( Rect.new(0, 0, bitmap.width / 2, bitmap.height / 2), diff --git a/Data/Scripts/020_Debug/002_Editor_DataTypes.rb b/Data/Scripts/020_Debug/002_Editor_DataTypes.rb index de0beff16..8a5b6d45d 100644 --- a/Data/Scripts/020_Debug/002_Editor_DataTypes.rb +++ b/Data/Scripts/020_Debug/002_Editor_DataTypes.rb @@ -769,15 +769,10 @@ module RegionMapCoordsProperty selregion = regions[0][0] else cmds = [] - regions.each do |region| - cmds.push(region[1]) - end + regions.each { |region| cmds.push(region[1]) } selcmd = pbMessage(_INTL("Choose a region map."), cmds, -1) - if selcmd >= 0 - selregion = regions[selcmd][0] - else - return oldsetting - end + return oldsetting if selcmd < 0 + selregion = regions[selcmd][0] end mappoint = chooseMapPoint(selregion, true) return (mappoint) ? [selregion, mappoint[0], mappoint[1]] : oldsetting @@ -788,12 +783,8 @@ module RegionMapCoordsProperty end def self.getMapNameList - mapdata = pbLoadTownMapData ret = [] - mapdata.length.times do |i| - next if !mapdata[i] - ret.push([i, pbGetMessage(MessageTypes::RegionNames, i)]) - end + GameData::TownMap.each { |town_map| ret.push([town_map.id, town_map.name]) } return ret end end diff --git a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb index 00fa43090..9dd7d2da1 100644 --- a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb +++ b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb @@ -60,80 +60,28 @@ module Compiler # Compile Town Map data #============================================================================= def compile_town_map(path = "PBS/town_map.txt") - compile_pbs_file_message_start(path) - sections = [] - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = { - "SectionName" => [:id, "u"], - "Name" => [:real_name, "s"], - "Filename" => [:filename, "s"], - "Point" => [:point, "^uussUUUU"] - } - idx = 0 - pbEachFileSection(f, schema) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - if schema[key][1][0] == "^" - contents[key].each do |val| - value = pbGetCsvRecord(val, key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] ||= [] - data_hash[schema[key][0]].push(value) - end - data_hash[schema[key][0]].compact! - else - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value - end - end - # Validate and modify the compiled data - validate_compiled_town_map(data_hash) - if sections[data_hash[:id]] - raise _INTL("Region ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add town map messages to records - sections[data_hash[:id]] = [data_hash[:real_name], data_hash[:filename], data_hash[:point]] - } - } - validate_all_compiled_town_maps(sections) - # Save all data - save_data(sections, "Data/town_map.dat") - process_pbs_file_message_end + compile_PBS_file_generic(GameData::TownMap, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_town_maps : validate_compiled_town_map(hash) + end end def validate_compiled_town_map(hash) end - def validate_all_compiled_town_maps(sections) + def validate_all_compiled_town_maps # Get town map names and descriptions for translating region_names = [] point_names = [] interest_names = [] - sections.each_with_index do |region, i| - region_names[i] = region[0] - region[2].each do |point| + GameData::TownMap.each do |town_map| + region_names[town_map.id] = town_map.real_name + town_map.point.each do |point| point_names.push(point[2]) interest_names.push(point[3]) end end + point_names.uniq! + interest_names.uniq! MessageTypes.setMessages(MessageTypes::RegionNames, region_names) MessageTypes.setMessagesAsHash(MessageTypes::PlaceNames, point_names) MessageTypes.setMessagesAsHash(MessageTypes::PlaceDescriptions, interest_names) @@ -182,43 +130,6 @@ module Compiler process_pbs_file_message_end end - #============================================================================= - # Compile phone messages - #============================================================================= - def compile_phone(path = "PBS/phone.txt") - compile_PBS_file_generic(GameData::PhoneMessage, path) do |final_validate, hash| - (final_validate) ? validate_all_compiled_phone_contacts : validate_compiled_phone_contact(hash) - end - end - - def validate_compiled_phone_contact(hash) - # Split trainer type/name/version into their own values, generate compound ID from them - if hash[:id].strip.downcase == "default" - hash[:id] = "default" - hash[:trainer_type] = hash[:id] - else - line_data = pbGetCsvRecord(hash[:id], -1, [0, "esU", :TrainerType]) - hash[:trainer_type] = line_data[0] - hash[:real_name] = line_data[1] - hash[:version] = line_data[2] || 0 - hash[:id] = [hash[:trainer_type], hash[:real_name], hash[:version]] - end - end - - def validate_all_compiled_phone_contacts - # Get all phone messages for translating - messages = [] - GameData::PhoneMessage.each do |contact| - [:intro, :intro_morning, :intro_afternoon, :intro_evening, :body, :body1, - :body2, :battle_request, :battle_remind, :end].each do |msg_type| - msgs = contact.send(msg_type) - next if !msgs || msgs.length == 0 - msgs.each { |msg| messages.push(msg) } - end - end - MessageTypes.setMessagesAsHash(MessageTypes::PhoneMessages, messages) - end - #============================================================================= # Compile type data #============================================================================= @@ -1220,6 +1131,43 @@ module Compiler def validate_all_compiled_dungeon_parameters end + #============================================================================= + # Compile phone messages + #============================================================================= + def compile_phone(path = "PBS/phone.txt") + compile_PBS_file_generic(GameData::PhoneMessage, path) do |final_validate, hash| + (final_validate) ? validate_all_compiled_phone_contacts : validate_compiled_phone_contact(hash) + end + end + + def validate_compiled_phone_contact(hash) + # Split trainer type/name/version into their own values, generate compound ID from them + if hash[:id].strip.downcase == "default" + hash[:id] = "default" + hash[:trainer_type] = hash[:id] + else + line_data = pbGetCsvRecord(hash[:id], -1, [0, "esU", :TrainerType]) + hash[:trainer_type] = line_data[0] + hash[:real_name] = line_data[1] + hash[:version] = line_data[2] || 0 + hash[:id] = [hash[:trainer_type], hash[:real_name], hash[:version]] + end + end + + def validate_all_compiled_phone_contacts + # Get all phone messages for translating + messages = [] + GameData::PhoneMessage.each do |contact| + [:intro, :intro_morning, :intro_afternoon, :intro_evening, :body, :body1, + :body2, :battle_request, :battle_remind, :end].each do |msg_type| + msgs = contact.send(msg_type) + next if !msgs || msgs.length == 0 + msgs.each { |msg| messages.push(msg) } + end + end + MessageTypes.setMessagesAsHash(MessageTypes::PhoneMessages, messages) + end + #============================================================================= # Compile battle animations #============================================================================= diff --git a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb index c93410f9b..0a85c3e1a 100644 --- a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb +++ b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb @@ -48,36 +48,7 @@ module Compiler # Save Town Map data to PBS file #============================================================================= def write_town_map(path = "PBS/town_map.txt") - write_pbs_file_message_start(path) - schema = { - "Name" => [0, "s"], - "Filename" => [1, "s"], - "Point" => [2, "^uussUUUU"] - } - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each element in turn - pbLoadTownMapData.each_with_index do |element, i| - f.write("\#-------------------------------\r\n") - f.write(sprintf("[%d]\r\n", i)) - schema.each_key do |key| - val = element[schema[key][0]] - next if val.nil? - if schema[key][1][0] == "^" && val.is_a?(Array) - val.each do |sub_val| - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(sub_val, f, schema[key]) - f.write("\r\n") - end - else - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(val, f, schema[key]) - f.write("\r\n") - end - end - end - } - process_pbs_file_message_end + write_PBS_file_generic(GameData::TownMap, path) end #============================================================================= @@ -140,13 +111,6 @@ module Compiler process_pbs_file_message_end end - #============================================================================= - # Save phone messages to PBS file - #============================================================================= - def write_phone(path = "PBS/phone.txt") - write_PBS_file_generic(GameData::PhoneMessage, path) - end - #============================================================================= # Save type data to PBS file #============================================================================= @@ -712,6 +676,13 @@ module Compiler write_PBS_file_generic(GameData::DungeonParameters, path) end + #============================================================================= + # Save phone messages to PBS file + #============================================================================= + def write_phone(path = "PBS/phone.txt") + write_PBS_file_generic(GameData::PhoneMessage, path) + end + #============================================================================= # Save all data to PBS files #============================================================================= From bd041121225476aebc00e1aa4275ae3c8572152e Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Tue, 22 Nov 2022 22:24:30 +0000 Subject: [PATCH 05/12] Allowed multiple PBS files per data type, removed hardcoded lists of PBS files/.dat files/GameData classes that need data loading --- Data/Scripts/010_Data/001_GameData.rb | 48 +- .../010_Data/002_PBS data/002_TownMap.rb | 13 +- .../Scripts/010_Data/002_PBS data/003_Type.rb | 27 +- .../010_Data/002_PBS data/004_Ability.rb | 3 + .../Scripts/010_Data/002_PBS data/005_Move.rb | 3 + .../Scripts/010_Data/002_PBS data/006_Item.rb | 3 + .../010_Data/002_PBS data/007_BerryPlant.rb | 3 + .../010_Data/002_PBS data/008_Species.rb | 3 + .../002_PBS data/010_SpeciesMetrics.rb | 3 + .../002_PBS data/011_ShadowPokemon.rb | 11 +- .../010_Data/002_PBS data/012_Ribbon.rb | 3 + .../010_Data/002_PBS data/013_Encounter.rb | 17 +- .../010_Data/002_PBS data/014_TrainerType.rb | 21 +- .../010_Data/002_PBS data/015_Trainer.rb | 17 +- .../010_Data/002_PBS data/016_Metadata.rb | 5 +- .../002_PBS data/017_PlayerMetadata.rb | 2 + .../010_Data/002_PBS data/018_MapMetadata.rb | 5 +- .../002_PBS data/019_DungeonTileset.rb | 3 + .../002_PBS data/020_DungeonParameters.rb | 15 +- .../010_Data/002_PBS data/021_PhoneMessage.rb | 7 +- .../001_Editor screens/001_EditorScreens.rb | 80 +- Data/Scripts/021_Compiler/001_Compiler.rb | 150 ++- .../021_Compiler/002_Compiler_CompilePBS.rb | 896 +++++++++--------- .../021_Compiler/003_Compiler_WritePBS.rb | 733 ++++++++------ 24 files changed, 1134 insertions(+), 937 deletions(-) diff --git a/Data/Scripts/010_Data/001_GameData.rb b/Data/Scripts/010_Data/001_GameData.rb index eacfaf053..209cec07c 100644 --- a/Data/Scripts/010_Data/001_GameData.rb +++ b/Data/Scripts/010_Data/001_GameData.rb @@ -246,24 +246,34 @@ module GameData # A bulk loader method for all data stored in .dat files in the Data folder. #============================================================================= def self.load_all - TownMap.load - Type.load - Ability.load - Move.load - Item.load - BerryPlant.load - Species.load - SpeciesMetrics.load - ShadowPokemon.load - Ribbon.load - Encounter.load - TrainerType.load - Trainer.load - Metadata.load - PlayerMetadata.load - MapMetadata.load - DungeonTileset.load - DungeonParameters.load - PhoneMessage.load + self.constants.each do |c| + next if !self.const_get(c).is_a?(Class) + self.const_get(c).load if self.const_get(c).const_defined?(:DATA_FILENAME) + end + end + + def self.get_all_data_filenames + ret = [] + self.constants.each do |c| + next if !self.const_get(c).is_a?(Class) + ret.push(self.const_get(c)::DATA_FILENAME) if self.const_get(c).const_defined?(:DATA_FILENAME) + end + return ret + end + + def self.get_all_pbs_base_filenames + ret = {} + self.constants.each do |c| + next if !self.const_get(c).is_a?(Class) + ret[c] = self.const_get(c)::PBS_BASE_FILENAME if self.const_get(c).const_defined?(:PBS_BASE_FILENAME) + if ret[c].is_a?(Array) + ret[c].length.times do |i| + next if i == 0 + ret[(c.to_s + i.to_s).to_sym] = ret[c][i] # :Species1 => "pokemon_forms" + end + ret[c] = ret[c][0] # :Species => "pokemon" + end + end + return ret end end diff --git a/Data/Scripts/010_Data/002_PBS data/002_TownMap.rb b/Data/Scripts/010_Data/002_PBS data/002_TownMap.rb index a11d850a1..53b1996ae 100644 --- a/Data/Scripts/010_Data/002_PBS data/002_TownMap.rb +++ b/Data/Scripts/010_Data/002_PBS data/002_TownMap.rb @@ -5,9 +5,11 @@ module GameData attr_reader :filename attr_reader :point attr_reader :flags + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "town_map.dat" + PBS_BASE_FILENAME = "town_map" SCHEMA = { "SectionName" => [:id, "u"], @@ -21,11 +23,12 @@ module GameData include InstanceMethods def initialize(hash) - @id = hash[:id] - @real_name = hash[:real_name] || "???" - @filename = hash[:filename] - @point = hash[:point] || [] - @flags = hash[:flags] || [] + @id = hash[:id] + @real_name = hash[:real_name] || "???" + @filename = hash[:filename] + @point = hash[:point] || [] + @flags = hash[:flags] || [] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this region diff --git a/Data/Scripts/010_Data/002_PBS data/003_Type.rb b/Data/Scripts/010_Data/002_PBS data/003_Type.rb index 0270b9c16..7ea0662c1 100644 --- a/Data/Scripts/010_Data/002_PBS data/003_Type.rb +++ b/Data/Scripts/010_Data/002_PBS data/003_Type.rb @@ -9,9 +9,11 @@ module GameData attr_reader :resistances attr_reader :immunities attr_reader :flags + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "types.dat" + PBS_BASE_FILENAME = "types" SCHEMA = { "SectionName" => [:id, "m"], @@ -29,18 +31,19 @@ module GameData include InstanceMethods def initialize(hash) - @id = hash[:id] - @real_name = hash[:real_name] || "Unnamed" - @icon_position = hash[:icon_position] || 0 - @special_type = hash[:special_type] || false - @pseudo_type = hash[:pseudo_type] || false - @weaknesses = hash[:weaknesses] || [] - @weaknesses = [@weaknesses] if !@weaknesses.is_a?(Array) - @resistances = hash[:resistances] || [] - @resistances = [@resistances] if !@resistances.is_a?(Array) - @immunities = hash[:immunities] || [] - @immunities = [@immunities] if !@immunities.is_a?(Array) - @flags = hash[:flags] || [] + @id = hash[:id] + @real_name = hash[:real_name] || "Unnamed" + @icon_position = hash[:icon_position] || 0 + @special_type = hash[:special_type] || false + @pseudo_type = hash[:pseudo_type] || false + @weaknesses = hash[:weaknesses] || [] + @weaknesses = [@weaknesses] if !@weaknesses.is_a?(Array) + @resistances = hash[:resistances] || [] + @resistances = [@resistances] if !@resistances.is_a?(Array) + @immunities = hash[:immunities] || [] + @immunities = [@immunities] if !@immunities.is_a?(Array) + @flags = hash[:flags] || [] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this item diff --git a/Data/Scripts/010_Data/002_PBS data/004_Ability.rb b/Data/Scripts/010_Data/002_PBS data/004_Ability.rb index 182ea2deb..3ac438a41 100644 --- a/Data/Scripts/010_Data/002_PBS data/004_Ability.rb +++ b/Data/Scripts/010_Data/002_PBS data/004_Ability.rb @@ -4,9 +4,11 @@ module GameData attr_reader :real_name attr_reader :real_description attr_reader :flags + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "abilities.dat" + PBS_BASE_FILENAME = "abilities" extend ClassMethodsSymbols include InstanceMethods @@ -23,6 +25,7 @@ module GameData @real_name = hash[:real_name] || "Unnamed" @real_description = hash[:real_description] || "???" @flags = hash[:flags] || [] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this ability diff --git a/Data/Scripts/010_Data/002_PBS data/005_Move.rb b/Data/Scripts/010_Data/002_PBS data/005_Move.rb index 7e0417a28..5a79f4e0a 100644 --- a/Data/Scripts/010_Data/002_PBS data/005_Move.rb +++ b/Data/Scripts/010_Data/002_PBS data/005_Move.rb @@ -14,9 +14,11 @@ module GameData attr_reader :flags attr_reader :effect_chance attr_reader :real_description + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "moves.dat" + PBS_BASE_FILENAME = "moves" SCHEMA = { "SectionName" => [:id, "m"], @@ -53,6 +55,7 @@ module GameData @flags = [@flags] if !@flags.is_a?(Array) @effect_chance = hash[:effect_chance] || 0 @real_description = hash[:real_description] || "???" + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this move 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 a46b52055..e5796a4b5 100644 --- a/Data/Scripts/010_Data/002_PBS data/006_Item.rb +++ b/Data/Scripts/010_Data/002_PBS data/006_Item.rb @@ -12,9 +12,11 @@ module GameData attr_reader :consumable attr_reader :move attr_reader :real_description + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "items.dat" + PBS_BASE_FILENAME = "items" SCHEMA = { "SectionName" => [:id, "m"], @@ -95,6 +97,7 @@ module GameData @consumable = !is_important? if @consumable.nil? @move = hash[:move] @real_description = hash[:real_description] || "???" + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this item diff --git a/Data/Scripts/010_Data/002_PBS data/007_BerryPlant.rb b/Data/Scripts/010_Data/002_PBS data/007_BerryPlant.rb index 47490f4ad..365dc2f7c 100644 --- a/Data/Scripts/010_Data/002_PBS data/007_BerryPlant.rb +++ b/Data/Scripts/010_Data/002_PBS data/007_BerryPlant.rb @@ -4,9 +4,11 @@ module GameData attr_reader :hours_per_stage attr_reader :drying_per_hour attr_reader :yield + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "berry_plants.dat" + PBS_BASE_FILENAME = "berry_plants" SCHEMA = { "SectionName" => [:id, "m"], @@ -29,6 +31,7 @@ module GameData @drying_per_hour = hash[:drying_per_hour] || 15 @yield = hash[:yield] || [2, 5] @yield.reverse! if @yield[1] < @yield[0] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end def minimum_yield 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 4c0b00998..7777a3a23 100644 --- a/Data/Scripts/010_Data/002_PBS data/008_Species.rb +++ b/Data/Scripts/010_Data/002_PBS data/008_Species.rb @@ -40,9 +40,11 @@ module GameData attr_reader :mega_move attr_reader :unmega_form attr_reader :mega_message + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "species.dat" + PBS_BASE_FILENAME = ["pokemon", "pokemon_forms"] extend ClassMethodsSymbols include InstanceMethods @@ -175,6 +177,7 @@ module GameData @mega_move = hash[:mega_move] @unmega_form = hash[:unmega_form] || 0 @mega_message = hash[:mega_message] || 0 + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this species diff --git a/Data/Scripts/010_Data/002_PBS data/010_SpeciesMetrics.rb b/Data/Scripts/010_Data/002_PBS data/010_SpeciesMetrics.rb index dc915efbe..87428a7fe 100644 --- a/Data/Scripts/010_Data/002_PBS data/010_SpeciesMetrics.rb +++ b/Data/Scripts/010_Data/002_PBS data/010_SpeciesMetrics.rb @@ -8,9 +8,11 @@ module GameData attr_accessor :front_sprite_altitude attr_accessor :shadow_x attr_accessor :shadow_size + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "species_metrics.dat" + PBS_BASE_FILENAME = "pokemon_metrics" SCHEMA = { "SectionName" => [:id, "eV", :Species], @@ -63,6 +65,7 @@ module GameData @front_sprite_altitude = hash[:front_sprite_altitude] || 0 @shadow_x = hash[:shadow_x] || 0 @shadow_size = hash[:shadow_size] || 2 + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end def apply_metrics_to_sprite(sprite, index, shadow = false) diff --git a/Data/Scripts/010_Data/002_PBS data/011_ShadowPokemon.rb b/Data/Scripts/010_Data/002_PBS data/011_ShadowPokemon.rb index 8cfe28db9..98891e119 100644 --- a/Data/Scripts/010_Data/002_PBS data/011_ShadowPokemon.rb +++ b/Data/Scripts/010_Data/002_PBS data/011_ShadowPokemon.rb @@ -4,9 +4,11 @@ module GameData attr_reader :moves attr_reader :gauge_size attr_reader :flags + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "shadow_pokemon.dat" + PBS_BASE_FILENAME = "shadow_pokemon" SCHEMA = { "SectionName" => [:id, "e", :Species], @@ -20,10 +22,11 @@ module GameData include InstanceMethods def initialize(hash) - @id = hash[:id] - @gauge_size = hash[:gauge_size] || HEART_GAUGE_SIZE - @moves = hash[:moves] || [] - @flags = hash[:flags] || [] + @id = hash[:id] + @gauge_size = hash[:gauge_size] || HEART_GAUGE_SIZE + @moves = hash[:moves] || [] + @flags = hash[:flags] || [] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end def has_flag?(flag) diff --git a/Data/Scripts/010_Data/002_PBS data/012_Ribbon.rb b/Data/Scripts/010_Data/002_PBS data/012_Ribbon.rb index d153c9cdc..90c0f058c 100644 --- a/Data/Scripts/010_Data/002_PBS data/012_Ribbon.rb +++ b/Data/Scripts/010_Data/002_PBS data/012_Ribbon.rb @@ -5,9 +5,11 @@ module GameData attr_reader :icon_position # Where this ribbon's graphic is within ribbons.png attr_reader :real_description attr_reader :flags + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "ribbons.dat" + PBS_BASE_FILENAME = "ribbons" SCHEMA = { "SectionName" => [:id, "m"], @@ -26,6 +28,7 @@ module GameData @icon_position = hash[:icon_position] || 0 @real_description = hash[:real_description] || "???" @flags = hash[:flags] || [] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this ribbon diff --git a/Data/Scripts/010_Data/002_PBS data/013_Encounter.rb b/Data/Scripts/010_Data/002_PBS data/013_Encounter.rb index 157ba26e8..e69d300dd 100644 --- a/Data/Scripts/010_Data/002_PBS data/013_Encounter.rb +++ b/Data/Scripts/010_Data/002_PBS data/013_Encounter.rb @@ -3,11 +3,13 @@ module GameData attr_accessor :id attr_accessor :map attr_accessor :version - attr_reader :step_chances - attr_reader :types + attr_reader :step_chances + attr_reader :types + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "encounters.dat" + PBS_BASE_FILENAME = "encounters" extend ClassMethodsSymbols include InstanceMethods @@ -58,11 +60,12 @@ module GameData end def initialize(hash) - @id = hash[:id] - @map = hash[:map] - @version = hash[:version] || 0 - @step_chances = hash[:step_chances] - @types = hash[:types] || {} + @id = hash[:id] + @map = hash[:map] + @version = hash[:version] || 0 + @step_chances = hash[:step_chances] + @types = hash[:types] || {} + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end end end 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 1c2adca37..6254e03d7 100644 --- a/Data/Scripts/010_Data/002_PBS data/014_TrainerType.rb +++ b/Data/Scripts/010_Data/002_PBS data/014_TrainerType.rb @@ -9,9 +9,11 @@ module GameData attr_reader :intro_BGM attr_reader :battle_BGM attr_reader :victory_BGM + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "trainer_types.dat" + PBS_BASE_FILENAME = "trainer_types" SCHEMA = { "SectionName" => [:id, "m"], @@ -81,15 +83,16 @@ module GameData end def initialize(hash) - @id = hash[:id] - @real_name = hash[:real_name] || "Unnamed" - @gender = hash[:gender] || 2 - @base_money = hash[:base_money] || 30 - @skill_level = hash[:skill_level] || @base_money - @flags = hash[:flags] || [] - @intro_BGM = hash[:intro_BGM] - @battle_BGM = hash[:battle_BGM] - @victory_BGM = hash[:victory_BGM] + @id = hash[:id] + @real_name = hash[:real_name] || "Unnamed" + @gender = hash[:gender] || 2 + @base_money = hash[:base_money] || 30 + @skill_level = hash[:skill_level] || @base_money + @flags = hash[:flags] || [] + @intro_BGM = hash[:intro_BGM] + @battle_BGM = hash[:battle_BGM] + @victory_BGM = hash[:victory_BGM] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this trainer type diff --git a/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb b/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb index 82cce006a..ceebb4044 100644 --- a/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb +++ b/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb @@ -7,9 +7,11 @@ module GameData attr_reader :items attr_reader :real_lose_text attr_reader :pokemon + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "trainers.dat" + PBS_BASE_FILENAME = "trainers" SCHEMA = { "Items" => [:items, "*e", :Item], @@ -71,19 +73,20 @@ module GameData end def initialize(hash) - @id = hash[:id] - @trainer_type = hash[:trainer_type] - @real_name = hash[:name] || "Unnamed" - @version = hash[:version] || 0 - @items = hash[:items] || [] - @real_lose_text = hash[:lose_text] || "..." - @pokemon = hash[:pokemon] || [] + @id = hash[:id] + @trainer_type = hash[:trainer_type] + @real_name = hash[:name] || "Unnamed" + @version = hash[:version] || 0 + @items = hash[:items] || [] + @real_lose_text = hash[:lose_text] || "..." + @pokemon = hash[:pokemon] || [] @pokemon.each do |pkmn| GameData::Stat.each_main do |s| pkmn[:iv][s.id] ||= 0 if pkmn[:iv] pkmn[:ev][s.id] ||= 0 if pkmn[:ev] end end + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this trainer 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 5f02f86df..b5afe9ea2 100644 --- a/Data/Scripts/010_Data/002_PBS data/016_Metadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/016_Metadata.rb @@ -12,9 +12,11 @@ module GameData attr_reader :wild_capture_ME attr_reader :surf_BGM attr_reader :bicycle_BGM + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "metadata.dat" + PBS_BASE_FILENAME = "metadata" SCHEMA = { "SectionName" => [:id, "u"], @@ -67,11 +69,12 @@ module GameData @wild_capture_ME = hash[:wild_capture_ME] @surf_BGM = hash[:surf_BGM] @bicycle_BGM = hash[:bicycle_BGM] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of the Pokémon Storage creator def storage_creator - ret = pbGetMessage(MessageTypes::StorageCreator, 0) + ret = pbGetMessageFromHash(MessageTypes::StorageCreator, @real_storage_creator) return nil_or_empty?(ret) ? _INTL("Bill") : ret end end 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 6d2844d82..e6fa4df6d 100644 --- a/Data/Scripts/010_Data/002_PBS data/017_PlayerMetadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/017_PlayerMetadata.rb @@ -4,6 +4,7 @@ module GameData attr_reader :trainer_type attr_reader :walk_charset attr_reader :home + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "player_metadata.dat" @@ -57,6 +58,7 @@ module GameData @fish_charset = hash[:fish_charset] @surf_fish_charset = hash[:surf_fish_charset] @home = hash[:home] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end def run_charset 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 8ccba189e..96b3ebf28 100644 --- a/Data/Scripts/010_Data/002_PBS data/018_MapMetadata.rb +++ b/Data/Scripts/010_Data/002_PBS data/018_MapMetadata.rb @@ -23,9 +23,11 @@ module GameData attr_reader :town_map_size attr_reader :battle_environment attr_reader :flags + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "map_metadata.dat" + PBS_BASE_FILENAME = "map_metadata" SCHEMA = { "SectionName" => [:id, "u"], @@ -106,7 +108,8 @@ module GameData @wild_capture_ME = hash[:wild_capture_ME] @town_map_size = hash[:town_map_size] @battle_environment = hash[:battle_environment] - @flags = hash[:flags] || [] + @flags = hash[:flags] || [] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end # @return [String] the translated name of this map diff --git a/Data/Scripts/010_Data/002_PBS data/019_DungeonTileset.rb b/Data/Scripts/010_Data/002_PBS data/019_DungeonTileset.rb index 854a0d50d..4e0a511b8 100644 --- a/Data/Scripts/010_Data/002_PBS data/019_DungeonTileset.rb +++ b/Data/Scripts/010_Data/002_PBS data/019_DungeonTileset.rb @@ -10,9 +10,11 @@ module GameData attr_reader :floor_patch_under_walls attr_reader :thin_north_wall_offset attr_reader :flags + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "dungeon_tilesets.dat" + PBS_BASE_FILENAME = "dungeon_tilesets" SCHEMA = { "SectionName" => [:id, "u"], @@ -51,6 +53,7 @@ module GameData @flags = hash[:flags] || [] @tile_type_ids = {} set_tile_type_ids(hash) + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end def set_tile_type_ids(hash) diff --git a/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb b/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb index 91723de05..2da02c2b1 100644 --- a/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb +++ b/Data/Scripts/010_Data/002_PBS data/020_DungeonParameters.rb @@ -25,9 +25,11 @@ module GameData attr_reader :void_decoration_density, :void_decoration_large_density attr_reader :rng_seed attr_reader :flags + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "dungeon_parameters.dat" + PBS_BASE_FILENAME = "dungeon_parameters" SCHEMA = { "SectionName" => [:id, "mV"], @@ -67,7 +69,7 @@ module GameData def initialize(hash) @id = hash[:id] @area = hash[:area] - @version = hash[:version] || 0 + @version = hash[:version] || 0 @cell_count_x = (hash[:dungeon_size]) ? hash[:dungeon_size][0] : 5 @cell_count_y = (hash[:dungeon_size]) ? hash[:dungeon_size][1] : 5 @cell_width = (hash[:cell_size]) ? hash[:cell_size][0] : 10 @@ -76,11 +78,11 @@ module GameData @room_min_height = (hash[:min_room_size]) ? hash[:min_room_size][1] : 5 @room_max_width = (hash[:max_room_size]) ? hash[:max_room_size][0] : @cell_width - 1 @room_max_height = (hash[:max_room_size]) ? hash[:max_room_size][1] : @cell_height - 1 - @corridor_width = hash[:corridor_width] || 2 + @corridor_width = hash[:corridor_width] || 2 @random_corridor_shift = hash[:random_corridor_shift] - @node_layout = hash[:node_layout] || :full - @room_layout = hash[:room_layout] || :full - @room_chance = hash[:room_chance] || 70 + @node_layout = hash[:node_layout] || :full + @room_layout = hash[:room_layout] || :full + @room_chance = hash[:room_chance] || 70 @extra_connections_count = hash[:extra_connections_count] || 2 @floor_patch_radius = (hash[:floor_patches]) ? hash[:floor_patches][0] : 3 @floor_patch_chance = (hash[:floor_patches]) ? hash[:floor_patches][1] : 75 @@ -90,7 +92,8 @@ module GameData @void_decoration_density = (hash[:void_decorations]) ? hash[:void_decorations][0] : 50 @void_decoration_large_density = (hash[:void_decorations]) ? hash[:void_decorations][1] : 200 @rng_seed = hash[:rng_seed] - @flags = hash[:flags] || [] + @flags = hash[:flags] || [] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end def has_flag?(flag) diff --git a/Data/Scripts/010_Data/002_PBS data/021_PhoneMessage.rb b/Data/Scripts/010_Data/002_PBS data/021_PhoneMessage.rb index 2a5dcb27d..5c1b7bda1 100644 --- a/Data/Scripts/010_Data/002_PBS data/021_PhoneMessage.rb +++ b/Data/Scripts/010_Data/002_PBS data/021_PhoneMessage.rb @@ -6,9 +6,11 @@ module GameData attr_reader :body, :body1, :body2 attr_reader :battle_request, :battle_remind attr_reader :end + attr_reader :pbs_file_suffix DATA = {} DATA_FILENAME = "phone.dat" + PBS_BASE_FILENAME = "phone" SCHEMA = { "SectionName" => [:id, "q"], @@ -16,9 +18,9 @@ module GameData "IntroMorning" => [:intro_morning, "^q"], "IntroAfternoon" => [:intro_afternoon, "^q"], "IntroEvening" => [:intro_evening, "^q"], + "Body" => [:body, "^q"], "Body1" => [:body1, "^q"], "Body2" => [:body2, "^q"], - "Body" => [:body, "^q"], "BattleRequest" => [:battle_request, "^q"], "BattleRemind" => [:battle_remind, "^q"], "End" => [:end, "^q"] @@ -71,7 +73,7 @@ module GameData @id = hash[:id] @trainer_type = hash[:trainer_type] @real_name = hash[:real_name] - @version = hash[:version] || 0 + @version = hash[:version] || 0 @intro = hash[:intro] @intro_morning = hash[:intro_morning] @intro_afternoon = hash[:intro_afternoon] @@ -82,6 +84,7 @@ module GameData @battle_request = hash[:battle_request] @battle_remind = hash[:battle_remind] @end = hash[:end] + @pbs_file_suffix = hash[:pbs_file_suffix] || "" end alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS) 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 fbfe37d17..5f3cbf0a5 100644 --- a/Data/Scripts/020_Debug/001_Editor screens/001_EditorScreens.rb +++ b/Data/Scripts/020_Debug/001_Editor screens/001_EditorScreens.rb @@ -77,11 +77,12 @@ def pbEncountersEditor # Construct encounter hash key = sprintf("%s_%d", new_map_ID, new_version).to_sym encounter_hash = { - :id => key, - :map => new_map_ID, - :version => new_version, - :step_chances => {}, - :types => {} + :id => key, + :map => new_map_ID, + :version => new_version, + :step_chances => {}, + :types => {}, + :pbs_file_suffix => GameData::Encounter.get(this_set[0], this_set[1]).pbs_file_suffix } GameData::Encounter.get(this_set[0], this_set[1]).step_chances.each do |type, value| encounter_hash[:step_chances][type] = value @@ -384,15 +385,16 @@ def pbTrainerTypeEditor if pbPropertyList(t_data.id.to_s, data, trainer_type_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] + :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 } # Add trainer type's data to records GameData::TrainerType.register(type_hash) @@ -543,12 +545,13 @@ def pbTrainerBattleEditor pbMessage(_INTL("Can't save. The Pokémon list is empty.")) else trainer_hash = { - :trainer_type => data[0], - :name => data[1], - :version => data[2], - :lose_text => data[3], - :pokemon => party, - :items => items + :trainer_type => data[0], + :name => data[1], + :version => data[2], + :lose_text => data[3], + :pokemon => party, + :items => items, + :pbs_file_suffix => tr_data.pbs_file_suffix } # Add trainer type's data to records trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]] @@ -750,7 +753,8 @@ def pbEditMetadata :trainer_victory_BGM => data[7], :wild_capture_ME => data[8], :surf_BGM => data[9], - :bicycle_BGM => data[10] + :bicycle_BGM => data[10], + :pbs_file_suffix => metadata.pbs_file_suffix } # Add metadata's data to records GameData::Metadata.register(metadata_hash) @@ -794,7 +798,8 @@ def pbEditPlayerMetadata(player_id = 1) :dive_charset => data[5], :fish_charset => data[6], :surf_fish_charset => data[7], - :home => data[8] + :home => data[8], + :pbs_file_suffix => metadata.pbs_file_suffix } # Add player metadata's data to records GameData::PlayerMetadata.register(metadata_hash) @@ -853,7 +858,8 @@ def pbEditMapMetadata(map_id) :wild_capture_ME => data[18], :town_map_size => data[19], :battle_environment => data[20], - :flags => data[21] + :flags => data[21], + :pbs_file_suffix => metadata.pbs_file_suffix } # Add map metadata's data to records GameData::MapMetadata.register(metadata_hash) @@ -916,18 +922,19 @@ def pbItemEditor if pbPropertyList(itm.id.to_s, data, item_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] + :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 } # Add item's data to records GameData::Item.register(item_hash) @@ -1146,7 +1153,8 @@ def pbPokemonEditor :shape => data[35], :habitat => data[36], :generation => data[37], - :flags => data[38] + :flags => data[38], + :pbs_file_suffix => spec.pbs_file_suffix } # Add species' data to records GameData::Species.register(species_hash) diff --git a/Data/Scripts/021_Compiler/001_Compiler.rb b/Data/Scripts/021_Compiler/001_Compiler.rb index 0f415c84e..ef4596a67 100644 --- a/Data/Scripts/021_Compiler/001_Compiler.rb +++ b/Data/Scripts/021_Compiler/001_Compiler.rb @@ -780,30 +780,57 @@ module Compiler Graphics.update end + def get_all_pbs_files_to_compile + # Get the GameData classes and their respective base PBS filenames + ret = GameData.get_all_pbs_base_filenames + ret.merge!({ + :BattleFacility => "battle_facility_lists", + :Connection => "map_connections", + :RegionalDex => "regional_dexes" + }) + ret.each { |key, val| ret[key] = [val] } # [base_filename, ["PBS/file.txt", etc.]] + # Look through all PBS files and match them to a GameData class based on + # their base filenames + text_files_keys = ret.keys.sort! { |a, b| ret[b][0].length <=> ret[a][0].length } + Dir.chdir("PBS/") do + Dir.glob("*.txt") do |f| + base_name = File.basename(f, ".txt") + text_files_keys.each do |key| + next if base_name != ret[key][0] && !f.start_with?(ret[key][0] + "_") + ret[key][1] ||= [] + ret[key][1].push("PBS/" + f) + break + end + end + end + return ret + end + def compile_pbs_files + text_files = get_all_pbs_files_to_compile modify_pbs_file_contents_before_compiling - compile_town_map - compile_connections - compile_types - compile_abilities - compile_moves # Depends on Type - compile_items # Depends on Move - compile_berry_plants # Depends on Item - compile_pokemon # Depends on Move, Item, Type, Ability - compile_pokemon_forms # Depends on Species, Move, Item, Type, Ability - compile_pokemon_metrics # Depends on Species - compile_shadow_pokemon # Depends on Species - compile_regional_dexes # Depends on Species - compile_ribbons - compile_encounters # Depends on Species - compile_trainer_types - compile_trainers # Depends on Species, Item, Move - compile_trainer_lists # Depends on TrainerType - compile_metadata # Depends on TrainerType - compile_map_metadata - compile_dungeon_tilesets - compile_dungeon_parameters - compile_phone # Depends on TrainerType + compile_town_map(*text_files[:TownMap][1]) + compile_connections(*text_files[:Connection][1]) + compile_types(*text_files[:Type][1]) + compile_abilities(*text_files[:Ability][1]) + compile_moves(*text_files[:Move][1]) # Depends on Type + compile_items(*text_files[:Item][1]) # Depends on Move + compile_berry_plants(*text_files[:BerryPlant][1]) # Depends on Item + compile_pokemon(*text_files[:Species][1]) # Depends on Move, Item, Type, Ability + compile_pokemon_forms(*text_files[:Species1][1]) # Depends on Species, Move, Item, Type, Ability + compile_pokemon_metrics(*text_files[:SpeciesMetrics][1]) # Depends on Species + compile_shadow_pokemon(*text_files[:ShadowPokemon][1]) # Depends on Species + compile_regional_dexes(*text_files[:RegionalDex][1]) # Depends on Species + compile_ribbons(*text_files[:Ribbon][1]) + compile_encounters(*text_files[:Encounter][1]) # Depends on Species + compile_trainer_types(*text_files[:TrainerType][1]) + compile_trainers(*text_files[:Trainer][1]) # Depends on Species, Item, Move + compile_trainer_lists # Depends on TrainerType + compile_metadata(*text_files[:Metadata][1]) # Depends on TrainerType + compile_map_metadata(*text_files[:MapMetadata][1]) + compile_dungeon_tilesets(*text_files[:DungeonTileset][1]) + compile_dungeon_parameters(*text_files[:DungeonParameters][1]) + compile_phone(*text_files[:PhoneMessage][1]) # Depends on TrainerType end def compile_all(mustCompile) @@ -831,54 +858,14 @@ module Compiler def main return if !$DEBUG begin - dataFiles = [ - "abilities.dat", - "berry_plants.dat", - "dungeon_parameters.dat", - "dungeon_tilesets.dat", - "encounters.dat", - "items.dat", + # Get all data files and PBS files to be checked for their last modified times + data_files = GameData.get_all_data_filenames + data_files += [ # Extra .dat files for data that isn't a GameData class "map_connections.dat", - "map_metadata.dat", - "metadata.dat", - "moves.dat", - "phone.dat", - "player_metadata.dat", "regional_dexes.dat", - "ribbons.dat", - "shadow_pokemon.dat", - "species.dat", - "species_metrics.dat", - "town_map.dat", - "trainer_lists.dat", - "trainer_types.dat", - "trainers.dat", - "types.dat" - ] - textFiles = [ - "abilities.txt", - "battle_facility_lists.txt", - "berry_plants.txt", - "dungeon_parameters.txt", - "dungeon_tilesets.txt", - "encounters.txt", - "items.txt", - "map_connections.txt", - "map_metadata.txt", - "metadata.txt", - "moves.txt", - "phone.txt", - "pokemon.txt", - "pokemon_forms.txt", - "pokemon_metrics.txt", - "regional_dexes.txt", - "ribbons.txt", - "shadow_pokemon.txt", - "town_map.txt", - "trainer_types.txt", - "trainers.txt", - "types.txt" + "trainer_lists.dat" ] + text_files = get_all_pbs_files_to_compile latestDataTime = 0 latestTextTime = 0 mustCompile = false @@ -891,9 +878,8 @@ module Compiler write_all mustCompile = true end - # Check data files and PBS files, and recompile if any PBS file was edited - # more recently than the data files were last created - dataFiles.each do |filename| + # Check data files for their latest modify time + data_files.each do |filename| if safeExists?("Data/" + filename) begin File.open("Data/#{filename}") { |file| @@ -907,24 +893,26 @@ module Compiler break end end - textFiles.each do |filename| - next if !safeExists?("PBS/" + filename) - begin - File.open("PBS/#{filename}") { |file| - latestTextTime = [latestTextTime, file.mtime.to_i].max - } - rescue SystemCallError + # Check PBS files for their latest modify time + text_files.each do |key, value| + next if !value || !value[1].is_a?(Array) + value[1].each do |filepath| + begin + File.open(filepath) { |file| latestTextTime = [latestTextTime, file.mtime.to_i].max } + rescue SystemCallError + end end end + # Decide to compile if a PBS file was edited more recently than any .dat files mustCompile |= (latestTextTime >= latestDataTime) # Should recompile if holding Ctrl Input.update mustCompile = true if Input.press?(Input::CTRL) # Delete old data files in preparation for recompiling if mustCompile - dataFiles.length.times do |i| + data_files.length.times do |i| begin - File.delete("Data/#{dataFiles[i]}") if safeExists?("Data/#{dataFiles[i]}") + File.delete("Data/#{data_files[i]}") if safeExists?("Data/#{data_files[i]}") rescue SystemCallError end end @@ -935,9 +923,9 @@ module Compiler e = $! raise e if e.class.to_s == "Reset" || e.is_a?(Reset) || e.is_a?(SystemExit) pbPrintException(e) - dataFiles.length.times do |i| + data_files.length.times do |i| begin - File.delete("Data/#{dataFiles[i]}") + File.delete("Data/#{data_files[i]}") rescue SystemCallError end end diff --git a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb index 9dd7d2da1..168a590d8 100644 --- a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb +++ b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb @@ -1,66 +1,74 @@ module Compiler module_function - def compile_PBS_file_generic(game_data, path) - compile_pbs_file_message_start(path) + def compile_PBS_file_generic(game_data, *paths) game_data::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = game_data.schema - idx = 0 - pbEachFileSection(f, schema) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - if schema[key][1][0] == "^" - contents[key].each do |val| - value = pbGetCsvRecord(val, key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] ||= [] - data_hash[schema[key][0]].push(value) + schema = game_data.schema + # Read from PBS file(s) + paths.each do |path| + compile_pbs_file_message_start(path) + base_filename = game_data::PBS_BASE_FILENAME + base_filename = base_filename[0] if base_filename.is_a?(Array) # For Species + file_suffix = File.basename(path, ".txt")[base_filename.length + 1, path.length] || "" + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + idx = 0 + pbEachFileSection(f, schema) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = { + :id => section_name.to_sym, + :pbs_file_suffix => file_suffix + } + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + if schema[key][1][0] == "^" + contents[key].each do |val| + value = pbGetCsvRecord(val, key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] ||= [] + data_hash[schema[key][0]].push(value) + end + data_hash[schema[key][0]].compact! + else + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - data_hash[schema[key][0]].compact! - else - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value end - end - # Validate and modify the compiled data - yield false, data_hash if block_given? - if game_data.exists?(data_hash[:id]) - raise _INTL("Section name '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add section's data to records - game_data.register(data_hash) + # Validate and modify the compiled data + yield false, data_hash if block_given? + if game_data.exists?(data_hash[:id]) + raise _INTL("Section name '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + # Add section's data to records + game_data.register(data_hash) + } } - } + process_pbs_file_message_end + end yield true, nil if block_given? # Save all data game_data.save - process_pbs_file_message_end end #============================================================================= # Compile Town Map data #============================================================================= - def compile_town_map(path = "PBS/town_map.txt") - compile_PBS_file_generic(GameData::TownMap, path) do |final_validate, hash| + def compile_town_map(*paths) + compile_PBS_file_generic(GameData::TownMap, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_town_maps : validate_compiled_town_map(hash) end end @@ -90,51 +98,53 @@ module Compiler #============================================================================= # Compile map connections #============================================================================= - def compile_connections(path = "PBS/map_connections.txt") - compile_pbs_file_message_start(path) + def compile_connections(*paths) records = [] - pbCompilerEachPreppedLine(path) { |line, lineno| - hashenum = { - "N" => "N", "North" => "N", - "E" => "E", "East" => "E", - "S" => "S", "South" => "S", - "W" => "W", "West" => "W" + paths.each do |path| + compile_pbs_file_message_start(path) + pbCompilerEachPreppedLine(path) { |line, lineno| + hashenum = { + "N" => "N", "North" => "N", + "E" => "E", "East" => "E", + "S" => "S", "South" => "S", + "W" => "W", "West" => "W" + } + record = [] + thisline = line.dup + record.push(csvInt!(thisline, lineno)) + record.push(csvEnumFieldOrInt!(thisline, hashenum, "", sprintf("(line %d)", lineno))) + record.push(csvInt!(thisline, lineno)) + record.push(csvInt!(thisline, lineno)) + record.push(csvEnumFieldOrInt!(thisline, hashenum, "", sprintf("(line %d)", lineno))) + record.push(csvInt!(thisline, lineno)) + if !pbRgssExists?(sprintf("Data/Map%03d.rxdata", record[0])) + print _INTL("Warning: Map {1}, as mentioned in the map connection data, was not found.\r\n{2}", record[0], FileLineData.linereport) + end + if !pbRgssExists?(sprintf("Data/Map%03d.rxdata", record[3])) + print _INTL("Warning: Map {1}, as mentioned in the map connection data, was not found.\r\n{2}", record[3], FileLineData.linereport) + end + case record[1] + when "N" + raise _INTL("North side of first map must connect with south side of second map\r\n{1}", FileLineData.linereport) if record[4] != "S" + when "S" + raise _INTL("South side of first map must connect with north side of second map\r\n{1}", FileLineData.linereport) if record[4] != "N" + when "E" + raise _INTL("East side of first map must connect with west side of second map\r\n{1}", FileLineData.linereport) if record[4] != "W" + when "W" + raise _INTL("West side of first map must connect with east side of second map\r\n{1}", FileLineData.linereport) if record[4] != "E" + end + records.push(record) } - record = [] - thisline = line.dup - record.push(csvInt!(thisline, lineno)) - record.push(csvEnumFieldOrInt!(thisline, hashenum, "", sprintf("(line %d)", lineno))) - record.push(csvInt!(thisline, lineno)) - record.push(csvInt!(thisline, lineno)) - record.push(csvEnumFieldOrInt!(thisline, hashenum, "", sprintf("(line %d)", lineno))) - record.push(csvInt!(thisline, lineno)) - if !pbRgssExists?(sprintf("Data/Map%03d.rxdata", record[0])) - print _INTL("Warning: Map {1}, as mentioned in the map connection data, was not found.\r\n{2}", record[0], FileLineData.linereport) - end - if !pbRgssExists?(sprintf("Data/Map%03d.rxdata", record[3])) - print _INTL("Warning: Map {1}, as mentioned in the map connection data, was not found.\r\n{2}", record[3], FileLineData.linereport) - end - case record[1] - when "N" - raise _INTL("North side of first map must connect with south side of second map\r\n{1}", FileLineData.linereport) if record[4] != "S" - when "S" - raise _INTL("South side of first map must connect with north side of second map\r\n{1}", FileLineData.linereport) if record[4] != "N" - when "E" - raise _INTL("East side of first map must connect with west side of second map\r\n{1}", FileLineData.linereport) if record[4] != "W" - when "W" - raise _INTL("West side of first map must connect with east side of second map\r\n{1}", FileLineData.linereport) if record[4] != "E" - end - records.push(record) - } + process_pbs_file_message_end + end save_data(records, "Data/map_connections.dat") - process_pbs_file_message_end end #============================================================================= # Compile type data #============================================================================= - def compile_types(path = "PBS/types.txt") - compile_PBS_file_generic(GameData::Type, path) do |final_validate, hash| + def compile_types(*paths) + compile_PBS_file_generic(GameData::Type, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_types : validate_compiled_type(hash) end end @@ -171,8 +181,8 @@ module Compiler #============================================================================= # Compile ability data #============================================================================= - def compile_abilities(path = "PBS/abilities.txt") - compile_PBS_file_generic(GameData::Ability, path) do |final_validate, hash| + def compile_abilities(*paths) + compile_PBS_file_generic(GameData::Ability, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_abilities : validate_compiled_ability(hash) end end @@ -195,8 +205,8 @@ module Compiler #============================================================================= # Compile move data #============================================================================= - def compile_moves(path = "PBS/moves.txt") - compile_PBS_file_generic(GameData::Move, path) do |final_validate, hash| + def compile_moves(*paths) + compile_PBS_file_generic(GameData::Move, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_moves : validate_compiled_move(hash) end end @@ -227,8 +237,8 @@ module Compiler #============================================================================= # Compile item data #============================================================================= - def compile_items(path = "PBS/items.txt") - compile_PBS_file_generic(GameData::Item, path) do |final_validate, hash| + def compile_items(*paths) + compile_PBS_file_generic(GameData::Item, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_items : validate_compiled_item(hash) end end @@ -254,8 +264,8 @@ module Compiler #============================================================================= # Compile berry plant data #============================================================================= - def compile_berry_plants(path = "PBS/berry_plants.txt") - compile_PBS_file_generic(GameData::BerryPlant, path) do |final_validate, hash| + def compile_berry_plants(*paths) + compile_PBS_file_generic(GameData::BerryPlant, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_berry_plants : validate_compiled_berry_plant(hash) end end @@ -269,8 +279,8 @@ module Compiler #============================================================================= # Compile Pokémon data #============================================================================= - def compile_pokemon(path = "PBS/pokemon.txt") - compile_PBS_file_generic(GameData::Species, path) do |final_validate, hash| + def compile_pokemon(*paths) + compile_PBS_file_generic(GameData::Species, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_pokemon : validate_compiled_pokemon(hash) end end @@ -361,58 +371,64 @@ module Compiler # NOTE: Doesn't use compile_PBS_file_generic because it needs its own schema # and shouldn't clear GameData::Species at the start. #============================================================================= - def compile_pokemon_forms(path = "PBS/pokemon_forms.txt") - compile_pbs_file_message_start(path) - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - schema = GameData::Species.schema(true) - idx = 0 - pbEachFileSection(f, schema) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - if schema[key][1][0] == "^" - contents[key].each do |val| - value = pbGetCsvRecord(val, key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] ||= [] - data_hash[schema[key][0]].push(value) + def compile_pokemon_forms(*paths) + schema = GameData::Species.schema(true) + # Read from PBS file(s) + paths.each do |path| + compile_pbs_file_message_start(path) + file_suffix = File.basename(path, ".txt")[GameData::Species::PBS_BASE_FILENAME[1].length + 1, path.length] || "" + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + idx = 0 + pbEachFileSection(f, schema) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + data_hash = { + :id => section_name.to_sym, + :pbs_file_suffix => file_suffix + } + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + if schema[key][1][0] == "^" + contents[key].each do |val| + value = pbGetCsvRecord(val, key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] ||= [] + data_hash[schema[key][0]].push(value) + end + data_hash[schema[key][0]].compact! + else + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value end - data_hash[schema[key][0]].compact! - else - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value end - end - # Validate and modify the compiled data - validate_compiled_pokemon_form(data_hash) - if GameData::Species.exists?(data_hash[:id]) - raise _INTL("Section name '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - # Add section's data to records - GameData::Species.register(data_hash) + # Validate and modify the compiled data + validate_compiled_pokemon_form(data_hash) + if GameData::Species.exists?(data_hash[:id]) + raise _INTL("Section name '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end + # Add section's data to records + GameData::Species.register(data_hash) + } } - } + process_pbs_file_message_end + end validate_all_compiled_pokemon_forms # Save all data GameData::Species.save - process_pbs_file_message_end end def validate_compiled_pokemon_form(hash) @@ -491,8 +507,8 @@ module Compiler #============================================================================= # Compile Pokémon metrics data #============================================================================= - def compile_pokemon_metrics(path = "PBS/pokemon_metrics.txt") - compile_PBS_file_generic(GameData::SpeciesMetrics, path) do |final_validate, hash| + def compile_pokemon_metrics(*paths) + compile_PBS_file_generic(GameData::SpeciesMetrics, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_pokemon_metrics : validate_compiled_pokemon_metrics(hash) end end @@ -516,8 +532,8 @@ module Compiler #============================================================================= # Compile Shadow Pokémon data #============================================================================= - def compile_shadow_pokemon(path = "PBS/shadow_pokemon.txt") - compile_PBS_file_generic(GameData::ShadowPokemon, path) do |final_validate, hash| + def compile_shadow_pokemon(*paths) + compile_PBS_file_generic(GameData::ShadowPokemon, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_shadow_pokemon : validate_compiled_shadow_pokemon(hash) end end @@ -531,28 +547,31 @@ module Compiler #============================================================================= # Compile Regional Dexes #============================================================================= - def compile_regional_dexes(path = "PBS/regional_dexes.txt") - compile_pbs_file_message_start(path) + def compile_regional_dexes(*paths) dex_lists = [] - section = nil - pbCompilerEachPreppedLine(path) { |line, line_no| - Graphics.update if line_no % 200 == 0 - if line[/^\s*\[\s*(\d+)\s*\]\s*$/] - section = $~[1].to_i - if dex_lists[section] - raise _INTL("Dex list number {1} is defined at least twice.\r\n{2}", section, FileLineData.linereport) + paths.each do |path| + compile_pbs_file_message_start(path) + section = nil + pbCompilerEachPreppedLine(path) { |line, line_no| + Graphics.update if line_no % 200 == 0 + if line[/^\s*\[\s*(\d+)\s*\]\s*$/] + section = $~[1].to_i + if dex_lists[section] + raise _INTL("Dex list number {1} is defined at least twice.\r\n{2}", section, FileLineData.linereport) + end + dex_lists[section] = [] + else + raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) if !section + species_list = line.split(",") + species_list.each do |species| + next if !species || species.empty? + s = parseSpecies(species) + dex_lists[section].push(s) + end end - dex_lists[section] = [] - else - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) if !section - species_list = line.split(",") - species_list.each do |species| - next if !species || species.empty? - s = parseSpecies(species) - dex_lists[section].push(s) - end - end - } + } + process_pbs_file_message_end + end # Check for duplicate species in a Regional Dex dex_lists.each_with_index do |list, index| unique_list = list.uniq @@ -564,14 +583,13 @@ module Compiler end # Save all data save_data(dex_lists, "Data/regional_dexes.dat") - process_pbs_file_message_end end #============================================================================= # Compile ribbon data #============================================================================= - def compile_ribbons(path = "PBS/ribbons.txt") - compile_PBS_file_generic(GameData::Ribbon, path) do |final_validate, hash| + def compile_ribbons(*paths) + compile_PBS_file_generic(GameData::Ribbon, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_ribbons : validate_compiled_ribbon(hash) end end @@ -594,117 +612,121 @@ module Compiler #============================================================================= # Compile wild encounter data #============================================================================= - def compile_encounters(path = "PBS/encounters.txt") - compile_pbs_file_message_start(path) + def compile_encounters(*paths) GameData::Encounter::DATA.clear - encounter_hash = nil - step_chances = nil - current_type = nil max_level = GameData::GrowthRate.max_level - idx = 0 - pbCompilerEachPreppedLine(path) { |line, line_no| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - next if line.length == 0 - if current_type && line[/^\d+,/] # Species line - values = line.split(",").collect! { |v| v.strip } - if !values || values.length < 3 - raise _INTL("Expected a species entry line for encounter type {1} for map '{2}', got \"{3}\" instead.\r\n{4}", - GameData::EncounterType.get(current_type).real_name, encounter_hash[:map], line, FileLineData.linereport) - end - values = pbGetCsvRecord(line, line_no, [0, "vevV", nil, :Species]) - values[3] = values[2] if !values[3] - if values[2] > max_level - raise _INTL("Level number {1} is not valid (max. {2}).\r\n{3}", values[2], max_level, FileLineData.linereport) - elsif values[3] > max_level - raise _INTL("Level number {1} is not valid (max. {2}).\r\n{3}", values[3], max_level, FileLineData.linereport) - elsif values[2] > values[3] - raise _INTL("Minimum level is greater than maximum level: {1}\r\n{2}", line, FileLineData.linereport) - end - encounter_hash[:types][current_type].push(values) - elsif line[/^\[\s*(.+)\s*\]$/] # Map ID line - values = $~[1].split(",").collect! { |v| v.strip.to_i } - values[1] = 0 if !values[1] - map_number = values[0] - map_version = values[1] - # Add map encounter's data to records - if encounter_hash - encounter_hash[:types].each_value do |slots| - next if !slots || slots.length == 0 - slots.each_with_index do |slot, i| - next if !slot - slots.each_with_index do |other_slot, j| - next if i == j || !other_slot - next if slot[1] != other_slot[1] || slot[2] != other_slot[2] || slot[3] != other_slot[3] - slot[0] += other_slot[0] - slots[j] = nil + paths.each do |path| + compile_pbs_file_message_start(path) + file_suffix = File.basename(path, ".txt")[GameData::Encounter::PBS_BASE_FILENAME.length + 1, path.length] || "" + encounter_hash = nil + step_chances = nil + current_type = nil + idx = 0 + pbCompilerEachPreppedLine(path) { |line, line_no| + echo "." if idx % 50 == 0 + idx += 1 + Graphics.update if idx % 250 == 0 + next if line.length == 0 + if current_type && line[/^\d+,/] # Species line + values = line.split(",").collect! { |v| v.strip } + if !values || values.length < 3 + raise _INTL("Expected a species entry line for encounter type {1} for map '{2}', got \"{3}\" instead.\r\n{4}", + GameData::EncounterType.get(current_type).real_name, encounter_hash[:map], line, FileLineData.linereport) + end + values = pbGetCsvRecord(line, line_no, [0, "vevV", nil, :Species]) + values[3] = values[2] if !values[3] + if values[2] > max_level + raise _INTL("Level number {1} is not valid (max. {2}).\r\n{3}", values[2], max_level, FileLineData.linereport) + elsif values[3] > max_level + raise _INTL("Level number {1} is not valid (max. {2}).\r\n{3}", values[3], max_level, FileLineData.linereport) + elsif values[2] > values[3] + raise _INTL("Minimum level is greater than maximum level: {1}\r\n{2}", line, FileLineData.linereport) + end + encounter_hash[:types][current_type].push(values) + elsif line[/^\[\s*(.+)\s*\]$/] # Map ID line + values = $~[1].split(",").collect! { |v| v.strip.to_i } + values[1] = 0 if !values[1] + map_number = values[0] + map_version = values[1] + # Add map encounter's data to records + if encounter_hash + encounter_hash[:types].each_value do |slots| + next if !slots || slots.length == 0 + slots.each_with_index do |slot, i| + next if !slot + slots.each_with_index do |other_slot, j| + next if i == j || !other_slot + next if slot[1] != other_slot[1] || slot[2] != other_slot[2] || slot[3] != other_slot[3] + slot[0] += other_slot[0] + slots[j] = nil + end end + slots.compact! + slots.sort! { |a, b| (a[0] == b[0]) ? a[1].to_s <=> b[1].to_s : b[0] <=> a[0] } end - slots.compact! - slots.sort! { |a, b| (a[0] == b[0]) ? a[1].to_s <=> b[1].to_s : b[0] <=> a[0] } + GameData::Encounter.register(encounter_hash) end - GameData::Encounter.register(encounter_hash) - end - # Raise an error if a map/version combo is used twice - key = sprintf("%s_%d", map_number, map_version).to_sym - if GameData::Encounter::DATA[key] - raise _INTL("Encounters for map '{1}' are defined twice.\r\n{2}", map_number, FileLineData.linereport) - end - step_chances = {} - # Construct encounter hash - encounter_hash = { - :id => key, - :map => map_number, - :version => map_version, - :step_chances => step_chances, - :types => {} - } - current_type = nil - elsif !encounter_hash # File began with something other than a map ID line - raise _INTL("Expected a map number, got \"{1}\" instead.\r\n{2}", line, FileLineData.linereport) - else - # Check if line is an encounter method name or not - values = line.split(",").collect! { |v| v.strip } - current_type = (values[0] && !values[0].empty?) ? values[0].to_sym : nil - if current_type && GameData::EncounterType.exists?(current_type) # Start of a new encounter method - step_chances[current_type] = values[1].to_i if values[1] && !values[1].empty? - step_chances[current_type] ||= GameData::EncounterType.get(current_type).trigger_chance - encounter_hash[:types][current_type] = [] + # Raise an error if a map/version combo is used twice + key = sprintf("%s_%d", map_number, map_version).to_sym + if GameData::Encounter::DATA[key] + raise _INTL("Encounters for map '{1}' are defined twice.\r\n{2}", map_number, FileLineData.linereport) + end + step_chances = {} + # Construct encounter hash + encounter_hash = { + :id => key, + :map => map_number, + :version => map_version, + :step_chances => step_chances, + :types => {}, + :pbs_file_suffix => file_suffix + } + current_type = nil + elsif !encounter_hash # File began with something other than a map ID line + raise _INTL("Expected a map number, got \"{1}\" instead.\r\n{2}", line, FileLineData.linereport) else - raise _INTL("Undefined encounter type \"{1}\" for map '{2}'.\r\n{3}", - line, encounter_hash[:map], FileLineData.linereport) - end - end - } - # Add last map's encounter data to records - if encounter_hash - encounter_hash[:types].each_value do |slots| - next if !slots || slots.length == 0 - slots.each_with_index do |slot, i| - next if !slot - slots.each_with_index do |other_slot, j| - next if i == j || !other_slot - next if slot[1] != other_slot[1] || slot[2] != other_slot[2] || slot[3] != other_slot[3] - slot[0] += other_slot[0] - slots[j] = nil + # Check if line is an encounter method name or not + values = line.split(",").collect! { |v| v.strip } + current_type = (values[0] && !values[0].empty?) ? values[0].to_sym : nil + if current_type && GameData::EncounterType.exists?(current_type) # Start of a new encounter method + step_chances[current_type] = values[1].to_i if values[1] && !values[1].empty? + step_chances[current_type] ||= GameData::EncounterType.get(current_type).trigger_chance + encounter_hash[:types][current_type] = [] + else + raise _INTL("Undefined encounter type \"{1}\" for map '{2}'.\r\n{3}", + line, encounter_hash[:map], FileLineData.linereport) end end - slots.compact! - slots.sort! { |a, b| (a[0] == b[0]) ? a[1].to_s <=> b[1].to_s : b[0] <=> a[0] } + } + # Add last map's encounter data to records + if encounter_hash + encounter_hash[:types].each_value do |slots| + next if !slots || slots.length == 0 + slots.each_with_index do |slot, i| + next if !slot + slots.each_with_index do |other_slot, j| + next if i == j || !other_slot + next if slot[1] != other_slot[1] || slot[2] != other_slot[2] || slot[3] != other_slot[3] + slot[0] += other_slot[0] + slots[j] = nil + end + end + slots.compact! + slots.sort! { |a, b| (a[0] == b[0]) ? a[1].to_s <=> b[1].to_s : b[0] <=> a[0] } + end + GameData::Encounter.register(encounter_hash) end - GameData::Encounter.register(encounter_hash) + process_pbs_file_message_end end # Save all data GameData::Encounter.save - process_pbs_file_message_end end #============================================================================= # Compile trainer type data #============================================================================= - def compile_trainer_types(path = "PBS/trainer_types.txt") - compile_PBS_file_generic(GameData::TrainerType, path) do |final_validate, hash| + def compile_trainer_types(*paths) + compile_PBS_file_generic(GameData::TrainerType, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_trainer_types : validate_compiled_trainer_type(hash) end end @@ -724,131 +746,135 @@ module Compiler #============================================================================= # Compile individual trainer data #============================================================================= - def compile_trainers(path = "PBS/trainers.txt") - compile_pbs_file_message_start(path) + def compile_trainers(*paths) GameData::Trainer::DATA.clear schema = GameData::Trainer.schema max_level = GameData::GrowthRate.max_level trainer_names = [] trainer_lose_texts = [] - trainer_hash = nil - current_pkmn = nil - # Read each line of trainers.txt at a time and compile it as a trainer property - idx = 0 - pbCompilerEachPreppedLine(path) { |line, line_no| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - if line[/^\s*\[\s*(.+)\s*\]\s*$/] - # New section [trainer_type, name] or [trainer_type, name, version] - if trainer_hash - if !current_pkmn - raise _INTL("Started new trainer while previous trainer has no Pokémon.\r\n{1}", FileLineData.linereport) + paths.each do |path| + compile_pbs_file_message_start(path) + file_suffix = File.basename(path, ".txt")[GameData::Trainer::PBS_BASE_FILENAME.length + 1, path.length] || "" + trainer_hash = nil + current_pkmn = nil + # Read each line of trainers.txt at a time and compile it as a trainer property + idx = 0 + pbCompilerEachPreppedLine(path) { |line, line_no| + echo "." if idx % 50 == 0 + idx += 1 + Graphics.update if idx % 250 == 0 + if line[/^\s*\[\s*(.+)\s*\]\s*$/] + # New section [trainer_type, name] or [trainer_type, name, version] + if trainer_hash + if !current_pkmn + raise _INTL("Started new trainer while previous trainer has no Pokémon.\r\n{1}", FileLineData.linereport) + end + # Add trainer's data to records + trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]] + GameData::Trainer.register(trainer_hash) end - # Add trainer's data to records - trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]] - GameData::Trainer.register(trainer_hash) - end - line_data = pbGetCsvRecord($~[1], line_no, [0, "esU", :TrainerType]) - # Construct trainer hash - trainer_hash = { - :trainer_type => line_data[0], - :name => line_data[1], - :version => line_data[2] || 0, - :pokemon => [] - } - current_pkmn = nil - trainer_names.push(trainer_hash[:name]) - elsif line[/^\s*(\w+)\s*=\s*(.*)$/] - # XXX=YYY lines - if !trainer_hash - raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) - end - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Error checking in XXX=YYY lines - case property_name - when "Pokemon" - 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) - end - when "Name" - 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] + line_data = pbGetCsvRecord($~[1], line_no, [0, "esU", :TrainerType]) + # Construct trainer hash + trainer_hash = { + :trainer_type => line_data[0], + :name => line_data[1], + :version => line_data[2] || 0, + :pokemon => [], + :pbs_file_suffix => file_suffix } - trainer_hash[line_schema[0]].push(current_pkmn) - else - if !current_pkmn - raise _INTL("Pokémon hasn't been defined yet!\r\n{1}", FileLineData.linereport) + current_pkmn = nil + trainer_names.push(trainer_hash[:name]) + elsif line[/^\s*(\w+)\s*=\s*(.*)$/] + # XXX=YYY lines + if !trainer_hash + raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport) end + property_name = $~[1] + line_schema = schema[property_name] + next if !line_schema + property_value = pbGetCsvRecord($~[2], line_no, line_schema) + # Error checking in XXX=YYY lines case property_name - when "IV", "EV" - value_hash = {} + when "Pokemon" + 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) + end + when "Name" + 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 - value_hash[s.id] = property_value[s.pbs_order] || property_value[0] + ev_total += (property_value[s.pbs_order] || property_value[0]) end - current_pkmn[line_schema[0]] = value_hash + 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 - current_pkmn[line_schema[0]] = property_value + if !current_pkmn + raise _INTL("Pokémon hasn't been defined yet!\r\n{1}", FileLineData.linereport) + end + case property_name + 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 + } + # Add last trainer's data to records + if trainer_hash + if !current_pkmn + raise _INTL("End of file reached while last trainer has no Pokémon.\r\n{1}", FileLineData.linereport) + end + trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]] + GameData::Trainer.register(trainer_hash) end - } - # Add last trainer's data to records - if trainer_hash - if !current_pkmn - raise _INTL("End of file reached while last trainer has no Pokémon.\r\n{1}", FileLineData.linereport) - end - trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]] - GameData::Trainer.register(trainer_hash) + process_pbs_file_message_end end # Save all data GameData::Trainer.save MessageTypes.setMessagesAsHash(MessageTypes::TrainerNames, trainer_names) MessageTypes.setMessagesAsHash(MessageTypes::TrainerLoseText, trainer_lose_texts) - process_pbs_file_message_end end #============================================================================= @@ -973,74 +999,80 @@ module Compiler # NOTE: Doesn't use compile_PBS_file_generic because it contains data for two # different GameData classes. #============================================================================= - def compile_metadata(path = "PBS/metadata.txt") - compile_pbs_file_message_start(path) + def compile_metadata(*paths) GameData::Metadata::DATA.clear GameData::PlayerMetadata::DATA.clear - # Read from PBS file - File.open(path, "rb") { |f| - FileLineData.file = path # 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). - global_schema = GameData::Metadata.schema - player_schema = GameData::PlayerMetadata.schema - idx = 0 - pbEachFileSection(f) { |contents, section_name| - echo "." if idx % 50 == 0 - Graphics.update if idx % 250 == 0 - idx += 1 - schema = (section_name.to_i == 0) ? global_schema : player_schema - data_hash = {:id => section_name.to_sym} - # Go through schema hash of compilable data and compile this section - schema.each_key do |key| - FileLineData.setSection(section_name, key, contents[key]) # For error reporting - if key == "SectionName" - data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) - next - end - # Skip empty properties - next if contents[key].nil? - # Compile value for key - if schema[key][1][0] == "^" - contents[key].each do |val| - value = pbGetCsvRecord(val, key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] ||= [] - data_hash[schema[key][0]].push(value) + global_schema = GameData::Metadata.schema + player_schema = GameData::PlayerMetadata.schema + paths.each do |path| + compile_pbs_file_message_start(path) + file_suffix = File.basename(path, ".txt")[GameData::Metadata::PBS_BASE_FILENAME.length + 1, path.length] || "" + # Read from PBS file + File.open(path, "rb") { |f| + FileLineData.file = path # 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). + idx = 0 + pbEachFileSection(f) { |contents, section_name| + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + schema = (section_name.to_i == 0) ? global_schema : player_schema + data_hash = { + :id => section_name.to_sym, + :pbs_file_suffix => file_suffix + } + # Go through schema hash of compilable data and compile this section + schema.each_key do |key| + FileLineData.setSection(section_name, key, contents[key]) # For error reporting + if key == "SectionName" + data_hash[schema[key][0]] = pbGetCsvRecord(section_name, key, schema[key]) + next + end + # Skip empty properties + next if contents[key].nil? + # Compile value for key + if schema[key][1][0] == "^" + contents[key].each do |val| + value = pbGetCsvRecord(val, key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] ||= [] + data_hash[schema[key][0]].push(value) + end + data_hash[schema[key][0]].compact! + else + value = pbGetCsvRecord(contents[key], key, schema[key]) + value = nil if value.is_a?(Array) && value.empty? + data_hash[schema[key][0]] = value + end + end + # Validate and modify the compiled data + if data_hash[:id] == 0 + validate_compiled_global_metadata(data_hash) + if GameData::Metadata.exists?(data_hash[:id]) + raise _INTL("Global metadata ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) end - data_hash[schema[key][0]].compact! else - value = pbGetCsvRecord(contents[key], key, schema[key]) - value = nil if value.is_a?(Array) && value.empty? - data_hash[schema[key][0]] = value + validate_compiled_player_metadata(data_hash) + if GameData::PlayerMetadata.exists?(data_hash[:id]) + raise _INTL("Player metadata ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + end end - end - # Validate and modify the compiled data - if data_hash[:id] == 0 - validate_compiled_global_metadata(data_hash) - if GameData::Metadata.exists?(data_hash[:id]) - raise _INTL("Global metadata ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) + # Add section's data to records + if data_hash[:id] == 0 + GameData::Metadata.register(data_hash) + else + GameData::PlayerMetadata.register(data_hash) end - else - validate_compiled_player_metadata(data_hash) - if GameData::PlayerMetadata.exists?(data_hash[:id]) - raise _INTL("Player metadata ID '{1}' is used twice.\r\n{2}", data_hash[:id], FileLineData.linereport) - end - end - # Add section's data to records - if data_hash[:id] == 0 - GameData::Metadata.register(data_hash) - else - GameData::PlayerMetadata.register(data_hash) - end + } } - } + process_pbs_file_message_end + end validate_all_compiled_metadata # Save all data GameData::Metadata.save GameData::PlayerMetadata.save - process_pbs_file_message_end end def validate_compiled_global_metadata(hash) @@ -1064,14 +1096,14 @@ module Compiler end # Get storage creator's name for translating storage_creator = [GameData::Metadata.get.real_storage_creator] - MessageTypes.setMessages(MessageTypes::StorageCreator, storage_creator) + MessageTypes.setMessagesAsHash(MessageTypes::StorageCreator, storage_creator) end #============================================================================= # Compile map metadata #============================================================================= - def compile_map_metadata(path = "PBS/map_metadata.txt") - compile_PBS_file_generic(GameData::MapMetadata, path) do |final_validate, hash| + def compile_map_metadata(*paths) + compile_PBS_file_generic(GameData::MapMetadata, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_map_metadata : validate_compiled_map_metadata(hash) end end @@ -1093,8 +1125,8 @@ module Compiler #============================================================================= # Compile dungeon tileset data #============================================================================= - def compile_dungeon_tilesets(path = "PBS/dungeon_tilesets.txt") - compile_PBS_file_generic(GameData::DungeonTileset, path) do |final_validate, hash| + def compile_dungeon_tilesets(*paths) + compile_PBS_file_generic(GameData::DungeonTileset, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_dungeon_tilesets : validate_compiled_dungeon_tileset(hash) end end @@ -1108,8 +1140,8 @@ module Compiler #============================================================================= # Compile dungeon parameters data #============================================================================= - def compile_dungeon_parameters(path = "PBS/dungeon_parameters.txt") - compile_PBS_file_generic(GameData::DungeonParameters, path) do |final_validate, hash| + def compile_dungeon_parameters(*paths) + compile_PBS_file_generic(GameData::DungeonParameters, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_dungeon_parameters : validate_compiled_dungeon_parameters(hash) end end @@ -1134,8 +1166,8 @@ module Compiler #============================================================================= # Compile phone messages #============================================================================= - def compile_phone(path = "PBS/phone.txt") - compile_PBS_file_generic(GameData::PhoneMessage, path) do |final_validate, hash| + def compile_phone(*paths) + compile_PBS_file_generic(GameData::PhoneMessage, *paths) do |final_validate, hash| (final_validate) ? validate_all_compiled_phone_contacts : validate_compiled_phone_contact(hash) end end diff --git a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb index 0a85c3e1a..0c09085a8 100644 --- a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb +++ b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb @@ -1,6 +1,18 @@ module Compiler module_function + def get_all_PBS_file_paths(game_data) + ret = [] + game_data.each { |element| ret.push(element.pbs_file_suffix) if !ret.include?(element.pbs_file_suffix) } + ret.each_with_index do |element, i| + ret[i] = [sprintf("PBS/%s.txt", game_data::PBS_BASE_FILENAME), element] + if !nil_or_empty?(element) + ret[i][0] = sprintf("PBS/%s_%s.txt", game_data::PBS_BASE_FILENAME, element) + end + end + return ret + end + def add_PBS_header_to_file(file) file.write(0xEF.chr) file.write(0xBB.chr) @@ -8,47 +20,55 @@ module Compiler file.write("\# " + _INTL("See the documentation on the wiki to learn how to edit this file.") + "\r\n") end - def write_PBS_file_generic(game_data, path) - write_pbs_file_message_start(path) + def write_PBS_file_generic(game_data) + paths = get_all_PBS_file_paths(game_data) schema = game_data.schema - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each element in turn - game_data.each do |element| - f.write("\#-------------------------------\r\n") - if schema["SectionName"] - f.write("[") - pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) - f.write("]\r\n") - else - f.write("[#{element.id}]\r\n") - end - schema.each_key do |key| - next if key == "SectionName" - val = element.get_property_for_PBS(key) - next if val.nil? - if schema[key][1][0] == "^" && val.is_a?(Array) - val.each do |sub_val| + idx = 0 + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + # Write each element in turn + game_data.each do |element| + next if element.pbs_file_suffix != path[1] + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + f.write("\#-------------------------------\r\n") + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") + end + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key) + next if val.nil? + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(sub_val, f, schema[key]) + pbWriteCsvRecord(val, f, schema[key]) f.write("\r\n") end - else - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(val, f, schema[key]) - f.write("\r\n") end end - end - } - process_pbs_file_message_end + } + process_pbs_file_message_end + end end #============================================================================= # Save Town Map data to PBS file #============================================================================= - def write_town_map(path = "PBS/town_map.txt") - write_PBS_file_generic(GameData::TownMap, path) + def write_town_map + write_PBS_file_generic(GameData::TownMap) end #============================================================================= @@ -114,36 +134,36 @@ module Compiler #============================================================================= # Save type data to PBS file #============================================================================= - def write_types(path = "PBS/types.txt") - write_PBS_file_generic(GameData::Type, path) + def write_types + write_PBS_file_generic(GameData::Type) end #============================================================================= # Save ability data to PBS file #============================================================================= - def write_abilities(path = "PBS/abilities.txt") - write_PBS_file_generic(GameData::Ability, path) + def write_abilities + write_PBS_file_generic(GameData::Ability) end #============================================================================= # Save move data to PBS file #============================================================================= - def write_moves(path = "PBS/moves.txt") - write_PBS_file_generic(GameData::Move, path) + def write_moves + write_PBS_file_generic(GameData::Move) end #============================================================================= # Save item data to PBS file #============================================================================= - def write_items(path = "PBS/items.txt") - write_PBS_file_generic(GameData::Item, path) + def write_items + write_PBS_file_generic(GameData::Item) end #============================================================================= # Save berry plant data to PBS file #============================================================================= - def write_berry_plants(path = "PBS/berry_plants.txt") - write_PBS_file_generic(GameData::BerryPlant, path) + def write_berry_plants + write_PBS_file_generic(GameData::BerryPlant) end #============================================================================= @@ -151,40 +171,55 @@ module Compiler # NOTE: Doesn't use write_PBS_file_generic because it needs to ignore defined # species with a form that isn't 0. #============================================================================= - def write_pokemon(path = "PBS/pokemon.txt") - write_pbs_file_message_start(path) + def write_pokemon + paths = [] + GameData::Species.each_species { |element| paths.push(element.pbs_file_suffix) if !paths.include?(element.pbs_file_suffix) } + paths.each_with_index do |element, i| + paths[i] = [sprintf("PBS/%s.txt", GameData::Species::PBS_BASE_FILENAME[0]), element] + if !nil_or_empty?(element) + paths[i][0] = sprintf("PBS/%s_%s.txt", GameData::Species::PBS_BASE_FILENAME[0], element) + end + end schema = GameData::Species.schema - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each element in turn - GameData::Species.each_species do |element| - f.write("\#-------------------------------\r\n") - if schema["SectionName"] - f.write("[") - pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) - f.write("]\r\n") - else - f.write("[#{element.id}]\r\n") - end - schema.each_key do |key| - next if key == "SectionName" - val = element.get_property_for_PBS(key) - next if val.nil? - if schema[key][1][0] == "^" && val.is_a?(Array) - val.each do |sub_val| + idx = 0 + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + # Write each element in turn + GameData::Species.each_species do |element| + next if element.pbs_file_suffix != path[1] + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + f.write("\#-------------------------------\r\n") + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") + end + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key) + next if val.nil? + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(sub_val, f, schema[key]) + pbWriteCsvRecord(val, f, schema[key]) f.write("\r\n") end - else - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(val, f, schema[key]) - f.write("\r\n") end end - end - } - process_pbs_file_message_end + } + process_pbs_file_message_end + end end #============================================================================= @@ -192,41 +227,59 @@ module Compiler # NOTE: Doesn't use write_PBS_file_generic because it needs to ignore defined # species with a form of 0, and needs its own schema. #============================================================================= - def write_pokemon_forms(path = "PBS/pokemon_forms.txt") - write_pbs_file_message_start(path) + def write_pokemon_forms + paths = [] + GameData::Species.each do |element| + next if element.form == 0 + paths.push(element.pbs_file_suffix) if !paths.include?(element.pbs_file_suffix) + end + paths.each_with_index do |element, i| + paths[i] = [sprintf("PBS/%s.txt", GameData::Species::PBS_BASE_FILENAME[1]), element] + if !nil_or_empty?(element) + paths[i][0] = sprintf("PBS/%s_%s.txt", GameData::Species::PBS_BASE_FILENAME[1], element) + end + end schema = GameData::Species.schema(true) - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each element in turn - GameData::Species.each do |element| - next if element.form == 0 - f.write("\#-------------------------------\r\n") - if schema["SectionName"] - f.write("[") - pbWriteCsvRecord(element.get_property_for_PBS("SectionName", true), f, schema["SectionName"]) - f.write("]\r\n") - else - f.write("[#{element.id}]\r\n") - end - schema.each_key do |key| - next if key == "SectionName" - val = element.get_property_for_PBS(key, true) - next if val.nil? - if schema[key][1][0] == "^" && val.is_a?(Array) - val.each do |sub_val| + idx = 0 + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + # Write each element in turn + GameData::Species.each do |element| + next if element.form == 0 + next if element.pbs_file_suffix != path[1] + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + f.write("\#-------------------------------\r\n") + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName", true), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") + end + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key, true) + next if val.nil? + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(sub_val, f, schema[key]) + pbWriteCsvRecord(val, f, schema[key]) f.write("\r\n") end - else - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(val, f, schema[key]) - f.write("\r\n") end end - end - } - process_pbs_file_message_end + } + process_pbs_file_message_end + end end #============================================================================= @@ -235,55 +288,73 @@ module Compiler # metrics for forms of species where the metrics are the same as for the # base species. #============================================================================= - def write_pokemon_metrics(path = "PBS/pokemon_metrics.txt") - write_pbs_file_message_start(path) + def write_pokemon_metrics + paths = [] + GameData::SpeciesMetrics.each do |element| + next if element.form == 0 + paths.push(element.pbs_file_suffix) if !paths.include?(element.pbs_file_suffix) + end + paths.each_with_index do |element, i| + paths[i] = [sprintf("PBS/%s.txt", GameData::SpeciesMetrics::PBS_BASE_FILENAME), element] + if !nil_or_empty?(element) + paths[i][0] = sprintf("PBS/%s_%s.txt", GameData::SpeciesMetrics::PBS_BASE_FILENAME, element) + end + end schema = GameData::SpeciesMetrics.schema - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each element in turn - GameData::SpeciesMetrics.each do |element| - if element.form > 0 - base_element = GameData::SpeciesMetrics.get(element.species) - next if element.back_sprite == base_element.back_sprite && - element.front_sprite == base_element.front_sprite && - element.front_sprite_altitude == base_element.front_sprite_altitude && - element.shadow_x == base_element.shadow_x && - element.shadow_size == base_element.shadow_size - end - f.write("\#-------------------------------\r\n") - if schema["SectionName"] - f.write("[") - pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) - f.write("]\r\n") - else - f.write("[#{element.id}]\r\n") - end - schema.each_key do |key| - next if key == "SectionName" - val = element.get_property_for_PBS(key) - next if val.nil? - if schema[key][1][0] == "^" && val.is_a?(Array) - val.each do |sub_val| + idx = 0 + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + # Write each element in turn + GameData::SpeciesMetrics.each do |element| + next if element.pbs_file_suffix != path[1] + if element.form > 0 + base_element = GameData::SpeciesMetrics.get(element.species) + next if element.back_sprite == base_element.back_sprite && + element.front_sprite == base_element.front_sprite && + element.front_sprite_altitude == base_element.front_sprite_altitude && + element.shadow_x == base_element.shadow_x && + element.shadow_size == base_element.shadow_size + end + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + f.write("\#-------------------------------\r\n") + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") + end + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key) + next if val.nil? + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(sub_val, f, schema[key]) + pbWriteCsvRecord(val, f, schema[key]) f.write("\r\n") end - else - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(val, f, schema[key]) - f.write("\r\n") end end - end - } - process_pbs_file_message_end + } + process_pbs_file_message_end + end end #============================================================================= # Save Shadow Pokémon data to PBS file #============================================================================= - def write_shadow_pokemon(path = "PBS/shadow_pokemon.txt") - write_PBS_file_generic(GameData::ShadowPokemon, path) + def write_shadow_pokemon + write_PBS_file_generic(GameData::ShadowPokemon) end #============================================================================= @@ -321,107 +392,115 @@ module Compiler #============================================================================= # Save ability data to PBS file #============================================================================= - def write_ribbons(path = "PBS/ribbons.txt") - write_PBS_file_generic(GameData::Ribbon, path) + def write_ribbons + write_PBS_file_generic(GameData::Ribbon) end #============================================================================= # Save wild encounter data to PBS file #============================================================================= - def write_encounters(path = "PBS/encounters.txt") - write_pbs_file_message_start(path) + def write_encounters + paths = get_all_PBS_file_paths(GameData::Encounter) map_infos = pbLoadMapInfos - File.open(path, "wb") { |f| - idx = 0 - add_PBS_header_to_file(f) - GameData::Encounter.each do |encounter_data| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - f.write("\#-------------------------------\r\n") - map_name = (map_infos[encounter_data.map]) ? " # #{map_infos[encounter_data.map].name}" : "" - if encounter_data.version > 0 - f.write(sprintf("[%03d,%d]%s\r\n", encounter_data.map, encounter_data.version, map_name)) - else - f.write(sprintf("[%03d]%s\r\n", encounter_data.map, map_name)) - end - encounter_data.types.each do |type, slots| - next if !slots || slots.length == 0 - if encounter_data.step_chances[type] && encounter_data.step_chances[type] > 0 - f.write(sprintf("%s,%d\r\n", type.to_s, encounter_data.step_chances[type])) + idx = 0 + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + GameData::Encounter.each do |element| + next if element.pbs_file_suffix != path[1] + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + f.write("\#-------------------------------\r\n") + map_name = (map_infos[element.map]) ? " # #{map_infos[element.map].name}" : "" + if element.version > 0 + f.write(sprintf("[%03d,%d]%s\r\n", element.map, element.version, map_name)) else - f.write(sprintf("%s\r\n", type.to_s)) + f.write(sprintf("[%03d]%s\r\n", element.map, map_name)) end - slots.each do |slot| - if slot[2] == slot[3] - f.write(sprintf(" %d,%s,%d\r\n", slot[0], slot[1], slot[2])) + element.types.each do |type, slots| + next if !slots || slots.length == 0 + if element.step_chances[type] && element.step_chances[type] > 0 + f.write(sprintf("%s,%d\r\n", type.to_s, element.step_chances[type])) else - f.write(sprintf(" %d,%s,%d,%d\r\n", slot[0], slot[1], slot[2], slot[3])) + f.write(sprintf("%s\r\n", type.to_s)) + end + slots.each do |slot| + if slot[2] == slot[3] + f.write(sprintf(" %d,%s,%d\r\n", slot[0], slot[1], slot[2])) + else + f.write(sprintf(" %d,%s,%d,%d\r\n", slot[0], slot[1], slot[2], slot[3])) + end end end end - end - } - process_pbs_file_message_end + } + process_pbs_file_message_end + end end #============================================================================= # Save trainer type data to PBS file #============================================================================= - def write_trainer_types(path = "PBS/trainer_types.txt") - write_PBS_file_generic(GameData::TrainerType, path) + def write_trainer_types + write_PBS_file_generic(GameData::TrainerType) end #============================================================================= # Save individual trainer data to PBS file #============================================================================= - def write_trainers(path = "PBS/trainers.txt") - write_pbs_file_message_start(path) - File.open(path, "wb") { |f| - idx = 0 - add_PBS_header_to_file(f) - GameData::Trainer.each do |trainer| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - f.write("\#-------------------------------\r\n") - if trainer.version > 0 - f.write(sprintf("[%s,%s,%d]\r\n", trainer.trainer_type, trainer.real_name, trainer.version)) - else - f.write(sprintf("[%s,%s]\r\n", trainer.trainer_type, trainer.real_name)) - end - f.write(sprintf("Items = %s\r\n", trainer.items.join(","))) if trainer.items.length > 0 - if trainer.real_lose_text && !trainer.real_lose_text.empty? - f.write(sprintf("LoseText = %s\r\n", trainer.real_lose_text)) - end - trainer.pokemon.each do |pkmn| - f.write(sprintf("Pokemon = %s,%d\r\n", pkmn[:species], pkmn[:level])) - f.write(sprintf(" Name = %s\r\n", pkmn[:name])) if pkmn[:name] && !pkmn[:name].empty? - f.write(sprintf(" Form = %d\r\n", pkmn[:form])) if pkmn[:form] && pkmn[:form] > 0 - f.write(sprintf(" Gender = %s\r\n", (pkmn[:gender] == 1) ? "female" : "male")) if pkmn[:gender] - f.write(" Shiny = yes\r\n") if pkmn[:shininess] && !pkmn[:super_shininess] - f.write(" SuperShiny = yes\r\n") if pkmn[:super_shininess] - f.write(" Shadow = yes\r\n") if pkmn[:shadowness] - f.write(sprintf(" Moves = %s\r\n", pkmn[:moves].join(","))) if pkmn[:moves] && pkmn[:moves].length > 0 - f.write(sprintf(" Ability = %s\r\n", pkmn[:ability])) if pkmn[:ability] - f.write(sprintf(" AbilityIndex = %d\r\n", pkmn[:ability_index])) if pkmn[:ability_index] - f.write(sprintf(" Item = %s\r\n", pkmn[:item])) if pkmn[:item] - f.write(sprintf(" Nature = %s\r\n", pkmn[:nature])) if pkmn[:nature] - ivs_array = [] - 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] + def write_trainers + paths = get_all_PBS_file_paths(GameData::Trainer) + idx = 0 + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + GameData::Trainer.each do |element| + next if element.pbs_file_suffix != path[1] + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + f.write("\#-------------------------------\r\n") + if element.version > 0 + f.write(sprintf("[%s,%s,%d]\r\n", element.trainer_type, element.real_name, element.version)) + else + f.write(sprintf("[%s,%s]\r\n", element.trainer_type, element.real_name)) + end + f.write(sprintf("Items = %s\r\n", element.items.join(","))) if element.items.length > 0 + if element.real_lose_text && !element.real_lose_text.empty? + f.write(sprintf("LoseText = %s\r\n", element.real_lose_text)) + end + element.pokemon.each do |pkmn| + f.write(sprintf("Pokemon = %s,%d\r\n", pkmn[:species], pkmn[:level])) + f.write(sprintf(" Name = %s\r\n", pkmn[:name])) if pkmn[:name] && !pkmn[:name].empty? + f.write(sprintf(" Form = %d\r\n", pkmn[:form])) if pkmn[:form] && pkmn[:form] > 0 + f.write(sprintf(" Gender = %s\r\n", (pkmn[:gender] == 1) ? "female" : "male")) if pkmn[:gender] + f.write(" Shiny = yes\r\n") if pkmn[:shininess] && !pkmn[:super_shininess] + f.write(" SuperShiny = yes\r\n") if pkmn[:super_shininess] + f.write(" Shadow = yes\r\n") if pkmn[:shadowness] + f.write(sprintf(" Moves = %s\r\n", pkmn[:moves].join(","))) if pkmn[:moves] && pkmn[:moves].length > 0 + f.write(sprintf(" Ability = %s\r\n", pkmn[:ability])) if pkmn[:ability] + f.write(sprintf(" AbilityIndex = %d\r\n", pkmn[:ability_index])) if pkmn[:ability_index] + f.write(sprintf(" Item = %s\r\n", pkmn[:item])) if pkmn[:item] + f.write(sprintf(" Nature = %s\r\n", pkmn[:nature])) if pkmn[:nature] + ivs_array = [] + 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 + 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 - 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 - } - process_pbs_file_message_end + } + process_pbs_file_message_end + end end #============================================================================= @@ -542,22 +621,132 @@ module Compiler # NOTE: Doesn't use write_PBS_file_generic because it contains data for two # different GameData classes. #============================================================================= - def write_metadata(path = "PBS/metadata.txt") - write_pbs_file_message_start(path) + def write_metadata + paths = [] + GameData::Metadata.each do |element| + paths.push(element.pbs_file_suffix) if !paths.include?(element.pbs_file_suffix) + end + GameData::PlayerMetadata.each do |element| + paths.push(element.pbs_file_suffix) if !paths.include?(element.pbs_file_suffix) + end + paths.each_with_index do |element, i| + paths[i] = [sprintf("PBS/%s.txt", GameData::Metadata::PBS_BASE_FILENAME), element] + if !nil_or_empty?(element) + paths[i][0] = sprintf("PBS/%s_%s.txt", GameData::Metadata::PBS_BASE_FILENAME, element) + end + end global_schema = GameData::Metadata.schema player_schema = GameData::PlayerMetadata.schema - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each element in turn - [GameData::Metadata, GameData::PlayerMetadata].each do |game_data| - schema = global_schema if game_data == GameData::Metadata - schema = player_schema if game_data == GameData::PlayerMetadata - game_data.each do |element| + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + # Write each element in turn + [GameData::Metadata, GameData::PlayerMetadata].each do |game_data| + schema = global_schema if game_data == GameData::Metadata + schema = player_schema if game_data == GameData::PlayerMetadata + game_data.each do |element| + next if element.pbs_file_suffix != path[1] + f.write("\#-------------------------------\r\n") + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") + else + f.write("[#{element.id}]\r\n") + end + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key) + next if val.nil? + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end + end + end + end + } + process_pbs_file_message_end + end + end + + #============================================================================= + # Save map metadata data to PBS file + # NOTE: Doesn't use write_PBS_file_generic because it writes the RMXP map name + # next to the section header for each map. + #============================================================================= + def write_map_metadata + paths = get_all_PBS_file_paths(GameData::MapMetadata) + map_infos = pbLoadMapInfos + schema = GameData::MapMetadata.schema + idx = 0 + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + GameData::MapMetadata.each do |element| + next if element.pbs_file_suffix != path[1] + echo "." if idx % 50 == 0 + Graphics.update if idx % 250 == 0 + idx += 1 + f.write("\#-------------------------------\r\n") + map_name = (map_infos && map_infos[element.id]) ? map_infos[element.id].name : nil + f.write(sprintf("[%03d]", element.id)) + f.write(sprintf(" # %s", map_name)) if map_name + f.write("\r\n") + schema.each_key do |key| + next if key == "SectionName" + val = element.get_property_for_PBS(key) + next if val.nil? + if schema[key][1][0] == "^" && val.is_a?(Array) + val.each do |sub_val| + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(sub_val, f, schema[key]) + f.write("\r\n") + end + else + f.write(sprintf("%s = ", key)) + pbWriteCsvRecord(val, f, schema[key]) + f.write("\r\n") + end + end + end + } + process_pbs_file_message_end + end + end + + #============================================================================= + # Save dungeon tileset contents data to PBS file + # NOTE: Doesn't use write_PBS_file_generic because it writes the tileset name + # next to the section header for each tileset. + #============================================================================= + def write_dungeon_tilesets + paths = get_all_PBS_file_paths(GameData::DungeonTileset) + schema = GameData::DungeonTileset.schema + tilesets = load_data("Data/Tilesets.rxdata") + paths.each do |path| + write_pbs_file_message_start(path[0]) + File.open(path[0], "wb") { |f| + add_PBS_header_to_file(f) + # Write each element in turn + GameData::DungeonTileset.each do |element| + next if element.pbs_file_suffix != path[1] f.write("\#-------------------------------\r\n") if schema["SectionName"] f.write("[") pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) - f.write("]\r\n") + f.write("]") + f.write(" # #{tilesets[element.id].name}") if tilesets && tilesets[element.id] + f.write("\r\n") else f.write("[#{element.id}]\r\n") end @@ -578,109 +767,23 @@ module Compiler end end end - end - } - process_pbs_file_message_end - end - - #============================================================================= - # Save map metadata data to PBS file - # NOTE: Doesn't use write_PBS_file_generic because it writes the RMXP map name - # next to the section header for each map. - #============================================================================= - def write_map_metadata(path = "PBS/map_metadata.txt") - write_pbs_file_message_start(path) - map_infos = pbLoadMapInfos - schema = GameData::MapMetadata.schema - File.open(path, "wb") { |f| - idx = 0 - add_PBS_header_to_file(f) - GameData::MapMetadata.each do |element| - echo "." if idx % 50 == 0 - idx += 1 - Graphics.update if idx % 250 == 0 - f.write("\#-------------------------------\r\n") - map_name = (map_infos && map_infos[element.id]) ? map_infos[element.id].name : nil - f.write(sprintf("[%03d]", element.id)) - f.write(sprintf(" # %s", map_name)) if map_name - f.write("\r\n") - schema.each_key do |key| - next if key == "SectionName" - val = element.get_property_for_PBS(key) - next if val.nil? - if schema[key][1][0] == "^" && val.is_a?(Array) - val.each do |sub_val| - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(sub_val, f, schema[key]) - f.write("\r\n") - end - else - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(val, f, schema[key]) - f.write("\r\n") - end - end - end - } - process_pbs_file_message_end - end - - #============================================================================= - # Save dungeon tileset contents data to PBS file - # NOTE: Doesn't use write_PBS_file_generic because it writes the tileset name - # next to the section header for each tileset. - #============================================================================= - def write_dungeon_tilesets(path = "PBS/dungeon_tilesets.txt") - write_pbs_file_message_start(path) - tilesets = load_data("Data/Tilesets.rxdata") - schema = GameData::DungeonTileset.schema - File.open(path, "wb") { |f| - add_PBS_header_to_file(f) - # Write each element in turn - GameData::DungeonTileset.each do |element| - f.write("\#-------------------------------\r\n") - if schema["SectionName"] - f.write("[") - pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) - f.write("]") - f.write(" # #{tilesets[element.id].name}") if tilesets && tilesets[element.id] - f.write("\r\n") - else - f.write("[#{element.id}]\r\n") - end - schema.each_key do |key| - next if key == "SectionName" - val = element.get_property_for_PBS(key) - next if val.nil? - if schema[key][1][0] == "^" && val.is_a?(Array) - val.each do |sub_val| - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(sub_val, f, schema[key]) - f.write("\r\n") - end - else - f.write(sprintf("%s = ", key)) - pbWriteCsvRecord(val, f, schema[key]) - f.write("\r\n") - end - end - end - } - process_pbs_file_message_end + } + process_pbs_file_message_end + end end #============================================================================= # Save dungeon parameters to PBS file #============================================================================= - def write_dungeon_parameters(path = "PBS/dungeon_parameters.txt") - write_PBS_file_generic(GameData::DungeonParameters, path) + def write_dungeon_parameters + write_PBS_file_generic(GameData::DungeonParameters) end #============================================================================= # Save phone messages to PBS file #============================================================================= - def write_phone(path = "PBS/phone.txt") - write_PBS_file_generic(GameData::PhoneMessage, path) + def write_phone + write_PBS_file_generic(GameData::PhoneMessage) end #============================================================================= From 91efb4684b4ce1bf7ad1916f85986f59777d4291 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Wed, 23 Nov 2022 22:43:11 +0000 Subject: [PATCH 06/12] Fixed file-choosing methods not removing file extensions, fixed typo in Puddle envirnment registration --- .../001_Hardcoded data/014_Environment.rb | 6 +- .../010_Data/002_PBS data/015_Trainer.rb | 58 ++++++++++++++++--- Data/Scripts/016_UI/011_UI_Jukebox.rb | 2 +- .../005_AnimEditor_Functions.rb | 11 ++-- .../Scripts/020_Debug/002_Editor_DataTypes.rb | 8 +-- Data/Scripts/020_Debug/003_Editor_Listers.rb | 5 -- 6 files changed, 64 insertions(+), 26 deletions(-) diff --git a/Data/Scripts/010_Data/001_Hardcoded data/014_Environment.rb b/Data/Scripts/010_Data/001_Hardcoded data/014_Environment.rb index c7923ac01..9bde07bca 100644 --- a/Data/Scripts/010_Data/001_Hardcoded data/014_Environment.rb +++ b/Data/Scripts/010_Data/001_Hardcoded data/014_Environment.rb @@ -57,9 +57,9 @@ GameData::Environment.register({ }) GameData::Environment.register({ - :id => :Puddle, - :name => _INTL("Puddle"), - :battle_basec => "puddle" + :id => :Puddle, + :name => _INTL("Puddle"), + :battle_base => "puddle" }) GameData::Environment.register({ diff --git a/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb b/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb index ceebb4044..7192b96ff 100644 --- a/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb +++ b/Data/Scripts/010_Data/002_PBS data/015_Trainer.rb @@ -13,12 +13,19 @@ module GameData DATA_FILENAME = "trainers.dat" PBS_BASE_FILENAME = "trainers" + # "Pokemon" is specially mentioned in def compile_trainers and def + # write_trainers, and acts as a subheading for a particular Pokémon. SCHEMA = { - "Items" => [:items, "*e", :Item], - "LoseText" => [:lose_text, "q"], - "Pokemon" => [:pokemon, "ev", :Species], # Species, level + "SectionName" => [:id, "esU", :TrainerType], + "Items" => [:items, "*e", :Item], + "LoseText" => [:real_lose_text, "q"], + "Pokemon" => [:pokemon, "ev", :Species] # Species, level + } + # This schema is for definable properties of individual Pokémon (apart from + # species and level which are above). + SUB_SCHEMA = { "Form" => [:form, "u"], - "Name" => [:name, "s"], + "Name" => [:real_name, "s"], "Moves" => [:moves, "*e", :Move], "Ability" => [:ability, "e", :Ability], "AbilityIndex" => [:ability_index, "u"], @@ -38,6 +45,10 @@ module GameData extend ClassMethodsSymbols include InstanceMethods + def self.sub_schema + return SUB_SCHEMA + end + # @param tr_type [Symbol, String] # @param tr_name [String] # @param tr_version [Integer, nil] @@ -75,10 +86,10 @@ module GameData def initialize(hash) @id = hash[:id] @trainer_type = hash[:trainer_type] - @real_name = hash[:name] || "Unnamed" + @real_name = hash[:real_name] || "" @version = hash[:version] || 0 @items = hash[:items] || [] - @real_lose_text = hash[:lose_text] || "..." + @real_lose_text = hash[:real_lose_text] || "..." @pokemon = hash[:pokemon] || [] @pokemon.each do |pkmn| GameData::Stat.each_main do |s| @@ -156,7 +167,7 @@ module GameData end end pkmn.happiness = pkmn_data[:happiness] if pkmn_data[:happiness] - pkmn.name = pkmn_data[:name] if pkmn_data[:name] && !pkmn_data[:name].empty? + pkmn.name = pkmn_data[:real_name] if !nil_or_empty?(pkmn_data[:real_name]) if pkmn_data[:shadowness] pkmn.makeShadow pkmn.shiny = false @@ -166,5 +177,38 @@ module GameData end return trainer 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, index = 0) + ret = __orig__get_property_for_PBS(key) + case key + when "SectionName" + ret = [@trainer_type, @real_name] if @version == 0 + when "Pokemon" + ret = [@pokemon[index][:species], @pokemon[index][:level]] + end + return ret + end + + def get_pokemon_property_for_PBS(key, index = 0) + return [@pokemon[index][:species], @pokemon[index][:level]] if key == "Pokemon" + ret = @pokemon[index][SUB_SCHEMA[key][0]] + ret = nil if ret == false || (ret.is_a?(Array) && ret.length == 0) || ret == "" + case key + when "Gender" + ret = ["male", "female"][ret] if ret + when "IV", "EV" + if ret + new_ret = [] + GameData::Stat.each_main do |s| + new_ret[s.pbs_order] = ret[s.id] if s.pbs_order >= 0 + end + ret = new_ret + end + when "Shiny" + ret = nil if @pokemon[index][:super_shininess] + end + return ret + end end end diff --git a/Data/Scripts/016_UI/011_UI_Jukebox.rb b/Data/Scripts/016_UI/011_UI_Jukebox.rb index a89d10d29..633620660 100644 --- a/Data/Scripts/016_UI/011_UI_Jukebox.rb +++ b/Data/Scripts/016_UI/011_UI_Jukebox.rb @@ -105,7 +105,7 @@ class PokemonJukeboxScreen Dir.glob("*.mid") { |f| files.push(f) } Dir.glob("*.midi") { |f| files.push(f) } } - files.map! { |f| f.chomp(File.extname(f)) } + files.map! { |f| File.basename(f, ".*") } files.uniq! files.sort! { |a, b| a.downcase <=> b.downcase } @scene.pbSetCommands(files, 0) diff --git a/Data/Scripts/020_Debug/002_Animation editor/005_AnimEditor_Functions.rb b/Data/Scripts/020_Debug/002_Animation editor/005_AnimEditor_Functions.rb index 2f0914bbc..70bf6d323 100644 --- a/Data/Scripts/020_Debug/002_Animation editor/005_AnimEditor_Functions.rb +++ b/Data/Scripts/020_Debug/002_Animation editor/005_AnimEditor_Functions.rb @@ -49,7 +49,7 @@ def pbSelectAnim(canvas, animwin) if Input.trigger?(Input::USE) && animfiles.length > 0 filename = cmdwin.commands[cmdwin.index] bitmap = AnimatedBitmap.new("Graphics/Animations/" + filename, ctlwin.value(0)).deanimate - canvas.animation.graphic = File.basename(filename, ".png") + canvas.animation.graphic = File.basename(filename, ".*") canvas.animation.hue = ctlwin.value(0) canvas.animbitmap = bitmap animwin.animbitmap = bitmap @@ -544,11 +544,7 @@ def pbSelectSE(canvas, audio) pbSEStop end if maxsizewindow.changed?(5) # OK - filename = File.basename(filename, ".wav") -# filename = File.basename(filename,".mp3") - filename = File.basename(filename, ".ogg") - filename = File.basename(filename, ".wma") - audio.name = filename + audio.name = File.basename(filename, ".*") audio.volume = maxsizewindow.value(1) audio.pitch = maxsizewindow.value(2) ret = true @@ -583,6 +579,9 @@ def pbSelectBG(canvas, timing) # animfiles.concat(Dir.glob("*.jpeg")) # animfiles.concat(Dir.glob("*.bmp")) } + animfiles.map! { |f| File.basename(f, ".*") } + animfiles.uniq! + animfiles.sort! { |a, b| a.downcase <=> b.downcase } cmdwin = pbListWindow(animfiles, 320) cmdwin.height = 480 cmdwin.opacity = 200 diff --git a/Data/Scripts/020_Debug/002_Editor_DataTypes.rb b/Data/Scripts/020_Debug/002_Editor_DataTypes.rb index 8a5b6d45d..36be2b9a0 100644 --- a/Data/Scripts/020_Debug/002_Editor_DataTypes.rb +++ b/Data/Scripts/020_Debug/002_Editor_DataTypes.rb @@ -359,7 +359,7 @@ end module BGMProperty def self.set(settingname, oldsetting) chosenmap = pbListScreen(settingname, MusicFileLister.new(true, oldsetting)) - return (chosenmap && chosenmap != "") ? chosenmap : oldsetting + return (chosenmap && chosenmap != "") ? File.basename(chosenmap, ".*") : oldsetting end def self.format(value) @@ -372,7 +372,7 @@ end module MEProperty def self.set(settingname, oldsetting) chosenmap = pbListScreen(settingname, MusicFileLister.new(false, oldsetting)) - return (chosenmap && chosenmap != "") ? chosenmap : oldsetting + return (chosenmap && chosenmap != "") ? File.basename(chosenmap, ".*") : oldsetting end def self.format(value) @@ -385,7 +385,7 @@ end module WindowskinProperty def self.set(settingname, oldsetting) chosenmap = pbListScreen(settingname, GraphicsLister.new("Graphics/Windowskins/", oldsetting)) - return (chosenmap && chosenmap != "") ? chosenmap : oldsetting + return (chosenmap && chosenmap != "") ? File.basename(chosenmap, ".*") : oldsetting end def self.format(value) @@ -653,7 +653,7 @@ end module CharacterProperty def self.set(settingname, oldsetting) chosenmap = pbListScreen(settingname, GraphicsLister.new("Graphics/Characters/", oldsetting)) - return (chosenmap && chosenmap != "") ? chosenmap : oldsetting + return (chosenmap && chosenmap != "") ? File.basename(chosenmap, ".*") : oldsetting end def self.format(value) diff --git a/Data/Scripts/020_Debug/003_Editor_Listers.rb b/Data/Scripts/020_Debug/003_Editor_Listers.rb index e00f0fb40..938b92db6 100644 --- a/Data/Scripts/020_Debug/003_Editor_Listers.rb +++ b/Data/Scripts/020_Debug/003_Editor_Listers.rb @@ -148,15 +148,10 @@ class GraphicsLister @commands.clear Dir.chdir(@folder) { Dir.glob("*.png") { |f| @commands.push(f) } - Dir.glob("*.PNG") { |f| @commands.push(f) } Dir.glob("*.gif") { |f| @commands.push(f) } - Dir.glob("*.GIF") { |f| @commands.push(f) } # Dir.glob("*.jpg") { |f| @commands.push(f) } -# Dir.glob("*.JPG") { |f| @commands.push(f) } # Dir.glob("*.jpeg") { |f| @commands.push(f) } -# Dir.glob("*.JPEG") { |f| @commands.push(f) } # Dir.glob("*.bmp") { |f| @commands.push(f) } -# Dir.glob("*.BMP") { |f| @commands.push(f) } } @commands.sort! @commands.length.times do |i| From 427cc4562967ce00fed240db6c553f67154385b6 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Wed, 23 Nov 2022 22:44:15 +0000 Subject: [PATCH 07/12] Generalised compiler and writer methods for trainers.txt --- .../021_Compiler/002_Compiler_CompilePBS.rb | 211 ++++++++++-------- .../021_Compiler/003_Compiler_WritePBS.rb | 59 ++--- 2 files changed, 148 insertions(+), 122 deletions(-) diff --git a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb index 168a590d8..f36bf8207 100644 --- a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb +++ b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb @@ -749,132 +749,157 @@ module Compiler def compile_trainers(*paths) GameData::Trainer::DATA.clear schema = GameData::Trainer.schema - max_level = GameData::GrowthRate.max_level - trainer_names = [] - trainer_lose_texts = [] + sub_schema = GameData::Trainer.sub_schema + idx = 0 + # Read from PBS file(s) paths.each do |path| compile_pbs_file_message_start(path) file_suffix = File.basename(path, ".txt")[GameData::Trainer::PBS_BASE_FILENAME.length + 1, path.length] || "" - trainer_hash = nil + data_hash = 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 - idx = 0 pbCompilerEachPreppedLine(path) { |line, line_no| echo "." if idx % 50 == 0 idx += 1 Graphics.update if idx % 250 == 0 + FileLineData.setSection(section_name, nil, section_line) if line[/^\s*\[\s*(.+)\s*\]\s*$/] # New section [trainer_type, name] or [trainer_type, name, version] - if trainer_hash - if !current_pkmn - raise _INTL("Started new trainer while previous trainer has no Pokémon.\r\n{1}", FileLineData.linereport) - end - # Add trainer's data to records - trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]] - GameData::Trainer.register(trainer_hash) + section_name = $~[1] + section_line = line + if data_hash + validate_compiled_trainer(data_hash) + GameData::Trainer.register(data_hash) end - line_data = pbGetCsvRecord($~[1], line_no, [0, "esU", :TrainerType]) - # Construct trainer hash - trainer_hash = { - :trainer_type => line_data[0], - :name => line_data[1], - :version => line_data[2] || 0, - :pokemon => [], + FileLineData.setSection(section_name, nil, section_line) + # Construct data hash + data_hash = { :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 - trainer_names.push(trainer_hash[:name]) elsif line[/^\s*(\w+)\s*=\s*(.*)$/] # 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) end - property_name = $~[1] - line_schema = schema[property_name] - next if !line_schema - property_value = pbGetCsvRecord($~[2], line_no, line_schema) - # Error checking in XXX=YYY lines - case property_name - when "Pokemon" - 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) + key = $~[1] + if schema[key] # Property of the trainer + property_value = pbGetCsvRecord($~[2], line_no, schema[key]) + if key == "Pokemon" + current_pkmn = { + :species => property_value[0], + :level => property_value[1] + } + data_hash[schema[key][0]].push(current_pkmn) + else + data_hash[schema[key][0]] = property_value end - when "Name" - 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 + elsif sub_schema[key] # Property of a Pokémon if !current_pkmn raise _INTL("Pokémon hasn't been defined yet!\r\n{1}", FileLineData.linereport) end - case property_name - 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 + current_pkmn[sub_schema[key][0]] = pbGetCsvRecord($~[2], line_no, sub_schema[key]) end end } # Add last trainer's data to records - if trainer_hash - if !current_pkmn - raise _INTL("End of file reached while last trainer has no Pokémon.\r\n{1}", FileLineData.linereport) - end - trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]] - GameData::Trainer.register(trainer_hash) + if data_hash + FileLineData.setSection(section_name, nil, section_line) + validate_compiled_trainer(data_hash) + GameData::Trainer.register(data_hash) end process_pbs_file_message_end end + validate_all_compiled_trainers # Save all data 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::TrainerLoseText, trainer_lose_texts) + MessageTypes.setMessagesAsHash(MessageTypes::TrainerLoseText, lose_texts) end #============================================================================= diff --git a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb index 0c09085a8..d4ebd5a65 100644 --- a/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb +++ b/Data/Scripts/021_Compiler/003_Compiler_WritePBS.rb @@ -452,50 +452,51 @@ module Compiler #============================================================================= def write_trainers paths = get_all_PBS_file_paths(GameData::Trainer) + schema = GameData::Trainer.schema + sub_schema = GameData::Trainer.sub_schema idx = 0 paths.each do |path| write_pbs_file_message_start(path[0]) File.open(path[0], "wb") { |f| add_PBS_header_to_file(f) + # Write each element in turn GameData::Trainer.each do |element| next if element.pbs_file_suffix != path[1] echo "." if idx % 50 == 0 Graphics.update if idx % 250 == 0 idx += 1 f.write("\#-------------------------------\r\n") - if element.version > 0 - f.write(sprintf("[%s,%s,%d]\r\n", element.trainer_type, element.real_name, element.version)) + if schema["SectionName"] + f.write("[") + pbWriteCsvRecord(element.get_property_for_PBS("SectionName"), f, schema["SectionName"]) + f.write("]\r\n") else - f.write(sprintf("[%s,%s]\r\n", element.trainer_type, element.real_name)) + f.write("[#{element.id}]\r\n") end - f.write(sprintf("Items = %s\r\n", element.items.join(","))) if element.items.length > 0 - if element.real_lose_text && !element.real_lose_text.empty? - f.write(sprintf("LoseText = %s\r\n", element.real_lose_text)) + # Write each trainer property + schema.each_key do |key| + 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 - element.pokemon.each do |pkmn| - f.write(sprintf("Pokemon = %s,%d\r\n", pkmn[:species], pkmn[:level])) - f.write(sprintf(" Name = %s\r\n", pkmn[:name])) if pkmn[:name] && !pkmn[:name].empty? - f.write(sprintf(" Form = %d\r\n", pkmn[:form])) if pkmn[:form] && pkmn[:form] > 0 - f.write(sprintf(" Gender = %s\r\n", (pkmn[:gender] == 1) ? "female" : "male")) if pkmn[:gender] - f.write(" Shiny = yes\r\n") if pkmn[:shininess] && !pkmn[:super_shininess] - f.write(" SuperShiny = yes\r\n") if pkmn[:super_shininess] - f.write(" Shadow = yes\r\n") if pkmn[:shadowness] - f.write(sprintf(" Moves = %s\r\n", pkmn[:moves].join(","))) if pkmn[:moves] && pkmn[:moves].length > 0 - f.write(sprintf(" Ability = %s\r\n", pkmn[:ability])) if pkmn[:ability] - f.write(sprintf(" AbilityIndex = %d\r\n", pkmn[:ability_index])) if pkmn[:ability_index] - f.write(sprintf(" Item = %s\r\n", pkmn[:item])) if pkmn[:item] - f.write(sprintf(" Nature = %s\r\n", pkmn[:nature])) if pkmn[:nature] - ivs_array = [] - 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] + # Write each Pokémon in turn + element.pokemon.each_with_index do |pkmn, i| + # Write species/level + val = element.get_pokemon_property_for_PBS("Pokemon", i) + f.write("Pokemon = ") + pbWriteCsvRecord(val, f, schema["Pokemon"]) + f.write("\r\n") + # Write other Pokémon properties + sub_schema.each_key do |key| + val = element.get_pokemon_property_for_PBS(key, i) + next if val.nil? + f.write(sprintf(" %s = ", key)) + pbWriteCsvRecord(val, f, sub_schema[key]) + f.write("\r\n") 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 } From 7c39a56a43b86df4d505ecca20674ab9d76c97d5 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 27 Nov 2022 22:38:47 +0000 Subject: [PATCH 08/12] =?UTF-8?q?Made=20tutored=20moves=20learnable=20by?= =?UTF-8?q?=20Pok=C3=A9mon=20if=20they=20can=20get=20the=20move=20via=20le?= =?UTF-8?q?vel/egg=20move,=20followers=20won't=20follow=20the=20player=20i?= =?UTF-8?q?f=20they=20already=20have=20a=20move=20route,=20added=20console?= =?UTF-8?q?=20warning=20if=20a=20different=20version=20of=20mkxp-z=20is=20?= =?UTF-8?q?detected?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Data/Scripts/001_Settings.rb | 1 + Data/Scripts/001_Technical/001_MKXP_Compatibility.rb | 6 ++++++ Data/Scripts/004_Game classes/011_Game_Follower.rb | 1 + Data/Scripts/014_Pokemon/001_Pokemon.rb | 6 +++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Data/Scripts/001_Settings.rb b/Data/Scripts/001_Settings.rb index 073cf51bd..a81c938d7 100644 --- a/Data/Scripts/001_Settings.rb +++ b/Data/Scripts/001_Settings.rb @@ -444,4 +444,5 @@ end module Essentials VERSION = "20.1.dev" ERROR_TEXT = "" + MKXPZ_VERSION = "2.3.1" end diff --git a/Data/Scripts/001_Technical/001_MKXP_Compatibility.rb b/Data/Scripts/001_Technical/001_MKXP_Compatibility.rb index 6eae95ad1..c40084e58 100644 --- a/Data/Scripts/001_Technical/001_MKXP_Compatibility.rb +++ b/Data/Scripts/001_Technical/001_MKXP_Compatibility.rb @@ -46,3 +46,9 @@ def pbSetResizeFactor(factor) Graphics.center end end + +if System::VERSION != Essentials::MKXPZ_VERSION + printf(sprintf("\e[1;33mWARNING: mkxp-z version %s detected, but this version of Pokémon Essentials was designed for mkxp-z version %s.\e[0m\r\n", + System::VERSION, Essentials::MKXPZ_VERSION)) + printf("\e[1;33mWARNING: Pokémon Essentials may not work properly.\e[0m\r\n") +end diff --git a/Data/Scripts/004_Game classes/011_Game_Follower.rb b/Data/Scripts/004_Game classes/011_Game_Follower.rb index de06b11be..6b209e999 100644 --- a/Data/Scripts/004_Game classes/011_Game_Follower.rb +++ b/Data/Scripts/004_Game classes/011_Game_Follower.rb @@ -112,6 +112,7 @@ class Game_Follower < Game_Event end def follow_leader(leader, instant = false, leaderIsTrueLeader = true) + return if @move_route_forcing maps_connected = $map_factory.areConnected?(leader.map.map_id, self.map.map_id) target = nil # Get the target tile that self wants to move to diff --git a/Data/Scripts/014_Pokemon/001_Pokemon.rb b/Data/Scripts/014_Pokemon/001_Pokemon.rb index a2eb88e22..9ce374827 100644 --- a/Data/Scripts/014_Pokemon/001_Pokemon.rb +++ b/Data/Scripts/014_Pokemon/001_Pokemon.rb @@ -707,7 +707,11 @@ class Pokemon # @return [Boolean] whether the Pokémon is compatible with the given move def compatible_with_move?(move_id) move_data = GameData::Move.try_get(move_id) - return move_data && species_data.tutor_moves.include?(move_data.id) + return false if !move_data + return true if species_data.tutor_moves.include?(move_data.id) + return true if getMoveList.any? { |m| m[1] == move_data.id } + return true if species_data.get_egg_moves.include?(move_data.id) + return false end def can_relearn_move? From b13c2ed2edd2b4b783532796554ba644bbf2e5df Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Mon, 28 Nov 2022 20:28:48 +0000 Subject: [PATCH 09/12] Fixed and generalised PBS editors --- .../Scripts/010_Data/002_PBS data/006_Item.rb | 22 ++ .../010_Data/002_PBS data/008_Species.rb | 87 ++-- .../010_Data/002_PBS data/014_TrainerType.rb | 17 + .../010_Data/002_PBS data/016_Metadata.rb | 2 +- .../002_PBS data/017_PlayerMetadata.rb | 7 + .../010_Data/002_PBS data/018_MapMetadata.rb | 7 + .../001_Editor screens/001_EditorScreens.rb | 371 +++++------------- .../Scripts/020_Debug/002_Editor_DataTypes.rb | 114 ++++-- 8 files changed, 293 insertions(+), 334 deletions(-) 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 From d654f3edbf7d8ad9f80dff88bc1d291a572073f8 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Thu, 1 Dec 2022 22:43:47 +0000 Subject: [PATCH 10/12] Added BP shop and prices to various items --- .../Scripts/010_Data/002_PBS data/006_Item.rb | 8 +- Data/Scripts/016_UI/021_BattlePointShop.rb | 522 ++++++++++++++++++ ...veRelearner.rb => 022_UI_MoveRelearner.rb} | 0 ...rifyChamber.rb => 023_UI_PurifyChamber.rb} | 0 ...I_MysteryGift.rb => 024_UI_MysteryGift.rb} | 0 ...24_UI_TextEntry.rb => 025_UI_TextEntry.rb} | 0 PBS/Gen 5/items.txt | 178 ++++++ PBS/Gen 6/items.txt | 246 +++++++++ PBS/Gen 7/items.txt | 149 +++++ PBS/Gen 8/items.txt | 295 +++++++++- PBS/items.txt | 285 ++++++++++ 11 files changed, 1677 insertions(+), 6 deletions(-) create mode 100644 Data/Scripts/016_UI/021_BattlePointShop.rb rename Data/Scripts/016_UI/{021_UI_MoveRelearner.rb => 022_UI_MoveRelearner.rb} (100%) rename Data/Scripts/016_UI/{022_UI_PurifyChamber.rb => 023_UI_PurifyChamber.rb} (100%) rename Data/Scripts/016_UI/{023_UI_MysteryGift.rb => 024_UI_MysteryGift.rb} (100%) rename Data/Scripts/016_UI/{024_UI_TextEntry.rb => 025_UI_TextEntry.rb} (100%) 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 a077c8bdd..6ccc702c6 100644 --- a/Data/Scripts/010_Data/002_PBS data/006_Item.rb +++ b/Data/Scripts/010_Data/002_PBS data/006_Item.rb @@ -6,6 +6,7 @@ module GameData attr_reader :pocket attr_reader :price attr_reader :sell_price + attr_reader :bp_price attr_reader :field_use attr_reader :battle_use attr_reader :flags @@ -25,6 +26,7 @@ module GameData "Pocket" => [:pocket, "v"], "Price" => [:price, "u"], "SellPrice" => [:sell_price, "u"], + "BPPrice" => [:bp_price, "u"], "FieldUse" => [:field_use, "e", { "OnPokemon" => 1, "Direct" => 2, "TM" => 3, "HM" => 4, "TR" => 5 }], "BattleUse" => [:battle_use, "e", { "OnPokemon" => 1, "OnMove" => 2, "OnBattler" => 3, @@ -50,6 +52,7 @@ module GameData ["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.")], + ["BPPrice", LimitProperty.new(Settings::MAX_BATTLE_POINTS), _INTL("Purchase price of this item in Battle Points (BP).")], ["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.")], @@ -111,6 +114,7 @@ module GameData @pocket = hash[:pocket] || 1 @price = hash[:price] || 0 @sell_price = hash[:sell_price] || (@price / 2) + @bp_price = hash[:bp_price] || 1 @field_use = hash[:field_use] || 0 @battle_use = hash[:battle_use] || 0 @flags = hash[:flags] || [] @@ -163,7 +167,7 @@ module GameData return false end - def can_hold?; return !is_important?; end + def can_hold?; return !is_important?; end def consumed_after_use? return !is_important? && @consumable @@ -224,6 +228,8 @@ module GameData case key when "SellPrice" ret = nil if ret == @price / 2 + when "BPPrice" + ret = nil if ret == 1 when "FieldUse", "BattleUse" ret = nil if ret == 0 when "Consumable" diff --git a/Data/Scripts/016_UI/021_BattlePointShop.rb b/Data/Scripts/016_UI/021_BattlePointShop.rb new file mode 100644 index 000000000..1cf793bab --- /dev/null +++ b/Data/Scripts/016_UI/021_BattlePointShop.rb @@ -0,0 +1,522 @@ +#=============================================================================== +# Abstraction layer for Pokemon Essentials +#=============================================================================== +class BattlePointShopAdapter + def getBP + return $player.battle_points + end + + def getBPString + return _INTL("{1} BP", $player.battle_points.to_s_formatted) + end + + def setBP(value) + $player.battle_points = value + end + + def getInventory + return $bag + end + + def getName(item) + return GameData::Item.get(item).name + end + + def getNamePlural(item) + return GameData::Item.get(item).name_plural + end + + def getDisplayName(item) + item_name = getName(item) + if GameData::Item.get(item).is_machine? + machine = GameData::Item.get(item).move + item_name = _INTL("{1} {2}", item_name, GameData::Move.get(machine).name) + end + return item_name + end + + def getDisplayNamePlural(item) + item_name_plural = getNamePlural(item) + if GameData::Item.get(item).is_machine? + machine = GameData::Item.get(item).move + item_name_plural = _INTL("{1} {2}", item_name_plural, GameData::Move.get(machine).name) + end + return item_name_plural + end + + def getDescription(item) + return GameData::Item.get(item).description + end + + def getItemIcon(item) + return (item) ? GameData::Item.icon_filename(item) : nil + end + + # Unused + def getItemIconRect(_item) + return Rect.new(0, 0, 48, 48) + end + + def getQuantity(item) + return $bag.quantity(item) + end + + def showQuantity?(item) + return !GameData::Item.get(item).is_important? + end + + def getPrice(item) + if $game_temp.mart_prices && $game_temp.mart_prices[item] + if $game_temp.mart_prices[item][0] > 0 + return $game_temp.mart_prices[item][0] + end + end + return GameData::Item.get(item).bp_price + end + + def getDisplayPrice(item, selling = false) + price = getPrice(item).to_s_formatted + return _INTL("{1} BP", price) + end + + def addItem(item) + return $bag.add(item) + end + + def removeItem(item) + return $bag.remove(item) + end +end + +#=============================================================================== +# Battle Point Shop +#=============================================================================== +class Window_BattlePointShop < Window_DrawableCommand + def initialize(stock, adapter, x, y, width, height, viewport = nil) + @stock = stock + @adapter = adapter + super(x, y, width, height, viewport) + @selarrow = AnimatedBitmap.new("Graphics/Pictures/martSel") + @baseColor = Color.new(88, 88, 80) + @shadowColor = Color.new(168, 184, 184) + self.windowskin = nil + end + + def itemCount + return @stock.length + 1 + end + + def item + return (self.index >= @stock.length) ? nil : @stock[self.index] + end + + def drawItem(index, count, rect) + textpos = [] + rect = drawCursor(index, rect) + ypos = rect.y + if index == count - 1 + textpos.push([_INTL("CANCEL"), rect.x, ypos + 2, false, self.baseColor, self.shadowColor]) + else + item = @stock[index] + itemname = @adapter.getDisplayName(item) + qty = @adapter.getDisplayPrice(item) + sizeQty = self.contents.text_size(qty).width + xQty = rect.x + rect.width - sizeQty - 2 - 16 + textpos.push([itemname, rect.x, ypos + 2, false, self.baseColor, self.shadowColor]) + textpos.push([qty, xQty, ypos + 2, false, self.baseColor, self.shadowColor]) + end + pbDrawTextPositions(self.contents, textpos) + end +end + +#=============================================================================== +# +#=============================================================================== +class BattlePointShop_Scene + def update + pbUpdateSpriteHash(@sprites) + @subscene&.pbUpdate + end + + def pbRefresh + if @subscene + @subscene.pbRefresh + else + itemwindow = @sprites["itemwindow"] + @sprites["icon"].item = itemwindow.item + @sprites["itemtextwindow"].text = + (itemwindow.item) ? @adapter.getDescription(itemwindow.item) : _INTL("Quit shopping.") + @sprites["qtywindow"].visible = !itemwindow.item.nil? + @sprites["qtywindow"].text = _INTL("In Bag:{1}", @adapter.getQuantity(itemwindow.item)) + @sprites["qtywindow"].y = Graphics.height - 102 - @sprites["qtywindow"].height + itemwindow.refresh + end + @sprites["battlepointwindow"].text = _INTL("Battle Points:\r\n{1}", @adapter.getBPString) + end + + def pbStartScene(stock, adapter) + # Scroll right before showing screen + pbScrollMap(6, 5, 5) + @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) + @viewport.z = 99999 + @stock = stock + @adapter = adapter + @sprites = {} + @sprites["background"] = IconSprite.new(0, 0, @viewport) + @sprites["background"].setBitmap("Graphics/Pictures/martScreen") + @sprites["icon"] = ItemIconSprite.new(36, Graphics.height - 50, nil, @viewport) + winAdapter = BattlePointShopAdapter.new() + @sprites["itemwindow"] = Window_BattlePointShop.new( + stock, winAdapter, Graphics.width - 316 - 16, 10, 330 + 16, Graphics.height - 124 + ) + @sprites["itemwindow"].viewport = @viewport + @sprites["itemwindow"].index = 0 + @sprites["itemwindow"].refresh + @sprites["itemtextwindow"] = Window_UnformattedTextPokemon.newWithSize( + "", 64, Graphics.height - 96 - 16, Graphics.width - 64, 128, @viewport + ) + pbPrepareWindow(@sprites["itemtextwindow"]) + @sprites["itemtextwindow"].baseColor = Color.new(248, 248, 248) + @sprites["itemtextwindow"].shadowColor = Color.new(0, 0, 0) + @sprites["itemtextwindow"].windowskin = nil + @sprites["helpwindow"] = Window_AdvancedTextPokemon.new("") + pbPrepareWindow(@sprites["helpwindow"]) + @sprites["helpwindow"].visible = false + @sprites["helpwindow"].viewport = @viewport + pbBottomLeftLines(@sprites["helpwindow"], 1) + @sprites["battlepointwindow"] = Window_AdvancedTextPokemon.new("") + pbPrepareWindow(@sprites["battlepointwindow"]) + @sprites["battlepointwindow"].setSkin("Graphics/Windowskins/goldskin") + @sprites["battlepointwindow"].visible = true + @sprites["battlepointwindow"].viewport = @viewport + @sprites["battlepointwindow"].x = 0 + @sprites["battlepointwindow"].y = 0 + @sprites["battlepointwindow"].width = 190 + @sprites["battlepointwindow"].height = 96 + @sprites["battlepointwindow"].baseColor = Color.new(88, 88, 80) + @sprites["battlepointwindow"].shadowColor = Color.new(168, 184, 184) + @sprites["qtywindow"] = Window_AdvancedTextPokemon.new("") + pbPrepareWindow(@sprites["qtywindow"]) + @sprites["qtywindow"].setSkin("Graphics/Windowskins/goldskin") + @sprites["qtywindow"].viewport = @viewport + @sprites["qtywindow"].width = 190 + @sprites["qtywindow"].height = 64 + @sprites["qtywindow"].baseColor = Color.new(88, 88, 80) + @sprites["qtywindow"].shadowColor = Color.new(168, 184, 184) + @sprites["qtywindow"].text = _INTL("In Bag:{1}", @adapter.getQuantity(@sprites["itemwindow"].item)) + @sprites["qtywindow"].y = Graphics.height - 102 - @sprites["qtywindow"].height + pbDeactivateWindows(@sprites) + pbRefresh + Graphics.frame_reset + end + + def pbEndScene + pbDisposeSpriteHash(@sprites) + @viewport.dispose + # Scroll left after showing screen + pbScrollMap(4, 5, 5) + end + + def pbPrepareWindow(window) + window.visible = true + window.letterbyletter = false + end + + def pbShowBattlePoints + pbRefresh + @sprites["battlepointwindow"].visible = true + end + + def pbHideBattlePoints + pbRefresh + @sprites["battlepointwindow"].visible = false + end + + def pbShowQuantity + pbRefresh + @sprites["qtywindow"].visible = true + end + + def pbHideQuantity + pbRefresh + @sprites["qtywindow"].visible = false + end + + def pbDisplay(msg, brief = false) + cw = @sprites["helpwindow"] + cw.letterbyletter = true + cw.text = msg + pbBottomLeftLines(cw, 2) + cw.visible = true + i = 0 + pbPlayDecisionSE + loop do + Graphics.update + Input.update + self.update + if !cw.busy? + return if brief + pbRefresh if i == 0 + end + if Input.trigger?(Input::USE) || Input.trigger?(Input::BACK) + cw.resume if cw.busy? + end + return if i >= Graphics.frame_rate * 3 / 2 + i += 1 if !cw.busy? + end + end + + def pbDisplayPaused(msg) + cw = @sprites["helpwindow"] + cw.letterbyletter = true + cw.text = msg + pbBottomLeftLines(cw, 2) + cw.visible = true + yielded = false + pbPlayDecisionSE + loop do + Graphics.update + Input.update + wasbusy = cw.busy? + self.update + if !cw.busy? && !yielded + yield if block_given? # For playing SE as soon as the message is all shown + yielded = true + end + pbRefresh if !cw.busy? && wasbusy + if Input.trigger?(Input::USE) || Input.trigger?(Input::BACK) + if cw.resume && !cw.busy? + @sprites["helpwindow"].visible = false + break + end + end + end + end + + def pbConfirm(msg) + dw = @sprites["helpwindow"] + dw.letterbyletter = true + dw.text = msg + dw.visible = true + pbBottomLeftLines(dw, 2) + commands = [_INTL("Yes"), _INTL("No")] + cw = Window_CommandPokemon.new(commands) + cw.viewport = @viewport + pbBottomRight(cw) + cw.y -= dw.height + cw.index = 0 + pbPlayDecisionSE + loop do + cw.visible = !dw.busy? + Graphics.update + Input.update + cw.update + self.update + if Input.trigger?(Input::BACK) && dw.resume && !dw.busy? + cw.dispose + @sprites["helpwindow"].visible = false + return false + end + if Input.trigger?(Input::USE) && dw.resume && !dw.busy? + cw.dispose + @sprites["helpwindow"].visible = false + return (cw.index == 0) + end + end + end + + def pbChooseNumber(helptext, item, maximum) + curnumber = 1 + ret = 0 + helpwindow = @sprites["helpwindow"] + itemprice = @adapter.getPrice(item) + itemprice /= 2 if !@buying + pbDisplay(helptext, true) + using(numwindow = Window_AdvancedTextPokemon.new("")) do # Showing number of items + pbPrepareWindow(numwindow) + numwindow.viewport = @viewport + numwindow.width = 224 + numwindow.height = 64 + numwindow.baseColor = Color.new(88, 88, 80) + numwindow.shadowColor = Color.new(168, 184, 184) + numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + pbBottomRight(numwindow) + numwindow.y -= helpwindow.height + loop do + Graphics.update + Input.update + numwindow.update + update + oldnumber = curnumber + if Input.repeat?(Input::LEFT) + curnumber -= 10 + curnumber = 1 if curnumber < 1 + if curnumber != oldnumber + numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + pbPlayCursorSE + end + elsif Input.repeat?(Input::RIGHT) + curnumber += 10 + curnumber = maximum if curnumber > maximum + if curnumber != oldnumber + numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + pbPlayCursorSE + end + elsif Input.repeat?(Input::UP) + curnumber += 1 + curnumber = 1 if curnumber > maximum + if curnumber != oldnumber + numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + pbPlayCursorSE + end + elsif Input.repeat?(Input::DOWN) + curnumber -= 1 + curnumber = maximum if curnumber < 1 + if curnumber != oldnumber + numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + pbPlayCursorSE + end + elsif Input.trigger?(Input::USE) + ret = curnumber + break + elsif Input.trigger?(Input::BACK) + pbPlayCancelSE + ret = 0 + break + end + end + end + helpwindow.visible = false + return ret + end + + def pbChooseItem + itemwindow = @sprites["itemwindow"] + @sprites["helpwindow"].visible = false + pbActivateWindow(@sprites, "itemwindow") { + pbRefresh + loop do + Graphics.update + Input.update + olditem = itemwindow.item + self.update + pbRefresh if itemwindow.item != olditem + if Input.trigger?(Input::BACK) + pbPlayCloseMenuSE + return nil + elsif Input.trigger?(Input::USE) + if itemwindow.index < @stock.length + pbRefresh + return @stock[itemwindow.index] + else + return nil + end + end + end + } + end +end + +#=============================================================================== +# +#=============================================================================== +class BattlePointShopScreen + def initialize(scene, stock) + @scene = scene + @stock = stock + @adapter = BattlePointShopAdapter.new + end + + def pbConfirm(msg) + return @scene.pbConfirm(msg) + end + + def pbDisplay(msg) + return @scene.pbDisplay(msg) + end + + def pbDisplayPaused(msg, &block) + return @scene.pbDisplayPaused(msg, &block) + end + + def pbBuyScreen + @scene.pbStartScene(@stock, @adapter) + item = nil + loop do + item = @scene.pbChooseItem + break if !item + quantity = 0 + itemname = @adapter.getDisplayName(item) + itemnameplural = @adapter.getDisplayNamePlural(item) + price = @adapter.getPrice(item) + if @adapter.getBP < price + pbDisplayPaused(_INTL("You don't have enough BP.")) + next + end + if GameData::Item.get(item).is_important? + next if !pbConfirm(_INTL("You would like the {1}?\nThat will be {2} BP.", + itemname, price.to_s_formatted)) + quantity = 1 + else + maxafford = (price <= 0) ? Settings::BAG_MAX_PER_SLOT : @adapter.getBP / price + maxafford = Settings::BAG_MAX_PER_SLOT if maxafford > Settings::BAG_MAX_PER_SLOT + quantity = @scene.pbChooseNumber( + _INTL("How many {1} would you like?", itemnameplural), item, maxafford + ) + next if quantity == 0 + price *= quantity + if quantity > 1 + next if !pbConfirm(_INTL("You would like {1} {2}?\nThey'll be {3} BP.", + quantity, itemnameplural, price.to_s_formatted)) + elsif quantity > 0 + next if !pbConfirm(_INTL("So you want {1} {2}?\nIt'll be {3} BP.", + quantity, itemname, price.to_s_formatted)) + end + end + if @adapter.getBP < price + pbDisplayPaused(_INTL("I'm sorry, you don't have enough BP.")) + next + end + added = 0 + quantity.times do + break if !@adapter.addItem(item) + added += 1 + end + if added == quantity + $stats.battle_points_spent += price + #Add bpshop_items_bought to $stats? + #$stats.bpshop_items_bought += quantity + @adapter.setBP(@adapter.getBP - price) + @stock.delete_if { |item| GameData::Item.get(item).is_important? && $bag.has?(item) } + pbDisplayPaused(_INTL("Here you are! Thank you!")) { pbSEPlay("Mart buy item") } + else + added.times do + if !@adapter.removeItem(item) + raise _INTL("Failed to delete stored items") + end + end + pbDisplayPaused(_INTL("You have no room in your Bag.")) + end + end + @scene.pbEndScene + end +end + +#=============================================================================== +# +#=============================================================================== +def pbBattlePointShop(stock, speech = nil) + stock.delete_if { |item| GameData::Item.get(item).is_important? && $bag.has?(item) } + if speech.nil? + pbMessage(_INTL("Welcome to the Exchange Service Corner!")) + pbMessage(_INTL("We can exchange your BP for fabulous items.")) + else + pbMessage(speech) + end + scene = BattlePointShop_Scene.new + screen = BattlePointShopScreen.new(scene, stock) + screen.pbBuyScreen + pbMessage(_INTL("Thank you for visiting.")) + pbMessage(_INTL("Please visit us again when you have saved up more BP.")) + $game_temp.clear_mart_prices +end diff --git a/Data/Scripts/016_UI/021_UI_MoveRelearner.rb b/Data/Scripts/016_UI/022_UI_MoveRelearner.rb similarity index 100% rename from Data/Scripts/016_UI/021_UI_MoveRelearner.rb rename to Data/Scripts/016_UI/022_UI_MoveRelearner.rb diff --git a/Data/Scripts/016_UI/022_UI_PurifyChamber.rb b/Data/Scripts/016_UI/023_UI_PurifyChamber.rb similarity index 100% rename from Data/Scripts/016_UI/022_UI_PurifyChamber.rb rename to Data/Scripts/016_UI/023_UI_PurifyChamber.rb diff --git a/Data/Scripts/016_UI/023_UI_MysteryGift.rb b/Data/Scripts/016_UI/024_UI_MysteryGift.rb similarity index 100% rename from Data/Scripts/016_UI/023_UI_MysteryGift.rb rename to Data/Scripts/016_UI/024_UI_MysteryGift.rb diff --git a/Data/Scripts/016_UI/024_UI_TextEntry.rb b/Data/Scripts/016_UI/025_UI_TextEntry.rb similarity index 100% rename from Data/Scripts/016_UI/024_UI_TextEntry.rb rename to Data/Scripts/016_UI/025_UI_TextEntry.rb diff --git a/PBS/Gen 5/items.txt b/PBS/Gen 5/items.txt index 6c4cebd37..0ed571afb 100644 --- a/PBS/Gen 5/items.txt +++ b/PBS/Gen 5/items.txt @@ -102,6 +102,7 @@ Name = Fire Stone NamePlural = Fire Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is colored orange. @@ -111,6 +112,7 @@ Name = Thunder Stone NamePlural = Thunder Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a thunderbolt pattern. @@ -120,6 +122,7 @@ Name = Water Stone NamePlural = Water Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is a clear, light blue. @@ -129,6 +132,7 @@ Name = Leaf Stone NamePlural = Leaf Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a leaf pattern. @@ -138,6 +142,7 @@ Name = Moon Stone NamePlural = Moon Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as black as the night sky. @@ -147,6 +152,7 @@ Name = Sun Stone NamePlural = Sun Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as red as the sun. @@ -156,6 +162,7 @@ Name = Dusk Stone NamePlural = Dusk Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as dark as dark can be. @@ -165,6 +172,7 @@ Name = Dawn Stone NamePlural = Dawn Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It sparkles like eyes. @@ -174,6 +182,7 @@ Name = Shiny Stone NamePlural = Shiny Stones Pocket = 1 Price = 2100 +BPPrice = 3 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It shines with a dazzling light. @@ -542,6 +551,7 @@ Name = Air Balloon NamePlural = Air Balloons Pocket = 1 Price = 200 +BPPrice = 12 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder will float in the air until hit. Once hit, this item will burst. #------------------------------- @@ -550,6 +560,7 @@ Name = Bright Powder NamePlural = Bright Powders Pocket = 1 Price = 10 +BPPrice = 12 Flags = Fling_10 Description = An item to be held by a Pokémon. It casts a tricky glare that lowers the opponent's accuracy. #------------------------------- @@ -558,6 +569,7 @@ Name = Eviolite NamePlural = Eviolites Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_40 Description = A mysterious evolutionary lump. When held, it raises the Defense and Sp. Def if the holder can still evolve. #------------------------------- @@ -566,6 +578,7 @@ Name = Float Stone NamePlural = Float Stones Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_30 Description = A very light stone. It reduces the weight of a Pokémon when held. #------------------------------- @@ -574,6 +587,7 @@ Name = Destiny Knot NamePlural = Destiny Knots Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_10 Description = A long, thin, bright-red string to be held by a Pokémon. If the holder becomes infatuated, so does the foe. #------------------------------- @@ -582,6 +596,7 @@ Name = Rocky Helmet NamePlural = Rocky Helmets Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_60 Description = If the holder of this item takes damage, the attacker will also be damaged upon contact. #------------------------------- @@ -590,6 +605,7 @@ Name = Eject Button NamePlural = Eject Buttons Pocket = 1 Price = 200 +BPPrice = 16 Flags = Fling_30 Description = If the holder is hit by an attack, it will switch with another Pokémon in your party. #------------------------------- @@ -598,6 +614,7 @@ Name = Red Card NamePlural = Red Cards Pocket = 1 Price = 200 +BPPrice = 16 Flags = Fling_10 Description = A card with a mysterious power. When the holder is struck by a foe, the attacker is removed from battle. #------------------------------- @@ -622,6 +639,7 @@ Name = Lucky Egg NamePlural = Lucky Eggs Pocket = 1 Price = 200 +BPPrice = 77 Flags = Fling_30 Description = An item to be held by a Pokémon. It is an egg filled with happiness that earns extra Exp. Points in battle. #------------------------------- @@ -646,6 +664,7 @@ Name = Soothe Bell NamePlural = Soothe Bells Pocket = 1 Price = 100 +BPPrice = 8 Flags = Fling_10 Description = An item to be held by a Pokémon. The comforting chime of this bell calms the holder, making it friendly. #------------------------------- @@ -662,6 +681,7 @@ Name = Choice Band NamePlural = Choice Bands Pocket = 1 Price = 100 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. This headband ups Attack, but allows the use of only one move. #------------------------------- @@ -670,6 +690,7 @@ Name = Choice Specs NamePlural = Choice Specs Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. These curious glasses boost Sp. Atk but allows the use of only one move. #------------------------------- @@ -678,6 +699,7 @@ Name = Choice Scarf NamePlural = Choice Scarves Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. This scarf boosts Speed but allows the use of only one move. #------------------------------- @@ -686,6 +708,7 @@ Name = Heat Rock NamePlural = Heat Rocks Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Sunny Day used by the holder. #------------------------------- @@ -694,6 +717,7 @@ Name = Damp Rock NamePlural = Damp Rocks Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Rain Dance used by the holder. #------------------------------- @@ -702,6 +726,7 @@ Name = Smooth Rock NamePlural = Smooth Rocks Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_10 Description = A Pokémon held item that extends the duration of the move Sandstorm used by the holder. #------------------------------- @@ -710,6 +735,7 @@ Name = Icy Rock NamePlural = Icy Rocks Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_40 Description = A Pokémon held item that extends the duration of the move Hail used by the holder. #------------------------------- @@ -718,6 +744,7 @@ Name = Light Clay NamePlural = Light Clays Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_30 Description = An item to be held by a Pokémon. Protective moves like Light Screen and Reflect will be effective longer. #------------------------------- @@ -726,6 +753,7 @@ Name = Grip Claw NamePlural = Grip Claws Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_90 Description = A Pokémon held item that extends the duration of multiturn attacks like Bind and Wrap. #------------------------------- @@ -734,6 +762,7 @@ Name = Binding Band NamePlural = Binding Bands Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_30 Description = A band that increases the power of binding moves when held. #------------------------------- @@ -742,6 +771,7 @@ Name = Big Root NamePlural = Big Roots Pocket = 1 Price = 200 +BPPrice = 16 Flags = Fling_10 Description = A Pokémon held item that boosts the power of HP-stealing moves to let the holder recover more HP. #------------------------------- @@ -750,6 +780,7 @@ Name = Black Sludge NamePlural = Black Sludges Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_30 Description = A held item that gradually restores the HP of Poison-type Pokémon. It inflicts damage on all other types. #------------------------------- @@ -758,6 +789,7 @@ Name = Leftovers NamePlural = Leftovers Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder's HP is gradually restored during battle. #------------------------------- @@ -766,6 +798,7 @@ Name = Shell Bell NamePlural = Shell Bells Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_30 Description = An item to be held by a Pokémon. The holder's HP is restored a little every time it inflicts damage. #------------------------------- @@ -774,6 +807,7 @@ Name = Mental Herb NamePlural = Mental Herbs Pocket = 1 Price = 100 +BPPrice = 16 Flags = Fling_10 Description = An item to be held by a Pokémon. It snaps the holder out of infatuation. It can be used only once. #------------------------------- @@ -782,6 +816,7 @@ Name = White Herb NamePlural = White Herbs Pocket = 1 Price = 100 +BPPrice = 16 Flags = Fling_10 Description = An item to be held by a Pokémon. It restores any lowered stat in battle. It can be used only once. #------------------------------- @@ -790,6 +825,7 @@ Name = Power Herb NamePlural = Power Herbs Pocket = 1 Price = 100 +BPPrice = 16 Flags = Fling_10 Description = A single-use item to be held by a Pokémon. It allows the immediate use of a move that charges up first. #------------------------------- @@ -798,6 +834,7 @@ Name = Absorb Bulb NamePlural = Absorb Bulbs Pocket = 1 Price = 200 +BPPrice = 16 Flags = Fling_30 Description = A consumable bulb. If the holder is hit by a Water-type move, its Sp. Atk will rise. #------------------------------- @@ -806,6 +843,7 @@ Name = Cell Battery NamePlural = Cell Batteries Pocket = 1 Price = 200 +BPPrice = 16 Flags = Fling_30 Description = A consumable battery. If the holder is hit by an Electric-type move, its Attack will rise. #------------------------------- @@ -814,6 +852,7 @@ Name = Life Orb NamePlural = Life Orbs Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts the power of moves, but at the cost of some HP on each hit. #------------------------------- @@ -822,6 +861,7 @@ Name = Expert Belt NamePlural = Expert Belts Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a well-worn belt that slightly boosts the power of supereffective moves. #------------------------------- @@ -830,6 +870,7 @@ Name = Metronome NamePlural = Metronomes Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_30 Description = A Pokémon held item that boosts a move used consecutively. Its effect is reset if another move is used. #------------------------------- @@ -838,6 +879,7 @@ Name = Muscle Band NamePlural = Muscle Bands Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a headband that slightly boosts the power of physical moves. #------------------------------- @@ -846,6 +888,7 @@ Name = Wise Glasses NamePlural = Wise Glasses Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a thick pair of glasses that slightly boosts the power of special moves. #------------------------------- @@ -854,6 +897,7 @@ Name = Razor Claw NamePlural = Razor Claws Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_80 Description = An item to be held by a Pokémon. It is a sharply hooked claw that ups the holder's critical-hit ratio. #------------------------------- @@ -862,6 +906,7 @@ Name = Scope Lens NamePlural = Scope Lenses Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a lens that boosts the holder's critical-hit ratio. #------------------------------- @@ -870,6 +915,7 @@ Name = Wide Lens NamePlural = Wide Lenses Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a magnifying lens that slightly boosts the accuracy of moves. #------------------------------- @@ -878,6 +924,7 @@ Name = Zoom Lens NamePlural = Zoom Lenses Pocket = 1 Price = 200 +BPPrice = 12 Flags = Fling_10 Description = An item to be held by a Pokémon. If the holder moves after its target, its accuracy will be boosted. #------------------------------- @@ -886,6 +933,7 @@ Name = King's Rock NamePlural = King's Rocks Pocket = 1 Price = 100 +BPPrice = 8 Flags = Fling_30 Description = An item to be held by a Pokémon. When the holder inflicts damage, the target may flinch. #------------------------------- @@ -894,6 +942,7 @@ Name = Razor Fang NamePlural = Razor Fangs Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_30 Description = An item to be held by a Pokémon. It may make foes and allies flinch when the holder inflicts damage. #------------------------------- @@ -902,6 +951,7 @@ Name = Lagging Tail NamePlural = Lagging Tails Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. It is tremendously heavy and makes the holder move slower than usual. #------------------------------- @@ -910,6 +960,7 @@ Name = Quick Claw NamePlural = Quick Claws Pocket = 1 Price = 100 +BPPrice = 24 Flags = Fling_80 Description = An item to be held by a Pokémon. A light, sharp claw that lets the bearer move first occasionally. #------------------------------- @@ -918,6 +969,7 @@ Name = Focus Band NamePlural = Focus Bands Pocket = 1 Price = 200 +BPPrice = 12 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder may endure a potential KO attack, leaving it with just 1 HP. #------------------------------- @@ -926,6 +978,7 @@ Name = Focus Sash NamePlural = Focus Sashes Pocket = 1 Price = 200 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. If it has full HP, the holder will endure one potential KO attack, leaving 1 HP. #------------------------------- @@ -934,6 +987,7 @@ Name = Flame Orb NamePlural = Flame Orbs Pocket = 1 Price = 100 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that inflicts a burn on the holder in battle. #------------------------------- @@ -942,6 +996,7 @@ Name = Toxic Orb NamePlural = Toxic Orbs Pocket = 1 Price = 100 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that badly poisons the holder in battle. #------------------------------- @@ -950,6 +1005,7 @@ Name = Sticky Barb NamePlural = Sticky Barbs Pocket = 1 Price = 200 +BPPrice = 16 Flags = Fling_80 Description = A held item that damages the holder on every turn. It may latch on to Pokémon that touch the holder. #------------------------------- @@ -958,6 +1014,7 @@ Name = Iron Ball NamePlural = Iron Balls Pocket = 1 Price = 200 +BPPrice = 12 Flags = Fling_130 Description = A Pokémon held item that cuts Speed. It makes Flying-type and levitating holders susceptible to Ground moves. #------------------------------- @@ -966,6 +1023,7 @@ Name = Ring Target NamePlural = Ring Targets Pocket = 1 Price = 200 +BPPrice = 12 Flags = Fling_10 Description = Moves that would otherwise have no effect will land on the Pokémon that holds it. #------------------------------- @@ -974,6 +1032,7 @@ Name = Macho Brace NamePlural = Macho Braces Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_60 Description = An item to be held by a Pokémon. It is a stiff, heavy brace that promotes strong growth but lowers Speed. #------------------------------- @@ -982,6 +1041,7 @@ Name = Power Weight NamePlural = Power Weights Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes HP gain on leveling, but reduces the Speed stat. #------------------------------- @@ -990,6 +1050,7 @@ Name = Power Bracer NamePlural = Power Bracers Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Attack gain on leveling, but reduces the Speed stat. #------------------------------- @@ -998,6 +1059,7 @@ Name = Power Belt NamePlural = Power Belts Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Defense gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1006,6 +1068,7 @@ Name = Power Lens NamePlural = Power Lenses Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Atk gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1014,6 +1077,7 @@ Name = Power Band NamePlural = Power Bands Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Def gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1022,6 +1086,7 @@ Name = Power Anklet NamePlural = Power Anklets Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Speed gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1510,6 +1575,7 @@ Name = Lucky Punch NamePlural = Lucky Punches Pocket = 1 Price = 10 +BPPrice = 7 Flags = Fling_40 Description = An item to be held by Chansey. It is a pair of gloves that boosts Chansey's critical-hit ratio. #------------------------------- @@ -1558,6 +1624,7 @@ Name = Deep Sea Tooth NamePlural = Deep Sea Teeth Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_90 Description = An item to be held by Clamperl. A fang that gleams a sharp silver, it raises the Sp. Atk stat. #------------------------------- @@ -1566,6 +1633,7 @@ Name = Deep Sea Scale NamePlural = Deep Sea Scales Pocket = 1 Price = 200 +BPPrice = 8 Flags = Fling_30 Description = An item to be held by Clamperl. A scale that shines a faint pink, it raises the Sp. Def stat. #------------------------------- @@ -1630,6 +1698,7 @@ Name = Everstone NamePlural = Everstones Pocket = 1 Price = 200 +BPPrice = 3 Flags = Fling_30 Description = An item to be held by a Pokémon. The Pokémon holding this peculiar stone is prevented from evolving. #------------------------------- @@ -1638,6 +1707,7 @@ Name = Dragon Scale NamePlural = Dragon Scales Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_30 Description = A thick and tough scale. Dragon-type Pokémon may be holding this item when caught. #------------------------------- @@ -1646,6 +1716,7 @@ Name = Up-Grade NamePlural = Up-Grades Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_30 Description = A transparent device filled with all sorts of data. It was produced by Silph Co. #------------------------------- @@ -1654,6 +1725,7 @@ Name = Dubious Disc NamePlural = Dubious Discs Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_50 Description = A transparent device overflowing with dubious data. Its producer is unknown. #------------------------------- @@ -1662,6 +1734,7 @@ Name = Protector NamePlural = Protectors Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_80 Description = A protective item of some sort. It is extremely stiff and heavy. It is loved by a certain Pokémon. #------------------------------- @@ -1670,6 +1743,7 @@ Name = Electirizer NamePlural = Electirizers Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_80 Description = A box packed with a tremendous amount of electric energy. It is loved by a certain Pokémon. #------------------------------- @@ -1678,6 +1752,7 @@ Name = Magmarizer NamePlural = Magmarizers Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_80 Description = A box packed with a tremendous amount of magma energy. It is loved by a certain Pokémon. #------------------------------- @@ -1686,6 +1761,7 @@ Name = Reaper Cloth NamePlural = Reaper Cloths Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_10 Description = A cloth imbued with horrifyingly strong spiritual energy. It is loved by a certain Pokémon. #------------------------------- @@ -1694,6 +1770,7 @@ Name = Prism Scale NamePlural = Prism Scales Pocket = 1 Price = 500 +BPPrice = 8 Flags = Fling_30 Description = A mysterious scale that evolves certain Pokémon. It shines in rainbow colors. #------------------------------- @@ -1702,6 +1779,7 @@ Name = Oval Stone NamePlural = Oval Stones Pocket = 1 Price = 2100 +BPPrice = 8 Flags = Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is shaped like an egg. #------------------------------- @@ -1780,6 +1858,7 @@ Name = Max Potion NamePlural = Max Potions Pocket = 2 Price = 2500 +BPPrice = 2 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -1909,6 +1988,7 @@ Name = Max Revive NamePlural = Max Revives Pocket = 2 Price = 4000 +BPPrice = 24 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -2029,6 +2109,7 @@ Name = Ether NamePlural = Ethers Pocket = 2 Price = 1200 +BPPrice = 4 FieldUse = OnPokemon BattleUse = OnMove Flags = Fling_30 @@ -2069,6 +2150,7 @@ Name = PP Up NamePlural = PP Ups Pocket = 2 Price = 9800 +BPPrice = 16 FieldUse = OnPokemon Flags = Fling_30 Description = It slightly raises the maximum PP of a selected move that has been learned by the target Pokémon. @@ -2195,6 +2277,7 @@ Name = Rare Candy NamePlural = Rare Candies Pocket = 2 Price = 4800 +BPPrice = 24 FieldUse = OnPokemon Flags = Fling_30 Description = A candy that is packed with energy. It raises the level of a single Pokémon by one. @@ -2420,6 +2503,7 @@ Name = TM01 NamePlural = TM01s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = HONECLAWS Description = The user sharpens its claws to boost its Attack stat and accuracy. @@ -2429,6 +2513,7 @@ Name = TM02 NamePlural = TM02s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = DRAGONCLAW Description = The user slashes the target with huge, sharp claws. @@ -2438,6 +2523,7 @@ Name = TM03 NamePlural = TM03s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = PSYSHOCK Description = The user materializes an odd psychic wave to attack the target. This attack does physical damage. @@ -2447,6 +2533,7 @@ Name = TM04 NamePlural = TM04s Pocket = 4 Price = 1500 +BPPrice = 6 FieldUse = TM Move = CALMMIND Description = The user quietly focuses its mind and calms its spirit to raise its Sp. Atk and Sp. Def stats. @@ -2456,6 +2543,7 @@ Name = TM05 NamePlural = TM05s Pocket = 4 Price = 1000 +BPPrice = 6 FieldUse = TM Move = ROAR Description = The target is scared off and replaced by another Pokémon in its party. In the wild, the battle ends. @@ -2465,6 +2553,7 @@ Name = TM06 NamePlural = TM06s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = TOXIC Description = A move that leaves the target badly poisoned. Its poison damage worsens every turn. @@ -2474,6 +2563,7 @@ Name = TM07 NamePlural = TM07s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = HAIL Description = Summons a hailstorm that lasts for five turns. The hailstorm damages all types except Ice. @@ -2483,6 +2573,7 @@ Name = TM08 NamePlural = TM08s Pocket = 4 Price = 1500 +BPPrice = 6 FieldUse = TM Move = BULKUP Description = The user tenses its muscles to bulk up its body, boosting both its Attack and Defense stats. @@ -2492,6 +2583,7 @@ Name = TM09 NamePlural = TM09s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = VENOSHOCK Description = The user drenches the target in a special poisonous liquid. Its power is doubled if the target is poisoned. @@ -2501,6 +2593,7 @@ Name = TM10 NamePlural = TM10s Pocket = 4 Price = 2000 +BPPrice = 18 FieldUse = TM Move = HIDDENPOWER Description = A unique attack that varies in type and intensity depending on the Pokémon using it. @@ -2510,6 +2603,7 @@ Name = TM11 NamePlural = TM11s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = SUNNYDAY Description = The user intensifies the sun for five turns, powering up Fire-type moves. @@ -2519,6 +2613,7 @@ Name = TM12 NamePlural = TM12s Pocket = 4 Price = 1500 +BPPrice = 6 FieldUse = TM Move = TAUNT Description = The target is taunted into a rage that allows it to use only attack moves for three turns. @@ -2528,6 +2623,7 @@ Name = TM13 NamePlural = TM13s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = ICEBEAM Description = The target is struck with an icy-cold beam of energy. It may also freeze the target solid. @@ -2537,6 +2633,7 @@ Name = TM14 NamePlural = TM14s Pocket = 4 Price = 5500 +BPPrice = 6 FieldUse = TM Move = BLIZZARD Description = A howling blizzard is summoned to strike the opposing team. It may also freeze them solid. @@ -2546,6 +2643,7 @@ Name = TM15 NamePlural = TM15s Pocket = 4 Price = 7500 +BPPrice = 6 FieldUse = TM Move = HYPERBEAM Description = The target is attacked with a powerful beam. The user must rest on the next turn to regain its energy. @@ -2555,6 +2653,7 @@ Name = TM16 NamePlural = TM16s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = LIGHTSCREEN Description = A wondrous wall of light is put up to suppress damage from special attacks for five turns. @@ -2564,6 +2663,7 @@ Name = TM17 NamePlural = TM17s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = PROTECT Description = It enables the user to evade all attacks. Its chance of failing rises if it is used in succession. @@ -2573,6 +2673,7 @@ Name = TM18 NamePlural = TM18s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = RAINDANCE Description = The user summons a heavy rain that falls for five turns, powering up Water-type moves. @@ -2582,6 +2683,7 @@ Name = TM19 NamePlural = TM19s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = TELEKINESIS Description = The user makes the target float with its psychic power. The target is easier to hit for three turns. @@ -2591,6 +2693,7 @@ Name = TM20 NamePlural = TM20s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = SAFEGUARD Description = The user creates a protective field that prevents status problems for five turns. @@ -2600,6 +2703,7 @@ Name = TM21 NamePlural = TM21s Pocket = 4 Price = 1000 +BPPrice = 6 FieldUse = TM Move = FRUSTRATION Description = A full-power attack that grows more powerful the less the user likes its Trainer. @@ -2609,6 +2713,7 @@ Name = TM22 NamePlural = TM22s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = SOLARBEAM Description = A two-turn attack. The user gathers light, then blasts a bundled beam on the second turn. @@ -2618,6 +2723,7 @@ Name = TM23 NamePlural = TM23s Pocket = 4 Price = 3000 +BPPrice = 18 FieldUse = TM Move = SMACKDOWN Description = The user throws a stone or similar projectile to attack a foe. A flying Pokémon will fall to the ground if hit. @@ -2627,6 +2733,7 @@ Name = TM24 NamePlural = TM24s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = THUNDERBOLT Description = A strong electric blast is loosed at the target. It may also leave the target with paralysis. @@ -2636,6 +2743,7 @@ Name = TM25 NamePlural = TM25s Pocket = 4 Price = 5500 +BPPrice = 6 FieldUse = TM Move = THUNDER Description = A wicked thunderbolt is dropped on the target to inflict damage. It may also leave the target with paralysis. @@ -2645,6 +2753,7 @@ Name = TM26 NamePlural = TM26s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = EARTHQUAKE Description = The user sets off an earthquake that strikes every Pokémon around it. @@ -2654,6 +2763,7 @@ Name = TM27 NamePlural = TM27s Pocket = 4 Price = 1000 +BPPrice = 6 FieldUse = TM Move = RETURN Description = A full-power attack that grows more powerful the more the user likes its Trainer. @@ -2663,6 +2773,7 @@ Name = TM28 NamePlural = TM28s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = DIG Description = The user burrows, then attacks on the second turn. It can also be used to exit dungeons. @@ -2672,6 +2783,7 @@ Name = TM29 NamePlural = TM29s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = PSYCHIC Description = The target is hit by a strong telekinetic force. It may also reduce the target's Sp. Def stat. @@ -2681,6 +2793,7 @@ Name = TM30 NamePlural = TM30s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = SHADOWBALL Description = The user hurls a shadowy blob at the target. It may also lower the target's Sp. Def stat. @@ -2690,6 +2803,7 @@ Name = TM31 NamePlural = TM31s Pocket = 4 Price = 3000 +BPPrice = 12 FieldUse = TM Move = BRICKBREAK Description = The user attacks with tough fists, etc. It can also break any barrier such as Light Screen and Reflect. @@ -2699,6 +2813,7 @@ Name = TM32 NamePlural = TM32s Pocket = 4 Price = 1000 +BPPrice = 6 FieldUse = TM Move = DOUBLETEAM Description = By moving rapidly, the user makes illusory copies of itself to raise its evasiveness. @@ -2708,6 +2823,7 @@ Name = TM33 NamePlural = TM33s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = REFLECT Description = A wondrous wall of light is put up to suppress damage from physical attacks for five turns. @@ -2717,6 +2833,7 @@ Name = TM34 NamePlural = TM34s Pocket = 4 Price = 3000 +BPPrice = 24 FieldUse = TM Move = SLUDGEWAVE Description = It swamps the area around the user with a giant sludge wave. It may also poison those hit. @@ -2726,6 +2843,7 @@ Name = TM35 NamePlural = TM35s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = FLAMETHROWER Description = The target is scorched with an intense blast of fire. It may also leave the target with a burn. @@ -2735,6 +2853,7 @@ Name = TM36 NamePlural = TM36s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = SLUDGEBOMB Description = Unsanitary sludge is hurled at the target. It may also poison the target. @@ -2744,6 +2863,7 @@ Name = TM37 NamePlural = TM37s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = SANDSTORM Description = A five-turn sandstorm is summoned to hurt all combatants except the Rock, Ground, and Steel types. @@ -2753,6 +2873,7 @@ Name = TM38 NamePlural = TM38s Pocket = 4 Price = 5500 +BPPrice = 6 FieldUse = TM Move = FIREBLAST Description = The foe is attacked with an intense blast of all-consuming fire. It may also leave the target with a burn. @@ -2762,6 +2883,7 @@ Name = TM39 NamePlural = TM39s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = ROCKTOMB Description = Boulders are hurled at the target. It also lowers the target's Speed by preventing its movement. @@ -2771,6 +2893,7 @@ Name = TM40 NamePlural = TM40s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = AERIALACE Description = The user confounds the target with speed, then slashes. The attack lands without fail. @@ -2780,6 +2903,7 @@ Name = TM41 NamePlural = TM41s Pocket = 4 Price = 1500 +BPPrice = 6 FieldUse = TM Move = TORMENT Description = The user torments and enrages the target, making it incapable of using the same move twice in a row. @@ -2789,6 +2913,7 @@ Name = TM42 NamePlural = TM42s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = FACADE Description = An attack move that doubles its power if the user is poisoned, paralyzed, or has a burn. @@ -2798,6 +2923,7 @@ Name = TM43 NamePlural = TM43s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = FLAMECHARGE Description = The user cloaks itself with flame and attacks. Building up more power, it raises the user's Speed stat. @@ -2807,6 +2933,7 @@ Name = TM44 NamePlural = TM44s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = REST Description = The user goes to sleep for two turns. It fully restores the user's HP and heals any status problem. @@ -2816,6 +2943,7 @@ Name = TM45 NamePlural = TM45s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = ATTRACT Description = If it is the opposite gender of the user, the target becomes infatuated and less likely to attack. @@ -2825,6 +2953,7 @@ Name = TM46 NamePlural = TM46s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = THIEF Description = The user attacks and steals the target's held item simultaneously. It can't steal if the user holds an item. @@ -2834,6 +2963,7 @@ Name = TM47 NamePlural = TM47s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = LOWSWEEP Description = The user attacks the target's legs swiftly, reducing the target's Speed stat. @@ -2843,6 +2973,7 @@ Name = TM48 NamePlural = TM48s Pocket = 4 Price = 3000 +BPPrice = 18 FieldUse = TM Move = ROUND Description = The user attacks the target with a song. Others can join in the Round to increase the power of the attack. @@ -2852,6 +2983,7 @@ Name = TM49 NamePlural = TM49s Pocket = 4 Price = 1500 +BPPrice = 6 FieldUse = TM Move = ECHOEDVOICE Description = The user attacks the target with an echoing voice. If this move is used every turn, it does greater damage. @@ -2861,6 +2993,7 @@ Name = TM50 NamePlural = TM50s Pocket = 4 Price = 5500 +BPPrice = 6 FieldUse = TM Move = OVERHEAT Description = The user attacks the target at full power. The attack's recoil sharply reduces the user's Sp. Atk stat. @@ -2870,6 +3003,7 @@ Name = TM51 NamePlural = TM51s Pocket = 4 Price = 1000 +BPPrice = 24 FieldUse = TM Move = ALLYSWITCH Description = The user teleports using a strange power and switches its place with one of its allies. @@ -2879,6 +3013,7 @@ Name = TM52 NamePlural = TM52s Pocket = 4 Price = 5500 +BPPrice = 6 FieldUse = TM Move = FOCUSBLAST Description = The user heightens its mental focus and unleashes its power. It may also lower the target's Sp. Def. @@ -2888,6 +3023,7 @@ Name = TM53 NamePlural = TM53s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = ENERGYBALL Description = The user draws power from nature and fires it at the target. It may also lower the target's Sp. Def. @@ -2897,6 +3033,7 @@ Name = TM54 NamePlural = TM54s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = FALSESWIPE Description = A restrained attack that prevents the target from fainting. The target is left with at least 1 HP. @@ -2906,6 +3043,7 @@ Name = TM55 NamePlural = TM55s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = SCALD Description = The user shoots boiling hot water at its target. It may also leave the target with a burn. @@ -2915,6 +3053,7 @@ Name = TM56 NamePlural = TM56s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = FLING Description = The user flings its held item at the target as an attack. Its power and effects depend on the item. @@ -2924,6 +3063,7 @@ Name = TM57 NamePlural = TM57s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = CHARGEBEAM Description = The user fires a concentrated bundle of electricity. It may also raise the user's Sp. Atk stat. @@ -2933,6 +3073,7 @@ Name = TM58 NamePlural = TM58s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = SKYDROP Description = The user hurls the foe into the sky, then drops it on the next turn. The foe cannot attack while in the sky. @@ -2942,6 +3083,7 @@ Name = TM59 NamePlural = TM59s Pocket = 4 Price = 1500 +BPPrice = 6 FieldUse = TM Move = INCINERATE Description = The user attacks the target with fire. If the target is holding a Berry, it becomes burnt up and unusable. @@ -2951,6 +3093,7 @@ Name = TM60 NamePlural = TM60s Pocket = 4 Price = 3000 +BPPrice = 24 FieldUse = TM Move = QUASH Description = The user suppresses the target and makes its move go last. @@ -2960,6 +3103,7 @@ Name = TM61 NamePlural = TM61s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = WILLOWISP Description = The user shoots a sinister, bluish-white flame at the target to inflict a burn. @@ -2969,6 +3113,7 @@ Name = TM62 NamePlural = TM62s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = ACROBATICS Description = The user nimbly strikes the target. If the user is not holding an item, this attack inflicts massive damage. @@ -2978,6 +3123,7 @@ Name = TM63 NamePlural = TM63s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = EMBARGO Description = It prevents the target from using its held item. Its Trainer is also prevented from using items on it. @@ -2987,6 +3133,7 @@ Name = TM64 NamePlural = TM64s Pocket = 4 Price = 7500 +BPPrice = 24 FieldUse = TM Move = EXPLOSION Description = The user explodes to inflict damage on those around it. The user faints upon using this move. @@ -2996,6 +3143,7 @@ Name = TM65 NamePlural = TM65s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = SHADOWCLAW Description = The user slashes with a sharp claw made from shadows. It has a high critical-hit ratio. @@ -3005,6 +3153,7 @@ Name = TM66 NamePlural = TM66s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = PAYBACK Description = The user stores power, then attacks. If the user can use this attack after the foe, its power is doubled. @@ -3014,6 +3163,7 @@ Name = TM67 NamePlural = TM67s Pocket = 4 Price = 1000 +BPPrice = 6 FieldUse = TM Move = RETALIATE Description = The user gets revenge for a fainted ally. If an ally fainted in the last turn, this move's power is increased. @@ -3023,6 +3173,7 @@ Name = TM68 NamePlural = TM68s Pocket = 4 Price = 7500 +BPPrice = 6 FieldUse = TM Move = GIGAIMPACT Description = The user charges at the target using every bit of its power. The user must rest on the next turn. @@ -3032,6 +3183,7 @@ Name = TM69 NamePlural = TM69s Pocket = 4 Price = 1500 +BPPrice = 6 FieldUse = TM Move = ROCKPOLISH Description = The user polishes its body to reduce drag. It sharply raises the Speed stat. @@ -3041,6 +3193,7 @@ Name = TM70 NamePlural = TM70s Pocket = 4 Price = 1000 +BPPrice = 6 FieldUse = TM Move = FLASH Description = The user flashes a bright light that cuts the target's accuracy. It can also be used to illuminate caves. @@ -3050,6 +3203,7 @@ Name = TM71 NamePlural = TM71s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = STONEEDGE Description = The user stabs the foe with sharpened stones from below. It has a high critical-hit ratio. @@ -3059,6 +3213,7 @@ Name = TM72 NamePlural = TM72s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = VOLTSWITCH Description = After making its attack, the user rushes back to switch places with a party Pokémon in waiting. @@ -3068,6 +3223,7 @@ Name = TM73 NamePlural = TM73s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = THUNDERWAVE Description = A weak electric charge is launched at the target. It causes paralysis if it hits. @@ -3077,6 +3233,7 @@ Name = TM74 NamePlural = TM74s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = GYROBALL Description = The user tackles the target with a high-speed spin. The slower the user, the greater the damage. @@ -3086,6 +3243,7 @@ Name = TM75 NamePlural = TM75s Pocket = 4 Price = 1500 +BPPrice = 18 FieldUse = TM Move = SWORDSDANCE Description = A frenetic dance to uplift the fighting spirit. It sharply raises the user's Attack stat. @@ -3095,6 +3253,7 @@ Name = TM76 NamePlural = TM76s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = STRUGGLEBUG Description = Resisting, the user attacks the opposing Pokémon. The targets' Sp. Atk stat is reduced. @@ -3104,6 +3263,7 @@ Name = TM77 NamePlural = TM77s Pocket = 4 Price = 1500 +BPPrice = 24 FieldUse = TM Move = PSYCHUP Description = The user hypnotizes itself into copying any stat change made by the target. @@ -3113,6 +3273,7 @@ Name = TM78 NamePlural = TM78s Pocket = 4 Price = 1500 +BPPrice = 6 FieldUse = TM Move = BULLDOZE Description = The user stomps down on the ground and attacks everything in the area. The targets' Speed stat is reduced. @@ -3122,6 +3283,7 @@ Name = TM79 NamePlural = TM79s Pocket = 4 Price = 3000 +BPPrice = 12 FieldUse = TM Move = FROSTBREATH Description = The user blows a cold breath on the target. This attack always results in a critical hit. @@ -3131,6 +3293,7 @@ Name = TM80 NamePlural = TM80s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = ROCKSLIDE Description = Large boulders are hurled at the opposing team to inflict damage. They may also make the targets flinch. @@ -3140,6 +3303,7 @@ Name = TM81 NamePlural = TM81s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = XSCISSOR Description = The user slashes at the target by crossing its scythes or claws as if they were a pair of scissors. @@ -3149,6 +3313,7 @@ Name = TM82 NamePlural = TM82s Pocket = 4 Price = 1000 +BPPrice = 6 FieldUse = TM Move = DRAGONTAIL Description = The user knocks away the target and drags out another Pokémon in its party. In the wild, the battle ends. @@ -3158,6 +3323,7 @@ Name = TM83 NamePlural = TM83s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = WORKUP Description = The user is roused, and its Attack and Sp. Atk stats increase. @@ -3167,6 +3333,7 @@ Name = TM84 NamePlural = TM84s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = POISONJAB Description = The target is stabbed with a tentacle or arm steeped in poison. It may also poison the target. @@ -3176,6 +3343,7 @@ Name = TM85 NamePlural = TM85s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = DREAMEATER Description = The user eats the dreams of a sleeping target. It absorbs half the damage caused to heal the user's HP. @@ -3185,6 +3353,7 @@ Name = TM86 NamePlural = TM86s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = GRASSKNOT Description = The user snares the target with grass and trips it. The heavier the target, the greater the damage. @@ -3194,6 +3363,7 @@ Name = TM87 NamePlural = TM87s Pocket = 4 Price = 1500 +BPPrice = 18 FieldUse = TM Move = SWAGGER Description = The user enrages and confuses the target. However, it also sharply raises the target's Attack stat. @@ -3203,6 +3373,7 @@ Name = TM88 NamePlural = TM88s Pocket = 4 Price = 3000 +BPPrice = 18 FieldUse = TM Move = PLUCK Description = The user pecks the target. If the target is holding a Berry, the user plucks it and gains its effect. @@ -3212,6 +3383,7 @@ Name = TM89 NamePlural = TM89s Pocket = 4 Price = 3000 +BPPrice = 12 FieldUse = TM Move = UTURN Description = After making its attack, the user rushes back to switch places with a party Pokémon in waiting. @@ -3221,6 +3393,7 @@ Name = TM90 NamePlural = TM90s Pocket = 4 Price = 2000 +BPPrice = 6 FieldUse = TM Move = SUBSTITUTE Description = The user makes a copy of itself using some of its HP. The copy serves as the user's decoy. @@ -3230,6 +3403,7 @@ Name = TM91 NamePlural = TM91s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = FLASHCANNON Description = The user gathers all its light energy and releases it at once. It may also lower the target's Sp. Def stat. @@ -3239,6 +3413,7 @@ Name = TM92 NamePlural = TM92s Pocket = 4 Price = 5500 +BPPrice = 6 FieldUse = TM Move = TRICKROOM Description = The user creates a bizarre space in which slower Pokémon get to move first for five turns. @@ -3248,6 +3423,7 @@ Name = TM93 NamePlural = TM93s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = WILDCHARGE Description = The user shrouds itself in electricity and smashes into its target. It also damages the user a little. @@ -3257,6 +3433,7 @@ Name = TM94 NamePlural = TM94s Pocket = 4 Price = 1000 +BPPrice = 6 FieldUse = TM Move = ROCKSMASH Description = The user attacks with a punch that can shatter a rock. It may also lower the target's Defense stat. @@ -3266,6 +3443,7 @@ Name = TM95 NamePlural = TM95s Pocket = 4 Price = 3000 +BPPrice = 6 FieldUse = TM Move = SNARL Description = The user yells as if it is ranting about something, making the target's Sp. Atk stat decrease. diff --git a/PBS/Gen 6/items.txt b/PBS/Gen 6/items.txt index 16317d313..464fa633a 100644 --- a/PBS/Gen 6/items.txt +++ b/PBS/Gen 6/items.txt @@ -102,6 +102,7 @@ Name = Fire Stone NamePlural = Fire Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is colored orange. @@ -111,6 +112,7 @@ Name = Thunder Stone NamePlural = Thunder Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a thunderbolt pattern. @@ -120,6 +122,7 @@ Name = Water Stone NamePlural = Water Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is a clear, light blue. @@ -129,6 +132,7 @@ Name = Leaf Stone NamePlural = Leaf Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a leaf pattern. @@ -138,6 +142,7 @@ Name = Moon Stone NamePlural = Moon Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as black as the night sky. @@ -147,6 +152,7 @@ Name = Sun Stone NamePlural = Sun Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as red as the sun. @@ -156,6 +162,7 @@ Name = Dusk Stone NamePlural = Dusk Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as dark as dark can be. @@ -165,6 +172,7 @@ Name = Dawn Stone NamePlural = Dawn Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It sparkles like eyes. @@ -174,6 +182,7 @@ Name = Shiny Stone NamePlural = Shiny Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It shines with a dazzling light. @@ -558,6 +567,7 @@ Name = Air Balloon NamePlural = Air Balloons Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder will float in the air until hit. Once hit, this item will burst. #------------------------------- @@ -566,6 +576,7 @@ Name = Bright Powder NamePlural = Bright Powders Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It casts a tricky glare that lowers the opponent's accuracy. #------------------------------- @@ -574,6 +585,7 @@ Name = Eviolite NamePlural = Eviolites Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_40 Description = A mysterious evolutionary lump. When held, it raises the Defense and Sp. Def if the holder can still evolve. #------------------------------- @@ -582,6 +594,7 @@ Name = Float Stone NamePlural = Float Stones Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = A very light stone. It reduces the weight of a Pokémon when held. #------------------------------- @@ -590,6 +603,7 @@ Name = Destiny Knot NamePlural = Destiny Knots Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = A long, thin, bright-red string to be held by a Pokémon. If the holder becomes infatuated, so does the foe. #------------------------------- @@ -598,6 +612,7 @@ Name = Rocky Helmet NamePlural = Rocky Helmets Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_60 Description = If the holder of this item takes damage, the attacker will also be damaged upon contact. #------------------------------- @@ -606,6 +621,7 @@ Name = Assault Vest NamePlural = Assault Vests Pocket = 1 Price = 1000 +BPPrice = 48 Flags = Fling_80 Description = An item to be held by a Pokémon. This offensive vest raises Sp. Def but prevents the use of status moves. #------------------------------- @@ -614,6 +630,7 @@ Name = Safety Goggles NamePlural = Safety Goggles Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_80 Description = An item to be held by a Pokémon. They protect the holder from weather-related damage and powder. #------------------------------- @@ -622,6 +639,7 @@ Name = Eject Button NamePlural = Eject Buttons Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_30 Description = If the holder is hit by an attack, it will switch with another Pokémon in your party. #------------------------------- @@ -630,6 +648,7 @@ Name = Red Card NamePlural = Red Cards Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = A card with a mysterious power. When the holder is struck by a foe, the attacker is removed from battle. #------------------------------- @@ -654,6 +673,7 @@ Name = Lucky Egg NamePlural = Lucky Eggs Pocket = 1 Price = 10000 +BPPrice = 77 Flags = Fling_30 Description = An item to be held by a Pokémon. It is an egg filled with happiness that earns extra Exp. Points in battle. #------------------------------- @@ -678,6 +698,7 @@ Name = Soothe Bell NamePlural = Soothe Bells Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. The comforting chime of this bell calms the holder, making it friendly. #------------------------------- @@ -694,6 +715,7 @@ Name = Choice Band NamePlural = Choice Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. This headband ups Attack, but allows the use of only one move. #------------------------------- @@ -702,6 +724,7 @@ Name = Choice Specs NamePlural = Choice Specs Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. These curious glasses boost Sp. Atk but allows the use of only one move. #------------------------------- @@ -710,6 +733,7 @@ Name = Choice Scarf NamePlural = Choice Scarves Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. This scarf boosts Speed but allows the use of only one move. #------------------------------- @@ -718,6 +742,7 @@ Name = Heat Rock NamePlural = Heat Rocks Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Sunny Day used by the holder. #------------------------------- @@ -726,6 +751,7 @@ Name = Damp Rock NamePlural = Damp Rocks Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Rain Dance used by the holder. #------------------------------- @@ -734,6 +760,7 @@ Name = Smooth Rock NamePlural = Smooth Rocks Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = A Pokémon held item that extends the duration of the move Sandstorm used by the holder. #------------------------------- @@ -742,6 +769,7 @@ Name = Icy Rock NamePlural = Icy Rocks Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_40 Description = A Pokémon held item that extends the duration of the move Hail used by the holder. #------------------------------- @@ -750,6 +778,7 @@ Name = Light Clay NamePlural = Light Clays Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. Protective moves like Light Screen and Reflect will be effective longer. #------------------------------- @@ -758,6 +787,7 @@ Name = Grip Claw NamePlural = Grip Claws Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_90 Description = A Pokémon held item that extends the duration of multiturn attacks like Bind and Wrap. #------------------------------- @@ -766,6 +796,7 @@ Name = Binding Band NamePlural = Binding Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = A band that increases the power of binding moves when held. #------------------------------- @@ -774,6 +805,7 @@ Name = Big Root NamePlural = Big Roots Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = A Pokémon held item that boosts the power of HP-stealing moves to let the holder recover more HP. #------------------------------- @@ -782,6 +814,7 @@ Name = Black Sludge NamePlural = Black Sludges Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = A held item that gradually restores the HP of Poison-type Pokémon. It inflicts damage on all other types. #------------------------------- @@ -790,6 +823,7 @@ Name = Leftovers NamePlural = Leftovers Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder's HP is gradually restored during battle. #------------------------------- @@ -798,6 +832,7 @@ Name = Shell Bell NamePlural = Shell Bells Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. The holder's HP is restored a little every time it inflicts damage. #------------------------------- @@ -806,6 +841,7 @@ Name = Mental Herb NamePlural = Mental Herbs Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = An item to be held by a Pokémon. It snaps the holder out of infatuation. It can be used only once. #------------------------------- @@ -814,6 +850,7 @@ Name = White Herb NamePlural = White Herbs Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = An item to be held by a Pokémon. It restores any lowered stat in battle. It can be used only once. #------------------------------- @@ -822,6 +859,7 @@ Name = Power Herb NamePlural = Power Herbs Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = A single-use item to be held by a Pokémon. It allows the immediate use of a move that charges up first. #------------------------------- @@ -830,6 +868,7 @@ Name = Absorb Bulb NamePlural = Absorb Bulbs Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_30 Description = A consumable bulb. If the holder is hit by a Water-type move, its Sp. Atk will rise. #------------------------------- @@ -838,6 +877,7 @@ Name = Cell Battery NamePlural = Cell Batteries Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_30 Description = A consumable battery. If the holder is hit by an Electric-type move, its Attack will rise. #------------------------------- @@ -846,6 +886,7 @@ Name = Luminous Moss NamePlural = Luminous Mosses Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Sp. Def if hit by a Water-type attack. It can only be used once. #------------------------------- @@ -854,6 +895,7 @@ Name = Snowball NamePlural = Snowballs Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Attack if hit by an Ice-type attack. It can only be used once. #------------------------------- @@ -862,6 +904,7 @@ Name = Weakness Policy NamePlural = Weakness Policies Pocket = 1 Price = 1000 +BPPrice = 32 Flags = Fling_80 Description = An item to be held by a Pokémon. The holder's Attack and Sp. Atk sharply increase if hit by a move it's weak to. #------------------------------- @@ -870,6 +913,7 @@ Name = Life Orb NamePlural = Life Orbs Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts the power of moves, but at the cost of some HP on each hit. #------------------------------- @@ -878,6 +922,7 @@ Name = Expert Belt NamePlural = Expert Belts Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a well-worn belt that slightly boosts the power of supereffective moves. #------------------------------- @@ -886,6 +931,7 @@ Name = Metronome NamePlural = Metronomes Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = A Pokémon held item that boosts a move used consecutively. Its effect is reset if another move is used. #------------------------------- @@ -894,6 +940,7 @@ Name = Muscle Band NamePlural = Muscle Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a headband that slightly boosts the power of physical moves. #------------------------------- @@ -902,6 +949,7 @@ Name = Wise Glasses NamePlural = Wise Glasses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a thick pair of glasses that slightly boosts the power of special moves. #------------------------------- @@ -910,6 +958,7 @@ Name = Razor Claw NamePlural = Razor Claws Pocket = 1 Price = 5000 +BPPrice = 48 Flags = Fling_80 Description = An item to be held by a Pokémon. It is a sharply hooked claw that ups the holder's critical-hit ratio. #------------------------------- @@ -918,6 +967,7 @@ Name = Scope Lens NamePlural = Scope Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a lens that boosts the holder's critical-hit ratio. #------------------------------- @@ -926,6 +976,7 @@ Name = Wide Lens NamePlural = Wide Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a magnifying lens that slightly boosts the accuracy of moves. #------------------------------- @@ -934,6 +985,7 @@ Name = Zoom Lens NamePlural = Zoom Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. If the holder moves after its target, its accuracy will be boosted. #------------------------------- @@ -942,6 +994,7 @@ Name = King's Rock NamePlural = King's Rocks Pocket = 1 Price = 5000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. When the holder inflicts damage, the target may flinch. #------------------------------- @@ -950,6 +1003,7 @@ Name = Razor Fang NamePlural = Razor Fangs Pocket = 1 Price = 5000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. It may make foes and allies flinch when the holder inflicts damage. #------------------------------- @@ -958,6 +1012,7 @@ Name = Lagging Tail NamePlural = Lagging Tails Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is tremendously heavy and makes the holder move slower than usual. #------------------------------- @@ -966,6 +1021,7 @@ Name = Quick Claw NamePlural = Quick Claws Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_80 Description = An item to be held by a Pokémon. A light, sharp claw that lets the bearer move first occasionally. #------------------------------- @@ -974,6 +1030,7 @@ Name = Focus Band NamePlural = Focus Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder may endure a potential KO attack, leaving it with just 1 HP. #------------------------------- @@ -982,6 +1039,7 @@ Name = Focus Sash NamePlural = Focus Sashes Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. If it has full HP, the holder will endure one potential KO attack, leaving 1 HP. #------------------------------- @@ -990,6 +1048,7 @@ Name = Flame Orb NamePlural = Flame Orbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that inflicts a burn on the holder in battle. #------------------------------- @@ -998,6 +1057,7 @@ Name = Toxic Orb NamePlural = Toxic Orbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that badly poisons the holder in battle. #------------------------------- @@ -1006,6 +1066,7 @@ Name = Sticky Barb NamePlural = Sticky Barbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_80 Description = A held item that damages the holder on every turn. It may latch on to Pokémon that touch the holder. #------------------------------- @@ -1014,6 +1075,7 @@ Name = Iron Ball NamePlural = Iron Balls Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_130 Description = A Pokémon held item that cuts Speed. It makes Flying-type and levitating holders susceptible to Ground moves. #------------------------------- @@ -1022,6 +1084,7 @@ Name = Ring Target NamePlural = Ring Targets Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = Moves that would otherwise have no effect will land on the Pokémon that holds it. #------------------------------- @@ -1030,6 +1093,7 @@ Name = Macho Brace NamePlural = Macho Braces Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_60 Description = An item to be held by a Pokémon. It is a stiff, heavy brace that promotes strong growth but lowers Speed. #------------------------------- @@ -1038,6 +1102,7 @@ Name = Power Weight NamePlural = Power Weights Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes HP gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1046,6 +1111,7 @@ Name = Power Bracer NamePlural = Power Bracers Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Attack gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1054,6 +1120,7 @@ Name = Power Belt NamePlural = Power Belts Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Defense gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1062,6 +1129,7 @@ Name = Power Lens NamePlural = Power Lenses Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Atk gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1070,6 +1138,7 @@ Name = Power Band NamePlural = Power Bands Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Def gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1078,6 +1147,7 @@ Name = Power Anklet NamePlural = Power Anklets Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Speed gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1582,6 +1652,7 @@ Name = Lucky Punch NamePlural = Lucky Punches Pocket = 1 Price = 1000 +BPPrice = 7 Flags = Fling_40 Description = An item to be held by Chansey. It is a pair of gloves that boosts Chansey's critical-hit ratio. #------------------------------- @@ -1630,6 +1701,7 @@ Name = Deep Sea Tooth NamePlural = Deep Sea Teeth Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_90 Description = An item to be held by Clamperl. A fang that gleams a sharp silver, it raises the Sp. Atk stat. #------------------------------- @@ -1638,6 +1710,7 @@ Name = Deep Sea Scale NamePlural = Deep Sea Scales Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_30 Description = An item to be held by Clamperl. A scale that shines a faint pink, it raises the Sp. Def stat. #------------------------------- @@ -1702,6 +1775,7 @@ Name = Everstone NamePlural = Everstones Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. The Pokémon holding this peculiar stone is prevented from evolving. #------------------------------- @@ -1710,6 +1784,7 @@ Name = Dragon Scale NamePlural = Dragon Scales Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_30 Description = A thick and tough scale. Dragon-type Pokémon may be holding this item when caught. #------------------------------- @@ -1718,6 +1793,7 @@ Name = Up-Grade NamePlural = Up-Grades Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_30 Description = A transparent device filled with all sorts of data. It was produced by Silph Co. #------------------------------- @@ -1726,6 +1802,7 @@ Name = Dubious Disc NamePlural = Dubious Discs Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_50 Description = A transparent device overflowing with dubious data. Its producer is unknown. #------------------------------- @@ -1734,6 +1811,7 @@ Name = Protector NamePlural = Protectors Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A protective item of some sort. It is extremely stiff and heavy. It is loved by a certain Pokémon. #------------------------------- @@ -1742,6 +1820,7 @@ Name = Electirizer NamePlural = Electirizers Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A box packed with a tremendous amount of electric energy. It is loved by a certain Pokémon. #------------------------------- @@ -1750,6 +1829,7 @@ Name = Magmarizer NamePlural = Magmarizers Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A box packed with a tremendous amount of magma energy. It is loved by a certain Pokémon. #------------------------------- @@ -1758,6 +1838,7 @@ Name = Reaper Cloth NamePlural = Reaper Cloths Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_10 Description = A cloth imbued with horrifyingly strong spiritual energy. It is loved by a certain Pokémon. #------------------------------- @@ -1766,6 +1847,7 @@ Name = Prism Scale NamePlural = Prism Scales Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_30 Description = A mysterious scale that evolves certain Pokémon. It shines in rainbow colors. #------------------------------- @@ -1774,6 +1856,7 @@ Name = Oval Stone NamePlural = Oval Stones Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is shaped like an egg. #------------------------------- @@ -1782,6 +1865,7 @@ Name = Whipped Dream NamePlural = Whipped Dreams Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A soft and sweet treat made of fluffy, puffy and whirled cream. It's loved by a certain Pokémon. #------------------------------- @@ -1790,6 +1874,7 @@ Name = Sachet NamePlural = Sachets Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A sachet filled with slightly overwhelming fragrant perfumes. Yet it's loved by a certain Pokémon. #------------------------------- @@ -1838,6 +1923,7 @@ Name = Venusaurite NamePlural = Venusaurites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Venusaur hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1846,6 +1932,7 @@ Name = Charizardite X NamePlural = Charizardite Xs Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Charizard hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1854,6 +1941,7 @@ Name = Charizardite Y NamePlural = Charizardite Ys Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Charizard hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1862,6 +1950,7 @@ Name = Blastoisinite NamePlural = Blastoisinites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Blastoise hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1870,6 +1959,7 @@ Name = Beedrillite NamePlural = Beedrillites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Beedrill hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1878,6 +1968,7 @@ Name = Pidgeotite NamePlural = Pidgeotites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Pidgeot hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1886,6 +1977,7 @@ Name = Alakazite NamePlural = Alakazites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Alakazam hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1894,6 +1986,7 @@ Name = Slowbronite NamePlural = Slowbronites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Slowbro hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1902,6 +1995,7 @@ Name = Gengarite NamePlural = Gengarites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gengar hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1910,6 +2004,7 @@ Name = Kangaskhanite NamePlural = Kangaskhanites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Kangaskhan hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1918,6 +2013,7 @@ Name = Pinsirite NamePlural = Pinsirites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Pinsir hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1926,6 +2022,7 @@ Name = Gyaradosite NamePlural = Gyaradosites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gyarados hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1934,6 +2031,7 @@ Name = Aerodactylite NamePlural = Aerodactylites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Aerodactyl hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1942,6 +2040,7 @@ Name = Mewtwonite X NamePlural = Mewtwonite Xs Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mewtwo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1950,6 +2049,7 @@ Name = Mewtwonite Y NamePlural = Mewtwonite Ys Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mewtwo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1958,6 +2058,7 @@ Name = Ampharosite NamePlural = Ampharosites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Ampharos hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1966,6 +2067,7 @@ Name = Steelixite NamePlural = Steelixites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Steelix hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1974,6 +2076,7 @@ Name = Scizorite NamePlural = Scizorites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Scizor hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1982,6 +2085,7 @@ Name = Heracronite NamePlural = Heracronites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Heracross hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1990,6 +2094,7 @@ Name = Houndoominite NamePlural = Houndoominites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Houndoom hold it, and it will be able to Mega Evolve. #------------------------------- @@ -1998,6 +2103,7 @@ Name = Tyranitarite NamePlural = Tyranitarites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Tyranitar hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2006,6 +2112,7 @@ Name = Sceptilite NamePlural = Sceptilites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sceptile hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2014,6 +2121,7 @@ Name = Blazikenite NamePlural = Blazikenites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Blaziken hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2022,6 +2130,7 @@ Name = Swampertite NamePlural = Swampertites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Swampert hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2030,6 +2139,7 @@ Name = Gardevoirite NamePlural = Gardevoirites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gardevoir hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2038,6 +2148,7 @@ Name = Sablenite NamePlural = Sablenites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sableye hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2046,6 +2157,7 @@ Name = Mawilite NamePlural = Mawilites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mawile hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2054,6 +2166,7 @@ Name = Aggronite NamePlural = Aggronites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Aggron hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2062,6 +2175,7 @@ Name = Medichamite NamePlural = Medichamites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Medicham hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2070,6 +2184,7 @@ Name = Manectite NamePlural = Manectites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Manectric hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2078,6 +2193,7 @@ Name = Sharpedonite NamePlural = Sharpedonites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sharpedo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2086,6 +2202,7 @@ Name = Cameruptite NamePlural = Cameruptites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Camerupt hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2094,6 +2211,7 @@ Name = Altarianite NamePlural = Altarianites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Altaria hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2102,6 +2220,7 @@ Name = Banettite NamePlural = Banettites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Banette hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2110,6 +2229,7 @@ Name = Absolite NamePlural = Absolites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Absol hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2118,6 +2238,7 @@ Name = Glalitite NamePlural = Glalitites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Glalie hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2126,6 +2247,7 @@ Name = Salamencite NamePlural = Salamencites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Salamence hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2134,6 +2256,7 @@ Name = Metagrossite NamePlural = Metagrossites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Metagross hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2142,6 +2265,7 @@ Name = Latiasite NamePlural = Latiasites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Latias hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2150,6 +2274,7 @@ Name = Latiosite NamePlural = Latiosites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Latios hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2158,6 +2283,7 @@ Name = Lopunnite NamePlural = Lopunnites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Lopunny hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2166,6 +2292,7 @@ Name = Garchompite NamePlural = Garchompites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Garchomp hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2174,6 +2301,7 @@ Name = Lucarionite NamePlural = Lucarionites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Lucario hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2182,6 +2310,7 @@ Name = Abomasite NamePlural = Abomasites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Abomasnow hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2190,6 +2319,7 @@ Name = Galladite NamePlural = Galladites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gallade hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2198,6 +2328,7 @@ Name = Audinite NamePlural = Audinites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Audino hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2206,6 +2337,7 @@ Name = Diancite NamePlural = Diancites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Diancie hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2214,6 +2346,7 @@ Name = Red Orb NamePlural = Red Orbs Pocket = 1 Price = 0 +BPPrice = 64 Description = A shiny red orb that is said to have a legend tied to it. It's known to be connected with the Hoenn region. #------------------------------- [BLUEORB] @@ -2221,6 +2354,7 @@ Name = Blue Orb NamePlural = Blue Orbs Pocket = 1 Price = 0 +BPPrice = 64 Description = A shiny blue orb that is said to have a legend tied to it. It's known to be connected with the Hoenn region. #------------------------------- [POTION] @@ -2258,6 +2392,7 @@ Name = Max Potion NamePlural = Max Potions Pocket = 2 Price = 2500 +BPPrice = 2 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -2417,6 +2552,7 @@ Name = Max Revive NamePlural = Max Revives Pocket = 2 Price = 4000 +BPPrice = 32 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -2527,6 +2663,7 @@ Name = Ether NamePlural = Ethers Pocket = 2 Price = 1200 +BPPrice = 4 FieldUse = OnPokemon BattleUse = OnMove Flags = Fling_30 @@ -2567,6 +2704,7 @@ Name = PP Up NamePlural = PP Ups Pocket = 2 Price = 10000 +BPPrice = 48 FieldUse = OnPokemon Flags = Fling_30 Description = It slightly raises the maximum PP of a selected move that has been learned by the target Pokémon. @@ -2585,6 +2723,7 @@ Name = HP Up NamePlural = HP Ups Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base HP of a single Pokémon. @@ -2594,6 +2733,7 @@ Name = Protein NamePlural = Proteins Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Attack stat of a single Pokémon. @@ -2603,6 +2743,7 @@ Name = Iron NamePlural = Irons Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Defense stat of a single Pokémon. @@ -2612,6 +2753,7 @@ Name = Calcium NamePlural = Calciums Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Sp. Atk (Special Attack) stat of a single Pokémon. @@ -2621,6 +2763,7 @@ Name = Zinc NamePlural = Zincs Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Sp. Def (Special Defense) stat of a single Pokémon. @@ -2630,6 +2773,7 @@ Name = Carbos NamePlural = Carbos Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Speed stat of a single Pokémon. @@ -2693,6 +2837,7 @@ Name = Ability Capsule NamePlural = Ability Capsule Pocket = 2 Price = 10000 +BPPrice = 200 FieldUse = OnPokemon Description = A capsule that allows a Pokémon with two Abilities to switch between these Abilities when it is used. #------------------------------- @@ -2701,6 +2846,7 @@ Name = Rare Candy NamePlural = Rare Candies Pocket = 2 Price = 10000 +BPPrice = 48 FieldUse = OnPokemon Flags = Fling_30 Description = A candy that is packed with energy. It raises the level of a single Pokémon by one. @@ -2935,6 +3081,7 @@ Name = TM01 NamePlural = TM01s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = HONECLAWS Description = The user sharpens its claws to boost its Attack stat and accuracy. @@ -2944,6 +3091,7 @@ Name = TM02 NamePlural = TM02s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = DRAGONCLAW Description = The user slashes the target with huge, sharp claws. @@ -2953,6 +3101,7 @@ Name = TM03 NamePlural = TM03s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = PSYSHOCK Description = The user materializes an odd psychic wave to attack the target. This attack does physical damage. @@ -2962,6 +3111,7 @@ Name = TM04 NamePlural = TM04s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = CALMMIND Description = The user quietly focuses its mind and calms its spirit to raise its Sp. Atk and Sp. Def stats. @@ -2971,6 +3121,7 @@ Name = TM05 NamePlural = TM05s Pocket = 4 Price = 10000 +BPPrice = 24 FieldUse = TM Move = ROAR Description = The target is scared off and replaced by another Pokémon in its party. In the wild, the battle ends. @@ -2980,6 +3131,7 @@ Name = TM06 NamePlural = TM06s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = TOXIC Description = A move that leaves the target badly poisoned. Its poison damage worsens every turn. @@ -2989,6 +3141,7 @@ Name = TM07 NamePlural = TM07s Pocket = 4 Price = 50000 +BPPrice = 16 FieldUse = TM Move = HAIL Description = Summons a hailstorm that lasts for five turns. The hailstorm damages all types except Ice. @@ -2998,6 +3151,7 @@ Name = TM08 NamePlural = TM08s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = BULKUP Description = The user tenses its muscles to bulk up its body, boosting both its Attack and Defense stats. @@ -3007,6 +3161,7 @@ Name = TM09 NamePlural = TM09s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = VENOSHOCK Description = The user drenches the target in a special poisonous liquid. Its power is doubled if the target is poisoned. @@ -3016,6 +3171,7 @@ Name = TM10 NamePlural = TM10s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = HIDDENPOWER Description = A unique attack that varies in type and intensity depending on the Pokémon using it. @@ -3025,6 +3181,7 @@ Name = TM11 NamePlural = TM11s Pocket = 4 Price = 50000 +BPPrice = 16 FieldUse = TM Move = SUNNYDAY Description = The user intensifies the sun for five turns, powering up Fire-type moves. @@ -3034,6 +3191,7 @@ Name = TM12 NamePlural = TM12s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = TAUNT Description = The target is taunted into a rage that allows it to use only attack moves for three turns. @@ -3043,6 +3201,7 @@ Name = TM13 NamePlural = TM13s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ICEBEAM Description = The target is struck with an icy-cold beam of energy. It may also freeze the target solid. @@ -3052,6 +3211,7 @@ Name = TM14 NamePlural = TM14s Pocket = 4 Price = 30000 +BPPrice = 16 FieldUse = TM Move = BLIZZARD Description = A howling blizzard is summoned to strike the opposing team. It may also freeze them solid. @@ -3061,6 +3221,7 @@ Name = TM15 NamePlural = TM15s Pocket = 4 Price = 50000 +BPPrice = 16 FieldUse = TM Move = HYPERBEAM Description = The target is attacked with a powerful beam. The user must rest on the next turn to regain its energy. @@ -3070,6 +3231,7 @@ Name = TM16 NamePlural = TM16s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = LIGHTSCREEN Description = A wondrous wall of light is put up to suppress damage from special attacks for five turns. @@ -3079,6 +3241,7 @@ Name = TM17 NamePlural = TM17s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = PROTECT Description = It enables the user to evade all attacks. Its chance of failing rises if it is used in succession. @@ -3088,6 +3251,7 @@ Name = TM18 NamePlural = TM18s Pocket = 4 Price = 50000 +BPPrice = 16 FieldUse = TM Move = RAINDANCE Description = The user summons a heavy rain that falls for five turns, powering up Water-type moves. @@ -3097,6 +3261,7 @@ Name = TM19 NamePlural = TM19s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ROOST Description = The user lands and rests its body. It restores the user's HP by up to half of its max HP. @@ -3106,6 +3271,7 @@ Name = TM20 NamePlural = TM20s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SAFEGUARD Description = The user creates a protective field that prevents status problems for five turns. @@ -3115,6 +3281,7 @@ Name = TM21 NamePlural = TM21s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = FRUSTRATION Description = A full-power attack that grows more powerful the less the user likes its Trainer. @@ -3124,6 +3291,7 @@ Name = TM22 NamePlural = TM22s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SOLARBEAM Description = A two-turn attack. The user gathers light, then blasts a bundled beam on the second turn. @@ -3133,6 +3301,7 @@ Name = TM23 NamePlural = TM23s Pocket = 4 Price = 10000 +BPPrice = 32 FieldUse = TM Move = SMACKDOWN Description = The user throws a stone or similar projectile to attack a foe. A flying Pokémon will fall to the ground if hit. @@ -3142,6 +3311,7 @@ Name = TM24 NamePlural = TM24s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = THUNDERBOLT Description = A strong electric blast is loosed at the target. It may also leave the target with paralysis. @@ -3151,6 +3321,7 @@ Name = TM25 NamePlural = TM25s Pocket = 4 Price = 30000 +BPPrice = 16 FieldUse = TM Move = THUNDER Description = A wicked thunderbolt is dropped on the target to inflict damage. It may also leave the target with paralysis. @@ -3160,6 +3331,7 @@ Name = TM26 NamePlural = TM26s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = EARTHQUAKE Description = The user sets off an earthquake that strikes every Pokémon around it. @@ -3169,6 +3341,7 @@ Name = TM27 NamePlural = TM27s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = RETURN Description = A full-power attack that grows more powerful the more the user likes its Trainer. @@ -3178,6 +3351,7 @@ Name = TM28 NamePlural = TM28s Pocket = 4 Price = 2000 +BPPrice = 16 FieldUse = TM Move = DIG Description = The user burrows, then attacks on the second turn. It can also be used to exit dungeons. @@ -3187,6 +3361,7 @@ Name = TM29 NamePlural = TM29s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = PSYCHIC Description = The target is hit by a strong telekinetic force. It may also reduce the target's Sp. Def stat. @@ -3196,6 +3371,7 @@ Name = TM30 NamePlural = TM30s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SHADOWBALL Description = The user hurls a shadowy blob at the target. It may also lower the target's Sp. Def stat. @@ -3205,6 +3381,7 @@ Name = TM31 NamePlural = TM31s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = BRICKBREAK Description = The user attacks with tough fists, etc. It can also break any barrier such as Light Screen and Reflect. @@ -3214,6 +3391,7 @@ Name = TM32 NamePlural = TM32s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = DOUBLETEAM Description = By moving rapidly, the user makes illusory copies of itself to raise its evasiveness. @@ -3223,6 +3401,7 @@ Name = TM33 NamePlural = TM33s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = REFLECT Description = A wondrous wall of light is put up to suppress damage from physical attacks for five turns. @@ -3232,6 +3411,7 @@ Name = TM34 NamePlural = TM34s Pocket = 4 Price = 10000 +BPPrice = 32 FieldUse = TM Move = SLUDGEWAVE Description = It swamps the area around the user with a giant sludge wave. It may also poison those hit. @@ -3241,6 +3421,7 @@ Name = TM35 NamePlural = TM35s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = FLAMETHROWER Description = The target is scorched with an intense blast of fire. It may also leave the target with a burn. @@ -3250,6 +3431,7 @@ Name = TM36 NamePlural = TM36s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SLUDGEBOMB Description = Unsanitary sludge is hurled at the target. It may also poison the target. @@ -3259,6 +3441,7 @@ Name = TM37 NamePlural = TM37s Pocket = 4 Price = 50000 +BPPrice = 16 FieldUse = TM Move = SANDSTORM Description = A five-turn sandstorm is summoned to hurt all combatants except the Rock, Ground, and Steel types. @@ -3268,6 +3451,7 @@ Name = TM38 NamePlural = TM38s Pocket = 4 Price = 30000 +BPPrice = 16 FieldUse = TM Move = FIREBLAST Description = The foe is attacked with an intense blast of all-consuming fire. It may also leave the target with a burn. @@ -3277,6 +3461,7 @@ Name = TM39 NamePlural = TM39s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ROCKTOMB Description = Boulders are hurled at the target. It also lowers the target's Speed by preventing its movement. @@ -3286,6 +3471,7 @@ Name = TM40 NamePlural = TM40s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = AERIALACE Description = The user confounds the target with speed, then slashes. The attack lands without fail. @@ -3295,6 +3481,7 @@ Name = TM41 NamePlural = TM41s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = TORMENT Description = The user torments and enrages the target, making it incapable of using the same move twice in a row. @@ -3304,6 +3491,7 @@ Name = TM42 NamePlural = TM42s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = FACADE Description = An attack move that doubles its power if the user is poisoned, paralyzed, or has a burn. @@ -3313,6 +3501,7 @@ Name = TM43 NamePlural = TM43s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = FLAMECHARGE Description = The user cloaks itself with flame and attacks. Building up more power, it raises the user's Speed stat. @@ -3322,6 +3511,7 @@ Name = TM44 NamePlural = TM44s Pocket = 4 Price = 1000 +BPPrice = 16 FieldUse = TM Move = REST Description = The user goes to sleep for two turns. It fully restores the user's HP and heals any status problem. @@ -3331,6 +3521,7 @@ Name = TM45 NamePlural = TM45s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ATTRACT Description = If it is the opposite gender of the user, the target becomes infatuated and less likely to attack. @@ -3340,6 +3531,7 @@ Name = TM46 NamePlural = TM46s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = THIEF Description = The user attacks and steals the target's held item simultaneously. It can't steal if the user holds an item. @@ -3349,6 +3541,7 @@ Name = TM47 NamePlural = TM47s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = LOWSWEEP Description = The user attacks the target's legs swiftly, reducing the target's Speed stat. @@ -3358,6 +3551,7 @@ Name = TM48 NamePlural = TM48s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ROUND Description = The user attacks the target with a song. Others can join in the Round to increase the power of the attack. @@ -3367,6 +3561,7 @@ Name = TM49 NamePlural = TM49s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ECHOEDVOICE Description = The user attacks the target with an echoing voice. If this move is used every turn, it does greater damage. @@ -3376,6 +3571,7 @@ Name = TM50 NamePlural = TM50s Pocket = 4 Price = 80000 +BPPrice = 16 FieldUse = TM Move = OVERHEAT Description = The user attacks the target at full power. The attack's recoil sharply reduces the user's Sp. Atk stat. @@ -3385,6 +3581,7 @@ Name = TM51 NamePlural = TM51s Pocket = 4 Price = 10000 +BPPrice = 32 FieldUse = TM Move = STEELWING Description = The target is hit with wings of steel. This may also raise the user's Defense stat. @@ -3394,6 +3591,7 @@ Name = TM52 NamePlural = TM52s Pocket = 4 Price = 30000 +BPPrice = 16 FieldUse = TM Move = FOCUSBLAST Description = The user heightens its mental focus and unleashes its power. It may also lower the target's Sp. Def. @@ -3403,6 +3601,7 @@ Name = TM53 NamePlural = TM53s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ENERGYBALL Description = The user draws power from nature and fires it at the target. It may also lower the target's Sp. Def. @@ -3412,6 +3611,7 @@ Name = TM54 NamePlural = TM54s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = FALSESWIPE Description = A restrained attack that prevents the target from fainting. The target is left with at least 1 HP. @@ -3421,6 +3621,7 @@ Name = TM55 NamePlural = TM55s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SCALD Description = The user shoots boiling hot water at its target. It may also leave the target with a burn. @@ -3430,6 +3631,7 @@ Name = TM56 NamePlural = TM56s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = FLING Description = The user flings its held item at the target as an attack. Its power and effects depend on the item. @@ -3439,6 +3641,7 @@ Name = TM57 NamePlural = TM57s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = CHARGEBEAM Description = The user fires a concentrated bundle of electricity. It may also raise the user's Sp. Atk stat. @@ -3448,6 +3651,7 @@ Name = TM58 NamePlural = TM58s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SKYDROP Description = The user hurls the foe into the sky, then drops it on the next turn. The foe cannot attack while in the sky. @@ -3457,6 +3661,7 @@ Name = TM59 NamePlural = TM59s Pocket = 4 Price = 1500 +BPPrice = 16 FieldUse = TM Move = INCINERATE Description = The user attacks the target with fire. If the target is holding a Berry, it becomes burnt up and unusable. @@ -3466,6 +3671,7 @@ Name = TM60 NamePlural = TM60s Pocket = 4 Price = 10000 +BPPrice = 24 FieldUse = TM Move = QUASH Description = The user suppresses the target and makes its move go last. @@ -3475,6 +3681,7 @@ Name = TM61 NamePlural = TM61s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = WILLOWISP Description = The user shoots a sinister, bluish-white flame at the target to inflict a burn. @@ -3484,6 +3691,7 @@ Name = TM62 NamePlural = TM62s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ACROBATICS Description = The user nimbly strikes the target. If the user is not holding an item, this attack inflicts massive damage. @@ -3493,6 +3701,7 @@ Name = TM63 NamePlural = TM63s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = EMBARGO Description = It prevents the target from using its held item. Its Trainer is also prevented from using items on it. @@ -3502,6 +3711,7 @@ Name = TM64 NamePlural = TM64s Pocket = 4 Price = 10000 +BPPrice = 48 FieldUse = TM Move = EXPLOSION Description = The user explodes to inflict damage on those around it. The user faints upon using this move. @@ -3511,6 +3721,7 @@ Name = TM65 NamePlural = TM65s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SHADOWCLAW Description = The user slashes with a sharp claw made from shadows. It has a high critical-hit ratio. @@ -3520,6 +3731,7 @@ Name = TM66 NamePlural = TM66s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = PAYBACK Description = The user stores power, then attacks. If the user can use this attack after the foe, its power is doubled. @@ -3529,6 +3741,7 @@ Name = TM67 NamePlural = TM67s Pocket = 4 Price = 1000 +BPPrice = 48 FieldUse = TM Move = RETALIATE Description = The user gets revenge for a fainted ally. If an ally fainted in the last turn, this move's power is increased. @@ -3538,6 +3751,7 @@ Name = TM68 NamePlural = TM68s Pocket = 4 Price = 50000 +BPPrice = 16 FieldUse = TM Move = GIGAIMPACT Description = The user charges at the target using every bit of its power. The user must rest on the next turn. @@ -3547,6 +3761,7 @@ Name = TM69 NamePlural = TM69s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ROCKPOLISH Description = The user polishes its body to reduce drag. It sharply raises the Speed stat. @@ -3556,6 +3771,7 @@ Name = TM70 NamePlural = TM70s Pocket = 4 Price = 1000 +BPPrice = 16 FieldUse = TM Move = FLASH Description = The user flashes a bright light that cuts the target's accuracy. It can also be used to illuminate caves. @@ -3565,6 +3781,7 @@ Name = TM71 NamePlural = TM71s Pocket = 4 Price = 30000 +BPPrice = 16 FieldUse = TM Move = STONEEDGE Description = The user stabs the foe with sharpened stones from below. It has a high critical-hit ratio. @@ -3574,6 +3791,7 @@ Name = TM72 NamePlural = TM72s Pocket = 4 Price = 10000 +BPPrice = 48 FieldUse = TM Move = VOLTSWITCH Description = After making its attack, the user rushes back to switch places with a party Pokémon in waiting. @@ -3583,6 +3801,7 @@ Name = TM73 NamePlural = TM73s Pocket = 4 Price = 5000 +BPPrice = 16 FieldUse = TM Move = THUNDERWAVE Description = A weak electric charge is launched at the target. It causes paralysis if it hits. @@ -3592,6 +3811,7 @@ Name = TM74 NamePlural = TM74s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = GYROBALL Description = The user tackles the target with a high-speed spin. The slower the user, the greater the damage. @@ -3601,6 +3821,7 @@ Name = TM75 NamePlural = TM75s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SWORDSDANCE Description = A frenetic dance to uplift the fighting spirit. It sharply raises the user's Attack stat. @@ -3610,6 +3831,7 @@ Name = TM76 NamePlural = TM76s Pocket = 4 Price = 2000 +BPPrice = 16 FieldUse = TM Move = STRUGGLEBUG Description = Resisting, the user attacks the opposing Pokémon. The targets' Sp. Atk stat is reduced. @@ -3619,6 +3841,7 @@ Name = TM77 NamePlural = TM77s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = PSYCHUP Description = The user hypnotizes itself into copying any stat change made by the target. @@ -3628,6 +3851,7 @@ Name = TM78 NamePlural = TM78s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = BULLDOZE Description = The user stomps down on the ground and attacks everything in the area. The targets' Speed stat is reduced. @@ -3637,6 +3861,7 @@ Name = TM79 NamePlural = TM79s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = FROSTBREATH Description = The user blows a cold breath on the target. This attack always results in a critical hit. @@ -3646,6 +3871,7 @@ Name = TM80 NamePlural = TM80s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = ROCKSLIDE Description = Large boulders are hurled at the opposing team to inflict damage. They may also make the targets flinch. @@ -3655,6 +3881,7 @@ Name = TM81 NamePlural = TM81s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = XSCISSOR Description = The user slashes at the target by crossing its scythes or claws as if they were a pair of scissors. @@ -3664,6 +3891,7 @@ Name = TM82 NamePlural = TM82s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = DRAGONTAIL Description = The user knocks away the target and drags out another Pokémon in its party. In the wild, the battle ends. @@ -3673,6 +3901,7 @@ Name = TM83 NamePlural = TM83s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = INFESTATION Description = The target is infested and attacked for four to five turns. The target can't flee during this time. @@ -3682,6 +3911,7 @@ Name = TM84 NamePlural = TM84s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = POISONJAB Description = The target is stabbed with a tentacle or arm steeped in poison. It may also poison the target. @@ -3691,6 +3921,7 @@ Name = TM85 NamePlural = TM85s Pocket = 4 Price = 10000 +BPPrice = 48 FieldUse = TM Move = DREAMEATER Description = The user eats the dreams of a sleeping target. It absorbs half the damage caused to heal the user's HP. @@ -3700,6 +3931,7 @@ Name = TM86 NamePlural = TM86s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = GRASSKNOT Description = The user snares the target with grass and trips it. The heavier the target, the greater the damage. @@ -3709,6 +3941,7 @@ Name = TM87 NamePlural = TM87s Pocket = 4 Price = 10000 +BPPrice = 24 FieldUse = TM Move = SWAGGER Description = The user enrages and confuses the target. However, it also sharply raises the target's Attack stat. @@ -3718,6 +3951,7 @@ Name = TM88 NamePlural = TM88s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SLEEPTALK Description = While it is asleep, the user randomly uses one of the moves it knows. @@ -3727,6 +3961,7 @@ Name = TM89 NamePlural = TM89s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = UTURN Description = After making its attack, the user rushes back to switch places with a party Pokémon in waiting. @@ -3736,6 +3971,7 @@ Name = TM90 NamePlural = TM90s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SUBSTITUTE Description = The user makes a copy of itself using some of its HP. The copy serves as the user's decoy. @@ -3745,6 +3981,7 @@ Name = TM91 NamePlural = TM91s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = FLASHCANNON Description = The user gathers all its light energy and releases it at once. It may also lower the target's Sp. Def stat. @@ -3754,6 +3991,7 @@ Name = TM92 NamePlural = TM92s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = TRICKROOM Description = The user creates a bizarre space in which slower Pokémon get to move first for five turns. @@ -3763,6 +4001,7 @@ Name = TM93 NamePlural = TM93s Pocket = 4 Price = 50000 +BPPrice = 16 FieldUse = TM Move = WILDCHARGE Description = The user shrouds itself in electricity and smashes into its target. It also damages the user a little. @@ -3772,6 +4011,7 @@ Name = TM94 NamePlural = TM94s Pocket = 4 Price = 2000 +BPPrice = 16 FieldUse = TM Move = SECRETPOWER Description = The user attacks with a secret power. Its added effects vary depending on the user's environment. @@ -3781,6 +4021,7 @@ Name = TM95 NamePlural = TM95s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = SNARL Description = The user yells as if it is ranting about something, making the target's Sp. Atk stat decrease. @@ -3790,6 +4031,7 @@ Name = TM96 NamePlural = TM96s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = NATUREPOWER Description = This attack makes use of nature's power. Its effects vary depending on the user's environment. @@ -3799,6 +4041,7 @@ Name = TM97 NamePlural = TM97s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = DARKPULSE Description = The user releases a horrible aura imbued with dark thoughts. This may also make the target flinch. @@ -3808,6 +4051,7 @@ Name = TM98 NamePlural = TM98s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = POWERUPPUNCH Description = Striking opponents repeatedly makes the user's fists harder. Hitting a target raises the Attack stat. @@ -3817,6 +4061,7 @@ Name = TM99 NamePlural = TM99s Pocket = 4 Price = 10000 +BPPrice = 16 FieldUse = TM Move = DAZZLINGGLEAM Description = The user damages opposing Pokémon by emitting a powerful flash. @@ -3826,6 +4071,7 @@ Name = TM100 NamePlural = TM100s Pocket = 4 Price = 5000 +BPPrice = 16 FieldUse = TM Move = CONFIDE Description = The user tells the target a secret. The target loses concentration and its Sp. Atk stat is lowered. diff --git a/PBS/Gen 7/items.txt b/PBS/Gen 7/items.txt index 240e6fb88..4cb04dd8b 100644 --- a/PBS/Gen 7/items.txt +++ b/PBS/Gen 7/items.txt @@ -102,6 +102,7 @@ Name = Fire Stone NamePlural = Fire Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is colored orange. @@ -111,6 +112,7 @@ Name = Thunder Stone NamePlural = Thunder Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a thunderbolt pattern. @@ -120,6 +122,7 @@ Name = Water Stone NamePlural = Water Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is a clear, light blue. @@ -129,6 +132,7 @@ Name = Leaf Stone NamePlural = Leaf Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a leaf pattern. @@ -138,6 +142,7 @@ Name = Moon Stone NamePlural = Moon Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as black as the night sky. @@ -147,6 +152,7 @@ Name = Sun Stone NamePlural = Sun Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as red as the sun. @@ -156,6 +162,7 @@ Name = Dusk Stone NamePlural = Dusk Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as dark as dark can be. @@ -165,6 +172,7 @@ Name = Dawn Stone NamePlural = Dawn Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It sparkles like eyes. @@ -174,6 +182,7 @@ Name = Shiny Stone NamePlural = Shiny Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It shines with a dazzling light. @@ -183,6 +192,7 @@ Name = Ice Stone NamePlural = Ice Stones Pocket = 1 Price = 3000 +BPPrice = 16 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a snowflake pattern. @@ -603,6 +613,7 @@ Name = Air Balloon NamePlural = Air Balloons Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder will float in the air until hit. Once hit, this item will burst. #------------------------------- @@ -611,6 +622,7 @@ Name = Bright Powder NamePlural = Bright Powders Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It casts a tricky glare that lowers the opponent's accuracy. #------------------------------- @@ -619,6 +631,7 @@ Name = Eviolite NamePlural = Eviolites Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_40 Description = A mysterious evolutionary lump. When held, it raises the Defense and Sp. Def if the holder can still evolve. #------------------------------- @@ -627,6 +640,7 @@ Name = Float Stone NamePlural = Float Stones Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = A very light stone. It reduces the weight of a Pokémon when held. #------------------------------- @@ -635,6 +649,7 @@ Name = Destiny Knot NamePlural = Destiny Knots Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = A long, thin, bright-red string to be held by a Pokémon. If the holder becomes infatuated, so does the foe. #------------------------------- @@ -643,6 +658,7 @@ Name = Rocky Helmet NamePlural = Rocky Helmets Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_60 Description = If the holder of this item takes damage, the attacker will also be damaged upon contact. #------------------------------- @@ -651,6 +667,7 @@ Name = Assault Vest NamePlural = Assault Vests Pocket = 1 Price = 1000 +BPPrice = 48 Flags = Fling_80 Description = An item to be held by a Pokémon. This offensive vest raises Sp. Def but prevents the use of status moves. #------------------------------- @@ -659,6 +676,7 @@ Name = Safety Goggles NamePlural = Safety Goggles Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_80 Description = An item to be held by a Pokémon. They protect the holder from weather-related damage and powder. #------------------------------- @@ -667,6 +685,7 @@ Name = Protective Pads NamePlural = Protective Pads Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. They protect the holder from effects caused by making contact. #------------------------------- @@ -675,6 +694,7 @@ Name = Eject Button NamePlural = Eject Buttons Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_30 Description = If the holder is hit by an attack, it will switch with another Pokémon in your party. #------------------------------- @@ -683,6 +703,7 @@ Name = Red Card NamePlural = Red Cards Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = A card with a mysterious power. When the holder is struck by a foe, the attacker is removed from battle. #------------------------------- @@ -707,6 +728,7 @@ Name = Lucky Egg NamePlural = Lucky Eggs Pocket = 1 Price = 10000 +BPPrice = 77 Flags = Fling_30 Description = An item to be held by a Pokémon. It is an egg filled with happiness that earns extra Exp. Points in battle. #------------------------------- @@ -731,6 +753,7 @@ Name = Soothe Bell NamePlural = Soothe Bells Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. The comforting chime of this bell calms the holder, making it friendly. #------------------------------- @@ -747,6 +770,7 @@ Name = Choice Band NamePlural = Choice Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. This headband ups Attack, but allows the use of only one move. #------------------------------- @@ -755,6 +779,7 @@ Name = Choice Specs NamePlural = Choice Specs Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. These curious glasses boost Sp. Atk but allows the use of only one move. #------------------------------- @@ -763,6 +788,7 @@ Name = Choice Scarf NamePlural = Choice Scarves Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. This scarf boosts Speed but allows the use of only one move. #------------------------------- @@ -771,6 +797,7 @@ Name = Heat Rock NamePlural = Heat Rocks Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Sunny Day used by the holder. #------------------------------- @@ -779,6 +806,7 @@ Name = Damp Rock NamePlural = Damp Rocks Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Rain Dance used by the holder. #------------------------------- @@ -787,6 +815,7 @@ Name = Smooth Rock NamePlural = Smooth Rocks Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = A Pokémon held item that extends the duration of the move Sandstorm used by the holder. #------------------------------- @@ -795,6 +824,7 @@ Name = Icy Rock NamePlural = Icy Rocks Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_40 Description = A Pokémon held item that extends the duration of the move Hail used by the holder. #------------------------------- @@ -803,6 +833,7 @@ Name = Terrain Extender NamePlural = Terrain Extenders Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_60 Description = An item to be held by a Pokémon. It extends the duration of the terrain caused by the holder. #------------------------------- @@ -811,6 +842,7 @@ Name = Light Clay NamePlural = Light Clays Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. Protective moves like Light Screen and Reflect will be effective longer. #------------------------------- @@ -819,6 +851,7 @@ Name = Grip Claw NamePlural = Grip Claws Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_90 Description = A Pokémon held item that extends the duration of multiturn attacks like Bind and Wrap. #------------------------------- @@ -827,6 +860,7 @@ Name = Binding Band NamePlural = Binding Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = A band that increases the power of binding moves when held. #------------------------------- @@ -835,6 +869,7 @@ Name = Big Root NamePlural = Big Roots Pocket = 1 Price = 4000 +BPPrice = 24 Flags = Fling_10 Description = A Pokémon held item that boosts the power of HP-stealing moves to let the holder recover more HP. #------------------------------- @@ -843,6 +878,7 @@ Name = Black Sludge NamePlural = Black Sludges Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = A held item that gradually restores the HP of Poison-type Pokémon. It inflicts damage on all other types. #------------------------------- @@ -851,6 +887,7 @@ Name = Leftovers NamePlural = Leftovers Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder's HP is gradually restored during battle. #------------------------------- @@ -859,6 +896,7 @@ Name = Shell Bell NamePlural = Shell Bells Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. The holder's HP is restored a little every time it inflicts damage. #------------------------------- @@ -867,6 +905,7 @@ Name = Mental Herb NamePlural = Mental Herbs Pocket = 1 Price = 4000 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. It snaps the holder out of infatuation. It can be used only once. #------------------------------- @@ -875,6 +914,7 @@ Name = White Herb NamePlural = White Herbs Pocket = 1 Price = 4000 +BPPrice = 24 Flags = Fling_10 Description = An item to be held by a Pokémon. It restores any lowered stat in battle. It can be used only once. #------------------------------- @@ -883,6 +923,7 @@ Name = Power Herb NamePlural = Power Herbs Pocket = 1 Price = 4000 +BPPrice = 24 Flags = Fling_10 Description = A single-use item to be held by a Pokémon. It allows the immediate use of a move that charges up first. #------------------------------- @@ -891,6 +932,7 @@ Name = Absorb Bulb NamePlural = Absorb Bulbs Pocket = 1 Price = 4000 +BPPrice = 24 Flags = Fling_30 Description = A consumable bulb. If the holder is hit by a Water-type move, its Sp. Atk will rise. #------------------------------- @@ -899,6 +941,7 @@ Name = Cell Battery NamePlural = Cell Batteries Pocket = 1 Price = 4000 +BPPrice = 24 Flags = Fling_30 Description = A consumable battery. If the holder is hit by an Electric-type move, its Attack will rise. #------------------------------- @@ -907,6 +950,7 @@ Name = Luminous Moss NamePlural = Luminous Mosses Pocket = 1 Price = 4000 +BPPrice = 24 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Sp. Def if hit by a Water-type attack. It can only be used once. #------------------------------- @@ -915,6 +959,7 @@ Name = Snowball NamePlural = Snowballs Pocket = 1 Price = 4000 +BPPrice = 24 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Attack if hit by an Ice-type attack. It can only be used once. #------------------------------- @@ -923,6 +968,7 @@ Name = Weakness Policy NamePlural = Weakness Policies Pocket = 1 Price = 1000 +BPPrice = 32 Flags = Fling_80 Description = An item to be held by a Pokémon. The holder's Attack and Sp. Atk sharply increase if hit by a move it's weak to. #------------------------------- @@ -931,6 +977,7 @@ Name = Adrenaline Orb NamePlural = Adrenaline Orbs Pocket = 1 Price = 300 +BPPrice = 24 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Speed when intimidated. It can be used only once. #------------------------------- @@ -971,6 +1018,7 @@ Name = Life Orb NamePlural = Life Orbs Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts the power of moves, but at the cost of some HP on each hit. #------------------------------- @@ -979,6 +1027,7 @@ Name = Expert Belt NamePlural = Expert Belts Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a well-worn belt that slightly boosts the power of supereffective moves. #------------------------------- @@ -987,6 +1036,7 @@ Name = Metronome NamePlural = Metronomes Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = A Pokémon held item that boosts a move used consecutively. Its effect is reset if another move is used. #------------------------------- @@ -995,6 +1045,7 @@ Name = Muscle Band NamePlural = Muscle Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a headband that slightly boosts the power of physical moves. #------------------------------- @@ -1003,6 +1054,7 @@ Name = Wise Glasses NamePlural = Wise Glasses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a thick pair of glasses that slightly boosts the power of special moves. #------------------------------- @@ -1011,6 +1063,7 @@ Name = Razor Claw NamePlural = Razor Claws Pocket = 1 Price = 5000 +BPPrice = 32 Flags = Fling_80 Description = An item to be held by a Pokémon. It is a sharply hooked claw that ups the holder's critical-hit ratio. #------------------------------- @@ -1019,6 +1072,7 @@ Name = Scope Lens NamePlural = Scope Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a lens that boosts the holder's critical-hit ratio. #------------------------------- @@ -1027,6 +1081,7 @@ Name = Wide Lens NamePlural = Wide Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a magnifying lens that slightly boosts the accuracy of moves. #------------------------------- @@ -1035,6 +1090,7 @@ Name = Zoom Lens NamePlural = Zoom Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. If the holder moves after its target, its accuracy will be boosted. #------------------------------- @@ -1043,6 +1099,7 @@ Name = King's Rock NamePlural = King's Rocks Pocket = 1 Price = 5000 +BPPrice = 32 Flags = Fling_30 Description = An item to be held by a Pokémon. When the holder inflicts damage, the target may flinch. #------------------------------- @@ -1051,6 +1108,7 @@ Name = Razor Fang NamePlural = Razor Fangs Pocket = 1 Price = 5000 +BPPrice = 32 Flags = Fling_30 Description = An item to be held by a Pokémon. It may make foes and allies flinch when the holder inflicts damage. #------------------------------- @@ -1059,6 +1117,7 @@ Name = Lagging Tail NamePlural = Lagging Tails Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is tremendously heavy and makes the holder move slower than usual. #------------------------------- @@ -1067,6 +1126,7 @@ Name = Quick Claw NamePlural = Quick Claws Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_80 Description = An item to be held by a Pokémon. A light, sharp claw that lets the bearer move first occasionally. #------------------------------- @@ -1075,6 +1135,7 @@ Name = Focus Band NamePlural = Focus Bands Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder may endure a potential KO attack, leaving it with just 1 HP. #------------------------------- @@ -1083,6 +1144,7 @@ Name = Focus Sash NamePlural = Focus Sashes Pocket = 1 Price = 4000 +BPPrice = 32 Flags = Fling_10 Description = An item to be held by a Pokémon. If it has full HP, the holder will endure one potential KO attack, leaving 1 HP. #------------------------------- @@ -1091,6 +1153,7 @@ Name = Flame Orb NamePlural = Flame Orbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that inflicts a burn on the holder in battle. #------------------------------- @@ -1099,6 +1162,7 @@ Name = Toxic Orb NamePlural = Toxic Orbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that badly poisons the holder in battle. #------------------------------- @@ -1107,6 +1171,7 @@ Name = Sticky Barb NamePlural = Sticky Barbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_80 Description = A held item that damages the holder on every turn. It may latch on to Pokémon that touch the holder. #------------------------------- @@ -1115,6 +1180,7 @@ Name = Iron Ball NamePlural = Iron Balls Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_130 Description = A Pokémon held item that cuts Speed. It makes Flying-type and levitating holders susceptible to Ground moves. #------------------------------- @@ -1123,6 +1189,7 @@ Name = Ring Target NamePlural = Ring Targets Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_10 Description = Moves that would otherwise have no effect will land on the Pokémon that holds it. #------------------------------- @@ -1131,6 +1198,7 @@ Name = Macho Brace NamePlural = Macho Braces Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_60 Description = An item to be held by a Pokémon. It is a stiff, heavy brace that promotes strong growth but lowers Speed. #------------------------------- @@ -1139,6 +1207,7 @@ Name = Power Weight NamePlural = Power Weights Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes HP gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1147,6 +1216,7 @@ Name = Power Bracer NamePlural = Power Bracers Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Attack gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1155,6 +1225,7 @@ Name = Power Belt NamePlural = Power Belts Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Defense gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1163,6 +1234,7 @@ Name = Power Lens NamePlural = Power Lenses Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Atk gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1171,6 +1243,7 @@ Name = Power Band NamePlural = Power Bands Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Def gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1179,6 +1252,7 @@ Name = Power Anklet NamePlural = Power Anklets Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_70 Description = A Pokémon held item that promotes Speed gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1683,6 +1757,7 @@ Name = Lucky Punch NamePlural = Lucky Punches Pocket = 1 Price = 1000 +BPPrice = 7 Flags = Fling_40 Description = An item to be held by Chansey. It is a pair of gloves that boosts Chansey's critical-hit ratio. #------------------------------- @@ -1731,6 +1806,7 @@ Name = Deep Sea Tooth NamePlural = Deep Sea Teeth Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_90 Description = An item to be held by Clamperl. A fang that gleams a sharp silver, it raises the Sp. Atk stat. #------------------------------- @@ -1739,6 +1815,7 @@ Name = Deep Sea Scale NamePlural = Deep Sea Scales Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_30 Description = An item to be held by Clamperl. A scale that shines a faint pink, it raises the Sp. Def stat. #------------------------------- @@ -1939,6 +2016,7 @@ Name = Everstone NamePlural = Everstones Pocket = 1 Price = 3000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. The Pokémon holding this peculiar stone is prevented from evolving. #------------------------------- @@ -1947,6 +2025,7 @@ Name = Dragon Scale NamePlural = Dragon Scales Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_30 Description = A thick and tough scale. Dragon-type Pokémon may be holding this item when caught. #------------------------------- @@ -1955,6 +2034,7 @@ Name = Upgrade NamePlural = Upgrades Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_30 Description = A transparent device filled with all sorts of data. It was produced by Silph Co. #------------------------------- @@ -1963,6 +2043,7 @@ Name = Dubious Disc NamePlural = Dubious Discs Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_50 Description = A transparent device overflowing with dubious data. Its producer is unknown. #------------------------------- @@ -1971,6 +2052,7 @@ Name = Protector NamePlural = Protectors Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A protective item of some sort. It is extremely stiff and heavy. It is loved by a certain Pokémon. #------------------------------- @@ -1979,6 +2061,7 @@ Name = Electirizer NamePlural = Electirizers Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A box packed with a tremendous amount of electric energy. It is loved by a certain Pokémon. #------------------------------- @@ -1987,6 +2070,7 @@ Name = Magmarizer NamePlural = Magmarizers Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A box packed with a tremendous amount of magma energy. It is loved by a certain Pokémon. #------------------------------- @@ -1995,6 +2079,7 @@ Name = Reaper Cloth NamePlural = Reaper Cloths Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_10 Description = A cloth imbued with horrifyingly strong spiritual energy. It is loved by a certain Pokémon. #------------------------------- @@ -2003,6 +2088,7 @@ Name = Prism Scale NamePlural = Prism Scales Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_30 Description = A mysterious scale that evolves certain Pokémon. It shines in rainbow colors. #------------------------------- @@ -2011,6 +2097,7 @@ Name = Oval Stone NamePlural = Oval Stones Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is shaped like an egg. #------------------------------- @@ -2019,6 +2106,7 @@ Name = Whipped Dream NamePlural = Whipped Dreams Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A soft and sweet treat made of fluffy, puffy and whirled cream. It's loved by a certain Pokémon. #------------------------------- @@ -2027,6 +2115,7 @@ Name = Sachet NamePlural = Sachets Pocket = 1 Price = 2000 +BPPrice = 32 Flags = Fling_80 Description = A sachet filled with slightly overwhelming fragrant perfumes. Yet it's loved by a certain Pokémon. #------------------------------- @@ -2075,6 +2164,7 @@ Name = Venusaurite NamePlural = Venusaurites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Venusaur hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2083,6 +2173,7 @@ Name = Charizardite X NamePlural = Charizardite Xs Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Charizard hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2091,6 +2182,7 @@ Name = Charizardite Y NamePlural = Charizardite Ys Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Charizard hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2099,6 +2191,7 @@ Name = Blastoisinite NamePlural = Blastoisinites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Blastoise hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2107,6 +2200,7 @@ Name = Beedrillite NamePlural = Beedrillites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Beedrill hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2115,6 +2209,7 @@ Name = Pidgeotite NamePlural = Pidgeotites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Pidgeot hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2123,6 +2218,7 @@ Name = Alakazite NamePlural = Alakazites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Alakazam hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2131,6 +2227,7 @@ Name = Slowbronite NamePlural = Slowbronites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Slowbro hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2139,6 +2236,7 @@ Name = Gengarite NamePlural = Gengarites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gengar hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2147,6 +2245,7 @@ Name = Kangaskhanite NamePlural = Kangaskhanites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Kangaskhan hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2155,6 +2254,7 @@ Name = Pinsirite NamePlural = Pinsirites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Pinsir hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2163,6 +2263,7 @@ Name = Gyaradosite NamePlural = Gyaradosites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gyarados hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2171,6 +2272,7 @@ Name = Aerodactylite NamePlural = Aerodactylites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Aerodactyl hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2179,6 +2281,7 @@ Name = Mewtwonite X NamePlural = Mewtwonite Xs Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mewtwo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2187,6 +2290,7 @@ Name = Mewtwonite Y NamePlural = Mewtwonite Ys Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mewtwo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2195,6 +2299,7 @@ Name = Ampharosite NamePlural = Ampharosites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Ampharos hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2203,6 +2308,7 @@ Name = Steelixite NamePlural = Steelixites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Steelix hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2211,6 +2317,7 @@ Name = Scizorite NamePlural = Scizorites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Scizor hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2219,6 +2326,7 @@ Name = Heracronite NamePlural = Heracronites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Heracross hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2227,6 +2335,7 @@ Name = Houndoominite NamePlural = Houndoominites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Houndoom hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2235,6 +2344,7 @@ Name = Tyranitarite NamePlural = Tyranitarites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Tyranitar hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2243,6 +2353,7 @@ Name = Sceptilite NamePlural = Sceptilites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sceptile hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2251,6 +2362,7 @@ Name = Blazikenite NamePlural = Blazikenites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Blaziken hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2259,6 +2371,7 @@ Name = Swampertite NamePlural = Swampertites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Swampert hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2267,6 +2380,7 @@ Name = Gardevoirite NamePlural = Gardevoirites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gardevoir hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2275,6 +2389,7 @@ Name = Sablenite NamePlural = Sablenites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sableye hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2283,6 +2398,7 @@ Name = Mawilite NamePlural = Mawilites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mawile hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2291,6 +2407,7 @@ Name = Aggronite NamePlural = Aggronites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Aggron hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2299,6 +2416,7 @@ Name = Medichamite NamePlural = Medichamites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Medicham hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2307,6 +2425,7 @@ Name = Manectite NamePlural = Manectites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Manectric hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2315,6 +2434,7 @@ Name = Sharpedonite NamePlural = Sharpedonites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sharpedo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2323,6 +2443,7 @@ Name = Cameruptite NamePlural = Cameruptites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Camerupt hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2331,6 +2452,7 @@ Name = Altarianite NamePlural = Altarianites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Altaria hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2339,6 +2461,7 @@ Name = Banettite NamePlural = Banettites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Banette hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2347,6 +2470,7 @@ Name = Absolite NamePlural = Absolites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Absol hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2355,6 +2479,7 @@ Name = Glalitite NamePlural = Glalitites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Glalie hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2363,6 +2488,7 @@ Name = Salamencite NamePlural = Salamencites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Salamence hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2371,6 +2497,7 @@ Name = Metagrossite NamePlural = Metagrossites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Metagross hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2379,6 +2506,7 @@ Name = Latiasite NamePlural = Latiasites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Latias hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2387,6 +2515,7 @@ Name = Latiosite NamePlural = Latiosites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Latios hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2395,6 +2524,7 @@ Name = Lopunnite NamePlural = Lopunnites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Lopunny hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2403,6 +2533,7 @@ Name = Garchompite NamePlural = Garchompites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Garchomp hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2411,6 +2542,7 @@ Name = Lucarionite NamePlural = Lucarionites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Lucario hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2419,6 +2551,7 @@ Name = Abomasite NamePlural = Abomasites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Abomasnow hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2427,6 +2560,7 @@ Name = Galladite NamePlural = Galladites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gallade hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2435,6 +2569,7 @@ Name = Audinite NamePlural = Audinites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Audino hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2443,6 +2578,7 @@ Name = Diancite NamePlural = Diancites Pocket = 1 Price = 0 +BPPrice = 64 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Diancie hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2451,6 +2587,7 @@ Name = Red Orb NamePlural = Red Orbs Pocket = 1 Price = 0 +BPPrice = 64 Description = A shiny red orb that is said to have a legend tied to it. It's known to be connected with the Hoenn region. #------------------------------- [BLUEORB] @@ -2458,6 +2595,7 @@ Name = Blue Orb NamePlural = Blue Orbs Pocket = 1 Price = 0 +BPPrice = 64 Description = A shiny blue orb that is said to have a legend tied to it. It's known to be connected with the Hoenn region. #------------------------------- [POTION] @@ -2664,6 +2802,7 @@ Name = Max Revive NamePlural = Max Revives Pocket = 2 Price = 4000 +BPPrice = 24 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -2774,6 +2913,7 @@ Name = Ether NamePlural = Ethers Pocket = 2 Price = 1200 +BPPrice = 4 FieldUse = OnPokemon BattleUse = OnMove Flags = Fling_30 @@ -2814,6 +2954,7 @@ Name = PP Up NamePlural = PP Ups Pocket = 2 Price = 10000 +BPPrice = 48 FieldUse = OnPokemon Flags = Fling_30 Description = It slightly raises the maximum PP of a selected move that has been learned by the target Pokémon. @@ -2832,6 +2973,7 @@ Name = HP Up NamePlural = HP Ups Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base HP of a single Pokémon. @@ -2841,6 +2983,7 @@ Name = Protein NamePlural = Proteins Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Attack stat of a single Pokémon. @@ -2850,6 +2993,7 @@ Name = Iron NamePlural = Irons Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Defense stat of a single Pokémon. @@ -2859,6 +3003,7 @@ Name = Calcium NamePlural = Calciums Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Sp. Atk (Special Attack) stat of a single Pokémon. @@ -2868,6 +3013,7 @@ Name = Zinc NamePlural = Zincs Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Sp. Def (Special Defense) stat of a single Pokémon. @@ -2877,6 +3023,7 @@ Name = Carbos NamePlural = Carbos Pocket = 2 Price = 10000 +BPPrice = 2 FieldUse = OnPokemon Flags = Fling_30 Description = A nutritious drink for Pokémon. It raises the base Speed stat of a single Pokémon. @@ -2940,6 +3087,7 @@ Name = Ability Capsule NamePlural = Ability Capsule Pocket = 2 Price = 10000 +BPPrice = 100 FieldUse = OnPokemon Description = A capsule that allows a Pokémon with two Abilities to switch between these Abilities when it is used. #------------------------------- @@ -2948,6 +3096,7 @@ Name = Rare Candy NamePlural = Rare Candies Pocket = 2 Price = 10000 +BPPrice = 48 FieldUse = OnPokemon Flags = Fling_30 Description = A candy that is packed with energy. It raises the level of a single Pokémon by one. diff --git a/PBS/Gen 8/items.txt b/PBS/Gen 8/items.txt index e1459fa97..4642a646e 100644 --- a/PBS/Gen 8/items.txt +++ b/PBS/Gen 8/items.txt @@ -33,8 +33,8 @@ NamePlural = Black Flutes Pocket = 1 Price = 20 FieldUse = Direct -Consumable = false Flags = Fling_30 +Consumable = false Description = A black flute made from blown glass. Its melody makes wild Pokémon less likely to appear. #------------------------------- [WHITEFLUTE] @@ -43,8 +43,8 @@ NamePlural = White Flutes Pocket = 1 Price = 20 FieldUse = Direct -Consumable = false Flags = Fling_30 +Consumable = false Description = A white flute made from blown glass. Its melody makes wild Pokémon more likely to appear. #------------------------------- [HONEY] @@ -93,6 +93,7 @@ Name = Fire Stone NamePlural = Fire Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is colored orange. @@ -102,6 +103,7 @@ Name = Thunder Stone NamePlural = Thunder Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a thunderbolt pattern. @@ -111,6 +113,7 @@ Name = Water Stone NamePlural = Water Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is a clear, light blue. @@ -120,6 +123,7 @@ Name = Leaf Stone NamePlural = Leaf Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a leaf pattern. @@ -129,6 +133,7 @@ Name = Moon Stone NamePlural = Moon Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as black as the night sky. @@ -138,6 +143,7 @@ Name = Sun Stone NamePlural = Sun Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as red as the sun. @@ -147,6 +153,7 @@ Name = Dusk Stone NamePlural = Dusk Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as dark as dark can be. @@ -156,6 +163,7 @@ Name = Dawn Stone NamePlural = Dawn Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It sparkles like eyes. @@ -165,6 +173,7 @@ Name = Shiny Stone NamePlural = Shiny Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It shines with a dazzling light. @@ -174,6 +183,7 @@ Name = Ice Stone NamePlural = Ice Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a snowflake pattern. @@ -183,6 +193,7 @@ Name = Sweet Apple NamePlural = Sweet Apples Pocket = 1 Price = 2200 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar apple that can make a certain species of Pokémon evolve. It's exceptionally sweet. @@ -192,6 +203,7 @@ Name = Tart Apple NamePlural = Tart Apples Pocket = 1 Price = 2200 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar apple that can make a certain species of Pokémon evolve. It's exceptionally tart. @@ -202,6 +214,7 @@ NamePlural = Cracked Pots Pocket = 1 Price = 3000 SellPrice = 800 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar cracked teapot that can make a certain species of Pokémon evolve. It makes delicious tea. @@ -212,6 +225,7 @@ NamePlural = Chipped Pots Pocket = 1 Price = 3000 SellPrice = 19000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar chipped teapot that can make a certain species of Pokémon evolve. It makes delicious tea. @@ -221,6 +235,7 @@ Name = Galarica Cuff NamePlural = Galarica Cuffs Pocket = 1 Price = 6000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A cuff made from woven-together Galarica Twigs. Giving it to a Galarian Slowpoke would make it very happy. @@ -230,6 +245,7 @@ Name = Galarica Wreath NamePlural = Galarica Wreaths Pocket = 1 Price = 6000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A wreath made from woven-together Galarica Twigs. A Galarian Slowpoke wearing this would be very happy. @@ -683,6 +699,7 @@ NamePlural = Air Balloons Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder will float in the air until hit. Once hit, this item will burst. #------------------------------- @@ -692,6 +709,7 @@ NamePlural = Bright Powders Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It casts a tricky glare that lowers the opponent's accuracy. #------------------------------- @@ -701,6 +719,7 @@ NamePlural = Eviolites Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_40 Description = A mysterious evolutionary lump. When held, it raises the Defense and Sp. Def if the holder can still evolve. #------------------------------- @@ -710,6 +729,7 @@ NamePlural = Float Stones Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 10 Flags = Fling_30 Description = A very light stone. It reduces the weight of a Pokémon when held. #------------------------------- @@ -719,6 +739,7 @@ NamePlural = Destiny Knots Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 10 Flags = Fling_10 Description = A long, thin, bright-red string to be held by a Pokémon. If the holder becomes infatuated, so does the foe. #------------------------------- @@ -728,6 +749,7 @@ NamePlural = Rocky Helmets Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_60 Description = If the holder of this item takes damage, the attacker will also be damaged upon contact. #------------------------------- @@ -736,6 +758,7 @@ Name = Assault Vest NamePlural = Assault Vests Pocket = 1 Price = 1000 +BPPrice = 25 Flags = Fling_80 Description = An item to be held by a Pokémon. This offensive vest raises Sp. Def but prevents the use of status moves. #------------------------------- @@ -745,6 +768,7 @@ NamePlural = Safety Goggles Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_80 Description = An item to be held by a Pokémon. They protect the holder from weather-related damage and powder. #------------------------------- @@ -754,6 +778,7 @@ NamePlural = Protective Pads Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_30 Description = An item to be held by a Pokémon. They protect the holder from effects caused by making contact. #------------------------------- @@ -763,6 +788,7 @@ NamePlural = pairs of Heavy-Duty Boots Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_80 Description = These boots prevent the effects of traps set on the battlefield. #------------------------------- @@ -772,6 +798,7 @@ NamePlural = Utility Umbrellas Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_60 Description = An item to be held by a Pokémon. This sturdy umbrella protects the holder from the effects of rain and sun. #------------------------------- @@ -781,6 +808,7 @@ NamePlural = Eject Buttons Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 20 Flags = Fling_30 Description = If the holder is hit by an attack, it will switch with another Pokémon in your party. #------------------------------- @@ -790,6 +818,7 @@ NamePlural = Eject Packs Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 20 Flags = Fling_50 Description = An item to be held by a Pokémon. When the holder's stats are lowered, it will be switched out of battle. #------------------------------- @@ -799,6 +828,7 @@ NamePlural = Red Cards Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 20 Flags = Fling_10 Description = A card with a mysterious power. When the holder is struck by a foe, the attacker is removed from battle. #------------------------------- @@ -825,6 +855,7 @@ Name = Lucky Egg NamePlural = Lucky Eggs Pocket = 1 Price = 10000 +BPPrice = 77 Flags = Fling_30 Description = An item to be held by a Pokémon. It is an egg filled with happiness that earns extra Exp. Points in battle. #------------------------------- @@ -849,6 +880,7 @@ Name = Soothe Bell NamePlural = Soothe Bells Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. The comforting chime of this bell calms the holder, making it friendly. #------------------------------- @@ -865,6 +897,7 @@ Name = Choice Band NamePlural = Choice Bands Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. This headband ups Attack, but allows the use of only one move. #------------------------------- @@ -873,6 +906,7 @@ Name = Choice Specs NamePlural = Choice Specs Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. These curious glasses boost Sp. Atk but allows the use of only one move. #------------------------------- @@ -881,6 +915,7 @@ Name = Choice Scarf NamePlural = Choice Scarves Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. This scarf boosts Speed but allows the use of only one move. #------------------------------- @@ -889,6 +924,7 @@ Name = Heat Rock NamePlural = Heat Rocks Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Sunny Day used by the holder. #------------------------------- @@ -897,6 +933,7 @@ Name = Damp Rock NamePlural = Damp Rocks Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Rain Dance used by the holder. #------------------------------- @@ -905,6 +942,7 @@ Name = Smooth Rock NamePlural = Smooth Rocks Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = A Pokémon held item that extends the duration of the move Sandstorm used by the holder. #------------------------------- @@ -913,6 +951,7 @@ Name = Icy Rock NamePlural = Icy Rocks Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_40 Description = A Pokémon held item that extends the duration of the move Hail used by the holder. #------------------------------- @@ -921,6 +960,7 @@ Name = Terrain Extender NamePlural = Terrain Extenders Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_60 Description = An item to be held by a Pokémon. It extends the duration of the terrain caused by the holder. #------------------------------- @@ -929,6 +969,7 @@ Name = Light Clay NamePlural = Light Clays Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_30 Description = An item to be held by a Pokémon. Protective moves like Light Screen and Reflect will be effective longer. #------------------------------- @@ -937,6 +978,7 @@ Name = Grip Claw NamePlural = Grip Claws Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_90 Description = A Pokémon held item that extends the duration of multiturn attacks like Bind and Wrap. #------------------------------- @@ -946,6 +988,7 @@ NamePlural = Binding Bands Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 15 Flags = Fling_30 Description = A band that increases the power of binding moves when held. #------------------------------- @@ -954,6 +997,7 @@ Name = Big Root NamePlural = Big Roots Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = A Pokémon held item that boosts the power of HP-stealing moves to let the holder recover more HP. #------------------------------- @@ -963,6 +1007,7 @@ NamePlural = Black Sludges Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_30 Description = A held item that gradually restores the HP of Poison-type Pokémon. It inflicts damage on all other types. #------------------------------- @@ -971,6 +1016,7 @@ Name = Leftovers NamePlural = Leftovers Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder's HP is gradually restored during battle. #------------------------------- @@ -979,6 +1025,7 @@ Name = Shell Bell NamePlural = Shell Bells Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_30 Description = An item to be held by a Pokémon. The holder's HP is restored a little every time it inflicts damage. #------------------------------- @@ -987,6 +1034,7 @@ Name = Mental Herb NamePlural = Mental Herbs Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. It snaps the holder out of infatuation. It can be used only once. #------------------------------- @@ -995,6 +1043,7 @@ Name = White Herb NamePlural = White Herbs Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. It restores any lowered stat in battle. It can be used only once. #------------------------------- @@ -1003,6 +1052,7 @@ Name = Power Herb NamePlural = Power Herbs Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = A single-use item to be held by a Pokémon. It allows the immediate use of a move that charges up first. #------------------------------- @@ -1011,6 +1061,7 @@ Name = Absorb Bulb NamePlural = Absorb Bulbs Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = A consumable bulb. If the holder is hit by a Water-type move, its Sp. Atk will rise. #------------------------------- @@ -1019,6 +1070,7 @@ Name = Cell Battery NamePlural = Cell Batteries Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = A consumable battery. If the holder is hit by an Electric-type move, its Attack will rise. #------------------------------- @@ -1027,6 +1079,7 @@ Name = Luminous Moss NamePlural = Luminous Mosses Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Sp. Def if hit by a Water-type attack. It can only be used once. #------------------------------- @@ -1035,6 +1088,7 @@ Name = Snowball NamePlural = Snowballs Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Attack if hit by an Ice-type attack. It can only be used once. #------------------------------- @@ -1043,6 +1097,7 @@ Name = Weakness Policy NamePlural = Weakness Policies Pocket = 1 Price = 1000 +BPPrice = 20 Flags = Fling_80 Description = An item to be held by a Pokémon. The holder's Attack and Sp. Atk sharply increase if hit by a move it's weak to. #------------------------------- @@ -1051,6 +1106,7 @@ Name = Blunder Policy NamePlural = Blunder Policies Pocket = 1 Price = 4000 +BPPrice = 20 Flags = Fling_80 Description = Raises Speed sharply when a Pokémon misses with a move because of accuracy. #------------------------------- @@ -1059,6 +1115,7 @@ Name = Throat Spray NamePlural = Throat Sprays Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = Raises Sp. Atk when a Pokémon uses a sound-based move. #------------------------------- @@ -1067,6 +1124,7 @@ Name = Adrenaline Orb NamePlural = Adrenaline Orbs Pocket = 1 Price = 300 +BPPrice = 10 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Speed when intimidated. It can be used only once. #------------------------------- @@ -1075,6 +1133,7 @@ Name = Room Service NamePlural = Room Services Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_100 Description = An item to be held by a Pokémon. Lowers Speed when Trick Room takes effect. #------------------------------- @@ -1119,6 +1178,7 @@ Name = Life Orb NamePlural = Life Orbs Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts the power of moves, but at the cost of some HP on each hit. #------------------------------- @@ -1127,6 +1187,7 @@ Name = Expert Belt NamePlural = Expert Belts Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a well-worn belt that slightly boosts the power of supereffective moves. #------------------------------- @@ -1136,6 +1197,7 @@ NamePlural = Metronomes Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_30 Description = A Pokémon held item that boosts a move used consecutively. Its effect is reset if another move is used. #------------------------------- @@ -1144,6 +1206,7 @@ Name = Muscle Band NamePlural = Muscle Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a headband that slightly boosts the power of physical moves. #------------------------------- @@ -1152,6 +1215,7 @@ Name = Wise Glasses NamePlural = Wise Glasses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a thick pair of glasses that slightly boosts the power of special moves. #------------------------------- @@ -1161,6 +1225,7 @@ NamePlural = Razor Claws Pocket = 1 Price = 3000 SellPrice = 2500 +BPPrice = 5 Flags = Fling_80 Description = An item to be held by a Pokémon. It is a sharply hooked claw that ups the holder's critical-hit ratio. #------------------------------- @@ -1169,6 +1234,7 @@ Name = Scope Lens NamePlural = Scope Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a lens that boosts the holder's critical-hit ratio. #------------------------------- @@ -1177,6 +1243,7 @@ Name = Wide Lens NamePlural = Wide Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a magnifying lens that slightly boosts the accuracy of moves. #------------------------------- @@ -1185,6 +1252,7 @@ Name = Zoom Lens NamePlural = Zoom Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. If the holder moves after its target, its accuracy will be boosted. #------------------------------- @@ -1193,6 +1261,7 @@ Name = King's Rock NamePlural = King's Rocks Pocket = 1 Price = 5000 +BPPrice = 5 Flags = Fling_30 Description = An item to be held by a Pokémon. When the holder inflicts damage, the target may flinch. #------------------------------- @@ -1201,6 +1270,7 @@ Name = Razor Fang NamePlural = Razor Fangs Pocket = 1 Price = 5000 +BPPrice = 5 Flags = Fling_30 Description = An item to be held by a Pokémon. It may make foes and allies flinch when the holder inflicts damage. #------------------------------- @@ -1209,6 +1279,7 @@ Name = Lagging Tail NamePlural = Lagging Tails Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. It is tremendously heavy and makes the holder move slower than usual. #------------------------------- @@ -1218,6 +1289,7 @@ NamePlural = Quick Claws Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_80 Description = An item to be held by a Pokémon. A light, sharp claw that lets the bearer move first occasionally. #------------------------------- @@ -1227,6 +1299,7 @@ NamePlural = Focus Bands Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder may endure a potential KO attack, leaving it with just 1 HP. #------------------------------- @@ -1236,6 +1309,7 @@ NamePlural = Focus Sashes Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. If it has full HP, the holder will endure one potential KO attack, leaving 1 HP. #------------------------------- @@ -1244,6 +1318,7 @@ Name = Flame Orb NamePlural = Flame Orbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that inflicts a burn on the holder in battle. #------------------------------- @@ -1252,6 +1327,7 @@ Name = Toxic Orb NamePlural = Toxic Orbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that badly poisons the holder in battle. #------------------------------- @@ -1260,6 +1336,7 @@ Name = Sticky Barb NamePlural = Sticky Barbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_80 Description = A held item that damages the holder on every turn. It may latch on to Pokémon that touch the holder. #------------------------------- @@ -1268,6 +1345,7 @@ Name = Iron Ball NamePlural = Iron Balls Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_130 Description = A Pokémon held item that cuts Speed. It makes Flying-type and levitating holders susceptible to Ground moves. #------------------------------- @@ -1277,6 +1355,7 @@ NamePlural = Ring Targets Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 10 Flags = Fling_10 Description = Moves that would otherwise have no effect will land on the Pokémon that holds it. #------------------------------- @@ -1285,6 +1364,7 @@ Name = Macho Brace NamePlural = Macho Braces Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_60 Description = An item to be held by a Pokémon. It is a stiff, heavy brace that promotes strong growth but lowers Speed. #------------------------------- @@ -1293,6 +1373,7 @@ Name = Power Weight NamePlural = Power Weights Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes HP gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1301,6 +1382,7 @@ Name = Power Bracer NamePlural = Power Bracers Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Attack gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1309,6 +1391,7 @@ Name = Power Belt NamePlural = Power Belts Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Defense gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1317,6 +1400,7 @@ Name = Power Lens NamePlural = Power Lenses Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Atk gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1325,6 +1409,7 @@ Name = Power Band NamePlural = Power Bands Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Def gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1333,6 +1418,7 @@ Name = Power Anklet NamePlural = Power Anklets Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Speed gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1871,6 +1957,7 @@ Name = Lucky Punch NamePlural = Lucky Punches Pocket = 1 Price = 1000 +BPPrice = 7 Flags = Fling_40 Description = An item to be held by Chansey. It is a pair of gloves that boosts Chansey's critical-hit ratio. #------------------------------- @@ -1919,6 +2006,7 @@ Name = Deep Sea Tooth NamePlural = Deep Sea Teeth Pocket = 1 Price = 2000 +BPPrice = 5 Flags = Fling_90 Description = An item to be held by Clamperl. A fang that gleams a sharp silver, it raises the Sp. Atk stat. #------------------------------- @@ -1927,6 +2015,7 @@ Name = Deep Sea Scale NamePlural = Deep Sea Scales Pocket = 1 Price = 2000 +BPPrice = 5 Flags = Fling_30 Description = An item to be held by Clamperl. A scale that shines a faint pink, it raises the Sp. Def stat. #------------------------------- @@ -2144,6 +2233,7 @@ Name = Everstone NamePlural = Everstones Pocket = 1 Price = 3000 +BPPrice = 5 Flags = Fling_30 Description = An item to be held by a Pokémon. The Pokémon holding this peculiar stone is prevented from evolving. #------------------------------- @@ -2153,6 +2243,7 @@ NamePlural = Dragon Scales Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_30 Description = A thick and tough scale. Dragon-type Pokémon may be holding this item when caught. #------------------------------- @@ -2162,6 +2253,7 @@ NamePlural = Upgrades Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_30 Description = A transparent device filled with all sorts of data. It was produced by Silph Co. #------------------------------- @@ -2171,6 +2263,7 @@ NamePlural = Dubious Discs Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_50 Description = A transparent device overflowing with dubious data. Its producer is unknown. #------------------------------- @@ -2180,6 +2273,7 @@ NamePlural = Protectors Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A protective item of some sort. It is extremely stiff and heavy. It is loved by a certain Pokémon. #------------------------------- @@ -2189,6 +2283,7 @@ NamePlural = Electirizers Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A box packed with a tremendous amount of electric energy. It is loved by a certain Pokémon. #------------------------------- @@ -2198,6 +2293,7 @@ NamePlural = Magmarizers Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A box packed with a tremendous amount of magma energy. It is loved by a certain Pokémon. #------------------------------- @@ -2207,6 +2303,7 @@ NamePlural = Reaper Cloths Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_10 Description = A cloth imbued with horrifyingly strong spiritual energy. It is loved by a certain Pokémon. #------------------------------- @@ -2216,6 +2313,7 @@ NamePlural = Prism Scales Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 10 Flags = Fling_30 Description = A mysterious scale that evolves certain Pokémon. It shines in rainbow colors. #------------------------------- @@ -2225,6 +2323,7 @@ NamePlural = Oval Stones Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is shaped like an egg. #------------------------------- @@ -2234,6 +2333,7 @@ NamePlural = Whipped Dreams Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A soft and sweet treat made of fluffy, puffy and whirled cream. It's loved by a certain Pokémon. #------------------------------- @@ -2243,6 +2343,7 @@ NamePlural = Sachets Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A sachet filled with slightly overwhelming fragrant perfumes. Yet it's loved by a certain Pokémon. #------------------------------- @@ -2251,6 +2352,7 @@ Name = Strawberry Sweet NamePlural = Strawberry Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A strawberry-shaped sweet. When a Milcery holds this, it will spin around happily. #------------------------------- @@ -2259,6 +2361,7 @@ Name = Love Sweet NamePlural = Love Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A heart-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2267,6 +2370,7 @@ Name = Berry Sweet NamePlural = Berry Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A berry-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2275,6 +2379,7 @@ Name = Clover Sweet NamePlural = Clover Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A clover-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2283,6 +2388,7 @@ Name = Flower Sweet NamePlural = Flower Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A flower-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2291,6 +2397,7 @@ Name = Star Sweet NamePlural = Star Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A star-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2299,6 +2406,7 @@ Name = Ribbon Sweet NamePlural = Ribbon Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A ribbon-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2307,6 +2415,7 @@ Name = Venusaurite NamePlural = Venusaurites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Venusaur hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2314,6 +2423,7 @@ Description = One of a variety of mysterious Mega Stones. Have Venusaur hold it, Name = Charizardite X NamePlural = Charizardite Xs Pocket = 1 +BPPrice = 50 Price = 0 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Charizard hold it, and it will be able to Mega Evolve. @@ -2323,6 +2433,7 @@ Name = Charizardite Y NamePlural = Charizardite Ys Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Charizard hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2331,6 +2442,7 @@ Name = Blastoisinite NamePlural = Blastoisinites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Blastoise hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2339,6 +2451,7 @@ Name = Beedrillite NamePlural = Beedrillites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Beedrill hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2347,6 +2460,7 @@ Name = Pidgeotite NamePlural = Pidgeotites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Pidgeot hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2355,6 +2469,7 @@ Name = Alakazite NamePlural = Alakazites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Alakazam hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2363,6 +2478,7 @@ Name = Slowbronite NamePlural = Slowbronites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Slowbro hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2371,6 +2487,7 @@ Name = Gengarite NamePlural = Gengarites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gengar hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2379,6 +2496,7 @@ Name = Kangaskhanite NamePlural = Kangaskhanites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Kangaskhan hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2387,6 +2505,7 @@ Name = Pinsirite NamePlural = Pinsirites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Pinsir hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2395,6 +2514,7 @@ Name = Gyaradosite NamePlural = Gyaradosites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gyarados hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2403,6 +2523,7 @@ Name = Aerodactylite NamePlural = Aerodactylites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Aerodactyl hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2411,6 +2532,7 @@ Name = Mewtwonite X NamePlural = Mewtwonite Xs Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mewtwo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2419,6 +2541,7 @@ Name = Mewtwonite Y NamePlural = Mewtwonite Ys Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mewtwo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2427,6 +2550,7 @@ Name = Ampharosite NamePlural = Ampharosites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Ampharos hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2435,6 +2559,7 @@ Name = Steelixite NamePlural = Steelixites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Steelix hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2443,6 +2568,7 @@ Name = Scizorite NamePlural = Scizorites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Scizor hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2451,6 +2577,7 @@ Name = Heracronite NamePlural = Heracronites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Heracross hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2459,6 +2586,7 @@ Name = Houndoominite NamePlural = Houndoominites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Houndoom hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2467,6 +2595,7 @@ Name = Tyranitarite NamePlural = Tyranitarites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Tyranitar hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2475,6 +2604,7 @@ Name = Sceptilite NamePlural = Sceptilites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sceptile hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2483,6 +2613,7 @@ Name = Blazikenite NamePlural = Blazikenites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Blaziken hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2491,6 +2622,7 @@ Name = Swampertite NamePlural = Swampertites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Swampert hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2499,6 +2631,7 @@ Name = Gardevoirite NamePlural = Gardevoirites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gardevoir hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2507,6 +2640,7 @@ Name = Sablenite NamePlural = Sablenites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sableye hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2515,6 +2649,7 @@ Name = Mawilite NamePlural = Mawilites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mawile hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2523,6 +2658,7 @@ Name = Aggronite NamePlural = Aggronites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Aggron hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2531,6 +2667,7 @@ Name = Medichamite NamePlural = Medichamites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Medicham hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2539,6 +2676,7 @@ Name = Manectite NamePlural = Manectites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Manectric hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2547,6 +2685,7 @@ Name = Sharpedonite NamePlural = Sharpedonites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sharpedo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2555,6 +2694,7 @@ Name = Cameruptite NamePlural = Cameruptites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Camerupt hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2563,6 +2703,7 @@ Name = Altarianite NamePlural = Altarianites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Altaria hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2571,6 +2712,7 @@ Name = Banettite NamePlural = Banettites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Banette hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2579,6 +2721,7 @@ Name = Absolite NamePlural = Absolites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Absol hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2587,6 +2730,7 @@ Name = Glalitite NamePlural = Glalitites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Glalie hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2595,6 +2739,7 @@ Name = Salamencite NamePlural = Salamencites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Salamence hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2603,6 +2748,7 @@ Name = Metagrossite NamePlural = Metagrossites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Metagross hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2611,6 +2757,7 @@ Name = Latiasite NamePlural = Latiasites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Latias hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2619,6 +2766,7 @@ Name = Latiosite NamePlural = Latiosites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Latios hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2627,6 +2775,7 @@ Name = Lopunnite NamePlural = Lopunnites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Lopunny hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2635,6 +2784,7 @@ Name = Garchompite NamePlural = Garchompites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Garchomp hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2643,6 +2793,7 @@ Name = Lucarionite NamePlural = Lucarionites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Lucario hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2651,6 +2802,7 @@ Name = Abomasite NamePlural = Abomasites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Abomasnow hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2659,6 +2811,7 @@ Name = Galladite NamePlural = Galladites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gallade hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2667,6 +2820,7 @@ Name = Audinite NamePlural = Audinites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Audino hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2675,6 +2829,7 @@ Name = Diancite NamePlural = Diancites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Diancie hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2684,6 +2839,7 @@ NamePlural = Red Orbs Pocket = 1 Price = 10000 SellPrice = 0 +BPPrice = 50 Description = A shiny red orb that is said to have a legend tied to it. It's known to be connected with the Hoenn region. #------------------------------- [BLUEORB] @@ -2692,6 +2848,7 @@ NamePlural = Blue Orbs Pocket = 1 Price = 10000 SellPrice = 0 +BPPrice = 50 Description = A shiny blue orb that is said to have a legend tied to it. It's known to be connected with the Hoenn region. #------------------------------- [POTION] @@ -2729,6 +2886,7 @@ Name = Max Potion NamePlural = Max Potions Pocket = 2 Price = 2500 +BPPrice = 2 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -2908,6 +3066,7 @@ Name = Max Revive NamePlural = Max Revives Pocket = 2 Price = 4000 +BPPrice = 20 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -3029,6 +3188,7 @@ Name = Ether NamePlural = Ethers Pocket = 2 Price = 1200 +BPPrice = 4 FieldUse = OnPokemon BattleUse = OnMove Flags = Fling_30 @@ -3069,6 +3229,7 @@ Name = PP Up NamePlural = PP Ups Pocket = 2 Price = 10000 +BPPrice = 10 FieldUse = OnPokemon Flags = Fling_30 Description = It slightly raises the maximum PP of a selected move that has been learned by the target Pokémon. @@ -3195,6 +3356,7 @@ Name = Lonely Mint NamePlural = Lonely Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Attack will grow more easily, but its Defense will grow more slowly. @@ -3204,6 +3366,7 @@ Name = Adamant Mint NamePlural = Adamant Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Attack will grow more easily, but its Sp. Atk will grow more slowly. @@ -3213,6 +3376,7 @@ Name = Naughty Mint NamePlural = Naughty Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Attack will grow more easily, but its Sp. Def will grow more slowly. @@ -3222,6 +3386,7 @@ Name = Brave Mint NamePlural = Brave Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Attack will grow more easily, but its Speed will grow more slowly. @@ -3231,6 +3396,7 @@ Name = Bold Mint NamePlural = Bold Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Defense will grow more easily, but its Attack will grow more slowly. @@ -3240,6 +3406,7 @@ Name = Impish Mint NamePlural = Impish Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Defense will grow more easily, but its Sp. Atk will grow more slowly. @@ -3249,6 +3416,7 @@ Name = Lax Mint NamePlural = Lax Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Defense will grow more easily, but its Sp. Def will grow more slowly. @@ -3258,6 +3426,7 @@ Name = Relaxed Mint NamePlural = Relaxed Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Defense will grow more easily, but its Speed will grow more slowly. @@ -3267,6 +3436,7 @@ Name = Modest Mint NamePlural = Modest Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Atk will grow more easily, but its Attack will grow more slowly. @@ -3276,6 +3446,7 @@ Name = Mild Mint NamePlural = Mild Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Atk will grow more easily, but its Defense will grow more slowly. @@ -3285,6 +3456,7 @@ Name = Rash Mint NamePlural = Rash Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Atk will grow more easily, but its Sp. Def will grow more slowly. @@ -3294,6 +3466,7 @@ Name = Quiet Mint NamePlural = Quiet Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Atk will grow more easily, but its Speed will grow more slowly. @@ -3303,6 +3476,7 @@ Name = Calm Mint NamePlural = Calm Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Def will grow more easily, but its Attack will grow more slowly. @@ -3312,6 +3486,7 @@ Name = Gentle Mint NamePlural = Gentle Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Def will grow more easily, but its Defense will grow more slowly. @@ -3321,6 +3496,7 @@ Name = Careful Mint NamePlural = Careful Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Def will grow more easily, but its Sp. Atk will grow more slowly. @@ -3330,6 +3506,7 @@ Name = Sassy Mint NamePlural = Sassy Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Def will grow more easily, but its Speed will grow more slowly. @@ -3339,6 +3516,7 @@ Name = Timid Mint NamePlural = Timid Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Speed will grow more easily, but its Attack will grow more slowly. @@ -3348,6 +3526,7 @@ Name = Hasty Mint NamePlural = Hasty Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Speed will grow more easily, but its Defense will grow more slowly. @@ -3357,6 +3536,7 @@ Name = Jolly Mint NamePlural = Jolly Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Speed will grow more easily, but its Sp. Atk will grow more slowly. @@ -3366,6 +3546,7 @@ Name = Naive Mint NamePlural = Naive Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Speed will grow more easily, but its Sp. Def will grow more slowly. @@ -3375,6 +3556,7 @@ Name = Serious Mint NamePlural = Serious Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, all of its stats will grow at an equal rate. @@ -3384,6 +3566,7 @@ Name = Ability Capsule NamePlural = Ability Capsule Pocket = 2 Price = 10000 +BPPrice = 50 FieldUse = OnPokemon Description = A capsule that allows a Pokémon with two Abilities to switch between these Abilities when it is used. #------------------------------- @@ -3392,6 +3575,7 @@ Name = Ability Patch NamePlural = Ability Patches Pocket = 2 Price = 10000 +BPPrice = 200 FieldUse = OnPokemon Description = A patch that allows a Pokémon with a regular Ability to have a rare Ability. #------------------------------- @@ -3445,6 +3629,7 @@ Name = Rare Candy NamePlural = Rare Candies Pocket = 2 Price = 10000 +BPPrice = 20 FieldUse = OnPokemon Flags = Fling_30 Description = A candy that is packed with energy. It raises the level of a single Pokémon by one. @@ -3689,6 +3874,7 @@ Name = TM01 NamePlural = TM01s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_150 Move = FOCUSPUNCH @@ -3699,6 +3885,7 @@ Name = TM02 NamePlural = TM02s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = DRAGONCLAW @@ -3709,6 +3896,7 @@ Name = TM03 NamePlural = TM03s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = WATERPULSE @@ -3719,6 +3907,7 @@ Name = TM04 NamePlural = TM04s Pocket = 4 Price = 1500 +BPPrice = 48 FieldUse = TR Flags = Fling_10 Move = CALMMIND @@ -3729,6 +3918,7 @@ Name = TM05 NamePlural = TM05s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ROAR @@ -3739,6 +3929,7 @@ Name = TM06 NamePlural = TM06s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = TOXIC @@ -3749,6 +3940,7 @@ Name = TM07 NamePlural = TM07s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = HAIL @@ -3759,6 +3951,7 @@ Name = TM08 NamePlural = TM08s Pocket = 4 Price = 1500 +BPPrice = 48 FieldUse = TR Flags = Fling_10 Move = BULKUP @@ -3769,6 +3962,7 @@ Name = TM09 NamePlural = TM09s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_25 Move = BULLETSEED @@ -3779,6 +3973,7 @@ Name = TM10 NamePlural = TM10s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = WORKUP @@ -3789,6 +3984,7 @@ Name = TM11 NamePlural = TM11s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SUNNYDAY @@ -3799,6 +3995,7 @@ Name = TM12 NamePlural = TM12s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = TAUNT @@ -3809,6 +4006,7 @@ Name = TM13 NamePlural = TM13s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = ICEBEAM @@ -3819,6 +4017,7 @@ Name = TM14 NamePlural = TM14s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_110 Move = BLIZZARD @@ -3829,6 +4028,7 @@ Name = TM15 NamePlural = TM15s Pocket = 4 Price = 7500 +BPPrice = 32 FieldUse = TR Flags = Fling_150 Move = HYPERBEAM @@ -3839,6 +4039,7 @@ Name = TM16 NamePlural = TM16s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = LIGHTSCREEN @@ -3849,6 +4050,7 @@ Name = TM17 NamePlural = TM17s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = PROTECT @@ -3859,6 +4061,7 @@ Name = TM18 NamePlural = TM18s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = RAINDANCE @@ -3869,6 +4072,7 @@ Name = TM19 NamePlural = TM19s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_75 Move = GIGADRAIN @@ -3879,6 +4083,7 @@ Name = TM20 NamePlural = TM20s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SAFEGUARD @@ -3889,6 +4094,7 @@ Name = TM21 NamePlural = TM21s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = DAZZLINGGLEAM @@ -3899,6 +4105,7 @@ Name = TM22 NamePlural = TM22s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_120 Move = SOLARBEAM @@ -3909,6 +4116,7 @@ Name = TM23 NamePlural = TM23s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_100 Move = IRONTAIL @@ -3919,6 +4127,7 @@ Name = TM24 NamePlural = TM24s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = THUNDERBOLT @@ -3929,6 +4138,7 @@ Name = TM25 NamePlural = TM25s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_110 Move = THUNDER @@ -3939,6 +4149,7 @@ Name = TM26 NamePlural = TM26s Pocket = 4 Price = 3000 +BPPrice = 80 FieldUse = TR Flags = Fling_100 Move = EARTHQUAKE @@ -3949,6 +4160,7 @@ Name = TM27 NamePlural = TM27s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_65 Move = LOWSWEEP @@ -3959,6 +4171,7 @@ Name = TM28 NamePlural = TM28s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = DIG @@ -3969,6 +4182,7 @@ Name = TM29 NamePlural = TM29s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = PSYCHIC @@ -3979,6 +4193,7 @@ Name = TM30 NamePlural = TM30s Pocket = 4 Price = 3000 +BPPrice = 64 FieldUse = TR Flags = Fling_80 Move = SHADOWBALL @@ -3989,6 +4204,7 @@ Name = TM31 NamePlural = TM31s Pocket = 4 Price = 3000 +BPPrice = 40 FieldUse = TR Flags = Fling_75 Move = BRICKBREAK @@ -3999,6 +4215,7 @@ Name = TM32 NamePlural = TM32s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = DOUBLETEAM @@ -4009,6 +4226,7 @@ Name = TM33 NamePlural = TM33s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = REFLECT @@ -4019,6 +4237,7 @@ Name = TM34 NamePlural = TM34s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = SHOCKWAVE @@ -4029,6 +4248,7 @@ Name = TM35 NamePlural = TM35s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = FLAMETHROWER @@ -4039,6 +4259,7 @@ Name = TM36 NamePlural = TM36s Pocket = 4 Price = 3000 +BPPrice = 80 FieldUse = TR Flags = Fling_90 Move = SLUDGEBOMB @@ -4049,6 +4270,7 @@ Name = TM37 NamePlural = TM37s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SANDSTORM @@ -4059,6 +4281,7 @@ Name = TM38 NamePlural = TM38s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_110 Move = FIREBLAST @@ -4069,6 +4292,7 @@ Name = TM39 NamePlural = TM39s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = ROCKTOMB @@ -4079,6 +4303,7 @@ Name = TM40 NamePlural = TM40s Pocket = 4 Price = 3000 +BPPrice = 40 FieldUse = TR Flags = Fling_60 Move = AERIALACE @@ -4089,6 +4314,7 @@ Name = TM41 NamePlural = TM41s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = TORMENT @@ -4099,6 +4325,7 @@ Name = TM42 NamePlural = TM42s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = FACADE @@ -4109,6 +4336,7 @@ Name = TM43 NamePlural = TM43s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = VOLTSWITCH @@ -4119,6 +4347,7 @@ Name = TM44 NamePlural = TM44s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = REST @@ -4129,6 +4358,7 @@ Name = TM45 NamePlural = TM45s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ATTRACT @@ -4139,6 +4369,7 @@ Name = TM46 NamePlural = TM46s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = THIEF @@ -4149,6 +4380,7 @@ Name = TM47 NamePlural = TM47s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = STEELWING @@ -4159,6 +4391,7 @@ Name = TM48 NamePlural = TM48s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SKILLSWAP @@ -4169,6 +4402,7 @@ Name = TM49 NamePlural = TM49s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = SCALD @@ -4179,6 +4413,7 @@ Name = TM50 NamePlural = TM50s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_130 Move = OVERHEAT @@ -4189,6 +4424,7 @@ Name = TM51 NamePlural = TM51s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ROOST @@ -4199,6 +4435,7 @@ Name = TM52 NamePlural = TM52s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_120 Move = FOCUSBLAST @@ -4209,6 +4446,7 @@ Name = TM53 NamePlural = TM53s Pocket = 4 Price = 3000 +BPPrice = 64 FieldUse = TR Flags = Fling_90 Move = ENERGYBALL @@ -4219,6 +4457,7 @@ Name = TM54 NamePlural = TM54s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_40 Move = FALSESWIPE @@ -4229,6 +4468,7 @@ Name = TM55 NamePlural = TM55s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_65 Move = BRINE @@ -4239,6 +4479,7 @@ Name = TM56 NamePlural = TM56s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = FLING @@ -4249,6 +4490,7 @@ Name = TM57 NamePlural = TM57s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_50 Move = CHARGEBEAM @@ -4259,6 +4501,7 @@ Name = TM58 NamePlural = TM58s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ENDURE @@ -4269,6 +4512,7 @@ Name = TM59 NamePlural = TM59s Pocket = 4 Price = 3000 +BPPrice = 80 FieldUse = TR Flags = Fling_85 Move = DRAGONPULSE @@ -4279,6 +4523,7 @@ Name = TM60 NamePlural = TM60s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_75 Move = DRAINPUNCH @@ -4289,6 +4534,7 @@ Name = TM61 NamePlural = TM61s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = WILLOWISP @@ -4299,6 +4545,7 @@ Name = TM62 NamePlural = TM62s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = BUGBUZZ @@ -4309,6 +4556,7 @@ Name = TM63 NamePlural = TM63s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = NASTYPLOT @@ -4319,6 +4567,7 @@ Name = TM64 NamePlural = TM64s Pocket = 4 Price = 7500 +BPPrice = 32 FieldUse = TR Flags = Fling_250 Move = EXPLOSION @@ -4329,6 +4578,7 @@ Name = TM65 NamePlural = TM65s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = SHADOWCLAW @@ -4339,6 +4589,7 @@ Name = TM66 NamePlural = TM66s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_50 Move = PAYBACK @@ -4349,6 +4600,7 @@ Name = TM67 NamePlural = TM67s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = RECYCLE @@ -4359,6 +4611,7 @@ Name = TM68 NamePlural = TM68s Pocket = 4 Price = 7500 +BPPrice = 32 FieldUse = TR Flags = Fling_150 Move = GIGAIMPACT @@ -4369,6 +4622,7 @@ Name = TM69 NamePlural = TM69s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ROCKPOLISH @@ -4379,6 +4633,7 @@ Name = TM70 NamePlural = TM70s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = FLASH @@ -4389,6 +4644,7 @@ Name = TM71 NamePlural = TM71s Pocket = 4 Price = 3000 +BPPrice = 80 FieldUse = TR Flags = Fling_100 Move = STONEEDGE @@ -4399,6 +4655,7 @@ Name = TM72 NamePlural = TM72s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = AVALANCHE @@ -4409,6 +4666,7 @@ Name = TM73 NamePlural = TM73s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = THUNDERWAVE @@ -4419,6 +4677,7 @@ Name = TM74 NamePlural = TM74s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = GYROBALL @@ -4429,6 +4688,7 @@ Name = TM75 NamePlural = TM75s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SWORDSDANCE @@ -4439,6 +4699,7 @@ Name = TM76 NamePlural = TM76s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = STEALTHROCK @@ -4449,6 +4710,7 @@ Name = TM77 NamePlural = TM77s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = PSYCHUP @@ -4459,6 +4721,7 @@ Name = TM78 NamePlural = TM78s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_55 Move = SNARL @@ -4469,6 +4732,7 @@ Name = TM79 NamePlural = TM79s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = DARKPULSE @@ -4479,6 +4743,7 @@ Name = TM80 NamePlural = TM80s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_75 Move = ROCKSLIDE @@ -4489,6 +4754,7 @@ Name = TM81 NamePlural = TM81s Pocket = 4 Price = 3000 +BPPrice = 64 FieldUse = TR Flags = Fling_80 Move = XSCISSOR @@ -4499,6 +4765,7 @@ Name = TM82 NamePlural = TM82s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SLEEPTALK @@ -4509,6 +4776,7 @@ Name = TM83 NamePlural = TM83s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = BULLDOZE @@ -4519,6 +4787,7 @@ Name = TM84 NamePlural = TM84s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = POISONJAB @@ -4529,6 +4798,7 @@ Name = TM85 NamePlural = TM85s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_100 Move = DREAMEATER @@ -4539,6 +4809,7 @@ Name = TM86 NamePlural = TM86s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = GRASSKNOT @@ -4549,6 +4820,7 @@ Name = TM87 NamePlural = TM87s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SWAGGER @@ -4559,6 +4831,7 @@ Name = TM88 NamePlural = TM88s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = PLUCK @@ -4569,6 +4842,7 @@ Name = TM89 NamePlural = TM89s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = UTURN @@ -4579,6 +4853,7 @@ Name = TM90 NamePlural = TM90s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SUBSTITUTE @@ -4589,6 +4864,7 @@ Name = TM91 NamePlural = TM91s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = FLASHCANNON @@ -4599,6 +4875,7 @@ Name = TM92 NamePlural = TM92s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = TRICKROOM @@ -4609,6 +4886,7 @@ Name = TM93 NamePlural = TM93s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_50 Move = CUT @@ -4619,6 +4897,7 @@ Name = TM94 NamePlural = TM94s Pocket = 4 Price = 2000 +BPPrice = 40 FieldUse = TR Flags = Fling_90 Move = FLY @@ -4629,6 +4908,7 @@ Name = TM95 NamePlural = TM95s Pocket = 4 Price = 2500 +BPPrice = 64 FieldUse = TR Flags = Fling_90 Move = SURF @@ -4639,6 +4919,7 @@ Name = TM96 NamePlural = TM96s Pocket = 4 Price = 2000 +BPPrice = 40 FieldUse = TR Flags = Fling_80 Move = STRENGTH @@ -4649,6 +4930,7 @@ Name = TM97 NamePlural = TM97s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = DEFOG @@ -4659,6 +4941,7 @@ Name = TM98 NamePlural = TM98s Pocket = 4 Price = 2000 +BPPrice = 40 FieldUse = TR Flags = Fling_40 Move = ROCKSMASH @@ -4669,6 +4952,7 @@ Name = TM99 NamePlural = TM99s Pocket = 4 Price = 2500 +BPPrice = 64 FieldUse = TR Flags = Fling_80 Move = WATERFALL @@ -4679,6 +4963,7 @@ Name = TM100 NamePlural = TM100s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = ROCKCLIMB @@ -5695,8 +5980,8 @@ Pocket = 7 Price = 20 FieldUse = OnPokemon BattleUse = OnPokemon -Consumable = false Flags = Fling_30 +Consumable = false Description = A blue flute made from blown glass. Its melody awakens a single Pokémon from sleep. #------------------------------- [YELLOWFLUTE] @@ -5705,8 +5990,8 @@ NamePlural = Yellow Flutes Pocket = 7 Price = 20 BattleUse = OnBattler -Consumable = false Flags = Fling_30 +Consumable = false Description = A yellow flute made from blown glass. Its melody snaps a single Pokémon out of confusion. #------------------------------- [REDFLUTE] @@ -5715,8 +6000,8 @@ NamePlural = Red Flutes Pocket = 7 Price = 20 BattleUse = OnBattler -Consumable = false Flags = Fling_30 +Consumable = false Description = A red flute made from blown glass. Its melody snaps a single Pokémon out of infatuation. #------------------------------- [POKEDOLL] diff --git a/PBS/items.txt b/PBS/items.txt index a1cdb6091..4642a646e 100644 --- a/PBS/items.txt +++ b/PBS/items.txt @@ -93,6 +93,7 @@ Name = Fire Stone NamePlural = Fire Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is colored orange. @@ -102,6 +103,7 @@ Name = Thunder Stone NamePlural = Thunder Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a thunderbolt pattern. @@ -111,6 +113,7 @@ Name = Water Stone NamePlural = Water Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is a clear, light blue. @@ -120,6 +123,7 @@ Name = Leaf Stone NamePlural = Leaf Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a leaf pattern. @@ -129,6 +133,7 @@ Name = Moon Stone NamePlural = Moon Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as black as the night sky. @@ -138,6 +143,7 @@ Name = Sun Stone NamePlural = Sun Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as red as the sun. @@ -147,6 +153,7 @@ Name = Dusk Stone NamePlural = Dusk Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is as dark as dark can be. @@ -156,6 +163,7 @@ Name = Dawn Stone NamePlural = Dawn Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It sparkles like eyes. @@ -165,6 +173,7 @@ Name = Shiny Stone NamePlural = Shiny Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It shines with a dazzling light. @@ -174,6 +183,7 @@ Name = Ice Stone NamePlural = Ice Stones Pocket = 1 Price = 3000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar stone that makes certain species of Pokémon evolve. It has a snowflake pattern. @@ -183,6 +193,7 @@ Name = Sweet Apple NamePlural = Sweet Apples Pocket = 1 Price = 2200 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar apple that can make a certain species of Pokémon evolve. It's exceptionally sweet. @@ -192,6 +203,7 @@ Name = Tart Apple NamePlural = Tart Apples Pocket = 1 Price = 2200 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A peculiar apple that can make a certain species of Pokémon evolve. It's exceptionally tart. @@ -202,6 +214,7 @@ NamePlural = Cracked Pots Pocket = 1 Price = 3000 SellPrice = 800 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar cracked teapot that can make a certain species of Pokémon evolve. It makes delicious tea. @@ -212,6 +225,7 @@ NamePlural = Chipped Pots Pocket = 1 Price = 3000 SellPrice = 19000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_80 Description = A peculiar chipped teapot that can make a certain species of Pokémon evolve. It makes delicious tea. @@ -221,6 +235,7 @@ Name = Galarica Cuff NamePlural = Galarica Cuffs Pocket = 1 Price = 6000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A cuff made from woven-together Galarica Twigs. Giving it to a Galarian Slowpoke would make it very happy. @@ -230,6 +245,7 @@ Name = Galarica Wreath NamePlural = Galarica Wreaths Pocket = 1 Price = 6000 +BPPrice = 5 FieldUse = OnPokemon Flags = EvolutionStone,Fling_30 Description = A wreath made from woven-together Galarica Twigs. A Galarian Slowpoke wearing this would be very happy. @@ -683,6 +699,7 @@ NamePlural = Air Balloons Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder will float in the air until hit. Once hit, this item will burst. #------------------------------- @@ -692,6 +709,7 @@ NamePlural = Bright Powders Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It casts a tricky glare that lowers the opponent's accuracy. #------------------------------- @@ -701,6 +719,7 @@ NamePlural = Eviolites Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_40 Description = A mysterious evolutionary lump. When held, it raises the Defense and Sp. Def if the holder can still evolve. #------------------------------- @@ -710,6 +729,7 @@ NamePlural = Float Stones Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 10 Flags = Fling_30 Description = A very light stone. It reduces the weight of a Pokémon when held. #------------------------------- @@ -719,6 +739,7 @@ NamePlural = Destiny Knots Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 10 Flags = Fling_10 Description = A long, thin, bright-red string to be held by a Pokémon. If the holder becomes infatuated, so does the foe. #------------------------------- @@ -728,6 +749,7 @@ NamePlural = Rocky Helmets Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_60 Description = If the holder of this item takes damage, the attacker will also be damaged upon contact. #------------------------------- @@ -736,6 +758,7 @@ Name = Assault Vest NamePlural = Assault Vests Pocket = 1 Price = 1000 +BPPrice = 25 Flags = Fling_80 Description = An item to be held by a Pokémon. This offensive vest raises Sp. Def but prevents the use of status moves. #------------------------------- @@ -745,6 +768,7 @@ NamePlural = Safety Goggles Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_80 Description = An item to be held by a Pokémon. They protect the holder from weather-related damage and powder. #------------------------------- @@ -754,6 +778,7 @@ NamePlural = Protective Pads Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_30 Description = An item to be held by a Pokémon. They protect the holder from effects caused by making contact. #------------------------------- @@ -763,6 +788,7 @@ NamePlural = pairs of Heavy-Duty Boots Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_80 Description = These boots prevent the effects of traps set on the battlefield. #------------------------------- @@ -772,6 +798,7 @@ NamePlural = Utility Umbrellas Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_60 Description = An item to be held by a Pokémon. This sturdy umbrella protects the holder from the effects of rain and sun. #------------------------------- @@ -781,6 +808,7 @@ NamePlural = Eject Buttons Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 20 Flags = Fling_30 Description = If the holder is hit by an attack, it will switch with another Pokémon in your party. #------------------------------- @@ -790,6 +818,7 @@ NamePlural = Eject Packs Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 20 Flags = Fling_50 Description = An item to be held by a Pokémon. When the holder's stats are lowered, it will be switched out of battle. #------------------------------- @@ -799,6 +828,7 @@ NamePlural = Red Cards Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 20 Flags = Fling_10 Description = A card with a mysterious power. When the holder is struck by a foe, the attacker is removed from battle. #------------------------------- @@ -825,6 +855,7 @@ Name = Lucky Egg NamePlural = Lucky Eggs Pocket = 1 Price = 10000 +BPPrice = 77 Flags = Fling_30 Description = An item to be held by a Pokémon. It is an egg filled with happiness that earns extra Exp. Points in battle. #------------------------------- @@ -849,6 +880,7 @@ Name = Soothe Bell NamePlural = Soothe Bells Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. The comforting chime of this bell calms the holder, making it friendly. #------------------------------- @@ -865,6 +897,7 @@ Name = Choice Band NamePlural = Choice Bands Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. This headband ups Attack, but allows the use of only one move. #------------------------------- @@ -873,6 +906,7 @@ Name = Choice Specs NamePlural = Choice Specs Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. These curious glasses boost Sp. Atk but allows the use of only one move. #------------------------------- @@ -881,6 +915,7 @@ Name = Choice Scarf NamePlural = Choice Scarves Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. This scarf boosts Speed but allows the use of only one move. #------------------------------- @@ -889,6 +924,7 @@ Name = Heat Rock NamePlural = Heat Rocks Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Sunny Day used by the holder. #------------------------------- @@ -897,6 +933,7 @@ Name = Damp Rock NamePlural = Damp Rocks Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_60 Description = A Pokémon held item that extends the duration of the move Rain Dance used by the holder. #------------------------------- @@ -905,6 +942,7 @@ Name = Smooth Rock NamePlural = Smooth Rocks Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = A Pokémon held item that extends the duration of the move Sandstorm used by the holder. #------------------------------- @@ -913,6 +951,7 @@ Name = Icy Rock NamePlural = Icy Rocks Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_40 Description = A Pokémon held item that extends the duration of the move Hail used by the holder. #------------------------------- @@ -921,6 +960,7 @@ Name = Terrain Extender NamePlural = Terrain Extenders Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_60 Description = An item to be held by a Pokémon. It extends the duration of the terrain caused by the holder. #------------------------------- @@ -929,6 +969,7 @@ Name = Light Clay NamePlural = Light Clays Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_30 Description = An item to be held by a Pokémon. Protective moves like Light Screen and Reflect will be effective longer. #------------------------------- @@ -937,6 +978,7 @@ Name = Grip Claw NamePlural = Grip Claws Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_90 Description = A Pokémon held item that extends the duration of multiturn attacks like Bind and Wrap. #------------------------------- @@ -946,6 +988,7 @@ NamePlural = Binding Bands Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 15 Flags = Fling_30 Description = A band that increases the power of binding moves when held. #------------------------------- @@ -954,6 +997,7 @@ Name = Big Root NamePlural = Big Roots Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = A Pokémon held item that boosts the power of HP-stealing moves to let the holder recover more HP. #------------------------------- @@ -963,6 +1007,7 @@ NamePlural = Black Sludges Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_30 Description = A held item that gradually restores the HP of Poison-type Pokémon. It inflicts damage on all other types. #------------------------------- @@ -971,6 +1016,7 @@ Name = Leftovers NamePlural = Leftovers Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder's HP is gradually restored during battle. #------------------------------- @@ -979,6 +1025,7 @@ Name = Shell Bell NamePlural = Shell Bells Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_30 Description = An item to be held by a Pokémon. The holder's HP is restored a little every time it inflicts damage. #------------------------------- @@ -987,6 +1034,7 @@ Name = Mental Herb NamePlural = Mental Herbs Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. It snaps the holder out of infatuation. It can be used only once. #------------------------------- @@ -995,6 +1043,7 @@ Name = White Herb NamePlural = White Herbs Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. It restores any lowered stat in battle. It can be used only once. #------------------------------- @@ -1003,6 +1052,7 @@ Name = Power Herb NamePlural = Power Herbs Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_10 Description = A single-use item to be held by a Pokémon. It allows the immediate use of a move that charges up first. #------------------------------- @@ -1011,6 +1061,7 @@ Name = Absorb Bulb NamePlural = Absorb Bulbs Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = A consumable bulb. If the holder is hit by a Water-type move, its Sp. Atk will rise. #------------------------------- @@ -1019,6 +1070,7 @@ Name = Cell Battery NamePlural = Cell Batteries Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = A consumable battery. If the holder is hit by an Electric-type move, its Attack will rise. #------------------------------- @@ -1027,6 +1079,7 @@ Name = Luminous Moss NamePlural = Luminous Mosses Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Sp. Def if hit by a Water-type attack. It can only be used once. #------------------------------- @@ -1035,6 +1088,7 @@ Name = Snowball NamePlural = Snowballs Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Attack if hit by an Ice-type attack. It can only be used once. #------------------------------- @@ -1043,6 +1097,7 @@ Name = Weakness Policy NamePlural = Weakness Policies Pocket = 1 Price = 1000 +BPPrice = 20 Flags = Fling_80 Description = An item to be held by a Pokémon. The holder's Attack and Sp. Atk sharply increase if hit by a move it's weak to. #------------------------------- @@ -1051,6 +1106,7 @@ Name = Blunder Policy NamePlural = Blunder Policies Pocket = 1 Price = 4000 +BPPrice = 20 Flags = Fling_80 Description = Raises Speed sharply when a Pokémon misses with a move because of accuracy. #------------------------------- @@ -1059,6 +1115,7 @@ Name = Throat Spray NamePlural = Throat Sprays Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_30 Description = Raises Sp. Atk when a Pokémon uses a sound-based move. #------------------------------- @@ -1067,6 +1124,7 @@ Name = Adrenaline Orb NamePlural = Adrenaline Orbs Pocket = 1 Price = 300 +BPPrice = 10 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts Speed when intimidated. It can be used only once. #------------------------------- @@ -1075,6 +1133,7 @@ Name = Room Service NamePlural = Room Services Pocket = 1 Price = 4000 +BPPrice = 15 Flags = Fling_100 Description = An item to be held by a Pokémon. Lowers Speed when Trick Room takes effect. #------------------------------- @@ -1119,6 +1178,7 @@ Name = Life Orb NamePlural = Life Orbs Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_30 Description = An item to be held by a Pokémon. It boosts the power of moves, but at the cost of some HP on each hit. #------------------------------- @@ -1127,6 +1187,7 @@ Name = Expert Belt NamePlural = Expert Belts Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a well-worn belt that slightly boosts the power of supereffective moves. #------------------------------- @@ -1136,6 +1197,7 @@ NamePlural = Metronomes Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_30 Description = A Pokémon held item that boosts a move used consecutively. Its effect is reset if another move is used. #------------------------------- @@ -1144,6 +1206,7 @@ Name = Muscle Band NamePlural = Muscle Bands Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a headband that slightly boosts the power of physical moves. #------------------------------- @@ -1152,6 +1215,7 @@ Name = Wise Glasses NamePlural = Wise Glasses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a thick pair of glasses that slightly boosts the power of special moves. #------------------------------- @@ -1161,6 +1225,7 @@ NamePlural = Razor Claws Pocket = 1 Price = 3000 SellPrice = 2500 +BPPrice = 5 Flags = Fling_80 Description = An item to be held by a Pokémon. It is a sharply hooked claw that ups the holder's critical-hit ratio. #------------------------------- @@ -1169,6 +1234,7 @@ Name = Scope Lens NamePlural = Scope Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a lens that boosts the holder's critical-hit ratio. #------------------------------- @@ -1177,6 +1243,7 @@ Name = Wide Lens NamePlural = Wide Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. It is a magnifying lens that slightly boosts the accuracy of moves. #------------------------------- @@ -1185,6 +1252,7 @@ Name = Zoom Lens NamePlural = Zoom Lenses Pocket = 1 Price = 4000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. If the holder moves after its target, its accuracy will be boosted. #------------------------------- @@ -1193,6 +1261,7 @@ Name = King's Rock NamePlural = King's Rocks Pocket = 1 Price = 5000 +BPPrice = 5 Flags = Fling_30 Description = An item to be held by a Pokémon. When the holder inflicts damage, the target may flinch. #------------------------------- @@ -1201,6 +1270,7 @@ Name = Razor Fang NamePlural = Razor Fangs Pocket = 1 Price = 5000 +BPPrice = 5 Flags = Fling_30 Description = An item to be held by a Pokémon. It may make foes and allies flinch when the holder inflicts damage. #------------------------------- @@ -1209,6 +1279,7 @@ Name = Lagging Tail NamePlural = Lagging Tails Pocket = 1 Price = 4000 +BPPrice = 25 Flags = Fling_10 Description = An item to be held by a Pokémon. It is tremendously heavy and makes the holder move slower than usual. #------------------------------- @@ -1218,6 +1289,7 @@ NamePlural = Quick Claws Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 25 Flags = Fling_80 Description = An item to be held by a Pokémon. A light, sharp claw that lets the bearer move first occasionally. #------------------------------- @@ -1227,6 +1299,7 @@ NamePlural = Focus Bands Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 48 Flags = Fling_10 Description = An item to be held by a Pokémon. The holder may endure a potential KO attack, leaving it with just 1 HP. #------------------------------- @@ -1236,6 +1309,7 @@ NamePlural = Focus Sashes Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 15 Flags = Fling_10 Description = An item to be held by a Pokémon. If it has full HP, the holder will endure one potential KO attack, leaving 1 HP. #------------------------------- @@ -1244,6 +1318,7 @@ Name = Flame Orb NamePlural = Flame Orbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that inflicts a burn on the holder in battle. #------------------------------- @@ -1252,6 +1327,7 @@ Name = Toxic Orb NamePlural = Toxic Orbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_30 Description = An item to be held by a Pokémon. It is a bizarre orb that badly poisons the holder in battle. #------------------------------- @@ -1260,6 +1336,7 @@ Name = Sticky Barb NamePlural = Sticky Barbs Pocket = 1 Price = 4000 +BPPrice = 16 Flags = Fling_80 Description = A held item that damages the holder on every turn. It may latch on to Pokémon that touch the holder. #------------------------------- @@ -1268,6 +1345,7 @@ Name = Iron Ball NamePlural = Iron Balls Pocket = 1 Price = 4000 +BPPrice = 10 Flags = Fling_130 Description = A Pokémon held item that cuts Speed. It makes Flying-type and levitating holders susceptible to Ground moves. #------------------------------- @@ -1277,6 +1355,7 @@ NamePlural = Ring Targets Pocket = 1 Price = 3000 SellPrice = 2000 +BPPrice = 10 Flags = Fling_10 Description = Moves that would otherwise have no effect will land on the Pokémon that holds it. #------------------------------- @@ -1285,6 +1364,7 @@ Name = Macho Brace NamePlural = Macho Braces Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_60 Description = An item to be held by a Pokémon. It is a stiff, heavy brace that promotes strong growth but lowers Speed. #------------------------------- @@ -1293,6 +1373,7 @@ Name = Power Weight NamePlural = Power Weights Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes HP gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1301,6 +1382,7 @@ Name = Power Bracer NamePlural = Power Bracers Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Attack gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1309,6 +1391,7 @@ Name = Power Belt NamePlural = Power Belts Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Defense gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1317,6 +1400,7 @@ Name = Power Lens NamePlural = Power Lenses Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Atk gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1325,6 +1409,7 @@ Name = Power Band NamePlural = Power Bands Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Sp. Def gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1333,6 +1418,7 @@ Name = Power Anklet NamePlural = Power Anklets Pocket = 1 Price = 3000 +BPPrice = 10 Flags = Fling_70 Description = A Pokémon held item that promotes Speed gain on leveling, but reduces the Speed stat. #------------------------------- @@ -1871,6 +1957,7 @@ Name = Lucky Punch NamePlural = Lucky Punches Pocket = 1 Price = 1000 +BPPrice = 7 Flags = Fling_40 Description = An item to be held by Chansey. It is a pair of gloves that boosts Chansey's critical-hit ratio. #------------------------------- @@ -1919,6 +2006,7 @@ Name = Deep Sea Tooth NamePlural = Deep Sea Teeth Pocket = 1 Price = 2000 +BPPrice = 5 Flags = Fling_90 Description = An item to be held by Clamperl. A fang that gleams a sharp silver, it raises the Sp. Atk stat. #------------------------------- @@ -1927,6 +2015,7 @@ Name = Deep Sea Scale NamePlural = Deep Sea Scales Pocket = 1 Price = 2000 +BPPrice = 5 Flags = Fling_30 Description = An item to be held by Clamperl. A scale that shines a faint pink, it raises the Sp. Def stat. #------------------------------- @@ -2144,6 +2233,7 @@ Name = Everstone NamePlural = Everstones Pocket = 1 Price = 3000 +BPPrice = 5 Flags = Fling_30 Description = An item to be held by a Pokémon. The Pokémon holding this peculiar stone is prevented from evolving. #------------------------------- @@ -2153,6 +2243,7 @@ NamePlural = Dragon Scales Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_30 Description = A thick and tough scale. Dragon-type Pokémon may be holding this item when caught. #------------------------------- @@ -2162,6 +2253,7 @@ NamePlural = Upgrades Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_30 Description = A transparent device filled with all sorts of data. It was produced by Silph Co. #------------------------------- @@ -2171,6 +2263,7 @@ NamePlural = Dubious Discs Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_50 Description = A transparent device overflowing with dubious data. Its producer is unknown. #------------------------------- @@ -2180,6 +2273,7 @@ NamePlural = Protectors Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A protective item of some sort. It is extremely stiff and heavy. It is loved by a certain Pokémon. #------------------------------- @@ -2189,6 +2283,7 @@ NamePlural = Electirizers Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A box packed with a tremendous amount of electric energy. It is loved by a certain Pokémon. #------------------------------- @@ -2198,6 +2293,7 @@ NamePlural = Magmarizers Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A box packed with a tremendous amount of magma energy. It is loved by a certain Pokémon. #------------------------------- @@ -2207,6 +2303,7 @@ NamePlural = Reaper Cloths Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_10 Description = A cloth imbued with horrifyingly strong spiritual energy. It is loved by a certain Pokémon. #------------------------------- @@ -2216,6 +2313,7 @@ NamePlural = Prism Scales Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 10 Flags = Fling_30 Description = A mysterious scale that evolves certain Pokémon. It shines in rainbow colors. #------------------------------- @@ -2225,6 +2323,7 @@ NamePlural = Oval Stones Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A peculiar stone that makes certain species of Pokémon evolve. It is shaped like an egg. #------------------------------- @@ -2234,6 +2333,7 @@ NamePlural = Whipped Dreams Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A soft and sweet treat made of fluffy, puffy and whirled cream. It's loved by a certain Pokémon. #------------------------------- @@ -2243,6 +2343,7 @@ NamePlural = Sachets Pocket = 1 Price = 3000 SellPrice = 1000 +BPPrice = 5 Flags = Fling_80 Description = A sachet filled with slightly overwhelming fragrant perfumes. Yet it's loved by a certain Pokémon. #------------------------------- @@ -2251,6 +2352,7 @@ Name = Strawberry Sweet NamePlural = Strawberry Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A strawberry-shaped sweet. When a Milcery holds this, it will spin around happily. #------------------------------- @@ -2259,6 +2361,7 @@ Name = Love Sweet NamePlural = Love Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A heart-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2267,6 +2370,7 @@ Name = Berry Sweet NamePlural = Berry Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A berry-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2275,6 +2379,7 @@ Name = Clover Sweet NamePlural = Clover Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A clover-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2283,6 +2388,7 @@ Name = Flower Sweet NamePlural = Flower Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A flower-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2291,6 +2397,7 @@ Name = Star Sweet NamePlural = Star Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A star-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2299,6 +2406,7 @@ Name = Ribbon Sweet NamePlural = Ribbon Sweets Pocket = 1 Price = 500 +BPPrice = 5 Flags = Fling_10 Description = A ribbon-shaped sweet. When a Milcery holds this, it spins around happily. #------------------------------- @@ -2307,6 +2415,7 @@ Name = Venusaurite NamePlural = Venusaurites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Venusaur hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2314,6 +2423,7 @@ Description = One of a variety of mysterious Mega Stones. Have Venusaur hold it, Name = Charizardite X NamePlural = Charizardite Xs Pocket = 1 +BPPrice = 50 Price = 0 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Charizard hold it, and it will be able to Mega Evolve. @@ -2323,6 +2433,7 @@ Name = Charizardite Y NamePlural = Charizardite Ys Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Charizard hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2331,6 +2442,7 @@ Name = Blastoisinite NamePlural = Blastoisinites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Blastoise hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2339,6 +2451,7 @@ Name = Beedrillite NamePlural = Beedrillites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Beedrill hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2347,6 +2460,7 @@ Name = Pidgeotite NamePlural = Pidgeotites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Pidgeot hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2355,6 +2469,7 @@ Name = Alakazite NamePlural = Alakazites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Alakazam hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2363,6 +2478,7 @@ Name = Slowbronite NamePlural = Slowbronites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Slowbro hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2371,6 +2487,7 @@ Name = Gengarite NamePlural = Gengarites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gengar hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2379,6 +2496,7 @@ Name = Kangaskhanite NamePlural = Kangaskhanites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Kangaskhan hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2387,6 +2505,7 @@ Name = Pinsirite NamePlural = Pinsirites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Pinsir hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2395,6 +2514,7 @@ Name = Gyaradosite NamePlural = Gyaradosites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gyarados hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2403,6 +2523,7 @@ Name = Aerodactylite NamePlural = Aerodactylites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Aerodactyl hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2411,6 +2532,7 @@ Name = Mewtwonite X NamePlural = Mewtwonite Xs Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mewtwo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2419,6 +2541,7 @@ Name = Mewtwonite Y NamePlural = Mewtwonite Ys Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mewtwo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2427,6 +2550,7 @@ Name = Ampharosite NamePlural = Ampharosites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Ampharos hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2435,6 +2559,7 @@ Name = Steelixite NamePlural = Steelixites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Steelix hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2443,6 +2568,7 @@ Name = Scizorite NamePlural = Scizorites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Scizor hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2451,6 +2577,7 @@ Name = Heracronite NamePlural = Heracronites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Heracross hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2459,6 +2586,7 @@ Name = Houndoominite NamePlural = Houndoominites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Houndoom hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2467,6 +2595,7 @@ Name = Tyranitarite NamePlural = Tyranitarites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Tyranitar hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2475,6 +2604,7 @@ Name = Sceptilite NamePlural = Sceptilites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sceptile hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2483,6 +2613,7 @@ Name = Blazikenite NamePlural = Blazikenites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Blaziken hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2491,6 +2622,7 @@ Name = Swampertite NamePlural = Swampertites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Swampert hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2499,6 +2631,7 @@ Name = Gardevoirite NamePlural = Gardevoirites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gardevoir hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2507,6 +2640,7 @@ Name = Sablenite NamePlural = Sablenites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sableye hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2515,6 +2649,7 @@ Name = Mawilite NamePlural = Mawilites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Mawile hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2523,6 +2658,7 @@ Name = Aggronite NamePlural = Aggronites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Aggron hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2531,6 +2667,7 @@ Name = Medichamite NamePlural = Medichamites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Medicham hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2539,6 +2676,7 @@ Name = Manectite NamePlural = Manectites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Manectric hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2547,6 +2685,7 @@ Name = Sharpedonite NamePlural = Sharpedonites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Sharpedo hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2555,6 +2694,7 @@ Name = Cameruptite NamePlural = Cameruptites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Camerupt hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2563,6 +2703,7 @@ Name = Altarianite NamePlural = Altarianites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Altaria hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2571,6 +2712,7 @@ Name = Banettite NamePlural = Banettites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Banette hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2579,6 +2721,7 @@ Name = Absolite NamePlural = Absolites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Absol hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2587,6 +2730,7 @@ Name = Glalitite NamePlural = Glalitites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Glalie hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2595,6 +2739,7 @@ Name = Salamencite NamePlural = Salamencites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Salamence hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2603,6 +2748,7 @@ Name = Metagrossite NamePlural = Metagrossites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Metagross hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2611,6 +2757,7 @@ Name = Latiasite NamePlural = Latiasites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Latias hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2619,6 +2766,7 @@ Name = Latiosite NamePlural = Latiosites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Latios hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2627,6 +2775,7 @@ Name = Lopunnite NamePlural = Lopunnites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Lopunny hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2635,6 +2784,7 @@ Name = Garchompite NamePlural = Garchompites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Garchomp hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2643,6 +2793,7 @@ Name = Lucarionite NamePlural = Lucarionites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Lucario hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2651,6 +2802,7 @@ Name = Abomasite NamePlural = Abomasites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Abomasnow hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2659,6 +2811,7 @@ Name = Galladite NamePlural = Galladites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Gallade hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2667,6 +2820,7 @@ Name = Audinite NamePlural = Audinites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Audino hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2675,6 +2829,7 @@ Name = Diancite NamePlural = Diancites Pocket = 1 Price = 0 +BPPrice = 50 Flags = MegaStone,Fling_80 Description = One of a variety of mysterious Mega Stones. Have Diancie hold it, and it will be able to Mega Evolve. #------------------------------- @@ -2684,6 +2839,7 @@ NamePlural = Red Orbs Pocket = 1 Price = 10000 SellPrice = 0 +BPPrice = 50 Description = A shiny red orb that is said to have a legend tied to it. It's known to be connected with the Hoenn region. #------------------------------- [BLUEORB] @@ -2692,6 +2848,7 @@ NamePlural = Blue Orbs Pocket = 1 Price = 10000 SellPrice = 0 +BPPrice = 50 Description = A shiny blue orb that is said to have a legend tied to it. It's known to be connected with the Hoenn region. #------------------------------- [POTION] @@ -2729,6 +2886,7 @@ Name = Max Potion NamePlural = Max Potions Pocket = 2 Price = 2500 +BPPrice = 2 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -2908,6 +3066,7 @@ Name = Max Revive NamePlural = Max Revives Pocket = 2 Price = 4000 +BPPrice = 20 FieldUse = OnPokemon BattleUse = OnPokemon Flags = Fling_30 @@ -3029,6 +3188,7 @@ Name = Ether NamePlural = Ethers Pocket = 2 Price = 1200 +BPPrice = 4 FieldUse = OnPokemon BattleUse = OnMove Flags = Fling_30 @@ -3069,6 +3229,7 @@ Name = PP Up NamePlural = PP Ups Pocket = 2 Price = 10000 +BPPrice = 10 FieldUse = OnPokemon Flags = Fling_30 Description = It slightly raises the maximum PP of a selected move that has been learned by the target Pokémon. @@ -3195,6 +3356,7 @@ Name = Lonely Mint NamePlural = Lonely Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Attack will grow more easily, but its Defense will grow more slowly. @@ -3204,6 +3366,7 @@ Name = Adamant Mint NamePlural = Adamant Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Attack will grow more easily, but its Sp. Atk will grow more slowly. @@ -3213,6 +3376,7 @@ Name = Naughty Mint NamePlural = Naughty Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Attack will grow more easily, but its Sp. Def will grow more slowly. @@ -3222,6 +3386,7 @@ Name = Brave Mint NamePlural = Brave Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Attack will grow more easily, but its Speed will grow more slowly. @@ -3231,6 +3396,7 @@ Name = Bold Mint NamePlural = Bold Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Defense will grow more easily, but its Attack will grow more slowly. @@ -3240,6 +3406,7 @@ Name = Impish Mint NamePlural = Impish Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Defense will grow more easily, but its Sp. Atk will grow more slowly. @@ -3249,6 +3416,7 @@ Name = Lax Mint NamePlural = Lax Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Defense will grow more easily, but its Sp. Def will grow more slowly. @@ -3258,6 +3426,7 @@ Name = Relaxed Mint NamePlural = Relaxed Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Defense will grow more easily, but its Speed will grow more slowly. @@ -3267,6 +3436,7 @@ Name = Modest Mint NamePlural = Modest Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Atk will grow more easily, but its Attack will grow more slowly. @@ -3276,6 +3446,7 @@ Name = Mild Mint NamePlural = Mild Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Atk will grow more easily, but its Defense will grow more slowly. @@ -3285,6 +3456,7 @@ Name = Rash Mint NamePlural = Rash Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Atk will grow more easily, but its Sp. Def will grow more slowly. @@ -3294,6 +3466,7 @@ Name = Quiet Mint NamePlural = Quiet Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Atk will grow more easily, but its Speed will grow more slowly. @@ -3303,6 +3476,7 @@ Name = Calm Mint NamePlural = Calm Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Def will grow more easily, but its Attack will grow more slowly. @@ -3312,6 +3486,7 @@ Name = Gentle Mint NamePlural = Gentle Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Def will grow more easily, but its Defense will grow more slowly. @@ -3321,6 +3496,7 @@ Name = Careful Mint NamePlural = Careful Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Def will grow more easily, but its Sp. Atk will grow more slowly. @@ -3330,6 +3506,7 @@ Name = Sassy Mint NamePlural = Sassy Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Sp. Def will grow more easily, but its Speed will grow more slowly. @@ -3339,6 +3516,7 @@ Name = Timid Mint NamePlural = Timid Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Speed will grow more easily, but its Attack will grow more slowly. @@ -3348,6 +3526,7 @@ Name = Hasty Mint NamePlural = Hasty Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Speed will grow more easily, but its Defense will grow more slowly. @@ -3357,6 +3536,7 @@ Name = Jolly Mint NamePlural = Jolly Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Speed will grow more easily, but its Sp. Atk will grow more slowly. @@ -3366,6 +3546,7 @@ Name = Naive Mint NamePlural = Naive Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, its Speed will grow more easily, but its Sp. Def will grow more slowly. @@ -3375,6 +3556,7 @@ Name = Serious Mint NamePlural = Serious Mints Pocket = 2 Price = 20 +BPPrice = 50 FieldUse = OnPokemon Flags = Fling_10 Description = When a Pokémon smells this mint, all of its stats will grow at an equal rate. @@ -3384,6 +3566,7 @@ Name = Ability Capsule NamePlural = Ability Capsule Pocket = 2 Price = 10000 +BPPrice = 50 FieldUse = OnPokemon Description = A capsule that allows a Pokémon with two Abilities to switch between these Abilities when it is used. #------------------------------- @@ -3392,6 +3575,7 @@ Name = Ability Patch NamePlural = Ability Patches Pocket = 2 Price = 10000 +BPPrice = 200 FieldUse = OnPokemon Description = A patch that allows a Pokémon with a regular Ability to have a rare Ability. #------------------------------- @@ -3445,6 +3629,7 @@ Name = Rare Candy NamePlural = Rare Candies Pocket = 2 Price = 10000 +BPPrice = 20 FieldUse = OnPokemon Flags = Fling_30 Description = A candy that is packed with energy. It raises the level of a single Pokémon by one. @@ -3689,6 +3874,7 @@ Name = TM01 NamePlural = TM01s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_150 Move = FOCUSPUNCH @@ -3699,6 +3885,7 @@ Name = TM02 NamePlural = TM02s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = DRAGONCLAW @@ -3709,6 +3896,7 @@ Name = TM03 NamePlural = TM03s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = WATERPULSE @@ -3719,6 +3907,7 @@ Name = TM04 NamePlural = TM04s Pocket = 4 Price = 1500 +BPPrice = 48 FieldUse = TR Flags = Fling_10 Move = CALMMIND @@ -3729,6 +3918,7 @@ Name = TM05 NamePlural = TM05s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ROAR @@ -3739,6 +3929,7 @@ Name = TM06 NamePlural = TM06s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = TOXIC @@ -3749,6 +3940,7 @@ Name = TM07 NamePlural = TM07s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = HAIL @@ -3759,6 +3951,7 @@ Name = TM08 NamePlural = TM08s Pocket = 4 Price = 1500 +BPPrice = 48 FieldUse = TR Flags = Fling_10 Move = BULKUP @@ -3769,6 +3962,7 @@ Name = TM09 NamePlural = TM09s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_25 Move = BULLETSEED @@ -3779,6 +3973,7 @@ Name = TM10 NamePlural = TM10s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = WORKUP @@ -3789,6 +3984,7 @@ Name = TM11 NamePlural = TM11s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SUNNYDAY @@ -3799,6 +3995,7 @@ Name = TM12 NamePlural = TM12s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = TAUNT @@ -3809,6 +4006,7 @@ Name = TM13 NamePlural = TM13s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = ICEBEAM @@ -3819,6 +4017,7 @@ Name = TM14 NamePlural = TM14s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_110 Move = BLIZZARD @@ -3829,6 +4028,7 @@ Name = TM15 NamePlural = TM15s Pocket = 4 Price = 7500 +BPPrice = 32 FieldUse = TR Flags = Fling_150 Move = HYPERBEAM @@ -3839,6 +4039,7 @@ Name = TM16 NamePlural = TM16s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = LIGHTSCREEN @@ -3849,6 +4050,7 @@ Name = TM17 NamePlural = TM17s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = PROTECT @@ -3859,6 +4061,7 @@ Name = TM18 NamePlural = TM18s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = RAINDANCE @@ -3869,6 +4072,7 @@ Name = TM19 NamePlural = TM19s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_75 Move = GIGADRAIN @@ -3879,6 +4083,7 @@ Name = TM20 NamePlural = TM20s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SAFEGUARD @@ -3889,6 +4094,7 @@ Name = TM21 NamePlural = TM21s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = DAZZLINGGLEAM @@ -3899,6 +4105,7 @@ Name = TM22 NamePlural = TM22s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_120 Move = SOLARBEAM @@ -3909,6 +4116,7 @@ Name = TM23 NamePlural = TM23s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_100 Move = IRONTAIL @@ -3919,6 +4127,7 @@ Name = TM24 NamePlural = TM24s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = THUNDERBOLT @@ -3929,6 +4138,7 @@ Name = TM25 NamePlural = TM25s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_110 Move = THUNDER @@ -3939,6 +4149,7 @@ Name = TM26 NamePlural = TM26s Pocket = 4 Price = 3000 +BPPrice = 80 FieldUse = TR Flags = Fling_100 Move = EARTHQUAKE @@ -3949,6 +4160,7 @@ Name = TM27 NamePlural = TM27s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_65 Move = LOWSWEEP @@ -3959,6 +4171,7 @@ Name = TM28 NamePlural = TM28s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = DIG @@ -3969,6 +4182,7 @@ Name = TM29 NamePlural = TM29s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = PSYCHIC @@ -3979,6 +4193,7 @@ Name = TM30 NamePlural = TM30s Pocket = 4 Price = 3000 +BPPrice = 64 FieldUse = TR Flags = Fling_80 Move = SHADOWBALL @@ -3989,6 +4204,7 @@ Name = TM31 NamePlural = TM31s Pocket = 4 Price = 3000 +BPPrice = 40 FieldUse = TR Flags = Fling_75 Move = BRICKBREAK @@ -3999,6 +4215,7 @@ Name = TM32 NamePlural = TM32s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = DOUBLETEAM @@ -4009,6 +4226,7 @@ Name = TM33 NamePlural = TM33s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = REFLECT @@ -4019,6 +4237,7 @@ Name = TM34 NamePlural = TM34s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = SHOCKWAVE @@ -4029,6 +4248,7 @@ Name = TM35 NamePlural = TM35s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = FLAMETHROWER @@ -4039,6 +4259,7 @@ Name = TM36 NamePlural = TM36s Pocket = 4 Price = 3000 +BPPrice = 80 FieldUse = TR Flags = Fling_90 Move = SLUDGEBOMB @@ -4049,6 +4270,7 @@ Name = TM37 NamePlural = TM37s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SANDSTORM @@ -4059,6 +4281,7 @@ Name = TM38 NamePlural = TM38s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_110 Move = FIREBLAST @@ -4069,6 +4292,7 @@ Name = TM39 NamePlural = TM39s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = ROCKTOMB @@ -4079,6 +4303,7 @@ Name = TM40 NamePlural = TM40s Pocket = 4 Price = 3000 +BPPrice = 40 FieldUse = TR Flags = Fling_60 Move = AERIALACE @@ -4089,6 +4314,7 @@ Name = TM41 NamePlural = TM41s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = TORMENT @@ -4099,6 +4325,7 @@ Name = TM42 NamePlural = TM42s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = FACADE @@ -4109,6 +4336,7 @@ Name = TM43 NamePlural = TM43s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = VOLTSWITCH @@ -4119,6 +4347,7 @@ Name = TM44 NamePlural = TM44s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = REST @@ -4129,6 +4358,7 @@ Name = TM45 NamePlural = TM45s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ATTRACT @@ -4139,6 +4369,7 @@ Name = TM46 NamePlural = TM46s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = THIEF @@ -4149,6 +4380,7 @@ Name = TM47 NamePlural = TM47s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = STEELWING @@ -4159,6 +4391,7 @@ Name = TM48 NamePlural = TM48s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SKILLSWAP @@ -4169,6 +4402,7 @@ Name = TM49 NamePlural = TM49s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = SCALD @@ -4179,6 +4413,7 @@ Name = TM50 NamePlural = TM50s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_130 Move = OVERHEAT @@ -4189,6 +4424,7 @@ Name = TM51 NamePlural = TM51s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ROOST @@ -4199,6 +4435,7 @@ Name = TM52 NamePlural = TM52s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_120 Move = FOCUSBLAST @@ -4209,6 +4446,7 @@ Name = TM53 NamePlural = TM53s Pocket = 4 Price = 3000 +BPPrice = 64 FieldUse = TR Flags = Fling_90 Move = ENERGYBALL @@ -4219,6 +4457,7 @@ Name = TM54 NamePlural = TM54s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_40 Move = FALSESWIPE @@ -4229,6 +4468,7 @@ Name = TM55 NamePlural = TM55s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_65 Move = BRINE @@ -4239,6 +4479,7 @@ Name = TM56 NamePlural = TM56s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = FLING @@ -4249,6 +4490,7 @@ Name = TM57 NamePlural = TM57s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_50 Move = CHARGEBEAM @@ -4259,6 +4501,7 @@ Name = TM58 NamePlural = TM58s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ENDURE @@ -4269,6 +4512,7 @@ Name = TM59 NamePlural = TM59s Pocket = 4 Price = 3000 +BPPrice = 80 FieldUse = TR Flags = Fling_85 Move = DRAGONPULSE @@ -4279,6 +4523,7 @@ Name = TM60 NamePlural = TM60s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_75 Move = DRAINPUNCH @@ -4289,6 +4534,7 @@ Name = TM61 NamePlural = TM61s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = WILLOWISP @@ -4299,6 +4545,7 @@ Name = TM62 NamePlural = TM62s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = BUGBUZZ @@ -4309,6 +4556,7 @@ Name = TM63 NamePlural = TM63s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = NASTYPLOT @@ -4319,6 +4567,7 @@ Name = TM64 NamePlural = TM64s Pocket = 4 Price = 7500 +BPPrice = 32 FieldUse = TR Flags = Fling_250 Move = EXPLOSION @@ -4329,6 +4578,7 @@ Name = TM65 NamePlural = TM65s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = SHADOWCLAW @@ -4339,6 +4589,7 @@ Name = TM66 NamePlural = TM66s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_50 Move = PAYBACK @@ -4349,6 +4600,7 @@ Name = TM67 NamePlural = TM67s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = RECYCLE @@ -4359,6 +4611,7 @@ Name = TM68 NamePlural = TM68s Pocket = 4 Price = 7500 +BPPrice = 32 FieldUse = TR Flags = Fling_150 Move = GIGAIMPACT @@ -4369,6 +4622,7 @@ Name = TM69 NamePlural = TM69s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = ROCKPOLISH @@ -4379,6 +4633,7 @@ Name = TM70 NamePlural = TM70s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = FLASH @@ -4389,6 +4644,7 @@ Name = TM71 NamePlural = TM71s Pocket = 4 Price = 3000 +BPPrice = 80 FieldUse = TR Flags = Fling_100 Move = STONEEDGE @@ -4399,6 +4655,7 @@ Name = TM72 NamePlural = TM72s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = AVALANCHE @@ -4409,6 +4666,7 @@ Name = TM73 NamePlural = TM73s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = THUNDERWAVE @@ -4419,6 +4677,7 @@ Name = TM74 NamePlural = TM74s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = GYROBALL @@ -4429,6 +4688,7 @@ Name = TM75 NamePlural = TM75s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SWORDSDANCE @@ -4439,6 +4699,7 @@ Name = TM76 NamePlural = TM76s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = STEALTHROCK @@ -4449,6 +4710,7 @@ Name = TM77 NamePlural = TM77s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = PSYCHUP @@ -4459,6 +4721,7 @@ Name = TM78 NamePlural = TM78s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_55 Move = SNARL @@ -4469,6 +4732,7 @@ Name = TM79 NamePlural = TM79s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = DARKPULSE @@ -4479,6 +4743,7 @@ Name = TM80 NamePlural = TM80s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_75 Move = ROCKSLIDE @@ -4489,6 +4754,7 @@ Name = TM81 NamePlural = TM81s Pocket = 4 Price = 3000 +BPPrice = 64 FieldUse = TR Flags = Fling_80 Move = XSCISSOR @@ -4499,6 +4765,7 @@ Name = TM82 NamePlural = TM82s Pocket = 4 Price = 1000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SLEEPTALK @@ -4509,6 +4776,7 @@ Name = TM83 NamePlural = TM83s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = BULLDOZE @@ -4519,6 +4787,7 @@ Name = TM84 NamePlural = TM84s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = POISONJAB @@ -4529,6 +4798,7 @@ Name = TM85 NamePlural = TM85s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_100 Move = DREAMEATER @@ -4539,6 +4809,7 @@ Name = TM86 NamePlural = TM86s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = GRASSKNOT @@ -4549,6 +4820,7 @@ Name = TM87 NamePlural = TM87s Pocket = 4 Price = 1500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SWAGGER @@ -4559,6 +4831,7 @@ Name = TM88 NamePlural = TM88s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_60 Move = PLUCK @@ -4569,6 +4842,7 @@ Name = TM89 NamePlural = TM89s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_70 Move = UTURN @@ -4579,6 +4853,7 @@ Name = TM90 NamePlural = TM90s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = SUBSTITUTE @@ -4589,6 +4864,7 @@ Name = TM91 NamePlural = TM91s Pocket = 4 Price = 3000 +BPPrice = 32 FieldUse = TR Flags = Fling_80 Move = FLASHCANNON @@ -4599,6 +4875,7 @@ Name = TM92 NamePlural = TM92s Pocket = 4 Price = 5500 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = TRICKROOM @@ -4609,6 +4886,7 @@ Name = TM93 NamePlural = TM93s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_50 Move = CUT @@ -4619,6 +4897,7 @@ Name = TM94 NamePlural = TM94s Pocket = 4 Price = 2000 +BPPrice = 40 FieldUse = TR Flags = Fling_90 Move = FLY @@ -4629,6 +4908,7 @@ Name = TM95 NamePlural = TM95s Pocket = 4 Price = 2500 +BPPrice = 64 FieldUse = TR Flags = Fling_90 Move = SURF @@ -4639,6 +4919,7 @@ Name = TM96 NamePlural = TM96s Pocket = 4 Price = 2000 +BPPrice = 40 FieldUse = TR Flags = Fling_80 Move = STRENGTH @@ -4649,6 +4930,7 @@ Name = TM97 NamePlural = TM97s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_10 Move = DEFOG @@ -4659,6 +4941,7 @@ Name = TM98 NamePlural = TM98s Pocket = 4 Price = 2000 +BPPrice = 40 FieldUse = TR Flags = Fling_40 Move = ROCKSMASH @@ -4669,6 +4952,7 @@ Name = TM99 NamePlural = TM99s Pocket = 4 Price = 2500 +BPPrice = 64 FieldUse = TR Flags = Fling_80 Move = WATERFALL @@ -4679,6 +4963,7 @@ Name = TM100 NamePlural = TM100s Pocket = 4 Price = 2000 +BPPrice = 32 FieldUse = TR Flags = Fling_90 Move = ROCKCLIMB From 3a4b01e2dc999053bf39bd5361ab4c1bb962c652 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sat, 10 Dec 2022 22:04:24 +0000 Subject: [PATCH 11/12] Fixed default terrain not being set properly sometimes --- .../001_Overworld_BattleStarting.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Data/Scripts/012_Overworld/002_Battle triggering/001_Overworld_BattleStarting.rb b/Data/Scripts/012_Overworld/002_Battle triggering/001_Overworld_BattleStarting.rb index 0bb367891..84c97e8a6 100644 --- a/Data/Scripts/012_Overworld/002_Battle triggering/001_Overworld_BattleStarting.rb +++ b/Data/Scripts/012_Overworld/002_Battle triggering/001_Overworld_BattleStarting.rb @@ -227,12 +227,14 @@ module BattleCreationHelperMethods battle.showAnims = ($PokemonSystem.battlescene == 0) battle.showAnims = battleRules["battleAnims"] if !battleRules["battleAnims"].nil? # Terrain - if battleRules["defaultTerrain"].nil? && Settings::OVERWORLD_WEATHER_SETS_BATTLE_TERRAIN - case $game_screen.weather_type - when :Storm - battle.defaultTerrain = :Electric - when :Fog - battle.defaultTerrain = :Misty + if battleRules["defaultTerrain"].nil? + if Settings::OVERWORLD_WEATHER_SETS_BATTLE_TERRAIN + case $game_screen.weather_type + when :Storm + battle.defaultTerrain = :Electric + when :Fog + battle.defaultTerrain = :Misty + end end else battle.defaultTerrain = battleRules["defaultTerrain"] From 3fe324d0da15c66b9b8e03a97ef14ecf589dc6a3 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sat, 31 Dec 2022 17:24:33 +0000 Subject: [PATCH 12/12] Generalised a species' types to allow any number of types --- .../Scripts/010_Data/002_PBS data/003_Type.rb | 68 +++++++------- .../010_Data/002_PBS data/008_Species.rb | 4 +- .../001_Battle/005_Battle_ActionSwitching.rb | 3 +- .../002_Battler/001_Battle_Battler.rb | 6 +- .../002_Battler/002_Battler_Initialize.rb | 2 +- .../002_Battler/003_Battler_ChangeSelf.rb | 10 +- .../003_Move/003_Move_UsageCalculations.rb | 37 +++----- .../003_Move/007_MoveEffects_BattlerOther.rb | 10 +- .../008_MoveEffects_MoveAttributes.rb | 3 +- .../003_Move/009_MoveEffects_MultiHit.rb | 2 +- .../005_AI/006_AI_Move_EffectScores_2.rb | 2 +- .../005_AI/008_AI_Move_Utilities.rb | 55 +++++------ .../006_Other battle code/001_PBEffects.rb | 2 +- .../003_Battle_DamageState.rb | 2 +- .../008_Battle_AbilityEffects.rb | 2 +- .../004_BattleArenaBattle.rb | 2 +- Data/Scripts/016_UI/003_UI_Pokedex_Main.rb | 91 ++++++++++--------- Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb | 32 +++++-- Data/Scripts/016_UI/023_UI_PurifyChamber.rb | 33 +++---- .../017_Minigames/002_Minigame_TripleTriad.rb | 11 ++- .../004_ChallengeGenerator_BattleSim.rb | 11 ++- .../005_Debug_BattlePkmnCommands.rb | 8 +- .../006_Debug_BattleExtraCode.rb | 2 +- .../021_Compiler/002_Compiler_CompilePBS.rb | 5 +- 24 files changed, 200 insertions(+), 203 deletions(-) diff --git a/Data/Scripts/010_Data/002_PBS data/003_Type.rb b/Data/Scripts/010_Data/002_PBS data/003_Type.rb index 7ea0662c1..95fde1829 100644 --- a/Data/Scripts/010_Data/002_PBS data/003_Type.rb +++ b/Data/Scripts/010_Data/002_PBS data/003_Type.rb @@ -59,11 +59,11 @@ module GameData end def effectiveness(other_type) - return Effectiveness::NORMAL_EFFECTIVE_ONE if !other_type - return Effectiveness::SUPER_EFFECTIVE_ONE if @weaknesses.include?(other_type) - return Effectiveness::NOT_VERY_EFFECTIVE_ONE if @resistances.include?(other_type) + return Effectiveness::NORMAL_EFFECTIVE if !other_type + return Effectiveness::SUPER_EFFECTIVE if @weaknesses.include?(other_type) + return Effectiveness::NOT_VERY_EFFECTIVE if @resistances.include?(other_type) return Effectiveness::INEFFECTIVE if @immunities.include?(other_type) - return Effectiveness::NORMAL_EFFECTIVE_ONE + return Effectiveness::NORMAL_EFFECTIVE end end end @@ -71,73 +71,71 @@ end #=============================================================================== module Effectiveness - INEFFECTIVE = 0 - NOT_VERY_EFFECTIVE_ONE = 1 - NORMAL_EFFECTIVE_ONE = 2 - SUPER_EFFECTIVE_ONE = 4 - NORMAL_EFFECTIVE = NORMAL_EFFECTIVE_ONE**3 + INEFFECTIVE = 0 + NOT_VERY_EFFECTIVE = 1 + NORMAL_EFFECTIVE = 2 + SUPER_EFFECTIVE = 4 + INEFFECTIVE_MULTIPLIER = INEFFECTIVE.to_f / NORMAL_EFFECTIVE + NOT_VERY_EFFECTIVE_MULTIPLIER = NOT_VERY_EFFECTIVE.to_f / NORMAL_EFFECTIVE + NORMAL_EFFECTIVE_MULTIPLIER = 1.0 + SUPER_EFFECTIVE_MULTIPLIER = SUPER_EFFECTIVE.to_f / NORMAL_EFFECTIVE module_function def ineffective?(value) - return value == INEFFECTIVE + return value == INEFFECTIVE_MULTIPLIER end def not_very_effective?(value) - return value > INEFFECTIVE && value < NORMAL_EFFECTIVE + return value > INEFFECTIVE_MULTIPLIER && value < NORMAL_EFFECTIVE_MULTIPLIER end def resistant?(value) - return value < NORMAL_EFFECTIVE + return value < NORMAL_EFFECTIVE_MULTIPLIER end def normal?(value) - return value == NORMAL_EFFECTIVE + return value == NORMAL_EFFECTIVE_MULTIPLIER end def super_effective?(value) - return value > NORMAL_EFFECTIVE + return value > NORMAL_EFFECTIVE_MULTIPLIER end - def ineffective_type?(attack_type, defend_type1, defend_type2 = nil, defend_type3 = nil) - value = calculate(attack_type, defend_type1, defend_type2, defend_type3) + def ineffective_type?(attack_type, *defend_types) + value = calculate(attack_type, *defend_types) return ineffective?(value) end - def not_very_effective_type?(attack_type, defend_type1, defend_type2 = nil, defend_type3 = nil) - value = calculate(attack_type, defend_type1, defend_type2, defend_type3) + def not_very_effective_type?(attack_type, *defend_types) + value = calculate(attack_type, *defend_types) return not_very_effective?(value) end - def resistant_type?(attack_type, defend_type1, defend_type2 = nil, defend_type3 = nil) - value = calculate(attack_type, defend_type1, defend_type2, defend_type3) + def resistant_type?(attack_type, *defend_types) + value = calculate(attack_type, *defend_types) return resistant?(value) end - def normal_type?(attack_type, defend_type1, defend_type2 = nil, defend_type3 = nil) - value = calculate(attack_type, defend_type1, defend_type2, defend_type3) + def normal_type?(attack_type, *defend_types) + value = calculate(attack_type, *defend_types) return normal?(value) end - def super_effective_type?(attack_type, defend_type1, defend_type2 = nil, defend_type3 = nil) - value = calculate(attack_type, defend_type1, defend_type2, defend_type3) + def super_effective_type?(attack_type, *defend_types) + value = calculate(attack_type, *defend_types) return super_effective?(value) end - def calculate_one(attack_type, defend_type) + def get_type_effectiveness(attack_type, defend_type) return GameData::Type.get(defend_type).effectiveness(attack_type) end - def calculate(attack_type, defend_type1, defend_type2 = nil, defend_type3 = nil) - mod1 = (defend_type1) ? calculate_one(attack_type, defend_type1) : NORMAL_EFFECTIVE_ONE - mod2 = NORMAL_EFFECTIVE_ONE - mod3 = NORMAL_EFFECTIVE_ONE - if defend_type2 && defend_type1 != defend_type2 - mod2 = calculate_one(attack_type, defend_type2) + def calculate(attack_type, *defend_types) + ret = NORMAL_EFFECTIVE_MULTIPLIER + defend_types.each do |type| + ret *= get_type_effectiveness(attack_type, type) / NORMAL_EFFECTIVE.to_f end - if defend_type3 && defend_type1 != defend_type3 && defend_type2 != defend_type3 - mod3 = calculate_one(attack_type, defend_type3) - end - return mod1 * mod2 * mod3 + return ret end end 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 2d5186d06..202ad0257 100644 --- a/Data/Scripts/010_Data/002_PBS data/008_Species.rb +++ b/Data/Scripts/010_Data/002_PBS data/008_Species.rb @@ -65,7 +65,7 @@ module GameData ret["UnmegaForm"] = [:unmega_form, "u"] ret["MegaMessage"] = [:mega_message, "u"] end - ret["Types"] = [:types, "eE", :Type, :Type] + ret["Types"] = [:types, "*e", :Type] ret["BaseStats"] = [:base_stats, "vvvvvv"] if !compiling_forms ret["GenderRatio"] = [:gender_ratio, "e", :GenderRatio] @@ -113,7 +113,7 @@ module GameData ["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).")], + ["Types", GameDataPoolProperty.new(:Type, false), _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.")], diff --git a/Data/Scripts/011_Battle/001_Battle/005_Battle_ActionSwitching.rb b/Data/Scripts/011_Battle/001_Battle/005_Battle_ActionSwitching.rb index df44b498f..7a80aba15 100644 --- a/Data/Scripts/011_Battle/001_Battle/005_Battle_ActionSwitching.rb +++ b/Data/Scripts/011_Battle/001_Battle/005_Battle_ActionSwitching.rb @@ -427,9 +427,8 @@ class Battle if battler_side.effects[PBEffects::StealthRock] && battler.takesIndirectDamage? && GameData::Type.exists?(:ROCK) && !battler.hasActiveItem?(:HEAVYDUTYBOOTS) bTypes = battler.pbTypes(true) - eff = Effectiveness.calculate(:ROCK, bTypes[0], bTypes[1], bTypes[2]) + eff = Effectiveness.calculate(:ROCK, *bTypes) if !Effectiveness.ineffective?(eff) - eff = eff.to_f / Effectiveness::NORMAL_EFFECTIVE battler.pbReduceHP(battler.totalhp * eff / 8, false) pbDisplay(_INTL("Pointed stones dug into {1}!", battler.pbThis)) battler.pbItemHPHealCheck diff --git a/Data/Scripts/011_Battle/002_Battler/001_Battle_Battler.rb b/Data/Scripts/011_Battle/002_Battler/001_Battle_Battler.rb index 09185db96..7a9829e9a 100644 --- a/Data/Scripts/011_Battle/002_Battler/001_Battle_Battler.rb +++ b/Data/Scripts/011_Battle/002_Battler/001_Battle_Battler.rb @@ -300,7 +300,7 @@ class Battle::Battler # Returns the active types of this Pokémon. The array should not include the # same type more than once, and should not include any invalid types. - def pbTypes(withType3 = false) + def pbTypes(withExtraType = false) ret = @types.uniq # Burn Up erases the Fire-type. ret.delete(:FIRE) if @effects[PBEffects::BurnUp] @@ -311,8 +311,8 @@ class Battle::Battler ret.push(:NORMAL) if ret.length == 0 end # Add the third type specially. - if withType3 && @effects[PBEffects::Type3] && !ret.include?(@effects[PBEffects::Type3]) - ret.push(@effects[PBEffects::Type3]) + if withExtraType && @effects[PBEffects::ExtraType] && !ret.include?(@effects[PBEffects::ExtraType]) + ret.push(@effects[PBEffects::ExtraType]) end return ret end diff --git a/Data/Scripts/011_Battle/002_Battler/002_Battler_Initialize.rb b/Data/Scripts/011_Battle/002_Battler/002_Battler_Initialize.rb index 6d31cece1..65bbc4e54 100644 --- a/Data/Scripts/011_Battle/002_Battler/002_Battler_Initialize.rb +++ b/Data/Scripts/011_Battle/002_Battler/002_Battler_Initialize.rb @@ -171,6 +171,7 @@ class Battle::Battler @effects[PBEffects::Encore] = 0 @effects[PBEffects::EncoreMove] = nil @effects[PBEffects::Endure] = false + @effects[PBEffects::ExtraType] = nil @effects[PBEffects::FirstPledge] = nil @effects[PBEffects::FlashFire] = false @effects[PBEffects::Flinch] = false @@ -270,7 +271,6 @@ class Battle::Battler end @effects[PBEffects::Truant] = false @effects[PBEffects::TwoTurnAttack] = nil - @effects[PBEffects::Type3] = nil @effects[PBEffects::Unburden] = false @effects[PBEffects::Uproar] = 0 @effects[PBEffects::WaterSport] = false diff --git a/Data/Scripts/011_Battle/002_Battler/003_Battler_ChangeSelf.rb b/Data/Scripts/011_Battle/002_Battler/003_Battler_ChangeSelf.rb index 0d7fcee5c..36e9efbd8 100644 --- a/Data/Scripts/011_Battle/002_Battler/003_Battler_ChangeSelf.rb +++ b/Data/Scripts/011_Battle/002_Battler/003_Battler_ChangeSelf.rb @@ -129,14 +129,14 @@ class Battle::Battler if newType.is_a?(Battle::Battler) newTypes = newType.pbTypes newTypes.push(:NORMAL) if newTypes.length == 0 - newType3 = newType.effects[PBEffects::Type3] - newType3 = nil if newTypes.include?(newType3) + newExtraType = newType.effects[PBEffects::ExtraType] + newExtraType = nil if newTypes.include?(newExtraType) @types = newTypes.clone - @effects[PBEffects::Type3] = newType3 + @effects[PBEffects::ExtraType] = newExtraType else newType = GameData::Type.get(newType).id @types = [newType] - @effects[PBEffects::Type3] = nil + @effects[PBEffects::ExtraType] = nil end @effects[PBEffects::BurnUp] = false @effects[PBEffects::Roost] = false @@ -144,7 +144,7 @@ class Battle::Battler def pbResetTypes @types = @pokemon.types - @effects[PBEffects::Type3] = nil + @effects[PBEffects::ExtraType] = nil @effects[PBEffects::BurnUp] = false @effects[PBEffects::Roost] = false end diff --git a/Data/Scripts/011_Battle/003_Move/003_Move_UsageCalculations.rb b/Data/Scripts/011_Battle/003_Move/003_Move_UsageCalculations.rb index 5b36a2c2e..bab8fff14 100644 --- a/Data/Scripts/011_Battle/003_Move/003_Move_UsageCalculations.rb +++ b/Data/Scripts/011_Battle/003_Move/003_Move_UsageCalculations.rb @@ -30,58 +30,51 @@ class Battle::Move # Type effectiveness calculation #============================================================================= def pbCalcTypeModSingle(moveType, defType, user, target) - ret = Effectiveness.calculate_one(moveType, defType) + ret = Effectiveness.calculate(moveType, defType) if Effectiveness.ineffective_type?(moveType, defType) # Ring Target if target.hasActiveItem?(:RINGTARGET) - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end # Foresight if (user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]) && defType == :GHOST - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end # Miracle Eye if target.effects[PBEffects::MiracleEye] && defType == :DARK - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end elsif Effectiveness.super_effective_type?(moveType, defType) # Delta Stream's weather if target.effectiveWeather == :StrongWinds && defType == :FLYING - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end end # Grounded Flying-type Pokémon become susceptible to Ground moves if !target.airborne? && defType == :FLYING && moveType == :GROUND - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end return ret end def pbCalcTypeMod(moveType, user, target) - return Effectiveness::NORMAL_EFFECTIVE if !moveType - return Effectiveness::NORMAL_EFFECTIVE if moveType == :GROUND && - target.pbHasType?(:FLYING) && - target.hasActiveItem?(:IRONBALL) - # Determine types - tTypes = target.pbTypes(true) + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER + return ret if !moveType + return ret if moveType == :GROUND && target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL) # Get effectivenesses - typeMods = [Effectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max if moveType == :SHADOW if target.shadowPokemon? - typeMods[0] = Effectiveness::NOT_VERY_EFFECTIVE_ONE + ret = Effectiveness::NOT_VERY_EFFECTIVE_MULTIPLIER else - typeMods[0] = Effectiveness::SUPER_EFFECTIVE_ONE + ret = Effectiveness::SUPER_EFFECTIVE_MULTIPLIER end else - tTypes.each_with_index do |type, i| - typeMods[i] = pbCalcTypeModSingle(moveType, type, user, target) + target.pbTypes(true).each do |type| + ret *= pbCalcTypeModSingle(moveType, type, user, target) end + ret *= 2 if target.effects[PBEffects::TarShot] && moveType == :FIRE end - # Multiply all effectivenesses together - ret = 1 - typeMods.each { |m| ret *= m } - ret *= 2 if target.effects[PBEffects::TarShot] && moveType == :FIRE return ret end @@ -449,7 +442,7 @@ class Battle::Move end end # Type effectiveness - multipliers[:final_damage_multiplier] *= target.damageState.typeMod.to_f / Effectiveness::NORMAL_EFFECTIVE + multipliers[:final_damage_multiplier] *= target.damageState.typeMod # Burn if user.status == :BURN && physicalMove? && damageReducedByBurn? && !user.hasActiveAbility?(:GUTS) diff --git a/Data/Scripts/011_Battle/003_Move/007_MoveEffects_BattlerOther.rb b/Data/Scripts/011_Battle/003_Move/007_MoveEffects_BattlerOther.rb index ba4a447a6..a5aee6565 100644 --- a/Data/Scripts/011_Battle/003_Move/007_MoveEffects_BattlerOther.rb +++ b/Data/Scripts/011_Battle/003_Move/007_MoveEffects_BattlerOther.rb @@ -280,7 +280,7 @@ end #=============================================================================== class Battle::Move::FreezeTargetSuperEffectiveAgainstWater < Battle::Move::FreezeTarget def pbCalcTypeModSingle(moveType, defType, user, target) - return Effectiveness::SUPER_EFFECTIVE_ONE if defType == :WATER + return Effectiveness::SUPER_EFFECTIVE_MULTIPLIER if defType == :WATER return super end end @@ -786,7 +786,7 @@ class Battle::Move::SetUserTypesToTargetTypes < Battle::Move return true end if user.pbTypes == target.pbTypes && - user.effects[PBEffects::Type3] == target.effects[PBEffects::Type3] + user.effects[PBEffects::ExtraType] == target.effects[PBEffects::ExtraType] @battle.pbDisplay(_INTL("But it failed!")) if show_message return true end @@ -895,7 +895,7 @@ class Battle::Move::AddGhostTypeToTarget < Battle::Move end def pbEffectAgainstTarget(user, target) - target.effects[PBEffects::Type3] = :GHOST + target.effects[PBEffects::ExtraType] = :GHOST typeName = GameData::Type.get(:GHOST).name @battle.pbDisplay(_INTL("{1} transformed into the {2} type!", target.pbThis, typeName)) end @@ -916,7 +916,7 @@ class Battle::Move::AddGrassTypeToTarget < Battle::Move end def pbEffectAgainstTarget(user, target) - target.effects[PBEffects::Type3] = :GRASS + target.effects[PBEffects::ExtraType] = :GRASS typeName = GameData::Type.get(:GRASS).name @battle.pbDisplay(_INTL("{1} transformed into the {2} type!", target.pbThis, typeName)) end @@ -1278,7 +1278,7 @@ class Battle::Move::HitsTargetInSkyGroundsTarget < Battle::Move def hitsFlyingTargets?; return true; end def pbCalcTypeModSingle(moveType, defType, user, target) - return Effectiveness::NORMAL_EFFECTIVE_ONE if moveType == :GROUND && defType == :FLYING + return Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER if moveType == :GROUND && defType == :FLYING return super end diff --git a/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb b/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb index 71cd0e56a..40b25b8f7 100644 --- a/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb +++ b/Data/Scripts/011_Battle/003_Move/008_MoveEffects_MoveAttributes.rb @@ -1113,8 +1113,7 @@ class Battle::Move::EffectivenessIncludesFlyingType < Battle::Move def pbCalcTypeModSingle(moveType, defType, user, target) ret = super if GameData::Type.exists?(:FLYING) - flyingEff = Effectiveness.calculate_one(:FLYING, defType) - ret *= flyingEff.to_f / Effectiveness::NORMAL_EFFECTIVE_ONE + ret *= Effectiveness.calculate(:FLYING, defType) end return ret end diff --git a/Data/Scripts/011_Battle/003_Move/009_MoveEffects_MultiHit.rb b/Data/Scripts/011_Battle/003_Move/009_MoveEffects_MultiHit.rb index 6cec25d88..61f813dd3 100644 --- a/Data/Scripts/011_Battle/003_Move/009_MoveEffects_MultiHit.rb +++ b/Data/Scripts/011_Battle/003_Move/009_MoveEffects_MultiHit.rb @@ -444,7 +444,7 @@ class Battle::Move::TwoTurnAttackInvulnerableInSkyTargetCannotAct < Battle::Move end def pbCalcTypeMod(movetype, user, target) - return Effectiveness::INEFFECTIVE if target.pbHasType?(:FLYING) + return Effectiveness::INEFFECTIVE_MULTIPLIER if target.pbHasType?(:FLYING) return super end diff --git a/Data/Scripts/011_Battle/005_AI/006_AI_Move_EffectScores_2.rb b/Data/Scripts/011_Battle/005_AI/006_AI_Move_EffectScores_2.rb index 1b1670db2..064752c19 100644 --- a/Data/Scripts/011_Battle/005_AI/006_AI_Move_EffectScores_2.rb +++ b/Data/Scripts/011_Battle/005_AI/006_AI_Move_EffectScores_2.rb @@ -378,7 +378,7 @@ class Battle::AI if !user.canChangeType? || target.pbTypes(true).length == 0 score -= 90 elsif user.pbTypes == target.pbTypes && - user.effects[PBEffects::Type3] == target.effects[PBEffects::Type3] + user.effects[PBEffects::ExtraType] == target.effects[PBEffects::ExtraType] score -= 90 end #--------------------------------------------------------------------------- diff --git a/Data/Scripts/011_Battle/005_AI/008_AI_Move_Utilities.rb b/Data/Scripts/011_Battle/005_AI/008_AI_Move_Utilities.rb index 98f5869ec..e9dd31915 100644 --- a/Data/Scripts/011_Battle/005_AI/008_AI_Move_Utilities.rb +++ b/Data/Scripts/011_Battle/005_AI/008_AI_Move_Utilities.rb @@ -27,70 +27,61 @@ class Battle::AI # Move's type effectiveness #============================================================================= def pbCalcTypeModSingle(moveType, defType, user, target) - ret = Effectiveness.calculate_one(moveType, defType) + ret = Effectiveness.calculate(moveType, defType) if Effectiveness.ineffective_type?(moveType, defType) # Ring Target if target.hasActiveItem?(:RINGTARGET) - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end # Foresight if (user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]) && defType == :GHOST - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end # Miracle Eye if target.effects[PBEffects::MiracleEye] && defType == :DARK - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end elsif Effectiveness.super_effective_type?(moveType, defType) # Delta Stream's weather if target.effectiveWeather == :StrongWinds && defType == :FLYING - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end end # Grounded Flying-type Pokémon become susceptible to Ground moves if !target.airborne? && defType == :FLYING && moveType == :GROUND - ret = Effectiveness::NORMAL_EFFECTIVE_ONE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER end return ret end def pbCalcTypeMod(moveType, user, target) - return Effectiveness::NORMAL_EFFECTIVE if !moveType - return Effectiveness::NORMAL_EFFECTIVE if moveType == :GROUND && - target.pbHasType?(:FLYING) && - target.hasActiveItem?(:IRONBALL) - # Determine types - tTypes = target.pbTypes(true) + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER + return ret if !moveType + return ret if moveType == :GROUND && target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL) # Get effectivenesses - typeMods = [Effectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max if moveType == :SHADOW if target.shadowPokemon? - typeMods[0] = Effectiveness::NOT_VERY_EFFECTIVE_ONE + ret = Effectiveness::NOT_VERY_EFFECTIVE_MULTIPLIER else - typeMods[0] = Effectiveness::SUPER_EFFECTIVE_ONE + ret = Effectiveness::SUPER_EFFECTIVE_MULTIPLIER end else - tTypes.each_with_index do |type, i| - typeMods[i] = pbCalcTypeModSingle(moveType, type, user, target) + target.pbTypes(true).each do |type| + ret *= pbCalcTypeModSingle(moveType, type, user, target) end end - # Multiply all effectivenesses together - ret = 1 - typeMods.each { |m| ret *= m } return ret end # For switching. Determines the effectiveness of a potential switch-in against # an opposing battler. def pbCalcTypeModPokemon(battlerThis, battlerOther) - mod1 = Effectiveness.calculate(battlerThis.types[0], battlerOther.types[0], battlerOther.types[1]) - mod2 = Effectiveness::NORMAL_EFFECTIVE - if battlerThis.types.length > 1 - mod2 = Effectiveness.calculate(battlerThis.types[1], battlerOther.types[0], battlerOther.types[1]) - mod2 = mod2.to_f / Effectiveness::NORMAL_EFFECTIVE + ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER + battlerThis.types.each do |thisType| + ret *= Effectiveness.calculate(thisType, *battlerOther.types) end - return mod1 * mod2 + return ret end #============================================================================= @@ -271,15 +262,11 @@ class Battle::AI if GameData::Type.exists?(:FLYING) if skill >= PBTrainerAI.highSkill targetTypes = target.pbTypes(true) - mult = Effectiveness.calculate( - :FLYING, targetTypes[0], targetTypes[1], targetTypes[2] - ) + mult = Effectiveness.calculate(:FLYING, *targetTypes) else - mult = Effectiveness.calculate( - :FLYING, target.types[0], target.types[1], target.effects[PBEffects::Type3] - ) + mult = Effectiveness.calculate(:FLYING, target.types[0], target.types[1], target.effects[PBEffects::ExtraType]) end - baseDmg = (baseDmg.to_f * mult / Effectiveness::NORMAL_EFFECTIVE).round + baseDmg *= mult end baseDmg *= 2 if skill >= PBTrainerAI.mediumSkill && target.effects[PBEffects::Minimize] when "DoublePowerIfUserLastMoveFailed" # Stomping Tantrum @@ -500,7 +487,7 @@ class Battle::AI # Type effectiveness if skill >= PBTrainerAI.mediumSkill typemod = pbCalcTypeMod(type, user, target) - multipliers[:final_damage_multiplier] *= typemod.to_f / Effectiveness::NORMAL_EFFECTIVE + multipliers[:final_damage_multiplier] *= typemod end # Burn if skill >= PBTrainerAI.highSkill && move.physicalMove?(type) && diff --git a/Data/Scripts/011_Battle/006_Other battle code/001_PBEffects.rb b/Data/Scripts/011_Battle/006_Other battle code/001_PBEffects.rb index 24b6ca216..af515bf32 100644 --- a/Data/Scripts/011_Battle/006_Other battle code/001_PBEffects.rb +++ b/Data/Scripts/011_Battle/006_Other battle code/001_PBEffects.rb @@ -28,6 +28,7 @@ module PBEffects Encore = 23 EncoreMove = 24 Endure = 25 + ExtraType = 111 FirstPledge = 26 FlashFire = 27 Flinch = 28 @@ -113,7 +114,6 @@ module PBEffects TrappingUser = 108 Truant = 109 TwoTurnAttack = 110 - Type3 = 111 Unburden = 112 Uproar = 113 WaterSport = 114 diff --git a/Data/Scripts/011_Battle/006_Other battle code/003_Battle_DamageState.rb b/Data/Scripts/011_Battle/006_Other battle code/003_Battle_DamageState.rb index 4e2eda445..2df4ac5be 100644 --- a/Data/Scripts/011_Battle/006_Other battle code/003_Battle_DamageState.rb +++ b/Data/Scripts/011_Battle/006_Other battle code/003_Battle_DamageState.rb @@ -30,7 +30,7 @@ class Battle::DamageState def initialize; reset; end def reset - @typeMod = Effectiveness::INEFFECTIVE + @typeMod = Effectiveness::INEFFECTIVE_MULTIPLIER @unaffected = false @protected = false @missed = false diff --git a/Data/Scripts/011_Battle/006_Other battle code/008_Battle_AbilityEffects.rb b/Data/Scripts/011_Battle/006_Other battle code/008_Battle_AbilityEffects.rb index 36df96eda..d1254f9bc 100644 --- a/Data/Scripts/011_Battle/006_Other battle code/008_Battle_AbilityEffects.rb +++ b/Data/Scripts/011_Battle/006_Other battle code/008_Battle_AbilityEffects.rb @@ -2607,7 +2607,7 @@ Battle::AbilityEffects::OnSwitchIn.add(:ANTICIPATION, if Settings::MECHANICS_GENERATION >= 6 && m.function == "TypeDependsOnUserIVs" # Hidden Power moveType = pbHiddenPower(b.pokemon)[0] end - eff = Effectiveness.calculate(moveType, types[0], types[1], types[2]) + eff = Effectiveness.calculate(moveType, types) next if Effectiveness.ineffective?(eff) next if !Effectiveness.super_effective?(eff) && !["OHKO", "OHKOIce", "OHKOHitsUndergroundTarget"].include?(m.function) diff --git a/Data/Scripts/011_Battle/007_Other battle types/004_BattleArenaBattle.rb b/Data/Scripts/011_Battle/007_Other battle types/004_BattleArenaBattle.rb index 6334b98e3..82f41c070 100644 --- a/Data/Scripts/011_Battle/007_Other battle types/004_BattleArenaBattle.rb +++ b/Data/Scripts/011_Battle/007_Other battle types/004_BattleArenaBattle.rb @@ -10,7 +10,7 @@ class Battle::SuccessState def initialize; clear; end def clear(full = true) - @typeMod = Effectiveness::NORMAL_EFFECTIVE + @typeMod = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER @useState = 0 @protected = false @skill = 0 if full diff --git a/Data/Scripts/016_UI/003_UI_Pokedex_Main.rb b/Data/Scripts/016_UI/003_UI_Pokedex_Main.rb index 043d4fdf2..abf66b3b6 100644 --- a/Data/Scripts/016_UI/003_UI_Pokedex_Main.rb +++ b/Data/Scripts/016_UI/003_UI_Pokedex_Main.rb @@ -25,7 +25,7 @@ class Window_Pokedex < Window_DrawableCommand end def species - return (@commands.length == 0) ? 0 : @commands[self.index][0] + return (@commands.length == 0) ? 0 : @commands[self.index][:species] end def itemCount @@ -35,9 +35,9 @@ class Window_Pokedex < Window_DrawableCommand def drawItem(index, _count, rect) return if index >= self.top_row + self.page_item_max rect = Rect.new(rect.x + 16, rect.y, rect.width - 16, rect.height) - species = @commands[index][0] - indexNumber = @commands[index][4] - indexNumber -= 1 if @commands[index][5] + species = @commands[index][:species] + indexNumber = @commands[index][:number] + indexNumber -= 1 if @commands[index][:shift] if $player.seen?(species) if $player.owned?(species) pbCopyBitmap(self.contents, @pokeballOwn.bitmap, rect.x - 6, rect.y + 10) @@ -45,7 +45,7 @@ class Window_Pokedex < Window_DrawableCommand pbCopyBitmap(self.contents, @pokeballSeen.bitmap, rect.x - 6, rect.y + 10) end num_text = sprintf("%03d", indexNumber) - name_text = @commands[index][1] + name_text = @commands[index][:name] else num_text = sprintf("%03d", indexNumber) name_text = "----------" @@ -362,13 +362,17 @@ class PokemonPokedex_Scene next if !pbCanAddForModeList?($PokemonGlobal.pokedexMode, species) _gender, form, _shiny = $player.pokedex.last_form_seen(species) species_data = GameData::Species.get_species_form(species, form) - color = species_data.color - type1 = species_data.types[0] - type2 = species_data.types[1] || type1 - shape = species_data.shape - height = species_data.height - weight = species_data.weight - ret.push([species, species_data.name, height, weight, i + 1, shift, type1, type2, color, shape]) + ret.push({ + :species => species, + :name => species_data.name, + :height => species_data.height, + :weight => species_data.weight, + :number => i + 1, + :shift => shift, + :types => species_data.types, + :color => species_data.color, + :shape => species_data.shape + }) end return ret end @@ -378,27 +382,27 @@ class PokemonPokedex_Scene case $PokemonGlobal.pokedexMode when MODENUMERICAL # Hide the Dex number 0 species if unseen - dexlist[0] = nil if dexlist[0][5] && !$player.seen?(dexlist[0][0]) + dexlist[0] = nil if dexlist[0][:shift] && !$player.seen?(dexlist[0][:species]) # Remove unseen species from the end of the list i = dexlist.length - 1 loop do - break if i < 0 || !dexlist[i] || $player.seen?(dexlist[i][0]) + break if i < 0 || !dexlist[i] || $player.seen?(dexlist[i][:species]) dexlist[i] = nil i -= 1 end dexlist.compact! # Sort species in ascending order by Regional Dex number - dexlist.sort! { |a, b| a[4] <=> b[4] } + dexlist.sort! { |a, b| a[:number] <=> b[:number] } when MODEATOZ - dexlist.sort! { |a, b| (a[1] == b[1]) ? a[4] <=> b[4] : a[1] <=> b[1] } + dexlist.sort! { |a, b| (a[:name] == b[:name]) ? a[:number] <=> b[:number] : a[:name] <=> b[:name] } when MODEHEAVIEST - dexlist.sort! { |a, b| (a[3] == b[3]) ? a[4] <=> b[4] : b[3] <=> a[3] } + dexlist.sort! { |a, b| (a[:weight] == b[:weight]) ? a[:number] <=> b[:number] : b[:weight] <=> a[:weight] } when MODELIGHTEST - dexlist.sort! { |a, b| (a[3] == b[3]) ? a[4] <=> b[4] : a[3] <=> b[3] } + dexlist.sort! { |a, b| (a[:weight] == b[:weight]) ? a[:number] <=> b[:number] : a[:weight] <=> b[:weight] } when MODETALLEST - dexlist.sort! { |a, b| (a[2] == b[2]) ? a[4] <=> b[4] : b[2] <=> a[2] } + dexlist.sort! { |a, b| (a[:height] == b[:height]) ? a[:number] <=> b[:number] : b[:height] <=> a[:height] } when MODESMALLEST - dexlist.sort! { |a, b| (a[2] == b[2]) ? a[4] <=> b[4] : a[2] <=> b[2] } + dexlist.sort! { |a, b| (a[:height] == b[:height]) ? a[:number] <=> b[:number] : a[:height] <=> b[:height] } end @dexlist = dexlist @sprites["pokedex"].commands = @dexlist @@ -774,8 +778,8 @@ class PokemonPokedex_Scene if params[1] >= 0 scanNameCommand = @nameCommands[params[1]].scan(/./) dexlist = dexlist.find_all { |item| - next false if !$player.seen?(item[0]) - firstChar = item[1][0, 1] + next false if !$player.seen?(item[:species]) + firstChar = item[:name][0, 1] next scanNameCommand.any? { |v| v == firstChar } } end @@ -784,18 +788,17 @@ class PokemonPokedex_Scene stype1 = (params[2] >= 0) ? @typeCommands[params[2]].id : nil stype2 = (params[3] >= 0) ? @typeCommands[params[3]].id : nil dexlist = dexlist.find_all { |item| - next false if !$player.owned?(item[0]) - type1 = item[6] - type2 = item[7] + next false if !$player.owned?(item[:species]) + types = item[:types] if stype1 && stype2 # Find species that match both types - next (type1 == stype1 && type2 == stype2) || (type1 == stype2 && type2 == stype1) + next types.include?(stype1) && types.include?(stype2) elsif stype1 # Find species that match first type entered - next type1 == stype1 || type2 == stype1 + next types.include?(stype1) elsif stype2 # Find species that match second type entered - next type1 == stype2 || type2 == stype2 + next types.include?(stype2) else next false end @@ -806,8 +809,8 @@ class PokemonPokedex_Scene minh = (params[4] < 0) ? 0 : (params[4] >= @heightCommands.length) ? 999 : @heightCommands[params[4]] maxh = (params[5] < 0) ? 999 : (params[5] >= @heightCommands.length) ? 0 : @heightCommands[params[5]] dexlist = dexlist.find_all { |item| - next false if !$player.owned?(item[0]) - height = item[2] + next false if !$player.owned?(item[:species]) + height = item[:height] next height >= minh && height <= maxh } end @@ -816,8 +819,8 @@ class PokemonPokedex_Scene minw = (params[6] < 0) ? 0 : (params[6] >= @weightCommands.length) ? 9999 : @weightCommands[params[6]] maxw = (params[7] < 0) ? 9999 : (params[7] >= @weightCommands.length) ? 0 : @weightCommands[params[7]] dexlist = dexlist.find_all { |item| - next false if !$player.owned?(item[0]) - weight = item[3] + next false if !$player.owned?(item[:species]) + weight = item[:weight] next weight >= minw && weight <= maxw } end @@ -825,27 +828,27 @@ class PokemonPokedex_Scene if params[8] >= 0 scolor = @colorCommands[params[8]].id dexlist = dexlist.find_all { |item| - next false if !$player.seen?(item[0]) - next item[8] == scolor + next false if !$player.seen?(item[:species]) + next item[:color] == scolor } end # Filter by shape if params[9] >= 0 sshape = @shapeCommands[params[9]].id dexlist = dexlist.find_all { |item| - next false if !$player.seen?(item[0]) - next item[9] == sshape + next false if !$player.seen?(item[:species]) + next item[:shape] == sshape } end # Remove all unseen species from the results - dexlist = dexlist.find_all { |item| next $player.seen?(item[0]) } + dexlist = dexlist.find_all { |item| next $player.seen?(item[:species]) } case $PokemonGlobal.pokedexMode - when MODENUMERICAL then dexlist.sort! { |a, b| a[4] <=> b[4] } - when MODEATOZ then dexlist.sort! { |a, b| a[1] <=> b[1] } - when MODEHEAVIEST then dexlist.sort! { |a, b| b[3] <=> a[3] } - when MODELIGHTEST then dexlist.sort! { |a, b| a[3] <=> b[3] } - when MODETALLEST then dexlist.sort! { |a, b| b[2] <=> a[2] } - when MODESMALLEST then dexlist.sort! { |a, b| a[2] <=> b[2] } + when MODENUMERICAL then dexlist.sort! { |a, b| a[:number] <=> b[:number] } + when MODEATOZ then dexlist.sort! { |a, b| a[:name] <=> b[:name] } + when MODEHEAVIEST then dexlist.sort! { |a, b| b[:weight] <=> a[:weight] } + when MODELIGHTEST then dexlist.sort! { |a, b| a[:weight] <=> b[:weight] } + when MODETALLEST then dexlist.sort! { |a, b| b[:height] <=> a[:height] } + when MODESMALLEST then dexlist.sort! { |a, b| a[:height] <=> b[:height] } end return dexlist end @@ -858,7 +861,7 @@ class PokemonPokedex_Scene @searchParams = [$PokemonGlobal.pokedexMode, -1, -1, -1, -1, -1, -1, -1, -1, -1] pbRefreshDexList($PokemonGlobal.pokedexIndex[pbGetSavePositionIndex]) @dexlist.length.times do |i| - next if @dexlist[i][0] != oldspecies + next if @dexlist[i][:species] != oldspecies @sprites["pokedex"].index = i pbRefresh break diff --git a/Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb b/Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb index ba1a5fec4..2b43f9525 100644 --- a/Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb +++ b/Data/Scripts/016_UI/004_UI_Pokedex_Entry.rb @@ -90,8 +90,15 @@ class PokemonPokedexInfo_Scene break end end - @dexlist = [[species, "", 0, 0, dexnum, dexnumshift]] - @index = 0 + @dexlist = [{ + :species => species, + :name => "", + :height => 0, + :weight => 0, + :number => dexnum, + :shift => dexnumshift + }] + @index = 0 @page = 1 @brief = true @typebitmap = AnimatedBitmap.new(_INTL("Graphics/UI/Pokedex/icon_types")) @@ -125,7 +132,7 @@ class PokemonPokedexInfo_Scene end def pbUpdateDummyPokemon - @species = @dexlist[@index][0] + @species = @dexlist[@index][:species] @gender, @form, _shiny = $player.pokedex.last_form_seen(@species) @shiny = false metrics_data = GameData::SpeciesMetrics.get_species_form(@species, @form) @@ -209,9 +216,9 @@ class PokemonPokedexInfo_Scene species_data = GameData::Species.get_species_form(@species, @form) # Write various bits of text indexText = "???" - if @dexlist[@index][4] > 0 - indexNumber = @dexlist[@index][4] - indexNumber -= 1 if @dexlist[@index][5] + if @dexlist[@index][:number] > 0 + indexNumber = @dexlist[@index][:number] + indexNumber -= 1 if @dexlist[@index][:shift] indexText = sprintf("%03d", indexNumber) end textpos = [ @@ -406,7 +413,7 @@ class PokemonPokedexInfo_Scene newindex = @index while newindex > 0 newindex -= 1 - if $player.seen?(@dexlist[newindex][0]) + if $player.seen?(@dexlist[newindex][:species]) @index = newindex break end @@ -417,7 +424,7 @@ class PokemonPokedexInfo_Scene newindex = @index while newindex < @dexlist.length - 1 newindex += 1 - if $player.seen?(@dexlist[newindex][0]) + if $player.seen?(@dexlist[newindex][:species]) @index = newindex break end @@ -581,7 +588,14 @@ class PokemonPokedexInfoScreen end dexnum = pbGetRegionalNumber(region, species) dexnumshift = Settings::DEXES_WITH_OFFSETS.include?(region) - dexlist = [[species, GameData::Species.get(species).name, 0, 0, dexnum, dexnumshift]] + dexlist = [{ + :species => species, + :name => GameData::Species.get(species).name, + :height => 0, + :weight => 0, + :number => dexnum, + :shift => dexnumshift + }] @scene.pbStartScene(dexlist, 0, region) @scene.pbScene @scene.pbEndScene diff --git a/Data/Scripts/016_UI/023_UI_PurifyChamber.rb b/Data/Scripts/016_UI/023_UI_PurifyChamber.rb index d3d0f6d23..ff77fb2f7 100644 --- a/Data/Scripts/016_UI/023_UI_PurifyChamber.rb +++ b/Data/Scripts/016_UI/023_UI_PurifyChamber.rb @@ -141,17 +141,17 @@ class PurifyChamberSet end # Purify Chamber treats Normal/Normal matchup as super effective - def self.typeAdvantage(p1, p2) - return true if p1 == :NORMAL && p2 == :NORMAL - return Effectiveness.super_effective_type?(p1, p2) + def self.typeAdvantage(type1, type2) + return true if type1 == :NORMAL && type2 == :NORMAL + return Effectiveness.super_effective_type?(type1, type2) end - def self.isSuperEffective(p1, p2) - return true if typeAdvantage(p1.types[0], p2.types[0]) - return true if p2.types[1] && typeAdvantage(p1.types[0], p2.types[1]) - return false if p1.types[1].nil? - return true if typeAdvantage(p1.types[1], p2.types[0]) - return true if p2.types[1] && typeAdvantage(p1.types[1], p2.types[1]) + def self.isSuperEffective(pkmn1, pkmn2) + pkmn1.types.each do |type1| + pkmn2.types.each do |type2| + return true if typeAdvantage(type1, type2) + end + end return false end end @@ -952,16 +952,13 @@ class PurifyChamberSetView < Sprite pbSetSmallFont(@info.bitmap) textpos = [] if pkmn - if pkmn.types.length == 1 - textpos.push([_INTL("{1} Lv.{2} {3}", pkmn.name, pkmn.level, - GameData::Type.get(pkmn.types[0]).name), - 2, 6, 0, Color.new(248, 248, 248), Color.new(128, 128, 128)]) - else - textpos.push([_INTL("{1} Lv.{2} {3}/{4}", pkmn.name, pkmn.level, - GameData::Type.get(pkmn.types[0]).name, - GameData::Type.get(pkmn.types[1]).name), - 2, 6, 0, Color.new(248, 248, 248), Color.new(128, 128, 128)]) + type_string = "" + pkmn.types.each_with_index do |type, i| + type_string += "/" if i > 0 + type_string += GameData::Type.get(type).name end + textpos.push([_INTL("{1} Lv.{2} {3}", pkmn.name, pkmn.level, type_string), + 2, 6, 0, Color.new(248, 248, 248), Color.new(128, 128, 128)]) textpos.push([_INTL("FLOW"), 2 + (@info.bitmap.width / 2), 30, 0, Color.new(248, 248, 248), Color.new(128, 128, 128)]) # draw heart gauge diff --git a/Data/Scripts/017_Minigames/002_Minigame_TripleTriad.rb b/Data/Scripts/017_Minigames/002_Minigame_TripleTriad.rb index 217558e35..7aeda0940 100644 --- a/Data/Scripts/017_Minigames/002_Minigame_TripleTriad.rb +++ b/Data/Scripts/017_Minigames/002_Minigame_TripleTriad.rb @@ -51,10 +51,13 @@ class TriadCard end def bonus(opponent) - case Effectiveness.calculate_one(@type, opponent.type) - when Effectiveness::INEFFECTIVE then return -2 - when Effectiveness::NOT_VERY_EFFECTIVE_ONE then return -1 - when Effectiveness::SUPER_EFFECTIVE_ONE then return 1 + effectiveness = Effectiveness.calculate(@type, opponent.type) + if Effectiveness.ineffective?(effectiveness) + return -2 + elsif Effectiveness.not_very_effective?(effectiveness) + return -1 + elsif Effectiveness.super_effective?(effectiveness) + return 1 end return 0 end diff --git a/Data/Scripts/018_Alternate battle modes/003_Battle Frontier generator/004_ChallengeGenerator_BattleSim.rb b/Data/Scripts/018_Alternate battle modes/003_Battle Frontier generator/004_ChallengeGenerator_BattleSim.rb index cd1222137..c1768e9ee 100644 --- a/Data/Scripts/018_Alternate battle modes/003_Battle Frontier generator/004_ChallengeGenerator_BattleSim.rb +++ b/Data/Scripts/018_Alternate battle modes/003_Battle Frontier generator/004_ChallengeGenerator_BattleSim.rb @@ -309,16 +309,17 @@ def pbDecideWinnerEffectiveness(move, otype1, otype2, ability, scores) data = GameData::Move.get(move) return 0 if data.base_damage == 0 atype = data.type - typemod = Effectiveness::NORMAL_EFFECTIVE_ONE**2 + typemod = 1.0 if ability != :LEVITATE || data.type != :GROUND - mod1 = Effectiveness.calculate_one(atype, otype1) - mod2 = (otype1 == otype2) ? Effectiveness::NORMAL_EFFECTIVE_ONE : Effectiveness.calculate_one(atype, otype2) + mod1 = Effectiveness.calculate(atype, otype1) + mod2 = (otype1 == otype2) ? 1.0 : Effectiveness.calculate(atype, otype2) if ability == :WONDERGUARD - mod1 = Effectiveness::NORMAL_EFFECTIVE_ONE if mod1 <= Effectiveness::NORMAL_EFFECTIVE_ONE - mod2 = Effectiveness::NORMAL_EFFECTIVE_ONE if mod2 <= Effectiveness::NORMAL_EFFECTIVE_ONE + mod1 = 1.0 if !Effectiveness.super_effective?(mod1) + mod2 = 1.0 if !Effectiveness.super_effective?(mod2) end typemod = mod1 * mod2 end + typemod *= 4 # Because dealing with 2 types return scores[0] if typemod == 0 # Ineffective return scores[1] if typemod == 1 # Doubly not very effective return scores[2] if typemod == 2 # Not very effective diff --git a/Data/Scripts/020_Debug/003_Debug menus/005_Debug_BattlePkmnCommands.rb b/Data/Scripts/020_Debug/003_Debug menus/005_Debug_BattlePkmnCommands.rb index baf49069a..5f80ba295 100644 --- a/Data/Scripts/020_Debug/003_Debug menus/005_Debug_BattlePkmnCommands.rb +++ b/Data/Scripts/020_Debug/003_Debug menus/005_Debug_BattlePkmnCommands.rb @@ -416,7 +416,7 @@ MenuHandlers.add(:battle_pokemon_debug_menu, :set_types, { "parent" => :main, "usage" => :battler, "effect" => proc { |pkmn, battler, battle| - max_main_types = 2 # The most types a Pokémon can have normally + max_main_types = 5 # Arbitrary value, could be any number cmd = 0 loop do commands = [] @@ -427,7 +427,7 @@ MenuHandlers.add(:battle_pokemon_debug_menu, :set_types, { commands.push(_INTL("Type {1}: {2}", i + 1, type_name)) types.push(type) end - extra_type = battler.effects[PBEffects::Type3] + extra_type = battler.effects[PBEffects::ExtraType] extra_type_name = (extra_type) ? GameData::Type.get(extra_type).name : "-" commands.push(_INTL("Extra type: {1}", extra_type_name)) types.push(extra_type) @@ -443,14 +443,14 @@ MenuHandlers.add(:battle_pokemon_debug_menu, :set_types, { if cmd < max_main_types battler.types[cmd] = nil else - battler.effects[PBEffects::Type3] = nil + battler.effects[PBEffects::ExtraType] = nil end battler.types.compact! end elsif cmd < max_main_types battler.types[cmd] = new_type else - battler.effects[PBEffects::Type3] = new_type + battler.effects[PBEffects::ExtraType] = new_type end end end diff --git a/Data/Scripts/020_Debug/003_Debug menus/006_Debug_BattleExtraCode.rb b/Data/Scripts/020_Debug/003_Debug menus/006_Debug_BattleExtraCode.rb index 6f31f8283..2ec21bb9d 100644 --- a/Data/Scripts/020_Debug/003_Debug menus/006_Debug_BattleExtraCode.rb +++ b/Data/Scripts/020_Debug/003_Debug menus/006_Debug_BattleExtraCode.rb @@ -114,7 +114,7 @@ module Battle::DebugVariables PBEffects::TrappingUser => { name: "Battler trapping self (for Binding Band)", default: -1 }, # Battler index PBEffects::Truant => { name: "Truant will loaf around this round", default: false }, # PBEffects::TwoTurnAttack - only applies to use of specific moves, not suitable for setting via debug -# PBEffects::Type3 - set elsewhere +# PBEffects::ExtraType - set elsewhere PBEffects::Unburden => { name: "Self lost its item (for Unburden)", default: false }, PBEffects::Uproar => { name: "Uproar number of rounds remaining", default: 0 }, PBEffects::WaterSport => { name: "Used Water Sport (Gen 5 and older)", default: false }, diff --git a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb index f36bf8207..ff220ba45 100644 --- a/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb +++ b/Data/Scripts/021_Compiler/002_Compiler_CompilePBS.rb @@ -312,7 +312,10 @@ module Compiler hash[:evolutions].each { |evo| evo[3] = false } end # Remove duplicate types - hash[:types].uniq! if hash[:types].is_a?(Array) + if hash[:types].is_a?(Array) + hash[:types].uniq! + hash[:types].compact! + end end def validate_all_compiled_pokemon