Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

[Resolved] Some help needed with a Custom Menu System

I've been fooling around with menu edits, seeing if I can understand the way the RMXP codes things and whatnot to see if I can alter it to do whatever I want. I've been trying to mock the layout used in Tales of Phantasia (PS1) as a test of this, but I have a few problems I can't figure out on my own that I was hoping someone could help with.

I'll list them in the order of priority.

1. Displaying the "Experience to next level" amount on the Menu's status portion (see screenshot). I just put a plain text placeholder for now of what I want it to show and how I want it to look, but I don't actually know how to make it read off the game variables. I saw something like: "@actor.next_rest_exp_s" in Window_status, but using this just gave me some kinda error (undefined method or something probably). I also tried it without the "_s" at the end, but that still errored on me. Could anyone tell me the correct way to call up that number?

2. I want the actual menu (the part with the commands) to stretch down the same length as the parts to the right of it. I have them sized just fine right now, but the it leaves a lot of dead space at the bottom since my commands don't actually run that long. I was wondering if there was a way I could define the space between each line of text so that they fill it out better.

3. Very minor thing (but would add a nice little touch) is would there be a way for me to make each character's info be in its own box? What I have now is the regular way of one box that contains info for all 4 characters. What I would instead like is to have a seperate border drawn around each character's info to kinda seperate them if that's possible.

4. Even more minor is I wondered how you can change the way the cursor works. By default, it's a square box that gets stretched into a rectangle across the word that is selected. In Phantasia, they just have a hand pointer cursor that sits at the left of the word, pointing to it. Is there a way to mimic that effect in RMXP?

finally, here is a screenshot of what I got it to do so far so you can get a better idea of what I'm trying to do along with what I said above:

menu_example.png
 
Okay, heeere we go...

1) Simple. As you said, Window_Status is using this line:
[rgss]self.contents.draw_text(320 + 80, 80, 84, 32, @actor.next_rest_exp_s, 2)
[/rgss]
You should use that too. The difference is: instead of @actor, you should use simply actor.
[rgss]actor.next_rest_exp_s
[/rgss]

2) Ooh, that's a tough one. Well, of course it's possible, why it wouldn't be?
There are two solutions for your heightened problem. First, you could make a copy of Window_Command and Window_Selection. Or second, you could change these scripts so you can specify the line spacing.
Let's make the copies, then. Make a copy of Window_Command and Window_Selection. Rename them for Window_MenuCommand and Window_MenuSelection. Don't forget to change the superclass on the Window_Command script!
[rgss]class Window_MenuCommand < Window_Selectable # This is wrong
class Window_MenuCommand < Window_MenuSelectable # Correct
[/rgss]
And now, search for "* 32" and change it for another value, probably "* 40" is just enough. Do that on BOTH scripts.
And now, get to Scene_Menu and change Window_Command.new for Window_MenuCommand.new.

3) Yeah, that's possible, too. But that would require a lot of coding, and I'm tired...
Let me give you a general explanation of what you'll need to do:
Create two classes: the first will be one of the character status windows, and the second will create and handle these windows.
The first window should simply draw the specified actor. Don't do anything else there. The second script will asign to this an actor.
At the second script, create the windows, passing for them the actor that'll be shown. Push the windows to an Array. Add a @index attribute to this class, and add to the update code conditions that'll check the buttons pressed, changing the @index accordingly.

4) You'll have to add a Sprite to the Window_Selection (or Window_MenuSelection, if you created that). At the "update_cursor_rect" method of the Window_Selection class, you'll have to update the Sprite position accordingly. You'll also have to add a "dispose" method. This method should look like this:
[rgss]def dispose
  super
  @select_sprite.dispose
end
[/rgss]

Well, if you need more help, go ahead. :biggrin:
Good luck, buddy!
SEE YA!!!!!
 
Thanks for the help. I think I tried everything BUT the right syntax for #1 o.o;

but for #2, I can't seem to get it to work as you said. There are multiple instances of stuff being multiplied by 32, and I tried changing various ones to 40, but no change seemed to affect the menu spacing at all. At most, I got a black arrow at the bottom from one of them.
 
