[XP][VX] Dialog System

Started by Zeriab, January 08, 2008, 06:53:41 am

Previous topic - Next topic

Zeriab

January 08, 2008, 06:53:41 am Last Edit: February 21, 2009, 05:45:13 am by Blizzard
Dialog System
Authors: Zeriab
Version: 1.0
Type: Extra
Key Term: Scripting Tool



Introduction

I have tried to make a Dialog system which is intended to ease the creation of dialogs.



Quote from: Dialog system
#==============================================================================
# ** Dialog system
#------------------------------------------------------------------------------
# Zeriab
# Version 1.0
# 2007-11-07 (Year-Month-Day)
#------------------------------------------------------------------------------
# * Description :
#
#   A small framework like script for dialogs
#------------------------------------------------------------------------------
# * License :
#
#   Copyright (C) 2007  Zeriab
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Lesser Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Lesser Public License for more details.
#
#   For the full license see <http://www.gnu.org/licenses/>
#   The GNU General Public License: http://www.gnu.org/licenses/gpl.txt
#   The GNU Lesser General Public License: http://www.gnu.org/licenses/lgpl.txt
#------------------------------------------------------------------------------
# * Instructions :
#
#   You can place this script pretty much anyway you like.
#   Place it above any other Dialogs you might be using.
#   Increase the STARTING_Z_VALUE if you have trouble with the dialog not
#   on top.
#==============================================================================
class Dialog
  STARTING_Z_VALUE = 1500 # Default value is 1500
  attr_accessor :value
  attr_writer :marked_to_close
  #--------------------------------------------------------------------------
  # * Getter with 'false' as default value
  #--------------------------------------------------------------------------
  def marked_to_close
    @marked_to_close = false  if @marked_to_close.nil?
    return @marked_to_close
  end
  #--------------------------------------------------------------------------
  # * Initialization
  #--------------------------------------------------------------------------
  def mark_to_close
    self.marked_to_close = true
  end
  #--------------------------------------------------------------------------
  # * Show the dialog
  #   Returns the value from the dialog
  #--------------------------------------------------------------------------
  def self.show(*args, &block)
    dialog = self.new(*args, &block)
    dialog.marked_to_close = false
    return dialog.main
  end
  #--------------------------------------------------------------------------
  # * Initialization
  #--------------------------------------------------------------------------
  def initialize(*args, &block)
    # For subclasses to overwrite
  end
  #--------------------------------------------------------------------------
  # * Main processing
  #--------------------------------------------------------------------------
  def main
    # Create the dimmed background
    create_background
    # Create Windows
    main_window
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if the dialog should close
      if marked_to_close
        break
      end
    end
    # Dispose of windows
    main_dispose
    # Dispose of background
    dispose_background
    # Update input information
    Input.update
    # Returns the acquired value
    return self.value
  end
  #--------------------------------------------------------------------------
  # * Create the dimmed background
  #--------------------------------------------------------------------------
  def create_background
    bitmap = Bitmap.new(640,480)
    bitmap.fill_rect(0,0,640,480,Color.new(0,0,0,128))
    @background_sprite = Sprite.new
    @background_sprite.z = STARTING_Z_VALUE
    @background_sprite.bitmap = bitmap
  end
  #--------------------------------------------------------------------------
  # * Create the windows
  #--------------------------------------------------------------------------
  def main_window
    # For the subclasses to override
    # Remember to set their z.value to at least STARTING_Z_VALUE + 1
  end
  #--------------------------------------------------------------------------
  # * Dispose the background
  #--------------------------------------------------------------------------
  def dispose_background
    @background_sprite.dispose
  end
  #--------------------------------------------------------------------------
  # * Dispose the windows
  #--------------------------------------------------------------------------
  def main_dispose
    # For the subclasses to override
    # Dispose your windows here
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # For the subclasses to override
    if Input.trigger?(Input::B)
      mark_to_close
    end
  end
end


What is a dialog? You can consider it as a scene that runs on top of the current scene.
Here is an example of how the system can be used. It is a yes/no dialog.
Quote from: An example - A Yes/No Dialog
#============================================================================
# * A Simple Yes/No dialog
#============================================================================
class Dialog_YesNo < Dialog
  # self.value: false = No, true = Yes
 
  #--------------------------------------------------------------------------
  # * A show method
  #--------------------------------------------------------------------------
  def initialize(default_value = false, text = nil)
    # Sets the default value
    self.value = default_value
    @text = text
    # Sets the menu index
    if default_value
      @menu_index = 0
    else
      @menu_index = 1
    end
  end
  #--------------------------------------------------------------------------
  # * Create the windows
  #--------------------------------------------------------------------------
  def main_window
    @disposables = []
   
    # The command window
    @command_window = Window_Command.new(80, ['Yes', 'No'])
    @command_window.index = @menu_index
    @command_window.x = (640 - @command_window.width) / 2
    @command_window.y = (480 - @command_window.height) / 2
    @command_window.z = STARTING_Z_VALUE + 1
    @disposables << @command_window
   
    # The text window
    if @text.is_a?(String)
      @text_window = Window_Help.new
      @text_window.set_text(@text, 1)
      @text_window.z = STARTING_Z_VALUE + 1
      @disposables << @text_window
    end
  end
  #--------------------------------------------------------------------------
  # * Dispose the windows
  #--------------------------------------------------------------------------
  def main_dispose
    @disposables.each {|element| element.dispose}
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    @command_window.update
    if Input.trigger?(Input::B)
      mark_to_close
    end
    if Input.trigger?(Input::C)
      if @command_window.index == 0
        self.value = true
      else
        self.value = false
      end
      mark_to_close
    end
  end
