Merge branch 'dev' into ai

This commit is contained in:
Maruno17
2022-12-31 17:28:56 +00:00
75 changed files with 4599 additions and 3590 deletions

View File

@@ -444,4 +444,5 @@ end
module Essentials
VERSION = "20.1.dev"
ERROR_TEXT = ""
MKXPZ_VERSION = "2.3.1"
end

View File

@@ -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

View File

@@ -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

View File

@@ -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
@@ -219,29 +231,49 @@ module GameData
end
return false
end
def get_property_for_PBS(key)
ret = nil
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
return ret
end
end
#=============================================================================
# A bulk loader method for all data stored in .dat files in the Data folder.
#=============================================================================
def self.load_all
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

View File

@@ -59,7 +59,7 @@ GameData::Environment.register({
GameData::Environment.register({
:id => :Puddle,
:name => _INTL("Puddle"),
:battle_basec => "puddle"
:battle_base => "puddle"
})
GameData::Environment.register({

View File

@@ -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.
#===============================================================================

View File

@@ -0,0 +1,43 @@
module GameData
class TownMap
attr_reader :id
attr_reader :real_name
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"],
"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] || []
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
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

View File

@@ -1,140 +0,0 @@
module GameData
class Type
attr_reader :id
attr_reader :real_name
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
DATA = {}
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"]
}
extend ClassMethodsSymbols
include InstanceMethods
def initialize(hash)
@id = hash[:id]
@real_name = hash[:name] || "Unnamed"
@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
end
# @return [String] the translated name of this item
def name
return pbGetMessageFromHash(MessageTypes::Types, @real_name)
end
def physical?; return !@special_type; end
def special?; return @special_type; end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
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::INEFFECTIVE if @immunities.include?(other_type)
return Effectiveness::NORMAL_EFFECTIVE_ONE
end
end
end
#===============================================================================
module Effectiveness
INEFFECTIVE = 0
NOT_VERY_EFFECTIVE_ONE = 1
NORMAL_EFFECTIVE_ONE = 2
SUPER_EFFECTIVE_ONE = 4
NORMAL_EFFECTIVE = NORMAL_EFFECTIVE_ONE**3
module_function
def ineffective?(value)
return value == INEFFECTIVE
end
def not_very_effective?(value)
return value > INEFFECTIVE && value < NORMAL_EFFECTIVE
end
def resistant?(value)
return value < NORMAL_EFFECTIVE
end
def normal?(value)
return value == NORMAL_EFFECTIVE
end
def super_effective?(value)
return value > NORMAL_EFFECTIVE
end
def ineffective_type?(attack_type, defend_type1, defend_type2 = nil, defend_type3 = nil)
value = calculate(attack_type, defend_type1, defend_type2, defend_type3)
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)
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)
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)
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)
return super_effective?(value)
end
def calculate_one(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)
end
if defend_type3 && defend_type1 != defend_type3 && defend_type2 != defend_type3
mod3 = calculate_one(attack_type, defend_type3)
end
return mod1 * mod2 * mod3
end
end

View File

