Envision, Create, Share

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

[VX] BDR Dialog system

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

#------------------------------------------------------------------------------
#  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

You should be able to download the Demo there :

http://www.mediafire.com/download.php?ti31ynm5oym


I hope you'll enjoy it.
 

Thank you for viewing

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

Discord

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

Content

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