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 module Essentials
VERSION = "20.1.dev" VERSION = "20.1.dev"
ERROR_TEXT = "" ERROR_TEXT = ""
MKXPZ_VERSION = "2.3.1"
end end

View File

@@ -46,3 +46,9 @@ def pbSetResizeFactor(factor)
Graphics.center Graphics.center
end end
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 end
def follow_leader(leader, instant = false, leaderIsTrueLeader = true) 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) maps_connected = $map_factory.areConnected?(leader.map.map_id, self.map.map_id)
target = nil target = nil
# Get the target tile that self wants to move to # 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. # For data that is known by a symbol or an ID number.
#============================================================================= #=============================================================================
module ClassMethods module ClassMethods
def schema
return self::SCHEMA
end
def register(hash) def register(hash)
self::DATA[hash[:id]] = self::DATA[hash[:id_number]] = self.new(hash) self::DATA[hash[:id]] = self::DATA[hash[:id_number]] = self.new(hash)
end end
@@ -72,6 +76,10 @@ module GameData
# For data that is only known by a symbol. # For data that is only known by a symbol.
#============================================================================= #=============================================================================
module ClassMethodsSymbols module ClassMethodsSymbols
def schema
return self::SCHEMA
end
def register(hash) def register(hash)
self::DATA[hash[:id]] = self.new(hash) self::DATA[hash[:id]] = self.new(hash)
end end
@@ -143,6 +151,10 @@ module GameData
# For data that is only known by an ID number. # For data that is only known by an ID number.
#============================================================================= #=============================================================================
module ClassMethodsIDNumbers module ClassMethodsIDNumbers
def schema
return self::SCHEMA
end
def register(hash) def register(hash)
self::DATA[hash[:id]] = self.new(hash) self::DATA[hash[:id]] = self.new(hash)
end end
@@ -219,29 +231,49 @@ module GameData
end end
return false return false
end 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 end
#============================================================================= #=============================================================================
# A bulk loader method for all data stored in .dat files in the Data folder. # A bulk loader method for all data stored in .dat files in the Data folder.
#============================================================================= #=============================================================================
def self.load_all def self.load_all
Type.load self.constants.each do |c|
Ability.load next if !self.const_get(c).is_a?(Class)
Move.load self.const_get(c).load if self.const_get(c).const_defined?(:DATA_FILENAME)
Item.load end
BerryPlant.load end
Species.load
SpeciesMetrics.load def self.get_all_data_filenames
ShadowPokemon.load ret = []
Ribbon.load self.constants.each do |c|
Encounter.load next if !self.const_get(c).is_a?(Class)
TrainerType.load ret.push(self.const_get(c)::DATA_FILENAME) if self.const_get(c).const_defined?(:DATA_FILENAME)
Trainer.load end
Metadata.load return ret
PlayerMetadata.load end
MapMetadata.load
DungeonTileset.load def self.get_all_pbs_base_filenames
DungeonParameters.load ret = {}
PhoneMessage.load 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
end end

View File

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

View File

@@ -2,7 +2,6 @@
# Data caches. # Data caches.
#=============================================================================== #===============================================================================
class Game_Temp class Game_Temp
attr_accessor :town_map_data
attr_accessor :regional_dexes_data attr_accessor :regional_dexes_data
attr_accessor :battle_animations_data attr_accessor :battle_animations_data
attr_accessor :move_to_battle_animation_data attr_accessor :move_to_battle_animation_data
@@ -11,7 +10,6 @@ end
def pbClearData def pbClearData
if $game_temp if $game_temp
$game_temp.town_map_data = nil
$game_temp.regional_dexes_data = nil $game_temp.regional_dexes_data = nil
$game_temp.battle_animations_data = nil $game_temp.battle_animations_data = nil
$game_temp.move_to_battle_animation_data = nil $game_temp.move_to_battle_animation_data = nil
@@ -24,17 +22,6 @@ def pbClearData
end end
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. # 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_name
attr_reader :real_description attr_reader :real_description
attr_reader :flags attr_reader :flags
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "abilities.dat" DATA_FILENAME = "abilities.dat"
PBS_BASE_FILENAME = "abilities"
extend ClassMethodsSymbols extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
SCHEMA = { SCHEMA = {
"Name" => [:name, "s"], "SectionName" => [:id, "m"],
"Description" => [:description, "q"], "Name" => [:real_name, "s"],
"Description" => [:real_description, "q"],
"Flags" => [:flags, "*s"] "Flags" => [:flags, "*s"]
} }
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@real_name = hash[:name] || "Unnamed" @real_name = hash[:real_name] || "Unnamed"
@real_description = hash[:description] || "???" @real_description = hash[:real_description] || "???"
@flags = hash[:flags] || [] @flags = hash[:flags] || []
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
# @return [String] the translated name of this ability # @return [String] the translated name of this ability

View File

@@ -14,12 +14,15 @@ module GameData
attr_reader :flags attr_reader :flags
attr_reader :effect_chance attr_reader :effect_chance
attr_reader :real_description attr_reader :real_description
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "moves.dat" DATA_FILENAME = "moves.dat"
PBS_BASE_FILENAME = "moves"
SCHEMA = { SCHEMA = {
"Name" => [:name, "s"], "SectionName" => [:id, "m"],
"Name" => [:real_name, "s"],
"Type" => [:type, "e", :Type], "Type" => [:type, "e", :Type],
"Category" => [:category, "e", ["Physical", "Special", "Status"]], "Category" => [:category, "e", ["Physical", "Special", "Status"]],
"Power" => [:base_damage, "u"], "Power" => [:base_damage, "u"],
@@ -30,10 +33,7 @@ module GameData
"FunctionCode" => [:function_code, "s"], "FunctionCode" => [:function_code, "s"],
"Flags" => [:flags, "*s"], "Flags" => [:flags, "*s"],
"EffectChance" => [:effect_chance, "u"], "EffectChance" => [:effect_chance, "u"],
"Description" => [:description, "q"], "Description" => [:real_description, "q"]
# All properties below here are old names for some properties above.
# They will be removed in v21.
"BaseDamage" => [:base_damage, "u"]
} }
extend ClassMethodsSymbols extend ClassMethodsSymbols
@@ -42,7 +42,7 @@ module GameData
def initialize(hash) def initialize(hash)
convert_move_data(hash) convert_move_data(hash)
@id = hash[:id] @id = hash[:id]
@real_name = hash[:name] || "Unnamed" @real_name = hash[:real_name] || "Unnamed"
@type = hash[:type] || :NONE @type = hash[:type] || :NONE
@category = hash[:category] || 2 @category = hash[:category] || 2
@base_damage = hash[:base_damage] || 0 @base_damage = hash[:base_damage] || 0
@@ -54,7 +54,8 @@ module GameData
@flags = hash[:flags] || [] @flags = hash[:flags] || []
@flags = [@flags] if !@flags.is_a?(Array) @flags = [@flags] if !@flags.is_a?(Array)
@effect_chance = hash[:effect_chance] || 0 @effect_chance = hash[:effect_chance] || 0
@real_description = hash[:description] || "???" @real_description = hash[:real_description] || "???"
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
# @return [String] the translated name of this move # @return [String] the translated name of this move
@@ -816,5 +817,12 @@ module GameData
data[:function_code] = new_code data[:function_code] = new_code
return data return data
end 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
end end

View File

@@ -6,35 +6,62 @@ module GameData
attr_reader :pocket attr_reader :pocket
attr_reader :price attr_reader :price
attr_reader :sell_price attr_reader :sell_price
attr_reader :real_description attr_reader :bp_price
attr_reader :field_use attr_reader :field_use
attr_reader :battle_use attr_reader :battle_use
attr_reader :consumable
attr_reader :flags attr_reader :flags
attr_reader :consumable
attr_reader :move attr_reader :move
attr_reader :real_description
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "items.dat" DATA_FILENAME = "items.dat"
PBS_BASE_FILENAME = "items"
SCHEMA = { SCHEMA = {
"Name" => [:name, "s"], "SectionName" => [:id, "m"],
"NamePlural" => [:name_plural, "s"], "Name" => [:real_name, "s"],
"NamePlural" => [:real_name_plural, "s"],
"Pocket" => [:pocket, "v"], "Pocket" => [:pocket, "v"],
"Price" => [:price, "u"], "Price" => [:price, "u"],
"SellPrice" => [:sell_price, "u"], "SellPrice" => [:sell_price, "u"],
"Description" => [:description, "q"], "BPPrice" => [:bp_price, "u"],
"FieldUse" => [:field_use, "e", { "OnPokemon" => 1, "Direct" => 2, "TM" => 3, "FieldUse" => [:field_use, "e", { "OnPokemon" => 1, "Direct" => 2, "TM" => 3,
"HM" => 4, "TR" => 5 }], "HM" => 4, "TR" => 5 }],
"BattleUse" => [:battle_use, "e", { "OnPokemon" => 1, "OnMove" => 2, "OnBattler" => 3, "BattleUse" => [:battle_use, "e", { "OnPokemon" => 1, "OnMove" => 2, "OnBattler" => 3,
"OnFoe" => 4, "Direct" => 5 }], "OnFoe" => 4, "Direct" => 5 }],
"Consumable" => [:consumable, "b"],
"Flags" => [:flags, "*s"], "Flags" => [:flags, "*s"],
"Move" => [:move, "e", :Move] "Consumable" => [:consumable, "b"],
"Move" => [:move, "e", :Move],
"Description" => [:real_description, "q"]
} }
extend ClassMethodsSymbols extend ClassMethodsSymbols
include InstanceMethods 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) def self.icon_filename(item)
return "Graphics/Items/back" if item.nil? return "Graphics/Items/back" if item.nil?
item_data = self.try_get(item) item_data = self.try_get(item)
@@ -82,18 +109,20 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@real_name = hash[:name] || "Unnamed" @real_name = hash[:real_name] || "Unnamed"
@real_name_plural = hash[:name_plural] || "Unnamed" @real_name_plural = hash[:real_name_plural] || "Unnamed"
@pocket = hash[:pocket] || 1 @pocket = hash[:pocket] || 1
@price = hash[:price] || 0 @price = hash[:price] || 0
@sell_price = hash[:sell_price] || (@price / 2) @sell_price = hash[:sell_price] || (@price / 2)
@real_description = hash[:description] || "???" @bp_price = hash[:bp_price] || 1
@field_use = hash[:field_use] || 0 @field_use = hash[:field_use] || 0
@battle_use = hash[:battle_use] || 0 @battle_use = hash[:battle_use] || 0
@flags = hash[:flags] || [] @flags = hash[:flags] || []
@consumable = hash[:consumable] @consumable = hash[:consumable]
@consumable = !is_important? if @consumable.nil? @consumable = !is_important? if @consumable.nil?
@move = hash[:move] @move = hash[:move]
@real_description = hash[:real_description] || "???"
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
# @return [String] the translated name of this item # @return [String] the translated name of this item
@@ -191,5 +220,23 @@ module GameData
} }
return combos[species]&.include?(@id) return combos[species]&.include?(@id)
end 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
end end

View File

