[VX] PAC Main Menu

Started by AngryPacman, July 29, 2011, 07:46:57 pm

Previous topic - Next topic

AngryPacman

July 29, 2011, 07:46:57 pm Last Edit: August 22, 2011, 08:59:20 am by AngryPacman
PAC Main Menu
Authors: Pacman
Version: 1.7a
Type: Custom Menu System
Key Term: Custom Menu System



Introduction

This script is protected by an attribution share-alike creative commons license.
It's about time I posted something from my engine, PAC, here. I've been doing it for a couple of months and it seems as though nobody here might know about it. You know Yanfly's engines? Yeah, it's like that, but I'm making it, so it's different!
Anyway, the script. My first CMS. Finally. The PAC Main Menu is focused around simple customization. Only a little has been done in terms of display to the menu, the focus of the first version, 1.7, was to get the core code out of the way so I could focus more on exotic displays in later versions. Now that's been redone and finalized, I've begun focus on display work. So far, there is one graphical 'mode'.


Features


  • Easy configuration

  • Menu Icons

  • Auto-remembering command index

  • Simple support for other custom scripts

  • REALLY easy configuration.

  • Customizable, comprehensive display.




Screenshots

Try it out for yourself. It can be used as plug-and-play.


Demo

This will be included in the PAC 1.7 demo, which will be released in about two weeks.


Script

Paste below materials, above main. If using the :compact window display, it would work best lower in the custom scripts list.
Spoiler: ShowHide
#===============================================================================
#
# Pacman Advanced Creative (PAC) Engine - Main Menu 1.7a
# 22/8/2011
# Type: Menu
# Installation: Heavy arrays and hashes, booleans and values.
# Level: Simple, Average, Difficult
#
#===============================================================================
#
# Description:
# So, here's the main menu. I'm sure you were looking for this. The setup is
# now revolutionized; all the commands are done in one hash filled with arrays.
# I'm pretty certain the configuration's going to stay like this.
# With base code truly out of the way, I've begun working on aesthetic aspects
# of the menu. So far, I've made one 'mode' for the menu, but others are sure
# to follow.
# Enjoy.
#
#===============================================================================
#
# Instructions:
# INSTALLATION
# Paste above main, below materials. It's not very difficult, even an XP
# user could do it.
# CONFIGURATION
# There are detailed instructions for the configuration beginning at line 44.
# Follow them closely, they shall lead you to your dream menu.
#
#===============================================================================
#
# CONFIGURATION BEGINS AT LINE 44
#
#==============================================================================

$pac = {} if $pac == nil
$pac["Main Menu"] = true

module PAC
  module MM
 