Okay, for #2...

I've made the changes for you. This should work as expected. Don't forget to change from Window_Command.new to Window_MenuCommand.new at the Scene_Menu script.

Here's the scripts:
Code:
#==============================================================================

# ** Window_MenuSelectable

#==============================================================================

 

class Window_MenuSelectable < Window_Base

  #--------------------------------------------------------------------------

  # * Public Instance Variables

  #--------------------------------------------------------------------------

  attr_reader   :index                    # cursor position

  attr_reader   :help_window              # help window

  #--------------------------------------------------------------------------

  # * Object Initialization

  #     x      : window x-coordinate

  #     y      : window y-coordinate

  #     width  : window width

  #     height : window height

  #--------------------------------------------------------------------------

  def initialize(x, y, width, height)

    super(x, y, width, height)

    @item_max = 1

    @column_max = 1

    @index = -1

  end

  #--------------------------------------------------------------------------

  # * Set Cursor Position

  #     index : new cursor position

  #--------------------------------------------------------------------------

  def index=(index)

    @index = index

    # Update Help Text (update_help is defined by the subclasses)

    if self.active and @help_window != nil

      update_help

    end

    # Update cursor rectangle

    update_cursor_rect

  end

  #--------------------------------------------------------------------------

  # * Get Row Count

  #--------------------------------------------------------------------------

  def row_max

    # Compute rows from number of items and columns

    return (@item_max + @column_max - 1) / @column_max

  end

  #--------------------------------------------------------------------------

  # * Get Top Row

  #--------------------------------------------------------------------------

  def top_row

    # Divide y-coordinate of window contents transfer origin by 1 row

    # height of 32

    return self.oy / 40

  end

  #--------------------------------------------------------------------------

  # * Set Top Row

  #     row : row shown on top

  #--------------------------------------------------------------------------

  def top_row=(row)

    # If row is less than 0, change it to 0

    if row < 0

      row = 0

    end

    # If row exceeds row_max - 1, change it to row_max - 1

    if row > row_max - 1

      row = row_max - 1

    end

    # Multiply 1 row height by 32 for y-coordinate of window contents

    # transfer origin

    self.oy = row * 40

  end

  #--------------------------------------------------------------------------

  # * Get Number of Rows Displayable on 1 Page

  #--------------------------------------------------------------------------

  def page_row_max

    # Subtract a frame height of 32 from the window height, and divide it by

    # 1 row height of 32

    return (self.height - 32) / 40

  end

  #--------------------------------------------------------------------------

  # * Get Number of Items Displayable on 1 Page

  #--------------------------------------------------------------------------

  def page_item_max

    # Multiply row count (page_row_max) times column count (@column_max)

    return page_row_max * @column_max

  end

  #--------------------------------------------------------------------------

  # * Set Help Window

  #     help_window : new help window

  #--------------------------------------------------------------------------

  def help_window=(help_window)

    @help_window = help_window

    # Update help text (update_help is defined by the subclasses)

    if self.active and @help_window != nil

      update_help

    end

  end

  #--------------------------------------------------------------------------

  # * Update Cursor Rectangle

  #--------------------------------------------------------------------------

  def update_cursor_rect

    # If cursor position is less than 0

    if @index < 0

      self.cursor_rect.empty

      return

    end

    # Get current row

    row = @index / @column_max

    # If current row is before top row

    if row < self.top_row

      # Scroll so that current row becomes top row

      self.top_row = row

    end

    # If current row is more to back than back row

    if row > self.top_row + (self.page_row_max - 1)

      # Scroll so that current row becomes back row

      self.top_row = row - (self.page_row_max - 1)

    end

    # Calculate cursor width

    cursor_width = self.width / @column_max - 32

    # Calculate cursor coordinates

    x = @index % @column_max * (cursor_width + 32)

    y = @index / @column_max * 40 - self.oy

    # Update cursor rectangle

    self.cursor_rect.set(x, y, cursor_width, 40)

  end

  #--------------------------------------------------------------------------

  # * Frame Update

  #--------------------------------------------------------------------------

  def update

    super

    # If cursor is movable

    if self.active and @item_max > 0 and @index >= 0

      # If pressing down on the directional buttons

      if Input.repeat?(Input::DOWN)

        # If column count is 1 and directional button was pressed down with no

        # repeat, or if cursor position is more to the front than

        # (item count - column count)

        if (@column_max == 1 and Input.trigger?(Input::DOWN)) or

           @index < @item_max - @column_max

          # Move cursor down

          $game_system.se_play($data_system.cursor_se)

          @index = (@index + @column_max) % @item_max

        end

      end

      # If the up directional button was pressed

      if Input.repeat?(Input::UP)

        # If column count is 1 and directional button was pressed up with no

        # repeat, or if cursor position is more to the back than column count

        if (@column_max == 1 and Input.trigger?(Input::UP)) or

           @index >= @column_max

          # Move cursor up

          $game_system.se_play($data_system.cursor_se)

          @index = (@index - @column_max + @item_max) % @item_max

        end

      end

      # If the right directional button was pressed

      if Input.repeat?(Input::RIGHT)

        # If column count is 2 or more, and cursor position is closer to front

        # than (item count -1)

        if @column_max >= 2 and @index < @item_max - 1

          # Move cursor right

          $game_system.se_play($data_system.cursor_se)

          @index += 1

        end

      end

      # If the left directional button was pressed

      if Input.repeat?(Input::LEFT)

        # If column count is 2 or more, and cursor position is more back than 0

        if @column_max >= 2 and @index > 0

          # Move cursor left

          $game_system.se_play($data_system.cursor_se)

          @index -= 1

        end

      end

      # If R button was pressed

      if Input.repeat?(Input::R)

        # If bottom row being displayed is more to front than bottom data row

        if self.top_row + (self.page_row_max - 1) < (self.row_max - 1)

          # Move cursor 1 page back

          $game_system.se_play($data_system.cursor_se)

          @index = [@index + self.page_item_max, @item_max - 1].min

          self.top_row += self.page_row_max

        end

      end

      # If L button was pressed

      if Input.repeat?(Input::L)

        # If top row being displayed is more to back than 0

        if self.top_row > 0

          # Move cursor 1 page forward

          $game_system.se_play($data_system.cursor_se)

          @index = [@index - self.page_item_max, 0].max

          self.top_row -= self.page_row_max

        end

      end

    end

    # Update help text (update_help is defined by the subclasses)

    if self.active and @help_window != nil

      update_help

    end

    # Update cursor rectangle

    update_cursor_rect

  end