@@ -4,11 +4,14 @@ module GameData
attr_reader :hours_per_stage attr_reader :hours_per_stage
attr_reader :drying_per_hour attr_reader :drying_per_hour
attr_reader :yield attr_reader :yield
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "berry_plants.dat" DATA_FILENAME = "berry_plants.dat"
PBS_BASE_FILENAME = "berry_plants"
SCHEMA = { SCHEMA = {
"SectionName" => [:id, "m"],
"HoursPerStage" => [:hours_per_stage, "v"], "HoursPerStage" => [:hours_per_stage, "v"],
"DryingPerHour" => [:drying_per_hour, "u"], "DryingPerHour" => [:drying_per_hour, "u"],
"Yield" => [:yield, "uv"] "Yield" => [:yield, "uv"]
@@ -28,6 +31,7 @@ module GameData
@drying_per_hour = hash[:drying_per_hour] || 15 @drying_per_hour = hash[:drying_per_hour] || 15
@yield = hash[:yield] || [2, 5] @yield = hash[:yield] || [2, 5]
@yield.reverse! if @yield[1] < @yield[0] @yield.reverse! if @yield[1] < @yield[0]
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
def minimum_yield def minimum_yield

View File

@@ -40,13 +40,112 @@ module GameData
attr_reader :mega_move attr_reader :mega_move
attr_reader :unmega_form attr_reader :unmega_form
attr_reader :mega_message attr_reader :mega_message
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "species.dat" DATA_FILENAME = "species.dat"
PBS_BASE_FILENAME = ["pokemon", "pokemon_forms"]
extend ClassMethodsSymbols extend ClassMethodsSymbols
include InstanceMethods 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 species [Symbol, self, String]
# @param form [Integer] # @param form [Integer]
# @return [self, nil] # @return [self, nil]
@@ -71,84 +170,14 @@ module GameData
return ret return ret
end 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) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@species = hash[:species] || @id @species = hash[:species] || @id
@form = hash[:form] || 0 @form = hash[:form] || 0
@real_name = hash[:name] || "Unnamed" @real_name = hash[:real_name] || "Unnamed"
@real_form_name = hash[:form_name] @real_form_name = hash[:real_form_name]
@real_category = hash[:category] || "???" @real_category = hash[:real_category] || "???"
@real_pokedex_entry = hash[:pokedex_entry] || "???" @real_pokedex_entry = hash[:real_pokedex_entry] || "???"
@pokedex_form = hash[:pokedex_form] || @form @pokedex_form = hash[:pokedex_form] || @form
@types = hash[:types] || [:NORMAL] @types = hash[:types] || [:NORMAL]
@base_stats = hash[:base_stats] || {} @base_stats = hash[:base_stats] || {}
@@ -186,6 +215,7 @@ module GameData
@mega_move = hash[:mega_move] @mega_move = hash[:mega_move]
@unmega_form = hash[:unmega_form] || 0 @unmega_form = hash[:unmega_form] || 0
@mega_message = hash[:mega_message] || 0 @mega_message = hash[:mega_message] || 0
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
# @return [String] the translated name of this species # @return [String] the translated name of this species
@@ -352,5 +382,67 @@ module GameData
end end
return 1 return 1
end 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
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 :front_sprite_altitude
attr_accessor :shadow_x attr_accessor :shadow_x
attr_accessor :shadow_size attr_accessor :shadow_size
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "species_metrics.dat" DATA_FILENAME = "species_metrics.dat"
PBS_BASE_FILENAME = "pokemon_metrics"
SCHEMA = { SCHEMA = {
"BackSprite" => [0, "ii"], "SectionName" => [:id, "eV", :Species],
"FrontSprite" => [0, "ii"], "BackSprite" => [:back_sprite, "ii"],
"FrontSpriteAltitude" => [0, "i"], "FrontSprite" => [:front_sprite, "ii"],
"ShadowX" => [0, "i"], "FrontSpriteAltitude" => [:front_sprite_altitude, "i"],
"ShadowSize" => [0, "u"] "ShadowX" => [:shadow_x, "i"],
"ShadowSize" => [:shadow_size, "u"]
} }
extend ClassMethodsSymbols extend ClassMethodsSymbols
@@ -62,6 +65,7 @@ module GameData
@front_sprite_altitude = hash[:front_sprite_altitude] || 0 @front_sprite_altitude = hash[:front_sprite_altitude] || 0
@shadow_x = hash[:shadow_x] || 0 @shadow_x = hash[:shadow_x] || 0
@shadow_size = hash[:shadow_size] || 2 @shadow_size = hash[:shadow_size] || 2
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
def apply_metrics_to_sprite(sprite, index, shadow = false) def apply_metrics_to_sprite(sprite, index, shadow = false)
@@ -83,5 +87,17 @@ module GameData
return true return true
# return @front_sprite_altitude > 0 # return @front_sprite_altitude > 0
end 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
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 :icon_position # Where this ribbon's graphic is within ribbons.png
attr_reader :real_description attr_reader :real_description
attr_reader :flags attr_reader :flags
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "ribbons.dat" DATA_FILENAME = "ribbons.dat"
PBS_BASE_FILENAME = "ribbons"
SCHEMA = { SCHEMA = {
"Name" => [:name, "s"], "SectionName" => [:id, "m"],
"Name" => [:real_name, "s"],
"IconPosition" => [:icon_position, "u"], "IconPosition" => [:icon_position, "u"],
"Description" => [:description, "q"], "Description" => [:real_description, "q"],
"Flags" => [:flags, "*s"] "Flags" => [:flags, "*s"]
} }
@@ -21,10 +24,11 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@real_name = hash[:name] || "Unnamed" @real_name = hash[:real_name] || "Unnamed"
@icon_position = hash[:icon_position] || 0 @icon_position = hash[:icon_position] || 0
@real_description = hash[:description] || "???" @real_description = hash[:real_description] || "???"
@flags = hash[:flags] || [] @flags = hash[:flags] || []
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
# @return [String] the translated name of this ribbon # @return [String] the translated name of this ribbon

View File

@@ -5,9 +5,11 @@ module GameData
attr_accessor :version attr_accessor :version
attr_reader :step_chances attr_reader :step_chances
attr_reader :types attr_reader :types
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "encounters.dat" DATA_FILENAME = "encounters.dat"
PBS_BASE_FILENAME = "encounters"
extend ClassMethodsSymbols extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
@@ -63,6 +65,7 @@ module GameData
@version = hash[:version] || 0 @version = hash[:version] || 0
@step_chances = hash[:step_chances] @step_chances = hash[:step_chances]
@types = hash[:types] || {} @types = hash[:types] || {}
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
end 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 :items
attr_reader :real_lose_text attr_reader :real_lose_text
attr_reader :pokemon attr_reader :pokemon
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "trainers.dat" 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 = { SCHEMA = {
"SectionName" => [:id, "esU", :TrainerType],
"Items" => [:items, "*e", :Item], "Items" => [:items, "*e", :Item],
"LoseText" => [:lose_text, "q"], "LoseText" => [:real_lose_text, "q"],
"Pokemon" => [:pokemon, "ev", :Species], # Species, level "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"], "Form" => [:form, "u"],
"Name" => [:name, "s"], "Name" => [:real_name, "s"],
"Moves" => [:moves, "*e", :Move], "Moves" => [:moves, "*e", :Move],
"Ability" => [:ability, "e", :Ability], "Ability" => [:ability, "e", :Ability],
"AbilityIndex" => [:ability_index, "u"], "AbilityIndex" => [:ability_index, "u"],
@@ -36,6 +45,10 @@ module GameData
extend ClassMethodsSymbols extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
def self.sub_schema
return SUB_SCHEMA
end
# @param tr_type [Symbol, String] # @param tr_type [Symbol, String]
# @param tr_name [String] # @param tr_name [String]
# @param tr_version [Integer, nil] # @param tr_version [Integer, nil]
@@ -73,10 +86,10 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@trainer_type = hash[:trainer_type] @trainer_type = hash[:trainer_type]
@real_name = hash[:name] || "Unnamed" @real_name = hash[:real_name] || ""
@version = hash[:version] || 0 @version = hash[:version] || 0
@items = hash[:items] || [] @items = hash[:items] || []
@real_lose_text = hash[:lose_text] || "..." @real_lose_text = hash[:real_lose_text] || "..."
@pokemon = hash[:pokemon] || [] @pokemon = hash[:pokemon] || []
@pokemon.each do |pkmn| @pokemon.each do |pkmn|
GameData::Stat.each_main do |s| GameData::Stat.each_main do |s|
@@ -84,6 +97,7 @@ module GameData
pkmn[:ev][s.id] ||= 0 if pkmn[:ev] pkmn[:ev][s.id] ||= 0 if pkmn[:ev]
end end
end end
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
# @return [String] the translated name of this trainer # @return [String] the translated name of this trainer
@@ -153,7 +167,7 @@ module GameData
end end
end end
pkmn.happiness = pkmn_data[:happiness] if pkmn_data[:happiness] 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] if pkmn_data[:shadowness]
pkmn.makeShadow pkmn.makeShadow
pkmn.shiny = false pkmn.shiny = false
@@ -163,5 +177,38 @@ module GameData
end end
return trainer return trainer
end 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
end end

View File

@@ -12,22 +12,25 @@ module GameData
attr_reader :wild_capture_ME attr_reader :wild_capture_ME
attr_reader :surf_BGM attr_reader :surf_BGM
attr_reader :bicycle_BGM attr_reader :bicycle_BGM
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "metadata.dat" DATA_FILENAME = "metadata.dat"
PBS_BASE_FILENAME = "metadata"
SCHEMA = { SCHEMA = {
"StartMoney" => [1, "u"], "SectionName" => [:id, "u"],
"StartItemStorage" => [2, "*e", :Item], "StartMoney" => [:start_money, "u"],
"Home" => [3, "vuuu"], "StartItemStorage" => [:start_item_storage, "*e", :Item],
"StorageCreator" => [4, "s"], "Home" => [:home, "vuuu"],
"WildBattleBGM" => [5, "s"], "StorageCreator" => [:real_storage_creator, "s"],
"TrainerBattleBGM" => [6, "s"], "WildBattleBGM" => [:wild_battle_BGM, "s"],
"WildVictoryBGM" => [7, "s"], "TrainerBattleBGM" => [:trainer_battle_BGM, "s"],
"TrainerVictoryBGM" => [8, "s"], "WildVictoryBGM" => [:wild_victory_BGM, "s"],
"WildCaptureME" => [9, "s"], "TrainerVictoryBGM" => [:trainer_victory_BGM, "s"],
"SurfBGM" => [10, "s"], "WildCaptureME" => [:wild_capture_ME, "s"],
"BicycleBGM" => [11, "s"] "SurfBGM" => [:surf_BGM, "s"],
"BicycleBGM" => [:bicycle_BGM, "s"]
} }
extend ClassMethodsIDNumbers extend ClassMethodsIDNumbers
@@ -54,11 +57,11 @@ module GameData
end end
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id] || 0
@start_money = hash[:start_money] || 3000 @start_money = hash[:start_money] || 3000
@start_item_storage = hash[:start_item_storage] || [] @start_item_storage = hash[:start_item_storage] || []
@home = hash[:home] @home = hash[:home]
@real_storage_creator = hash[:storage_creator] @real_storage_creator = hash[:real_storage_creator]
@wild_battle_BGM = hash[:wild_battle_BGM] @wild_battle_BGM = hash[:wild_battle_BGM]
@trainer_battle_BGM = hash[:trainer_battle_BGM] @trainer_battle_BGM = hash[:trainer_battle_BGM]
@wild_victory_BGM = hash[:wild_victory_BGM] @wild_victory_BGM = hash[:wild_victory_BGM]
@@ -66,29 +69,13 @@ module GameData
@wild_capture_ME = hash[:wild_capture_ME] @wild_capture_ME = hash[:wild_capture_ME]
@surf_BGM = hash[:surf_BGM] @surf_BGM = hash[:surf_BGM]
@bicycle_BGM = hash[:bicycle_BGM] @bicycle_BGM = hash[:bicycle_BGM]
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
# @return [String] the translated name of the Pokémon Storage creator # @return [String] the translated name of the Pokémon Storage creator
def 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 return nil_or_empty?(ret) ? _INTL("Bill") : ret
end 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
end end

View File

@@ -4,20 +4,22 @@ module GameData
attr_reader :trainer_type attr_reader :trainer_type
attr_reader :walk_charset attr_reader :walk_charset
attr_reader :home attr_reader :home
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "player_metadata.dat" DATA_FILENAME = "player_metadata.dat"
SCHEMA = { SCHEMA = {
"TrainerType" => [1, "e", :TrainerType], "SectionName" => [:id, "u"],
"WalkCharset" => [2, "s"], "TrainerType" => [:trainer_type, "e", :TrainerType],
"RunCharset" => [3, "s"], "WalkCharset" => [:walk_charset, "s"],
"CycleCharset" => [4, "s"], "RunCharset" => [:run_charset, "s"],
"SurfCharset" => [5, "s"], "CycleCharset" => [:cycle_charset, "s"],
"DiveCharset" => [6, "s"], "SurfCharset" => [:surf_charset, "s"],
"FishCharset" => [7, "s"], "DiveCharset" => [:dive_charset, "s"],
"SurfFishCharset" => [8, "s"], "FishCharset" => [:fish_charset, "s"],
"Home" => [9, "vuuu"] "SurfFishCharset" => [:surf_fish_charset, "s"],
"Home" => [:home, "vuuu"]
} }
extend ClassMethodsIDNumbers extend ClassMethodsIDNumbers
@@ -25,6 +27,7 @@ module GameData
def self.editor_properties def self.editor_properties
return [ return [
["ID", ReadOnlyProperty, _INTL("ID number of this player.")],
["TrainerType", TrainerTypeProperty, _INTL("Trainer type of this player.")], ["TrainerType", TrainerTypeProperty, _INTL("Trainer type of this player.")],
["WalkCharset", CharacterProperty, _INTL("Charset used while the player is still or walking.")], ["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.")], ["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] @fish_charset = hash[:fish_charset]
@surf_fish_charset = hash[:surf_fish_charset] @surf_fish_charset = hash[:surf_fish_charset]
@home = hash[:home] @home = hash[:home]
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
def run_charset def run_charset
@@ -82,19 +86,10 @@ module GameData
return @surf_fish_charset || fish_charset return @surf_fish_charset || fish_charset
end end
def property_from_string(str) alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
case str def get_property_for_PBS(key)
when "TrainerType" then return @trainer_type key = "SectionName" if key == "ID"
when "WalkCharset" then return @walk_charset return __orig__get_property_for_PBS(key)
when "RunCharset" then return @run_charset
when "CycleCharset" then return @cycle_charset
when "SurfCharset" then return @surf_charset
when "DiveCharset" then return @dive_charset
when "FishCharset" then return @fish_charset
when "SurfFishCharset" then return @surf_fish_charset
when "Home" then return @home
end
return nil
end end
end end
end end

View File

@@ -23,33 +23,36 @@ module GameData
attr_reader :town_map_size attr_reader :town_map_size
attr_reader :battle_environment attr_reader :battle_environment
attr_reader :flags attr_reader :flags
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "map_metadata.dat" DATA_FILENAME = "map_metadata.dat"
PBS_BASE_FILENAME = "map_metadata"
SCHEMA = { SCHEMA = {
"Name" => [1, "s"], "SectionName" => [:id, "u"],
"Outdoor" => [2, "b"], "Name" => [:real_name, "s"],
"ShowArea" => [3, "b"], "Outdoor" => [:outdoor_map, "b"],
"Bicycle" => [4, "b"], "ShowArea" => [:announce_location, "b"],
"BicycleAlways" => [5, "b"], "Bicycle" => [:can_bicycle, "b"],
"HealingSpot" => [6, "vuu"], "BicycleAlways" => [:always_bicycle, "b"],
"Weather" => [7, "eu", :Weather], "HealingSpot" => [:teleport_destination, "vuu"],
"MapPosition" => [8, "uuu"], "Weather" => [:weather, "eu", :Weather],
"DiveMap" => [9, "v"], "MapPosition" => [:town_map_position, "uuu"],
"DarkMap" => [10, "b"], "DiveMap" => [:dive_map_id, "v"],
"SafariMap" => [11, "b"], "DarkMap" => [:dark_map, "b"],
"SnapEdges" => [12, "b"], "SafariMap" => [:safari_map, "b"],
"Dungeon" => [13, "b"], "SnapEdges" => [:snap_edges, "b"],
"BattleBack" => [14, "s"], "Dungeon" => [:random_dungeon, "b"],
"WildBattleBGM" => [15, "s"], "BattleBack" => [:battle_background, "s"],
"TrainerBattleBGM" => [16, "s"], "WildBattleBGM" => [:wild_battle_BGM, "s"],
"WildVictoryBGM" => [17, "s"], "TrainerBattleBGM" => [:trainer_battle_BGM, "s"],
"TrainerVictoryBGM" => [18, "s"], "WildVictoryBGM" => [:wild_victory_BGM, "s"],
"WildCaptureME" => [19, "s"], "TrainerVictoryBGM" => [:trainer_victory_BGM, "s"],
"MapSize" => [20, "us"], "WildCaptureME" => [:wild_capture_ME, "s"],
"Environment" => [21, "e", :Environment], "MapSize" => [:town_map_size, "us"],
"Flags" => [22, "*s"] "Environment" => [:battle_environment, "e", :Environment],
"Flags" => [:flags, "*s"]
} }
extend ClassMethodsIDNumbers extend ClassMethodsIDNumbers
@@ -57,6 +60,7 @@ module GameData
def self.editor_properties def self.editor_properties
return [ 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.")], ["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.")], ["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.")], ["ShowArea", BooleanProperty, _INTL("If true, the game will display the map's name upon entry.")],
@@ -84,7 +88,7 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@real_name = hash[:name] @real_name = hash[:real_name]
@outdoor_map = hash[:outdoor_map] @outdoor_map = hash[:outdoor_map]
@announce_location = hash[:announce_location] @announce_location = hash[:announce_location]
@can_bicycle = hash[:can_bicycle] @can_bicycle = hash[:can_bicycle]
@@ -106,34 +110,7 @@ module GameData
@town_map_size = hash[:town_map_size] @town_map_size = hash[:town_map_size]
@battle_environment = hash[:battle_environment] @battle_environment = hash[:battle_environment]
@flags = hash[:flags] || [] @flags = hash[:flags] || []
end @pbs_file_suffix = hash[:pbs_file_suffix] || ""
def property_from_string(str)
case str
when "Name" then return @real_name
when "Outdoor" then return @outdoor_map
when "ShowArea" then return @announce_location
when "Bicycle" then return @can_bicycle
when "BicycleAlways" then return @always_bicycle
when "HealingSpot" then return @teleport_destination
when "Weather" then return @weather
when "MapPosition" then return @town_map_position
when "DiveMap" then return @dive_map_id
when "DarkMap" then return @dark_map
when "SafariMap" then return @safari_map
when "SnapEdges" then return @snap_edges
when "Dungeon" then return @random_dungeon
when "BattleBack" then return @battle_background
when "WildBattleBGM" then return @wild_battle_BGM
when "TrainerBattleBGM" then return @trainer_battle_BGM
when "WildVictoryBGM" then return @wild_victory_BGM
when "TrainerVictoryBGM" then return @trainer_victory_BGM
when "WildCaptureME" then return @wild_capture_ME
when "MapSize" then return @town_map_size
when "Environment" then return @battle_environment
when "Flags" then return @flags
end
return nil
end end
# @return [String] the translated name of this map # @return [String] the translated name of this map
@@ -144,5 +121,11 @@ module GameData
def has_flag?(flag) def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase } return @flags.any? { |f| f.downcase == flag.downcase }
end 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
end end

View File

@@ -10,13 +10,16 @@ module GameData
attr_reader :floor_patch_under_walls attr_reader :floor_patch_under_walls
attr_reader :thin_north_wall_offset attr_reader :thin_north_wall_offset
attr_reader :flags attr_reader :flags
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "dungeon_tilesets.dat" DATA_FILENAME = "dungeon_tilesets.dat"
PBS_BASE_FILENAME = "dungeon_tilesets"
SCHEMA = { SCHEMA = {
"Autotile" => [:autotile, "us"], "SectionName" => [:id, "u"],
"Tile" => [:tile, "us"], "Autotile" => [:autotile, "^um"],
"Tile" => [:tile, "^um"],
"SnapToLargeGrid" => [:snap_to_large_grid, "b"], "SnapToLargeGrid" => [:snap_to_large_grid, "b"],
"LargeVoidTiles" => [:large_void_tiles, "b"], "LargeVoidTiles" => [:large_void_tiles, "b"],
"LargeWallTiles" => [:large_wall_tiles, "b"], "LargeWallTiles" => [:large_wall_tiles, "b"],
@@ -50,13 +53,14 @@ module GameData
@flags = hash[:flags] || [] @flags = hash[:flags] || []
@tile_type_ids = {} @tile_type_ids = {}
set_tile_type_ids(hash) set_tile_type_ids(hash)
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
def set_tile_type_ids(hash) def set_tile_type_ids(hash)
[hash[:autotile], hash[:tile]].each_with_index do |array, i| [hash[:autotile], hash[:tile]].each_with_index do |array, i|
array.each do |tile_info| array.each do |tile_info|
next if !tile_info next if !tile_info
tile_type = tile_info[1].downcase.to_sym tile_type = tile_info[1]
if tile_type == :walls if tile_type == :walls
if @double_walls if @double_walls
if @large_wall_tiles if @large_wall_tiles
@@ -192,18 +196,27 @@ module GameData
return ret return ret
end end
def property_from_string(str) alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
case str def get_property_for_PBS(key)
when "SnapToLargeGrid" then return @snap_to_large_grid ret = __orig__get_property_for_PBS(key)
when "LargeVoidTiles" then return @large_void_tiles case key
when "LargeWallTiles" then return @large_wall_tiles when "ThinNorthWallOffset"
when "LargeFloorTiles" then return @large_floor_tiles ret = nil if ret == 0
when "DoubleWalls" then return @double_walls when "Tile", "Autotile"
when "FloorPatchUnderWalls" then return @floor_patch_under_walls ret = []
when "ThinNorthWallOffset" then return @thin_north_wall_offset @tile_type_ids.each do |tile_type, tile_ids|
when "Flags" then return @flags tile_ids.each do |tile|
end case key
return nil 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 end
end end

View File

@@ -25,19 +25,22 @@ module GameData
attr_reader :void_decoration_density, :void_decoration_large_density attr_reader :void_decoration_density, :void_decoration_large_density
attr_reader :rng_seed attr_reader :rng_seed
attr_reader :flags attr_reader :flags
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "dungeon_parameters.dat" DATA_FILENAME = "dungeon_parameters.dat"
PBS_BASE_FILENAME = "dungeon_parameters"
SCHEMA = { SCHEMA = {
"SectionName" => [:id, "mV"],
"DungeonSize" => [:dungeon_size, "vv"], "DungeonSize" => [:dungeon_size, "vv"],
"CellSize" => [:cell_size, "vv"], "CellSize" => [:cell_size, "vv"],
"MinRoomSize" => [:min_room_size, "vv"], "MinRoomSize" => [:min_room_size, "vv"],
"MaxRoomSize" => [:max_room_size, "vv"], "MaxRoomSize" => [:max_room_size, "vv"],
"CorridorWidth" => [:corridor_width, "v"], "CorridorWidth" => [:corridor_width, "v"],
"ShiftCorridors" => [:shift_corridors, "b"], "ShiftCorridors" => [:random_corridor_shift, "b"],
"NodeLayout" => [:node_layout, "s"], "NodeLayout" => [:node_layout, "m"],
"RoomLayout" => [:room_layout, "s"], "RoomLayout" => [:room_layout, "m"],
"RoomChance" => [:room_chance, "v"], "RoomChance" => [:room_chance, "v"],
"ExtraConnections" => [:extra_connections_count, "u"], "ExtraConnections" => [:extra_connections_count, "u"],
"FloorPatches" => [:floor_patches, "vvu"], "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_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 @room_max_height = (hash[:max_room_size]) ? hash[:max_room_size][1] : @cell_height - 1
@corridor_width = hash[:corridor_width] || 2 @corridor_width = hash[:corridor_width] || 2
@random_corridor_shift = hash[:shift_corridors] @random_corridor_shift = hash[:random_corridor_shift]
@node_layout = hash[:node_layout]&.downcase&.to_sym || :full @node_layout = hash[:node_layout] || :full
@room_layout = hash[:room_layout]&.downcase&.to_sym || :full @room_layout = hash[:room_layout] || :full
@room_chance = hash[:room_chance] || 70 @room_chance = hash[:room_chance] || 70
@extra_connections_count = hash[:extra_connections_count] || 2 @extra_connections_count = hash[:extra_connections_count] || 2
@floor_patch_radius = (hash[:floor_patches]) ? hash[:floor_patches][0] : 3 @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 @void_decoration_large_density = (hash[:void_decorations]) ? hash[:void_decorations][1] : 200
@rng_seed = hash[:rng_seed] @rng_seed = hash[:rng_seed]
@flags = hash[:flags] || [] @flags = hash[:flags] || []
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
def has_flag?(flag) def has_flag?(flag)
@@ -114,25 +118,19 @@ module GameData
return width, height return width, height
end end
def property_from_string(str) alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
case str 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 "DungeonSize" then return [@cell_count_x, @cell_count_y]
when "CellSize" then return [@cell_width, @cell_height] when "CellSize" then return [@cell_width, @cell_height]
when "MinRoomSize" then return [@room_min_width, @room_min_height] when "MinRoomSize" then return [@room_min_width, @room_min_height]
when "MaxRoomSize" then return [@room_max_width, @room_max_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 "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 "FloorDecorations" then return [@floor_decoration_density, @floor_decoration_large_density]
when "VoidDecorations" then return [@void_decoration_density, @void_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 end
return nil return __orig__get_property_for_PBS(key)
end end
end end
end end

View File

@@ -6,34 +6,43 @@ module GameData
attr_reader :body, :body1, :body2 attr_reader :body, :body1, :body2
attr_reader :battle_request, :battle_remind attr_reader :battle_request, :battle_remind
attr_reader :end attr_reader :end
attr_reader :pbs_file_suffix
DATA = {} DATA = {}
DATA_FILENAME = "phone.dat" DATA_FILENAME = "phone.dat"
PBS_BASE_FILENAME = "phone"
SCHEMA = { SCHEMA = {
"Intro" => [:intro, "q"], "SectionName" => [:id, "q"],
"IntroMorning" => [:intro_morning, "q"], "Intro" => [:intro, "^q"],
"IntroAfternoon" => [:intro_afternoon, "q"], "IntroMorning" => [:intro_morning, "^q"],
"IntroEvening" => [:intro_evening, "q"], "IntroAfternoon" => [:intro_afternoon, "^q"],
"Body" => [:body, "q"], "IntroEvening" => [:intro_evening, "^q"],
"Body1" => [:body1, "q"], "Body" => [:body, "^q"],
"Body2" => [:body2, "q"], "Body1" => [:body1, "^q"],
"BattleRequest" => [:battle_request, "q"], "Body2" => [:body2, "^q"],
"BattleRemind" => [:battle_remind, "q"], "BattleRequest" => [:battle_request, "^q"],
"End" => [:end, "q"] "BattleRemind" => [:battle_remind, "^q"],
"End" => [:end, "^q"]
} }
extend ClassMethodsSymbols extend ClassMethodsSymbols
include InstanceMethods include InstanceMethods
# @param tr_type [Symbol, String] # @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] # @param tr_version [Integer, nil]
# @return [Boolean] whether the given other is defined as a self # @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_type => [Symbol, String]
validate tr_name => [String] validate tr_name => [String, NilClass]
key = [tr_type.to_sym, tr_name, tr_version] key = [tr_type.to_sym, tr_name, tr_version]
key = key[0] if key[1] == nil
return !self::DATA[key].nil? return !self::DATA[key].nil?
end end
@@ -63,7 +72,7 @@ module GameData
def initialize(hash) def initialize(hash)
@id = hash[:id] @id = hash[:id]
@trainer_type = hash[:trainer_type] @trainer_type = hash[:trainer_type]
@real_name = hash[:name] @real_name = hash[:real_name]
@version = hash[:version] || 0 @version = hash[:version] || 0
@intro = hash[:intro] @intro = hash[:intro]
@intro_morning = hash[:intro_morning] @intro_morning = hash[:intro_morning]
@@ -75,22 +84,17 @@ module GameData
@battle_request = hash[:battle_request] @battle_request = hash[:battle_request]
@battle_remind = hash[:battle_remind] @battle_remind = hash[:battle_remind]
@end = hash[:end] @end = hash[:end]
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end end
def property_from_string(str) alias __orig__get_property_for_PBS get_property_for_PBS unless method_defined?(:__orig__get_property_for_PBS)
case str def get_property_for_PBS(key)
when "Intro" then return @intro if key == "SectionName"
when "IntroMorning" then return @intro_morning return "Default" if @id == "default"
when "IntroAfternoon" then return @intro_afternoon ret = [@trainer_type, @real_name, (@version > 0) ? @version : nil]
when "IntroEvening" then return @intro_evening return ret.compact.join(",")
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
end end
return nil return __orig__get_property_for_PBS(key)
end end
end end
end end

View File

@@ -427,9 +427,8 @@ class Battle
if battler_side.effects[PBEffects::StealthRock] && battler.takesIndirectDamage? && if battler_side.effects[PBEffects::StealthRock] && battler.takesIndirectDamage? &&
GameData::Type.exists?(:ROCK) && !battler.hasActiveItem?(:HEAVYDUTYBOOTS) GameData::Type.exists?(:ROCK) && !battler.hasActiveItem?(:HEAVYDUTYBOOTS)
bTypes = battler.pbTypes(true) bTypes = battler.pbTypes(true)
eff = Effectiveness.calculate(:ROCK, bTypes[0], bTypes[1], bTypes[2]) eff = Effectiveness.calculate(:ROCK, *bTypes)
if !Effectiveness.ineffective?(eff) if !Effectiveness.ineffective?(eff)
eff = eff.to_f / Effectiveness::NORMAL_EFFECTIVE
battler.pbReduceHP(battler.totalhp * eff / 8, false) battler.pbReduceHP(battler.totalhp * eff / 8, false)
pbDisplay(_INTL("Pointed stones dug into {1}!", battler.pbThis)) pbDisplay(_INTL("Pointed stones dug into {1}!", battler.pbThis))
battler.pbItemHPHealCheck 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 # 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. # same type more than once, and should not include any invalid types.
def pbTypes(withType3 = false) def pbTypes(withExtraType = false)
ret = @types.uniq ret = @types.uniq
# Burn Up erases the Fire-type. # Burn Up erases the Fire-type.
ret.delete(:FIRE) if @effects[PBEffects::BurnUp] ret.delete(:FIRE) if @effects[PBEffects::BurnUp]
@@ -312,8 +312,8 @@ class Battle::Battler
ret.push(:NORMAL) if ret.length == 0 ret.push(:NORMAL) if ret.length == 0
end end
# Add the third type specially. # Add the third type specially.
if withType3 && @effects[PBEffects::Type3] && !ret.include?(@effects[PBEffects::Type3]) if withExtraType && @effects[PBEffects::ExtraType] && !ret.include?(@effects[PBEffects::ExtraType])
ret.push(@effects[PBEffects::Type3]) ret.push(@effects[PBEffects::ExtraType])
end end
return ret return ret
end end

View File

@@ -172,6 +172,7 @@ class Battle::Battler
@effects[PBEffects::Encore] = 0 @effects[PBEffects::Encore] = 0
@effects[PBEffects::EncoreMove] = nil @effects[PBEffects::EncoreMove] = nil
@effects[PBEffects::Endure] = false @effects[PBEffects::Endure] = false
@effects[PBEffects::ExtraType] = nil
@effects[PBEffects::FirstPledge] = nil @effects[PBEffects::FirstPledge] = nil
@effects[PBEffects::FlashFire] = false @effects[PBEffects::FlashFire] = false
@effects[PBEffects::Flinch] = false @effects[PBEffects::Flinch] = false
@@ -271,7 +272,6 @@ class Battle::Battler
end end
@effects[PBEffects::Truant] = false @effects[PBEffects::Truant] = false
@effects[PBEffects::TwoTurnAttack] = nil @effects[PBEffects::TwoTurnAttack] = nil
@effects[PBEffects::Type3] = nil
@effects[PBEffects::Unburden] = false @effects[PBEffects::Unburden] = false
@effects[PBEffects::Uproar] = 0 @effects[PBEffects::Uproar] = 0
@effects[PBEffects::WaterSport] = false @effects[PBEffects::WaterSport] = false

View File

@@ -130,14 +130,14 @@ class Battle::Battler
if newType.is_a?(Battle::Battler) if newType.is_a?(Battle::Battler)
newTypes = newType.pbTypes newTypes = newType.pbTypes
newTypes.push(:NORMAL) if newTypes.length == 0 newTypes.push(:NORMAL) if newTypes.length == 0
newType3 = newType.effects[PBEffects::Type3] newExtraType = newType.effects[PBEffects::ExtraType]
newType3 = nil if newTypes.include?(newType3) newExtraType = nil if newTypes.include?(newExtraType)
@types = newTypes.clone @types = newTypes.clone
@effects[PBEffects::Type3] = newType3 @effects[PBEffects::ExtraType] = newExtraType
else else
newType = GameData::Type.get(newType).id newType = GameData::Type.get(newType).id
@types = [newType] @types = [newType]
@effects[PBEffects::Type3] = nil @effects[PBEffects::ExtraType] = nil
end end
@effects[PBEffects::BurnUp] = false @effects[PBEffects::BurnUp] = false
@effects[PBEffects::Roost] = false @effects[PBEffects::Roost] = false
@@ -145,7 +145,7 @@ class Battle::Battler
def pbResetTypes def pbResetTypes
@types = @pokemon.types @types = @pokemon.types
@effects[PBEffects::Type3] = nil @effects[PBEffects::ExtraType] = nil
@effects[PBEffects::BurnUp] = false @effects[PBEffects::BurnUp] = false
@effects[PBEffects::Roost] = false @effects[PBEffects::Roost] = false
end end

View File

@@ -30,58 +30,51 @@ class Battle::Move
# Type effectiveness calculation # Type effectiveness calculation
#============================================================================= #=============================================================================
def pbCalcTypeModSingle(moveType, defType, user, target) def pbCalcTypeModSingle(moveType, defType, user, target)
ret = Effectiveness.calculate_one(moveType, defType) ret = Effectiveness.calculate(moveType, defType)
if Effectiveness.ineffective_type?(moveType, defType) if Effectiveness.ineffective_type?(moveType, defType)
# Ring Target # Ring Target
if target.hasActiveItem?(:RINGTARGET) if target.hasActiveItem?(:RINGTARGET)
ret = Effectiveness::NORMAL_EFFECTIVE_ONE ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
end end
# Foresight # Foresight
if (user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]) && if (user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]) &&
defType == :GHOST defType == :GHOST
ret = Effectiveness::NORMAL_EFFECTIVE_ONE ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
end end
# Miracle Eye # Miracle Eye
if target.effects[PBEffects::MiracleEye] && defType == :DARK if target.effects[PBEffects::MiracleEye] && defType == :DARK
ret = Effectiveness::NORMAL_EFFECTIVE_ONE ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
end end
elsif Effectiveness.super_effective_type?(moveType, defType) elsif Effectiveness.super_effective_type?(moveType, defType)
# Delta Stream's weather # Delta Stream's weather
if target.effectiveWeather == :StrongWinds && defType == :FLYING if target.effectiveWeather == :StrongWinds && defType == :FLYING
ret = Effectiveness::NORMAL_EFFECTIVE_ONE ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
end end
end end
# Grounded Flying-type Pokémon become susceptible to Ground moves # Grounded Flying-type Pokémon become susceptible to Ground moves
if !target.airborne? && defType == :FLYING && moveType == :GROUND if !target.airborne? && defType == :FLYING && moveType == :GROUND
ret = Effectiveness::NORMAL_EFFECTIVE_ONE ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
end end
return ret return ret
end end
def pbCalcTypeMod(moveType, user, target) def pbCalcTypeMod(moveType, user, target)
return Effectiveness::NORMAL_EFFECTIVE if !moveType ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
return Effectiveness::NORMAL_EFFECTIVE if moveType == :GROUND && return ret if !moveType
target.pbHasType?(:FLYING) && return ret if moveType == :GROUND && target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL)
target.hasActiveItem?(:IRONBALL)
# Determine types
tTypes = target.pbTypes(true)
# Get effectivenesses # Get effectivenesses
typeMods = [Effectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max
if moveType == :SHADOW if moveType == :SHADOW
if target.shadowPokemon? if target.shadowPokemon?
typeMods[0] = Effectiveness::NOT_VERY_EFFECTIVE_ONE ret = Effectiveness::NOT_VERY_EFFECTIVE_MULTIPLIER
else else
typeMods[0] = Effectiveness::SUPER_EFFECTIVE_ONE ret = Effectiveness::SUPER_EFFECTIVE_MULTIPLIER
end end
else else
tTypes.each_with_index do |type, i| target.pbTypes(true).each do |type|
typeMods[i] = pbCalcTypeModSingle(moveType, type, user, target) ret *= pbCalcTypeModSingle(moveType, type, user, target)
end end
end
# Multiply all effectivenesses together
ret = 1
typeMods.each { |m| ret *= m }
ret *= 2 if target.effects[PBEffects::TarShot] && moveType == :FIRE ret *= 2 if target.effects[PBEffects::TarShot] && moveType == :FIRE
end
return ret return ret
end end
@@ -453,7 +446,7 @@ class Battle::Move
end end
end end
# Type effectiveness # Type effectiveness
multipliers[:final_damage_multiplier] *= target.damageState.typeMod.to_f / Effectiveness::NORMAL_EFFECTIVE multipliers[:final_damage_multiplier] *= target.damageState.typeMod
# Burn # Burn
if user.status == :BURN && physicalMove? && damageReducedByBurn? && if user.status == :BURN && physicalMove? && damageReducedByBurn? &&
!user.hasActiveAbility?(:GUTS) !user.hasActiveAbility?(:GUTS)

View File

@@ -280,7 +280,7 @@ end
#=============================================================================== #===============================================================================
class Battle::Move::FreezeTargetSuperEffectiveAgainstWater < Battle::Move::FreezeTarget class Battle::Move::FreezeTargetSuperEffectiveAgainstWater < Battle::Move::FreezeTarget
def pbCalcTypeModSingle(moveType, defType, user, target) def pbCalcTypeModSingle(moveType, defType, user, target)
return Effectiveness::SUPER_EFFECTIVE_ONE if defType == :WATER return Effectiveness::SUPER_EFFECTIVE_MULTIPLIER if defType == :WATER
return super return super
end end
end end
@@ -771,7 +771,7 @@ class Battle::Move::SetUserTypesToTargetTypes < Battle::Move
return true return true
end end
if user.pbTypes == target.pbTypes && 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 @battle.pbDisplay(_INTL("But it failed!")) if show_message
return true return true
end end
@@ -880,7 +880,7 @@ class Battle::Move::AddGhostTypeToTarget < Battle::Move
end end
def pbEffectAgainstTarget(user, target) def pbEffectAgainstTarget(user, target)
target.effects[PBEffects::Type3] = :GHOST target.effects[PBEffects::ExtraType] = :GHOST
typeName = GameData::Type.get(:GHOST).name typeName = GameData::Type.get(:GHOST).name
@battle.pbDisplay(_INTL("{1} transformed into the {2} type!", target.pbThis, typeName)) @battle.pbDisplay(_INTL("{1} transformed into the {2} type!", target.pbThis, typeName))
end end
@@ -901,7 +901,7 @@ class Battle::Move::AddGrassTypeToTarget < Battle::Move
end end
def pbEffectAgainstTarget(user, target) def pbEffectAgainstTarget(user, target)
target.effects[PBEffects::Type3] = :GRASS target.effects[PBEffects::ExtraType] = :GRASS
typeName = GameData::Type.get(:GRASS).name typeName = GameData::Type.get(:GRASS).name
@battle.pbDisplay(_INTL("{1} transformed into the {2} type!", target.pbThis, typeName)) @battle.pbDisplay(_INTL("{1} transformed into the {2} type!", target.pbThis, typeName))
end end
@@ -1263,7 +1263,7 @@ class Battle::Move::HitsTargetInSkyGroundsTarget < Battle::Move
def hitsFlyingTargets?; return true; end def hitsFlyingTargets?; return true; end
def pbCalcTypeModSingle(moveType, defType, user, target) 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 return super
end end

View File

@@ -1111,8 +1111,7 @@ class Battle::Move::EffectivenessIncludesFlyingType < Battle::Move
def pbCalcTypeModSingle(moveType, defType, user, target) def pbCalcTypeModSingle(moveType, defType, user, target)
ret = super ret = super
if GameData::Type.exists?(:FLYING) if GameData::Type.exists?(:FLYING)
flyingEff = Effectiveness.calculate_one(:FLYING, defType) ret *= Effectiveness.calculate(:FLYING, defType)
ret *= flyingEff.to_f / Effectiveness::NORMAL_EFFECTIVE_ONE
end end
return ret return ret
end end

View File

@@ -455,7 +455,7 @@ class Battle::Move::TwoTurnAttackInvulnerableInSkyTargetCannotAct < Battle::Move
end end
def pbCalcTypeMod(movetype, user, target) def pbCalcTypeMod(movetype, user, target)
return Effectiveness::INEFFECTIVE if target.pbHasType?(:FLYING) return Effectiveness::INEFFECTIVE_MULTIPLIER if target.pbHasType?(:FLYING)
return super return super
end end

View File

@@ -24,16 +24,62 @@ class Battle::AI
#============================================================================= #=============================================================================
# Move's type effectiveness # 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 # For switching. Determines the effectiveness of a potential switch-in against
# an opposing battler. # an opposing battler.
def pbCalcTypeModPokemon(pkmn, target_battler) def pbCalcTypeModPokemon(pkmn, target_battler)
mod1 = Effectiveness.calculate(pkmn.types[0], target_battler.types[0], target_battler.types[1]) ret = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
mod2 = Effectiveness::NORMAL_EFFECTIVE pkmn.types.each do |thisType|
if pkmn.types.length > 1 ret *= Effectiveness.calculate(thisType, *target_battler.types)
mod2 = Effectiveness.calculate(pkmn.types[1], target_battler.types[0], target_battler.types[1])
mod2 = mod2.to_f / Effectiveness::NORMAL_EFFECTIVE
end end
return mod1 * mod2 return ret
end end
#============================================================================= #=============================================================================

View File

@@ -28,6 +28,7 @@ module PBEffects
Encore = 23 Encore = 23
EncoreMove = 24 EncoreMove = 24
Endure = 25 Endure = 25
ExtraType = 111
FirstPledge = 26 FirstPledge = 26
FlashFire = 27 FlashFire = 27
Flinch = 28 Flinch = 28
@@ -113,7 +114,6 @@ module PBEffects
TrappingUser = 108 TrappingUser = 108
Truant = 109 Truant = 109
TwoTurnAttack = 110 TwoTurnAttack = 110
Type3 = 111
Unburden = 112 Unburden = 112
Uproar = 113 Uproar = 113
WaterSport = 114 WaterSport = 114

View File

@@ -30,7 +30,7 @@ class Battle::DamageState
def initialize; reset; end def initialize; reset; end
def reset def reset
@typeMod = Effectiveness::INEFFECTIVE @typeMod = Effectiveness::INEFFECTIVE_MULTIPLIER
@unaffected = false @unaffected = false
@protected = false @protected = false
@missed = false @missed = false

View File

@@ -2607,7 +2607,7 @@ Battle::AbilityEffects::OnSwitchIn.add(:ANTICIPATION,
if Settings::MECHANICS_GENERATION >= 6 && m.function == "TypeDependsOnUserIVs" # Hidden Power if Settings::MECHANICS_GENERATION >= 6 && m.function == "TypeDependsOnUserIVs" # Hidden Power
moveType = pbHiddenPower(b.pokemon)[0] moveType = pbHiddenPower(b.pokemon)[0]
end end
eff = Effectiveness.calculate(moveType, types[0], types[1], types[2]) eff = Effectiveness.calculate(moveType, types)
next if Effectiveness.ineffective?(eff) next if Effectiveness.ineffective?(eff)
next if !Effectiveness.super_effective?(eff) && next if !Effectiveness.super_effective?(eff) &&
!["OHKO", "OHKOIce", "OHKOHitsUndergroundTarget"].include?(m.function) !["OHKO", "OHKOIce", "OHKOHitsUndergroundTarget"].include?(m.function)

View File

@@ -10,7 +10,7 @@ class Battle::SuccessState
def initialize; clear; end def initialize; clear; end
def clear(full = true) def clear(full = true)
@typeMod = Effectiveness::NORMAL_EFFECTIVE @typeMod = Effectiveness::NORMAL_EFFECTIVE_MULTIPLIER
@useState = 0 @useState = 0
@protected = false @protected = false
@skill = 0 if full @skill = 0 if full

View File

@@ -227,13 +227,15 @@ module BattleCreationHelperMethods
battle.showAnims = ($PokemonSystem.battlescene == 0) battle.showAnims = ($PokemonSystem.battlescene == 0)
battle.showAnims = battleRules["battleAnims"] if !battleRules["battleAnims"].nil? battle.showAnims = battleRules["battleAnims"] if !battleRules["battleAnims"].nil?
# Terrain # 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 case $game_screen.weather_type
when :Storm when :Storm
battle.defaultTerrain = :Electric battle.defaultTerrain = :Electric
when :Fog when :Fog
battle.defaultTerrain = :Misty battle.defaultTerrain = :Misty
end end
end
else else
battle.defaultTerrain = battleRules["defaultTerrain"] battle.defaultTerrain = battleRules["defaultTerrain"]
end end

View File

@@ -707,7 +707,11 @@ class Pokemon
# @return [Boolean] whether the Pokémon is compatible with the given move # @return [Boolean] whether the Pokémon is compatible with the given move
def compatible_with_move?(move_id) def compatible_with_move?(move_id)
move_data = GameData::Move.try_get(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 end
def can_relearn_move? def can_relearn_move?

View File

@@ -25,7 +25,7 @@ class Window_Pokedex < Window_DrawableCommand
end end
def species def species
return (@commands.length == 0) ? 0 : @commands[self.index][0] return (@commands.length == 0) ? 0 : @commands[self.index][:species]
end end
def itemCount def itemCount
@@ -35,9 +35,9 @@ class Window_Pokedex < Window_DrawableCommand
def drawItem(index, _count, rect) def drawItem(index, _count, rect)
return if index >= self.top_row + self.page_item_max return if index >= self.top_row + self.page_item_max
rect = Rect.new(rect.x + 16, rect.y, rect.width - 16, rect.height) rect = Rect.new(rect.x + 16, rect.y, rect.width - 16, rect.height)
species = @commands[index][0] species = @commands[index][:species]
indexNumber = @commands[index][4] indexNumber = @commands[index][:number]
indexNumber -= 1 if @commands[index][5] indexNumber -= 1 if @commands[index][:shift]
if $player.seen?(species) if $player.seen?(species)
if $player.owned?(species) if $player.owned?(species)
pbCopyBitmap(self.contents, @pokeballOwn.bitmap, rect.x - 6, rect.y + 10) 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) pbCopyBitmap(self.contents, @pokeballSeen.bitmap, rect.x - 6, rect.y + 10)
end end
num_text = sprintf("%03d", indexNumber) num_text = sprintf("%03d", indexNumber)
name_text = @commands[index][1] name_text = @commands[index][:name]
else else
num_text = sprintf("%03d", indexNumber) num_text = sprintf("%03d", indexNumber)
name_text = "----------" name_text = "----------"
@@ -362,13 +362,17 @@ class PokemonPokedex_Scene
next if !pbCanAddForModeList?($PokemonGlobal.pokedexMode, species) next if !pbCanAddForModeList?($PokemonGlobal.pokedexMode, species)
_gender, form, _shiny = $player.pokedex.last_form_seen(species) _gender, form, _shiny = $player.pokedex.last_form_seen(species)
species_data = GameData::Species.get_species_form(species, form) species_data = GameData::Species.get_species_form(species, form)
color = species_data.color ret.push({
type1 = species_data.types[0] :species => species,
type2 = species_data.types[1] || type1 :name => species_data.name,
shape = species_data.shape :height => species_data.height,
height = species_data.height :weight => species_data.weight,
weight = species_data.weight :number => i + 1,
ret.push([species, species_data.name, height, weight, i + 1, shift, type1, type2, color, shape]) :shift => shift,
:types => species_data.types,
:color => species_data.color,
:shape => species_data.shape
})
end end
return ret return ret
end end
@@ -378,27 +382,27 @@ class PokemonPokedex_Scene
case $PokemonGlobal.pokedexMode case $PokemonGlobal.pokedexMode
when MODENUMERICAL when MODENUMERICAL
# Hide the Dex number 0 species if unseen # 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 # Remove unseen species from the end of the list
i = dexlist.length - 1 i = dexlist.length - 1
loop do 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 dexlist[i] = nil
i -= 1 i -= 1
end end
dexlist.compact! dexlist.compact!
# Sort species in ascending order by Regional Dex number # 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 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 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 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 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 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 end
@dexlist = dexlist @dexlist = dexlist
@sprites["pokedex"].commands = @dexlist @sprites["pokedex"].commands = @dexlist
@@ -774,8 +778,8 @@ class PokemonPokedex_Scene
if params[1] >= 0 if params[1] >= 0
scanNameCommand = @nameCommands[params[1]].scan(/./) scanNameCommand = @nameCommands[params[1]].scan(/./)
dexlist = dexlist.find_all { |item| dexlist = dexlist.find_all { |item|
next false if !$player.seen?(item[0]) next false if !$player.seen?(item[:species])
firstChar = item[1][0, 1] firstChar = item[:name][0, 1]
next scanNameCommand.any? { |v| v == firstChar } next scanNameCommand.any? { |v| v == firstChar }
} }
end end
@@ -784,18 +788,17 @@ class PokemonPokedex_Scene
stype1 = (params[2] >= 0) ? @typeCommands[params[2]].id : nil stype1 = (params[2] >= 0) ? @typeCommands[params[2]].id : nil
stype2 = (params[3] >= 0) ? @typeCommands[params[3]].id : nil stype2 = (params[3] >= 0) ? @typeCommands[params[3]].id : nil
dexlist = dexlist.find_all { |item| dexlist = dexlist.find_all { |item|
next false if !$player.owned?(item[0]) next false if !$player.owned?(item[:species])
type1 = item[6] types = item[:types]
type2 = item[7]
if stype1 && stype2 if stype1 && stype2
# Find species that match both types # Find species that match both types
next (type1 == stype1 && type2 == stype2) || (type1 == stype2 && type2 == stype1) next types.include?(stype1) && types.include?(stype2)
elsif stype1 elsif stype1
# Find species that match first type entered # Find species that match first type entered
next type1 == stype1 || type2 == stype1 next types.include?(stype1)
elsif stype2 elsif stype2
# Find species that match second type entered # Find species that match second type entered
next type1 == stype2 || type2 == stype2 next types.include?(stype2)
else else
next false next false
end end
@@ -806,8 +809,8 @@ class PokemonPokedex_Scene
minh = (params[4] < 0) ? 0 : (params[4] >= @heightCommands.length) ? 999 : @heightCommands[params[4]] 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]] maxh = (params[5] < 0) ? 999 : (params[5] >= @heightCommands.length) ? 0 : @heightCommands[params[5]]
dexlist = dexlist.find_all { |item| dexlist = dexlist.find_all { |item|
next false if !$player.owned?(item[0]) next false if !$player.owned?(item[:species])
height = item[2] height = item[:height]
next height >= minh && height <= maxh next height >= minh && height <= maxh
} }
end end
@@ -816,8 +819,8 @@ class PokemonPokedex_Scene
minw = (params[6] < 0) ? 0 : (params[6] >= @weightCommands.length) ? 9999 : @weightCommands[params[6]] 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]] maxw = (params[7] < 0) ? 9999 : (params[7] >= @weightCommands.length) ? 0 : @weightCommands[params[7]]
dexlist = dexlist.find_all { |item| dexlist = dexlist.find_all { |item|
next false if !$player.owned?(item[0]) next false if !$player.owned?(item[:species])
weight = item[3] weight = item[:weight]
next weight >= minw && weight <= maxw next weight >= minw && weight <= maxw
} }
end end
@@ -825,27 +828,27 @@ class PokemonPokedex_Scene
if params[8] >= 0 if params[8] >= 0
scolor = @colorCommands[params[8]].id scolor = @colorCommands[params[8]].id
dexlist = dexlist.find_all { |item| dexlist = dexlist.find_all { |item|
next false if !$player.seen?(item[0]) next false if !$player.seen?(item[:species])
next item[8] == scolor next item[:color] == scolor
} }
end end
# Filter by shape # Filter by shape
if params[9] >= 0 if params[9] >= 0
sshape = @shapeCommands[params[9]].id sshape = @shapeCommands[params[9]].id
dexlist = dexlist.find_all { |item| dexlist = dexlist.find_all { |item|
next false if !$player.seen?(item[0]) next false if !$player.seen?(item[:species])
next item[9] == sshape next item[:shape] == sshape
} }
end end
# Remove all unseen species from the results # 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 case $PokemonGlobal.pokedexMode
when MODENUMERICAL then dexlist.sort! { |a, b| a[4] <=> b[4] } when MODENUMERICAL then dexlist.sort! { |a, b| a[:number] <=> b[:number] }
when MODEATOZ then dexlist.sort! { |a, b| a[1] <=> b[1] } when MODEATOZ then dexlist.sort! { |a, b| a[:name] <=> b[:name] }
when MODEHEAVIEST then dexlist.sort! { |a, b| b[3] <=> a[3] } when MODEHEAVIEST then dexlist.sort! { |a, b| b[:weight] <=> a[:weight] }
when MODELIGHTEST then dexlist.sort! { |a, b| a[3] <=> b[3] } when MODELIGHTEST then dexlist.sort! { |a, b| a[:weight] <=> b[:weight] }
when MODETALLEST then dexlist.sort! { |a, b| b[2] <=> a[2] } when MODETALLEST then dexlist.sort! { |a, b| b[:height] <=> a[:height] }
when MODESMALLEST then dexlist.sort! { |a, b| a[2] <=> b[2] } when MODESMALLEST then dexlist.sort! { |a, b| a[:height] <=> b[:height] }
end end
return dexlist return dexlist
end end
@@ -858,7 +861,7 @@ class PokemonPokedex_Scene
@searchParams = [$PokemonGlobal.pokedexMode, -1, -1, -1, -1, -1, -1, -1, -1, -1] @searchParams = [$PokemonGlobal.pokedexMode, -1, -1, -1, -1, -1, -1, -1, -1, -1]
pbRefreshDexList($PokemonGlobal.pokedexIndex[pbGetSavePositionIndex]) pbRefreshDexList($PokemonGlobal.pokedexIndex[pbGetSavePositionIndex])
@dexlist.length.times do |i| @dexlist.length.times do |i|
next if @dexlist[i][0] != oldspecies next if @dexlist[i][:species] != oldspecies
@sprites["pokedex"].index = i @sprites["pokedex"].index = i
pbRefresh pbRefresh
break break

View File

@@ -17,13 +17,13 @@ class PokemonPokedexInfo_Scene
@sprites["infosprite"].setOffset(PictureOrigin::CENTER) @sprites["infosprite"].setOffset(PictureOrigin::CENTER)
@sprites["infosprite"].x = 104 @sprites["infosprite"].x = 104
@sprites["infosprite"].y = 136 @sprites["infosprite"].y = 136
@mapdata = pbLoadTownMapData
mappos = $game_map.metadata&.town_map_position mappos = $game_map.metadata&.town_map_position
if @region < 0 # Use player's current region if @region < 0 # Use player's current region
@region = (mappos) ? mappos[0] : 0 # Region 0 default @region = (mappos) ? mappos[0] : 0 # Region 0 default
end end
@mapdata = GameData::TownMap.get(@region)
@sprites["areamap"] = IconSprite.new(0, 0, @viewport) @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"].x += (Graphics.width - @sprites["areamap"].bitmap.width) / 2
@sprites["areamap"].y += (Graphics.height + 32 - @sprites["areamap"].bitmap.height) / 2 @sprites["areamap"].y += (Graphics.height + 32 - @sprites["areamap"].bitmap.height) / 2
Settings::REGION_MAP_EXTRAS.each do |hidden| Settings::REGION_MAP_EXTRAS.each do |hidden|
@@ -90,7 +90,14 @@ class PokemonPokedexInfo_Scene
break break
end end
end end
@dexlist = [[species, "", 0, 0, dexnum, dexnumshift]] @dexlist = [{
:species => species,
:name => "",
:height => 0,
:weight => 0,
:number => dexnum,
:shift => dexnumshift
}]
@index = 0 @index = 0
@page = 1 @page = 1
@brief = true @brief = true
@@ -125,7 +132,7 @@ class PokemonPokedexInfo_Scene
end end
def pbUpdateDummyPokemon def pbUpdateDummyPokemon
@species = @dexlist[@index][0] @species = @dexlist[@index][:species]
@gender, @form, _shiny = $player.pokedex.last_form_seen(@species) @gender, @form, _shiny = $player.pokedex.last_form_seen(@species)
@shiny = false @shiny = false
metrics_data = GameData::SpeciesMetrics.get_species_form(@species, @form) 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) species_data = GameData::Species.get_species_form(@species, @form)
# Write various bits of text # Write various bits of text
indexText = "???" indexText = "???"
if @dexlist[@index][4] > 0 if @dexlist[@index][:number] > 0
indexNumber = @dexlist[@index][4] indexNumber = @dexlist[@index][:number]
indexNumber -= 1 if @dexlist[@index][5] indexNumber -= 1 if @dexlist[@index][:shift]
indexText = sprintf("%03d", indexNumber) indexText = sprintf("%03d", indexNumber)
end end
textpos = [ textpos = [
@@ -296,7 +303,7 @@ class PokemonPokedexInfo_Scene
# defined point in town_map.txt, and which either have no Self Switch # defined point in town_map.txt, and which either have no Self Switch
# controlling their visibility or whose Self Switch is ON) # controlling their visibility or whose Self Switch is ON)
visible_points = [] 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 next if loc[7] && !$game_switches[loc[7]] # Point is not visible
visible_points.push([loc[0], loc[1]]) visible_points.push([loc[0], loc[1]])
end end
@@ -375,7 +382,7 @@ class PokemonPokedexInfo_Scene
) )
textpos.push([_INTL("Area unknown"), Graphics.width / 2, (Graphics.height / 2) + 6, 2, base, shadow]) textpos.push([_INTL("Area unknown"), Graphics.width / 2, (Graphics.height / 2) + 6, 2, base, shadow])
end 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), textpos.push([_INTL("{1}'s area", GameData::Species.get(@species).name),
Graphics.width / 2, 358, 2, base, shadow]) Graphics.width / 2, 358, 2, base, shadow])
pbDrawTextPositions(overlay, textpos) pbDrawTextPositions(overlay, textpos)
@@ -406,7 +413,7 @@ class PokemonPokedexInfo_Scene
newindex = @index newindex = @index
while newindex > 0 while newindex > 0
newindex -= 1 newindex -= 1
if $player.seen?(@dexlist[newindex][0]) if $player.seen?(@dexlist[newindex][:species])
@index = newindex @index = newindex
break break
end end
@@ -417,7 +424,7 @@ class PokemonPokedexInfo_Scene
newindex = @index newindex = @index
while newindex < @dexlist.length - 1 while newindex < @dexlist.length - 1
newindex += 1 newindex += 1
if $player.seen?(@dexlist[newindex][0]) if $player.seen?(@dexlist[newindex][:species])
@index = newindex @index = newindex
break break
end end
@@ -581,7 +588,14 @@ class PokemonPokedexInfoScreen
end end
dexnum = pbGetRegionalNumber(region, species) dexnum = pbGetRegionalNumber(region, species)
dexnumshift = Settings::DEXES_WITH_OFFSETS.include?(region) 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.pbStartScene(dexlist, 0, region)
@scene.pbScene @scene.pbScene
@scene.pbEndScene @scene.pbEndScene

View File

@@ -72,24 +72,23 @@ class PokemonRegionMap_Scene
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999 @viewport.z = 99999
@sprites = {} @sprites = {}
@map_data = pbLoadTownMapData
@fly_map = fly_map @fly_map = fly_map
@mode = fly_map ? 1 : 0 @mode = fly_map ? 1 : 0
map_metadata = $game_map.metadata map_metadata = $game_map.metadata
playerpos = (map_metadata) ? map_metadata.town_map_position : nil playerpos = (map_metadata) ? map_metadata.town_map_position : nil
if !playerpos if !playerpos
mapindex = 0 mapindex = 0
@map = @map_data[0] @map = GameData::TownMap.get(0)
@map_x = LEFT @map_x = LEFT
@map_y = TOP @map_y = TOP
elsif @region >= 0 && @region != playerpos[0] && @map_data[@region] elsif @region >= 0 && @region != playerpos[0] && GameData::TownMap.exists?(@region)
mapindex = @region mapindex = @region
@map = @map_data[@region] @map = GameData::TownMap.get(@region)
@map_x = LEFT @map_x = LEFT
@map_y = TOP @map_y = TOP
else else
mapindex = playerpos[0] mapindex = playerpos[0]
@map = @map_data[playerpos[0]] @map = GameData::TownMap.get(playerpos[0])
@map_x = playerpos[1] @map_x = playerpos[1]
@map_y = playerpos[2] @map_y = playerpos[2]
mapsize = map_metadata.town_map_size mapsize = map_metadata.town_map_size
@@ -106,7 +105,7 @@ class PokemonRegionMap_Scene
end end
addBackgroundOrColoredPlane(@sprites, "background", "Town Map/bg", Color.black, @viewport) addBackgroundOrColoredPlane(@sprites, "background", "Town Map/bg", Color.black, @viewport)
@sprites["map"] = IconSprite.new(0, 0, @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"].x += (Graphics.width - @sprites["map"].bitmap.width) / 2
@sprites["map"].y += (Graphics.height - @sprites["map"].bitmap.height) / 2 @sprites["map"].y += (Graphics.height - @sprites["map"].bitmap.height) / 2
Settings::REGION_MAP_EXTRAS.each do |graphic| Settings::REGION_MAP_EXTRAS.each do |graphic|
@@ -122,7 +121,7 @@ class PokemonRegionMap_Scene
) )
end end
@sprites["mapbottom"] = MapBottomSprite.new(@viewport) @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"].maplocation = pbGetMapLocation(@map_x, @map_y)
@sprites["mapbottom"].mapdetails = pbGetMapDetails(@map_x, @map_y) @sprites["mapbottom"].mapdetails = pbGetMapDetails(@map_x, @map_y)
if playerpos && mapindex == playerpos[0] if playerpos && mapindex == playerpos[0]
@@ -177,27 +176,13 @@ class PokemonRegionMap_Scene
end end
def pbSaveMapData def pbSaveMapData
File.open("PBS/town_map.txt", "wb") { |f| GameData::TownMap.save
Compiler.add_PBS_header_to_file(f) Compiler.write_town_map
@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
}
end end
def pbGetMapLocation(x, y) def pbGetMapLocation(x, y)
return "" if !@map[2] return "" if !@map.point
@map[2].each do |point| @map.point.each do |point|
next if point[0] != x || point[1] != y next if point[0] != x || point[1] != y
return "" if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]]) return "" if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]])
name = pbGetMessageFromHash(MessageTypes::PlaceNames, point[2]) name = pbGetMessageFromHash(MessageTypes::PlaceNames, point[2])
@@ -207,25 +192,25 @@ class PokemonRegionMap_Scene
end end
def pbChangeMapLocation(x, y) def pbChangeMapLocation(x, y)
return "" if !@editor || !@map[2] return "" if !@editor || !@map.point
map = @map[2].select { |loc| loc[0] == x && loc[1] == y }[0] point = @map.point.select { |loc| loc[0] == x && loc[1] == y }[0]
currentobj = map currentobj = point
currentname = (map) ? map[2] || "" : "" currentname = (point) ? point[2] : ""
currentname = pbMessageFreeText(_INTL("Set the name for this point."), currentname, false, 250) { pbUpdate } currentname = pbMessageFreeText(_INTL("Set the name for this point."), currentname, false, 250) { pbUpdate }
if currentname if currentname
if currentobj if currentobj
currentobj[2] = currentname currentobj[2] = currentname
else else
newobj = [x, y, currentname, ""] newobj = [x, y, currentname, ""]
@map[2].push(newobj) @map.point.push(newobj)
end end
@changed = true @changed = true
end end
end end
def pbGetMapDetails(x, y) # From Wichu, with my help def pbGetMapDetails(x, y) # From Wichu, with my help
return "" if !@map[2] return "" if !@map.point
@map[2].each do |point| @map.point.each do |point|
next if point[0] != x || point[1] != y next if point[0] != x || point[1] != y
return "" if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]]) return "" if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]])
mapdesc = pbGetMessageFromHash(MessageTypes::PlaceDescriptions, point[3]) mapdesc = pbGetMessageFromHash(MessageTypes::PlaceDescriptions, point[3])
@@ -235,8 +220,8 @@ class PokemonRegionMap_Scene
end end
def pbGetHealingSpot(x, y) def pbGetHealingSpot(x, y)
return nil if !@map[2] return nil if !@map.point
@map[2].each do |point| @map.point.each do |point|
next if point[0] != x || point[1] != y next if point[0] != x || point[1] != y
return nil if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]]) 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 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("*.mid") { |f| files.push(f) }
Dir.glob("*.midi") { |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.uniq!
files.sort! { |a, b| a.downcase <=> b.downcase } files.sort! { |a, b| a.downcase <=> b.downcase }
@scene.pbSetCommands(files, 0) @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 end
# Purify Chamber treats Normal/Normal matchup as super effective # Purify Chamber treats Normal/Normal matchup as super effective
def self.typeAdvantage(p1, p2) def self.typeAdvantage(type1, type2)
return true if p1 == :NORMAL && p2 == :NORMAL return true if type1 == :NORMAL && type2 == :NORMAL
return Effectiveness.super_effective_type?(p1, p2) return Effectiveness.super_effective_type?(type1, type2)
end end
def self.isSuperEffective(p1, p2) def self.isSuperEffective(pkmn1, pkmn2)
return true if typeAdvantage(p1.types[0], p2.types[0]) pkmn1.types.each do |type1|
return true if p2.types[1] && typeAdvantage(p1.types[0], p2.types[1]) pkmn2.types.each do |type2|
return false if p1.types[1].nil? return true if typeAdvantage(type1, type2)
return true if typeAdvantage(p1.types[1], p2.types[0]) end
return true if p2.types[1] && typeAdvantage(p1.types[1], p2.types[1]) end
return false return false
end end
end end
@@ -952,16 +952,13 @@ class PurifyChamberSetView < Sprite
pbSetSmallFont(@info.bitmap) pbSetSmallFont(@info.bitmap)
textpos = [] textpos = []
if pkmn if pkmn
if pkmn.types.length == 1 type_string = ""
textpos.push([_INTL("{1} Lv.{2} {3}", pkmn.name, pkmn.level, pkmn.types.each_with_index do |type, i|
GameData::Type.get(pkmn.types[0]).name), type_string += "/" if i > 0
2, 6, 0, Color.new(248, 248, 248), Color.new(128, 128, 128)]) type_string += GameData::Type.get(type).name
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)])
end 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, textpos.push([_INTL("FLOW"), 2 + (@info.bitmap.width / 2), 30, 0,
Color.new(248, 248, 248), Color.new(128, 128, 128)]) Color.new(248, 248, 248), Color.new(128, 128, 128)])
# draw heart gauge # draw heart gauge