@@ -0,0 +1,141 @@
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 :weaknesses
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"],
"Name" => [:real_name, "s"],
"IconPosition" => [:icon_position, "u"],
"IsSpecialType" => [:special_type, "b"],
"IsPseudoType" => [:pseudo_type, "b"],
"Weaknesses" => [:weaknesses, "*m"],
"Resistances" => [:resistances, "*m"],
"Immunities" => [:immunities, "*m"],
"Flags" => [:flags, "*s"]
}
extend ClassMethodsSymbols
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] || []
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
# @return [String] the translated name of this item
def name
return pbGetMessageFromHash(MessageTypes::Types, @real_name)
end
def physical?; return !@special_type; end
def special?; return @special_type; end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end
def effectiveness(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
end
end
end
#===============================================================================
module Effectiveness
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_MULTIPLIER
end
def not_very_effective?(value)
return value > INEFFECTIVE_MULTIPLIER && value < NORMAL_EFFECTIVE_MULTIPLIER
end
def resistant?(value)
return value < NORMAL_EFFECTIVE_MULTIPLIER
end
def normal?(value)
return value == NORMAL_EFFECTIVE_MULTIPLIER
end
def super_effective?(value)
return value > NORMAL_EFFECTIVE_MULTIPLIER
end
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_types)
value = calculate(attack_type, *defend_types)
return not_very_effective?(value)
end
def resistant_type?(attack_type, *defend_types)
value = calculate(attack_type, *defend_types)
return resistant?(value)
end
def normal_type?(attack_type, *defend_types)
value = calculate(attack_type, *defend_types)
return normal?(value)
end
def super_effective_type?(attack_type, *defend_types)
value = calculate(attack_type, *defend_types)
return super_effective?(value)
end
def get_type_effectiveness(attack_type, defend_type)
return GameData::Type.get(defend_type).effectiveness(attack_type)
end
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
return ret
end
end

View File

@@ -4,24 +4,28 @@ 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
SCHEMA = {
"Name" => [:name, "s"],
"Description" => [:description, "q"],
"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] || "???"
@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

View File

@@ -14,12 +14,15 @@ 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 = {
"Name" => [:name, "s"],
"SectionName" => [:id, "m"],
"Name" => [:real_name, "s"],
"Type" => [:type, "e", :Type],
"Category" => [:category, "e", ["Physical", "Special", "Status"]],
"Power" => [:base_damage, "u"],
@@ -30,10 +33,7 @@ module GameData
"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"]
"Description" => [:real_description, "q"]
}
extend ClassMethodsSymbols
@@ -42,7 +42,7 @@ module GameData
def initialize(hash)
convert_move_data(hash)
@id = hash[:id]
@real_name = hash[:name] || "Unnamed"
@real_name = hash[:real_name] || "Unnamed"
@type = hash[:type] || :NONE
@category = hash[:category] || 2
@base_damage = hash[:base_damage] || 0
@@ -54,7 +54,8 @@ module GameData
@flags = hash[:flags] || []
@flags = [@flags] if !@flags.is_a?(Array)
@effect_chance = hash[:effect_chance] || 0
@real_description = hash[:description] || "???"
@real_description = hash[:real_description] || "???"
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
# @return [String] the translated name of this move
@@ -816,5 +817,12 @@ module GameData
data[:function_code] = new_code
return data
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)
ret = __orig__get_property_for_PBS(key)
ret = nil if ["Power", "Priority", "EffectChance"].include?(key) && ret == 0
return ret
end
end
end

View File

@@ -6,35 +6,62 @@ module GameData
attr_reader :pocket
attr_reader :price
attr_reader :sell_price
attr_reader :real_description
attr_reader :bp_price
attr_reader :field_use
attr_reader :battle_use
attr_reader :consumable
attr_reader :flags
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 = {
"Name" => [:name, "s"],
"NamePlural" => [:name_plural, "s"],
"SectionName" => [:id, "m"],
"Name" => [:real_name, "s"],
"NamePlural" => [:real_name_plural, "s"],
"Pocket" => [:pocket, "v"],
"Price" => [:price, "u"],
"SellPrice" => [:sell_price, "u"],
"Description" => [:description, "q"],
"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,
"OnFoe" => 4, "Direct" => 5 }],
"Consumable" => [:consumable, "b"],
"Flags" => [:flags, "*s"],
"Move" => [:move, "e", :Move]
"Consumable" => [:consumable, "b"],
"Move" => [:move, "e", :Move],
"Description" => [:real_description, "q"]
}
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.")],
["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.")],
["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)
@@ -82,18 +109,20 @@ module GameData
def initialize(hash)
@id = hash[:id]
@real_name = hash[:name] || "Unnamed"
@real_name_plural = hash[:name_plural] || "Unnamed"
@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[:description] || "???"
@bp_price = hash[:bp_price] || 1
@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] || "???"
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
# @return [String] the translated name of this item
@@ -191,5 +220,23 @@ module GameData
}
return combos[species]&.include?(@id)
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"
ret = __orig__get_property_for_PBS(key)
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"
ret = @consumable
ret = nil if ret || is_important? # Only return false, only for non-important items
end
return ret
end
end
end