#==============================================================================
#
# BEGIN CONFIGURATION
#
#==============================================================================

    #--------------------------------------------------------------------------
    # Use icons in the main menu? (true / false)
    #--------------------------------------------------------------------------
   
    USE_ICONS = true
   
    #--------------------------------------------------------------------------
    # Setup for commands in the menu. Each entry must be an array ([]), ended
    # with a comma and begin with a number (the place where it is in the menu.
    # The indexes start at 0, so make sure you have a 0 command.
    # Syntax:
    # COMMANDS = {
    #   INDEX (number) => [
    #     'Command Name',
    #     'Command action',
    #     IconID,
    #     'Disable action', (optional)
    #   ],
    # }
    # Command action should be left as is unless you know what you are doing.
    # For example, if you are implementing a custom scene into this menu, you
    # have to know the name of the scene and the arguments required. Disable
    # action is code that will be evaluated; if it returns true then the command
    # will not be allowed. Command Name, Command action and Disable action
    # must all be string, i.e. in quotation marks ''. If you do not want a
    # disable action, either do not enter one or enter it as nil.
    # Note that for the command action, if the scene requires actor selection,
    # place an @status_window.index in the paranthesis. It will trigger actor
    # selection upon pressing the command.
    # If you do not want to use an icon for a particular index, enter that
    # entry as nil.
    #--------------------------------------------------------------------------
   
    #--------------------------------------------------------------------------
    COMMANDS = {  # Do not touch this!
    #--------------------------------------------------------------------------
      0 => [  # Do not touch this!
        #----------------------------------------------------------------------
        # Entry for command 1 (index 0)
        #----------------------------------------------------------------------
        'Inventory',                # Name
        '$scene = Scene_Item.new',  # Command
        144,                        # Icon
        nil                         # Disable
      #------------------------------------------------------------------------
      ],  # Do not touch this!
      #------------------------------------------------------------------------
      1 => [  # Do not touch this!
        #----------------------------------------------------------------------
        # Entry for command 2 (index 1)
        #----------------------------------------------------------------------
        'Skills',                                           # Name
        '$scene = Scene_Skill.new(@status_window.index)',   # Command
        137                                                 # Icon
                                                            # No disable needed.
      #------------------------------------------------------------------------
      ],  # Do not touch this!
      #------------------------------------------------------------------------
      2 => [  # Do not touch this!
        #----------------------------------------------------------------------
        # Entry for command 3 (index 2)
        #----------------------------------------------------------------------
        'Equip',                                          # Name
        '$scene = Scene_Equip.new(@status_window.index)', # Command
        1,                                                # Icon       
      #------------------------------------------------------------------------
      ],  # Do not touch this!
      #------------------------------------------------------------------------
      3 => [
        'Status',
        '$scene = Scene_Status.new(@status_window.index)',
        130,
      ],
      4 => [
        'Save',
        '$scene = Scene_File.new(true, false, false)',
        200,
        '$game_system.save_disabled',
      ],
      5 => [
        'End Game',
        '$scene = Scene_End.new',
        224,
      ],
     
    #--------------------------------------------------------------------------
    } # Do not touch this!
    #--------------------------------------------------------------------------
   
    # Mode of graphics used for the menu. So far, only :compact is usable.
    # If you do not want to use this, set it to nil.
   
    WINDOW_MODE = :compact
    #--------------------------------------------------------------------------
    # THESE OPTIONS ARE FOR THE COMPACT OPTION
    #--------------------------------------------------------------------------
      # Pixels per frame the windows move (number)
      COMPACT_SCROLL_SPEED = 4
      # Direction the command window will move to when actor selection begins
      # (:left / :right)
      COMPACT_SELECTION = :right
      # Button to toggle gold window visibility (Input::Button)
      COMPACT_GOLD_BUTTON = Input::L
      # Start scene with gold window visible? (true / false)
      COMPACT_GOLD_WINDOW = true
    #--------------------------------------------------------------------------

#===============================================================================
#
# END CONFIGURATION
#
#===============================================================================

   
  end
end

#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
#  This class handles system-related data. Also manages vehicles and BGM, etc.
# The instance of this class is referenced by $game_system.
#==============================================================================

class Game_System
  #--------------------------------------------------------------------------
  # Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :menu_index
  attr_accessor :menu_window_mode
  #--------------------------------------------------------------------------
  # Alias listing
  #--------------------------------------------------------------------------
  alias pac_menu_initialize initialize
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    pac_menu_initialize
    @menu_index = 0
    @menu_window_mode = PAC::MM::WINDOW_MODE
  end
end

#==============================================================================
# ** Window_MenuCommand
#------------------------------------------------------------------------------
#  This window displays selectable commands on the menu screen.
#==============================================================================

class Window_MenuCommand < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     width      : window width
  #     commands   : command string array
  #     column_max : digit count (if 2 or more, horizontal selection)
  #     row_max    : row count (0: match command count)
  #     spacing    : blank space when items are arrange horizontally
  #--------------------------------------------------------------------------
  def initialize(width, commands, column_max = 1, row_max = 0, spacing = 32)
    if row_max == 0
      row_max = (commands.size + column_max - 1) / column_max
    end
    super(0, 0, width, row_max * WLH + 32, spacing)
    @commands = commands
    @item_max = commands.size
    @column_max = column_max
    refresh
    self.index = 0
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    for i in 0...@item_max
      draw_item(i)
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Item
  #     index   : item number
  #     enabled : enabled flag. When false, draw semi-transparently.
  #--------------------------------------------------------------------------
  def draw_item(index, enabled = true)
    rect = item_rect(index)
    rect.x += 4
    rect.width -= 8
    self.contents.clear_rect(rect)
    self.contents.font.color = normal_color
    self.contents.font.color.alpha = enabled ? 255 : 128
    if PAC::MM::COMMANDS[index][2] != nil and PAC::MM::USE_ICONS
      draw_icon(PAC::MM::COMMANDS[index][2], rect.x, rect.y)
      rect.x += 24
    end
    self.contents.draw_text(rect, PAC::MM::COMMANDS[index][0])
  end