end


The idea is that you can all this dialog anywhere with the code:
# Code before
var = Dialog_YesNo.show(default_value, text) # Calls the dialog
# Code after

The dialog should then be shown and the code after will only be executed after the player chooses yes or no. It will return false if No is selected and true if Yes is selected.
Then the code placed after the call will be executed. You can say it will freeze execution until the dialog is closed.
The principle is that you can call this code anyway. In script calls as well as in normal scripts.
Here is an example of a script call:
s = 'Do you want to open the chest?'
v = Dialog_YesNo.show(true, s)
$game_switches[5] = v

Here is an event using this:
Quote from: Angry Chest

I assume you know how to make page 2 and page 3 yourself.

I know. This can easily be done with the normal choice system in events. So what about an example where its use is more clear?
Did you know that if you try to save on a slot where there already is a savegame it does not ask if you want to overwrite? It simply just overwrites the savegame. Let us say we don't want that. The remedy?
class Scene_Save < Scene_File
  alias scene_save_overwrite_dialog_on_decision on_decision
  #--------------------------------------------------------------------------
  # * Decision Processing
  #--------------------------------------------------------------------------
  def on_decision(filename)
    if File.exist?(filename)
      var = Dialog_YesNo.show(false, 'Do you want to overwrite' +
                                     ' the old savegame?')
      unless var
        $game_system.se_play($data_system.buzzer_se)
        return
      end
    end
    scene_save_overwrite_dialog_on_decision(filename)
  end
end

Just paste this anywhere below the original Scene_Save.


I have tried to give dialogs the feeling of scenes.
When you create a dialog you will in most cases only have to overwrite 3-4 methods:

main_window
You should create the windows you are going to use in this method.
Please set the .z-values of the windows to at least STARTING_Z_VALUE + 1
This is what you put before the main loop when creating a normal scene.
You can consider it pretty much equivalent to the main_window method in the SDK.
Does nothing by default

main_dispose
Dispose of the windows you have created here and do any other clean up you find necessary.
Does nothing by default

update
The update method is pretty much equivalent to the update method in a normal scene.
Exits the scene when you press the B-button by default.

You end the dialog by calling the mark_to_close method. It will then exit just like if you normally change the scene.
Remember to set the value that will be returned. By default is nil returned.
Use self.value = ... to set the value. This value will not be frozen after you use the mark_to_close method, which means that you can change the value after you use that method if it happens later in the update method.

I am certain that I have messed something up or forgotten to tell something important. Please do tell if you run into any problems

*hugs*
- Zeriab

Fantasist

The ideal dialog system, Vista effect =D
Do you like ambient/electronic music? Then you should promote a talented artist! Help out here. (I'm serious. Just listen to his work at least!)


The best of freeware reviews: Gizmo's Freeware Reviews




Zeriab

The Vista effect was indeed the foundation for the idea ^^

Zeriab

I just found out that this system works amazingly well on RMVX. All that is needed is to change the fixed widths 640 and 480 to Graphics.width and Graphics.height.
So here is an update with a RMVX version:

The dialog framework:
#==============================================================================
# ** Dialog system - RMVX
#------------------------------------------------------------------------------
# Zeriab
# Version 1.0
# 2008-02-16 (Year-Month-Day)
#------------------------------------------------------------------------------
# * Description :
#
#   A small framework like script for dialogs
#------------------------------------------------------------------------------
# * License :
#
#   Copyright (C) 2008  Zeriab
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Lesser Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Lesser Public License for more details.
#
#   For the full license see <http://www.gnu.org/licenses/>
#   The GNU General Public License: http://www.gnu.org/licenses/gpl.txt
#   The GNU Lesser General Public License: http://www.gnu.org/licenses/lgpl.txt
#------------------------------------------------------------------------------
# * Instructions :
#
#   You can place this script pretty much anyway you like.
#   Place it above any other Dialogs you might be using.
#   Increase the STARTING_Z_VALUE if you have trouble with the dialog not
#   on top.
#==============================================================================
class Dialog
  STARTING_Z_VALUE = 1500 # Default value is 1500
  attr_accessor :value
  attr_writer :marked_to_close
  #--------------------------------------------------------------------------
  # * Getter with 'false' as default value
  #--------------------------------------------------------------------------
  def marked_to_close
@marked_to_close = false  if @marked_to_close.nil?
return @marked_to_close
  end
  #--------------------------------------------------------------------------
  # * Mark the dialog to close
  #--------------------------------------------------------------------------
  def mark_to_close
self.marked_to_close = true
  end
  #--------------------------------------------------------------------------
  # * Show the dialog
  #   Returns the value from the dialog
  #--------------------------------------------------------------------------
  def self.show(*args, &block)
dialog = self.new(*args, &block)
dialog.marked_to_close = false
return dialog.main
  end
  #--------------------------------------------------------------------------
  # * Initialization
  #--------------------------------------------------------------------------
  def initialize(*args, &block)
# For subclasses to overwrite
  end
  #--------------------------------------------------------------------------
  # * Main processing
  #--------------------------------------------------------------------------
  def main
# Create the dimmed background
create_background
# Create Windows
main_window
# Main loop
loop do
  # Update game screen
  Graphics.update
  # Update input information
  Input.update
  # Frame update
  update
  # Abort loop if the dialog should close
  if marked_to_close
break
  end
end
# Dispose of windows
main_dispose
# Dispose of background
dispose_background
# Update input information
Input.update
# Returns the acquired value
return self.value
  end
  #--------------------------------------------------------------------------
  # * Create the dimmed background
  #--------------------------------------------------------------------------
  def create_background
bitmap = Bitmap.new(Graphics.width,Graphics.height)
bitmap.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(0,0,0,128))
@background_sprite = Sprite.new
@background_sprite.z = STARTING_Z_VALUE
@background_sprite.bitmap = bitmap
  end
  #--------------------------------------------------------------------------
  # * Create the windows
  #--------------------------------------------------------------------------
  def main_window