View File

@@ -4,11 +4,14 @@ 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"],
"HoursPerStage" => [:hours_per_stage, "v"],
"DryingPerHour" => [:drying_per_hour, "u"],
"Yield" => [:yield, "uv"]
@@ -28,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

View File

@@ -40,13 +40,112 @@ 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
def self.schema(compiling_forms = false)
ret = {}
if compiling_forms
ret["SectionName"] = [:id, "ev", :Species]
else
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, "*e", :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
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", 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.")],
["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]
@@ -71,84 +170,14 @@ module GameData
return ret
end
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"]
}
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"]
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]
end
return ret
end
def initialize(hash)
@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] || {}
@@ -186,6 +215,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
@@ -352,5 +382,67 @@ module GameData
end
return 1
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, 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])
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

View File

@@ -1,32 +0,0 @@
module GameData
class ShadowPokemon
attr_reader :id
attr_reader :moves
attr_reader :gauge_size
attr_reader :flags
DATA = {}
DATA_FILENAME = "shadow_pokemon.dat"
SCHEMA = {
"GaugeSize" => [:gauge_size, "v"],
"Moves" => [:moves, "*s"], # Not enumerated when compiled
"Flags" => [:flags, "*s"]
}
HEART_GAUGE_SIZE = 4000 # Default gauge size
extend ClassMethodsSymbols
include InstanceMethods
def initialize(hash)
@id = hash[:id]
@moves = hash[:moves] || []
@gauge_size = hash[:gauge_size] || HEART_GAUGE_SIZE
@flags = hash[:flags] || []
end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end
end
end

View File

@@ -8,16 +8,19 @@ 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 = {
"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
@@ -62,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)
@@ -83,5 +87,17 @@ module GameData
return true
# return @front_sprite_altitude > 0
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)
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

View File

@@ -0,0 +1,36 @@
module GameData
class ShadowPokemon
attr_reader :id
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],
"GaugeSize" => [:gauge_size, "v"],
"Moves" => [:moves, "*m"], # Not enumerated when compiled
"Flags" => [:flags, "*s"]
}
HEART_GAUGE_SIZE = 4000 # Default gauge size
extend ClassMethodsSymbols
include InstanceMethods
def initialize(hash)
@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)
return @flags.any? { |f| f.downcase == flag.downcase }
end
end
end

View File

@@ -5,14 +5,17 @@ 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 = {
"Name" => [:name, "s"],
"SectionName" => [:id, "m"],
"Name" => [:real_name, "s"],
"IconPosition" => [:icon_position, "u"],
"Description" => [:description, "q"],
"Description" => [:real_description, "q"],
"Flags" => [:flags, "*s"]
}
@@ -21,10 +24,11 @@ module GameData
def initialize(hash)
@id = hash[:id]
@real_name = hash[:name] || "Unnamed"
@real_name = hash[:real_name] || "Unnamed"
@icon_position = hash[:icon_position] || 0
@real_description = hash[:description] || "???"
@real_description = hash[:real_description] || "???"
@flags = hash[:flags] || []
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
# @return [String] the translated name of this ribbon

View File

@@ -5,9 +5,11 @@ module GameData
attr_accessor :version
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
@@ -63,6 +65,7 @@ module GameData
@version = hash[:version] || 0
@step_chances = hash[:step_chances]
@types = hash[:types] || {}
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
end
end

View File

