[XP] Advanced Time and Environment System (ATES)

Started by ThallionDarkshine, February 12, 2013, 06:27:10 pm

Previous topic - Next topic

ThallionDarkshine

February 12, 2013, 06:27:10 pm Last Edit: December 18, 2017, 10:40:38 am by ThallionDarkshine
Advanced Time and Environment System (ATES)
Authors: Blizzard, ThallionDarkshine
Version: 1.1
Type: Time and Weather System
Key Term: Custom Environment System



Introduction

You all know Blizz's old time system, the ATES. Well, I saw it in his dev pack, and saw that he had never finished implementing all the planned features. So, I decided to finish it for him. This system adds a time and weather system to games that can be turned on and off at will. Every aspect of the script is configurable, from the time system, to the weather system, and even the clock hud.

The time system allows you to create multiple times of day, each with their own unique and configurable tint. At any point within the day, the script will interpolate between the two closest times of day to create the current tint. In turn, these times of day will fall at different times throughout the year. You can set the values for the longest and shortest days of the year, and the script will determine the current times by interpolating between these.

The weather system gives you lots of options, allowing you to customize the bgs, fog, weather effect, and even effects like thunder with screen flashes and sound effects. Each weather effect can be assigned a severity, which influences the likelihood that they will occur. More on this when I talk about seasons. You can also configure a range of durations for each weather effect. When a weather effect starts, a random value in the range will be chosen for its duration.

Both the tint and the weather effects are influenced by the player's current location (outside, inside, or inside a dark place). When outside, all tint and weather effects will be applied at full force. When inside, the engine weather effects (rain, snow, etc) and fog effects will not be applied, and sounds and tints will be dampened. When inside a dark place, everything is the same as for inside, except the screen tint will be set to a fixed configurable value.

The year is divided into seasons set up in the configuration. Each season has a defined temperature range, probability of weather, bad weather, and very bad weather, and set of weather possibilities.

You can also configure various terrains that can influence various aspects of the system. Each terrain has a defined range of temperature modifiers, and a set of weather effect exclusions.

You can create holidays, which have essentially no effect besides changing certain lines of text in the clock. Each holiday can either be defined by date or by a position within the month (i.e. first monday, second to last thursday, etc).

Finally, the clock is fully configurable, and gives you a wide range of information to pull from and various methods to display it. For instance, you can display either the weekday name (replaced by the holiday if applicable) or the weekday abbreviation. More on these in the instructions in the script.

This work is protected by the following license:
Quote
Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
( http://creativecommons.org/licenses/by-nc-sa/3.0/ )

You are free:

to Share - to copy, distribute and transmit the work
to Remix -- to adapt the work

Under the following conditions:

Attribution. You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).

Noncommercial. You may not use this work for commercial purposes.

Share alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.

- For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page.

- Any of the above conditions can be waived if you get permission from the copyright holder.

- Nothing in this license impairs or restricts the author's moral rights.



Features


  • Adds a weather and time system to your game.

  • Disable several pieces of the system at will: the tinting, the weather, the clock, or the entire script.

  • Lock in any particular weather.

  • Jump quickly between time periods configured in the script.

  • Customize your own terrains, weather types, and time periods, as well as the screen tints for these time periods.

  • And much more!




Screenshots

Spoiler: ShowHide








Demo

https://app.box.com/s/vi3hqfkn2l8z0upnlx60


Script

Spoiler: ShowHide

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Advanced Time and Environment System (ATES) by Blizzard and ThallionDarkshine
# Version: 1.1
# Type: Autonomous Timeflow and Environment Controller
# Date v0.3: 11.3.2008
# Date v0.31: 8.4.2009
# Date v0.32: 13.4.2009
# Date v0.33: 4.5.2009
# Date v0.34: 5.5.2009
# Date v1.0: 12.2.2013
# Date v1.01: 28.4.2013
# Date v1.02: 20.3.2015
# Date v1.1: 18.12.2017
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#   
#  This work is protected by the following license:
# #----------------------------------------------------------------------------
# # 
# #  Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# #  ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# # 
# #  You are free:
# # 
# #  to Share - to copy, distribute and transmit the work
# #  to Remix - to adapt the work
# # 
# #  Under the following conditions:
# # 
# #  Attribution. You must attribute the work in the manner specified by the
# #  author or licensor (but not in any way that suggests that they endorse you
# #  or your use of the work).
# # 
# #  Noncommercial. You may not use this work for commercial purposes.
# # 
# #  Share alike. If you alter, transform, or build upon this work, you may
# #  distribute the resulting work only under the same or similar license to
# #  this one.
# # 
# #  - For any reuse or distribution, you must make clear to others the license
# #    terms of this work. The best way to do this is with a link to this web
# #    page.
# # 
# #  - Any of the above conditions can be waived if you get permission from the
# #    copyright holder.
# # 
# #  - Nothing in this license impairs or restricts the author's moral rights.
# # 
# #----------------------------------------------------------------------------
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# Compatibility:
#
#   99% compatible with SDK v1.x. 90% compatible with SDK 2.x. WILL corrupt old
#   savegames. Can cause incompatibilty issues with DNS-es.
#
#
# Features:
#
#   - complete control over and easy manipulating of time and weather
#   - customizable day and night tinting
#   - HUD clock optional
#   - easier to control and more powerful than DDNS
#
#
# IMPORTANT NOTES:
#
# - This system has a working preconfiguration, be aware that a custom setup
#   will need you to understand what each option does, so please read the
#   configuration instructions.
# - Why does this system use switches to determine whether it's day or night?
#   Simple: You can use conditions in enemy attacks to determine whether an
#   attack should be used only at night or only at day.
#
#
# Instructions:
#
# - Explanation:
#
#   This Time System will make your game have daytime and nighttime periods.
#   The screen will be tinted accordingly. You can set up the length of the
#   day. Other features are explained below. Please be sure to configure this
#   system appropriately.
#
#
# - Basic manipulation of ATES:
#
#   This system is based upon your eventing. It will work basically if you
#   want, but with a little bit of using the "Call Script" event command you
#   are able to control this system fully. You can call following commands:
#
#   On/Off Controls
# ------------------------------------------------------------------------------
#     ATES.on
#   Turns ATES on.
#
#     ATES.off
#   Turns ATES off.
#
#     ATES.tint_on
#   Turns ATES's screen tinting on.
#
#     ATES.tint_off
#   Turns ATES's screen tinting off.
#
#     ATES.clock_on
#   Turns ATES's clock display on.
#
#     ATES.clock_off
#   Turns ATES's clock display off.
#
#     ATES.weather_on
#   Turns ATES's weather system on.
#
#     ATES.weather_off
#   Turns ATES's weather system off.
# ------------------------------------------------------------------------------
#   
#   Time Controls
# ------------------------------------------------------------------------------
#     ATES.advance(M, H)
#   This will make the time advanced by M minutes and H hours. Any negative
#   value used will cancel the execution of this command.
#   
#     ATES.make_it_day
#   This is a feature from DDNS which allows you to quickly jump to the
#   daytime.
#   
#     ATES.make_it_night
#   This is a feature from DDNS which allows you to quickly jump to the
#   nighttime.
#
#     ATES.set_time(TIME_INDEX or TIME_NAME)
#   Sets the current time to the time at the index of TIME_INDEX or with the
#   name of TIME_NAME. Its better to use TIME_NAME because some bugs may occur
#   from using TIME_INDEX.
# ------------------------------------------------------------------------------
#   
#   Weather Controls
# ------------------------------------------------------------------------------
#     ATES.lock_weather
#   This allows you to lock the current weather in place without disabling the
#   weather system entirely.
#
#     ATES.unlock_weather
#   This command unlocks the current weather.
#
#     ATES.set_weather(INDEX)
#   Sets the current weather to the weather at index INDEX.
# ------------------------------------------------------------------------------
#
#   Location (inside/outside) Controls
# ------------------------------------------------------------------------------
#     ATES.go_inside
#   A feature from the DDNS which allows you to change the lighting mode to
#   inside.
#
#     ATES.go_inside_dark
#   A feature from the DDNS which allows you to change the lighting mode to
#   inside dark.
#
#     ATES.go_outside
#   A feature from the DDNS which allows you to change the lighting mode to
#   outside.
# ------------------------------------------------------------------------------
#
#   Terrain Controls
# ------------------------------------------------------------------------------
#     ATES.terrain=(TERRAIN_NAME)
#   Sets the terrain to the terrain named TERRAIN_NAME.
# ------------------------------------------------------------------------------
#
#   Conditionals
# ------------------------------------------------------------------------------
#     ATES.active?
#   Returns true if ATES is turned on, otherwise false.
#
#     ATES.tinting?
#   Returns true if ATES tinting is turned on, otherwise false.
#
#     ATES.weather_active?
#   Returns true if the weather system is turned on, otherwise false.
#
#     ATES.day?
#   Returns true if it's day, otherwise false. Alternatively you can check the
#   assigned switch instead.
#
#     ATES.night?
#   Returns true if it's night, otherwise false. Alternatively you can check
#   the assigned switch instead.
# ------------------------------------------------------------------------------
#
#   Getters
# ------------------------------------------------------------------------------
#     ATES.time_name
#   Returns the name of the current time of day.
# ------------------------------------------------------------------------------
#
# - Enhancement hints:
#
#   If you wish to implement the DDNS further into your game and e.g. allow
#   different behavious of monsters during day and night, you only need to
#   check the the state of the appropriate switch. e.g. If NSWITCH is turned
#   on inflict "Sleep" on one enemy. The same is true for temperature (check
#   TVARIABLE) and weather (check WVARIABLE).
#
#
# Additional info:
#
# - The daytime and nighttime tintings were tested appropriately and optimal
#   tinting is being used.
#
# - Keep in mind that all aspects of the ATES are initially turned off, so
#   you'll have to use the commands ATES.on, ATES.tint_on, ATES.clock_on, and
#   ATES.weather_on to enable the components.
#
# - Further instructions can be found in the script database topic:
#   http://forum.chaos-project.com/index.php/topic,12869.0.html
#
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