View File

@@ -51,10 +51,13 @@ class TriadCard
end end
def bonus(opponent) def bonus(opponent)
case Effectiveness.calculate_one(@type, opponent.type) effectiveness = Effectiveness.calculate(@type, opponent.type)
when Effectiveness::INEFFECTIVE then return -2 if Effectiveness.ineffective?(effectiveness)
when Effectiveness::NOT_VERY_EFFECTIVE_ONE then return -1 return -2
when Effectiveness::SUPER_EFFECTIVE_ONE then return 1 elsif Effectiveness.not_very_effective?(effectiveness)
return -1
elsif Effectiveness.super_effective?(effectiveness)
return 1
end end
return 0 return 0
end end

View File

@@ -309,16 +309,17 @@ def pbDecideWinnerEffectiveness(move, otype1, otype2, ability, scores)
data = GameData::Move.get(move) data = GameData::Move.get(move)
return 0 if data.base_damage == 0 return 0 if data.base_damage == 0
atype = data.type atype = data.type
typemod = Effectiveness::NORMAL_EFFECTIVE_ONE**2 typemod = 1.0
if ability != :LEVITATE || data.type != :GROUND if ability != :LEVITATE || data.type != :GROUND
mod1 = Effectiveness.calculate_one(atype, otype1) mod1 = Effectiveness.calculate(atype, otype1)
mod2 = (otype1 == otype2) ? Effectiveness::NORMAL_EFFECTIVE_ONE : Effectiveness.calculate_one(atype, otype2) mod2 = (otype1 == otype2) ? 1.0 : Effectiveness.calculate(atype, otype2)
if ability == :WONDERGUARD if ability == :WONDERGUARD
mod1 = Effectiveness::NORMAL_EFFECTIVE_ONE if mod1 <= Effectiveness::NORMAL_EFFECTIVE_ONE mod1 = 1.0 if !Effectiveness.super_effective?(mod1)
mod2 = Effectiveness::NORMAL_EFFECTIVE_ONE if mod2 <= Effectiveness::NORMAL_EFFECTIVE_ONE mod2 = 1.0 if !Effectiveness.super_effective?(mod2)
end end
typemod = mod1 * mod2 typemod = mod1 * mod2
end end
typemod *= 4 # Because dealing with 2 types
return scores[0] if typemod == 0 # Ineffective return scores[0] if typemod == 0 # Ineffective
return scores[1] if typemod == 1 # Doubly not very effective return scores[1] if typemod == 1 # Doubly not very effective
return scores[2] if typemod == 2 # Not very effective return scores[2] if typemod == 2 # Not very effective