end

#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
#  This class performs the menu screen processing.
#==============================================================================

class Scene_Menu < Scene_Base
  #--------------------------------------------------------------------------
  # Include Configuration Data
  #--------------------------------------------------------------------------
  include PAC::MM
  #--------------------------------------------------------------------------
  # Alias listing
  #--------------------------------------------------------------------------
  alias pac_menu_initialize initialize
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     menu_index : command cursor's initial position
  #--------------------------------------------------------------------------
  def initialize(menu_index = $game_system.menu_index)
    pac_menu_initialize(menu_index)
  end
  #--------------------------------------------------------------------------
  # * Create Command Window
  #--------------------------------------------------------------------------
  def create_command_window
    commands = COMMANDS
    @command_window = Window_MenuCommand.new(160, commands)
    @command_window.index = @menu_index
    pac_menu_disable_commands
  end
  #--------------------------------------------------------------------------
  # * Disable Menu Commands
  #--------------------------------------------------------------------------
  def pac_menu_disable_commands
    if $game_party.members.size == 0
      for i in 0...COMMANDS.size
        if selection?(i)
          @command_window.draw_item(i, false)
        end
      end
    end
    for i in 0...COMMANDS.size
      unless COMMANDS[i][3].nil?
        if eval(COMMANDS[i][3])
          text = COMMANDS[i[0]]
          @command_window.draw_item(text, false)
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Require Selection?
  #     command : command to be determined whether or not to have selection
  #--------------------------------------------------------------------------
  def selection?(command)
    return COMMANDS[command][1].include?('@status_window.index')
  end
  #--------------------------------------------------------------------------
  # * Update Command Selection
  #--------------------------------------------------------------------------
  def update_command_selection
    $game_system.menu_index = @command_window.index
    selection = @command_window.index
    if Input.trigger?(Input::B)
      Sound.play_cancel
      $scene = Scene_Map.new
    elsif Input.trigger?(Input::C)
      if $game_party.members.size == 0 and selection?(selection)
        Sound.play_buzzer
        return
      elsif !COMMANDS[selection][3].nil?
        if eval(COMMANDS[selection][3])
          Sound.play_buzzer
          return
        end
      end
      Sound.play_decision
      if selection?(selection)
        start_actor_selection
      else
        eval(COMMANDS[selection][1])
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Update Actor Selection
  #--------------------------------------------------------------------------
  def update_actor_selection
    if Input.trigger?(Input::B)
      Sound.play_cancel
      end_actor_selection
    elsif Input.trigger?(Input::C)
      selection = @command_window.index
      $game_party.last_actor_index = @status_window.index
      Sound.play_decision
      eval(COMMANDS[selection][1])
    end
  end
