PAC Main Menu
Authors: Pacman
Version: 1.7a
Type: Custom Menu System
Key Term: Custom Menu System
IntroductionThis script is protected by an attribution share-alike creative commons license. (http://creativecommons.org/licenses/by-sa/3.0/)
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.
ScreenshotsTry it out for yourself. It can be used as plug-and-play.
DemoThis will be included in the PAC 1.7 demo, which will be released in about two weeks.
ScriptPaste below materials, above main. If using the :compact window display, it would work best lower in the custom scripts list.
#===============================================================================
#
# 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
#
#===============================================================================
InstructionsI'll be directing you to the instructions included in the script, conveniently situated next to the applicable configuration options.
CompatibilityObviously, 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 NotesIf 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 (http://rmrk.net/index.php/topic,43352.msg493715.html#msg493715) 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 (http://rmrk.net/index.php/topic,43617.msg496006/topicseen.html#msg496006).
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.
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.