View File

@@ -81,7 +81,8 @@ def pbEncountersEditor
:map => new_map_ID, :map => new_map_ID,
:version => new_version, :version => new_version,
:step_chances => {}, :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| GameData::Encounter.get(this_set[0], this_set[1]).step_chances.each do |type, value|
encounter_hash[:step_chances][type] = value encounter_hash[:step_chances][type] = value
@@ -344,19 +345,7 @@ end
# Trainer type editor # Trainer type editor
#=============================================================================== #===============================================================================
def pbTrainerTypeEditor def pbTrainerTypeEditor
gender_array = [] properties = GameData::TrainerType.editor_properties
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.")]
]
pbListScreenBlock(_INTL("Trainer Types"), TrainerTypeLister.new(0, true)) { |button, tr_type| pbListScreenBlock(_INTL("Trainer Types"), TrainerTypeLister.new(0, true)) { |button, tr_type|
if tr_type if tr_type
case button case button
@@ -370,30 +359,25 @@ def pbTrainerTypeEditor
when Input::USE when Input::USE
if tr_type.is_a?(Symbol) if tr_type.is_a?(Symbol)
t_data = GameData::TrainerType.get(tr_type) t_data = GameData::TrainerType.get(tr_type)
data = [ data = []
t_data.id.to_s, properties.each do |prop|
t_data.real_name, val = t_data.get_property_for_PBS(prop[0])
t_data.gender, val = prop[1].defaultValue if val.nil? && prop[1].respond_to?(:defaultValue)
t_data.base_money, data.push(val)
t_data.skill_level, end
t_data.flags, if pbPropertyList(t_data.id.to_s, data, properties, true)
t_data.intro_BGM,
t_data.battle_BGM,
t_data.victory_BGM
]
if pbPropertyList(t_data.id.to_s, data, trainer_type_properties, true)
# Construct trainer type hash # Construct trainer type hash
type_hash = { schema = GameData::TrainerType.schema
:id => t_data.id, type_hash = {}
:name => data[1], properties.each_with_index do |prop, i|
:gender => data[2], case prop[0]
:base_money => data[3], when "ID"
:skill_level => data[4], type_hash[schema["SectionName"][0]] = data[i]
:flags => data[5], else
:intro_BGM => data[6], type_hash[schema[prop[0]][0]] = data[i]
:battle_BGM => data[7], end
:victory_BGM => data[8] end
} type_hash[:pbs_file_suffix] = t_data.pbs_file_suffix
# Add trainer type's data to records # Add trainer type's data to records
GameData::TrainerType.register(type_hash) GameData::TrainerType.register(type_hash)
GameData::TrainerType.save GameData::TrainerType.save
@@ -548,7 +532,8 @@ def pbTrainerBattleEditor
:version => data[2], :version => data[2],
:lose_text => data[3], :lose_text => data[3],
:pokemon => party, :pokemon => party,
:items => items :items => items,
:pbs_file_suffix => tr_data.pbs_file_suffix
} }
# Add trainer type's data to records # Add trainer type's data to records
trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]] trainer_hash[:id] = [trainer_hash[:trainer_type], trainer_hash[:name], trainer_hash[:version]]
@@ -732,24 +717,19 @@ def pbEditMetadata
metadata = GameData::Metadata.get metadata = GameData::Metadata.get
properties = GameData::Metadata.editor_properties properties = GameData::Metadata.editor_properties
properties.each do |property| 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 end
if pbPropertyList(_INTL("Global Metadata"), data, properties, true) if pbPropertyList(_INTL("Global Metadata"), data, properties, true)
# Construct metadata hash # Construct metadata hash
metadata_hash = { schema = GameData::Metadata.schema
:id => 0, metadata_hash = {}
:start_money => data[0], properties.each_with_index do |prop, i|
:start_item_storage => data[1], metadata_hash[schema[prop[0]][0]] = data[i]
:home => data[2], end
:storage_creator => data[3], metadata_hash[:id] = 0
:wild_battle_BGM => data[4], metadata_hash[:pbs_file_suffix] = metadata.pbs_file_suffix
:trainer_battle_BGM => data[5],
:wild_victory_BGM => data[6],
:trainer_victory_BGM => data[7],
:wild_capture_ME => data[8],
:surf_BGM => data[9],
:bicycle_BGM => data[10]
}
# Add metadata's data to records # Add metadata's data to records
GameData::Metadata.register(metadata_hash) GameData::Metadata.register(metadata_hash)
GameData::Metadata.save GameData::Metadata.save
@@ -776,21 +756,23 @@ def pbEditPlayerMetadata(player_id = 1)
metadata = GameData::PlayerMetadata.try_get(player_id) if metadata.nil? metadata = GameData::PlayerMetadata.try_get(player_id) if metadata.nil?
properties = GameData::PlayerMetadata.editor_properties properties = GameData::PlayerMetadata.editor_properties
properties.each do |property| 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 end
if pbPropertyList(_INTL("Player {1}", metadata.id), data, properties, true) if pbPropertyList(_INTL("Player {1}", metadata.id), data, properties, true)
# Construct player metadata hash # Construct player metadata hash
metadata_hash = { schema = GameData::PlayerMetadata.schema
:id => player_id, metadata_hash = {}
:trainer_type => data[0], properties.each_with_index do |prop, i|
:walk_charset => data[1], case prop[0]
:run_charset => data[2], when "ID"
:cycle_charset => data[3], metadata_hash[schema["SectionName"][0]] = data[i]
:surf_charset => data[4], else
:dive_charset => data[5], metadata_hash[schema[prop[0]][0]] = data[i]
:fish_charset => data[6], end
:surf_fish_charset => data[7] end
} metadata_hash[:pbs_file_suffix] = metadata.pbs_file_suffix
# Add player metadata's data to records # Add player metadata's data to records
GameData::PlayerMetadata.register(metadata_hash) GameData::PlayerMetadata.register(metadata_hash)
GameData::PlayerMetadata.save GameData::PlayerMetadata.save
@@ -819,35 +801,23 @@ def pbEditMapMetadata(map_id)
metadata = GameData::MapMetadata.new({ :id => map_id }) if !metadata metadata = GameData::MapMetadata.new({ :id => map_id }) if !metadata
properties = GameData::MapMetadata.editor_properties properties = GameData::MapMetadata.editor_properties
properties.each do |property| 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 end
if pbPropertyList(map_name, data, properties, true) if pbPropertyList(map_name, data, properties, true)
# Construct map metadata hash # Construct map metadata hash
metadata_hash = { schema = GameData::MapMetadata.schema
:id => map_id, metadata_hash = {}
:name => data[0], properties.each_with_index do |prop, i|
:outdoor_map => data[1], case prop[0]
:announce_location => data[2], when "ID"
:can_bicycle => data[3], metadata_hash[schema["SectionName"][0]] = data[i]
:always_bicycle => data[4], else
:teleport_destination => data[5], metadata_hash[schema[prop[0]][0]] = data[i]
:weather => data[6], end
:town_map_position => data[7], end
:dive_map_id => data[8], metadata_hash[:pbs_file_suffix] = metadata.pbs_file_suffix
: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]
}
# Add map metadata's data to records # Add map metadata's data to records
GameData::MapMetadata.register(metadata_hash) GameData::MapMetadata.register(metadata_hash)
GameData::MapMetadata.save GameData::MapMetadata.save
@@ -861,24 +831,7 @@ end
# Item editor # Item editor
#=============================================================================== #===============================================================================
def pbItemEditor def pbItemEditor
field_use_array = [_INTL("Can't use in field")] properties = GameData::Item.editor_properties
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.")]
]
pbListScreenBlock(_INTL("Items"), ItemLister.new(0, true)) { |button, item| pbListScreenBlock(_INTL("Items"), ItemLister.new(0, true)) { |button, item|
if item if item
case button case button
@@ -892,36 +845,25 @@ def pbItemEditor
when Input::USE when Input::USE
if item.is_a?(Symbol) if item.is_a?(Symbol)
itm = GameData::Item.get(item) itm = GameData::Item.get(item)
data = [ data = []
itm.id.to_s, properties.each do |prop|
itm.real_name, val = itm.get_property_for_PBS(prop[0])
itm.real_name_plural, val = prop[1].defaultValue if val.nil? && prop[1].respond_to?(:defaultValue)
itm.pocket, data.push(val)
itm.price, end
itm.sell_price, if pbPropertyList(itm.id.to_s, data, properties, true)
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)
# Construct item hash # Construct item hash
item_hash = { schema = GameData::Item.schema
:id => itm.id, item_hash = {}
:name => data[1], properties.each_with_index do |prop, i|
:name_plural => data[2], case prop[0]
:pocket => data[3], when "ID"
:price => data[4], item_hash[schema["SectionName"][0]] = data[i]
:sell_price => data[5], else
:description => data[6], item_hash[schema[prop[0]][0]] = data[i]
:field_use => data[7], end
:battle_use => data[8], end
:consumable => data[9], item_hash[:pbs_file_suffix] = itm.pbs_file_suffix
:flags => data[10],
:move => data[11]
}
# Add item's data to records # Add item's data to records
GameData::Item.register(item_hash) GameData::Item.register(item_hash)
GameData::Item.save GameData::Item.save
@@ -995,47 +937,7 @@ end
# Pokémon species editor # Pokémon species editor
#=============================================================================== #===============================================================================
def pbPokemonEditor def pbPokemonEditor
species_properties = [ properties = GameData::Species.editor_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.")]
]
pbListScreenBlock(_INTL("Pokémon species"), SpeciesLister.new(0, false)) { |button, species| pbListScreenBlock(_INTL("Pokémon species"), SpeciesLister.new(0, false)) { |button, species|
if species if species
case button case button
@@ -1049,98 +951,40 @@ def pbPokemonEditor
when Input::USE when Input::USE
if species.is_a?(Symbol) if species.is_a?(Symbol)
spec = GameData::Species.get(species) spec = GameData::Species.get(species)
moves = [] data = []
spec.moves.each_with_index { |m, i| moves.push(m.clone.push(i)) } properties.each do |prop|
moves.sort! { |a, b| (a[0] == b[0]) ? a[2] <=> b[2] : a[0] <=> b[0] } val = spec.get_property_for_PBS(prop[0])
moves.each { |m| m.pop } val = prop[1].defaultValue if val.nil? && prop[1].respond_to?(:defaultValue)
evolutions = [] val = (val * 10).round if ["Height", "Weight"].include?(prop[0])
spec.evolutions.each { |e| evolutions.push(e.clone) if !e[3] } data.push(val)
data = [ end
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
]
# Edit the properties # Edit the properties
if pbPropertyList(spec.id.to_s, data, species_properties, true) if pbPropertyList(spec.id.to_s, data, 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
# Construct species hash # Construct species hash
species_hash = { schema = GameData::Species.schema
:id => spec.id, species_hash = {}
:name => data[1], properties.each_with_index do |prop, i|
:form_name => data[2], data[i] = data[i].to_f / 10 if ["Height", "Weight"].include?(prop[0])
:category => data[3], case prop[0]
:pokedex_entry => data[4], when "ID"
:types => types, # 5, 6 species_hash[schema["SectionName"][0]] = data[i]
:base_stats => data[7], else
:evs => data[8], species_hash[schema[prop[0]][0]] = data[i]
:base_exp => data[9], end
:growth_rate => data[10], end
:gender_ratio => data[11], species_hash[:pbs_file_suffix] = spec.pbs_file_suffix
:catch_rate => data[12], # Sanitise data
:happiness => data[13], Compiler.validate_compiled_pokemon(species_hash)
:moves => data[14], species_hash[:evolutions].each do |evo|
:tutor_moves => data[15], param_type = GameData::Evolution.get(evo[1]).parameter
:egg_moves => data[16], if param_type.nil?
:abilities => abilities, # 17, 18 evo[2] = nil
:hidden_abilities => hidden_abilities, # 19, 20, 21, 22 elsif param_type == Integer
:wild_item_common => data[23], evo[2] = Compiler.csvPosInt!(evo[2])
:wild_item_uncommon => data[24], elsif param_type != String
:wild_item_rare => data[25], evo[2] = Compiler.csvEnumField!(evo[2], param_type, "Evolutions", species_hash[:id])
:egg_groups => egg_groups, # 26, 27 end
:hatch_steps => data[28], end
: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]
}
# Add species' data to records # Add species' data to records
GameData::Species.register(species_hash) GameData::Species.register(species_hash)
GameData::Species.save GameData::Species.save

View File

@@ -105,9 +105,8 @@ class RegionMapSprite
end end
def createRegionMap(map) def createRegionMap(map)
@mapdata = pbLoadTownMapData town_map = GameData::TownMap.get(map)
@map = @mapdata[map] bitmap = AnimatedBitmap.new("Graphics/UI/Town Map/#{town_map.filename}").deanimate
bitmap = AnimatedBitmap.new("Graphics/UI/Town Map/#{@map[1]}").deanimate
retbitmap = BitmapWrapper.new(bitmap.width / 2, bitmap.height / 2) retbitmap = BitmapWrapper.new(bitmap.width / 2, bitmap.height / 2)
retbitmap.stretch_blt( retbitmap.stretch_blt(
Rect.new(0, 0, bitmap.width / 2, bitmap.height / 2), 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 if Input.trigger?(Input::USE) && animfiles.length > 0
filename = cmdwin.commands[cmdwin.index] filename = cmdwin.commands[cmdwin.index]
bitmap = AnimatedBitmap.new("Graphics/Animations/" + filename, ctlwin.value(0)).deanimate 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.animation.hue = ctlwin.value(0)
canvas.animbitmap = bitmap canvas.animbitmap = bitmap
animwin.animbitmap = bitmap animwin.animbitmap = bitmap
@@ -544,11 +544,7 @@ def pbSelectSE(canvas, audio)
pbSEStop pbSEStop
end end
if maxsizewindow.changed?(5) # OK if maxsizewindow.changed?(5) # OK
filename = File.basename(filename, ".wav") audio.name = File.basename(filename, ".*")
# filename = File.basename(filename,".mp3")
filename = File.basename(filename, ".ogg")
filename = File.basename(filename, ".wma")
audio.name = filename
audio.volume = maxsizewindow.value(1) audio.volume = maxsizewindow.value(1)
audio.pitch = maxsizewindow.value(2) audio.pitch = maxsizewindow.value(2)
ret = true ret = true
@@ -583,6 +579,9 @@ def pbSelectBG(canvas, timing)
# animfiles.concat(Dir.glob("*.jpeg")) # animfiles.concat(Dir.glob("*.jpeg"))
# animfiles.concat(Dir.glob("*.bmp")) # 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 = pbListWindow(animfiles, 320)
cmdwin.height = 480 cmdwin.height = 480
cmdwin.opacity = 200 cmdwin.opacity = 200

View File

@@ -238,9 +238,10 @@ end
class StringListProperty class StringListProperty
def self.set(_setting_name, old_setting) def self.set(_setting_name, old_setting)
old_setting = [] if !old_setting
real_cmds = [] real_cmds = []
real_cmds.push([_INTL("[ADD VALUE]"), -1]) 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]) real_cmds.push([old_setting[i], 0])
end end
# Edit list # Edit list
@@ -319,7 +320,7 @@ class StringListProperty
end end
def self.format(value) def self.format(value)
return value.join(",") return (value) ? value.join(",") : ""
end end
end end
@@ -359,7 +360,7 @@ end
module BGMProperty module BGMProperty
def self.set(settingname, oldsetting) def self.set(settingname, oldsetting)
chosenmap = pbListScreen(settingname, MusicFileLister.new(true, oldsetting)) chosenmap = pbListScreen(settingname, MusicFileLister.new(true, oldsetting))
return (chosenmap && chosenmap != "") ? chosenmap : oldsetting return (chosenmap && chosenmap != "") ? File.basename(chosenmap, ".*") : oldsetting
end end
def self.format(value) def self.format(value)
@@ -372,7 +373,7 @@ end
module MEProperty module MEProperty
def self.set(settingname, oldsetting) def self.set(settingname, oldsetting)
chosenmap = pbListScreen(settingname, MusicFileLister.new(false, oldsetting)) chosenmap = pbListScreen(settingname, MusicFileLister.new(false, oldsetting))
return (chosenmap && chosenmap != "") ? chosenmap : oldsetting return (chosenmap && chosenmap != "") ? File.basename(chosenmap, ".*") : oldsetting
end end
def self.format(value) def self.format(value)
@@ -385,7 +386,7 @@ end
module WindowskinProperty module WindowskinProperty
def self.set(settingname, oldsetting) def self.set(settingname, oldsetting)
chosenmap = pbListScreen(settingname, GraphicsLister.new("Graphics/Windowskins/", oldsetting)) chosenmap = pbListScreen(settingname, GraphicsLister.new("Graphics/Windowskins/", oldsetting))
return (chosenmap && chosenmap != "") ? chosenmap : oldsetting return (chosenmap && chosenmap != "") ? File.basename(chosenmap, ".*") : oldsetting
end end
def self.format(value) 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 module MoveProperty
def self.set(_settingname, oldsetting) def self.set(_settingname, oldsetting)
ret = pbChooseMoveList(oldsetting || nil) ret = pbChooseMoveList(oldsetting || nil)
@@ -653,7 +685,7 @@ end
module CharacterProperty module CharacterProperty
def self.set(settingname, oldsetting) def self.set(settingname, oldsetting)
chosenmap = pbListScreen(settingname, GraphicsLister.new("Graphics/Characters/", oldsetting)) chosenmap = pbListScreen(settingname, GraphicsLister.new("Graphics/Characters/", oldsetting))
return (chosenmap && chosenmap != "") ? chosenmap : oldsetting return (chosenmap && chosenmap != "") ? File.basename(chosenmap, ".*") : oldsetting
end end
def self.format(value) def self.format(value)
@@ -769,15 +801,10 @@ module RegionMapCoordsProperty
selregion = regions[0][0] selregion = regions[0][0]
else else
cmds = [] cmds = []
regions.each do |region| regions.each { |region| cmds.push(region[1]) }
cmds.push(region[1])
end
selcmd = pbMessage(_INTL("Choose a region map."), cmds, -1) selcmd = pbMessage(_INTL("Choose a region map."), cmds, -1)
if selcmd >= 0 return oldsetting if selcmd < 0
selregion = regions[selcmd][0] selregion = regions[selcmd][0]
else
return oldsetting
end
end end
mappoint = chooseMapPoint(selregion, true) mappoint = chooseMapPoint(selregion, true)
return (mappoint) ? [selregion, mappoint[0], mappoint[1]] : oldsetting return (mappoint) ? [selregion, mappoint[0], mappoint[1]] : oldsetting
@@ -788,12 +815,8 @@ module RegionMapCoordsProperty
end end
def self.getMapNameList def self.getMapNameList
mapdata = pbLoadTownMapData
ret = [] ret = []
mapdata.length.times do |i| GameData::TownMap.each { |town_map| ret.push([town_map.id, town_map.name]) }
next if !mapdata[i]
ret.push([i, pbGetMessage(MessageTypes::RegionNames, i)])
end
return ret return ret
end end
end end
@@ -834,7 +857,7 @@ module MapProperty
end end
def self.defaultValue def self.defaultValue
return 0 return nil
end end
def self.format(value) def self.format(value)
@@ -890,30 +913,25 @@ module BaseStatsProperty
next if s.pbs_order < 0 next if s.pbs_order < 0
properties[s.pbs_order] = [_INTL("Base {1}", s.name), NonzeroLimitProperty.new(255), properties[s.pbs_order] = [_INTL("Base {1}", s.name), NonzeroLimitProperty.new(255),
_INTL("Base {1} stat of the Pokémon.", s.name)] _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 stat_ids[s.pbs_order] = s.id
end end
if pbPropertyList(settingname, data, properties, true) if pbPropertyList(settingname, data, properties, true)
ret = {} ret = []
stat_ids.each_with_index { |s, i| ret[s] = data[i] || 10 } stat_ids.each_with_index { |s, i| ret[i] = data[i] || 10 }
oldsetting = ret oldsetting = ret
end end
return oldsetting return oldsetting
end end
def self.defaultValue def self.defaultValue
ret = {} ret = []
GameData::Stat.each_main { |s| ret[s.id] = 10 if s.pbs_order >= 0 } GameData::Stat.each_main { |s| ret[s.pbs_order] = 10 if s.pbs_order >= 0 }
return ret return ret
end end
def self.format(value) def self.format(value)
array = [] return value.join(",")
GameData::Stat.each_main do |s|
next if s.pbs_order < 0
array[s.pbs_order] = value[s.id] || 0
end
return array.join(",")
end end
end end
@@ -929,30 +947,33 @@ module EffortValuesProperty
next if s.pbs_order < 0 next if s.pbs_order < 0
properties[s.pbs_order] = [_INTL("{1} EVs", s.name), LimitProperty.new(255), 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)] _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 stat_ids[s.pbs_order] = s.id
end end
if pbPropertyList(settingname, data, properties, true) if pbPropertyList(settingname, data, properties, true)
ret = {} ret = []
stat_ids.each_with_index { |s, i| ret[s] = data[i] || 0 } 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 oldsetting = ret
end end
return oldsetting return oldsetting
end end
def self.defaultValue def self.defaultValue
ret = {} return []
GameData::Stat.each_main { |s| ret[s.id] = 0 if s.pbs_order >= 0 }
return ret
end end
def self.format(value) def self.format(value)
array = [] return "" if !value
GameData::Stat.each_main do |s| ret = ""
next if s.pbs_order < 0 value.each_with_index do |val, i|
array[s.pbs_order] = value[s.id] || 0 ret += "," if i > 0
ret += GameData::Stat.get(val[0]).real_name_brief + "," + val[1].to_s
end end
return array.join(",") return ret
end end
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 module LevelUpMovesProperty
def self.set(_settingname, oldsetting) def self.set(_settingname, oldsetting)
# Get all moves in move pool # Get all moves in move pool
@@ -1286,12 +1323,12 @@ class EvolutionsProperty
else else
params = ChooseNumberParams.new params = ChooseNumberParams.new
params.setRange(0, 65_535) params.setRange(0, 65_535)
params.setDefaultValue(value) if value params.setDefaultValue(value.to_i) if value
params.setCancelValue(-1) params.setCancelValue(-1)
ret = pbMessageChooseNumber(_INTL("Choose a parameter."), params) ret = pbMessageChooseNumber(_INTL("Choose a parameter."), params)
ret = nil if ret < 0 ret = nil if ret < 0
end end
return ret return (ret) ? ret.to_s : nil
end end
def set(_settingname, oldsetting) def set(_settingname, oldsetting)
@@ -1474,21 +1511,13 @@ class EvolutionsProperty
end end
def format(value) def format(value)
return "" if !value
ret = "" ret = ""
value.length.times do |i| value.length.times do |i|
ret << "," if i > 0 ret << "," if i > 0
param = value[i][2] ret << value[i][0].to_s + ","
evo_method_data = GameData::Evolution.get(value[i][1]) ret << value[i][1].to_s + ","
param_type = evo_method_data.parameter ret << value[i][2].to_s if value[i][2] != nil
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}")
end end
return ret return ret
end end

View File

@@ -416,7 +416,7 @@ MenuHandlers.add(:battle_pokemon_debug_menu, :set_types, {
"parent" => :main, "parent" => :main,
"usage" => :battler, "usage" => :battler,
"effect" => proc { |pkmn, battler, battle| "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 cmd = 0
loop do loop do
commands = [] commands = []
@@ -427,7 +427,7 @@ MenuHandlers.add(:battle_pokemon_debug_menu, :set_types, {
commands.push(_INTL("Type {1}: {2}", i + 1, type_name)) commands.push(_INTL("Type {1}: {2}", i + 1, type_name))
types.push(type) types.push(type)
end end
extra_type = battler.effects[PBEffects::Type3] extra_type = battler.effects[PBEffects::ExtraType]
extra_type_name = (extra_type) ? GameData::Type.get(extra_type).name : "-" extra_type_name = (extra_type) ? GameData::Type.get(extra_type).name : "-"
commands.push(_INTL("Extra type: {1}", extra_type_name)) commands.push(_INTL("Extra type: {1}", extra_type_name))
types.push(extra_type) types.push(extra_type)
@@ -443,14 +443,14 @@ MenuHandlers.add(:battle_pokemon_debug_menu, :set_types, {
if cmd < max_main_types if cmd < max_main_types
battler.types[cmd] = nil battler.types[cmd] = nil
else else
battler.effects[PBEffects::Type3] = nil battler.effects[PBEffects::ExtraType] = nil
end end
battler.types.compact! battler.types.compact!
end end
elsif cmd < max_main_types elsif cmd < max_main_types
battler.types[cmd] = new_type battler.types[cmd] = new_type
else else
battler.effects[PBEffects::Type3] = new_type battler.effects[PBEffects::ExtraType] = new_type
end end
end 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::TrappingUser => { name: "Battler trapping self (for Binding Band)", default: -1 }, # Battler index
PBEffects::Truant => { name: "Truant will loaf around this round", default: false }, 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::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::Unburden => { name: "Self lost its item (for Unburden)", default: false },
PBEffects::Uproar => { name: "Uproar number of rounds remaining", default: 0 }, PBEffects::Uproar => { name: "Uproar number of rounds remaining", default: 0 },
PBEffects::WaterSport => { name: "Used Water Sport (Gen 5 and older)", default: false }, PBEffects::WaterSport => { name: "Used Water Sport (Gen 5 and older)", default: false },

View File

@@ -148,15 +148,10 @@ class GraphicsLister
@commands.clear @commands.clear
Dir.chdir(@folder) { Dir.chdir(@folder) {
Dir.glob("*.png") { |f| @commands.push(f) } 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("*.GIF") { |f| @commands.push(f) }
# Dir.glob("*.jpg") { |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("*.JPEG") { |f| @commands.push(f) }
# Dir.glob("*.bmp") { |f| @commands.push(f) } # Dir.glob("*.bmp") { |f| @commands.push(f) }
# Dir.glob("*.BMP") { |f| @commands.push(f) }
} }
@commands.sort! @commands.sort!
@commands.length.times do |i| @commands.length.times do |i|

View File

@@ -92,7 +92,7 @@ module Compiler
#============================================================================= #=============================================================================
# PBS file readers # PBS file readers
#============================================================================= #=============================================================================
def pbEachFileSectionEx(f) def pbEachFileSectionEx(f, schema = nil)
lineno = 1 lineno = 1
havesection = false havesection = false
sectionname = nil sectionname = nil
@@ -120,37 +120,38 @@ module Compiler
end end
r1 = $~[1] r1 = $~[1]
r2 = $~[2] r2 = $~[2]
if schema && schema[r1] && schema[r1][1][0] == "^"
lastsection[r1] ||= []
lastsection[r1].push(r2.gsub(/\s+$/, ""))
else
lastsection[r1] = r2.gsub(/\s+$/, "") lastsection[r1] = r2.gsub(/\s+$/, "")
end end
end end
end
lineno += 1 lineno += 1
Graphics.update if lineno % 1000 == 0 Graphics.update if lineno % 1000 == 0
} }
yield lastsection, sectionname if havesection yield lastsection, sectionname if havesection
end end
# Used for types.txt, pokemon.txt, battle_facility_lists.txt and Battle Tower trainers PBS files # Used for types.txt, abilities.txt, moves.txt, items.txt, berry_plants.txt,
def pbEachFileSection(f) # pokemon.txt, pokemon_forms.txt, pokemon_metrics.txt, shadow_pokemon.txt,
pbEachFileSectionEx(f) { |section, name| # 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[/^.+$/] yield section, name if block_given? && name[/^.+$/]
} }
end end
# Used for metadata.txt and map_metadata.txt # Used for metadata.txt and map_metadata.txt
def pbEachFileSectionNumbered(f) def pbEachFileSectionNumbered(f, schema = nil)
pbEachFileSectionEx(f) { |section, name| pbEachFileSectionEx(f, schema) { |section, name|
yield section, name.to_i if block_given? && name[/^\d+$/] yield section, name.to_i if block_given? && name[/^\d+$/]
} }
end end
# Used for pokemon_forms.txt # Unused
def pbEachFileSectionPokemonForms(f)
pbEachFileSectionEx(f) { |section, name|
yield section, name if block_given? && name[/^\w+[-,\s]{1}\d+$/]
}
end
# Used for phone.txt
def pbEachSection(f) def pbEachSection(f)
lineno = 1 lineno = 1
havesection = false havesection = false
@@ -193,7 +194,7 @@ module Compiler
} }
end end
# Used for many PBS files # Used for town_map.txt and Battle Tower Pokémon PBS files
def pbCompilerEachCommentedLine(filename) def pbCompilerEachCommentedLine(filename)
File.open(filename, "rb") { |f| File.open(filename, "rb") { |f|
FileLineData.file = filename FileLineData.file = filename
@@ -226,7 +227,8 @@ module Compiler
} }
end 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) def pbCompilerEachPreppedLine(filename)
File.open(filename, "rb") { |f| File.open(filename, "rb") { |f|
FileLineData.file = filename FileLineData.file = filename
@@ -404,10 +406,14 @@ module Compiler
def pbGetCsvRecord(rec, lineno, schema) def pbGetCsvRecord(rec, lineno, schema)
record = [] record = []
repeat = false repeat = false
schema_length = schema[1].length
start = 0 start = 0
if schema[1][0, 1] == "*" if schema[1][0, 1] == "*"
repeat = true repeat = true
start = 1 start = 1
elsif schema[1][0, 1] == "^"
start = 1
schema_length -= 1
end end
subarrays = repeat && schema[1].length > 2 subarrays = repeat && schema[1].length > 2
loop do loop do
@@ -519,6 +525,21 @@ module Compiler
subrecord.push(rec) subrecord.push(rec)
rec = "" rec = ""
end 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 when "e" # Enumerable
subrecord.push(csvEnumField!(rec, schema[2 + i - start], "", FileLineData.linereport)) subrecord.push(csvEnumField!(rec, schema[2 + i - start], "", FileLineData.linereport))
when "E" # Optional enumerable when "E" # Optional enumerable
@@ -548,7 +569,7 @@ module Compiler
break if repeat && nil_or_empty?(rec) break if repeat && nil_or_empty?(rec)
break unless repeat break unless repeat
end end
return (schema[1].length == 1) ? record[0] : record return (!repeat && schema_length == 1) ? record[0] : record
end end
#============================================================================= #=============================================================================
@@ -556,17 +577,23 @@ module Compiler
#============================================================================= #=============================================================================
def pbWriteCsvRecord(record, file, schema) def pbWriteCsvRecord(record, file, schema)
rec = (record.is_a?(Array)) ? record.flatten : [record] 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 index = -1
loop do loop do
(start...schema[1].length).each do |i| (start...schema[1].length).each do |i|
index += 1 index += 1
file.write(",") if index > 0
value = rec[index] value = rec[index]
if schema[1][i, 1].upcase != schema[1][i, 1] || !value.nil?
file.write(",") if index > 0
end
if value.nil? if value.nil?
# do nothing # do nothing
elsif value.is_a?(String) elsif value.is_a?(String)
if schema[1][i, 1].downcase == "q"
file.write(value)
else
file.write(csvQuote(value)) file.write(csvQuote(value))
end
elsif value.is_a?(Symbol) elsif value.is_a?(Symbol)
file.write(csvQuote(value.to_s)) file.write(csvQuote(value.to_s))
elsif value == true elsif value == true
@@ -753,30 +780,57 @@ module Compiler
Graphics.update Graphics.update
end 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 def compile_pbs_files
text_files = get_all_pbs_files_to_compile
modify_pbs_file_contents_before_compiling modify_pbs_file_contents_before_compiling
compile_town_map compile_town_map(*text_files[:TownMap][1])
compile_connections compile_connections(*text_files[:Connection][1])
compile_types compile_types(*text_files[:Type][1])
compile_abilities compile_abilities(*text_files[:Ability][1])
compile_moves # Depends on Type compile_moves(*text_files[:Move][1]) # Depends on Type
compile_items # Depends on Move compile_items(*text_files[:Item][1]) # Depends on Move
compile_berry_plants # Depends on Item compile_berry_plants(*text_files[:BerryPlant][1]) # Depends on Item
compile_pokemon # Depends on Move, Item, Type, Ability compile_pokemon(*text_files[:Species][1]) # Depends on Move, Item, Type, Ability
compile_pokemon_forms # Depends on Species, Move, Item, Type, Ability compile_pokemon_forms(*text_files[:Species1][1]) # Depends on Species, Move, Item, Type, Ability
compile_pokemon_metrics # Depends on Species compile_pokemon_metrics(*text_files[:SpeciesMetrics][1]) # Depends on Species
compile_shadow_pokemon # Depends on Species compile_shadow_pokemon(*text_files[:ShadowPokemon][1]) # Depends on Species
compile_regional_dexes # Depends on Species compile_regional_dexes(*text_files[:RegionalDex][1]) # Depends on Species
compile_ribbons compile_ribbons(*text_files[:Ribbon][1])
compile_encounters # Depends on Species compile_encounters(*text_files[:Encounter][1]) # Depends on Species
compile_trainer_types compile_trainer_types(*text_files[:TrainerType][1])
compile_trainers # Depends on Species, Item, Move compile_trainers(*text_files[:Trainer][1]) # Depends on Species, Item, Move
compile_trainer_lists # Depends on TrainerType compile_trainer_lists # Depends on TrainerType
compile_metadata # Depends on TrainerType compile_metadata(*text_files[:Metadata][1]) # Depends on TrainerType
compile_map_metadata compile_map_metadata(*text_files[:MapMetadata][1])
compile_dungeon_tilesets compile_dungeon_tilesets(*text_files[:DungeonTileset][1])
compile_dungeon_parameters compile_dungeon_parameters(*text_files[:DungeonParameters][1])
compile_phone # Depends on TrainerType compile_phone(*text_files[:PhoneMessage][1]) # Depends on TrainerType
end end
def compile_all(mustCompile) def compile_all(mustCompile)
@@ -804,54 +858,14 @@ module Compiler
def main def main
return if !$DEBUG return if !$DEBUG
begin begin
dataFiles = [ # Get all data files and PBS files to be checked for their last modified times
"abilities.dat", data_files = GameData.get_all_data_filenames
"berry_plants.dat", data_files += [ # Extra .dat files for data that isn't a GameData class
"dungeon_parameters.dat",
"dungeon_tilesets.dat",
"encounters.dat",
"items.dat",
"map_connections.dat", "map_connections.dat",
"map_metadata.dat",
"metadata.dat",
"moves.dat",
"phone.dat",
"player_metadata.dat",
"regional_dexes.dat", "regional_dexes.dat",
"ribbons.dat", "trainer_lists.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"
] ]
text_files = get_all_pbs_files_to_compile
latestDataTime = 0 latestDataTime = 0
latestTextTime = 0 latestTextTime = 0
mustCompile = false mustCompile = false
@@ -864,9 +878,8 @@ module Compiler
write_all write_all
mustCompile = true mustCompile = true
end end
# Check data files and PBS files, and recompile if any PBS file was edited # Check data files for their latest modify time
# more recently than the data files were last created data_files.each do |filename|
dataFiles.each do |filename|
if safeExists?("Data/" + filename) if safeExists?("Data/" + filename)
begin begin
File.open("Data/#{filename}") { |file| File.open("Data/#{filename}") { |file|
@@ -880,24 +893,26 @@ module Compiler
break break
end end
end end
textFiles.each do |filename| # Check PBS files for their latest modify time
next if !safeExists?("PBS/" + filename) text_files.each do |key, value|
next if !value || !value[1].is_a?(Array)
value[1].each do |filepath|
begin begin
File.open("PBS/#{filename}") { |file| File.open(filepath) { |file| latestTextTime = [latestTextTime, file.mtime.to_i].max }
latestTextTime = [latestTextTime, file.mtime.to_i].max
}
rescue SystemCallError rescue SystemCallError
end end
end end
end
# Decide to compile if a PBS file was edited more recently than any .dat files
mustCompile |= (latestTextTime >= latestDataTime) mustCompile |= (latestTextTime >= latestDataTime)
# Should recompile if holding Ctrl # Should recompile if holding Ctrl
Input.update Input.update
mustCompile = true if Input.press?(Input::CTRL) mustCompile = true if Input.press?(Input::CTRL)
# Delete old data files in preparation for recompiling # Delete old data files in preparation for recompiling
if mustCompile if mustCompile
dataFiles.length.times do |i| data_files.length.times do |i|
begin 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 rescue SystemCallError
end end
end end
@@ -908,9 +923,9 @@ module Compiler
e = $! e = $!
raise e if e.class.to_s == "Reset" || e.is_a?(Reset) || e.is_a?(SystemExit) raise e if e.class.to_s == "Reset" || e.is_a?(Reset) || e.is_a?(SystemExit)
pbPrintException(e) pbPrintException(e)
dataFiles.length.times do |i| data_files.length.times do |i|
begin begin
File.delete("Data/#{dataFiles[i]}") File.delete("Data/#{data_files[i]}")
rescue SystemCallError rescue SystemCallError
end end
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] [MAGMAARMOR]
Name = Magma Armor Name = Magma Armor
Flags = FasterEggHatching
Description = Prevents the Pokémon from becoming frozen. Description = Prevents the Pokémon from becoming frozen.
Flags = FasterEggHatching
#------------------------------- #-------------------------------
[WATERVEIL] [WATERVEIL]
Name = Water Veil Name = Water Veil
@@ -195,8 +195,8 @@ Description = The Pokémon awakens quickly from sleep.
#------------------------------- #-------------------------------
[FLAMEBODY] [FLAMEBODY]
Name = Flame Body Name = Flame Body
Flags = FasterEggHatching
Description = Contact with the Pokémon may burn the attacker. Description = Contact with the Pokémon may burn the attacker.
Flags = FasterEggHatching
#------------------------------- #-------------------------------
[RUNAWAY] [RUNAWAY]
Name = Run Away Name = Run Away
@@ -972,8 +972,8 @@ Description = This Pokémon's moves cannot be redirected.
#------------------------------- #-------------------------------
[STEAMENGINE] [STEAMENGINE]
Name = Steam Engine Name = Steam Engine
Flags = FasterEggHatching
Description = Boosts Speed drastically if hit by a Fire or Water move. Description = Boosts Speed drastically if hit by a Fire or Water move.
Flags = FasterEggHatching
#------------------------------- #-------------------------------
[PUNKROCK] [PUNKROCK]
Name = Punk Rock 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 RunCharset = boy_run
CycleCharset = boy_bike CycleCharset = boy_bike
SurfCharset = boy_surf SurfCharset = boy_surf
DiveCharset = boy_surf
FishCharset = boy_fish_offset FishCharset = boy_fish_offset
SurfFishCharset = boy_fish_offset
#------------------------------- #-------------------------------
[2] [2]
TrainerType = POKEMONTRAINER_Leaf TrainerType = POKEMONTRAINER_Leaf
@@ -26,4 +28,6 @@ WalkCharset = trainer_POKEMONTRAINER_Leaf
RunCharset = girl_run RunCharset = girl_run
CycleCharset = girl_bike CycleCharset = girl_bike
SurfCharset = girl_surf SurfCharset = girl_surf
DiveCharset = girl_surf
FishCharset = girl_fish_offset 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? 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... 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. 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! End = See you later!
#------------------------------- #-------------------------------
[PICNICKER,Susie] [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 = 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... 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? 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! End = Bye! Let's chat again!

View File

@@ -5279,6 +5279,7 @@ Evolutions = MISMAGIUS,Item,DUSKSTONE
#------------------------------- #-------------------------------
[UNOWN] [UNOWN]
Name = Unown Name = Unown
FormName = A
Types = PSYCHIC Types = PSYCHIC
BaseStats = 48,72,48,48,72,48 BaseStats = 48,72,48,48,72,48
GenderRatio = Genderless GenderRatio = Genderless
@@ -5299,7 +5300,6 @@ Shape = Head
Habitat = Rare Habitat = Rare
Category = Symbol 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. 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 Generation = 2
#------------------------------- #-------------------------------
[WOBBUFFET] [WOBBUFFET]
@@ -9238,6 +9238,7 @@ Generation = 3
#------------------------------- #-------------------------------
[CASTFORM] [CASTFORM]
Name = Castform Name = Castform
FormName = Normal Form
Types = NORMAL Types = NORMAL
BaseStats = 70,70,70,70,70,70 BaseStats = 70,70,70,70,70,70
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -9259,7 +9260,6 @@ Shape = Head
Habitat = Grassland Habitat = Grassland
Category = Weather 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. 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 Generation = 3
WildItemCommon = MYSTICWATER WildItemCommon = MYSTICWATER
WildItemUncommon = MYSTICWATER WildItemUncommon = MYSTICWATER
@@ -10156,6 +10156,7 @@ WildItemRare = STARPIECE
#------------------------------- #-------------------------------
[DEOXYS] [DEOXYS]
Name = Deoxys Name = Deoxys
FormName = Normal Forme
Types = PSYCHIC Types = PSYCHIC
BaseStats = 50,150,50,150,150,50 BaseStats = 50,150,50,150,150,50
GenderRatio = Genderless GenderRatio = Genderless
@@ -10176,7 +10177,6 @@ Shape = Bipedal
Habitat = Rare Habitat = Rare
Category = DNA 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. 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 Generation = 3
#------------------------------- #-------------------------------
[TURTWIG] [TURTWIG]
@@ -10810,6 +10810,7 @@ Generation = 4
#------------------------------- #-------------------------------
[BURMY] [BURMY]
Name = Burmy Name = Burmy
FormName = Plant Cloak
Types = BUG Types = BUG
BaseStats = 40,29,45,36,29,45 BaseStats = 40,29,45,36,29,45
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -10830,13 +10831,13 @@ Color = Green
Shape = HeadBase Shape = HeadBase
Category = Bagworm Category = Bagworm
Pokedex = To shelter itself from cold, wintry winds, it covers itself with a cloak made of twigs and leaves. Pokedex = To shelter itself from cold, wintry winds, it covers itself with a cloak made of twigs and leaves.
FormName = Plant Cloak
Generation = 4 Generation = 4
Flags = InheritFormFromMother Flags = InheritFormFromMother
Evolutions = WORMADAM,LevelFemale,20,MOTHIM,LevelMale,20 Evolutions = WORMADAM,LevelFemale,20,MOTHIM,LevelMale,20
#------------------------------- #-------------------------------
[WORMADAM] [WORMADAM]
Name = Wormadam Name = Wormadam
FormName = Plant Cloak
Types = BUG,GRASS Types = BUG,GRASS
BaseStats = 60,59,85,36,79,105 BaseStats = 60,59,85,36,79,105
GenderRatio = AlwaysFemale GenderRatio = AlwaysFemale
@@ -10857,7 +10858,6 @@ Color = Green
Shape = HeadBase Shape = HeadBase
Category = Bagworm Category = Bagworm
Pokedex = When Burmy evolved, its cloak became a part of this Pokémon's body. The cloak is never shed. 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 Generation = 4
Flags = InheritFormFromMother Flags = InheritFormFromMother
WildItemUncommon = SILVERPOWDER WildItemUncommon = SILVERPOWDER
@@ -11042,6 +11042,7 @@ Evolutions = CHERRIM,Level,25
#------------------------------- #-------------------------------
[CHERRIM] [CHERRIM]
Name = Cherrim Name = Cherrim
FormName = Overcast Form
Types = GRASS Types = GRASS
BaseStats = 70,60,70,85,87,78 BaseStats = 70,60,70,85,87,78
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -11061,12 +11062,12 @@ Color = Purple
Shape = HeadLegs Shape = HeadLegs
Category = Blossom 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. 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 Generation = 4
WildItemUncommon = MIRACLESEED WildItemUncommon = MIRACLESEED
#------------------------------- #-------------------------------
[SHELLOS] [SHELLOS]
Name = Shellos Name = Shellos
FormName = West Sea
Types = WATER Types = WATER
BaseStats = 76,48,48,34,57,62 BaseStats = 76,48,48,34,57,62
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -11088,13 +11089,13 @@ Color = Purple
Shape = Serpentine Shape = Serpentine
Category = Sea Slug 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. 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 Generation = 4
Flags = InheritFormFromMother Flags = InheritFormFromMother
Evolutions = GASTRODON,Level,30 Evolutions = GASTRODON,Level,30
#------------------------------- #-------------------------------
[GASTRODON] [GASTRODON]
Name = Gastrodon Name = Gastrodon
FormName = West Sea
Types = WATER,GROUND Types = WATER,GROUND
BaseStats = 111,83,68,39,92,82 BaseStats = 111,83,68,39,92,82
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -11115,7 +11116,6 @@ Color = Purple
Shape = Serpentine Shape = Serpentine
Category = Sea Slug 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. 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 Generation = 4
Flags = InheritFormFromMother Flags = InheritFormFromMother
#------------------------------- #-------------------------------
@@ -12505,6 +12505,7 @@ Generation = 4
#------------------------------- #-------------------------------
[ROTOM] [ROTOM]
Name = Rotom Name = Rotom
FormName = Rotom
Types = ELECTRIC,GHOST Types = ELECTRIC,GHOST
BaseStats = 50,50,77,91,95,77 BaseStats = 50,50,77,91,95,77
GenderRatio = Genderless GenderRatio = Genderless
@@ -12524,7 +12525,6 @@ Color = Red
Shape = Head Shape = Head
Category = Plasma Category = Plasma
Pokedex = Its body is composed of plasma. It is known to infiltrate electronic devices and wreak havoc. Pokedex = Its body is composed of plasma. It is known to infiltrate electronic devices and wreak havoc.
FormName = Rotom
Generation = 4 Generation = 4
#------------------------------- #-------------------------------
[UXIE] [UXIE]
@@ -12693,6 +12693,7 @@ Generation = 4
#------------------------------- #-------------------------------
[GIRATINA] [GIRATINA]
Name = Giratina Name = Giratina
FormName = Altered Forme
Types = GHOST,DRAGON Types = GHOST,DRAGON
BaseStats = 150,100,120,90,100,120 BaseStats = 150,100,120,90,100,120
GenderRatio = Genderless GenderRatio = Genderless
@@ -12713,7 +12714,6 @@ Color = Black
Shape = Multiped Shape = Multiped
Category = Renegade 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. 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 Generation = 4
#------------------------------- #-------------------------------
[CRESSELIA] [CRESSELIA]
@@ -12811,6 +12811,7 @@ Generation = 4
#------------------------------- #-------------------------------
[SHAYMIN] [SHAYMIN]
Name = Shaymin Name = Shaymin
FormName = Land Forme
Types = GRASS Types = GRASS
BaseStats = 100,100,100,100,100,100 BaseStats = 100,100,100,100,100,100
GenderRatio = Genderless GenderRatio = Genderless
@@ -12830,7 +12831,6 @@ Color = Green
Shape = Quadruped Shape = Quadruped
Category = Gratitude Category = Gratitude
Pokedex = It lives in flower patches and avoids detection by curling up to look like a flowering plant. Pokedex = It lives in flower patches and avoids detection by curling up to look like a flowering plant.
FormName = Land Forme
Generation = 4 Generation = 4
WildItemCommon = LUMBERRY WildItemCommon = LUMBERRY
WildItemUncommon = LUMBERRY WildItemUncommon = LUMBERRY
@@ -12838,6 +12838,7 @@ WildItemRare = LUMBERRY
#------------------------------- #-------------------------------
[ARCEUS] [ARCEUS]
Name = Arceus Name = Arceus
FormName = Normal Type
Types = NORMAL Types = NORMAL
BaseStats = 120,120,120,120,120,120 BaseStats = 120,120,120,120,120,120
GenderRatio = Genderless GenderRatio = Genderless
@@ -12857,7 +12858,6 @@ Color = White
Shape = Quadruped Shape = Quadruped
Category = Alpha Category = Alpha
Pokedex = It is described in mythology as the Pokémon that shaped the universe with its 1,000 arms. Pokedex = It is described in mythology as the Pokémon that shaped the universe with its 1,000 arms.
FormName = Normal Type
Generation = 4 Generation = 4
#------------------------------- #-------------------------------
[VICTINI] [VICTINI]
@@ -14278,6 +14278,7 @@ WildItemUncommon = ABSORBBULB
#------------------------------- #-------------------------------
[BASCULIN] [BASCULIN]
Name = Basculin Name = Basculin
FormName = Red-Striped
Types = WATER Types = WATER
BaseStats = 70,92,65,98,80,55 BaseStats = 70,92,65,98,80,55
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -14299,7 +14300,6 @@ Color = Green
Shape = Finned Shape = Finned
Category = Hostile Category = Hostile
Pokedex = Savage, violent Pokémon, red and blue Basculin are always fighting each other over territory. Pokedex = Savage, violent Pokémon, red and blue Basculin are always fighting each other over territory.
FormName = Red-Striped
Generation = 5 Generation = 5
Flags = InheritFormFromMother Flags = InheritFormFromMother
WildItemUncommon = DEEPSEATOOTH WildItemUncommon = DEEPSEATOOTH
@@ -14410,6 +14410,7 @@ Evolutions = DARMANITAN,Level,35
#------------------------------- #-------------------------------
[DARMANITAN] [DARMANITAN]
Name = Darmanitan Name = Darmanitan
FormName = Standard Mode
Types = FIRE Types = FIRE
BaseStats = 105,140,55,95,30,55 BaseStats = 105,140,55,95,30,55
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -14430,7 +14431,6 @@ Color = Red
Shape = Quadruped Shape = Quadruped
Category = Blazing Category = Blazing
Pokedex = When weakened in battle, it transforms into a stone statue. Then it sharpens its mind and fights on mentally. 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 Generation = 5
#------------------------------- #-------------------------------
[MARACTUS] [MARACTUS]
@@ -15167,6 +15167,7 @@ WildItemCommon = NEVERMELTICE
#------------------------------- #-------------------------------
[DEERLING] [DEERLING]
Name = Deerling Name = Deerling
FormName = Spring Form
Types = NORMAL,GRASS Types = NORMAL,GRASS
BaseStats = 60,60,50,75,40,50 BaseStats = 60,60,50,75,40,50
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -15188,12 +15189,12 @@ Color = Pink
Shape = Quadruped Shape = Quadruped
Category = Season 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. 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 Generation = 5
Evolutions = SAWSBUCK,Level,34 Evolutions = SAWSBUCK,Level,34
#------------------------------- #-------------------------------
[SAWSBUCK] [SAWSBUCK]
Name = Sawsbuck Name = Sawsbuck
FormName = Spring Form
Types = NORMAL,GRASS Types = NORMAL,GRASS
BaseStats = 80,100,70,95,60,70 BaseStats = 80,100,70,95,60,70
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -15214,7 +15215,6 @@ Color = Brown
Shape = Quadruped Shape = Quadruped
Category = Season Category = Season
Pokedex = The plants growing on its horns change according to the season. The leaders of the herd possess magnificent horns. 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 Generation = 5
#------------------------------- #-------------------------------
[EMOLGA] [EMOLGA]
@@ -16564,6 +16564,7 @@ Generation = 5
#------------------------------- #-------------------------------
[TORNADUS] [TORNADUS]
Name = Tornadus Name = Tornadus
FormName = Incarnate Forme
Types = FLYING Types = FLYING
BaseStats = 79,115,70,111,125,80 BaseStats = 79,115,70,111,125,80
GenderRatio = AlwaysMale GenderRatio = AlwaysMale
@@ -16584,11 +16585,11 @@ Color = Green
Shape = HeadArms Shape = HeadArms
Category = Cyclone Category = Cyclone
Pokedex = Tornadus expels massive energy from its tail, causing severe storms. Its power is great enough to blow houses away. 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 Generation = 5
#------------------------------- #-------------------------------
[THUNDURUS] [THUNDURUS]
Name = Thundurus Name = Thundurus
FormName = Incarnate Forme
Types = ELECTRIC,FLYING Types = ELECTRIC,FLYING
BaseStats = 79,115,70,111,125,80 BaseStats = 79,115,70,111,125,80
GenderRatio = AlwaysMale GenderRatio = AlwaysMale
@@ -16609,7 +16610,6 @@ Color = Blue
Shape = HeadArms Shape = HeadArms
Category = Bolt Strike Category = Bolt Strike
Pokedex = The spikes on its tail discharge immense bolts of lightning. It flies around the Unova region firing off lightning bolts. 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 Generation = 5
#------------------------------- #-------------------------------
[RESHIRAM] [RESHIRAM]
@@ -16660,6 +16660,7 @@ Generation = 5
#------------------------------- #-------------------------------
[LANDORUS] [LANDORUS]
Name = Landorus Name = Landorus
FormName = Incarnate Forme
Types = GROUND,FLYING Types = GROUND,FLYING
BaseStats = 89,125,90,101,115,80 BaseStats = 89,125,90,101,115,80
GenderRatio = AlwaysMale GenderRatio = AlwaysMale
@@ -16680,7 +16681,6 @@ Color = Brown
Shape = HeadArms Shape = HeadArms
Category = Abundance Category = Abundance
Pokedex = The energy that comes pouring from its tail increases the nutrition in the soil, making crops grow to great size. 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 Generation = 5
#------------------------------- #-------------------------------
[KYUREM] [KYUREM]
@@ -16708,6 +16708,7 @@ Generation = 5
#------------------------------- #-------------------------------
[KELDEO] [KELDEO]
Name = Keldeo Name = Keldeo
FormName = Ordinary Form
Types = WATER,FIGHTING Types = WATER,FIGHTING
BaseStats = 91,72,90,108,129,90 BaseStats = 91,72,90,108,129,90
GenderRatio = Genderless GenderRatio = Genderless
@@ -16727,11 +16728,11 @@ Color = Yellow
Shape = Quadruped Shape = Quadruped
Category = Colt Category = Colt
Pokedex = It crosses the world, running over the surfaces of oceans and rivers. It appears at scenic waterfronts. Pokedex = It crosses the world, running over the surfaces of oceans and rivers. It appears at scenic waterfronts.
FormName = Ordinary Form
Generation = 5 Generation = 5
#------------------------------- #-------------------------------
[MELOETTA] [MELOETTA]
Name = Meloetta Name = Meloetta
FormName = Aria Forme
Types = NORMAL,PSYCHIC Types = NORMAL,PSYCHIC
BaseStats = 100,77,77,90,128,128 BaseStats = 100,77,77,90,128,128
GenderRatio = Genderless GenderRatio = Genderless
@@ -16751,7 +16752,6 @@ Color = White
Shape = Bipedal Shape = Bipedal
Category = Melody Category = Melody
Pokedex = Many famous songs have been inspired by the melodies that Meloetta plays. Pokedex = Many famous songs have been inspired by the melodies that Meloetta plays.
FormName = Aria Forme
Generation = 5 Generation = 5
WildItemCommon = STARPIECE WildItemCommon = STARPIECE
WildItemUncommon = STARPIECE WildItemUncommon = STARPIECE
@@ -16759,6 +16759,7 @@ WildItemRare = STARPIECE
#------------------------------- #-------------------------------
[GENESECT] [GENESECT]
Name = Genesect Name = Genesect
FormName = Normal
Types = BUG,STEEL Types = BUG,STEEL
BaseStats = 71,120,95,99,120,95 BaseStats = 71,120,95,99,120,95
GenderRatio = Genderless GenderRatio = Genderless
@@ -16778,7 +16779,6 @@ Color = Purple
Shape = Bipedal Shape = Bipedal
Category = Paleozoic Category = Paleozoic
Pokedex = This ancient bug Pokémon was altered by Team Plasma. They upgraded the cannon on its back. Pokedex = This ancient bug Pokémon was altered by Team Plasma. They upgraded the cannon on its back.
FormName = Normal
Generation = 5 Generation = 5
#------------------------------- #-------------------------------
[CHESPIN] [CHESPIN]
@@ -17184,6 +17184,7 @@ Evolutions = VIVILLON,Level,12
#------------------------------- #-------------------------------
[VIVILLON] [VIVILLON]
Name = Vivillon Name = Vivillon
FormName = Archipelago Pattern
Types = BUG,FLYING Types = BUG,FLYING
BaseStats = 80,52,50,89,90,50 BaseStats = 80,52,50,89,90,50
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -17204,7 +17205,6 @@ Color = White
Shape = MultiWinged Shape = MultiWinged
Category = Scale Category = Scale
Pokedex = Vivillon with many different patterns are found all over the world. These patterns are affected by the climate of their habitat. 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 Generation = 6
#------------------------------- #-------------------------------
[LITLEO] [LITLEO]
@@ -17259,6 +17259,7 @@ Generation = 6
#------------------------------- #-------------------------------
[FLABEBE] [FLABEBE]
Name = Flabébé Name = Flabébé
FormName = Red Flower
Types = FAIRY Types = FAIRY
BaseStats = 44,38,39,42,61,79 BaseStats = 44,38,39,42,61,79
GenderRatio = AlwaysFemale GenderRatio = AlwaysFemale
@@ -17280,13 +17281,13 @@ Color = White
Shape = HeadArms Shape = HeadArms
Category = Single Bloom 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. 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 Generation = 6
Flags = InheritFormFromMother Flags = InheritFormFromMother
Evolutions = FLOETTE,Level,19 Evolutions = FLOETTE,Level,19
#------------------------------- #-------------------------------
[FLOETTE] [FLOETTE]
Name = Floette Name = Floette
FormName = Red Flower
Types = FAIRY Types = FAIRY
BaseStats = 54,45,47,52,75,98 BaseStats = 54,45,47,52,75,98
GenderRatio = AlwaysFemale GenderRatio = AlwaysFemale
@@ -17307,13 +17308,13 @@ Color = White
Shape = HeadArms Shape = HeadArms
Category = Single Bloom 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. 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 Generation = 6
Flags = InheritFormFromMother Flags = InheritFormFromMother
Evolutions = FLORGES,Item,SHINYSTONE Evolutions = FLORGES,Item,SHINYSTONE
#------------------------------- #-------------------------------
[FLORGES] [FLORGES]
Name = Florges Name = Florges
FormName = Red Flower
Types = FAIRY Types = FAIRY
BaseStats = 78,65,68,75,112,154 BaseStats = 78,65,68,75,112,154
GenderRatio = AlwaysFemale GenderRatio = AlwaysFemale
@@ -17334,7 +17335,6 @@ Color = White
Shape = HeadArms Shape = HeadArms
Category = Garden Category = Garden
Pokedex = It claims exquisite flower gardens as its territory, and it obtains power from basking in the energy emitted by flowering plants. 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 Generation = 6
Flags = InheritFormFromMother Flags = InheritFormFromMother
#------------------------------- #-------------------------------
@@ -17442,6 +17442,7 @@ WildItemUncommon = MENTALHERB
#------------------------------- #-------------------------------
[FURFROU] [FURFROU]
Name = Furfrou Name = Furfrou
FormName = Natural Form
Types = NORMAL Types = NORMAL
BaseStats = 75,80,60,102,65,90 BaseStats = 75,80,60,102,65,90
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -17462,7 +17463,6 @@ Color = White
Shape = Quadruped Shape = Quadruped
Category = Poodle Category = Poodle
Pokedex = Trimming its fluffy fur not only makes it more elegant but also increases the swiftness of its movements. Pokedex = Trimming its fluffy fur not only makes it more elegant but also increases the swiftness of its movements.
FormName = Natural Form
Generation = 6 Generation = 6
#------------------------------- #-------------------------------
[ESPURR] [ESPURR]
@@ -17493,6 +17493,7 @@ Evolutions = MEOWSTIC,Level,25
#------------------------------- #-------------------------------
[MEOWSTIC] [MEOWSTIC]
Name = Meowstic Name = Meowstic
FormName = Male
Types = PSYCHIC Types = PSYCHIC
BaseStats = 74,48,76,104,83,81 BaseStats = 74,48,76,104,83,81
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -17513,7 +17514,6 @@ Color = Blue
Shape = BipedalTail Shape = BipedalTail
Category = Constraint 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. 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 Generation = 6
#------------------------------- #-------------------------------
[HONEDGE] [HONEDGE]
@@ -17567,6 +17567,7 @@ Evolutions = AEGISLASH,Item,DUSKSTONE
#------------------------------- #-------------------------------
[AEGISLASH] [AEGISLASH]
Name = Aegislash Name = Aegislash
FormName = Shield Forme
Types = STEEL,GHOST Types = STEEL,GHOST
BaseStats = 60,50,140,60,50,140 BaseStats = 60,50,140,60,50,140
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -17586,7 +17587,6 @@ Color = Brown
Shape = HeadBase Shape = HeadBase
Category = Royal Sword 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. 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 Generation = 6
#------------------------------- #-------------------------------
[SPRITZEE] [SPRITZEE]
@@ -18290,6 +18290,7 @@ Generation = 6
#------------------------------- #-------------------------------
[PUMPKABOO] [PUMPKABOO]
Name = Pumpkaboo Name = Pumpkaboo
FormName = Small Size
Types = GHOST,GRASS Types = GHOST,GRASS
BaseStats = 44,66,70,56,44,55 BaseStats = 44,66,70,56,44,55
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -18310,13 +18311,13 @@ Color = Brown
Shape = Head Shape = Head
Category = Pumpkin Category = Pumpkin
Pokedex = When taking spirits to the afterlife, small Pumpkaboo prefer the spirits of children to those of adults. Pokedex = When taking spirits to the afterlife, small Pumpkaboo prefer the spirits of children to those of adults.
FormName = Small Size
Generation = 6 Generation = 6
Flags = InheritFormFromMother Flags = InheritFormFromMother
Evolutions = GOURGEIST,Trade, Evolutions = GOURGEIST,Trade,
#------------------------------- #-------------------------------
[GOURGEIST] [GOURGEIST]
Name = Gourgeist Name = Gourgeist
FormName = Small Size
Types = GHOST,GRASS Types = GHOST,GRASS
BaseStats = 55,85,122,99,58,75 BaseStats = 55,85,122,99,58,75
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -18336,7 +18337,6 @@ Color = Brown
Shape = HeadBase Shape = HeadBase
Category = Pumpkin Category = Pumpkin
Pokedex = Small Gourgeist pretend to be children to fool adults. Anyone who falls for the act gets carried away to the hereafter. 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 Generation = 6
Flags = InheritFormFromMother Flags = InheritFormFromMother
#------------------------------- #-------------------------------
@@ -18442,6 +18442,7 @@ Generation = 6
#------------------------------- #-------------------------------
[XERNEAS] [XERNEAS]
Name = Xerneas Name = Xerneas
FormName = Neutral Mode
Types = FAIRY Types = FAIRY
BaseStats = 126,131,95,99,131,98 BaseStats = 126,131,95,99,131,98
GenderRatio = Genderless GenderRatio = Genderless
@@ -18461,7 +18462,6 @@ Color = Blue
Shape = Quadruped Shape = Quadruped
Category = Life 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. 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 Generation = 6
#------------------------------- #-------------------------------
[YVELTAL] [YVELTAL]
@@ -18489,6 +18489,7 @@ Generation = 6
#------------------------------- #-------------------------------
[ZYGARDE] [ZYGARDE]
Name = Zygarde Name = Zygarde
FormName = 50% Forme
Types = DRAGON,GROUND Types = DRAGON,GROUND
BaseStats = 108,100,121,95,81,95 BaseStats = 108,100,121,95,81,95
GenderRatio = Genderless GenderRatio = Genderless
@@ -18508,7 +18509,6 @@ Color = Green
Shape = Serpentine Shape = Serpentine
Category = Order Category = Order
Pokedex = It's thought to be monitoring the ecosystem. There are rumors that even greater power lies hidden within it. 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 Generation = 6
#------------------------------- #-------------------------------
[DIANCIE] [DIANCIE]
@@ -18536,6 +18536,7 @@ Generation = 6
#------------------------------- #-------------------------------
[HOOPA] [HOOPA]
Name = Hoopa Name = Hoopa
FormName = Hoopa Confined
Types = PSYCHIC,GHOST Types = PSYCHIC,GHOST
BaseStats = 80,110,60,70,150,130 BaseStats = 80,110,60,70,150,130
GenderRatio = Genderless GenderRatio = Genderless
@@ -18555,7 +18556,6 @@ Color = Purple
Shape = HeadArms Shape = HeadArms
Category = Mischief Category = Mischief
Pokedex = This troublemaker sends anything and everything to faraway places using its loop, which can warp space. Pokedex = This troublemaker sends anything and everything to faraway places using its loop, which can warp space.
FormName = Hoopa Confined
Generation = 6 Generation = 6
#------------------------------- #-------------------------------
[VOLCANION] [VOLCANION]
@@ -19063,6 +19063,7 @@ WildItemUncommon = CHERIBERRY
#------------------------------- #-------------------------------
[ORICORIO] [ORICORIO]
Name = Oricorio Name = Oricorio
FormName = Baile Style
Types = FIRE,FLYING Types = FIRE,FLYING
BaseStats = 75,70,70,93,98,70 BaseStats = 75,70,70,93,98,70
GenderRatio = Female75Percent GenderRatio = Female75Percent
@@ -19083,7 +19084,6 @@ Color = Red
Shape = Winged Shape = Winged
Category = Dancing 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. 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 Generation = 7
Flags = InheritFormFromMother Flags = InheritFormFromMother
WildItemUncommon = HONEY WildItemUncommon = HONEY
@@ -19168,6 +19168,7 @@ Evolutions = LYCANROC,Level,25
#------------------------------- #-------------------------------
[LYCANROC] [LYCANROC]
Name = Lycanroc Name = Lycanroc
FormName = Midday Form
Types = ROCK Types = ROCK
BaseStats = 75,115,65,112,55,65 BaseStats = 75,115,65,112,55,65
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -19188,11 +19189,11 @@ Color = Brown
Shape = Quadruped Shape = Quadruped
Category = Wolf 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. 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 Generation = 7
#------------------------------- #-------------------------------
[WISHIWASHI] [WISHIWASHI]
Name = Wishiwashi Name = Wishiwashi
FormName = Solo Form
Types = WATER Types = WATER
BaseStats = 45,20,20,40,25,25 BaseStats = 45,20,20,40,25,25
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -19213,7 +19214,6 @@ Color = Blue
Shape = Finned Shape = Finned
Category = Small Fry 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. 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 Generation = 7
#------------------------------- #-------------------------------
[MAREANIE] [MAREANIE]
@@ -19885,6 +19885,7 @@ Evolutions = SILVALLY,Happiness,
#------------------------------- #-------------------------------
[SILVALLY] [SILVALLY]
Name = Silvally Name = Silvally
FormName = Type: Normal
Types = NORMAL Types = NORMAL
BaseStats = 95,95,95,95,95,95 BaseStats = 95,95,95,95,95,95
GenderRatio = Genderless GenderRatio = Genderless
@@ -19904,11 +19905,11 @@ Color = Gray
Shape = Quadruped Shape = Quadruped
Category = Synthetic 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. 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 Generation = 7
#------------------------------- #-------------------------------
[MINIOR] [MINIOR]
Name = Minior Name = Minior
FormName = Meteor Form
Types = ROCK,FLYING Types = ROCK,FLYING
BaseStats = 60,60,100,60,60,100 BaseStats = 60,60,100,60,60,100
GenderRatio = Genderless GenderRatio = Genderless
@@ -19928,7 +19929,6 @@ Color = Brown
Shape = Head Shape = Head
Category = Meteor 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. 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 Generation = 7
WildItemUncommon = STARPIECE WildItemUncommon = STARPIECE
#------------------------------- #-------------------------------
@@ -20009,6 +20009,7 @@ WildItemUncommon = ELECTRICSEED
#------------------------------- #-------------------------------
[MIMIKYU] [MIMIKYU]
Name = Mimikyu Name = Mimikyu
FormName = Disguised Form
Types = GHOST,FAIRY Types = GHOST,FAIRY
BaseStats = 55,90,80,96,50,105 BaseStats = 55,90,80,96,50,105
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -20029,7 +20030,6 @@ Color = Yellow
Shape = Serpentine Shape = Serpentine
Category = Disguise 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. 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 Generation = 7
WildItemUncommon = CHESTOBERRY WildItemUncommon = CHESTOBERRY
#------------------------------- #-------------------------------
@@ -21758,6 +21758,7 @@ Evolutions = TOXTRICITY,Level,30
#------------------------------- #-------------------------------
[TOXTRICITY] [TOXTRICITY]
Name = Toxtricity Name = Toxtricity
FormName = Amped Form
Types = ELECTRIC,POISON Types = ELECTRIC,POISON
BaseStats = 75,98,70,75,114,70 BaseStats = 75,98,70,75,114,70
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -21778,7 +21779,6 @@ Color = Purple
Shape = BipedalTail Shape = BipedalTail
Category = Punk 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. 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 Generation = 8
#------------------------------- #-------------------------------
[SIZZLIPEDE] [SIZZLIPEDE]
@@ -21883,6 +21883,7 @@ Generation = 8
#------------------------------- #-------------------------------
[SINISTEA] [SINISTEA]
Name = Sinistea Name = Sinistea
FormName = Phony Form
Types = GHOST Types = GHOST
BaseStats = 40,45,45,50,74,54 BaseStats = 40,45,45,50,74,54
GenderRatio = Genderless GenderRatio = Genderless
@@ -21903,12 +21904,12 @@ Color = Purple
Shape = Head Shape = Head
Category = Black Tea 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. 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 Generation = 8
Evolutions = POLTEAGEIST,Item,CRACKEDPOT Evolutions = POLTEAGEIST,Item,CRACKEDPOT
#------------------------------- #-------------------------------
[POLTEAGEIST] [POLTEAGEIST]
Name = Polteageist Name = Polteageist
FormName = Phony Form
Types = GHOST Types = GHOST
BaseStats = 60,65,65,70,134,114 BaseStats = 60,65,65,70,134,114
GenderRatio = Genderless GenderRatio = Genderless
@@ -21929,7 +21930,6 @@ Color = Purple
Shape = Head Shape = Head
Category = Black Tea Category = Black Tea
Pokedex = This species lives in antique teapots. Most pots are forgeries, but on rare occasions, an authentic work is found. 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 Generation = 8
#------------------------------- #-------------------------------
[HATENNA] [HATENNA]
@@ -22265,6 +22265,7 @@ Evolutions = ALCREMIE,HoldItem,STRAWBERRYSWEET,ALCREMIE,HoldItem,BERRYSWEET,ALCR
#------------------------------- #-------------------------------
[ALCREMIE] [ALCREMIE]
Name = Alcremie Name = Alcremie
FormName = Vanilla Cream
Types = FAIRY Types = FAIRY
BaseStats = 65,60,75,64,110,121 BaseStats = 65,60,75,64,110,121
GenderRatio = AlwaysFemale GenderRatio = AlwaysFemale
@@ -22285,7 +22286,6 @@ Color = White
Shape = HeadBase Shape = HeadBase
Category = Cream Category = Cream
Pokedex = When Alcremie is content, the cream it secretes from its hands becomes sweeter and richer. Pokedex = When Alcremie is content, the cream it secretes from its hands becomes sweeter and richer.
FormName = Vanilla Cream
Generation = 8 Generation = 8
#------------------------------- #-------------------------------
[FALINKS] [FALINKS]
@@ -22414,6 +22414,7 @@ Generation = 8
#------------------------------- #-------------------------------
[EISCUE] [EISCUE]
Name = Eiscue Name = Eiscue
FormName = Ice Face
Types = ICE Types = ICE
BaseStats = 75,80,110,50,65,90 BaseStats = 75,80,110,50,65,90
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -22434,11 +22435,11 @@ Color = Blue
Shape = BipedalTail Shape = BipedalTail
Category = Penguin 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. 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 Generation = 8
#------------------------------- #-------------------------------
[INDEEDEE] [INDEEDEE]
Name = Indeedee Name = Indeedee
FormName = Male
Types = PSYCHIC,NORMAL Types = PSYCHIC,NORMAL
BaseStats = 60,65,55,95,105,95 BaseStats = 60,65,55,95,105,95
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -22460,11 +22461,11 @@ Color = Purple
Shape = BipedalTail Shape = BipedalTail
Category = Emotion 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. 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 Generation = 8
#------------------------------- #-------------------------------
[MORPEKO] [MORPEKO]
Name = Morpeko Name = Morpeko
FormName = Full Belly Mode
Types = ELECTRIC,DARK Types = ELECTRIC,DARK
BaseStats = 58,95,58,97,70,58 BaseStats = 58,95,58,97,70,58
GenderRatio = Female50Percent GenderRatio = Female50Percent
@@ -22485,7 +22486,6 @@ Color = Yellow
Shape = Bipedal Shape = Bipedal
Category = Two-Sided 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. 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 Generation = 8
#------------------------------- #-------------------------------
[CUFANT] [CUFANT]
@@ -22738,6 +22738,7 @@ Generation = 8
#------------------------------- #-------------------------------
[ZACIAN] [ZACIAN]
Name = Zacian Name = Zacian
FormName = Hero of Many Battles
Types = FAIRY Types = FAIRY
BaseStats = 92,130,115,138,80,115 BaseStats = 92,130,115,138,80,115
GenderRatio = Genderless GenderRatio = Genderless
@@ -22757,7 +22758,6 @@ Color = Blue
Shape = Quadruped Shape = Quadruped
Category = Warrior Category = Warrior
Pokedex = Known as a legendary hero, this Pokémon absorbs metal particles, transforming them into a weapon it uses to battle. 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 Generation = 8
WildItemCommon = RUSTEDSWORD WildItemCommon = RUSTEDSWORD
WildItemUncommon = RUSTEDSWORD WildItemUncommon = RUSTEDSWORD
@@ -22765,6 +22765,7 @@ WildItemRare = RUSTEDSWORD
#------------------------------- #-------------------------------
[ZAMAZENTA] [ZAMAZENTA]
Name = Zamazenta Name = Zamazenta
FormName = Hero of Many Battles
Types = FIGHTING Types = FIGHTING
BaseStats = 92,130,115,138,80,115 BaseStats = 92,130,115,138,80,115
GenderRatio = Genderless GenderRatio = Genderless
@@ -22784,7 +22785,6 @@ Color = Red
Shape = Quadruped Shape = Quadruped
Category = Warrior 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. 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 Generation = 8
WildItemCommon = RUSTEDSHIELD WildItemCommon = RUSTEDSHIELD
WildItemUncommon = RUSTEDSHIELD WildItemUncommon = RUSTEDSHIELD
@@ -22839,6 +22839,7 @@ Evolutions = URSHIFU,Event,1
#------------------------------- #-------------------------------
[URSHIFU] [URSHIFU]
Name = Urshifu Name = Urshifu
FormName = Single Strike Style
Types = FIGHTING,DARK Types = FIGHTING,DARK
BaseStats = 100,130,100,97,63,60 BaseStats = 100,130,100,97,63,60
GenderRatio = FemaleOneEighth GenderRatio = FemaleOneEighth
@@ -22858,7 +22859,6 @@ Color = Gray
Shape = Bipedal Shape = Bipedal
Category = Wushu Category = Wushu
Pokedex = Inhabiting the mountains of a distant region, this Pokémon races across sheer cliffs, training its legs and refining its moves. 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 Generation = 8
#------------------------------- #-------------------------------
[ZARUDE] [ZARUDE]

View File

@@ -3,34 +3,34 @@
[0] [0]
Name = Essen Name = Essen
Filename = mapRegion0.png Filename = mapRegion0.png
Point = 13,12,Lappet Town,Oak's Lab,2,8,8, Point = 13,12,Lappet Town,Oak's Lab,2,8,8
Point = 13,11,Route 1,,,,, Point = 13,11,Route 1,
Point = 13,10,Cedolan City,Cedolan Dept. Store,7,47,11, Point = 13,10,Cedolan City,Cedolan Dept. Store,7,47,11
Point = 14,10,Cedolan City,,7,47,11, Point = 14,10,Cedolan City,,7,47,11
Point = 14,9,Route 2,,,,, Point = 14,9,Route 2,
Point = 14,8,Route 2,,,,, Point = 14,8,Route 2,
Point = 15,8,Lerucean Town,,23,11,15, Point = 15,8,Lerucean Town,,23,11,15
Point = 16,8,Natural Park,,,,, Point = 16,8,Natural Park,
Point = 15,7,Route 3,,,,, Point = 15,7,Route 3,
Point = 15,6,Route 3,Ice Cave,,,, Point = 15,6,Route 3,Ice Cave
Point = 14,6,Route 3,,,,, Point = 14,6,Route 3,
Point = 13,6,Ingido Plateau,,35,17,7, Point = 13,6,Ingido Plateau,,35,17,7
Point = 12,6,Route 4,,,,, Point = 12,6,Route 4,
Point = 11,6,Route 4,,,,, Point = 11,6,Route 4,
Point = 11,7,Route 5,Cycle Road,,,, Point = 11,7,Route 5,Cycle Road
Point = 11,8,Route 5,Cycle Road,,,, Point = 11,8,Route 5,Cycle Road
Point = 11,9,Route 5,Cycle Road,,,, Point = 11,9,Route 5,Cycle Road
Point = 11,10,Route 6,,,,, Point = 11,10,Route 6,
Point = 12,10,Route 6,,,,, Point = 12,10,Route 6,
Point = 15,10,Route 7,,,,, Point = 15,10,Route 7,
Point = 16,10,Route 7,Rock Cave,,,, Point = 16,10,Route 7,Rock Cave
Point = 17,10,Battle Frontier,,52,17,14, Point = 17,10,Battle Frontier,,52,17,14
Point = 12,12,Safari Zone,,,,, Point = 12,12,Safari Zone,
Point = 13,13,Route 8,Diving area,,,, Point = 13,13,Route 8,Diving area
Point = 18,17,Berth Island,,,,,51 Point = 18,17,Berth Island,,51
Point = 22,16,Faraday Island,,,,,52 Point = 22,16,Faraday Island,,52
#------------------------------- #-------------------------------
[1] [1]
Name = Tiall Name = Tiall
Filename = mapRegion1.png Filename = mapRegion1.png
Point = 13,16,Here,,,,, Point = 13,16,Here,