#===============================================================================
# COMPACT MODE
#===============================================================================
  if WINDOW_MODE == :compact
  $pac["Compact Menu"] = true
  #--------------------------------------------------------------------------
  # Alias listing
  #--------------------------------------------------------------------------
  alias pac_compact_start start
  alias pac_compact_start_actor_selection start_actor_selection
  alias pac_compact_end_actor_selection end_actor_selection
  alias pac_compact_update update
  #--------------------------------------------------------------------------
  # * Start Processing
  #--------------------------------------------------------------------------
  def start
    pac_compact_start
    pac_compact_windows
  end
  #--------------------------------------------------------------------------
  # * Make Windows Compact
  #--------------------------------------------------------------------------
  def pac_compact_windows
    @command_window.x = Graphics.width / 2 - @command_window.width / 2
    @gold_window.visible = COMPACT_GOLD_WINDOW
    @gold_window.x = @command_window.x
    @gold_window.openness = COMPACT_GOLD_WINDOW ? 255 : 0
    @status_window.x = case COMPACT_SELECTION
    when :left then Graphics.width - @status_window.width
    when :right then 0
    end
    @status_window.visible = false
    @status_window.openness = 0
    if @gold_window.visible
      @command_window.y = Graphics.height / 2 - (@command_window.height +
      @gold_window.height) / 2
    else
      @command_window.y = Graphics.height / 2 - @command_window.height / 2
    end
    @gold_window.y = @command_window.y + @command_window.height
    @check_x = @command_window.x
  end
  #--------------------------------------------------------------------------
  # * Start Actor Selection
  #--------------------------------------------------------------------------
  def start_actor_selection
    @status_window.visible = true
    check = case COMPACT_SELECTION
    when :left then 0
    when :right then Graphics.width - @command_window.width
    end
    begin
      @command_window.x -= case COMPACT_SELECTION
      when :left then COMPACT_SCROLL_SPEED
      when :right then -COMPACT_SCROLL_SPEED
      end
      @gold_window.x = @command_window.x
      Graphics.update
    end until @command_window.x == check
    @status_window.open
    begin
      @status_window.update
      Graphics.update
    end until @status_window.openness == 255
    pac_compact_start_actor_selection
  end
  #--------------------------------------------------------------------------
  # * End Actor Selection
  #--------------------------------------------------------------------------
  def end_actor_selection
    pac_compact_end_actor_selection
    @status_window.close
    begin
      @status_window.update
      Graphics.update
    end until @status_window.openness == 0
    @status_window.visible = false
    begin
      unless @command_window.x == @check_x
        @command_window.x += case COMPACT_SELECTION
        when :left then COMPACT_SCROLL_SPEED
        when :right then -COMPACT_SCROLL_SPEED
        end
      end
      @gold_window.x = @command_window.x
      Graphics.update
    end until @command_window.x == @check_x
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    pac_compact_update
    update_gold_visible
  end
  #--------------------------------------------------------------------------
  # * Update Visibility of Gold Window (and scroll to cater)
  #--------------------------------------------------------------------------
  def update_gold_visible
    @gold_window.x = @command_window.x if @gold_window.x != @command_window.x
    if Input.trigger?(COMPACT_GOLD_BUTTON)
      Sound.play_decision
      if @gold_window.visible
        @gold_window.close
        begin
          @gold_window.update
          Graphics.update
        end until @gold_window.openness == 0
        @gold_window.visible = false
        begin
          @command_window.y += COMPACT_SCROLL_SPEED
          @command_window.update
          Graphics.update
        end until @command_window.y == Graphics.height / 2 -
         @command_window.height / 2
       else
        begin
          @command_window.y -= COMPACT_SCROLL_SPEED
          @command_window.update
          Graphics.update
        end until @command_window.y == Graphics.height / 2 -
         (@command_window.height + @gold_window.height) / 2
        @gold_window.visible = true
        @gold_window.open
        begin
          @gold_window.update
          Graphics.update
        end until @gold_window.openness == 255
      end
    end
  end
#===============================================================================
# END COMPACT MODE
#===============================================================================
  end
end

#==============================================================================
# ** Scene_Base
#------------------------------------------------------------------------------
#  This is a superclass of all scenes in the game.
#==============================================================================

class Scene_Base
  #--------------------------------------------------------------------------
  # * Dispose of Background for Menu Screen
  #--------------------------------------------------------------------------
  def dispose_menu_background
    @menuback_sprite.dispose if @menuback_sprite != nil
  end
end

#==============================================================================
# ** Scene_Item
#------------------------------------------------------------------------------
#  This class performs the item screen processing.
#==============================================================================

class Scene_Item < Scene_Base
  #--------------------------------------------------------------------------
  # * Return to Original Screen
  #--------------------------------------------------------------------------
  def return_scene
    $scene = Scene_Menu.new
  end
end

#==============================================================================
# ** Scene_Skill
#------------------------------------------------------------------------------
#  This class performs the skill screen processing.
#==============================================================================

