From d8263da05eb8f32377388cf79499c24adf782153 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Fri, 13 Sep 2024 23:01:40 +0100 Subject: [PATCH] Rewrote Bag screen --- .../006_Event_HandlerCollections.rb | 2 +- .../005_SpriteWindow_text.rb | 9 +- .../Scripts/010_Data/002_PBS data/006_Item.rb | 9 + .../004_Scene/003_Scene_ChooseCommands.rb | 212 ++--- .../006_Overworld_BerryPlants.rb | 12 +- Data/Scripts/013_Items/001_Item_Utilities.rb | 32 +- Data/Scripts/013_Items/002_Item_Effects.rb | 31 +- Data/Scripts/013_Items/005_Item_PokeRadar.rb | 2 +- Data/Scripts/016_UI/016_UI_ReadyMenu.rb | 2 +- Data/Scripts/016_UI/017_UI_PokemonStorage.rb | 6 +- Data/Scripts/016_UI/018_UI_ItemStorage.rb | 103 +- Data/Scripts/016_UI/019_UI_PC.rb | 38 +- Data/Scripts/016_UI/020_UI_PokeMart.rb | 23 +- Data/Scripts/016_UI/021_UI_BattlePointShop.rb | 10 +- Data/Scripts/016b_UI redesign/000_UI_base.rb | 42 +- .../016b_UI redesign/001_UI_PauseMenu.rb | 8 +- Data/Scripts/016b_UI redesign/005_UI_Party.rb | 80 +- .../016b_UI redesign/006_UI_Summary.rb | 10 +- Data/Scripts/016b_UI redesign/007_UI_Bag.rb | 883 ++++++++++++++++++ .../007_UI_old_Bag.rb} | 0 20 files changed, 1271 insertions(+), 243 deletions(-) create mode 100644 Data/Scripts/016b_UI redesign/007_UI_Bag.rb rename Data/Scripts/{016_UI/007_UI_Bag.rb => 016c_UI_old/007_UI_old_Bag.rb} (100%) diff --git a/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb b/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb index 183ee66a7..4ae837a99 100644 --- a/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb +++ b/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb @@ -126,7 +126,7 @@ module MenuHandlers next end if hash["name"].is_a?(Proc) - name = hash["name"].call + name = hash["name"].call(*args) else name = _INTL(hash["name"]) end 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 1f58ded29..f615d505d 100644 --- a/Data/Scripts/007_Objects and windows/005_SpriteWindow_text.rb +++ b/Data/Scripts/007_Objects and windows/005_SpriteWindow_text.rb @@ -835,12 +835,11 @@ class SpriteWindow_Selectable < SpriteWindow_Base if item < 0 || item >= @item_max || item < self.top_item || item > self.top_item + self.page_item_max return Rect.new(0, 0, 0, 0) - else - cursor_width = (self.width - self.borderX - ((@column_max - 1) * @column_spacing)) / @column_max - x = item % @column_max * (cursor_width + @column_spacing) - y = (item / @column_max * @row_height) - @virtualOy - return Rect.new(x, y, cursor_width, @row_height) end + cursor_width = (self.width - self.borderX - ((@column_max - 1) * @column_spacing)) / @column_max + x = item % @column_max * (cursor_width + @column_spacing) + y = (item / @column_max * @row_height) - @virtualOy + return Rect.new(x, y, cursor_width, @row_height) end def refresh; end diff --git a/Data/Scripts/010_Data/002_PBS data/006_Item.rb b/Data/Scripts/010_Data/002_PBS data/006_Item.rb index 7d7e5eccf..c501e6f7a 100644 --- a/Data/Scripts/010_Data/002_PBS data/006_Item.rb +++ b/Data/Scripts/010_Data/002_PBS data/006_Item.rb @@ -146,6 +146,15 @@ module GameData return pbGetMessageFromHash(MessageTypes::ITEM_NAMES, @real_name) end + def display_name + ret = name + if is_machine? + machine = @move + ret = sprintf("%s %s", ret, GameData::Move.get(@move).name) + end + return ret + end + # @return [String] the translated plural version of the name of this item def name_plural return pbGetMessageFromHash(MessageTypes::ITEM_NAME_PLURALS, @real_name_plural) 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 d4eb94910..ba145d73c 100644 --- a/Data/Scripts/011_Battle/004_Scene/003_Scene_ChooseCommands.rb +++ b/Data/Scripts/011_Battle/004_Scene/003_Scene_ChooseCommands.rb @@ -199,123 +199,127 @@ class Battle::Scene else $bag.reset_last_selections end - # Start Bag screen - itemScene = PokemonBag_Scene.new - itemScene.pbStartScene($bag, true, - proc { |item| - useType = GameData::Item.get(item).battle_use - next useType && useType > 0 - }, false) - # Loop while in Bag screen wasTargeting = false - loop do - # Select an item - item = itemScene.pbChooseItem - break if !item - # Choose a command for the selected item - item = GameData::Item.get(item) - itemName = item.name - useType = item.battle_use - cmdUse = -1 - commands = [] - commands[cmdUse = commands.length] = _INTL("Use") if useType && useType != 0 - commands[commands.length] = _INTL("Cancel") - command = itemScene.pbShowCommands(_INTL("{1} is selected.", itemName), commands) - next unless cmdUse >= 0 && command == cmdUse # Use - # Use types: - # 0 = not usable in battle - # 1 = use on Pokémon (lots of items, Blue Flute) - # 2 = use on Pokémon's move (Ethers) - # 3 = use on battler (X items, Persim Berry, Red/Yellow Flutes) - # 4 = use on opposing battler (Poké Balls) - # 5 = use no target (Poké Doll, Guard Spec., Poké Flute, Launcher items) - case useType - when 1, 2, 3 # Use on Pokémon/Pokémon's move/battler - # Auto-choose the Pokémon/battler whose action is being decided if they - # are the only available Pokémon/battler to use the item on + # Start Bag screen + bag_screen = UI::Bag.new($bag, mode: :choose_item_in_battle) + bag_screen.set_filter_proc(proc { |itm| + use_type = GameData::Item.get(itm).battle_use + next use_type && use_type > 0 + }) + bag_screen.show_and_hide do + # Loop while in Bag screen + loop do + # Select an item + item = bag_screen.choose_item_core + break if !item + # Choose a command for the selected item + item = GameData::Item.get(item) + itemName = item.name + useType = item.battle_use + cmdUse = -1 + commands = [] + commands[cmdUse = commands.length] = _INTL("Use") if useType && useType != 0 + commands[commands.length] = _INTL("Cancel") + command = bag_screen.show_choice_message(_INTL("{1} is selected.", itemName), commands) + next unless cmdUse >= 0 && command == cmdUse # Use + # Use types: + # 0 = not usable in battle + # 1 = use on Pokémon (lots of items, Blue Flute) + # 2 = use on Pokémon's move (Ethers) + # 3 = use on battler (X items, Persim Berry, Red/Yellow Flutes) + # 4 = use on opposing battler (Poké Balls) + # 5 = use no target (Poké Doll, Guard Spec., Poké Flute, Launcher items) case useType - when 1 # Use on Pokémon - if @battle.pbTeamLengthFromBattlerIndex(idxBattler) == 1 - if yield item.id, useType, @battle.battlers[idxBattler].pokemonIndex, -1, itemScene - break - else - next + when 1, 2, 3 # Use on Pokémon/Pokémon's move/battler + # Auto-choose the Pokémon/battler whose action is being decided if they + # are the only available Pokémon/battler to use the item on + case useType + when 1 # Use on Pokémon + if @battle.pbTeamLengthFromBattlerIndex(idxBattler) == 1 + if yield item.id, useType, @battle.battlers[idxBattler].pokemonIndex, -1, bag_screen + break + else + next + end + end + when 3 # Use on battler + if @battle.pbPlayerBattlerCount == 1 + if yield item.id, useType, @battle.battlers[idxBattler].pokemonIndex, -1, bag_screen + break + else + next + end end end - when 3 # Use on battler - if @battle.pbPlayerBattlerCount == 1 - if yield item.id, useType, @battle.battlers[idxBattler].pokemonIndex, -1, itemScene - break - else - next - end - end - end - # Fade out and hide Bag screen - itemScene.pbFadeOutScene - # Get player's party - party = @battle.pbParty(idxBattler) - partyPos = @battle.pbPartyOrder(idxBattler) - partyStart, _partyEnd = @battle.pbTeamIndexRangeFromBattlerIndex(idxBattler) - modParty = @battle.pbPlayerDisplayParty(idxBattler) - # Start party screen - party_idx = -1 - party_screen = UI::Party.new(modParty, mode: :battle_use_item) - party_screen.choose_pokemon do |pkmn, party_index| - party_idx = party_index - next true if party_index < 0 - # Use the item on the selected Pokémon - real_party_index = -1 - partyPos.each_with_index do |pos, i| - next if pos != party_index + partyStart - real_party_index = i - break - end - next false if real_party_index < 0 - next false if !pkmn || pkmn.egg? - move_index = -1 - if useType == 2 # Use on Pokémon's move - move_index = party_screen.choose_move(pkmn, _INTL("Restore which move?")) - next false if move_index < 0 - end - next true if yield item.id, useType, real_party_index, move_index, party_screen - next false - end - 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) - idxTarget = -1 - if @battle.pbOpposingBattlerCount(idxBattler) == 1 - @battle.allOtherSideBattlers(idxBattler).each { |b| idxTarget = b.index } - break if yield item.id, useType, idxTarget, -1, itemScene - else - wasTargeting = true # Fade out and hide Bag screen - itemScene.pbFadeOutScene - # Fade in and show the battle screen, choosing a target - tempVisibleSprites = visibleSprites.clone - tempVisibleSprites["commandWindow"] = false - tempVisibleSprites["targetWindow"] = true - idxTarget = pbChooseTarget(idxBattler, GameData::Target.get(:Foe), tempVisibleSprites) - if idxTarget >= 0 - break if yield item.id, useType, idxTarget, -1, self + bag_sprites_status = pbFadeOutAndHide(bag_screen.sprites) + # Get player's party + party = @battle.pbParty(idxBattler) + partyPos = @battle.pbPartyOrder(idxBattler) + partyStart, _partyEnd = @battle.pbTeamIndexRangeFromBattlerIndex(idxBattler) + modParty = @battle.pbPlayerDisplayParty(idxBattler) + # Start party screen + party_idx = -1 + party_screen = UI::Party.new(modParty, mode: :battle_use_item) + party_screen.choose_pokemon do |pkmn, party_index| + party_idx = party_index + next true if party_index < 0 + # Use the item on the selected Pokémon + real_party_index = -1 + partyPos.each_with_index do |pos, i| + next if pos != party_index + partyStart + real_party_index = i + break + end + next false if real_party_index < 0 + next false if !pkmn || pkmn.egg? + move_index = -1 + if useType == 2 # Use on Pokémon's move + move_index = party_screen.choose_move(pkmn, _INTL("Restore which move?")) + next false if move_index < 0 + end + if yield item.id, useType, real_party_index, move_index, party_screen + bag_screen.silent_end_screen + next true + end + party_idx = -1 + next false end - # Target invalid/cancelled choosing a target; show the Bag screen again - wasTargeting = false - pbFadeOutAndHide(@sprites) - itemScene.pbFadeInScene + break if party_idx >= 0 # Item was used; close the Bag screen + # Cancelled choosing a Pokémon; show the Bag screen again + pbFadeInAndShow(bag_screen.sprites, bag_sprites_status) + when 4 # Use on opposing battler (Poké Balls) + idxTarget = -1 + if @battle.pbOpposingBattlerCount(idxBattler) == 1 + @battle.allOtherSideBattlers(idxBattler).each { |b| idxTarget = b.index } + break if yield item.id, useType, idxTarget, -1, bag_screen + else + wasTargeting = true + # Fade out and hide Bag screen + bag_sprites_status = pbFadeOutAndHide(bag_screen.sprites) + # Fade in and show the battle screen, choosing a target + tempVisibleSprites = visibleSprites.clone + tempVisibleSprites["commandWindow"] = false + tempVisibleSprites["targetWindow"] = true + idxTarget = pbChooseTarget(idxBattler, GameData::Target.get(:Foe), tempVisibleSprites) + if idxTarget >= 0 + break if yield item.id, useType, idxTarget, -1, self + end + # Target invalid/cancelled choosing a target; show the Bag screen again + wasTargeting = false + pbFadeOutAndHide(@sprites) + pbFadeInAndShow(bag_screen.sprites, bag_sprites_status) + end + when 5 # Use with no target + break if yield item.id, useType, idxBattler, -1, bag_screen end - when 5 # Use with no target - break if yield item.id, useType, idxBattler, -1, itemScene end + next true end @bagLastPocket = $bag.last_viewed_pocket @bagChoices = $bag.last_pocket_selections.clone $bag.last_viewed_pocket = oldLastPocket $bag.last_pocket_selections = oldChoices - # Close Bag screen - itemScene.pbEndScene # Fade back into battle screen (if not already showing it) pbFadeInAndShow(@sprites, visibleSprites) if !wasTargeting end diff --git a/Data/Scripts/012_Overworld/006_Overworld_BerryPlants.rb b/Data/Scripts/012_Overworld/006_Overworld_BerryPlants.rb index 21bb0fad3..b87657f0f 100644 --- a/Data/Scripts/012_Overworld/006_Overworld_BerryPlants.rb +++ b/Data/Scripts/012_Overworld/006_Overworld_BerryPlants.rb @@ -382,9 +382,9 @@ def pbBerryPlant when 0 # Fertilize mulch = nil pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - mulch = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).is_mulch? }) + bag_screen = UI::Bag.new($bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |item| GameData::Item.get(item).is_mulch? }) + mulch = bag_screen.choose_item end return if !mulch mulch_data = GameData::Item.get(mulch) @@ -409,9 +409,9 @@ def pbBerryPlant end if !ask_to_plant || pbConfirmMessage(_INTL("Want to plant a Berry?")) pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - berry = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).is_berry? }) + bag_screen = UI::Bag.new($bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |item| GameData::Item.get(item).is_berry? }) + berry = bag_screen.choose_item end if berry $stats.berries_planted += 1 diff --git a/Data/Scripts/013_Items/001_Item_Utilities.rb b/Data/Scripts/013_Items/001_Item_Utilities.rb index 00610827a..53d45546d 100644 --- a/Data/Scripts/013_Items/001_Item_Utilities.rb +++ b/Data/Scripts/013_Items/001_Item_Utilities.rb @@ -58,8 +58,8 @@ module ItemHandlers # 0 - Item not used # 1 - Item used, don't end screen # 2 - Item used, end screen - def triggerUseFromBag(item) - return UseFromBag.trigger(item) if UseFromBag[item] + def triggerUseFromBag(item, bag_screen = nil) + return UseFromBag.trigger(item, bag_screen) if UseFromBag[item] # No UseFromBag handler exists; check the UseInField handler if present if UseInField[item] return (UseInField.trigger(item)) ? 1 : 0 @@ -618,8 +618,11 @@ def pbLearnMove(pkmn, move, ignore_if_known = false, by_machine = false, screen if by_machine && Settings::TAUGHT_MACHINES_KEEP_OLD_PP pkmn.moves[move_index].pp = [old_move_pp, pkmn.moves[move_index].total_pp].min end + # TODO: The last \\wt[16] is skipped in instant text speed. Or rather, + # the text after it is shown at the same time as the text before + # it, but the SE waits for that duration and then plays. pbMessage(_INTL("1, 2, and...\\wt[16] ...\\wt[16] ...\\wt[16] Ta-da!") + "\\se[Battle ball drop]\1", &block) - pbMessage(_INTL("{1} forgot how to use {2}.\nAnd..." + "\1", pkmn_name, old_move_name), &block) + pbMessage(_INTL("{1} forgot how to use {2}.\nAnd...", pkmn_name, old_move_name) + "\1", &block) pbMessage("\\se[]" + _INTL("{1} learned {2}!", pkmn_name, move_name) + "\\se[Pkmn move learnt]", &block) pkmn.changeHappiness("machine") if by_machine return true @@ -646,6 +649,8 @@ end #=============================================================================== # Use an item from the Bag and/or on a Pokémon. #=============================================================================== +# Called from the Bag screen and also when prompted to use a Repel when one runs +# out (bag_scene will be nil for the latter). # @return [Integer] 0 = item wasn't used; 1 = item used; 2 = close Bag to use in field def pbUseItem(bag, item, bag_scene = nil) itm = GameData::Item.get(item) @@ -697,7 +702,7 @@ def pbUseItem(bag, item, bag_scene = nil) end return (ret) ? 1 : 0 elsif useType == 2 || itm.is_machine? # Item is usable from Bag or teaches a move - intret = ItemHandlers.triggerUseFromBag(item) + intret = ItemHandlers.triggerUseFromBag(item, bag_scene) if intret >= 0 bag.remove(item) if intret == 1 && itm.consumed_after_use? return intret @@ -796,7 +801,7 @@ def pbGiveItemToPokemon(item, pkmn, scene, pkmnid = 0) end if pkmn.hasItem? olditemname = pkmn.item.portion_name - if newitemname.starts_with_vowel? + if olditemname.starts_with_vowel? scene.pbDisplay(_INTL("{1} is already holding an {2}.", pkmn.name, olditemname) + "\1") else scene.pbDisplay(_INTL("{1} is already holding a {2}.", pkmn.name, olditemname) + "\1") @@ -869,9 +874,8 @@ end def pbChooseItem(var = 0, *args) ret = nil pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - ret = screen.pbChooseItemScreen + bag_screen = UI::Bag.new($bag, mode: :choose_item) + ret = bag_screen.choose_item end $game_variables[var] = ret || :NONE if var > 0 return ret @@ -880,9 +884,9 @@ end def pbChooseApricorn(var = 0) ret = nil pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - ret = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).is_apricorn? }) + bag_screen = UI::Bag.new($bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |item| GameData::Item.get(item).is_apricorn? }) + ret = bag_screen.choose_item end $game_variables[var] = ret || :NONE if var > 0 return ret @@ -891,9 +895,9 @@ end def pbChooseFossil(var = 0) ret = nil pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - ret = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).is_fossil? }) + bag_screen = UI::Bag.new($bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |item| GameData::Item.get(item).is_fossil? }) + ret = bag_screen.choose_item end $game_variables[var] = ret || :NONE if var > 0 return ret diff --git a/Data/Scripts/013_Items/002_Item_Effects.rb b/Data/Scripts/013_Items/002_Item_Effects.rb index 3e07a5f67..190433a08 100644 --- a/Data/Scripts/013_Items/002_Item_Effects.rb +++ b/Data/Scripts/013_Items/002_Item_Effects.rb @@ -25,11 +25,11 @@ ItemHandlers::UseText.add(:EXPALL, proc { |item| # a Pokémon), calls the UseInField handler for it instead. #=============================================================================== -ItemHandlers::UseFromBag.add(:HONEY, proc { |item| +ItemHandlers::UseFromBag.add(:HONEY, proc { |item, bag_screen| next 2 }) -ItemHandlers::UseFromBag.add(:ESCAPEROPE, proc { |item| +ItemHandlers::UseFromBag.add(:ESCAPEROPE, proc { |item, bag_screen| if !$game_player.can_map_transfer_with_follower? pbMessage(_INTL("It can't be used when you have someone with you.")) next 0 @@ -41,13 +41,13 @@ ItemHandlers::UseFromBag.add(:ESCAPEROPE, proc { |item| next 0 }) -ItemHandlers::UseFromBag.add(:BICYCLE, proc { |item| +ItemHandlers::UseFromBag.add(:BICYCLE, proc { |item, bag_screen| next (pbBikeCheck) ? 2 : 0 }) ItemHandlers::UseFromBag.copy(:BICYCLE, :MACHBIKE, :ACROBIKE) -ItemHandlers::UseFromBag.add(:OLDROD, proc { |item| +ItemHandlers::UseFromBag.add(:OLDROD, proc { |item, bag_screen| notCliff = $game_map.passable?($game_player.x, $game_player.y, $game_player.direction, $game_player) next 2 if $game_player.pbFacingTerrainTag.can_fish && ($PokemonGlobal.surfing || notCliff) pbMessage(_INTL("Can't use that here.")) @@ -56,26 +56,28 @@ ItemHandlers::UseFromBag.add(:OLDROD, proc { |item| ItemHandlers::UseFromBag.copy(:OLDROD, :GOODROD, :SUPERROD) -ItemHandlers::UseFromBag.add(:ITEMFINDER, proc { |item| +ItemHandlers::UseFromBag.add(:ITEMFINDER, proc { |item, bag_screen| next 2 }) ItemHandlers::UseFromBag.copy(:ITEMFINDER, :DOWSINGMCHN, :DOWSINGMACHINE) -ItemHandlers::UseFromBag.add(:TOWNMAP, proc { |item| - pbFadeOutIn do +ItemHandlers::UseFromBag.add(:TOWNMAP, proc { |item, bag_screen| + pbFadeOutInWithUpdate(bag_screen&.sprites) do scene = PokemonRegionMap_Scene.new(-1, false) screen = PokemonRegionMapScreen.new(scene) ret = screen.pbStartScreen - $game_temp.fly_destination = ret if ret - next 99999 if ret # Ugly hack to make Bag scene not reappear if flying + if ret + $game_temp.fly_destination = ret + bag_screen&.silent_end_screen + end end next ($game_temp.fly_destination) ? 2 : 0 }) ItemHandlers::UseFromBag.addIf(:move_machines, proc { |item| GameData::Item.get(item).is_machine? }, - proc { |item| + proc { |item, bag_screen| if $player.pokemon_count == 0 pbMessage(_INTL("There is no Pokémon.")) next 0 @@ -159,10 +161,13 @@ EventHandlers.add(:on_player_step_taken, :repel_counter, next if !pbConfirmMessage(_INTL("The repellent's effect wore off! Would you like to use another one?")) ret = nil pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - ret = screen.pbChooseItemScreen(proc { |item| repels.include?(item) }) + bag_screen = UI::Bag.new($bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |item| repels.include?(item) }) + ret = bag_screen.choose_item end + # TODO: Would be nice if this didn't call pbUseItem, so that pbUseItem would + # be exclusively called from the Bag screen and could rely on that + # screen existing. pbUseItem($bag, ret) if ret } ) diff --git a/Data/Scripts/013_Items/005_Item_PokeRadar.rb b/Data/Scripts/013_Items/005_Item_PokeRadar.rb index c26ac2209..3eebca97e 100644 --- a/Data/Scripts/013_Items/005_Item_PokeRadar.rb +++ b/Data/Scripts/013_Items/005_Item_PokeRadar.rb @@ -264,6 +264,6 @@ ItemHandlers::UseInField.add(:POKERADAR, proc { |item| next pbUsePokeRadar }) -ItemHandlers::UseFromBag.add(:POKERADAR, proc { |item| +ItemHandlers::UseFromBag.add(:POKERADAR, proc { |item, bag_screen| next (pbCanUsePokeRadar?) ? 2 : 0 }) diff --git a/Data/Scripts/016_UI/016_UI_ReadyMenu.rb b/Data/Scripts/016_UI/016_UI_ReadyMenu.rb index e3229953a..62da5d22e 100644 --- a/Data/Scripts/016_UI/016_UI_ReadyMenu.rb +++ b/Data/Scripts/016_UI/016_UI_ReadyMenu.rb @@ -82,7 +82,7 @@ class ReadyMenuButton < Sprite textpos.push([_INTL(">99"), 230, 24, :right, Color.new(248, 248, 248), Color.new(40, 40, 40), :outline]) else - textpos.push([_INTL("x{1}", qty), 230, 24, :right, + textpos.push([_INTL("×{1}", qty), 230, 24, :right, Color.new(248, 248, 248), Color.new(40, 40, 40), :outline]) end end diff --git a/Data/Scripts/016_UI/017_UI_PokemonStorage.rb b/Data/Scripts/016_UI/017_UI_PokemonStorage.rb index 288a10f00..9d788e91f 100644 --- a/Data/Scripts/016_UI/017_UI_PokemonStorage.rb +++ b/Data/Scripts/016_UI/017_UI_PokemonStorage.rb @@ -1237,9 +1237,9 @@ class PokemonStorageScene def pbChooseItem(bag) ret = nil pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, bag) - ret = screen.pbChooseItemScreen(proc { |item| GameData::Item.get(item).can_hold? }) + bag_screen = UI::Bag.new(bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |itm| GameData::Item.get(itm).can_hold? }) + ret = bag_screen.choose_item end return ret end diff --git a/Data/Scripts/016_UI/018_UI_ItemStorage.rb b/Data/Scripts/016_UI/018_UI_ItemStorage.rb index a7f37d6aa..10d9ae95f 100644 --- a/Data/Scripts/016_UI/018_UI_ItemStorage.rb +++ b/Data/Scripts/016_UI/018_UI_ItemStorage.rb @@ -1,3 +1,5 @@ +# TODO: Could inherit from class UI::BagVisuals and just change some graphics. + #=============================================================================== # #=============================================================================== @@ -39,7 +41,7 @@ class Window_PokemonItemStorage < Window_DrawableCommand baseColor = (index == @sortIndex) ? Color.new(248, 24, 24) : self.baseColor textpos.push([itemname, rect.x, rect.y, :left, self.baseColor, self.shadowColor]) if GameData::Item.get(item).show_quantity? - qty = _ISPRINTF("x{1: 2d}", @bag[index][1]) + qty = _ISPRINTF("×{1: 2d}", @bag[index][1]) sizeQty = self.contents.text_size(qty).width xQty = rect.x + rect.width - sizeQty - 2 textpos.push([qty, xQty, rect.y, :left, baseColor, self.shadowColor]) @@ -190,6 +192,93 @@ class TossItemScene < ItemStorage_Scene end end +#=============================================================================== +# +#=============================================================================== +class ItemStorageScreen + def initialize(scene, bag) + @bag = bag + @scene = scene + end + + def pbDisplay(text) + @scene.pbDisplay(text) + end + + def pbConfirm(text) + return @scene.pbConfirm(text) + end + + # UI logic for withdrawing an item in the item storage screen. + def pbWithdrawItemScreen + if !$PokemonGlobal.pcItemStorage + $PokemonGlobal.pcItemStorage = PCItemStorage.new + end + storage = $PokemonGlobal.pcItemStorage + @scene.pbStartScene(storage) + loop do + item = @scene.pbChooseItem + break if !item + itm = GameData::Item.get(item) + qty = storage.quantity(item) + if qty > 1 && !itm.is_important? + qty = @scene.pbChooseNumber(_INTL("How many do you want to withdraw?"), qty) + end + next if qty <= 0 + if @bag.can_add?(item, qty) + if !storage.remove(item, qty) + raise "Can't delete items from storage" + end + if !@bag.add(item, qty) + raise "Can't withdraw items from storage" + end + @scene.pbRefresh + dispqty = (itm.is_important?) ? 1 : qty + itemname = (dispqty > 1) ? itm.portion_name_plural : itm.portion_name + pbDisplay(_INTL("Withdrew {1} {2}.", dispqty, itemname)) + else + pbDisplay(_INTL("There's no more room in the Bag.")) + end + end + @scene.pbEndScene + end + + # UI logic for tossing an item in the item storage screen. + def pbTossItemScreen + if !$PokemonGlobal.pcItemStorage + $PokemonGlobal.pcItemStorage = PCItemStorage.new + end + storage = $PokemonGlobal.pcItemStorage + @scene.pbStartScene(storage) + loop do + item = @scene.pbChooseItem + break if !item + itm = GameData::Item.get(item) + if itm.is_important? + @scene.pbDisplay(_INTL("That's too important to toss out!")) + next + end + qty = storage.quantity(item) + itemname = itm.portion_name + itemnameplural = itm.portion_name_plural + if qty > 1 + qty = @scene.pbChooseNumber(_INTL("Toss out how many {1}?", itemnameplural), qty) + end + next if qty <= 0 + itemname = itemnameplural if qty > 1 + next if !pbConfirm(_INTL("Is it OK to throw away {1} {2}?", qty, itemname)) + if !storage.remove(item, qty) + raise "Can't delete items from storage" + end + @scene.pbRefresh + pbDisplay(_INTL("Threw away {1} {2}.", qty, itemname)) + end + @scene.pbEndScene + end +end + + + #=============================================================================== # Common UI functions used in both the Bag and item storage screens. # Displays messages and allows the user to choose a number/command. @@ -282,10 +371,10 @@ module UIHelper helpwindow.letterbyletter = false curnumber = initnum ret = 0 - numwindow = Window_UnformattedTextPokemon.new("x000") + numwindow = Window_UnformattedTextPokemon.new("×000") numwindow.viewport = helpwindow.viewport numwindow.letterbyletter = false - numwindow.text = _ISPRINTF("x{1:03d}", curnumber) + numwindow.text = _ISPRINTF("×{1:03d}", curnumber) numwindow.resizeToFit(numwindow.text, Graphics.width) pbBottomRight(numwindow) helpwindow.resizeHeightToFit(helpwindow.text, Graphics.width - numwindow.width) @@ -309,28 +398,28 @@ module UIHelper curnumber += 1 curnumber = 1 if curnumber > maximum if curnumber != oldnumber - numwindow.text = _ISPRINTF("x{1:03d}", curnumber) + numwindow.text = _ISPRINTF("×{1:03d}", curnumber) pbPlayCursorSE end elsif Input.repeat?(Input::DOWN) curnumber -= 1 curnumber = maximum if curnumber < 1 if curnumber != oldnumber - numwindow.text = _ISPRINTF("x{1:03d}", curnumber) + numwindow.text = _ISPRINTF("×{1:03d}", curnumber) pbPlayCursorSE end elsif Input.repeat?(Input::LEFT) curnumber -= 10 curnumber = 1 if curnumber < 1 if curnumber != oldnumber - numwindow.text = _ISPRINTF("x{1:03d}", curnumber) + numwindow.text = _ISPRINTF("×{1:03d}", curnumber) pbPlayCursorSE end elsif Input.repeat?(Input::RIGHT) curnumber += 10 curnumber = maximum if curnumber > maximum if curnumber != oldnumber - numwindow.text = _ISPRINTF("x{1:03d}", curnumber) + numwindow.text = _ISPRINTF("×{1:03d}", curnumber) pbPlayCursorSE end end diff --git a/Data/Scripts/016_UI/019_UI_PC.rb b/Data/Scripts/016_UI/019_UI_PC.rb index 6bba84766..4ae74457a 100644 --- a/Data/Scripts/016_UI/019_UI_PC.rb +++ b/Data/Scripts/016_UI/019_UI_PC.rb @@ -15,34 +15,50 @@ def pbPCItemStorage _INTL("Go back to the previous menu.")], -1, command) case command when 0 # Withdraw Item - if !$PokemonGlobal.pcItemStorage - $PokemonGlobal.pcItemStorage = PCItemStorage.new - end + $PokemonGlobal.pcItemStorage ||= PCItemStorage.new if $PokemonGlobal.pcItemStorage.empty? pbMessage(_INTL("There are no items.")) else pbFadeOutIn do scene = WithdrawItemScene.new - screen = PokemonBagScreen.new(scene, $bag) + screen = ItemStorageScreen.new(scene, $bag) screen.pbWithdrawItemScreen end end when 1 # Deposit Item + $PokemonGlobal.pcItemStorage ||= PCItemStorage.new + item_storage = $PokemonGlobal.pcItemStorage pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - screen.pbDepositItemScreen + bag_screen = UI::Bag.new($bag, mode: :choose_item) + given_item = bag_screen.choose_item do |item| + item_data = GameData::Item.get(item) + qty = $bag.quantity(item) + if qty > 1 && !item_data.is_important? + qty = bag_screen.choose_number(_INTL("How many do you want to deposit?"), qty) + end + if qty > 0 + if item_storage.can_add?(item, qty) + raise "Can't delete items from Bag" if !$bag.remove(item, qty) + raise "Can't deposit items to storage" if !item_storage.add(item, qty) + bag_screen.refresh + disp_qty = (item_data.is_important?) ? 1 : qty + item_name = (disp_qty > 1) ? item_data.portion_name_plural : item_data.portion_name + bag_screen.show_message(_INTL("Deposited {1} {2}.", disp_qty, item_name)) + else + bag_screen.show_message(_INTL("There's no room to store items.")) + end + end + next false + end end when 2 # Toss Item - if !$PokemonGlobal.pcItemStorage - $PokemonGlobal.pcItemStorage = PCItemStorage.new - end + $PokemonGlobal.pcItemStorage ||= PCItemStorage.new if $PokemonGlobal.pcItemStorage.empty? pbMessage(_INTL("There are no items.")) else pbFadeOutIn do scene = TossItemScene.new - screen = PokemonBagScreen.new(scene, $bag) + screen = ItemStorageScreen.new(scene, $bag) screen.pbTossItemScreen end end diff --git a/Data/Scripts/016_UI/020_UI_PokeMart.rb b/Data/Scripts/016_UI/020_UI_PokeMart.rb index c918a9613..b8fd543b9 100644 --- a/Data/Scripts/016_UI/020_UI_PokeMart.rb +++ b/Data/Scripts/016_UI/020_UI_PokeMart.rb @@ -27,12 +27,7 @@ class PokemonMartAdapter end def getDisplayName(item) - item_name = GameData::Item.get(item).name - if GameData::Item.get(item).is_machine? - machine = GameData::Item.get(item).move - item_name = _INTL("{1} {2}", item_name, GameData::Move.get(machine).name) - end - return item_name + return GameData::Item.get(item).display_name end def getDisplayNamePlural(item) @@ -162,7 +157,7 @@ class SellAdapter def getDisplayPrice(item) if @adapter.showQuantity?(item) - return sprintf("x%d", @adapter.getQuantity(item)) + return sprintf("×%d", @adapter.getQuantity(item)) else return "" end @@ -309,6 +304,10 @@ class PokemonMart_Scene end def pbStartSellScene2(bag, adapter) + # TODO: Don't have a subscene. Make a new BagVisuals class for choosing an + # item to sell, and open that. It can inherit from class + # UI::BagVisuals and add the money window (that may be all that needs + # adding). @subscene = PokemonBag_Scene.new @adapter = adapter @viewport2 = Viewport.new(0, 0, Graphics.width, Graphics.height) @@ -487,7 +486,7 @@ class PokemonMart_Scene numwindow.height = 64 numwindow.baseColor = Color.new(88, 88, 80) numwindow.shadowColor = Color.new(168, 184, 184) - numwindow.text = _INTL("x{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) pbBottomRight(numwindow) numwindow.y -= helpwindow.height loop do @@ -500,28 +499,28 @@ class PokemonMart_Scene curnumber -= 10 curnumber = 1 if curnumber < 1 if curnumber != oldnumber - numwindow.text = _INTL("x{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) pbPlayCursorSE end elsif Input.repeat?(Input::RIGHT) curnumber += 10 curnumber = maximum if curnumber > maximum if curnumber != oldnumber - numwindow.text = _INTL("x{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) pbPlayCursorSE end elsif Input.repeat?(Input::UP) curnumber += 1 curnumber = 1 if curnumber > maximum if curnumber != oldnumber - numwindow.text = _INTL("x{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) pbPlayCursorSE end elsif Input.repeat?(Input::DOWN) curnumber -= 1 curnumber = maximum if curnumber < 1 if curnumber != oldnumber - numwindow.text = _INTL("x{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}$ {2}", curnumber, (curnumber * itemprice).to_s_formatted) pbPlayCursorSE end elsif Input.trigger?(Input::USE) diff --git a/Data/Scripts/016_UI/021_UI_BattlePointShop.rb b/Data/Scripts/016_UI/021_UI_BattlePointShop.rb index fa744787a..c82763f66 100644 --- a/Data/Scripts/016_UI/021_UI_BattlePointShop.rb +++ b/Data/Scripts/016_UI/021_UI_BattlePointShop.rb @@ -343,7 +343,7 @@ class BattlePointShop_Scene numwindow.height = 64 numwindow.baseColor = Color.new(88, 88, 80) numwindow.shadowColor = Color.new(168, 184, 184) - numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) pbBottomRight(numwindow) numwindow.y -= helpwindow.height loop do @@ -356,28 +356,28 @@ class BattlePointShop_Scene curnumber -= 10 curnumber = 1 if curnumber < 1 if curnumber != oldnumber - numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) pbPlayCursorSE end elsif Input.repeat?(Input::RIGHT) curnumber += 10 curnumber = maximum if curnumber > maximum if curnumber != oldnumber - numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) pbPlayCursorSE end elsif Input.repeat?(Input::UP) curnumber += 1 curnumber = 1 if curnumber > maximum if curnumber != oldnumber - numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) pbPlayCursorSE end elsif Input.repeat?(Input::DOWN) curnumber -= 1 curnumber = maximum if curnumber < 1 if curnumber != oldnumber - numwindow.text = _INTL("x{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) + numwindow.text = _INTL("×{1}{2} BP", curnumber, (curnumber * itemprice).to_s_formatted) pbPlayCursorSE end elsif Input.trigger?(Input::USE) diff --git a/Data/Scripts/016b_UI redesign/000_UI_base.rb b/Data/Scripts/016b_UI redesign/000_UI_base.rb index cdb3b9d17..aadb808f7 100644 --- a/Data/Scripts/016b_UI redesign/000_UI_base.rb +++ b/Data/Scripts/016b_UI redesign/000_UI_base.rb @@ -315,6 +315,12 @@ module UI #--------------------------------------------------------------------------- + def index + return 0 + end + + #--------------------------------------------------------------------------- + def show_message(text) @sprites[:speech_box].visible = true @sprites[:speech_box].text = text @@ -451,8 +457,16 @@ module UI 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 } + def choose_number(help_text, maximum, init_value = 1) + if maximum.is_a?(ChooseNumberParams) + return pbMessageChooseNumber(help_text, maximum) { update_visuals } + end + return UIHelper.pbChooseNumber(@sprites[:speech_box], help_text, maximum, init_value) { update_visuals } + end + + #--------------------------------------------------------------------------- + + def refresh_on_index_changed(old_index) end #--------------------------------------------------------------------------- @@ -471,8 +485,12 @@ module UI loop do Graphics.update Input.update + old_index = index update_visuals + refresh_on_index_changed(old_index) if index != old_index + old_index = index ret = update_input + refresh_on_index_changed(old_index) if index != old_index break if ret end return ret @@ -483,8 +501,8 @@ module UI # The logic class. #============================================================================= class BaseScreen - attr_reader :visuals - attr_reader :result + attr_reader :visuals + attr_accessor :result def initialize @disposed = false @@ -515,6 +533,16 @@ module UI #----------------------------------------------------------------------------- + def sprites + return @visuals.sprites + end + + def index + return @visuals.index + end + + #----------------------------------------------------------------------------- + def show_message(text) @visuals.show_message(text) end @@ -546,8 +574,8 @@ module UI return show_choice(commands) end - def choose_number(help_text, maximum, init_num = 1) - return @visuals.choose_number(help_text, maximum, init_num) + def choose_number(help_text, maximum, init_value = 1) + return @visuals.choose_number(help_text, maximum, init_value) end alias pbChooseNumber choose_number @@ -597,7 +625,7 @@ module UI return nil if action_hash[:condition] && !action_hash[:condition].call(self) if action_hash[:menu] choice = show_choice_from_menu_handler(action_hash[:menu], action_hash[:menu_message]&.call(self)) - perform_action(choice) if choice + return perform_action(choice) if choice elsif action_hash[:effect] return perform_action_effect(action_hash) end diff --git a/Data/Scripts/016b_UI redesign/001_UI_PauseMenu.rb b/Data/Scripts/016b_UI redesign/001_UI_PauseMenu.rb index 3c5522704..0968012ab 100644 --- a/Data/Scripts/016b_UI redesign/001_UI_PauseMenu.rb +++ b/Data/Scripts/016b_UI redesign/001_UI_PauseMenu.rb @@ -221,9 +221,9 @@ MenuHandlers.add(:pause_menu, :bag, { pbPlayDecisionSE item = nil pbFadeOutIn do - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - item = screen.pbStartScreen + bag_screen = UI::Bag.new($bag) + bag_screen.main + item = bag_screen.result (item) ? menu.silent_end_screen : menu.refresh end next false if !item @@ -267,7 +267,7 @@ MenuHandlers.add(:pause_menu, :town_map, { }) MenuHandlers.add(:pause_menu, :trainer_card, { - "name" => proc { next $player.name }, + "name" => proc { |menu| next $player.name }, "order" => 50, "effect" => proc { |menu| pbPlayDecisionSE diff --git a/Data/Scripts/016b_UI redesign/005_UI_Party.rb b/Data/Scripts/016b_UI redesign/005_UI_Party.rb index 801834b63..4e5bd48c8 100644 --- a/Data/Scripts/016b_UI redesign/005_UI_Party.rb +++ b/Data/Scripts/016b_UI redesign/005_UI_Party.rb @@ -326,8 +326,8 @@ end # #=============================================================================== class UI::PartyVisuals < UI::BaseVisuals - attr_reader :index attr_reader :sprites + attr_reader :index attr_reader :sub_mode GRAPHICS_FOLDER = "Party/" # Subfolder in Graphics/UI @@ -783,10 +783,6 @@ class UI::Party < UI::BaseScreen #----------------------------------------------------------------------------- - def index - return @visuals.index - end - def set_index(new_index) @visuals.set_index(new_index) end @@ -795,10 +791,6 @@ class UI::Party < UI::BaseScreen return (index < @party.length) ? @party[index] : nil end - def sprites - return @visuals.sprites - end - def can_access_storage? return @visuals.can_access_storage? end @@ -1194,18 +1186,18 @@ UIActionHandlers.add(UI::Party::SCREEN_ID, :item_use, { 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) + bag_screen = UI::Bag.new($bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |itm| + item_data = GameData::Item.get(itm) 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.hyper_mode && !item_data&.is_scent? + if item_data.is_machine? + move = item_data.move next false if pkmn.hasMove?(move) || !pkmn.compatible_with_move?(move) end next true }) + used_item = bag_screen.choose_item end if used_item pbUseItemOnPokemon(used_item, pkmn, screen) @@ -1219,9 +1211,9 @@ UIActionHandlers.add(UI::Party::SCREEN_ID, :item_give, { 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? }) + bag_screen = UI::Bag.new($bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |itm| GameData::Item.get(itm).can_hold? }) + given_item = bag_screen.choose_item end if given_item pbGiveItemToPokemon(given_item, pkmn, screen, screen.index) @@ -1360,6 +1352,31 @@ UIActionHandlers.add(UI::Party::SCREEN_ID, :use_SOFTBOILED, { #=============================================================================== # Menu options for choice menus that exist in the party screen. #=============================================================================== +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 +}) + +#------------------------------------------------------------------------------- + MenuHandlers.add(:party_screen_interact, :summary, { "name" => _INTL("Summary"), "order" => 10 @@ -1450,31 +1467,6 @@ MenuHandlers.add(:party_screen_interact, :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. #=============================================================================== diff --git a/Data/Scripts/016b_UI redesign/006_UI_Summary.rb b/Data/Scripts/016b_UI redesign/006_UI_Summary.rb index e841968fb..fa5566f38 100644 --- a/Data/Scripts/016b_UI redesign/006_UI_Summary.rb +++ b/Data/Scripts/016b_UI redesign/006_UI_Summary.rb @@ -1489,10 +1489,10 @@ UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :interact_menu, { UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :give_item, { :effect => proc { |screen| item = nil - pbFadeOutIn do - bag_scene = PokemonBag_Scene.new - bag_screen = PokemonBagScreen.new(bag_scene, $bag) - item = bag_screen.pbChooseItemScreen(proc { |itm| GameData::Item.get(itm).can_hold? }) + pbFadeOutInWithUpdate(screen.sprites) do + bag_screen = UI::Bag.new($bag, mode: :choose_item) + bag_screen.set_filter_proc(proc { |itm| GameData::Item.get(itm).can_hold? }) + item = bag_screen.choose_item end screen.refresh if pbGiveItemToPokemon(item, screen.pokemon, screen, screen.party_index) } @@ -1507,7 +1507,7 @@ UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :take_item, { UIActionHandlers.add(UI::PokemonSummary::SCREEN_ID, :pokedex, { :effect => proc { |screen| $player.pokedex.register_last_seen(screen.pokemon) - pbFadeOutIn do + pbFadeOutInWithUpdate(screen.sprites) do dex_scene = PokemonPokedexInfo_Scene.new dex_screen = PokemonPokedexInfoScreen.new(dex_scene) dex_screen.pbStartSceneSingle(screen.pokemon.species) diff --git a/Data/Scripts/016b_UI redesign/007_UI_Bag.rb b/Data/Scripts/016b_UI redesign/007_UI_Bag.rb new file mode 100644 index 000000000..49fce1966 --- /dev/null +++ b/Data/Scripts/016b_UI redesign/007_UI_Bag.rb @@ -0,0 +1,883 @@ +#=============================================================================== +# +#=============================================================================== +class UI::BagVisualsList < Window_DrawableCommand + attr_accessor :sorting + + def initialize(bag, x, y, width, height, viewport) + @bag = bag + @sorting = false + super(x, y, width, height, viewport) + @selarrow = AnimatedBitmap.new(bag_folder + "cursor") + @swaparrow = AnimatedBitmap.new(bag_folder + "cursor_swap") + self.windowskin = nil + end + + def dispose + @swaparrow.dispose + super + end + + #----------------------------------------------------------------------------- + + def page_row_max; return UI::BagVisuals::ITEMS_VISIBLE; end + def page_item_max; return page_row_max; end + + def itemCount + return (@items&.length || 0) + 1 # The extra 1 is the Close Bag option + end + + def bag_folder + return UI::BagVisuals::UI_FOLDER + UI::BagVisuals::GRAPHICS_FOLDER + end + + def items=(value) + @items = value + refresh + end + + def item_id + return (@items[self.index]) ? @items[self.index][0] : nil + end + + #----------------------------------------------------------------------------- + + # Custom method that allows for an extra option to be displayed above and + # below the main visible list. + def itemRect(item) + if item < 0 || item >= @item_max || item < self.top_item - 1 || + item > self.top_item + self.page_item_max + return Rect.new(0, 0, 0, 0) + end + cursor_width = (self.width - self.borderX - ((@column_max - 1) * @column_spacing)) / @column_max + x = item % @column_max * (cursor_width + @column_spacing) + y = (item / @column_max * @row_height) - @virtualOy + return Rect.new(x, y, cursor_width, @row_height) + end + + #----------------------------------------------------------------------------- + + # This draws all the visible options first, and then draws the cursor. It also + # draws an additional option above the main visible ones. + def refresh + @item_max = itemCount + update_cursor_rect + dwidth = self.width - self.borderX + dheight = self.height - self.borderY + self.contents = pbDoEnsureBitmap(self.contents, dwidth, dheight) + self.contents.clear + @item_max.times do |i| + next if i < self.top_item - 1 || i > self.top_item + self.page_item_max + drawItem(i, @item_max, itemRect(i)) + end + drawCursor(self.index, itemRect(self.index)) + end + + def switching_base_color=(value) + @switching_base_color = value + end + + def switching_shadow_color=(value) + @switching_shadow_color = value + end + + def drawItem(index, _count, rect) + textpos = [] + rect = Rect.new(rect.x + 16, rect.y + 16, rect.width - 16, rect.height) + if index == self.itemCount - 1 + textpos.push([_INTL("CLOSE BAG"), rect.x, rect.y + 2, :left, self.baseColor, self.shadowColor]) + else + this_item_id = @items[index][0] + item_data = GameData::Item.get(this_item_id) + baseColor = self.baseColor + shadowColor = self.shadowColor + if @sorting && index == self.index + baseColor = @switching_base_color || self.baseColor + shadowColor = @switching_shadow_color || self.shadowColor + end + # Draw item name + textpos.push( + [item_data.display_name, rect.x, rect.y + 2, :left, baseColor, shadowColor] + ) + # Draw register icon + showing_register_icon = false + if item_data.is_important? + if @bag.registered?(this_item_id) + pbDrawImagePositions( + self.contents, + [[bag_folder + _INTL("icon_register"), rect.x + rect.width - 72, rect.y + 8, 0, 0, -1, 24]] + ) + showing_register_icon = true + elsif pbCanRegisterItem?(this_item_id) + pbDrawImagePositions( + self.contents, + [[bag_folder + _INTL("icon_register"), rect.x + rect.width - 72, rect.y + 8, 0, 24, -1, 24]] + ) + showing_register_icon = true + end + end + # Draw quantity + if item_data.show_quantity? && !showing_register_icon + qty = @items[index][1] + qtytext = _ISPRINTF("×{1: 3d}", qty) + xQty = rect.x + rect.width - self.contents.text_size(qtytext).width - 16 + textpos.push([qtytext, xQty, rect.y + 2, :left, baseColor, shadowColor]) + end + end + pbDrawTextPositions(self.contents, textpos) + end + + def drawCursor(index, rect) + if self.index == index + bmp = (@sorting) ? @swaparrow.bitmap : @selarrow.bitmap + pbCopyBitmap(self.contents, bmp, rect.x, rect.y + 2) + end + end + + #----------------------------------------------------------------------------- + + def update + super + @uparrow.visible = false + @downarrow.visible = false + end +end + +#=============================================================================== +# +#=============================================================================== +class UI::BagVisuals < UI::BaseVisuals + attr_reader :sprites + + GRAPHICS_FOLDER = "Bag/" # Subfolder in Graphics/UI + TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay] + :default => [Color.new(248, 248, 248), Color.new(104, 104, 104)], # Base and shadow colour +# :white => [Color.new(248, 248, 248), Color.new(104, 104, 104)], # Summary screen's white +# :black => [Color.new(64, 64, 64), Color.new(176, 176, 176)] # Summary screen's black + :white => [Color.new(248, 248, 248), Color.new(0, 0, 0)], + :black => [Color.new(88, 88, 80), Color.new(168, 184, 184)], + :switching => [Color.new(224, 0, 0), Color.new(248, 144, 144)] + } + ITEMS_VISIBLE = 7 + + def initialize(bag, mode = :normal) + @bag = bag + @mode = mode + @pocket = @bag.last_viewed_pocket + super() + end + + def initialize_bitmaps + @bitmaps[:slider] = AnimatedBitmap.new(graphics_folder + "icon_slider") + @bitmaps[:pocket_icons] = AnimatedBitmap.new(graphics_folder + "icon_pocket") + end + + def initialize_overlay + super + add_overlay(:slider_overlay, 36, 470 + 38 + 38) + @sprites[:slider_overlay].x = 470 + @sprites[:slider_overlay].y = 54 - 38 + end + + def initialize_sprites + initialize_pocket_sprites + initialize_item_list + initialize_item_sprites + end + + def initialize_pocket_sprites + @sprites[:bag] = IconSprite.new(30, 20, @viewport) + @sprites[:pocket_icons] = BitmapSprite.new(186, 32, @viewport) + @sprites[:pocket_icons].x = 0 + @sprites[:pocket_icons].y = 224 + # TODO: I won't need these two animated arrows once new ones are put next to + # the pocket icons. + # Arrow to indicate more ribbons are above the ones visible when navigating ribbons + add_animated_arrow(:left_arrow, -4, 76, :left) + @sprites[:left_arrow].z = 1700 + # TODO: Set visibility. +# @sprites[:left_arrow].visible = (!@choosing || numfilledpockets > 1) + # Arrow to indicate more ribbons are below the ones visible when navigating ribbons + add_animated_arrow(:right_arrow, 150, 76, :right) + @sprites[:right_arrow].z = 1700 + # TODO: Set visibility. +# @sprites[:right_arrow].visible = (!@choosing || numfilledpockets > 1) + end + + def initialize_item_list + @sprites[:item_list] = UI::BagVisualsList.new(@bag, 168, -8, 314, 40 + 32 + (ITEMS_VISIBLE * 32), @viewport) + @sprites[:item_list].baseColor = TEXT_COLOR_THEMES[:black][0] + @sprites[:item_list].shadowColor = TEXT_COLOR_THEMES[:black][1] + @sprites[:item_list].switching_base_color = TEXT_COLOR_THEMES[:switching][0] + @sprites[:item_list].switching_shadow_color = TEXT_COLOR_THEMES[:switching][1] + @sprites[:item_list].items = @bag.pockets[@pocket] + @sprites[:item_list].index = @bag.last_viewed_index(@pocket) + @sprites[:item_list].active = false + end + + def initialize_item_sprites + # Selected item's icon + @sprites[:item_icon] = ItemIconSprite.new(48, Graphics.height - 48, nil, @viewport) + # Selected item's description text box + @sprites[:item_description] = Window_UnformattedTextPokemon.newWithSize( + "", 72, 272, Graphics.width - 96, 128, @viewport + ) + @sprites[:item_description].baseColor = TEXT_COLOR_THEMES[:white][0] + @sprites[:item_description].shadowColor = TEXT_COLOR_THEMES[:white][1] + @sprites[:item_description].visible = true + @sprites[:item_description].windowskin = nil + end + + #----------------------------------------------------------------------------- + + def background_filename + return gendered_filename(self.class::BACKGROUND_FILENAME + "_" + @pocket.to_s) + end + + def index + return @sprites[:item_list].index + end + + def item + return @sprites[:item_list].item_id + end + + #----------------------------------------------------------------------------- + + def set_filter_proc(filter_proc) + @filter_proc = filter_proc + # Create filtered pocket lists + @filtered_list = [] + (1...@bag.pockets.length).each do |pckt| + @filtered_list[pckt] = [] + @bag.pockets[pckt].length.times do |j| + @filtered_list[pckt].push(@bag.pockets[pckt][j]) if @filter_proc.call(@bag.pockets[pckt][j][0]) + end + end + # Ensure current pocket is one that isn't empty + new_pocket = 1 + if @mode == :choose_item_in_battle && !@filtered_list[@bag.last_viewed_pocket].empty? + new_pocket = @bag.last_viewed_pocket + end + num_pockets = PokemonBag.pocket_count + num_pockets.times do |i| + next_pocket = new_pocket + i + next_pocket -= num_pockets if next_pocket > num_pockets + next if @filtered_list[next_pocket].empty? + new_pocket = next_pocket + break + end + new_pocket = 1 if @filtered_list[new_pocket].empty? # In case all pockets are empty + # Set the new pocket + set_pocket(new_pocket) + @sprites[:item_list].index = 0 + end + + def set_pocket(new_pocket) + @pocket = new_pocket + @bag.last_viewed_pocket = @pocket + if @filtered_list + @sprites[:item_list].items = @filtered_list[@pocket] + else + @sprites[:item_list].items = @bag.pockets[@pocket] + end + @sprites[:item_list].index = @bag.last_viewed_index(@pocket) + refresh + end + + def go_to_next_pocket + new_pocket = @pocket + loop do + new_pocket = (new_pocket >= PokemonBag.pocket_count) ? 1 : new_pocket + 1 + break if ![:choose_item, :choose_item_in_battle].include?(@mode) + break if new_pocket == @pocket # Bag is empty somehow + if @filtered_list + break if @filtered_list[new_pocket].length > 0 + else + break if @bag.pockets[new_pocket].length > 0 + end + end + return if new_pocket == @pocket + pbPlayCursorSE + set_pocket(new_pocket) + end + + def go_to_previous_pocket + new_pocket = @pocket + loop do + new_pocket = (new_pocket <= 1) ? PokemonBag.pocket_count : new_pocket - 1 + break if ![:choose_item, :choose_item_in_battle].include?(@mode) + break if new_pocket == @pocket # Bag is empty somehow + if @filtered_list + break if @filtered_list[new_pocket].length > 0 + else + break if @bag.pockets[new_pocket].length > 0 + end + end + return if new_pocket == @pocket + pbPlayCursorSE + set_pocket(new_pocket) + end + + def switch_index + return @switch_index || -1 + end + + def can_switch? + return false if @mode != :normal || @filtered_list + return false if @bag.pockets[@pocket].length <= 1 + return false if index >= @bag.pockets[@pocket].length + return false if Settings::BAG_POCKET_AUTO_SORT[@pocket - 1] + return true + end + + def switching? + return switch_index >= 0 + end + + def start_switching(sw_index) + @switch_index = sw_index + @sprites[:item_list].sorting = true + refresh_item_list + end + + def end_switching + @switch_index = -1 + @sprites[:item_list].sorting = false + refresh_item_list + end + + def cancel_switching + this_pocket = @bag.pockets[@pocket] + this_pocket.insert(@switch_index, this_pocket.delete_at(@sprites[:item_list].index)) + @sprites[:item_list].items = this_pocket + @sprites[:item_list].index = @switch_index + end_switching + refresh + end + + #----------------------------------------------------------------------------- + + def refresh + super + refresh_background + refresh_pocket_icons + refresh_pocket + refresh_item_list + refresh_slider + refresh_selected_item + end + + def refresh_background + @sprites[:background].setBitmap(graphics_folder + background_filename) + end + + def refresh_pocket_icons + @sprites[:pocket_icons].bitmap.clear + # Draw the pocket icons + if [:choose_item, :choose_item_in_battle].include?(@mode) && @filtered_list + (1...@bag.pockets.length).each do |i| + next if @filtered_list[i].length > 0 + draw_image(@bitmaps[:pocket_icons], 6 + ((i - 1) * 22), 6, + (i - 1) * 20, 28, 20, 20, overlay: :pocket_icons) + end + end + draw_image(@bitmaps[:pocket_icons], 2 + ((@pocket - 1) * 22), 2, + (@pocket - 1) * 28, 0, 28, 28, overlay: :pocket_icons) + # TODO: Draw the left and right arrows, if @mode != :choose_item || + # @filtered_list has 2+ non-empty pockets. + end + + def refresh_pocket + # Draw pocket's name + draw_text(PokemonBag.pocket_names[@pocket - 1], 94, 186, align: :center, theme: :black) + # Set the bag sprite + bag_sprite_filename = graphics_folder + gendered_filename(sprintf("bag_%d", @pocket)) + @sprites[:bag].setBitmap(bag_sprite_filename) + end + + def refresh_item_list + @sprites[:item_list].refresh + end + + # TODO: Probably turn this method into a helper method. Put the defined values + # in constants so that initializing the slider overlay can use them to + # automatically determine its size. + def refresh_slider + @sprites[:slider_overlay].bitmap.clear + # Define useful values + slider_rects = { + :up_arrow => [0, 0, 36, 38], + :down_arrow => [0, 38, 36, 38], + :box_top => [36, 0, 36, 4], + :box_middle => [36, 4, 36, 16], + :box_bottom => [36, 20, 36, 18] + } + slider_x = 0 + slider_y = slider_rects[:up_arrow][3] + slider_height = 174 + min_box_height = slider_rects[:box_top][3] + slider_rects[:box_middle][3] + slider_rects[:box_bottom][3] + # Draw things + show_slider = false + # Draw slider up arrow + if @sprites[:item_list].top_row > 0 + draw_image(@bitmaps[:slider], slider_x, slider_y - slider_rects[:up_arrow][3], + *slider_rects[:up_arrow], overlay: :slider_overlay) + show_slider = true + end + # Draw slider down arrow + if @sprites[:item_list].top_item + @sprites[:item_list].page_item_max < @sprites[:item_list].itemCount + draw_image(@bitmaps[:slider], slider_x, slider_y + slider_height, + *slider_rects[:down_arrow], overlay: :slider_overlay) + show_slider = true + end + # Draw slider box + if show_slider + box_height = (slider_height * @sprites[:item_list].page_row_max / @sprites[:item_list].row_max).floor + box_height += [(slider_height - box_height) / 2, slider_height / 6].min # Make it bigger than expected + box_height = [box_height.floor, min_box_height].max + box_y = slider_rects[:up_arrow][3] + box_y += ((slider_height - box_height) * @sprites[:item_list].top_row / (@sprites[:item_list].row_max - @sprites[:item_list].page_row_max)).floor + # Draw slider box top + draw_image(@bitmaps[:slider], slider_x, box_y, + *slider_rects[:box_top], overlay: :slider_overlay) + # Draw slider box middle + middle_height = box_height - slider_rects[:box_top][3] - slider_rects[:box_bottom][3] + iterations = (middle_height / slider_rects[:box_middle][3].to_f).ceil + iterations.times do |i| + segment_y = box_y + slider_rects[:box_top][3] + (i * slider_rects[:box_middle][3]) + box_middle_rect = slider_rects[:box_middle].clone + if i == iterations - 1 # Last part + box_middle_rect[3] = middle_height - (i * slider_rects[:box_middle][3]) + end + draw_image(@bitmaps[:slider], slider_x, segment_y, + *box_middle_rect, overlay: :slider_overlay) + end + # Draw slider box bottom + draw_image(@bitmaps[:slider], slider_x, box_y + box_height - slider_rects[:box_bottom][3], + *slider_rects[:box_bottom], overlay: :slider_overlay) + end + end + + def refresh_selected_item + selected_item = item + # Set the selected item's icon + @sprites[:item_icon].item = selected_item + # Set the selected item's description + if selected_item + @sprites[:item_description].text = GameData::Item.get(selected_item).description + else + @sprites[:item_description].text = _INTL("Close bag.") + end + end + + def refresh_on_index_changed(old_index) + if switching? + # Skip past "Cancel" + this_pocket = @bag.pockets[@pocket] + if index >= this_pocket.length + @sprites[:item_list].index = (old_index == this_pocket.length - 1) ? 0 : this_pocket.length - 1 + end + # Move the item being switched + this_pocket.insert(index, this_pocket.delete_at(old_index)) + @sprites[:item_list].items = this_pocket + end + @bag.set_last_viewed_index(@pocket, index) + refresh_slider + refresh_selected_item + end + + #----------------------------------------------------------------------------- + + def update_input + # Check for movement to a new pocket + if Input.repeat?(Input::LEFT) + go_to_previous_pocket if !switching? + elsif Input.repeat?(Input::RIGHT) + go_to_next_pocket if !switching? + 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_interaction(input) + case input + when Input::USE + if switching? + pbPlayDecisionSE + return :switch_item_end + end + if !item # "CLOSE BAG" + pbPlayCloseMenuSE + return :quit + end + pbPlayDecisionSE + return :interact_menu + when Input::ACTION + if switching? + pbPlayDecisionSE + return :switch_item_end + elsif can_switch? + pbPlayDecisionSE + return :switch_item_start + end + when Input::SPECIAL + # TODO: May be unused. Originally toggled registering an item, but this + # has been disabled for ages. + when Input::BACK + if switching? + pbPlayCancelSE + return :switch_item_cancel + end + pbPlayCloseMenuSE + return :quit + end + return nil + end + + def navigate + @sprites[:item_list].active = true + ret = super + @sprites[:item_list].active = false + return ret + end + + #----------------------------------------------------------------------------- + + def update_input_choose_item + # Check for movement to a new pocket + if Input.repeat?(Input::LEFT) + go_to_previous_pocket + elsif Input.repeat?(Input::RIGHT) + go_to_next_pocket + end + # Check for interaction + if Input.trigger?(Input::USE) + return update_interaction_choose_item(Input::USE) + elsif Input.trigger?(Input::BACK) + return update_interaction_choose_item(Input::BACK) + end + return nil + end + + def update_interaction_choose_item(input) + case input + when Input::USE + if !item # "CLOSE BAG" + pbPlayCloseMenuSE + return :quit + end + pbPlayDecisionSE + return :chosen + when Input::BACK + pbPlayCloseMenuSE + return :quit + end + return nil + end + + def navigate_choose_item + @sprites[:item_list].active = true + ret = nil + loop do + Graphics.update + Input.update + old_index = index + update_visuals + refresh_on_index_changed(old_index) if index != old_index + ret = update_input_choose_item + break if ret + end + @sprites[:item_list].active = false + return ret + end +end + +#=============================================================================== +# +#=============================================================================== +class UI::Bag < UI::BaseScreen + attr_reader :bag + + SCREEN_ID = :bag_screen + + def initialize(bag, mode: :normal) + @bag = bag + @mode = mode + super() + end + + def initialize_visuals + @visuals = UI::BagVisuals.new(@bag, @mode) + end + + #----------------------------------------------------------------------------- + + def item + return nil if @visuals.item.nil? + return GameData::Item.get(@visuals.item) + end + + def set_filter_proc(filter_proc) + @visuals.set_filter_proc(filter_proc) + 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 cancel_switching + @visuals.cancel_switching + end + + def switch_items(index1, index2) + @visuals.end_switching + end + + #----------------------------------------------------------------------------- + + def choose_item + start_screen + loop do + on_start_main_loop + chosen_item = choose_item_core + if chosen_item && block_given? + next if !yield chosen_item + end + @result = chosen_item + break + end + end_screen + return @result + end + + def choose_item_core + command = @visuals.navigate_choose_item + return item.id if command == :chosen + return nil + end +end + +#=============================================================================== +# +#=============================================================================== +# Shows a choice menu using the MenuHandlers options below. +UIActionHandlers.add(UI::Bag::SCREEN_ID, :screen_menu, { + :menu => :bag_screen_menu, + :menu_message => proc { |screen| _INTL("Choose an option.") } +}) + +#------------------------------------------------------------------------------- + +# Shows a choice menu using the MenuHandlers options below. +UIActionHandlers.add(UI::Bag::SCREEN_ID, :interact_menu, { + :menu => :bag_screen_interact, + :menu_message => proc { |screen| _INTL("{1} is selected.", screen.item.name) } +}) + +UIActionHandlers.add(UI::Bag::SCREEN_ID, :read_mail, { + :effect => proc { |screen| + pbFadeOutInWithUpdate(screen.sprites) do + pbDisplayMail(Mail.new(screen.item.id, "", "")) + end + } +}) + +UIActionHandlers.add(UI::Bag::SCREEN_ID, :use, { + :returns_value => true, + :effect => proc { |screen| + item = screen.item.id + ret = pbUseItem(screen.bag, item, screen) + # ret: 0=Item wasn't used; 1=Item used; 2=Close Bag to use in field + if ret == 2 + screen.result = item + next :quit + end + screen.refresh + next nil + } +}) + +UIActionHandlers.add(UI::Bag::SCREEN_ID, :give, { + :effect => proc { |screen| + if $player.pokemon_count == 0 + screen.show_message(_INTL("There is no Pokémon.")) + elsif screen.item.is_important? + screen.show_message(_INTL("The {1} can't be held.", screen.item.portion_name)) + else + pbFadeOutInWithUpdate(screen.sprites) do + party_screen = UI::Party.new($player.party, mode: :choose_pokemon) + party_screen.choose_pokemon do |pkmn, party_index| + pbGiveItemToPokemon(screen.item.id, party_screen.pokemon, party_screen, party_index) if party_index >= 0 + next true + end + screen.refresh + end + end + } +}) + +UIActionHandlers.add(UI::Bag::SCREEN_ID, :toss, { + :effect => proc { |screen| + qty = screen.bag.quantity(screen.item.id) + if qty > 1 + help_text = _INTL("Toss out how many {1}?", screen.item.portion_name_plural) + qty = screen.choose_number(help_text, qty) + end + if qty > 0 + item_name = (qty > 1) ? screen.item.portion_name_plural : screen.item.portion_name + if screen.show_confirm_message(_INTL("Is it OK to throw away {1} {2}?", qty, item_name)) + qty.times { screen.bag.remove(screen.item.id) } + screen.refresh + screen.show_message(_INTL("Threw away {1} {2}.", qty, item_name)) + end + end + } +}) + +# Handles both registering and unregistering the item. +UIActionHandlers.add(UI::Bag::SCREEN_ID, :register, { + :effect => proc { |screen| + if screen.bag.registered?(screen.item.id) + screen.bag.unregister(screen.item.id) + else + screen.bag.register(screen.item.id) + end + screen.refresh + } +}) + +UIActionHandlers.add(UI::Bag::SCREEN_ID, :debug, { + :effect => proc { |screen| + command = 0 + loop do + command = screen.show_choice_message( + _INTL("Do what with {1}?", screen.item.name), + [_INTL("Change quantity"), _INTL("Make Mystery Gift"), _INTL("Cancel")], command) + case command + when 0 # Change quantity + qty = screen.bag.quantity(screen.item.id) + item_name_plural = screen.item.name_plural + params = ChooseNumberParams.new + params.setRange(0, Settings::BAG_MAX_PER_SLOT) + params.setDefaultValue(qty) + new_qty = screen.choose_number( + _INTL("Choose new quantity of {1} (max. {2}).", item_name_plural, Settings::BAG_MAX_PER_SLOT), params + ) + if new_qty > qty + screen.bag.add(screen.item.id, new_qty - qty) + elsif new_qty < qty + screen.bag.remove(screen.item.id, qty - new_qty) + end + screen.refresh + break if new_qty == 0 + when 1 # Make Mystery Gift + pbCreateMysteryGift(1, screen.item.id) + else + break + end + end + } +}) + +#------------------------------------------------------------------------------- + +UIActionHandlers.add(UI::Bag::SCREEN_ID, :switch_item_start, { + :effect => proc { |screen| + screen.start_switching + } +}) + +UIActionHandlers.add(UI::Bag::SCREEN_ID, :switch_item_end, { + :effect => proc { |screen| + screen.switch_items(screen.switch_index, screen.index) + } +}) + +UIActionHandlers.add(UI::Bag::SCREEN_ID, :switch_item_cancel, { + :effect => proc { |screen| + screen.cancel_switching + } +}) + +#=============================================================================== +# Menu options for choice menus that exist in the party screen. +#=============================================================================== +MenuHandlers.add(:bag_screen_menu, :open_storage, { + "name" => _INTL("Access Pokémon Boxes"), + "order" => 10, +# "condition" => proc { |screen| next screen.can_access_storage? } +}) + +MenuHandlers.add(:bag_screen_menu, :cancel, { + "name" => _INTL("Cancel"), + "order" => 9999 +}) + +#------------------------------------------------------------------------------- + +MenuHandlers.add(:bag_screen_interact, :read_mail, { + "name" => _INTL("Read"), + "order" => 10, + "condition" => proc { |screen| next screen.item.is_mail? } +}) + +MenuHandlers.add(:bag_screen_interact, :use, { + "name" => proc { |screen| + next ItemHandlers.getUseText(screen.item.id) if ItemHandlers.hasUseText(screen.item.id) + next _INTL("Use") + }, + "order" => 20, + "condition" => proc { |screen| + next ItemHandlers.hasOutHandler(screen.item.id) || (screen.item.is_machine? && $player.party.length > 0) + } +}) + +MenuHandlers.add(:bag_screen_interact, :give, { + "name" => _INTL("Give"), + "order" => 30, + "condition" => proc { |screen| next $player.pokemon_party.length > 0 && screen.item.can_hold? } +}) + +MenuHandlers.add(:bag_screen_interact, :toss, { + "name" => _INTL("Toss"), + "order" => 40, + "condition" => proc { |screen| next !screen.item.is_important? || $DEBUG } +}) + +MenuHandlers.add(:bag_screen_interact, :register, { + "name" => proc { |screen| + next _INTL("Deselect") if $bag.registered?(screen.item.id) + next _INTL("Select") + }, + "order" => 50, + "condition" => proc { |screen| next pbCanRegisterItem?(screen.item.id) } +}) + +MenuHandlers.add(:bag_screen_interact, :debug, { + "name" => _INTL("Debug"), + "order" => 60, + "condition" => proc { |screen| next $DEBUG } +}) + +MenuHandlers.add(:bag_screen_interact, :cancel, { + "name" => _INTL("Cancel"), + "order" => 9999 +}) diff --git a/Data/Scripts/016_UI/007_UI_Bag.rb b/Data/Scripts/016c_UI_old/007_UI_old_Bag.rb similarity index 100% rename from Data/Scripts/016_UI/007_UI_Bag.rb rename to Data/Scripts/016c_UI_old/007_UI_old_Bag.rb