Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #═╦═════════════════════════════════════════════════════════════════════════════
- # ║ § Dynamic Time (1.3) by Solistra [License: CC BY-SA 3.0]
- # ║ <RMVX Ace>
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Change Log
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ v1.3 (January 4th, 2013) - Removed the option for multiple time managers --
- # ║ honestly, it was obnoxious to use, and not commonly requested. Other
- # ║ portions of the script were rewritten, but there is no change for users.
- # ║ Saved games will be incompatible with this update, however.
- # ║ v1.2 (December 4th, 2012) - Rewrote large portions of the script to allow
- # ║ multiple time managers to run simultaneously. Changed the way in which
- # ║ these managers are updated as well (saved games will not be compatible).
- # ║ v1.1 (December 1st, 2012) - Added the methods [unit]_max and reset. Also
- # ║ added a configuration option to allow storing values in $game_variables.
- # ║ v1.0 (November 29th, 2012) - Initial release
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Summary
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ This script allows you to use time in extraordinarily dynamic ways and makes
- # ║ almost no assumptions about how you want to set up or use time. Essentially,
- # ║ you define how much (or little) you want to use segmentations of time.
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Required Scripts
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ None.
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Known Incompatibilities
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ None.
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Installation
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ For best compatibility, place this script below Materials, but above all
- # ║ other custom scripts.
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Configuration
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ In this script, you define the segmentations of time and the maximum values
- # ║ for each segment. Once a segment has reached its maximum value, the next
- # ║ segment increases its value by 1 (so for every 60 seconds, one minute could
- # ║ be added, and for every 60 minutes, one hour could be added). For example,
- # ║ to create a game that uses minutes, hours, meridians, and days, you could
- # ║ set up the script as follows (units should always be symbols):
- # ║
- # ║ UNIT = [:minute, :hour, :meridian, :day]
- # ║ MAX = [60, 12, 2, nil]
- # ║
- # ║ A maximum value of "nil" means that there is no maximum -- this value will
- # ║ simply continue to increase. In this example, you can see that there are
- # ║ two meridians in a day, twelve hours in each meridian, and sixty minutes
- # ║ per hour.
- # ║
- # ║ Below this, you can define which segment will change the tone of the screen
- # ║ and the tone that each segment changes into. For instance, with the above
- # ║ example, we could set up a simple day and night system like so:
- # ║
- # ║ TONE_UNIT = :meridian
- # ║ TONE_LENGTH = 120
- # ║ TONES = [
- # ║ Tone.new(-68, -68, 0, 68), # Night (meridian 1)
- # ║ Tone.new(0, 0, 0, 0), # Day (meridian 2)
- # ║ ]
- # ║
- # ║ This will cause the tone to change over the course of 120 frames whenever
- # ║ the meridian changes. The current meridian will determine the tone used
- # ║ (remember to define tones in order from earliest to latest). Please note
- # ║ that the array of tones you want to use MUST be equal to the maximum value
- # ║ of whatever time unit you use to change the screen's tone!
- # ║
- # ║ Below this, you may configure any units of time that you wish to store in
- # ║ variables automatically (the kind you can manipulate with the Control
- # ║ Variables event command). This option is in the format of a hash: the key
- # ║ is the unit of time to store, and its value is the variable ID that you wish
- # ║ to store the value of the unit in. For example, to store the values for
- # ║ hours and days in variables 20 and 21 (respectively), you would do this:
- # ║
- # ║ VARIABLES = {:hour => 20, :day => 21}
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Tags
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ ● Map
- # ║ <time no_tone>
- # ║ Suppresses tone changes on the map.
- # ║ <time stop>
- # ║ Explicitly stops time on the map (even if time is enabled).
- # ║ <time run>
- # ║ Explicitly runs time on the map (even if time is disabled).
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Script Calls
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ You can access the current value of any unit of time by using the following
- # ║ script call:
- # ║ $game_system.time.[unit]
- # ║
- # ║ Using the previous example, you can access the current hour with the script
- # ║ call $game_system.time.hour. You can also explicitly set a unit's value like
- # ║ so:
- # ║ $game_system.time.[unit] = [value]
- # ║
- # ║ If you need to know the maximum value of any unit of game time, just use
- # ║ the following script call:
- # ║ $game_system.time.[unit]_max
- # ║
- # ║ For example, to get the maximum value for minutes, you'd use the script
- # ║ call $game_system.time.minute_max.
- # ║
- # ║ You may also start or stop game time with a number of different methods:
- # ║ $game_system.time.enable OR start OR run
- # ║ $game_system.time.disable OR stop OR pause
- # ║
- # ║ You can also get the current state of time with these calls:
- # ║ $game_system.time.running? AND $game_system.time.stopped?
- # ║
- # ║ Time can also move more quickly or slowly by modifying the value of the
- # ║ SES::Time module's @frame_skip instance variable. You can do this with the
- # ║ following script call:
- # ║ $game_system.time.frame_skip = [value]
- # ║
- # ║ To move back or forward through time, use the following script call with a
- # ║ positive value to move forward or a negative value to move backwards:
- # ║ $game_system.time.traverse([unit symbol], [value])
- # ║
- # ║ For example, to advance 12 hours, you'd call the following:
- # ║ $game_system.time.traverse(:hour, 12)
- # ║
- # ║ You may also save the current time values and restore these values with
- # ║ these script calls:
- # ║ $game_system.time.save
- # ║ $game_system.time.restore
- # ║
- # ║ Resetting time back to the initial values that you have set is easy, too:
- # ║ $game_system.time.reset
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § Aliased Methods
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ ● Game_System
- # ║ initialize
- # ║ ● Game_Map
- # ║ setup
- # ║ ● Scene_Base
- # ║ update
- # ║ ● Scene_Map
- # ║ post_transfer
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ § New Methods
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ ● Game_Map
- # ║ no_tone?
- # ║ no_time?
- # ║ run_time?
- # ║
- #═╬═════════════════════════════════════════════════════════════════════════════
- # ║ ▼ module SES::Time
- #═╩═════════════════════════════════════════════════════════════════════════════
- module SES module Time
- class << self; attr_reader :frame_skip end
- #═╦═══════════════════════════════════════════════════════════════════════════
- # ║ α BEGIN CONFIGURATION
- #═╩═══════════════════════════════════════════════════════════════════════════
- # Set whether or not time should start with a new game.
- ENABLED = true
- # The number of frames to skip before the most basic unit of time is updated.
- @frame_skip = 60
- # Scenes where time is updated.
- UPDATE_SCENES = [Scene_Map, Scene_Battle]
- # Should the message window pause time while it is in use?
- MSG_PAUSE = true
- # Units of game time in order of length. Note that these should all be
- # symbols, not strings (so you would write :minute instead of "minute").
- UNIT = [:minute, :hour, :time_of_day, :day]
- # Maximum values for each unit of game time. Must be the same size as the
- # UNIT constant above. A value of "nil" means there is no maximum.
- MAX = [60, 6, 4, nil]
- # Initial values for units of game time. Must be the same size as the UNIT
- # and MAX constants above. (Note that this runs from 0 to MAX - 1, not 1
- # to MAX.)
- INIT = [0, 0, 0, 1]
- # The time unit to use for tone changes and the number of frames changes take.
- TONE_UNIT = :time_of_day
- TONE_LENGTH = 120
- # The array of tones. This must be the same length as the maximum value for
- # the time unit used for tone changes. (If MAX is 4, create 4 tones.)
- TONES = [
- Tone.new(-68, -68, 0, 68), # Night
- Tone.new(17, -34, 17, 34), # Morning
- Tone.new(0, 0, 0, 0), # Day
- Tone.new(34, -34, -34, 34), # Evening
- ]
- # The hash of time units to store in $game_variables. Use the unit you wish
- # to store as the key and the ID of the desired variable as the value.
- VARIABLES = {:hour => 1, :time_of_day => 2, :day => 3}
- #═╦═══════════════════════════════════════════════════════════════════════════
- # ║ Ω END CONFIGURATION
- #─╫───────────────────────────────────────────────────────────────────────────
- # ║ ▼ class Manager
- #═╩═══════════════════════════════════════════════════════════════════════════
- class Manager
- # Initialize this manager.
- def initialize
- construct_methods
- @time_enabled, @tone_temp = ENABLED, Tone.new
- end
- # Create an instance variable and accessors for each unit of game time.
- def construct_methods
- UNIT.each do |u|
- instance_variable_set("@#{u}", INIT[UNIT.index(u)])
- self.class.send(:define_method, u){instance_variable_get("@#{u}")}
- self.class.send(:define_method, "#{u}=".to_sym) do |value|
- instance_variable_set("@#{u}", value) end
- self.class.send(:define_method, "#{u}_max".to_sym) do
- return MAX[UNIT.index(u)] end
- end
- end
- # Updates the most basic unit of game time (which initiates a potential
- # chain of updates) and requests a tone update.
- def update
- return unless update_conditions_met?
- self.send("update_#{UNIT[0]}")
- update_tone
- end
- # Defines the conditions under which time should or should not be updated.
- def update_conditions_met?
- return false if stopped? || !running?
- return false unless Graphics.frame_count % SES::Time.frame_skip == 0
- return false unless UPDATE_SCENES.include?(SceneManager.scene.class)
- return false if $game_message.busy? && MSG_PAUSE
- return true
- end
- # Updates the tone if time is enabled or running, the tone has not been
- # changed, and the map allows the tone to change.
- def update_tone
- return if (stopped? && !running?) || tone_changed? || $game_map.no_tone?
- screen.start_tone_change(get_tone, TONE_LENGTH)
- @tone_temp = get_tone
- end
- # Gets the screen used for tone changes.
- def screen
- $game_party.in_battle ? $game_troop.screen : $game_map.screen
- end
- # Gets the tone for this unit of game time by using the value of the
- # TONE_UNIT instance variable as the index for the TONES array.
- def get_tone() TONES[self.send(TONE_UNIT)] end
- # Check if the temporary tone is the currently requested tone.
- def tone_changed?() @tone_temp == get_tone end
- # Convenience method that allows the user to travel back or forward through
- # units of game time.
- def traverse(unit, amount)
- return if amount == 0 || UNIT.index(unit.to_sym).nil?
- amount > 0 ? amount.times{self.send("update_#{unit}".to_sym)} :
- amount.abs.times{self.send("rollback_#{unit}".to_sym)}
- end
- # Saves the state of all instance variables used by Manager. The @tone_temp
- # instance variable is left out so tone changes will occur properly.
- def save
- @save_state = {}
- instance_variables.each do |var|
- next if var == :@save_state || var == :@tone_temp
- @save_state[var] = instance_variable_get(var)
- end
- end
- # Restores the saved state of previously stored instance variables.
- def restore
- return unless @save_state
- @save_state.keys.each{|var| instance_variable_set(var, @save_state[var])}
- end
- # Resets time back to the initial values used.
- def reset
- UNIT.each{|u| instance_variable_set("@#{u}", INIT[UNIT.index(u)])}
- end
- # Convenience method for storing the values of a unit of time into the
- # $game_variables array.
- def store_in_variables(u, v) $game_variables[v] = self.send(u.to_sym) end
- # This is the workhorse of the script; this method moves time forward or
- # backward depending on the name of the method passed to it.
- def method_missing(method)
- if method =~ /^update_(\S+)$/
- raise(NoMethodError) if UNIT.index($1.to_sym).nil?
- # Increase the instance variable by 1.
- instance_variable_set("@#{$1}", instance_variable_get("@#{$1}") + 1)
- store_in_variables($1, VARIABLES[$1.to_sym]) if VARIABLES[$1.to_sym]
- unless MAX[UNIT.index($1.to_sym)].nil?
- if instance_variable_get("@#{$1}") < MAX[UNIT.index($1.to_sym)]
- return
- end
- else return end
- # This code is only run once the maximum value of time has been reached
- # for the given unit of game time. Set the value of this unit to 0,
- # then call the update method for the next unit of game time.
- instance_variable_set("@#{$1}", 0)
- store_in_variables($1, VARIABLES[$1.to_sym]) if VARIABLES[$1.to_sym]
- unless UNIT[UNIT.index($1.to_sym) + 1].nil?
- self.send("update_#{UNIT[UNIT.index($1.to_sym) + 1]}")
- end
- elsif method =~ /^rollback_(\S+)$/
- raise(NoMethodError) if UNIT.index($1.to_sym).nil?
- if instance_variable_get("@#{$1}") - 1 >= 0
- # Rolls time back by 1 if doing so doesn't result in a negative value.
- instance_variable_set("@#{$1}", instance_variable_get("@#{$1}") - 1)
- store_in_variables($1, VARIABLES[$1.to_sym]) if VARIABLES[$1.to_sym]
- else
- # Rolling back would create a negative value, so set it to the maximum
- # value for this unit of game time (which is MAX - 1).
- instance_variable_set("@#{$1}", MAX[UNIT.index($1.to_sym)] - 1)
- store_in_variables($1, VARIABLES[$1.to_sym]) if VARIABLES[$1.to_sym]
- self.send("rollback_#{UNIT[UNIT.index($1.to_sym) + 1]}")
- end
- else raise(NoMethodError) end
- end
- # Convenience methods to cleanly enable or disable time updates.
- def enable() @time_enabled = true end
- alias :start :enable; alias :run :start
- def disable() @time_enabled = false end
- alias :pause :disable; alias :stop :pause
- # This determines whether or not time is running. Note that this isn't
- # necessarily whether or not time has been enabled, but if it's been told
- # to run at all.
- def running?()
- return false if $game_map.no_time?
- return true if $game_map.run_time?
- return @time_enabled
- end
- # Similarly, check if time is stopped (but not necessarily disabled).
- def stopped?()
- return true if $game_map.no_time?
- return false if $game_map.run_time?
- return !@time_enabled
- end
- end
- #═╦═══════════════════════════════════════════════════════════════════════════
- # ║ ▲ class Manager
- #═╩═══════════════════════════════════════════════════════════════════════════
- end end
- #═╦═════════════════════════════════════════════════════════════════════════════
- # ║ ▲ module SES::Time
- #═╩═════════════════════════════════════════════════════════════════════════════
- ($imported ||= {})["SES - Time"] = 1.3
- #═╦═════════════════════════════════════════════════════════════════════════════
- # ║ ▼ class Game_System
- #═╩═════════════════════════════════════════════════════════════════════════════
- class Game_System
- attr_reader :time
- alias :ses_time_gs_init :initialize
- def initialize(*args, &block)
- ses_time_gs_init(*args, &block)
- @time = SES::Time::Manager.new
- end
- end
- #═╦═════════════════════════════════════════════════════════════════════════════
- # ║ ▲ class Game_System
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ ▼ class Game_Map
- #═╩═════════════════════════════════════════════════════════════════════════════
- class Game_Map
- attr_reader :last_map
- # Aliasing setup to record the previous map's information whenever a new map
- # is entered. This is done for the tone-changing code in Scene_Map below.
- alias :ses_game_time_gm_setup :setup
- def setup(*args, &block)
- @last_map = @map unless @map.nil?
- ses_game_time_gm_setup(*args, &block)
- end
- # Methods to check for the presence of various note tags.
- def no_tone?(map = @map) map.note =~ /\<time no\_tone\>/ unless map.nil? end
- def no_time?(map = @map) map.note =~ /\<time stop\>/ unless map.nil? end
- def run_time?(map = @map) map.note =~ /\<time run\>/ unless map.nil? end
- end
- #═╦═════════════════════════════════════════════════════════════════════════════
- # ║ ▲ class Game_Map
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ ▼ class Scene_Base
- #═╩═════════════════════════════════════════════════════════════════════════════
- class Scene_Base
- # Update the time in every Scene class (considering there's no reasonable way
- # to know which scenes in particular the user is going to want time in).
- alias :ses_game_time_sb_upd :update
- def update(*args, &block)
- ses_game_time_sb_upd(*args, &block)
- $game_system.time.update
- end
- end
- #═╦═════════════════════════════════════════════════════════════════════════════
- # ║ ▲ class Scene_Base
- #─╫─────────────────────────────────────────────────────────────────────────────
- # ║ ▼ class Scene_Map
- #═╩═════════════════════════════════════════════════════════════════════════════
- class Scene_Map < Scene_Base
- # Aliasing post_transfer to cleanly change the tone of the map we're going to
- # if the previous map requested no tone updates and the new map wants them.
- # This is mostly cosmetic, and done before the original method is run.
- alias :ses_game_time_sm_post :post_transfer
- def post_transfer(*args, &block)
- if $game_map.no_tone?($game_map.last_map)
- unless $game_map.no_tone?
- time = $game_system.time
- return if time.stopped? && !time.running?
- tone = SES::Time::TONES[time.send(SES::Time::TONE_UNIT)]
- $game_map.screen.start_tone_change(tone, 1)
- end
- end
- ses_game_time_sm_post(*args, &block)
- end
- end
- #═╦═════════════════════════════════════════════════════════════════════════════
- # ║ ▲ class Scene_Map
- #═╩═════════════════════════════════════════════════════════════════════════════
Advertisement
Add Comment
Please, Sign In to add comment