class Scene_Skill < Scene_Base
  #--------------------------------------------------------------------------
  # * Return to Original Screen
  #--------------------------------------------------------------------------
  def return_scene
    $scene = Scene_Menu.new
  end
end

#==============================================================================
# ** Scene_Equip
#------------------------------------------------------------------------------
#  This class performs the equipment screen processing.
#==============================================================================

class Scene_Equip < Scene_Base
  #--------------------------------------------------------------------------
  # * Return to Original Screen
  #--------------------------------------------------------------------------
  def return_scene
    $scene = Scene_Menu.new
  end
end

#==============================================================================
# ** Scene_Status
#------------------------------------------------------------------------------
#  This class performs the status screen processing.
#==============================================================================

class Scene_Status < Scene_Base
  #--------------------------------------------------------------------------
  # * Return to Original Screen
  #--------------------------------------------------------------------------
  def return_scene
    $scene = Scene_Menu.new
  end
end

#==============================================================================
# ** Scene_File
#------------------------------------------------------------------------------
#  This class performs the save and load screen processing.
#==============================================================================

class Scene_File < Scene_Base
  #--------------------------------------------------------------------------
  # * Return to Original Screen
  #--------------------------------------------------------------------------
  def return_scene
    if @from_title
      $scene = Scene_Title.new
    elsif @from_event
      $scene = Scene_Map.new
    else
      $scene = Scene_Menu.new
    end
  end
end

#==============================================================================
# ** Scene_End
#------------------------------------------------------------------------------
#  This class performs game end screen processing.
#==============================================================================

class Scene_End < Scene_Base
  #--------------------------------------------------------------------------
  # * Return to Original Screen
  #--------------------------------------------------------------------------
  def return_scene
    $scene = Scene_Menu.new
  end
end

#===============================================================================
#
# END OF SCRIPT
#
#===============================================================================



Instructions

I'll be directing you to the instructions included in the script, conveniently situated next to the applicable configuration options.


Compatibility

Obviously, it won't work with other CMS's. To check if a script is compatible, here is a list of methods altered/created in the script:

  • Game_System#initialize - alias

  • Window_MenuCommand (entire class) - new

  • Scene_Menu#initialize - alias

  • Scene_Menu#create_command_window, update_command_selection, update_actor_selection - overwritten

  • Scene_Menu#pac_mm_disable_commands, selection? - new

  • Scene_Base#dispose_menu_background - overwritten

  • Scene_Item, Scene_Skill, Scene_Equip, Scene_Status, Scene_File, Scene_End#return_scene - overwritten

  • The following apply if using the :compact window option:
  • Scene_Menu#start, start_actor_selection, end_actor_selection, update - alias

  • Scene_Menu#pac_compact_windows, update_gold_visible - new




Credits and Thanks


  • Pacman

  • Enterbrain, for making such a terrible DMS in the first place.




Author's Notes

If you need support, post here or on RMRK, no matter how old the topic is. I'll probably respond to PMs as well. It won't work with any other menu systems. Custom scenes will probably return to the wrong index: I've posted a short tutorial on how to fix this. It can get a bit problematic, so don't hesitate to ask for help.
If you want the compact display, but not the data of the menu (for whatever insane reason :V), find it at this thread.

I'd like to thank Twb6543 for helping me deal with the command index issue, Modern Algebra for inspiring a display, and LoganForrests, Cozziekuns and the almighty Zeriab for generally helping out and showing me how I can improve in Ruby. And, of course, Yanfly for inspiring PAC by creating YERD, YEZ and YEM.
G_G's a silly boy.

InfinateX

the few things I checked are different then before and they're neat!
I made a signature!

AngryPacman

Updated to 1.7a - Revamp.
Configuration has been massively overhauled, and the display option has been added. I think that's where the configuration's going to stay. Any complaints about that?
While we're at it, I'm looking for ideas of menu design. I'll probably take some inspiration from other CMSes, but I'd like to have original designs, and I'm too lazy to do that. So I'm at a point where I'd so just about any CMS that isn't outrageously ridiculous, and could be implemented into PAC MM.
Anyway, enjoy.
G_G's a silly boy.