@@ -1,106 +0,0 @@
module GameData
class TrainerType
attr_reader :id
attr_reader :real_name
attr_reader :gender
attr_reader :base_money
attr_reader :skill_level
attr_reader :flags
attr_reader :intro_BGM
attr_reader :battle_BGM
attr_reader :victory_BGM
DATA = {}
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"]
}
extend ClassMethodsSymbols
include InstanceMethods
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?
# Check for files
if optional_suffix && !optional_suffix.empty?
ret = path + tr_type_data.id.to_s + optional_suffix + suffix
return ret if pbResolveBitmap(ret)
end
ret = path + tr_type_data.id.to_s + suffix
return (pbResolveBitmap(ret)) ? ret : nil
end
def self.charset_filename(tr_type)
return self.check_file(tr_type, "Graphics/Characters/trainer_")
end
def self.charset_filename_brief(tr_type)
ret = self.charset_filename(tr_type)
ret&.slice!("Graphics/Characters/")
return ret
end
def self.front_sprite_filename(tr_type)
return self.check_file(tr_type, "Graphics/Trainers/")
end
def self.player_front_sprite_filename(tr_type)
outfit = ($player) ? $player.outfit : 0
return self.check_file(tr_type, "Graphics/Trainers/", sprintf("_%d", outfit))
end
def self.back_sprite_filename(tr_type)
return self.check_file(tr_type, "Graphics/Trainers/", "", "_back")
end
def self.player_back_sprite_filename(tr_type)
outfit = ($player) ? $player.outfit : 0
return self.check_file(tr_type, "Graphics/Trainers/", sprintf("_%d", outfit), "_back")
end
def self.map_icon_filename(tr_type)
return self.check_file(tr_type, "Graphics/UI/Town Map/player_")
end
def self.player_map_icon_filename(tr_type)
outfit = ($player) ? $player.outfit : 0
return self.check_file(tr_type, "Graphics/UI/Town Map/player_", sprintf("_%d", outfit))
end
def initialize(hash)
@id = hash[:id]
@real_name = hash[: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]
end
# @return [String] the translated name of this trainer type
def name
return pbGetMessageFromHash(MessageTypes::TrainerTypes, @real_name)
end
def male?; return @gender == 0; end
def female?; return @gender == 1; end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end
end
end

View File

@@ -0,0 +1,134 @@
module GameData
class TrainerType
attr_reader :id
attr_reader :real_name
attr_reader :gender
attr_reader :base_money
attr_reader :skill_level
attr_reader :flags
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"],
"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
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?
# Check for files
if optional_suffix && !optional_suffix.empty?
ret = path + tr_type_data.id.to_s + optional_suffix + suffix
return ret if pbResolveBitmap(ret)
end
ret = path + tr_type_data.id.to_s + suffix
return (pbResolveBitmap(ret)) ? ret : nil
end
def self.charset_filename(tr_type)
return self.check_file(tr_type, "Graphics/Characters/trainer_")
end
def self.charset_filename_brief(tr_type)
ret = self.charset_filename(tr_type)
ret&.slice!("Graphics/Characters/")
return ret
end
def self.front_sprite_filename(tr_type)
return self.check_file(tr_type, "Graphics/Trainers/")
end
def self.player_front_sprite_filename(tr_type)
outfit = ($player) ? $player.outfit : 0
return self.check_file(tr_type, "Graphics/Trainers/", sprintf("_%d", outfit))
end
def self.back_sprite_filename(tr_type)
return self.check_file(tr_type, "Graphics/Trainers/", "", "_back")
end
def self.player_back_sprite_filename(tr_type)
outfit = ($player) ? $player.outfit : 0
return self.check_file(tr_type, "Graphics/Trainers/", sprintf("_%d", outfit), "_back")
end
def self.map_icon_filename(tr_type)
return self.check_file(tr_type, "Graphics/UI/Town Map/player_")
end
def self.player_map_icon_filename(tr_type)
outfit = ($player) ? $player.outfit : 0
return self.check_file(tr_type, "Graphics/UI/Town Map/player_", sprintf("_%d", outfit))
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]
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
# @return [String] the translated name of this trainer type
def name
return pbGetMessageFromHash(MessageTypes::TrainerTypes, @real_name)
end
def male?; return @gender == 0; end
def female?; return @gender == 1; end
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"
ret = __orig__get_property_for_PBS(key)
ret = nil if key == "SkillLevel" && ret == @base_money
return ret
end
end
end

