Merge branch 'ui-redesign' into dev

This commit is contained in:
Maruno17
2025-01-16 22:54:12 +00:00
111 changed files with 36440 additions and 24208 deletions

View File

@@ -46,7 +46,7 @@ module Settings
#-----------------------------------------------------------------------------
# The maximum amount of money the player can have.
MAX_MONEY = 999_999
MAX_MONEY = 9_999_999
# The maximum number of Game Corner coins the player can have.
MAX_COINS = 99_999
# The maximum number of Battle Points the player can have.
@@ -54,7 +54,7 @@ module Settings
# The maximum amount of soot the player can have.
MAX_SOOT = 9_999
# The maximum length, in characters, that the player's name can be.
MAX_PLAYER_NAME_SIZE = 10
MAX_PLAYER_NAME_SIZE = 12
# A set of arrays each containing a trainer type followed by a Game Variable
# number. If the Variable isn't set to 0, then all trainers with the
# associated trainer type will be named as whatever is in that Variable.
@@ -88,13 +88,13 @@ module Settings
SAFARI_STEPS = 600
# The number of seconds a Bug-Catching Contest lasts for (0=infinite).
BUG_CONTEST_TIME = 20 * 60 # 20 minutes
# Pairs of map IDs, where the location signpost isn't shown when moving from
# one of the maps in a pair to the other (and vice versa). Useful for single
# long routes/towns that are spread over multiple maps.
# Pairs of map IDs, where the location sign isn't shown when moving from one
# of the maps in a pair to the other (and vice versa). Useful for single long
# routes/towns that are spread over multiple maps.
# e.g. [4,5,16,17,42,43] will be map pairs 4,5 and 16,17 and 42,43.
# Moving between two maps that have the exact same name won't show the
# location signpost anyway, so you don't need to list those maps here.
NO_SIGNPOSTS = []
# location sign anyway, so you don't need to list those maps here.
NO_LOCATION_SIGNS = []
# Whether poisoned Pokémon will lose HP while walking around in the field.
POISON_IN_FIELD = (MECHANICS_GENERATION <= 4)
# Whether poisoned Pokémon will faint while walking around in the field
@@ -186,30 +186,58 @@ module Settings
66 => [5, 21, 28, 31, 39, 41, 44, 47, 69],
69 => [5, 21, 28, 31, 39, 41, 44, 47, 66 ]
}
# A set of arrays, each containing the details of a roaming Pokémon. The
# information within each array is as follows:
# * Species.
# * Level.
# * Game Switch; the Pokémon roams while this is ON.
# * Encounter type (see def pbRoamingMethodAllowed for their use):
# 0 = grass, walking in cave, surfing
# 1 = grass, walking in cave
# 2 = surfing
# 3 = fishing
# 4 = surfing, fishing
# * Name of BGM to play for that encounter (optional).
# * Roaming areas specifically for this Pokémon (optional; used instead of
# ROAMING_AREAS).
# A set of hashes, each containing the details of a roaming Pokémon. The
# information within each hash is as follows:
# * :species
# * :level
# * :icon - Filename in Graphics/UI/Town Map/ of the roamer's Town Map icon.
# * :game_switch - The Pokémon roams if this is nil or <=0 or if that Game
# Switch is ON. Optional.
# * :encounter_type - One of:
# :all = grass, walking in cave, surfing (default)
# :land = grass, walking in cave
# :water = surfing, fishing
# :surfing = surfing
# :fishing = fishing
# * :bgm - The BGM to play for the encounter. Optional.
# * :areas - A hash of map IDs that determine where this Pokémon roams. Used
# instead of ROAMING_AREAS above. Optional.
ROAMING_SPECIES = [
[:LATIAS, 30, 53, 0, "Battle roaming"],
[:LATIOS, 30, 53, 0, "Battle roaming"],
[:KYOGRE, 40, 54, 2, nil, {
2 => [ 21, 31 ],
21 => [2, 31, 69],
31 => [2, 21, 69],
69 => [ 21, 31 ]
}],
[:ENTEI, 40, 55, 1]
{
:species => :LATIAS,
:level => 30,
:icon => "pin_latias",
:game_switch => 53,
:encounter_type => :all,
:bgm => "Battle roaming"
},
{
:species => :LATIOS,
:level => 30,
:icon => "pin_latios",
:game_switch => 53,
:encounter_type => :all,
:bgm => "Battle roaming"
},
{
:species => :KYOGRE,
:level => 40,
:game_switch => 54,
:encounter_type => :surfing,
:areas => {
2 => [ 21, 31 ],
21 => [2, 31, 69],
31 => [2, 21, 69],
69 => [ 21, 31 ]
}
},
{
:species => :ENTEI,
:level => 40,
:icon => "pin_entei",
:game_switch => 55,
:encounter_type => :land
}
]
#-----------------------------------------------------------------------------
@@ -259,31 +287,6 @@ module Settings
# this number.
ITEM_SELL_PRICE_DIVISOR = (MECHANICS_GENERATION >= 9) ? 4 : 2
#-----------------------------------------------------------------------------
# Bag
#-----------------------------------------------------------------------------
# The names of each pocket of the Bag.
def self.bag_pocket_names
return [
_INTL("Items"),
_INTL("Medicine"),
_INTL("Poké Balls"),
_INTL("TMs & HMs"),
_INTL("Berries"),
_INTL("Mail"),
_INTL("Battle Items"),
_INTL("Key Items")
]
end
# The maximum number of slots per pocket (-1 means infinite number).
BAG_MAX_POCKET_SIZE = [-1, -1, -1, -1, -1, -1, -1, -1]
# Whether each pocket in turn auto-sorts itself by the order items are defined
# in the PBS file items.txt.
BAG_POCKET_AUTO_SORT = [false, false, false, true, true, false, false, false]
# The maximum number of items each slot in the Bag can hold.
BAG_MAX_PER_SLOT = 999
#-----------------------------------------------------------------------------
# Pokédex
#-----------------------------------------------------------------------------

View File

@@ -6,16 +6,25 @@
# @see SaveData.register_conversion
#===============================================================================
module SaveData
# Contains the file path of the save file.
FILE_PATH = if File.directory?(System.data_directory)
System.data_directory + "/Game.rxdata"
else
"./Game.rxdata"
end
DIRECTORY = (File.directory?(System.data_directory)) ? System.data_directory : "./"
FILENAME_REGEX = /Game(\d*)\.rxdata$/
# @return [Boolean] whether the save file exists
# @return [Boolean] whether any save files exist
def self.exists?
return File.file?(FILE_PATH)
return !all_save_files.empty?
end
# @return[Array] array of filenames in the save folder that are save files
def self.all_save_files
files = Dir.get(DIRECTORY, "*", false)
ret = []
files.each do |file|
next if !file[FILENAME_REGEX]
ret.push([$~[1].to_i, file])
end
ret.sort! { |a, b| a[0] <=> b[0] }
ret.map! { |val| val[1] }
return ret
end
# Fetches the save data from the given file.
@@ -45,7 +54,7 @@ module SaveData
def self.read_from_file(file_path)
validate file_path => String
save_data = get_data_from_file(file_path)
save_data = to_hash_format(save_data) if save_data.is_a?(Array)
save_data = to_hash_format(save_data) if save_data.is_a?(Array) # Pre-v19 save file support
if !save_data.empty? && run_conversions(save_data)
File.open(file_path, "wb") { |file| Marshal.dump(save_data, file) }
end
@@ -64,9 +73,14 @@ module SaveData
# Deletes the save file (and a possible .bak backup file if one exists)
# @raise [Error::ENOENT]
def self.delete_file
File.delete(FILE_PATH)
File.delete(FILE_PATH + ".bak") if File.file?(FILE_PATH + ".bak")
def self.delete_file(filename)
File.delete(DIRECTORY + filename)
File.delete(DIRECTORY + filename + ".bak") if File.file?(DIRECTORY + filename + ".bak")
end
def self.filename_from_index(index = 0)
return "Game.rxdata" if index <= 0
return "Game#{index}.rxdata"
end
# Converts the pre-v19 format data to the new format.

View File

@@ -259,9 +259,9 @@ module SaveData
# been set to be loaded during bootup. Done when a save file exists.
# @param save_data [Hash] save data to load
# @raise [InvalidValueError] if an invalid value is being loaded
def self.load_bootup_values(save_data)
def self.load_bootup_values(save_data, reload = false)
validate save_data => Hash
load_values(save_data) { |value| !value.loaded? && value.load_in_bootup? }
load_values(save_data) { |value| (reload || !value.loaded?) && value.load_in_bootup? }
end
# Goes through each value with {Value#load_in_bootup} enabled and loads their

View File

@@ -201,7 +201,8 @@ module SaveData
validate save_data => Hash
conversions_to_run = self.get_conversions(save_data)
return false if conversions_to_run.none?
File.open(SaveData::FILE_PATH + ".bak", "wb") { |f| Marshal.dump(save_data, f) }
filepath = SaveData::DIRECTORY + SaveData.filename_from_index(save_data[:stats].save_filename_number || 0)
File.open(filepath + ".bak", "wb") { |f| Marshal.dump(save_data, f) }
Console.echo_h1(_INTL("Converting save file"))
conversions_to_run.each do |conversion|
Console.echo_li("#{conversion.title}...")

View File

@@ -10,16 +10,14 @@ SaveData.register(:player) do
end
SaveData.register(:game_system) do
load_in_bootup
ensure_class :Game_System
save_value { $game_system }
load_value { |value| $game_system = value }
new_game_value { Game_System.new }
reset_on_new_game
end
SaveData.register(:pokemon_system) do
load_in_bootup
load_in_bootup # Because this contains values for the Options screen
ensure_class :PokemonSystem
save_value { $PokemonSystem }
load_value { |value| $PokemonSystem = value }
@@ -96,7 +94,6 @@ SaveData.register(:storage_system) do
end
SaveData.register(:essentials_version) do
load_in_bootup
ensure_class :String
save_value { Essentials::VERSION }
load_value { |value| $save_engine_version = value }
@@ -104,7 +101,6 @@ SaveData.register(:essentials_version) do
end
SaveData.register(:game_version) do
load_in_bootup
ensure_class :String
save_value { Settings::GAME_VERSION }
load_value { |value| $save_game_version = value }
@@ -112,10 +108,8 @@ SaveData.register(:game_version) do
end
SaveData.register(:stats) do
load_in_bootup
ensure_class :GameStats
save_value { $stats }
load_value { |value| $stats = value }
new_game_value { GameStats.new }
reset_on_new_game
end

View File

@@ -72,6 +72,18 @@ end
#===============================================================================
SaveData.register_conversion(:v22_add_adventure_magic_number) do
essentials_version 22
display_title "Adding adventure ID"
to_value :game_system do |game_system|
game_system.instance_eval do
@adventure_magic_number ||= rand(2**32)
end
end
end
#===============================================================================
SaveData.register_conversion(:v22_add_new_stats) do
essentials_version 22
display_title "Adding some more stats"
@@ -83,3 +95,40 @@ SaveData.register_conversion(:v22_add_new_stats) do
end
end
end
#===============================================================================
SaveData.register_conversion(:v22_convert_bag_object) do
essentials_version 22
display_title "Converting Bag's pockets"
to_value :bag do |bag|
bag.instance_eval do
all_pockets = GameData::BagPocket.all_pockets
if @pockets.is_a?(Array)
new_pockets = {}
all_pockets.each { |pckt| new_pockets[pckt] = [] }
@pockets.each_with_index do |value, i|
next if i == 0
value.each do |item|
pckt = GameData::Item.get(item[0]).bag_pocket
new_pockets[pckt].push(item)
end
end
@pockets = new_pockets
end
if @last_viewed_pocket.is_a?(Integer)
@last_viewed_pocket = all_pockets[@last_viewed_pocket - 1] || all_pockets.first
end
if @last_pocket_selections.is_a?(Array)
new_sels = {}
all_pockets.each { |pckt| new_sels[pckt] = 0 }
@last_pocket_selections.each_with_index do |value, i|
next if i == 0
pckt = all_pockets[i - 1]
new_sels[pckt] = value if pckt && value <= @pockets[pckt].length - 1
end
@last_pocket_selections = new_sels
end
end
end
end

View File

@@ -23,17 +23,11 @@ module Game
# Loads bootup data from save file (if it exists) or creates bootup data (if
# it doesn't).
def set_up_system
save_data = (SaveData.exists?) ? SaveData.read_from_file(SaveData::FILE_PATH) : {}
if save_data.empty?
SaveData.initialize_bootup_values
else
SaveData.load_bootup_values(save_data)
end
# Set resize factor
SaveData.initialize_bootup_values
pbSetResizeFactor([$PokemonSystem.screensize, 4].min)
# Set language (and choose language if there is no save file)
if !Settings::LANGUAGES.empty?
$PokemonSystem.language = pbChooseLanguage if save_data.empty? && Settings::LANGUAGES.length >= 2
$PokemonSystem.language = pbChooseLanguage if !SaveData.exists? && Settings::LANGUAGES.length >= 2
MessageTypes.load_message_files(Settings::LANGUAGES[$PokemonSystem.language][1])
end
end
@@ -45,7 +39,6 @@ module Game
$game_map.events.each_value { |event| event.clear_starting }
end
$game_temp.common_event_id = 0 if $game_temp
$game_temp.begun_new_game = true
pbMapInterpreter&.clear
pbMapInterpreter&.setup(nil, 0, 0)
$scene = Scene_Map.new
@@ -108,18 +101,21 @@ module Game
end
# Saves the game. Returns whether the operation was successful.
# @param save_file [String] the save file path
# @param index [Integer] the number to put in the save file's name Game#.rzdata
# @param directory [String] the folder to put the save file in
# @param safe [Boolean] whether $PokemonGlobal.safesave should be set to true
# @return [Boolean] whether the operation was successful
# @raise [SaveData::InvalidValueError] if an invalid value is being saved
def save(save_file = SaveData::FILE_PATH, safe: false)
validate save_file => String, safe => [TrueClass, FalseClass]
def save(index, directory = SaveData::DIRECTORY, safe: false)
validate index => Integer, directory => String, safe => [TrueClass, FalseClass]
filename = SaveData.filename_from_index(index)
$PokemonGlobal.safesave = safe
$game_system.save_count += 1
$game_system.magic_number = $data_system.magic_number
$stats.set_time_last_saved
$stats.save_filename_number = index
begin
SaveData.save_to_file(save_file)
SaveData.save_to_file(directory + filename)
Graphics.frame_reset
rescue IOError, SystemCallError
$game_system.save_count -= 1

View File

@@ -103,9 +103,7 @@ class Scene_Map
$game_temp.in_menu = true
$game_player.straighten
$game_map.update
sscene = PokemonPauseMenu_Scene.new
sscreen = PokemonPauseMenu.new(sscene)
sscreen.pbStartPokemonMenu
UI::PauseMenu.new.main
$game_temp.in_menu = false
end

View File

@@ -1153,9 +1153,7 @@ class Interpreter
# * Call Save Screen
#-----------------------------------------------------------------------------
def command_352
scene = PokemonSave_Scene.new
screen = PokemonSaveScreen.new(scene)
screen.pbSaveScreen
pbFadeOutIn { UI::Save.new.main }
return true
end

View File

@@ -104,6 +104,10 @@ class HandlerHash
return nil
end
def keys
return @hash.keys
end
def add(id, handler = nil, &handlerBlock)
if ![Proc, Hash].include?(handler.class) && !block_given?
raise ArgumentError, "#{self.class.name} for #{id.inspect} has no valid handler (#{handler.inspect} was given)"
@@ -160,6 +164,10 @@ class HandlerHashSymbol
return nil
end
def keys
return @hash.keys
end
def add(sym, handler = nil, &handlerBlock)
if ![Proc, Hash].include?(handler.class) && !block_given?
raise ArgumentError, "#{self.class.name} for #{sym.inspect} has no valid handler (#{handler.inspect} was given)"
@@ -225,6 +233,10 @@ class HandlerHashEnum
return ret
end
def keys
return @hash.keys
end
def fromSymbol(sym)
return sym unless sym.is_a?(Symbol) || sym.is_a?(String)
mod = Object.const_get(@mod) rescue nil

View File

@@ -97,6 +97,10 @@ module MenuHandlers
@@handlers[menu]&.clear
end
def get(menu, option)
return @@handlers[menu][option]
end
def each(menu)
return if !@@handlers.has_key?(menu)
@@handlers[menu].each { |option, hash| yield option, hash }
@@ -110,8 +114,19 @@ module MenuHandlers
sorted_keys.each do |option|
hash = options[option]
next if hash["condition"] && !hash["condition"].call(*args)
if hash["multi_options"]
extra_options = hash["multi_options"].call(*args)
if extra_options && extra_options.length > 0
if extra_options[0].is_a?(Array)
extra_options.each { |opt| yield *opt }
else
yield *extra_options
end
end
next
end
if hash["name"].is_a?(Proc)
name = hash["name"].call
name = hash["name"].call(*args)
else
name = _INTL(hash["name"])
end
@@ -125,3 +140,34 @@ module MenuHandlers
return option_hash[function].call(*args)
end
end
#===============================================================================
#
#===============================================================================
module UIActionHandlers
@@handlers = {}
module_function
def add(menu, action, hash)
@@handlers[menu] = HandlerHash.new if !@@handlers.has_key?(menu)
@@handlers[menu].add(action, hash)
end
def remove(menu, action)
@@handlers[menu]&.remove(action)
end
def clear(menu)
@@handlers[menu]&.clear
end
def get(menu, action)
return @@handlers[menu][action]
end
def each(menu)
return if !@@handlers.has_key?(menu)
@@handlers[menu].each { |action, hash| yield action, hash }
end
end

View File

@@ -0,0 +1,62 @@
#===============================================================================
# NOTE: Some Settings in here will be moved elsewhere eventually. They're all
# just gathered here while the new UI is being written.
#===============================================================================
module Settings
# :one, :adventure, :multiple
SAVE_SLOTS = :multiple
# Whether the main color of a move's name in the Fight menu in battle matches
# the pixel at coordinate (10,34) in cursor_fight.png for that move's type
# (true), or whether the move name's color is the default black (false).
BATTLE_MOVE_NAME_COLOR_FROM_GRAPHIC = true
# Whether "Town Map" will show as an option in the pause menu if the player
# has that item in the Bag and doesn't have a Pokégear.
SHOW_TOWN_MAP_IN_PAUSE_MENU = true
# The filename of a location sign graphic to be used if the map metadata for a
# map doesn't define one. Make this nil to use the default menu windowskin.
DEFAULT_LOCATION_SIGN_GRAPHIC = "Pt default"
# Assigns location sign graphics to text styles (numbers). These are used in
# class LocationWindow to display the text appropriately for the graphic being
# used. Style :none is reserved for the "no graphic" style. A filename may
# instead be an array of [filename, text base color, text shadow color].
LOCATION_SIGN_GRAPHIC_STYLES = {
:dp => [["DP", Color.new(72, 80, 72), Color.new(144, 160, 160)]],
:hgss => [["HGSS cave", Color.new(232, 232, 232), Color.new(120, 144, 160)],
["HGSS city", Color.new(56, 64, 72), Color.new(152, 152, 144)],
["HGSS default", Color.new(48, 64, 72), Color.new(144, 144, 96)],
["HGSS forest", Color.new(232, 232, 232), Color.new(120, 176, 144)],
["HGSS lake", Color.new(40, 48, 56), Color.new(104, 144, 192)],
["HGSS park", Color.new(40, 48, 56), Color.new(120, 136, 152)],
["HGSS route", Color.new(48, 64, 72), Color.new(136, 136, 104)],
["HGSS sea", Color.new(216, 240, 248), Color.new(24, 96, 144)],
["HGSS town", Color.new(48, 56, 64), Color.new(144, 120, 80)]],
:platinum => ["Pt cave", "Pt city", "Pt default", "Pt forest", "Pt lake",
"Pt park", "Pt route", "Pt sea", "Pt town"]
}
# Whether a move's power/type/category/etc. as shown in battle, the summary
# screen and the Move Reminder screen will appear as their calculated values
# (true) or their values from the PBS file moves.txt (false). For example, if
# this is true, Judgment's displayed type will depend on the Plate being held
# by the Pokémon that knows it.
SHOW_MODIFIED_MOVE_PROPERTIES = false
# Whether pressing Use in the Town Map will zoom it in to 200% and show a text
# pane on the right showing the selected point's description. The cursor can
# still be moved while zoomed in.
ENABLE_TOWN_MAP_ZOOM_IN_FOR_DETAILS = true
# Whether points in the Town Map can be marked.
ENABLE_TOWN_MAP_MARKING = true
# TODO: Allow renaming a Pokémon from the party screen/summary screen (not
# sure which). Gen 9 feature.
# TODO: Allow forgetting/remembering moves from the summary screen. Gen 9
# feature.
# TODO: Show usability party balls in the Bag. Maybe?
# TODO: Replace Run with Call in battle; don't have this depend on the Shadow
# type existing?
# TODO: Whether new items go at the top or bottom of its Bag pocket?
end

View File

@@ -13,6 +13,8 @@ class Game_Temp
attr_accessor :battle_abort # battle flag: interrupt (unused)
attr_accessor :title_screen_calling # return to title screen flag
attr_accessor :common_event_id # common event ID to start
attr_accessor :field_move_to_use
attr_accessor :field_move_user
# Flags indicating something is happening
attr_accessor :in_menu # menu is open
attr_accessor :in_storage # in-Pokémon storage flag
@@ -39,7 +41,6 @@ class Game_Temp
attr_accessor :background_bitmap
attr_accessor :fadestate # for sprite hashes
# Other
attr_accessor :begun_new_game # new game flag (true fron new game until saving)
attr_accessor :menu_beep # menu: play sound effect flag
attr_accessor :menu_last_choice # pause menu: index of last selection
attr_accessor :memorized_bgm # set when trainer intro BGM is played
@@ -77,7 +78,6 @@ class Game_Temp
@transition_name = ""
@fadestate = 0
# Other
@begun_new_game = false
@menu_beep = false
@memorized_bgm = nil
@memorized_bgm_position = 0

View File

@@ -22,21 +22,27 @@ class Game_System
attr_accessor :bgm_position
def initialize
@map_interpreter = Interpreter.new(0, true)
@battle_interpreter = Interpreter.new(0, false)
@timer_start = nil
@timer_duration = 0
@save_disabled = false
@menu_disabled = false
@encounter_disabled = false
@message_position = 2
@message_frame = 0
@save_count = 0
@magic_number = 0
@autoscroll_x_speed = 0
@autoscroll_y_speed = 0
@bgm_position = 0
@bgs_position = 0
@map_interpreter = Interpreter.new(0, true)
@battle_interpreter = Interpreter.new(0, false)
@timer_start = nil
@timer_duration = 0
@save_disabled = false
@menu_disabled = false
@encounter_disabled = false
@message_position = 2
@message_frame = 0
@save_count = 0
@magic_number = 0
@adventure_magic_number = rand(2**32)
@autoscroll_x_speed = 0
@autoscroll_y_speed = 0
@bgm_position = 0
@bgs_position = 0
end
def adventure_magic_number
@adventure_magic_number ||= rand(2**32)
return @adventure_magic_number
end
def battle_bgm

View File

@@ -61,6 +61,8 @@ class GameStats
attr_writer :play_time # In seconds; the reader also updates the value
attr_accessor :play_sessions
attr_accessor :time_last_saved # In seconds
attr_reader :real_time_saved
attr_accessor :save_filename_number # -1 if haven't saved yet
def initialize
# Travel
@@ -149,6 +151,8 @@ class GameStats
@play_time = 0
@play_sessions = 0
@time_last_saved = 0
@real_time_saved = 0
@save_filename_number = -1
end
def distance_moved
@@ -183,12 +187,18 @@ class GameStats
return @play_time
end
# For looking at a save file's play time.
def real_play_time
return @play_time
end
def play_time_per_session
return play_time / @play_sessions
end
def set_time_last_saved
@time_last_saved = play_time
@real_time_saved = Time.now.to_i
end
def time_since_last_save

View File

@@ -243,17 +243,15 @@ end
def pbRepositionMessageWindow(msgwindow, linecount = 2)
msgwindow.height = (32 * linecount) + msgwindow.borderY
msgwindow.y = (Graphics.height) - (msgwindow.height)
if $game_system
case $game_system.message_position
when 0 # up
msgwindow.y = 0
when 1 # middle
msgwindow.y = (Graphics.height / 2) - (msgwindow.height / 2)
when 2
msgwindow.y = (Graphics.height) - (msgwindow.height)
end
msgwindow.opacity = 0 if $game_system.message_frame != 0
case $game_system&.message_position || 2
when 0 # top
msgwindow.y = 0
when 1 # middle
msgwindow.y = (Graphics.height - msgwindow.height) / 2
when 2 # bottom
msgwindow.y = Graphics.height - msgwindow.height
end
msgwindow.opacity = 0 if ($game_system&.message_frame || 0) != 0
end
# internal function
@@ -376,7 +374,7 @@ def get_text_colors_for_windowskin(windowskin, color, isDarkSkin)
end
# Light background, dark text
if textcolors[2 * (color - 1)].is_a?(Color)
return textcolors[2 * (color - 1)], textcolors[2 * (color - 1) + 1]
return textcolors[2 * (color - 1)], textcolors[(2 * (color - 1)) + 1]
end
return Color.new(*textcolors[2 * (color - 1)]), Color.new(*textcolors[(2 * (color - 1)) + 1])
end
@@ -497,7 +495,7 @@ def using(window)
end
def pbUpdateSpriteHash(windows)
windows.each do |i|
windows&.each do |i|
window = i[1]
if window
if window.is_a?(Sprite) || window.is_a?(Window)
@@ -597,7 +595,7 @@ def pbFadeOutIn(z = 99999, nofadeout = false)
end
end
def pbFadeOutInWithUpdate(z, sprites, nofadeout = false)
def pbFadeOutInWithUpdate(sprites, z = 99999, nofadeout = false)
duration = 0.4 # In seconds
col = Color.new(0, 0, 0, 0)
viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)

View File

@@ -231,7 +231,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
dims = [0, 0]
cwidth = (maxwidth < 0) ? Graphics.width : maxwidth
chars = getFormattedTextForDims(self.contents, 0, 0,
cwidth - self.borderX - 2 - 6, -1, text, @lineHeight, true)
cwidth - self.borderX - SpriteWindow_Base::TEXT_PADDING, -1, text, @lineHeight, true)
chars.each do |ch|
dims[0] = [dims[0], ch[1] + ch[3]].max
dims[1] = [dims[1], ch[2] + ch[4]].max
@@ -244,7 +244,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
oldstarting = @starting
@starting = true
self.width = (width < 0) ? Graphics.width : width
self.height = dims[1] + self.borderY
self.height = dims[1] + self.borderY + 2 # TEXT OFFSET
@starting = oldstarting
redrawText
end
@@ -565,8 +565,8 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
elsif @textchars[@curchar] == "\1"
@pausing = true if @curchar < @numtextchars - 1
self.startPause
refresh
end
refresh
end
end
end
@@ -602,8 +602,8 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
ret = true
@curchar += 1
break if @textchars[@curchar] == "\n" || # newline
@textchars[@curchar] == "\1" || # pause
@textchars[@curchar] == "\2" || # letter-by-letter break
@textchars[@curchar] == "\1" || # pause: "\!"
@textchars[@curchar] == "\2" || # letter-by-letter break: "\wt[]", "\wtnp[]", "\.", "\|"
@textchars[@curchar].nil?
end
return ret
@@ -835,12 +835,11 @@ class SpriteWindow_Selectable < SpriteWindow_Base
if item < 0 || item >= @item_max || item < self.top_item ||
item > self.top_item + self.page_item_max
return Rect.new(0, 0, 0, 0)
else
cursor_width = (self.width - self.borderX - ((@column_max - 1) * @column_spacing)) / @column_max
x = item % @column_max * (cursor_width + @column_spacing)
y = (item / @column_max * @row_height) - @virtualOy
return Rect.new(x, y, cursor_width, @row_height)
end
cursor_width = (self.width - self.borderX - ((@column_max - 1) * @column_spacing)) / @column_max
x = item % @column_max * (cursor_width + @column_spacing)
y = (item / @column_max * @row_height) - @virtualOy
return Rect.new(x, y, cursor_width, @row_height)
end
def refresh; end
@@ -954,7 +953,7 @@ class SpriteWindow_Selectable < SpriteWindow_Base
new_top_row = [[new_top_row, self.row_max - self.page_row_max].min, 0].max
if self.top_row != new_top_row
self.top_row = new_top_row
# dorefresh = true
dorefresh = true
end
# End of code
cursor_width = (self.width - self.borderX) / @column_max
@@ -1243,19 +1242,6 @@ end
class Window_AdvancedCommandPokemon < Window_DrawableCommand
attr_reader :commands
def textWidth(bitmap, text)
dims = [nil, 0]
chars = getFormattedText(bitmap, 0, 0,
Graphics.width - self.borderX - SpriteWindow_Base::TEXT_PADDING - 16,
-1, text, self.rowHeight, true, true)
chars.each do |ch|
dims[0] = dims[0] ? [dims[0], ch[1]].min : ch[1]
dims[1] = [dims[1], ch[1] + ch[3]].max
end
dims[0] = 0 if !dims[0]
return dims[1] - dims[0]
end
def initialize(commands, width = nil)
@starting = true
@commands = []
@@ -1321,11 +1307,60 @@ class Window_AdvancedCommandPokemon < Window_DrawableCommand
end
end
def textWidth(bitmap, text)
dims = [nil, 0]
chars = getFormattedText(bitmap, 0, 0,
Graphics.width - self.borderX - SpriteWindow_Base::TEXT_PADDING - 16,
-1, text, self.rowHeight, true, true)
chars.each do |ch|
dims[0] = dims[0] ? [dims[0], ch[1]].min : ch[1]
dims[1] = [dims[1], ch[1] + ch[3]].max
end
dims[0] = 0 if !dims[0]
return dims[1] - dims[0]
end
def getAutoDims(commands, dims, width = nil)
rowMax = ((commands.length + self.columns - 1) / self.columns).to_i
windowheight = (rowMax * self.rowHeight)
windowheight += self.borderY
if !width || width < 0
width = 0
tmp_bitmap = Bitmap.new(1, 1)
pbSetSystemFont(tmp_bitmap)
commands.each do |cmd|
txt = toUnformattedText(cmd).gsub(/\n/, "")
txt_width = tmp_bitmap.text_size(txt).width
check_text = cmd
while check_text[FORMATREGEXP]
if $~[2].downcase == "icon" && $~[3]
check_text = $~.post_match
filename = $~[4].sub(/\s+$/, "")
temp_graphic = Bitmap.new("Graphics/Icons/#{filename}")
txt_width += temp_graphic.width
temp_graphic.dispose
else
check_text = $~.post_match
end
end
width = [width, txt_width].max
end
# one 16 to allow cursor
width += 16 + 16 + SpriteWindow_Base::TEXT_PADDING
tmp_bitmap.dispose
end
# Store suggested width and height of window
dims[0] = [self.borderX + 1,
(width * self.columns) + self.borderX + ((self.columns - 1) * self.columnSpacing)].max
dims[1] = [self.borderY + 1, windowheight].max
dims[1] = [dims[1], Graphics.height].min
end
def resizeToFit(commands, width = nil)
dims = []
getAutoDims(commands, dims, width)
self.width = dims[0]
self.height = dims[1] - 6
self.height = dims[1]
end
def itemCount
@@ -1340,8 +1375,8 @@ class Window_AdvancedCommandPokemon < Window_DrawableCommand
pbDrawShadowText(self.contents, rect.x, rect.y + (self.contents.text_offset_y || 0),
rect.width, rect.height, @commands[index], self.baseColor, self.shadowColor)
else
chars = getFormattedText(self.contents, rect.x, rect.y + (self.contents.text_offset_y || 0),
rect.width, rect.height, @commands[index], rect.height, true, true)
chars = getFormattedText(self.contents, rect.x, rect.y + (self.contents.text_offset_y || 0) + 2, # TEXT OFFSET
rect.width, rect.height, @commands[index], rect.height, true, true, false, self)
drawFormattedChars(self.contents, chars)
end
end

View File

@@ -3,19 +3,117 @@
# This bitmap can't be changed to a different one.
#===============================================================================
class BitmapSprite < Sprite
attr_reader :text_themes
def initialize(width, height, viewport = nil)
super(viewport)
self.bitmap = Bitmap.new(width, height)
@text_themes = {}
@initialized = true
end
def dispose
self.bitmap.dispose if !self.disposed?
super
end
def bitmap=(value)
super(value) if !@initialized
end
def dispose
self.bitmap.dispose if !self.disposed?
super
#-----------------------------------------------------------------------------
def add_text_theme(id, base_color, shadow_color = nil)
@text_themes[id] = [base_color, shadow_color]
end
# TODO: Replaces def pbDrawTextPositions.
def draw_themed_text(string, text_x, text_y, align = :left, theme = :default, outline = :shadow)
string_size = self.bitmap.text_size(string)
case align
when :right
text_x -= string_size.width
when :center
text_x -= (string_size.width / 2)
end
if !@text_themes[theme]
theme = (@text_themes[:default]) ? :default : @text_themes.keys.first
end
case outline || :shadow
when :shadow
draw_shadowed_text(string, text_x, text_y, theme)
when :outline
draw_outlined_text(string, text_x, text_y, theme)
when :none
draw_plain_text(string, text_x, text_y, theme)
end
end
# TODO: Replaces def pbDrawShadowText.
def draw_shadowed_text(string, text_x, text_y, theme)
return if !@text_themes[theme]
base_color, shadow_color = @text_themes[theme]
string_size = self.bitmap.text_size(string)
string_width = string_size.width + 1
string_height = string_size.height + 1
if shadow_color && shadow_color.alpha > 0
self.bitmap.font.color = shadow_color
self.bitmap.draw_text(text_x + 2, text_y, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x, text_y + 2, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x + 2, text_y + 2, string_width, string_height, string, 0)
end
if base_color && base_color.alpha > 0
self.bitmap.font.color = base_color
self.bitmap.draw_text(text_x, text_y, string_width, string_height, string, 0)
end
end
# TODO: Replaces def pbDrawOutlineText.
def draw_outlined_text(string, text_x, text_y, theme)
return if !@text_themes[theme]
base_color, shadow_color = @text_themes[theme]
string_size = self.bitmap.text_size(string)
string_width = string_size.width + 1
string_height = string_size.height + 1
if shadow_color && shadow_color.alpha > 0
self.bitmap.font.color = shadow_color
self.bitmap.draw_text(text_x - 2, text_y - 2, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x, text_y - 2, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x + 2, text_y - 2, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x - 2, text_y, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x + 2, text_y, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x - 2, text_y + 2, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x, text_y + 2, string_width, string_height, string, 0)
self.bitmap.draw_text(text_x + 2, text_y + 2, string_width, string_height, string, 0)
end
if base_color && base_color.alpha > 0
self.bitmap.font.color = base_color
self.bitmap.draw_text(text_x, text_y, string_width, string_height, string, 0)
end
end
# TODO: Replaces def pbDrawPlainText.
def draw_plain_text(string, text_x, text_y, theme)
return if !@text_themes[theme]
base_color = @text_themes[theme][0]
return if !base_color || base_color.alpha == 0
string_size = self.bitmap.text_size(string)
string_width = string_size.width + 1
string_height = string_size.height + 1
self.bitmap.font.color = base_color
self.bitmap.draw_text(text_x, text_y, string_width, string_height, string, 0)
end
#-----------------------------------------------------------------------------
# TODO: Replaces def pbDrawImagePositions.
def draw_image(filename, image_x, image_y, src_x = 0, src_y = 0, src_width = -1, src_height = -1)
src_bitmap = (filename.is_a?(AnimatedBitmap)) ? filename : AnimatedBitmap.new(pbBitmapName(filename))
src_width = (src_width >= 0) ? src_width : src_bitmap.width
src_height = (src_height >= 0) ? src_height : src_bitmap.height
src_rect = Rect.new(src_x, src_y, src_width, src_height)
self.bitmap.blt(image_x, image_y, src_bitmap.bitmap, src_rect)
src_bitmap.dispose if !filename.is_a?(AnimatedBitmap)
end
end
@@ -210,22 +308,24 @@ end
# Sprite class that stores multiple bitmaps, and displays only one at once.
#===============================================================================
class ChangelingSprite < Sprite
# Key is the mode (a symbol).
# Value is one of:
# filepath
# [filepath, src_x, src_y, src_width, src_height]
BITMAPS = {}
def initialize(x = 0, y = 0, viewport = nil)
super(viewport)
self.x = x
self.y = y
@bitmaps = {}
@currentBitmap = nil
@changeling_data = {}
@current_bitmap = nil
initialize_changeling_data
end
def addBitmap(key, path)
@bitmaps[key]&.dispose
@bitmaps[key] = AnimatedBitmap.new(path)
end
def changeBitmap(key)
@currentBitmap = @bitmaps[key]
self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil
def initialize_changeling_data
self.class::BITMAPS.each_pair { |mode, data| add_bitmap(mode, data) }
end
def dispose
@@ -235,9 +335,37 @@ class ChangelingSprite < Sprite
super
end
#-----------------------------------------------------------------------------
def add_bitmap(mode, *data)
raise ArgumentError.new(_INTL("wrong number of arguments (given {1}, expected 2 or 6)", data.length + 1)) if ![1, 5].include?(data.length)
filepath = (data[0].is_a?(Array)) ? data[0][0] : data[0]
@bitmaps[filepath] = AnimatedBitmap.new(filepath) if !@bitmaps[filepath]
@changeling_data[mode] = (data[0].is_a?(Array) ? data[0].clone : [data[0]])
end
def change_bitmap(mode)
@current_mode = mode
if @current_mode && @changeling_data[@current_mode]
data = @changeling_data[@current_mode]
@current_bitmap = @bitmaps[data[0]]
self.bitmap = @current_bitmap.bitmap
if data.length > 1
self.src_rect.set(data[1], data[2], data[3], data[4])
else
self.src_rect.set(0, 0, self.bitmap.width, self.bitmap.height)
end
else
@current_bitmap = nil
self.bitmap = nil
end
end
#-----------------------------------------------------------------------------
def update
return if disposed?
@bitmaps.each_value { |bm| bm.update }
self.bitmap = (@currentBitmap) ? @currentBitmap.bitmap : nil
self.bitmap = @current_bitmap.bitmap if @current_bitmap
end
end

View File

@@ -66,7 +66,9 @@ def fmtReplaceEscapes(text)
end
def toUnformattedText(text)
text2 = text.gsub(FORMATREGEXP, "")
text2 = text.clone
pbReplaceMessageText(text2, nil)
text2 = text2.gsub(FORMATREGEXP, "")
fmtReplaceEscapes(text2)
return text2
end
@@ -147,7 +149,7 @@ def getFormattedTextFast(bitmap, xDst, yDst, widthDst, heightDst, text, lineheig
elsif isspace
hadspace = true
end
texty = (lineheight * y) + yDst + yStart
texty = (lineheight * y) + yDst + yStart - 2 # TEXT OFFSET
# Push character
if heightDst < 0 || yStart < yDst + heightDst
havenl = true if isWaitChar(textchars[position])
@@ -314,7 +316,7 @@ end
#===============================================================================
def getFormattedText(bitmap, xDst, yDst, widthDst, heightDst, text, lineheight = 32,
newlineBreaks = true, explicitBreaksOnly = false,
collapseAlignments = false)
collapseAlignments = false, msg_window = nil)
dummybitmap = nil
if !bitmap || bitmap.disposed? # allows function to be called with nil bitmap
dummybitmap = Bitmap.new(1, 1)
@@ -327,6 +329,7 @@ def getFormattedText(bitmap, xDst, yDst, widthDst, heightDst, text, lineheight =
textchunks = []
controls = []
# oldtext = text
pbReplaceMessageText(text, msg_window)
while text[FORMATREGEXP]
textchunks.push($~.pre_match)
if $~[3]
@@ -376,7 +379,11 @@ def getFormattedText(bitmap, xDst, yDst, widthDst, heightDst, text, lineheight =
fontsize = defaultfontsize
fontnamestack = []
fontsizestack = []
defaultcolors = [oldfont.color.clone, nil]
if msg_window
defaultcolors = [msg_window.baseColor, msg_window.shadowColor]
else
defaultcolors = [oldfont.color.clone, nil]
end
if defaultfontname.is_a?(Array)
defaultfontname = defaultfontname.find { |i| Font.exist?(i) } || "Arial"
elsif !Font.exist?(defaultfontname)
@@ -917,17 +924,18 @@ def drawSingleFormattedChar(bitmap, ch)
if ch[5] # If a graphic
graphic = Bitmap.new(ch[0])
graphicRect = ch[15]
bitmap.blt(ch[1], ch[2], graphic, graphicRect, ch[8].alpha)
bitmap.blt(ch[1], ch[2] - (bitmap.text_offset_y || 0), graphic, graphicRect, ch[8].alpha)
graphic.dispose
return
end
bitmap.font.size = ch[13] if bitmap.font.size != ch[13]
if ch[9] # shadow
if ch[10] # underline
bitmap.fill_rect(ch[1], ch[2] + ch[4] - [(ch[4] - bitmap.font.size) / 2, 0].max - 2, ch[3], 4, ch[9])
bitmap.fill_rect(ch[1], ch[2] + ch[4] - [(ch[4] - bitmap.font.size) / 2, 0].max - 2 - (bitmap.text_offset_y || 0),
ch[3], 4, ch[9])
end
if ch[11] # strikeout
bitmap.fill_rect(ch[1], ch[2] + 2 + (ch[4] / 2), ch[3], 4, ch[9])
bitmap.fill_rect(ch[1], ch[2] + 2 + (ch[4] / 2) - (bitmap.text_offset_y || 0), ch[3], 4, ch[9])
end
end
if ch[0] == "\n" || ch[0] == "\r" || ch[0] == " " || isWaitChar(ch[0])
@@ -969,10 +977,11 @@ def drawSingleFormattedChar(bitmap, ch)
bitmap.draw_text(ch[1] + offset, ch[2] + offset, ch[3], ch[4], ch[0])
end
if ch[10] # underline
bitmap.fill_rect(ch[1], ch[2] + ch[4] - [(ch[4] - bitmap.font.size) / 2, 0].max - 2, ch[3] - 2, 2, ch[8])
bitmap.fill_rect(ch[1], ch[2] + ch[4] - [(ch[4] - bitmap.font.size) / 2, 0].max - 2 - (bitmap.text_offset_y || 0),
ch[3] - 2, 2, ch[8])
end
if ch[11] # strikeout
bitmap.fill_rect(ch[1], ch[2] + 2 + (ch[4] / 2), ch[3] - 2, 2, ch[8])
bitmap.fill_rect(ch[1], ch[2] + 2 + (ch[4] / 2) - (bitmap.text_offset_y || 0), ch[3] - 2, 2, ch[8])
end
end

View File

@@ -254,9 +254,10 @@ end
def pbGetMapNameFromId(id)
name = GameData::MapMetadata.try_get(id)&.name
if nil_or_empty?(name)
name = pbGetBasicMapNameFromId(id)
name.gsub!(/\\PN/, $player.name) if $player
name = pbGetBasicMapNameFromId(id) if nil_or_empty?(name)
name = name.gsub(/\\PN/, $player.name) if $player
if $game_variables
name = name.gsub(/\\v\[(\d+)\]/) { |num| $game_variables[$~[1].to_i].to_s }
end
return name
end
@@ -304,6 +305,44 @@ def pbCsvPosInt!(str)
return ret.to_i
end
def pbReplaceMessageText(text, msg_window)
# \sign[something] gets turned into \op\cl\ts[]\w[something]
text.gsub!(/\\sign\[([^\]]*)\]/i) { next "\\op\\cl\\ts[]\\w[" + $1 + "]" }
# Escaped characters
text.gsub!(/\\\\/, "\5")
text.gsub!(/\\1/, "\1")
text.gsub!(/\\n/i, "\n")
# Text placeholders
text.gsub!(/\\pn/i, $player.name) if $player
text.gsub!(/\\pm/i, _INTL("${1}", $player.money.to_s_formatted)) if $player
loop do
last_text = text.clone
text.gsub!(/\\v\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
break if text == last_text
end
if $game_actors
text.gsub!(/\\n\[([1-8])\]/i) { next $game_actors[$1.to_i].name }
end
# Male/female text colors
text.gsub!(/\\pg/i, "\\b") if $player&.male?
text.gsub!(/\\pg/i, "\\r") if $player&.female?
text.gsub!(/\\pog/i, "\\r") if $player&.male?
text.gsub!(/\\pog/i, "\\b") if $player&.female?
text.gsub!(/\\pg/i, "")
text.gsub!(/\\pog/i, "")
male_text_tag = shadowc3tag(MessageConfig::MALE_TEXT_MAIN_COLOR, MessageConfig::MALE_TEXT_SHADOW_COLOR)
female_text_tag = shadowc3tag(MessageConfig::FEMALE_TEXT_MAIN_COLOR, MessageConfig::FEMALE_TEXT_SHADOW_COLOR)
text.gsub!(/\\b/i, male_text_tag)
text.gsub!(/\\r/i, female_text_tag)
# Other text colors
text.gsub!(/\\\[([0-9a-f]{8,8})\]/i) { "<c2=" + $1 + ">" }
isDarkSkin = msg_window && isDarkWindowskin(msg_window.windowskin)
text.gsub!(/\\c\[([0-9]+)\]/i) do
main_color, shadow_color = get_text_colors_for_windowskin(msg_window&.windowskin, $1.to_i, isDarkSkin)
next shadowc3tag(main_color, shadow_color)
end
end
#===============================================================================
# Money and coins windows.
#===============================================================================
@@ -419,28 +458,7 @@ def pbMessageDisplay(msgwindow, message, letterbyletter = true, commandProc = ni
text = message.clone
linecount = (Graphics.height > 400) ? 3 : 2
### Text replacement
text.gsub!(/\\sign\[([^\]]*)\]/i) do # \sign[something] gets turned into
next "\\op\\cl\\ts[]\\w[" + $1 + "]" # \op\cl\ts[]\w[something]
end
text.gsub!(/\\\\/, "\5")
text.gsub!(/\\1/, "\1")
if $game_actors
text.gsub!(/\\n\[([1-8])\]/i) { next $game_actors[$1.to_i].name }
end
text.gsub!(/\\pn/i, $player.name) if $player
text.gsub!(/\\pm/i, _INTL("${1}", $player.money.to_s_formatted)) if $player
text.gsub!(/\\n/i, "\n")
text.gsub!(/\\\[([0-9a-f]{8,8})\]/i) { "<c2=" + $1 + ">" }
text.gsub!(/\\pg/i, "\\b") if $player&.male?
text.gsub!(/\\pg/i, "\\r") if $player&.female?
text.gsub!(/\\pog/i, "\\r") if $player&.male?
text.gsub!(/\\pog/i, "\\b") if $player&.female?
text.gsub!(/\\pg/i, "")
text.gsub!(/\\pog/i, "")
male_text_tag = shadowc3tag(MessageConfig::MALE_TEXT_MAIN_COLOR, MessageConfig::MALE_TEXT_SHADOW_COLOR)
female_text_tag = shadowc3tag(MessageConfig::FEMALE_TEXT_MAIN_COLOR, MessageConfig::FEMALE_TEXT_SHADOW_COLOR)
text.gsub!(/\\b/i, male_text_tag)
text.gsub!(/\\r/i, female_text_tag)
pbReplaceMessageText(text, msgwindow)
text.gsub!(/\\[Ww]\[([^\]]*)\]/) do
w = $1.to_s
if w == ""
@@ -450,16 +468,6 @@ def pbMessageDisplay(msgwindow, message, letterbyletter = true, commandProc = ni
end
next ""
end
isDarkSkin = isDarkWindowskin(msgwindow.windowskin)
text.gsub!(/\\c\[([0-9]+)\]/i) do
main_color, shadow_color = get_text_colors_for_windowskin(msgwindow.windowskin, $1.to_i, isDarkSkin)
next shadowc3tag(main_color, shadow_color)
end
loop do
last_text = text.clone
text.gsub!(/\\v\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
break if text == last_text
end
loop do
last_text = text.clone
text.gsub!(/\\l\[([0-9]+)\]/i) do
@@ -473,6 +481,7 @@ def pbMessageDisplay(msgwindow, message, letterbyletter = true, commandProc = ni
main_color, shadow_color = get_text_colors_for_windowskin(msgwindow.windowskin, 0, true)
colortag = shadowc3tag(main_color, shadow_color)
else
isDarkSkin = isDarkWindowskin(msgwindow.windowskin)
main_color, shadow_color = get_text_colors_for_windowskin(msgwindow.windowskin, 0, isDarkSkin)
colortag = shadowc3tag(main_color, shadow_color)
end
@@ -723,7 +732,7 @@ end
def pbShowCommands(msgwindow, commands = nil, cmdIfCancel = 0, defaultCmd = 0)
return 0 if !commands
cmdwindow = Window_CommandPokemonEx.new(commands)
cmdwindow = Window_AdvancedCommandPokemon.new(commands)
cmdwindow.z = 99999
cmdwindow.visible = true
cmdwindow.resizeToFit(cmdwindow.commands)
@@ -763,7 +772,7 @@ def pbShowCommandsWithHelp(msgwindow, commands, help, cmdIfCancel = 0, defaultCm
oldlbl = msgwin.letterbyletter
msgwin.letterbyletter = false
if commands
cmdwindow = Window_CommandPokemonEx.new(commands)
cmdwindow = Window_AdvancedCommandPokemon.new(commands)
cmdwindow.z = 99999
cmdwindow.visible = true
cmdwindow.resizeToFit(cmdwindow.commands)

View File

@@ -9,6 +9,7 @@ module GameData
class Stat
attr_reader :id
attr_reader :real_name
attr_reader :real_name_semi_brief
attr_reader :real_name_brief
attr_reader :type
attr_reader :pbs_order
@@ -39,11 +40,12 @@ module GameData
#---------------------------------------------------------------------------
def initialize(hash)
@id = hash[:id]
@real_name = hash[:name] || "Unnamed"
@real_name_brief = hash[:name_brief] || "None"
@type = hash[:type] || :none
@pbs_order = hash[:pbs_order] || -1
@id = hash[:id]
@real_name = hash[:name] || "Unnamed"
@real_name_semi_brief = hash[:name_semi_brief]
@real_name_brief = hash[:name_brief] || "None"
@type = hash[:type] || :none
@pbs_order = hash[:pbs_order] || -1
end
# @return [String] the translated name of this stat
@@ -51,6 +53,10 @@ module GameData
return _INTL(@real_name)
end
def name_semi_brief
return _INTL(@real_name_semi_brief || @real_name)
end
# @return [String] the translated brief name of this stat
def name_brief
return _INTL(@real_name_brief)
@@ -87,19 +93,21 @@ GameData::Stat.register({
})
GameData::Stat.register({
:id => :SPECIAL_ATTACK,
:name => _INTL("Special Attack"),
:name_brief => _INTL("SpAtk"),
:type => :main_battle,
:pbs_order => 4
:id => :SPECIAL_ATTACK,
:name => _INTL("Special Attack"),
:name_semi_brief => _INTL("Sp. Attack"),
:name_brief => _INTL("SpAtk"),
:type => :main_battle,
:pbs_order => 4
})
GameData::Stat.register({
:id => :SPECIAL_DEFENSE,
:name => _INTL("Special Defense"),
:name_brief => _INTL("SpDef"),
:type => :main_battle,
:pbs_order => 5
:id => :SPECIAL_DEFENSE,
:name => _INTL("Special Defense"),
:name_semi_brief => _INTL("Sp. Defense"),
:name_brief => _INTL("SpDef"),
:type => :main_battle,
:pbs_order => 5
})
GameData::Stat.register({

View File

@@ -0,0 +1,160 @@
#===============================================================================
#
#===============================================================================
module GameData
class BagPocket
attr_reader :id
attr_reader :real_name
attr_reader :icon_position # Where this pocket's icon is within icon_pocket.png
attr_reader :order
attr_reader :max_slots
attr_reader :auto_sort
DATA = {}
extend ClassMethodsSymbols
include InstanceMethods
def self.load; end
def self.save; end
def self.all_pockets
ret = []
DATA.each_value { |pocket| ret.push([pocket.bag_pocket]) }
ret.uniq!
ret.each { |data| data.push(self.get(data[0]).order) }
ret.sort_by! { |pckt| pckt[1] }
ret.map! { |pckt| pckt[0] }
return ret
end
def self.index(pocket)
return self.all_pockets.index(pocket)
end
# @param other [Symbol, self, String]
# @return [self]
def self.get(other)
validate other => [Symbol, self, String, Integer]
return other if other.is_a?(self)
other = self.all_pockets[other - 1] if other.is_a?(Integer)
other = other.to_sym if other.is_a?(String)
raise "Unknown ID #{other}." unless self::DATA.has_key?(other)
return self::DATA[other]
end
# @param other [Symbol, self, String]
# @return [self, nil]
def try_get(other)
return nil if other.nil?
validate other => [Symbol, self, String, Integer]
return other if other.is_a?(self)
other = self.all_pockets[other - 1] if other.is_a?(Integer)
other = other.to_sym if other.is_a?(String)
return (self::DATA.has_key?(other)) ? self::DATA[other] : nil
end
#---------------------------------------------------------------------------
def initialize(hash)
@id = hash[:id]
@real_name = hash[:name] || "Unnamed"
@icon_position = hash[:icon_position] || 0
@order = hash[:order] || 999
@max_slots = hash[:max_slots] || -1
@auto_sort = hash[:auto_sort] || false
@parent_pocket = hash[:parent_pocket]
end
# @return [String] the translated name of this nature
def name
return _INTL(@real_name)
end
def bag_pocket
return @parent_pocket || @id
end
end
end
#===============================================================================
# NOTE: If :parent_pocket is defined for a BagPocket below, that parent pocket
# is assumed to be one that appears in the Bag. They don't chain.
# i.e. You can't give "MegaStones" a :parent_pocket of "HeldItems", and
# "HeldItems" a :parent_pocket of "Items" (where "Items" is the only one
# of these pockets that appears in the Bag). Both "MegaStones" and
# "HeldItems" should have a :parent_pocket of "Items".
#===============================================================================
GameData::BagPocket.register({
:id => :Items,
:name => _INTL("Other Items"),
:icon_position => 0,
:order => 10
})
GameData::BagPocket.register({
:id => :Mail,
:parent_pocket => :Items
})
GameData::BagPocket.register({
:id => :Medicine,
:name => _INTL("Medicine"),
:icon_position => 1,
:order => 20
})
GameData::BagPocket.register({
:id => :PokeBalls,
:name => _INTL("Poké Balls"),
:icon_position => 2,
:order => 30
})
GameData::BagPocket.register({
:id => :Berries,
:name => _INTL("Berries"),
:icon_position => 3,
:order => 40,
:auto_sort => true
})
GameData::BagPocket.register({
:id => :HeldItems,
:name => _INTL("Held Items"),
:icon_position => 4,
:order => 50
})
GameData::BagPocket.register({
:id => :MegaStones,
:parent_pocket => :HeldItems
})
GameData::BagPocket.register({
:id => :BattleItems,
:name => _INTL("Battle Items"),
:icon_position => 5,
:order => 60
})
# This pocket is hardcoded to allow showing the details of a machine item in
# this pocket in the Bag. The display of this information is toggled by pressing
# the Action input. It is not possible to open the screen menu with the Action
# input in this pocket (although you also can't open it if the pocket auto-sorts
# so that's not a problem).
GameData::BagPocket.register({
:id => :Machines,
:name => _INTL("TMs & HMs"),
:icon_position => 6,
:order => 70,
:auto_sort => true
})
GameData::BagPocket.register({
:id => :KeyItems,
:name => _INTL("Key Items"),
:icon_position => 7,
:order => 80
})

View File

@@ -6,7 +6,10 @@ module GameData
attr_reader :id
attr_reader :real_name
attr_reader :filename
attr_reader :point
attr_reader :margins
attr_reader :point_size
attr_reader :size
attr_reader :points
attr_reader :flags
attr_reader :pbs_file_suffix
@@ -14,23 +17,43 @@ module GameData
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"]
"SectionName" => [:id, "u"],
"Name" => [:real_name, "s"],
"Filename" => [:filename, "s"],
"Margins" => [:margins, "uu"], # Left/right and top/bottom padding in pixels
"PointSize" => [:point_size, "vv"], # Size of a point in pixels
"Size" => [:size, "vv"], # Width and height in points
"Point" => [:points, "^uusSUUUU"],
"Flags" => [:flags, "*s"]
}
# This schema is for definable properties of individual points (apart from
# position and name which are above).
SUB_SCHEMA = {
"Image" => [:image, "s"],
"Description" => [:real_description, "q"],
"FlySpot" => [:fly_spot, "vuu"], # Map ID, x coord, y coord
"HideFlyIcon" => [:hide_fly_icon, "b"],
"FlyIconOffset" => [:fly_icon_offset, "ii"], # x and y offsets in pixels
"Switch" => [:switch, "v"] # Game Switch ID
}
extend ClassMethodsIDNumbers
include InstanceMethods
def self.sub_schema
return SUB_SCHEMA
end
#---------------------------------------------------------------------------
def initialize(hash)
@id = hash[:id]
@real_name = hash[:real_name] || "???"
@filename = hash[:filename]
@point = hash[:point] || []
@margins = hash[:margins] || [0, 0]
@point_size = hash[:point_size] || [16, 16]
@size = hash[:size] || [30, 20]
@points = hash[:points] || []
@flags = hash[:flags] || []
@pbs_file_suffix = hash[:pbs_file_suffix] || ""
end
@@ -43,5 +66,18 @@ module GameData
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end
def get_point_property_for_PBS(key, index = 0)
return [*@points[index][:position], @points[index][:real_name]] if key == "Point"
ret = @points[index][SUB_SCHEMA[key][0]]
ret = nil if ret == false || (ret.is_a?(Array) && ret.length == 0) || ret == ""
case key
when "Margins"
ret = nil if ret == [0, 0]
when "FlySpot"
ret = nil if ret && ret.compact.empty?
end
return ret
end
end
end

View File

@@ -103,132 +103,132 @@ module GameData
end
def display_type(pkmn, move = nil)
=begin
case @function_code
when "TypeDependsOnUserIVs"
return pbHiddenPower(pkmn)[0]
when "TypeAndPowerDependOnUserBerry"
item_data = pkmn.item
if item_data
item_data.flags.each do |flag|
next if !flag[/^NaturalGift_(\w+)_(?:\d+)$/i]
typ = $~[1].to_sym
ret = typ if GameData::Type.exists?(typ)
break
if Settings::SHOW_MODIFIED_MOVE_PROPERTIES
case @function_code
when "TypeDependsOnUserIVs"
return pbHiddenPower(pkmn)[0]
when "TypeAndPowerDependOnUserBerry"
item_data = pkmn.item
if item_data
item_data.flags.each do |flag|
next if !flag[/^NaturalGift_(\w+)_(?:\d+)$/i]
typ = $~[1].to_sym
ret = typ if GameData::Type.exists?(typ)
break
end
end
end
return :NORMAL
when "TypeDependsOnUserPlate"
item_types = {
:FISTPLATE => :FIGHTING,
:SKYPLATE => :FLYING,
:TOXICPLATE => :POISON,
:EARTHPLATE => :GROUND,
:STONEPLATE => :ROCK,
:INSECTPLATE => :BUG,
:SPOOKYPLATE => :GHOST,
:IRONPLATE => :STEEL,
:FLAMEPLATE => :FIRE,
:SPLASHPLATE => :WATER,
:MEADOWPLATE => :GRASS,
:ZAPPLATE => :ELECTRIC,
:MINDPLATE => :PSYCHIC,
:ICICLEPLATE => :ICE,
:DRACOPLATE => :DRAGON,
:DREADPLATE => :DARK,
:PIXIEPLATE => :FAIRY
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
return :NORMAL
when "TypeDependsOnUserPlate"
item_types = {
:FISTPLATE => :FIGHTING,
:SKYPLATE => :FLYING,
:TOXICPLATE => :POISON,
:EARTHPLATE => :GROUND,
:STONEPLATE => :ROCK,
:INSECTPLATE => :BUG,
:SPOOKYPLATE => :GHOST,
:IRONPLATE => :STEEL,
:FLAMEPLATE => :FIRE,
:SPLASHPLATE => :WATER,
:MEADOWPLATE => :GRASS,
:ZAPPLATE => :ELECTRIC,
:MINDPLATE => :PSYCHIC,
:ICICLEPLATE => :ICE,
:DRACOPLATE => :DRAGON,
:DREADPLATE => :DARK,
:PIXIEPLATE => :FAIRY
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
end
end
end
when "TypeDependsOnUserMemory"
item_types = {
:FIGHTINGMEMORY => :FIGHTING,
:FLYINGMEMORY => :FLYING,
:POISONMEMORY => :POISON,
:GROUNDMEMORY => :GROUND,
:ROCKMEMORY => :ROCK,
:BUGMEMORY => :BUG,
:GHOSTMEMORY => :GHOST,
:STEELMEMORY => :STEEL,
:FIREMEMORY => :FIRE,
:WATERMEMORY => :WATER,
:GRASSMEMORY => :GRASS,
:ELECTRICMEMORY => :ELECTRIC,
:PSYCHICMEMORY => :PSYCHIC,
:ICEMEMORY => :ICE,
:DRAGONMEMORY => :DRAGON,
:DARKMEMORY => :DARK,
:FAIRYMEMORY => :FAIRY
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
when "TypeDependsOnUserMemory"
item_types = {
:FIGHTINGMEMORY => :FIGHTING,
:FLYINGMEMORY => :FLYING,
:POISONMEMORY => :POISON,
:GROUNDMEMORY => :GROUND,
:ROCKMEMORY => :ROCK,
:BUGMEMORY => :BUG,
:GHOSTMEMORY => :GHOST,
:STEELMEMORY => :STEEL,
:FIREMEMORY => :FIRE,
:WATERMEMORY => :WATER,
:GRASSMEMORY => :GRASS,
:ELECTRICMEMORY => :ELECTRIC,
:PSYCHICMEMORY => :PSYCHIC,
:ICEMEMORY => :ICE,
:DRAGONMEMORY => :DRAGON,
:DARKMEMORY => :DARK,
:FAIRYMEMORY => :FAIRY
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
end
end
end
when "TypeDependsOnUserDrive"
item_types = {
:SHOCKDRIVE => :ELECTRIC,
:BURNDRIVE => :FIRE,
:CHILLDRIVE => :ICE,
:DOUSEDRIVE => :WATER
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
when "TypeDependsOnUserDrive"
item_types = {
:SHOCKDRIVE => :ELECTRIC,
:BURNDRIVE => :FIRE,
:CHILLDRIVE => :ICE,
:DOUSEDRIVE => :WATER
}
if pkmn.hasItem?
item_types.each do |item, item_type|
return item_type if pkmn.item_id == item && GameData::Type.exists?(item_type)
end
end
when "TypeIsUserFirstType"
return pkmn.types[0]
end
when "TypeIsUserFirstType"
return pkmn.types[0]
end
=end
return @type
end
def display_damage(pkmn, move = nil)
=begin
case @function_code
when "TypeDependsOnUserIVs"
return pbHiddenPower(pkmn)[1]
when "TypeAndPowerDependOnUserBerry"
item_data = pkmn.item
if item_data
item_data.flags.each do |flag|
return [$~[1].to_i, 10].max if flag[/^NaturalGift_(?:\w+)_(\d+)$/i]
def display_power(pkmn, move = nil)
if Settings::SHOW_MODIFIED_MOVE_PROPERTIES
case @function_code
when "TypeDependsOnUserIVs"
return pbHiddenPower(pkmn)[1]
when "TypeAndPowerDependOnUserBerry"
item_data = pkmn.item
if item_data
item_data.flags.each do |flag|
return [$~[1].to_i, 10].max if flag[/^NaturalGift_(?:\w+)_(\d+)$/i]
end
end
end
return 1
when "ThrowUserItemAtTarget"
item_data = pkmn.item
if item_data
item_data.flags.each do |flag|
return [$~[1].to_i, 10].max if flag[/^Fling_(\d+)$/i]
return 1
when "ThrowUserItemAtTarget"
item_data = pkmn.item
if item_data
item_data.flags.each do |flag|
return [$~[1].to_i, 10].max if flag[/^Fling_(\d+)$/i]
end
return 10
end
return 10
return 0
when "PowerHigherWithUserHP"
return [150 * pkmn.hp / pkmn.totalhp, 1].max
when "PowerLowerWithUserHP"
n = 48 * pkmn.hp / pkmn.totalhp
return 200 if n < 2
return 150 if n < 5
return 100 if n < 10
return 80 if n < 17
return 40 if n < 33
return 20
when "PowerHigherWithUserHappiness"
return [(pkmn.happiness * 2 / 5).floor, 1].max
when "PowerLowerWithUserHappiness"
return [((255 - pkmn.happiness) * 2 / 5).floor, 1].max
when "PowerHigherWithLessPP"
dmgs = [200, 80, 60, 50, 40]
ppLeft = [[(move&.pp || @total_pp) - 1, 0].max, dmgs.length - 1].min
return dmgs[ppLeft]
end
return 0
when "PowerHigherWithUserHP"
return [150 * pkmn.hp / pkmn.totalhp, 1].max
when "PowerLowerWithUserHP"
n = 48 * pkmn.hp / pkmn.totalhp
return 200 if n < 2
return 150 if n < 5
return 100 if n < 10
return 80 if n < 17
return 40 if n < 33
return 20
when "PowerHigherWithUserHappiness"
return [(pkmn.happiness * 2 / 5).floor, 1].max
when "PowerLowerWithUserHappiness"
return [((255 - pkmn.happiness) * 2 / 5).floor, 1].max
when "PowerHigherWithLessPP"
dmgs = [200, 80, 60, 50, 40]
ppLeft = [[(move&.pp || @total_pp) - 1, 0].max, dmgs.length - 1].min
return dmgs[ppLeft]
end
=end
return @power
end

View File

@@ -30,7 +30,7 @@ module GameData
"NamePlural" => [:real_name_plural, "s"],
"PortionName" => [:real_portion_name, "s"],
"PortionNamePlural" => [:real_portion_name_plural, "s"],
"Pocket" => [:pocket, "v"],
"Pocket" => [:pocket, "y", :BagPocket],
"Price" => [:price, "u"],
"SellPrice" => [:sell_price, "u"],
"BPPrice" => [:bp_price, "u"],
@@ -126,7 +126,7 @@ module GameData
@real_name_plural = hash[:real_name_plural] || "Unnamed"
@real_portion_name = hash[:real_portion_name]
@real_portion_name_plural = hash[:real_portion_name_plural]
@pocket = hash[:pocket] || 1
@pocket = hash[:pocket] || :None
@price = hash[:price] || 0
@sell_price = hash[:sell_price] || (@price / Settings::ITEM_SELL_PRICE_DIVISOR)
@bp_price = hash[:bp_price] || 1
@@ -146,6 +146,15 @@ module GameData
return pbGetMessageFromHash(MessageTypes::ITEM_NAMES, @real_name)
end
def display_name
ret = name
if is_machine?
machine = @move
ret = sprintf("%s %s", ret, GameData::Move.get(@move).name)
end
return ret
end
# @return [String] the translated plural version of the name of this item
def name_plural
return pbGetMessageFromHash(MessageTypes::ITEM_NAME_PLURALS, @real_name_plural)
@@ -168,6 +177,10 @@ module GameData
return pbGetMessageFromHash(MessageTypes::ITEM_DESCRIPTIONS, @real_description)
end
def bag_pocket
return GameData::BagPocket.get(@pocket).bag_pocket
end
def has_flag?(flag)
return @flags.any? { |f| f.downcase == flag.downcase }
end

View File

@@ -7,6 +7,7 @@ module GameData
attr_reader :real_name
attr_reader :outdoor_map
attr_reader :announce_location
attr_reader :location_sign
attr_reader :can_bicycle
attr_reader :always_bicycle
attr_reader :teleport_destination
@@ -37,6 +38,7 @@ module GameData
"Name" => [:real_name, "s"],
"Outdoor" => [:outdoor_map, "b"],
"ShowArea" => [:announce_location, "b"],
"LocationSign" => [:location_sign, "s"],
"Bicycle" => [:can_bicycle, "b"],
"BicycleAlways" => [:always_bicycle, "b"],
"HealingSpot" => [:teleport_destination, "vuu"],
@@ -68,6 +70,7 @@ module GameData
["Name", StringProperty, _INTL("The name of the map, as seen by the player. Can be different to the map's name as seen in RMXP.")],
["Outdoor", BooleanProperty, _INTL("If true, this map is an outdoor map and will be tinted according to time of day.")],
["ShowArea", BooleanProperty, _INTL("If true, the game will display the map's name upon entry.")],
["LocationSign", StringProperty, _INTL("Filename in 'Graphics/UI/Location/' to be used as the location sign.")],
["Bicycle", BooleanProperty, _INTL("If true, the bicycle can be used on this map.")],
["BicycleAlways", BooleanProperty, _INTL("If true, the bicycle will be mounted automatically on this map and cannot be dismounted.")],
["HealingSpot", MapCoordsProperty, _INTL("Map ID of this Pokémon Center's town, and X and Y coordinates of its entrance within that town.")],
@@ -98,6 +101,7 @@ module GameData
@real_name = hash[:real_name]
@outdoor_map = hash[:outdoor_map]
@announce_location = hash[:announce_location]
@location_sign = hash[:location_sign]
@can_bicycle = hash[:can_bicycle]
@always_bicycle = hash[:always_bicycle]
@teleport_destination = hash[:teleport_destination]

View File

@@ -785,17 +785,17 @@ class Battle
when :HarshSun
if !pbCheckGlobalAbility(:DESOLATELAND)
@field.weather = :None
pbDisplay("The harsh sunlight faded!")
pbDisplay(_INTL("The harsh sunlight faded!"))
end
when :HeavyRain
if !pbCheckGlobalAbility(:PRIMORDIALSEA)
@field.weather = :None
pbDisplay("The heavy rain has lifted!")
pbDisplay(_INTL("The heavy rain has lifted!"))
end
when :StrongWinds
if !pbCheckGlobalAbility(:DELTASTREAM)
@field.weather = :None
pbDisplay("The mysterious air current has dissipated!")
pbDisplay(_INTL("The mysterious air current has dissipated!"))
end
end
if @field.weather != oldWeather

View File

@@ -159,40 +159,38 @@ class Battle::Move
if battler.isSpecies?(:MORPEKO) || battler.effects[PBEffects::TransformSpecies] == :MORPEKO
return pbBaseType(battler)
end
=begin
when "TypeDependsOnUserPlate", "TypeDependsOnUserMemory",
"TypeDependsOnUserDrive", "TypeAndPowerDependOnUserBerry",
"TypeIsUserFirstType", "TypeAndPowerDependOnWeather",
"TypeAndPowerDependOnTerrain"
return pbBaseType(battler)
=end
return pbBaseType(battler) if Settings::SHOW_MODIFIED_MOVE_PROPERTIES
end
return @realMove.display_type(battler.pokemon)
end
def display_damage(battler)
=begin
case @function_code
when "TypeAndPowerDependOnUserBerry"
return pbNaturalGiftBaseDamage(battler.item_id)
when "TypeAndPowerDependOnWeather", "TypeAndPowerDependOnTerrain",
"PowerHigherWithUserHP", "PowerLowerWithUserHP",
"PowerHigherWithUserHappiness", "PowerLowerWithUserHappiness",
"PowerHigherWithUserPositiveStatStages", "PowerDependsOnUserStockpile"
return pbBaseType(@power, battler, nil)
def display_power(battler)
if Settings::SHOW_MODIFIED_MOVE_PROPERTIES
case @function_code
when "TypeAndPowerDependOnUserBerry"
return pbNaturalGiftBaseDamage(battler.item_id)
when "TypeAndPowerDependOnWeather", "TypeAndPowerDependOnTerrain",
"PowerHigherWithUserHP", "PowerLowerWithUserHP",
"PowerHigherWithUserHappiness", "PowerLowerWithUserHappiness",
"PowerHigherWithUserPositiveStatStages", "PowerDependsOnUserStockpile"
return pbBaseType(@power, battler, nil)
end
end
=end
return @realMove.display_damage(battler.pokemon)
return @realMove.display_power(battler.pokemon)
end
def display_category(battler)
=begin
case @function_code
when "CategoryDependsOnHigherDamageIgnoreTargetAbility"
pbOnStartUse(user, nil)
return @calcCategory
if Settings::SHOW_MODIFIED_MOVE_PROPERTIES
case @function_code
when "CategoryDependsOnHigherDamageIgnoreTargetAbility"
pbOnStartUse(user, nil)
return @calcCategory
end
end
=end
return @realMove.display_category(battler.pokemon)
end

View File

@@ -209,23 +209,21 @@ class Battle::Move
elsif target.effects[PBEffects::Endure]
target.damageState.endured = true
damage -= 1
elsif damage == target.totalhp
if target.hasActiveAbility?(:STURDY) && !target.beingMoldBroken?
target.damageState.sturdy = true
elsif target.hasActiveAbility?(:STURDY) && !target.beingMoldBroken? && target.hp == target.totalhp
target.damageState.sturdy = true
damage -= 1
elsif target.hasActiveItem?(:FOCUSSASH) && target.hp == target.totalhp
target.damageState.focusSash = true
damage -= 1
elsif target.hasActiveItem?(:FOCUSBAND) && @battle.pbRandom(100) < 10
target.damageState.focusBand = true
damage -= 1
elsif Settings::AFFECTION_EFFECTS && @battle.internalBattle &&
target.pbOwnedByPlayer? && !target.mega?
chance = [0, 0, 0, 10, 15, 25][target.affection_level]
if chance > 0 && @battle.pbRandom(100) < chance
target.damageState.affection_endured = true
damage -= 1
elsif target.hasActiveItem?(:FOCUSSASH) && target.hp == target.totalhp
target.damageState.focusSash = true
damage -= 1
elsif target.hasActiveItem?(:FOCUSBAND) && @battle.pbRandom(100) < 10
target.damageState.focusBand = true
damage -= 1
elsif Settings::AFFECTION_EFFECTS && @battle.internalBattle &&
target.pbOwnedByPlayer? && !target.mega?
chance = [0, 0, 0, 10, 15, 25][target.affection_level]
if chance > 0 && @battle.pbRandom(100) < chance
target.damageState.affection_endured = true
damage -= 1
end
end
end
end

View File

@@ -152,46 +152,33 @@ class Battle::Scene
partyStart, _partyEnd = @battle.pbTeamIndexRangeFromBattlerIndex(idxBattler)
modParty = @battle.pbPlayerDisplayParty(idxBattler)
# Start party screen
scene = PokemonParty_Scene.new
switchScreen = PokemonPartyScreen.new(scene, modParty)
msg = _INTL("Choose a Pokémon.")
msg = _INTL("Send which Pokémon to Boxes?") if mode == 1
switchScreen.pbStartScene(msg, @battle.pbNumPositions(0, 0))
# Loop while in party screen
loop do
# Select a Pokémon
scene.pbSetHelpText(msg)
idxParty = switchScreen.pbChoosePokemon
if idxParty < 0
next if !canCancel
break
end
party_mode = (mode == 1) ? :battle_choose_to_box : :battle_choose_pokemon
screen = UI::Party.new(modParty, mode: party_mode)
screen.choose_pokemon do |pkmn, party_index|
next canCancel if party_index < 0
# Choose a command for the selected Pokémon
cmdSwitch = -1
cmdBoxes = -1
cmdSummary = -1
commands = []
commands[cmdSwitch = commands.length] = _INTL("Switch In") if mode == 0 && modParty[idxParty].able? &&
(@battle.canSwitch || !canCancel)
commands[cmdBoxes = commands.length] = _INTL("Send to Boxes") if mode == 1
commands[cmdSummary = commands.length] = _INTL("Summary")
commands[commands.length] = _INTL("Cancel")
command = scene.pbShowCommands(_INTL("Do what with {1}?", modParty[idxParty].name), commands)
if (cmdSwitch >= 0 && command == cmdSwitch) || # Switch In
(cmdBoxes >= 0 && command == cmdBoxes) # Send to Boxes
idxPartyRet = -1
commands = {}
commands[:switch_in] = _INTL("Switch In") if mode == 0 && pkmn.able? &&
(@battle.canSwitch || !canCancel)
commands[:send_to_boxes] = _INTL("Send to Boxes") if mode == 1
commands[:summary] = _INTL("Summary")
commands[:cancel] = _INTL("Cancel")
choice = screen.show_menu(_INTL("Do what with {1}?", pkmn.name), commands)
next canCancel if choice.nil?
case choice
when :switch_in, :send_to_boxes
real_party_index = -1
partyPos.each_with_index do |pos, i|
next if pos != idxParty + partyStart
idxPartyRet = i
next if pos != party_index + partyStart
real_party_index = i
break
end
break if yield idxPartyRet, switchScreen
elsif cmdSummary >= 0 && command == cmdSummary # Summary
scene.pbSummary(idxParty, true)
next true if yield real_party_index, screen
when :summary
screen.perform_action(:summary)
end
next false
end
# Close party screen
switchScreen.pbEndScene
# Fade back into battle screen
pbFadeInAndShow(@sprites, visibleSprites)
end
@@ -212,128 +199,127 @@ class Battle::Scene
else
$bag.reset_last_selections
end
# Start Bag screen
itemScene = PokemonBag_Scene.new
itemScene.pbStartScene($bag, true,
proc { |item|
useType = GameData::Item.get(item).battle_use
next useType && useType > 0
}, false)
# Loop while in Bag screen
wasTargeting = false
loop do
# Select an item
item = itemScene.pbChooseItem
break if !item
# Choose a command for the selected item
item = GameData::Item.get(item)
itemName = item.name
useType = item.battle_use
cmdUse = -1
commands = []
commands[cmdUse = commands.length] = _INTL("Use") if useType && useType != 0
commands[commands.length] = _INTL("Cancel")
command = itemScene.pbShowCommands(_INTL("{1} is selected.", itemName), commands)
next unless cmdUse >= 0 && command == cmdUse # Use
# Use types:
# 0 = not usable in battle
# 1 = use on Pokémon (lots of items, Blue Flute)
# 2 = use on Pokémon's move (Ethers)
# 3 = use on battler (X items, Persim Berry, Red/Yellow Flutes)
# 4 = use on opposing battler (Poké Balls)
# 5 = use no target (Poké Doll, Guard Spec., Poké Flute, Launcher items)
case useType
when 1, 2, 3 # Use on Pokémon/Pokémon's move/battler
# Auto-choose the Pokémon/battler whose action is being decided if they
# are the only available Pokémon/battler to use the item on
# Start Bag screen
bag_screen = UI::Bag.new($bag, mode: :choose_item_in_battle)
bag_screen.set_filter_proc(proc { |itm|
use_type = GameData::Item.get(itm).battle_use
next use_type && use_type > 0
})
bag_screen.show_and_hide do
# Loop while in Bag screen
loop do
# Select an item
item = bag_screen.choose_item_core
break if !item
# Choose a command for the selected item
item = GameData::Item.get(item)
itemName = item.name
useType = item.battle_use
cmdUse = -1
commands = []
commands[cmdUse = commands.length] = _INTL("Use") if useType && useType != 0
commands[commands.length] = _INTL("Cancel")
command = bag_screen.show_menu(_INTL("{1} is selected.", itemName), commands)
next unless cmdUse >= 0 && command == cmdUse # Use
# Use types:
# 0 = not usable in battle
# 1 = use on Pokémon (lots of items, Blue Flute)
# 2 = use on Pokémon's move (Ethers)
# 3 = use on battler (X items, Persim Berry, Red/Yellow Flutes)
# 4 = use on opposing battler (Poké Balls)
# 5 = use no target (Poké Doll, Guard Spec., Poké Flute, Launcher items)
case useType
when 1 # Use on Pokémon
if @battle.pbTeamLengthFromBattlerIndex(idxBattler) == 1
if yield item.id, useType, @battle.battlers[idxBattler].pokemonIndex, -1, itemScene
break
else
next
when 1, 2, 3 # Use on Pokémon/Pokémon's move/battler
# Auto-choose the Pokémon/battler whose action is being decided if they
# are the only available Pokémon/battler to use the item on
case useType
when 1 # Use on Pokémon
if @battle.pbTeamLengthFromBattlerIndex(idxBattler) == 1
if yield item.id, useType, @battle.battlers[idxBattler].pokemonIndex, -1, bag_screen
break
else
next
end
end
when 3 # Use on battler
if @battle.pbPlayerBattlerCount == 1
if yield item.id, useType, @battle.battlers[idxBattler].pokemonIndex, -1, bag_screen
break
else
next
end
end
end
when 3 # Use on battler
if @battle.pbPlayerBattlerCount == 1
if yield item.id, useType, @battle.battlers[idxBattler].pokemonIndex, -1, itemScene
break
else
next
end
end
end
# Fade out and hide Bag screen
itemScene.pbFadeOutScene
# Get player's party
party = @battle.pbParty(idxBattler)
partyPos = @battle.pbPartyOrder(idxBattler)
partyStart, _partyEnd = @battle.pbTeamIndexRangeFromBattlerIndex(idxBattler)
modParty = @battle.pbPlayerDisplayParty(idxBattler)
# Start party screen
pkmnScene = PokemonParty_Scene.new
pkmnScreen = PokemonPartyScreen.new(pkmnScene, modParty)
pkmnScreen.pbStartScene(_INTL("Use on which Pokémon?"), @battle.pbNumPositions(0, 0))
idxParty = -1
# Loop while in party screen
loop do
# Select a Pokémon
pkmnScene.pbSetHelpText(_INTL("Use on which Pokémon?"))
idxParty = pkmnScreen.pbChoosePokemon
break if idxParty < 0
idxPartyRet = -1
partyPos.each_with_index do |pos, i|
next if pos != idxParty + partyStart
idxPartyRet = i
break
end
next if idxPartyRet < 0
pkmn = party[idxPartyRet]
next if !pkmn || pkmn.egg?
idxMove = -1
if useType == 2 # Use on Pokémon's move
idxMove = pkmnScreen.pbChooseMove(pkmn, _INTL("Restore which move?"))
next if idxMove < 0
end
break if yield item.id, useType, idxPartyRet, idxMove, pkmnScene
end
pkmnScene.pbEndScene
break if idxParty >= 0
# Cancelled choosing a Pokémon; show the Bag screen again
itemScene.pbFadeInScene
when 4 # Use on opposing battler (Poké Balls)
idxTarget = -1
if @battle.pbOpposingBattlerCount(idxBattler) == 1
@battle.allOtherSideBattlers(idxBattler).each { |b| idxTarget = b.index }
break if yield item.id, useType, idxTarget, -1, itemScene
else
wasTargeting = true
# Fade out and hide Bag screen
itemScene.pbFadeOutScene
# Fade in and show the battle screen, choosing a target
tempVisibleSprites = visibleSprites.clone
tempVisibleSprites["commandWindow"] = false
tempVisibleSprites["targetWindow"] = true
idxTarget = pbChooseTarget(idxBattler, GameData::Target.get(:Foe), tempVisibleSprites)
if idxTarget >= 0
break if yield item.id, useType, idxTarget, -1, self
bag_sprites_status = pbFadeOutAndHide(bag_screen.sprites)
# Get player's party
party = @battle.pbParty(idxBattler)
partyPos = @battle.pbPartyOrder(idxBattler)
partyStart, _partyEnd = @battle.pbTeamIndexRangeFromBattlerIndex(idxBattler)
modParty = @battle.pbPlayerDisplayParty(idxBattler)
# Start party screen
party_idx = -1
party_screen = UI::Party.new(modParty, mode: :battle_use_item)
party_screen.choose_pokemon do |pkmn, party_index|
party_idx = party_index
next true if party_index < 0
# Use the item on the selected Pokémon
real_party_index = -1
partyPos.each_with_index do |pos, i|
next if pos != party_index + partyStart
real_party_index = i
break
end
next false if real_party_index < 0
next false if !pkmn || pkmn.egg?
move_index = -1
if useType == 2 # Use on Pokémon's move
move_index = party_screen.choose_move(pkmn, _INTL("Restore which move?"))
next false if move_index < 0
end
if yield item.id, useType, real_party_index, move_index, party_screen
bag_screen.silent_end_screen
next true
end
party_idx = -1
next false
end
# Target invalid/cancelled choosing a target; show the Bag screen again
wasTargeting = false
pbFadeOutAndHide(@sprites)
itemScene.pbFadeInScene
break if party_idx >= 0 # Item was used; close the Bag screen
# Cancelled choosing a Pokémon; show the Bag screen again
pbFadeInAndShow(bag_screen.sprites, bag_sprites_status)
when 4 # Use on opposing battler (Poké Balls)
idxTarget = -1
if @battle.pbOpposingBattlerCount(idxBattler) == 1
@battle.allOtherSideBattlers(idxBattler).each { |b| idxTarget = b.index }
break if yield item.id, useType, idxTarget, -1, bag_screen
else
wasTargeting = true
# Fade out and hide Bag screen
bag_sprites_status = pbFadeOutAndHide(bag_screen.sprites)
# Fade in and show the battle screen, choosing a target
tempVisibleSprites = visibleSprites.clone
tempVisibleSprites["commandWindow"] = false
tempVisibleSprites["targetWindow"] = true
idxTarget = pbChooseTarget(idxBattler, GameData::Target.get(:Foe), tempVisibleSprites)
if idxTarget >= 0
break if yield item.id, useType, idxTarget, -1, self
end
# Target invalid/cancelled choosing a target; show the Bag screen again
wasTargeting = false
pbFadeOutAndHide(@sprites)
pbFadeInAndShow(bag_screen.sprites, bag_sprites_status)
end
when 5 # Use with no target
break if yield item.id, useType, idxBattler, -1, bag_screen
end
when 5 # Use with no target
break if yield item.id, useType, idxBattler, -1, itemScene
end
next true
end
@bagLastPocket = $bag.last_viewed_pocket
@bagChoices = $bag.last_pocket_selections.clone
$bag.last_viewed_pocket = oldLastPocket
$bag.last_pocket_selections = oldChoices
# Close Bag screen
itemScene.pbEndScene
# Fade back into battle screen (if not already showing it)
pbFadeInAndShow(@sprites, visibleSprites) if !wasTargeting
end
@@ -465,9 +451,8 @@ class Battle::Scene
def pbForgetMove(pkmn, moveToLearn)
ret = -1
pbFadeOutIn do
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene)
ret = screen.pbStartForgetScreen([pkmn], 0, moveToLearn)
screen = UI::PokemonSummary.new([pkmn], 0, mode: :choose_move, new_move: moveToLearn)
ret = screen.choose_move
end
return ret
end

View File

@@ -199,8 +199,6 @@ class Battle::Scene::FightMenu < Battle::Scene::MenuBase
attr_reader :battler
attr_reader :shiftMode
GET_MOVE_TEXT_COLOR_FROM_MOVE_BUTTON = true
# If true, displays graphics from Graphics/UI/Battle/overlay_fight.png
# and Graphics/UI/Battle/cursor_fight.png.
# If false, just displays text and the command window over the graphic
@@ -350,7 +348,7 @@ class Battle::Scene::FightMenu < Battle::Scene::MenuBase
x = button.x - self.x + (button.src_rect.width / 2)
y = button.y - self.y + 14
moveNameBase = TEXT_BASE_COLOR
if GET_MOVE_TEXT_COLOR_FROM_MOVE_BUTTON && moves[i].display_type(@battler)
if Settings::BATTLE_MOVE_NAME_COLOR_FROM_GRAPHIC && moves[i].display_type(@battler)
# NOTE: This takes a color from a particular pixel in the button
# graphic and makes the move name's base color that same color.
# The pixel is at coordinates 10,34 in the button box. If you

View File

@@ -24,7 +24,7 @@ class Battle::Peer
end
def pbGetStorageCreatorName
return pbGetStorageCreator if $player.seen_storage_creator
return UI::PC.pbGetStorageCreator if $player.seen_storage_creator
return nil
end

View File

@@ -63,9 +63,7 @@ module Battle::CatchAndStoreMixin
break
when 2 # See X's summary
pbFadeOutIn do
summary_scene = PokemonSummary_Scene.new
summary_screen = PokemonSummaryScreen.new(summary_scene, true)
summary_screen.pbStartScreen([pkmn], 0)
UI::PokemonSummary.new(pkmn, mode: :in_battle).main
end
when 3 # Check party
@scene.pbPartyScreen(0, true, 2)

View File

@@ -1,20 +1,98 @@
#===============================================================================
# Location signpost
# Location sign.
#===============================================================================
class LocationWindow
APPEAR_TIME = 0.4 # In seconds; is also the disappear time
LINGER_TIME = 1.6 # In seconds; time during which self is fully visible
def initialize(name)
def initialize(name, graphic_name = nil)
initialize_viewport
initialize_graphic(graphic_name)
initialize_text_window(name)
apply_style(graphic_name)
@current_map = $game_map.map_id
@timer_start = System.uptime
@delayed = !$game_temp.fly_destination.nil?
end
def initialize_viewport
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
end
def initialize_graphic(graphic_name)
return if graphic_name.nil? || !pbResolveBitmap("Graphics/UI/Location/#{graphic_name}")
@graphic = Sprite.new(@viewport)
@graphic.bitmap = RPG::Cache.ui("Location/#{graphic_name}")
@graphic.x = 0
@graphic.y = -@graphic.height
end
def initialize_text_window(name)
@window = Window_AdvancedTextPokemon.new(name)
@window.resizeToFit(name, Graphics.width)
@window.x = 0
@window.y = -@window.height
@window.viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@window.viewport.z = 99999
@currentmap = $game_map.map_id
@timer_start = System.uptime
@delayed = !$game_temp.fly_destination.nil?
@window.z = 1
@window.viewport = @viewport
end
def apply_style(graphic_name)
# Set up values to be used elsewhere
@graphic_offset = [0, 0]
@window_offset = [0, 0]
@y_distance = @window.height
return if graphic_name.nil?
# Determine the style and base/shadow colors
style = :none
base_color = nil
shadow_color = nil
Settings::LOCATION_SIGN_GRAPHIC_STYLES.each_pair do |val, filenames|
filenames.each do |filename|
if filename.is_a?(Array)
next if filename[0] != graphic_name
base_color = filename[1]
shadow_color = filename[2]
else
next if filename != graphic_name
end
style = val
break
end
break if style != :none
end
return if style == :none
# Apply the style
@y_distance = @graphic&.height || @window.height
@window.back_opacity = 0
case style
when :dp
@window.baseColor = base_color if base_color
@window.shadowColor = shadow_color if shadow_color
@window.text = @window.text # Because the text colors were changed
@window_offset = [8, -10]
@graphic&.dispose
@graphic = Window_AdvancedTextPokemon.new("")
@graphic.setSkin("Graphics/UI/Location/#{graphic_name}")
@graphic.width = @window.width + (@window_offset[0] * 2) - 4
@graphic.height = 48
@graphic.x = 0
@graphic.y = -@graphic.height
@graphic.z = 0
@graphic.viewport = @viewport
@y_distance = @graphic.height
when :hgss
@window.baseColor = base_color if base_color
@window.shadowColor = shadow_color if shadow_color
@window.width = @graphic.width
@window.text = "<ac>" + @window.text
when :platinum
@window.baseColor = base_color || Color.black
@window.shadowColor = shadow_color || Color.new(144, 144, 160)
@window.text = @window.text # Because the text colors were changed
@window_offset = [10, 16]
end
@window.x = @window_offset[0]
end
def disposed?
@@ -22,25 +100,32 @@ class LocationWindow
end
def dispose
@graphic&.dispose
@window.dispose
@viewport.dispose
end
def update
return if @window.disposed? || $game_temp.fly_destination
return if disposed? || $game_temp.fly_destination
if @delayed
@timer_start = System.uptime
@delayed = false
end
@graphic&.update
@window.update
if $game_temp.message_window_showing || @currentmap != $game_map.map_id
@window.dispose
if $game_temp.message_window_showing || @current_map != $game_map.map_id
dispose
return
end
if System.uptime - @timer_start >= APPEAR_TIME + LINGER_TIME
@window.y = lerp(0, -@window.height, APPEAR_TIME, @timer_start + APPEAR_TIME + LINGER_TIME, System.uptime)
@window.dispose if @window.y + @window.height <= 0
y_pos = lerp(0, -@y_distance, APPEAR_TIME, @timer_start + APPEAR_TIME + LINGER_TIME, System.uptime)
@window.y = y_pos + @window_offset[1]
@graphic&.y = y_pos + @graphic_offset[1]
dispose if y_pos <= -@y_distance
else
@window.y = lerp(-@window.height, 0, APPEAR_TIME, @timer_start, System.uptime)
y_pos = lerp(-@y_distance, 0, APPEAR_TIME, @timer_start, System.uptime)
@window.y = y_pos + @window_offset[1]
@graphic&.y = y_pos + @graphic_offset[1]
end
end
end

View File

@@ -319,23 +319,27 @@ EventHandlers.add(:on_map_or_spriteset_change, :show_darkness,
}
)
# Show location signpost.
EventHandlers.add(:on_map_or_spriteset_change, :show_location_window,
# Show location sign.
EventHandlers.add(:on_map_or_spriteset_change, :show_location_sign,
proc { |scene, map_changed|
next if !scene || !scene.spriteset
next if !map_changed || !$game_map.metadata&.announce_location
nosignpost = false
no_sign = false
if $PokemonGlobal.mapTrail[1]
(Settings::NO_SIGNPOSTS.length / 2).times do |i|
nosignpost = true if Settings::NO_SIGNPOSTS[2 * i] == $PokemonGlobal.mapTrail[1] &&
Settings::NO_SIGNPOSTS[(2 * i) + 1] == $game_map.map_id
nosignpost = true if Settings::NO_SIGNPOSTS[(2 * i) + 1] == $PokemonGlobal.mapTrail[1] &&
Settings::NO_SIGNPOSTS[2 * i] == $game_map.map_id
break if nosignpost
(Settings::NO_LOCATION_SIGNS.length / 2).times do |i|
no_sign = true if Settings::NO_LOCATION_SIGNS[2 * i] == $PokemonGlobal.mapTrail[1] &&
Settings::NO_LOCATION_SIGNS[(2 * i) + 1] == $game_map.map_id
no_sign = true if Settings::NO_LOCATION_SIGNS[(2 * i) + 1] == $PokemonGlobal.mapTrail[1] &&
Settings::NO_LOCATION_SIGNS[2 * i] == $game_map.map_id
break if no_sign
end
nosignpost = true if $game_map.name == pbGetMapNameFromId($PokemonGlobal.mapTrail[1])
no_sign = true if $game_map.name == pbGetMapNameFromId($PokemonGlobal.mapTrail[1])
end
scene.spriteset.addUserSprite(LocationWindow.new($game_map.name)) if !nosignpost
next if no_sign
map_name = $game_map.name
location_sign_graphic = $game_map.metadata&.location_sign || Settings::DEFAULT_LOCATION_SIGN_GRAPHIC
location_sign_graphic = Settings::DEFAULT_LOCATION_SIGN_GRAPHIC
scene.spriteset.addUserSprite(LocationWindow.new(map_name, location_sign_graphic))
}
)
@@ -684,7 +688,7 @@ def pbItemBall(item, quantity = 1)
item = GameData::Item.get(item)
return false if !item || quantity < 1
itemname = (quantity > 1) ? item.portion_name_plural : item.portion_name
pocket = item.pocket
pocket = item.bag_pocket
move = item.move
if $bag.add(item, quantity) # If item can be picked up
meName = (item.is_key_item?) ? "Key item get" : "Item get"
@@ -706,7 +710,7 @@ def pbItemBall(item, quantity = 1)
pbMessage("\\me[#{meName}]" + _INTL("You found a \\c[1]{1}\\c[0]!", itemname) + "\\wtnp[40]")
end
pbMessage(_INTL("You put the {1} in\nyour Bag's <icon=bagPocket{2}>\\c[1]{3}\\c[0] pocket.",
itemname, pocket, PokemonBag.pocket_names[pocket - 1]))
itemname, pocket, GameData::BagPocket.get(pocket).name))
return true
end
# Can't add the item
@@ -734,7 +738,7 @@ def pbReceiveItem(item, quantity = 1)
item = GameData::Item.get(item)
return false if !item || quantity < 1
itemname = (quantity > 1) ? item.portion_name_plural : item.portion_name
pocket = item.pocket
pocket = item.bag_pocket
move = item.move
meName = (item.is_key_item?) ? "Key item get" : "Item get"
if item == :DNASPLICERS
@@ -756,7 +760,7 @@ def pbReceiveItem(item, quantity = 1)
end
if $bag.add(item, quantity) # If item can be added
pbMessage(_INTL("You put the {1} in\nyour Bag's <icon=bagPocket{2}>\\c[1]{3}\\c[0] pocket.",
itemname, pocket, PokemonBag.pocket_names[pocket - 1]))
itemname, pocket, GameData::BagPocket.get(pocket).name))
return true
end
return false # Can't add the item
@@ -769,9 +773,9 @@ def pbBuyPrize(item, quantity = 1)
item = GameData::Item.get(item)
return false if !item || quantity < 1
item_name = (quantity > 1) ? item.portion_name_plural : item.portion_name
pocket = item.pocket
pocket = item.bag_pocket
return false if !$bag.add(item, quantity)
pbMessage("\\CN" + _INTL("You put the {1} in\nyour Bag's <icon=bagPocket{2}>\\c[1]{3}\\c[0] pocket.",
item_name, pocket, PokemonBag.pocket_names[pocket - 1]))
item_name, pocket, GameData::BagPocket.get(pocket).name))
return true
end

View File

@@ -17,6 +17,15 @@ end
#===============================================================================
# Making roaming Pokémon roam around.
#===============================================================================
def each_active_roamer(ignore_caught = true)
Settings::ROAMING_SPECIES.each_with_index do |roamer, i|
next if !GameData::Species.exists?(roamer[:species])
next if roamer[:game_switch] && roamer[:game_switch] > 0 && !$game_switches[roamer[:game_switch]]
next if ignore_caught && $PokemonGlobal.roamPokemon[i] == true # Has been caught
yield roamer, i
end
end
# Resets all roaming Pokemon that were defeated without having been caught.
def pbResetAllRoamers
return if !$PokemonGlobal.roamPokemon
@@ -30,7 +39,7 @@ end
def pbRoamingAreas(idxRoamer)
# [species ID, level, Game Switch, encounter type, battle BGM, area maps hash]
roamData = Settings::ROAMING_SPECIES[idxRoamer]
return roamData[5] if roamData && roamData[5]
return roamData[:areas] if roamData && roamData[:areas]
return Settings::ROAMING_AREAS
end
@@ -47,8 +56,8 @@ def pbRoamPokemon
# Start all roamers off in random maps
if !$PokemonGlobal.roamPosition
$PokemonGlobal.roamPosition = {}
Settings::ROAMING_SPECIES.length.times do |i|
next if !GameData::Species.exists?(Settings::ROAMING_SPECIES[i][0])
Settings::ROAMING_SPECIES.each_with_index do |roamer, i|
next if !GameData::Species.exists?(roamer[:species])
keys = pbRoamingAreas(i).keys
$PokemonGlobal.roamPosition[i] = keys[rand(keys.length)]
end
@@ -62,10 +71,9 @@ end
# Makes a single roaming Pokémon roam to another map. Doesn't roam if it isn't
# currently possible to encounter it (i.e. its Game Switch is off).
def pbRoamPokemonOne(idxRoamer)
# [species ID, level, Game Switch, encounter type, battle BGM, area maps hash]
roamData = Settings::ROAMING_SPECIES[idxRoamer]
return if roamData[2] > 0 && !$game_switches[roamData[2]] # Game Switch is off
return if !GameData::Species.exists?(roamData[0])
roamer = Settings::ROAMING_SPECIES[idxRoamer]
return if !GameData::Species.exists?(roamer[:species])
return if roamer[:game_switch] && roamer[:game_switch] > 0 && !$game_switches[roamer[:game_switch]]
# Get hash of area patrolled by the roaming Pokémon
mapIDs = pbRoamingAreas(idxRoamer).keys
return if !mapIDs || mapIDs.length == 0 # No roaming area defined somehow
@@ -81,10 +89,10 @@ def pbRoamPokemonOne(idxRoamer)
return if !nextMaps
nextMaps.each { |map| newMapChoices.push(map) }
# Rarely, add a random possible map into the mix
newMapChoices.push(mapIDs[rand(mapIDs.length)]) if rand(32) == 0
newMapChoices.push(mapIDs.sample) if rand(32) == 0
# Choose a random new map to roam to
if newMapChoices.length > 0
$PokemonGlobal.roamPosition[idxRoamer] = newMapChoices[rand(newMapChoices.length)]
$PokemonGlobal.roamPosition[idxRoamer] = newMapChoices.sample
end
end
@@ -118,16 +126,16 @@ def pbRoamingMethodAllowed(roamer_method)
enc_type = $PokemonEncounters.encounter_type
type = GameData::EncounterType.get(enc_type).type
case roamer_method
when 0 # Any step-triggered method (except Bug Contest)
when :all # Any step-triggered method (except Bug Contest)
return [:land, :cave, :water].include?(type)
when 1 # Walking (except Bug Contest)
when :land # Walking (except Bug Contest)
return [:land, :cave].include?(type)
when 2 # Surfing
return type == :water
when 3 # Fishing
return type == :fishing
when 4 # Water-based
when :water # Surfing or rishing
return [:water, :fishing].include?(type)
when :surfing # Surfing
return type == :water
when :fishing # Fishing
return type == :fishing
end
return false
end
@@ -146,11 +154,7 @@ EventHandlers.add(:on_wild_species_chosen, :roaming_pokemon,
currentRegion = pbGetCurrentRegion
currentMapName = $game_map.name
possible_roamers = []
Settings::ROAMING_SPECIES.each_with_index do |data, i|
# data = [species, level, Game Switch, roamer method, battle BGM, area maps hash]
next if !GameData::Species.exists?(data[0])
next if data[2] > 0 && !$game_switches[data[2]] # Isn't roaming
next if $PokemonGlobal.roamPokemon[i] == true # Roaming Pokémon has been caught
each_active_roamer do |roamer, i|
# Get the roamer's current map
roamerMap = $PokemonGlobal.roamPosition[i]
if !roamerMap
@@ -168,9 +172,9 @@ EventHandlers.add(:on_wild_species_chosen, :roaming_pokemon,
next if pbGetMapNameFromId(roamerMap) != currentMapName
end
# Check whether the roamer's roamer method is currently possible
next if !pbRoamingMethodAllowed(data[3])
next if !pbRoamingMethodAllowed(roamer[:encounter_type])
# Add this roaming Pokémon to the list of possible roaming Pokémon to encounter
possible_roamers.push([i, data[0], data[1], data[4]]) # [i, species, level, BGM]
possible_roamers.push([i, roamer[:species], roamer[:level], roamer[:bgm]])
end
# No encounterable roaming Pokémon were found, just have the regular encounter
next if possible_roamers.length == 0

View File

@@ -23,6 +23,8 @@ class PokemonGlobalMetadata
attr_accessor :pokedexDex # Dex currently looking at (-1 is National Dex)
attr_accessor :pokedexIndex # Last species viewed per Dex
attr_accessor :pokedexMode # Search mode
# Town Map
attr_accessor :townMapMarkings
# Day Care
attr_accessor :day_care
# Special battle modes
@@ -78,6 +80,8 @@ class PokemonGlobalMetadata
(numRegions + 1).times do |i| # National Dex isn't a region, but is included
@pokedexIndex[i] = 0
end
# Town Map
@townMapMarkings = []
# Day Care
@day_care = DayCare.new
# Special battle modes

View File

@@ -14,6 +14,11 @@ module HiddenMoveHandlers
return !CanUseMove[item].nil? && !UseMove[item].nil?
end
def self.eachHandler
ret = CanUseMove.keys & UseMove.keys
ret.each { |key| yield key }
end
# Returns whether move can be used
def self.triggerCanUseMove(item, pokemon, showmsg)
return false if !CanUseMove[item]

View File

@@ -382,9 +382,9 @@ def pbBerryPlant
when 0 # Fertilize
mulch = nil
pbFadeOutIn do
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene, $bag)
mulch = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).is_mulch? })
bag_screen = UI::Bag.new($bag, mode: :choose_item)
bag_screen.set_filter_proc(proc { |item| GameData::Item.get(item).is_mulch? })
mulch = bag_screen.choose_item
end
return if !mulch
mulch_data = GameData::Item.get(mulch)
@@ -409,9 +409,9 @@ def pbBerryPlant
end
if !ask_to_plant || pbConfirmMessage(_INTL("Want to plant a Berry?"))
pbFadeOutIn do
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene, $bag)
berry = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).is_berry? })
bag_screen = UI::Bag.new($bag, mode: :choose_item)
bag_screen.set_filter_proc(proc { |item| GameData::Item.get(item).is_berry? })
berry = bag_screen.choose_item
end
if berry
$stats.berries_planted += 1
@@ -457,9 +457,9 @@ def pbPickBerry(berry, qty = 1)
else
pbMessage("\\me[Berry get]" + _INTL("You picked the \\c[1]{1}\\c[0].", berry_name) + "\\wtnp[30]")
end
pocket = berry.pocket
pocket = berry.bag_pocket
pbMessage(_INTL("You put the {1} in\nyour Bag's <icon=bagPocket{2}>\\c[1]{3}\\c[0] pocket.",
berry_name, pocket, PokemonBag.pocket_names[pocket - 1]) + "\1")
berry_name, pocket, GameData::BagPocket.get(pocket).name) + "\1")
if Settings::NEW_BERRY_PLANTS
pbMessage(_INTL("The soil returned to its soft and earthy state."))
else

View File

@@ -6,6 +6,7 @@ module ItemHandlers
UseFromBag = ItemHandlerHash.new
ConfirmUseInField = ItemHandlerHash.new
UseInField = ItemHandlerHash.new
UsableOnPokemon = ItemHandlerHash.new
UseOnPokemon = ItemHandlerHash.new
UseOnPokemonMaximum = ItemHandlerHash.new
CanUseInBattle = ItemHandlerHash.new
@@ -29,6 +30,10 @@ module ItemHandlers
return !UseInField[item].nil?
end
def hasUsableOnPokemon(item)
return !UsableOnPokemon[item].nil?
end
def hasUseOnPokemon(item)
return !UseOnPokemon[item].nil?
end
@@ -58,8 +63,8 @@ module ItemHandlers
# 0 - Item not used
# 1 - Item used, don't end screen
# 2 - Item used, end screen
def triggerUseFromBag(item)
return UseFromBag.trigger(item) if UseFromBag[item]
def triggerUseFromBag(item, bag_screen = nil)
return UseFromBag.trigger(item, bag_screen) if UseFromBag[item]
# No UseFromBag handler exists; check the UseInField handler if present
if UseInField[item]
return (UseInField.trigger(item)) ? 1 : 0
@@ -82,6 +87,12 @@ module ItemHandlers
return (UseInField.trigger(item)) ? 1 : 0
end
# Returns whether item will have an effect if used on pkmn.
def triggerUsableOnPokemon(item, pkmn)
return false if !UsableOnPokemon[item]
return UsableOnPokemon.trigger(item, pkmn)
end
# Returns whether item was used.
def triggerUseOnPokemon(item, qty, pkmn, scene)
return false if !UseOnPokemon[item]
@@ -120,91 +131,6 @@ end
#===============================================================================
#
#===============================================================================
def pbCanRegisterItem?(item)
return ItemHandlers.hasUseInFieldHandler(item)
end
def pbCanUseOnPokemon?(item)
return ItemHandlers.hasUseOnPokemon(item) || GameData::Item.get(item).is_machine?
end
#===============================================================================
# Change a Pokémon's level.
#===============================================================================
def pbChangeLevel(pkmn, new_level, scene)
new_level = new_level.clamp(1, GameData::GrowthRate.max_level)
if pkmn.level == new_level
if scene.is_a?(PokemonPartyScreen)
scene.pbDisplay(_INTL("{1}'s level remained unchanged.", pkmn.name))
else
pbMessage(_INTL("{1}'s level remained unchanged.", pkmn.name))
end
return
end
old_level = pkmn.level
old_total_hp = pkmn.totalhp
old_attack = pkmn.attack
old_defense = pkmn.defense
old_special_attack = pkmn.spatk
old_special_defense = pkmn.spdef
old_speed = pkmn.speed
pkmn.level = new_level
pkmn.calc_stats
pkmn.hp = 1 if new_level > old_level && pkmn.species_data.base_stats[:HP] == 1
scene.pbRefresh
if old_level > new_level
if scene.is_a?(PokemonPartyScreen)
scene.pbDisplay(_INTL("{1} dropped to Lv. {2}!", pkmn.name, pkmn.level))
else
pbMessage(_INTL("{1} dropped to Lv. {2}!", pkmn.name, pkmn.level))
end
total_hp_diff = pkmn.totalhp - old_total_hp
attack_diff = pkmn.attack - old_attack
defense_diff = pkmn.defense - old_defense
special_attack_diff = pkmn.spatk - old_special_attack
special_defense_diff = pkmn.spdef - old_special_defense
speed_diff = pkmn.speed - old_speed
pbTopRightWindow(_INTL("Max. HP<r>{1}\nAttack<r>{2}\nDefense<r>{3}\nSp. Atk<r>{4}\nSp. Def<r>{5}\nSpeed<r>{6}",
total_hp_diff, attack_diff, defense_diff, special_attack_diff, special_defense_diff, speed_diff), scene)
pbTopRightWindow(_INTL("Max. HP<r>{1}\nAttack<r>{2}\nDefense<r>{3}\nSp. Atk<r>{4}\nSp. Def<r>{5}\nSpeed<r>{6}",
pkmn.totalhp, pkmn.attack, pkmn.defense, pkmn.spatk, pkmn.spdef, pkmn.speed), scene)
else
pkmn.changeHappiness("vitamin")
if scene.is_a?(PokemonPartyScreen)
scene.pbDisplay(_INTL("{1} grew to Lv. {2}!", pkmn.name, pkmn.level))
else
pbMessage(_INTL("{1} grew to Lv. {2}!", pkmn.name, pkmn.level))
end
total_hp_diff = pkmn.totalhp - old_total_hp
attack_diff = pkmn.attack - old_attack
defense_diff = pkmn.defense - old_defense
special_attack_diff = pkmn.spatk - old_special_attack
special_defense_diff = pkmn.spdef - old_special_defense
speed_diff = pkmn.speed - old_speed
pbTopRightWindow(_INTL("Max. HP<r>+{1}\nAttack<r>+{2}\nDefense<r>+{3}\nSp. Atk<r>+{4}\nSp. Def<r>+{5}\nSpeed<r>+{6}",
total_hp_diff, attack_diff, defense_diff, special_attack_diff, special_defense_diff, speed_diff), scene)
pbTopRightWindow(_INTL("Max. HP<r>{1}\nAttack<r>{2}\nDefense<r>{3}\nSp. Atk<r>{4}\nSp. Def<r>{5}\nSpeed<r>{6}",
pkmn.totalhp, pkmn.attack, pkmn.defense, pkmn.spatk, pkmn.spdef, pkmn.speed), scene)
# Learn new moves upon level up
movelist = pkmn.getMoveList
movelist.each do |i|
next if i[0] <= old_level || i[0] > pkmn.level
pbLearnMove(pkmn, i[1], true) { scene.pbUpdate }
end
# Check for evolution
new_species = pkmn.check_evolution_on_level_up
if new_species
pbFadeOutInWithMusic do
evo = PokemonEvolutionScene.new
evo.pbStartScreen(pkmn, new_species)
evo.pbEvolution
evo.pbEndScreen
scene.pbRefresh if scene.is_a?(PokemonPartyScreen)
end
end
end
end
def pbTopRightWindow(text, scene = nil)
window = Window_AdvancedTextPokemon.new(text)
window.width = 198
@@ -222,13 +148,301 @@ def pbTopRightWindow(text, scene = nil)
window.dispose
end
def pbChangeExp(pkmn, new_exp, scene)
new_exp = new_exp.clamp(0, pkmn.growth_rate.maximum_exp)
if pkmn.exp == new_exp
if scene.is_a?(PokemonPartyScreen)
scene.pbDisplay(_INTL("{1}'s Exp. Points remained unchanged.", pkmn.name))
#===============================================================================
#
#===============================================================================
def pbCanRegisterItem?(item)
return ItemHandlers.hasUseInFieldHandler(item)
end
# Returns whether pkmn is able to have an item used on it.
def pbCanPokemonHaveItemUsedOnIt?(pkmn, item)
return pkmn && !pkmn.egg? && (!pkmn.hyper_mode || GameData::Item.get(item)&.is_scent?)
end
# Used to filter the Bag when choosing an item to use on a party Pokémon.
# Also used in the Bag to indicate which party Pokémon the selected item is
# usable on.
def pbCanUseItemOnPokemon?(item)
return ItemHandlers.hasUseOnPokemon(item) ||
ItemHandlers.hasUsableOnPokemon(item) ||
GameData::Item.get(item).is_machine?
end
# This method assumes the item is usable on a Pokémon. It returns whether the
# item will have an effect when used on pkmn, i.e. it won't have no effect.
# Used in the Bag to indicate which party Pokémon the selected item is usable
# on.
def pbItemHasEffectOnPokemon?(item, pkmn)
return false if !pbCanPokemonHaveItemUsedOnIt?(pkmn, item)
ret = ItemHandlers.triggerUsableOnPokemon(item, pkmn)
return ret
end
#===============================================================================
# Use an item from the Bag and/or on a Pokémon.
#===============================================================================
# Called from the Bag screen and also when prompted to use a Repel when one runs
# out (bag_screen will be nil for the latter).
# @return [Integer] 0 = item wasn't used; 1 = item used; 2 = close Bag to use in field
def pbUseItem(bag, item, bag_screen = nil)
item_data = GameData::Item.get(item)
useType = item_data.field_use
if useType == 1 # Item is usable on a Pokémon
if $player.pokemon_count == 0
pbMessage(_INTL("There is no Pokémon."))
return 0
end
ret = false
annot = nil
if item_data.is_evolution_stone?
annot = []
$player.party.each do |pkmn|
elig = pkmn.check_evolution_on_use_item(item)
annot.push((elig) ? _INTL("ABLE") : _INTL("NOT ABLE"))
end
end
pbFadeOutIn do
screen = UI::Party.new($player.party, mode: :use_item)
if item_data.is_evolution_stone?
screen.set_able_annotation_proc(proc { |pkmn| next pkmn.check_evolution_on_use_item(item) })
end
screen.choose_pokemon do |pkmn, party_index|
next true if party_index < 0
next false if !pbCanPokemonHaveItemUsedOnIt?(pkmn, item)
qty = 1
max_at_once = ItemHandlers.triggerUseOnPokemonMaximum(item, pkmn)
max_at_once = [max_at_once, bag.quantity(item)].min
if max_at_once > 1
pbPlayDecisionSE
qty = screen.choose_number(
_INTL("How many {1} do you want to use?", GameData::Item.get(item).portion_name_plural), max_at_once
)
screen.set_help_text("")
end
next false if qty <= 0
ret = ItemHandlers.triggerUseOnPokemon(item, qty, pkmn, screen)
if ret && item_data.consumed_after_use?
bag.remove(item, qty)
if !bag.has?(item)
screen.show_message(_INTL("You used your last {1}.", item_data.portion_name))
next true
end
end
next false
end
bag_screen&.pbRefresh
end
return (ret) ? 1 : 0
elsif useType == 2 || item_data.is_machine? # Item is usable from Bag or teaches a move
intret = ItemHandlers.triggerUseFromBag(item, bag_screen)
if intret >= 0
bag.remove(item) if intret == 1 && item_data.consumed_after_use?
return intret
end
pbMessage(_INTL("Can't use that here."))
return 0
end
pbMessage(_INTL("Can't use that here."))
return 0
end
# Only called when in the party screen and having chosen an item to be used on
# the selected Pokémon. screen is the party screen.
def pbUseItemOnPokemon(item, pkmn, screen)
item_data = GameData::Item.get(item)
# TM or HM
if item_data.is_machine?
move = item_data.move
return false if !move
move_name = GameData::Move.get(move).name
if pkmn.shadowPokemon?
screen.show_message(_INTL("Shadow Pokémon can't be taught any moves."))
elsif !pkmn.compatible_with_move?(move)
screen.show_message(_INTL("{1} can't learn {2}.", pkmn.name, move_name))
else
pbMessage(_INTL("{1}'s Exp. Points remained unchanged.", pkmn.name))
pbSEPlay("PC access")
screen.show_message(_INTL("You booted up the {1}.", item_data.portion_name) + "\1")
if screen.show_confirm_message(_INTL("Do you want to teach {1} to {2}?", move_name, pkmn.name))
if pbLearnMove(pkmn, move, false, true) { screen.update }
$bag.remove(item) if item_data.consumed_after_use?
return true
end
end
end
return false
end
# Other item
qty = 1
max_at_once = ItemHandlers.triggerUseOnPokemonMaximum(item, pkmn)
max_at_once = [max_at_once, $bag.quantity(item)].min
if max_at_once > 1
qty = screen.choose_number(
_INTL("How many {1} do you want to use?", item_data.portion_name_plural), max_at_once
)
screen.set_help_text("")
end
return false if qty <= 0
ret = ItemHandlers.triggerUseOnPokemon(item, qty, pkmn, screen)
screen.clear_annotations
screen.refresh
if ret && item_data.consumed_after_use?
$bag.remove(item, qty)
if !$bag.has?(item)
screen.show_message(_INTL("You used your last {1}.", item_data.portion_name))
end
end
return ret
end
def pbUseKeyItemInField(item)
ret = ItemHandlers.triggerUseInField(item)
if ret == -1 # Item effect not found
pbMessage(_INTL("Can't use that here."))
elsif ret > 0 && GameData::Item.get(item).consumed_after_use?
$bag.remove(item)
end
return ret > 0
end
def pbUseItemMessage(item)
itemname = GameData::Item.get(item).portion_name
if itemname.starts_with_vowel?
pbMessage(_INTL("You used an {1}.", itemname))
else
pbMessage(_INTL("You used a {1}.", itemname))
end
end
#===============================================================================
# Give an item to a Pokémon to hold, and take a held item from a Pokémon.
#===============================================================================
# screen is either the party screen or the summary screen.
def pbGiveItemToPokemon(item, pkmn, screen, pkmnid = 0)
return false if item.nil?
# Check if the Pokémon can hold the item, or have its item removed if it's
# already holding one
if pkmn.egg?
screen.show_message(_INTL("Eggs can't hold items."))
return false
elsif pkmn.mail
screen.show_message(_INTL("{1}'s mail must be removed before giving it an item.", pkmn.name))
return false if !pbTakeItemFromPokemon(pkmn, screen)
end
new_item_name = GameData::Item.get(item).portion_name
if pkmn.hasItem?
# Swap existing held item with the new item
old_item_name = pkmn.item.portion_name
if old_item_name.starts_with_vowel?
screen.show_message(_INTL("{1} is already holding an {2}.", pkmn.name, old_item_name) + "\1")
else
screen.show_message(_INTL("{1} is already holding a {2}.", pkmn.name, old_item_name) + "\1")
end
if screen.show_confirm_message(_INTL("Would you like to switch the two items?"))
$bag.remove(item)
if !$bag.add(pkmn.item)
raise _INTL("Couldn't re-store deleted item in Bag somehow") if !$bag.add(item)
screen.show_message(_INTL("The Bag is full. The Pokémon's item could not be removed."))
elsif GameData::Item.get(item).is_mail?
if pbWriteMail(item, pkmn, pkmnid, screen)
pkmn.item = item
screen.show_message(_INTL("Took the {1} from {2} and gave it the {3}.", old_item_name, pkmn.name, new_item_name))
return true
elsif !$bag.add(item)
raise _INTL("Couldn't re-store deleted item in Bag somehow")
end
else
pkmn.item = item
screen.show_message(_INTL("Took the {1} from {2} and gave it the {3}.", old_item_name, pkmn.name, new_item_name))
return true
end
end
elsif !GameData::Item.get(item).is_mail? || pbWriteMail(item, pkmn, pkmnid, screen)
# Give the new item
$bag.remove(item)
pkmn.item = item
screen.show_message(_INTL("{1} is now holding the {2}.", pkmn.name, new_item_name))
return true
end
return false
end
# screen is either the party screen or the summary screen.
def pbTakeItemFromPokemon(pkmn, screen)
ret = false
# Check if the Pokémon has an item to remove, and whether the item can be put
# in the Bag
if !pkmn.hasItem?
screen.show_message(_INTL("{1} isn't holding anything.", pkmn.name))
return false
elsif !$bag.can_add?(pkmn.item)
screen.show_message(_INTL("The Bag is full. The Pokémon's item could not be removed."))
return false
end
if pkmn.mail
# Remove a mail item
if screen.show_confirm_message(_INTL("Save the removed mail in your PC?"))
if pbMoveToMailbox(pkmn)
pkmn.item = nil
screen.show_message(_INTL("The mail was saved in your PC."))
ret = true
else
screen.show_message(_INTL("Your PC's Mailbox is full."))
end
elsif screen.show_confirm_message(_INTL("If the mail is removed, its message will be lost. OK?"))
item_name = pkmn.item.portion_name
$bag.add(pkmn.item)
pkmn.item = nil
screen.show_message(_INTL("Received the {1} from {2}.", item_name, pkmn.name))
ret = true
end
else
# Remove a regular item
item_name = pkmn.item.portion_name
$bag.add(pkmn.item)
pkmn.item = nil
screen.show_message(_INTL("Received the {1} from {2}.", item_name, pkmn.name))
ret = true
end
return ret
end
#===============================================================================
# Choose an item from a given list. Only lets you choose an item you have at
# least 1 of in the Bag. The chosen item's ID is stored in the given Game
# Variable.
#===============================================================================
def pbChooseItemFromList(message, variable, *args)
commands = {}
args.each do |item|
item_data = GameData::Item.try_get(item)
next if !item_data || !$bag.has?(item_data.id)
commands[item_data.id] = item_data.name
end
if commands.length == 0
$game_variables[variable] = :NONE
return nil
end
commands[:NONE] = _INTL("Cancel")
ret = pbMessage(message, commands.values, -1)
if ret < 0 || ret >= commands.length - 1
$game_variables[variable] = :NONE
return nil
end
$game_variables[variable] = commands.keys[ret] || :NONE
return commands.keys[ret]
end
#===============================================================================
# Change a Pokémon's level.
#===============================================================================
def pbChangeLevel(pkmn, new_level, scene)
new_level = new_level.clamp(1, GameData::GrowthRate.max_level)
if pkmn.level == new_level
if scene.is_a?(UI::Party)
scene.show_message(_INTL("{1}'s level remained unchanged.", pkmn.name))
else
pbMessage(_INTL("{1}'s level remained unchanged.", pkmn.name))
end
return
end
@@ -239,20 +453,13 @@ def pbChangeExp(pkmn, new_exp, scene)
old_special_attack = pkmn.spatk
old_special_defense = pkmn.spdef
old_speed = pkmn.speed
if pkmn.exp > new_exp # Loses Exp
difference = pkmn.exp - new_exp
if scene.is_a?(PokemonPartyScreen)
scene.pbDisplay(_INTL("{1} lost {2} Exp. Points!", pkmn.name, difference))
else
pbMessage(_INTL("{1} lost {2} Exp. Points!", pkmn.name, difference))
end
pkmn.exp = new_exp
pkmn.calc_stats
scene.pbRefresh
return if pkmn.level == old_level
# Level changed
if scene.is_a?(PokemonPartyScreen)
scene.pbDisplay(_INTL("{1} dropped to Lv. {2}!", pkmn.name, pkmn.level))
pkmn.level = new_level
pkmn.calc_stats
pkmn.hp = 1 if new_level > old_level && pkmn.species_data.base_stats[:HP] == 1
scene.pbRefresh
if old_level > new_level
if scene.is_a?(UI::Party)
scene.show_message(_INTL("{1} dropped to Lv. {2}!", pkmn.name, pkmn.level))
else
pbMessage(_INTL("{1} dropped to Lv. {2}!", pkmn.name, pkmn.level))
end
@@ -266,21 +473,10 @@ def pbChangeExp(pkmn, new_exp, scene)
total_hp_diff, attack_diff, defense_diff, special_attack_diff, special_defense_diff, speed_diff), scene)
pbTopRightWindow(_INTL("Max. HP<r>{1}\nAttack<r>{2}\nDefense<r>{3}\nSp. Atk<r>{4}\nSp. Def<r>{5}\nSpeed<r>{6}",
pkmn.totalhp, pkmn.attack, pkmn.defense, pkmn.spatk, pkmn.spdef, pkmn.speed), scene)
else # Gains Exp
difference = new_exp - pkmn.exp
if scene.is_a?(PokemonPartyScreen)
scene.pbDisplay(_INTL("{1} gained {2} Exp. Points!", pkmn.name, difference))
else
pbMessage(_INTL("{1} gained {2} Exp. Points!", pkmn.name, difference))
end
pkmn.exp = new_exp
else
pkmn.changeHappiness("vitamin")
pkmn.calc_stats
scene.pbRefresh
return if pkmn.level == old_level
# Level changed
if scene.is_a?(PokemonPartyScreen)
scene.pbDisplay(_INTL("{1} grew to Lv. {2}!", pkmn.name, pkmn.level))
if scene.is_a?(UI::Party)
scene.show_message(_INTL("{1} grew to Lv. {2}!", pkmn.name, pkmn.level))
else
pbMessage(_INTL("{1} grew to Lv. {2}!", pkmn.name, pkmn.level))
end
@@ -308,7 +504,102 @@ def pbChangeExp(pkmn, new_exp, scene)
evo.pbStartScreen(pkmn, new_species)
evo.pbEvolution
evo.pbEndScreen
scene.pbRefresh if scene.is_a?(PokemonPartyScreen)
scene.refresh if scene.is_a?(UI::Party)
end
end
end
end
#===============================================================================
# Change a Pokémon's Experience amount.
#===============================================================================
def pbChangeExp(pkmn, new_exp, scene)
new_exp = new_exp.clamp(0, pkmn.growth_rate.maximum_exp)
if pkmn.exp == new_exp
if scene.is_a?(UI::Party)
scene.show_message(_INTL("{1}'s Exp. Points remained unchanged.", pkmn.name))
else
pbMessage(_INTL("{1}'s Exp. Points remained unchanged.", pkmn.name))
end
return
end
old_level = pkmn.level
old_total_hp = pkmn.totalhp
old_attack = pkmn.attack
old_defense = pkmn.defense
old_special_attack = pkmn.spatk
old_special_defense = pkmn.spdef
old_speed = pkmn.speed
if pkmn.exp > new_exp # Loses Exp
difference = pkmn.exp - new_exp
if scene.is_a?(UI::Party)
scene.show_message(_INTL("{1} lost {2} Exp. Points!", pkmn.name, difference))
else
pbMessage(_INTL("{1} lost {2} Exp. Points!", pkmn.name, difference))
end
pkmn.exp = new_exp
pkmn.calc_stats
scene.pbRefresh
return if pkmn.level == old_level
# Level changed
if scene.is_a?(UI::Party)
scene.show_message(_INTL("{1} dropped to Lv. {2}!", pkmn.name, pkmn.level))
else
pbMessage(_INTL("{1} dropped to Lv. {2}!", pkmn.name, pkmn.level))
end
total_hp_diff = pkmn.totalhp - old_total_hp
attack_diff = pkmn.attack - old_attack
defense_diff = pkmn.defense - old_defense
special_attack_diff = pkmn.spatk - old_special_attack
special_defense_diff = pkmn.spdef - old_special_defense
speed_diff = pkmn.speed - old_speed
pbTopRightWindow(_INTL("Max. HP<r>{1}\nAttack<r>{2}\nDefense<r>{3}\nSp. Atk<r>{4}\nSp. Def<r>{5}\nSpeed<r>{6}",
total_hp_diff, attack_diff, defense_diff, special_attack_diff, special_defense_diff, speed_diff), scene)
pbTopRightWindow(_INTL("Max. HP<r>{1}\nAttack<r>{2}\nDefense<r>{3}\nSp. Atk<r>{4}\nSp. Def<r>{5}\nSpeed<r>{6}",
pkmn.totalhp, pkmn.attack, pkmn.defense, pkmn.spatk, pkmn.spdef, pkmn.speed), scene)
else # Gains Exp
difference = new_exp - pkmn.exp
if scene.is_a?(UI::Party)
scene.show_message(_INTL("{1} gained {2} Exp. Points!", pkmn.name, difference))
else
pbMessage(_INTL("{1} gained {2} Exp. Points!", pkmn.name, difference))
end
pkmn.exp = new_exp
pkmn.changeHappiness("vitamin")
pkmn.calc_stats
scene.pbRefresh
return if pkmn.level == old_level
# Level changed
if scene.is_a?(UI::Party)
scene.show_message(_INTL("{1} grew to Lv. {2}!", pkmn.name, pkmn.level))
else
pbMessage(_INTL("{1} grew to Lv. {2}!", pkmn.name, pkmn.level))
end
total_hp_diff = pkmn.totalhp - old_total_hp
attack_diff = pkmn.attack - old_attack
defense_diff = pkmn.defense - old_defense
special_attack_diff = pkmn.spatk - old_special_attack
special_defense_diff = pkmn.spdef - old_special_defense
speed_diff = pkmn.speed - old_speed
pbTopRightWindow(_INTL("Max. HP<r>+{1}\nAttack<r>+{2}\nDefense<r>+{3}\nSp. Atk<r>+{4}\nSp. Def<r>+{5}\nSpeed<r>+{6}",
total_hp_diff, attack_diff, defense_diff, special_attack_diff, special_defense_diff, speed_diff), scene)
pbTopRightWindow(_INTL("Max. HP<r>{1}\nAttack<r>{2}\nDefense<r>{3}\nSp. Atk<r>{4}\nSp. Def<r>{5}\nSpeed<r>{6}",
pkmn.totalhp, pkmn.attack, pkmn.defense, pkmn.spatk, pkmn.spdef, pkmn.speed), scene)
# Learn new moves upon level up
movelist = pkmn.getMoveList
movelist.each do |i|
next if i[0] <= old_level || i[0] > pkmn.level
pbLearnMove(pkmn, i[1], true) { scene.pbUpdate }
end
# Check for evolution
new_species = pkmn.check_evolution_on_level_up
if new_species
pbFadeOutInWithMusic do
evo = PokemonEvolutionScene.new
evo.pbStartScreen(pkmn, new_species)
evo.pbEvolution
evo.pbEndScreen
scene.refresh if scene.is_a?(UI::Party)
end
end
end
@@ -320,7 +611,7 @@ def pbGainExpFromExpCandy(pkmn, base_amt, qty, scene)
return false
end
pbSEPlay("Pkmn level up")
scene.scene.pbSetHelpText("") if scene.is_a?(PokemonPartyScreen)
scene.set_help_text("") if scene.is_a?(UI::Party)
if qty > 1
(qty - 1).times { pkmn.changeHappiness("vitamin") }
end
@@ -581,9 +872,12 @@ end
#===============================================================================
# Teach and forget a move.
#===============================================================================
def pbLearnMove(pkmn, move, ignore_if_known = false, by_machine = false, &block)
def pbLearnMove(pkmn, move, ignore_if_known = false, by_machine = false, screen = nil, &block)
return false if !pkmn
pkmn_name = pkmn.name
move = GameData::Move.get(move).id
move_name = GameData::Move.get(move).name
# Check if Pokémon is unable to learn any moves
if pkmn.egg? && !$DEBUG
pbMessage(_INTL("Eggs can't be taught any moves."), &block)
return false
@@ -591,30 +885,32 @@ def pbLearnMove(pkmn, move, ignore_if_known = false, by_machine = false, &block)
pbMessage(_INTL("Shadow Pokémon can't be taught any moves."), &block)
return false
end
pkmn_name = pkmn.name
move_name = GameData::Move.get(move).name
# Check if Pokémon can learn this move
if pkmn.hasMove?(move)
pbMessage(_INTL("{1} already knows {2}.", pkmn_name, move_name), &block) if !ignore_if_known
if !ignore_if_known
pbMessage(_INTL("{1} already knows {2}.", pkmn_name, move_name), &block)
end
return false
elsif pkmn.numMoves < Pokemon::MAX_MOVES
pkmn.learn_move(move)
pbMessage("\\se[]" + _INTL("{1} learned {2}!", pkmn_name, move_name) + "\\se[Pkmn move learnt]", &block)
return true
end
# Pokémon needs to forget a move to learn this one
pbMessage(_INTL("{1} wants to learn {2}, but it already knows {3} moves.",
pkmn_name, move_name, pkmn.numMoves.to_word) + "\1", &block)
if pbConfirmMessage(_INTL("Should {1} forget a move to learn {2}?", pkmn_name, move_name), &block)
loop do
move_index = pbForgetMove(pkmn, move)
move_index = pbForgetMove(pkmn, move, screen)
if move_index >= 0
old_move_name = pkmn.moves[move_index].name
oldmovepp = pkmn.moves[move_index].pp
old_move_pp = pkmn.moves[move_index].pp
pkmn.moves[move_index] = Pokemon::Move.new(move) # Replaces current/total PP
if by_machine && Settings::TAUGHT_MACHINES_KEEP_OLD_PP
pkmn.moves[move_index].pp = [oldmovepp, pkmn.moves[move_index].total_pp].min
pkmn.moves[move_index].pp = [old_move_pp, pkmn.moves[move_index].total_pp].min
end
pbMessage(_INTL("1, 2, and...\\wt[16] ...\\wt[16] ...\\wt[16] Ta-da!") + "\\se[Battle ball drop]\1", &block)
pbMessage(_INTL("{1} forgot how to use {2}.\nAnd..." + "\1", pkmn_name, old_move_name), &block)
pbMessage(_INTL("{1} forgot how to use {2}.\nAnd...", pkmn_name, old_move_name) + "\1", &block)
pbMessage("\\se[]" + _INTL("{1} learned {2}!", pkmn_name, move_name) + "\\se[Pkmn move learnt]", &block)
pkmn.changeHappiness("machine") if by_machine
return true
@@ -629,291 +925,11 @@ def pbLearnMove(pkmn, move, ignore_if_known = false, by_machine = false, &block)
return false
end
def pbForgetMove(pkmn, moveToLearn)
def pbForgetMove(pkmn, move_to_learn, screen = nil)
ret = -1
pbFadeOutIn do
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene)
ret = screen.pbStartForgetScreen([pkmn], 0, moveToLearn)
pbFadeOutInWithUpdate(screen&.sprites) do
summary_screen = UI::PokemonSummary.new([pkmn], 0, mode: :choose_move, new_move: move_to_learn)
ret = summary_screen.choose_move
end
return ret
end
#===============================================================================
# Use an item from the Bag and/or on a Pokémon.
#===============================================================================
# @return [Integer] 0 = item wasn't used; 1 = item used; 2 = close Bag to use in field
def pbUseItem(bag, item, bagscene = nil)
itm = GameData::Item.get(item)
useType = itm.field_use
if useType == 1 # Item is usable on a Pokémon
if $player.pokemon_count == 0
pbMessage(_INTL("There is no Pokémon."))
return 0
end
ret = false
annot = nil
if itm.is_evolution_stone?
annot = []
$player.party.each do |pkmn|
elig = pkmn.check_evolution_on_use_item(item)
annot.push((elig) ? _INTL("ABLE") : _INTL("NOT ABLE"))
end
end
pbFadeOutIn do
scene = PokemonParty_Scene.new
screen = PokemonPartyScreen.new(scene, $player.party)
screen.pbStartScene(_INTL("Use on which Pokémon?"), false, annot)
loop do
scene.pbSetHelpText(_INTL("Use on which Pokémon?"))
chosen = screen.pbChoosePokemon
if chosen < 0
ret = false
break
end
pkmn = $player.party[chosen]
next if !pbCheckUseOnPokemon(item, pkmn, screen)
qty = 1
max_at_once = ItemHandlers.triggerUseOnPokemonMaximum(item, pkmn)
max_at_once = [max_at_once, $bag.quantity(item)].min
if max_at_once > 1
qty = screen.scene.pbChooseNumber(
_INTL("How many {1} do you want to use?", GameData::Item.get(item).portion_name_plural), max_at_once
)
screen.scene.pbSetHelpText("") if screen.is_a?(PokemonPartyScreen)
end
next if qty <= 0
ret = ItemHandlers.triggerUseOnPokemon(item, qty, pkmn, screen)
next unless ret && itm.consumed_after_use?
bag.remove(item, qty)
next if bag.has?(item)
pbMessage(_INTL("You used your last {1}.", itm.portion_name)) { screen.pbUpdate }
break
end
screen.pbEndScene
bagscene&.pbRefresh
end
return (ret) ? 1 : 0
elsif useType == 2 || itm.is_machine? # Item is usable from Bag or teaches a move
intret = ItemHandlers.triggerUseFromBag(item)
if intret >= 0
bag.remove(item) if intret == 1 && itm.consumed_after_use?
return intret
end
pbMessage(_INTL("Can't use that here."))
return 0
end
pbMessage(_INTL("Can't use that here."))
return 0
end
# Only called when in the party screen and having chosen an item to be used on
# the selected Pokémon.
def pbUseItemOnPokemon(item, pkmn, scene)
itm = GameData::Item.get(item)
# TM or HM
if itm.is_machine?
machine = itm.move
return false if !machine
movename = GameData::Move.get(machine).name
if pkmn.shadowPokemon?
pbMessage(_INTL("Shadow Pokémon can't be taught any moves.")) { scene.pbUpdate }
elsif !pkmn.compatible_with_move?(machine)
pbMessage(_INTL("{1} can't learn {2}.", pkmn.name, movename)) { scene.pbUpdate }
else
pbMessage("\\se[PC access]" + _INTL("You booted up the {1}.", itm.portion_name) + "\1") { scene.pbUpdate }
if pbConfirmMessage(_INTL("Do you want to teach {1} to {2}?", movename, pkmn.name)) { scene.pbUpdate }
if pbLearnMove(pkmn, machine, false, true) { scene.pbUpdate }
$bag.remove(item) if itm.consumed_after_use?
return true
end
end
end
return false
end
# Other item
qty = 1
max_at_once = ItemHandlers.triggerUseOnPokemonMaximum(item, pkmn)
max_at_once = [max_at_once, $bag.quantity(item)].min
if max_at_once > 1
qty = scene.scene.pbChooseNumber(
_INTL("How many {1} do you want to use?", itm.portion_name_plural), max_at_once
)
scene.scene.pbSetHelpText("") if scene.is_a?(PokemonPartyScreen)
end
return false if qty <= 0
ret = ItemHandlers.triggerUseOnPokemon(item, qty, pkmn, scene)
scene.pbClearAnnotations
scene.pbHardRefresh
if ret && itm.consumed_after_use?
$bag.remove(item, qty)
if !$bag.has?(item)
pbMessage(_INTL("You used your last {1}.", itm.portion_name)) { scene.pbUpdate }
end
end
return ret
end
def pbUseKeyItemInField(item)
ret = ItemHandlers.triggerUseInField(item)
if ret == -1 # Item effect not found
pbMessage(_INTL("Can't use that here."))
elsif ret > 0 && GameData::Item.get(item).consumed_after_use?
$bag.remove(item)
end
return ret > 0
end
def pbUseItemMessage(item)
itemname = GameData::Item.get(item).portion_name
if itemname.starts_with_vowel?
pbMessage(_INTL("You used an {1}.", itemname))
else
pbMessage(_INTL("You used a {1}.", itemname))
end
end
def pbCheckUseOnPokemon(item, pkmn, _screen)
return pkmn && !pkmn.egg? && (!pkmn.hyper_mode || GameData::Item.get(item)&.is_scent?)
end
#===============================================================================
# Give an item to a Pokémon to hold, and take a held item from a Pokémon.
#===============================================================================
def pbGiveItemToPokemon(item, pkmn, scene, pkmnid = 0)
newitemname = GameData::Item.get(item).portion_name
if pkmn.egg?
scene.pbDisplay(_INTL("Eggs can't hold items."))
return false
elsif pkmn.mail
scene.pbDisplay(_INTL("{1}'s mail must be removed before giving it an item.", pkmn.name))
return false if !pbTakeItemFromPokemon(pkmn, scene)
end
if pkmn.hasItem?
olditemname = pkmn.item.portion_name
if newitemname.starts_with_vowel?
scene.pbDisplay(_INTL("{1} is already holding an {2}.", pkmn.name, olditemname) + "\1")
else
scene.pbDisplay(_INTL("{1} is already holding a {2}.", pkmn.name, olditemname) + "\1")
end
if scene.pbConfirm(_INTL("Would you like to switch the two items?"))
$bag.remove(item)
if !$bag.add(pkmn.item)
raise _INTL("Couldn't re-store deleted item in Bag somehow") if !$bag.add(item)
scene.pbDisplay(_INTL("The Bag is full. The Pokémon's item could not be removed."))
elsif GameData::Item.get(item).is_mail?
if pbWriteMail(item, pkmn, pkmnid, scene)
pkmn.item = item
scene.pbDisplay(_INTL("Took the {1} from {2} and gave it the {3}.", olditemname, pkmn.name, newitemname))
return true
elsif !$bag.add(item)
raise _INTL("Couldn't re-store deleted item in Bag somehow")
end
else
pkmn.item = item
scene.pbDisplay(_INTL("Took the {1} from {2} and gave it the {3}.", olditemname, pkmn.name, newitemname))
return true
end
end
elsif !GameData::Item.get(item).is_mail? || pbWriteMail(item, pkmn, pkmnid, scene)
$bag.remove(item)
pkmn.item = item
scene.pbDisplay(_INTL("{1} is now holding the {2}.", pkmn.name, newitemname))
return true
end
return false
end
def pbTakeItemFromPokemon(pkmn, scene)
ret = false
if !pkmn.hasItem?
scene.pbDisplay(_INTL("{1} isn't holding anything.", pkmn.name))
elsif !$bag.can_add?(pkmn.item)
scene.pbDisplay(_INTL("The Bag is full. The Pokémon's item could not be removed."))
elsif pkmn.mail
if scene.pbConfirm(_INTL("Save the removed mail in your PC?"))
if pbMoveToMailbox(pkmn)
scene.pbDisplay(_INTL("The mail was saved in your PC."))
pkmn.item = nil
ret = true
else
scene.pbDisplay(_INTL("Your PC's Mailbox is full."))
end
elsif scene.pbConfirm(_INTL("If the mail is removed, its message will be lost. OK?"))
$bag.add(pkmn.item)
scene.pbDisplay(_INTL("Received the {1} from {2}.", pkmn.item.portion_name, pkmn.name))
pkmn.item = nil
pkmn.mail = nil
ret = true
end
else
$bag.add(pkmn.item)
scene.pbDisplay(_INTL("Received the {1} from {2}.", pkmn.item.portion_name, pkmn.name))
pkmn.item = nil
ret = true
end
return ret
end
#===============================================================================
# Choose an item from the Bag.
#===============================================================================
def pbChooseItem(var = 0, *args)
ret = nil
pbFadeOutIn do
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene, $bag)
ret = screen.pbChooseItemScreen
end
$game_variables[var] = ret || :NONE if var > 0
return ret
end
def pbChooseApricorn(var = 0)
ret = nil
pbFadeOutIn do
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene, $bag)
ret = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).is_apricorn? })
end
$game_variables[var] = ret || :NONE if var > 0
return ret
end
def pbChooseFossil(var = 0)
ret = nil
pbFadeOutIn do
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene, $bag)
ret = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).is_fossil? })
end
$game_variables[var] = ret || :NONE if var > 0
return ret
end
# Shows a list of items to choose from, with the chosen item's ID being stored
# in the given Game Variable. Only items which the player has are listed.
def pbChooseItemFromList(message, variable, *args)
commands = []
itemid = []
args.each do |item|
next if !GameData::Item.exists?(item)
itm = GameData::Item.get(item)
next if !$bag.has?(itm)
commands.push(itm.name)
itemid.push(itm.id)
end
if commands.length == 0
$game_variables[variable] = :NONE
return nil
end
commands.push(_INTL("Cancel"))
itemid.push(nil)
ret = pbMessage(message, commands, -1)
if ret < 0 || ret >= commands.length - 1
$game_variables[variable] = :NONE
return nil
end
$game_variables[variable] = itemid[ret] || :NONE
return itemid[ret]
end

File diff suppressed because it is too large Load Diff

View File

@@ -264,6 +264,6 @@ ItemHandlers::UseInField.add(:POKERADAR, proc { |item|
next pbUsePokeRadar
})
ItemHandlers::UseFromBag.add(:POKERADAR, proc { |item|
ItemHandlers::UseFromBag.add(:POKERADAR, proc { |item, bag_screen|
next (pbCanUsePokeRadar?) ? 2 : 0
})

View File

@@ -101,7 +101,7 @@ def pbWriteMail(item, pkmn, pkmnid, scene)
message = ""
loop do
message = pbMessageFreeText(_INTL("Please enter a message (max. 250 characters)."),
"", false, 250, Graphics.width) { scene.pbUpdate }
"", false, 250, Graphics.width) { scene.update }
if message != ""
# Store mail if a message was written
poke1 = poke2 = nil
@@ -120,6 +120,6 @@ def pbWriteMail(item, pkmn, pkmnid, scene)
pbStoreMail(pkmn, item, message, poke1, poke2, poke3)
return true
end
return false if scene.pbConfirm(_INTL("Stop giving the Pokémon Mail?"))
return false if scene.show_confirm_message(_INTL("Stop giving the Pokémon Mail?"))
end
end

View File

@@ -120,7 +120,7 @@ class HeldItemIconSprite < Sprite
self.y = y
@pokemon = pokemon
@item = nil
self.item = @pokemon.item_id
self.item = @pokemon&.item_id
end
def dispose
@@ -130,7 +130,7 @@ class HeldItemIconSprite < Sprite
def pokemon=(value)
@pokemon = value
self.item = @pokemon.item_id
self.item = @pokemon&.item_id
end
def item=(value)
@@ -148,7 +148,7 @@ class HeldItemIconSprite < Sprite
def update
super
self.item = @pokemon.item_id
self.item = @pokemon&.item_id
if @animbitmap
@animbitmap.update
self.bitmap = @animbitmap.bitmap

View File

@@ -8,38 +8,41 @@ class PokemonBag
attr_reader :registered_items
attr_reader :ready_menu_selection
def self.pocket_names
return Settings.bag_pocket_names
end
MAX_PER_SLOT = 999
def self.pocket_count
return self.pocket_names.length
return GameData::BagPocket.count
end
def initialize
@pockets = []
(0..PokemonBag.pocket_count).each { |i| @pockets[i] = [] }
@pockets = {}
GameData::BagPocket.all_pockets.each { |pckt| @pockets[pckt] = [] }
reset_last_selections
@registered_items = []
@ready_menu_selection = [0, 0, 1] # Used by the Ready Menu to remember cursor positions
end
def reset_last_selections
@last_viewed_pocket = 1
@last_pocket_selections ||= []
(0..PokemonBag.pocket_count).each { |i| @last_pocket_selections[i] = 0 }
@last_viewed_pocket = GameData::BagPocket.all_pockets.first
@last_pocket_selections ||= {}
GameData::BagPocket.all_pockets.each { |pckt| @last_pocket_selections[pckt] = 0 }
end
def clear
@pockets.each { |pocket| pocket.clear }
(PokemonBag.pocket_count + 1).times { |i| @last_pocket_selections[i] = 0 }
@pockets.each_value { |pocket| pocket.clear }
@pockets.clear
@last_pocket_selections.clear
GameData::BagPocket.all_pockets.each do |pckt|
@pockets[pckt] = []
@last_pocket_selections[pckt] = 0
end
end
#-----------------------------------------------------------------------------
# Gets the index of the current selected item in the pocket
def last_viewed_index(pocket)
if pocket <= 0 || pocket > PokemonBag.pocket_count
if !GameData::BagPocket.exists?(pocket)
raise ArgumentError.new(_INTL("Invalid pocket: {1}", pocket.inspect))
end
return [@last_pocket_selections[pocket], @pockets[pocket].length].min || 0
@@ -47,7 +50,7 @@ class PokemonBag
# Sets the index of the current selected item in the pocket
def set_last_viewed_index(pocket, value)
if pocket <= 0 || pocket > PokemonBag.pocket_count
if !GameData::BagPocket.exists?(pocket)
raise ArgumentError.new(_INTL("Invalid pocket: {1}", pocket.inspect))
end
@last_pocket_selections[pocket] = value if value <= @pockets[pocket].length
@@ -58,7 +61,7 @@ class PokemonBag
def quantity(item)
item_data = GameData::Item.try_get(item)
return 0 if !item_data
pocket = item_data.pocket
pocket = item_data.bag_pocket
return ItemStorageHelper.quantity(@pockets[pocket], item_data.id)
end
@@ -70,23 +73,23 @@ class PokemonBag
def can_add?(item, qty = 1)
item_data = GameData::Item.try_get(item)
return false if !item_data
pocket = item_data.pocket
pocket = item_data.bag_pocket
max_size = max_pocket_size(pocket)
max_size = @pockets[pocket].length + 1 if max_size < 0 # Infinite size
return ItemStorageHelper.can_add?(
@pockets[pocket], max_size, Settings::BAG_MAX_PER_SLOT, item_data.id, qty
@pockets[pocket], max_size, MAX_PER_SLOT, item_data.id, qty
)
end
def add(item, qty = 1)
item_data = GameData::Item.try_get(item)
return false if !item_data
pocket = item_data.pocket
pocket = item_data.bag_pocket
max_size = max_pocket_size(pocket)
max_size = @pockets[pocket].length + 1 if max_size < 0 # Infinite size
ret = ItemStorageHelper.add(@pockets[pocket],
max_size, Settings::BAG_MAX_PER_SLOT, item_data.id, qty)
if ret && Settings::BAG_POCKET_AUTO_SORT[pocket - 1]
max_size, MAX_PER_SLOT, item_data.id, qty)
if ret && GameData::BagPocket.get(pocket).auto_sort
@pockets[pocket].sort! { |a, b| GameData::Item.keys.index(a[0]) <=> GameData::Item.keys.index(b[0]) }
end
return ret
@@ -103,7 +106,7 @@ class PokemonBag
def remove(item, qty = 1)
item_data = GameData::Item.try_get(item)
return false if !item_data
pocket = item_data.pocket
pocket = item_data.bag_pocket
return ItemStorageHelper.remove(@pockets[pocket], item_data.id, qty)
end
@@ -121,7 +124,7 @@ class PokemonBag
old_item_data = GameData::Item.try_get(old_item)
new_item_data = GameData::Item.try_get(new_item)
return false if !old_item_data || !new_item_data
pocket = old_item_data.pocket
pocket = old_item_data.bag_pocket
old_id = old_item_data.id
new_id = new_item_data.id
ret = false
@@ -160,7 +163,7 @@ class PokemonBag
private
def max_pocket_size(pocket)
return Settings::BAG_MAX_POCKET_SIZE[pocket - 1] || -1
return GameData::BagPocket.get(pocket).max_slots
end
end

View File

@@ -893,5 +893,5 @@ MultipleForms.register(:QUILAVA, {
MultipleForms.copy(:QUILAVA,
:DEWOTT, :PETILIL, :RUFFLET, :GOOMY, :BERGMITE, :DARTRIX)
# Paldean forms
# Paldean forms.
# None!

View File

@@ -123,6 +123,21 @@ class PokemonIconSprite < Sprite
def pokemon=(value)
@pokemon = value
# Check if the bitmap needs to be reloaded
new_values = nil
if @pokemon
new_values = {
:species => @pokemon.species,
:form => @pokemon.form,
:gender => @pokemon.gender,
:shiny => @pokemon.shiny?,
:shadow => @pokemon.shadowPokemon?,
:egg => @pokemon.egg?
}
end
return if @pokemon_values == new_values
@pokemon_values = new_values
# Reload the bitmap
@animBitmap&.dispose
@animBitmap = nil
if !@pokemon

View File

@@ -60,13 +60,13 @@ class PokemonStorage
attr_accessor :currentBox
attr_writer :unlockedWallpapers
BASICWALLPAPERQTY = 16
BASIC_WALLPAPER_COUNT = 16
def initialize(maxBoxes = Settings::NUM_STORAGE_BOXES, maxPokemon = PokemonBox::BOX_SIZE)
@boxes = []
maxBoxes.times do |i|
@boxes[i] = PokemonBox.new(_INTL("Box {1}", i + 1), maxPokemon)
@boxes[i].background = i % BASICWALLPAPERQTY
@boxes[i].background = i % BASIC_WALLPAPER_COUNT
end
@currentBox = 0
@boxmode = -1
@@ -76,6 +76,11 @@ class PokemonStorage
end
end
# NOTE: These wallpaper names are shown in a list in the storage screen that
# is a fixed width. The names should be kept relatively short; longer
# names will get shrunk to fit the width of the list, and that looks bad.
# NOTE: The order these wallpapers are listed determines the number in their
# filenames.
def allWallpapers
return [
# Basic wallpapers
@@ -85,9 +90,9 @@ class PokemonStorage
_INTL("Poké Center"), _INTL("Machine"), _INTL("Checks"), _INTL("Simple"),
# Special wallpapers
_INTL("Space"), _INTL("Backyard"), _INTL("Nostalgic 1"), _INTL("Torchic"),
_INTL("Trio 1"), _INTL("PikaPika 1"), _INTL("Legend 1"), _INTL("Team Galactic 1"),
_INTL("Trio 1"), _INTL("PikaPika 1"), _INTL("Legend 1"), _INTL("Galactic 1"),
_INTL("Distortion"), _INTL("Contest"), _INTL("Nostalgic 2"), _INTL("Croagunk"),
_INTL("Trio 2"), _INTL("PikaPika 2"), _INTL("Legend 2"), _INTL("Team Galactic 2"),
_INTL("Trio 2"), _INTL("PikaPika 2"), _INTL("Legend 2"), _INTL("Galactic 2"),
_INTL("Heart"), _INTL("Soul"), _INTL("Big Brother"), _INTL("Pokéathlon"),
_INTL("Trio 3"), _INTL("Spiky Pika"), _INTL("Kimono Girl"), _INTL("Revival")
]
@@ -100,25 +105,22 @@ class PokemonStorage
def isAvailableWallpaper?(i)
@unlockedWallpapers = [] if !@unlockedWallpapers
return true if i < BASICWALLPAPERQTY
return true if i < BASIC_WALLPAPER_COUNT
return true if @unlockedWallpapers[i]
return false
end
def availableWallpapers
ret = [[], []] # Names, IDs
papers = allWallpapers
@unlockedWallpapers = [] if !@unlockedWallpapers
papers.length.times do |i|
next if !isAvailableWallpaper?(i)
ret[0].push(papers[i])
ret[1].push(i)
ret = {}
allWallpapers.each_with_index do |paper, i|
ret[i] = paper if isAvailableWallpaper?(i)
end
return ret
end
def party
$player.party
return $player.party
end
def party=(_value)

View File

@@ -94,7 +94,7 @@ class Pokemon
# Max EVs that a single stat can have
EV_STAT_LIMIT = 252
# Maximum length a Pokémon's nickname can be
MAX_NAME_SIZE = 10
MAX_NAME_SIZE = 12
# Maximum number of moves a Pokémon can know at once
MAX_MOVES = 4
@@ -314,6 +314,21 @@ class Pokemon
@ready_to_evolve = false
end
#-----------------------------------------------------------------------------
# Stats.
#-----------------------------------------------------------------------------
def stat(id)
case id
when :HP then return @totalhp
when :ATTACK then return @attack
when :DEFENSE then return @defense
when :SPECIAL_ATTACK then return @spatk
when :SPECIAL_DEFENSE then return @spdef
when :SPEED then return @speed
end
return 0
end
#-----------------------------------------------------------------------------
# Types.
#-----------------------------------------------------------------------------
@@ -560,6 +575,7 @@ class Pokemon
def item=(value)
return if value && !GameData::Item.exists?(value)
@item = (value) ? GameData::Item.get(value).id : value
@mail = nil if @item.nil?
end
# Returns whether this Pokémon is holding an item. If an item id is passed,
@@ -593,6 +609,7 @@ class Pokemon
raise ArgumentError, _INTL("Invalid value {1} given", mail.inspect)
end
@mail = mail
@item = mail&.item
end
#-----------------------------------------------------------------------------

View File

@@ -65,7 +65,7 @@ class Pokemon
def display_type(pkmn); return GameData::Move.get(@id).display_type(pkmn, self); end
def display_category(pkmn); return GameData::Move.get(@id).display_category(pkmn, self); end
def display_damage(pkmn); return GameData::Move.get(@id).display_damage(pkmn, self); end
def display_power(pkmn); return GameData::Move.get(@id).display_power(pkmn, self); end
def display_accuracy(pkmn); return GameData::Move.get(@id).display_accuracy(pkmn, self); end
end
end

View File

@@ -59,6 +59,14 @@ class Pokemon
@gender = new_gender
end
def male?
return @gender == 0
end
def female?
return @gender == 1
end
# @param new_language [Integer] new owner language
def language=(new_language)
validate new_language => Integer

View File

@@ -90,16 +90,7 @@ class IntroEventScene < EventScene
def close_title_screen(scene, *args)
fade_out_title_screen(scene)
sscene = PokemonLoad_Scene.new
sscreen = PokemonLoadScreen.new(sscene)
sscreen.pbStartLoadScreen
end
def close_title_screen_delete(scene, *args)
fade_out_title_screen(scene)
sscene = PokemonLoad_Scene.new
sscreen = PokemonLoadScreen.new(sscene)
sscreen.pbStartDeleteScreen
UI::Load.new.main
end
def title_screen_update(scene, args)
@@ -108,11 +99,6 @@ class IntroEventScene < EventScene
@pic2.moveOpacity(TICKS_PER_ENTER_FLASH * 2 / 10, TICKS_PER_ENTER_FLASH * 4 / 10, 0)
@pic2.moveOpacity(TICKS_PER_ENTER_FLASH * 6 / 10, TICKS_PER_ENTER_FLASH * 4 / 10, 255)
end
if Input.press?(Input::DOWN) &&
Input.press?(Input::BACK) &&
Input.press?(Input::CTRL)
close_title_screen_delete(scene, args)
end
end
end

View File

@@ -1,322 +0,0 @@
#===============================================================================
#
#===============================================================================
class PokemonPauseMenu_Scene
def pbStartScene
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@sprites = {}
@sprites["cmdwindow"] = Window_CommandPokemon.new([])
@sprites["cmdwindow"].visible = false
@sprites["cmdwindow"].viewport = @viewport
@sprites["infowindow"] = Window_UnformattedTextPokemon.newWithSize("", 0, 0, 32, 32, @viewport)
@sprites["infowindow"].visible = false
@sprites["helpwindow"] = Window_UnformattedTextPokemon.newWithSize("", 0, 0, 32, 32, @viewport)
@sprites["helpwindow"].visible = false
@infostate = false
@helpstate = false
pbSEPlay("GUI menu open")
end
def pbShowInfo(text)
@sprites["infowindow"].resizeToFit(text, Graphics.height)
@sprites["infowindow"].text = text
@sprites["infowindow"].visible = true
@infostate = true
end
def pbShowHelp(text)
@sprites["helpwindow"].resizeToFit(text, Graphics.height)
@sprites["helpwindow"].text = text
@sprites["helpwindow"].visible = true
pbBottomLeft(@sprites["helpwindow"])
@helpstate = true
end
def pbShowMenu
@sprites["cmdwindow"].visible = true
@sprites["infowindow"].visible = @infostate
@sprites["helpwindow"].visible = @helpstate
end
def pbHideMenu
@sprites["cmdwindow"].visible = false
@sprites["infowindow"].visible = false
@sprites["helpwindow"].visible = false
end
def pbShowCommands(commands)
ret = -1
cmdwindow = @sprites["cmdwindow"]
cmdwindow.commands = commands
cmdwindow.index = $game_temp.menu_last_choice
cmdwindow.resizeToFit(commands)
cmdwindow.x = Graphics.width - cmdwindow.width
cmdwindow.y = 0
cmdwindow.visible = true
loop do
cmdwindow.update
Graphics.update
Input.update
pbUpdateSceneMap
if Input.trigger?(Input::BACK) || Input.trigger?(Input::ACTION)
ret = -1
break
elsif Input.trigger?(Input::USE)
ret = cmdwindow.index
$game_temp.menu_last_choice = ret
break
end
end
return ret
end
def pbEndScene
pbDisposeSpriteHash(@sprites)
@viewport.dispose
end
def pbRefresh; end
end
#===============================================================================
#
#===============================================================================
class PokemonPauseMenu
def initialize(scene)
@scene = scene
end
def pbShowMenu
@scene.pbRefresh
@scene.pbShowMenu
end
def pbShowInfo; end
def pbStartPokemonMenu
if !$player
if $DEBUG
pbMessage(_INTL("The player trainer was not defined, so the pause menu can't be displayed."))
pbMessage(_INTL("Please see the documentation to learn how to set up the trainer player."))
end
return
end
@scene.pbStartScene
# Show extra info window if relevant
pbShowInfo
# Get all commands
command_list = []
commands = []
MenuHandlers.each_available(:pause_menu) do |option, hash, name|
command_list.push(name)
commands.push(hash)
end
# Main loop
end_scene = false
loop do
choice = @scene.pbShowCommands(command_list)
if choice < 0
pbPlayCloseMenuSE
end_scene = true
break
end
break if commands[choice]["effect"].call(@scene)
end
@scene.pbEndScene if end_scene
end
end
#===============================================================================
# Pause menu commands.
#===============================================================================
MenuHandlers.add(:pause_menu, :pokedex, {
"name" => _INTL("Pokédex"),
"order" => 10,
"condition" => proc { next $player.has_pokedex && $player.pokedex.accessible_dexes.length > 0 },
"effect" => proc { |menu|
pbPlayDecisionSE
if Settings::USE_CURRENT_REGION_DEX
pbFadeOutIn do
scene = PokemonPokedex_Scene.new
screen = PokemonPokedexScreen.new(scene)
screen.pbStartScreen
menu.pbRefresh
end
elsif $player.pokedex.accessible_dexes.length == 1
$PokemonGlobal.pokedexDex = $player.pokedex.accessible_dexes[0]
pbFadeOutIn do
scene = PokemonPokedex_Scene.new
screen = PokemonPokedexScreen.new(scene)
screen.pbStartScreen
menu.pbRefresh
end
else
pbFadeOutIn do
scene = PokemonPokedexMenu_Scene.new
screen = PokemonPokedexMenuScreen.new(scene)
screen.pbStartScreen
menu.pbRefresh
end
end
next false
}
})
MenuHandlers.add(:pause_menu, :party, {
"name" => _INTL("Pokémon"),
"order" => 20,
"condition" => proc { next $player.party_count > 0 },
"effect" => proc { |menu|
pbPlayDecisionSE
hidden_move = nil
pbFadeOutIn do
sscene = PokemonParty_Scene.new
sscreen = PokemonPartyScreen.new(sscene, $player.party)
hidden_move = sscreen.pbPokemonScreen
(hidden_move) ? menu.pbEndScene : menu.pbRefresh
end
next false if !hidden_move
$game_temp.in_menu = false
pbUseHiddenMove(hidden_move[0], hidden_move[1])
next true
}
})
MenuHandlers.add(:pause_menu, :bag, {
"name" => _INTL("Bag"),
"order" => 30,
"condition" => proc { next !pbInBugContest? },
"effect" => proc { |menu|
pbPlayDecisionSE
item = nil
pbFadeOutIn do
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene, $bag)
item = screen.pbStartScreen
(item) ? menu.pbEndScene : menu.pbRefresh
end
next false if !item
$game_temp.in_menu = false
pbUseKeyItemInField(item)
next true
}
})
MenuHandlers.add(:pause_menu, :pokegear, {
"name" => _INTL("Pokégear"),
"order" => 40,
"condition" => proc { next $player.has_pokegear },
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
scene = PokemonPokegear_Scene.new
screen = PokemonPokegearScreen.new(scene)
screen.pbStartScreen
($game_temp.fly_destination) ? menu.pbEndScene : menu.pbRefresh
end
next pbFlyToNewLocation
}
})
MenuHandlers.add(:pause_menu, :town_map, {
"name" => _INTL("Town Map"),
"order" => 40,
"condition" => proc { next !$player.has_pokegear && $bag.has?(:TOWNMAP) },
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
scene = PokemonRegionMap_Scene.new(-1, false)
screen = PokemonRegionMapScreen.new(scene)
ret = screen.pbStartScreen
$game_temp.fly_destination = ret if ret
($game_temp.fly_destination) ? menu.pbEndScene : menu.pbRefresh
end
next pbFlyToNewLocation
}
})
MenuHandlers.add(:pause_menu, :trainer_card, {
"name" => proc { next $player.name },
"order" => 50,
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
scene = PokemonTrainerCard_Scene.new
screen = PokemonTrainerCardScreen.new(scene)
screen.pbStartScreen
menu.pbRefresh
end
next false
}
})
MenuHandlers.add(:pause_menu, :save, {
"name" => _INTL("Save"),
"order" => 60,
"condition" => proc {
next $game_system && !$game_system.save_disabled && !pbInSafari? && !pbInBugContest?
},
"effect" => proc { |menu|
menu.pbHideMenu
scene = PokemonSave_Scene.new
screen = PokemonSaveScreen.new(scene)
if screen.pbSaveScreen
menu.pbEndScene
next true
end
menu.pbRefresh
menu.pbShowMenu
next false
}
})
MenuHandlers.add(:pause_menu, :options, {
"name" => _INTL("Options"),
"order" => 70,
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
scene = PokemonOption_Scene.new
screen = PokemonOptionScreen.new(scene)
screen.pbStartScreen
pbUpdateSceneMap
menu.pbRefresh
end
next false
}
})
MenuHandlers.add(:pause_menu, :debug, {
"name" => _INTL("Debug"),
"order" => 80,
"condition" => proc { next $DEBUG },
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
pbDebugMenu
menu.pbRefresh
end
next false
}
})
MenuHandlers.add(:pause_menu, :quit_game, {
"name" => _INTL("Quit Game"),
"order" => 90,
"effect" => proc { |menu|
menu.pbHideMenu
if pbConfirmMessage(_INTL("Are you sure you want to quit the game?"))
scene = PokemonSave_Scene.new
screen = PokemonSaveScreen.new(scene)
screen.pbSaveScreen
menu.pbEndScene
$scene = nil
next true
end
menu.pbRefresh
menu.pbShowMenu
next false
}
})

View File

@@ -2,6 +2,13 @@
#
#===============================================================================
class PokemonPokedexInfo_Scene
LEFT = 0
TOP = 0
RIGHT = 29
BOTTOM = 19
SQUARE_WIDTH = 16
SQUARE_HEIGHT = 16
def pbStartScene(dexlist, index, region)
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@@ -31,8 +38,8 @@ class PokemonPokedexInfo_Scene
pbDrawImagePositions(
@sprites["areamap"].bitmap,
[["Graphics/UI/Town Map/#{hidden[4]}",
hidden[2] * PokemonRegionMap_Scene::SQUARE_WIDTH,
hidden[3] * PokemonRegionMap_Scene::SQUARE_HEIGHT]]
hidden[2] * SQUARE_WIDTH,
hidden[3] * SQUARE_HEIGHT]]
)
end
@sprites["areahighlight"] = BitmapSprite.new(Graphics.width, Graphics.height, @viewport)
@@ -315,12 +322,12 @@ class PokemonPokedexInfo_Scene
# defined point in town_map.txt, and which either have no Self Switch
# controlling their visibility or whose Self Switch is ON)
visible_points = []
@mapdata.point.each do |loc|
next if loc[7] && !$game_switches[loc[7]] # Point is not visible
visible_points.push([loc[0], loc[1]])
@mapdata.points.each do |loc|
next if loc[:switch] && !$game_switches[loc[:switch]] # Point is not visible
visible_points.push(loc[:position])
end
# Find all points with a visible area for @species
town_map_width = 1 + PokemonRegionMap_Scene::RIGHT - PokemonRegionMap_Scene::LEFT
town_map_width = 1 + RIGHT - LEFT
ret = []
GameData::Encounter.each_of_version($PokemonGlobal.encounter_version) do |enc_data|
next if !pbFindEncounter(enc_data.types, @species) # Species isn't in encounter table
@@ -362,9 +369,9 @@ class PokemonPokedexInfo_Scene
# Draw coloured squares on each point of the Town Map with a nest
pointcolor = Color.new(0, 248, 248)
pointcolorhl = Color.new(192, 248, 248)
town_map_width = 1 + PokemonRegionMap_Scene::RIGHT - PokemonRegionMap_Scene::LEFT
sqwidth = PokemonRegionMap_Scene::SQUARE_WIDTH
sqheight = PokemonRegionMap_Scene::SQUARE_HEIGHT
town_map_width = 1 + RIGHT - LEFT
sqwidth = SQUARE_WIDTH
sqheight = SQUARE_HEIGHT
points.length.times do |j|
next if !points[j]
x = (j % town_map_width) * sqwidth

View File

@@ -164,11 +164,10 @@ MenuHandlers.add(:pokegear_menu, :map, {
"order" => 10,
"effect" => proc { |menu|
pbFadeOutIn do
scene = PokemonRegionMap_Scene.new(-1, false)
screen = PokemonRegionMapScreen.new(scene)
ret = screen.pbStartScreen
if ret
$game_temp.fly_destination = ret
town_map_screen = UI::TownMap.new
town_map_screen.main
if town_map_screen.result
$game_temp.fly_destination = town_map_screen.result
menu.dispose
next 99999
end

View File

@@ -392,7 +392,7 @@ MenuHandlers.add(:options_menu, :bgm_volume, {
"set_proc" => proc { |value, scene|
next if $PokemonSystem.bgmvolume == value
$PokemonSystem.bgmvolume = value
next if scene.in_load_screen || $game_system.playing_bgm.nil?
next if scene.in_load_screen || !$game_system || $game_system.playing_bgm.nil?
playingBGM = $game_system.getPlayingBGM
$game_system.bgm_pause
$game_system.bgm_resume(playingBGM)
@@ -409,7 +409,7 @@ MenuHandlers.add(:options_menu, :se_volume, {
"set_proc" => proc { |value, _scene|
next if $PokemonSystem.sevolume == value
$PokemonSystem.sevolume = value
if $game_system.playing_bgs
if $game_system && $game_system.playing_bgs
$game_system.playing_bgs.volume = value
playingBGS = $game_system.getPlayingBGS
$game_system.bgs_pause

View File

@@ -82,7 +82,7 @@ class ReadyMenuButton < Sprite
textpos.push([_INTL(">99"), 230, 24, :right,
Color.new(248, 248, 248), Color.new(40, 40, 40), :outline])
else
textpos.push([_INTL("x{1}", qty), 230, 24, :right,
textpos.push([_INTL("×{1}", qty), 230, 24, :right,
Color.new(248, 248, 248), Color.new(40, 40, 40), :outline])
end
end
@@ -261,11 +261,11 @@ class PokemonReadyMenu
user = $player.party[commands[0][command[1]][3]]
if move == :FLY
ret = nil
pbFadeOutInWithUpdate(99999, @scene.sprites) do
pbFadeOutInWithUpdate(@scene.sprites) do
pbHideMenu
scene = PokemonRegionMap_Scene.new(-1, false)
screen = PokemonRegionMapScreen.new(scene)
ret = screen.pbStartFlyScreen
town_map_screen = UI::TownMap.new(mode: :fly)
town_map_screen.main
ret = town_map_screen.result
pbShowMenu if !ret
end
if ret

View File

@@ -1,3 +1,5 @@
# TODO: Could inherit from class UI::BagVisuals and just change some graphics.
#===============================================================================
#
#===============================================================================
@@ -14,7 +16,6 @@ class Window_PokemonItemStorage < Window_DrawableCommand
def initialize(bag, x, y, width, height)
@bag = bag
@sortIndex = -1
@adapter = PokemonMartAdapter.new
super(x, y, width, height)
self.windowskin = nil
end
@@ -35,11 +36,11 @@ class Window_PokemonItemStorage < Window_DrawableCommand
textpos.push([_INTL("CANCEL"), rect.x, rect.y, :left, self.baseColor, self.shadowColor])
else
item = @bag[index][0]
itemname = @adapter.getDisplayName(item)
itemname = GameData::Item.get(item).display_name
baseColor = (index == @sortIndex) ? Color.new(248, 24, 24) : self.baseColor
textpos.push([itemname, rect.x, rect.y, :left, self.baseColor, self.shadowColor])
if GameData::Item.get(item).show_quantity?
qty = _ISPRINTF("x{1: 2d}", @bag[index][1])
qty = _ISPRINTF("×{1: 2d}", @bag[index][1])
sizeQty = self.contents.text_size(qty).width
xQty = rect.x + rect.width - sizeQty - 2
textpos.push([qty, xQty, rect.y, :left, baseColor, self.shadowColor])
@@ -76,7 +77,7 @@ class ItemStorage_Scene
@sprites = {}
@sprites["background"] = IconSprite.new(0, 0, @viewport)
@sprites["background"].setBitmap("Graphics/UI/itemstorage_bg")
@sprites["icon"] = ItemIconSprite.new(50, 334, nil, @viewport)
@sprites["icon"] = ItemIconSprite.new(48, Graphics.height - 48, nil, @viewport)
# Item list
@sprites["itemwindow"] = Window_PokemonItemStorage.new(@bag, 98, 14, 334, 32 + (ITEMSVISIBLE * 32))
@sprites["itemwindow"].viewport = @viewport
@@ -90,7 +91,7 @@ class ItemStorage_Scene
@sprites["pocketwindow"].y = 16
pbSetNarrowFont(@sprites["pocketwindow"].bitmap)
# Item description
@sprites["itemtextwindow"] = Window_UnformattedTextPokemon.newWithSize("", 84, 272, Graphics.width - 84, 128, @viewport)
@sprites["itemtextwindow"] = Window_UnformattedTextPokemon.newWithSize("", 80, 272, Graphics.width - 98, 128, @viewport)
@sprites["itemtextwindow"].baseColor = ITEMTEXTBASECOLOR
@sprites["itemtextwindow"].shadowColor = ITEMTEXTSHADOWCOLOR
@sprites["itemtextwindow"].windowskin = nil
@@ -190,6 +191,93 @@ class TossItemScene < ItemStorage_Scene
end
end
#===============================================================================
#
#===============================================================================
class ItemStorageScreen
def initialize(scene, bag)
@bag = bag
@scene = scene
end
def pbDisplay(text)
@scene.pbDisplay(text)
end
def pbConfirm(text)
return @scene.pbConfirm(text)
end
# UI logic for withdrawing an item in the item storage screen.
def pbWithdrawItemScreen
if !$PokemonGlobal.pcItemStorage
$PokemonGlobal.pcItemStorage = PCItemStorage.new
end
storage = $PokemonGlobal.pcItemStorage
@scene.pbStartScene(storage)
loop do
item = @scene.pbChooseItem
break if !item
itm = GameData::Item.get(item)
qty = storage.quantity(item)
if qty > 1 && !itm.is_important?
qty = @scene.pbChooseNumber(_INTL("How many do you want to withdraw?"), qty)
end
next if qty <= 0
if @bag.can_add?(item, qty)
if !storage.remove(item, qty)
raise "Can't delete items from storage"
end
if !@bag.add(item, qty)
raise "Can't withdraw items from storage"
end
@scene.pbRefresh
dispqty = (itm.is_important?) ? 1 : qty
itemname = (dispqty > 1) ? itm.portion_name_plural : itm.portion_name
pbDisplay(_INTL("Withdrew {1} {2}.", dispqty, itemname))
else
pbDisplay(_INTL("There's no more room in the Bag."))
end
end
@scene.pbEndScene
end
# UI logic for tossing an item in the item storage screen.
def pbTossItemScreen
if !$PokemonGlobal.pcItemStorage
$PokemonGlobal.pcItemStorage = PCItemStorage.new
end
storage = $PokemonGlobal.pcItemStorage
@scene.pbStartScene(storage)
loop do
item = @scene.pbChooseItem
break if !item
itm = GameData::Item.get(item)
if itm.is_important?
@scene.pbDisplay(_INTL("That's too important to toss out!"))
next
end
qty = storage.quantity(item)
itemname = itm.portion_name
itemnameplural = itm.portion_name_plural
if qty > 1
qty = @scene.pbChooseNumber(_INTL("Toss out how many {1}?", itemnameplural), qty)
end
next if qty <= 0
itemname = itemnameplural if qty > 1
next if !pbConfirm(_INTL("Is it OK to throw away {1} {2}?", qty, itemname))
if !storage.remove(item, qty)
raise "Can't delete items from storage"
end
@scene.pbRefresh
pbDisplay(_INTL("Threw away {1} {2}.", qty, itemname))
end
@scene.pbEndScene
end
end
#===============================================================================
# Common UI functions used in both the Bag and item storage screens.
# Displays messages and allows the user to choose a number/command.
@@ -282,10 +370,10 @@ module UIHelper
helpwindow.letterbyletter = false
curnumber = initnum
ret = 0
numwindow = Window_UnformattedTextPokemon.new("x000")
numwindow = Window_UnformattedTextPokemon.new("×000")
numwindow.viewport = helpwindow.viewport
numwindow.letterbyletter = false
numwindow.text = _ISPRINTF("x{1:03d}", curnumber)
numwindow.text = _ISPRINTF("×{1:03d}", curnumber)
numwindow.resizeToFit(numwindow.text, Graphics.width)
pbBottomRight(numwindow)
helpwindow.resizeHeightToFit(helpwindow.text, Graphics.width - numwindow.width)
@@ -309,28 +397,28 @@ module UIHelper
curnumber += 1
curnumber = 1 if curnumber > maximum
if curnumber != oldnumber
numwindow.text = _ISPRINTF("x{1:03d}", curnumber)
numwindow.text = _ISPRINTF("×{1:03d}", curnumber)
pbPlayCursorSE
end
elsif Input.repeat?(Input::DOWN)
curnumber -= 1
curnumber = maximum if curnumber < 1
if curnumber != oldnumber
numwindow.text = _ISPRINTF("x{1:03d}", curnumber)
numwindow.text = _ISPRINTF("×{1:03d}", curnumber)
pbPlayCursorSE
end
elsif Input.repeat?(Input::LEFT)
curnumber -= 10
curnumber = 1 if curnumber < 1
if curnumber != oldnumber
numwindow.text = _ISPRINTF("x{1:03d}", curnumber)
numwindow.text = _ISPRINTF("×{1:03d}", curnumber)
pbPlayCursorSE
end
elsif Input.repeat?(Input::RIGHT)
curnumber += 10
curnumber = maximum if curnumber > maximum
if curnumber != oldnumber
numwindow.text = _ISPRINTF("x{1:03d}", curnumber)
numwindow.text = _ISPRINTF("×{1:03d}", curnumber)
pbPlayCursorSE
end
end

View File

@@ -1,238 +0,0 @@
#===============================================================================
#
#===============================================================================
def pbPCItemStorage
command = 0
loop do
command = pbShowCommandsWithHelp(nil,
[_INTL("Withdraw Item"),
_INTL("Deposit Item"),
_INTL("Toss Item"),
_INTL("Exit")],
[_INTL("Take out items from the PC."),
_INTL("Store items in the PC."),
_INTL("Throw away items stored in the PC."),
_INTL("Go back to the previous menu.")], -1, command)
case command
when 0 # Withdraw Item
if !$PokemonGlobal.pcItemStorage
$PokemonGlobal.pcItemStorage = PCItemStorage.new
end
if $PokemonGlobal.pcItemStorage.empty?
pbMessage(_INTL("There are no items."))
else
pbFadeOutIn do
scene = WithdrawItemScene.new
screen = PokemonBagScreen.new(scene, $bag)
screen.pbWithdrawItemScreen
end
end
when 1 # Deposit Item
pbFadeOutIn do
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene, $bag)
screen.pbDepositItemScreen
end
when 2 # Toss Item
if !$PokemonGlobal.pcItemStorage
$PokemonGlobal.pcItemStorage = PCItemStorage.new
end
if $PokemonGlobal.pcItemStorage.empty?
pbMessage(_INTL("There are no items."))
else
pbFadeOutIn do
scene = TossItemScene.new
screen = PokemonBagScreen.new(scene, $bag)
screen.pbTossItemScreen
end
end
else
break
end
end
end
#===============================================================================
#
#===============================================================================
def pbPCMailbox
if !$PokemonGlobal.mailbox || $PokemonGlobal.mailbox.length == 0
pbMessage(_INTL("There's no Mail here."))
else
loop do
command = 0
commands = []
$PokemonGlobal.mailbox.each do |mail|
commands.push(mail.sender)
end
commands.push(_INTL("Cancel"))
command = pbShowCommands(nil, commands, -1, command)
if command >= 0 && command < $PokemonGlobal.mailbox.length
mailIndex = command
commandMail = pbMessage(
_INTL("What do you want to do with {1}'s Mail?", $PokemonGlobal.mailbox[mailIndex].sender),
[_INTL("Read"),
_INTL("Move to Bag"),
_INTL("Give"),
_INTL("Cancel")], -1
)
case commandMail
when 0 # Read
pbFadeOutIn do
pbDisplayMail($PokemonGlobal.mailbox[mailIndex])
end
when 1 # Move to Bag
if pbConfirmMessage(_INTL("The message will be lost. Is that OK?"))
if $bag.add($PokemonGlobal.mailbox[mailIndex].item)
pbMessage(_INTL("The Mail was returned to the Bag with its message erased."))
$PokemonGlobal.mailbox.delete_at(mailIndex)
else
pbMessage(_INTL("The Bag is full."))
end
end
when 2 # Give
pbFadeOutIn do
sscene = PokemonParty_Scene.new
sscreen = PokemonPartyScreen.new(sscene, $player.party)
sscreen.pbPokemonGiveMailScreen(mailIndex)
end
end
else
break
end
end
end
end
#===============================================================================
#
#===============================================================================
def pbTrainerPC
pbMessage("\\se[PC open]" + _INTL("{1} booted up the PC.", $player.name))
pbTrainerPCMenu
pbSEPlay("PC close")
end
def pbTrainerPCMenu
command = 0
loop do
command = pbMessage(_INTL("What do you want to do?"),
[_INTL("Item Storage"),
_INTL("Mailbox"),
_INTL("Turn Off")], -1, nil, command)
case command
when 0 then pbPCItemStorage
when 1 then pbPCMailbox
else break
end
end
end
#===============================================================================
#
#===============================================================================
def pbPokeCenterPC
pbMessage("\\se[PC open]" + _INTL("{1} booted up the PC.", $player.name))
# Get all commands
command_list = []
commands = []
MenuHandlers.each_available(:pc_menu) do |option, hash, name|
command_list.push(name)
commands.push(hash)
end
# Main loop
command = 0
loop do
choice = pbMessage(_INTL("Which PC should be accessed?"), command_list, -1, nil, command)
if choice < 0
pbPlayCloseMenuSE
break
end
break if commands[choice]["effect"].call
end
pbSEPlay("PC close")
end
def pbGetStorageCreator
return GameData::Metadata.get.storage_creator
end
#===============================================================================
#
#===============================================================================
MenuHandlers.add(:pc_menu, :pokemon_storage, {
"name" => proc {
next ($player.seen_storage_creator) ? _INTL("{1}'s PC", pbGetStorageCreator) : _INTL("Someone's PC")
},
"order" => 10,
"effect" => proc { |menu|
pbMessage("\\se[PC access]" + _INTL("The Pokémon Storage System was opened."))
command = 0
loop do
command = pbShowCommandsWithHelp(nil,
[_INTL("Organize Boxes"),
_INTL("Withdraw Pokémon"),
_INTL("Deposit Pokémon"),
_INTL("See ya!")],
[_INTL("Organize the Pokémon in Boxes and in your party."),
_INTL("Move Pokémon stored in Boxes to your party."),
_INTL("Store Pokémon in your party in Boxes."),
_INTL("Return to the previous menu.")], -1, command)
break if command < 0
case command
when 0 # Organize
pbFadeOutIn do
scene = PokemonStorageScene.new
screen = PokemonStorageScreen.new(scene, $PokemonStorage)
screen.pbStartScreen(0)
end
when 1 # Withdraw
if $PokemonStorage.party_full?
pbMessage(_INTL("Your party is full!"))
next
end
pbFadeOutIn do
scene = PokemonStorageScene.new
screen = PokemonStorageScreen.new(scene, $PokemonStorage)
screen.pbStartScreen(1)
end
when 2 # Deposit
count = 0
$PokemonStorage.party.each do |p|
count += 1 if p && !p.egg? && p.hp > 0
end
if count <= 1
pbMessage(_INTL("Can't deposit the last Pokémon!"))
next
end
pbFadeOutIn do
scene = PokemonStorageScene.new
screen = PokemonStorageScreen.new(scene, $PokemonStorage)
screen.pbStartScreen(2)
end
else
break
end
end
next false
}
})
MenuHandlers.add(:pc_menu, :player_pc, {
"name" => proc { next _INTL("{1}'s PC", $player.name) },
"order" => 20,
"effect" => proc { |menu|
pbMessage("\\se[PC access]" + _INTL("Accessed {1}'s PC.", $player.name))
pbTrainerPCMenu
next false
}
})
MenuHandlers.add(:pc_menu, :close, {
"name" => _INTL("Log off"),
"order" => 100,
"effect" => proc { |menu|
next true
}
})

View File

@@ -1232,9 +1232,7 @@ class PurifyChamberScene
def pbSummary(pos, heldpkmn)
if heldpkmn
oldsprites = pbFadeOutAndHide(@sprites)
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene)
screen.pbStartScreen([heldpkmn], 0)
UI::PokemonSummary.new(heldpkmn).main
pbFadeInAndShow(@sprites, oldsprites)
return
end
@@ -1251,9 +1249,8 @@ class PurifyChamberScene
end
return if party.length == 0
oldsprites = pbFadeOutAndHide(@sprites)
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene)
selection = screen.pbStartScreen(party, startindex)
screen = UI::PokemonSummary.new(party, startindex).main
selection = screen.result
@sprites["setview"].cursor = indexes[selection]
pbFadeInAndShow(@sprites, oldsprites)
end
@@ -1270,13 +1267,19 @@ class PurifyChamberScene
pbRefresh
end
# TODO: Depending on which position is selected, make Shadow Pokémon/non-Shadow
# Pokémon in UI::PokemonStorage semi-transparent and don't let them be
# selected.
# TODO: Don't let eggs be selected.
# TODO: Don't let the last able Pokémon in the party be selected.
def pbChoosePokemon
visible = pbFadeOutAndHide(@sprites)
scene = PokemonStorageScene.new
screen = PokemonStorageScreen.new(scene, $PokemonStorage)
pos = screen.pbChoosePokemon
pbRefresh
pbFadeInAndShow(@sprites, visible)
pos = nil
pbFadeOutInWithUpdate(@sprites) do
screen = UI::PokemonStorage.new($PokemonStorage, mode: :choose_pokemon)
screen.main
pos = screen.result
pbRefresh
end
return pos
end
end

View File

@@ -226,7 +226,7 @@ def pbRefreshMGCommands(master, online)
elsif gift[1] > 0
itemname = GameData::Item.get(gift[2]).name + sprintf(" x%d", gift[1])
end
ontext = ["[ ]", "[X]"][(online.include?(gift[0])) ? 1 : 0]
ontext = ["[ ]", "[Y]"][(online.include?(gift[0])) ? 1 : 0]
commands.push(_INTL("{1} {2}: {3} ({4})", ontext, gift[0], gift[3], itemname))
end
commands.push(_INTL("Export selected to file"))

View File

@@ -779,6 +779,8 @@ def pbEnterNPCName(helptext, minlength, maxlength, initialText = "", id = 0, nof
return pbEnterText(helptext, minlength, maxlength, initialText, 3, id, nofadeout)
end
# TODO: maxlength for this is 16, so the entry screen should support showing 16
# characters.
def pbEnterBoxName(helptext, minlength, maxlength, initialText = "", nofadeout = false)
return pbEnterText(helptext, minlength, maxlength, initialText, 4, nil, nofadeout)
end

View File

@@ -0,0 +1,863 @@
module UI
#=============================================================================
# The visuals class.
#=============================================================================
module SpriteContainerMixin
UI_FOLDER = "Graphics/UI/"
GRAPHICS_FOLDER = "" # Subfolder in UI_FOLDER
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
:default => [Color.new(72, 72, 72), Color.new(160, 160, 160)] # Base and shadow colour
}
def add_overlay(overlay, overlay_width = -1, overlay_height = -1)
overlay_width = Graphics.width if overlay_width < 0
overlay_height = Graphics.height if overlay_height < 0
@sprites[overlay] = BitmapSprite.new(overlay_width, overlay_height, @viewport)
@sprites[overlay].z = 1000
self.class::TEXT_COLOR_THEMES.each_pair { |key, values| @sprites[overlay].add_text_theme(key, *values) }
pbSetSystemFont(@sprites[overlay].bitmap)
end
def add_icon_sprite(key, x, y, filename = nil)
@sprites[key] = IconSprite.new(x, y, @viewport)
@sprites[key].setBitmap(filename) if filename
end
def add_animated_arrow(key, x, y, direction)
case direction
when :up
@sprites[key] = AnimatedSprite.new(UI_FOLDER + "up_arrow", 8, 28, 40, 2, @viewport)
when :down
@sprites[key] = AnimatedSprite.new(UI_FOLDER + "down_arrow", 8, 28, 40, 2, @viewport)
when :left
@sprites[key] = AnimatedSprite.new(UI_FOLDER + "left_arrow", 8, 40, 28, 2, @viewport)
when :right
@sprites[key] = AnimatedSprite.new(UI_FOLDER + "right_arrow", 8, 40, 28, 2, @viewport)
end
@sprites[key].x = x
@sprites[key].y = y
@sprites[key].visible = false
@sprites[key].play
end
#---------------------------------------------------------------------------
def dispose
@sprites.each_value { |s| s.dispose if s && !s.disposed? }
@sprites.clear
@bitmaps.each_value { |b| b.dispose if b && !b.disposed? }
@bitmaps.clear
@disposed = true
end
def disposed?
return !!@disposed
end
#---------------------------------------------------------------------------
def graphics_folder
return UI_FOLDER + self.class::GRAPHICS_FOLDER
end
def background_filename
return gendered_filename(self.class::BACKGROUND_FILENAME)
end
def gendered_filename(base_filename)
return filename_with_appendix(base_filename, "_f") if $player&.female?
return base_filename
end
def filename_with_appendix(base_filename, appendix)
if appendix && appendix != ""
trial_filename = base_filename + appendix
return trial_filename if pbResolveBitmap(graphics_folder + trial_filename)
end
return base_filename
end
#---------------------------------------------------------------------------
# NOTE: max_width should include the width of the text shadow at the end of
# the string (because characters in the font have a blank 2 pixels
# after them for the shadow to occupy).
def crop_text(string, max_width, continue_string = "", overlay: :overlay)
return string if max_width <= 0
return string if @sprites[overlay].bitmap.text_size(string).width <= max_width
ret = string
continue_width = @sprites[overlay].bitmap.text_size(continue_string).width
loop do
ret = ret[0...-1]
break if @sprites[overlay].bitmap.text_size(ret).width <= max_width - continue_width
end
ret += continue_string
return ret
end
#---------------------------------------------------------------------------
def draw_text(string, text_x, text_y, align: :left, theme: :default, outline: :shadow, overlay: :overlay)
@sprites[overlay].draw_themed_text(string.to_s, text_x, text_y, align, theme, outline)
end
def draw_paragraph_text(string, text_x, text_y, text_width, num_lines, theme: :default, overlay: :overlay)
drawTextEx(@sprites[overlay].bitmap, text_x, text_y, text_width, num_lines,
string, *self.class::TEXT_COLOR_THEMES[theme])
end
# NOTE: This also draws string in a paragraph, but with no limit on the
# number of lines.
def draw_formatted_text(string, text_x, text_y, text_width, theme: :default, overlay: :overlay)
drawFormattedTextEx(@sprites[overlay].bitmap, text_x, text_y, text_width,
string, *self.class::TEXT_COLOR_THEMES[theme])
end
def draw_image(filename, image_x, image_y, src_x = 0, src_y = 0, src_width = -1, src_height = -1, overlay: :overlay)
@sprites[overlay].draw_image(filename, image_x, image_y, src_x, src_y, src_width, src_height)
end
# The image is assumed to be the digits 0-9 and then a "/", all the same
# width, in a horizontal row.
def draw_number_from_image(bitmap, string, text_x, text_y, align: :left, overlay: :overlay)
string = string.to_s
raise _INTL("Can't draw {1} as a number.", string) if !string.scan(/[^\d\/]/).empty?
char_width = bitmap.width / 11
char_height = bitmap.height
chars = string.split(//)
chars.reverse! if align == :right
chars.length.times do |i|
char = chars[i]
index = (char == "/") ? 10 : char.to_i
char_x = (align == :right) ? text_x - ((i + 1) * char_width) : text_x + (i * char_width)
draw_image(bitmap, char_x, text_y,
index * char_width, 0, char_width, char_height, overlay: overlay)
end
end
SLIDER_COORDS = { # Size of elements in slider graphic
:arrow_size => [24, 28],
:box_heights => [4, 8, 18] # Heights of top, middle and bottom segments of slider box
}
# slider_height includes the heights of the arrows at either end.
def draw_slider(bitmap, slider_x, slider_y, slider_height, visible_top, visible_height, total_height, hide_if_inactive: :false, overlay: :overlay)
coords = self.class::SLIDER_COORDS
bar_y = slider_y + coords[:arrow_size][1]
bar_height = slider_height - (2 * coords[:arrow_size][1])
bar_segment_height = coords[:box_heights].sum # Also minimum height of slider box
show_up_arrow = (visible_top > 0)
show_down_arrow = (visible_top + visible_height < total_height)
return if hide_if_inactive && !show_up_arrow && !show_down_arrow
# Draw up arrow
x_offset = (show_up_arrow) ? coords[:arrow_size][0] : 0
draw_image(bitmap, slider_x, slider_y,
x_offset, 0, *coords[:arrow_size], overlay: overlay)
# Draw down arrow
x_offset = (show_down_arrow) ? coords[:arrow_size][0] : 0
draw_image(bitmap, slider_x, slider_y + slider_height - coords[:arrow_size][1],
x_offset, coords[:arrow_size][1] + bar_segment_height, *coords[:arrow_size], overlay: overlay)
# Draw bar background
iterations = (bar_height / bar_segment_height.to_f).ceil
iterations.times do |i|
segment_y = bar_y + (i * bar_segment_height)
iteration_height = bar_segment_height
iteration_height = bar_height - (i * bar_segment_height) if i == iterations - 1 # Last part
draw_image(bitmap, slider_x, segment_y,
0, coords[:arrow_size][1], coords[:arrow_size][0], iteration_height, overlay: overlay)
end
# Draw slider box
if show_up_arrow || show_down_arrow
box_height = (bar_height * visible_height / total_height).floor
box_height += [(bar_height - box_height) / 2, bar_height / 6].min # Make it bigger than expected
box_height = [box_height.floor, bar_segment_height].max
box_y = bar_y
box_y += ((bar_height - box_height) * visible_top / (total_height - visible_height)).floor
# Draw slider box top
draw_image(bitmap, slider_x, box_y,
coords[:arrow_size][0], coords[:arrow_size][1],
coords[:arrow_size][0], coords[:box_heights][0], overlay: overlay)
# Draw slider box middle
middle_height = box_height - coords[:box_heights][0] - coords[:box_heights][2]
iterations = (middle_height / coords[:box_heights][1].to_f).ceil
iterations.times do |i|
segment_y = box_y + coords[:box_heights][0] + (i * coords[:box_heights][1])
iteration_height = coords[:box_heights][1]
iteration_height = middle_height - (i * coords[:box_heights][1]) if i == iterations - 1 # Last part
draw_image(bitmap, slider_x, segment_y,
coords[:arrow_size][0], coords[:arrow_size][1] + coords[:box_heights][0],
coords[:arrow_size][0], iteration_height, overlay: overlay)
end
# Draw slider box bottom
draw_image(bitmap, slider_x, box_y + box_height - coords[:box_heights][2],
coords[:arrow_size][0], coords[:arrow_size][1] + coords[:box_heights][0] + coords[:box_heights][1],
coords[:arrow_size][0], coords[:box_heights][2], overlay: overlay)
end
end
#---------------------------------------------------------------------------
# Redraw everything on the screen.
def refresh
refresh_overlay
end
def refresh_overlay
@sprites[:overlay].bitmap.clear if @sprites[:overlay]
end
#---------------------------------------------------------------------------
def update_visuals
pbUpdateSpriteHash(@sprites)
end
def update
update_visuals
end
end
#=============================================================================
# The visuals class.
#=============================================================================
class SpriteContainer
attr_reader :x, :y, :z, :visible, :color
include SpriteContainerMixin
def initialize(viewport)
@viewport = viewport
@x ||= 0
@y ||= 0
@z ||= 0
@visible = true
@color = Color.new(0, 0, 0, 0)
@bitmaps = {}
@sprites = {}
@sprites_values = {}
initialize_bitmaps
initialize_sprites
refresh_sprites_values
end
def initialize_bitmaps
end
def initialize_sprites
end
#---------------------------------------------------------------------------
# x, y, z, visible, opacity, color
def x=(value)
@x = value
@sprites.each_pair do |key, sprite|
sprite.x = @x + @sprites_values[key][:x]
end
end
def y=(value)
@y = value
@sprites.each_pair do |key, sprite|
sprite.y = @y + @sprites_values[key][:y]
end
end
def z=(value)
@z = value
@sprites.each_pair do |key, sprite|
sprite.z = @z + @sprites_values[key][:z]
end
end
def visible=(value)
@visible = value
@sprites.each_pair do |key, sprite|
sprite.visible = @visible && @sprites_values[key][:visible]
end
end
def color=(value)
@color = value
@sprites.each_pair do |key, sprite|
sprite.color = @color
end
end
#---------------------------------------------------------------------------
def record_values(key)
@sprites_values[key] ||= {}
@sprites_values[key][:x] = @sprites[key].x
@sprites_values[key][:y] = @sprites[key].y
@sprites_values[key][:z] = @sprites[key].z
@sprites_values[key][:visible] = @sprites[key].visible
end
def refresh_sprites_values
self.x = @x
self.y = @y
self.z = @z
self.visible = @visible
end
end
#=============================================================================
# The visuals class.
#=============================================================================
class BaseVisuals
attr_reader :sprites
attr_reader :mode
BACKGROUND_FILENAME = "bg"
include SpriteContainerMixin
def initialize
@bitmaps = {}
@sprites = {}
initialize_viewport
initialize_bitmaps
initialize_background
initialize_overlay
initialize_message_box
initialize_sprites
refresh
end
def initialize_viewport
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
end
def initialize_bitmaps
end
def initialize_background
addBackgroundPlane(@sprites, :background, self.class::GRAPHICS_FOLDER + background_filename, @viewport)
@sprites[:background].z = -1000
end
def initialize_overlay
add_overlay(:overlay)
end
def initialize_message_box
# TODO: It looks like :message_box isn't used anywhere.
@sprites[:message_box] = Window_AdvancedTextPokemon.new("")
@sprites[:message_box].viewport = @viewport
@sprites[:message_box].z = 2000
@sprites[:message_box].visible = false
@sprites[:message_box].letterbyletter = true
pbBottomLeftLines(@sprites[:message_box], 2)
@sprites[:speech_box] = Window_AdvancedTextPokemon.new("")
@sprites[:speech_box].viewport = @viewport
@sprites[:speech_box].z = 2001
@sprites[:speech_box].visible = false
@sprites[:speech_box].letterbyletter = true
@sprites[:speech_box].setSkin(MessageConfig.pbGetSpeechFrame)
pbBottomLeftLines(@sprites[:speech_box], 2)
end
def initialize_sprites
end
#---------------------------------------------------------------------------
def set_viewport_color(new_color)
@viewport.color = new_color
end
def fade_in
duration = 0.4 # In seconds
col = Color.new(0, 0, 0, 0)
timer_start = System.uptime
loop do
col.set(0, 0, 0, lerp(255, 0, duration, timer_start, System.uptime))
set_viewport_color(col)
Graphics.update
Input.update
update_visuals
break if col.alpha == 0
end
end
def fade_out
duration = 0.4 # In seconds
col = Color.new(0, 0, 0, 0)
timer_start = System.uptime
loop do
col.set(0, 0, 0, lerp(0, 255, duration, timer_start, System.uptime))
set_viewport_color(col)
Graphics.update
Input.update
update_visuals
break if col.alpha == 255
end
end
def dispose
super
@viewport.dispose
end
#---------------------------------------------------------------------------
def index
return 0
end
#---------------------------------------------------------------------------
def position_speech_box(text = "")
pbBottomLeftLines(@sprites[:speech_box], 2)
end
def show_message(text)
@sprites[:speech_box].visible = true
@sprites[:speech_box].text = text
position_speech_box(text)
yielded = false
loop do
Graphics.update
Input.update
update_visuals
if @sprites[:speech_box].busy?
if Input.trigger?(Input::USE)
pbPlayDecisionSE if @sprites[:speech_box].pausing?
@sprites[:speech_box].resume
end
else
yield if !yielded && block_given?
yielded = true
if Input.trigger?(Input::USE) || Input.trigger?(Input::BACK)
break
end
end
end
@sprites[:speech_box].visible = false
end
def show_confirm_message(text)
ret = false
@sprites[:speech_box].visible = true
@sprites[:speech_box].text = text
position_speech_box(text)
using(cmd_window = Window_CommandPokemon.new([_INTL("Yes"), _INTL("No")])) do
cmd_window.z = @viewport.z + 1
cmd_window.visible = false
pbBottomRight(cmd_window)
cmd_window.y -= @sprites[:speech_box].height
cmd_window.visible = true if !@sprites[:speech_box].busy?
loop do
Graphics.update
Input.update
update_visuals
cmd_window.visible = true if !@sprites[:speech_box].busy?
cmd_window.update
if !@sprites[:speech_box].busy?
if Input.trigger?(Input::BACK)
pbPlayCancelSE
ret = false
break
elsif Input.trigger?(Input::USE) && @sprites[:speech_box].resume
pbPlayDecisionSE
ret = (cmd_window.index == 0)
break
end
end
end
end
@sprites[:speech_box].visible = false
return ret
end
def show_confirm_serious_message(text)
ret = false
@sprites[:speech_box].visible = true
@sprites[:speech_box].text = text
position_speech_box(text)
using(cmd_window = Window_CommandPokemon.new([_INTL("No"), _INTL("Yes")])) do
cmd_window.z = @viewport.z + 1
cmd_window.visible = false
pbBottomRight(cmd_window)
cmd_window.y -= @sprites[:speech_box].height
cmd_window.visible = true if !@sprites[:speech_box].busy?
loop do
Graphics.update
Input.update
update_visuals
cmd_window.visible = true if !@sprites[:speech_box].busy?
cmd_window.update
if !@sprites[:speech_box].busy?
if Input.trigger?(Input::BACK)
pbPlayCancelSE
ret = false
break
elsif Input.trigger?(Input::USE) && @sprites[:speech_box].resume
pbPlayDecisionSE
ret = (cmd_window.index == 1)
break
end
end
end
end
@sprites[:speech_box].visible = false
return ret
end
# Used for dialogue.
# align: Where the command window is in relation to the message window.
# :horizontal is side by side, :vertical is command window above.
def show_choice_message(text, options, index = 0, align: :vertical, cmd_side: :right)
ret = -1
commands = options
commands = options.values if options.is_a?(Hash)
@sprites[:speech_box].visible = true
@sprites[:speech_box].text = text
using(cmd_window = Window_AdvancedCommandPokemon.new(commands)) do
if align == :vertical
@sprites[:speech_box].resizeHeightToFit(text, Graphics.width)
else
@sprites[:speech_box].resizeHeightToFit(text, Graphics.width - cmd_window.width)
end
cmd_window.z = @viewport.z + 1
cmd_window.visible = false
cmd_window.index = index
if cmd_side == :right
pbBottomLeft(@sprites[:speech_box])
pbBottomRight(cmd_window)
else
pbBottomRight(@sprites[:speech_box])
pbBottomLeft(cmd_window)
end
if align == :vertical
cmd_window.height = [cmd_window.height, Graphics.height - @sprites[:speech_box].height].min
cmd_window.y = Graphics.height - @sprites[:speech_box].height - cmd_window.height
end
cmd_window.visible = true if !@sprites[:speech_box].busy?
loop do
Graphics.update
Input.update
update_visuals
cmd_window.visible = true if !@sprites[:speech_box].busy?
cmd_window.update
if !@sprites[:speech_box].busy?
if Input.trigger?(Input::BACK)
pbPlayCancelSE
ret = -1
break
elsif Input.trigger?(Input::USE) && @sprites[:speech_box].resume
pbPlayDecisionSE
ret = cmd_window.index
break
end
end
end
end
@sprites[:speech_box].visible = false
if options.is_a?(Hash)
ret = (ret < 0) ? nil : options.keys[ret]
end
return ret
end
def show_menu(text, options, index = 0, cmd_side: :right)
old_letter_by_letter = @sprites[:speech_box].letterbyletter
@sprites[:speech_box].letterbyletter = false
ret = show_choice_message(text, options, index, align: :horizontal, cmd_side: cmd_side)
@sprites[:speech_box].letterbyletter = old_letter_by_letter
return ret
end
def show_choice(options, index = 0)
ret = -1
commands = options
commands = options.values if options.is_a?(Hash)
using(cmd_window = Window_AdvancedCommandPokemon.new(commands)) do
cmd_window.z = @viewport.z + 1
cmd_window.index = index
pbBottomRight(cmd_window)
loop do
Graphics.update
Input.update
update_visuals
cmd_window.update
if Input.trigger?(Input::BACK)
pbPlayCancelSE
ret = -1
break
elsif Input.trigger?(Input::USE)
pbPlayDecisionSE
ret = cmd_window.index
break
end
end
end
ret = options.keys[ret] if options.is_a?(Hash)
return ret
end
# TODO: Rewrite this.
def choose_number(help_text, maximum, init_value = 1)
if maximum.is_a?(ChooseNumberParams)
return pbMessageChooseNumber(help_text, maximum) { update_visuals }
end
return UIHelper.pbChooseNumber(@sprites[:speech_box], help_text, maximum, init_value) { update_visuals }
end
def choose_number_as_money_multiplier(help_text, money_per_unit, maximum, init_value = 1)
@sprites[:speech_box].visible = true
@sprites[:speech_box].text = help_text
position_speech_box(help_text)
# Show the help text
loop do
Graphics.update
Input.update
update_visuals
if @sprites[:speech_box].busy?
if Input.trigger?(Input::USE)
pbPlayDecisionSE if @sprites[:speech_box].pausing?
@sprites[:speech_box].resume
end
else
break
end
end
# Choose a quantity
item_price = money_per_unit
quantity = init_value
using(num_window = Window_AdvancedTextPokemon.newWithSize(
_INTL("×{1}<r>${2}", quantity, (quantity * item_price).to_s_formatted),
0, 0, 224, 64, @viewport)) do
num_window.z = 2000
num_window.visible = true
num_window.letterbyletter = false
pbBottomRight(num_window)
num_window.y -= @sprites[:speech_box].height
loop do
Graphics.update
Input.update
update
num_window.update
# Change quantity
old_quantity = quantity
if Input.repeat?(Input::LEFT)
quantity = [quantity - 10, 1].max
elsif Input.repeat?(Input::RIGHT)
quantity = [quantity + 10, maximum].min
elsif Input.repeat?(Input::UP)
quantity += 1
quantity = 1 if quantity > maximum
elsif Input.repeat?(Input::DOWN)
quantity -= 1
quantity = maximum if quantity < 1
end
if quantity != old_quantity
num_window.text = _INTL("×{1}<r>${2}", quantity, (quantity * item_price).to_s_formatted)
pbPlayCursorSE
end
# Finish choosing a quantity
if Input.trigger?(Input::USE)
pbPlayDecisionSE
break
elsif Input.trigger?(Input::BACK)
pbPlayCancelSE
quantity = 0
break
end
end
end
@sprites[:speech_box].visible = false
return quantity
end
#---------------------------------------------------------------------------
def refresh_on_index_changed(old_index)
end
#---------------------------------------------------------------------------
def update_input
if Input.trigger?(Input::BACK)
return :quit
end
return nil
end
#---------------------------------------------------------------------------
def navigate
ret = nil
loop do
Graphics.update
Input.update
old_index = index
update_visuals
refresh_on_index_changed(old_index) if index != old_index
old_index = index
ret = update_input
refresh_on_index_changed(old_index) if index != old_index
break if ret
end
return ret
end
end
#=============================================================================
# The logic class.
#=============================================================================
class BaseScreen
attr_reader :visuals
attr_reader :mode
attr_accessor :result
def initialize
@disposed = false
initialize_visuals
end
def initialize_visuals
@visuals = UI::BaseVisuals.new
end
def start_screen
@visuals.fade_in
end
def end_screen
return if @disposed
@visuals.fade_out
@visuals.dispose
@disposed = true
end
# Same as def end_screen but without fading out.
def silent_end_screen
return if @disposed
@visuals.dispose
@disposed = true
end
#-----------------------------------------------------------------------------
def sprites
return @visuals.sprites
end
def index
return @visuals.index
end
#-----------------------------------------------------------------------------
def show_message(text, &block)
@visuals.show_message(text, &block)
end
alias pbDisplay show_message
def show_confirm_message(text)
return @visuals.show_confirm_message(text)
end
alias pbConfirm show_confirm_message
def show_confirm_serious_message(text)
return @visuals.show_confirm_serious_message(text)
end
def show_choice_message(text, options, initial_index = 0)
return @visuals.show_choice_message(text, options, initial_index)
end
alias pbShowCommands show_choice_message
def show_menu(text, options, initial_index = 0, cmd_side: :right)
return @visuals.show_menu(text, options, initial_index, cmd_side: cmd_side)
end
def show_choice(options, initial_index = 0)
return @visuals.show_choice(options, initial_index)
end
def show_choice_from_menu_handler(menu_handler_id, message = nil)
commands = {}
MenuHandlers.each_available(menu_handler_id, self) do |option, _hash, name|
commands[option] = name
end
return show_menu(message, commands) if message
return show_choice(commands)
end
def choose_number(help_text, maximum, init_value = 1)
return @visuals.choose_number(help_text, maximum, init_value)
end
alias pbChooseNumber choose_number
def choose_number_as_money_multiplier(help_text, money_per_unit, maximum, init_value = 1)
return @visuals.choose_number_as_money_multiplier(help_text, money_per_unit, maximum, init_value)
end
#-----------------------------------------------------------------------------
def refresh
@visuals.refresh
end
alias pbRefresh refresh
def update
@visuals.update
end
alias pbUpdate update
#-----------------------------------------------------------------------------
def show_and_hide
start_screen
yield if block_given?
end_screen
end
def main
return if @disposed
start_screen
loop do
on_start_main_loop
command = @visuals.navigate
break if command == :quit
command = perform_action(command)
break if command == :quit
break if @disposed
end
end_screen
end
def on_start_main_loop
end
def perform_action(command)
return nil if !self.class::SCREEN_ID
action_hash = UIActionHandlers.get(self.class::SCREEN_ID, command)
return nil if !action_hash
return nil if action_hash[:condition] && !action_hash[:condition].call(self)
if action_hash[:menu]
choice = show_choice_from_menu_handler(action_hash[:menu], action_hash[:menu_message]&.call(self))
return perform_action(choice) if choice
elsif action_hash[:effect]
return perform_action_effect(action_hash)
end
return nil
end
def perform_action_effect(action_hash)
ret = action_hash[:effect].call(self)
return ret if action_hash[:returns_value]
return nil
end
end
end

View File

@@ -0,0 +1,346 @@
#===============================================================================
#
#===============================================================================
class UI::PauseMenuVisuals < UI::BaseVisuals
def initialize
@info_text_visible = false
# @help_text_visible = false
super
end
def initialize_background; end
def initialize_overlay; end
def initialize_sprites
# Pause menu
@sprites[:commands] = Window_CommandPokemon.new([])
@sprites[:commands].visible = false
@sprites[:commands].viewport = @viewport
# Info text box
@sprites[:info_text] = Window_UnformattedTextPokemon.newWithSize("", 0, 0, 32, 32, @viewport)
@sprites[:info_text].visible = false
# Help text box
# @sprites[:help_text] = Window_UnformattedTextPokemon.newWithSize("", 0, 0, 32, 32, @viewport)
# @sprites[:help_text].visible = false
end
#-----------------------------------------------------------------------------
# commands is [[command IDs], [command names]].
def set_commands(commands)
@commands = commands
cmd_window = @sprites[:commands]
cmd_window.commands = @commands[1]
cmd_window.index = $game_temp.menu_last_choice
cmd_window.resizeToFit(@commands[1])
cmd_window.x = Graphics.width - cmd_window.width
cmd_window.y = 0
cmd_window.visible = true
end
#-----------------------------------------------------------------------------
def show_menu
@sprites[:commands].visible = true
@sprites[:info_text].visible = @info_text_visible
# @sprites[:help_text].visible = @help_text_visible
end
def hide_menu
@sprites[:commands].visible = false
@sprites[:info_text].visible = false
# @sprites[:help_text].visible = false
end
# Used in Safari Zone and Bug-Catching Contest to show extra information.
def show_info(text)
@sprites[:info_text].resizeToFit(text, Graphics.height)
@sprites[:info_text].text = text
@sprites[:info_text].visible = true
@info_text_visible = true
end
# Unused.
# def show_help(text)
# @sprites[:help_text].resizeToFit(text, Graphics.height)
# @sprites[:help_text].text = text
# @sprites[:help_text].visible = true
# pbBottomLeft(@sprites[:help_text])
# @help_text_visible = true
# end
#-----------------------------------------------------------------------------
def update_visuals
pbUpdateSceneMap
super
end
def update_input
if Input.trigger?(Input::BACK) || Input.trigger?(Input::ACTION)
return :quit
end
if Input.trigger?(Input::USE)
idx = @sprites[:commands].index
$game_temp.menu_last_choice = idx
return @commands[0][idx]
end
return nil
end
end
#===============================================================================
#
#===============================================================================
class UI::PauseMenu < UI::BaseScreen
def initialize
raise _INTL("Tried to open the pause menu when $player was not defined.") if !$player
initialize_commands
super
end
def initialize_commands
@commands ||= [[], []]
@commands[0].clear
@commands[1].clear
@commands_hashes ||= {}
@commands_hashes.clear
MenuHandlers.each_available(:pause_menu) do |option, hash, name|
@commands[0].push(option)
@commands[1].push(name)
@commands_hashes[option] = hash
end
end
def initialize_visuals
@visuals = UI::PauseMenuVisuals.new
@visuals.set_commands(@commands)
show_info
end
def hide_menu
@visuals.hide_menu
end
def show_menu
@visuals.show_menu
end
def show_info; end
def start_screen
pbSEPlay("GUI menu open")
end
def end_screen
return if @disposed
pbPlayCloseMenuSE
silent_end_screen
end
#-----------------------------------------------------------------------------
def refresh
initialize_commands
@visuals.set_commands(@commands)
super
end
def perform_action(command)
if @commands_hashes[command]["effect"].call(self)
# NOTE: Calling end_screen will have been done in the "effect" proc, so
# there's no need to do anything special here to mark that this
# screen has already been closed/disposed of.
return :quit
end
return nil
end
end
#===============================================================================
# Pause menu commands.
#===============================================================================
MenuHandlers.add(:pause_menu, :pokedex, {
"name" => _INTL("Pokédex"),
"order" => 10,
"condition" => proc { next $player.has_pokedex && $player.pokedex.accessible_dexes.length > 0 },
"effect" => proc { |menu|
pbPlayDecisionSE
if Settings::USE_CURRENT_REGION_DEX
pbFadeOutIn do
scene = PokemonPokedex_Scene.new
screen = PokemonPokedexScreen.new(scene)
screen.pbStartScreen
menu.refresh
end
elsif $player.pokedex.accessible_dexes.length == 1
$PokemonGlobal.pokedexDex = $player.pokedex.accessible_dexes[0]
pbFadeOutIn do
scene = PokemonPokedex_Scene.new
screen = PokemonPokedexScreen.new(scene)
screen.pbStartScreen
menu.refresh
end
else
pbFadeOutIn do
scene = PokemonPokedexMenu_Scene.new
screen = PokemonPokedexMenuScreen.new(scene)
screen.pbStartScreen
menu.refresh
end
end
next false
}
})
MenuHandlers.add(:pause_menu, :party, {
"name" => _INTL("Pokémon"),
"order" => 20,
"condition" => proc { next $player.party_count > 0 },
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
UI::Party.new($player.party).main
($game_temp.field_move_to_use) ? menu.silent_end_screen : menu.refresh
end
next false if !$game_temp.field_move_to_use
$game_temp.in_menu = false
pbUseHiddenMove($game_temp.field_move_user, $game_temp.field_move_to_use)
$game_temp.field_move_user = nil
$game_temp.field_move_to_use = nil
next true
}
})
MenuHandlers.add(:pause_menu, :bag, {
"name" => _INTL("Bag"),
"order" => 30,
"condition" => proc { next !pbInBugContest? },
"effect" => proc { |menu|
pbPlayDecisionSE
item = nil
pbFadeOutIn do
bag_screen = UI::Bag.new($bag)
bag_screen.main
item = bag_screen.result
(item) ? menu.silent_end_screen : menu.refresh
end
next false if !item
$game_temp.in_menu = false
pbUseKeyItemInField(item)
next true
}
})
MenuHandlers.add(:pause_menu, :pokegear, {
"name" => _INTL("Pokégear"),
"order" => 40,
"condition" => proc { next $player.has_pokegear },
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
scene = PokemonPokegear_Scene.new
screen = PokemonPokegearScreen.new(scene)
screen.pbStartScreen
($game_temp.fly_destination) ? menu.silent_end_screen : menu.refresh
end
next pbFlyToNewLocation
}
})
MenuHandlers.add(:pause_menu, :town_map, {
"name" => _INTL("Town Map"),
"order" => 40,
"condition" => proc { next Settings::SHOW_TOWN_MAP_IN_PAUSE_MENU && !$player.has_pokegear && $bag.has?(:TOWNMAP) },
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
town_map_screen = UI::TownMap.new
town_map_screen.main
ret = town_map_screen.result
$game_temp.fly_destination = ret if ret
($game_temp.fly_destination) ? menu.silent_end_screen : menu.refresh
end
next pbFlyToNewLocation
}
})
MenuHandlers.add(:pause_menu, :trainer_card, {
"name" => proc { |menu| next $player.name },
"order" => 50,
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
UI::TrainerCard.new.main
menu.refresh
end
next false
}
})
MenuHandlers.add(:pause_menu, :save, {
"name" => _INTL("Save"),
"order" => 60,
"condition" => proc {
next $game_system && !$game_system.save_disabled && !pbInSafari? && !pbInBugContest?
},
"effect" => proc { |menu|
pbPlayDecisionSE
ret = false
pbFadeOutIn do
ret = UI::Save.new.main
if ret
menu.silent_end_screen
else
menu.refresh
end
end
next ret
}
})
MenuHandlers.add(:pause_menu, :options, {
"name" => _INTL("Options"),
"order" => 70,
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
scene = PokemonOption_Scene.new
screen = PokemonOptionScreen.new(scene)
screen.pbStartScreen
pbUpdateSceneMap
menu.refresh
end
next false
}
})
MenuHandlers.add(:pause_menu, :debug, {
"name" => _INTL("Debug"),
"order" => 80,
"condition" => proc { next $DEBUG },
"effect" => proc { |menu|
pbPlayDecisionSE
pbFadeOutIn do
pbDebugMenu
menu.refresh
end
next false
}
})
MenuHandlers.add(:pause_menu, :quit_game, {
"name" => _INTL("Quit Game"),
"order" => 90,
"effect" => proc { |menu|
menu.hide_menu
if pbConfirmMessage(_INTL("Are you sure you want to quit the game?"))
$scene = nil
next true
end
menu.refresh
menu.show_info
next false
}
})

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

@@ -0,0 +1,110 @@
#===============================================================================
#
#===============================================================================
class UI::TrainerCardVisuals < UI::BaseVisuals
GRAPHICS_FOLDER = "Trainer Card/" # Subfolder in Graphics/UI
BADGE_SIZE = [32, 32] # [width, height] of a Gym Badge
BADGE_SPACING = 16 # Size of gap between adjacent Gym Badges
FIRST_BADGE_X = 72 # Left edge of the first Gym Badge
FIRST_BADGE_Y = 310 # Top edge of the first Gym Badge
BADGE_COUNT = 8 # Number of Gym Badges to show
def initialize_sprites
# Trainer card
add_icon_sprite(:card, 0, 0, graphics_folder + gendered_filename(_INTL("trainer_card")))
# Player sprite (coordinates are the bottom middle of the sprite)
add_icon_sprite(:player, 400, 240, GameData::TrainerType.player_front_sprite_filename($player.trainer_type))
if !@sprites[:player].bitmap
raise _INTL("No trainer front sprite exists for the player character, expected a file at {1}.",
"Graphics/Trainers/" + $player.trainer_type.to_s + ".png")
end
@sprites[:player].x -= @sprites[:player].bitmap.width / 2
@sprites[:player].y -= @sprites[:player].bitmap.height
@sprites[:player].z = 10
end
#-----------------------------------------------------------------------------
def refresh_overlay
super
draw_ID
draw_stats
draw_badges
end
# Draws the player's name and ID number onto the overlay.
def draw_ID
draw_text(_INTL("Name"), 34, 70)
draw_text($player.name, 302, 70, align: :right)
draw_text(_INTL("ID No."), 332, 70)
draw_text(sprintf("%05d", $player.public_ID), 468, 70, align: :right)
end
# Draws the player's money, Pokédex numbers, play time and start date onto the
# overlay.
def draw_stats
# Create money text
money_text = _INTL("${1}", $player.money.to_s_formatted)
# Create Pokédex stats text
pokedex_text = sprintf("%d/%d", $player.pokedex.owned_count, $player.pokedex.seen_count)
# Create play time text
total_secs = $stats.play_time.to_i
hour = (total_secs / 60) / 60
min = (total_secs / 60) % 60
play_time_text = (hour > 0) ? _INTL("{1}h {2}m", hour, min) : _INTL("{1}m", min)
# Create start date text
$PokemonGlobal.startTime = Time.now if !$PokemonGlobal.startTime
if System.user_language[3..4] == "US"
start_date_text = _INTL("{1} {2}, {3}",
pbGetAbbrevMonthName($PokemonGlobal.startTime.mon),
$PokemonGlobal.startTime.day,
$PokemonGlobal.startTime.year)
else
start_date_text = _INTL("{1} {2}, {3}",
$PokemonGlobal.startTime.day,
pbGetAbbrevMonthName($PokemonGlobal.startTime.mon),
$PokemonGlobal.startTime.year)
end
# Draw text
draw_text(_INTL("Money"), 34, 118)
draw_text(money_text, 302, 118, align: :right)
draw_text(_INTL("Pokédex"), 34, 166)
draw_text(pokedex_text, 302, 166, align: :right)
draw_text(_INTL("Time"), 34, 214)
draw_text(play_time_text, 302, 214, align: :right)
draw_text(_INTL("Started"), 34, 262)
draw_text(start_date_text, 302, 262, align: :right)
end
# Draws the player's owned Gym Badges onto the overlay.
def draw_badges
x = FIRST_BADGE_X
region = pbGetCurrentRegion(0) # Get the current region
BADGE_COUNT.times do |i|
if $player.badges[i + (region * BADGE_COUNT)]
draw_image(graphics_folder + "icon_badges", x, FIRST_BADGE_Y,
i * BADGE_SIZE[0], region * BADGE_SIZE[1], *BADGE_SIZE)
end
x += BADGE_SIZE[0] + BADGE_SPACING
end
end
end
#===============================================================================
#
#===============================================================================
class UI::TrainerCard < UI::BaseScreen
def initialize_visuals
@visuals = UI::TrainerCardVisuals.new
end
def start_screen
super
pbSEPlay("GUI trainer card open")
end
def end_screen
pbPlayCloseMenuSE
super
end
end

View File

@@ -0,0 +1,769 @@
module UI::LoadSaveDataMixin
def load_all_save_data
@save_data = []
files = SaveData.all_save_files
files.each do |file|
this_save_data = load_save_file(SaveData::DIRECTORY, file)
@save_data.push([file, this_save_data])
end
end
def load_save_file(directory, filename)
ret = SaveData.read_from_file(directory + filename)
if !SaveData.valid?(ret)
if File.file?(directory + filename + ".bak")
show_message(_INTL("The save file is corrupt. A backup will be loaded."))
ret = load_save_file(directory, filename + ".bak")
end
if prompt_corrupted_save_deletion(filename)
delete_save_data(filename)
$PokemonSystem = PokemonSystem.new if self.is_a?(UI::Load)
else
exit
end
end
return ret
end
def prompt_corrupted_save_deletion(filename)
show_message(_INTL("The save file is corrupt, or is incompatible with this game.") + "\1")
pbPlayDecisionSE
return show_confirm_serious_message(_INTL("Do you want to delete the save file and start anew?"))
end
def delete_save_data(filename)
begin
SaveData.delete_file(filename)
yield if block_given?
show_message(_INTL("The save file was deleted."))
rescue SystemCallError
show_message(_INTL("The save file could not be deleted."))
end
end
end
#===============================================================================
#
#===============================================================================
class UI::LoadPanel < UI::SpriteContainer
attr_writer :label
GRAPHICS_FOLDER = "Load/"
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
:default => [Color.new(88, 88, 80), Color.new(168, 184, 184)] # Base and shadow colour
}
PANEL_WIDTH = 392
PANEL_HEIGHT = 56
def initialize(label, viewport)
@label = label
@selected = nil
super(viewport)
end
def initialize_sprites
initialize_panel_background
initialize_overlay
end
def initialize_panel_background
@sprites[:background] = ChangelingSprite.new(0, 0, @viewport)
panel_srcs.each_pair do |key, values|
@sprites[:background].add_bitmap(key, values)
end
@sprites[:background].change_bitmap(:default)
record_values(:background)
end
def initialize_overlay
add_overlay(:overlay, @sprites[:background].src_rect.width, @sprites[:background].src_rect.height)
@sprites[:overlay].z = 10
record_values(:overlay)
end
#-----------------------------------------------------------------------------
def width
return self.class::PANEL_WIDTH
end
def height
return self.class::PANEL_HEIGHT
end
def panel_srcs
return {
:default => [graphics_folder + "panels", 0, UI::LoadContinuePanel::PANEL_HEIGHT * 2,
self.class::PANEL_WIDTH, self.class::PANEL_HEIGHT],
:selected => [graphics_folder + "panels", 0, (UI::LoadContinuePanel::PANEL_HEIGHT * 2) + self.class::PANEL_HEIGHT,
self.class::PANEL_WIDTH, self.class::PANEL_HEIGHT]
}
end
def selected=(value)
return if @selected == value
@selected = value
@sprites[:background].change_bitmap((@selected) ? :selected : :default)
refresh
end
#-----------------------------------------------------------------------------
def refresh
super
draw_text(@label, 18, 18)
end
end
#===============================================================================
#
#===============================================================================
class UI::LoadContinuePanel < UI::LoadPanel
attr_reader :sprites
GRAPHICS_FOLDER = "Load/"
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
:default => [Color.new(88, 88, 80), Color.new(168, 184, 184)], # Base and shadow colour
:male => [Color.new(0, 112, 248), Color.new(120, 184, 232)],
:female => [Color.new(232, 32, 16), Color.new(248, 168, 184)]
}
PANEL_WIDTH = 392
PANEL_HEIGHT = 248
def initialize(label, save_data, slot_index, total_slots, viewport)
@save_data = save_data
@slot_index = slot_index
@total_slots = total_slots
super(label, viewport)
refresh
end
def initialize_sprites
super
initialize_player_sprite
initialize_pokemon_icons
initialize_arrow_sprites
end
def initialize_player_sprite
meta = GameData::PlayerMetadata.get(@save_data[:player].character_ID)
filename = pbGetPlayerCharset(meta.walk_charset, @save_data[:player], true)
@sprites[:player] = TrainerWalkingCharSprite.new(filename, @viewport)
if !@sprites[:player].bitmap
raise _INTL("Player character {1}'s walking charset was not found (filename: \"{2}\").",
@save_data[:player].character_ID, filename)
end
@sprites[:player].x = 48 - (@sprites[:player].bitmap.width / 8)
@sprites[:player].y = 72 - (@sprites[:player].bitmap.height / 8)
@sprites[:player].z = 1
record_values(:player)
end
def initialize_pokemon_icons
Settings::MAX_PARTY_SIZE.times do |i|
@sprites["pokemon_#{i}"] = PokemonIconSprite.new(@save_data[:player].party[i], @viewport)
@sprites["pokemon_#{i}"].x, @sprites["pokemon_#{i}"].y = pokemon_coords(i)
@sprites["pokemon_#{i}"].z = 1
@sprites["pokemon_#{i}"].setOffset
record_values("pokemon_#{i}")
end
end
def initialize_arrow_sprites
@sprites[:left_arrow] = AnimatedSprite.new(UI_FOLDER + "left_arrow", 8, 40, 28, 2, @viewport)
@sprites[:left_arrow].x = -16
@sprites[:left_arrow].y = (height / 2) - 14
@sprites[:left_arrow].z = 20
@sprites[:left_arrow].play
record_values(:left_arrow)
@sprites[:right_arrow] = AnimatedSprite.new(UI_FOLDER + "right_arrow", 8, 40, 28, 2, @viewport)
@sprites[:right_arrow].x = width - 24
@sprites[:right_arrow].y = (height / 2) - 14
@sprites[:right_arrow].z = 20
@sprites[:right_arrow].play
record_values(:right_arrow)
end
#-----------------------------------------------------------------------------
def panel_srcs
return {
:default => [graphics_folder + "panels", 0, 0,
self.class::PANEL_WIDTH, self.class::PANEL_HEIGHT],
:selected => [graphics_folder + "panels", 0, self.class::PANEL_HEIGHT,
self.class::PANEL_WIDTH, self.class::PANEL_HEIGHT]
}
end
def pokemon_coords(index)
return 276 + (66 * (index % 2)),
74 + (50 * (index / 2))
end
def visible=(value)
super
@sprites[:left_arrow].visible = (@selected && @total_slots >= 2)
@sprites[:right_arrow].visible = (@selected && @total_slots >= 2)
end
def selected=(value)
@sprites[:left_arrow].visible = (value && @total_slots >= 2)
@sprites[:right_arrow].visible = (value && @total_slots >= 2)
super
end
def set_data(save_data, slot_index, total_slots)
@save_data = save_data
@slot_index = slot_index
@total_slots = total_slots
@sprites[:left_arrow].visible = (@selected && total_slots >= 2)
@sprites[:right_arrow].visible = (@selected && total_slots >= 2)
set_player_sprite
refresh
end
def set_player_sprite
meta = GameData::PlayerMetadata.get(@save_data[:player].character_ID)
filename = pbGetPlayerCharset(meta.walk_charset, @save_data[:player], true)
@sprites[:player].charset = filename
if !@sprites[:player].bitmap
raise _INTL("Player character {1}'s walking charset was not found (filename: \"{2}\").",
@save_data[:player].character_ID, filename)
end
end
#-----------------------------------------------------------------------------
def refresh
super
refresh_pokemon
draw_slot_number
draw_save_file_text
end
def refresh_pokemon
Settings::MAX_PARTY_SIZE.times do |i|
@sprites["pokemon_#{i}"].pokemon = @save_data[:player].party[i]
end
end
def draw_slot_number
return if @total_slots <= 1
draw_text(sprintf("%d/%d", @slot_index + 1, @total_slots), PANEL_WIDTH - 18, 18, align: :right)
end
def draw_save_file_text
gender_theme = :default
if @save_data[:player].male?
gender_theme = :male
elsif @save_data[:player].female?
gender_theme = :female
end
# Player's name
draw_text(@save_data[:player].name, 78, 66, theme: gender_theme)
# Location
map_id = @save_data[:map_factory].map.map_id
map_name = pbGetMapNameFromId(map_id)
map_name = map_name.gsub(/\\PN/, @save_data[:player].name)
map_name = map_name.gsub(/\\v\[(\d+)\]/) { |num| @save_data[:variables][$~[1].to_i].to_s }
draw_text(map_name, 18, 114, theme: gender_theme)
# Gym Badges
draw_text(_INTL("Badges:"), 18, 146)
draw_text(@save_data[:player].badge_count.to_s, 156, 146, theme: gender_theme)
# Pokédex owned count
draw_text(_INTL("Pokédex:"), 18, 178)
draw_text(@save_data[:player].pokedex.seen_count.to_s, 156, 178, theme: gender_theme)
# Time played
draw_text(_INTL("Time played:"), 18, 210)
play_time = @save_data[:stats]&.play_time.to_i || 0
hour = (play_time / 60) / 60
min = (play_time / 60) % 60
play_time_text = (hour > 0) ? _INTL("{1}h {2}m", hour, min) : _INTL("{1}m", min)
draw_text(play_time_text, 156, 210, theme: gender_theme)
save_time = @save_data[:stats]&.real_time_saved
if save_time
save_time = Time.at(save_time)
if System.user_language[3..4] == "US" # If the user is in the United States
save_text = save_time.strftime("%-m/&-d/%Y")
else
save_text = save_time.strftime("%-d/%-m/%Y")
end
draw_text(save_text, PANEL_WIDTH - 18, 210, align: :right, theme: gender_theme)
end
end
def refresh_existing_pokemon
Settings::MAX_PARTY_SIZE.times do |i|
@sprites["pokemon_#{i}"].pokemon = @save_data[:player].party[i]
end
end
end
#===============================================================================
#
#===============================================================================
class UI::LoadVisuals < UI::BaseVisuals
attr_reader :slot_index
attr_reader :save_data
GRAPHICS_FOLDER = "Load/" # Subfolder in Graphics/UI
PANEL_SPACING_EDGE = 4
PANEL_SPACING = PANEL_SPACING_EDGE * 2
# save_data here is an array of [save filename, save data hash]. It has been
# compacted.
# commands is {:continue => _INTL("Continue"), :new_game => _INTL("New Game")},
# etc.
def initialize(commands, save_data, default_slot_index = 0)
@save_data = save_data
@commands = commands
@index = @commands.keys.first # A symbol from @commands
@slot_index = default_slot_index # Which save slot is selected
super()
end
def initialize_sprites
initialize_continue_panels
initialize_other_panels
end
def initialize_continue_panels
return if @save_data.nil? || @commands.keys.first != :continue
# Continue panel in middle
this_slot_index = @slot_index
@sprites[:continue] = create_continue_panel(this_slot_index)
# Continue panel to left
if @save_data.length >= 2
previous_slot_index = this_slot_index - 1
@sprites[:continue_previous] = create_continue_panel(this_slot_index - 1)
@sprites[:continue_previous].x = @sprites[:continue].x - @sprites[:continue].width - PANEL_SPACING
# Continue panel to right
next_slot_index = this_slot_index + 1
@sprites[:continue_next] = create_continue_panel(this_slot_index + 1)
@sprites[:continue_next].x = @sprites[:continue].x + @sprites[:continue].width + PANEL_SPACING
end
end
def initialize_other_panels
@commands.each_pair do |key, text|
next if key == :continue
@sprites[key] = UI::LoadPanel.new(text, @viewport)
@sprites[key].x = (Graphics.width - @sprites[key].width) / 2
end
@sprites[:mystery_gift]&.visible = @save_data[@slot_index] && @save_data[@slot_index][1][:player].mystery_gift_unlocked
end
#-----------------------------------------------------------------------------
def create_continue_panel(slot_index)
slot_index += @save_data.length if slot_index < 0
slot_index -= @save_data.length if slot_index >= @save_data.length
ret = UI::LoadContinuePanel.new(@commands[:continue],
@save_data[slot_index][1], slot_index, @save_data.length, @viewport)
ret.x = (Graphics.width - ret.width) / 2
return ret
end
def set_index(new_index)
@index = new_index
refresh_on_index_changed(@index)
end
def go_to_next_option(play_se = true)
return if @commands.length == 1
old_index = @commands.keys.index(@index)
new_index = old_index
loop do
new_index = (new_index + 1) % @commands.length
break if @sprites[@commands.keys[new_index]] && @sprites[@commands.keys[new_index]].visible
break if new_index == old_index
end
return if new_index == old_index
pbPlayCursorSE if play_se
set_index(@commands.keys[new_index])
end
def go_to_previous_option(play_se = true)
return if @commands.length == 1
old_index = @commands.keys.index(@index)
new_index = old_index
loop do
new_index -= 1
new_index += @commands.length if new_index < 0
break if @sprites[@commands.keys[new_index]] && @sprites[@commands.keys[new_index]].visible
break if new_index == old_index
end
return if new_index == old_index
pbPlayCursorSE if play_se
set_index(@commands.keys[new_index])
end
#-----------------------------------------------------------------------------
def set_slot_index(new_index, forced = false)
while new_index < 0
new_index += @save_data.length
end
while new_index >= @save_data.length
new_index -= @save_data.length
end
return if !forced && @slot_index == new_index
# Set the new index
@slot_index = new_index
# Show the newly selected slot's information in the Continue panel
@sprites[:continue].set_data(@save_data[@slot_index][1], @slot_index, @save_data.length)
# Show the newly adjacent slots' information in the adjacent Continue panels
prev_index = @slot_index - 1
prev_index += @save_data.length if prev_index < 0
@sprites[:continue_previous]&.set_data(@save_data[prev_index][1], prev_index, @save_data.length)
next_index = (@slot_index + 1) % @save_data.length
@sprites[:continue_next]&.set_data(@save_data[next_index][1], next_index, @save_data.length)
# Determine whether the Mystery Gift option is visible
@sprites[:mystery_gift].visible = @save_data[@slot_index][1][:player].mystery_gift_unlocked
refresh_panel_positions
# Set the options, and change the language if relevant
old_language = $PokemonSystem.language
SaveData.load_bootup_values(@save_data[@slot_index][1], true)
if $PokemonSystem.language != old_language && Settings::LANGUAGES[$PokemonSystem.language]
MessageTypes.load_message_files(Settings::LANGUAGES[$PokemonSystem.language][1])
full_refresh
end
pbPlayCursorSE if !forced
end
def go_to_next_save_slot
set_slot_index(@slot_index + 1)
end
def go_to_previous_save_slot
set_slot_index(@slot_index - 1)
end
#-----------------------------------------------------------------------------
def refresh
super
@commands.keys.each { |key| @sprites[key]&.refresh }
refresh_panel_positions
refresh_selected_panel
end
def full_refresh
refresh
refresh_labels
@sprites.each_pair { |key, sprite| sprite.refresh if sprite.respond_to?(:refresh) }
end
def refresh_panel_positions
@panel_y_offset ||= 0
sprite_y = PANEL_SPACING_EDGE
# Determine the relative positions of all option panels
sprite_pos = {}
@commands.keys.each do |key|
next if !@sprites[key] || !@sprites[key].visible # If Mystery Gift option isn't available
sprite_pos[key] = sprite_y
sprite_y += @sprites[key].height + PANEL_SPACING
end
# Determine an offset that ensures the selected option panel is on-screen
screen_y = sprite_pos[@index] - @panel_y_offset
if screen_y < PANEL_SPACING_EDGE
@panel_y_offset = sprite_pos[@index] - PANEL_SPACING_EDGE
elsif screen_y + @sprites[@index].height > Graphics.height - PANEL_SPACING_EDGE
@panel_y_offset = sprite_pos[@index] + @sprites[@index].height + PANEL_SPACING_EDGE - Graphics.height
end
# Apply the calculated positions to all option panels
sprite_pos.each_pair do |key, value|
@sprites[key].y = value - @panel_y_offset
end
@sprites[:continue_previous]&.y = @sprites[:continue].y
@sprites[:continue_next]&.y = @sprites[:continue].y
end
def refresh_selected_panel
@commands.keys.each do |key|
@sprites[key]&.selected = (key == @index)
end
@sprites[:continue_previous]&.selected = false
@sprites[:continue_next]&.selected = false
end
def refresh_labels
MenuHandlers.each_available(:load_screen, self) do |option, _hash, name|
@sprites[option].label = name
if option == :continue
@sprites[:continue_previous].label = name
@sprites[:continue_next].label = name
end
end
end
def refresh_on_index_changed(old_index)
refresh_selected_panel
refresh_panel_positions
end
def refresh_after_save_file_deleted
@slot_index = [@slot_index, @save_data.length - 1].min
if @save_data.empty?
[:continue, :continue_previous, :continue_next].each do |key|
@sprites[key].dispose if @sprites[key] && !@sprites[key].disposed?
@sprites[key] = nil
end
@sprites[:mystery_gift].visible = false
go_to_next_option(false)
else
if @save_data.length == 1
[:continue_previous, :continue_next].each do |key|
@sprites[key].dispose if @sprites[key] && !@sprites[key].disposed?
@sprites[key] = nil
end
end
set_slot_index(@slot_index, true)
end
end
#-----------------------------------------------------------------------------
def update_input
# Check for movement to a new option
if Input.repeat?(Input::UP)
go_to_previous_option
elsif Input.repeat?(Input::DOWN)
go_to_next_option
end
# Check for movement to a different save slot
if @index == :continue && @save_data.length > 1
if Input.repeat?(Input::LEFT)
go_to_previous_save_slot
elsif Input.repeat?(Input::RIGHT)
go_to_next_save_slot
end
end
# Check for interaction
if Input.trigger?(Input::USE)
if @index == :continue && Input.press?(Input::ACTION) && Input.press?(Input::BACK)
pbPlayDecisionSE
return :delete_save
end
return update_interaction(Input::USE)
elsif Input.trigger?(Input::JUMPUP)
if @index != @commands.keys[0]
pbPlayCursorSE
set_index(@commands.keys[0])
end
elsif Input.trigger?(Input::JUMPDOWN)
if @index != @commands.keys[@commands.length - 1]
pbPlayCursorSE
set_index(@commands.keys[@commands.length - 1])
end
end
return nil
end
def update_interaction(input)
case input
when Input::USE
pbPlayDecisionSE if @index != :quit_game
return @index # This is a key from @commands
end
return nil
end
end
#===============================================================================
#
#===============================================================================
class UI::Load < UI::BaseScreen
attr_reader :save_data
SCREEN_ID = :load_screen
include UI::LoadSaveDataMixin
def initialize
load_all_save_data
determine_default_save_file
if $DEBUG && !FileTest.exist?("Game.rgssad") && Settings::SKIP_CONTINUE_SCREEN
@disposed = true
perform_action((@save_data.empty?) ? :new_game : :continue)
return
end
set_commands
super
end
def initialize_visuals
@visuals = UI::LoadVisuals.new(@commands, @save_data, @default_slot_index)
end
#-----------------------------------------------------------------------------
def slot_index
return @visuals&.slot_index || @default_slot_index
end
def set_commands
@commands = {}
MenuHandlers.each_available(:load_screen, self) do |option, _hash, name|
@commands[option] = name
end
end
#-----------------------------------------------------------------------------
def determine_default_save_file
@default_slot_index = 0
last_edited_time = nil
@save_data.each_with_index do |data, i|
save_time = data[1][:stats].real_time_saved || 0
if !last_edited_time || save_time > last_edited_time
last_edited_time = save_time
@default_slot_index = i
end
end
SaveData.load_bootup_values(@save_data[@default_slot_index][1], true) if !@save_data.empty?
MessageTypes.load_message_files(Settings::LANGUAGES[$PokemonSystem.language][1]) if Settings::LANGUAGES[$PokemonSystem.language]
end
def prompt_save_deletion(filename)
if show_confirm_serious_message(_INTL("Delete this save file?"))
show_message(_INTL("Once a save file has been deleted, there is no way to recover it.") + "\1")
pbPlayDecisionSE
if show_confirm_serious_message(_INTL("Delete the save file anyway?"))
delete_save_data(filename) {
@save_data.delete_if { |save| save[0] == filename }
@visuals.refresh_after_save_file_deleted
}
end
end
end
#-----------------------------------------------------------------------------
def full_refresh
@visuals.full_refresh
end
end
#===============================================================================
# Actions that can be triggered in the load screen.
#===============================================================================
UIActionHandlers.add(UI::Load::SCREEN_ID, :continue, {
:effect => proc { |screen|
screen.end_screen
Game.load(screen.save_data[screen.slot_index][1])
}
})
UIActionHandlers.add(UI::Load::SCREEN_ID, :mystery_gift, {
:effect => proc { |screen|
pbFadeOutInWithUpdate(screen.sprites) do
pbDownloadMysteryGift(screen.save_data[screen.slot_index][1][:player])
end
}
})
UIActionHandlers.add(UI::Load::SCREEN_ID, :new_game, {
:effect => proc { |screen|
screen.end_screen
Game.start_new
}
})
UIActionHandlers.add(UI::Load::SCREEN_ID, :options, {
:effect => proc { |screen|
pbFadeOutInWithUpdate(screen.sprites) do
options_scene = PokemonOption_Scene.new
options_screen = PokemonOptionScreen.new(options_scene)
options_screen.pbStartScreen(true)
screen.full_refresh
end
}
})
UIActionHandlers.add(UI::Load::SCREEN_ID, :language, {
:effect => proc { |screen|
screen.end_screen
$PokemonSystem.language = pbChooseLanguage
MessageTypes.load_message_files(Settings::LANGUAGES[$PokemonSystem.language][1])
if screen.save_data[screen.slot_index]
screen.save_data[screen.slot_index][1][:pokemon_system] = $PokemonSystem
File.open(SaveData::DIRECTORY + screen.save_data[screen.slot_index][0], "wb") do |file|
Marshal.dump(screen.save_data[screen.slot_index][1], file)
end
end
$scene = pbCallTitle
}
})
UIActionHandlers.add(UI::Load::SCREEN_ID, :debug, {
:effect => proc { |screen|
pbFadeOutInWithUpdate(screen.sprites) do
pbDebugMenu(false)
end
}
})
UIActionHandlers.add(UI::Load::SCREEN_ID, :quit_game, {
:effect => proc { |screen|
pbPlayCloseMenuSE
screen.end_screen
$scene = nil
}
})
UIActionHandlers.add(UI::Load::SCREEN_ID, :delete_save, {
:effect => proc { |screen|
screen.prompt_save_deletion(screen.save_data[screen.slot_index][0])
}
})
#===============================================================================
# Menu options that exist in the load screen.
# NOTE: This can also be called when screen is UI::LoadVisuals (for
# retranslating the names upon selecting a save file with a different
# language). Try not to have a condition that references things only in
# UI::Load.
#===============================================================================
MenuHandlers.add(:load_screen, :continue, {
"name" => _INTL("Continue"),
"order" => 10,
"condition" => proc { |screen| next screen.save_data && !screen.save_data.empty? }
})
# NOTE: Mystery Gift is always added as an option here, even if no save files
# have unlocked it. Whether it is shown depends on the selected save file,
# and its visibility is toggled elsewhere because of that.
MenuHandlers.add(:load_screen, :mystery_gift, {
"name" => _INTL("Mystery Gift"),
"order" => 20,
"condition" => proc { |screen| next screen.save_data && !screen.save_data.empty? }
})
MenuHandlers.add(:load_screen, :new_game, {
"name" => _INTL("New Game"),
"order" => 30
})
MenuHandlers.add(:load_screen, :options, {
"name" => _INTL("Options"),
"order" => 40
})
# TODO: Put language in the options screen?
MenuHandlers.add(:load_screen, :language, {
"name" => _INTL("Language"),
"order" => 50,
"condition" => proc { |screen| next Settings::LANGUAGES.length >= 2 }
})
MenuHandlers.add(:load_screen, :debug, {
"name" => _INTL("Debug"),
"order" => 60,
"condition" => proc { |screen| next $DEBUG }
})
MenuHandlers.add(:load_screen, :quit_game, {
"name" => _INTL("Quit Game"),
"order" => 9999
})

View File

@@ -0,0 +1,609 @@
#===============================================================================
#
#===============================================================================
class UI::SavePanel < UI::SpriteContainer
attr_reader :sprites
GRAPHICS_FOLDER = "Save/"
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
:default => [Color.new(88, 88, 80), Color.new(168, 184, 184)], # Base and shadow colour
:white => [Color.new(248, 248, 248), Color.new(172, 188, 188)],
:male => [Color.new(0, 112, 248), Color.new(120, 184, 232)],
:female => [Color.new(232, 32, 16), Color.new(248, 168, 184)]
}
PANEL_WIDTH = 384
PANEL_HEIGHT = 204
def initialize(save_data, viewport)
@save_data = save_data
@show_arrows = false
super(viewport)
refresh
end
def initialize_sprites
initialize_panel_background
initialize_overlay
initialize_player_sprite
initialize_pokemon_icons
initialize_arrow_sprites
end
def initialize_panel_background
@sprites[:background] = ChangelingSprite.new(0, 0, @viewport)
panel_srcs.each_pair do |key, values|
@sprites[:background].add_bitmap(key, values)
end
@sprites[:background].change_bitmap(:default)
record_values(:background)
end
def initialize_overlay
add_overlay(:overlay, @sprites[:background].width, @sprites[:background].height)
@sprites[:overlay].z = 10
record_values(:overlay)
end
def initialize_player_sprite
meta = GameData::PlayerMetadata.get(@save_data[:player].character_ID)
filename = pbGetPlayerCharset(meta.walk_charset, @save_data[:player], true)
@sprites[:player] = TrainerWalkingCharSprite.new(filename, @viewport)
if !@sprites[:player].bitmap
raise _INTL("Player character {1}'s walking charset was not found (filename: \"{2}\").",
@save_data[:player].character_ID, filename)
end
@sprites[:player].x = 44 - (@sprites[:player].bitmap.width / 8)
@sprites[:player].y = 36 - (@sprites[:player].bitmap.height / 8)
@sprites[:player].z = 1
record_values(:player)
end
def initialize_pokemon_icons
Settings::MAX_PARTY_SIZE.times do |i|
@sprites["pokemon_#{i}"] = PokemonIconSprite.new(@save_data[:player].party[i], @viewport)
@sprites["pokemon_#{i}"].x, @sprites["pokemon_#{i}"].y = pokemon_coords(i)
@sprites["pokemon_#{i}"].z = 1
@sprites["pokemon_#{i}"].setOffset
record_values("pokemon_#{i}")
end
end
def initialize_arrow_sprites
@sprites[:left_arrow] = AnimatedSprite.new(UI_FOLDER + "left_arrow", 8, 40, 28, 2, @viewport)
@sprites[:left_arrow].x = -16
@sprites[:left_arrow].y = (height / 2) - 14
@sprites[:left_arrow].z = 20
@sprites[:left_arrow].visible = false
@sprites[:left_arrow].play
record_values(:left_arrow)
@sprites[:right_arrow] = AnimatedSprite.new(UI_FOLDER + "right_arrow", 8, 40, 28, 2, @viewport)
@sprites[:right_arrow].x = width - 24
@sprites[:right_arrow].y = (height / 2) - 14
@sprites[:right_arrow].z = 20
@sprites[:right_arrow].visible = false
@sprites[:right_arrow].play
record_values(:right_arrow)
end
#-----------------------------------------------------------------------------
def width
return PANEL_WIDTH
end
def height
return PANEL_HEIGHT
end
def panel_srcs
return {
:default => [graphics_folder + "panels", 0, 0, PANEL_WIDTH, PANEL_HEIGHT],
:new_slot => [graphics_folder + "panels", 0, PANEL_HEIGHT, PANEL_WIDTH, PANEL_HEIGHT]
}
end
def pokemon_coords(index)
return 272 + (66 * (index % 2)),
36 + (50 * (index / 2))
end
def show_arrows=(value)
return if @show_arrows == value
@show_arrows = value
@sprites[:left_arrow].visible = value
@sprites[:right_arrow].visible = value
end
def set_data(save_data)
@save_data = save_data
@sprites[:background].change_bitmap((@save_data) ? :default : :new_slot)
set_player_sprite
refresh
end
def set_player_sprite
if !@save_data
@sprites[:player].visible = false
return
end
@sprites[:player].visible = true
meta = GameData::PlayerMetadata.get(@save_data[:player].character_ID)
filename = pbGetPlayerCharset(meta.walk_charset, @save_data[:player], true)
@sprites[:player].charset = filename
if !@sprites[:player].bitmap
raise _INTL("Player character {1}'s walking charset was not found (filename: \"{2}\").",
@save_data[:player].character_ID, filename)
end
end
#-----------------------------------------------------------------------------
def refresh
super
refresh_pokemon
draw_save_file_text
end
def refresh_pokemon
Settings::MAX_PARTY_SIZE.times do |i|
if @save_data
@sprites["pokemon_#{i}"].pokemon = @save_data[:player].party[i]
@sprites["pokemon_#{i}"].visible = true
else
@sprites["pokemon_#{i}"].visible = false
end
end
end
def draw_save_file_text
if !@save_data
draw_text(_INTL("Create a new save file"), width / 2, (height / 2) - 10, align: :center)
return
end
gender_theme = :default
if @save_data[:player].male?
gender_theme = :male
elsif @save_data[:player].female?
gender_theme = :female
end
# Player's name
draw_text(@save_data[:player].name, 78, 30, theme: gender_theme)
# Location
map_id = @save_data[:map_factory].map.map_id
map_name = pbGetMapNameFromId(map_id)
map_name = map_name.gsub(/\\PN/, @save_data[:player].name)
map_name = map_name.gsub(/\\v\[(\d+)\]/) { |num| @save_data[:variables][$~[1].to_i].to_s }
draw_text(map_name, 14, 78)
# Gym Badges
draw_text(_INTL("Badges:"), 14, 110, theme: :white)
draw_text(@save_data[:player].badge_count.to_s, 222, 110, align: :right)
# Pokédex owned count
draw_text(_INTL("Pokédex:"), 14, 142, theme: :white)
draw_text(@save_data[:player].pokedex.seen_count.to_s, 222, 142, align: :right)
# Time played
draw_text(_INTL("Play time:"), 14, 174, theme: :white)
play_time = @save_data[:stats]&.real_play_time.to_i || 0
hour = (play_time / 60) / 60
min = (play_time / 60) % 60
play_time_text = (hour > 0) ? _INTL("{1}h {2}m", hour, min) : _INTL("{1}m", min)
draw_text(play_time_text, 222, 174, align: :right)
save_time = @save_data[:stats]&.real_time_saved
if save_time
save_time = Time.at(save_time)
if System.user_language[3..4] == "US" # If the user is in the United States
save_text = save_time.strftime("%-m/&-d/%Y")
else
save_text = save_time.strftime("%-d/%-m/%Y")
end
draw_text(save_text, PANEL_WIDTH - 14, 174, align: :right)
else
draw_text("???", PANEL_WIDTH - 14, 174, align: :right)
end
end
def refresh_existing_pokemon
Settings::MAX_PARTY_SIZE.times do |i|
@sprites["pokemon_#{i}"].pokemon = @save_data[:player].party[i]
end
end
end
#===============================================================================
#
#===============================================================================
class UI::SaveVisuals < UI::BaseVisuals
attr_reader :index
GRAPHICS_FOLDER = "Save/" # Subfolder in Graphics/UI
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
:default => [Color.new(80, 80, 88), Color.new(176, 192, 192)] # Base and shadow colour
}
PANEL_SPACING = 8
# save_data here is an array of [save filename, save data hash]. It has been
# compacted.
def initialize(save_data, current_save_data, default_index = 0)
@save_data = save_data
@current_save_data = current_save_data
@index = default_index # Which save slot is selected
@choosing_save_file = false
super()
end
def initialize_sprites
initialize_continue_panels
end
def initialize_continue_panels
# Continue panel in middle
this_index = @index
@sprites[:continue] = create_slot_panel(this_index)
# Continue panel to left
if !@save_data.empty?
previous_index = this_index - 1
@sprites[:continue_previous] = create_slot_panel(this_index - 1)
@sprites[:continue_previous].x = @sprites[:continue].x - @sprites[:continue].width - PANEL_SPACING
@sprites[:continue_previous].visible = false
# Continue panel to right
next_index = this_index + 1
@sprites[:continue_next] = create_slot_panel(this_index + 1)
@sprites[:continue_next].x = @sprites[:continue].x + @sprites[:continue].width + PANEL_SPACING
@sprites[:continue_next].visible = false
end
end
#-----------------------------------------------------------------------------
def create_slot_panel(slot_index, initializing = true)
slot_index += @save_data.length + 1 if slot_index < 0
slot_index -= @save_data.length + 1 if slot_index >= @save_data.length + 1
if initializing
this_save_data = @current_save_data[1]
else
this_save_data = (@save_data[slot_index]) ? @save_data[slot_index][1] : nil
end
ret = UI::SavePanel.new(this_save_data, @viewport)
ret.x = (Graphics.width - ret.width) / 2
ret.y = 40
return ret
end
#-----------------------------------------------------------------------------
def set_index(new_index, forced = false)
while new_index < 0
new_index += @save_data.length + 1
end
while new_index >= @save_data.length + 1
new_index -= @save_data.length + 1
end
return if !forced && @index == new_index
# Set the new index
@index = new_index
# Show the newly selected slot's information in the Continue panel
this_save_data = (@save_data[@index]) ? @save_data[@index][1] : nil
@sprites[:continue].set_data(this_save_data)
# Show the newly adjacent slots' information in the adjacent Continue panels
prev_index = @index - 1
prev_index += @save_data.length + 1 if prev_index < 0
this_save_data = (@save_data[prev_index]) ? @save_data[prev_index][1] : nil
@sprites[:continue_previous]&.set_data(this_save_data)
next_index = (@index + 1) % (@save_data.length + 1)
this_save_data = (@save_data[next_index]) ? @save_data[next_index][1] : nil
@sprites[:continue_next]&.set_data(this_save_data)
refresh
pbPlayCursorSE if !forced
end
def go_to_next_save_slot
set_index(@index + 1)
end
def go_to_previous_save_slot
set_index(@index - 1)
end
#-----------------------------------------------------------------------------
def start_choose_save_file
@choosing_save_file = true
@sprites[:continue_previous].visible = true
@sprites[:continue_next].visible = true
@sprites[:continue].show_arrows = true
set_index(@index, true)
end
#-----------------------------------------------------------------------------
def refresh_overlay
super
if @choosing_save_file
if @save_data[index] &&
@save_data[index][1][:game_system].adventure_magic_number
if @save_data[index][1][:game_system].adventure_magic_number == $game_system.adventure_magic_number
save_time = @save_data[index][1][:stats].real_play_time
delta_time = ($stats.play_time - save_time).to_i
if delta_time >= 0
hour = (delta_time / 60) / 60
min = (delta_time / 60) % 60
if hour > 0
draw_text(_INTL("Play time since save: {1}h {2}m", hour, min), 8, 4)
else
draw_text(_INTL("Play time since save: {1}m", min), 8, 4)
end
else
draw_text(_INTL("Alternate version of your adventure!"), 8, 4)
end
else
draw_text(_INTL("Different adventure!"), 8, 4)
end
end
if @save_data[@index]
draw_text(sprintf("%d/%d", @index + 1, @save_data.length), Graphics.width - 8, 4, align: :right)
end
elsif $stats.save_count > 0 && $stats.real_time_saved
save_time = Time.at($stats.real_time_saved)
if System.user_language[3..4] == "US" # If the user is in the United States
date_text = save_time.strftime("%-m/&-d/%Y")
else
date_text = save_time.strftime("%-d/%-m/%Y")
end
time_text = save_time.strftime("%H:%M")
draw_text(_INTL("Last saved on {1} at {2}", date_text, time_text), 8, 4)
end
end
def full_refresh
refresh
@sprites.each_pair { |key, sprite| sprite.refresh if sprite.respond_to?(:refresh) }
end
#-----------------------------------------------------------------------------
def update_input
# Check for movement to a different save slot
if Input.repeat?(Input::LEFT)
go_to_previous_save_slot
elsif Input.repeat?(Input::RIGHT)
go_to_next_save_slot
end
# Check for interaction
if Input.trigger?(Input::USE)
return update_interaction(Input::USE)
elsif Input.trigger?(Input::BACK)
return update_interaction(Input::BACK)
end
return nil
end
def update_interaction(input)
case input
when Input::USE
pbPlayDecisionSE
return :choose_slot
when Input::BACK
pbPlayCancelSE
return :quit
end
return nil
end
#-----------------------------------------------------------------------------
def navigate
help_text = _INTL("Choose a file to save in.")
help_window = Window_AdvancedTextPokemon.newWithSize(
help_text, 0, 0, Graphics.width, 96, @viewport
)
help_window.z = 2000
help_window.setSkin(MessageConfig.pbGetSpeechFrame)
help_window.letterbyletter = false
pbBottomRight(help_window)
# Navigate loop
ret = super
# Clean up
help_window.dispose
return ret
end
end
#===============================================================================
#
#===============================================================================
class UI::Save < UI::BaseScreen
attr_reader :save_data
SCREEN_ID = :save_screen
include UI::LoadSaveDataMixin
def initialize
create_current_save_data
load_all_save_data
determine_default_save_file
super
end
def initialize_visuals
@visuals = UI::SaveVisuals.new(@save_data, @current_save_data, @default_index)
end
#-----------------------------------------------------------------------------
def index
return @visuals&.index || @default_index
end
#-----------------------------------------------------------------------------
# This is pseudo-save data containing the current state of the game.
def create_current_save_data
@current_save_data = [0, {
:player => $player,
:map_factory => $map_factory,
:variables => $game_variables,
:stats => $stats
}]
end
def determine_default_save_file
# Find the save file index matching the current game's filename number
if $stats.save_filename_number && $stats.save_filename_number >= 0
expected_filename = SaveData.filename_from_index($stats.save_filename_number)
@default_index = @save_data.index { |sav| sav[0] == expected_filename }
@default_index ||= @save_data.length # Just in case
else
@default_index = @save_data.length # New save slot
end
end
def different_adventure?(slot_index)
return false if !@save_data[slot_index]
return false if !@save_data[slot_index][1][:game_system].adventure_magic_number
return @save_data[slot_index][1][:game_system].adventure_magic_number != $game_system.adventure_magic_number
end
def prompt_overwrite_save_file(slot_index)
if different_adventure?(slot_index)
show_message(_INTL("WARNING!") + "\1")
show_message(_INTL("There is a different game file that is already saved.") + "\1")
show_message(_INTL("If you save now, the other file's adventure, including items and Pokémon, will be entirely lost.") + "\1")
if !show_confirm_serious_message(_INTL("Are you sure you want to save now and overwrite the other save file?"))
return false
end
end
return true
end
# NOTE: Save filenames are "Game#.rxdata" where "#" is slot_index, except for
# 0 which just produces "Game.rzdata". This is to support old save
# files which are that name.
def save_game(file_number)
# TODO: I don't know about this "GUI save choice" being here.
# pbSEPlay("GUI save choice")
if Game.save(file_number)
# Refresh the panels to show the new save's data
file = SaveData.filename_from_index(file_number)
slot_index = @save_data.index { |sav| sav[0] == file }
slot_index ||= @save_data.length # New save file
this_save_data = load_save_file(SaveData::DIRECTORY, file)
@save_data[slot_index] = [file, this_save_data]
@visuals.set_index(slot_index, true)
# Announce the save success
show_message(_INTL("{1} saved the game.", $player.name)) {
# TODO: Stop SE.
pbMEPlay("GUI save game")
# TODO: Wait for ME to finish playing, then auto-close the message.
}
@result = true
else
show_message(_INTL("Save failed."))
# TODO: Auto-close this message.
@result = false
end
end
def get_save_file_number(slot_index = -1)
filename = (slot_index >= 0 && @save_data[slot_index]) ? @save_data[slot_index][0] : @save_data.last[0]
filename[SaveData::FILENAME_REGEX] # Just to get the number in the filename
ret = $~[1].to_i
ret += 1 if slot_index < 0 || !@save_data[slot_index]
return ret
end
#-----------------------------------------------------------------------------
def full_refresh
@visuals.full_refresh
end
#-----------------------------------------------------------------------------
def main
start_screen
# If the player doesn't want to save, just exit the screen
if !show_confirm_message(_INTL("Would you like to save the game?"))
end_screen
return false
end
# If there are no existing save files, just save in the first slot
if @save_data.empty?
save_game(0)
end_screen
return @result
end
# If there are existing save files, do something depending on which save
# files are allowed to be made
case Settings::SAVE_SLOTS
when :multiple
# Choose a save slot to replace
@visuals.start_choose_save_file
loop do
command = @visuals.navigate
break if command == :quit
if !@save_data[index] ||
show_confirm_message(_INTL("Do you want to overwrite this save file?"))
if different_adventure?(index)
show_message(_INTL("WARNING!") + "\1")
pbPlayDecisionSE
show_message(_INTL("This save file is a different adventure.") + "\1")
pbPlayDecisionSE
show_message(_INTL("If you save now, that adventure, including items and Pokémon, will be entirely lost.") + "\1")
pbPlayDecisionSE
next if !show_confirm_serious_message(_INTL("Are you sure you want to overwrite it?"))
end
file_number = get_save_file_number(index)
save_game(file_number)
break
end
end
when :adventure
if $stats.save_filename_number && $stats.save_filename_number >= 0 # Was saved previously
save_game($stats.save_filename_number)
else
file_number = get_save_file_number(-1) # New save slot
save_game(file_number)
end
when :one
save_game(0) if prompt_overwrite_save_file(0)
end
end_screen
return @result
end
end
#===============================================================================
#
#===============================================================================
def pbSaveScreen
ret = false
pbFadeOutIn { ret = UI::Save.new.main }
return ret
end
def pbEmergencySave
oldscene = $scene
$scene = nil
pbMessage(_INTL("The script is taking too long. The game will restart."))
return if !$player
filename_number = $stats.save_filename_number || -1
filename = SaveData.filename_from_index(filename_number)
if SaveData.exists?
File.open(SaveData::DIRECTORY + filename, "rb") do |r|
File.open(SaveData::DIRECTORY + filename + ".bak", "wb") do |w|
loop do
s = r.read(4096)
break if !s
w.write(s)
end
end
end
end
if Game.save(filename_number)
pbMessage("\\se[]" + _INTL("The game was saved.") + "\\me[GUI save game]\\wtnp[20]")
pbMessage("\\se[]" + _INTL("The previous save file has been backed up.") + "\\wtnp[20]")
else
pbMessage("\\se[]" + _INTL("Save failed.") + "\\wtnp[30]")
end
$scene = oldscene
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,271 @@
#===============================================================================
# TODO: Make this code more consistent between having methods in the module and
# code in MenuHandlers.
#===============================================================================
module UI::PC
module_function
def pbGetStorageCreator
return GameData::Metadata.get.storage_creator
end
#-----------------------------------------------------------------------------
def pbPokeCenterPC
pbMessage("\\se[PC open]" + _INTL("{1} booted up the PC.", $player.name))
# Get all commands
command_list = []
commands = []
MenuHandlers.each_available(:pc_menu) do |option, hash, name|
command_list.push(name)
commands.push(hash)
end
# Main loop
command = 0
loop do
choice = pbMessage(_INTL("Which PC should be accessed?"), command_list, -1, nil, command)
break if choice < 0
break if commands[choice]["effect"].call
end
pbSEPlay("PC close")
end
def pbTrainerPC
pbMessage("\\se[PC open]" + _INTL("{1} booted up the PC.", $player.name))
pbTrainerPCMenu
pbSEPlay("PC close")
end
def pbTrainerPCMenu
commands = {
:item_storage => _INTL("Item Storage"),
:mailbox => _INTL("Mailbox"),
:turn_off => _INTL("Turn off")
}
command = 0
loop do
command = pbMessage(_INTL("What do you want to do?"), commands.values, -1, nil, command)
case commands.keys[command]
when :item_storage
pbPlayDecisionSE
pbPCItemStorage
when :mailbox
if !$PokemonGlobal.mailbox || $PokemonGlobal.mailbox.length == 0
pbMessage(_INTL("There's no Mail here."))
next
end
pbPlayDecisionSE
pbPCMailbox
else
break
end
end
end
#-----------------------------------------------------------------------------
def pbPCItemStorage
$PokemonGlobal.pcItemStorage ||= PCItemStorage.new
commands = {
:withdraw => [_INTL("Withdraw Item"), _INTL("Take out items from the PC.")],
:deposit => [_INTL("Deposit Item"), _INTL("Store items in the PC.")],
:toss => [_INTL("Toss Item"), _INTL("Throw away items stored in the PC.")],
:exit => [_INTL("Exit"), _INTL("Go back to the previous menu.")]
}
command = 0
loop do
commands.values.map { |val| val[0] }
command = pbShowCommandsWithHelp(nil, commands.values.map { |val| val[0] },
commands.values.map { |val| val[1] }, -1, command)
break if command < 0
case commands.keys[command]
when :withdraw
if $PokemonGlobal.pcItemStorage.empty?
pbMessage(_INTL("There are no items."))
else
pbPlayDecisionSE
pbFadeOutIn do
scene = WithdrawItemScene.new
screen = ItemStorageScreen.new(scene, $bag)
screen.pbWithdrawItemScreen
end
end
when :deposit
pbPlayDecisionSE
item_storage = $PokemonGlobal.pcItemStorage
pbFadeOutIn do
bag_screen = UI::Bag.new($bag, mode: :choose_item)
given_item = bag_screen.choose_item do |item|
item_data = GameData::Item.get(item)
qty = $bag.quantity(item)
if qty > 1 && !item_data.is_important?
qty = bag_screen.choose_number(_INTL("How many do you want to deposit?"), qty)
end
next false if qty == 0
if !item_storage.can_add?(item, qty)
raise "Can't delete items from Bag" if !$bag.remove(item, qty)
raise "Can't deposit items to storage" if !item_storage.add(item, qty)
bag_screen.refresh
disp_qty = (item_data.is_important?) ? 1 : qty
item_name = (disp_qty > 1) ? item_data.portion_name_plural : item_data.portion_name
bag_screen.show_message(_INTL("Deposited {1} {2}.", disp_qty, item_name))
else
bag_screen.show_message(_INTL("There's no room to store items."))
end
next false
end
end
when :toss
if $PokemonGlobal.pcItemStorage.empty?
pbMessage(_INTL("There are no items."))
else
pbPlayDecisionSE
pbFadeOutIn do
scene = TossItemScene.new
screen = ItemStorageScreen.new(scene, $bag)
screen.pbTossItemScreen
end
end
else
break
end
end
end
#-----------------------------------------------------------------------------
def pbPCMailbox
command = 0
loop do
commands = []
$PokemonGlobal.mailbox.each { |mail| commands.push(mail.sender) }
commands.push(_INTL("Cancel"))
mail_index = pbShowCommands(nil, commands, -1, command)
break if mail_index < 0 || mail_index >= $PokemonGlobal.mailbox.length
interact_commands = {
:read => _INTL("Read"),
:move_to_bag => _INTL("Move to Bag"),
:give => _INTL("Give"),
:cancel => _INTL("Cancel")
}
command_mail = pbMessage(
_INTL("What do you want to do with {1}'s Mail?", $PokemonGlobal.mailbox[mail_index].sender),
interact_commands.values, -1
)
case interact_commands.keys[command_mail]
when :read
pbPlayDecisionSE
pbFadeOutIn { pbDisplayMail($PokemonGlobal.mailbox[mail_index]) }
when :move_to_bag
if pbConfirmMessage(_INTL("The message will be lost. Is that OK?"))
if $bag.add($PokemonGlobal.mailbox[mail_index].item)
pbMessage(_INTL("The Mail was returned to the Bag with its message erased."))
$PokemonGlobal.mailbox.delete_at(mail_index)
else
pbMessage(_INTL("The Bag is full."))
end
end
when :give
pbPlayDecisionSE
pbFadeOutIn do
screen = UI::Party.new($player.party, mode: :choose_pokemon)
screen.choose_pokemon do |pkmn, party_index|
next true if party_index < 0
if pkmn.egg?
screen.show_message(_INTL("Eggs can't hold mail."))
elsif pkmn.hasItem? || pkmn.mail
screen.show_message(_INTL("This Pokémon is holding an item. It can't hold mail."))
else
pkmn.mail = $PokemonGlobal.mailbox[mail_index]
$PokemonGlobal.mailbox.delete_at(mail_index)
screen.refresh
screen.show_message(_INTL("Mail was transferred from the Mailbox."))
next true
end
next false
end
end
else
pbPlayDecisionSE
end
end
end
end
#===============================================================================
#
#===============================================================================
MenuHandlers.add(:pc_menu, :pokemon_storage, {
"name" => proc {
next ($player.seen_storage_creator) ? _INTL("{1}'s PC", UI::PC.pbGetStorageCreator) : _INTL("Someone's PC")
},
"order" => 10,
"effect" => proc { |menu|
pbMessage("\\se[PC access]" + _INTL("The Pokémon Storage System was opened."))
commands = {
:organize => [_INTL("Organize Boxes"), _INTL("Organize the Pokémon in Boxes and in your party.")],
:withdraw => [_INTL("Withdraw Pokémon"), _INTL("Move Pokémon stored in Boxes to your party.")],
:deposit => [_INTL("Deposit Pokémon"), _INTL("Store Pokémon in your party in Boxes.")],
:quit => [_INTL("See ya!"), _INTL("Return to the previous menu.")]
}
command = 0
loop do
command = pbShowCommandsWithHelp(nil, commands.values.map { |val| val[0] },
commands.values.map { |val| val[1] }, -1, command)
break if command < 0
case commands.keys[command]
when :organize
pbPlayDecisionSE
pbFadeOutIn do
UI::PokemonStorage.new($PokemonStorage, mode: :organize).main
end
when :withdraw
if $PokemonStorage.party_full?
pbMessage(_INTL("Your party is full!"))
next
end
pbPlayDecisionSE
pbFadeOutIn do
UI::PokemonStorage.new($PokemonStorage, mode: :withdraw).main
end
when :deposit
if $player.able_pokemon_count <= 1
pbMessage(_INTL("Can't deposit the last Pokémon!"))
next
end
pbPlayDecisionSE
pbFadeOutIn do
UI::PokemonStorage.new($PokemonStorage, mode: :deposit).main
end
else
break
end
end
next false
}
})
MenuHandlers.add(:pc_menu, :player_pc, {
"name" => proc { next _INTL("{1}'s PC", $player.name) },
"order" => 20,
"effect" => proc { |menu|
pbMessage("\\se[PC access]" + _INTL("Accessed {1}'s PC.", $player.name))
UI::PC.pbTrainerPCMenu
next false
}
})
MenuHandlers.add(:pc_menu, :close, {
"name" => _INTL("Log off"),
"order" => 999,
"effect" => proc { |menu|
next true
}
})
#===============================================================================
#
#===============================================================================
def pbPokeCenterPC
UI::PC.pbPokeCenterPC
end

View File

@@ -0,0 +1,544 @@
#===============================================================================
#
#===============================================================================
class UI::MartStockWrapper
def initialize(stock)
@stock = stock
refresh
end
def length
return @stock.length
end
def [](index)
return @stock[index]
end
def buy_price(item)
return 0 if item.nil?
if $game_temp.mart_prices && $game_temp.mart_prices[item]
return $game_temp.mart_prices[item][0] if $game_temp.mart_prices[item][0] > 0
end
return GameData::Item.get(item).price
end
def buy_price_string(item)
price = buy_price(item)
return _INTL("${1}", price.to_s_formatted)
end
def sell_price(item)
return 0 if item.nil?
if $game_temp.mart_prices && $game_temp.mart_prices[item]
return $game_temp.mart_prices[item][1] if $game_temp.mart_prices[item][1] >= 0
end
return GameData::Item.get(item).sell_price
end
def refresh
@stock.delete_if { |itm| GameData::Item.get(itm).is_important? && $bag.has?(itm) }
end
end
#===============================================================================
# Pokémon Mart.
#===============================================================================
class UI::MartVisualsList < Window_DrawableCommand
def initialize(stock, x, y, width, height, viewport = nil)
@stock = stock
super(x, y, width, height, viewport)
@selarrow = AnimatedBitmap.new(bag_folder + "cursor")
@baseColor = UI::MartVisuals::TEXT_COLOR_THEMES[:black][0]
@shadowColor = UI::MartVisuals::TEXT_COLOR_THEMES[:black][1]
self.windowskin = nil
end
#-----------------------------------------------------------------------------
def itemCount
return @stock.length + 1 # The extra 1 is the Cancel option
end
def bag_folder
return UI::MartVisuals::UI_FOLDER + UI::MartVisuals::GRAPHICS_FOLDER
end
def item_id
return (self.index >= @stock.length) ? nil : @stock[self.index]
end
def expensive_base_color=(value)
@expensive_base_color = value
end
def expensive_shadow_color=(value)
@expensive_shadow_color = value
end
def expensive?(this_item)
return @stock.buy_price(this_item) > $player.money
end
#-----------------------------------------------------------------------------
# This draws all the visible options first, and then draws the cursor.
def refresh
@item_max = itemCount
update_cursor_rect
dwidth = self.width - self.borderX
dheight = self.height - self.borderY
self.contents = pbDoEnsureBitmap(self.contents, dwidth, dheight)
self.contents.clear
@item_max.times do |i|
next if i < self.top_item || i > self.top_item + self.page_item_max
drawItem(i, @item_max, itemRect(i))
end
drawCursor(self.index, itemRect(self.index))
end
def drawItem(index, count, rect)
textpos = []
rect = drawCursor(index, rect)
ypos = rect.y
this_item = @stock[index]
if this_item
# Draw item name
item_name = GameData::Item.get(this_item).display_name
textpos.push([item_name, rect.x, ypos + 2, :left, self.baseColor, self.shadowColor])
# Draw item price
price = @stock.buy_price_string(this_item)
price_width = self.contents.text_size(price).width
price_x = rect.x + rect.width - price_width - 2 - 16
expensive = expensive?(this_item)
price_base_color = (expensive) ? @expensive_base_color || self.baseColor : self.baseColor
price_shadow_color = (expensive) ? @expensive_shadow_color || self.shadowColor : self.shadowColor
textpos.push([price, price_x, ypos + 2, :left, price_base_color, price_shadow_color])
else
textpos.push([_INTL("CANCEL"), rect.x, ypos + 2, :left, self.baseColor, self.shadowColor])
end
pbDrawTextPositions(self.contents, textpos)
end
end
#===============================================================================
#
#===============================================================================
class UI::MartVisuals < UI::BaseVisuals
attr_reader :pocket
GRAPHICS_FOLDER = "Mart/" # Subfolder in Graphics/UI
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
:default => [Color.new(248, 248, 248), Color.new(56, 56, 56)], # Base and shadow colour
:white => [Color.new(248, 248, 248), Color.new(56, 56, 56)],
:black => [Color.new(88, 88, 80), Color.new(168, 184, 184)],
:expensive => [Color.new(224, 0, 0), Color.new(248, 144, 144)]
}
ITEMS_VISIBLE = 7
def initialize(stock, bag)
@stock = stock
@bag = bag
super()
end
def initialize_sprites
initialize_item_list
initialize_item_sprites
initialize_money_window
initialize_bag_quantity_window
end
def initialize_item_list
@sprites[:item_list] = UI::MartVisualsList.new(@stock, 152, 10, 374, 38 + (ITEMS_VISIBLE * 32), @viewport)
@sprites[:item_list].expensive_base_color = TEXT_COLOR_THEMES[:expensive][0]
@sprites[:item_list].expensive_shadow_color = TEXT_COLOR_THEMES[:expensive][1]
@sprites[:item_list].active = false
end
def initialize_item_sprites
# Selected item's icon
@sprites[:item_icon] = ItemIconSprite.new(48, Graphics.height - 48, nil, @viewport)
# Selected item's description text box
@sprites[:item_description] = Window_UnformattedTextPokemon.newWithSize(
"", 80, 272, Graphics.width - 98, 128, @viewport
)
@sprites[:item_description].baseColor = TEXT_COLOR_THEMES[:white][0]
@sprites[:item_description].shadowColor = TEXT_COLOR_THEMES[:white][1]
@sprites[:item_description].visible = true
@sprites[:item_description].windowskin = nil
end
def initialize_money_window
@sprites[:money_window] = Window_AdvancedTextPokemon.newWithSize("", 0, 0, 162, 96, @viewport)
@sprites[:money_window].setSkin("Graphics/Windowskins/goldskin")
@sprites[:money_window].baseColor = TEXT_COLOR_THEMES[:black][0]
@sprites[:money_window].shadowColor = TEXT_COLOR_THEMES[:black][1]
@sprites[:money_window].letterbyletter = false
@sprites[:money_window].visible = true
end
def initialize_bag_quantity_window
@sprites[:bag_quantity_window] = Window_AdvancedTextPokemon.newWithSize(
_INTL("In Bag:<r>{1}", @bag.quantity(item)), 0, 0, 162, 64, @viewport
)
@sprites[:bag_quantity_window].setSkin("Graphics/Windowskins/goldskin")
@sprites[:bag_quantity_window].baseColor = TEXT_COLOR_THEMES[:black][0]
@sprites[:bag_quantity_window].shadowColor = TEXT_COLOR_THEMES[:black][1]
@sprites[:bag_quantity_window].letterbyletter = false
@sprites[:bag_quantity_window].visible = true
@sprites[:bag_quantity_window].y = Graphics.height - 102 - @sprites[:bag_quantity_window].height
end
#-----------------------------------------------------------------------------
def index
return @sprites[:item_list].index
end
def set_index(value)
@sprites[:item_list].index = value
refresh_on_index_changed(nil)
end
def item
return @sprites[:item_list].item_id
end
def show_money_window
@sprites[:money_window].visible = true
end
def hide_money_window
@sprites[:money_window].visible = false
end
def show_bag_quantity_window
@sprites[:bag_quantity_window].visible = true
end
def hide_bag_quantity_window
@sprites[:bag_quantity_window].visible = false
end
#-----------------------------------------------------------------------------
def refresh
refresh_item_list
refresh_selected_item
refresh_money_window
end
def refresh_item_list
@sprites[:item_list].refresh
end
def refresh_selected_item
selected_item = item
# Set the selected item's icon
@sprites[:item_icon].item = selected_item
# Set the selected item's description
if selected_item
@sprites[:item_description].text = GameData::Item.get(selected_item).description
else
@sprites[:item_description].text = _INTL("Quit shopping.")
end
refresh_bag_quantity_window
end
def refresh_bag_quantity_window
@sprites[:bag_quantity_window].text = _INTL("In Bag:<r>{1}", @bag.quantity(item))
(item) ? show_bag_quantity_window : hide_bag_quantity_window
end
def refresh_money_window
@sprites[:money_window].text = _INTL("Money:\n<r>${1}", $player.money.to_s_formatted)
end
def refresh_on_index_changed(old_index)
refresh_selected_item
end
#-----------------------------------------------------------------------------
def update_input
# Check for interaction
if Input.trigger?(Input::USE)
return update_interaction(Input::USE)
elsif Input.trigger?(Input::BACK)
return update_interaction(Input::BACK)
end
return nil
end
def update_interaction(input)
case input
when Input::USE
if item
pbPlayDecisionSE
return :interact
end
pbPlayCloseMenuSE
return :quit
when Input::BACK
pbPlayCloseMenuSE
return :quit
end
return nil
end
def navigate
@sprites[:item_list].active = true
ret = super
@sprites[:item_list].active = false
return ret
end
end
#===============================================================================
#
#===============================================================================
class UI::Mart < UI::BaseScreen
attr_reader :stock, :bag
SCREEN_ID = :mart_screen
def initialize(stock, bag)
pbScrollMap(6, 5, 5) # Direction 6 (right), 5 tiles, speed 5 (cycling speed, 10 tiles/second)
@bag = bag
initialize_stock(stock)
super()
end
def initialize_stock(stock)
@stock = UI::MartStockWrapper.new(stock)
end
def initialize_visuals
@visuals = UI::MartVisuals.new(@stock, @bag)
end
def start_screen
pbSEPlay("GUI menu open")
end
def end_screen
return if @disposed
pbPlayCloseMenuSE
silent_end_screen
pbScrollMap(4, 5, 5) # Direction 4 (left), 5 tiles, speed 5 (cycling speed, 10 tiles/second)
end
#-----------------------------------------------------------------------------
def item
return nil if @visuals.item.nil?
return GameData::Item.get(@visuals.item)
end
end
#===============================================================================
#
#===============================================================================
UIActionHandlers.add(UI::Mart::SCREEN_ID, :interact, {
:effect => proc { |screen|
item = screen.item
item_price = screen.stock.buy_price(item)
# Check affordability
if $player.money < item_price
screen.show_message(_INTL("You don't have enough money."))
next
end
# Choose how many of the item to buy
quantity = 0
if item.is_important?
quantity = 1
next if !screen.show_confirm_message(
_INTL("So you want the {1}?\nIt'll be ${2}. All right?",
item.portion_name, item_price.to_s_formatted)
)
else
max_quantity = (item_price <= 0) ? PokemonBag::MAX_PER_SLOT : $player.money / item_price
max_quantity = [max_quantity, PokemonBag::MAX_PER_SLOT].min
quantity = screen.choose_number_as_money_multiplier(
_INTL("How many {1} would you like?", item.portion_name_plural), item_price, max_quantity
)
next if quantity == 0
item_price *= quantity
if quantity > 1
next if !screen.show_confirm_message(
_INTL("So you want {1} {2}?\nThey'll be ${3}. All right?",
quantity, item.portion_name_plural, item_price.to_s_formatted)
)
elsif quantity > 0
next if !screen.show_confirm_message(
_INTL("So you want {1} {2}?\nIt'll be ${3}. All right?",
quantity, item.portion_name, item_price.to_s_formatted)
)
end
end
# Check affordability (should always be possible, but just make sure)
if $player.money < item_price
screen.show_message(_INTL("You don't have enough money."))
next
end
# Check the item can be put in the Bag
if !screen.bag.can_add?(item.id, quantity)
screen.show_message(_INTL("You have no room in your Bag."))
next
end
# Add the bought item(s)
screen.bag.add(item.id, quantity)
$stats.money_spent_at_marts += item_price
$stats.mart_items_bought += quantity
$player.money -= item_price
screen.stock.refresh
screen.refresh
screen.show_message(_INTL("Here you are! Thank you!")) { pbSEPlay("Mart buy item") }
# Give bonus Premier Ball(s)
if quantity >= 10 && item.is_poke_ball? && GameData::Item.exists?(:PREMIERBALL)
if Settings::MORE_BONUS_PREMIER_BALLS || item.id == :POKEBALL
premier_balls_earned = (Settings::MORE_BONUS_PREMIER_BALLS) ? (quantity / 10) : 1
premier_balls_added = 0
premier_balls_earned.times do
break if !screen.bag.add(:PREMIERBALL)
premier_balls_added += 1
end
if premier_balls_added > 0
$stats.premier_balls_earned += premier_balls_added
if premier_balls_added > 1
ball_name = GameData::Item.get(:PREMIERBALL).portion_name_plural
else
ball_name = GameData::Item.get(:PREMIERBALL).portion_name
end
screen.show_message(_INTL("And have {1} {2} on the house!", premier_balls_added, ball_name))
end
end
end
}
})
#===============================================================================
#
#===============================================================================
class UI::BagSellVisuals < UI::BagVisuals
def initialize(bag, stock, mode = :choose_item)
@stock = stock
super(bag, mode: mode)
end
def initialize_sprites
super
@sprites[:money_window] = Window_AdvancedTextPokemon.newWithSize("", 0, 36, 184, 96, @viewport)
@sprites[:money_window].setSkin("Graphics/Windowskins/goldskin")
@sprites[:money_window].z = 2000
@sprites[:money_window].baseColor = TEXT_COLOR_THEMES[:black][0]
@sprites[:money_window].shadowColor = TEXT_COLOR_THEMES[:black][1]
@sprites[:money_window].letterbyletter = false
@sprites[:money_window].visible = true
@sprites[:unit_price_window] = Window_AdvancedTextPokemon.newWithSize("", 0, 184, 184, 96, @viewport)
@sprites[:unit_price_window].setSkin("Graphics/Windowskins/goldskin")
@sprites[:unit_price_window].z = 2000
@sprites[:unit_price_window].baseColor = TEXT_COLOR_THEMES[:black][0]
@sprites[:unit_price_window].shadowColor = TEXT_COLOR_THEMES[:black][1]
@sprites[:unit_price_window].letterbyletter = false
@sprites[:unit_price_window].visible = true
end
def refresh
super
@sprites[:money_window].text = _INTL("Money:\n<r>${1}", $player.money.to_s_formatted)
refresh_unit_price_window
end
def refresh_input_indicators; end
def refresh_unit_price_window
@sprites[:unit_price_window].visible = (!item.nil?)
return if item.nil?
price = @stock.sell_price(item)
if GameData::Item.get(item).is_important? || price == 0
@sprites[:unit_price_window].text = _INTL("You can't sell this item.")
else
@sprites[:unit_price_window].text = _INTL("Price each:\n<r>${1}", price.to_s_formatted)
end
end
def refresh_on_index_changed(old_index)
super
refresh_unit_price_window
end
end
#===============================================================================
#
#===============================================================================
class UI::BagSell < UI::Bag
def initialize(bag, mode: :choose_item)
@stock = UI::MartStockWrapper.new([])
super(bag, mode: mode)
end
def initialize_visuals
@visuals = UI::BagSellVisuals.new(@bag, @stock, mode: @mode)
end
def sell_items
choose_item do |item|
item_data = GameData::Item.get(item)
item_name = item_data.portion_name
item_name_plural = item_data.portion_name_plural
price = @stock.sell_price(item)
# Ensure item can be sold
if item_data.is_important? || price == 0
show_message(_INTL("Oh, no. I can't buy {1}.", item_name_plural))
next
end
# Choose a quantity of the item to sell
quantity = @bag.quantity(item)
if quantity > 1
quantity = choose_number_as_money_multiplier(
_INTL("How many {1} would you like to sell?", item_name_plural), price, quantity
)
end
next if quantity == 0
# Sell the item(s)
price *= quantity
if show_confirm_message(_INTL("I can pay ${1}.\nWould that be OK?", price.to_s_formatted))
@bag.remove(item, quantity)
old_money = $player.money
$player.money += price
$stats.money_earned_at_marts += $player.money - old_money
refresh
sold_item_name = (quantity > 1) ? item_name_plural : item_name
show_message(_INTL("You turned over the {1} and got ${2}.",
sold_item_name, price.to_s_formatted)) { pbSEPlay("Mart buy item") }
end
next false
end
end
end
#===============================================================================
#
#===============================================================================
def pbPokemonMart(stock, speech = nil, cannot_sell = false)
commands = {}
commands[:buy] = _INTL("I'm here to buy")
commands[:sell] = _INTL("I'm here to sell") if !cannot_sell
commands[:cancel] = _INTL("No, thanks")
cmd = pbMessage(speech || _INTL("Welcome! How may I help you?"), commands.values, commands.length)
loop do
case commands.keys[cmd]
when :buy
UI::Mart.new(stock, $bag).main
when :sell
pbFadeOutIn { UI::BagSell.new($bag).sell_items }
else
pbMessage(_INTL("Do come again!"))
break
end
cmd = pbMessage(_INTL("Is there anything else I can do for you?"), commands.values, commands.length, nil, cmd)
end
$game_temp.clear_mart_prices
end

View File

@@ -0,0 +1,205 @@
#===============================================================================
#
#===============================================================================
class UI::BPShopStockWrapper < UI::MartStockWrapper
def buy_price(item)
return 0 if item.nil?
if $game_temp.mart_prices && $game_temp.mart_prices[item]
return $game_temp.mart_prices[item][0] if $game_temp.mart_prices[item][0] > 0
end
return GameData::Item.get(item).bp_price
end
def buy_price_string(item)
price = buy_price(item)
return _INTL("{1} BP", price.to_s_formatted)
end
end
#===============================================================================
# Pokémon Mart.
#===============================================================================
class UI::BPShopVisualsList < UI::MartVisualsList
def expensive?(this_item)
return @stock.buy_price(this_item) > $player.battle_points
end
end
#===============================================================================
#
#===============================================================================
class UI::BPShopVisuals < UI::MartVisuals
def initialize_item_list
@sprites[:item_list] = UI::BPShopVisualsList.new(@stock, 152, 10, 374, 38 + (ITEMS_VISIBLE * 32), @viewport)
@sprites[:item_list].expensive_base_color = TEXT_COLOR_THEMES[:expensive][0]
@sprites[:item_list].expensive_shadow_color = TEXT_COLOR_THEMES[:expensive][1]
@sprites[:item_list].active = false
end
#-----------------------------------------------------------------------------
# Like the one in class BaseVisuals, but shows the money as BP instead of $.
def choose_number_as_money_multiplier(help_text, money_per_unit, maximum, init_value = 1)
@sprites[:speech_box].visible = true
@sprites[:speech_box].text = help_text
pbBottomLeftLines(@sprites[:speech_box], 2)
# Show the help text
loop do
Graphics.update
Input.update
update_visuals
if @sprites[:speech_box].busy?
if Input.trigger?(Input::USE)
pbPlayDecisionSE if @sprites[:speech_box].pausing?
@sprites[:speech_box].resume
end
else
break
end
end
# Choose a quantity
item_price = money_per_unit
quantity = init_value
using(num_window = Window_AdvancedTextPokemon.newWithSize(
_INTL("×{1}<r>{2} BP", quantity, (quantity * item_price).to_s_formatted),
0, 0, 224, 64, @viewport)) do
num_window.z = 2000
num_window.visible = true
num_window.letterbyletter = false
pbBottomRight(num_window)
num_window.y -= @sprites[:speech_box].height
loop do
Graphics.update
Input.update
update
num_window.update
# Change quantity
old_quantity = quantity
if Input.repeat?(Input::LEFT)
quantity = [quantity - 10, 1].max
elsif Input.repeat?(Input::RIGHT)
quantity = [quantity + 10, maximum].min
elsif Input.repeat?(Input::UP)
quantity += 1
quantity = 1 if quantity > maximum
elsif Input.repeat?(Input::DOWN)
quantity -= 1
quantity = maximum if quantity < 1
end
if quantity != old_quantity
num_window.text = _INTL("×{1}<r>{2} BP", quantity, (quantity * item_price).to_s_formatted)
pbPlayCursorSE
end
# Finish choosing a quantity
if Input.trigger?(Input::USE)
pbPlayDecisionSE
break
elsif Input.trigger?(Input::BACK)
pbPlayCancelSE
quantity = 0
break
end
end
end
@sprites[:speech_box].visible = false
return quantity
end
#-----------------------------------------------------------------------------
def refresh_money_window
@sprites[:money_window].text = _INTL("BP:\n<r>{1}", $player.battle_points.to_s_formatted)
end
end
#===============================================================================
#
#===============================================================================
class UI::BPShop < UI::Mart
SCREEN_ID = :bp_shop
def initialize_stock(stock)
@stock = UI::BPShopStockWrapper.new(stock)
end
def initialize_visuals
@visuals = UI::BPShopVisuals.new(@stock, @bag)
end
end
#===============================================================================
#
#===============================================================================
UIActionHandlers.add(UI::BPShop::SCREEN_ID, :interact, {
:effect => proc { |screen|
item = screen.item
item_price = screen.stock.buy_price(item)
# Check affordability
if $player.battle_points < item_price
screen.show_message(_INTL("I'm sorry, you don't have enough BP."))
next
end
# Choose how many of the item to buy
quantity = 0
if item.is_important?
quantity = 1
next if !screen.show_confirm_message(
_INTL("You would like the {1}?\nThat will be {2} BP.",
item.portion_name, item_price.to_s_formatted)
)
else
max_quantity = (item_price <= 0) ? PokemonBag::MAX_PER_SLOT : $player.battle_points / item_price
max_quantity = [max_quantity, PokemonBag::MAX_PER_SLOT].min
quantity = screen.choose_number_as_money_multiplier(
_INTL("How many {1} would you like?", item.portion_name_plural), item_price, max_quantity
)
next if quantity == 0
item_price *= quantity
if quantity > 1
next if !screen.show_confirm_message(
_INTL("You would like {1} {2}?\nThey'll be {3} BP.",
quantity, item.portion_name_plural, item_price.to_s_formatted)
)
elsif quantity > 0
next if !screen.show_confirm_message(
_INTL("You would like {1} {2}?\nThat will be {3} BP.",
quantity, item.portion_name, item_price.to_s_formatted)
)
end
end
# Check affordability (should always be possible, but just make sure)
if $player.battle_points < item_price
screen.show_message(_INTL("I'm sorry, you don't have enough BP."))
next
end
# Check the item can be put in the Bag
if !screen.bag.can_add?(item.id, quantity)
screen.show_message(_INTL("You have no room in your Bag."))
next
end
# Add the bought item(s)
screen.bag.add(item.id, quantity)
$stats.battle_points_spent += item_price
$stats.mart_items_bought += quantity
$player.battle_points -= item_price
screen.stock.refresh
screen.refresh
screen.show_message(_INTL("Here you are! Thank you!")) { pbSEPlay("Mart buy item") }
}
})
#===============================================================================
#
#===============================================================================
def pbBattlePointShop(stock, speech = nil)
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
UI::BPShop.new(stock, $bag).main
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

@@ -0,0 +1,364 @@
#===============================================================================
#
#===============================================================================
class UI::MoveReminderCursor < IconSprite
attr_accessor :top_index
CURSOR_WIDTH = 258
CURSOR_HEIGHT = 72
CURSOR_THICKNESS = 6
def initialize(viewport = nil)
super(0, 0, viewport)
setBitmap("Graphics/UI/Move Reminder/cursor")
self.src_rect = Rect.new(0, 0, CURSOR_WIDTH, CURSOR_HEIGHT)
self.z = 1600
@bg_sprite = IconSprite.new(x, y, viewport)
@bg_sprite.setBitmap("Graphics/UI/Move Reminder/cursor")
@bg_sprite.src_rect = Rect.new(0, CURSOR_HEIGHT, CURSOR_WIDTH, CURSOR_HEIGHT)
@top_index = 0
self.index = 0
end
def dispose
@bg_sprite.dispose
@bg_sprite = nil
super
end
def index=(value)
@index = value
refresh_position
end
def visible=(value)
super
@bg_sprite.visible = value
end
def refresh_position
return if @index < 0
self.x = UI::MoveReminderVisuals::MOVE_LIST_X
self.y = UI::MoveReminderVisuals::MOVE_LIST_Y - CURSOR_THICKNESS
self.y += (@index - @top_index) * UI::MoveReminderVisuals::MOVE_LIST_SPACING
@bg_sprite.x = self.x
@bg_sprite.y = self.y
end
end
#===============================================================================
#
#===============================================================================
class UI::MoveReminderVisuals < UI::BaseVisuals
attr_reader :index
GRAPHICS_FOLDER = "Move Reminder/" # Subfolder in Graphics/UI
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
:default => [Color.new(248, 248, 248), Color.new(0, 0, 0)], # Base and shadow colour
:white => [Color.new(248, 248, 248), Color.new(0, 0, 0)],
:black => [Color.new(64, 64, 64), Color.new(176, 176, 176)],
:header => [Color.new(88, 88, 80), Color.new(168, 184, 184)]
}
MOVE_LIST_X = 0
MOVE_LIST_Y = 84
MOVE_LIST_SPACING = 64 # Y distance between top of two adjacent move areas
VISIBLE_MOVES = 4
def initialize(pokemon, moves)
@pokemon = pokemon
@moves = moves
@top_index = 0
@index = 0
super()
refresh_cursor
end
def initialize_bitmaps
@bitmaps[:types] = AnimatedBitmap.new(UI_FOLDER + _INTL("types"))
@bitmaps[:buttons] = AnimatedBitmap.new(graphics_folder + "buttons")
end
def initialize_sprites
# Pokémon icon
@sprites[:pokemon_icon] = PokemonIconSprite.new(@pokemon, @viewport)
@sprites[:pokemon_icon].setOffset(PictureOrigin::CENTER)
@sprites[:pokemon_icon].x = 314
@sprites[:pokemon_icon].y = 84
@sprites[:pokemon_icon].z = 200
# Cursor
@sprites[:cursor] = UI::MoveReminderCursor.new(@viewport)
end
#-----------------------------------------------------------------------------
def moves=(move_list)
@moves = move_list
@index = @moves.length - 1 if @index >= @moves.length
refresh_on_index_changed(@index)
@cursor.visible = false if @moves.empty?
refresh
end
#-----------------------------------------------------------------------------
def refresh_overlay
super
draw_header
draw_pokemon_type_icons(396, 70, 6)
draw_moves_list
draw_move_properties
draw_buttons
end
def draw_header
draw_text(_INTL("Teach which move?"), 16, 14, theme: :header)
end
# x and y are the top left corner of the type icon if there is only one type.
def draw_pokemon_type_icons(x, y, spacing)
@pokemon.types.each_with_index do |type, i|
type_number = GameData::Type.get(type).icon_position
offset = ((@pokemon.types.length - 1) * (GameData::Type::ICON_SIZE[0] + spacing) / 2)
offset = (offset / 2) * 2
type_x = x - offset + ((GameData::Type::ICON_SIZE[0] + spacing) * i)
draw_image(@bitmaps[:types], type_x, y,
0, type_number * GameData::Type::ICON_SIZE[1], *GameData::Type::ICON_SIZE)
end
end
def draw_moves_list
VISIBLE_MOVES.times do |i|
move = @moves[@top_index + i]
next if move.nil?
move_data = GameData::Move.get(move)
draw_move_in_list(move_data, MOVE_LIST_X, MOVE_LIST_Y + (i * MOVE_LIST_SPACING))
end
end
def draw_move_in_list(move_data, x, y)
# Draw move name
move_name = move_data.name
move_name = crop_text(move_name, 230)
draw_text(move_name, x + 10, y + 6)
# Draw move type icon
type_number = GameData::Type.get(move_data.display_type(@pokemon)).icon_position
draw_image(@bitmaps[:types], x + 10, y + 32,
0, type_number * GameData::Type::ICON_SIZE[1], *GameData::Type::ICON_SIZE)
# Draw move category
draw_image(UI_FOLDER + "category", x + 76, y + 32,
0, move_data.display_category(@pokemon) * GameData::Move::CATEGORY_ICON_SIZE[1], *GameData::Move::CATEGORY_ICON_SIZE)
# Draw PP text
if move_data.total_pp > 0
draw_text(_INTL("PP"), x + 150, y + 38, theme: :black)
draw_text(sprintf("%d/%d", move_data.total_pp, move_data.total_pp), x + 240, y + 38, align: :right, theme: :black)
end
end
def draw_move_properties
move = @moves[@index]
move_data = GameData::Move.get(move)
# Power
draw_text(_INTL("POWER"), 278, 120)
power_text = move_data.display_power(@pokemon)
power_text = "---" if power_text == 0 # Status move
power_text = "???" if power_text == 1 # Variable power move
draw_text(power_text, 480, 120, align: :right, theme: :black)
# Accuracy
draw_text(_INTL("ACCURACY"), 278, 152)
accuracy = move_data.display_accuracy(@pokemon)
if accuracy == 0
draw_text("---", 480, 152, align: :right, theme: :black)
else
draw_text(accuracy, 480, 152, align: :right, theme: :black)
draw_text("%", 480, 152, theme: :black)
end
# Description
draw_paragraph_text(move_data.description, 262, 184, 246, 6, theme: :black)
end
def draw_buttons
draw_image(@bitmaps[:buttons], 44, 350, 0, 0, 76, 32) if @top_index < @moves.length - VISIBLE_MOVES
draw_image(@bitmaps[:buttons], 132, 350, 76, 0, 76, 32) if @top_index > 0
end
#-----------------------------------------------------------------------------
def refresh_cursor
@sprites[:cursor].top_index = @top_index
@sprites[:cursor].index = @index
end
def refresh_on_index_changed(old_index)
pbPlayCursorSE
# Change @top_index to keep @index in the middle of the visible list (or as
# close to it as possible)
middle_range_top = (VISIBLE_MOVES / 2) - ((VISIBLE_MOVES + 1) % 2)
middle_range_bottom = VISIBLE_MOVES / 2
if @index < @top_index + middle_range_top
@top_index = @index - middle_range_top
elsif @index > @top_index + middle_range_bottom
@top_index = @index - middle_range_bottom
end
@top_index = @top_index.clamp(0, [@moves.length - VISIBLE_MOVES, 0].max)
refresh_cursor
refresh
end
#-----------------------------------------------------------------------------
def update_input
# Check for movement to a new move
update_cursor_movement
# Check for interaction
if Input.trigger?(Input::USE)
return update_interaction(Input::USE)
elsif Input.trigger?(Input::BACK)
return update_interaction(Input::BACK)
elsif Input.trigger?(Input::ACTION)
return update_interaction(Input::ACTION)
end
return nil
end
def update_cursor_movement
# Check for movement to a new move
if Input.repeat?(Input::UP)
@index -= 1
if Input.trigger?(Input::UP)
@index = @moves.length - 1 if @index < 0 # Wrap around
else
@index = 0 if @index < 0
end
elsif Input.repeat?(Input::DOWN)
@index += 1
if Input.trigger?(Input::DOWN)
@index = 0 if @index >= @moves.length # Wrap around
else
@index = @moves.length - 1 if @index >= @moves.length
end
elsif Input.repeat?(Input::JUMPUP)
@index -= VISIBLE_MOVES
@index = 0 if @index < 0
elsif Input.repeat?(Input::JUMPDOWN)
@index += VISIBLE_MOVES
@index = @moves.length - 1 if @index >= @moves.length
end
return false
end
def update_interaction(input)
case input
when Input::USE
pbPlayDecisionSE
return :learn
when Input::BACK
pbPlayCloseMenuSE
return :quit
end
return nil
end
end
#===============================================================================
#
#===============================================================================
class UI::MoveReminder < UI::BaseScreen
attr_reader :pokemon
SCREEN_ID = :move_reminder_screen
# mode is either :normal or :single.
def initialize(pokemon, mode: :normal)
@pokemon = pokemon
@mode = mode
generate_move_list
super()
end
def initialize_visuals
@visuals = UI::MoveReminderVisuals.new(@pokemon, @moves)
end
#-----------------------------------------------------------------------------
def generate_move_list
@moves = []
return if !@pokemon || @pokemon.egg? || @pokemon.shadowPokemon?
@pokemon.getMoveList.each do |move|
next if move[0] > @pokemon.level || @pokemon.hasMove?(move[1])
@moves.push(move[1]) if !@moves.include?(move[1])
end
if Settings::MOVE_RELEARNER_CAN_TEACH_MORE_MOVES && @pokemon.first_moves
first_moves = []
@pokemon.first_moves.each do |move|
first_moves.push(move) if !@moves.include?(move) && !@pokemon.hasMove?(move)
end
@moves = first_moves + @moves # List first moves before level-up moves
end
@moves = @moves | [] # remove duplicates
end
def refresh_move_list
generate_move_list
@visuals.moves = @moves
end
#-----------------------------------------------------------------------------
def move
return @moves[self.index]
end
#-----------------------------------------------------------------------------
def main
return if @disposed
start_screen
loop do
on_start_main_loop
command = @visuals.navigate
break if command == :quit && (@mode == @normal ||
show_confirm_message(_INTL("Give up trying to teach a new move to {1}?", @pokemon.name)))
perform_action(command)
if @moves.empty?
show_message(_INTL("There are no more moves for {1} to learn.", @pokemon.name))
break
end
if @disposed
@result = true
break
end
end
end_screen
return @result
end
end
#===============================================================================
# Actions that can be triggered in the Move Reminder screen.
#===============================================================================
UIActionHandlers.add(UI::MoveReminder::SCREEN_ID, :learn, {
:effect => proc { |screen|
if screen.show_confirm_message(_INTL("Teach {1}?", GameData::Move.get(screen.move).name))
if pbLearnMove(screen.pokemon, screen.move, false, false, screen)
$stats.moves_taught_by_reminder += 1
if screen.mode == :normal
screen.refresh_move_list
else
screen.end_screen
end
end
end
}
})
#===============================================================================
#
#===============================================================================
def pbRelearnMoveScreen(pkmn)
ret = true
pbFadeOutIn do
ret = UI::MoveReminder.new(pkmn, mode: :single).main
end
return ret
end

View File

@@ -0,0 +1,130 @@
=begin
#===============================================================================
#
#===============================================================================
class PokemonPauseMenu_Scene
def pbStartScene
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@sprites = {}
@sprites["cmdwindow"] = Window_CommandPokemon.new([])
@sprites["cmdwindow"].visible = false
@sprites["cmdwindow"].viewport = @viewport
@sprites["infowindow"] = Window_UnformattedTextPokemon.newWithSize("", 0, 0, 32, 32, @viewport)
@sprites["infowindow"].visible = false
@sprites["helpwindow"] = Window_UnformattedTextPokemon.newWithSize("", 0, 0, 32, 32, @viewport)
@sprites["helpwindow"].visible = false
@infostate = false
@helpstate = false
pbSEPlay("GUI menu open")
end
def pbShowInfo(text)
@sprites["infowindow"].resizeToFit(text, Graphics.height)
@sprites["infowindow"].text = text
@sprites["infowindow"].visible = true
@infostate = true
end
def pbShowHelp(text)
@sprites["helpwindow"].resizeToFit(text, Graphics.height)
@sprites["helpwindow"].text = text
@sprites["helpwindow"].visible = true
pbBottomLeft(@sprites["helpwindow"])
@helpstate = true
end
def pbShowMenu
@sprites["cmdwindow"].visible = true
@sprites["infowindow"].visible = @infostate
@sprites["helpwindow"].visible = @helpstate
end
def pbHideMenu
@sprites["cmdwindow"].visible = false
@sprites["infowindow"].visible = false
@sprites["helpwindow"].visible = false
end
def pbShowCommands(commands)
ret = -1
cmdwindow = @sprites["cmdwindow"]
cmdwindow.commands = commands
cmdwindow.index = $game_temp.menu_last_choice
cmdwindow.resizeToFit(commands)
cmdwindow.x = Graphics.width - cmdwindow.width
cmdwindow.y = 0
cmdwindow.visible = true
loop do
cmdwindow.update
Graphics.update
Input.update
pbUpdateSceneMap
if Input.trigger?(Input::BACK) || Input.trigger?(Input::ACTION)
ret = -1
break
elsif Input.trigger?(Input::USE)
ret = cmdwindow.index
$game_temp.menu_last_choice = ret
break
end
end
return ret
end
def pbEndScene
pbDisposeSpriteHash(@sprites)
@viewport.dispose
end
def pbRefresh; end
end
#===============================================================================
#
#===============================================================================
class PokemonPauseMenu
def initialize(scene)
@scene = scene
end
def pbShowMenu
@scene.pbRefresh
@scene.pbShowMenu
end
def pbShowInfo; end
def pbStartPokemonMenu
if !$player
if $DEBUG
pbMessage(_INTL("The player trainer was not defined, so the pause menu can't be displayed."))
pbMessage(_INTL("Please see the documentation to learn how to set up the trainer player."))
end
return
end
@scene.pbStartScene
# Show extra info window if relevant
pbShowInfo
# Get all commands
command_list = []
commands = []
MenuHandlers.each_available(:pause_menu) do |option, hash, name|
command_list.push(name)
commands.push(hash)
end
# Main loop
end_scene = false
loop do
choice = @scene.pbShowCommands(command_list)
if choice < 0
pbPlayCloseMenuSE
end_scene = true
break
end
break if commands[choice]["effect"].call(@scene)
end
@scene.pbEndScene if end_scene
end
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
# Pokémon party buttons and menu.
#===============================================================================
@@ -9,13 +10,13 @@ class PokemonPartyConfirmCancelSprite < Sprite
@refreshBitmap = true
@bgsprite = ChangelingSprite.new(0, 0, viewport)
if narrowbox
@bgsprite.addBitmap("desel", "Graphics/UI/Party/icon_cancel_narrow")
@bgsprite.addBitmap("sel", "Graphics/UI/Party/icon_cancel_narrow_sel")
@bgsprite.add_bitmap(:desel, "Graphics/UI/Party/icon_cancel_narrow")
@bgsprite.add_bitmap(:sel, "Graphics/UI/Party/icon_cancel_narrow_sel")
else
@bgsprite.addBitmap("desel", "Graphics/UI/Party/icon_cancel")
@bgsprite.addBitmap("sel", "Graphics/UI/Party/icon_cancel_sel")
@bgsprite.add_bitmap(:desel, "Graphics/UI/Party/icon_cancel")
@bgsprite.add_bitmap(:sel, "Graphics/UI/Party/icon_cancel_sel")
end
@bgsprite.changeBitmap("desel")
@bgsprite.change_bitmap(:desel)
@overlaysprite = BitmapSprite.new(@bgsprite.bitmap.width, @bgsprite.bitmap.height, viewport)
@overlaysprite.z = self.z + 1
pbSetSystemFont(@overlaysprite.bitmap)
@@ -61,7 +62,7 @@ class PokemonPartyConfirmCancelSprite < Sprite
def refresh
if @bgsprite && !@bgsprite.disposed?
@bgsprite.changeBitmap((@selected) ? "sel" : "desel")
@bgsprite.change_bitmap((@selected) ? :sel : :desel)
@bgsprite.x = self.x
@bgsprite.y = self.y
@bgsprite.color = self.color
@@ -184,31 +185,31 @@ class PokemonPartyPanel < Sprite
@panelbgsprite = ChangelingSprite.new(0, 0, viewport)
@panelbgsprite.z = self.z
if @active # Rounded panel
@panelbgsprite.addBitmap("able", "Graphics/UI/Party/panel_round")
@panelbgsprite.addBitmap("ablesel", "Graphics/UI/Party/panel_round_sel")
@panelbgsprite.addBitmap("fainted", "Graphics/UI/Party/panel_round_faint")
@panelbgsprite.addBitmap("faintedsel", "Graphics/UI/Party/panel_round_faint_sel")
@panelbgsprite.addBitmap("swap", "Graphics/UI/Party/panel_round_swap")
@panelbgsprite.addBitmap("swapsel", "Graphics/UI/Party/panel_round_swap_sel")
@panelbgsprite.addBitmap("swapsel2", "Graphics/UI/Party/panel_round_swap_sel2")
@panelbgsprite.add_bitmap(:able, "Graphics/UI/Party/panel_round")
@panelbgsprite.add_bitmap(:ablesel, "Graphics/UI/Party/panel_round_sel")
@panelbgsprite.add_bitmap(:fainted, "Graphics/UI/Party/panel_round_faint")
@panelbgsprite.add_bitmap(:faintedsel, "Graphics/UI/Party/panel_round_faint_sel")
@panelbgsprite.add_bitmap(:swap, "Graphics/UI/Party/panel_round_swap")
@panelbgsprite.add_bitmap(:swapsel, "Graphics/UI/Party/panel_round_swap_sel")
@panelbgsprite.add_bitmap(:swapsel2, "Graphics/UI/Party/panel_round_swap_sel2")
else # Rectangular panel
@panelbgsprite.addBitmap("able", "Graphics/UI/Party/panel_rect")
@panelbgsprite.addBitmap("ablesel", "Graphics/UI/Party/panel_rect_sel")
@panelbgsprite.addBitmap("fainted", "Graphics/UI/Party/panel_rect_faint")
@panelbgsprite.addBitmap("faintedsel", "Graphics/UI/Party/panel_rect_faint_sel")
@panelbgsprite.addBitmap("swap", "Graphics/UI/Party/panel_rect_swap")
@panelbgsprite.addBitmap("swapsel", "Graphics/UI/Party/panel_rect_swap_sel")
@panelbgsprite.addBitmap("swapsel2", "Graphics/UI/Party/panel_rect_swap_sel2")
@panelbgsprite.add_bitmap(:able, "Graphics/UI/Party/panel_rect")
@panelbgsprite.add_bitmap(:ablesel, "Graphics/UI/Party/panel_rect_sel")
@panelbgsprite.add_bitmap(:fainted, "Graphics/UI/Party/panel_rect_faint")
@panelbgsprite.add_bitmap(:faintedsel, "Graphics/UI/Party/panel_rect_faint_sel")
@panelbgsprite.add_bitmap(:swap, "Graphics/UI/Party/panel_rect_swap")
@panelbgsprite.add_bitmap(:swapsel, "Graphics/UI/Party/panel_rect_swap_sel")
@panelbgsprite.add_bitmap(:swapsel2, "Graphics/UI/Party/panel_rect_swap_sel2")
end
@hpbgsprite = ChangelingSprite.new(0, 0, viewport)
@hpbgsprite.z = self.z + 1
@hpbgsprite.addBitmap("able", _INTL("Graphics/UI/Party/overlay_hp_back"))
@hpbgsprite.addBitmap("fainted", _INTL("Graphics/UI/Party/overlay_hp_back_faint"))
@hpbgsprite.addBitmap("swap", _INTL("Graphics/UI/Party/overlay_hp_back_swap"))
@hpbgsprite.add_bitmap(:able, _INTL("Graphics/UI/Party/overlay_hp_back"))
@hpbgsprite.add_bitmap(:fainted, _INTL("Graphics/UI/Party/overlay_hp_back_faint"))
@hpbgsprite.add_bitmap(:swap, _INTL("Graphics/UI/Party/overlay_hp_back_swap"))
@ballsprite = ChangelingSprite.new(0, 0, viewport)
@ballsprite.z = self.z + 1
@ballsprite.addBitmap("desel", "Graphics/UI/Party/icon_ball")
@ballsprite.addBitmap("sel", "Graphics/UI/Party/icon_ball_sel")
@ballsprite.add_bitmap(:desel, "Graphics/UI/Party/icon_ball")
@ballsprite.add_bitmap(:sel, "Graphics/UI/Party/icon_ball_sel")
@pkmnsprite = PokemonIconSprite.new(pokemon, viewport)
@pkmnsprite.setOffset(PictureOrigin::CENTER)
@pkmnsprite.active = @active
@@ -296,21 +297,21 @@ class PokemonPartyPanel < Sprite
return if !@panelbgsprite || @panelbgsprite.disposed?
if self.selected
if self.preselected
@panelbgsprite.changeBitmap("swapsel2")
@panelbgsprite.change_bitmap(:swapsel2)
elsif @switching
@panelbgsprite.changeBitmap("swapsel")
@panelbgsprite.change_bitmap(:swapsel)
elsif @pokemon.fainted?
@panelbgsprite.changeBitmap("faintedsel")
@panelbgsprite.change_bitmap(:faintedsel)
else
@panelbgsprite.changeBitmap("ablesel")
@panelbgsprite.change_bitmap(:ablesel)
end
else
if self.preselected
@panelbgsprite.changeBitmap("swap")
@panelbgsprite.change_bitmap(:swap)
elsif @pokemon.fainted?
@panelbgsprite.changeBitmap("fainted")
@panelbgsprite.change_bitmap(:fainted)
else
@panelbgsprite.changeBitmap("able")
@panelbgsprite.change_bitmap(:able)
end
end
@panelbgsprite.x = self.x
@@ -323,11 +324,11 @@ class PokemonPartyPanel < Sprite
@hpbgsprite.visible = (!@pokemon.egg? && !(@text && @text.length > 0))
return if !@hpbgsprite.visible
if self.preselected || (self.selected && @switching)
@hpbgsprite.changeBitmap("swap")
@hpbgsprite.change_bitmap(:swap)
elsif @pokemon.fainted?
@hpbgsprite.changeBitmap("fainted")
@hpbgsprite.change_bitmap(:fainted)
else
@hpbgsprite.changeBitmap("able")
@hpbgsprite.change_bitmap(:able)
end
@hpbgsprite.x = self.x + 96
@hpbgsprite.y = self.y + 50
@@ -336,7 +337,7 @@ class PokemonPartyPanel < Sprite
def refresh_ball_graphic
return if !@ballsprite || @ballsprite.disposed?
@ballsprite.changeBitmap((self.selected) ? "sel" : "desel")
@ballsprite.change_bitmap((self.selected) ? :sel : :desel)
@ballsprite.x = self.x + 10
@ballsprite.y = self.y
@ballsprite.color = self.color
@@ -686,10 +687,7 @@ class PokemonParty_Scene
self.update
break if oldsprite.x == old_start_x - (old_mult * Graphics.width / 2)
end
Settings::MAX_PARTY_SIZE.times do |i|
@sprites["pokemon#{i}"].preselected = false
@sprites["pokemon#{i}"].switching = false
end
pbClearSwitching
pbRefresh
end
@@ -702,9 +700,7 @@ class PokemonParty_Scene
def pbSummary(pkmnid, inbattle = false)
oldsprites = pbFadeOutAndHide(@sprites)
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene, inbattle)
screen.pbStartScreen(@party, pkmnid)
UI::PokemonSummary.new(@party, pkmnid, mode: (inbattle ? :in_battle : :normal)).main
yield if block_given?
pbRefresh
pbFadeInAndShow(@sprites, oldsprites)
@@ -728,7 +724,7 @@ class PokemonParty_Scene
screen = PokemonBagScreen.new(scene, bag)
ret = screen.pbChooseItemScreen(proc { |item|
itm = GameData::Item.get(item)
next false if !pbCanUseOnPokemon?(itm)
next false if !pbCanUseItemOnPokemon?(itm)
next false if pokemon.hyper_mode && !GameData::Item.get(item)&.is_scent?
if itm.is_machine?
move = itm.move
@@ -916,43 +912,6 @@ class PokemonPartyScreen
@scene.pbStartScene(@party, helptext, annotations)
end
def pbChoosePokemon(helptext = nil)
@scene.pbSetHelpText(helptext) if helptext
return @scene.pbChoosePokemon
end
def pbPokemonGiveScreen(item)
@scene.pbStartScene(@party, _INTL("Give to which Pokémon?"))
pkmnid = @scene.pbChoosePokemon
ret = false
if pkmnid >= 0
ret = pbGiveItemToPokemon(item, @party[pkmnid], self, pkmnid)
end
pbRefreshSingle(pkmnid)
@scene.pbEndScene
return ret
end
def pbPokemonGiveMailScreen(mailIndex)
@scene.pbStartScene(@party, _INTL("Give to which Pokémon?"))
pkmnid = @scene.pbChoosePokemon
if pkmnid >= 0
pkmn = @party[pkmnid]
if pkmn.hasItem? || pkmn.mail
pbDisplay(_INTL("This Pokémon is holding an item. It can't hold mail."))
elsif pkmn.egg?
pbDisplay(_INTL("Eggs can't hold mail."))
else
pbDisplay(_INTL("Mail was transferred from the Mailbox."))
pkmn.mail = $PokemonGlobal.mailbox[mailIndex]
pkmn.item = pkmn.mail.item
$PokemonGlobal.mailbox.delete_at(mailIndex)
pbRefreshSingle(pkmnid)
end
end
@scene.pbEndScene
end
def pbEndScene
@scene.pbEndScene
end
@@ -1008,6 +967,53 @@ class PokemonPartyScreen
return true
end
# For after using an evolution stone.
def pbRefreshAnnotations(ableProc)
return if !@scene.pbHasAnnotations?
annot = []
@party.each do |pkmn|
elig = ableProc.call(pkmn)
annot.push((elig) ? _INTL("ABLE") : _INTL("NOT ABLE"))
end
@scene.pbAnnotate(annot)
end
def pbClearAnnotations
@scene.pbAnnotate(nil)
end
def pbPokemonGiveScreen(item)
@scene.pbStartScene(@party, _INTL("Give to which Pokémon?"))
pkmnid = @scene.pbChoosePokemon
ret = false
if pkmnid >= 0
ret = pbGiveItemToPokemon(item, @party[pkmnid], self, pkmnid)
end
pbRefreshSingle(pkmnid)
@scene.pbEndScene
return ret
end
def pbPokemonGiveMailScreen(mailIndex)
@scene.pbStartScene(@party, _INTL("Give to which Pokémon?"))
pkmnid = @scene.pbChoosePokemon
if pkmnid >= 0
pkmn = @party[pkmnid]
if pkmn.hasItem? || pkmn.mail
pbDisplay(_INTL("This Pokémon is holding an item. It can't hold mail."))
elsif pkmn.egg?
pbDisplay(_INTL("Eggs can't hold mail."))
else
pbDisplay(_INTL("Mail was transferred from the Mailbox."))
pkmn.mail = $PokemonGlobal.mailbox[mailIndex]
pkmn.item = pkmn.mail.item
$PokemonGlobal.mailbox.delete_at(mailIndex)
pbRefreshSingle(pkmnid)
end
end
@scene.pbEndScene
end
def pbSwitch(oldid, newid)
if oldid != newid
@scene.pbSwitchBegin(oldid, newid)
@@ -1031,21 +1037,6 @@ class PokemonPartyScreen
return @scene.pbShowCommands(helptext, movenames, index)
end
# For after using an evolution stone.
def pbRefreshAnnotations(ableProc)
return if !@scene.pbHasAnnotations?
annot = []
@party.each do |pkmn|
elig = ableProc.call(pkmn)
annot.push((elig) ? _INTL("ABLE") : _INTL("NOT ABLE"))
end
@scene.pbAnnotate(annot)
end
def pbClearAnnotations
@scene.pbAnnotate(nil)
end
def pbPokemonMultipleEntryScreenEx(ruleset)
annot = []
statuses = []
@@ -1136,6 +1127,11 @@ class PokemonPartyScreen
return ret
end
def pbChoosePokemon(helptext = nil)
@scene.pbSetHelpText(helptext) if helptext
return @scene.pbChoosePokemon
end
def pbChooseAblePokemon(ableProc, allowIneligible = false)
annot = []
eligibility = []
@@ -1482,78 +1478,4 @@ MenuHandlers.add(:party_menu_item, :move, {
screen.scene.pbSelect(old_party_idx) if !moved
}
})
#===============================================================================
# Open the party screen.
#===============================================================================
def pbPokemonScreen
pbFadeOutIn do
sscene = PokemonParty_Scene.new
sscreen = PokemonPartyScreen.new(sscene, $player.party)
sscreen.pbPokemonScreen
end
end
#===============================================================================
# Choose a Pokémon in the party.
#===============================================================================
# Choose a Pokémon/egg from the party.
# Stores result in variable _variableNumber_ and the chosen Pokémon's name in
# variable _nameVarNumber_; result is -1 if no Pokémon was chosen
def pbChoosePokemon(variableNumber, nameVarNumber, ableProc = nil, allowIneligible = false)
chosen = 0
pbFadeOutIn do
scene = PokemonParty_Scene.new
screen = PokemonPartyScreen.new(scene, $player.party)
if ableProc
chosen = screen.pbChooseAblePokemon(ableProc, allowIneligible)
else
screen.pbStartScene(_INTL("Choose a Pokémon."), false)
chosen = screen.pbChoosePokemon
screen.pbEndScene
end
end
pbSet(variableNumber, chosen)
if chosen >= 0
pbSet(nameVarNumber, $player.party[chosen].name)
else
pbSet(nameVarNumber, "")
end
end
def pbChooseNonEggPokemon(variableNumber, nameVarNumber)
pbChoosePokemon(variableNumber, nameVarNumber, proc { |pkmn| !pkmn.egg? })
end
def pbChooseAblePokemon(variableNumber, nameVarNumber)
pbChoosePokemon(variableNumber, nameVarNumber, proc { |pkmn| !pkmn.egg? && pkmn.hp > 0 })
end
# Same as pbChoosePokemon, but prevents choosing an egg or a Shadow Pokémon.
def pbChooseTradablePokemon(variableNumber, nameVarNumber, ableProc = nil, allowIneligible = false)
chosen = 0
pbFadeOutIn do
scene = PokemonParty_Scene.new
screen = PokemonPartyScreen.new(scene, $player.party)
if ableProc
chosen = screen.pbChooseTradablePokemon(ableProc, allowIneligible)
else
screen.pbStartScene(_INTL("Choose a Pokémon."), false)
chosen = screen.pbChoosePokemon
screen.pbEndScene
end
end
pbSet(variableNumber, chosen)
if chosen >= 0
pbSet(nameVarNumber, $player.party[chosen].name)
else
pbSet(nameVarNumber, "")
end
end
def pbChoosePokemonForTrade(variableNumber, nameVarNumber, wanted)
wanted = GameData::Species.get(wanted).species
pbChooseTradablePokemon(variableNumber, nameVarNumber, proc { |pkmn|
next pkmn.species == wanted
})
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
#
#===============================================================================
@@ -75,12 +76,23 @@ class RibbonSelectionSprite < MoveSelectionSprite
@spriteVisible = value if !@updating
end
def recheck_visibility
@updating = true
self.visible = @spriteVisible && @index >= 0 &&
@index < UI::PokemonSummaryVisuals::RIBBON_COLUMNS * UI::PokemonSummaryVisuals::RIBBON_ROWS
@updating = false
end
def refresh
recheck_visibility
cols = UI::PokemonSummaryVisuals::RIBBON_COLUMNS
offset_x = UI::PokemonSummaryVisuals::RIBBON_SIZE[0] + UI::PokemonSummaryVisuals::RIBBON_SPACING_X
offset_y = UI::PokemonSummaryVisuals::RIBBON_SIZE[1] + UI::PokemonSummaryVisuals::RIBBON_SPACING_Y
self.x = UI::PokemonSummaryVisuals::RIBBON_X - 2 + ((self.index % cols) * offset_x)
self.y = UI::PokemonSummaryVisuals::RIBBON_Y - 2 + ((self.index / cols) * offset_y)
self.bitmap = @movesel.bitmap
w = @movesel.width
h = @movesel.height / 2
self.x = 228 + ((self.index % 4) * 68)
self.y = 76 + ((self.index / 4).floor * 68)
self.bitmap = @movesel.bitmap
if self.preselected
self.src_rect.set(0, h, w, h)
else
@@ -89,11 +101,9 @@ class RibbonSelectionSprite < MoveSelectionSprite
end
def update
@updating = true
super
self.visible = @spriteVisible && @index >= 0 && @index < 12
recheck_visibility
@movesel.update
@updating = false
refresh
end
end
@@ -839,7 +849,7 @@ class PokemonSummary_Scene
pbDrawTextPositions(overlay, textpos)
# Draw selected move's damage category icon
imagepos = [["Graphics/UI/category", 166, 124,
0, selected_move.display_category(@pokemon) * CATEGORY_ICON_SIZE[1], *CATEGORY_ICON_SIZE]]
0, selected_move.display_category(@pokemon) * GameData::Move::CATEGORY_ICON_SIZE[1], *GameData::Move::CATEGORY_ICON_SIZE]]
pbDrawImagePositions(overlay, imagepos)
# Draw selected move's description
drawTextEx(overlay, 4, 224, 230, 5, selected_move.description, base, shadow)
@@ -1367,6 +1377,7 @@ class PokemonSummaryScreen
return ret
end
# Unused.
def pbStartChooseMoveScreen(party, partyindex, message)
ret = -1
@scene.pbStartForgetScene(party, partyindex, nil)
@@ -1388,9 +1399,8 @@ def pbChooseMove(pokemon, variableNumber, nameVarNumber)
return if !pokemon
ret = -1
pbFadeOutIn do
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene)
ret = screen.pbStartForgetScreen([pokemon], 0, nil)
screen = UI::PokemonSummary.new(pokemon, mode: :choose_move)
ret = screen.choose_move
end
$game_variables[variableNumber] = ret
if ret >= 0
@@ -1400,3 +1410,4 @@ def pbChooseMove(pokemon, variableNumber, nameVarNumber)
end
$game_map.need_refresh = true if $game_map
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
#
#===============================================================================
@@ -97,7 +98,7 @@ class Window_PokemonBag < Window_DrawableCommand
end
if item_data.show_quantity? && !showing_register_icon
qty = (@filterlist) ? thispocket[@filterlist[@pocket][index]][1] : thispocket[index][1]
qtytext = _ISPRINTF("x{1: 3d}", qty)
qtytext = _ISPRINTF("×{1: 3d}", qty)
xQty = rect.x + rect.width - self.contents.text_size(qtytext).width - 16
textpos.push([qtytext, xQty, rect.y + 2, :left, baseColor, shadowColor])
end
@@ -513,10 +514,11 @@ class PokemonBagScreen
@scene.pbDisplay(_INTL("The {1} can't be held.", itm.portion_name))
else
pbFadeOutIn do
sscene = PokemonParty_Scene.new
sscreen = PokemonPartyScreen.new(sscene, $player.party)
sscreen.pbPokemonGiveScreen(item)
@scene.pbRefresh
screen = UI::Party.new($player.party, mode: :choose_pokemon)
screen.choose_pokemon do |pkmn, party_index|
pbGiveItemToPokemon(item, screen.pokemon, screen, chosen) if party_index >= 0
next true
end
end
end
elsif cmdToss >= 0 && command == cmdToss # Toss item
@@ -702,3 +704,4 @@ class PokemonBagScreen
@scene.pbEndScene
end
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
#
#===============================================================================
@@ -186,6 +187,8 @@ class PokemonRegionMap_Scene
next if point[0] != x || point[1] != y
return "" if point[7] && (@wallmap || point[7] <= 0 || !$game_switches[point[7]])
name = pbGetMessageFromHash(MessageTypes::REGION_LOCATION_NAMES, point[2])
name = name.gsub(/\\PN/, $player.name)
name = name.gsub(/\\v\[(\d+)\]/) { |num| $game_variables[$~[1].to_i].to_s }
return (@editor) ? point[2] : name
end
return ""
@@ -336,7 +339,7 @@ class PokemonRegionMapScreen
end
def pbStartScreen
@scene.pbStartScene($DEBUG)
@scene.pbStartScene # ($DEBUG)
ret = @scene.pbMapScene
@scene.pbEndScene
return ret
@@ -354,3 +357,4 @@ def pbShowMap(region = -1, wallmap = true)
$game_temp.fly_destination = ret if ret && !wallmap
end
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
#
#===============================================================================
@@ -113,3 +114,4 @@ class PokemonTrainerCardScreen
@scene.pbEndScene
end
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
#
#===============================================================================
@@ -356,3 +357,4 @@ class PokemonLoadScreen
end
end
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
#
#===============================================================================
@@ -107,9 +108,8 @@ end
#
#===============================================================================
def pbSaveScreen
scene = PokemonSave_Scene.new
screen = PokemonSaveScreen.new(scene)
ret = screen.pbSaveScreen
ret = false
pbFadeOutIn { ret = UI::Save.new.main }
return ret
end
@@ -137,3 +137,4 @@ def pbEmergencySave
end
$scene = oldscene
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
# Pokémon icons.
#===============================================================================
@@ -156,15 +157,15 @@ class PokemonBoxArrow < Sprite
@quickswap = false
@heldpkmn = nil
@handsprite = ChangelingSprite.new(0, 0, viewport)
@handsprite.addBitmap("point1", "Graphics/UI/Storage/cursor_point_1")
@handsprite.addBitmap("point2", "Graphics/UI/Storage/cursor_point_2")
@handsprite.addBitmap("grab", "Graphics/UI/Storage/cursor_grab")
@handsprite.addBitmap("fist", "Graphics/UI/Storage/cursor_fist")
@handsprite.addBitmap("point1q", "Graphics/UI/Storage/cursor_point_1_q")
@handsprite.addBitmap("point2q", "Graphics/UI/Storage/cursor_point_2_q")
@handsprite.addBitmap("grabq", "Graphics/UI/Storage/cursor_grab_q")
@handsprite.addBitmap("fistq", "Graphics/UI/Storage/cursor_fist_q")
@handsprite.changeBitmap("fist")
@handsprite.add_bitmap(:point1, "Graphics/UI/Storage/cursor_point_1")
@handsprite.add_bitmap(:point2, "Graphics/UI/Storage/cursor_point_2")
@handsprite.add_bitmap(:grab, "Graphics/UI/Storage/cursor_grab")
@handsprite.add_bitmap(:fist, "Graphics/UI/Storage/cursor_fist")
@handsprite.add_bitmap(:point1q, "Graphics/UI/Storage/cursor_point_1_q")
@handsprite.add_bitmap(:point2q, "Graphics/UI/Storage/cursor_point_2_q")
@handsprite.add_bitmap(:grabq, "Graphics/UI/Storage/cursor_grab_q")
@handsprite.add_bitmap(:fistq, "Graphics/UI/Storage/cursor_fist_q")
@handsprite.change_bitmap(:fist)
@spriteX = self.x
@spriteY = self.y
end
@@ -269,36 +270,36 @@ class PokemonBoxArrow < Sprite
@holding = false if !heldpkmn
if @grabbing_timer_start
if System.uptime - @grabbing_timer_start <= GRAB_TIME / 2
@handsprite.changeBitmap((@quickswap) ? "grabq" : "grab")
@handsprite.change_bitmap((@quickswap) ? :grabq : :grab)
self.y = @spriteY + lerp(0, 16, GRAB_TIME / 2, @grabbing_timer_start, System.uptime)
else
@holding = true
@handsprite.changeBitmap((@quickswap) ? "fistq" : "fist")
@handsprite.change_bitmap((@quickswap) ? :fistq : :fist)
delta_y = lerp(16, 0, GRAB_TIME / 2, @grabbing_timer_start + (GRAB_TIME / 2), System.uptime)
self.y = @spriteY + delta_y
@grabbing_timer_start = nil if delta_y == 0
end
elsif @placing_timer_start
if System.uptime - @placing_timer_start <= GRAB_TIME / 2
@handsprite.changeBitmap((@quickswap) ? "fistq" : "fist")
@handsprite.change_bitmap((@quickswap) ? :fistq : :fist)
self.y = @spriteY + lerp(0, 16, GRAB_TIME / 2, @placing_timer_start, System.uptime)
else
@holding = false
@heldpkmn = nil
@handsprite.changeBitmap((@quickswap) ? "grabq" : "grab")
@handsprite.change_bitmap((@quickswap) ? :grabq : :grab)
delta_y = lerp(16, 0, GRAB_TIME / 2, @placing_timer_start + (GRAB_TIME / 2), System.uptime)
self.y = @spriteY + delta_y
@placing_timer_start = nil if delta_y == 0
end
elsif holding?
@handsprite.changeBitmap((@quickswap) ? "fistq" : "fist")
@handsprite.change_bitmap((@quickswap) ? :fistq : :fist)
else # Idling
self.x = @spriteX
self.y = @spriteY
if (System.uptime / 0.5).to_i.even? # Changes every 0.5 seconds
@handsprite.changeBitmap((@quickswap) ? "point1q" : "point1")
@handsprite.change_bitmap((@quickswap) ? :point1q : :point1)
else
@handsprite.changeBitmap((@quickswap) ? "point2q" : "point2")
@handsprite.change_bitmap((@quickswap) ? :point2q : :point2)
end
end
@updating = false
@@ -501,6 +502,13 @@ class PokemonBoxPartySprite < Sprite
refresh
end
def z=(value)
super
Settings::MAX_PARTY_SIZE.times do |i|
@pokemonsprites[i].z = value + 1 if @pokemonsprites[i] && !@pokemonsprites[i].disposed?
end
end
def color=(value)
super
Settings::MAX_PARTY_SIZE.times do |i|
@@ -565,7 +573,7 @@ class PokemonBoxPartySprite < Sprite
sprite.viewport = self.viewport
sprite.x = self.x + xvalues[j]
sprite.y = self.y + yvalues[j]
sprite.z = 1
sprite.z = self.z + 1
end
end
@@ -1237,25 +1245,24 @@ class PokemonStorageScene
def pbChooseItem(bag)
ret = nil
pbFadeOutIn do
scene = PokemonBag_Scene.new
screen = PokemonBagScreen.new(scene, bag)
ret = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).can_hold? })
bag_screen = UI::Bag.new(bag, mode: :choose_item)
bag_screen.set_filter_proc(proc { |itm| GameData::Item.get(itm).can_hold? })
ret = bag_screen.choose_item
end
return ret
end
def pbSummary(selected, heldpoke)
oldsprites = pbFadeOutAndHide(@sprites)
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene)
if heldpoke
screen.pbStartScreen([heldpoke], 0)
UI::PokemonSummary.new(heldpoke).main
elsif selected[0] == -1
@selection = screen.pbStartScreen(@storage.party, selected[1])
screen = UI::PokemonSummary.new(@storage.party, selected[1]).main
@selection = screen.result
pbPartySetArrow(@sprites["arrow"], @selection)
pbUpdateOverlay(@selection, @storage.party)
else
@selection = screen.pbStartScreen(@storage.boxes[selected[0]], selected[1])
@selection = UI::PokemonSummary.new(@storage.boxes[selected[0]].pokemon, selected[1]).main
pbSetArrow(@sprites["arrow"], @selection)
pbUpdateOverlay(@selection)
end
@@ -1576,7 +1583,7 @@ class PokemonStorageScreen
elsif cmdRelease >= 0 && command == cmdRelease # Release
pbRelease(selected, @heldpkmn)
elsif cmdDebug >= 0 && command == cmdDebug # Debug
pbPokemonDebug((@heldpkmn) ? @heldpkmn : pokemon, selected, heldpoke)
pokemon_debug_menu((@heldpkmn) ? @heldpkmn : pokemon, selected, heldpoke)
end
end
end
@@ -2023,3 +2030,4 @@ class PokemonStorageScreen
return retval
end
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
# Abstraction layer for Pokemon Essentials.
#===============================================================================
@@ -27,12 +28,7 @@ class PokemonMartAdapter
end
def getDisplayName(item)
item_name = GameData::Item.get(item).name
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
return GameData::Item.get(item).display_name
end
def getDisplayNamePlural(item)
@@ -161,11 +157,8 @@ class SellAdapter
end
def getDisplayPrice(item)
if @adapter.showQuantity?(item)
return sprintf("x%d", @adapter.getQuantity(item))
else
return ""
end
return sprintf("×%d", @adapter.getQuantity(item)) if @adapter.showQuantity?(item)
return ""
end
def isSelling?
@@ -218,27 +211,6 @@ end
#
#===============================================================================
class PokemonMart_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["moneywindow"].text = _INTL("Money:\n<r>{1}", @adapter.getMoneyString)
end
def pbStartBuyOrSellScene(buying, stock, adapter)
# Scroll right before showing screen
pbScrollMap(6, 5, 5)
@@ -249,7 +221,7 @@ class PokemonMart_Scene
@sprites = {}
@sprites["background"] = IconSprite.new(0, 0, @viewport)
@sprites["background"].setBitmap("Graphics/UI/Mart/bg")
@sprites["icon"] = ItemIconSprite.new(36, Graphics.height - 50, nil, @viewport)
@sprites["icon"] = ItemIconSprite.new(48, Graphics.height - 48, nil, @viewport)
winAdapter = buying ? BuyAdapter.new(adapter) : SellAdapter.new(adapter)
@sprites["itemwindow"] = Window_PokemonMart.new(
stock, winAdapter, Graphics.width - 316 - 16, 10, 330 + 16, Graphics.height - 124
@@ -258,7 +230,7 @@ class PokemonMart_Scene
@sprites["itemwindow"].index = 0
@sprites["itemwindow"].refresh
@sprites["itemtextwindow"] = Window_UnformattedTextPokemon.newWithSize(
"", 64, Graphics.height - 96 - 16, Graphics.width - 64, 128, @viewport
"", 76, 272, Graphics.width - 98, 128, @viewport
)
pbPrepareWindow(@sprites["itemtextwindow"])
@sprites["itemtextwindow"].baseColor = Color.new(248, 248, 248)
@@ -362,6 +334,8 @@ class PokemonMart_Scene
pbScrollMap(4, 5, 5) if !@subscene
end
#-----------------------------------------------------------------------------
def pbPrepareWindow(window)
window.visible = true
window.letterbyletter = false
@@ -387,6 +361,8 @@ class PokemonMart_Scene
@sprites["qtywindow"].visible = false
end
#-----------------------------------------------------------------------------
def pbDisplay(msg, brief = false)
cw = @sprites["helpwindow"]
cw.letterbyletter = true
@@ -487,7 +463,7 @@ class PokemonMart_Scene
numwindow.height = 64
numwindow.baseColor = Color.new(88, 88, 80)
numwindow.shadowColor = Color.new(168, 184, 184)
numwindow.text = _INTL("x{1}<r>$ {2}", curnumber, (curnumber * itemprice).to_s_formatted)
numwindow.text = _INTL("×{1}<r>$ {2}", curnumber, (curnumber * itemprice).to_s_formatted)
pbBottomRight(numwindow)
numwindow.y -= helpwindow.height
loop do
@@ -500,28 +476,28 @@ class PokemonMart_Scene
curnumber -= 10
curnumber = 1 if curnumber < 1
if curnumber != oldnumber
numwindow.text = _INTL("x{1}<r>$ {2}", curnumber, (curnumber * itemprice).to_s_formatted)
numwindow.text = _INTL("×{1}<r>$ {2}", 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}", curnumber, (curnumber * itemprice).to_s_formatted)
numwindow.text = _INTL("×{1}<r>$ {2}", 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}", curnumber, (curnumber * itemprice).to_s_formatted)
numwindow.text = _INTL("×{1}<r>$ {2}", 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}", curnumber, (curnumber * itemprice).to_s_formatted)
numwindow.text = _INTL("×{1}<r>$ {2}", curnumber, (curnumber * itemprice).to_s_formatted)
pbPlayCursorSE
end
elsif Input.trigger?(Input::USE)
@@ -538,6 +514,31 @@ class PokemonMart_Scene
return ret
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["moneywindow"].text = _INTL("Money:\n<r>{1}", @adapter.getMoneyString)
end
def update
pbUpdateSpriteHash(@sprites)
@subscene&.pbUpdate
end
#-----------------------------------------------------------------------------
def pbChooseBuyItem
itemwindow = @sprites["itemwindow"]
@sprites["helpwindow"].visible = false
@@ -583,18 +584,22 @@ class PokemonMartScreen
@adapter = PokemonMartAdapter.new
end
def pbConfirm(msg)
return @scene.pbConfirm(msg)
end
#-----------------------------------------------------------------------------
def pbDisplay(msg)
return @scene.pbDisplay(msg)
end
def pbConfirm(msg)
return @scene.pbConfirm(msg)
end
def pbDisplayPaused(msg, &block)
return @scene.pbDisplayPaused(msg, &block)
end
#-----------------------------------------------------------------------------
def pbBuyScreen
@scene.pbStartBuyScene(@stock, @adapter)
item = nil
@@ -614,8 +619,8 @@ class PokemonMartScreen
itemname, price.to_s_formatted))
quantity = 1
else
maxafford = (price <= 0) ? Settings::BAG_MAX_PER_SLOT : @adapter.getMoney / price
maxafford = Settings::BAG_MAX_PER_SLOT if maxafford > Settings::BAG_MAX_PER_SLOT
maxafford = (price <= 0) ? PokemonBag::MAX_PER_SLOT : @adapter.getMoney / price
maxafford = PokemonBag::MAX_PER_SLOT if maxafford > PokemonBag::MAX_PER_SLOT
quantity = @scene.pbChooseNumber(
_INTL("So how many {1}?", itemnameplural), item, maxafford
)
@@ -715,34 +720,4 @@ class PokemonMartScreen
@scene.pbEndSellScene
end
end
#===============================================================================
#
#===============================================================================
def pbPokemonMart(stock, speech = nil, cantsell = false)
stock.delete_if { |item| GameData::Item.get(item).is_important? && $bag.has?(item) }
commands = []
cmdBuy = -1
cmdSell = -1
cmdQuit = -1
commands[cmdBuy = commands.length] = _INTL("I'm here to buy")
commands[cmdSell = commands.length] = _INTL("I'm here to sell") if !cantsell
commands[cmdQuit = commands.length] = _INTL("No, thanks")
cmd = pbMessage(speech || _INTL("Welcome! How may I help you?"), commands, cmdQuit + 1)
loop do
if cmdBuy >= 0 && cmd == cmdBuy
scene = PokemonMart_Scene.new
screen = PokemonMartScreen.new(scene, stock)
screen.pbBuyScreen
elsif cmdSell >= 0 && cmd == cmdSell
scene = PokemonMart_Scene.new
screen = PokemonMartScreen.new(scene, stock)
screen.pbSellScreen
else
pbMessage(_INTL("Do come again!"))
break
end
cmd = pbMessage(_INTL("Is there anything else I can do for you?"), commands, cmdQuit + 1)
end
$game_temp.clear_mart_prices
end
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
# Abstraction layer for Pokemon Essentials.
#===============================================================================
@@ -343,7 +344,7 @@ class BattlePointShop_Scene
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)
numwindow.text = _INTL("×{1}<r>{2} BP", curnumber, (curnumber * itemprice).to_s_formatted)
pbBottomRight(numwindow)
numwindow.y -= helpwindow.height
loop do
@@ -356,28 +357,28 @@ class BattlePointShop_Scene
curnumber -= 10
curnumber = 1 if curnumber < 1
if curnumber != oldnumber
numwindow.text = _INTL("x{1}<r>{2} BP", curnumber, (curnumber * itemprice).to_s_formatted)
numwindow.text = _INTL("×{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)
numwindow.text = _INTL("×{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)
numwindow.text = _INTL("×{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)
numwindow.text = _INTL("×{1}<r>{2} BP", curnumber, (curnumber * itemprice).to_s_formatted)
pbPlayCursorSE
end
elsif Input.trigger?(Input::USE)
@@ -462,8 +463,8 @@ class BattlePointShopScreen
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
maxafford = (price <= 0) ? PokemonBag::MAX_PER_SLOT : @adapter.getBP / price
maxafford = PokemonBag::MAX_PER_SLOT if maxafford > PokemonBag::MAX_PER_SLOT
quantity = @scene.pbChooseNumber(
_INTL("How many {1} would you like?", itemnameplural), item, maxafford
)
@@ -504,22 +505,4 @@ class BattlePointShopScreen
@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
=end

View File

@@ -1,3 +1,4 @@
=begin
#===============================================================================
# Scene class for handling appearance of the screen.
#===============================================================================
@@ -84,7 +85,7 @@ class MoveRelearner_Scene
0, 78 + ((@sprites["commands"].index - @sprites["commands"].top_item) * 64),
0, 0, 258, 72])
selMoveData = GameData::Move.get(@moves[@sprites["commands"].index])
power = selMoveData.display_damage(@pokemon)
power = selMoveData.display_power(@pokemon)
category = selMoveData.display_category(@pokemon)
accuracy = selMoveData.display_accuracy(@pokemon)
textpos.push([_INTL("CATEGORY"), 272, 120, :left, Color.new(248, 248, 248), Color.black])
@@ -95,7 +96,7 @@ class MoveRelearner_Scene
textpos.push([accuracy == 0 ? "---" : "#{accuracy}%", 468, 184, :center,
Color.new(64, 64, 64), Color.new(176, 176, 176)])
pbDrawTextPositions(overlay, textpos)
imagepos.push(["Graphics/UI/category", 436, 116, 0, category * CATEGORY_ICON_SIZE[1], *CATEGORY_ICON_SIZE])
imagepos.push(["Graphics/UI/category", 436, 116, 0, category * GameData::Move::CATEGORY_ICON_SIZE[1], *GameData::Move::CATEGORY_ICON_SIZE])
if @sprites["commands"].index < @moves.length - 1
imagepos.push(["Graphics/UI/Move Reminder/buttons", 48, 350, 0, 0, 76, 32])
end
@@ -197,3 +198,4 @@ def pbRelearnMoveScreen(pkmn)
end
return retval
end
=end

View File

@@ -36,17 +36,16 @@ end
#
#===============================================================================
def pbEntryScreen(*arg)
retval = false
ret_val = false
pbFadeOutIn do
scene = PokemonParty_Scene.new
screen = PokemonPartyScreen.new(scene, $player.party)
ret = screen.pbPokemonMultipleEntryScreenEx(pbBattleChallenge.rules.ruleset)
screen = UI::Party.new($player.party, mode: :choose_entry_order)
ret = screen.choose_pokemon_entry_order(pbBattleChallenge.rules.ruleset)
# Set party
pbBattleChallenge.setParty(ret) if ret
# Continue (return true) if Pokémon were chosen
retval = (ret && ret.length > 0)
ret_val = (ret && ret.length > 0)
end
return retval
return ret_val
end
#===============================================================================

View File

@@ -146,9 +146,8 @@ class BattleSwapScene
def pbSummary(list, index)
visibleSprites = pbFadeOutAndHide(@sprites) { pbUpdate }
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene)
@sprites["list"].index = screen.pbStartScreen(list, index)
screen = UI::PokemonSummary.new(list, index).main
@sprites["list"].index = screen.result
pbFadeInAndShow(@sprites, visibleSprites) { pbUpdate }
end

View File

@@ -164,21 +164,36 @@ end
#===============================================================================
#
#===============================================================================
class PokemonPauseMenu
alias __safari_pbShowInfo pbShowInfo unless method_defined?(:__safari_pbShowInfo)
class UI::PauseMenu < UI::BaseScreen
alias __safari_show_info show_info unless method_defined?(:__safari_show_info)
def pbShowInfo
__safari_pbShowInfo
def show_info
__safari_show_info
return if !pbInSafari?
if Settings::SAFARI_STEPS <= 0
@scene.pbShowInfo(_INTL("Balls: {1}", pbSafariState.ballcount))
@visuals.show_info(_INTL("Balls: {1}", pbSafariState.ballcount))
else
@scene.pbShowInfo(_INTL("Steps: {1}/{2}\nBalls: {3}",
pbSafariState.steps, Settings::SAFARI_STEPS, pbSafariState.ballcount))
@visuals.show_info(_INTL("Steps: {1}/{2}\nBalls: {3}",
pbSafariState.steps, Settings::SAFARI_STEPS, pbSafariState.ballcount))
end
end
end
# class PokemonPauseMenu
# alias __safari_pbShowInfo pbShowInfo unless method_defined?(:__safari_pbShowInfo)
#
# def pbShowInfo
# __safari_pbShowInfo
# return if !pbInSafari?
# if Settings::SAFARI_STEPS <= 0
# @scene.pbShowInfo(_INTL("Balls: {1}", pbSafariState.ballcount))
# else
# @scene.pbShowInfo(_INTL("Steps: {1}/{2}\nBalls: {3}",
# pbSafariState.steps, Settings::SAFARI_STEPS, pbSafariState.ballcount))
# end
# end
# end
#===============================================================================
#
#===============================================================================
@@ -188,15 +203,15 @@ MenuHandlers.add(:pause_menu, :quit_safari_game, {
"order" => 60,
"condition" => proc { next pbInSafari? },
"effect" => proc { |menu|
menu.pbHideMenu
menu.hide_menu
if pbConfirmMessage(_INTL("Would you like to leave the Safari Game right now?"))
menu.pbEndScene
menu.silent_end_screen
pbSafariState.decision = 1
pbSafariState.pbGoToStart
next true
end
menu.pbRefresh
menu.pbShowMenu
menu.refresh
menu.show_menu
next false
}
})

View File

@@ -408,23 +408,40 @@ end
#===============================================================================
#
#===============================================================================
class PokemonPauseMenu
alias __bug_contest_pbShowInfo pbShowInfo unless method_defined?(:__bug_contest_pbShowInfo)
class UI::PauseMenu < UI::BaseScreen
alias __bug_contest_show_info show_info unless method_defined?(:__bug_contest_show_info)
def pbShowInfo
__bug_contest_pbShowInfo
def show_info
__bug_contest_show_info
return if !pbInBugContest?
if pbBugContestState.lastPokemon
@scene.pbShowInfo(_INTL("Caught: {1}\nLevel: {2}\nBalls: {3}",
pbBugContestState.lastPokemon.speciesName,
pbBugContestState.lastPokemon.level,
pbBugContestState.ballcount))
@visuals.show_info(_INTL("Caught: {1}\nLevel: {2}\nBalls: {3}",
pbBugContestState.lastPokemon.speciesName,
pbBugContestState.lastPokemon.level,
pbBugContestState.ballcount))
else
@scene.pbShowInfo(_INTL("Caught: None\nBalls: {1}", pbBugContestState.ballcount))
@visuals.show_info(_INTL("Caught: None\nBalls: {1}", pbBugContestState.ballcount))
end
end
end
# class PokemonPauseMenu
# alias __bug_contest_pbShowInfo pbShowInfo unless method_defined?(:__bug_contest_pbShowInfo)
#
# def pbShowInfo
# __bug_contest_pbShowInfo
# return if !pbInBugContest?
# if pbBugContestState.lastPokemon
# @scene.pbShowInfo(_INTL("Caught: {1}\nLevel: {2}\nBalls: {3}",
# pbBugContestState.lastPokemon.speciesName,
# pbBugContestState.lastPokemon.level,
# pbBugContestState.ballcount))
# else
# @scene.pbShowInfo(_INTL("Caught: None\nBalls: {1}", pbBugContestState.ballcount))
# end
# end
# end
#===============================================================================
#
#===============================================================================
@@ -434,14 +451,14 @@ MenuHandlers.add(:pause_menu, :quit_bug_contest, {
"order" => 60,
"condition" => proc { next pbInBugContest? },
"effect" => proc { |menu|
menu.pbHideMenu
menu.hide_menu
if pbConfirmMessage(_INTL("Would you like to end the Contest now?"))
menu.pbEndScene
menu.silent_end_screen
pbBugContestState.pbStartJudging
next true
end
menu.pbRefresh
menu.pbShowMenu
menu.refresh
menu.show_menu
next false
}
})

View File

@@ -60,6 +60,11 @@ def pbGetLanguage
return 2 # Use 'English' by default
end
def pbChooseLanguage
commands = Settings::LANGUAGES.map { |val| val[0] }
return pbShowCommands(nil, commands)
end
# Converts a Celsius temperature to Fahrenheit.
def toFahrenheit(celsius)
return (celsius * 9.0 / 5.0).round + 32
@@ -445,39 +450,38 @@ def pbMoveTutorAnnotations(move, movelist = nil)
return ret
end
def pbMoveTutorChoose(move, movelist = nil, bymachine = false, oneusemachine = false)
# TODO: The Bag screen needs passing into this method (if using a machine). If
# it exists, refresh it before finishing pbFadeOutIn to update the party
# compatibility icons.
def pbMoveTutorChoose(move, movelist = nil, by_machine = false, one_use_machine = false)
ret = false
move = GameData::Move.get(move).id
if movelist.is_a?(Array)
movelist.map! { |m| GameData::Move.get(m).id }
end
pbFadeOutIn do
movename = GameData::Move.get(move).name
move_name = GameData::Move.get(move).name
screen = UI::Party.new($player.party, mode: :teach_pokemon)
annot = pbMoveTutorAnnotations(move, movelist)
scene = PokemonParty_Scene.new
screen = PokemonPartyScreen.new(scene, $player.party)
screen.pbStartScene(_INTL("Teach which Pokémon?"), false, annot)
loop do
chosen = screen.pbChoosePokemon
break if chosen < 0
pokemon = $player.party[chosen]
if pokemon.egg?
pbMessage(_INTL("Eggs can't be taught any moves.")) { screen.pbUpdate }
elsif pokemon.shadowPokemon?
pbMessage(_INTL("Shadow Pokémon can't be taught any moves.")) { screen.pbUpdate }
elsif movelist && movelist.none? { |j| j == pokemon.species }
pbMessage(_INTL("{1} can't learn {2}.", pokemon.name, movename)) { screen.pbUpdate }
elsif !pokemon.compatible_with_move?(move)
pbMessage(_INTL("{1} can't learn {2}.", pokemon.name, movename)) { screen.pbUpdate }
elsif pbLearnMove(pokemon, move, false, bymachine) { screen.pbUpdate }
$stats.moves_taught_by_item += 1 if bymachine
$stats.moves_taught_by_tutor += 1 if !bymachine
pokemon.add_first_move(move) if oneusemachine
ret = true
break
screen.set_annotations(annot)
screen.choose_pokemon do |pkmn, party_index|
next true if party_index < 0
if pkmn.egg?
screen.show_message(_INTL("Eggs can't be taught any moves."))
elsif pkmn.shadowPokemon?
screen.show_message(_INTL("Shadow Pokémon can't be taught any moves."))
elsif movelist && movelist.none? { |j| j == pkmn.species }
screen.show_message(_INTL("{1} can't learn {2}.", pkmn.name, move_name))
elsif !pkmn.compatible_with_move?(move)
screen.show_message(_INTL("{1} can't learn {2}.", pkmn.name, move_name))
elsif pbLearnMove(pkmn, move, false, by_machine, screen) { screen.update }
$stats.moves_taught_by_item += 1 if by_machine
$stats.moves_taught_by_tutor += 1 if !by_machine
pkmn.add_first_move(move) if one_use_machine
next true
end
next false
end
screen.pbEndScene
end
return ret # Returns whether the move was learned by a Pokemon
end
@@ -596,14 +600,6 @@ def pbLoadRpgxpScene(scene)
Graphics.transition
end
def pbChooseLanguage
commands = []
Settings::LANGUAGES.each do |lang|
commands.push(lang[0])
end
return pbShowCommands(nil, commands)
end
def pbScreenCapture
t = Time.now
filestart = t.strftime("[%Y-%m-%d] %H_%M_%S.%L")

View File

@@ -896,8 +896,8 @@ def pbItemEditorNew(default_name)
return
end
# Choose a pocket
pocket = PocketProperty.set("", 0)
return if pocket == 0
pocket = PocketProperty.set("", :None)
return if pocket == :None
# Choose a price
price = LimitProperty.new(999_999).set(_INTL("Purchase price"), -1)
return if price == -1

View File

@@ -923,18 +923,21 @@ end
#===============================================================================
module PocketProperty
def self.set(_settingname, oldsetting)
commands = Settings.bag_pocket_names.clone
cmd = pbMessage(_INTL("Choose a pocket for this item."), commands, -1)
return (cmd >= 0) ? cmd + 1 : oldsetting
pockets = GameData::BagPocket.all_pockets
commands = []
pockets.each { |pckt| commands.push(GameData::BagPocket.get(pckt).name) }
initial_val = pockets.index(GameData::BagPocket.get(oldsetting || 1).id)
cmd = pbMessage(_INTL("Choose a pocket for this item."), commands, -1, nil, initial_val)
return (cmd >= 0) ? pockets[cmd] : oldsetting
end
def self.defaultValue
return 1
return GameData::BagPocket.all_pockets.first
end
def self.format(value)
return _INTL("No Pocket") if value == 0
return (value) ? Settings.bag_pocket_names[value - 1] : value.inspect
return _INTL("No Pocket") if value == 0 || value == :None
return (value) ? GameData::BagPocket.get(value).name : value.inspect
end
end

View File

@@ -149,7 +149,7 @@ end
#
#===============================================================================
module PokemonDebugMixin
def pbPokemonDebug(pkmn, pkmnid, heldpoke = nil, settingUpBattle = false)
def pokemon_debug_menu(pkmn, pkmnid, settingUpBattle = false)
# Get all commands
commands = CommandMenuList.new
MenuHandlers.each_available(:pokemon_debug_menu) do |option, hash, name|
@@ -159,7 +159,7 @@ module PokemonDebugMixin
# Main loop
command = 0
loop do
command = pbShowCommands(_INTL("Do what with {1}?", pkmn.name), commands.list, command)
command = show_menu(_INTL("Do what with {1}?", pkmn.name), commands.list, command)
if command < 0
parent = commands.getParent
break if !parent
@@ -170,7 +170,7 @@ module PokemonDebugMixin
if commands.hasSubMenu?(cmd)
commands.currentList = cmd
command = 0
elsif MenuHandlers.call(:pokemon_debug_menu, cmd, "effect", pkmn, pkmnid, heldpoke, settingUpBattle, self)
elsif MenuHandlers.call(:pokemon_debug_menu, cmd, "effect", pkmn, pkmnid, settingUpBattle, self)
break
end
end
@@ -178,6 +178,73 @@ module PokemonDebugMixin
end
end
#===============================================================================
#
#===============================================================================
class UI::Party
include PokemonDebugMixin
end
#===============================================================================
#
#===============================================================================
class UI::PokemonStorage
include PokemonDebugMixin
def choose_move(pkmn, message)
move_names = []
pkmn.moves.each do |move|
next if !move || !move.id
if move.total_pp <= 0
move_names.push(_INTL("{1} (PP: ---)", move.name))
else
move_names.push(_INTL("{1} (PP: {2}/{3})", move.name, move.pp, move.total_pp))
end
end
return show_menu(message, move_names)
end
end
#===============================================================================
#
#===============================================================================
class UI::PartyDebugVisuals < UI::BaseVisuals
def initialize_background; end
def initialize_overlay; end
def choose_number(help_text, maximum, init_value = 1)
old_letter_by_letter = @sprites[:speech_box].letterbyletter
@sprites[:speech_box].letterbyletter = false
ret = super
@sprites[:speech_box].letterbyletter = old_letter_by_letter
return ret
end
end
class UI::PartyDebug < UI::BaseScreen
include PokemonDebugMixin
def initialize_visuals
@visuals = UI::PartyDebugVisuals.new
end
def choose_move(pkmn, message, index = 0)
# TODO: The move names can get rather wide, making the message box rather
# thin. It's just about acceptable, but maybe the choice window needs
# to be displayed above the message box instead of to the right of it.
move_names = []
pkmn.moves.each do |move|
next if !move || !move.id
if move.total_pp <= 0
move_names.push(_INTL("{1} (PP: ---)", move.name))
else
move_names.push(_INTL("{1} (PP: {2}/{3})", move.name, move.pp, move.total_pp))
end
end
return show_menu(message, move_names, index)
end
end
#===============================================================================
#
#===============================================================================
@@ -405,27 +472,6 @@ module Battle::DebugMixin
end
end
#===============================================================================
#
#===============================================================================
class PokemonPartyScreen
include PokemonDebugMixin
end
#===============================================================================
#
#===============================================================================
class PokemonStorageScreen
include PokemonDebugMixin
end
#===============================================================================
#
#===============================================================================
class PokemonDebugPartyScreen
include PokemonDebugMixin
end
#===============================================================================
#
#===============================================================================

View File

@@ -221,33 +221,33 @@ MenuHandlers.add(:debug_menu, :storage_wallpapers, {
"description" => _INTL("Unlock and lock special wallpapers used in Pokémon storage."),
"effect" => proc {
w = $PokemonStorage.allWallpapers
if w.length <= PokemonStorage::BASICWALLPAPERQTY
if w.length <= PokemonStorage::BASIC_WALLPAPER_COUNT
pbMessage(_INTL("There are no special wallpapers defined."))
else
paperscmd = 0
unlockarray = $PokemonStorage.unlockedWallpapers
loop do
paperscmds = []
paperscmds.push(_INTL("Unlock all"))
paperscmds.push(_INTL("Lock all"))
(PokemonStorage::BASICWALLPAPERQTY...w.length).each do |i|
paperscmds.push((unlockarray[i] ? "[Y]" : "[ ]") + " " + w[i])
next
end
paperscmd = 0
unlockarray = $PokemonStorage.unlockedWallpapers
loop do
paperscmds = []
paperscmds.push(_INTL("Unlock all"))
paperscmds.push(_INTL("Lock all"))
(PokemonStorage::BASIC_WALLPAPER_COUNT...w.length).each do |i|
paperscmds.push((unlockarray[i] ? "[Y]" : "[ ]") + " " + w[i])
end
paperscmd = pbShowCommands(nil, paperscmds, -1, paperscmd)
break if paperscmd < 0
case paperscmd
when 0 # Unlock all
(PokemonStorage::BASIC_WALLPAPER_COUNT...w.length).each do |i|
unlockarray[i] = true
end
paperscmd = pbShowCommands(nil, paperscmds, -1, paperscmd)
break if paperscmd < 0
case paperscmd
when 0 # Unlock all
(PokemonStorage::BASICWALLPAPERQTY...w.length).each do |i|
unlockarray[i] = true
end
when 1 # Lock all
(PokemonStorage::BASICWALLPAPERQTY...w.length).each do |i|
unlockarray[i] = false
end
else
paperindex = paperscmd - 2 + PokemonStorage::BASICWALLPAPERQTY
unlockarray[paperindex] = !$PokemonStorage.unlockedWallpapers[paperindex]
when 1 # Lock all
(PokemonStorage::BASIC_WALLPAPER_COUNT...w.length).each do |i|
unlockarray[i] = false
end
else
paperindex = paperscmd - 2 + PokemonStorage::BASIC_WALLPAPER_COUNT
unlockarray[paperindex] = !$PokemonStorage.unlockedWallpapers[paperindex]
end
end
}
@@ -354,9 +354,9 @@ MenuHandlers.add(:debug_menu, :test_wild_battle_advanced, {
end
else # Edit a Pokémon
if pbConfirmMessage(_INTL("Change this Pokémon?"))
scr = PokemonDebugPartyScreen.new
scr.pbPokemonDebug(pkmn[pkmnCmd], -1, nil, true)
scr.pbEndScreen
scr = UI::PartyDebug.new
scr.pokemon_debug_menu(pkmn[pkmnCmd], -1, true)
scr.silent_end_screen
elsif pbConfirmMessage(_INTL("Delete this Pokémon?"))
pkmn.delete_at(pkmnCmd)
size0 = [pkmn.length, 1].max
@@ -711,9 +711,7 @@ MenuHandlers.add(:debug_menu, :open_storage, {
"description" => _INTL("Opens the Pokémon storage boxes in Organize Boxes mode."),
"effect" => proc {
pbFadeOutIn do
scene = PokemonStorageScene.new
screen = PokemonStorageScreen.new(scene, $PokemonStorage)
screen.pbStartScreen(0)
UI::PokemonStorage.new($PokemonStorage, mode: :organize).main
end
}
})
@@ -788,7 +786,7 @@ MenuHandlers.add(:debug_menu, :add_item, {
pbListScreenBlock(_INTL("ADD ITEM"), ItemLister.new) do |button, item|
if button == Input::USE && item
params = ChooseNumberParams.new
params.setRange(1, Settings::BAG_MAX_PER_SLOT)
params.setRange(1, PokemonBag::MAX_PER_SLOT)
params.setInitialValue(1)
params.setCancelValue(0)
qty = pbMessageChooseNumber(_INTL("Add how many {1}?",
@@ -808,7 +806,7 @@ MenuHandlers.add(:debug_menu, :fill_bag, {
"description" => _INTL("Empties the Bag and then fills it with a certain number of every item."),
"effect" => proc {
params = ChooseNumberParams.new
params.setRange(1, Settings::BAG_MAX_PER_SLOT)
params.setRange(1, PokemonBag::MAX_PER_SLOT)
params.setInitialValue(1)
params.setCancelValue(0)
qty = pbMessageChooseNumber(_INTL("Choose the number of items."), params)
@@ -816,13 +814,15 @@ MenuHandlers.add(:debug_menu, :fill_bag, {
$bag.clear
# NOTE: This doesn't simply use $bag.add for every item in turn, because
# that's really slow when done in bulk.
pocket_sizes = Settings::BAG_MAX_POCKET_SIZE
pocket_sizes = {}
GameData::BagPocket.each { |pckt| pocket_sizes[pckt.id] = pckt.max_slots }
bag = $bag.pockets # Called here so that it only rearranges itself once
GameData::Item.each do |i|
next if !pocket_sizes[i.pocket - 1] || pocket_sizes[i.pocket - 1] == 0
next if pocket_sizes[i.pocket - 1] > 0 && bag[i.pocket].length >= pocket_sizes[i.pocket - 1]
bag_pocket = i.bag_pocket
next if !pocket_sizes[bag_pocket] || pocket_sizes[bag_pocket] == 0
next if pocket_sizes[bag_pocket] > 0 && bag[bag_pocket].length >= pocket_sizes[bag_pocket]
item_qty = (i.is_important?) ? 1 : qty
bag[i.pocket].push([i.id, item_qty])
bag[bag_pocket].push([i.id, item_qty])
end
# NOTE: Auto-sorting pockets don't need to be sorted afterwards, because
# items are added in the same order they would be sorted into.

View File

@@ -362,9 +362,7 @@ def pbDebugDayCare
[_INTL("Summary"), _INTL("Withdraw"), _INTL("Cancel")], 3)
when 0 # Summary
pbFadeOutIn do
scene = PokemonSummary_Scene.new
screen = PokemonSummaryScreen.new(scene, false)
screen.pbStartScreen([pkmn], 0)
UI::PokemonSummary.new(pkmn).main
need_refresh = true
end
when 1 # Withdraw
@@ -450,10 +448,10 @@ class SpriteWindow_DebugRoamers < Window_DrawableCommand
self.shadowtext(_INTL("[Clear all current roamer locations]"), rect.x, rect.y, nameWidth, rect.height)
else
pkmn = Settings::ROAMING_SPECIES[index]
name = GameData::Species.get(pkmn[0]).name + " (Lv. #{pkmn[1]})"
name = GameData::Species.get(pkmn[:species]).name + " (Lv. #{pkmn[:level]})"
status = ""
statuscolor = 0
if pkmn[2] <= 0 || $game_switches[pkmn[2]]
if !pkmn[:game_switch] || pkmn[:game_switch] <= 0 || $game_switches[pkmn[:game_switch]]
status = $PokemonGlobal.roamPokemon[index]
if status == true
if $PokemonGlobal.roamPokemonCaught[index]
@@ -474,7 +472,7 @@ class SpriteWindow_DebugRoamers < Window_DrawableCommand
statuscolor = 2
end
else
status = "[NOT ROAMING][Switch #{pkmn[2]} is off]"
status = "[NOT ROAMING][Switch #{pkmn[:game_switch]} is off]"
end
self.shadowtext(name, rect.x, rect.y, nameWidth, rect.height)
self.shadowtext(status, rect.x + nameWidth, rect.y, statusWidth, rect.height, 1, statuscolor)
@@ -502,7 +500,7 @@ def pbDebugRoamers
pkmn = nil
end
if Input.trigger?(Input::ACTION) && cmdwindow.index < cmdwindow.roamerCount &&
(pkmn[2] <= 0 || $game_switches[pkmn[2]]) &&
(!pkmn[:game_switch] || pkmn[:game_switch] <= 0 || $game_switches[pkmn[:game_switch]]) &&
$PokemonGlobal.roamPokemon[cmdwindow.index] != true
# Roam selected Pokémon
pbPlayDecisionSE
@@ -529,9 +527,9 @@ def pbDebugRoamers
if cmdwindow.index < cmdwindow.roamerCount
pbPlayDecisionSE
# Toggle through roaming, not roaming, defeated
if pkmn[2] > 0 && !$game_switches[pkmn[2]]
if pkmn[:game_switch] && pkmn[:game_switch] > 0 && !$game_switches[pkmn[:game_switch]]
# not roaming -> roaming
$game_switches[pkmn[2]] = true
$game_switches[pkmn[:game_switch]] = true
elsif $PokemonGlobal.roamPokemon[cmdwindow.index] != true
# roaming -> defeated
$PokemonGlobal.roamPokemon[cmdwindow.index] = true
@@ -540,9 +538,9 @@ def pbDebugRoamers
!$PokemonGlobal.roamPokemonCaught[cmdwindow.index]
# defeated -> caught
$PokemonGlobal.roamPokemonCaught[cmdwindow.index] = true
elsif pkmn[2] > 0
elsif pkmn[:game_switch] && pkmn[:game_switch] > 0
# caught -> not roaming (or roaming if Switch ID is 0)
$game_switches[pkmn[2]] = false if pkmn[2] > 0
$game_switches[pkmn[:game_switch]] = false if pkmn[:game_switch] && pkmn[:game_switch] > 0
$PokemonGlobal.roamPokemon[cmdwindow.index] = nil
$PokemonGlobal.roamPokemonCaught[cmdwindow.index] = false
end
@@ -764,133 +762,3 @@ def pbCheckTileValidity(tile_id, map, tilesets, passages)
end
return false
end
#===============================================================================
# Pseudo-party screen for editing Pokémon being set up for a wild battle.
#===============================================================================
class PokemonDebugPartyScreen
def initialize
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@messageBox = Window_AdvancedTextPokemon.new("")
@messageBox.viewport = @viewport
@messageBox.visible = false
@messageBox.letterbyletter = true
pbBottomLeftLines(@messageBox, 2)
@helpWindow = Window_UnformattedTextPokemon.new("")
@helpWindow.viewport = @viewport
@helpWindow.visible = true
pbBottomLeftLines(@helpWindow, 1)
end
def pbEndScreen
@messageBox.dispose
@helpWindow.dispose
@viewport.dispose
end
def pbDisplay(text)
@messageBox.text = text
@messageBox.visible = true
@helpWindow.visible = false
pbPlayDecisionSE
loop do
Graphics.update
Input.update
pbUpdate
if @messageBox.busy?
if Input.trigger?(Input::USE)
pbPlayDecisionSE if @messageBox.pausing?
@messageBox.resume
end
else
if Input.trigger?(Input::BACK) || Input.trigger?(Input::USE)
break
end
end
end
@messageBox.visible = false
@helpWindow.visible = true
end
def pbConfirm(text)
ret = -1
@messageBox.text = text
@messageBox.visible = true
@helpWindow.visible = false
using(cmdwindow = Window_CommandPokemon.new([_INTL("Yes"), _INTL("No")])) do
cmdwindow.visible = false
pbBottomRight(cmdwindow)
cmdwindow.y -= @messageBox.height
cmdwindow.z = @viewport.z + 1
loop do
Graphics.update
Input.update
cmdwindow.visible = true if !@messageBox.busy?
cmdwindow.update
pbUpdate
if !@messageBox.busy?
if Input.trigger?(Input::BACK)
ret = false
break
elsif Input.trigger?(Input::USE) && @messageBox.resume
ret = (cmdwindow.index == 0)
break
end
end
end
end
@messageBox.visible = false
@helpWindow.visible = true
return ret
end
def pbShowCommands(text, commands, index = 0)
ret = -1
@helpWindow.visible = true
using(cmdwindow = Window_CommandPokemonColor.new(commands)) do
cmdwindow.z = @viewport.z + 1
cmdwindow.index = index
pbBottomRight(cmdwindow)
@helpWindow.resizeHeightToFit(text, Graphics.width - cmdwindow.width)
@helpWindow.text = text
pbBottomLeft(@helpWindow)
loop do
Graphics.update
Input.update
cmdwindow.update
pbUpdate
if Input.trigger?(Input::BACK)
pbPlayCancelSE
ret = -1
break
elsif Input.trigger?(Input::USE)
pbPlayDecisionSE
ret = cmdwindow.index
break
end
end
end
return ret
end
def pbChooseMove(pkmn, text, index = 0)
moveNames = []
pkmn.moves.each do |i|
if i.total_pp <= 0
moveNames.push(_INTL("{1} (PP: ---)", i.name))
else
moveNames.push(_INTL("{1} (PP: {2}/{3})", i.name, i.pp, i.total_pp))
end
end
return pbShowCommands(text, moveNames, index)
end
def pbRefreshSingle(index); end
def update
@messageBox.update
@helpWindow.update
end
alias pbUpdate update
end

View File

@@ -632,8 +632,8 @@ MenuHandlers.add(:battle_pokemon_debug_menu, :set_item, {
end
when 1 # Remove item
if pkmn.hasItem?
(battler || pkmn).item = nil
pkmn.mail = nil
pkmn.item = nil
battler.item = nil if battler
end
else
break

Some files were not shown because too many files have changed in this diff Show More