Solistra

SES Climate

Jan 4th, 2013
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 25.49 KB | None | 0 0
  1. #═╦═════════════════════════════════════════════════════════════════════════════
  2. # ║ § Climate (1.0) by Solistra                          [License: CC BY-SA 3.0]
  3. # ║                                                            <RMVX Ace>
  4. #═╬═════════════════════════════════════════════════════════════════════════════
  5. # ║ § Change Log
  6. #─╫─────────────────────────────────────────────────────────────────────────────
  7. # ║ v1.0 (January 4th, 2013) - Initial release
  8. # ║
  9. #═╬═════════════════════════════════════════════════════════════════════════════
  10. # ║ § Summary
  11. #─╫─────────────────────────────────────────────────────────────────────────────
  12. # ║ This script allows you to make use of weather effects by defining specific
  13. # ║ climates, each of which containing its own set of possible weather effects
  14. # ║ and the percentage chance for each effect to occur. You may define climate
  15. # ║ types for individual maps, or you can use regions to change the climate of
  16. # ║ a single map (a field map, for example). You may also define maps that have
  17. # ║ no climate, and maps which only play a muted BGS instead of the full effect
  18. # ║ (useful for interior maps).
  19. # ║
  20. #═╬═════════════════════════════════════════════════════════════════════════════
  21. # ║ § Required Scripts
  22. #─╫─────────────────────────────────────────────────────────────────────────────
  23. # ║ None.
  24. # ║
  25. #═╬═════════════════════════════════════════════════════════════════════════════
  26. # ║ § Known Incompatibilities
  27. #─╫─────────────────────────────────────────────────────────────────────────────
  28. # ║ None.
  29. # ║
  30. #═╬═════════════════════════════════════════════════════════════════════════════
  31. # ║ § Installation
  32. #─╫─────────────────────────────────────────────────────────────────────────────
  33. # ║ Place this script below Materials, but above Main.
  34. # ║
  35. #═╬═════════════════════════════════════════════════════════════════════════════
  36. # ║ § Configuration
  37. #─╫─────────────────────────────────────────────────────────────────────────────
  38. # ║ Before anything else, you'll want to configure whether or not the climate
  39. # ║ manager is active when a new game is started. If you set ENABLED to "false",
  40. # ║ note that you will have to manually start the manager (check the section on
  41. # ║ Script Calls below).
  42. # ║
  43. # ║ Once you have that, the real work begins: defining climate types. In this
  44. # ║ script, climates each have their own set of possible weather effects and
  45. # ║ a percentage value for each weather effect to occur (below this, you can
  46. # ║ also define your own weather effects, as well). The available climate types
  47. # ║ are written as a hash like so:
  48. # ║   TYPES = { arid: {none: 100}, temperate: {none: 60, rain: 20, storm: 10} }
  49. # ║
  50. # ║ This would define two climate types: arid and temperate. The arid climate
  51. # ║ type would always have no weather effect, while the temperate climate has
  52. # ║ a 60% of clear weather, a 20% chance of rain, and 10% chance of a storm.
  53. # ║ Note that you should make these percentage values add up to 100 for this
  54. # ║ script to function properly!
  55. # ║
  56. # ║ Below this, you can set up your own weather effects. This is a relatively
  57. # ║ advanced topic, and is unlikely to be useful unless you are using a script
  58. # ║ that provides new weather effects. If you are, however, you can define a
  59. # ║ new weather effect relatively easily:
  60. # ║   CALLS = { example: Proc.new{puts "Your Ruby code here."} }
  61. # ║
  62. # ║ Now you can define any background sounds that you want to play with your
  63. # ║ weather effects. This is a relatively simple hash which can be configured
  64. # ║ like so:
  65. # ║   BGS = { weather: ["Sound file", volume, pitch] }
  66. # ║   BGS = { rain: ["Rain", 80, 100] }
  67. # ║
  68. # ║ Any weather effect that does not have an associated BGS in this hash will
  69. # ║ have no BGS by default. Below this, you may define the default climate type
  70. # ║ that the climate manager will start with by setting DEFAULT_TYPE to a symbol
  71. # ║ corresponding to the name of a climate type (note that this is only used
  72. # ║ when a new game is started).
  73. # ║
  74. # ║ Lastly, you can configure the base length of each weather effect and the
  75. # ║ amount of time that this can vary with the WEATHER_LENGTH and WEATHER_VARY
  76. # ║ options. These are measured in frames (60 frames ~= 1 second), and a random
  77. # ║ amount from 0 to WEATHER_VARY is subtracted from WEATHER_LENGTH to get the
  78. # ║ amount of time for a weather effect to display. If you want weather effects
  79. # ║ to always take the same amount of time, you may set WEATHER_VARY to 1.
  80. # ║
  81. #═╬═════════════════════════════════════════════════════════════════════════════
  82. # ║ § Tags
  83. #─╫─────────────────────────────────────────────────────────────────────────────
  84. # ║ ● Map Note
  85. # ║   <climate type !name!>
  86. # ║     ► Replacements:
  87. # ║       !name! with the name of a defined climate type.
  88. # ║   <climate region !id! !name!>
  89. # ║     ► Replacements:
  90. # ║       !id! with a valid region ID, and !name! with the name of a defined
  91. # ║       climate type.
  92. # ║   <weather none>
  93. # ║       Disables the climate manager and its weather effects on this map.
  94. # ║   <weather sound_only>
  95. # ║       Plays a muted BGS with no weather effect for the current climate.
  96. # ║       Useful for interiors, for example.
  97. # ║
  98. #═╬═════════════════════════════════════════════════════════════════════════════
  99. # ║ § Script Calls
  100. #─╫─────────────────────────────────────────────────────────────────────────────
  101. # ║ There are a handful of script calls that you will most likely want to use,
  102. # ║ but for the most part, the climate manager does not make much use of them.
  103. # ║ In any case, you can enable and disable the climate manager with these
  104. # ║ script calls:
  105. # ║   $game_system.climate.enable OR start OR run
  106. # ║   $game_system.climate.disable OR stop OR pause
  107. # ║
  108. # ║ You may also force a particular weather effect to be shown and define how
  109. # ║ long it should be active with this script call:
  110. # ║   $game_system.climate.force_weather(:effect, frames)
  111. # ║
  112. # ║ Note that this is NOT a permanent change -- if the climate type changes in
  113. # ║ any way while your forced weather is active, it will deactivate and the
  114. # ║ manager will take over instead. You may also omit the number of frames for
  115. # ║ this weather effect to remain active if you want it to be active for the
  116. # ║ remainder of the time of the effect that it replaces.
  117. # ║
  118. # ║ Also, if you do not want to have this effect stop after any amount of time,
  119. # ║ you may use 1.0 / 0.0 as the frames (which is infinity), and if you want to
  120. # ║ immediately force a weather change, you can use 0. Examples:
  121. # ║   $game_system.climate.force_weather(:rain, 1.0/0.0)
  122. # ║   $game_system.climate.force_weather(:none, 0)
  123. # ║
  124. #═╬═════════════════════════════════════════════════════════════════════════════
  125. # ║ § Aliased Methods
  126. #─╫─────────────────────────────────────────────────────────────────────────────
  127. # ║ ● Game_System
  128. # ║     initialize
  129. # ║ ● Game_Map
  130. # ║     setup
  131. # ║     update
  132. # ║ ● Scene_Map
  133. # ║     update
  134. # ║     post_transfer
  135. # ║
  136. #═╬═════════════════════════════════════════════════════════════════════════════
  137. # ║ § New Methods
  138. #─╫─────────────────────────────────────────────────────────────────────────────
  139. # ║ ● Game_Map
  140. # ║     update_climate_regions
  141. # ║     no_weather?
  142. # ║     weather_sound_only?
  143. # ║     climate_type
  144. # ║     determine_climate_regions
  145. # ║
  146. #═╬═════════════════════════════════════════════════════════════════════════════
  147. # ║ ▼ module SES::Climate
  148. #═╩═════════════════════════════════════════════════════════════════════════════
  149. module SES module Climate
  150.   #═╦═══════════════════════════════════════════════════════════════════════════
  151.   # ║ α BEGIN CONFIGURATION
  152.   #═╩═══════════════════════════════════════════════════════════════════════════
  153.   # Whether or not the climate system should be enabled by default when a new
  154.   # game is started. If this is set to false, you will have to manually enable
  155.   # the climate system with the script call "$game_system.climate.enable".
  156.   ENABLED = true
  157.  
  158.   # These are the climate types that you can use. Here you will define the name
  159.   # for each climate type and the chance for each weather effect to take place.
  160.   # Note that the chances are percentages, so if you want them to be accurate,
  161.   # you should make the sum of all of the weather chances equal 100.
  162.   # climate_name: {weather_type: chance, weather_type: chance}
  163.   TYPES = { arid:      {none: 100},
  164.             temperate: {none: 65, rain: 25, storm: 10},
  165.             tropical:  {none: 40, rain: 40, storm: 20},
  166.             polar:     {snow: 60, blizzard: 25, none: 15},
  167.           }
  168.  
  169.   # The script calls used for weather effects. This is an advanced option --
  170.   # the defaults should suffice unless you are using an extended weather system
  171.   # or want to use your own script calls instead of the defaults. Ruby knowledge
  172.   # is required. Note: do not remove the none effect, this script depends on it!
  173.   # weather_type_name: Proc.new{puts "Your Ruby code here."}
  174.   CALLS = { none:     Proc.new{$game_map.screen.change_weather(:none, 0, 120)},
  175.             rain:     Proc.new{$game_map.screen.change_weather(:rain, 3, 120)},
  176.             storm:    Proc.new{$game_map.screen.change_weather(:storm, 6, 120)},
  177.             snow:     Proc.new{$game_map.screen.change_weather(:snow, 2, 120)},
  178.             blizzard: Proc.new{$game_map.screen.change_weather(:snow, 9, 120)},
  179.           }
  180.  
  181.   # Determine whether or not you want the climate manager to also play sounds
  182.   # for weather types here (if it does, you won't want to use a BGS on your
  183.   # maps; this script more or less monopolizes them).
  184.   USE_BGS = true
  185.  
  186.   # Background sounds for individual weather effects. Any effects not present
  187.   # in this hash will have no associated background sound.
  188.   # effect_name: ["Sound file", volume, pitch]
  189.   BGS   = { rain:      ["Rain",  80, 100],
  190.             storm:     ["Storm", 60, 100],
  191.             blizzard:  ["Wind",  40, 100]
  192.           }
  193.  
  194.   # The default climate type (only used when a new game is started). Note that
  195.   # this must be in the form of a symbol (so type becomes :type).
  196.   DEFAULT_TYPE   = :temperate
  197.  
  198.   # Length, in frames, of weather effects. This is the base length.
  199.   WEATHER_LENGTH = 7200
  200.  
  201.   # Amount of variance, in frames, to apply to the base weather length. A random
  202.   # number from 1 up to the value of this constant is subtracted from the base
  203.   # weather length to determine the overall length of each weather effect. Note:
  204.   # this option can be set to 1 to have no variance applied.
  205.   WEATHER_VARY   = 1800
  206.   #═╦═══════════════════════════════════════════════════════════════════════════
  207.   # ║ Ω END CONFIGURATION
  208.   #─╫───────────────────────────────────────────────────────────────────────────
  209.   # ║ ▼ class Manager
  210.   #═╩═══════════════════════════════════════════════════════════════════════════
  211.   class Manager
  212.     attr_reader :type
  213.    
  214.     def initialize() @enabled, @type, @delay = ENABLED, DEFAULT_TYPE, 1 end
  215.    
  216.     # Selects a new weather effect from the list of effects available for the
  217.     # current map's climate type.
  218.     def update
  219.       @delay = @delay <= 0 ? WEATHER_LENGTH - rand(WEATHER_VARY) : @delay - 1
  220.       return unless update_conditions_met?
  221.       set_climate_type if type_conditions_met?
  222.       roll_weather_chance
  223.       set_weather_effect
  224.       update_weather_effect
  225.     end
  226.    
  227.     # Performs a basic update -- sets the climate type and weather effect, but
  228.     # does not re-roll the weather chance.
  229.     def update_basic
  230.       return unless @enabled
  231.       set_climate_type if type_conditions_met?
  232.       set_weather_effect
  233.       update_weather_effect
  234.     end
  235.    
  236.     # This method determines if the manager is allowed to update or not.
  237.     def update_conditions_met?
  238.       return false unless @enabled && @delay <= 0
  239.       return false if $game_map.no_weather?
  240.       return true
  241.     end
  242.    
  243.     # Updates the effect for the currently selected weather type. Note that this
  244.     # method does not change the weather type -- that is done in the method
  245.     # set_weather_effect.
  246.     def update_weather_effect
  247.       return unless @enabled && @weather
  248.       if $game_map.no_weather? || $game_map.weather_sound_only?
  249.         CALLS[:none].call
  250.         return unless $game_map.weather_sound_only?
  251.       else CALLS[@weather].call end
  252.       if USE_BGS
  253.         sound = BGS[@weather]
  254.         if sound
  255.           volume = $game_map.weather_sound_only? ? sound[1] / 2 : sound[1]
  256.           RPG::BGS.new("#{sound[0]}", volume, sound[2]).play
  257.         else RPG::BGS.fade(2000) end
  258.       end
  259.     end
  260.    
  261.     # Sets the active climate type.
  262.     def set_climate_type
  263.       return unless @enabled
  264.       @type = player_region > 0 && $game_map.climate_regions[player_region] ?
  265.       $game_map.climate_regions[player_region] : $game_map.climate_type
  266.     end
  267.    
  268.     # Determines whether or not the climate type should be set.
  269.     def type_conditions_met?
  270.       return false unless @enabled
  271.       return true if region_conditions_met?
  272.       return true if @type != $game_map.climate_type
  273.       return false
  274.     end
  275.    
  276.     # Determines if the player is in a region with an assigned climate type
  277.     # that is not the same as the currently active climate type.
  278.     def region_conditions_met?
  279.       return false unless @enabled
  280.       if player_region > 0 && $game_map.climate_regions[player_region]
  281.         return true if @type != $game_map.climate_regions[player_region]
  282.       end
  283.       return false
  284.     end
  285.    
  286.     # Sets the current weather effect based on the rolled weather chance, then
  287.     # updates the effect so that it is displayed.
  288.     def set_weather_effect
  289.       return unless @enabled && @type && @chance
  290.       sum = 0; TYPES[@type].each do |weather, value|
  291.         last_sum, sum = sum, sum + value
  292.         next unless @chance >= last_sum && @chance < sum
  293.         @weather = weather; break
  294.       end
  295.       update_weather_effect
  296.     end
  297.    
  298.     # Forces the weather to a specific weather effect for an optional amount of
  299.     # time (written in number of frames).
  300.     def force_weather(effect, time = @delay)
  301.       @weather, @delay = effect.to_sym, time
  302.       update_weather_effect
  303.     end
  304.    
  305.     # Convenience methods to roll the weather chance and get the region ID that
  306.     # the player is in respectively.
  307.     def roll_weather_chance() @chance = rand(100) end
  308.     def player_region() $game_map.region_id($game_player.x, $game_player.y) end
  309.    
  310.     # Convenience methods to enable or disable the climate manager.
  311.     def enable() @enabled = true; force_weather(:none, 1) end
  312.     alias :start :enable; alias :run :start
  313.     def disable() @enabled = false end
  314.     alias :pause :disable; alias :stop :pause
  315.     def enabled?() @enabled end
  316.   end
  317.   #═╦═══════════════════════════════════════════════════════════════════════════
  318.   # ║ ▲ class Manager
  319.   #═╩═══════════════════════════════════════════════════════════════════════════
  320. end end
  321. #═╦═════════════════════════════════════════════════════════════════════════════
  322. # ║ ▲ module SES::Climate
  323. #═╩═════════════════════════════════════════════════════════════════════════════
  324.                    ($imported ||= {})["SES - Climate"] = 1.0
  325. #═╦═════════════════════════════════════════════════════════════════════════════
  326. # ║ ▼ class Game_System
  327. #═╩═════════════════════════════════════════════════════════════════════════════
  328. class Game_System
  329.   attr_reader :climate
  330.  
  331.   # Aliased to initialize the new instance variable @climate, which holds an
  332.   # instance of the climate manager.
  333.   alias :ses_climate_gs_init :initialize
  334.   def initialize(*args, &block)
  335.     ses_climate_gs_init(*args, &block)
  336.     @climate = SES::Climate::Manager.new
  337.   end
  338. end
  339. #═╦═════════════════════════════════════════════════════════════════════════════
  340. # ║ ▲ class Game_System
  341. #─╫─────────────────────────────────────────────────────────────────────────────
  342. # ║ ▼ class Game_Map
  343. #═╩═════════════════════════════════════════════════════════════════════════════
  344. class Game_Map
  345.   attr_reader :last_map, :climate_regions
  346.  
  347.   # Aliased to provide information about the previous map and collect climate
  348.   # regions defined in the map's note box.
  349.   alias :ses_climate_gm_setup :setup
  350.   def setup(*args, &block)
  351.     @last_map = @map unless @map.nil?
  352.     ses_climate_gm_setup(*args, &block)
  353.     @climate_regions = determine_climate_regions
  354.   end
  355.  
  356.   # Aliased to make use of the new method update_climate_regions.
  357.   alias :ses_climate_gm_upd :update
  358.   def update(*args, &block)
  359.     ses_climate_gm_upd(*args, &block)
  360.     update_climate_regions
  361.   end
  362.  
  363.   # New method that will cause the climate type and weather effect to be changed
  364.   # accordingly if the player enters a climate region.
  365.   def update_climate_regions
  366.     if $game_system.climate.region_conditions_met?
  367.       $game_system.climate.update_basic
  368.     end
  369.   end
  370.  
  371.   # Methods for accessing information relevant to the climate manager that is
  372.   # stored in a map's note box.
  373.   def no_weather?(map = @map) map.note =~ /\<weather none\>/ ? true : false end
  374.  
  375.   def weather_sound_only?(map = @map)
  376.     map.note =~ /\<weather sound\_only\>/ ? true : false
  377.   end
  378.  
  379.   def climate_type(map = @map)
  380.     map.note =~ /\<climate type (\S+)\>/ ? $1.to_sym : $game_system.climate.type
  381.   end
  382.  
  383.   def determine_climate_regions()
  384.     hash = {}; @map.note.split(/[\r\n]/).each do |note|
  385.       hash[$1.to_i] = $2.to_sym if note =~ /\<climate region (\d{1,2}) (\S+)>/
  386.     end; return hash
  387.   end
  388. end
  389. #═╦═════════════════════════════════════════════════════════════════════════════
  390. # ║ ▲ class Game_Map
  391. #─╫─────────────────────────────────────────────────────────────────────────────
  392. # ║ ▼ class Scene_Map
  393. #═╩═════════════════════════════════════════════════════════════════════════════
  394. class Scene_Map < Scene_Base
  395.   # Aliased to update the climate manager when Scene_Map is the active scene.
  396.   alias :ses_climate_sm_upd :update
  397.   def update(*args, &block)
  398.     ses_climate_sm_upd(*args, &block)
  399.     $game_system.climate.update
  400.   end
  401.  
  402.   # Aliased to update the climate manager accordingly based on information
  403.   # provided both by the current map and the previous one.
  404.   alias :ses_climate_sm_post :post_transfer
  405.   def post_transfer(*args, &block)
  406.     if $game_system.climate.enabled?
  407.       if $game_map.no_weather? || $game_map.weather_sound_only?
  408.         $game_map.screen.change_weather(:none, 0, 0)
  409.         RPG::BGS.stop if $game_map.no_weather?
  410.       else
  411.         if $game_map.climate_type($game_map.last_map) != $game_map.climate_type
  412.           $game_system.climate.update_basic
  413.         else $game_system.climate.update_weather_effect end
  414.       end
  415.     end
  416.     ses_climate_sm_post(*args, &block)
  417.   end
  418. end
  419. #═╦═════════════════════════════════════════════════════════════════════════════
  420. # ║ ▲ class Scene_Map
  421. #═╩═════════════════════════════════════════════════════════════════════════════
Advertisement
Add Comment
Please, Sign In to add comment