module ATES
 
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # switch ID of the "day" switch
  DSWITCH = 51
  # switch ID of the "night" switch
  NSWITCH = 52
  # variable ID of the temperature variable
  TVARIABLE = 51
  # variable ID of the weather variable
  WVARIABLE = 52
  # length of a day in seconds in-game, can't be less than 36, is being
  # quantized into intervals of 36 seconds
  LENGTH = 1440
  # the amount to multiply weather sound by when inside
  INSIDE_SOUND = 0.7
  # the amount to multiply tone red, green, blue and gray by when inside
  INSIDE_TONE = 0.0
  # the tone for dark interiors
  DARK_INSIDE_TONE = Tone.new(-85, -85, -85, 85)
  # weather setup, create new types of weather here
  #  note - if you don't want a certain effect such as weather, fog, or sound,
  #    just leave the array for that effect empty
  #        ['NAME', WEATHER_SEVERITY, LOW_STRENGTH..HIGH_STRENGTH,
  #          WEATHER_DURATION_MIN..WEATHER_DURATION_MAX, [WEATHER_TYPE],
  #          [SOUND_NAME, SOUND_VOLUME_MIN..SOUND_VOLUME_MAX, SOUND_PITCH],
  #          [FOG_NAME, FOG_OPACITY, FOG_HUE, FOG_ZOOM, FOG_SX, FOG_SY,
  #            [TONE_RED, TONE_GREEN, TONE_BLUE, TONE_GRAY]],
  #          [SOUND_EFFECT_NAME, SOUND_VOLUME_MIN..SOUND_VOLUME_MAX, SOUND_PITCH,
  #            EFFECT_PROBABILITY, FLASH_DURATION, [FLASH_COLOR_RED,
  #            FLASH_COLOR_GREEN, FLASH_COLOR_BLUE]]]
  WEATHER = [['Drizzling', 0, 1..4, 150..480, [1], ['005-Rain01', 65..80, 100], [], []],
             ['Raining', 0, 5..8, 150..450, [1], ['006-Rain02', 75..90, 100], [], ['061-Thunderclap01', 60..85, 100, 0.0018, 4, [255, 255, 255]]],
             ['Storm', 1, 9..10, 180..450, [1], ['007-Rain03', 80..100, 100], [], ['061-Thunderclap01', 70..95, 110, 0.002, 6, [255, 255, 255]]],
             ['Cloudy', 0, 1..1, 240..720, [], [], ['002-Clouds01', 60, 0, 200, 4, 3, [0, 0, 0, 0]], []],
             ['Raining', 0, 1..4, 150..450, [2], ['006-Rain02', 70..85, 100], [], ['061-Thunderclap01', 65..90, 110, 0.002, 6, [255, 255, 255]]],
             ['Storm', 1, 5..8, 180..450, [2], ['007-Rain03', 75..90, 100], [], ['061-Thunderclap01', 70..95, 110, 0.0022, 7, [255, 255, 255]]],
             ['Storm', 2, 9..10, 180..450, [2], ['007-Rain03', 90..100, 100], [], ['061-Thunderclap01', 85..100, 110, 0.0026, 7, [255, 255, 255]]],
             ['Flurry', 1, 1..4, 150..480, [3], ['002-Wind02', 70..85, 100], [], []],
             ['Snowing', 1, 5..8, 150..450, [3], ['003-Wind03', 80..95, 100], [], []],
             ['Blizzard', 2, 9..10, 180..450, [3], ['004-Wind04', 85..100, 100], [], []]]
  # the name of the default weather type (what gets shown in the clock when
  #   there is no weather)
  DEFAULT_WEATHER_NAME = 'Sunny'
  # season setup, create a new season by using this template
  #          ['NAME', START_DAY, START_MONTH, MIN_TEMP..MAX_TEMP, WEATHER_PROBABILITY,
  #            BAD_WEATHER_PROBABILITY, VERY_BAD_WEATHER_PROBABILITY, WEATHER_POSSIBILITIES]
  SEASONS = [
             ['Spring', 22,  3,   0..25, 0.003, 0.3, 0.05, [0, 1, 2, 3, 4, 5]] ,
             ['Summer', 21,  6,  20..35, 0.003, 0.1, 0.2, [0, 1, 3, 4, 5, 6]]  ,
             ['Autumn', 20,  9,   0..25, 0.003, 0.2, 0.1, [0, 2, 3, 4, 5, 7]]  ,
             ['Winter', 21, 12, -20..5, 0.003, 0.5, 0.1, [0, 2, 3, 4, 7, 8, 9]]
            ]
  # terrain setup, create a new terrain by using this template
  #          ['NAME', MIN_TEMP..MAX_TEMP, WEATHER_EXCLUSIONS]
  TERRAINS = [
              ['Forest', -7..0, [3]],
              ['Desert', 11..16, [8, 9]],
              ['Mountain', -9..-4, []],
              ['Plains', -2..0, []],
              ['Beach', -5..-2, [8, 9]]
             ]
  # longest day date, the date of the longest night is half a year later/earlier
  LONGEST = [21, 6]
  # the tone at which day starts
  DAY_START = "Sunrise"
  # the tone at which night starts
  NIGHT_START = "Dusk"
  # the different screen tones and temperature modifiers at certain points during the day on the longest and shortest days
  # to make a new time of day, add this into TIMES:
  #   NAME => [RED, GREEN, BLUE, GRAY, TEMPERATURE_MODIFIER]
  TIMES = {
           "Dawn" => [-17, -17, 17, 0, -4],
           "Sunrise" => [48, 30, 30, 0, -2],
           "Noon" => [24, 10, 10, 0, 5],
           "Sunset" => [57, -17, -17, 0, 1],
           "Dusk" => [-17, -17, 17, 0, -3],
           "Night" => [-140, -110, -110, 160, -8]
          }
  # once you have customized the tones, put the tones into LONG_TIMES and SHORT_TIMES with [name_of_time, hour, minute]
  LONG_TIMES = [["Dawn", 4, 30],
                ["Sunrise", 5, 30],
                ["Noon", 13, 00],
                ["Sunset", 21, 00],
                ["Dusk", 22, 00],
                ["Night", 1, 30]]
  SHORT_TIMES = [["Dawn", 6, 30],
                ["Sunrise", 7, 30],
                ["Noon", 13, 00],
                ["Sunset", 16, 30],
                ["Dusk", 17, 00],
                ["Night", 23, 30]]
  # the first year in your calender, the player can't scroll further back
  FYEAR = 1990
  # the last year in your calender, the player can't scroll further forth
  LYEAR = 2099
  # the suffix for temperature
  TEMP_SUFFIX = "°C"
  # the different holidays and their dates
  #   the format for adding a new holiday is:
  #     [NAME, SETUP_TYPE, MONTH, (DAY or WEEKDAY, NUMBER)]
  #   whether to use DAY or WEEKDAY, NUMBER depends on SETUP_TYPE:
  #     (0 - DAY; 1 - WDAY, NUMBER)
  # note - the current holiday will replace the weekday in the clock if it is a
  #   holiday
  HOLIDAYS = [
               ["Christmas", 0, 11, 24],
               ["New Year's Day", 0, 0, 0],
               ["Thanksgiving", 1, 10, 4, 4],
               ["Groundhog Day", 0, 1, 1],
               ["Valentine's Day", 0, 1, 13],
               ["Earth Day", 0, 3, 21],
               ["Arbor Day", 1, 3, 5, -1],
               ["Mother's Day", 1, 2, 7, 2],
               ["Father's Day", 1, 5, 7, 3],
               ["Halloween", 0, 9, 30],
             ]
  # HUD clock format
  # default : ['%H:%M%s', '%A', '%d/%m/%Y', '%S']
  # use [] for no clock
  # it means: 1st row - "HOURS:MINUTES SUFFIX"
  #           2nd row - "WEEKDAY"
  #           3rd row - "DAY/MONTH/YEAR"
  #           4th row - "SEASON"
  # different combinations to input ATES information into the clock
  #   %H - Hour
  #   %M - Minute
  #   %s - Suffix (AM or PM) (only if not using 24 hour time)
  #   %A - Weekday
  #   %a - Weekday Abbreviation
  #   %d - Day of the Month
  #   %D - Day of the Year
  #   %m - Month
  #   %n - Month Name
  #   %l - Month Length
  #   %Y - Year
  #   %L - Year Length
  #   %S - Season
  #   %w - Weather
  #   %t - Terrain
  #   %T - Temperature
  #   %p - Time of Day
  CFORMAT = ['%H:%M', '%d/%m/%Y', '%A', '%w', '%p']
  # the width of the clock
  CWIDTH = 180
  # names of your days, automatically sets up a week's length
  WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
              'Saturday']
  WEEKDAY_ABBREVIATIONS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
  # names of your months, automatically sets up a year's length
  MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
            'August', 'September', 'October', 'November', 'December']
  # abbreviations for month names
  MONTH_ABBREVIATIONS = ['Jan', 'Feb', 'March', 'Apr', 'May', 'June', 'July',
                         'Aug', 'Sept', 'Oct', 'Nov', 'Dec']
  # days in each month
  MONTHDAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  # the first day in the game [DAY, MONTH, YEAR, WEEKDAY]
  # set this option to [] if you want the game to start "now"
  START = [24, 11, 2007, 7]
  # set this option to true to turn on 24 hour time
  HOUR24 = true
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
  mon = (LONGEST[1] + MONTHS.length / 2) % 12
  mon = 12 if mon == 0
  day = LONGEST[0] + (MONTHS.length % 2) == 1 ? MONTHDAYS[mon - 1] / 2 : 0
  while day > MONTHDAYS[mon - 1]
    day -= MONTHDAYS[mon - 1]
    mon = (mon + 1) % 12
    mon = 12 if mon == 0
  end
  SHORTEST = [day, mon]
 
  # Perform some simple checks of the config
  if ATES::MONTHS.size > ATES::MONTHDAYS.size
    raise 'ATEScfgError: Not all months have a length in days specified!'
  elsif ATES::LENGTH < 36
    raise 'ATEScfgError: A day\'s length must be equal to or greater than 36 seconds!'
  end

  $ates = 1.0
 
  #============================================================================
  # ATES::Time
  #============================================================================
 
  class Time
   
    attr_accessor :min
    attr_accessor :hour
    attr_accessor :day
    attr_accessor :mon
    attr_accessor :year
    attr_accessor :wday
   
    def initialize(m, h, d, mon, y, w)
      @min, @hour, @day, @mon, @year, @wday = m, h, d, mon, y, w
    end
   
  end
 
  #==============================================================================
  # ATES::Weather
  #==============================================================================
 
  class Weather
    attr_accessor :current_weather, :current_intensity, :locked, :weather_enabled, :weather_count
    attr_reader :weather_duration
   
    def initialize
      @current_weather = -1
      @current_intensity = 0
      @locked = false
      @weather_enabled = true
    end
   
    def update
      if @current_weather != -1 && @weather_enabled && @current_weather[7].length > 0
        weather = @current_weather
        if rand <= weather[7][3]
          high, low = weather[2].first, weather[2].last
          vol = weather[7][1].first + (weather[7][1].last - weather[7][1].first) * (high - @current_intensity).to_f / (high - low)
          vol *= ATES::INSIDE_SOUND if $game_system.ates.map_type > 0
          sound = RPG::AudioFile.new(weather[7][0], vol, weather[7][2])
          $game_system.se_play(sound)
          col = Color.new(0, 0, 0)
          $game_screen.start_flash(Color.new(*weather[7][5]), weather[7][4])
        end
      end
    end
   
    def stop_weather(speed = -1)
      return if @current_weather == -1
      speed = speed == -1 ? rand(10) + 60 : speed
      if @current_weather[4].length > 0
        $game_screen.weather(0, 1, speed)
      end
      if @current_weather[5].length > 0
        $game_system.bgs_fade(speed.to_f / 40)
      end
      if @current_weather[6].length > 0
        $game_map.fog_name = ''
      end
      @current_weather = -1
    end
   
    def pause_weather(speed = -1)
      return if @current_weather == -1
      $game_system.ates.show_weather = false
      speed = speed == -1 ? rand(10) + 60 : speed
      if @current_weather[4].length > 0
        $game_screen.weather(0, 1, speed)
      end
      if @current_weather[5].length > 0
        $game_system.bgs_fade(speed.to_f / 40)
      end
      if @current_weather[6].length > 0
        $game_map.fog_name = ''
      end
    end
   
    def resume_weather(speed = -1)
      return if @current_weather == -1
      $game_system.ates.show_weather = true
      weather = @current_weather
      intensity = @current_intensity
      low, high = weather[2].first, weather[2].last
      speed = speed == -1 ? rand(10) + 60 : speed
      if weather[4].length > 0
        $game_screen.weather(weather[4][0], intensity, speed)
      end
      if weather[5].length > 0
        volume = weather[5][1].first + (weather[5][1].last - weather[5][1].first) * (high - intensity).to_f / (high - low)
        bgm = RPG::AudioFile.new(weather[5][0], volume, weather[5][2])
        $game_system.bgs_play(bgm)
      end
      if weather[6].length > 0
        $game_map.fog_name = weather[6][0]
        $game_map.fog_opacity = weather[6][1]
        $game_map.fog_hue = weather[6][2]
        $game_map.fog_zoom = weather[6][3]
        $game_map.fog_sx = weather[6][4]
        $game_map.fog_sy = weather[6][5]
        $game_map.start_fog_tone_change(Tone.new(*weather[6][6]), 0)
      end
    end
   
    def set_weather(weather, speed = -1)
      stop_weather if @current_weather != -1
      if weather.is_a?(Fixnum)
        weather = WEATHER[weather]
      end
      @weather_count = 0
      @weather_duration = rand(weather[3].max - weather[3].min) + weather[3].min
      low, high = weather[2].first, weather[2].last
      intensity = rand(high + 1 - low) + low
      @current_weather = weather
      @current_intensity = intensity
      return unless @weather_enabled
      speed = speed == -1 ? rand(10) + 60 : speed
      if weather[5].length > 0
        volume = weather[5][1].first + (weather[5][1].last - weather[5][1].first) * (high - intensity).to_f / (high - low)
        volume *= ATES::INSIDE_SOUND if $game_system.ates.map_type > 0
        bgm = RPG::AudioFile.new(weather[5][0], volume, weather[5][2])
        $game_system.bgs_play(bgm)
      end
      return if $game_system.ates.map_type > 0
      if weather[4].length > 0
        if $modified_aws and weather[4].length > 1
          $game_screen.weather(weather[4][0], intensity, speed, weather[3][1])
        else
          $game_screen.weather(weather[4][0], intensity, speed)
        end
      end
      if weather[6].length > 0
        $game_map.fog_name = weather[6][0]
        $game_map.fog_opacity = weather[6][1]
        $game_map.fog_hue = weather[6][2]
        $game_map.fog_zoom = weather[6][3]
        $game_map.fog_sx = weather[6][4]
        $game_map.fog_sy = weather[6][5]
        $game_map.start_fog_tone_change(Tone.new(*weather[6][6]), 0)
      end
    end
  end
 
  def self.on
    $game_system.ates.active = true
    return true
  end
 
  def self.off
    $game_system.ates.active = false
    return true
  end
 
  def self.tint_on(frames = 0)
    $game_screen.start_tone_change($game_system.ates.get_environment[0], frames)
    $game_system.ates.tinting = true
    return true
  end
 
  def self.tint_off(reset = true)
    $game_screen.start_tone_change(Tone.new(0, 0, 0, 0), 0) if reset
    $game_system.ates.tinting = false
    return true
  end
 
  def self.weather_off
    $game_system.ates.weather.weather_enabled = false
    $game_system.ates.weather.pause_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
    return true
  end
 
  def self.weather_on
    $game_system.ates.weather.weather_enabled = true
    $game_system.ates.weather.resume_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
    return true
  end
 
  def self.weather_active?
    return $game_system.ates.weather.weather_enabled
  end
 
  def self.lock_weather
    $game_system.ates.weather.locked = true
    return true
  end
 
  def self.unlock_weather
    $game_system.ates.weather.locked = false
    return true
  end
 
  def self.clock_on
    $game_system.show_clock = true
    return true
  end
 
  def self.clock_off
    $game_system.show_clock = false
    return true
  end
 
  def self.active?
    return $game_system.ates.active
  end
 
  def self.tinting?
    return $game_system.ates.tinting
  end
 
  def self.day?
    i = $game_system.ates.time_index
    while true
      if $game_system.ates.current_times[i][0] == DAY_START
        return true
      elsif $game_system.ates.current_times[i][0] == NIGHT_START
        return false
      end
     
      i = (i + $game_system.ates.current_times.length - 1) % $game_system.ates.current_times.length
    end
  end
 
  def self.night?
    return !self.day?
  end
 
  def self.make_it_day
    time = $game_system.ates.current_times.select { |time| time[0] == DAY_START }
    h, m = time[0][1], time[0][2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.make_it_night
    time = $game_system.ates.current_times.select { |time| time[0] == NIGHT_START }
    h, m = time[0][1], time[0][2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.set_time(time = 0)
    return unless $game_system
    if time.is_a?(Fixnum)
      time = $game_system.ates.current_times[time.to_i]
    else
      time = $game_system.ates.current_times.select { |current_time| current_time[0] == time }[0]
    end
    h, m = time[1], time[2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.day_start
    return DAY_START
  end
 
  def self.night_start
    return NIGHT_START
  end
 
  def self.go_inside_dark
    weather = $game_system.ates.weather.current_weather
    $game_system.ates.map_type = 2
    self.tint_on
    $game_system.ates.weather.pause_weather(0)
    return true if weather == -1
    low, high = weather[2].first, weather[2].last
    intensity = $game_system.ates.weather.current_intensity
    if weather[5].length > 0
      volume = ATES::INSIDE_SOUND * weather[5][1].first + (weather[5][1].last - weather[5][1].first) * (high - intensity).to_f / (high - low)
      bgm = RPG::AudioFile.new(weather[5][0], volume, weather[5][2])
      $game_system.bgs_play(bgm)
    end
    return true
  end
 
  def self.go_inside
    weather = $game_system.ates.weather.current_weather
    $game_system.ates.map_type = 1
    self.tint_on
    $game_system.ates.weather.pause_weather(0)
    return true if weather == -1
    low, high = weather[2].first, weather[2].last
    intensity = $game_system.ates.weather.current_intensity
    if weather[5].length > 0
      volume = ATES::INSIDE_SOUND * weather[5][1].first + (weather[5][1].last - weather[5][1].first) * (high - intensity).to_f / (high - low)
      bgm = RPG::AudioFile.new(weather[5][0], volume, weather[5][2])
      $game_system.bgs_play(bgm)
    end
    return true
  end
 
  def self.go_outside
    $game_system.ates.weather.resume_weather(0)
    $game_system.ates.map_type = 0
    self.tint_on
    return true
  end
 
  def self.set_weather(id)
    $game_system.ates.weather.set_weather(WEATHER[id])
    return true
  end
 
  def self.terrain=(terrain)
    terrain = TERRAINS[terrain.to_i][0] if terrain.is_a?(Fixnum)
    $game_system.ates.terrain = terrain
    return true
  end
 
  def self.advance(m, h, d, mon, y)
    return true if [m, h, d, mon, y].any? {|i| i < 0}
    h += ($game_system.ates.time.min + m) / 60
    $game_system.ates.time.min = ($game_system.ates.time.min + m) % 60
    d += ($game_system.ates.time.hour + h) / 24
    $game_system.ates.time.hour = ($game_system.ates.time.hour + h) % 24
    while d > 0
      if $game_system.ates.time.day < MONTHDAYS[mon]
        $game_system.ates.time.day += 1
      else
        $game_system.ates.time.day = 0
        mon = (mon + 1) % MONTHS.size
      end
      $game_system.ates.time.wday += 1
      $game_system.ates.time.wday %= WEEKDAYS.size
      d -= 1
    end
    y += ($game_system.ates.time.mon + mon) / MONTHS.size
    $game_system.ates.time.mon = ($game_system.ates.time.mon + mon) % MONTHS.size
    $game_system.ates.time.year += y
    return true
  end
 
  def self.time_name
    return $game_system.ates.current_times[$game_system.ates.time_index][0]
  end
 
end

#==============================================================================
# Game_System
#==============================================================================

class Game_System
 
  attr_accessor :ates
  attr_accessor :show_clock
 
  alias init_ates_later initialize
  def initialize
    init_ates_later
    @ates = Game_ATES.new
    @show_clock = false
  end

end

#==============================================================================
# Game_ATES
#==============================================================================

class Game_ATES
 
  attr_accessor :active
  attr_accessor :tinting
  attr_accessor :time
  attr_accessor :weather
  attr_accessor :frame_count
  attr_accessor :current_times
  attr_accessor :tone
  attr_accessor :map_type
  attr_accessor :show_weather
  attr_accessor :terrain
  attr_accessor :temp
  attr_reader   :holiday
  attr_reader   :time_index
 
  def initialize
    if ATES::START.size == 4
      @time = ATES::Time.new(0, 0, ATES::START[0], ATES::START[1],
          ATES::START[2], ATES::START[3])
    else
      @time = Time.now
      @time = ATES::Time.new(@time.min, @time.hour, @time.mday, @time.mon, @time.year, @time.wday)
    end
    @weather = ATES::Weather.new
     
    @long_times = ATES::LONG_TIMES.sort { |t1, t2| t1[1] * 100 + t1[2] <=> t2[1] * 100 + t2[2] }
    @short_times = ATES::SHORT_TIMES.sort { |t1, t2| t1[1] * 100 + t1[2] <=> t2[1] * 100 + t2[2] }
   
    @year_length = ATES::MONTHDAYS.inject { |sum, x| sum + x }
       
    @normal_weather = []
    @bad_weather = []
    @very_bad_weather = []
   
    @terrain = ''
    @current_times = setup_times
    @temp_modifier = (rand(201) - 100) / 100.0
    @tone, @temp = get_environment
    @holiday = get_holiday(@time.mon, @time.day, @time.wday)
    @s_time = get_time(@time.min, @time.hour)
    $game_screen.start_tone_change(@tone, 0) if $game_screen
   
    @active = true
    @tinting = true
    @show_weather = true
    @map_type = 0
    @frame_count = 0
  end
 
  # get the holiday corresponding to a date
  def get_holiday(month, day, wday)
    ATES::HOLIDAYS.each { |el|
      case el[1] # branch by holiday definition
      when 0 # defined by date
        return el if el[2..3] == [month, day]
      when 1 # defined by position in month
        if el[4] > 0 # nth instance of a weekday
          return el if el[2] == month and el[3] == wday and el[4] == (day.to_f / 7 + 1).floor
        elsif el[4] < 0 # nth to last instance of a weekday
          return el if el[2] == month and el[3] == wday and -el[4] == ((ATES::MONTHDAYS[month] - 1 - day).to_f / 7 + 1).floor
        end
      end
    }[0]
  end
 
  # generate the correct tone based on the time of day and current location
  def get_environment
    red = 0
    green = 0
    blue = 0
    grey = 0
    @temp_modifier += (rand(3) - 1) / 100.0 if rand(10) == 0
   
    changed = false
   
    # loop through the times of day to determine where the current time falls
    for i in 0...@current_times.length
      time1 = get_time(@current_times[i][2], @current_times[i][1])
      time2 = get_time(@current_times[(i + 1) % @current_times.length][2], @current_times[(i + 1) % @current_times.length][1])
      current = get_time(@time.min, @time.hour)
      if time2 < time1
        time2 += 24 * 60
      end
      if current < time1
        current += 24 * 60
      end
     
      # found the two times to interpolate between
      if time1 <= current and time2 >= current
        changed = true
        tone1 = @current_times[i]
        tone2 = @current_times[(i + 1) % @current_times.length]
        tone1 = ATES::TIMES[tone1[0]]
        tone2 = ATES::TIMES[tone2[0]]
        max = time2 - time1
       
        # interpolate the current screen tone
        ratios = [(current - time1).to_f / max, (time2 - current).to_f / max]
        red = tone1[0] * ratios[1] + tone2[0] * ratios[0]
        green = tone1[1] * ratios[1] + tone2[1] * ratios[0]
        blue = tone1[2] * ratios[1] + tone2[2] * ratios[0]
        grey = tone1[3] * ratios[1] + tone2[3] * ratios[0]
       
        # deal with temperature (NEEDS REWORK)
        season_data = get_full_season[3]
        temp_range = [season_data.first, season_data.last].sort
        unless @base_temp
          # set up initial temperature
          temp = temp_range[0] + rand(temp_range[1] - temp_range[0] + 1)
          if @terrain != ''
            modifier = get_terrain_full[1]
            modifier = [modifier.first, modifier.last].sort
            modifier = modifier[0] + rand(modifier[1] - modifier[0] + 1)
            temp += modifier
          end
          @base_temp = temp
        else
          temp = @base_temp
        end
       
        # handle temperature changes
        temp_mod = round(tone1[4] * ratios[1] + tone2[4] * ratios[0], 2)
        temp += temp_mod + @temp_modifier
       
        # update the time of day if necessary
        @time_index = ratios[0] < 0.5 ? i : (i + 1) % @current_times.length
       
        break
      end
    end
   
    print "not right" unless changed
   
    # use the generated tone to determine the actual screen tone based on
    #   whether the player is inside, outside, or inside a dark place
    if @map_type == 1
      return Tone.new(red * ATES::INSIDE_TONE, green * ATES::INSIDE_TONE, blue * ATES::INSIDE_TONE, grey * ATES::INSIDE_TONE), temp
    elsif @map_type == 2
      return ATES::DARK_INSIDE_TONE, temp
    else
      return Tone.new(red, green, blue, grey), temp
    end
  end
   
  def get_weather_possibilities(severity = 0)
    weather = []
    season = $game_system.ates.get_full_season
    terrain = get_terrain_full
    ATES::WEATHER.each_with_index { |el, ind|
      weather.push(el) if el[1] == severity && season[7].include?(ind) && (terrain.nil? || !terrain[2].include?(ind))
    }
    return weather
  end
 
  def get_terrain_full
    return ATES::TERRAINS.select { |terrain| terrain[0] == @terrain }[0]
  end
 
  # interpolate between LONG_TIMES and SHORT_TIMES to find the current time of
  #   day changes
  def setup_times
    current_date = [@time.day, @time.mon]
   
    # check for trivial cases
    if current_date == ATES::LONGEST or @long_times == @short_times
      return @long_times
    elsif current_date == ATES::SHORTEST
      return @short_times
    end
   
    short_times = @long_times.clone
    addons = @short_times.clone
    current_date = get_date(*current_date)
    long, short = get_date(*ATES::LONGEST), get_date(*ATES::SHORTEST)
   
    # calculate distances to shortest and longest days
    dists = []
    if (current_date >= short and current_date <= long)
      dists = [current_date - short, long - current_date]
    elsif (current_date >= short and short >= long)
      dists = [current_date - short, long + @year_length - current_date]
    elsif (current_date <= long and long <= short)
      dists = [current_date + @year_length - short, long - current_date]
    elsif (current_date >= long and current_date <= short)
      dists = [current_date - long, short - current_date]
    elsif (current_date <= short and short <= long)
      dists = [current_date + @year_length - long, short - current_date]
    elsif (current_date >= long and long >= short)
      dists = [current_date - long, short + @year_length - current_date]
    end
   
    # generate the time for each time of day by interpolating between short and long
    sum = dists[0] + dists[1]
    short_times.each { |tone|
      addons.each { |addon|
        if tone[0] == addon[0]
          ts = [get_time(tone[2], tone[1]), get_time(addon[2], addon[1])]
          min, max = ts.min, ts.max
          ts = [min + 1440, max] if max - min > min + 1440 - max
          ts = (ts[0] * dists[0] / sum.to_f + ts[1] * dists[1] / sum.to_f) % 1440
          h = (ts / 60).floor
          m = ts.floor - h * 60
          tone[1], tone[2] = h, m
          break
        end
      }
    }
   
    return short_times.sort { |x, y| get_time(x[2], x[1]) <=> get_time(y[2], y[1]) }
  end
 
  # utility function to round a number to specified number of decimal places
  def round(num, places = 0)
    return ((num * 10 ** places).round.to_f) / (10 ** places)
  end
 
  # converts a time to minutes
  def get_time(minutes, hours)
    return minutes + hours * 60
  end
 
  # determine the current season from the date
  def get_season
    get_full_season[0]
  end
 
  # determine the season data from the date
  def get_full_season
    season_list = ATES::SEASONS.sort { |x, y| get_date(x[1], x[2]) <=> get_date(y[1], y[2]) }
    day = @time.day
    month = @time.mon
    current = get_date(day, month)
    for i in 0...season_list.length
      seasons = [season_list[i], season_list[(i + 1) % season_list.length]]
      times = [get_date(seasons[0][1], seasons[0][2]), get_date(seasons[1][1], seasons[1][2])]
      if times[0] <= current and current < times[1]
        return seasons[0]
      end
    end
    return season_list[0]
  end
 
  # get the current day since the start of the year
  def get_date(day, month)
    month = ATES::MONTHS.length if month == 0
    return (ATES::MONTHDAYS[0...month - 1].inject { |sum, x| sum + x } or 0) + day
  end

  # weather update
  def update_weather
    return unless @weather.weather_enabled
   
    if @weather.current_weather != -1
      @weather.weather_count += 1
      if @weather.weather_count >= @weather.weather_duration && !@weather.locked
        @weather.stop_weather
      end
    end

    season = get_full_season
    if !@season or @season != season
      @normal_weather = get_weather_possibilities
      @bad_weather = get_weather_possibilities(1)
      @very_bad_weather = get_weather_possibilities(2)
      @season = season
    end
    unless @weather.locked
      if rand <= season[4] and season[7].length > 0
        if rand <= season[5] and @bad_weather.length > 0
          weather = rand(@bad_weather.length)
          weather = @bad_weather[weather]
          @weather.set_weather(weather)
        elsif rand <= season[6] and @very_bad_weather.length > 0
          weather = rand(@very_bad_weather.length)
          weather = @very_bad_weather[weather]
          @weather.set_weather(weather)
        elsif @normal_weather.length > 0
          weather = rand(@normal_weather.length)
          weather = @normal_weather[weather]
          @weather.set_weather(weather)
        end
      end
    end
  end
 
  # update function
  def update
    if @active
      @frame_count += 1
      if @frame_count % (ATES::LENGTH / 36) == 0
        tmp = @time.day
        ATES.advance(1, 0, 0, 0, 0)
        if @time.day != tmp
          @current_times = setup_times
          @holiday = get_holiday(@time.mon, @time.day, @time.wday)
        end
       
        update_weather
     
        # update the switches if necessary
        if ATES.day?
          $game_map.need_refresh = true if !$game_switches[ATES::DSWITCH]
          $game_switches[ATES::DSWITCH] = true
          $game_switches[ATES::NSWITCH] = false
        else
          $game_map.need_refresh = true if !$game_switches[ATES::NSWITCH]
          $game_switches[ATES::DSWITCH] = false
          $game_switches[ATES::NSWITCH] = true
        end
     
        # update the variables
        @tone, @temp = get_environment
        $game_variables[ATES::TVARIABLE] = @temp
        weather = -1
        if @weather.current_weather != -1
          weather = ATES::WEATHER.index(@weather.current_weather)
        end
        $game_variables[ATES::WVARIABLE] = weather
     
        if @tinting # handle screen tone
          cur_time = get_time(@time.min, @time.hour)
          $game_screen.start_tone_change(@tone, ((@s_time - cur_time).abs < [1440 / ATES::LENGTH, 1].max ? 0 : 20))
        end
      end
     
      # in-game time speed should not affect the weather animations and effects
      @weather.update
    end
  end
end

#==============================================================================
# Bitmap
#==============================================================================

class Bitmap
  if $tons_version == nil || $tons_version < 1.6
    alias draw_text_shaded_later draw_text
  end
  def draw_text_full(x2, y2, w2 = 0, h2 = 0, text2 = '', a2 = 0)
    if x2.is_a?(Rect)
      x, y, w, h, text, a = x2.x, x2.y, x2.width, x2.height, y2, w2
    else
      x, y, w, h, text, a = x2, y2, w2, h2, text2, a2
    end
    save_color = self.font.color.clone
    self.font.color = Color.new(0, 0, 0)
    [x-1, x+1].each {|xx| [y-1, y+1].each {|yy|
            draw_text_shaded_later(xx, yy, w, h, text, a)}}
    self.font.color = save_color
    draw_text_shaded_later(x, y, w, h, text, a)
  end
 
end

#==============================================================================
# Clock_Sprite
#==============================================================================

class Clock_Sprite < Sprite
 
  def initialize
    super
    self.x, self.y, self.z = 640 - 8 - ATES::CWIDTH, 8, 5000
    self.bitmap = Bitmap.new(ATES::CWIDTH, ATES::CFORMAT.length * 32)
    if $fontface != nil
      self.bitmap.font.name = $fontface
    elsif $defaultfonttype != nil
      self.bitmap.font.name = $defaultfonttype
    end
    self.bitmap.font.size = 26
    @odd = 0
    draw if $game_system.ates.active
  end
 
  def draw
    self.bitmap.clear
    hours = $game_system.ates.time.hour
    minutes = sprintf('%02d', $game_system.ates.time.min)
    weekday = ATES::WEEKDAYS[$game_system.ates.time.wday - 1]
    wday_abbr = ATES::WEEKDAY_ABBREVIATIONS[$game_system.ates.time.wday - 1]
    day = $game_system.ates.time.day + 1
    month = $game_system.ates.time.mon + 1
    yday = ATES::MONTHDAYS[0..month - 1].inject { |s, r| s + r } + day
    month_name = ATES::MONTHS[month - 1]
    month_abbr = ATES::MONTH_ABBREVIATIONS[month - 1]
    month_days = ATES::MONTHDAYS[month - 1]
    year = $game_system.ates.time.year
    year_days = ATES::MONTHDAYS.inject { |s, r| s + r }
    season = $game_system.ates.get_season
    terrain = $game_system.ates.terrain
    temp = $game_system.ates.temp.to_s + ATES::TEMP_SUFFIX
    weather = $game_system.ates.weather.current_weather == -1 ? ATES::DEFAULT_WEATHER_NAME : $game_system.ates.weather.current_weather[0]
    tod = $game_system.ates.current_times[$game_system.ates.time_index][0]
    hday = $game_system.ates.holiday
    if hday != nil
      weekday = hday[0]
    end
    clock_text = ATES::CFORMAT.map { |ln| ln.clone }
    unless ATES::HOUR24
      suffix = "PM"
      if hours < 12
        suffix = "AM"
        hours = 12 if hours == 0
      elsif hours > 12
        suffix = "PM"
        hours -= 12
      end
    else
      suffix = ""
      hours = 24 if hours == 0
      hours = sprintf('%02d', hours)
    end
    colon = @odd % 2 == 0 ? " " : ":"
    clock_text.each { |ln|
      ln.gsub!(/%M/, minutes)
      ln.gsub!(/%H/, hours.to_s)
      ln.gsub!(/%A/, weekday)
      ln.gsub!(/%a/, wday_abbr)
      ln.gsub!(/%s/, " " + suffix)
      ln.gsub!(/:/, colon)
      ln.gsub!(/%m/, month.to_s)
      ln.gsub!(/%n/, month_name)
      ln.gsub!(/%l/, month_days.to_s)
      ln.gsub!(/%Y/, year.to_s)
      ln.gsub!(/%L/, year_days.to_s)
      ln.gsub!(/%d/, day.to_s)
      ln.gsub!(/%D/, yday.to_s)
      ln.gsub!(/%S/, season)
      ln.gsub!(/%w/, weather)
      ln.gsub!(/%t/, terrain)
      ln.gsub!(/%T/, temp)
      ln.gsub!(/%p/, tod)
    }
    for i in 0...clock_text.length
      self.bitmap.draw_text_full(0, i * 32, self.bitmap.width, 32, clock_text[i], 1)
    end
    @odd = (@odd + 1) % 2
  end
   
end

#==============================================================================
# Scene_Map
#==============================================================================

class Scene_Map
 
  alias main_ates_later main
  def main
    @clock = Clock_Sprite.new if $game_system.show_clock
    main_ates_later
    @clock.dispose if @clock != nil
  end
 
  alias update_ates_later update
  def update
    $game_system.ates.update
    update_ates_later
    if $game_system.show_clock
      @clock = Clock_Sprite.new if @clock == nil
      @clock.draw if $game_system.ates.frame_count % 20 == 0
    elsif @clock != nil
      @clock.dispose
      @clock = nil
    end
  end
 
end

#==============================================================================
# Scene_Battle
#==============================================================================

class Scene_Battle
  alias update_ates_later update
  def update
    $game_system.ates.update
    update_ates_later
  end
 
end

#==============================================================================
# Game_Map
#==============================================================================

class Game_Map
  alias setup_ates_later setup
  def setup(map_id)
    $game_system.ates.update
    setup_ates_later(map_id)
    if $game_system.ates.show_weather and $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
      weather = $game_system.ates.weather.current_weather
      if weather[5].length > 0
        $game_map.fog_name = weather[5][0]
        $game_map.fog_opacity = weather[5][1]
        $game_map.fog_hue = weather[5][2]
        $game_map.fog_zoom = weather[5][3]
        $game_map.fog_sx = weather[5][4]
        $game_map.fog_sy = weather[5][5]
        $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
      end
    end
   
    @events.each { |ev|
      ev = ev[1]
      if ev.list and ev.list.length > 0 and ev.list[0].code == 108 and ev.list[0].parameters[0] =~ /Terrain='(.+)'/
        $game_system.ates.terrain = $1
      end
    }
  end 
end

#==============================================================================
# Scene_Calendar
#==============================================================================

class Scene_Calendar
  def main
    # Make calendar window
    @calendar_window = Window_Calendar.new
    @calendar_window.active = true
    @calendar_window.z = 1000
    #@day_window = Window_Day.new
    #@day_window.z = 1010
    #@day_window.visible = false
    #@dir = rand(4)
    # Make spriteset
    @spriteset = Spriteset_Map.new
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of window
    @calendar_window.dispose
    #@day_window.dispose
    # Dispose of spriteset
    @spriteset.dispose
  end
 
  def update
    @calendar_window.update
    #@day_window.update
    #if @calendar_window.active
      #if Input.trigger?(Input::C)
      #  @day_window.visible = true
      #  @day_window.active = true
      #  @calendar_window.active = false
      #  @day_window.x, @day_window.y = 80, 80
      #  @day_window.appear(@dir)
      #  @dir = rand(4)
      #end
      if Input.trigger?(Input::B)
        $game_system.se_play($data_system.cancel_se)
        $scene = Scene_Map.new
      end
    #elsif @day_window.active
      #if Input.trigger?(Input::B)
      #  @day_window.disappear(@dir)
      #  @day_window.active = false
      #  @calendar_window.active = true
      #end
    #end
  end
end

#==============================================================================
# Window_Calendar
#==============================================================================

class Window_Calendar < Window_Base
  def initialize
    super(48, 48, 544, 384)
    self.contents = Bitmap.new(width - 32, height - 32)
    @month, @day, @wday, @year = $game_system.ates.time.mon, $game_system.ates.time.day, $game_system.ates.time.wday, $game_system.ates.time.year
    update
    refresh
  end
 
  def update
    prev_mon = @month
    if Input.repeat?(Input::LEFT)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      @day -= 1
      if @day == 0
        @month -= 1
        if @month == 0
          unless @year == ATES::FYEAR
            @year -= 1
            @month = ATES::MONTHS.length
          else
            @day = 1
            @month = 1
            continue = false
          end
        end
        @day = ATES::MONTHDAYS[@month - 1]
      end
      if continue
        @wday = (@wday + ATES::WEEKDAYS.length - 1) % ATES::WEEKDAYS.length
        @wday = ATES::WEEKDAYS.length if @wday == 0
      end
    end
    if Input.repeat?(Input::RIGHT)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      @day += 1
      if @day == ATES::MONTHDAYS[@month - 1] + 1
        @month += 1
        if @month == ATES::MONTHS.length + 1
          unless @year == ATES::LYEAR
            @year += 1
            @month = 1
          else
            @month = ATES::MONTHS.length
            @day = ATES::MONTHDAYS[@month - 1]
            continue = false
          end
        end
        @day = 1
      end
      if continue
        @wday = (@wday + 1) % ATES::WEEKDAYS.length
        @wday = ATES::WEEKDAYS.length if @wday == 0
      end
    end
    if Input.repeat?(Input::UP)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      tmpday = @day
      @day -= ATES::WEEKDAYS.length
      if @day <= 0
        @month -= 1
        if @month == 0
          unless @year == ATES::FYEAR
            @year -= 1
            @month = ATES::MONTHS.length
          else
            @day = tmpday
            @month = 1
            continue = false
          end
        end
        if continue
          tmp = (@wday + ATES::WEEKDAYS.length - @day) % ATES::WEEKDAYS.length
          tmp = ATES::WEEKDAYS.length if tmp == 0
          if @wday > tmp
            tmp = tmp + ATES::WEEKDAYS.length - @wday
          else
            tmp = tmp - @wday
          end
          @day = ATES::MONTHDAYS[@month - 1]
          @day -= tmp
        end
      end
    end
    if Input.repeat?(Input::DOWN)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      tmpday = @day
      @day += ATES::WEEKDAYS.length
      if @day >= ATES::MONTHDAYS[@month - 1] + 1
        @month += 1
        if @month == ATES::MONTHS.length + 1
          unless @year == ATES::LYEAR
            @year += 1
            @month = 1
          else
            @day = tmpday
            @month = ATES::MONTHS.length
            continue = false
          end
        end
        if continue
          tmp = (@wday + ATES::MONTHDAYS[@month - 2] - @day) % ATES::WEEKDAYS.length
          tmp = ATES::WEEKDAYS.length if tmp == 0
          if @wday <= tmp
            tmp -= ATES::WEEKDAYS.length
          end
          @day = @wday - tmp
        end
      end
    end
    super()
    refresh if prev_mon != @month
    row_count = (ATES::MONTHDAYS.max - 2) / ATES::WEEKDAYS.length + 2
    row_height = height - 116
    top_margin = ((row_height % row_count) / 2.0).ceil
    row_height -= row_height % row_count
    row_height /= row_count
    colwidth = width - 32
    margin = ((colwidth % ATES::WEEKDAY_ABBREVIATIONS.length) / 2.0).ceil
    colwidth -= colwidth % ATES::WEEKDAY_ABBREVIATIONS.length
    colwidth /= ATES::WEEKDAY_ABBREVIATIONS.length
    start_wday = (@wday + ATES::WEEKDAYS.length - (@day - 1) % ATES::WEEKDAYS.length) % ATES::WEEKDAYS.length
    start_wday = ATES::WEEKDAYS.length if start_wday == 0
    row = (@day + start_wday - 2) / ATES::WEEKDAYS.length
    self.cursor_rect.set(margin + (@wday - 1) * colwidth, 84 + top_margin + row * row_height, colwidth, 32)
  end
 
  def refresh
    self.contents.clear
    self.contents.font.size = 32
    self.contents.font.color = system_color
    self.contents.draw_text_full(Rect.new(0, 0, width - 32, 32), ATES::MONTHS[@month - 1] + " " + @year.to_s, 1)
    self.contents.font.size = 24
   
    colwidth = width - 32
    margin = ((colwidth % ATES::WEEKDAY_ABBREVIATIONS.length) / 2.0).ceil
    colwidth -= colwidth % ATES::WEEKDAY_ABBREVIATIONS.length
    colwidth /= ATES::WEEKDAY_ABBREVIATIONS.length
   
    for i in 0...ATES::WEEKDAY_ABBREVIATIONS.length
      self.contents.draw_text_full(Rect.new(margin + i * colwidth, 40, colwidth, 32), ATES::WEEKDAY_ABBREVIATIONS[i], 1)
    end
    self.contents.fill_rect(Rect.new(0, 76, width - 32, 2), system_color)
   
    row_count = (ATES::MONTHDAYS.max - 2) / ATES::WEEKDAYS.length + 2
    row_height = height - 116
    top_margin = ((row_height % row_count) / 2.0).ceil
    row_height -= row_height % row_count
    row_height /= row_count
    cur_wday = (@wday + ATES::WEEKDAYS.length - (@day - 1) % ATES::WEEKDAYS.length) % ATES::WEEKDAYS.length
    cur_wday = ATES::WEEKDAYS.length if cur_wday == 0
    start_wday = cur_wday
    cur_day = 1
    cur_row = (cur_day - 1) / 7
    while cur_day <= ATES::MONTHDAYS[@month - 1]
      if (cur_day == $game_system.ates.time.day and @month == $game_system.ates.time.mon and @year == $game_system.ates.time.year)
        self.contents.font.color = Color.new(240, 40, 40)
      elsif $game_system.ates.get_holiday(@month - 1, cur_day - 1, cur_wday) != nil
        self.contents.font.color = Color.new(150, 150, 0)
      else
        self.contents.font.color = normal_color
      end
      self.contents.draw_text_full(Rect.new(margin + (cur_wday - 1) * colwidth, 84 + top_margin + cur_row * row_height, colwidth, 32), cur_day.to_s, 1)
      cur_day += 1
      cur_wday = cur_wday + 1
      if cur_wday > ATES::WEEKDAYS.length
        cur_wday -= ATES::WEEKDAYS.length
        cur_row += 1
      end
    end
  end
end

#==============================================================================
# Window_Day
#==============================================================================

class Window_Day < Window_Base
  def initialize
    #(dir == 2 ? 320 : 48), (dir == 3 ? 240 : 48), (dir % 2 == 0 ? 272 : 544), (dir % 2 == 1 ? 192 : 384)
    super(80, 80, 480, 320)
    self.contents = Bitmap.new(width - 32, height - 32)
  end
 
  def appear(dir, duration = 40)
    @d_pos = [self.x, self.y]
    case dir
    when 0
      self.x = -480
    when 1
      self.y = -320
    when 2
      self.x = 640
    when 3
      self.y = 480
    end
    @s_pos = [self.x, self.y]
    @dir = dir
    @duration = duration
    @frames = 0
    @moving = true
  end
 
  def disappear(dir, duration = 40)
    @s_pos = [self.x, self.y]
    case dir
    when 0
      self.x += 560
    when 1
      self.y -= 400
    when 2
      self.x += 560
    when 3
      self.y += 400
    end
    @d_pos = [self.x, self.y]
    self.x, self.y = *@s_pos
    @dir = dir
    @duration = duration
    @frames = 0
    @moving = true
  end
 
  def update
    if @moving
      self.x = (@d_pos[0] * @frames + @s_pos[0] * (@duration - @frames)) / @duration
      self.y = (@d_pos[1] * @frames + @s_pos[1] * (@duration - @frames)) / @duration
      @moving = ([self.x, self.y] != @d_pos)
      @frames += 1
    end
    super()
  end
end

class Window_Text < Window_Base
  def initialize
    super(48, 48, 544, 384)
    self.contents = Bitmap.new(width - 32, height - 32)
   
    @dual_keys = ['`','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E',
                  'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U',
                  'V','W','X','Y','Z','-','=','[',']','\\',';','\'',',','.','/']
    @single_keys = ['NumberPad 0','NumberPad 1','NumberPad 2','NumberPad 3',
                    'NumberPad 4','NumberPad 5','NumberPad 6','NumberPad 7',
                    'NumberPad 8','NumberPad 9','Space','Enter','Tab']
    @chars1 = ['`','1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f',
               'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
               'x','y','z','-','=','[',']','/',';','\'',',','.','\\']
    @chars2 = ['~','!','@','#','$','%','^','&','*','(',')','A','B','C','D','E','F',
               'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W',
               'X','Y','Z','_','+','{','}','?',':','"','<','>','|']
    @chars = ['0','1','2','3','4','5','6','7','8','9',' ','\n','\t']
   
    @text = ""
    @cursor = true
  end
 
  def update
    @dual_keys.each_with_index { |i, ind|
      if Input.repeat?(Input::Key[i])
        @text += (Input.press?(Input::Key['Shift']) ? @chars2[ind] : @chars1[ind])
      end
    }
    @single_keys.each_with_index { |i, ind|
      if Input.repeat?(Input::Key[i])
        @text += @chars[ind]
      end
    }
    if Input.repeat?(Input::Key['Backspace'])
      @text = @text.split('')
      tmp = @text.pop()
      if (tmp == 'n' or tmp == 't') and @text[@text.length - 1] == '\\'
        @text.pop()
      end
      @text = @text.join('')
    end
    @cursor = !@cursor if Graphics.frame_count % 20 == 0
    refresh
  end
 
  def refresh
    self.contents.clear
   
    tmp = @text.gsub(/((?:\\n)+)\z/, '')
    y_mod = $1 ? $1.length / 2 : 0
    x_pos = y_mod > 0
    lns = tmp.gsub(/\\t/,'    ').split(/\\n/)
    y = 0
    x = 0
    lns.each_with_index { |ln, ind|
      rect = self.contents.text_size(ln)
      rect.height = self.contents.text_size('a').height
      rect.width += 1 unless ln.index(/[vVAwf\/\\]\z/).nil?
      rect.y = y
      self.contents.draw_text(rect, ln)
      y += rect.height
      x = rect.width
    }
    #p lns if lns.length > 1
    height = self.contents.text_size('a').height
    y -= height unless lns.last.nil?
    y += y_mod * height
    x = (x_pos ? 0 : x + 1)
    self.contents.fill_rect(Rect.new(x, y, 2, height), Color.new(0, 0, 0)) if @cursor
    #@cursor = !@cursor
  end
end


unless $BlizzABS or ($tons_version and TONS_OF_ADDONS::CUSTOM_CONTROLS)

  #==============================================================================
  # module Input
  #==============================================================================
 
  module Input
   
    #----------------------------------------------------------------------------
    # Simple ASCII table
    #----------------------------------------------------------------------------
    Key = {'A' => 65, 'B' => 66, 'C' => 67, 'D' => 68, 'E' => 69, 'F' => 70,
           'G' => 71, 'H' => 72, 'I' => 73, 'J' => 74, 'K' => 75, 'L' => 76,
           'M' => 77, 'N' => 78, 'O' => 79, 'P' => 80, 'Q' => 81, 'R' => 82,
           'S' => 83, 'T' => 84, 'U' => 85, 'V' => 86, 'W' => 87, 'X' => 88,
           'Y' => 89, 'Z' => 90,
           '0' => 48, '1' => 49, '2' => 50, '3' => 51, '4' => 52, '5' => 53,
           '6' => 54, '7' => 55, '8' => 56, '9' => 57,
           'NumberPad 0' => 45, 'NumberPad 1' => 35, 'NumberPad 2' => 40,
           'NumberPad 3' => 34, 'NumberPad 4' => 37, 'NumberPad 5' => 12,
           'NumberPad 6' => 39, 'NumberPad 7' => 36, 'NumberPad 8' => 38,
           'NumberPad 9' => 33,
           'F1' => 112, 'F2' => 113, 'F3' => 114, 'F4' => 115, 'F5' => 116,
           'F6' => 117, 'F7' => 118, 'F8' => 119, 'F9' => 120, 'F10' => 121,
           'F11' => 122, 'F12' => 123,
           ';' => 186, '=' => 187, ',' => 188, '-' => 189, '.' => 190, '/' => 220,
           '\\' => 191, '\'' => 222, '[' => 219, ']' => 221, '`' => 192,
           'Backspace' => 8, 'Tab' => 9, 'Enter' => 13, 'Shift' => 16,
           'Left Shift' => 160, 'Right Shift' => 161, 'Left Ctrl' => 162,
           'Right Ctrl' => 163, 'Left Alt' => 164, 'Right Alt' => 165,
           'Ctrl' => 17, 'Alt' => 18, 'Esc' => 27, 'Space' => 32, 'Page Up' => 33,
           'Page Down' => 34, 'End' => 35, 'Home' => 36, 'Insert' => 45,
           'Delete' => 46, 'Arrow Left' => 37, 'Arrow Up' => 38,
           'Arrow Right' => 39, 'Arrow Down' => 40,
           'Mouse Left' => 1, 'Mouse Right' => 2, 'Mouse Middle' => 4,
           'Mouse 4' => 5, 'Mouse 5' => 6}
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # START Configuration
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    UP = [Key['Arrow Up']]
    LEFT = [Key['Arrow Left']]
    DOWN = [Key['Arrow Down']]
    RIGHT = [Key['Arrow Right']]
    A = [Key['Shift']]
    B = [Key['Esc'], Key['NumberPad 0'], Key['X']]
    C = [Key['Space'], Key['Enter'], Key['C']]
    X = [Key['A']]
    Y = [Key['S']]
    Z = [Key['D']]
    L = [Key['Q'], Key['Page Down']]
    R = [Key['W'], Key['Page Up']]
    F5 = [Key['F5']]
    F6 = [Key['F6']]
    F7 = [Key['F7']]
    F8 = [Key['F8']]
    F9 = [Key['F9']]
    SHIFT = [Key['Shift']]
    CTRL = [Key['Ctrl']]
    ALT = [Key['Alt']]
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # END Configuration
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    # All keys
    KEY_COUNT = 256
    ALL_KEYS = (0...KEY_COUNT).to_a
    # Win32 API calls
    GetKeyboardState = Win32API.new('user32', 'GetKeyboardState', 'P', 'I')
    GetKeyboardLayout = Win32API.new('user32', 'GetKeyboardLayout', 'L', 'L')
    MapVirtualKeyEx = Win32API.new('user32', 'MapVirtualKeyEx', 'IIL', 'I')
    ToUnicodeEx = Win32API.new('user32', 'ToUnicodeEx', 'LLPPILL', 'L')
    # some other constants
    DOWN_STATE_MASK = 0x80
    DEAD_KEY_MASK = 0x80000000
    # data
    @state = "\0" * KEY_COUNT
    @triggered = Array.new(KEY_COUNT, false)
    @pressed = Array.new(KEY_COUNT, false)
    @released = Array.new(KEY_COUNT, false)
    @repeatedKey = -1
    @repeatedCount = 0
    #----------------------------------------------------------------------------
    # update
    #  Updates input.
    #----------------------------------------------------------------------------
    def self.update
      # get current language layout
      @language_layout = GetKeyboardLayout.call(0)
      # get new keyboard state
      GetKeyboardState.call(@state)
      # this special code is used because Ruby 1.9.x does not return a char
      # when using String#[] but another String
      key = 0
      @state.each_byte {|byte|
          # if pressed state
          if (byte & DOWN_STATE_MASK) == DOWN_STATE_MASK
            # not released anymore
            @released[key] = false
            # if not pressed yet
            if !@pressed[key]
              # pressed and triggered
              @pressed[key] = true
              @triggered[key] = true
              @repeatedKey = key
              @repeatedCount = 0
            else
              # not triggered anymore
              @triggered[key] = false
            end
            # update of repeat counter
            if key == @repeatedKey
              @repeatedCount < 17 ? @repeatedCount += 1 : @repeatedCount = 15
            end
          # not released yet
          elsif !@released[key]
            # if still pressed
            if @pressed[key]
              # not triggered, pressed or repeated, but released
              @triggered[key] = false
              @pressed[key] = false
              @released[key] = true
              if key == @repeatedKey
                @repeatedKey = -1
                @repeatedCount = 0
              end
            end
          else
            # not released anymore
            @released[key] = false
          end
          key += 1}
    end
    #----------------------------------------------------------------------------
    # dir4
    #  4 direction check.
    #----------------------------------------------------------------------------
    def self.dir4
      return 2 if self.press?(DOWN)
      return 4 if self.press?(LEFT)
      return 6 if self.press?(RIGHT)
      return 8 if self.press?(UP)
      return 0
    end
    #----------------------------------------------------------------------------
    # dir8
    #  8 direction check.
    #----------------------------------------------------------------------------
    def self.dir8
      down = self.press?(DOWN)
      left = self.press?(LEFT)
      return 1 if down && left
      right = self.press?(RIGHT)
      return 3 if down && right
      up = self.press?(UP)
      return 7 if up && left
      return 9 if up && right
      return 2 if down
      return 4 if left
      return 6 if right
      return 8 if up
      return 0
    end
    #----------------------------------------------------------------------------
    # trigger?
    #  Test if key was triggered once.
    #----------------------------------------------------------------------------
    def self.trigger?(keys)
      keys = [keys] unless keys.is_a?(Array)
      return keys.any? {|key| @triggered[key]}
    end
    #----------------------------------------------------------------------------
    # press?
    #  Test if key is being pressed.
    #----------------------------------------------------------------------------
    def self.press?(keys)
      keys = [keys] unless keys.is_a?(Array)
      return keys.any? {|key| @pressed[key]}
    end
    #----------------------------------------------------------------------------
    # repeat?
    #  Test if key is being pressed for repeating.
    #----------------------------------------------------------------------------
    def self.repeat?(keys)
      keys = [keys] unless keys.is_a?(Array)
      return (@repeatedKey >= 0 && keys.include?(@repeatedKey) &&
          (@repeatedCount == 1 || @repeatedCount == 16))
    end
    #----------------------------------------------------------------------------
    # release?
    #  Test if key was released.
    #----------------------------------------------------------------------------
    def self.release?(keys)
      keys = [keys] unless keys.is_a?(Array)
      return keys.any? {|key| @released[key]}
    end
    #----------------------------------------------------------------------------
    # get_character
    #  vk - virtual key
    #  Gets the character from keyboard input using the input locale identifier
    #  (formerly called keyboard layout handles).
    #----------------------------------------------------------------------------
    def self.get_character(vk)
      # get corresponding character from virtual key
      c = MapVirtualKeyEx.call(vk, 2, @language_layout)
      # stop if character is non-printable and not a dead key
      return '' if c < 32 && (c & DEAD_KEY_MASK != DEAD_KEY_MASK)
      # get scan code
      vsc = MapVirtualKeyEx.call(vk, 0, @language_layout)
      # result string is never longer than 4 bytes (Unicode)
      result = "\0" * 4
      # get input string from Win32 API
      length = ToUnicodeEx.call(vk, vsc, @state, result, 4, 0, @language_layout)
      return (length == 0 ? '' : result)
    end
    #----------------------------------------------------------------------------
    # get_input_string
    #  Gets the string that was entered using the keyboard over the input locale
    #  identifier (formerly called keyboard layout handles).
    #----------------------------------------------------------------------------
    def self.get_input_string
      result = ''
      # check every key
      ALL_KEYS.each {|key|
          # if repeated
          if self.repeat?(key)
            # get character from keyboard state
            c = self.get_character(key)
            # add character if there is a character
            result += c if c != ''
          end}
      # empty if result is empty
      return '' if result == ''
      # convert string from Unicode to UTF-8
      return self.unicode_to_utf8(result)
    end
    #----------------------------------------------------------------------------
    # unicode_to_utf8
    #  string - string in Unicode format
    #  Converts a string from Unicode format to UTF-8 format as RGSS does not
    #  support Unicode.
    #----------------------------------------------------------------------------
    def self.unicode_to_utf8(string)
      result = ''
      # L* format means a bunch of 4-byte wide-chars
      string.unpack('L*').each {|c|
          # characters under 0x80 are 1 byte characters
          if c < 0x0080
            result += c.chr
          # other characters under 0x800 are 2 byte characters
          elsif c < 0x0800
            result += (0xC0 | (c >> 6)).chr
            result += (0x80 | (c & 0x3F)).chr
          # other characters under 0x10000 are 3 byte characters
          elsif c < 0x10000
            result += (0xE0 | (c >> 12)).chr
            result += (0x80 | ((c >> 6) & 0x3F)).chr
            result += (0x80 | (c & 0x3F)).chr
          # other characters under 0x200000 are 4 byte characters
          elsif c < 0x200000
            result += (0xF0 | (c >> 18)).chr
            result += (0x80 | ((c >> 12) & 0x3F)).chr
            result += (0x80 | ((c >> 6) & 0x3F)).chr
            result += (0x80 | (c & 0x3F)).chr
          # other characters under 0x4000000 are 5 byte characters
          elsif c < 0x4000000
            result += (0xF8 | (c >> 24)).chr
            result += (0x80 | ((c >> 18) & 0x3F)).chr
            result += (0x80 | ((c >> 12) & 0x3F)).chr
            result += (0x80 | ((c >> 6) & 0x3F)).chr
            result += (0x80 | (c & 0x3F)).chr
          # other characters under 0x80000000 are 6 byte characters
          elsif c < 0x80000000
            result += (0xFC | (c >> 30)).chr
            result += (0x80 | ((c >> 24) & 0x3F)).chr
            result += (0x80 | ((c >> 18) & 0x3F)).chr
            result += (0x80 | ((c >> 12) & 0x3F)).chr
            result += (0x80 | ((c >> 6) & 0x3F)).chr
            result += (0x80 | (c & 0x3F)).chr
          end}
      return result
    end
 
  end

end



Instructions

All in the script.


Compatibility

No known issues, but may not work with other scripts that change the tint unless you turn tinting off.


Credits and Thanks


  • Blizzard

  • ThallionDarkshine




Author's Notes

This is a finished and rereleased version of the original ATES script found here. If you are having questions or problems, please first read the original topic!

Zexion

Really nice script! Now I definately need to get an SD reader..

ThallionDarkshine

Thanks Zexion, I've had it for a while, I just was waiting for Blizz to give the main topic to me. But then he told me that it would be better to just make a new topic, so I did, and here it is.

Blizzard

There was a bug when using this with RMX-OS because you forgot to include RMX-OS in the check whether to enable the custom input module. I quickly fixed it and updated the script.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ThallionDarkshine

Thanks Blizz. I should have known that RMX-OS had a custom Input module too.

whitespirits


KK20

It's, once again, loading a saved game and accessing a variable that is only created upon starting a new game.

class Game_Map
  alias setup_ates_later setup
  def setup(map_id)
    $game_system.ates ||= Game_ATES.new                 #<==
    $game_system.show_clock ||= (ATES::CFORMAT != [])   #<==
    $game_system.ates.update
#...and the rest of the code...

Add the two marked lines in this script. This will create the new variables in a saved game if they don't exist yet.
Other solution is to just wipe your saved data and start a new game.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

whitespirits


whitespirits

How do i remove the hud? with time and date etc

KK20

As explained in the configuration:

  # HUD clock format
  # default : ['%H:%M%s', '%A', '%d/%m/%Y', '%S']
  # use [] for no clock


CFORMAT = []

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Tgkkiller102

Time goes to fast!!! How to make it slow down? And when I in house, if it rain, rains indoor. How do I fix it?
ps: I'm a vietnamese so I don't know a lot of English,

KK20

To change time speed:

  # length of a day in seconds in-game, can't be less than 36, is being
  # quantized into intervals of 36 seconds
  LENGTH = 144

Use this script call when going inside

ATES.go_inside

And this when going outside

ATES.go_outside

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!


treign

March 20, 2015, 01:06:31 am #13 Last Edit: March 20, 2015, 01:25:57 am by KK20
Been working on a game for a couple months. Been using this script, and got myself a bug.
First i'm running in this order,
Letter by Letter Message Window : Tons of Add-ons 7.65b : Easy LvlUp Notifier 1.21b : Stormtronics CMS 5,51b : ATES 1.01 : Battle Memory Commands v1.3
The issue is with ATES and with tone change i believe. The error i get is....

script 'interpreter 7' line 274: typeerror occurred.
can't convert FalseClass into tone

It happens when i'm in a town/map and the weather changes to clouds and i exit out to the world/map using the transfer player event.

If the weather don't change i don't get the error when i leave. I'm coping and pasting the script as it sits in my game below. I can't for the life of me figure this out and can't find a solution anywhere.

I was going to use the old 0.4 script i used back in the day but the script link as 404'd.

Help is appreciated. Ill check back tomorrow night for any reply's

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Advanced Time and Environment System (ATES) by Blizzard and ThallionDarkshine
# Version: 1.01
# Type: Autonomous Timeflow and Environment Controller
# Date v0.3: 11.3.2008
# Date v0.31: 8.4.2009
# Date v0.32: 13.4.2009
# Date v0.33: 4.5.2009
# Date v0.34: 5.5.2009
# Date v1.0: 12.2.2013
# Date v1.01: 28.4.2013
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#  
#  This work is protected by the following license:
# #----------------------------------------------------------------------------
# #  
# #  Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# #  ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# #  
# #  You are free:
# #  
# #  to Share - to copy, distribute and transmit the work
# #  to Remix - to adapt the work
# #  
# #  Under the following conditions:
# #  
# #  Attribution. You must attribute the work in the manner specified by the
# #  author or licensor (but not in any way that suggests that they endorse you
# #  or your use of the work).
# #  
# #  Noncommercial. You may not use this work for commercial purposes.
# #  
# #  Share alike. If you alter, transform, or build upon this work, you may
# #  distribute the resulting work only under the same or similar license to
# #  this one.
# #  
# #  - For any reuse or distribution, you must make clear to others the license
# #    terms of this work. The best way to do this is with a link to this web
# #    page.
# #  
# #  - Any of the above conditions can be waived if you get permission from the
# #    copyright holder.
# #  
# #  - Nothing in this license impairs or restricts the author's moral rights.
# #  
# #----------------------------------------------------------------------------
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# Compatibility:
#
#   99% compatible with SDK v1.x. 90% compatible with SDK 2.x. WILL corrupt old
#   savegames. Can cause incompatibilty issues with DNS-es.
#
#
# Features:
#
#   - complete control over and easy manipulating of time and weather
#   - customizable day and night tinting
#   - HUD clock optional
#   - easier to control and more powerful than DDNS
#
#
# IMPORTANT NOTES:
#
# - This system has a working preconfiguration, be aware that a custom setup
#   will need you to understand what each option does, so please read the
#   configuration instructions.
# - Why does this system use switches to determine whether it's day or night?
#   Simple: You can use conditions in enemy attacks to determine whether an
#   attack should be used only at night or only at day.
#
#
# Instructions:
#
# - Explanation:
#
#   This Time System will make your game have daytime and nighttime periods.
#   The screen will be tinted accordingly. You can set up the length of the
#   day. Other features are explained below. Please be sure to configure this
#   system appropriately.
#
#
# - Basic manipulation of ATES:
#
#   This system is based upon your eventing. It will work basically if you
#   want, but with a little bit of using the "Call Script" event command you
#   are able to control this system fully. You can call following commands:
#
#     ATES.on
#   Turns ATES on.
#
#     ATES.off
#   Turns ATES off.
#
#     ATES.tint_on
#   Turns ATES's screen tinting on.
#
#     ATES.tint_off
#   Turns ATES's screen tinting off.
#
#     ATES.clock_on
#   Turns ATES's clock display on.
#
#     ATES.clock_off
#   Turns ATES's clock display off.
#
#     ATES.active?
#   Returns true if ATES is turned on, otherwise false.
#
#     ATES.tinting?
#   Returns true if ATES tinting is turned on, otherwise false.
#
#     ATES.day?
#   Returns true if it's day, otherwise false. Alternatively you can check the
#   assigned switch instead.
#
#     ATES.night?
#   Returns true if it's night, otherwise false. Alternatively you can check
#   the assigned switch instead.
#  
#     ATES.advance(M, H)
#   This will make the time advanced by M minutes and H hours. Any negative
#   value used will cancel the execution of this command.
#  
#     ATES.make_it_day
#   This is a feature from DDNS which allows you to quickly jump to the
#   daytime.
#  
#     ATES.make_it_night
#   This is a feature from DDNS which allows you to quickly jump to the
#   nighttime.
#  
#     ATES.weather_on
#   This allows you to turn on the weather system.
#
#     ATES.weather_off
#   This allows you to turn off the weather system.
#
#     ATES.lock_weather
#   This allows you to lock the current weather in place without disabling the
#   weather system entirely.
#
#     ATES.unlock_weather
#   This command unlocks the current weather.
#
#     ATES.weather_active?
#   Returns true if the weather system is turned on, otherwise false.
#
#     ATES.set_time(TIME_INDEX or TIME_NAME)
#   Sets the current time to the time at the index of TIME_INDEX or with the
#   name of TIME_NAME. Its better to use TIME_NAME because some bugs may occur
#   from using TIME_INDEX.
#
#     ATES.go_inside
#   A feature from the DDNS which allows you to change the lighting mode to
#   inside.
#
#     ATES.go_inside_dark
#   A feature from the DDNS which allows you to change the lighting mode to
#   inside dark.
#
#     ATES.go_outside
#   A feature from the DDNS which allows you to change the lighting mode to
#   outside.
#
#     ATES.set_weather(INDEX)
#   Sets the current weather to the weather at index INDEX.
#
#     ATES.terrain=(TERRAIN_NAME)
#   Sets the terrain to the terrain named TERRAIN_NAME.
#
#     ATES.time_name
#   Returns the name of the current time of day.
#
# - Enhancement hints:
#
#   If you wish to implement the DDNS further into your game and e.g. allow
#   different behavious of monsters during day and night, you only need to
#   check the the state of the appropriate switch. e.g. If NSWITCH is turned
#   on inflict "Sleep" on one enemy.
#
#
# Additional info:
#
#   The daytime and nighttime tintings were tested appropriately and optimal
#   tinting is being used.
#   Keep in mind that ATES is initially turned off, you need to turn it on by
#   using the ATES.on and ATES.tint_on commands together.
#
#
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

module ATES
 
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 # switch ID of the "day" switch
 DSWITCH = 51
 # switch ID of the "night" switch
 NSWITCH = 52
 # variable ID of the temperature
 TVARIABLE = 53
 # length of a day in seconds in-game, can't be less than 36, is being
 # quantized into intervals of 36 seconds
 LENGTH = 288
 # the amount to multiply weather sound by when inside
 INSIDE_SOUND = 0.5
 # the amount to multiply tone red, green, blue and gray by when inside
 INSIDE_TONE = 0.0
 # the tone for dark interiors
 DARK_INSIDE_TONE = Tone.new(-85, -85, -85, 85)
 # weather setup, create new types of weather here
 #  note - if you don't want a certain effect such as weather, fog, or sound,
 #    just leave the array for that effect empty
 #          ['NAME', WEATHER_SEVERITY, [WEATHER_TYPE, LOW_STRENGTH..HIGH_STRENGTH],
 #            [SOUND_NAME, SOUND_VOLUME_MIN..SOUND_VOLUME_MAX, SOUND_PITCH], [FOG_NAME, FOG_OPACITY, FOG_HUE,
 #            FOG_ZOOM, FOG_SX, FOG_SY, [TONE_RED, TONE_GREEN, TONE_BLUE, TONE_GRAY]],
 #            [SOUND_EFFECT_NAME, SOUND_VOLUME_MIN..SOUND_VOLUME_MAX, SOUND_PITCH, EFFECT_PROBABILITY,
 #            FLASH_DURATION, [FLASH_COLOR_RED, FLASH_COLOR_GREEN, FLASH_COLOR_BLUE]]]
 WEATHER = [['Drizzling', 0, 1..4, [1], ['005-Rain01', 65..80, 100], [], []],
            ['Raining', 0, 5..8, [1], ['006-Rain02', 75..90, 100], [], ['061-Thunderclap01', 60..85, 100, 0.07, 4, [255, 255, 255]]],
            ['Storm', 1, 9..10, [1], ['007-Rain03', 80..100, 100], [], ['061-Thunderclap01', 70..95, 110, 0.08, 6, [255, 255, 255]]],
            ['Cloudy', 0, 1..1, [], [], ['002-Clouds01', 60, 0, 200, 4, 3, [0, 0, 0, 0]], []],
            ['Raining', 0, 1..4, [2], ['006-Rain02', 70..85, 100], [], ['061-Thunderclap01', 65..90, 110, 0.08, 6, [255, 255, 255]]],
            ['Storm', 1, 5..8, [2], ['007-Rain03', 75..90, 100], [], ['061-Thunderclap01', 70..95, 110, 0.09, 7, [255, 255, 255]]],
            ['Storm', 2, 9..10, [2], ['007-Rain03', 90..100, 100], [], ['061-Thunderclap01', 85..100, 110, 0.11, 7, [255, 255, 255]]],
            ['Flurry', 1, 1..4, [3], ['002-Wind02', 70..85, 100], [], []],
            ['Snowing', 1, 5..8, [3], ['003-Wind03', 80..95, 100], [], []],
            ['Blizzard', 2, 9..10, [3], ['004-Wind04', 85..100, 100], [], []]]
 # normal weather duration in seconds
 WEATHER_DURATION = 128
 # variance of the weather duration in seconds
 WEATHER_VARIANCE = 32
 # the name of the default weather type (what gets shown in the clock when
 #   there is no weather)
 DEFAULT_WEATHER_NAME = 'Sunny'
 # season setup, create a new season by using this template
 #          ['NAME', START_DAY, START_MONTH, MIN_TEMP..MAX_TEMP, WEATHER_PROBABILITY,
 #            BAD_WEATHER_PROBABILITY, VERY_BAD_WEATHER_PROBABILITY, WEATHER_POSSIBILITIES]
 SEASONS = [
            ['Spring', 22,  3,   0..25, 0.003, 0.3, 0.05, [0, 1, 2, 3, 4, 5]] ,
            ['Summer', 21,  6,  20..35, 0.003, 0.1, 0.2, [0, 1, 3, 4, 5, 6]]  ,
            ['Autumn', 20,  9,   0..25, 0.003, 0.2, 0.1, [0, 2, 3, 4, 5, 7]]  ,
            ['Winter', 21, 12, -20..5, 0.003, 0.5, 0.1, [0, 2, 3, 4, 7, 8, 9]]
           ]
 # terrain setup, create a new terrain by using this template
 #          ['NAME', MIN_TEMP..MAX_TEMP, WEATHER_EXCLUSIONS]
 TERRAINS = [
             ['Forest', -7..0, [3]],
             ['Desert', 11..16, [8, 9]],
             ['Mountain', -9..-4, []],
             ['Plains', -2..0, []],
             ['Beach', -5..-2, [8, 9]]
            ]
 # longest day date, the longest night date is half a year later/earlier
 LONGEST = [21, 6]
 # the tone at which day starts
 DAY_START = "Sunrise"
 # the tone at which night starts
 NIGHT_START = "Dusk"
 # the different screen tones and temperature modifiers at certain points during the day on the longest and shortest days
 # to make a new time of day, add this into TIMES: NAME => [RED, GREEN, BLUE, GRAY, TEMPERATURE_MODIFIER]
 TIMES = {
          "Dawn" => [-17, -17, 17, 0, -4],
          "Sunrise" => [48, 30, 30, 0, -2],
          "Noon" => [24, 10, 10, 0, 5],
          "Sunset" => [57, -17, -17, 0, 1],
          "Dusk" => [-17, -17, 17, 0, -3],
          "Night" => [-150, -120, -120, 200, -8]
         }
 # once you have customized the tones, put the tones into LONG_TIMES and SHORT_TIMES with [name_of_time, hour, minute]
 LONG_TIMES = [["Dawn", 4, 30],
               ["Sunrise", 5, 30],
               ["Noon", 13, 00],
               ["Sunset", 21, 00],
               ["Dusk", 22, 00],
               ["Night", 1, 30]]
 SHORT_TIMES = [["Dawn", 6, 30],
               ["Sunrise", 7, 30],
               ["Noon", 13, 00],
               ["Sunset", 16, 30],
               ["Dusk", 17, 00],
               ["Night", 23, 30]]
 # makes the screen brighter during "summer" days
 OVERLIGHTING = true
 # makes the screen darker during the night, not recommended
 OVERDARKENING = false
 # the first year in your calender, the player can't scroll further back
 FYEAR = 1980
 # the last year in your calender, the player can't scroll further forth
 LYEAR = 2599
 # the suffix for temperature
 TEMP_SUFFIX = "°C"
 # the different holidays and their dates
 #   the format for adding a new holiday is:
 #     [NAME, SETUP_TYPE, MONTH, (DAY or WEEKDAY, NUMBER)]
 #   whether to use DAY or WEEKDAY, NUMBER depends on SETUP_TYPE:
 #     (0 - DAY; 1 - WDAY, NUMBER)
 # note - the current holiday will replace the weekday in the clock if it is a
 #   holiday
 HOLIDAYS = [
              ["Christmas", 0, 11, 24],
              ["New Year's Day", 0, 0, 0],
              ["Thanksgiving", 1, 10, 4, 4],
              ["Groundhog Day", 0, 1, 1],
              ["Valentine's Day", 0, 1, 13],
              ["Earth Day", 0, 3, 21],
              ["Arbor Day", 1, 3, 5, -1],
              ["Mother's Day", 1, 2, 7, 2],
              ["Father's Day", 1, 5, 7, 3],
              ["Halloween", 0, 9, 30],
            ]
 # HUD clock format
 # default : ['%H:%M%s', '%A', '%d/%m/%Y', '%S']
 # use [] for no clock
 # it means: 1st row - "HOURS:MINUTES SUFFIX"
 #           2nd row - "WEEKDAY"
 #           3rd row - "DAY/MONTH/YEAR"
 #           4th row - "SEASON"
 # different combinations to input ATES information into the clock
 #   %H - Hour
 #   %M - Minute
 #   %s - Suffix (AM or PM) (only if not using 24 hour time)
 #   %A - Weekday
 #   %d - Day of the Month
 #   %D - Day of the Year
 #   %m - Month
 #   %n - Month Name
 #   %l - Month Length
 #   %Y - Year
 #   %L - Year Length
 #   %S - Season
 #   %w - Weather  #   %t - Terrain
 #   %T - Temperature
 #   %p - Time of Day
 CFORMAT = ['%H:%M %s']
 # the width of the clock
 CWIDTH = 180
 # names of your days, automatically sets up a week's length
 WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
             'Saturday']
 WEEKDAY_ABBREVIATIONS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
 # names of your months, automatically sets up a year's length
 MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
           'August', 'September', 'October', 'November', 'December']
 # abbreviations for month names
 MONTH_ABBREVIATIONS = ['Jan', 'Feb', 'March', 'Apr', 'May', 'June', 'July',
                        'Aug', 'Sept', 'Oct', 'Nov', 'Dec']
 # days in each month
 MONTHDAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
 # the first day in the game [DAY, MONTH, YEAR, WEEKDAY]
 # set this option to [] if you want the game to start "now"
 START = [23, 03, 1980, 7]
 # set this option to true to turn on military time (24 hour time)
 HOUR24 = false
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


KK20

First off, use code tags when pasting any code at all. Secondly, there really was no point to post the entire script when it's already provided in the OP. Besides, it's a huge script--you can't even fit the entire thing in a message post. I edited your post to reflect these changes.

The error message is stating that a Script event command is acting weird. Do you have any events, probably parallel process or autorun, that uses a script call? If so, post it.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

treign

Yes i do have a parallel process using a call script, on both the map transferring from and one on the map transferring too.
Blown away you got that from the info i provided, anyways here are how each are set up.

TOWN
Parallel Process
Change Actor Graphic .....
Change Actor Graphic Slot 2....
Change Actor Graphic Slot 3....
Change Actor Graphic Slot 4....
Set Move Route : player / Change Speed :4
Change Save Access: Enabled
Script: ATES.on
Script: ATES.tint_on
Script: ATES.weather_on
Script: ATES.clock.on
Text: \p\map\%[015]
Erase Event

WORLD MAP
Parallel Process
Change Actor Graphic .....
Change Actor Graphic Slot 2....
Change Actor Graphic Slot 3....
Change Actor Graphic Slot 4....
Set Move Route : player / Change Speed :3
Change Save Access: Enabled
Script: ATES.on
Script: ATES.tint_on
Script: ATES.weather_on
Script: ATES.clock.on
Text: \p\map\%[015]
Erase Event

I know its basically the same thing besides the speed change, and the reason behind me doing it that way was because if a player saved the game and i had manually set tint options and disabled the ATES i wanted to make sure everything weather related stayed on when he returned. I have parallel events on every map setting up the conditions of each. I'm guessing you will tell me to remove the script calls which i will be doing if necessary.

Oh and sorry for ticking ya off with the script paste....new as you can tell. That being said i used too talk with blizzard back on rpgmaker rmx or something back in 07. Decided i wanted to finish at least one game before i kick the bucket. Take care and thanks for replying.

KK20

I've noticed a pattern in the code...line 395 in OP

  def self.on
    $game_system.ates.active = true
    return true
  end
 
  def self.off
    $game_system.ates.active = false
    return true
  end
 
  def self.tint_on(frames = 0)
    $game_screen.start_tone_change($game_system.ates.get_environment[0], frames)
    $game_system.ates.tinting = true
    return true
  end
 
  def self.tint_off(reset = true)
    $game_screen.start_tone_change(Tone.new(0, 0, 0, 0), 0) if reset
    $game_system.ates.tinting = false
    return true
  end
 
  def self.weather_off
    $game_system.ates.weather.weather_enabled = false
    $game_system.ates.weather.pause_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
  end
 
  def self.weather_on
    $game_system.ates.weather.weather_enabled = true
    $game_system.ates.weather.resume_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
  end

Notice how the last two don't have a 'return true' at the end of them? So I went spelunking and

  def resume_weather(speed = -1)
  #...
  if weather[5].length > 0
    #...
    $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
  end
end

That last line is returning a Tone object, which is then returned to the Interpreter and compared with false, which gives us our error.

So yeah, just put return true in those two methods and it should be good.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

treign

That did the trick......thank you kindly. Greatly appreciate your time, Though my game won't be as crazy as some of the others i saw i'm going to finish it. I think the biggest thing i got going for mine is i'm doing all the music for it. Take care and hope you have a great weekend.

Travis

KK20

March 21, 2015, 12:23:02 am #18 Last Edit: March 21, 2015, 12:29:33 am by KK20
Script now updated to v1.02.

Oh a music man huh? I'd like to hear them :)

And thanks for confirming the solution. Fixed in OP.
There were actually a couple more script calls that didn't have any return statements in them so I fixed those other ones too, just in case.
(Scary thing is this has not been reported nor touched on for around 2 years. Maybe it's because those who used this also have Interpreter Script Call Fix.)

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

Krozandir

August 14, 2015, 09:34:59 am #19 Last Edit: August 14, 2015, 09:36:21 am by Krozandir
I'm having an error when using ATES.advance (0, 2, 0, 0, 0) I want the time to advance 2 hours and instead of that, it always advance 24 hours.
Spoiler: ShowHide

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Advanced Time and Environment System (ATES) by Blizzard and ThallionDarkshine
# Version: 1.02
# Type: Autonomous Timeflow and Environment Controller
# Date v0.3: 11.3.2008
# Date v0.31: 8.4.2009
# Date v0.32: 13.4.2009
# Date v0.33: 4.5.2009
# Date v0.34: 5.5.2009
# Date v1.0: 12.2.2013
# Date v1.01: 28.4.2013
# Date v1.02: 20.3.2015
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#   
#  This work is protected by the following license:
# #----------------------------------------------------------------------------
# # 
# #  Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# #  ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# # 
# #  You are free:
# # 
# #  to Share - to copy, distribute and transmit the work
# #  to Remix - to adapt the work
# # 
# #  Under the following conditions:
# # 
# #  Attribution. You must attribute the work in the manner specified by the
# #  author or licensor (but not in any way that suggests that they endorse you
# #  or your use of the work).
# # 
# #  Noncommercial. You may not use this work for commercial purposes.
# # 
# #  Share alike. If you alter, transform, or build upon this work, you may
# #  distribute the resulting work only under the same or similar license to
# #  this one.
# # 
# #  - For any reuse or distribution, you must make clear to others the license
# #    terms of this work. The best way to do this is with a link to this web
# #    page.
# # 
# #  - Any of the above conditions can be waived if you get permission from the
# #    copyright holder.
# # 
# #  - Nothing in this license impairs or restricts the author's moral rights.
# # 
# #----------------------------------------------------------------------------
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# Compatibility:
#
#   99% compatible with SDK v1.x. 90% compatible with SDK 2.x. WILL corrupt old
#   savegames. Can cause incompatibilty issues with DNS-es.
#
#
# Features:
#
#   - complete control over and easy manipulating of time and weather
#   - customizable day and night tinting
#   - HUD clock optional
#   - easier to control and more powerful than DDNS
#
#
# IMPORTANT NOTES:
#
# - This system has a working preconfiguration, be aware that a custom setup
#   will need you to understand what each option does, so please read the
#   configuration instructions.
# - Why does this system use switches to determine whether it's day or night?
#   Simple: You can use conditions in enemy attacks to determine whether an
#   attack should be used only at night or only at day.
#
#
# Instructions:
#
# - Explanation:
#
#   This Time System will make your game have daytime and nighttime periods.
#   The screen will be tinted accordingly. You can set up the length of the
#   day. Other features are explained below. Please be sure to configure this
#   system appropriately.
#
#
# - Basic manipulation of ATES:
#
#   This system is based upon your eventing. It will work basically if you
#   want, but with a little bit of using the "Call Script" event command you
#   are able to control this system fully. You can call following commands:
#
#     ATES.on
#   Turns ATES on.
#
#     ATES.off
#   Turns ATES off.
#
#     ATES.tint_on
#   Turns ATES's screen tinting on.
#
#     ATES.tint_off
#   Turns ATES's screen tinting off.
#
#     ATES.clock_on
#   Turns ATES's clock display on.
#
#     ATES.clock_off
#   Turns ATES's clock display off.
#
#     ATES.active?
#   Returns true if ATES is turned on, otherwise false.
#
#     ATES.tinting?
#   Returns true if ATES tinting is turned on, otherwise false.
#
#     ATES.day?
#   Returns true if it's day, otherwise false. Alternatively you can check the
#   assigned switch instead.
#
#     ATES.night?
#   Returns true if it's night, otherwise false. Alternatively you can check
#   the assigned switch instead.
#   
#     ATES.advance(Minutos, Horas, día, mes, año)
#   This will make the time advanced by M minutes and H hours. Any negative
#   value used will cancel the execution of this command.
#   
#     ATES.make_it_day
#   This is a feature from DDNS which allows you to quickly jump to the
#   daytime.
#   
#     ATES.make_it_night
#   This is a feature from DDNS which allows you to quickly jump to the
#   nighttime.
#   
#     ATES.weather_on
#   This allows you to turn on the weather system.
#
#     ATES.weather_off
#   This allows you to turn off the weather system.
#
#     ATES.lock_weather
#   This allows you to lock the current weather in place without disabling the
#   weather system entirely.
#
#     ATES.unlock_weather
#   This command unlocks the current weather.
#
#     ATES.weather_active?
#   Returns true if the weather system is turned on, otherwise false.
#
#     ATES.set_time(TIME_INDEX or TIME_NAME)
#   Sets the current time to the time at the index of TIME_INDEX or with the
#   name of TIME_NAME. Its better to use TIME_NAME because some bugs may occur
#   from using TIME_INDEX.
#
#     ATES.go_inside
#   A feature from the DDNS which allows you to change the lighting mode to
#   inside.
#
#     ATES.go_inside_dark
#   A feature from the DDNS which allows you to change the lighting mode to
#   inside dark.
#
#     ATES.go_outside
#   A feature from the DDNS which allows you to change the lighting mode to
#   outside.
#
#     ATES.set_weather(INDEX)
#   Sets the current weather to the weather at index INDEX.
#
#     ATES.terrain=(TERRAIN_NAME)
#   Sets the terrain to the terrain named TERRAIN_NAME.
#
#     ATES.time_name
#   Returns the name of the current time of day.
#
# - Enhancement hints:
#
#   If you wish to implement the DDNS further into your game and e.g. allow
#   different behavious of monsters during day and night, you only need to
#   check the the state of the appropriate switch. e.g. If NSWITCH is turned
#   on inflict "Sleep" on one enemy.
#
#
# Additional info:
#
#   The daytime and nighttime tintings were tested appropriately and optimal
#   tinting is being used.
#   Keep in mind that ATES is initially turned off, you need to turn it on by
#   using the ATES.on and ATES.tint_on commands together.
#
#
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

module ATES
 
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # switch ID of the "day" switch
  DSWITCH = 51
  # switch ID of the "night" switch
  NSWITCH = 52
  # variable ID of the temperature
  TVARIABLE = 51
  # length of a day in seconds in-game, can't be less than 36, is being
  # quantized into intervals of 36 seconds
  LENGTH = 1260
  # the amount to multiply weather sound by when inside
  INSIDE_SOUND = 0.7
  # the amount to multiply tone red, green, blue and gray by when inside
  INSIDE_TONE = 0.0
  # the tone for dark interiors
  DARK_INSIDE_TONE = Tone.new(-85, -85, -85, 85)
  # weather setup, create new types of weather here
  #  note - if you don't want a certain effect such as weather, fog, or sound,
  #    just leave the array for that effect empty
  #          ['NAME', WEATHER_SEVERITY, [WEATHER_TYPE, LOW_STRENGTH..HIGH_STRENGTH],
  #            [SOUND_NAME, SOUND_VOLUME_MIN..SOUND_VOLUME_MAX, SOUND_PITCH], [FOG_NAME, FOG_OPACITY, FOG_HUE,
  #            FOG_ZOOM, FOG_SX, FOG_SY, [TONE_RED, TONE_GREEN, TONE_BLUE, TONE_GRAY]],
  #            [SOUND_EFFECT_NAME, SOUND_VOLUME_MIN..SOUND_VOLUME_MAX, SOUND_PITCH, EFFECT_PROBABILITY,
  #            FLASH_DURATION, [FLASH_COLOR_RED, FLASH_COLOR_GREEN, FLASH_COLOR_BLUE]]]
  WEATHER = [['Drizzling', 0, 1..4, [1], ['005-Rain01', 65..80, 100], [], []],
             ['Raining', 0, 5..8, [1], ['006-Rain02', 75..90, 100], [], ['061-Thunderclap01', 60..85, 100, 0.07, 4, [255, 255, 255]]],
             ['Storm', 1, 9..10, [1], ['007-Rain03', 80..100, 100], [], ['061-Thunderclap01', 70..95, 110, 0.08, 6, [255, 255, 255]]],
             ['Cloudy', 0, 1..1, [], [], ['002-Clouds01', 60, 0, 200, 4, 3, [0, 0, 0, 0]], []],
             ['Raining', 0, 1..4, [2], ['006-Rain02', 70..85, 100], [], ['061-Thunderclap01', 65..90, 110, 0.08, 6, [255, 255, 255]]],
             ['Storm', 1, 5..8, [2], ['007-Rain03', 75..90, 100], [], ['061-Thunderclap01', 70..95, 110, 0.09, 7, [255, 255, 255]]],
             ['Storm', 2, 9..10, [2], ['007-Rain03', 90..100, 100], [], ['061-Thunderclap01', 85..100, 110, 0.11, 7, [255, 255, 255]]],
             ['Flurry', 1, 1..4, [3], ['002-Wind02', 70..85, 100], [], []],
             ['Snowing', 1, 5..8, [3], ['003-Wind03', 80..95, 100], [], []],
             ['Blizzard', 2, 9..10, [3], ['004-Wind04', 85..100, 100], [], []]]
  # normal weather duration in seconds
  WEATHER_DURATION = 57
  # variance of the weather duration in seconds
  WEATHER_VARIANCE = 24
  # the name of the default weather type (what gets shown in the clock when
  #   there is no weather)
  DEFAULT_WEATHER_NAME = 'Sunny'
  # season setup, create a new season by using this template
  #          ['NAME', START_DAY, START_MONTH, MIN_TEMP..MAX_TEMP, WEATHER_PROBABILITY,
  #            BAD_WEATHER_PROBABILITY, VERY_BAD_WEATHER_PROBABILITY, WEATHER_POSSIBILITIES]
  SEASONS = [
             ['Spring', 22,  3,   0..25, 0.003, 0.3, 0.05, [0, 1, 2, 3, 4, 5]] ,
             ['Summer', 21,  6,  20..35, 0.003, 0.1, 0.2, [0, 1, 3, 4, 5, 6]]  ,
             ['Autumn', 20,  9,   0..25, 0.003, 0.2, 0.1, [0, 2, 3, 4, 5, 7]]  ,
             ['Winter', 21, 12, -20..5, 0.003, 0.5, 0.1, [0, 2, 3, 4, 7, 8, 9]]
            ]
  # terrain setup, create a new terrain by using this template
  #          ['NAME', MIN_TEMP..MAX_TEMP, WEATHER_EXCLUSIONS]
  TERRAINS = [
              ['Forest', -7..0, [3]],
              ['Desert', 11..16, [8, 9]],
              ['Mountain', -9..-4, []],
              ['Plains', -2..0, []],
              ['Beach', -5..-2, [8, 9]]
             ]
  # longest day date, the longest night date is half a year later/earlier
  LONGEST = [21, 6]
  # the tone at which day starts
  DAY_START = "Sunrise"
  # the tone at which night starts
  NIGHT_START = "Dusk"
  # the different screen tones and temperature modifiers at certain points during the day on the longest and shortest days
  # to make a new time of day, add this into TIMES: NAME => [RED, GREEN, BLUE, GRAY, TEMPERATURE_MODIFIER]
  TIMES = {
           "Dawn" => [-17, -17, 17, 0, -4],
           "Sunrise" => [48, 30, 30, 0, -2],
           "Noon" => [24, 10, 10, 0, 5],
           "Sunset" => [57, -17, -17, 0, 1],
           "Dusk" => [-17, -17, 17, 0, -3],
           "Night" => [-150, -120, -120, 200, -8]
          }
  # once you have customized the tones, put the tones into LONG_TIMES and SHORT_TIMES with [name_of_time, hour, minute]
  LONG_TIMES = [["Dawn", 4, 30],
                ["Sunrise", 5, 30],
                ["Noon", 13, 00],
                ["Sunset", 21, 00],
                ["Dusk", 22, 00],
                ["Night", 1, 30]]
  SHORT_TIMES = [["Dawn", 6, 30],
                ["Sunrise", 7, 30],
                ["Noon", 13, 00],
                ["Sunset", 16, 30],
                ["Dusk", 17, 00],
                ["Night", 23, 30]]
  # makes the screen brighter during "summer" days
  OVERLIGHTING = true
  # makes the screen darker during the night, not recommended
  OVERDARKENING = false
  # the first year in your calender, the player can't scroll further back
  FYEAR = 1300
  # the last year in your calender, the player can't scroll further forth
  LYEAR = 1400
  # the suffix for temperature
  TEMP_SUFFIX = "°C"
  # the different holidays and their dates
  #   the format for adding a new holiday is:
  #     [NAME, SETUP_TYPE, MONTH, (DAY or WEEKDAY, NUMBER)]
  #   whether to use DAY or WEEKDAY, NUMBER depends on SETUP_TYPE:
  #     (0 - DAY; 1 - WDAY, NUMBER)
  # note - the current holiday will replace the weekday in the clock if it is a
  #   holiday
  HOLIDAYS = [
             ]
  # HUD clock format
  # default : ['%H:%M%s', '%A', '%d/%m/%Y', '%S']
  # use [] for no clock
  # it means: 1st row - "HOURS:MINUTES SUFFIX"
  #           2nd row - "WEEKDAY"
  #           3rd row - "DAY/MONTH/YEAR"
  #           4th row - "SEASON"
  # different combinations to input ATES information into the clock
  #   %H - Hour
  #   %M - Minute
  #   %s - Suffix (AM or PM) (only if not using 24 hour time)
  #   %A - Weekday
  #   %d - Day of the Month
  #   %D - Day of the Year
  #   %m - Month
  #   %n - Month Name
  #   %l - Month Length
  #   %Y - Year
  #   %L - Year Length
  #   %S - Season
  #   %w - Weather  #   %t - Terrain
  #   %T - Temperature
  #   %p - Time of Day
  CFORMAT = ['%H:%M', '%d/%m/%Y', '%A', '%T']
  # the width of the clock
  CWIDTH = 180
  # names of your days, automatically sets up a week's length
  WEEKDAYS = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes',
              'Sábado']
  WEEKDAY_ABBREVIATIONS = ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb']
  # names of your months, automatically sets up a year's length
  MONTHS = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio',
            'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
  # abbreviations for month names
  MONTH_ABBREVIATIONS = ['En', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul',
                         'Ago', 'Sept', 'Oct', 'Nov', 'Dic']
  # days in each month
  MONTHDAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  # the first day in the game [DAY, MONTH, YEAR, WEEKDAY]
  # set this option to [] if you want the game to start "now"
  START = [24, 3, 1316, 7]
  # set this option to true to turn on military time (24 hour time)
  HOUR24 = true
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
  mon = (LONGEST[1] + MONTHS.length / 2) % 12
  mon = 12 if mon == 0
  day = LONGEST[0] + (MONTHS.length % 2) == 1 ? MONTHDAYS[mon - 1] / 2 : 0
  while day > MONTHDAYS[mon - 1]
    day -= MONTHDAYS[mon - 1]
    mon = (mon + 1) % 12
    mon = 12 if mon == 0
  end
  SHORTEST = [day, mon]

  $ates = 1.01
 
  #============================================================================
  # ATES::Time
  #============================================================================
 
  class Time
   
    attr_accessor :min
    attr_accessor :hour
    attr_accessor :day
    attr_accessor :mon
    attr_accessor :year
    attr_accessor :wday
   
    def initialize(m, h, d, mon, y, w)
      @min, @hour, @day, @mon, @year, @wday = m, h, d, mon, y, w
    end
   
  end
 
  def self.on
    $game_system.ates.active = true
    return true
  end
 
  def self.off
    $game_system.ates.active = false
    return true
  end
 
  def self.tint_on(frames = 0)
    $game_screen.start_tone_change($game_system.ates.get_environment[0], frames)
    $game_system.ates.tinting = true
    return true
  end
 
  def self.tint_off(reset = true)
    $game_screen.start_tone_change(Tone.new(0, 0, 0, 0), 0) if reset
    $game_system.ates.tinting = false
    return true
  end
 
  def self.weather_off
    $game_system.ates.weather.weather_enabled = false
    $game_system.ates.weather.pause_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
    return true
  end
 
  def self.weather_on
    $game_system.ates.weather.weather_enabled = true
    $game_system.ates.weather.resume_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
    return true
  end
 
  def self.weather_active?
    return $game_system.ates.weather.weather_enabled
  end
 
  def self.lock_weather
    $game_system.ates.weather.locked = true
  end
 
  def self.unlock_weather
    $game_system.ates.weather.locked = false
    return true
  end
 
  def self.clock_on
    $game_system.show_clock = true
    return true
  end
 
  def self.clock_off
    $game_system.show_clock = false
    return true
  end
 
  def self.active?
    return $game_system.ates.active
  end
 
  def self.tinting?
    return $game_system.ates.tinting
  end
 
  def self.day?
    i = $game_system.ates.time_index
    while true
      if $game_system.ates.current_times
  • == DAY_START
            return true
          elsif $game_system.ates.current_times
    • == NIGHT_START
              return false
            end
           
            i = (i + $game_system.ates.current_times.length - 1) % $game_system.ates.current_times.length
          end
        end
       
        def self.night?
          return !(self.day?)
        end
       
        def self.make_it_day
          time = $game_system.ates.current_times.select { |time| time[0] == DAY_START }
          h, m = time[0][1], time[0][2]
          $game_system.ates.time.hour = h
          $game_system.ates.time.min = m
          return true
        end
       
        def self.make_it_night
          time = $game_system.ates.current_times.select { |time| time[0] == NIGHT_START }
          h, m = time[0][1], time[0][2]
          $game_system.ates.time.hour = h
          $game_system.ates.time.min = m
          return true
        end
       
        def self.set_time(time = 0)
          return unless $game_system
          if time.is_a?(Fixnum)
            time = $game_system.ates.current_times[time.to_i]
          else
            time = $game_system.ates.current_times.select { |current_time| current_time[0] == time }[0]
          end
          h, m = time[1], time[2]
          $game_system.ates.time.hour = h
          $game_system.ates.time.min = m
          return true
        end
       
        def self.day_start
          return DAY_START
        end
       
        def self.night_start
          return NIGHT_START
        end
       
        def self.go_inside_dark
          weather = $game_system.ates.weather.current_weather
          $game_system.ates.map_type = 2
          self.tint_on
          $game_system.ates.weather.pause_weather(0)
          return true if weather == -1
          low, high = weather[2].first, weather[2].last
          intensity = $game_system.ates.weather.current_intensity
          if weather[4].length > 0
            volume = ATES::INSIDE_SOUND * weather[4][1].first + (weather[4][1].last - weather[4][1].first) * (high - intensity).to_f / (high - low)
            bgm = RPG::AudioFile.new(weather[4][0], volume, weather[4][2])
            $game_system.bgs_play(bgm)
          end
          return true
        end
       
        def self.go_inside
          weather = $game_system.ates.weather.current_weather
          $game_system.ates.map_type = 1
          self.tint_on
          $game_system.ates.weather.pause_weather(0)
          return true if weather == -1
          low, high = weather[2].first, weather[2].last
          intensity = $game_system.ates.weather.current_intensity
          if weather[4].length > 0
            volume = ATES::INSIDE_SOUND * weather[4][1].first + (weather[4][1].last - weather[4][1].first) * (high - intensity).to_f / (high - low)
            bgm = RPG::AudioFile.new(weather[4][0], volume, weather[4][2])
            $game_system.bgs_play(bgm)
          end
          return true
        end
       
        def self.go_outside
          $game_system.ates.weather.resume_weather(0)
          $game_system.ates.map_type = 0
          self.tint_on
          return true
        end
       
        def self.set_weather(id)
          $game_system.ates.weather.set_weather(WEATHER[id])
          return true
        end
       
        def self.terrain=(terrain)
          terrain = TERRAINS[terrain.to_i][0] if terrain.is_a?(Fixnum)
          $game_system.ates.terrain = terrain
          return true
        end
       
        def self.advance(m, h, d, mon, y)
          return false if [m, h, d, mon, y].any? {|i| i < 0}
          changed = false
          h += ($game_system.ates.time.min + m) / 60
          $game_system.ates.time.min = ($game_system.ates.time.min + m) % 60
          d += ($game_system.ates.time.hour + h) / 24
          changed = true if d > 0
          $game_system.ates.time.hour = ($game_system.ates.time.hour + h) % 24
          while d > 0
            if $game_system.ates.time.day < MONTHDAYS[mon]
              $game_system.ates.time.day += 1
            else
              $game_system.ates.time.day = 0
              mon = (mon + 1) % MONTHS.size
            end
            $game_system.ates.time.wday += 1
            $game_system.ates.time.wday %= WEEKDAYS.size
            d -= 1
          end
          y += ($game_system.ates.time.mon + mon) / MONTHS.size
          $game_system.ates.time.mon = ($game_system.ates.time.mon + mon) % MONTHS.size
          $game_system.ates.time.year += y
          return changed
        end
       
        def self.time_name
          return $game_system.ates.current_times[$game_system.ates.time_index][0]
        end
       
      end

      if ATES::MONTHS.size > ATES::MONTHDAYS.size
        raise 'ATEScfgError: Not all months have a length in days specified!'
      #elsif ATES::DAY_START > ATES::NIGHT_START
      #  raise 'ATEScfgError: A night can\'t start earlier than a day.'
      elsif ATES::LENGTH < 36
        raise 'ATEScfgError: A day\'s length must be equal to or greater than 36 seconds!'
      end

      #==============================================================================
      # Weather
      #==============================================================================

      class Weather
        attr_accessor :current_weather, :current_intensity, :weather_enabled, :locked
       
        def initialize
          @current_weather = -1
          @current_intensity = 0
          @normal_weather = []
          @bad_weather = []
          @very_bad_weather = []
          @weather_enabled = true
          @locked = false
        end
       
        def decimal_places(num)
          if num.is_a?(Float)
            return num.to_s.split('.')[1].length
          else
            return 0
          end
        end
       
        def get_weather(severity = 0)
          weather = []
          season = $game_system.ates.get_full_season
          ATES::WEATHER.each_with_index { |el, ind|
            weather.push(el) if el[1] == severity and season[7].include?(ind)
          }
          return weather
        end
       
        def update
          season = $game_system.ates.get_full_season
          if !@season or @season != season
            @normal_weather = get_weather
            @bad_weather = get_weather(1)
            @very_bad_weather = get_weather(2)
            @season = season
          end
          unless @locked
            places = [decimal_places(season[4]), decimal_places(season[5]), decimal_places(season[6])]
            if rand(10 ** places[0]) <= season[4] * (10 ** places[0]) and season[7].length > 0
              if rand(10 ** places[1]) <= season[4] * (10 ** places[1]) and @bad_weather.length > 0
                weather = rand(@bad_weather.length)
                weather = @bad_weather[weather]
                set_weather(weather)
              elsif rand(10 ** places[2]) <= season[4] * (10 ** places[2]) and @very_bad_weather.length > 0
                weather = rand(@very_bad_weather.length)
                weather = @very_bad_weather[weather]
                set_weather(weather)
              elsif @normal_weather.length > 0
                weather = rand(@normal_weather.length)
                weather = @normal_weather[weather]
                set_weather(weather)
              end
            end
          end
          if @current_weather != -1
            update_effect if @weather_enabled and @current_weather[6].length > 0
            @weather_count += 1
            if @weather_count >= @weather_duration
              stop_weather unless @locked
            end
          end
        end
       
        def update_effect
          weather = @current_weather
          places = decimal_places(weather[6][3])
          if rand(10 ** places) <= weather[6][3] * 10 ** places
            high, low = weather[2].first, weather[2].last
            vol = weather[6][1].first + (weather[6][1].last - weather[6][1].first) * (high - @current_intensity).to_f / (high - low)
            vol *= ATES::INSIDE_SOUND if $game_system.ates.map_type > 0
            sound = RPG::AudioFile.new(weather[6][0], vol, weather[6][2])
            $game_system.se_play(sound)
            col = Color.new(0, 0, 0)
            $game_screen.start_flash(Color.new(*weather[6][5]), weather[6][4])
          end
        end
       
        def stop_weather(speed = -1)
          return if @current_weather == -1
          speed = speed == -1 ? rand(10) + 60 : speed
          if @current_weather[3].length > 0
            $game_screen.weather(0, 1, speed)
          end
          if @current_weather[4].length > 0
            $game_system.bgs_fade(speed.to_f / 40)
          end
          if @current_weather[5].length > 0
            $game_map.fog_name = ''
          end
          @current_weather = -1
        end
       
        def pause_weather(speed = -1)
          return if @current_weather == -1
          $game_system.ates.show_weather = false
          speed = speed == -1 ? rand(10) + 60 : speed
          if @current_weather[3].length > 0
            $game_screen.weather(0, 1, speed)
          end
          if @current_weather[4].length > 0
            $game_system.bgs_fade(speed.to_f / 40)
          end
          if @current_weather[5].length > 0
            $game_map.fog_name = ''
          end
        end
       
        def resume_weather(speed = -1)
          return if @current_weather == -1
          $game_system.ates.show_weather = true
          weather = @current_weather
          intensity = @current_intensity
          low, high = weather[2].first, weather[2].last
          speed = speed == -1 ? rand(10) + 60 : speed
          if weather[3].length > 0
            $game_screen.weather(weather[3][0], intensity, speed)
          end
          if weather[4].length > 0
            volume = weather[4][1].first + (weather[4][1].last - weather[4][1].first) * (high - intensity).to_f / (high - low)
            bgm = RPG::AudioFile.new(weather[4][0], volume, weather[4][2])
            $game_system.bgs_play(bgm)
          end
          if weather[5].length > 0
            $game_map.fog_name = weather[5][0]
            $game_map.fog_opacity = weather[5][1]
            $game_map.fog_hue = weather[5][2]
            $game_map.fog_zoom = weather[5][3]
            $game_map.fog_sx = weather[5][4]
            $game_map.fog_sy = weather[5][5]
            $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
          end
        end
       
        def set_weather(weather, speed = -1)
          stop_weather if @current_weather != -1
          @weather_count = 0
          @weather_duration = ATES::WEATHER_DURATION + rand(ATES::WEATHER_VARIANCE)
          low, high = weather[2].first, weather[2].last
          intensity = rand(high + 1 - low) + low
          @current_weather = weather
          @current_intensity = intensity
          return unless @weather_enabled
          if weather.is_a?(Fixnum)
            weather = WEATHER[weather]
          end
          speed = speed == -1 ? rand(10) + 60 : speed
          if weather[4].length > 0
            volume = weather[4][1].first + (weather[4][1].last - weather[4][1].first) * (high - intensity).to_f / (high - low)
            volume *= ATES::INSIDE_SOUND if $game_system.ates.map_type > 0
            bgm = RPG::AudioFile.new(weather[4][0], volume, weather[4][2])
            $game_system.bgs_play(bgm)
          end
          return if $game_system.ates.map_type > 0
          if weather[3].length > 0
            if $modified_aws and weather[3].length > 1
              $game_screen.weather(weather[3][0], intensity, speed, weather[3][1])
            else
              $game_screen.weather(weather[3][0], intensity, speed)
            end
          end
          if weather[5].length > 0
            $game_map.fog_name = weather[5][0]
            $game_map.fog_opacity = weather[5][1]
            $game_map.fog_hue = weather[5][2]
            $game_map.fog_zoom = weather[5][3]
            $game_map.fog_sx = weather[5][4]
            $game_map.fog_sy = weather[5][5]
            $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
          end
        end
      end

      #==============================================================================
      # Game_System
      #==============================================================================

      class Game_System
       
        attr_accessor :ates
        attr_accessor :show_clock
       
        alias init_ates_later initialize
        def initialize
          init_ates_later
          @ates = Game_ATES.new
          @show_clock = (ATES::CFORMAT != [])
        end

      end

      #==============================================================================
      # Game_ATES
      #==============================================================================

      class Game_ATES
       
        attr_accessor :active
        attr_accessor :tinting
        attr_accessor :time
        attr_accessor :weather
        attr_accessor :frame_count
        attr_accessor :current_times
        attr_accessor :tone
        attr_accessor :map_type
        attr_accessor :show_weather
        attr_accessor :terrain
        attr_accessor :temp
        attr_reader   :holiday
        attr_reader   :time_index
       
        def initialize
          if ATES::START.size == 4
            @time = ATES::Time.new(0, 0, ATES::START[0], ATES::START[1],
                ATES::START[2], ATES::START[3])
          else
            @time = Time.now
            @time = ATES::Time.new(@time.min, @time.hour, @time.mday, @time.mon, @time.year, @time.wday)
          end
          @weather = Weather.new
           
          @long_times = ATES::LONG_TIMES.sort { |t1, t2| t1[1] * 100 + t1[2] <=> t2[1] * 100 + t2[2] }
          @short_times = ATES::SHORT_TIMES.sort { |t1, t2| t1[1] * 100 + t1[2] <=> t2[1] * 100 + t2[2] }
         
          @year_length = ATES::MONTHDAYS.inject { |sum, x| sum + x }
         
          @terrain = ''
          @current_times = setup_times
          @temp_modifier = (rand(201) - 100) / 100.0
          @tone, @temp = get_environment
          @holiday = get_holiday(@time.mon, @time.day, @time.wday)
          @s_time = get_time(@time.min, @time.hour)
          $game_screen.start_tone_change(@tone, 0) if $game_screen
         
          @active = true
          @tinting = true
          @show_weather = true
          @map_type = 0
          @frame_count = 0
        end
       
        def get_holiday(month, day, wday)
          ATES::HOLIDAYS.select { |i|
            case i[1]
            when 0:
              i[2..3] == [month, day]
            when 1:
              if i[4] > 0
                i[2] == month and i[3] == wday and i[4] == (day.to_f / 7 + 1).floor
              elsif i[4] < 0
                i[2] == month and i[3] == wday and -i[4] == ((ATES::MONTHDAYS[month] - 1 - day).to_f / 7 + 1).floor
              end
            end
          }[0]
        end
       
        def get_environment
         
          red = 0
          green = 0
          blue = 0
          grey = 0
          @temp_modifier += (rand(3) - 1) / 100.0 if rand(10) == 0
         
          changed = false
         
          for i in 0...@current_times.length
            time1 = get_time(@current_times[2], @current_times[1])
            time2 = get_time(@current_times[(i + 1) % @current_times.length][2], @current_times[(i + 1) % @current_times.length][1])
            current = get_time(@time.min, @time.hour)
            if time2 < time1
              time2 += 24 * 60
            end
            if current < time1
              current += 24 * 60
            end
           
            if time1 <= current and time2 >= current
             
              changed = true
              tone1 = @current_times
              tone2 = @current_times[(i + 1) % @current_times.length]
              tone1 = ATES::TIMES[tone1[0]]
              tone2 = ATES::TIMES[tone2[0]]
              max = time2 - time1
             
              ratios = [(current - time1).to_f / max, (time2 - current).to_f / max]
              red = tone1[0] * ratios[1] + tone2[0] * ratios[0]
              green = tone1[1] * ratios[1] + tone2[1] * ratios[0]
              blue = tone1[2] * ratios[1] + tone2[2] * ratios[0]
              grey = tone1[3] * ratios[1] + tone2[3] * ratios[0]
             
              temp_range = get_full_season[3]
              temp_range = [temp_range.first, temp_range.last].sort
              unless @base_temp
                temp = temp_range[0] + rand(temp_range[1] - temp_range[0] + 1)
                if @terrain != ''
                  modifier = ATES::TERRAINS.select { |terrain| terrain[0] == @terrain }[0][1]
                  modifier = [modifier.first, modifier.last].sort
                  modifier = modifier[0] + rand(modifier[1] - modifier[0] + 1)
                  temp += modifier
                end
                @base_temp = temp
              else
                temp = @base_temp
              end
             
              temp_mod = round(tone1[4] * ratios[1] + tone2[4] * ratios[0], 2)
              temp += temp_mod + @temp_modifier
             
              @time_index = ratios[0] < 0.5 ? i : (i + 1) % @current_times.length
              break
            end
          end
         
          print "not right" unless changed
         
          if @map_type == 1
            return Tone.new(red * ATES::INSIDE_TONE, green * ATES::INSIDE_TONE, blue * ATES::INSIDE_TONE, grey * ATES::INSIDE_TONE), temp
          elsif @map_type == 2
            return ATES::DARK_INSIDE_TONE, temp
          else
            return Tone.new(red, green, blue, grey), temp
          end
        end
       
        def setup_times
          current_date = [@time.day, @time.mon]
          if current_date == ATES::LONGEST or @long_times == @short_times
            return @long_times
          elsif current_date == ATES::SHORTEST
            return @short_times
          end
         
          short_times = @long_times.clone
          addons = @short_times.clone
          current_date = get_date(*current_date)
          long, short = get_date(*ATES::LONGEST), get_date(*ATES::SHORTEST)
          dists = []
          if (current_date >= short and current_date <= long)
            dists = [current_date - short, long - current_date]
          elsif (current_date >= short and short >= long)
            dists = [current_date - short, long + @year_length - current_date]
          elsif (current_date <= long and long <= short)
            dists = [current_date + @year_length - short, long - current_date]
          elsif (current_date >= long and current_date <= short)
            dists = [current_date - long, short - current_date]
          elsif (current_date <= short and short <= long)
            dists = [current_date + @year_length - long, short - current_date]
          elsif (current_date >= long and long >= short)
            dists = [current_date - long, short + @year_length - current_date]
          end
          sum = dists.inject { |sum, x| sum + x }
          short_times.each { |tone|
            addons.each { |addon|
              if tone[0] == addon[0]
                ts = [tone[1] * 100 + tone[2] * 50 / 30.0, addon[1] * 100 + addon[2] * 50 / 30.0]
                ts = ts[0] * dists[0] / sum.to_f + ts[1] * dists[1] / sum.to_f
                h = (ts / 100).floor
                m = ((ts - h * 100) * 30 / 50).floor
                tone[1], tone[2] = h, m
              end
            }
          }
         
          return short_times.sort { |x, y| get_time(x[2], x[1]) <=> get_time(y[2], y[1]) }
        end
       
        def round(num, places = 0)
          return ((num * 10 ** places).round.to_f) / (10 ** places)
        end
       
        def get_time(minutes, hours)
          return minutes + hours * 60
        end
       
        def get_season
          season_list = ATES::SEASONS.sort { |x, y| get_date(x[1], x[2]) <=> get_date(y[1], y[2]) }
          day = @time.day
          month = @time.mon
          current = get_date(day, month)
          for i in 0...season_list.length
            seasons = [season_list, season_list[(i + 1) % season_list.length]]
            times = [get_date(seasons[0][1], seasons[0][2]), get_date(seasons[1][1], seasons[1][2])]
            if times[0] <= current and current < times[1]
              return seasons[0][0]
            end
          end
          return season_list[0][0]
        end
       
        def get_full_season
          season_list = ATES::SEASONS.sort { |x, y| get_date(x[1], x[2]) <=> get_date(y[1], y[2]) }
          day = @time.day
          month = @time.mon
          current = get_date(day, month)
          for i in 0...season_list.length
            seasons = [season_list, season_list[(i + 1) % season_list.length]]
            times = [get_date(seasons[0][1], seasons[0][2]), get_date(seasons[1][1], seasons[1][2])]
            if times[0] <= current and current < times[1]
              return seasons[0]
            end
          end
          return season_list[0]
        end
       
        def get_date(day, month)
          month = ATES::MONTHS.length if month == 0
          return (ATES::MONTHDAYS[0...month - 1].inject { |sum, x| sum + x } or 0) + day
        end
       
        def update
          if @active
            @frame_count += 1
            changed = false
            if @frame_count % (ATES::LENGTH / 36) == 0
              tmp = @time.day
              changed = (ATES.advance(1, 0, 0, 0, 0))
              if @time.day != tmp
                @holiday = get_holiday(@time.mon, @time.day, @time.wday)
              end
              @weather.update
            end
            if changed
              @current_times = setup_times
            end
          end
          if ATES.day?
            $game_map.need_refresh = true if $game_switches[ATES::NSWITCH]
            $game_switches[ATES::DSWITCH] = true
            $game_switches[ATES::NSWITCH] = false
          else
            $game_map.need_refresh = true if $game_switches[ATES::DSWITCH]
            $game_switches[ATES::DSWITCH] = false
            $game_switches[ATES::NSWITCH] = true
          end
          @tone, @temp = get_environment
          tmp = get_time(@time.min, @time.hour)
          $game_screen.start_tone_change(@tone, ((@s_time - tmp).abs < [1440 / ATES::LENGTH, 1].max ? 0 : 20)) if @tinting
        end
       
      end

      #==============================================================================
      # Bitmap
      #==============================================================================

      class Bitmap

        if $tons_version == nil || $tons_version < 1.6
          alias draw_text_shaded_later draw_text
        end
        def draw_text_full(x2, y2, w2 = 0, h2 = 0, text2 = '', a2 = 0)
          if x2.is_a?(Rect)
            x, y, w, h, text, a = x2.x, x2.y, x2.width, x2.height, y2, w2
          else
            x, y, w, h, text, a = x2, y2, w2, h2, text2, a2
          end
          save_color = self.font.color.clone
          self.font.color = Color.new(0, 0, 0)
          [x-1, x+1].each {|xx| [y-1, y+1].each {|yy|
                  draw_text_shaded_later(xx, yy, w, h, text, a)}}
          self.font.color = save_color
          draw_text_shaded_later(x, y, w, h, text, a)
        end
       
      end

      #==============================================================================
      # Clock_Sprite
      #==============================================================================

      class Clock_Sprite < Sprite
       
        def initialize
          super
          self.x, self.y, self.z = 640 - 8 - ATES::CWIDTH, 8, 5000
          self.bitmap = Bitmap.new(ATES::CWIDTH, ATES::CFORMAT.length * 32)
          if $fontface != nil
            self.bitmap.font.name = $fontface
          elsif $defaultfonttype != nil
            self.bitmap.font.name = $defaultfonttype
          end
          self.bitmap.font.size = 26
          @odd = 0
          draw if $game_system.ates.active
        end
       
        def draw
          self.bitmap.clear
          hours = $game_system.ates.time.hour
          minutes = sprintf('%02d', $game_system.ates.time.min)
          weekday = ATES::WEEKDAYS[$game_system.ates.time.wday - 1]
          wday_abbr = ATES::WEEKDAY_ABBREVIATIONS[$game_system.ates.time.wday - 1]
          day = $game_system.ates.time.day + 1
          month = $game_system.ates.time.mon + 1
          yday = ATES::MONTHDAYS[0..month - 1].inject { |s, r| s + r } + day
          month_name = ATES::MONTHS[month - 1]
          month_abbr = ATES::MONTH_ABBREVIATIONS[month - 1]
          month_days = ATES::MONTHDAYS[month - 1]
          year = $game_system.ates.time.year
          year_days = ATES::MONTHDAYS.inject { |s, r| s + r }
          season = $game_system.ates.get_season
          terrain = $game_system.ates.terrain
          temp = $game_system.ates.temp.to_s + ATES::TEMP_SUFFIX
          weather = $game_system.ates.weather.current_weather == -1 ? ATES::DEFAULT_WEATHER_NAME : $game_system.ates.weather.current_weather[0]
          tod = $game_system.ates.current_times[$game_system.ates.time_index][0]
          hday = $game_system.ates.holiday
          if hday != nil
            weekday = hday[0]
          end
          clock_text = ATES::CFORMAT.map { |ln| ln.clone }
          unless ATES::HOUR24
            suffix = "PM"
            if hours < 12
              suffix = "AM"
              hours = 12 if hours == 0
            elsif hours > 12
              suffix = "PM"
              hours -= 12
            end
          else
            suffix = ""
            hours = 24 if hours == 0
            hours = sprintf('%02d', hours)
          end
          colon = @odd % 2 == 0 ? " " : ":"
          clock_text.each { |ln|
            ln.gsub!(/%M/, minutes)
            ln.gsub!(/%H/, hours.to_s)
            ln.gsub!(/%A/, weekday)
            ln.gsub!(/%s/, " " + suffix)
            ln.gsub!(/:/, colon)
            ln.gsub!(/%m/, month.to_s)
            ln.gsub!(/%n/, month_name)
            ln.gsub!(/%l/, month_days.to_s)
            ln.gsub!(/%Y/, year.to_s)
            ln.gsub!(/%L/, year_days.to_s)
            ln.gsub!(/%d/, day.to_s)
            ln.gsub!(/%D/, yday.to_s)
            ln.gsub!(/%S/, season)
            ln.gsub!(/%w/, weather)
            ln.gsub!(/%t/, terrain)
            ln.gsub!(/%T/, temp)
            ln.gsub!(/%p/, tod)
          }
          if @odd % 2 == 0
            string = "#{hours} #{minutes}"
          else
            string = "#{hours}:#{minutes}"
          end
          string += " #{suffix}" unless ATES::HOUR24
          for i in 0...clock_text.length
            self.bitmap.draw_text_full(0, i * 32, self.bitmap.width, 32, clock_text, 1)
          end
          @odd = (@odd + 1) % 2
        end
         
      end

      #==============================================================================
      # Scene_Map
      #==============================================================================

      class Scene_Map
       
        alias main_ates_later main
        def main
          @clock = Clock_Sprite.new if $game_system.show_clock
          main_ates_later
          @clock.dispose if @clock != nil
        end
       
        alias update_ates_later update
        def update
          $game_system.ates.update
          update_ates_later
          if $game_system.show_clock
            @clock = Clock_Sprite.new if @clock == nil
            @clock.draw if $game_system.ates.frame_count % 20 == 0
          elsif @clock != nil
            @clock.dispose
            @clock = nil
          end
        end
       
      end

      #==============================================================================
      # Scene_Battle
      #==============================================================================

      class Scene_Battle
        alias update_ates_later update
        def update
          $game_system.ates.update
          update_ates_later
        end
       
      end

      #==============================================================================
      # Game_Map
      #==============================================================================

      class Game_Map
        alias setup_ates_later setup
        def setup(map_id)
          $game_system.ates.update
          setup_ates_later(map_id)
          if $game_system.ates.show_weather and $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
            weather = $game_system.ates.weather.current_weather
            if weather[5].length > 0
              $game_map.fog_name = weather[5][0]
              $game_map.fog_opacity = weather[5][1]
              $game_map.fog_hue = weather[5][2]
              $game_map.fog_zoom = weather[5][3]
              $game_map.fog_sx = weather[5][4]
              $game_map.fog_sy = weather[5][5]
              $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
            end
          end
         
          @events.each { |ev|
            ev = ev[1]
            if ev.list and ev.list.length > 0 and ev.list[0].code == 108 and ev.list[0].parameters[0] =~ /Terrain='(.+)'/
              $game_system.ates.terrain = $1
            end
          }
        end 
      end

      #==============================================================================
      # Scene_Calendar
      #==============================================================================

      class Scene_Calendar
        def main
          # Make calendar window
          @calendar_window = Window_Calendar.new
          @calendar_window.active = true
          @calendar_window.z = 1000
          #@day_window = Window_Day.new
          #@day_window.z = 1010
          #@day_window.visible = false
          #@dir = rand(4)
          # Make spriteset
          @spriteset = Spriteset_Map.new
          # Execute transition
          Graphics.transition
          # Main loop
          loop do
            # Update game screen
            Graphics.update
            # Update input information
            Input.update
            # Frame update
            update
            # Abort loop if screen is changed
            if $scene != self
              break
            end
          end
          # Prepare for transition
          Graphics.freeze
          # Dispose of window
          @calendar_window.dispose
          #@day_window.dispose
          # Dispose of spriteset
          @spriteset.dispose
        end
       
        def update
          @calendar_window.update
          #@day_window.update
          #if @calendar_window.active
            #if Input.trigger?(Input::C)
            #  @day_window.visible = true
            #  @day_window.active = true
            #  @calendar_window.active = false
            #  @day_window.x, @day_window.y = 80, 80
            #  @day_window.appear(@dir)
            #  @dir = rand(4)
            #end
            if Input.trigger?(Input::B)
              $game_system.se_play($data_system.cancel_se)
              $scene = Scene_Map.new
            end
          #elsif @day_window.active
            #if Input.trigger?(Input::B)
            #  @day_window.disappear(@dir)
            #  @day_window.active = false
            #  @calendar_window.active = true
            #end
          #end
        end
      end

      #==============================================================================
      # Window_Calendar
      #==============================================================================

      class Window_Calendar < Window_Base
        def initialize
          super(48, 48, 544, 384)
          self.contents = Bitmap.new(width - 32, height - 32)
          @month, @day, @wday, @year = $game_system.ates.time.mon, $game_system.ates.time.day, $game_system.ates.time.wday, $game_system.ates.time.year
          update
          refresh
        end
       
        def update
          prev_mon = @month
          if Input.repeat?(Input::LEFT)
            $game_system.se_play($data_system.cursor_se)
            continue = true
            @day -= 1
            if @day == 0
              @month -= 1
              if @month == 0
                unless @year == ATES::FYEAR
                  @year -= 1
                  @month = ATES::MONTHS.length
                else
                  @day = 1
                  @month = 1
                  continue = false
                end
              end
              @day = ATES::MONTHDAYS[@month - 1]
            end
            if continue
              @wday = (@wday + ATES::WEEKDAYS.length - 1) % ATES::WEEKDAYS.length
              @wday = ATES::WEEKDAYS.length if @wday == 0
            end
          end
          if Input.repeat?(Input::RIGHT)
            $game_system.se_play($data_system.cursor_se)
            continue = true
            @day += 1
            if @day == ATES::MONTHDAYS[@month - 1] + 1
              @month += 1
              if @month == ATES::MONTHS.length + 1
                unless @year == ATES::LYEAR
                  @year += 1
                  @month = 1
                else
                  @month = ATES::MONTHS.length
                  @day = ATES::MONTHDAYS[@month - 1]
                  continue = false
                end
              end
              @day = 1
            end
            if continue
              @wday = (@wday + 1) % ATES::WEEKDAYS.length
              @wday = ATES::WEEKDAYS.length if @wday == 0
            end
          end
          if Input.repeat?(Input::UP)
            $game_system.se_play($data_system.cursor_se)
            continue = true
            tmpday = @day
            @day -= ATES::WEEKDAYS.length
            if @day <= 0
              @month -= 1
              if @month == 0
                unless @year == ATES::FYEAR
                  @year -= 1
                  @month = ATES::MONTHS.length
                else
                  @day = tmpday
                  @month = 1
                  continue = false
                end
              end
              if continue
                tmp = (@wday + ATES::WEEKDAYS.length - @day) % ATES::WEEKDAYS.length
                tmp = ATES::WEEKDAYS.length if tmp == 0
                if @wday > tmp
                  tmp = tmp + ATES::WEEKDAYS.length - @wday
                else
                  tmp = tmp - @wday
                end
                @day = ATES::MONTHDAYS[@month - 1]
                @day -= tmp
              end
            end
          end
          if Input.repeat?(Input::DOWN)
            $game_system.se_play($data_system.cursor_se)
            continue = true
            tmpday = @day
            @day += ATES::WEEKDAYS.length
            if @day >= ATES::MONTHDAYS[@month - 1] + 1
              @month += 1
              if @month == ATES::MONTHS.length + 1
                unless @year == ATES::LYEAR
                  @year += 1
                  @month = 1
                else
                  @day = tmpday
                  @month = ATES::MONTHS.length
                  continue = false
                end
              end
              if continue
                tmp = (@wday + ATES::MONTHDAYS[@month - 2] - @day) % ATES::WEEKDAYS.length
                tmp = ATES::WEEKDAYS.length if tmp == 0
                if @wday <= tmp
                  tmp -= ATES::WEEKDAYS.length
                end
                @day = @wday - tmp
              end
            end
          end
          super()
          refresh if prev_mon != @month
          row_count = (ATES::MONTHDAYS.max - 2) / ATES::WEEKDAYS.length + 2
          row_height = height - 116
          top_margin = ((row_height % row_count) / 2.0).ceil
          row_height -= row_height % row_count
          row_height /= row_count
          colwidth = width - 32
          margin = ((colwidth % ATES::WEEKDAY_ABBREVIATIONS.length) / 2.0).ceil
          colwidth -= colwidth % ATES::WEEKDAY_ABBREVIATIONS.length
          colwidth /= ATES::WEEKDAY_ABBREVIATIONS.length
          start_wday = (@wday + ATES::WEEKDAYS.length - (@day - 1) % ATES::WEEKDAYS.length) % ATES::WEEKDAYS.length
          start_wday = ATES::WEEKDAYS.length if start_wday == 0
          row = (@day + start_wday - 2) / ATES::WEEKDAYS.length
          self.cursor_rect.set(margin + (@wday - 1) * colwidth, 84 + top_margin + row * row_height, colwidth, 32)
        end
       
        def refresh
          self.contents.clear
          self.contents.font.size = 32
          self.contents.font.color = system_color
          self.contents.draw_text_full(Rect.new(0, 0, width - 32, 32), ATES::MONTHS[@month - 1] + " " + @year.to_s, 1)
          self.contents.font.size = 24
         
          colwidth = width - 32
          margin = ((colwidth % ATES::WEEKDAY_ABBREVIATIONS.length) / 2.0).ceil
          colwidth -= colwidth % ATES::WEEKDAY_ABBREVIATIONS.length
          colwidth /= ATES::WEEKDAY_ABBREVIATIONS.length
         
          for i in 0...ATES::WEEKDAY_ABBREVIATIONS.length
            self.contents.draw_text_full(Rect.new(margin + i * colwidth, 40, colwidth, 32), ATES::WEEKDAY_ABBREVIATIONS, 1)
          end
          self.contents.fill_rect(Rect.new(0, 76, width - 32, 2), system_color)
         
          row_count = (ATES::MONTHDAYS.max - 2) / ATES::WEEKDAYS.length + 2
          row_height = height - 116
          top_margin = ((row_height % row_count) / 2.0).ceil
          row_height -= row_height % row_count
          row_height /= row_count
          cur_wday = (@wday + ATES::WEEKDAYS.length - (@day - 1) % ATES::WEEKDAYS.length) % ATES::WEEKDAYS.length
          cur_wday = ATES::WEEKDAYS.length if cur_wday == 0
          start_wday = cur_wday
          cur_day = 1
          cur_row = (cur_day - 1) / 7
          while cur_day <= ATES::MONTHDAYS[@month - 1]
            if (cur_day == $game_system.ates.time.day and @month == $game_system.ates.time.mon and @year == $game_system.ates.time.year)
              self.contents.font.color = Color.new(240, 40, 40)
            elsif $game_system.ates.get_holiday(@month - 1, cur_day - 1, cur_wday) != nil
              self.contents.font.color = Color.new(150, 150, 0)
            else
              self.contents.font.color = normal_color
            end
            self.contents.draw_text_full(Rect.new(margin + (cur_wday - 1) * colwidth, 84 + top_margin + cur_row * row_height, colwidth, 32), cur_day.to_s, 1)
            cur_day += 1
            cur_wday = cur_wday + 1
            if cur_wday > ATES::WEEKDAYS.length
              cur_wday -= ATES::WEEKDAYS.length
              cur_row += 1
            end
          end
        end
      end

      #==============================================================================
      # Window_Day
      #==============================================================================

      class Window_Day < Window_Base
        def initialize
          #(dir == 2 ? 320 : 48), (dir == 3 ? 240 : 48), (dir % 2 == 0 ? 272 : 544), (dir % 2 == 1 ? 192 : 384)
          super(80, 80, 480, 320)
          self.contents = Bitmap.new(width - 32, height - 32)
        end
       
        def appear(dir, duration = 40)
          @d_pos = [self.x, self.y]
          case dir
          when 0:
            self.x = -480
          when 1:
            self.y = -320
          when 2:
            self.x = 640
          when 3:
            self.y = 480
          end
          @s_pos = [self.x, self.y]
          @dir = dir
          @duration = duration
          @frames = 0
          @moving = true
        end
       
        def disappear(dir, duration = 40)
          @s_pos = [self.x, self.y]
          case dir
          when 0:
            self.x += 560
          when 1:
            self.y -= 400
          when 2:
            self.x += 560
          when 3:
            self.y += 400
          end
          @d_pos = [self.x, self.y]
          self.x, self.y = *@s_pos
          @dir = dir
          @duration = duration
          @frames = 0
          @moving = true
        end
       
        def update
          if @moving
            self.x = (@d_pos[0] * @frames + @s_pos[0] * (@duration - @frames)) / @duration
            self.y = (@d_pos[1] * @frames + @s_pos[1] * (@duration - @frames)) / @duration
            @moving = ([self.x, self.y] != @d_pos)
            @frames += 1
          end
          super()
        end
      end

      class Window_Text < Window_Base
        def initialize
          super(48, 48, 544, 384)
          self.contents = Bitmap.new(width - 32, height - 32)
         
          @dual_keys = ['`','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E',
                        'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U',
                        'V','W','X','Y','Z','-','=','[',']','\\',';','\'',',','.','/']
          @single_keys = ['NumberPad 0','NumberPad 1','NumberPad 2','NumberPad 3',
                          'NumberPad 4','NumberPad 5','NumberPad 6','NumberPad 7',
                          'NumberPad 8','NumberPad 9','Space','Enter','Tab']
          @chars1 = ['`','1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f',
                     'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
                     'x','y','z','-','=','[',']','/',';','\'',',','.','\\']
          @chars2 = ['~','!','@','#','$','%','^','&','*','(',')','A','B','C','D','E','F',
                     'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W',
                     'X','Y','Z','_','+','{','}','?',':','"','<','>','|']
          @chars = ['0','1','2','3','4','5','6','7','8','9',' ','\n','\t']
         
          @text = ""
          @cursor = true
        end
       
        def update
          @dual_keys.each_with_index { |i, ind|
            if Input.repeat?(Input::Key)
              @text += (Input.press?(Input::Key['Shift']) ? @chars2[ind] : @chars1[ind])
            end
          }
          @single_keys.each_with_index { |i, ind|
            if Input.repeat?(Input::Key)
              @text += @chars[ind]
            end
          }
          if Input.repeat?(Input::Key['Backspace'])
            @text = @text.split('')
            tmp = @text.pop()
            if (tmp == 'n' or tmp == 't') and @text[@text.length - 1] == '\\'
              @text.pop()
            end
            @text = @text.join('')
          end
          @cursor = !@cursor if Graphics.frame_count % 20 == 0
          refresh
        end
       
        def refresh
          self.contents.clear
         
          tmp = @text.gsub(/((?:\\n)+)\z/, '')
          y_mod = $1 ? $1.length / 2 : 0
          x_pos = y_mod > 0
          lns = tmp.gsub(/\\t/,'    ').split(/\\n/)
          y = 0
          x = 0
          lns.each_with_index { |ln, ind|
            rect = self.contents.text_size(ln)
            rect.height = self.contents.text_size('a').height
            rect.width += 1 unless ln.index(/[vVAwf\/\\]\z/).nil?
            rect.y = y
            self.contents.draw_text(rect, ln)
            y += rect.height
            x = rect.width
          }
          #p lns if lns.length > 1
          height = self.contents.text_size('a').height
          y -= height unless lns.last.nil?
          y += y_mod * height
          x = (x_pos ? 0 : x + 1)
          self.contents.fill_rect(Rect.new(x, y, 2, height), Color.new(0, 0, 0)) if @cursor
          #@cursor = !@cursor
        end
      end


      if !$BlizzABS && !defined?(RMXOS) && (!$tons_version ||
        !TONS_OF_ADDONS::CUSTOM_CONTROLS)

      #==============================================================================
      # module Input
      #==============================================================================

      module Input
       
        #----------------------------------------------------------------------------
        # Simple ASCII table
        #----------------------------------------------------------------------------
        Key = {'A' => 65, 'B' => 66, 'C' => 67, 'D' => 68, 'E' => 69, 'F' => 70,
               'G' => 71, 'H' => 72, 'I' => 73, 'J' => 74, 'K' => 75, 'L' => 76,
               'M' => 77, 'N' => 78, 'O' => 79, 'P' => 80, 'Q' => 81, 'R' => 82,
               'S' => 83, 'T' => 84, 'U' => 85, 'V' => 86, 'W' => 87, 'X' => 88,
               'Y' => 89, 'Z' => 90,
               '0' => 48, '1' => 49, '2' => 50, '3' => 51, '4' => 52, '5' => 53,
               '6' => 54, '7' => 55, '8' => 56, '9' => 57,
               'NumberPad 0' => 45, 'NumberPad 1' => 35, 'NumberPad 2' => 40,
               'NumberPad 3' => 34, 'NumberPad 4' => 37, 'NumberPad 5' => 12,
               'NumberPad 6' => 39, 'NumberPad 7' => 36, 'NumberPad 8' => 38,
               'NumberPad 9' => 33,
               'F1' => 112, 'F2' => 113, 'F3' => 114, 'F4' => 115, 'F5' => 116,
               'F6' => 117, 'F7' => 118, 'F8' => 119, 'F9' => 120, 'F10' => 121,
               'F11' => 122, 'F12' => 123,
               ';' => 186, '=' => 187, ',' => 188, '-' => 189, '.' => 190, '/' => 220,
               '\\' => 191, '\'' => 222, '[' => 219, ']' => 221, '`' => 192,
               'Backspace' => 8, 'Tab' => 9, 'Enter' => 13, 'Shift' => 16,
               'Left Shift' => 160, 'Right Shift' => 161, 'Left Ctrl' => 162,
               'Right Ctrl' => 163, 'Left Alt' => 164, 'Right Alt' => 165,
               'Ctrl' => 17, 'Alt' => 18, 'Esc' => 27, 'Space' => 32, 'Page Up' => 33,
               'Page Down' => 34, 'End' => 35, 'Home' => 36, 'Insert' => 45,
               'Delete' => 46, 'Arrow Left' => 37, 'Arrow Up' => 38,
               'Arrow Right' => 39, 'Arrow Down' => 40,
               'Mouse Left' => 1, 'Mouse Right' => 2, 'Mouse Middle' => 4,
               'Mouse 4' => 5, 'Mouse 5' => 6}
      #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
      # START Configuration
      #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        UP = [Key['Arrow Up']]
        LEFT = [Key['Arrow Left']]
        DOWN = [Key['Arrow Down']]
        RIGHT = [Key['Arrow Right']]
        A = [Key['Shift']]
        B = [Key['Esc'], Key['NumberPad 0'], Key['X']]
        C = [Key['Space'], Key['Enter'], Key['C']]
        X = [Key['A']]
        Y = [Key['S']]
        Z = [Key['D']]
        L = [Key['Q'], Key['Page Down']]
        R = [Key['W'], Key['Page Up']]
        F5 = [Key['F5']]
        F6 = [Key['F6']]
        F7 = [Key['F7']]
        F8 = [Key['F8']]
        F9 = [Key['F9']]
        SHIFT = [Key['Shift']]
        CTRL = [Key['Ctrl']]
        ALT = [Key['Alt']]
      #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
      # END Configuration
      #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        # All keys
        KEY_COUNT = 256
        ALL_KEYS = (0...KEY_COUNT).to_a
        # Win32 API calls
        GetKeyboardState = Win32API.new('user32', 'GetKeyboardState', 'P', 'I')
        GetKeyboardLayout = Win32API.new('user32', 'GetKeyboardLayout', 'L', 'L')
        MapVirtualKeyEx = Win32API.new('user32', 'MapVirtualKeyEx', 'IIL', 'I')
        ToUnicodeEx = Win32API.new('user32', 'ToUnicodeEx', 'LLPPILL', 'L')
        # some other constants
        DOWN_STATE_MASK = 0x80
        DEAD_KEY_MASK = 0x80000000
        # data
        @state = "\0" * KEY_COUNT
        @triggered = Array.new(KEY_COUNT, false)
        @pressed = Array.new(KEY_COUNT, false)
        @released = Array.new(KEY_COUNT, false)
        @repeatedKey = -1
        @repeatedCount = 0
        #----------------------------------------------------------------------------
        # update
        #  Updates input.
        #----------------------------------------------------------------------------
        def self.update
          # get current language layout
          @language_layout = GetKeyboardLayout.call(0)
          # get new keyboard state
          GetKeyboardState.call(@state)
          # this special code is used because Ruby 1.9.x does not return a char
          # when using String#[] but another String
          key = 0
          @state.each_byte {|byte|
              # if pressed state
              if (byte & DOWN_STATE_MASK) == DOWN_STATE_MASK
                # not released anymore
                @released[key] = false
                # if not pressed yet
                if !@pressed[key]
                  # pressed and triggered
                  @pressed[key] = true
                  @triggered[key] = true
                  @repeatedKey = key
                  @repeatedCount = 0
                else
                  # not triggered anymore
                  @triggered[key] = false
                end
                # update of repeat counter
                if key == @repeatedKey
                  @repeatedCount < 17 ? @repeatedCount += 1 : @repeatedCount = 15
                end
              # not released yet
              elsif !@released[key]
                # if still pressed
                if @pressed[key]
                  # not triggered, pressed or repeated, but released
                  @triggered[key] = false
                  @pressed[key] = false
                  @released[key] = true
                  if key == @repeatedKey
                    @repeatedKey = -1
                    @repeatedCount = 0
                  end
                end
              else
                # not released anymore
                @released[key] = false
              end
              key += 1}
        end
        #----------------------------------------------------------------------------
        # dir4
        #  4 direction check.
        #----------------------------------------------------------------------------
        def self.dir4
          return 2 if self.press?(DOWN)
          return 4 if self.press?(LEFT)
          return 6 if self.press?(RIGHT)
          return 8 if self.press?(UP)
          return 0
        end
        #----------------------------------------------------------------------------
        # dir8
        #  8 direction check.
        #----------------------------------------------------------------------------
        def self.dir8
          down = self.press?(DOWN)
          left = self.press?(LEFT)
          return 1 if down && left
          right = self.press?(RIGHT)
          return 3 if down && right
          up = self.press?(UP)
          return 7 if up && left
          return 9 if up && right
          return 2 if down
          return 4 if left
          return 6 if right
          return 8 if up
          return 0
        end
        #----------------------------------------------------------------------------
        # trigger?
        #  Test if key was triggered once.
        #----------------------------------------------------------------------------
        def self.trigger?(keys)
          keys = [keys] unless keys.is_a?(Array)
          return keys.any? {|key| @triggered[key]}
        end
        #----------------------------------------------------------------------------
        # press?
        #  Test if key is being pressed.
        #----------------------------------------------------------------------------
        def self.press?(keys)
          keys = [keys] unless keys.is_a?(Array)
          return keys.any? {|key| @pressed[key]}
        end
        #----------------------------------------------------------------------------
        # repeat?
        #  Test if key is being pressed for repeating.
        #----------------------------------------------------------------------------
        def self.repeat?(keys)
          keys = [keys] unless keys.is_a?(Array)
          return (@repeatedKey >= 0 && keys.include?(@repeatedKey) &&
              (@repeatedCount == 1 || @repeatedCount == 16))
        end
        #----------------------------------------------------------------------------
        # release?
        #  Test if key was released.
        #----------------------------------------------------------------------------
        def self.release?(keys)
          keys = [keys] unless keys.is_a?(Array)
          return keys.any? {|key| @released[key]}
        end
        #----------------------------------------------------------------------------
        # get_character
        #  vk - virtual key
        #  Gets the character from keyboard input using the input locale identifier
        #  (formerly called keyboard layout handles).
        #----------------------------------------------------------------------------
        def self.get_character(vk)
          # get corresponding character from virtual key
          c = MapVirtualKeyEx.call(vk, 2, @language_layout)
          # stop if character is non-printable and not a dead key
          return '' if c < 32 && (c & DEAD_KEY_MASK != DEAD_KEY_MASK)
          # get scan code
          vsc = MapVirtualKeyEx.call(vk, 0, @language_layout)
          # result string is never longer than 4 bytes (Unicode)
          result = "\0" * 4
          # get input string from Win32 API
          length = ToUnicodeEx.call(vk, vsc, @state, result, 4, 0, @language_layout)
          return (length == 0 ? '' : result)
        end
        #----------------------------------------------------------------------------
        # get_input_string
        #  Gets the string that was entered using the keyboard over the input locale
        #  identifier (formerly called keyboard layout handles).
        #----------------------------------------------------------------------------
        def self.get_input_string
          result = ''
          # check every key
          ALL_KEYS.each {|key|
              # if repeated
              if self.repeat?(key)
                # get character from keyboard state
                c = self.get_character(key)
                # add character if there is a character
                result += c if c != ''
              end}
          # empty if result is empty
          return '' if result == ''
          # convert string from Unicode to UTF-8
          return self.unicode_to_utf8(result)
        end
        #----------------------------------------------------------------------------
        # unicode_to_utf8
        #  string - string in Unicode format
        #  Converts a string from Unicode format to UTF-8 format as RGSS does not
        #  support Unicode.
        #----------------------------------------------------------------------------
        def self.unicode_to_utf8(string)
          result = ''
          # L* format means a bunch of 4-byte wide-chars
          string.unpack('L*').each {|c|
              # characters under 0x80 are 1 byte characters
              if c < 0x0080
                result += c.chr
              # other characters under 0x800 are 2 byte characters
              elsif c < 0x0800
                result += (0xC0 | (c >> 6)).chr
                result += (0x80 | (c & 0x3F)).chr
              # other characters under 0x10000 are 3 byte characters
              elsif c < 0x10000
                result += (0xE0 | (c >> 12)).chr
                result += (0x80 | ((c >> 6) & 0x3F)).chr
                result += (0x80 | (c & 0x3F)).chr
              # other characters under 0x200000 are 4 byte characters
              elsif c < 0x200000
                result += (0xF0 | (c >> 18)).chr
                result += (0x80 | ((c >> 12) & 0x3F)).chr
                result += (0x80 | ((c >> 6) & 0x3F)).chr
                result += (0x80 | (c & 0x3F)).chr
              # other characters under 0x4000000 are 5 byte characters
              elsif c < 0x4000000
                result += (0xF8 | (c >> 24)).chr
                result += (0x80 | ((c >> 18) & 0x3F)).chr
                result += (0x80 | ((c >> 12) & 0x3F)).chr
                result += (0x80 | ((c >> 6) & 0x3F)).chr
                result += (0x80 | (c & 0x3F)).chr
              # other characters under 0x80000000 are 6 byte characters
              elsif c < 0x80000000
                result += (0xFC | (c >> 30)).chr
                result += (0x80 | ((c >> 24) & 0x3F)).chr
                result += (0x80 | ((c >> 18) & 0x3F)).chr
                result += (0x80 | ((c >> 12) & 0x3F)).chr
                result += (0x80 | ((c >> 6) & 0x3F)).chr
                result += (0x80 | (c & 0x3F)).chr
              end}
          return result
        end

      end

      end