How does Glitchfinder's "Multiple Timers" Script Work?

Discussion in 'RGSSx Script Support' started by Yokiko, Sep 18, 2018.

Thread Status:
Not open for further replies.
  1. Yokiko

    Yokiko Villager Member

    Messages:
    24
    Likes Received:
    2
    First Language:
    German
    Primarily Uses:
    RMVX
    Hello everyone!

    Sooo, I tried to figure this out for at least 24 hours, but I did not find a solution. It's about a script called "Multiple Timers" by Glitchfinder. As the title implicates, it lets you several timers that run independently from each other. Even though it was originally made for XP, Glitchfinder states that it also works for VX. I really need it to make the on-map enemies respawn after a specific time even if the player goes to another map.

    By calling "Game_Timer.start", the timer successfully starts but I did not quite understand how to trigger an event after the timer runs out.

    Using the call "Game_Timer.finished?" did not do it for me, since it didn't change the boolean to true even after the countdown reaches 0. It could be possible that I didn't use the call correctly but I don't know what I could have done wrong.

    Alternatively, Glitchfinder posted an instruction on how to trigger an event by using a conditional branch. They said to add "$game_temp.game_timer.check(timer_number)" to the conditional branch script line if a timer has already been activated. I tried to do it but I guess this function only works in XP, since the project I tested it with gave me an error message:

    "NoMethodError occurred while running script.
    undefined method `game_timer´ for #<Game_Temp:0x360c248>"

    TL;DR - Could somebody please help me figuring out how to trigger an event after the timers run out? That would be very appreciated!

    Here's the script:

    Code:
        #≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
        # ** Glitchfinder's Multiple Timers               [RPG Maker XP] [RPG Maker VX]
        #    Version 3.44
        #------------------------------------------------------------------------------
        #  This script helps scripters and eventers use multiple hidden in-game timers
        #  that can be called and modified at any time. Refer to "Game_Timer" for the
        #  instance of this class.
        #==============================================================================
        # * Version History
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        #   Version 1.00 ------------------------------------------------- (??????????)
        #     - Initial version
        #     - Author: Glitchfinder
        #   Version 2.00 ------------------------------------------------- (2008-06-11)
        #     - Script completely rewritten to work with multiple timers
        #     - Author: Glitchfinder
        #    Version 2.10 ------------------------------------------------ (2002-06-18)
        #      - Added the check_timing() method
        #      - Fixed bug with check() method
        #      - Author: Glitchfinder
        #     Version 2.11 ----------------------------------------------- (2007-06-19)
        #       - Reformatted and cleaned script
        #       - Author: Glitchfinder
        #    Version 2.21 ------------------------------------------------ (2007-06-22)
        #      - Added the extended_start() method
        #      - Author: Glitchfinder
        #    Version 2.31 ------------------------------------------------ (2007-07-20)
        #      - Added the update_single() method
        #      - Added the kill_timer() method
        #      - Added the adjust_time() method
        #      - Author: Glitchfinder
        #     Version 2.32 ----------------------------------------------- (2007-07-24)
        #       - Fixed bug with VX and the start() method
        #       - Fixed bug with VX and the extended_start() method
        #       - Author: Glitchfinder
        #   Version 3.32 ------------------------------------------------- (2009-06-28)
        #     - Script completely rewritten to increase efficiency
        #     - Modified most methods to include error-checking
        #     - Renamed the check() method to finished?()
        #     - Removed the modifications of Game_Temp
        #     - Added the script to the global variable $game_timer
        #     - Added new output to the check_timing() method
        #     - Modified the update() method of Scene_Battle
        #     - Added the ability for a timer to end battle
        #     - Added the end_battle() method
        #     - Added the end_battle?() method
        #     - Modified the update() method of Sprite_Timer
        #     - Added the ability to display a timer using Sprite_Timer
        #     - Modified the "Conditional Branch..." event command
        #     - Modified the "Control Variables..." event command
        #     - Modified the "Control Timer..." event command
        #     - Replaced the default timer with $game_timer
        #     - Added the display() method
        #     - Added the display?() method
        #     - Modified the write_save_data() method of Scene_Save
        #     - Modified the read_save_data() method of Scene_Load
        #     - Added the ability to save a timer when the game is saved
        #     - Added the save() method
        #     - Added the save?() method
        #     - Added the load_save() method
        #     - Author: Glitchfinder
        #     Version 3.33 ----------------------------------------------- (2009-06-28)
        #       - Script optimized further
        #       - Unnecessary lines removed
        #       - Code efficiency improved
        #       - Author: theory
        #     Version 3.34 ----------------------------------------------- (2009-06-29)
        #       - Script optimized
        #       - Unnecessary lines removed
        #       - Author: Glitchfinder
        #     Version 3.44 ----------------------------------------------- (2011-03-16)
        #       - Fixed Crash on F12
        #       - Converted $game_timer global into the Game_Timer module.
        #       - Author: Glitchfinder
        #==============================================================================
        # * Instructions
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        #  Place this script above Main, and below the default scripts. (I realize this
        #  is obvious to most, but some people don't get it.)
        #
        #  To start a timer, use the following call:
        #    Game_Timer.start(seconds, key)
        #  Where seconds is the number of seconds you want the timer to run, and
        #  key is the name of that specific timer. You must use a seperate name for
        #  every timer, because when one finishes, only the first script checking for
        #  that name will return with the timer completed.
        #
        #  To check whether or not a timer has finished, use the following call:
        #    Game_Timer.finished?(key)
        #  Where timer_number is the number of the timer that you need to check. See
        #  the rules above regarding key.
        #
        #  To remove a timer, use the following call:
        #    Game_Timer.kill_timer(key)
        #  Where key is the timer that you wish to remove.
        #
        #  To adjuct the time remaining on a timer, use the following call:
        #    Game_Timer.adjust_time(setting, value, key)
        #  Where value is the number you want to adjust by, key is the timer you want
        #  to adjust, and setting in the operation you want to perform. (1 to add
        #  frames, 2 to subtract frames, 3 to multiply, 4 to divide, and 5 to perform a
        #  modulus operation)
        #
        #  To stop or start a timer, use the following call:
        #    Game_Timer.active(key, bool)
        #  Where key is the timer you want to start or stop, and bool is true if you
        #  want to start the timer, and false if you want to stop it.
        #
        #  To have a timer force battles to abort when they reach zero, use the
        #  following call:
        #    Game_Timer.end_battle(key, bool)
        #  Where key is the timer you want to modify, and bool is true if you want it
        #  to abort battles while it is 0, and false if you don't.
        #
        #  To set a timer to display, use the following call:
        #    Game_Timer.display(key, bool)
        #  Where key is the timer you want to display, and bool is either true or
        #  false, depending on the desired result.
        #
        #  To set a timer to be saved in the save file, use the following call:
        #    Game_Timer.save(key, bool)
        #  Where key is the timer you want to have saved, and bool is true if you want
        #  the timer to be saved, and false if you want it to disappear when the game
        #  is closed.
        #==============================================================================
        # * Method List
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        #  initialize
        #    Sets up the script. Intended for internal use only.
        #
        #  update
        #    Updates all timers. Although intended for internal use, may be added to
        #    other scenes to force a timer update elsewhere.
        #
        #  update_single(key)
        #    Updates a single timer, specified by key.
        #
        #  start(seconds, key)
        #    Set up a timer, which will be accessed in the future by using key.
        #
        #  extended_start(hours, minutes, seconds, key)
        #    Set up and extended timer. Functions in the same way as start().
        #
        #  finished?(key)
        #    Returns true if the timer specified by key has reached 0, false otherwise.
        #    This method will delete the checked timer if it has reached 0.
        #
        #  check_timing(key)
        #    Debugging method. Returns a variety of messages based on the current state
        #    of the timer specified by key.
        #
        #  kill_timer(key)
        #    Erases the timer specified by key.
        #
        #  adjust_time(setting, value, key)
        #    Adjusts the remaining time in the timer specified by key. Setting
        #    specifies an operation. (1 => addition, 2 => subtraction,
        #    3 => multiplication, 4 = division, 5 = modulus
        #
        #  active(key, bool)
        #    Sets the timer specified by key to active or inactive, based on whether
        #    bool is true or false.
        #
        #  active?(key)
        #    Returns true if the timer specified by key is active, and false otherwise.
        #
        #  end_battle(key, bool)
        #    When bool is set to true, this method sets the timer specified by key to
        #    abort battles when it reaches 0. Otherwise, the timer will not abort
        #    battles when it reaches 0.
        #
        #  end_battle?
        #    Checks to see if a timer that aborts battle has reached 0. Intended for
        #    internal use.
        #
        #  display(key, bool)
        #    If bool is set to true, will display the timer specified by key.
        #    Otherwise, the timer is not displayed. Please note that only one timer will
        #    be displayed at any given time, no matter how many are set to display.
        #
        #  display?
        #    Checks to see if a timer is being displayed, and reuturns remaining time.
        #    This method is intended for internal use only.
        #
        #  save(key, bool)
        #    If bool is set to true, the timer specified by key will be saved along
        #    with the rest of the game. If bool is false, the timer will be deleted
        #    when the game closes, even if a save was made.
        #
        #  save?
        #    Returns an array of all timers set to be saved. This method is intended
        #    for internal use only.
        #
        #  load_save(timers)
        #    Loads all timers in the timers variable. This method is intended for
        #    internal use, but could be used to create new timers as well.
        #
        #  conditional_branch(parameters)
        #    Part of the interpreter's conditional branch processing. Intended for
        #    internal use only.
        #
        #  control_variables(parameters)
        #    Part of the interpreter's control variable processing. Intended for
        #    internal use only.
        #
        #  control_timer(parameters)
        #    The interpreter's control timer processing. Intended for internal use
        #    only, although it could be used to create an event timer through scripts.
        #==============================================================================
        # *Glitchfinder's Advice
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        #  This script is meant for people with at least a basic level of scripting
        #  knowledge and ability. If you are unsure of your abilities, or don't know
        #  how to script, then it would be a good idea to avoid this script.
        #
        #  This script has been tested in both scripts and events, and will function in
        #  both cases.
        #
        #  This script will function in both RPG Maker XP and RPG Maker VX.
        #==============================================================================
        # * Contact
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        #  Glitchfinder, the author of this script, may be contacted through his
        #  website, found at http://www.glitchkey.com
        #
        #  You may also find Glitchfinder at http://www.hbgames.org
        #==============================================================================
        # * Usage
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        #  This script may be used with the following terms and conditions:
        #
        #    1. This script is free to use in any noncommercial project. If you wish to
        #       use this script in a commercial (paid) project, please contact
        #       Glitchfinder at his website.
        #    2. This script may only be hosted at the following domains:
        #         http://www.glitchkey.com
        #         http://www.hbgames.org
        #    3. If you wish to host this script elsewhere, please contact Glitchfinder
        #       or theory.
        #    4. If you wish to translate this script, please contact Glitchfinder or
        #       or theory. They will need the web address that you plan to host the
        #       script at, as well as the language this script is being translated to.
        #    5. This header must remain intact at all times.
        #    6. Glitchfinder and theory remain the sole owners of this code. They may
        #       modify or revoke this license at any time, for any reason.
        #    7. Any code derived from code within this script is owned by Glitchfinder
        #       and theory, and you must have their permission to publish, host, or
        #       distribute their code.
        #    8. This license applies to all code derived from the code within this
        #       script.
        #    9. If you use this script within your project, you must include visible
        #       credit to Glitchfinder and theory, within reason.
        #≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
        
        
        #==============================================================================
        # ** Sprite_Timer
        #------------------------------------------------------------------------------
        #  This sprite is used to display the timer.It observes the $game_system
        #  class and automatically changes sprite conditions.
        #==============================================================================
        
        class Sprite_Timer < Sprite
          #--------------------------------------------------------------------------
          # * Frame Update
          #--------------------------------------------------------------------------
          def update
            super
            # Hide timer sprite and return if there is no currently displayed timer
            self.visible = Game_Timer.display? == false ? false : true
            return if self.visible == false
            # If timer needs to be redrawn
            if Game_Timer.display? / Graphics.frame_rate != @total_sec
              # Calculate total number of seconds and make a string
              @total_sec = Game_Timer.display? / Graphics.frame_rate
              text = sprintf("%02d:%02d", @total_sec / 60, @total_sec % 60)
              # Clear window contents and draw timer
              self.bitmap.clear
              self.bitmap.draw_text(self.bitmap.rect, text, 1)
            end
          end
        end
        
        #----------------------------------------------------------------------------
        # * Check for RGSS1
        #----------------------------------------------------------------------------
        if !(defined?(Graphics.brightness))
        
        #==============================================================================
        # ** Scene_Save
        #------------------------------------------------------------------------------
        #  This class performs save screen processing.
        #==============================================================================
        
        class Scene_Save < Scene_File
          #--------------------------------------------------------------------------
          # * Alias Methods
          #--------------------------------------------------------------------------
          # If the method has not been aliased
          unless method_defined?(:multiple_timers_write_save_data)
            # Alias the method
            alias multiple_timers_write_save_data write_save_data
          end
          #--------------------------------------------------------------------------
          # * Write Save Data
          #     file : write file object (opened)
          #--------------------------------------------------------------------------
          def write_save_data(file)
            # Call original method
            multiple_timers_write_save_data(file)
            # Write save data
            Marshal.dump(Game_Timer.save?, file)
          end
        end
        
        #==============================================================================
        # ** Scene_Load
        #------------------------------------------------------------------------------
        #  This class performs load screen processing.
        #==============================================================================
        
        class Scene_Load < Scene_File
          #--------------------------------------------------------------------------
          # * Alias Methods
          #--------------------------------------------------------------------------
          # If the method has not been aliased
          unless method_defined?(:multiple_timers_read_save_data)
            # Alias the method
            alias multiple_timers_read_save_data read_save_data
          end
          #--------------------------------------------------------------------------
          # * Read Save Data
          #     file : file object for reading (opened)
          #--------------------------------------------------------------------------
          def read_save_data(file)
            # Call original method
            multiple_timers_read_save_data(file)
            # Load saved data
            Game_Timer.load_save(Marshal.load(file)) unless file.eof?
          end
        end
        
        #==============================================================================
        # ** Interpreter
        #------------------------------------------------------------------------------
        #  This interpreter runs event commands. This class is used within the
        #  Game_System class and the Game_Event class.
        #==============================================================================
        
        class Interpreter
          #--------------------------------------------------------------------------
          # * Alias Methods
          #--------------------------------------------------------------------------
          # If the method has not been aliased
          unless method_defined?(:multiple_timers_command_111)
            # Alias the method
            alias multiple_timers_command_111 command_111
          end
          # If the method has not been aliased
          unless method_defined?(:multiple_timers_command_122)
            # Alias the method
            alias multiple_timers_command_122 command_122
          end
          #--------------------------------------------------------------------------
          # * Conditional Branch
          #--------------------------------------------------------------------------
          def command_111
            # Initialize local variable: result
            result = false
            # If checking timer
            if @parameters[0] == 3
              # Call modified method
              result = Game_Timer.conditional_branch(@parameters)
              # Skip if branch is false
              return command_skip if result == false
            end
            # Store determinant results in hash
            @branch[@list[@index].indent] = result
            # If determinant results are true
            if @branch[@list[@index].indent] == true
              # Delete branch data
              @branch.delete(@list[@index].indent)
              # Continue
              return true
            end
            # Call aliased method
            multiple_timers_command_111
          end
          #--------------------------------------------------------------------------
          # * Control Variables
          #--------------------------------------------------------------------------
          def command_122
            # Initialize value
            value = 0
            # If @parameters[3] is set to other
            if @parameters[3] == 7
              # If @parameters[4] is set to timer
              if @parameters[4] == 5  # timer
                # Call modified method
                Game_Timer.control_variables(@parameters)
                # Continue
                return true
              end
            end
            # Call aliased method
            multiple_timers_command_122
          end
          #--------------------------------------------------------------------------
          # * Control Timer
          #--------------------------------------------------------------------------
          def command_124
            # Call modified method
            Game_Timer.control_timer(@parameters)
            # Continue
            return true
          end
        end
        
        #----------------------------------------------------------------------------
        # * End Check for RGSS1
        #----------------------------------------------------------------------------
        end
        
        #----------------------------------------------------------------------------
        # * Check for RGSS2
        #----------------------------------------------------------------------------
        if (defined?(Graphics.brightness) == true)
        
        #==============================================================================
        # ** Scene_File
        #------------------------------------------------------------------------------
        #  This class performs the save and load screen processing.
        #==============================================================================
        
        class Scene_File < Scene_Base
          #--------------------------------------------------------------------------
          # * Alias Methods
          #--------------------------------------------------------------------------
          # If the initialize method has not been aliased
          unless method_defined?(:multiple_timers_write_save_data)
            # Alias the enemy selection method
            alias multiple_timers_write_save_data write_save_data
          end
          # If the initialize method has not been aliased
          unless method_defined?(:multiple_timers_read_save_data)
            # Alias the enemy selection method
            alias multiple_timers_read_save_data read_save_data
          end
          #--------------------------------------------------------------------------
          # * Write Save Data
          #     file : write file object (opened)
          #--------------------------------------------------------------------------
          def write_save_data(file)
            # Call original method
            multiple_timers_write_save_data(file)
            # Write save data
            Marshal.dump(Game_Timer.save?, file)
          end
          #--------------------------------------------------------------------------
          # * Read Save Data
          #     file : file object for reading (opened)
          #--------------------------------------------------------------------------
          def read_save_data(file)
            # Call original method
            multiple_timers_read_save_data(file)
            # Load saved data
            Game_Timer.load_save(Marshal.load(file)) unless file.eof?
          end
        end
        
        #==============================================================================
        # ** Game_Interpreter
        #------------------------------------------------------------------------------
        #  An interpreter for executing event commands. This class is used within the
        # Game_Map, Game_Troop, and Game_Event classes.
        #==============================================================================
        
        class Game_Interpreter
          #--------------------------------------------------------------------------
          # * Alias Methods
          #--------------------------------------------------------------------------
          # If the initialize method has not been aliased
          unless method_defined?(:multiple_timers_command_111)
            # Alias the enemy selection method
            alias multiple_timers_command_111 command_111
          end
          # If the initialize method has not been aliased
          unless method_defined?(:multiple_timers_command_122)
            # Alias the enemy selection method
            alias multiple_timers_command_122 command_122
          end
          #--------------------------------------------------------------------------
          # * Conditional Branch
          #--------------------------------------------------------------------------
          def command_111
            # Initialize local variable: result
            result = false
            # If checking timer
            if @params[0] == 3
              # Call modified method
              result = Game_Timer.conditional_branch(@params)
              # Skip if branch is false
              return command_skip if reult == false
            end
            # Store determinant results in hash
            @branch[@indent] = result
            # If determinant results are true
            if @branch[@indent] == true
              # Delete branch data
              @branch.delete(@indent)
              # Continue
              return true
            end
            # Call aliased method
            multiple_timers_command_111
          end
          #--------------------------------------------------------------------------
          # * Control Variables
          #--------------------------------------------------------------------------
          def command_122
            # Initialize value
            value = 0
            # If @params[3] is set to other
            if @params[3] == 7
              # If @params[4] is set to timer
              if @params[4] == 5  # timer
                # Call modified method
                Game_Timer.control_variables(@params)
                # Continue
                return true
              end
            end
            # Call aliased method
            multiple_timers_command_122
          end
          #--------------------------------------------------------------------------
          # * Control Timer
          #--------------------------------------------------------------------------
          def command_124
            # Call modified method
            Game_Timer.control_timer(@params)
            # Continue
            return true
          end
        end
        
        #----------------------------------------------------------------------------
        # * End Check for RGSS2
        #----------------------------------------------------------------------------
        end
        
        #==============================================================================
        # ** Scene_Map
        #------------------------------------------------------------------------------
        #  This class performs map screen processing.
        #==============================================================================
        
        class Scene_Map
          #--------------------------------------------------------------------------
          # * Alias Methods
          #--------------------------------------------------------------------------
          # If the initialize method has not been aliased
          unless method_defined?(:multiple_timers_update)
            # Alias the enemy selection method
            alias multiple_timers_update update
          end
          #--------------------------------------------------------------------------
          # * Frame Update
          #--------------------------------------------------------------------------
          def update
            # Call original method
            multiple_timers_update
            # Update Game_Timer
            Game_Timer.update
          end
        end
        
        #==============================================================================
        # ** Scene_Battle
        #------------------------------------------------------------------------------
        #  This class performs battle screen processing.
        #==============================================================================
        
        class Scene_Battle
          #--------------------------------------------------------------------------
          # * Alias Methods
          #--------------------------------------------------------------------------
          # If the initialize method has not been aliased
          unless method_defined?(:multiple_timers_update)
            # Alias the enemy selection method
            alias multiple_timers_update update
          end
          #--------------------------------------------------------------------------
          # * Frame Update
          #--------------------------------------------------------------------------
          def update
            # Update Game_Timer
            Game_Timer.update
            # Abort Battle if an appropriate timer has ended
            $game_temp.battle_abort = true if Game_Timer.end_battle?
            # Call original method
            multiple_timers_update
          end
        end
        
        #==============================================================================
        # ** Game_Timer
        #------------------------------------------------------------------------------
        #  This class performs processing for in-script timers.
        # Refer to "$game_temp.game_timer" for the instance of this class.
        #==============================================================================
        
        module Game_Timer
          #--------------------------------------------------------------------------
          # * Object Initialization
          #--------------------------------------------------------------------------
          begin
            # Create timer hash
            Timers = {}
            # Set timer hash defaults
            Timers.default = {
              'time' => 0,
              'active' => false,
              'display' => false,
              'endbattle' => false,
              'finished' => false,
              'save' => false
            }
          end
          #--------------------------------------------------------------------------
          # * Frame Update
          #--------------------------------------------------------------------------
          def self.update
            # Iterate through all timers
            Timers.keys.each { |key|
            # Skip if the current timer is inactive, otherwise deduct timer
            Timers[key]['active'] == false ? next : Timers[key]['time'] -= 1
            # Set the timer to finished if the frame count is 0 or less
            Timers[key]['active'] = false and
            Timers[key]['finished'] = true if Timers[key]['time'] <= 0}
          end
          #--------------------------------------------------------------------------
          # * Frame Update (individual timer)
          #     key : key for specific timer
          #--------------------------------------------------------------------------
          def self.update_single(key)
            # Return if the current timer is inactive, otherwise deduct timer
            Timers[key]['active'] == false ? return : Timers[key]['time'] -= 1
            # Set the timer to finished if the frame count is 0 or less
            Timers[key]['active'] = false and
            Timers[key]['finished'] = true if Timers[key]['time'] <= 0
          end
          #--------------------------------------------------------------------------
          # * Start Timer
          #     seconds : time, in seconds
          #     key     : key for specific timer
          #--------------------------------------------------------------------------
          def self.start(seconds, key)
            # Check the validity of the second value
            unless seconds.is_a?(Integer)
              # Print an error and exit if the second value is invalid
              p "You must set a timer's remaining time to a numeric value"
              exit
            end
            # Setup new timer
            Timers[key] = {
              'time' => seconds * Graphics.frame_rate,
              'active' => true,
              'display' => false,
              'endbattle' => false,
              'finished' => false,
              'save' => false
            }
          end
          #--------------------------------------------------------------------------
          # * Start Timer (extended)
          #     hours   : added hours (not including minutes or seconds)
          #     minutes : added minutes (not including hours or seconds)
          #     seconds : added seconds (not including hours or minutes)
          #     key     : key for specific timer
          #--------------------------------------------------------------------------
          def self.extended_start(hours, minutes, seconds, key)
            # Check the validity of the time value
            unless (hours.is_a?(Integer) == true && minutes.is_a?(Integer) == true &&
                   seconds.is_a?(Integer) == true)
              # Print an error and exit if the time value is invalid
              p "You must set a timer's remaining time to a numeric value"
              exit
            end
            # Calculate time
            time = ((hours * 3600 * Graphics.frame_rate) +
                   (minutes * 60 * Graphics.frame_rate) +
                   (seconds * Graphics.frame_rate))
            # Setup new timer
            Timers[key] = {
              'time' => time,
              'active' => true,
              'display' => false,
              'endbattle' => false,
              'finished' => false,
              'save' => false
            }
          end
          #--------------------------------------------------------------------------
          # * Check Timer
          #     key : key for specific timer
          #--------------------------------------------------------------------------
          def self.finished?(key)
            # Return false if the timer has not finished
            return false if Timers[key]['finished'] == false
            # Delete timer
            Timers.delete(key)
            return true
          end
          #--------------------------------------------------------------------------
          # * Check Timer (Debugging)
          #     key : key for specific timer
          #--------------------------------------------------------------------------
          def self.check_timing(key)
            return unless ($DEBUG == true || $TEST == true)
            # If the Timers hash includes the key
            if Timers.include?(key)
              # If the timer has time remaining
              if Timers[key]['finished'] == false
                # Set up message and print
                s = 'The timer named ' + key.to_s + ' has ' + Timers[key]['time'].to_s
                s += ' frames remaining.'
                p s
              else
                # Print message
                p 'The timer named ' + key.to_s + ' has reached zero.'
              end
              # Print message if timer is inactive
              if Timers[key]['active'] == false
                p 'The timer named ' + key.to_s + ' is currently inactive.'
              end
              # Print message if timer is set to end battle
              if Timers[key]['endbattle'] == true
                p 'The timer named ' + key.to_s + ' is currently set to end battle.'
              end
              # print message if timer is set to be saved in the file
              if Timers[key]['save'] == true
                p 'The timer named ' + key.to_s + ' is currently saved with the game.'
              end
            else
              # Print message if the timer does not exist
              p 'The timer named ' + key.to_s + ' does not exist.'
            end
          end
          #--------------------------------------------------------------------------
          # * Kill Timer
          #     key : key for specific timer
          #--------------------------------------------------------------------------
          def self.kill_timer(key)
            # Delete the timer if it exists
            Timers.delete(key) if Timers.include?(key)
          end
          #--------------------------------------------------------------------------
          # * Adjust Remaining Time
          #     setting : type of operation
          #     value   : value to use in the operation
          #     key     : key for specific timer
          #--------------------------------------------------------------------------
          def self.adjust_time(setting, value, key)
            # Print an error and exit if the value is invalid
            unless value.is_a?(Integer)
              p "You must modify a timer's remaining time with a numeric value"
              exit
            end
            # Print an error and exit if the setting is invalid
            unless (setting >= 1 && setting <= 5)
              p "You have used an invalid setting when modifying the timer."
              exit
            end
            # Perform the appropriate math function based on setting variable
            case setting   
            when 1 then Timers[key]['time'] += value
            when 2 then Timers[key]['time'] -= value
            when 3 then Timers[key]['time'] *= value
            when 4 then Timers[key]['time'] /= value
            when 5 then Timers[key]['time'] %= value
            end
          end
          #--------------------------------------------------------------------------
          # * Set Timer's Active Boolean
          #     key  : key for specific timer
          #     bool : true or false, where true ends battle when timer is at 0
          #--------------------------------------------------------------------------
          def self.active(key, bool)
            # Check bool's validity
            unless (bool == true || bool == false)
              # Print an error and exit if bool is invalid
              p "You must set a timer's active boolean to either true or false."
              exit
            end
            # Set timer boolean if it exists
            Timers[key]['active'] == bool if Timers.include?(key)
          end
          #--------------------------------------------------------------------------
          # * Timer Active?
          #     key : key for specific timer
          #--------------------------------------------------------------------------
          def self.active?(key)
            # Return active value for specified timer
            return Timers[key]['active']
          end
          #--------------------------------------------------------------------------
          # * Set Timer's End Battle Boolean
          #     key  : key for specific timer
          #     bool : true or false, where true ends battle when timer is at 0
          #--------------------------------------------------------------------------
          def self.end_battle(key, bool)
            # Check bool's validity
            unless (bool == true || bool == false)
              # Print an error and exit if bool is invalid
              p "You must set a timer's end battle boolean to either true or false."
              exit
            end
            # Set timer boolean if it exists
            Timers[key]['endbattle'] == bool if Timers.include?(key)
          end
          #--------------------------------------------------------------------------
          # * End Battle?
          #--------------------------------------------------------------------------
          def self.end_battle?
            # Iterate through all timers
            Timers.keys.each {|key| next if Timers[key]['active'] == false
            # Return true if the timer is finished and is set to end battle
            return true if Timers[key]['endbattle'] && Timers[key]['time'] <= 0}
            return false
          end
          #--------------------------------------------------------------------------
          # * Set Timer's Display Boolean
          #     key  : key for specific timer
          #     bool : true or false, where true means the timer is displayed
          #--------------------------------------------------------------------------
          def self.display(key, bool)
            # Check bool's validity
            unless (bool == true || bool == false)
              # Print an error and exit if bool is invalid
              p "You must set a timer's display boolean to either true or false."
              exit
            end
            # Set timer boolean if it exists
            Timers[key]['display'] = bool if Timers.include?(key)
          end
          #--------------------------------------------------------------------------
          # * Display Timer?
          #--------------------------------------------------------------------------
          def self.display?
            # Iterate through all timers
            Timers.keys.each {|key| next if Timers[key]['active'] == false
            # Return remaining time if the timer is set to display
            return Timers[key]['time'] if Timers[key]['display'] == true}
            return false
          end
          #--------------------------------------------------------------------------
          # * Set Timer's Save Boolean
          #     key  : key for specific timer
          #     bool : true or false, where true means the timer is displayed
          #--------------------------------------------------------------------------
          def self.save(key, bool)
            # Check bool's validity
            unless (bool == true || bool == false)
              # Print an error and exit if bool is invalid
              p "You must set a timer's save boolean to either true or false."
              exit
            end
            # Set timer boolean if it exists
            Timers[key]['save'] = bool if Timers.include?(key)
          end
          #--------------------------------------------------------------------------
          # * Save Timer?
          #--------------------------------------------------------------------------
          def self.save?
            # Setup save hash
            save = {}
            # Iterate through timers and add the timer to the hash if it is set to save
            Timers.keys.each{|x| save[x] = Timers[x] if Timers[x]['save'] == true}
            return save
          end
          #--------------------------------------------------------------------------
          # * Load Saved Timer
          #--------------------------------------------------------------------------
          def self.load_save(timers)
            # Add timers to hash if any have been loaded
            timers.keys.each {|key| Timers[key] = timers[key]} unless timers.empty?
          end
          #--------------------------------------------------------------------------
          # * Conditional Branch
          #--------------------------------------------------------------------------
          def self.conditional_branch(parameters)
            # If event timer is active
            if active?('event')
              # Set timer variable to currently displayed timer
              timer = display?
              # Skip command if no timer is currently displayed
              return false if timer == false
              # Calculate remaining timer
              sec = timer / Graphics.frame_rate
              # If checking for a value <= remaining time
              if parameters[2] == 0
                # set result to the truth value of remaining time >= checked time
                result = (sec >= parameters[1])
              else
                # set result to the truth value of remaining time <= checked time
                result = (sec <= parameters[1])
              end
            else
              # Skip command if timer is not active
              return false
            end
          end
          #--------------------------------------------------------------------------
          # * Control Variables
          #--------------------------------------------------------------------------
          def self.control_variables(parameters)
            timer = display?
            timer = 0 if timer == false
            value = timer / Graphics.frame_rate
            # Loop for group control
            for i in parameters[0] .. parameters[1]
              # Branch with control
              case parameters[2]
              when 0 then $game_variables[i] = value
              when 1 then $game_variables[i] += value
              when 2 then$game_variables[i] -= value
              when 3 then $game_variables[i] *= value
              when 4  # divide
                if value != 0
                  $game_variables[i] /= value
                end
              when 5  # remainder
                if value != 0
                  $game_variables[i] %= value
                end
              end
              # Max / Min limit check
              $game_variables[i] = 99999999 if $game_variables[i] > 99999999
              $game_variables[i] = -99999999 if $game_variables[i] < -99999999
            end
            # Refresh map
            $game_map.need_refresh = true
          end
          #--------------------------------------------------------------------------
          # * Control Timer
          #--------------------------------------------------------------------------
          def self.control_timer(parameters)
            # If started
            if parameters[0] == 0
              # Start timer
              Game_Timer.start(parameters[1], 'event')
              # Set timer to end battle
              Game_Timer.end_battle('event', true)
              # Display timer
              Game_Timer.display('event', true)
              # Set timer to save with game
              Game_Timer.save('event', true)
            # If stopped
            else
              # Hide timer
              Game_Timer.active('event', false)
            end
          end
        end
     
    #1
  2. bgillisp

    bgillisp Global Moderators Global Mod

    Messages:
    11,898
    Likes Received:
    12,017
    Location:
    USA
    First Language:
    English
    Primarily Uses:
    RMVXA
    First, no script for XP can work for VX, due to major differences in the engine. There might be two versions of the script though, so be sure to check for that.

    I've moved this thread to RGSSx Script Support. Please be sure to post your threads in the correct forum next time. Thank you.

     
    #2
  3. Shaz

    Shaz Veteran Veteran

    Messages:
    37,572
    Likes Received:
    11,272
    Location:
    Australia
    First Language:
    English
    Primarily Uses:
    RMMV
    It's better to post a link to where you got the script from, rather than copy/pasting the whole script into your post. We don't have the benefit now of seeing the author's comments or any Q&A that happened in the thread.

    Did you add this script and then load a game you'd previously saved? That is a common cause of the "undefined method" error. If you've done that, try starting a new game and see if it works.

    Another way to have enemies respawn is simply to use Erase Event after the battle. The event will disappear while the player remains on that map, but when they leave and return, the event will be there again. This may not be exactly what you want, if you're after enemies that will disappear for X minutes and then reappear, even if the player hasn't left the map and returned.


    I am not sure how the script is going to help you reactivate the event though. Can you post a screenshot showing where you're doing this check? You certainly wouldn't want each event to switch to a new page that's a parallel process, constantly checking if the timer has run out. That's going to make your game lag like crazy!
     
    #3
    Yokiko likes this.
  4. Yokiko

    Yokiko Villager Member

    Messages:
    24
    Likes Received:
    2
    First Language:
    German
    Primarily Uses:
    RMVX
    Thank you both very much for responding and sorry for posting the thread in the wrong forum!

    @ Shaz: Oh gosh, you're absolutely right. Sorry, I seriously didn't think that it would be more convenient to post the link to the script instead of the script itself. All the hours of trying to figure out how to make the enemies respawn must have mushed my brain, whoopsie. Here's the link:
    http://www.hbgames.org/forums/viewtopic.php?t=49209

    To your question: No, unfortunately I did not add this script and then load a game I've previously saved. I even tried to test it out on a completely new project, just in case other scripts may interfere. I guess it's as bgillisp said and the script isn't completely compatible with VX, while Glitchfinder just presumed it would be? As you can see in the linked forum post, the author says it works on VX and according to the changelog of the script, there were even some bugfixed for VX, so my hopes were high...

    I also thought of using the Erase Command, however I figured it must be pretty inconvenient for the player to go through the map just to make some small errands or something and being immediately welcomed by all the monsters after re-entering the map. That's why I tried to search for other solutions. I'm a bit intimidated because of your last statement, though, since I actually planed to do exactly that: switch to a new page that's a parallel process. I thought it wouldn't lag so badly if there were, like, max 6 enemies on one map, mostly even fewer. I figured it would probably be no issue because when doing puzzles, 4-6 parallel processes constantly checking the coordinates of player and events wasn't an issue so far, either. But since I wasn't able to test the respawn parallel processes due to the script not working, I naturally wasn't able to test this thesis... Argh, guess I'm back to square one then, huh? :kaocry:
     
    Last edited: Sep 18, 2018
    #4
  5. Shaz

    Shaz Veteran Veteran

    Messages:
    37,572
    Likes Received:
    11,272
    Location:
    Australia
    First Language:
    English
    Primarily Uses:
    RMMV
    Alright - it looks like the way the timer was referenced has changed a few times. Version 3.32 removed game_timer from $game_temp and changed it to $game_timer. Version 3.44 then removed $game_timer and changed it to Game_Timer. So the instructions you're following refer to an old version of the script and will not work with the current version. I notice even the script still has some instructions that reference an old version.

    Instead of using $game_temp.game_timer, you have to use Game_Timer.

    Let's say you want to create a timer for 3 minutes to respawn an event. 1 second is 60 frames, 1 minute is 60 seconds, so 3 minutes is 60 x 60 x 3 = 10800. You would use Game_Timer.start(10800, "event1") but replace "event1" with whatever name you want to give to the timer. Each one must be unique. It doesn't have to be the event name or event number. You could use the map id and the event id like this (say, map 8, event 15): Game_Timer.start(10800, "8.15") - the format is up to you - it's just got to be unique, and in quotes as it's a string.

    If you want to know if the timer has finished, use Game_Timer.finished?("8.15")

    You COULD use this in a parallel process event page like this:
    Code:
    Wait 10 frames
    Conditional Branch: Script: Game_Timer.finished?("8.15")
      Control Self Switches: A = OFF
    End
    It's not a great way to do it, but if you go this way, definitely put that Wait command in there. You don't need each event to check 60 times a second to see if the timer has run out. It would be perfectly okay if the event respawned 3 minutes and 10 frames after you started the timer.

    I haven't tested this, but it's what I think you need to do based on taking a quick look through the script.
     
    Last edited: Sep 18, 2018
    #5
  6. Yokiko

    Yokiko Villager Member

    Messages:
    24
    Likes Received:
    2
    First Language:
    German
    Primarily Uses:
    RMVX
    I’m really, really grateful that you took the time to help me out; thank you very much!

    I actually already tried the call Game_Timer.finished?(x) as script call and as part of a conditional branch, but unfortunately, both don’t quite seem to work. There is no error message or something involved, it just don’t seem to turn the condition to true after the time runs out, since nothing starts to happen. I didn’t know that the key is a string though, that’s a good thing to know! Thank you.

    Thank you also for the tip regarding putting a wait command in the parallel process! I will definitely keep this in mind. In fact, I did some thinking as well and if the respawn events really do cause massive lags, I can probably just start a timer if the player leaves the dungeon map. When the player steps on the teleportation event that is supposed to bring them back to the dungeon map, I could let the event check whether the time ran out or not and depending on the result, I could simply turn self switch A of every enemy event on that map off (I already have a script call for that). That would solve the problem of inconveniency without requiring parallel processes. (At least I hope I don’t have some stupid mistake in my thesis again, haha!)
    However, that would also require the multiple timer script to work. Unfortunately.
     
    #6
  7. Shaz

    Shaz Veteran Veteran

    Messages:
    37,572
    Likes Received:
    11,272
    Location:
    Australia
    First Language:
    English
    Primarily Uses:
    RMMV
    The lag issue is with multiple parallel process events all running at the same time, that don't "come up for air". By putting in a wait (even a 60 frame wait, as it probably won't matter if your event doesn't spawn for an additional second), you get around that problem. The longer the wait, the better. It allows other processes to have their turn and not everyone is fighting over the computer's resources at once.

    If it's not working, please post a screenshot of your scripts window, so we can see where you have this one installed, a screenshot of the event that starts the timer, and a screenshot of the event that checks the timer. Make sure to include the entire event window - don't crop it, as the event commands are often not where the problem is happening.
     
    #7
    Yokiko likes this.
  8. Yokiko

    Yokiko Villager Member

    Messages:
    24
    Likes Received:
    2
    First Language:
    German
    Primarily Uses:
    RMVX
    Ohh I see, I didn't know that the wait command has such a huge impact! Thank you, I learned something new thanks to you!

    Regarding the timer - I tested it in a version of my games in which I deleted all the custom scripts. The Multi Timer script is the only custom script included. I'm not sure whether a screenshot of my scripts window will be very helpful, but here you go:
    [​IMG]

    Regarding the events, I should note that I didn't use my Enemy Respawn event to test the script. Instead I used some simple textboxes, so I can very clearly see whether it worked or not. Therefore, I also used the Game_Timer.display(key, bool) call to see whether the timer actually starts or not.
    You may also be wondering why I used the number 3 as time count. Apparently, the script does not measure time in frames, but in seconds. At least the call explaining it in the header of the script says so. It is supported by the display of the timer as well, since it counts down from 1:30 when I use 90 as time count. Just to make sure that the display isn't showing something wrong, I checked the Enemy Dummy event nontheless, but the condition is still not registered as true.
    (Edit: In the screenshot I posted, 90 is shown, but it's just a relict from my second attempt to test it out. Both time counts had the same effect on the Dummy Enemy. Fiddlesticks.)

    Here are the event pages:
    [​IMG]

    [​IMG]


    Needless to say, my enemy dummy is a real bad boy. He won't stop swearing.
    He seriously needs some J e s u s.
     
    Last edited: Sep 19, 2018
    #8
  9. Yokiko

    Yokiko Villager Member

    Messages:
    24
    Likes Received:
    2
    First Language:
    German
    Primarily Uses:
    RMVX
    Huh, this last joke was more cringy than I remember. Whoops. (Bump~)
     
    #9
  10. Yokiko

    Yokiko Villager Member

    Messages:
    24
    Likes Received:
    2
    First Language:
    German
    Primarily Uses:
    RMVX
    Bump? :kaoswt2:
     
    #10
  11. Yokiko

    Yokiko Villager Member

    Messages:
    24
    Likes Received:
    2
    First Language:
    German
    Primarily Uses:
    RMVX
    Nothing, huh..? (bump) :kaocry:
     
    #11
  12. Yokiko

    Yokiko Villager Member

    Messages:
    24
    Likes Received:
    2
    First Language:
    German
    Primarily Uses:
    RMVX
    Okay, after trying to work this out for a month (I'm not even kidding. Seriously, what am I doing with my life?), I finally found a solution.

    I actually ditched this script because I couldn't, for the life of me, get it to work. Luckily, I stumbled across a super helpful (and working) script yesterday that creates so-called self-variables. One of the big reasons why I searched for a timer script was because I couldn't recreate timers with events without using a s***-ton of variables because they would have to cover every single enemy in the entire game, probably even surpassing the variable limit. But thanks to the self-variables, I only needed two "normal" variables to event time-based respawns.

    Thanks to Shaz though for trying to help me! I will keep your advice about inserting wait commands when checking the time in mind. :kaoluv:

    Topic can be closed!
     
    #12
    Shaz likes this.
  13. Kes

    Kes Global Moderators Global Mod

    Messages:
    20,591
    Likes Received:
    10,510
    First Language:
    English
    Primarily Uses:
    RMVXA
    @Yokiko When your question is resolved please Report your opening post and ask for it to be closed. Mods might not see a post but they will see a Report.

    This thread is being closed, due to being solved. If for some reason you would like this thread re-opened, please report this post and leave a message why. Thank you.

     
    #13
Thread Status:
Not open for further replies.

Share This Page