From 2190f7c2519d3056a132302116de7888b30bd3f8 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sat, 7 Sep 2024 21:51:54 +0100 Subject: [PATCH] Rewrote party screen, implemented redesign of it --- .../003_Game processing/005_Event_Handlers.rb | 12 + .../006_Event_HandlerCollections.rb | 11 + .../001_Game_Temp.rb | 2 + .../002_MessageConfig.rb | 4 +- .../005_SpriteWindow_text.rb | 51 +- .../004_Scene/003_Scene_ChooseCommands.rb | 94 +- .../012_Overworld/004_Overworld_FieldMoves.rb | 5 + Data/Scripts/013_Items/001_Item_Utilities.rb | 128 +- Data/Scripts/013_Items/002_Item_Effects.rb | 50 +- Data/Scripts/013_Items/006_Item_Mail.rb | 4 +- Data/Scripts/013_Items/007_Item_Sprites.rb | 6 +- Data/Scripts/016_UI/005_UI_Party.rb | 184 +- Data/Scripts/016_UI/007_UI_Bag.rb | 9 +- Data/Scripts/016_UI/016_UI_ReadyMenu.rb | 2 +- Data/Scripts/016_UI/017_UI_PokemonStorage.rb | 2 +- Data/Scripts/016_UI/019_UI_PC.rb | 30 +- Data/Scripts/016b_UI redesign/000_UI_base.rb | 540 ++++-- .../016b_UI redesign/001_UI_PauseMenu.rb | 13 +- Data/Scripts/016b_UI redesign/005_UI_Party.rb | 1532 +++++++++++++++++ .../016b_UI redesign/006_UI_Summary.rb | 41 +- .../001_Battle Frontier/002_Challenge_Data.rb | 11 +- Data/Scripts/019_Utilities/001_Utilities.rb | 44 +- .../003_Debug menus/001_Debug_Menus.rb | 4 +- .../003_Debug menus/002_Debug_MenuCommands.rb | 2 +- .../003_Debug_MenuExtraCode.rb | 1 + .../007_Debug_PokemonCommands.rb | 16 +- 26 files changed, 2236 insertions(+), 562 deletions(-) create mode 100644 Data/Scripts/016b_UI redesign/005_UI_Party.rb diff --git a/Data/Scripts/003_Game processing/005_Event_Handlers.rb b/Data/Scripts/003_Game processing/005_Event_Handlers.rb index 8e6f098cc..18954c372 100644 --- a/Data/Scripts/003_Game processing/005_Event_Handlers.rb +++ b/Data/Scripts/003_Game processing/005_Event_Handlers.rb @@ -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 diff --git a/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb b/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb index a3c3393df..183ee66a7 100644 --- a/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb +++ b/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb @@ -114,6 +114,17 @@ 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 else diff --git a/Data/Scripts/004_Game classes/001_Switches and Variables/001_Game_Temp.rb b/Data/Scripts/004_Game classes/001_Switches and Variables/001_Game_Temp.rb index 1e622ffe6..7f15670fa 100644 --- a/Data/Scripts/004_Game classes/001_Switches and Variables/001_Game_Temp.rb +++ b/Data/Scripts/004_Game classes/001_Switches and Variables/001_Game_Temp.rb @@ -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 diff --git a/Data/Scripts/007_Objects and windows/002_MessageConfig.rb b/Data/Scripts/007_Objects and windows/002_MessageConfig.rb index 70f12291f..cb1f1592c 100644 --- a/Data/Scripts/007_Objects and windows/002_MessageConfig.rb +++ b/Data/Scripts/007_Objects and windows/002_MessageConfig.rb @@ -491,7 +491,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) @@ -591,7 +591,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) diff --git a/Data/Scripts/007_Objects and windows/005_SpriteWindow_text.rb b/Data/Scripts/007_Objects and windows/005_SpriteWindow_text.rb index bb50e0e82..1f58ded29 100644 --- a/Data/Scripts/007_Objects and windows/005_SpriteWindow_text.rb +++ b/Data/Scripts/007_Objects and windows/005_SpriteWindow_text.rb @@ -1243,19 +1243,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,6 +1308,42 @@ 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 + tmpbitmap = Bitmap.new(1, 1) + pbSetSystemFont(tmpbitmap) + commands.each do |i| + txt = toUnformattedText(i).gsub(/\n/, "") + width = [width, tmpbitmap.text_size(txt).width].max + end + # one 16 to allow cursor + width += 16 + 16 + SpriteWindow_Base::TEXT_PADDING + tmpbitmap.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) @@ -1340,7 +1363,7 @@ 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), + 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) drawFormattedChars(self.contents, chars) end diff --git a/Data/Scripts/011_Battle/004_Scene/003_Scene_ChooseCommands.rb b/Data/Scripts/011_Battle/004_Scene/003_Scene_ChooseCommands.rb index 2acd680f6..d4eb94910 100644 --- a/Data/Scripts/011_Battle/004_Scene/003_Scene_ChooseCommands.rb +++ b/Data/Scripts/011_Battle/004_Scene/003_Scene_ChooseCommands.rb @@ -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_choice_message(_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 @@ -272,34 +259,29 @@ class Battle::Scene 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 + 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 != idxParty + partyStart - idxPartyRet = i + next if pos != party_index + partyStart + real_party_index = i break end - next if idxPartyRet < 0 - pkmn = party[idxPartyRet] - next if !pkmn || pkmn.egg? - idxMove = -1 + 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 - idxMove = pkmnScreen.pbChooseMove(pkmn, _INTL("Restore which move?")) - next if idxMove < 0 + move_index = party_screen.choose_move(pkmn, _INTL("Restore which move?")) + next false if move_index < 0 end - break if yield item.id, useType, idxPartyRet, idxMove, pkmnScene + next true if yield item.id, useType, real_party_index, move_index, party_screen + next false end - pkmnScene.pbEndScene - break if idxParty >= 0 + break if party_idx >= 0 # Item was used; close the Bag screen # Cancelled choosing a Pokémon; show the Bag screen again itemScene.pbFadeInScene when 4 # Use on opposing battler (Poké Balls) diff --git a/Data/Scripts/012_Overworld/004_Overworld_FieldMoves.rb b/Data/Scripts/012_Overworld/004_Overworld_FieldMoves.rb index 3b07ef7dd..088792402 100644 --- a/Data/Scripts/012_Overworld/004_Overworld_FieldMoves.rb +++ b/Data/Scripts/012_Overworld/004_Overworld_FieldMoves.rb @@ -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] diff --git a/Data/Scripts/013_Items/001_Item_Utilities.rb b/Data/Scripts/013_Items/001_Item_Utilities.rb index 20d0651e7..00610827a 100644 --- a/Data/Scripts/013_Items/001_Item_Utilities.rb +++ b/Data/Scripts/013_Items/001_Item_Utilities.rb @@ -134,8 +134,8 @@ end 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)) + 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 @@ -153,8 +153,8 @@ def pbChangeLevel(pkmn, new_level, scene) 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)) + 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 @@ -170,8 +170,8 @@ def pbChangeLevel(pkmn, new_level, scene) 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)) + 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 @@ -199,7 +199,7 @@ def pbChangeLevel(pkmn, new_level, 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 @@ -225,8 +225,8 @@ 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)) + 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 @@ -241,8 +241,8 @@ def pbChangeExp(pkmn, new_exp, scene) 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)) + 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 @@ -251,8 +251,8 @@ def pbChangeExp(pkmn, new_exp, scene) 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)) + 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 @@ -268,8 +268,8 @@ def pbChangeExp(pkmn, new_exp, scene) 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)) + 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 @@ -279,8 +279,8 @@ def pbChangeExp(pkmn, new_exp, scene) 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 +308,7 @@ 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 @@ -320,7 +320,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 +581,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,27 +594,29 @@ 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) @@ -629,11 +634,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 - screen = UI::PokemonSummary.new([pkmn], 0, mode: :choose_move, new_move: moveToLearn) - ret = screen.choose_move + 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 @@ -642,7 +647,7 @@ 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) +def pbUseItem(bag, item, bag_scene = nil) itm = GameData::Item.get(item) useType = itm.field_use if useType == 1 # Item is usable on a Pokémon @@ -660,37 +665,35 @@ def pbUseItem(bag, item, bagscene = nil) 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) + screen = UI::Party.new($player.party, mode: :use_item) + if itm.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 !pbCheckUseOnPokemon(item, pkmn, screen) qty = 1 max_at_once = ItemHandlers.triggerUseOnPokemonMaximum(item, pkmn) - max_at_once = [max_at_once, $bag.quantity(item)].min + max_at_once = [max_at_once, bag.quantity(item)].min if max_at_once > 1 - qty = screen.scene.pbChooseNumber( + 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.scene.pbSetHelpText("") if screen.is_a?(PokemonPartyScreen) + screen.set_help_text("") end - next if qty <= 0 + next false 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 + if ret && itm.consumed_after_use? + bag.remove(item, qty) + if !bag.has?(item) + screen.show_message(_INTL("You used your last {1}.", itm.portion_name)) + next true + end + end + next false end - screen.pbEndScene - bagscene&.pbRefresh + bag_scene&.pbRefresh end return (ret) ? 1 : 0 elsif useType == 2 || itm.is_machine? # Item is usable from Bag or teaches a move @@ -708,6 +711,7 @@ end # Only called when in the party screen and having chosen an item to be used on # the selected Pokémon. +# TODO: Replace all pbMessage and so on in here. scene is the party screen. def pbUseItemOnPokemon(item, pkmn, scene) itm = GameData::Item.get(item) # TM or HM @@ -738,12 +742,12 @@ def pbUseItemOnPokemon(item, pkmn, scene) 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) + scene.set_help_text("") if scene.is_a?(UI::Party) end return false if qty <= 0 ret = ItemHandlers.triggerUseOnPokemon(item, qty, pkmn, scene) - scene.pbClearAnnotations - scene.pbHardRefresh + scene.clear_annotations + scene.refresh if ret && itm.consumed_after_use? $bag.remove(item, qty) if !$bag.has?(item) @@ -779,6 +783,7 @@ end #=============================================================================== # Give an item to a Pokémon to hold, and take a held item from a Pokémon. #=============================================================================== +# TODO: Replace all pbDisplay and so on in here. def pbGiveItemToPokemon(item, pkmn, scene, pkmnid = 0) return false if item.nil? newitemname = GameData::Item.get(item).portion_name @@ -824,6 +829,7 @@ def pbGiveItemToPokemon(item, pkmn, scene, pkmnid = 0) return false end +# TODO: Replace all pbDisplay and so on in here. def pbTakeItemFromPokemon(pkmn, scene) ret = false if !pkmn.hasItem? @@ -833,23 +839,25 @@ def pbTakeItemFromPokemon(pkmn, scene) 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 + scene.pbDisplay(_INTL("The mail was saved in your PC.")) 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?")) + item_name = pkmn.item.portion_name $bag.add(pkmn.item) - scene.pbDisplay(_INTL("Received the {1} from {2}.", pkmn.item.portion_name, pkmn.name)) pkmn.item = nil pkmn.mail = nil + scene.pbDisplay(_INTL("Received the {1} from {2}.", item_name, pkmn.name)) ret = true end else + item_name = pkmn.item.portion_name $bag.add(pkmn.item) - scene.pbDisplay(_INTL("Received the {1} from {2}.", pkmn.item.portion_name, pkmn.name)) pkmn.item = nil + scene.pbDisplay(_INTL("Received the {1} from {2}.", item_name, pkmn.name)) ret = true end return ret diff --git a/Data/Scripts/013_Items/002_Item_Effects.rb b/Data/Scripts/013_Items/002_Item_Effects.rb index d0d703ac2..3e07a5f67 100644 --- a/Data/Scripts/013_Items/002_Item_Effects.rb +++ b/Data/Scripts/013_Items/002_Item_Effects.rb @@ -243,19 +243,19 @@ ItemHandlers::UseInField.add(:SACREDASH, proc { |item| end revived = 0 pbFadeOutIn do - scene = PokemonParty_Scene.new - screen = PokemonPartyScreen.new(scene, $player.party) - screen.pbStartScene(_INTL("Using item..."), false) - pbSEPlay("Use item in party") - $player.party.each_with_index do |pkmn, i| - next if !pkmn.fainted? - revived += 1 - pkmn.heal - screen.pbRefreshSingle(i) - screen.pbDisplay(_INTL("{1}'s HP was restored.", pkmn.name)) + screen = UI::Party.new($player.party, mode: :choose_pokemon) + screen.set_help_text(_INTL("Using item...")) + screen.show_and_hide do + $player.party.each_with_index do |pkmn, i| + next if !pkmn.fainted? + revived += 1 + pkmn.heal + screen.refresh + pbSEPlay("Use item in party") + screen.show_message(_INTL("{1}'s HP was restored.", pkmn.name)) + end + screen.show_message(_INTL("It won't have any effect.")) if revived == 0 end - screen.pbDisplay(_INTL("It won't have any effect.")) if revived == 0 - screen.pbEndScene end next (revived > 0) }) @@ -391,16 +391,16 @@ ItemHandlers::UseOnPokemon.addIf(:evolution_stones, scene.pbDisplay(_INTL("It won't have any effect.")) next false end - newspecies = pkmn.check_evolution_on_use_item(item) - if newspecies + new_species = pkmn.check_evolution_on_use_item(item) + if new_species pbFadeOutInWithMusic do evo = PokemonEvolutionScene.new - evo.pbStartScreen(pkmn, newspecies) + evo.pbStartScreen(pkmn, new_species) evo.pbEvolution(false) evo.pbEndScreen - if scene.is_a?(PokemonPartyScreen) - scene.pbRefreshAnnotations(proc { |p| !p.check_evolution_on_use_item(item).nil? }) - scene.pbRefresh + if scene.is_a?(UI::Party) + scene.set_able_annotation_proc(proc { |pkmn| !pkmn.check_evolution_on_use_item(item).nil? }) + scene.refresh end end next true @@ -415,17 +415,17 @@ ItemHandlers::UseOnPokemon.add(:SCROLLOFWATERS, proc { |item, qty, pkmn, scene| scene.pbDisplay(_INTL("It won't have any effect.")) next false end - newspecies = pkmn.check_evolution_on_use_item(item) - if newspecies + new_species = pkmn.check_evolution_on_use_item(item) + if new_species pkmn.form = 1 # NOTE: This is the only difference to the generic evolution stone code. pbFadeOutInWithMusic do evo = PokemonEvolutionScene.new - evo.pbStartScreen(pkmn, newspecies) + evo.pbStartScreen(pkmn, new_species) evo.pbEvolution(false) evo.pbEndScreen - if scene.is_a?(PokemonPartyScreen) - scene.pbRefreshAnnotations(proc { |p| !p.check_evolution_on_use_item(item).nil? }) - scene.pbRefresh + if scene.is_a?(UI::Party) + scene.set_able_annotation_proc(proc { |p| !p.check_evolution_on_use_item(item).nil? }) + scene.refresh end end next true @@ -995,7 +995,7 @@ ItemHandlers::UseOnPokemon.add(:RARECANDY, proc { |item, qty, pkmn, 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 next true end diff --git a/Data/Scripts/013_Items/006_Item_Mail.rb b/Data/Scripts/013_Items/006_Item_Mail.rb index a667d5c29..84f4b1c50 100644 --- a/Data/Scripts/013_Items/006_Item_Mail.rb +++ b/Data/Scripts/013_Items/006_Item_Mail.rb @@ -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 diff --git a/Data/Scripts/013_Items/007_Item_Sprites.rb b/Data/Scripts/013_Items/007_Item_Sprites.rb index 2b9e8d090..95b38a5d5 100644 --- a/Data/Scripts/013_Items/007_Item_Sprites.rb +++ b/Data/Scripts/013_Items/007_Item_Sprites.rb @@ -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 diff --git a/Data/Scripts/016_UI/005_UI_Party.rb b/Data/Scripts/016_UI/005_UI_Party.rb index 506c5ca60..b9b522bd1 100644 --- a/Data/Scripts/016_UI/005_UI_Party.rb +++ b/Data/Scripts/016_UI/005_UI_Party.rb @@ -686,10 +686,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 @@ -914,43 +911,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 @@ -1006,6 +966,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) @@ -1029,21 +1036,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 = [] @@ -1134,6 +1126,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 = [] @@ -1480,78 +1477,3 @@ 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 diff --git a/Data/Scripts/016_UI/007_UI_Bag.rb b/Data/Scripts/016_UI/007_UI_Bag.rb index 3840913c5..97282e25c 100644 --- a/Data/Scripts/016_UI/007_UI_Bag.rb +++ b/Data/Scripts/016_UI/007_UI_Bag.rb @@ -513,10 +513,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 diff --git a/Data/Scripts/016_UI/016_UI_ReadyMenu.rb b/Data/Scripts/016_UI/016_UI_ReadyMenu.rb index 82cee665c..e3229953a 100644 --- a/Data/Scripts/016_UI/016_UI_ReadyMenu.rb +++ b/Data/Scripts/016_UI/016_UI_ReadyMenu.rb @@ -261,7 +261,7 @@ 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) diff --git a/Data/Scripts/016_UI/017_UI_PokemonStorage.rb b/Data/Scripts/016_UI/017_UI_PokemonStorage.rb index 938e2e163..288a10f00 100644 --- a/Data/Scripts/016_UI/017_UI_PokemonStorage.rb +++ b/Data/Scripts/016_UI/017_UI_PokemonStorage.rb @@ -1576,7 +1576,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 diff --git a/Data/Scripts/016_UI/019_UI_PC.rb b/Data/Scripts/016_UI/019_UI_PC.rb index 65a33cff9..6bba84766 100644 --- a/Data/Scripts/016_UI/019_UI_PC.rb +++ b/Data/Scripts/016_UI/019_UI_PC.rb @@ -68,9 +68,9 @@ def pbPCMailbox commands.push(_INTL("Cancel")) command = pbShowCommands(nil, commands, -1, command) if command >= 0 && command < $PokemonGlobal.mailbox.length - mailIndex = command + mail_index = command commandMail = pbMessage( - _INTL("What do you want to do with {1}'s Mail?", $PokemonGlobal.mailbox[mailIndex].sender), + _INTL("What do you want to do with {1}'s Mail?", $PokemonGlobal.mailbox[mail_index].sender), [_INTL("Read"), _INTL("Move to Bag"), _INTL("Give"), @@ -79,22 +79,36 @@ def pbPCMailbox case commandMail when 0 # Read pbFadeOutIn do - pbDisplayMail($PokemonGlobal.mailbox[mailIndex]) + pbDisplayMail($PokemonGlobal.mailbox[mail_index]) end when 1 # Move to Bag if pbConfirmMessage(_INTL("The message will be lost. Is that OK?")) - if $bag.add($PokemonGlobal.mailbox[mailIndex].item) + 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(mailIndex) + $PokemonGlobal.mailbox.delete_at(mail_index) 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) + 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] + pkmn.item = pkmn.mail.item + $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 end else diff --git a/Data/Scripts/016b_UI redesign/000_UI_base.rb b/Data/Scripts/016b_UI redesign/000_UI_base.rb index fc683895f..cdb3b9d17 100644 --- a/Data/Scripts/016b_UI redesign/000_UI_base.rb +++ b/Data/Scripts/016b_UI redesign/000_UI_base.rb @@ -2,60 +2,17 @@ module UI #============================================================================= # The visuals class. #============================================================================= - class BaseVisuals - UI_FOLDER = "Graphics/UI/" - GRAPHICS_FOLDER = "" # Subfolder in UI_FOLDER - BACKGROUND_FILENAME = "bg" - TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay] + 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 initialize - @bitmaps = {} - @sprites = {} - initialize_viewport - initialize_bitmaps - initialize_background - initialize_overlay - initialize_message_box - # TODO: Initialize dialogue box for messages to use. - 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 - @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) - end - - def initialize_sprites - end - - #--------------------------------------------------------------------------- - - def add_overlay(overlay) - @sprites[overlay] = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + 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) @@ -85,20 +42,16 @@ module UI #--------------------------------------------------------------------------- - def fade_in - pbFadeInAndShow(@sprites) { update_visuals } - end - - def fade_out - pbFadeOutAndHide(@sprites) { update_visuals } - 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 - @viewport.dispose + @disposed = true + end + + def disposed? + return !!@disposed end #--------------------------------------------------------------------------- @@ -126,123 +79,6 @@ module UI #--------------------------------------------------------------------------- - def show_message(text) - @sprites[:message_box].text = text - @sprites[:message_box].visible = true - loop do - Graphics.update - Input.update - update_visuals - if @sprites[:message_box].busy? - if Input.trigger?(Input::USE) - pbPlayDecisionSE if @sprites[:message_box].pausing? - @sprites[:message_box].resume - end - elsif Input.trigger?(Input::USE) || Input.trigger?(Input::BACK) - break - end - end - @sprites[:message_box].visible = false - end - - def show_confirm_message(text) - ret = false - @sprites[:message_box].text = text - @sprites[:message_box].visible = true - 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[:message_box].height - loop do - Graphics.update - Input.update - update_visuals - cmd_window.visible = true if !@sprites[:message_box].busy? - cmd_window.update - if !@sprites[:message_box].busy? - if Input.trigger?(Input::BACK) - pbPlayCancelSE - ret = false - break - elsif Input.trigger?(Input::USE) && @sprites[:message_box].resume - pbPlayDecisionSE - ret = (cmd_window.index == 0) - break - end - end - end - end - @sprites[:message_box].visible = false - return ret - end - - def show_choice_message(text, options, index = 0) - ret = -1 - commands = options - commands = options.values if options.is_a?(Hash) - @sprites[:message_box].text = text - @sprites[:message_box].visible = true - using(cmd_window = Window_CommandPokemon.new(commands)) do - cmd_window.z = @viewport.z + 1 - cmd_window.visible = false - cmd_window.index = index - pbBottomRight(cmd_window) - cmd_window.y -= @sprites[:message_box].height - loop do - Graphics.update - Input.update - update_visuals - cmd_window.visible = true if !@sprites[:message_box].busy? - cmd_window.update - if !@sprites[:message_box].busy? - if Input.trigger?(Input::BACK) - pbPlayCancelSE - ret = -1 - break - elsif Input.trigger?(Input::USE) && @sprites[:message_box].resume - pbPlayDecisionSE - ret = cmd_window.index - break - end - end - end - end - @sprites[:message_box].visible = false - ret = options.keys[ret] if options.is_a?(Hash) - 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_CommandPokemon.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 - - #--------------------------------------------------------------------------- - # 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). @@ -267,7 +103,7 @@ module UI 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]) + string, *self.class::TEXT_COLOR_THEMES[theme]) end # NOTE: This also draws string in a paragraph, but with no limit on the @@ -295,7 +131,7 @@ module UI 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) + index * char_width, 0, char_width, char_height, overlay: overlay) end end @@ -316,6 +152,311 @@ module UI 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 + 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 + @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 fade_in + pbFadeInAndShow(@sprites)# { update_visuals } + end + + def fade_out + pbFadeOutAndHide(@sprites)# { update_visuals } + end + + def dispose + super + @viewport.dispose + end + + #--------------------------------------------------------------------------- + + def show_message(text) + @sprites[:speech_box].visible = true + @sprites[:speech_box].text = text + pbBottomLeftLines(@sprites[:speech_box], 2) + 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 + elsif Input.trigger?(Input::USE) || Input.trigger?(Input::BACK) + break + 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 + pbBottomLeftLines(@sprites[:speech_box], 2) + 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 + + # 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: :horizontal, 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 + ret = options.keys[ret] if options.is_a?(Hash) + 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_num = 1) + return UIHelper.pbChooseNumber(@sprites[:speech_box], help_text, maximum, init_num) { update_visuals } + end + + #--------------------------------------------------------------------------- + def update_input if Input.trigger?(Input::BACK) return :quit @@ -323,11 +464,6 @@ module UI return nil end -# def update -# update_visuals -# return update_input -# end - #--------------------------------------------------------------------------- def navigate @@ -395,46 +531,72 @@ module UI return @visuals.show_choice_message(text, options, initial_index) end + alias pbShowCommands show_choice_message + def show_choice(options, initial_index = 0) return @visuals.show_choice(options, initial_index) end - alias pbShowCommands show_choice - - def show_choice_from_menu_handler(menu_handler_id) + def show_choice_from_menu_handler(menu_handler_id, message = nil) commands = {} - MenuHandlers.each_available(menu_handler_id, self) do |option, hash, name| + MenuHandlers.each_available(menu_handler_id, self) do |option, _hash, name| commands[option] = name end + return show_choice_message(message, commands) if message return show_choice(commands) end + def choose_number(help_text, maximum, init_num = 1) + return @visuals.choose_number(help_text, maximum, init_num) + end + + alias pbChooseNumber choose_number + #----------------------------------------------------------------------------- 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 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]) + choice = show_choice_from_menu_handler(action_hash[:menu], action_hash[:menu_message]&.call(self)) perform_action(choice) if choice elsif action_hash[:effect] return perform_action_effect(action_hash) diff --git a/Data/Scripts/016b_UI redesign/001_UI_PauseMenu.rb b/Data/Scripts/016b_UI redesign/001_UI_PauseMenu.rb index 7bc64e13e..3c5522704 100644 --- a/Data/Scripts/016b_UI redesign/001_UI_PauseMenu.rb +++ b/Data/Scripts/016b_UI redesign/001_UI_PauseMenu.rb @@ -200,16 +200,15 @@ MenuHandlers.add(:pause_menu, :party, { "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.silent_end_screen : menu.refresh + UI::Party.new($player.party).main + ($game_temp.field_move_to_use) ? menu.silent_end_screen : menu.refresh end - next false if !hidden_move + next false if !$game_temp.field_move_to_use $game_temp.in_menu = false - pbUseHiddenMove(hidden_move[0], hidden_move[1]) + 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 } }) diff --git a/Data/Scripts/016b_UI redesign/005_UI_Party.rb b/Data/Scripts/016b_UI redesign/005_UI_Party.rb new file mode 100644 index 000000000..801834b63 --- /dev/null +++ b/Data/Scripts/016b_UI redesign/005_UI_Party.rb @@ -0,0 +1,1532 @@ +# TODO: Rewrite def pbUseItemOnPokemon and all the ItemHandlers to stop using +# pbDisplay and whatnot, and ensure they do whatever is appropriate when +# being called with a screen of UI::Party. +#=============================================================================== +# +#=============================================================================== +class UI::PartyVisualsPanel < UI::SpriteContainer + attr_reader :index, :switch_index + attr_reader :pokemon, :text + + GRAPHICS_FOLDER = "Party/" + TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay] + :default => [Color.new(248, 248, 248), Color.new(40, 40, 40)], # 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)] + } + + def initialize(pokemon, index, viewport) + @pokemon = pokemon + @index = index + @x = (@index % 2) * Graphics.width / 2 + @y = (16 * (@index % 2)) + (96 * (@index / 2)) + @selected = false + @switch_index = -1 # -1 = not switching, 0+ = index of first panel for switching + @text = nil + super(viewport) + end + + def initialize_bitmaps + @bitmaps[:numbers] = AnimatedBitmap.new(graphics_folder + "numbers") + end + + def initialize_sprites + initialize_panel_bg + initialize_overlay + initialize_other_sprites + end + + def initialize_panel_bg + @sprites[:panel_bg] = ChangelingSprite.new(0, 0, @viewport) + @sprites[:panel_bg].add_bitmap(:blank, graphics_folder + "panel_blank") + @sprites[:panel_bg].add_bitmap(:able, graphics_folder + "panel_rect") + @sprites[:panel_bg].add_bitmap(:able_sel, graphics_folder + "panel_rect_sel") + @sprites[:panel_bg].add_bitmap(:fainted, graphics_folder + "panel_rect_faint") + @sprites[:panel_bg].add_bitmap(:fainted_sel, graphics_folder + "panel_rect_faint_sel") + @sprites[:panel_bg].add_bitmap(:switch, graphics_folder + "panel_rect_switch") + @sprites[:panel_bg].add_bitmap(:switch_sel, graphics_folder + "panel_rect_switch_sel") + @sprites[:panel_bg].add_bitmap(:switch_sel2, graphics_folder + "panel_rect_switch_sel2") + record_values(:panel_bg) + end + + def initialize_overlay + add_overlay(:overlay, 256, 98) + record_values(:overlay) + end + + def initialize_other_sprites + # HP bar sprite + @sprites[:hp_bar] = ChangelingSprite.new(104, 50, @viewport) + @sprites[:hp_bar].z = 1 + @sprites[:hp_bar].add_bitmap(:able, graphics_folder + _INTL("overlay_hp_back")) + @sprites[:hp_bar].add_bitmap(:fainted, graphics_folder + _INTL("overlay_hp_back_faint")) + @sprites[:hp_bar].add_bitmap(:switch, graphics_folder + _INTL("overlay_hp_back_switch")) + record_values(:hp_bar) + # Ball sprite + @sprites[:ball] = ChangelingSprite.new(10, 0, @viewport) + @sprites[:ball].z = 1 + @sprites[:ball].add_bitmap(:desel, graphics_folder + "icon_ball") + @sprites[:ball].add_bitmap(:sel, graphics_folder + "icon_ball_sel") + record_values(:ball) + # Pokémon icon + @sprites[:pokemon] = PokemonIconSprite.new(@pokemon, @viewport) + @sprites[:pokemon].x = 60 + @sprites[:pokemon].y = 40 + @sprites[:pokemon].z = 2 + @sprites[:pokemon].setOffset(PictureOrigin::CENTER) + @sprites[:pokemon].active = @active + record_values(:pokemon) + # Held item icon + @sprites[:held_item] = HeldItemIconSprite.new(70, 48, @pokemon, @viewport) + @sprites[:held_item].z = 3 + record_values(:held_item) + end + + #----------------------------------------------------------------------------- + + def text=(value) + return if @text == value + @text = value + refresh + end + + def pokemon=(value) + @pokemon = value + @sprites[:pokemon].pokemon = @pokemon if @sprites[:pokemon] && !@sprites[:pokemon].disposed? + @sprites[:held_item].pokemon = @pokemon if @sprites[:held_item] && !@sprites[:held_item].disposed? + refresh + end + + def blank? + return @pokemon.nil? + end + + def selected=(value) + return if @selected == value + @selected = value + @sprites[:pokemon].selected = @selected + refresh + end + + def set_switch_index(value) + @switch_index = value + refresh + end + + #----------------------------------------------------------------------------- + + def refresh + super + refresh_panel_bg + refresh_hp_bar_graphic + refresh_ball_graphic + refresh_pokemon_icon + refresh_held_item_icon + end + + def refresh_panel_bg + return if !@sprites[:panel_bg] || @sprites[:panel_bg].disposed? + if @pokemon.nil? + @sprites[:panel_bg].change_bitmap(:blank) + elsif @selected + if @switch_index == @index + @sprites[:panel_bg].change_bitmap(:switch_sel2) + elsif @switch_index >= 0 + @sprites[:panel_bg].change_bitmap(:switch_sel) + elsif @pokemon.fainted? + @sprites[:panel_bg].change_bitmap(:fainted_sel) + else + @sprites[:panel_bg].change_bitmap(:able_sel) + end + else + if @switch_index == @index + @sprites[:panel_bg].change_bitmap(:switch) + elsif @pokemon.fainted? + @sprites[:panel_bg].change_bitmap(:fainted) + else + @sprites[:panel_bg].change_bitmap(:able) + end + end + end + + def refresh_hp_bar_graphic + return if !@sprites[:hp_bar] || @sprites[:hp_bar].disposed? + @sprites[:hp_bar].visible = (@pokemon && !@pokemon.egg? && !(@text && @text.length > 0)) + return if !@sprites[:hp_bar].visible + if @switch_index == @index || (@switch_index >= 0 && @selected) + @sprites[:hp_bar].change_bitmap(:switch) + elsif @pokemon.fainted? + @sprites[:hp_bar].change_bitmap(:fainted) + else + @sprites[:hp_bar].change_bitmap(:able) + end + end + + def refresh_ball_graphic + return if !@sprites[:ball] || @sprites[:ball].disposed? + @sprites[:ball].visible = !@pokemon.nil? + @sprites[:ball].change_bitmap((@selected) ? :sel : :desel) + end + + def refresh_pokemon_icon + return if !@sprites[:pokemon] || @sprites[:pokemon].disposed? + @sprites[:pokemon].visible = !@pokemon.nil? + @sprites[:pokemon].selected = @selected + end + + def refresh_held_item_icon + return if !@sprites[:held_item] || @sprites[:held_item].disposed? + @sprites[:held_item].visible = !@pokemon.nil? + end + + def refresh_overlay + super + return if @pokemon.nil? + draw_name + draw_level + draw_gender + draw_hp_bar + draw_hp_numbers + draw_status_icon + draw_shiny_icon + draw_annotation + end + + #----------------------------------------------------------------------------- + + def draw_name + pokemon_name = @pokemon.name + pokemon_name = crop_text(pokemon_name, 144) + name_width = @sprites[:overlay].bitmap.text_size(pokemon_name).width + draw_text(pokemon_name, 94 - [name_width - 130, 0].max, 22) + end + + def draw_level + return if @pokemon.egg? + draw_image(graphics_folder + _INTL("overlay_lv"), 16, 70) + draw_number_from_image(@bitmaps[:numbers], @pokemon.level, 38, 70) + end + + def draw_gender + return if @pokemon.egg? + if @pokemon.male? + draw_text(_INTL("♂"), 230, 22, theme: :male) + elsif @pokemon.female? + draw_text(_INTL("♀"), 230, 22, theme: :female) + end + end + + def draw_hp_bar + return if @pokemon.egg? || @pokemon.fainted? || (@text && @text.length > 0) + bar_x = 136 + bar_y = 52 + bar_total_width = 96 + bar_width = [@pokemon.hp * bar_total_width / @pokemon.totalhp.to_f, 1.0].max + bar_width = ((bar_width / 2).round) * 2 # Make the bar's length a multiple of 2 pixels + hp_zone = 0 # Green + hp_zone = 1 if @pokemon.hp <= (@pokemon.totalhp / 2).floor # Yellow + hp_zone = 2 if @pokemon.hp <= (@pokemon.totalhp / 4).floor # Red + draw_image(graphics_folder + "hp_bar_fill", bar_x, bar_y, + 0, hp_zone * 8, bar_width, 8) + end + + def draw_hp_numbers + return if @pokemon.egg? || (@text && @text.length > 0) + draw_number_from_image(@bitmaps[:numbers], @pokemon.hp, 178, 70, align: :right) + draw_number_from_image(@bitmaps[:numbers], "/" + @pokemon.totalhp.to_s, 178, 70, align: :left) + end + + def draw_status_icon + return if @pokemon.egg? || (@text && @text.length > 0) + status = -1 + if @pokemon.fainted? + status = GameData::Status.count - 1 + elsif @pokemon.status != :NONE + status = GameData::Status.get(@pokemon.status).icon_position + elsif @pokemon.pokerusStage == 1 + status = GameData::Status.count + end + if status >= 0 + draw_image(UI_FOLDER + _INTL("statuses"), 86, 68, + 0, status * GameData::Status::ICON_SIZE[1], *GameData::Status::ICON_SIZE) + end + end + + def draw_shiny_icon + return if @pokemon.egg? || (@text && @text.length > 0) + draw_image(UI_FOLDER + "shiny", 88, 48) if @pokemon.shiny? + end + + def draw_annotation + draw_text(@text, 94, 62) if @text && @text.length > 0 + end +end + +#=============================================================================== +# +#=============================================================================== +class UI::PartyVisualsButton < UI::SpriteContainer + GRAPHICS_FOLDER = "Party/" + TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay] + :default => [Color.new(248, 248, 248), Color.new(40, 40, 40)] # Base and shadow colour + } + + def initialize(text, x, y, narrow, viewport) + @text = text + @x = x + @y = y + @narrow = narrow + @selected = false + super(viewport) + refresh + end + + def initialize_sprites + @sprites[:button] = ChangelingSprite.new(0, 0, @viewport) + if @narrow + @sprites[:button].add_bitmap(:desel, graphics_folder + "icon_cancel_narrow") + @sprites[:button].add_bitmap(:sel, graphics_folder + "icon_cancel_narrow_sel") + else + @sprites[:button].add_bitmap(:desel, graphics_folder + "icon_cancel") + @sprites[:button].add_bitmap(:sel, graphics_folder + "icon_cancel_sel") + end + @sprites[:button].change_bitmap(:desel) + record_values(:button) + initialize_overlay + end + + def initialize_overlay + add_overlay(:overlay, 112, 48) + @sprites[:overlay].z = 1 + record_values(:overlay) + end + + #----------------------------------------------------------------------------- + + def selected=(value) + return if @selected == value + @selected = value + refresh + end + + #----------------------------------------------------------------------------- + + def refresh + super + @sprites[:button].change_bitmap((@selected) ? :sel : :desel) + end + + def refresh_overlay + super + draw_text(@text, @sprites[:overlay].width / 2, (@narrow) ? 8 : 14, align: :center) + end +end + +#=============================================================================== +# +#=============================================================================== +class UI::PartyVisuals < UI::BaseVisuals + attr_reader :index + attr_reader :sprites + attr_reader :sub_mode + + GRAPHICS_FOLDER = "Party/" # Subfolder in Graphics/UI + + def initialize(party, mode = :normal) + @party = party + @mode = mode + @index = (@party.length == 0) ? Settings::MAX_PARTY_SIZE : 0 + @multi_select = (@mode == :choose_entry_order) + super() + set_index(@index) + end + + def initialize_message_box + super + @sprites[:help_window] = Window_AdvancedTextPokemon.new("") + @sprites[:help_window].viewport = @viewport + @sprites[:help_window].z = 1500 + @sprites[:help_window].setSkin(MessageConfig.pbGetSpeechFrame) + pbBottomLeftLines(@sprites[:help_window], 1, 396) + end + + def initialize_sprites + initialize_panels + initialize_cancel_button + @sprites[:storage_text] = Window_UnformattedTextPokemon.new( + (can_access_screen_menu?) ? _INTL("[Action]: Menu") : "" + ) + @sprites[:storage_text].x = 32 + @sprites[:storage_text].y = Graphics.height - @sprites[:message_box].height - 16 + @sprites[:storage_text].z = 10 + @sprites[:storage_text].viewport = @viewport + @sprites[:storage_text].baseColor = Color.new(248, 248, 248) + @sprites[:storage_text].shadowColor = Color.black + @sprites[:storage_text].windowskin = nil + end + + def initialize_panels + Settings::MAX_PARTY_SIZE.times do |i| + @sprites["pokemon#{i}"] = UI::PartyVisualsPanel.new(@party[i], i, @viewport) + end + end + + def initialize_cancel_button + party_max = Settings::MAX_PARTY_SIZE + if @multi_select + @sprites["pokemon#{party_max}"] = UI::PartyVisualsButton.new(_INTL("CONFIRM"), 396, 308, true, @viewport) + @sprites["pokemon#{party_max + 1}"] = UI::PartyVisualsButton.new(_INTL("CANCEL"), 396, 346, true, @viewport) + else + @sprites["pokemon#{party_max}"] = UI::PartyVisualsButton.new(_INTL("CANCEL"), 396, 328, false, @viewport) + end + end + + #----------------------------------------------------------------------------- + + def can_access_screen_menu? + return false if @mode != :normal + return !switching? && (can_access_storage? || @party.length > 1) + end + + def can_access_storage? + return false if @mode != :normal + return ($player.has_box_link || $bag.has?(:POKEMONBOXLINK)) && + !$game_switches[Settings::DISABLE_BOX_LINK_SWITCH] && + !$game_map.metadata&.has_flag?("DisableBoxLink") + end + + def set_help_text(text) + @sprites[:help_window].text = text + pbBottomLeftLines(@sprites[:help_window], 1, 396) + @sprites[:help_window].resizeHeightToFit(text, @sprites[:help_window].width) + pbBottomLeft(@sprites[:help_window]) + @sprites[:help_window].visible = true + end + + def panels_have_annotations? + return !@sprites["pokemon0"].text.nil? + end + + def set_annotations(annot) + Settings::MAX_PARTY_SIZE.times do |i| + @sprites["pokemon#{i}"].text = (annot) ? annot[i] : nil + end + end + + def set_able_annotation_proc(able_proc) + @able_proc = able_proc + refresh_able_annotations + end + + # Used for extra restrictions on Pokémon when choosing one to trade. + def set_able_annotation_proc2(able_proc) + @able_proc2 = able_proc + refresh_able_annotations + end + + def set_index(new_index) + @index = new_index + num_sprites = Settings::MAX_PARTY_SIZE + ((@multi_select) ? 2 : 1) + num_sprites.times do |i| + @sprites["pokemon#{i}"].selected = (i == @index) + end + end + + def set_sub_mode(sub_mode = :normal) + @sub_mode = sub_mode + end + + #----------------------------------------------------------------------------- + + def switch_index + return @sprites["pokemon0"].switch_index + end + + def switching? + return switch_index >= 0 + end + + def start_switching(index) + Settings::MAX_PARTY_SIZE.times do |i| + @sprites["pokemon#{i}"].set_switch_index(index) + end + end + + def end_switching + Settings::MAX_PARTY_SIZE.times do |i| + @sprites["pokemon#{i}"].set_switch_index(-1) + end + end + + def animate_switch_panels_out(index1, index2) + pbSEPlay("GUI party switch") + # Setup values + sprite1 = @sprites["pokemon#{index1}"] + sprite2 = @sprites["pokemon#{index2}"] + sprite1_start_x = sprite1.x + sprite2_start_x = sprite2.x + sprite1_dir = (index1.even?) ? -1 : 1 + sprite2_dir = (index2.even?) ? -1 : 1 + # Animate the panels moving off-screen + duration = 0.4 + timer_start = System.uptime + loop do + sprite1.x = sprite1_start_x + lerp(0, sprite1_dir * Graphics.width / 2, duration, timer_start, System.uptime) + sprite2.x = sprite2_start_x + lerp(0, sprite2_dir * Graphics.width / 2, duration, timer_start, System.uptime) + Graphics.update + Input.update + update_visuals + break if sprite1.x == sprite1_start_x + (sprite1_dir * Graphics.width / 2) + end + end + + def animate_switch_panels_in(index1, index2) + pbSEPlay("GUI party switch") + # Setup values + sprite1 = @sprites["pokemon#{index1}"] + sprite2 = @sprites["pokemon#{index2}"] + sprite1.pokemon = @party[index1] + sprite2.pokemon = @party[index2] + sprite1_start_x = sprite1.x + sprite2_start_x = sprite2.x + sprite1_dir = (index1.even?) ? 1 : -1 + sprite2_dir = (index2.even?) ? 1 : -1 + # Animate the panels moving back into position + duration = 0.4 + timer_start = System.uptime + loop do + sprite1.x = sprite1_start_x + lerp(0, sprite1_dir * Graphics.width / 2, duration, timer_start, System.uptime) + sprite2.x = sprite2_start_x + lerp(0, sprite2_dir * Graphics.width / 2, duration, timer_start, System.uptime) + Graphics.update + Input.update + update_visuals + break if sprite1.x == sprite1_start_x + (sprite1_dir * Graphics.width / 2) + end + end + + #----------------------------------------------------------------------------- + + def show_message(text) + @sprites[:help_window].visible = false + super + @sprites[:help_window].visible = true + end + + def show_confirm_message(text) + @sprites[:help_window].visible = false + ret = super + @sprites[:help_window].visible = true + return ret + end + + def show_choice_message(text, options, index = 0) + @sprites[:help_window].visible = false + old_letter_by_letter = @sprites[:speech_box].letterbyletter + @sprites[:speech_box].letterbyletter = false + cmd_menu_align = :right # (@index.even? ? :right : :left) + ret = super(text, options, index, cmd_side: cmd_menu_align) + @sprites[:speech_box].letterbyletter = old_letter_by_letter + @sprites[:help_window].visible = true + return ret + end + + def show_choice(options, index = 0) + @sprites[:help_window].visible = false + ret = super + @sprites[:help_window].visible = true + return ret + end + + def choose_number(help_text, maximum, init_num = 1) + @sprites[:help_window].visible = false + ret = super + @sprites[:help_window].visible = true + return ret + end + + #----------------------------------------------------------------------------- + + def refresh + ensure_valid_index + refresh_panels + end + + def ensure_valid_index + old_index = @index + @index = @party.length - 1 if @index < Settings::MAX_PARTY_SIZE && @index >= @party.length + set_index(@index) if @index != old_index + end + + def refresh_panels + Settings::MAX_PARTY_SIZE.times { |i| refresh_panel(i) } + end + + def refresh_panel(panel_index) + sprite = @sprites["pokemon#{panel_index}"] + return if !sprite + if sprite.is_a?(UI::PartyVisualsPanel) + sprite.pokemon = sprite.pokemon + else + sprite.refresh + end + end + + def refresh_party + Settings::MAX_PARTY_SIZE.times do |i| + @sprites["pokemon#{i}"].pokemon = @party[i] + end + end + + def refresh_able_annotations + Settings::MAX_PARTY_SIZE.times do |i| + next if @sprites["pokemon#{i}"].blank? + if !@able_proc && !@able_proc2 + @sprites["pokemon#{i}"].text = nil + next + end + is_able = true + is_able = false if @able_proc && !@able_proc.call(@party[i]) + is_able = false if @able_proc2 && !@able_proc2.call(@party[i]) + @sprites["pokemon#{i}"].text = (is_able) ? _INTL("ABLE") : _INTL("NOT ABLE") + end + end + + #----------------------------------------------------------------------------- + + def update_input + # Check for movement to a new Pokémon/button + old_index = @index + update_cursor_movement + if @index != old_index + pbPlayCursorSE + set_index(@index) + end + # 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) + elsif Input.trigger?(Input::SPECIAL) + return update_interaction(Input::SPECIAL) + end + return nil + end + + def update_cursor_movement + num_sprites = Settings::MAX_PARTY_SIZE + ((@multi_select) ? 2 : 1) + if Input.repeat?(Input::UP) + if @index >= Settings::MAX_PARTY_SIZE + @index -= 1 + @index = @party.length - 1 if @index < Settings::MAX_PARTY_SIZE && !@party[@index] + @index = num_sprites - 1 if !@party[@index] # In case party is empty + else + loop do + @index -= 2 + break if @index < 0 || @party[@index] + end + @index = num_sprites - 1 if @index < 0 # Wrap around to the cancel button + end + elsif Input.repeat?(Input::DOWN) + if @index >= Settings::MAX_PARTY_SIZE - 1 + @index += 1 + @index = 0 if @index >= num_sprites # Wrap around to the first Pokémon + else + @index += 2 + end + @index = Settings::MAX_PARTY_SIZE if @index < Settings::MAX_PARTY_SIZE && !@party[@index] + elsif Input.repeat?(Input::LEFT) + loop do + @index -= 1 + break if @index < 0 || @index >= Settings::MAX_PARTY_SIZE || @party[@index] + end + @index = num_sprites - 1 if @index < 0 # Wrap around to the cancel button + elsif Input.repeat?(Input::RIGHT) + loop do + @index += 1 + break if @index >= Settings::MAX_PARTY_SIZE || @party[@index] + end + @index = 0 if @index >= num_sprites # Wrap around to the first Pokémon + @index = Settings::MAX_PARTY_SIZE if @index < Settings::MAX_PARTY_SIZE && !@party[@index] + end + end + + def update_interaction(input) + case input + when Input::USE + return :switch_pokemon_end if switching? + if @index == Settings::MAX_PARTY_SIZE + pbPlayCloseMenuSE + return :quit + elsif @sub_mode == :switch_pokemon + pbPlayDecisionSE + return :switch_pokemon_start + elsif @sub_mode == :switch_items + if @party[@index].hasItem? + pbPlayDecisionSE + return :item_move + end + end + pbPlayDecisionSE + return :interact_menu + when Input::ACTION + if can_access_screen_menu? + pbPlayDecisionSE + return :screen_menu + end + when Input::BACK + if switching? + pbPlayCancelSE + return :switch_pokemon_cancel + elsif (@sub_mode || :normal) != :normal + pbPlayCancelSE + return :clear_sub_mode + end + pbPlayCloseMenuSE + return :quit + end + return nil + end + + def navigate + refresh + super + end + + #----------------------------------------------------------------------------- + + def update_input_choose_pokemon + # Check for movement to a new Pokémon/button + old_index = @index + update_cursor_movement + if @index != old_index + pbPlayCursorSE + set_index(@index) + end + # Check for interaction + if Input.trigger?(Input::USE) + return update_interaction_choose_pokemon(Input::USE) + elsif Input.trigger?(Input::BACK) + return update_interaction_choose_pokemon(Input::BACK) + end + return nil + end + + def update_interaction_choose_pokemon(input) + case input + when Input::USE + if @index == Settings::MAX_PARTY_SIZE + if @multi_select # Confirm + pbPlayDecisionSE + return :confirm + else # Cancel + (switching?) ? pbPlayCancelSE : pbPlayCloseMenuSE + return :quit + end + elsif @index == Settings::MAX_PARTY_SIZE + 1 # Cancel + (switching?) ? pbPlayCancelSE : pbPlayCloseMenuSE + return :quit + else + return :chosen + end + when Input::BACK + (switching?) ? pbPlayCancelSE : pbPlayCloseMenuSE + return :quit + end + return nil + end + + def navigate_choose_pokemon + ret = nil + loop do + Graphics.update + Input.update + update_visuals + ret = update_input_choose_pokemon + break if ret + end + return ret + end +end + +#=============================================================================== +# +#=============================================================================== +class UI::Party < UI::BaseScreen + attr_reader :party, :mode + + SCREEN_ID = :party_screen + + # mode is one of: + # :normal Can choose Fly/Dig/Teleport to use + # :choose_pokemon Result is index of chosen Pokémon; def pbMoveTutorChoose + # wants this to yield when chosen + # :battle_choose_pokemon For battle. + # :battle_choose_to_box For battle. Like :choose_pokemon but with a different help text. + # :battle_use_item For battle. + # :use_item Like :choose_pokemon but with a different help text + # :teach_pokemon Like :choose_pokemon but with a different help text + + + # :choose_entry_order Battle Frontier thing + def initialize(party, mode: :normal) + @party = (party.is_a?(Array)) ? party : [party] + @mode = mode + super() + reset_help_text + end + + def initialize_visuals + @visuals = UI::PartyVisuals.new(@party, @mode) + end + + #----------------------------------------------------------------------------- + + def index + return @visuals.index + end + + def set_index(new_index) + @visuals.set_index(new_index) + end + + def pokemon + return (index < @party.length) ? @party[index] : nil + end + + def sprites + return @visuals.sprites + end + + def can_access_storage? + return @visuals.can_access_storage? + end + + def set_help_text(text) + @visuals.set_help_text(text) + end + + def set_able_annotation_proc(able_proc) + @able_proc = able_proc + @visuals.set_able_annotation_proc(able_proc) + end + + # Used for extra restrictions on Pokémon when choosing one to trade. + def set_able_annotation_proc2(able_proc) + @able_proc2 = able_proc + @visuals.set_able_annotation_proc2(able_proc) + end + + def set_annotations(annot) + @visuals.set_annotations(annot) + end + + def clear_annotations + @visuals.set_annotations(nil) + end + + def set_sub_mode(sub_mode = :normal) + @visuals.set_sub_mode(sub_mode) + end + + #----------------------------------------------------------------------------- + + def switch_index + return @visuals.switch_index + end + + def switching? + return @visuals.switching? + end + + def start_switching(index = nil) + @visuals.start_switching(index || @visuals.index) + end + + def end_switching + @visuals.end_switching + end + + def switch_pokemon(index1, index2) + if index1 >= 0 && index1 < @party.length && + index2 >= 0 && index2 < @party.length && + index1 != index2 + @visuals.animate_switch_panels_out(index1, index2) + @party[index1], @party[index2] = @party[index2], @party[index1] + @visuals.animate_switch_panels_in(index1, index2) + end + end_switching + end + + #----------------------------------------------------------------------------- + + def refresh + super + reset_help_text + end + + def reset_help_text + case @mode + when :normal + if switching? + set_help_text(_INTL("Move to where?")) + else + case @visuals.sub_mode + when :switch_pokemon + set_help_text(_INTL("Choose Pokémon to switch.")) + when :switch_items + set_help_text(_INTL("Choose to switch items.")) + else + set_help_text((@party.length > 1) ? _INTL("Choose a Pokémon.") : _INTL("Choose Pokémon or cancel.")) + end + end + when :choose_pokemon, :battle_choose_pokemon + if switching? + set_help_text(_INTL("Move to where?")) + else + set_help_text(_INTL("Choose a Pokémon.")) + end + when :use_item, :battle_use_item + set_help_text(_INTL("Use on which Pokémon?")) + when :teach_pokemon + set_help_text(_INTL("Teach which Pokémon?")) + when :battle_choose_to_box + set_help_text(_INTL("Send which Pokémon to Boxes?")) + when :choose_entry_order + set_help_text(_INTL("Choose Pokémon and confirm.")) + end + end + + def refresh_party + @visuals.refresh_party + end + + # TODO: Get rid of this method once storage screen and PokemonDebugPartyScreen + # have been rewritten. + def pbRefreshSingle(_party_index) + refresh + end + + # TODO: Get rid of this method once storage screen and PokemonDebugPartyScreen + # have been rewritten. + def pbHardRefresh + refresh_party + refresh + end + + #----------------------------------------------------------------------------- + + # For Soft-Boiled and Milk Drink. + def use_field_move(move_id) + pkmn = pokemon + move = pkmn.moves.select { |mov| mov.id == move_id }.first + move_name = move.name + case move_id + when :SOFTBOILED, :MILKDRINK + heal_amt = [(pkmn.totalhp / 5).floor, 1].max + if pkmn.hp <= heal_amt + show_message(_INTL("Not enough HP...")) + return + end + old_party_idx = index + start_switching(old_party_idx) + loop do + set_help_text(_INTL("Use on which Pokémon?")) + new_party_idx = choose_pokemon_core + if new_party_idx < 0 || new_party_idx == old_party_idx + end_switching + break + end + new_pkmn = pokemon + if new_party_idx == old_party_idx + show_message(_INTL("{1} can't use {2} on itself!", pkmn.name, move_name)) + elsif new_pkmn.egg? + show_message(_INTL("{1} can't be used on an Egg!", move_name)) + elsif new_pkmn.fainted? || new_pkmn.hp == new_pkmn.totalhp + show_message(_INTL("{1} can't be used on that Pokémon.", move_name)) + else + pkmn.hp -= heal_amt + hp_gain = pbItemRestoreHP(new_pkmn, heal_amt) + show_message(_INTL("{1}'s HP was restored by {2} points.", new_pkmn.name, hp_gain)) + refresh + end + break if pkmn.hp <= heal_amt + end + end_switching + set_index(old_party_idx) + else + if pbCanUseHiddenMove?(pkmn, move_id) && pbConfirmUseHiddenMove(pkmn, move_id) + if move_id == :FLY + pbFadeOutInWithUpdate(sprites) do + town_map_scene = PokemonRegionMap_Scene.new(-1, false) + town_map_screen = PokemonRegionMapScreen.new(town_map_scene) + ret = town_map_screen.pbStartFlyScreen + if ret + $game_temp.field_move_to_use = move_id + $game_temp.field_move_user = pkmn + $game_temp.fly_destination = ret + silent_end_screen + end + end + else + $game_temp.field_move_to_use = move_id + $game_temp.field_move_user = pkmn + end_screen + end + end + end + end + + #----------------------------------------------------------------------------- + + def on_start_main_loop + reset_help_text + end + + def choose_pokemon + start_screen + loop do + on_start_main_loop + chosen_index = choose_pokemon_core + if chosen_index >= 0 && block_given? + next if !yield @party[chosen_index], chosen_index + end + @result = chosen_index + break + end + end_screen + return @result + end + + def choose_pokemon_core + ret = -1 + loop do + command = @visuals.navigate_choose_pokemon + if command != :chosen || index < 0 || index >= @party.length + ret = -1 + break + end + if (@able_proc && !@able_proc.call(pokemon)) || + (@able_proc2 && !@able_proc2.call(pokemon)) + pbPlayDecisionSE + if pokemon.egg? + show_message(_INTL("This egg can't be chosen.")) + else + show_message(_INTL("This Pokémon can't be chosen.")) + end + next + end + ret = index + break + end + return ret + end + + # Used by the Battle Frontier. + def choose_pokemon_entry_order(ruleset) + return nil if !ruleset.hasValidTeam?(@party) + # Setup party panel annotations + annot = [] + statuses = [] + ordinals = [_INTL("INELIGIBLE"), _INTL("NOT ENTERED"), _INTL("BANNED")] + positions = [_INTL("FIRST"), _INTL("SECOND"), _INTL("THIRD"), _INTL("FOURTH"), + _INTL("FIFTH"), _INTL("SIXTH"), _INTL("SEVENTH"), _INTL("EIGHTH"), + _INTL("NINTH"), _INTL("TENTH"), _INTL("ELEVENTH"), _INTL("TWELFTH")] + Settings::MAX_PARTY_SIZE.times do |i| + ordinals.push(positions[i] || "#{i + 1}th") + end + @party.length.times do |i| + statuses[i] = (ruleset.isPokemonValid?(@party[i])) ? 1 : 2 + annot[i] = ordinals[statuses[i]] + end + set_annotations(annot) + # Main loop + start_screen + ret = nil + added_entry = false # Whether an entry was added in the previous loop + loop do + on_start_main_loop + # Get an array of the chosen Pokémon in order + real_order = [] + @party.length.times do |i| + @party.length.times do |j| + next if statuses[j] != i + 3 + real_order.push(j) + break + end + end + real_order.length.times { |i| statuses[real_order[i]] = i + 3 } + # Refresh annotations + @party.length.times { |i| annot[i] = ordinals[statuses[i]] } + set_annotations(annot) + # Move index to the "Confirm" button if the required number of Pokémon are + # now chosen + if real_order.length == ruleset.number && added_entry + @visuals.set_index(Settings::MAX_PARTY_SIZE) + end + added_entry = false + # Choose a Pokémon or button + command = @visuals.navigate_choose_pokemon + case command + when :chosen + pbPlayDecisionSE + commands = {} + commands[:enter] = _INTL("Entry") if (statuses[index] || 0) == 1 # Not entered yet + commands[:not_enter] = _INTL("No Entry") if (statuses[index] || 0) > 2 # Already entered + commands[:summary] = _INTL("Summary") + commands[:cancel] = _INTL("Cancel") + chosen_command = show_choice_message(_INTL("Do what with {1}?", pokemon.name), commands) + case chosen_command + when :enter + if real_order.length >= ruleset.number && ruleset.number > 0 + show_message(_INTL("No more than {1} Pokémon may enter.", ruleset.number)) + else + statuses[index] = real_order.length + 3 + added_entry = true + refresh + end + when :not_enter + statuses[index] = 1 + refresh + when :summary + perform_action(:summary) + end + when :confirm + ret = [] + real_order.each { |i| ret.push(@party[i]) } + error = [] + break if ruleset.isValid?(ret, error) + show_message(error[0]) + ret = nil + when :quit # Cancelled + break + end + end + end_screen + @result = ret + return @result + end + + def choose_move(pkmn, message) + # 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_choice_message(message, move_names) + end + + alias pbChooseMove choose_move +end + +#=============================================================================== +# Actions that can be triggered in the party screen. +#=============================================================================== +# Shows a choice menu using the MenuHandlers options below. +UIActionHandlers.add(UI::Party::SCREEN_ID, :screen_menu, { + :menu => :party_screen_menu, + :menu_message => proc { |screen| _INTL("Choose an option.") } +}) + +# Shows a choice menu using the MenuHandlers options below. +UIActionHandlers.add(UI::Party::SCREEN_ID, :interact_menu, { + :menu => :party_screen_interact, + :menu_message => proc { |screen| _INTL("Do what with {1}?", screen.pokemon.name) } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :summary, { + :effect => proc { |screen| + summary_mode = [:battle_choose_pokemon, :battle_choose_to_box, :battle_use_item].include?(screen.mode) ? :in_battle : :normal + pbFadeOutInWithUpdate(screen.sprites) do + new_index = UI::PokemonSummary.new(screen.party, screen.index, mode: summary_mode).main + screen.set_index(new_index) + end + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :debug, { + :effect => proc { |screen| + screen.pokemon_debug_menu(screen.pokemon, screen.index) + } +}) + +# Start switching. +UIActionHandlers.add(UI::Party::SCREEN_ID, :switch_pokemon_start, { + :effect => proc { |screen| + screen.start_switching + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :switch_pokemon_end, { + :effect => proc { |screen| + screen.switch_pokemon(screen.switch_index, screen.index) + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :switch_pokemon_cancel, { + :effect => proc { |screen| + screen.end_switching + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :switch_pokemon_mode, { + :effect => proc { |screen| + screen.set_sub_mode(:switch_pokemon) + } +}) + +# Shows a choice menu using the MenuHandlers options below. +UIActionHandlers.add(UI::Party::SCREEN_ID, :item_menu, { + :menu => :party_screen_interact_item, + :menu_message => proc { |screen| _INTL("Do what with an item?") } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :item_use, { + :effect => proc { |screen| + pkmn = screen.pokemon + used_item = nil + pbFadeOutInWithUpdate(screen.sprites) do + bag_scene = PokemonBag_Scene.new + bag_screen = PokemonBagScreen.new(bag_scene, $bag) + used_item = bag_screen.pbChooseItemScreen(proc { |item| + itm = GameData::Item.get(item) + next false if !pbCanUseOnPokemon?(itm) + next false if pkmn.hyper_mode && !GameData::Item.get(item)&.is_scent? + if itm.is_machine? + move = itm.move + next false if pkmn.hasMove?(move) || !pkmn.compatible_with_move?(move) + end + next true + }) + end + if used_item + pbUseItemOnPokemon(used_item, pkmn, screen) + screen.refresh + end + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :item_give, { + :effect => proc { |screen| + pkmn = screen.pokemon + given_item = nil + pbFadeOutInWithUpdate(screen.sprites) do + bag_scene = PokemonBag_Scene.new + bag_screen = PokemonBagScreen.new(bag_scene, $bag) + given_item = bag_screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).can_hold? }) + end + if given_item + pbGiveItemToPokemon(given_item, pkmn, screen, screen.index) + screen.refresh + end + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :item_take, { + :effect => proc { |screen| + pkmn = screen.pokemon + next if !pbTakeItemFromPokemon(pkmn, screen) + screen.refresh + } +}) + +# TODO: Switching Pokémon goes through the regular navigate, but switching items +# (here) has the whole switching process in this handler. Be consistent. +UIActionHandlers.add(UI::Party::SCREEN_ID, :item_move, { + :effect => proc { |screen| + old_pkmn = screen.pokemon + old_item = old_pkmn.item + old_item_name = old_item.name + old_item_portion_name = old_item.portion_name + screen.set_help_text(_INTL("Move held item to where?")) + old_party_idx = screen.index + moved = false + loop do + screen.start_switching(old_party_idx) + new_party_idx = screen.choose_pokemon_core + if new_party_idx < 0 || new_party_idx == old_party_idx + screen.end_switching + break + end + pbPlayDecisionSE + new_pkmn = screen.party[new_party_idx] + if new_pkmn.egg? + screen.show_message(_INTL("Eggs can't hold items.")) + next + elsif !new_pkmn.hasItem? + new_pkmn.item = old_item + old_pkmn.item = nil + screen.end_switching + screen.show_message(_INTL("{1} was given the {2} to hold.", new_pkmn.name, old_item_portion_name)) + moved = true + break + elsif new_pkmn.item.is_mail? + screen.show_message(_INTL("{1}'s mail must be removed before giving it an item.", new_pkmn.name)) + next + end + # New Pokémon is also holding an item; ask what to do with it + new_item = new_pkmn.item + new_item_portion_name = new_item.portion_name + if new_item_portion_name.starts_with_vowel? + screen.show_message(_INTL("{1} is already holding an {2}.", new_pkmn.name, new_item_portion_name) + "\1") + else + screen.show_message(_INTL("{1} is already holding a {2}.", new_pkmn.name, new_item_portion_name) + "\1") + end + next if !screen.show_confirm_message(_INTL("Would you like to switch the two items?")) + new_pkmn.item = old_item + old_pkmn.item = new_item + screen.end_switching + screen.show_message(_INTL("{1} was given the {2} to hold.", new_pkmn.name, old_item_portion_name) + "\1") + screen.show_message(_INTL("{1} was given the {2} to hold.", old_pkmn.name, new_item_portion_name)) + moved = true + break + end + screen.set_index(old_party_idx) if !moved + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :item_move_mode, { + :effect => proc { |screen| + screen.set_sub_mode(:switch_items) + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :mail_read, { + :effect => proc { |screen| + pbFadeOutInWithUpdate(screen.sprites) do + pbDisplayMail(screen.pokemon.mail, screen.pokemon) + end + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :mail_take, { + :effect => proc { |screen| + if pbTakeItemFromPokemon(screen.pokemon, screen) + screen.refresh + end + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :clear_sub_mode, { + :effect => proc { |screen| + screen.set_sub_mode(:normal) + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :open_storage, { + :effect => proc { |screen| + pbFadeOutInWithUpdate(screen.sprites) do + storage_scene = PokemonStorageScene.new + storage_screen = PokemonStorageScreen.new(storage_scene, $PokemonStorage) + storage_screen.pbStartScreen(0) + screen.refresh_party + screen.refresh + end + } +}) + +# NOTE: This code adds a number of UIActionHandlers, one per move usable in the +# overworld. +HiddenMoveHandlers.eachHandler do |move_id| + eval <<-__END__ + UIActionHandlers.add(UI::Party::SCREEN_ID, :use_#{move_id}, { + :effect => proc { |screen| + screen.use_field_move(:#{move_id}) + } + }) + __END__ +end + +UIActionHandlers.add(UI::Party::SCREEN_ID, :use_MILKDRINK, { + :effect => proc { |screen| + screen.use_field_move(:MILKDRINK) + } +}) + +UIActionHandlers.add(UI::Party::SCREEN_ID, :use_SOFTBOILED, { + :effect => proc { |screen| + screen.use_field_move(:SOFTBOILED) + } +}) + +#=============================================================================== +# Menu options for choice menus that exist in the party screen. +#=============================================================================== +MenuHandlers.add(:party_screen_interact, :summary, { + "name" => _INTL("Summary"), + "order" => 10 +}) + +MenuHandlers.add(:party_screen_interact, :debug, { + "name" => _INTL("Debug"), + "order" => 20, + "condition" => proc { |screen| next $DEBUG } +}) + +MenuHandlers.add(:party_screen_interact, :field_moves, { + "order" => 30, + "multi_options" => proc { |screen| + ret = [] + next ret if screen.pokemon.egg? + screen.pokemon.moves.each do |move| + next if !HiddenMoveHandlers.hasHandler(move.id) && + ![:MILKDRINK, :SOFTBOILED].include?(move.id) + ret.push(["use_#{move.id}".to_sym, nil, "" + move.name + ""]) + end + next ret + } +}) + +MenuHandlers.add(:party_screen_interact, :switch_pokemon_start, { + "name" => _INTL("Switch"), + "order" => 40, + "condition" => proc { |screen| next screen.party.length > 1 } +}) + +MenuHandlers.add(:party_screen_interact, :item_menu, { + "name" => _INTL("Item"), + "order" => 50, + "condition" => proc { |screen| next !screen.pokemon.egg? && !screen.pokemon.mail } +}) + +MenuHandlers.add(:party_screen_interact_item, :item_use, { + "name" => _INTL("Use"), + "order" => 10 +}) + +MenuHandlers.add(:party_screen_interact_item, :item_give, { + "name" => _INTL("Give"), + "order" => 20 +}) + +MenuHandlers.add(:party_screen_interact_item, :item_take, { + "name" => _INTL("Take"), + "order" => 30, + "condition" => proc { |screen| next screen.pokemon.hasItem? } +}) + +MenuHandlers.add(:party_screen_interact_item, :item_move, { + "name" => _INTL("Move"), + "order" => 40, + "condition" => proc { |screen| next screen.pokemon.hasItem? && !screen.pokemon.item.is_mail? } +}) + +MenuHandlers.add(:party_screen_interact_item, :item_cancel, { + "name" => _INTL("Cancel"), + "order" => 9999 +}) + +MenuHandlers.add(:party_screen_interact, :mail_menu, { + "name" => _INTL("Mail"), + "order" => 50, + "condition" => proc { |screen| next !screen.pokemon.egg? && screen.pokemon.mail } +}) + +MenuHandlers.add(:party_screen_interact_mail, :mail_read, { + "name" => _INTL("Read"), + "order" => 10 +}) + +MenuHandlers.add(:party_screen_interact_mail, :mail_take, { + "name" => _INTL("Take"), + "order" => 20 +}) + +MenuHandlers.add(:party_screen_interact_mail, :mail_cancel, { + "name" => _INTL("Cancel"), + "order" => 30 +}) + +MenuHandlers.add(:party_screen_interact, :cancel, { + "name" => _INTL("Cancel"), + "order" => 9999 +}) + +#------------------------------------------------------------------------------- + +MenuHandlers.add(:party_screen_menu, :open_storage, { + "name" => _INTL("Access Pokémon Boxes"), + "order" => 10, + "condition" => proc { |screen| next screen.can_access_storage? } +}) + +MenuHandlers.add(:party_screen_menu, :switch_pokemon_mode, { + "name" => _INTL("Mode: Switch Pokémon"), + "order" => 20, + "condition" => proc { |screen| next screen.party.length > 1 } +}) + +MenuHandlers.add(:party_screen_menu, :item_move_mode, { + "name" => _INTL("Mode: Switch items"), + "order" => 30, + "condition" => proc { |screen| next screen.party.length > 1 } +}) + +MenuHandlers.add(:party_screen_menu, :cancel, { + "name" => _INTL("Cancel"), + "order" => 9999 +}) + +#=============================================================================== +# Open the party screen. +#=============================================================================== +def pbPokemonScreen + pbFadeOutIn do + UI::Party.new($player.party).main + end +end + +#=============================================================================== +# Choose a Pokémon in the party. +#=============================================================================== +# Choose a Pokémon/egg from the party. +# Stores result in variable _index_game_var_ and the chosen Pokémon's name in +# variable _name_game_var_; result is -1 if no Pokémon was chosen +# _allowIneligible is unused. +def pbChoosePokemon(index_game_var, name_game_var, able_proc = nil, _allow_ineligible = false) + chosen = -1 + pbFadeOutIn do + screen = UI::Party.new($player.party, mode: :choose_pokemon) + screen.set_able_annotation_proc(able_proc) if able_proc + chosen = screen.choose_pokemon + end + pbSet(index_game_var, chosen) + pbSet(name_game_var, (chosen >= 0) ? $player.party[chosen].name : "") +end + +def pbChooseNonEggPokemon(index_game_var, name_game_var) + pbChoosePokemon(index_game_var, name_game_var, proc { |pkmn| !pkmn.egg? }) +end + +def pbChooseAblePokemon(index_game_var, name_game_var) + pbChoosePokemon(index_game_var, name_game_var, proc { |pkmn| !pkmn.egg? && pkmn.hp > 0 }) +end + +# Same as pbChoosePokemon, but prevents choosing an egg or a Shadow Pokémon or a +# Pokémon that is marked and untradable. +def pbChooseTradablePokemon(index_game_var, name_game_var, able_proc = nil, _allow_ineligible = false) + chosen = 0 + pbFadeOutIn do + screen = UI::Party.new($player.party, mode: :choose_pokemon) + screen.set_able_annotation_proc(able_proc) if able_proc + screen.set_able_annotation_proc2(proc { |pkmn| next !pkmn.egg? && !pkmn.shadowPokemon? && !pkmn.cannot_trade }) + chosen = screen.choose_pokemon + end + pbSet(index_game_var, chosen) + pbSet(name_game_var, (chosen >= 0) ? $player.party[chosen].name : "") +end + +def pbChoosePokemonForTrade(index_game_var, name_game_var, wanted) + wanted = GameData::Species.get(wanted).species + pbChooseTradablePokemon(index_game_var, name_game_var, proc { |pkmn| + next pkmn.isSpecies?(wanted) + }) +end diff --git a/Data/Scripts/016b_UI redesign/006_UI_Summary.rb b/Data/Scripts/016b_UI redesign/006_UI_Summary.rb index a10a61356..bcd57e4d8 100644 --- a/Data/Scripts/016b_UI redesign/006_UI_Summary.rb +++ b/Data/Scripts/016b_UI redesign/006_UI_Summary.rb @@ -218,6 +218,7 @@ class UI::PokemonSummaryVisuals < UI::BaseVisuals @page = (@mode == :choose_move) ? :moves : all_pages[0] @move_index = (@mode == :choose_move) ? 0 : nil super() + refresh_move_cursor if @move_index end def initialize_bitmaps @@ -974,9 +975,9 @@ class UI::PokemonSummaryVisuals < UI::BaseVisuals def refresh_move_cursor # Update cursor positions @sprites[:move_cursor].index = @move_index - @sprites[:selected_move_cursor].index = @swap_move_index + @sprites[:selected_move_cursor].index = @swap_move_index || -1 # Update cursor z values - if @swap_move_index >= 0 + if @swap_move_index && @swap_move_index >= 0 @sprites[:selected_move_cursor].z = @sprites[:move_cursor].z + 1 @sprites[:selected_move_cursor].z -= 2 if @move_index != @swap_move_index end @@ -1417,7 +1418,7 @@ end #=============================================================================== # Actions that can be triggered in the Pokémon summary screen. #=============================================================================== -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :go_to_previous_pokemon, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :go_to_previous_pokemon, { :effect => proc { |screen| if screen.party_index > 0 new_index = screen.party_index @@ -1434,9 +1435,9 @@ UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :go_to_previous_pokemon, end end } -) +}) -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :go_to_next_pokemon, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :go_to_next_pokemon, { :effect => proc { |screen| if screen.party_index < screen.party.length - 1 new_index = screen.party_index @@ -1453,9 +1454,9 @@ UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :go_to_next_pokemon, end end } -) +}) -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :navigate_moves, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :navigate_moves, { :returns_value => true, :effect => proc { |screen| move_index = screen.visuals.navigate_moves @@ -1463,29 +1464,29 @@ UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :navigate_moves, screen.refresh next nil } -) +}) -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :navigate_ribbons, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :navigate_ribbons, { :effect => proc { |screen| screen.visuals.navigate_ribbons screen.refresh } -) +}) -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :marking, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :marking, { :effect => proc { |screen| screen.visuals.navigate_markings screen.refresh } -) +}) # Shows a choice menu using the MenuHandlers options below. -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :interact_menu, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :interact_menu, { :menu => :summary_screen_interact, :condition => proc { |screen| next screen.mode != :in_battle } -) +}) -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :give_item, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :give_item, { :effect => proc { |screen| item = nil pbFadeOutIn do @@ -1495,15 +1496,15 @@ UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :give_item, end screen.refresh if pbGiveItemToPokemon(item, screen.pokemon, screen, screen.party_index) } -) +}) -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :take_item, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :take_item, { :effect => proc { |screen| screen.refresh if pbTakeItemFromPokemon(screen.pokemon, screen) } -) +}) -UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :pokedex, +UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :pokedex, { :effect => proc { |screen| $player.pokedex.register_last_seen(screen.pokemon) pbFadeOutIn do @@ -1512,7 +1513,7 @@ UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :pokedex, dex_screen.pbStartSceneSingle(screen.pokemon.species) end } -) +}) #=============================================================================== # Menu options for choice menus that exist in the Pokémon summary screen. diff --git a/Data/Scripts/018_Alternate battle modes/001_Battle Frontier/002_Challenge_Data.rb b/Data/Scripts/018_Alternate battle modes/001_Battle Frontier/002_Challenge_Data.rb index e75815f93..62f26f8ff 100644 --- a/Data/Scripts/018_Alternate battle modes/001_Battle Frontier/002_Challenge_Data.rb +++ b/Data/Scripts/018_Alternate battle modes/001_Battle Frontier/002_Challenge_Data.rb @@ -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 #=============================================================================== diff --git a/Data/Scripts/019_Utilities/001_Utilities.rb b/Data/Scripts/019_Utilities/001_Utilities.rb index f78f0bf0e..3b03fa8c5 100644 --- a/Data/Scripts/019_Utilities/001_Utilities.rb +++ b/Data/Scripts/019_Utilities/001_Utilities.rb @@ -445,39 +445,35 @@ def pbMoveTutorAnnotations(move, movelist = nil) return ret end -def pbMoveTutorChoose(move, movelist = nil, bymachine = false, oneusemachine = false) +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 diff --git a/Data/Scripts/020_Debug/003_Debug menus/001_Debug_Menus.rb b/Data/Scripts/020_Debug/003_Debug menus/001_Debug_Menus.rb index bcd7903eb..0c0047648 100644 --- a/Data/Scripts/020_Debug/003_Debug menus/001_Debug_Menus.rb +++ b/Data/Scripts/020_Debug/003_Debug menus/001_Debug_Menus.rb @@ -149,7 +149,7 @@ end # #=============================================================================== module PokemonDebugMixin - def pbPokemonDebug(pkmn, pkmnid, heldpoke = nil, settingUpBattle = false) + def pokemon_debug_menu(pkmn, pkmnid, heldpoke = nil, settingUpBattle = false) # Get all commands commands = CommandMenuList.new MenuHandlers.each_available(:pokemon_debug_menu) do |option, hash, name| @@ -408,7 +408,7 @@ end #=============================================================================== # #=============================================================================== -class PokemonPartyScreen +class UI::Party include PokemonDebugMixin end diff --git a/Data/Scripts/020_Debug/003_Debug menus/002_Debug_MenuCommands.rb b/Data/Scripts/020_Debug/003_Debug menus/002_Debug_MenuCommands.rb index aaf9a57d1..4355cdf30 100644 --- a/Data/Scripts/020_Debug/003_Debug menus/002_Debug_MenuCommands.rb +++ b/Data/Scripts/020_Debug/003_Debug menus/002_Debug_MenuCommands.rb @@ -355,7 +355,7 @@ MenuHandlers.add(:debug_menu, :test_wild_battle_advanced, { else # Edit a Pokémon if pbConfirmMessage(_INTL("Change this Pokémon?")) scr = PokemonDebugPartyScreen.new - scr.pbPokemonDebug(pkmn[pkmnCmd], -1, nil, true) + scr.pokemon_debug_menu(pkmn[pkmnCmd], -1, nil, true) scr.pbEndScreen elsif pbConfirmMessage(_INTL("Delete this Pokémon?")) pkmn.delete_at(pkmnCmd) diff --git a/Data/Scripts/020_Debug/003_Debug menus/003_Debug_MenuExtraCode.rb b/Data/Scripts/020_Debug/003_Debug menus/003_Debug_MenuExtraCode.rb index d33f9249b..7488ad08d 100644 --- a/Data/Scripts/020_Debug/003_Debug menus/003_Debug_MenuExtraCode.rb +++ b/Data/Scripts/020_Debug/003_Debug menus/003_Debug_MenuExtraCode.rb @@ -738,6 +738,7 @@ end #=============================================================================== # Pseudo-party screen for editing Pokémon being set up for a wild battle. +# TODO: Rewrite this with the new UI code. #=============================================================================== class PokemonDebugPartyScreen def initialize diff --git a/Data/Scripts/020_Debug/003_Debug menus/007_Debug_PokemonCommands.rb b/Data/Scripts/020_Debug/003_Debug menus/007_Debug_PokemonCommands.rb index e4aaa7cf1..e409c291d 100644 --- a/Data/Scripts/020_Debug/003_Debug menus/007_Debug_PokemonCommands.rb +++ b/Data/Scripts/020_Debug/003_Debug menus/007_Debug_PokemonCommands.rb @@ -1,3 +1,5 @@ +# TODO: Rewrite all code in here to replace pbDisplay and whatnot, once storage +# screen and PokemonDebugPartyScreen have been rewritten. #=============================================================================== # HP/Status options. #=============================================================================== @@ -90,8 +92,8 @@ MenuHandlers.add(:pokemon_debug_menu, :full_heal, { screen.pbDisplay(_INTL("{1} is an egg.", pkmn.name)) else pkmn.heal - screen.pbDisplay(_INTL("{1} was fully healed.", pkmn.name)) screen.pbRefreshSingle(pkmnid) + screen.pbDisplay(_INTL("{1} was fully healed.", pkmn.name)) end next false } @@ -1018,7 +1020,7 @@ MenuHandlers.add(:pokemon_debug_menu, :set_egg, { "effect" => proc { |pkmn, pkmnid, heldpoke, settingUpBattle, screen| cmd = 0 loop do - msg = [_INTL("Not an egg"), + msg = [_INTL("Not an egg."), _INTL("Egg (hatches in {1} steps).", pkmn.steps_to_hatch)][pkmn.egg? ? 1 : 0] cmd = screen.pbShowCommands(msg, [_INTL("Make egg"), @@ -1113,9 +1115,10 @@ MenuHandlers.add(:pokemon_debug_menu, :duplicate, { next false if !screen.pbConfirm(_INTL("Are you sure you want to copy this Pokémon?")) clonedpkmn = pkmn.clone case screen - when PokemonPartyScreen + when UI::Party pbStorePokemon(clonedpkmn) - screen.pbHardRefresh + screen.refresh_party + screen.refresh screen.pbDisplay(_INTL("The Pokémon was duplicated.")) when PokemonStorageScreen if screen.storage.pbMoveCaughtToParty(clonedpkmn) @@ -1145,9 +1148,10 @@ MenuHandlers.add(:pokemon_debug_menu, :delete, { "effect" => proc { |pkmn, pkmnid, heldpoke, settingUpBattle, screen| next false if !screen.pbConfirm(_INTL("Are you sure you want to delete this Pokémon?")) case screen - when PokemonPartyScreen + when UI::Party screen.party.delete_at(pkmnid) - screen.pbHardRefresh + screen.refresh_party + screen.refresh when PokemonStorageScreen screen.scene.pbRelease(pkmnid, heldpoke) (heldpoke) ? screen.heldpkmn = nil : screen.storage.pbDelete(pkmnid[0], pkmnid[1])