BDR Dialog system
by Fustel
version 1.0
Introduction
In the process of learnig RMVX and RGSS2; and with a future project in mind, I wrote this little Dialog system.
All features I had in mind are not yet implemented, but it works well for now, and any improvment will need somme studies of my own.
Definition of a dialog system
The dialog system handles a number of dialogs, each dialog composed of a topics, each of wich capable of interacting with any other topic or dialog.
The scene is a simple one, with the list of topic listed as in a menu and the answer displaued next to it.
The dialogs are set up using scripted calls to the methods of the differents Objects compsining the Dialog system.
Features
- The dialog list can handle an ulimited number of dialogs
- Each dialog has its own title, greeting topic, and list of topics
- Each dialog can handle an ulimited number of topics
- Topics may be active (displayed) or inactive (hidden)
- When selected, a topics can do the following
* Change any dialog title
* Change any dialog greeting message
* Enable / Disable any topic of any dialog
* Set Game Switbes
- All the above actions of a caption can be set to occure a maximum number of time
- Topics can be set to force a dialog to be terminated or suspended
- Suspended dialogs may be resumed
- The Event calling the dialog may know if it has been exited or suspended
ToDo list
- Add handlers to override the title/greeting/active settings depending on external condirions (have an item, etc...).
- Implement an "Ask question" response to an answer given in a dialog. May be some kind of sub-dialog.
- Write an external software to visualy manage the whole dialogs thing, and generate the set-up ccript.
How to
Code
Exemple of Setup
Screenshot
Demo
I hope you'll enjoy it.
by Fustel
version 1.0
Introduction
In the process of learnig RMVX and RGSS2; and with a future project in mind, I wrote this little Dialog system.
All features I had in mind are not yet implemented, but it works well for now, and any improvment will need somme studies of my own.
Definition of a dialog system
The dialog system handles a number of dialogs, each dialog composed of a topics, each of wich capable of interacting with any other topic or dialog.
The scene is a simple one, with the list of topic listed as in a menu and the answer displaued next to it.
The dialogs are set up using scripted calls to the methods of the differents Objects compsining the Dialog system.
Features
- The dialog list can handle an ulimited number of dialogs
- Each dialog has its own title, greeting topic, and list of topics
- Each dialog can handle an ulimited number of topics
- Topics may be active (displayed) or inactive (hidden)
- When selected, a topics can do the following
* Change any dialog title
* Change any dialog greeting message
* Enable / Disable any topic of any dialog
* Set Game Switbes
- All the above actions of a caption can be set to occure a maximum number of time
- Topics can be set to force a dialog to be terminated or suspended
- Suspended dialogs may be resumed
- The Event calling the dialog may know if it has been exited or suspended
ToDo list
- Add handlers to override the title/greeting/active settings depending on external condirions (have an item, etc...).
- Implement an "Ask question" response to an answer given in a dialog. May be some kind of sub-dialog.
- Write an external software to visualy manage the whole dialogs thing, and generate the set-up ccript.
How to
#------------------------------------------------------------------------------
# INSTRUCTIONS:
# - Place this script above Main
# - Initialize your dialogs below the above one, in the same script or another
# - To process a dialog, have an event run the script:
# start_dialog(<dialog id>)
# (<dialog id> being the id of the processes dialog
# - To resume a suspended dialog, have anEevent call the script
# resume_dialog
# - To test if a dialog is suspended, have an Event make a Condition on the Script
# is_dialog_suspended?
# - To test if a dialog is terminated, have an Event make a Condition on the Script
# is_dialog_terminated?
#------------------------------------------------------------------------------
# NOTES
#
#------------------------------------------------------------------------------
# To initialize the data, you have to ...
#
# - for each dialog
# * add at least a title to each dialog
# $BDR_Dialog[<dialog id>].title = <title>
#
# * set the default greeting
# $BDR_Dialog[<dialog id>].greeting.answer = <greeting message>
#
# - for each topic
# * optionaly change the shortcut
# $BDR_Dialog[<dialog id>].topic(<topic id>).shortcut = <shortcut>
#
# * set the caption
# $BDR_Dialog[<dialog id>].topic(<topic id>).caption = <caption>
#
# * set the answer
# $BDR_Dialog[<dialog id>].dialog(<dialog id>).answer = <answer>
# $BDR_Dialog[<dialog id>].topic(<topic id>).answer = [<answer line1>, <answer line2>]
#
# * optionaly enable it so that it is active at the start of the dialog
# $BDR_Dialog[<dialog id>].topic(<topic id>).enable
#
# * optionaly set dialog titles to be changed
# (<title index> must be an Integer)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_titles = [ <any dialog id>, <title index>]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_titles = [ <any dialog id>, <title index>, n]
#
# * optionaly set dialog greetings to be changed
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_greetings = [ <any dialog id>, <any topic id>]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_greetings = [ <any dialog id>, <any topic id>, n]
#
# * optionaly set other topics to be enabled/diasbled
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_topics = [ <any dialog id>, <any topic id>, true/false]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_topics = [ <any dialog id>, <any topic id>, true/false, n]
#
# * optionaly set Game Switches ON/OFF
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_switches = [ <switch idx>, true/false]
# to have it done only the n first times (default = forever) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_switches = [ <switch idx>, true/false, n]
#
# * optionaly, you can declare a Game Variable to hold the number of time the topic was processed
# (<var idx> must be an Integer>)
# $BDR_Dialog[<dialog id>].topic(<topic id>).processed_count_var = <var idx>
#
# * optionaly set it to force a scene to terminate after orocessing the topic
# $BDR_Dialog[<dialog id>].topic(<topic id>).set_terminate_dlg
#
# * optionaly set it to force a scene to suspend after processing the topic
# $BDR_Dialog[<dialog id>].topic(<topic id>).set_suspend_dlg
#==============================================================================
# INSTRUCTIONS:
# - Place this script above Main
# - Initialize your dialogs below the above one, in the same script or another
# - To process a dialog, have an event run the script:
# start_dialog(<dialog id>)
# (<dialog id> being the id of the processes dialog
# - To resume a suspended dialog, have anEevent call the script
# resume_dialog
# - To test if a dialog is suspended, have an Event make a Condition on the Script
# is_dialog_suspended?
# - To test if a dialog is terminated, have an Event make a Condition on the Script
# is_dialog_terminated?
#------------------------------------------------------------------------------
# NOTES
#
#------------------------------------------------------------------------------
# To initialize the data, you have to ...
#
# - for each dialog
# * add at least a title to each dialog
# $BDR_Dialog[<dialog id>].title = <title>
#
# * set the default greeting
# $BDR_Dialog[<dialog id>].greeting.answer = <greeting message>
#
# - for each topic
# * optionaly change the shortcut
# $BDR_Dialog[<dialog id>].topic(<topic id>).shortcut = <shortcut>
#
# * set the caption
# $BDR_Dialog[<dialog id>].topic(<topic id>).caption = <caption>
#
# * set the answer
# $BDR_Dialog[<dialog id>].dialog(<dialog id>).answer = <answer>
# $BDR_Dialog[<dialog id>].topic(<topic id>).answer = [<answer line1>, <answer line2>]
#
# * optionaly enable it so that it is active at the start of the dialog
# $BDR_Dialog[<dialog id>].topic(<topic id>).enable
#
# * optionaly set dialog titles to be changed
# (<title index> must be an Integer)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_titles = [ <any dialog id>, <title index>]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_titles = [ <any dialog id>, <title index>, n]
#
# * optionaly set dialog greetings to be changed
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_greetings = [ <any dialog id>, <any topic id>]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_greetings = [ <any dialog id>, <any topic id>, n]
#
# * optionaly set other topics to be enabled/diasbled
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_topics = [ <any dialog id>, <any topic id>, true/false]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_topics = [ <any dialog id>, <any topic id>, true/false, n]
#
# * optionaly set Game Switches ON/OFF
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_switches = [ <switch idx>, true/false]
# to have it done only the n first times (default = forever) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_switches = [ <switch idx>, true/false, n]
#
# * optionaly, you can declare a Game Variable to hold the number of time the topic was processed
# (<var idx> must be an Integer>)
# $BDR_Dialog[<dialog id>].topic(<topic id>).processed_count_var = <var idx>
#
# * optionaly set it to force a scene to terminate after orocessing the topic
# $BDR_Dialog[<dialog id>].topic(<topic id>).set_terminate_dlg
#
# * optionaly set it to force a scene to suspend after processing the topic
# $BDR_Dialog[<dialog id>].topic(<topic id>).set_suspend_dlg
#==============================================================================
Code
Code:
#==============================================================================
# ** BDR Dialog
#------------------------------------------------------------------------------
# © Fustel, 2008
# 05/11/08
# Version 1.0
#------------------------------------------------------------------------------
# VERSION HISTORY:
# - 1.0 (05/11/08), Initial release
#------------------------------------------------------------------------------
# INSTRUCTIONS:
# - Place this script above Main
# - Initialize your dialogs below the above one, in the same script or another
# - To process a dialog, have an event run the script:
# start_dialog(<dialog id>)
# (<dialog id> being the id of the processes dialog
# - To resume a suspended dialog, have anEevent call the script
# resume_dialog
# - To test if a dialog is suspended, have an Event make a Condition on the Script
# is_dialog_suspended?
# - To test if a dialog is terminated, have an Event make a Condition on the Script
# is_dialog_terminated?
#------------------------------------------------------------------------------
# NOTES
#
#------------------------------------------------------------------------------
# To initialize the data, you have to ...
#
# - for each dialog
# * add at least a title to each dialog
# $BDR_Dialog[<dialog id>].title = <title>
#
# * set the default greeting
# $BDR_Dialog[<dialog id>].greeting.answer = <greeting message>
#
# - for each topic
# * optionaly change the shortcut
# $BDR_Dialog[<dialog id>].topic(<topic id>).shortcut = <shortcut>
#
# * set the caption
# $BDR_Dialog[<dialog id>].topic(<topic id>).caption = <caption>
#
# * set the answer
# $BDR_Dialog[<dialog id>].dialog(<dialog id>).answer = <answer>
# $BDR_Dialog[<dialog id>].topic(<topic id>).answer = [<answer line1>, <answer line2>]
#
# * optionaly enable it so that it is active at the start of the dialog
# $BDR_Dialog[<dialog id>].topic(<topic id>).enable
#
# * optionaly set dialog titles to be changed
# (<title index> must be an Integer)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_titles = [ <any dialog id>, <title index>]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_titles = [ <any dialog id>, <title index>, n]
#
# * optionaly set dialog greetings to be changed
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_greetings = [ <any dialog id>, <any topic id>]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_greetings = [ <any dialog id>, <any topic id>, n]
#
# * optionaly set other topics to be enabled/diasbled
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_topics = [ <any dialog id>, <any topic id>, true/false]
# to have it done only the n first times (default = 1st time only) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_topics = [ <any dialog id>, <any topic id>, true/false, n]
#
# * optionaly set Game Switches ON/OFF
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_switches = [ <switch idx>, true/false]
# to have it done only the n first times (default = forever) the topic is triggered (0 or less => forever)
# $BDR_Dialog[<dialog id>].topic(<topic id>).linked_switches = [ <switch idx>, true/false, n]
#
# * optionaly, you can declare a Game Variable to hold the number of time the topic was processed
# (<var idx> must be an Integer>)
# $BDR_Dialog[<dialog id>].topic(<topic id>).processed_count_var = <var idx>
#
# * optionaly set it to force a scene to terminate after orocessing the topic
# $BDR_Dialog[<dialog id>].topic(<topic id>).set_terminate_dlg
#
# * optionaly set it to force a scene to suspend after processing the topic
# $BDR_Dialog[<dialog id>].topic(<topic id>).set_suspend_dlg
#==============================================================================
#=====================================================================================================
# classes for BDR-Dialog
#=====================================================================================================
#=====================================================================================================
# BDR_Dlg_Topic
# defines a topic used in a dialog.
# a dialog is composed of many topics, but they may be discovered as the dialog goes on
#
# A topic has the following properties :
# - owner (R) : a pointer to its owning dialog
# - index (R) : the order of its creation, used internaly to sort the topics
# - id (R) : its id in the topics list of a dialog
# - processed_count (R) : the numeber of time the topic has been processed
# - orocessed_count_var (R/W) : idx of the Game Variable hodling the processed count
# - shortcut (R/W) : the shortcut displayed in the topics list of the dialog scene
# by default, it is set to its id
# - caption (R/W) : the one-line text displayed at the bottom of the dialog scene
# - answer (R/W) : the multi-line answer displayed in the main window of the dialog scene
# if an Array is assigned the answer is set to it, each elemnt representing a line
# if a non-array is assigned, it is added as a new line
# - enabled? (R) : determine the active state of the topic.
# only active topics are displayed in the topic list of the dialog scene
# can be set ON with the enable method
# can be set OFF with the disable method
# - linked_titles (W) : adds a title index to be set as the active title for the given dialog
# the list is proceeded when the current topic is activated in the dialog scene
# must be set to an array containig :
# * the id of the dialog
# * the index of the title to be activeted (0 by default)
# * the number of time this change may be done (1 by default)
# - linked_greetings (W) : adds a topic id to be set as the active greeting for the given dialog
# the list is proceeded when the current topic is activated in the dialog scene
# must be set to an array containig :
# * the id of the dialog
# * the id of the topic to be set as the greeting
# * the number of time this change may be done (1 by default)
# - linked_topics (W) : adds a topic id to be enabled/disabled for the given dialog
# the list is proceeded when the current topic is activated in the dialog scene
# must be set to an array containig :
# * the id of the dialog
# * the id of the topic to be set as the greeting
# * the state of the topic (true = enabled, false = disabled) (false by default)
# * the number of time this change may be done (1 by default)
# - linked_switches (W) : adds a Game Switch to be set
# the list is proceeded when the current topic is activated in the dialog scene
# must be set to an array containig :
# * the idx of the switch (must be an Integer)
# * the state of the switch (true or false) (false by default)
# * the number of time this change may be done (0 by default => forever)
# - is_continue_dlg? (R) : dialog is neither a "terminate" not a "suspend" ond. default state
# - is_terminate_dlg? (R) : if true, terminates the dialog scene immediately after executing the process_topic!
# - is_suspend_dlg? (R) : if true, suspend the dialog scene immediately after executing the process_topic!
#
# A topic may perform the following actions (methods)
# - enable : sets the enable state to true
# - disable: sets the enable state to false
# - set_continue_dlg : sets the "end of dialog" state to "continue"
# - set_terminate_dlg : sets the "end of dialog" state to "terminate"
# - set_suspend_dlg : sets the "end of dialog" state to "suspend"
# - update_linked_title!
# processes the linked_titles list to set active dialog titles
# - update_linked_greetings!
# processes the linked_greetings list to set active dialog greetings
# - update_linked_topics!
# processes the linked_topics list to enable/disable topics
# - update_linked_switches!
# processes the linked_switches list to set Game Switches
# - process_topic!
# count the number of processing of the topic
# process all the linked_<something> lists
#-----------------------------------------------------------------------------------------------------
class BDR_Dlg_Topic
attr_reader :owner
attr_reader :index
attr_reader :id
attr_reader :processed_count
attr_reader :processed_count_var
attr_reader :shortcut
attr_reader :caption
attr_reader :answer
def initialize(owner, index, id)
@owner = owner # owning dialog
@index = index # order of insertion in the dialog
@id = id # id, displayed in the topic list
@processed_count = 0 # number of procressing of the topic
@processed_count_var = nil # idx of the Game Variable receiving the processed count
@shortcut = id # shortcut displayed in the topic list
@caption = "" # the topic the PC wnats to discuss
@answer = [] # the answer the NPC will guive
@enabled = false # active state of the topic
@lnk_ttl = [] # list of dialog title to change
@lnk_grt = [] # list of greetings to change
@lnk_tpc = [] # list of topics to enable/disable
@lnk_swt = [] # list of Game Swithches to set
@end_of_dlg = 0 # 0 => do not end dialog, 1 => terminate dailog, 2 => suspend dialog
end
# writer for @processed_count_var
#---------------------------------------------------------------------------------------------------
def processed_count_var=(idx)
if idx.is_a?(Integer)
@processed_count_var = idx
end
end
# writer for @shortcut
# sets it to a String
#---------------------------------------------------------------------------------------------------
def shortcut=(txt)
@shortcut = txt.to_s
end
# writer for @caption
# sets it to a String
#---------------------------------------------------------------------------------------------------
def caption=(txt)
@caption = txt.to_s
end
# writer for @answer
# sets it to an Array of strings if an Array is the parameter
# adds the parameter as a String to the existing Array if is not an Array
#---------------------------------------------------------------------------------------------------
def answer=(txt)
if txt.is_a?(Array)
@answer = []
for l in txt do
@answer += [l.to_s]
end
else
@answer += [txt.to_s]
end
end
# writer for @enabled
# sets it to true
#---------------------------------------------------------------------------------------------------
def enable
@enabled = true
end
# writer for @enabled
# sets it to false
#---------------------------------------------------------------------------------------------------
def disable
@enabled = false
end
# reader for @enabled
# nb: may process a handler in future versions to handle external conditions
#---------------------------------------------------------------------------------------------------
def enabled?
@enabled
end
# writer for @lnk_ttl
# adds a Array containing
# - dialog id
# - title index
# - optional number of change that can be done (default = 1)
#---------------------------------------------------------------------------------------------------
def linked_titles=(keys)
k = keys.to_a
idx = 0
idx = k[1] if k[1].is_a?(Integer)
nmx = 1
nmx = k[2] if k[2].is_a?(Integer)
@lnk_ttl += [[k[0].to_s, idx, nmx]]
end
# processor for @lnk_ttl
#---------------------------------------------------------------------------------------------------
def update_linked_titles!
for (key, idx, nmx) in @lnk_ttl do
if (nmx <= 0) or (processed_count <= nmx)
owner.owner[key].title_idx = idx
end
end
end
# writer for @lnk_grt
# adds an Array containing
# - dialog id
# - topic id
# - optional number of change that can be done (default = 1)
#---------------------------------------------------------------------------------------------------
def linked_greetings=(keys)
k = keys.to_a
nmx = 1
nmx = k[2] if k[2].is_a?(Integer)
@lnk_grt += [[k[0].to_s, k[1].to_s, nmx]]
end
# processor for @lnk_grt
#---------------------------------------------------------------------------------------------------
def update_linked_greetings!
for (dkey, gkey, nmx) in @lnk_grt do
if (nmx <= 0) or (processed_count <= nmx)
owner.owner[dkey].greeting_id = gkey
end
end
end
# writer for @lnk_tpc : add the 3 1st element of the argument as an array the list
# adds an Array containing
# - dialog id
# - topic id
# - active/inactive flag
# - optional number of change that can be done (default = 1)
#---------------------------------------------------------------------------------------------------
def linked_topics=(keys)
k = keys.to_a
nmx = 1
nmx = k[3] if k[3].is_a?(Integer)
@lnk_tpc += [[k[0].to_s, k[1].to_s, keys[2], nmx]]
end
# processor for @lnk_tpc
#---------------------------------------------------------------------------------------------------
def update_linked_topics!
for (dkey, tkey, ok, nmx) in @lnk_tpc do
if (nmx <= 0) or (processed_count <= nmx)
if ok
owner.owner[dkey].topic(tkey).enable
else
owner.owner[dkey].topic(tkey).disable
end
end
end
end
# writer for @lnk_swt : add the 3 1st element of the argument as an array the list
# adds an Array containing
# - switch idx
# - boolea state
# - optional number of change that can be done (default = 1)
#---------------------------------------------------------------------------------------------------
def linked_switches=(keys)
k = keys.to_a
idx = k[0]
nmx = 0
nmx = k[2] if k[2].is_a?(Integer)
if idx.is_a?(Integer)
@lnk_swt += [[idx, k[1], nmx]]
end
end
# processor for @lnk_swt
#---------------------------------------------------------------------------------------------------
def update_linked_switches!
for (idx, ok, nmx) in @lnk_swt do
if (nmx <= 0) or (processed_count <= nmx)
if ok
$game_switches[ idx] = true
else
$game_switches[ idx] = false
end
end
end
end
# processor for
# - @lnk_ttl
# - @lnk_grt
# - @lnk_tpc
#---------------------------------------------------------------------------------------------------
def process_topic!
@processed_count += 1
if @processed_count_var.is_a?(Integer)
$game_variables[@processed_count_var] = processed_count
end
update_linked_titles!
update_linked_greetings!
update_linked_topics!
update_linked_switches!
end
# writer to @end_of_dlg
# sets it to 0 (continue dlg)
#---------------------------------------------------------------------------------------------------
def set_continue_dlg
@end_of_dlg = 0
end
# writer to @end_of_dlg
# sets it to 1 (terminate dlg)
#---------------------------------------------------------------------------------------------------
def set_terminate_dlg
@end_of_dlg = 1
end
# writer to @end_of_dlg
# sets it to 2 (suspend dlg)
#---------------------------------------------------------------------------------------------------
def set_suspend_dlg
@end_of_dlg = 2
end
# reader for @end_of_dlg
# true if 0 (continue)
#---------------------------------------------------------------------------------------------------
def is_continue_dlg?
@end_of_dlg == 0
end
# reader for @end_of_dlg
# true if 1 (terminate)
#---------------------------------------------------------------------------------------------------
def is_terminate_dlg?
@end_of_dlg == 1
end
# reader for @end_of_dlg
# true if 2 (suspend)
#---------------------------------------------------------------------------------------------------
def is_suspend_dlg?
@end_of_dlg == 2
end
end
#=====================================================================================================
# BDR_Dlg_Dialog
# defines a dialog
# a dialog is composed of many topics, but they may be discovered as the dialog goes on
# generally, a dilog contains all what you have to discuss with a single NPC
# a dialog may by modified by topics discussed even with other NPCs
#
# A dialog has the following properties :
# - owner (R) : a pointer to its owning dialog list
# - id (R) : its id in its owning dialog list
# - title (R) : its active title displayed at the top of the dialog scene
# - title (W) : list of all potential titles
# if an Array is assigned the title is set to it
# if a non-array is assigned, it is added to the list
# - title_idx (R/W) : the index to its active title in the title list (0 by default)
# - topic(id) (R) : the topic identified by its id
# to add a topic to the dialog, you just have to read it !! like
# * $BDR_dilaog[<dialog id>].topic(<topic id>).caption = <caption text>
# * s = $BDR_dilaog[<dialog id>].topic(<topic id>).caption
# - greeting (R) : the topic used when the dialog is entered
# same as topic(greeting_id)
# - greeting_id (R/W) : the id of the topic used as a greeting ("" by default)
# - active_topics (R) : the list of all the enabled topic ids
#-----------------------------------------------------------------------------------------------------
class BDR_Dlg_Dialog
attr_reader :owner
attr_reader :id
attr_reader :title_idx
attr_reader :greeting_id
def initialize(owner, id)
@owner = owner # owning dialog list
@id = id # id
@titles = [] # list of text displayable at the top of the dialog scene
@title_idx = 0 # the index of the active title
@greeting_id ="" # identifier of the greeting topic
@topics = {} # list of topics
end
# reader for @titles
# returns the title identified by @title_idx
# nb: may process a handler in future versions to handle external conditions
#---------------------------------------------------------------------------------------------------
def title
@titles[@title_idx].to_s
end
# writer for @titles
# sets it to an Array of strings if an Array is the parameter
# adds the parameter as a String to the existing Array if is not an Array
#---------------------------------------------------------------------------------------------------
def title=(txt)
if txt.is_a?(Array)
@titles = []
for l in txt do
@titles += [ l.to_s]
end
else
@titles += [txt.to_s]
end
end
# writer for @title_idx
#---------------------------------------------------------------------------------------------------
def title_idx=(idx)
@title_idx = [idx,0].max if idx.is_a?(Integer)
end
# reader for @topics
# returns the topic identified by <key>
# create a topic if non-existent
#---------------------------------------------------------------------------------------------------
def topic(key)
k = key.to_s
if @topics[k].nil?
@topics[k] = BDR_Dlg_Topic.new(self, @topics.size, k)
end
@topics[k]
end
# writer the @greeting_id
#---------------------------------------------------------------------------------------------------
def greeting_id=(key)
@greeting_id = key.to_s
end
# reader for @topics
# returns the topic identified by @greeting_id
#---------------------------------------------------------------------------------------------------
def greeting
topic(@greeting_id)
end
# reader for @topics
# returns an Array containing the ids of the enabled? topics
#---------------------------------------------------------------------------------------------------
def active_topics
r = []
# for (k, t) in @topics do
# to ensure a sorting by order of creation of the topics
for (k, t) in @topics.sort {|a,b| a[1].index <=> b[1].index} do
if t.enabled?
r += [k]
end
end
r
end
end
#=====================================================================================================
# BDR_Dlg_Dialogs
# the main class : the dialog list
# contains oll the dialog in a game
#
# its instance is BDR_Dialog
#
# it has the following properties :
# - [id] (R) : the dialog identified by its id
# to add a dialog to the list, you just have to read it !! like
# * $BDR_dilaog[<dialog id>].topic(<topic id>).caption = <caption text>
# * s = $BDR_dilaog[<dialog id>].topic(<topic id>).caption
# - suspend_dialog_id (R) : key of the suspending dialog
# - suspend_topic_id (R) : key of the suspending topic
# - is_terminated? (R) : true if the dialog scene was 'terminated', false if 'suspended'
# - is_suspended? (R) : false if the dialog scene was 'terminated', true if 'suspended'
#
# it can perform the following actions (methods)
# - set_terminated : set the exit status to 'terminated'
# - set_suspended : set the exit status to 'suspended'
#-----------------------------------------------------------------------------------------------------
class BDR_Dlg_Dialogs
attr_reader :suspend_dialog_id
attr_reader :suspend_topic_id
def initialize
@dialogs = {} # list of dialogs
@suspend_dialog_id = "" # key of suspending dialog
@suspend_topic_id = "" # key of suspending topic
@terminated = true # true = 'terminated', false = 'suspended'
end
# reader for @dialogs : returns the dialog identified by a key
# create a topic if non existent
#---------------------------------------------------------------------------------------------------
def [](key)
k = key.to_s
if @dialogs[k].nil?
@dialogs[k] = BDR_Dlg_Dialog.new(self, k)
end
@dialogs[k]
end
# writer for terminated
# sets it to true ('terminated')
#---------------------------------------------------------------------------------------------------
def set_terminated
@terminated = true
end
# writer for terminated
# sets it to false ('suspended')
#---------------------------------------------------------------------------------------------------
def set_suspended(dkey, tkey)
@suspend_dialog_id = dkey
@suspend_topic_id = tkey
@terminated = false
end
# reader for @terminated
#---------------------------------------------------------------------------------------------------
def is_terminated?
@terminated
end
# reader for @terminated
#---------------------------------------------------------------------------------------------------
def is_suspended?
not @terminated
end
end
#=====================================================================================================
# overriting of Scene_File for saving/loading of $BDR_Dialog
#=====================================================================================================
class Scene_File < Scene_Base
alias old_write_save_data write_save_data
alias old_read_save_data read_save_data
def write_save_data(file)
old_write_save_data(file)
Marshal.dump($BDR_Dialog,file)
end
def read_save_data(file)
old_read_save_data(file)
$BDR_Dialog=Marshal.load(file)
end
end
#=====================================================================================================
# instanciation of BDR_Dlg_Dialogs
#=====================================================================================================
$BDR_Dialog = BDR_Dlg_Dialogs.new
#=====================================================================================================
# the Scene using $BDR_Dialog
#=====================================================================================================
# to call it, have the Event execute the script:
# start_dialog(<dialog id>)
# with <dialog id> being the id of the dialog you want to handle
#-----------------------------------------------------------------------------------------------------
class Scene_BDR_Dlg < Scene_Base
def initialize(dlg=nil)
@dialog = dlg # the dialog being processed
@sel_topic = "" # id of the topic "under the cursor"
@active_topics_id = [] # list of active topic ids
@active_topics_short = [] # list of the sama active topic ids, to be passed to the command window
@dialog = $BDR_Dialog.suspend_dialog_id if $BDR_Dialog.is_suspended?
end
# to myself : a screen is 544*416
#---------------------------------------------------------------------------------------------------
def start
super
Sound.play_decision
create_menu_background
# create the answer window and display the greeting
ogreeting = $BDR_Dialog[@dialog].greeting_id
if $BDR_Dialog.is_suspended? # use the 'suspend' topic as the greeting
$BDR_Dialog[@dialog].greeting_id = $BDR_Dialog.suspend_topic_id
end
@win_answer = Window_Base.new(0,64,406,288)
show_greeting
if $BDR_Dialog.is_suspended? # restore the 'normal' greeting
$BDR_Dialog[@dialog].greeting_id = ogreeting
else # the 'suspend' topic has already been orocesses at suspention time
$BDR_Dialog[@dialog].greeting.process_topic! #
end
# create title window
@win_title = Window_Base.new(0,0,544,57)
update_title
# create the initial wommand window
create_topics
# create the caption window
@win_caption = Window_Base.new(0,359,544,57)
update_caption
$BDR_Dialog.set_terminated
end
def terminate
@win_answer.dispose
@win_caption.dispose
@win_topics.dispose
@win_title.dispose
dispose_menu_background
super
end
def update
oindex = @win_topics.index
super
update_menu_background
@win_topics.update
# if the cursor in the command window moved => do the apropriate display updates
if @win_topics.index != oindex
@sel_topic = @active_topics_id[@win_topics.index]
update_caption
end
# if B-key => exit
if Input.trigger?(Input::B)
Sound.play_cancel
do_terminate
end
# if C-key => process the selected topic
if Input.trigger?(Input::C)
Sound.play_decision
update_topics
end
end
# create the command window
def create_topics
if $BDR_Dialog.is_suspended?
# get old shortcut for memorized datas
oidx = 0
oshort = $BDR_Dialog.suspend_topic_id
else
# memorize the SHORTCUT of the topic selected
oidx = @active_topics_id.index(@sel_topic)
oshort = @active_topics_short[oidx] unless oidx.nil?
end
if not @win_topics.nil?
@win_topics.dispose
end
get_active_topics
@win_topics = Window_Command.new(136,@active_topics_short)
@win_topics.x = 408
@win_topics.y = 64
@win_topics.height = 288
# reposition the cursor at the same SHROTCUT as before the window recreation
if not oidx.nil? and @active_topics_short.include?( oshort)
@win_topics.index = @active_topics_short.index( oshort)
end
@sel_topic = @active_topics_id[@win_topics.index]
end
# update the title window
def update_title
@win_title.contents.clear
@win_title.contents.draw_text(0,0,512,25,$BDR_Dialog[@dialog].title,1)
end
# update the command window and its dependancies
def update_topics
update_answer
$BDR_Dialog[@dialog].topic(@sel_topic).process_topic!
create_topics # re-create the command window as the active topics list may have changed
update_title
update_caption
do_terminate if $BDR_Dialog[@dialog].topic(@sel_topic).is_terminate_dlg?
do_suspend if $BDR_Dialog[@dialog].topic(@sel_topic).is_suspend_dlg?
end
# update the caption window
def update_caption
@win_caption.contents.clear
@win_caption.contents.draw_text(0,0,512,25,$BDR_Dialog[@dialog].topic(@sel_topic).caption)
end
# display an answer
def update_answer
update_answer_with($BDR_Dialog[@dialog].topic(@sel_topic).answer)
end
# display the greeting
def show_greeting
update_answer_with($BDR_Dialog[@dialog].greeting.answer)
end
# general update of the answer window with a generic answer
def update_answer_with(txt)
@win_answer.contents.clear
t = txt.to_a
n=0
for l in t do
@win_answer.contents.draw_text(0,n*20,374,20,l)
n +=1
end
end
# get both active topics lists
def get_active_topics
@active_topics_id = $BDR_Dialog[@dialog].active_topics
@active_topics_short = []
for key in @active_topics_id do
@active_topics_short += [$BDR_Dialog[@dialog].topic(key).shortcut]
end
end
# performs the terminate procedure
def do_terminate
$BDR_Dialog.set_terminated
$scene = Scene_Map.new
end
# performs the suspend procedure
def do_suspend
$BDR_Dialog.set_suspended(@dialog,@active_topics_short[@win_topics.index])
$scene = Scene_Map.new
end
end
#=====================================================================================================
# general function to start the dialog scene
#-----------------------------------------------------------------------------------------------------
def start_dialog(id)
$scene = Scene_BDR_Dlg.new(id)
@wait_count = 1
end
def resume_dialog
$scene = Scene_BDR_Dlg.new
@wait_count = 1
end
def is_dialog_suspended?
$BDR_Dialog.is_suspended?
end
def is_dialog_terminated?
$BDR_Dialog.is_terminated?
end
Exemple of Setup
Code:
#=====================================================================================================
# initializing $BDR_Dialog data for the demo
# use of a 'to-be-writen' external software may help !!
#
# see INSTRUCTION to know how to initialize the dialogs
#=====================================================================================================
# Barnaby's dialog
$BDR_Dialog["Barnaby"].title = ["man with a funny hat","Brother Barnaby"]
$BDR_Dialog["Barnaby"].title = "Brother Barnaby the Healer"
$BDR_Dialog["Barnaby"].title = "Brother Barnaby the unpatient Healer"
$BDR_Dialog["Barnaby"].greeting.answer = "Hello"
$BDR_Dialog["Barnaby"].greeting.answer = "How do you do?"
$BDR_Dialog["Barnaby"].greeting.linked_greetings = ["Barnaby","hello"]
$BDR_Dialog["Barnaby"].topic("hello").answer = ["Hello","Didn't we meet already ?"]
$BDR_Dialog["Barnaby"].topic("Name").caption = "What is your name ?"
$BDR_Dialog["Barnaby"].topic("Name").answer = "I am Brother Barnaby"
$BDR_Dialog["Barnaby"].topic("Name").linked_titles = ["Barnaby", 1]
$BDR_Dialog["Barnaby"].topic("Name").linked_topics = ["Barnaby", "Job0", false]
$BDR_Dialog["Barnaby"].topic("Name").linked_topics = ["Barnaby", "Job1", true]
$BDR_Dialog["Barnaby"].topic("Name").linked_topics = ["Barnaby", "Job2", false]
$BDR_Dialog["Barnaby"].topic("Name").enable
$BDR_Dialog["Barnaby"].topic("Job0").shortcut = "Job"
$BDR_Dialog["Barnaby"].topic("Job0").caption = "What is your job ?"
$BDR_Dialog["Barnaby"].topic("Job0").answer = "How rude !!"
$BDR_Dialog["Barnaby"].topic("Job0").answer = "We have not yet being introduced"
$BDR_Dialog["Barnaby"].topic("Job0").enable
$BDR_Dialog["Barnaby"].topic("Job1").shortcut = "Job"
$BDR_Dialog["Barnaby"].topic("Job1").caption = "What is your job ?"
$BDR_Dialog["Barnaby"].topic("Job1").answer = "I am a healer"
$BDR_Dialog["Barnaby"].topic("Job1").answer = "I can also give you a couple of potions"
$BDR_Dialog["Barnaby"].topic("Job1").linked_titles = ["Barnaby", 2]
$BDR_Dialog["Barnaby"].topic("Job1").linked_topics = ["Barnaby", "Job1", false]
$BDR_Dialog["Barnaby"].topic("Job1").linked_topics = ["Barnaby", "Job2", true, 0]
$BDR_Dialog["Barnaby"].topic("Job1").linked_topics = ["Barnaby", "Heal", true]
$BDR_Dialog["Barnaby"].topic("Job1").linked_topics = ["Barnaby", "Potion", true]
$BDR_Dialog["Barnaby"].topic("Job2").shortcut = "Job"
$BDR_Dialog["Barnaby"].topic("Job2").caption = "What is your job ?"
$BDR_Dialog["Barnaby"].topic("Job2").answer = ["I already told you ...","I am a healer !!!!"]
$BDR_Dialog["Barnaby"].topic("Job2").answer = ""
$BDR_Dialog["Barnaby"].topic("Job2").answer = "And not a patient one !!!!"
$BDR_Dialog["Barnaby"].topic("Job2").linked_titles = ["Barnaby", 3]
$BDR_Dialog["Barnaby"].topic("Heal").caption = "Could you heal me ?"
$BDR_Dialog["Barnaby"].topic("Heal").answer = "Do you fell better ?"
$BDR_Dialog["Barnaby"].topic("Heal").linked_switches = [ 1, true]
$BDR_Dialog["Barnaby"].topic("Heal").set_suspend_dlg
$BDR_Dialog["Barnaby"].topic("Potion").caption = "I'd like some potion"
$BDR_Dialog["Barnaby"].topic("Potion").answer = "Pay attention, my stock is limited ?"
$BDR_Dialog["Barnaby"].topic("Potion").linked_switches = [ 2, true]
$BDR_Dialog["Barnaby"].topic("Potion").linked_switches = [ 3, true, 5]
$BDR_Dialog["Barnaby"].topic("Potion").processed_count_var = 1
$BDR_Dialog["Barnaby"].topic("Potion").set_suspend_dlg
$BDR_Dialog["Barnaby"].topic("Bye").caption = "Au revoir !!"
$BDR_Dialog["Barnaby"].topic("Bye").set_terminate_dlg
$BDR_Dialog["Barnaby"].topic("Bye").enable
# Rosemonde's dialog
$BDR_Dialog["Rosemonde"].title = "ugly woman with warts on her face"
$BDR_Dialog["Rosemonde"].title = "Rosemonde"
$BDR_Dialog["Rosemonde"].greeting.answer = "Hi, handsome hero !"
$BDR_Dialog["Rosemonde"].topic("Name").caption = "What is your name ?"
$BDR_Dialog["Rosemonde"].topic("Name").answer = "I am Rosemonde"
$BDR_Dialog["Rosemonde"].topic("Name").answer = "And Barnaby's sister"
$BDR_Dialog["Rosemonde"].topic("Name").linked_titles = ["Rosemonde",1]
$BDR_Dialog["Rosemonde"].topic("Name").linked_topics = ["Rosemonde","Barnaby",true]
$BDR_Dialog["Rosemonde"].topic("Name").enable
$BDR_Dialog["Rosemonde"].topic("Barnaby").caption = "Who is Barnaby ?"
$BDR_Dialog["Rosemonde"].topic("Barnaby").answer = "It's the guu you can see over there"
$BDR_Dialog["Rosemonde"].topic("Barnaby").answer = "He is a healer"
$BDR_Dialog["Rosemonde"].topic("Barnaby").linked_switches = [4, true]
$BDR_Dialog["Rosemonde"].topic("Barnaby").linked_titles = ["Barnaby", 2]
$BDR_Dialog["Rosemonde"].topic("Barnaby").linked_topics = ["Barnaby", "Job0", false]
$BDR_Dialog["Rosemonde"].topic("Barnaby").linked_topics = ["Barnaby", "Job1", true]
$BDR_Dialog["Rosemonde"].topic("Barnaby").linked_topics = ["Barnaby", "Job2", false]
$BDR_Dialog["Rosemonde"].topic("Barnaby").linked_topics = ["Barnaby", "Heal", true]
$BDR_Dialog["Rosemonde"].topic("Barnaby").set_suspend_dlg
$BDR_Dialog["Rosemonde"].topic("Bye").caption = "Goodbye"
$BDR_Dialog["Rosemonde"].topic("Bye").set_terminate_dlg
$BDR_Dialog["Rosemonde"].topic("Bye").enable
Screenshot
<just looking for how to load an image for now...>
Demo
I hope you'll enjoy it.