# For the subclasses to override
# Remember to set their z.value to at least STARTING_Z_VALUE + 1
  end
  #--------------------------------------------------------------------------
  # * Dispose the background
  #--------------------------------------------------------------------------
  def dispose_background
@background_sprite.dispose
  end
  #--------------------------------------------------------------------------
  # * Dispose the windows
  #--------------------------------------------------------------------------
  def main_dispose
# For the subclasses to override
# Dispose your windows here
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
# For the subclasses to override
if Input.trigger?(Input::B)
  mark_to_close
end
  end
end


A simple Yes/No Dialog: (as an example)
#============================================================================
# * A Simple Yes/No dialog (RMVX)
#============================================================================
class Dialog_YesNo < Dialog
  # self.value: false = No, true = Yes
 
  #--------------------------------------------------------------------------
  # * A show method
  #--------------------------------------------------------------------------
  def initialize(default_value = false, text = nil)
# Sets the default value
self.value = default_value
@text = text
# Sets the menu index
if default_value
  @menu_index = 0
else
  @menu_index = 1
end
  end
  #--------------------------------------------------------------------------
  # * Create the windows
  #--------------------------------------------------------------------------
  def main_window
@disposables = []

# The command window
@command_window = Window_Command.new(80, ['Yes', 'No'])
@command_window.index = @menu_index
@command_window.x = (Graphics.width - @command_window.width) / 2
@command_window.y = (Graphics.height - @command_window.height) / 2
@command_window.z = STARTING_Z_VALUE + 1
@disposables << @command_window

# The text window
if @text.is_a?(String)
  @text_window = Window_Help.new
  @text_window.set_text(@text, 1)
  @text_window.z = STARTING_Z_VALUE + 1
  @disposables << @text_window
end
  end
  #--------------------------------------------------------------------------
  # * Dispose the windows
  #--------------------------------------------------------------------------
  def main_dispose
@disposables.each {|element| element.dispose}
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
@command_window.update
if Input.trigger?(Input::B)
  mark_to_close
  self.value = false
end
if Input.trigger?(Input::C)
  if @command_window.index == 0
self.value = true
  else
self.value = false
  end
  mark_to_close
end
  end
end


An as an actual use here is a code if you want a confirmation dialog when attempting to overwrite an existing save:
class Scene_File
  alias scene_file_dialog_determine_savefile determine_savefile
  #--------------------------------------------------------------------------
  # * Determine savefile
  #--------------------------------------------------------------------------
  def determine_savefile
if @saving && @savefile_windows[@index].file_exist
  var = Dialog_YesNo.show(false, 'Do you want to overwrite' +
' the old savegame?')
  unless var
Sound.play_buzzer
return
  end
end
scene_file_dialog_determine_savefile
  end
end

It is used in the very same way as the RMXP version, so refer to instructions in the previous post on how to use it.

Sally

can someone make a demo, i dont under stand how to set it up :(

Nortos

gj on making VX compat Zeriab and Susy it is really just a script to make it easier for people to make scenes in scripting

Sally


Nortos

Take one of his examples he can add to scene_save that when you choose to save it it asks you "Are you sure you want to overwrite this" you could also say mod into shops asking if you're sure you want to sell it. The main use for it is yes or no and no makes it false canceling the action

Sally

oh.. i kinda get it now.. lol meh

Zeriab

February 17, 2008, 02:38:45 pm #9 Last Edit: February 17, 2008, 02:39:38 pm by Zeriab
Thanks Nortos ^^

@Susys: Uhm... do you still want a demo or don't you care? (I can only make a XP demo)

Fantasist

Do you like ambient/electronic music? Then you should promote a talented artist! Help out here. (I'm serious. Just listen to his work at least!)


The best of freeware reviews: Gizmo's Freeware Reviews