Solistra

SES Time: Clock Extension

Dec 1st, 2012
597
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 26.33 KB | None | 0 0
  1. #═╦═════════════════════════════════════════════════════════════════════════════
  2. # ║ § SES - Time: Clock (v1.3) by Solistra               [License: CC BY-SA 3.0]
  3. # ║                                                            <RMVX Ace>
  4. #═╬═════════════════════════════════════════════════════════════════════════════
  5. # ║ § Change Log
  6. #─╫─────────────────────────────────────────────────────────────────────────────
  7. # ║ v1.3 (January 4th, 2013) - Compatibility fix to work with Dynamic Time v1.3.
  8. # ║ v1.2 (December 4th, 2012) - Added the tag <time no_clock> to maps. This tag
  9. # ║   allows the developer to create maps that suppress the on-map clock. You
  10. # ║   can also now create multiple clocks.
  11. # ║ v1.1 (December 2nd, 2012) - Added the ability for players to toggle whether
  12. # ║   or not the clock is visible and added relevant configuration options. Also
  13. # ║   added the ability to use a different clock in Scene_Menu with its own
  14. # ║   relevant settings, and rearranged some of the code for compatibility.
  15. # ║ v1.0 (December 1st, 2012) - Initial Release
  16. # ║
  17. #═╬═════════════════════════════════════════════════════════════════════════════
  18. # ║ § Summary
  19. #─╫─────────────────────────────────────────────────────────────────────────────
  20. # ║ This script is a simple extension to the SES Dynamic Time script that adds
  21. # ║ a user-defined clock to the map which can keep track of the current time
  22. # ║ and date.
  23. # ║
  24. #═╬═════════════════════════════════════════════════════════════════════════════
  25. # ║ § Required Scripts
  26. #─╫─────────────────────────────────────────────────────────────────────────────
  27. # ║ The SES Dynamic Time script (version 1.3 or higher) is required in order to
  28. # ║ use this script.
  29. # ║
  30. #═╬═════════════════════════════════════════════════════════════════════════════
  31. # ║ § Known Incompatibilities
  32. #─╫─────────────────────────────────────────────────────────────────────────────
  33. # ║ See the SES Dynamic Time script for known incompatibilities.
  34. # ║
  35. #═╬═════════════════════════════════════════════════════════════════════════════
  36. # ║ § Installation
  37. #─╫─────────────────────────────────────────────────────────────────────────────
  38. # ║ Place this script below the SES Dynamic Time script, above any other custom
  39. # ║ scripts, and above Main.
  40. # ║
  41. #═╬═════════════════════════════════════════════════════════════════════════════
  42. # ║ § Configuration
  43. #─╫─────────────────────────────────────────────────────────────────────────────
  44. # ║ This clock is very flexible (like the base script is), so there is, once
  45. # ║ again, a fair amount of configuration to do.
  46. # ║
  47. # ║ First, you will have to define which units of time you want to use in the
  48. # ║ text for your clock. The order that you define these units in is important,
  49. # ║ as the order is used when you set up the actual text below. (The order you
  50. # ║ have the units in indexes them from 0, not 1.)
  51. # ║
  52. # ║ Once you have the units you wish to use defined, you may optionally name
  53. # ║ any of the values from these units. To do this, you will have to modify
  54. # ║ the NAMES hash. The key of the hash should be the symbol corresponding to
  55. # ║ the unit of time you wish to have named values for, and the value of the
  56. # ║ key should be an array. For each element in the array, that numeric value
  57. # ║ for the specified unit of time will be replaced by the element. For example,
  58. # ║ let's define some day names (assuming we set up the base script to use 7
  59. # ║ days for each week):
  60. # ║
  61. # ║   NAMES = {
  62. # ║     :day => ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
  63. # ║     :month => ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
  64. # ║       "Sep", "Oct", "Nov", "Dec"]
  65. # ║   }
  66. # ║
  67. # ║ If $game_time.day is equal to 3, this will show "Wed" in the clock instead.
  68. # ║ As an added example, you can also see that you can use this for months. If
  69. # ║ you're using a meridian, you could name the values "AM" and "PM", as well.
  70. # ║ This is a VERY flexible option, so get creative with it.
  71. # ║
  72. # ║ If you're using hours in your clock, you can add the symbol corresponding
  73. # ║ to the unit you are using for hours in the FORMAT_HOUR array to have its
  74. # ║ values formatted as a standard clock instead of military time. This will
  75. # ║ format 0 as 12, and will appropriately create "PM" times for values that
  76. # ║ are greater than 12 (so 16 would become 4 for display purposes).
  77. # ║
  78. # ║ Below this, you will define the actual text used in your clock. This string
  79. # ║ requires some special explanation: it uses placeholders that can affect
  80. # ║ the formatting of the unit they represent. Here, you'll make use of the
  81. # ║ order of the units that you defined in the UNITS array.
  82. # ║
  83. # ║ There are three different placeholders for different formatting styles that
  84. # ║ you can use: <#>, (#), and {#} (Replace # with the index of the unit you
  85. # ║ want to use in the UNITS array). The <#> placeholder has no formatting;
  86. # ║ it simply inserts the value of the unit # represents. The (#) placeholder,
  87. # ║ on the other hand, offsets the value with spaces (so if the value of # is
  88. # ║ 9 and the maximum for this unit is 60, it will display as " 9"). Likewise,
  89. # ║ the {#} placeholder prefixes the unit with leading zeroes (so a 9 for the
  90. # ║ unit above would display as "09").
  91. # ║
  92. # ║ For example, let's create a clock that has the format HH:MM [AM|PM] M/D/Y:
  93. # ║
  94. # ║   UNITS = [:minute, :hour, :meridian, :day, :month, :year]
  95. # ║   NAMES = { :meridian => ["AM", "PM"] }
  96. # ║   TEXT  = "(1):{0} <2> (4)/{3}/<5>"
  97. # ║
  98. # ║ Given all of that configuration, we could end up with a clock that looks
  99. # ║ like this: " 7:08 PM  2/04/458".
  100. # ║
  101. # ║ Now that you've defined the clock text how you want it to appear, you will
  102. # ║ want to set up the properties of the clock window itself. In comparison
  103. # ║ to the above, this is extremely easy: it's just a four-element array to
  104. # ║ set the X position, Y position, width, and height of the window in pixels.
  105. # ║ For example, let's create a 250-pixel-wide clock in the upper-right:
  106. # ║
  107. # ║   WINDOW_PROPERTIES = [Graphics.width - 250, 0, 250, 48]
  108. # ║
  109. # ║ Play with those values all that you want to get the clock placed just where
  110. # ║ you like it; just note that there MUST be four elements to this array, and
  111. # ║ all four MUST be integers.
  112. # ║
  113. # ║ Below this is the most advanced portion of this script: constructors. You
  114. # ║ may have noticed that time can be split in interesting ways with the base
  115. # ║ Dynamic Time script -- but this has the potential to have hours that only
  116. # ║ go up to 6, or a maximum of 30 minutes instead of 60. Without constructors,
  117. # ║ you would be forced to recreate the structure of your time scheme in order
  118. # ║ to accurately show those hours or minutes in a way that makes sense for a
  119. # ║ standard clock (otherwise you'd end up going from 5:29 PM to 0:00 PM next).
  120. # ║
  121. # ║ This is where constructors come in. A constructor is basically a snippet of
  122. # ║ Ruby code that will replace the actual value of a unit of time for DISPLAY
  123. # ║ PURPOSES ONLY. The setup for this should look familiar by now: it's a hash
  124. # ║ with the unit of time to use the constructor for as the key, and a Proc to
  125. # ║ use as the constructor for this unit (note: a Proc is basically a block of
  126. # ║ Ruby code).
  127. # ║
  128. # ║ At this point, if you don't know basic Ruby syntax or how to use Ruby, you
  129. # ║ might do well not to play around with constructors until you learn more
  130. # ║ about the language. Having said that, here's an example of how to build
  131. # ║ some constructors for some common problems -- for the example, we have time
  132. # ║ split as 30 minutes per hour, 6 hours per time of day, 4 times of day per
  133. # ║ day, 7 days per week, 4 weeks per month, and 12 months per year:
  134. # ║
  135. # ║   CONSTRUCTORS = {
  136. # ║     :minute => Proc.new{$game_system.time.minute * 2}, # So 30 becomes 60.
  137. # ║     :hour   => Proc.new do
  138. # ║         t = $game_system.time
  139. # ║         t.hour + t.time_of_day * t.hour_max # Make an hour in military time.
  140. # ║       end,
  141. # ║     :day    => Proc.new do
  142. # ║         t = $game_system.time
  143. # ║         t.day + t.week * t.day_max # Builds an accurate day count.
  144. # ║       end,
  145. # ║     :month  => Proc.new{$game_system.time.month + 1}, # So 0 is 1.
  146. # ║   }
  147. # ║
  148. # ║ With these constructors in place, we can now use these irregular units of
  149. # ║ time in our clock and have them show up like a standard clock or calendar
  150. # ║ would show them.
  151. # ║
  152. # ║ If you do not understand that example or how it works, you can try playing
  153. # ║ with the constructors if you know basic Ruby, or feel free to ignore the
  154. # ║ constructors completely.
  155. # ║
  156. # ║ For anyone who wishes to use constructors, note that the constructor's code
  157. # ║ replaces the value of the unit of time BEFORE any other formatting is done
  158. # ║ on the unit for display purposes. This is an EXTREMELY flexible option, and
  159. # ║ is only limited by your imagination and knowledge of Ruby.
  160. # ║
  161. #═╬═════════════════════════════════════════════════════════════════════════════
  162. # ║ § Script Calls
  163. #─╫─────────────────────────────────────────────────────────────────────────────
  164. # ║ With version 1.2 of this script, you can now add multiple clocks to your
  165. # ║ game relatively easily.
  166. # ║
  167. # ║ To do this, you will need to push an array of arguments to send to your
  168. # ║ clocks into $game_system.clocks. Each clock takes the following arguments:
  169. # ║ the units of time this clock uses, a hash of names for these units, an array
  170. # ║ of units to be formatted as standard hours, the text to use for your clock
  171. # ║ on the map, text to use for the clock in the menu, an array of the
  172. # ║ properties used for the window on the map (x, y, width, height), an array
  173. # ║ of the properties used for the window in the menu (x, y, width, height), and
  174. # ║ a hash of any contructors you wish to use.
  175. # ║
  176. # ║   $game_system.clocks.push([...arguments...])
  177. # ║
  178. #═╬═════════════════════════════════════════════════════════════════════════════
  179. # ║ § Tags
  180. #─╫─────────────────────────────────────────────────────────────────────────────
  181. # ║ ● Map
  182. # ║   <time no_clock>
  183. # ║     Suppresses showing the clock on this map only.
  184. # ║
  185. #═╬═════════════════════════════════════════════════════════════════════════════
  186. # ║ § Aliased Methods
  187. #─╫─────────────────────────────────────────────────────────────────────────────
  188. # ║ ● Game_System
  189. # ║     initialize
  190. # ║ ● Scene_Map
  191. # ║     create_all_windows
  192. # ║ ● Scene_Menu
  193. # ║     start
  194. # ║
  195. #═╬═════════════════════════════════════════════════════════════════════════════
  196. # ║ § New Methods
  197. #─╫─────────────────────────────────────────────────────────────────────────────
  198. # ║ ● Game_Map
  199. # ║     no_clock?
  200. # ║ ● Scene_Map
  201. # ║     create_clock_windows
  202. # ║ ● Scene_Menu
  203. # ║     create_clock_windows
  204. # ║
  205. #═╬═════════════════════════════════════════════════════════════════════════════
  206. # ║ ▼ module SES::Time::Clock
  207. #═╩═════════════════════════════════════════════════════════════════════════════
  208. module SES module Time module Clock
  209.   class << self; attr_accessor :visible end
  210.   #═╦═══════════════════════════════════════════════════════════════════════════
  211.   # ║ α BEGIN CONFIGURATION
  212.   #═╩═══════════════════════════════════════════════════════════════════════════
  213.   # Determines whether the clock is visible by default or not. (Note: this
  214.   # affects all clocks.)
  215.   @visible = true
  216.  
  217.   # The input key used to toggle the visibility of the clock. You may set this
  218.   # to nil if you do not want the player to be able to toggle the clock. (This
  219.   # setting is persistent across all clocks as well.)
  220.   TOGGLE_VISIBILITY = :L
  221.  
  222.   # Set whether or not you wish to have the clock available in the menu.
  223.   CLOCK_IN_MENU = true
  224.  
  225.   # Define which units of game time you will use in your clock's text here.
  226.   # Note: the order that you put your units in here is important, as the order
  227.   # is referenced in the TEXT constant below.
  228.   #       [index 0, index 1, index 2, ...]
  229.   UNITS = [:day, :hour, :minute, :time_of_day]
  230.  
  231.   # Name any units of time that you want to have alternate names for here.
  232.   # (Check the Configuration section in the header of this script for more
  233.   # information.)
  234.   NAMES = {
  235.     # [unit symbol] => ["Name 1", "Name 2", ...]
  236.     :time_of_day => ["AM", "AM", "PM", "PM"]
  237.   }
  238.  
  239.   # Configure any units you wish to offset as standard (not military) hours.
  240.   FORMAT_HOUR = [:hour]
  241.  
  242.   # Define the text used by the clock. (Check the Configuration section in the
  243.   # header of this script for more information.)
  244.   TEXT = "(1):{2} <3>"
  245.   MENU_TEXT = "Day <0>\n(1):{2} <3>"
  246.  
  247.   # Set the x, y, width, and height properties for the clock window here.
  248.   # All are measured in pixels. (Note: this array MUST have four elements!)
  249.   MAP_ARGS = [Graphics.width - 120, Graphics.height - 48, 120, 48]
  250.   MENU_ARGS = [0, Graphics.height - 120, 160, 72]
  251.  
  252.   # Build any custom constructors that you wish to use here. This is relatively
  253.   # advanced, and does require at least minimal knowledge of Ruby.
  254.   CONSTRUCTORS = {
  255.     :hour => Proc.new do
  256.         t = $game_system.time; t.hour + t.time_of_day * t.hour_max
  257.       end,
  258.   }
  259.   #═╦═══════════════════════════════════════════════════════════════════════════
  260.   # ║ Ω END CONFIGURATION
  261.   #─╫───────────────────────────────────────────────────────────────────────────
  262.   # ║ ▼ class Window
  263.   #═╩═══════════════════════════════════════════════════════════════════════════
  264.   class Window < Window_Base
  265.     def initialize(units = UNITS, names = NAMES, hour_format = FORMAT_HOUR,
  266.       text = TEXT, menu_text = MENU_TEXT, map_args = MAP_ARGS, menu_args =
  267.       MENU_ARGS, constructors = CONSTRUCTORS)
  268.       # Begin the actual initialization here.
  269.       @units, @names, @hour_format = units, names, hour_format
  270.       @text, @menu_text = text, menu_text
  271.       @constructors = constructors
  272.       super(*(SceneManager.scene.is_a?(Scene_Map) ? map_args : menu_args))
  273.       if SceneManager.scene.is_a?(Scene_Menu) then self.openness = 255
  274.       else self.openness = Clock.visible ? 255 : 0 end
  275.       initialize_tags
  276.       refresh
  277.     end
  278.    
  279.     def update
  280.       super
  281.       refresh if $game_system.time.update_conditions_met? && self.open?
  282.       toggle_visibility if Input.trigger?(TOGGLE_VISIBILITY)
  283.     end
  284.    
  285.     def toggle_visibility
  286.       return if SceneManager.scene.is_a?(Scene_Menu)
  287.       if self.open? then self.close
  288.       else self.open && refresh end
  289.       Clock.visible = !Clock.visible
  290.     end
  291.    
  292.     def refresh
  293.       contents.clear
  294.       draw_text_ex(4, 0, parse_clock_text)
  295.     end
  296.    
  297.     def initialize_tags
  298.       @tags = {
  299.         # Simple "just return it" tag.
  300.         '\<#\>' => Proc.new{|var| var},
  301.         # The whitespace offset tag.
  302.         '\(#\)' => Proc.new do |var, index|
  303.           max = $game_system.time.send("#{@units[index]}_max").to_s.length
  304.           if max - var.length > 0
  305.             var.length == max ? var : (" " * (max - var.length)) << var
  306.           else var end
  307.         end,
  308.         # Decimal prefix tag.
  309.         '\{#\}' => Proc.new do |var, index|
  310.           max = $game_system.time.send("#{@units[index]}_max").to_s.length
  311.           if max - var.length > 0
  312.             var.length == max ? var : ("0" * (max - var.length)) << var
  313.           else var end
  314.         end
  315.       }
  316.     end
  317.    
  318.     def parse_clock_text
  319.       text = (SceneManager.scene.is_a?(Scene_Map) ? @text : @menu_text).clone
  320.       time = $game_system.time
  321.       @units.each_with_index do |u, i|
  322.         v = @names[u] ? @names[u][time.send(u)] : time.send(@units[i])
  323.         v = format_variable(v, @units[i])
  324.         text = parse_text(text, i, v)
  325.       end
  326.       return text
  327.     end
  328.    
  329.     def parse_text(text, i, v)
  330.       @tags.each do |tag, code|
  331.         text.gsub!(Regexp.new(tag.sub("#", i.to_s)), code.call(v.to_s, i))
  332.       end
  333.       return text
  334.     end
  335.    
  336.     def format_variable(var, unit)
  337.       var = @constructors[unit].call if @constructors.include?(unit)
  338.       return format_hour(var) if @hour_format.include?(unit)
  339.       var
  340.     end
  341.    
  342.     def format_hour(var)
  343.       if var == 0 then 12
  344.       elsif var > 12 then var - 12
  345.       else var end
  346.     end
  347.   end
  348.   #═╦═══════════════════════════════════════════════════════════════════════════
  349.   # ║ ▲ class Window
  350.   #═╩═══════════════════════════════════════════════════════════════════════════
  351. end end end
  352. #═╦═════════════════════════════════════════════════════════════════════════════
  353. # ║ ▲ module SES::Time::Clock
  354. #═╩═════════════════════════════════════════════════════════════════════════════
  355.                  ($imported ||= {})["SES - Time: Clock"] = 1.3
  356.         if $imported["SES - Time"].nil? || $imported["SES - Time"] < 1.3
  357.              raise("SES Clock requires SES Time v1.3 or greater.")
  358.                                       end
  359. #═╦═════════════════════════════════════════════════════════════════════════════
  360. # ║ ▼ class Game_System
  361. #═╩═════════════════════════════════════════════════════════════════════════════
  362. class Game_System
  363.   attr_accessor :clocks
  364.   alias :ses_time_clock_sys_init :initialize
  365.   def initialize(*args, &block)
  366.     ses_time_clock_sys_init(*args, &block)
  367.     @clocks = []
  368.     @clocks.push([])
  369.   end
  370. end
  371. #═╦═════════════════════════════════════════════════════════════════════════════
  372. # ║ ▲ class Game_System
  373. #─╫─────────────────────────────────────────────────────────────────────────────
  374. # ║ ▼ class Game_Map
  375. #═╩═════════════════════════════════════════════════════════════════════════════
  376. class Game_Map
  377.   def no_clock?(map = @map)
  378.     (map.note =~ /\<time no\_clock\>/ ? true : false) unless map.nil?
  379.   end
  380. end
  381. #═╦═════════════════════════════════════════════════════════════════════════════
  382. # ║ ▲ class Game_Map
  383. #─╫─────────────────────────────────────────────────────────────────────────────
  384. # ║ ▼ class Scene_Map
  385. #═╩═════════════════════════════════════════════════════════════════════════════
  386. class Scene_Map < Scene_Base
  387.   alias :ses_time_clock_map_caw :create_all_windows
  388.   def create_all_windows(*args, &block)
  389.     ses_time_clock_map_caw(*args, &block)
  390.     create_clock_windows unless $game_map.no_clock?
  391.   end
  392.  
  393.   def create_clock_windows
  394.     $game_system.clocks.each_with_index do |args, i|
  395.       instance_variable_set("@clock_#{i}", SES::Time::Clock::Window.new(*args))
  396.     end
  397.   end
  398. end
  399. #═╦═════════════════════════════════════════════════════════════════════════════
  400. # ║ ▲ class Scene_Map
  401. #─╫─────────────────────────────────────────────────────────────────────────────
  402. # ║ ▼ class Scene_Menu
  403. #═╩═════════════════════════════════════════════════════════════════════════════
  404. if SES::Time::Clock::CLOCK_IN_MENU
  405.   class Scene_Menu < Scene_MenuBase
  406.     alias :ses_time_clock_menu_start :start
  407.     def start(*args, &block)
  408.       ses_time_clock_menu_start(*args, &block)
  409.       create_clock_windows
  410.     end
  411.    
  412.     def create_clock_windows
  413.       $game_system.clocks.each_with_index do |a, i|
  414.         instance_variable_set("@clock_#{i}", SES::Time::Clock::Window.new(*a))
  415.       end
  416.     end
  417.   end
  418. end
  419. #═╦═════════════════════════════════════════════════════════════════════════════
  420. # ║ ▲ class Scene_Menu
  421. #═╩═════════════════════════════════════════════════════════════════════════════
Advertisement
Add Comment
Please, Sign In to add comment