end

 

Code:
#==============================================================================

# ** Window_MenuCommand

#==============================================================================

 

class Window_MenuCommand < Window_MenuSelectable

  #--------------------------------------------------------------------------

  # * Object Initialization

  #     width    : window width

  #     commands : command text string array

  #--------------------------------------------------------------------------

  def initialize(width, commands)

    # Compute window height from command quantity

    super(0, 0, width, commands.size * 40 + 32)

    @item_max = commands.size

    @commands = commands

    self.contents = Bitmap.new(width - 32, @item_max * 40)

    refresh

    self.index = 0

  end

  #--------------------------------------------------------------------------

  # * Refresh

  #--------------------------------------------------------------------------

  def refresh

    self.contents.clear

    for i in 0...@item_max

      draw_item(i, normal_color)

    end

  end

  #--------------------------------------------------------------------------

  # * Draw Item

  #     index : item number

  #     color : text color

  #--------------------------------------------------------------------------

  def draw_item(index, color)

    self.contents.font.color = color

    rect = Rect.new(4, 40 * index, self.contents.width - 8, 40)

    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))

    self.contents.draw_text(rect, @commands[index])

  end

  #--------------------------------------------------------------------------

  # * Disable Item

  #     index : item number

  #--------------------------------------------------------------------------

  def disable_item(index)

    draw_item(index, disabled_color)

  end

end

 
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top