View File

@@ -7,16 +7,25 @@ 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"
# "Pokemon" is specially mentioned in def compile_trainers and def
# write_trainers, and acts as a subheading for a particular Pokémon.
SCHEMA = {
"SectionName" => [:id, "esU", :TrainerType],
"Items" => [:items, "*e", :Item],
"LoseText" => [:lose_text, "q"],
"Pokemon" => [:pokemon, "ev", :Species], # Species, level
"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"],
@@ -36,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]
@@ -73,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|
@@ -84,6 +97,7 @@ module GameData
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
@@ -153,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
@@ -163,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

View File

@@ -12,22 +12,25 @@ 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 = {
"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
@@ -54,11 +57,11 @@ 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]
@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]
@@ -66,29 +69,13 @@ 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
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

View File

@@ -4,20 +4,22 @@ module GameData
attr_reader :trainer_type
attr_reader :walk_charset
attr_reader :home
attr_reader :pbs_file_suffix
DATA = {}
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
@@ -25,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.")],
@@ -56,6 +59,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
@@ -82,19 +86,10 @@ module GameData
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
alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
def get_property_for_PBS(key)
key = "SectionName" if key == "ID"
return __orig__get_property_for_PBS(key)
end
end
end

View File

@@ -23,33 +23,36 @@ 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 = {
"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
@@ -57,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.")],
@@ -84,7 +88,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]
@@ -106,34 +110,7 @@ module GameData
@town_map_size = hash[:town_map_size]
@battle_environment = hash[:battle_environment]
@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
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
# @return [String] the translated name of this map
@@ -144,5 +121,11 @@ module GameData
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end
alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
def get_property_for_PBS(key)
key = "SectionName" if key == "ID"
return __orig__get_property_for_PBS(key)
end
end
end

View File

@@ -10,13 +10,16 @@ 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 = {
"Autotile" => [:autotile, "us"],
"Tile" => [:tile, "us"],
"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"],
@@ -50,13 +53,14 @@ 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)
[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
@@ -192,18 +196,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
end
return nil
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 ret
end
end
end

View File

@@ -25,19 +25,22 @@ 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"],
"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"],
"NodeLayout" => [:node_layout, "s"],
"RoomLayout" => [:room_layout, "s"],
"ShiftCorridors" => [:random_corridor_shift, "b"],
"NodeLayout" => [:node_layout, "m"],
"RoomLayout" => [:room_layout, "m"],
"RoomChance" => [:room_chance, "v"],
"ExtraConnections" => [:extra_connections_count, "u"],
"FloorPatches" => [:floor_patches, "vvu"],
@@ -76,9 +79,9 @@ 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]
@node_layout = hash[:node_layout]&.downcase&.to_sym || :full
@room_layout = hash[:room_layout]&.downcase&.to_sym || :full
@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
@extra_connections_count = hash[:extra_connections_count] || 2
@floor_patch_radius = (hash[:floor_patches]) ? hash[:floor_patches][0] : 3
@@ -90,6 +93,7 @@ module GameData
@void_decoration_large_density = (hash[:void_decorations]) ? hash[:void_decorations][1] : 200
@rng_seed = hash[:rng_seed]
@flags = hash[:flags] || []
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
def has_flag?(flag)
@@ -114,25 +118,19 @@ module GameData
return width, height
end
def property_from_string(str)
case str
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]
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

View File

@@ -6,34 +6,43 @@ 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 = {
"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"],
"Body" => [:body, "^q"],
"Body1" => [:body1, "^q"],
"Body2" => [:body2, "^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 +72,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]
@@ -75,22 +84,17 @@ module GameData
@battle_request = hash[:battle_request]
@battle_remind = hash[:battle_remind]
@end = hash[:end]
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
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

View File

@@ -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

View File

@@ -301,7 +301,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]
@@ -312,8 +312,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

