From 6d23d0101ab8bf2e785f6a9bc4b33b272d4ba528 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Mon, 3 Jan 2022 19:54:31 +0000 Subject: [PATCH] Added descriptions for Options screen options, tweaked appearance of Options screen, fixed SpriteWindow#back_opacity not applying to all parts of the window graphic --- .../004_SpriteWindow.rb | 4 +- Data/Scripts/016_UI/015_UI_Options.rb | 242 ++++++++++-------- 2 files changed, 133 insertions(+), 113 deletions(-) diff --git a/Data/Scripts/007_Objects and windows/004_SpriteWindow.rb b/Data/Scripts/007_Objects and windows/004_SpriteWindow.rb index ebb28c414..55eae493f 100644 --- a/Data/Scripts/007_Objects and windows/004_SpriteWindow.rb +++ b/Data/Scripts/007_Objects and windows/004_SpriteWindow.rb @@ -485,12 +485,12 @@ class SpriteWindow < Window @sprites["contents"].bitmap = @contents if haveskin 4.times do |i| - @sprites["corner#{i}"].opacity = @opacity + @sprites["corner#{i}"].opacity = backopac @sprites["corner#{i}"].tone = @tone @sprites["corner#{i}"].color = @color @sprites["corner#{i}"].visible = @visible @sprites["corner#{i}"].blend_type = @blend_type - @sprites["side#{i}"].opacity = @opacity + @sprites["side#{i}"].opacity = backopac @sprites["side#{i}"].tone = @tone @sprites["side#{i}"].color = @color @sprites["side#{i}"].blend_type = @blend_type diff --git a/Data/Scripts/016_UI/015_UI_Options.rb b/Data/Scripts/016_UI/015_UI_Options.rb index 742d0c102..9831bf5e3 100644 --- a/Data/Scripts/016_UI/015_UI_Options.rb +++ b/Data/Scripts/016_UI/015_UI_Options.rb @@ -38,11 +38,11 @@ module PropertyMixin attr_reader :name def get - (@getProc) ? @getProc.call : nil + return @get_proc&.call end def set(*args) - @setProc&.call(*args) + @set_proc&.call(*args) end end @@ -53,11 +53,11 @@ class EnumOption include PropertyMixin attr_reader :values - def initialize(name, values, getProc, setProc) - @name = name - @values = values.map { |val| _INTL(val) } - @getProc = getProc - @setProc = setProc + def initialize(name, values, get_proc, set_proc) + @name = name + @values = values.map { |val| _INTL(val) } + @get_proc = get_proc + @set_proc = set_proc end def next(current) @@ -78,35 +78,35 @@ end #=============================================================================== class NumberOption include PropertyMixin - attr_reader :optstart - attr_reader :optend + attr_reader :lowest_value + attr_reader :highest_value - def initialize(name, range, getProc, setProc) + def initialize(name, range, get_proc, set_proc) @name = name case range when Range - @optstart = range.begin - @optend = range.end + @lowest_value = range.begin + @highest_value = range.end when Array - @optstart = range[0] - @optend = range[1] + @lowest_value = range[0] + @highest_value = range[1] end - @getProc = getProc - @setProc = setProc + @get_proc = get_proc + @set_proc = set_proc end def next(current) - index = current + @optstart + index = current + @lowest_value index += 1 - index = @optstart if index > @optend - return index - @optstart + index = @lowest_value if index > @highest_value + return index - @lowest_value end def prev(current) - index = current + @optstart + index = current + @lowest_value index -= 1 - index = @optend if index < @optstart - return index - @optstart + index = @highest_value if index < @lowest_value + return index - @lowest_value end end @@ -115,30 +115,30 @@ end #=============================================================================== class SliderOption include PropertyMixin - attr_reader :optstart - attr_reader :optend + attr_reader :lowest_value + attr_reader :highest_value - def initialize(name, range, getProc, setProc) - @name = name - @optstart = range[0] - @optend = range[1] - @optinterval = range[2] - @getProc = getProc - @setProc = setProc + def initialize(name, range, get_proc, set_proc) + @name = name + @lowest_value = range[0] + @highest_value = range[1] + @interval = range[2] + @get_proc = get_proc + @set_proc = set_proc end def next(current) - index = current + @optstart - index += @optinterval - index = @optend if index > @optend - return index - @optstart + index = current + @lowest_value + index += @interval + index = @highest_value if index > @highest_value + return index - @lowest_value end def prev(current) - index = current + @optstart - index -= @optinterval - index = @optstart if index < @optstart - return index - @optstart + index = current + @lowest_value + index -= @interval + index = @lowest_value if index < @lowest_value + return index - @lowest_value end end @@ -146,33 +146,32 @@ end # Main options list #=============================================================================== class Window_PokemonOption < Window_DrawableCommand - attr_reader :mustUpdateOptions + attr_reader :value_changed + + SEL_NAME_BASE_COLOR = Color.new(192, 120, 0) + SEL_NAME_SHADOW_COLOR = Color.new(248, 176, 80) + SEL_VALUE_BASE_COLOR = Color.new(248, 48, 24) + SEL_VALUE_SHADOW_COLOR = Color.new(248, 136, 128) def initialize(options, x, y, width, height) @options = options - @nameBaseColor = Color.new(192, 120, 0) - @nameShadowColor = Color.new(248, 176, 80) - @selBaseColor = Color.new(248, 48, 24) - @selShadowColor = Color.new(248, 136, 128) - @optvalues = [] - @mustUpdateOptions = false - @options.length.times do |i| - @optvalues[i] = 0 - end + @values = [] + @options.length.times { |i| @values[i] = 0 } + @value_changed = false super(x, y, width, height) end def [](i) - return @optvalues[i] + return @values[i] end def []=(i, value) - @optvalues[i] = value + @values[i] = value refresh end def setValueNoRefresh(i, value) - @optvalues[i] = value + @values[i] = value end def itemCount @@ -181,11 +180,15 @@ class Window_PokemonOption < Window_DrawableCommand def drawItem(index, _count, rect) rect = drawCursor(index, rect) + sel_index = self.index + # Draw option's name optionname = (index == @options.length) ? _INTL("Close") : @options[index].name optionwidth = rect.width * 9 / 20 pbDrawShadowText(self.contents, rect.x, rect.y, optionwidth, rect.height, optionname, - @nameBaseColor, @nameShadowColor) + (index == sel_index) ? SEL_NAME_BASE_COLOR : self.baseColor, + (index == sel_index) ? SEL_NAME_SHADOW_COLOR : self.shadowColor) return if index == @options.length + # Draw option's values case @options[index] when EnumOption if @options[index].values.length > 1 @@ -193,14 +196,14 @@ class Window_PokemonOption < Window_DrawableCommand @options[index].values.each do |value| totalwidth += self.contents.text_size(value).width end - spacing = (optionwidth - totalwidth) / (@options[index].values.length - 1) + spacing = (rect.width - rect.x - optionwidth - totalwidth) / (@options[index].values.length - 1) spacing = 0 if spacing < 0 xpos = optionwidth + rect.x ivalue = 0 @options[index].values.each do |value| pbDrawShadowText(self.contents, xpos, rect.y, optionwidth, rect.height, value, - (ivalue == self[index]) ? @selBaseColor : self.baseColor, - (ivalue == self[index]) ? @selShadowColor : self.shadowColor) + (ivalue == self[index]) ? SEL_VALUE_BASE_COLOR : self.baseColor, + (ivalue == self[index]) ? SEL_VALUE_SHADOW_COLOR : self.shadowColor) xpos += self.contents.text_size(value).width xpos += spacing ivalue += 1 @@ -210,48 +213,47 @@ class Window_PokemonOption < Window_DrawableCommand optionname, self.baseColor, self.shadowColor) end when NumberOption - value = _INTL("Type {1}/{2}", @options[index].optstart + self[index], - @options[index].optend - @options[index].optstart + 1) - xpos = optionwidth + rect.x + value = _INTL("Type {1}/{2}", @options[index].lowest_value + self[index], + @options[index].highest_value - @options[index].lowest_value + 1) + xpos = optionwidth + rect.x * 2 pbDrawShadowText(self.contents, xpos, rect.y, optionwidth, rect.height, value, - @selBaseColor, @selShadowColor) + SEL_VALUE_BASE_COLOR, SEL_VALUE_SHADOW_COLOR, 1) when SliderOption - value = sprintf(" %d", @options[index].optend) - sliderlength = optionwidth - self.contents.text_size(value).width + value = sprintf(" %d", @options[index].highest_value) + sliderlength = rect.width - rect.x - optionwidth - self.contents.text_size(value).width xpos = optionwidth + rect.x - self.contents.fill_rect(xpos, rect.y - 2 + (rect.height / 2), - optionwidth - self.contents.text_size(value).width, 4, self.baseColor) + self.contents.fill_rect(xpos, rect.y - 2 + (rect.height / 2), sliderlength, 4, self.baseColor) self.contents.fill_rect( - xpos + ((sliderlength - 8) * (@options[index].optstart + self[index]) / @options[index].optend), + xpos + ((sliderlength - 8) * (@options[index].lowest_value + self[index]) / @options[index].highest_value), rect.y - 8 + (rect.height / 2), - 8, 16, @selBaseColor + 8, 16, SEL_VALUE_BASE_COLOR ) - value = sprintf("%d", @options[index].optstart + self[index]) - xpos += optionwidth - self.contents.text_size(value).width + value = sprintf("%d", @options[index].lowest_value + self[index]) + xpos += (rect.width - rect.x - optionwidth) - self.contents.text_size(value).width pbDrawShadowText(self.contents, xpos, rect.y, optionwidth, rect.height, value, - @selBaseColor, @selShadowColor) + SEL_VALUE_BASE_COLOR, SEL_VALUE_SHADOW_COLOR) else value = @options[index].values[self[index]] xpos = optionwidth + rect.x pbDrawShadowText(self.contents, xpos, rect.y, optionwidth, rect.height, value, - @selBaseColor, @selShadowColor) + SEL_VALUE_BASE_COLOR, SEL_VALUE_SHADOW_COLOR) end end def update oldindex = self.index - @mustUpdateOptions = false + @value_changed = false super dorefresh = (self.index != oldindex) if self.active && self.index < @options.length if Input.repeat?(Input::LEFT) self[self.index] = @options[self.index].prev(self[self.index]) dorefresh = true - @mustUpdateOptions = true + @value_changed = true elsif Input.repeat?(Input::RIGHT) self[self.index] = @options[self.index].next(self[self.index]) dorefresh = true - @mustUpdateOptions = true + @value_changed = true end end refresh if dorefresh @@ -265,71 +267,73 @@ class PokemonOption_Scene attr_reader :sprites attr_reader :in_load_screen - def pbUpdate - pbUpdateSpriteHash(@sprites) - end - def pbStartScene(in_load_screen = false) @in_load_screen = in_load_screen - @sprites = {} - @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) - @viewport.z = 99999 - @sprites["title"] = Window_UnformattedTextPokemon.newWithSize( - _INTL("Options"), 0, 0, Graphics.width, 64, @viewport - ) - @sprites["textbox"] = pbCreateMessageWindow - @sprites["textbox"].text = _INTL("Speech frame {1}.", 1 + $PokemonSystem.textskin) - @sprites["textbox"].letterbyletter = false - pbSetSystemFont(@sprites["textbox"].contents) # Get all options @options = [] + @hashes = [] MenuHandlers.each_available(:options_menu) do |option, hash, name| @options.push( hash["type"].new(name, hash["parameters"], hash["get_proc"], hash["set_proc"]) ) + @hashes.push(hash) end + # Create sprites + @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) + @viewport.z = 99999 + @sprites = {} + addBackgroundOrColoredPlane(@sprites, "bg", "optionsbg", Color.new(192, 200, 208), @viewport) + @sprites["title"] = Window_UnformattedTextPokemon.newWithSize( + _INTL("Options"), 0, -16, Graphics.width, 64, @viewport + ) + @sprites["title"].back_opacity = 0 + @sprites["textbox"] = pbCreateMessageWindow + pbSetSystemFont(@sprites["textbox"].contents) @sprites["option"] = Window_PokemonOption.new( - @options, 0, @sprites["title"].height, Graphics.width, - Graphics.height - @sprites["title"].height - @sprites["textbox"].height + @options, 0, @sprites["title"].y + @sprites["title"].height - 16, Graphics.width, + Graphics.height - (@sprites["title"].y + @sprites["title"].height - 16) - @sprites["textbox"].height ) @sprites["option"].viewport = @viewport @sprites["option"].visible = true # Get the values of each option - @options.length.times do |i| - @sprites["option"].setValueNoRefresh(i, (@options[i].get || 0)) - end + @options.length.times { |i| @sprites["option"].setValueNoRefresh(i, @options[i].get || 0) } @sprites["option"].refresh + pbChangeSelection pbDeactivateWindows(@sprites) pbFadeInAndShow(@sprites) { pbUpdate } end - def pbAddOnOptions(options) - return options + def pbChangeSelection + hash = @hashes[@sprites["option"].index] + # Call selected option's "on_select" proc (if defined) + @sprites["textbox"].letterbyletter = false + hash["on_select"]&.call(self) if hash + # Set descriptive text + description = "" + if hash + if hash["description"].is_a?(Proc) + description = hash["description"].call + elsif !hash["description"].nil? + description = _INTL(hash["description"]) + end + else + description = _INTL("Close the screen.") + end + @sprites["textbox"].text = description end def pbOptions - oldSystemSkin = $PokemonSystem.frame # Menu - oldTextSkin = $PokemonSystem.textskin # Speech pbActivateWindow(@sprites, "option") { + index = -1 loop do Graphics.update Input.update pbUpdate - if @sprites["option"].mustUpdateOptions - @sprites["textbox"].letterbyletter = false - # Set the values of each option - @options.length.times do |i| - @options[i].set(@sprites["option"][i], self) - end - if $PokemonSystem.textskin != oldTextSkin - @sprites["textbox"].text = _INTL("Speech frame {1}.", 1 + $PokemonSystem.textskin) - oldTextSkin = $PokemonSystem.textskin - end - if $PokemonSystem.frame != oldSystemSkin - @sprites["title"].setSkin(MessageConfig.pbGetSystemFrame) - oldSystemSkin = $PokemonSystem.frame - end + if @sprites["option"].index != index + pbChangeSelection + index = @sprites["option"].index end + @options[index].set(@sprites["option"][index], self) if @sprites["option"].value_changed if Input.trigger?(Input::BACK) break elsif Input.trigger?(Input::USE) @@ -342,7 +346,7 @@ class PokemonOption_Scene def pbEndScene pbPlayCloseMenuSE pbFadeOutAndHide(@sprites) { pbUpdate } - # Set the values of each option + # Set the values of each option, to make sure they're all set @options.length.times do |i| @options[i].set(@sprites["option"][i], self) end @@ -351,6 +355,10 @@ class PokemonOption_Scene pbRefreshSceneMap @viewport.dispose end + + def pbUpdate + pbUpdateSpriteHash(@sprites) + end end #=============================================================================== @@ -376,6 +384,7 @@ MenuHandlers.add(:options_menu, :bgm_volume, { "order" => 10, "type" => SliderOption, "parameters" => [0, 100, 5], # [minimum_value, maximum_value, interval] + "description" => _INTL("Adjust the volume of the background music."), "get_proc" => proc { next $PokemonSystem.bgmvolume }, "set_proc" => proc { |value, scene| next if $PokemonSystem.bgmvolume == value @@ -392,6 +401,7 @@ MenuHandlers.add(:options_menu, :se_volume, { "order" => 20, "type" => SliderOption, "parameters" => [0, 100, 5], # [minimum_value, maximum_value, interval] + "description" => _INTL("Adjust the volume of sound effects."), "get_proc" => proc { next $PokemonSystem.sevolume }, "set_proc" => proc { |value, _scene| next if $PokemonSystem.sevolume == value @@ -411,6 +421,8 @@ MenuHandlers.add(:options_menu, :text_speed, { "order" => 30, "type" => EnumOption, "parameters" => [_INTL("Slow"), _INTL("Normal"), _INTL("Fast")], + "description" => _INTL("Choose the speed at which text appears."), + "on_select" => proc { |scene| scene.sprites["textbox"].letterbyletter = true }, "get_proc" => proc { next $PokemonSystem.textspeed }, "set_proc" => proc { |value, scene| next if value == $PokemonSystem.textspeed @@ -428,6 +440,7 @@ MenuHandlers.add(:options_menu, :battle_animations, { "order" => 40, "type" => EnumOption, "parameters" => [_INTL("On"), _INTL("Off")], + "description" => _INTL("Choose whether you wish to see move animations in battle."), "get_proc" => proc { next $PokemonSystem.battlescene }, "set_proc" => proc { |value, _scene| $PokemonSystem.battlescene = value } }) @@ -437,6 +450,7 @@ MenuHandlers.add(:options_menu, :battle_style, { "order" => 50, "type" => EnumOption, "parameters" => [_INTL("Switch"), _INTL("Set")], + "description" => _INTL("Choose whether you can switch Pokémon when an opponent's Pokémon faints."), "get_proc" => proc { next $PokemonSystem.battlestyle }, "set_proc" => proc { |value, _scene| $PokemonSystem.battlestyle = value } }) @@ -446,6 +460,7 @@ MenuHandlers.add(:options_menu, :movement_style, { "order" => 60, "type" => EnumOption, "parameters" => [_INTL("Walking"), _INTL("Running")], + "description" => _INTL("Choose your movement speed. Hold Back while moving to move at the other speed."), "condition" => proc { next $player&.has_running_shoes }, "get_proc" => proc { next $PokemonSystem.runstyle }, "set_proc" => proc { |value, _sceme| $PokemonSystem.runstyle = value } @@ -456,6 +471,7 @@ MenuHandlers.add(:options_menu, :give_nicknames, { "order" => 70, "type" => EnumOption, "parameters" => [_INTL("Give"), _INTL("Don't give")], + "description" => _INTL("Choose whether you can give a nickname to a Pokémon when you obtain it."), "get_proc" => proc { next $PokemonSystem.givenicknames }, "set_proc" => proc { |value, _scene| $PokemonSystem.givenicknames = value } }) @@ -465,6 +481,7 @@ MenuHandlers.add(:options_menu, :speech_frame, { "order" => 80, "type" => NumberOption, "parameters" => 1..Settings::SPEECH_WINDOWSKINS.length, + "description" => _INTL("Choose the appearance of dialogue boxes."), "get_proc" => proc { next $PokemonSystem.textskin }, "set_proc" => proc { |value, scene| $PokemonSystem.textskin = value @@ -479,6 +496,7 @@ MenuHandlers.add(:options_menu, :menu_frame, { "order" => 90, "type" => NumberOption, "parameters" => 1..Settings::MENU_WINDOWSKINS.length, + "description" => _INTL("Choose the appearance of menu boxes."), "get_proc" => proc { next $PokemonSystem.frame }, "set_proc" => proc { |value, scene| $PokemonSystem.frame = value @@ -493,6 +511,7 @@ MenuHandlers.add(:options_menu, :text_input_style, { "order" => 100, "type" => EnumOption, "parameters" => [_INTL("Cursor"), _INTL("Keyboard")], + "description" => _INTL("Choose how you want to enter text."), "get_proc" => proc { next $PokemonSystem.textinput }, "set_proc" => proc { |value, _scene| $PokemonSystem.textinput = value } }) @@ -502,6 +521,7 @@ MenuHandlers.add(:options_menu, :screen_size, { "order" => 110, "type" => EnumOption, "parameters" => [_INTL("S"), _INTL("M"), _INTL("L"), _INTL("XL"), _INTL("Full")], + "description" => _INTL("Choose the size of the game window."), "get_proc" => proc { next [$PokemonSystem.screensize, 4].min }, "set_proc" => proc { |value, _scene| next if $PokemonSystem.screensize == value