#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# 进阶版时间与天气系统
# 黑暗骑士◎汉化修改
# 版本号 : 1.02
# 制作日期: 20.3.2015
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# 脚本冲突率:
# 经测试,本脚本与99%的其他脚本能够兼容!但是修改了资料,存档就不可以再用了。
# 这点请注意。
#
# 特性:
#
# - 容易操纵和控制时间以及天气
# - 可定制的日夜的色调
# - 可选HUD时钟
# - 更容易控制、比DDNS更强大
#
# 使用说明:
# 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(MINUTE, HOUR, DAY, MONTH, YEAR)
# This will make the time advanced by the specified values.
#
# 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.
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
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 = 144
# 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 = [['细雨', 0, 1..4, [1], ['005-Rain01', 65..80, 100], [], []],
['雨天', 0, 5..8, [1], ['006-Rain02', 75..90, 100], [], ['061-Thunderclap01', 60..85, 100, 0.07, 4, [255, 255, 255]]],
['暴风', 1, 9..10, [1], ['007-Rain03', 80..100, 100], [], ['061-Thunderclap01', 70..95, 110, 0.08, 6, [255, 255, 255]]],
['多风', 0, 1..1, [], [], ['002-Clouds01', 60, 0, 200, 4, 3, [0, 0, 0, 0]], []],
['雨天', 0, 1..4, [2], ['006-Rain02', 70..85, 100], [], ['061-Thunderclap01', 65..90, 110, 0.08, 6, [255, 255, 255]]],
['暴风', 1, 5..8, [2], ['007-Rain03', 75..90, 100], [], ['061-Thunderclap01', 70..95, 110, 0.09, 7, [255, 255, 255]]],
['暴风', 2, 9..10, [2], ['007-Rain03', 90..100, 100], [], ['061-Thunderclap01', 85..100, 110, 0.11, 7, [255, 255, 255]]],
['小雪', 1, 1..4, [3], ['002-Wind02', 70..85, 100], [], []],
['大雪', 1, 5..8, [3], ['003-Wind03', 80..95, 100], [], []],
['暴雪', 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 = '晴天'
# 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 = [
['春', 22, 3, 0..25, 0.003, 0.3, 0.05, [0, 1, 2, 3, 4, 5]] ,
['夏', 21, 6, 20..35, 0.003, 0.1, 0.2, [0, 1, 3, 4, 5, 6]] ,
['秋', 20, 9, 0..25, 0.003, 0.2, 0.1, [0, 2, 3, 4, 5, 7]] ,
['冬', 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 = 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 = [
["圣诞节", 0, 11, 24],
["新年", 0, 0, 0],
["感恩节", 1, 10, 4, 4],
["情人节", 0, 1, 13],
["地球日", 0, 3, 21],
["植树节", 1, 3, 5, -1],
["母亲节", 1, 2, 7, 2],
["父亲节", 1, 5, 7, 3],
["万圣节", 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', '%d/%m/%Y', '%A', '%w']
# the width of the clock
CWIDTH = 180
# names of your days, automatically sets up a week's length
WEEKDAYS = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五',
'星期六']
WEEKDAY_ABBREVIATIONS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
# names of your months, automatically sets up a year's length
MONTHS = ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
'八月', '九月', '十月', '十一月', '十二月']
# 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 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[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[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)
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
$game_system.ates.current_times = $game_system.ates.setup_times if 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 [email]0...@current_times.length[/email]
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
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
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[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][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[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
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
if @frame_count % (ATES::LENGTH / 36) == 0
tmp = @time.day
ATES.advance(1, 0, 0, 0, 0)
if @time.day != tmp
@holiday = get_holiday(@time.mon, @time.day, @time.wday)
end
@weather.update
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[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
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