View File

@@ -172,6 +172,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
@@ -271,7 +272,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

View File

@@ -130,14 +130,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
@@ -145,7 +145,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

View File

@@ -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
end
# Multiply all effectivenesses together
ret = 1
typeMods.each { |m| ret *= m }
ret *= 2 if target.effects[PBEffects::TarShot] && moveType == :FIRE
end
return ret
end
@@ -453,7 +446,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)

View File

@@ -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
@@ -771,7 +771,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
@@ -880,7 +880,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
@@ -901,7 +901,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
@@ -1263,7 +1263,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

View File

@@ -1111,8 +1111,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

View File

@@ -455,7 +455,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

View File

@@ -24,16 +24,62 @@ class Battle::AI
#=============================================================================
# Move's type effectiveness
#=============================================================================
def pbCalcTypeModSingle(moveType, defType, user, target)
ret = Effectiveness.calculate(moveType, defType)
if Effectiveness.ineffective_type?(moveType, defType)
# Ring Target
if target.hasActiveItem?(:RINGTARGET)
ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
end
# Foresight
if (user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]) &&
defType == :GHOST
ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
end
# Miracle Eye
if target.effects[PBEffects::MiracleEye] && defType == :DARK
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_MULTIPLIER
end
end
# Grounded Flying-type Pokémon become susceptible to Ground moves
if !target.airborne? && defType == :FLYING && moveType == :GROUND
ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
end
return ret
end
def pbCalcTypeMod(moveType, user, target)
ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
return ret if !moveType
return ret if moveType == :GROUND && target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL)
# Get effectivenesses
if moveType == :SHADOW
if target.shadowPokemon?
ret = Effectiveness::NOT_VERY_EFFECTIVE_MULTIPLIER
else
ret = Effectiveness::SUPER_EFFECTIVE_MULTIPLIER
end
else
target.pbTypes(true).each do |type|
ret *= pbCalcTypeModSingle(moveType, type, user, target)
end
end
return ret
end
# For switching. Determines the effectiveness of a potential switch-in against
# an opposing battler.
def pbCalcTypeModPokemon(pkmn, target_battler)
mod1 = Effectiveness.calculate(pkmn.types[0], target_battler.types[0], target_battler.types[1])
mod2 = Effectiveness::NORMAL_EFFECTIVE
if pkmn.types.length > 1
mod2 = Effectiveness.calculate(pkmn.types[1], target_battler.types[0], target_battler.types[1])
mod2 = mod2.to_f / Effectiveness::NORMAL_EFFECTIVE
ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
pkmn.types.each do |thisType|
ret *= Effectiveness.calculate(thisType, *target_battler.types)
end
return mod1 * mod2
return ret
end
#=============================================================================

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -227,13 +227,15 @@ 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
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"]
end

View File

@@ -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?

View File

@@ -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

View File

@@ -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|
@@ -90,7 +90,14 @@ class PokemonPokedexInfo_Scene
break
end
end
@dexlist = [[species, "", 0, 0, dexnum, dexnumshift]]
@dexlist = [{
:species => species,
:name => "",
:height => 0,
:weight => 0,
:number => dexnum,
:shift => dexnumshift
}]
@index = 0
@page = 1
@brief = true
@@ -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 = [
@@ -296,7 +303,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 +382,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)
@@ -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

View File

@@ -72,24 +72,23 @@ 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 = GameData::TownMap.get(playerpos[0])
@map_x = playerpos[1]
@map_y = playerpos[2]
mapsize = map_metadata.town_map_size
@@ -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

View File

@@ -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)

View File

@@ -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:<r>{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<r>{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:<r>{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}<r>{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}<r>{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}<r>{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}<r>{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}<r>{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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -81,7 +81,8 @@ def pbEncountersEditor
:map => new_map_ID,
:version => new_version,
:step_chances => {},
:types => {}
: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
@@ -344,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
@@ -370,30 +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]
}
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
@@ -548,7 +532,8 @@ def pbTrainerBattleEditor
:version => data[2],
:lose_text => data[3],
:pokemon => party,
:items => items
: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]]
@@ -732,24 +717,19 @@ 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]
}
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
@@ -776,21 +756,23 @@ 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
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]
}
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
@@ -819,35 +801,23 @@ 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],
: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]
}
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
@@ -861,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
@@ -892,36 +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]
}
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
@@ -995,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
@@ -1049,98 +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]
}
schema = GameData::Species.schema
species_hash = {}
properties.each_with_index do |prop, i|
data[i] = data[i].to_f / 10 if ["Height", "Weight"].include?(prop[0])
case prop[0]
when "ID"
species_hash[schema["SectionName"][0]] = data[i]
else
species_hash[schema[prop[0]][0]] = data[i]
end
end
species_hash[:pbs_file_suffix] = spec.pbs_file_suffix
# Sanitise data
Compiler.validate_compiled_pokemon(species_hash)
species_hash[:evolutions].each do |evo|
param_type = GameData::Evolution.get(evo[1]).parameter
if param_type.nil?
evo[2] = nil
elsif param_type == Integer
evo[2] = Compiler.csvPosInt!(evo[2])
elsif param_type != String
evo[2] = Compiler.csvEnumField!(evo[2], param_type, "Evolutions", species_hash[:id])
end
end
# Add species' data to records
GameData::Species.register(species_hash)
GameData::Species.save

View File

@@ -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),

View File

@@ -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

View File

@@ -238,9 +238,10 @@ 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
old_setting.length.times do |i|
real_cmds.push([old_setting[i], 0])
end
# Edit list
@@ -319,7 +320,7 @@ class StringListProperty
end
def self.format(value)
return value.join(",")
return (value) ? value.join(",") : ""
end
end
@@ -359,7 +360,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 +373,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 +386,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)
@@ -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)
@@ -653,7 +685,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)
@@ -769,15 +801,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
return oldsetting if selcmd < 0
selregion = regions[selcmd][0]
else
return oldsetting
end
end
mappoint = chooseMapPoint(selregion, true)
return (mappoint) ? [selregion, mappoint[0], mappoint[1]] : oldsetting
@@ -788,12 +815,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
@@ -834,7 +857,7 @@ module MapProperty
end
def self.defaultValue
return 0
return nil
end
def self.format(value)
@@ -890,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
@@ -929,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
@@ -1102,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
@@ -1286,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)
@@ -1474,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

View File

@@ -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

View File

@@ -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 },

View File

@@ -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|

View File

@@ -92,7 +92,7 @@ module Compiler
#=============================================================================
# PBS file readers
#=============================================================================
def pbEachFileSectionEx(f)
def pbEachFileSectionEx(f, schema = nil)
lineno = 1
havesection = false
sectionname = nil
@@ -120,37 +120,38 @@ module Compiler
end
r1 = $~[1]
r2 = $~[2]
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
Graphics.update if lineno % 1000 == 0
}
yield lastsection, sectionname if havesection
end
# Used for types.txt, pokemon.txt, battle_facility_lists.txt and Battle Tower trainers PBS files
def pbEachFileSection(f)
pbEachFileSectionEx(f) { |section, name|
# 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, 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
# 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 +194,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 +227,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
@@ -404,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
@@ -519,6 +525,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 +569,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_length == 1) ? record[0] : record
end
#=============================================================================
@@ -556,17 +577,23 @@ 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|
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)
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
@@ -753,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_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 # Depends on TrainerType
compile_map_metadata
compile_dungeon_tilesets
compile_dungeon_parameters
compile_phone # 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)
@@ -804,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
@@ -864,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|
@@ -880,24 +893,26 @@ module Compiler
break
end
end
textFiles.each do |filename|
next if !safeExists?("PBS/" + filename)
# 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("PBS/#{filename}") { |file|
latestTextTime = [latestTextTime, file.mtime.to_i].max
}
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
@@ -908,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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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!

View File

@@ -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]

View File

@@ -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,