mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
779 lines
25 KiB
Lua
779 lines
25 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
--[[-------------------------------------------------------------------------
|
|
My god, look at the time.
|
|
|
|
StormFox2.Time.GetTime(bNearestSecond) [nTime] -- Returns the time number. Between 0 and 1440
|
|
StormFox2.Time.TimeToString(nTime = current time,bUse12Hour) [sTime] -- Returns the time as a string.
|
|
StormFox2.Time.IsDay() [bIsDay] -- Returns true if its day
|
|
StormFox2.Time.IsNight() [bIsNight] -- Returns true if its night
|
|
StormFox2.Time.GetStamp(nTime = current time) [nTimeStamp] -- Returns a timestamp.
|
|
|
|
SERVER
|
|
StormFox2.Time.Set(nTime or string) -- Sets the time. Also supports a string "12:00" or "5:00 AM".
|
|
StormFox2.Time.SetSpeed(nSpeed) -- Sets the timespeed.
|
|
|
|
Hooks:
|
|
StormFox2.Time.Set -- Called when the time gets set.
|
|
StormFox2.Time.NewStamp NewStamp OldStamp -- Callend when the time matches a new stamp
|
|
|
|
BASE_TIME is CurTime + StartTime
|
|
---------------------------------------------------------------------------]]
|
|
|
|
---A number between 0 and 1440. Where 720 is midday and 0 / 1440 is midnight.
|
|
---@class TimeNumber : number
|
|
|
|
local floor,ceil,random = math.floor, math.ceil, math.random
|
|
StormFox2.Time = StormFox2.Time or {}
|
|
-- Settings
|
|
local s_start = StormFox2.Setting.AddSV("start_time",-1,nil, "Time", -1, 1440) -- Sets the starttime
|
|
local s_real = StormFox2.Setting.AddSV("real_time",false,nil, "Time") -- Sets the startime to match OS
|
|
local s_random = StormFox2.Setting.AddSV("random_time",false,nil,"Time") -- Makes the time random
|
|
local s_continue = StormFox2.Setting.AddSV("continue_time",true,nil,"Time"):SetRadioDefault() -- Make the time continue from last
|
|
|
|
s_start:SetRadioAll( s_real, s_random, s_continue )
|
|
|
|
StormFox2.Setting.SetType("start_time","Time_toggle")
|
|
|
|
local day_length = StormFox2.Setting.AddSV("day_length", 12,nil,"Time",-1, 24 * 60 * 7 )
|
|
:SetMenuType("special_float")
|
|
|
|
local night_length = StormFox2.Setting.AddSV("night_length", 12,nil,"Time",-1, 24 * 60 * 7 )
|
|
:SetMenuType("special_float")
|
|
|
|
local sun_rise = StormFox2.Setting.AddSV("sunrise",360,nil, "Time", 0, 1440)
|
|
StormFox2.Setting.SetType("sunrise", "Time")
|
|
local sun_set = StormFox2.Setting.AddSV("sunset",1080,nil, "Time", 0, 1440)
|
|
StormFox2.Setting.SetType("sunset", "Time")
|
|
|
|
--[[
|
|
Pause
|
|
day_length = <= 0
|
|
night_length = <= 0
|
|
Only day
|
|
day_length = > 0
|
|
night_length = < 0
|
|
Only night
|
|
day_length = < 0
|
|
night_length = >= 0
|
|
]]
|
|
|
|
|
|
--[[ ---- EDIT NOTE ----
|
|
x Instead of using Settings directly in UpdateMath. MAke UpdateMath use arguments instead.
|
|
|
|
These settings are send from the server to client on SetTime or join-data.
|
|
|
|
When changing settings on the server, wait a few ticks to set them. Sometimes there are multiple settings being changed at the same time.
|
|
Best to wait a bit.
|
|
|
|
StartTime also got removed .. need to fix that.
|
|
]]
|
|
|
|
-- Returns the total time in minutes for a day
|
|
local BASE_TIME = 0
|
|
--[[
|
|
Calculates the regular time
|
|
cycleTime - The total time it takes for a day to pass
|
|
|
|
Enums to keep me sane
|
|
- finishTime = The finished number between 0 and 1440. This is the ingame time
|
|
- cycleTime = The total seconds it takes for a day to pass
|
|
- dayTime = The total seconds it takes for "day-light" to pass
|
|
- nightTime = The total seconds it takes for a night to pass
|
|
- sunTime = The total of ingame the sun is up
|
|
- nightTime = The total of ingame the sun is down
|
|
- cyclePercentDay= The percent of the day, being day-light (Only with day and night on)
|
|
]]
|
|
-- Math Box to set and get time
|
|
local Get, Set, UpdateMath, isInDay, isDay, dayLength, nightLength, netWriteData
|
|
local GetCache, IsDayCache, CycleCache, FinsihToCycle, GetCycleRaw
|
|
local CR
|
|
do
|
|
local SF_PAUSE = 0
|
|
local SF_NORMAL = 1
|
|
local SF_DAYONLY = 2
|
|
local SF_NIGHTONLY = 3
|
|
local SF_REAL = 4
|
|
|
|
local cycleLength
|
|
local curType -- The time-type
|
|
-- Returns the percent from the given time ( 0 - 1440) between starttime and endtime
|
|
-- Also loops around if from is higer than to
|
|
local function lerp1440( time, from, to )
|
|
if from < to then
|
|
return ( time - from ) / ( to - from )
|
|
elseif time >= from then
|
|
return ( time - from ) / ( 1440 - from + to )
|
|
else
|
|
local ex = 1440 - from
|
|
return ( time + ex ) / ( to + ex )
|
|
end
|
|
end
|
|
local sunTimeUp, nightTimeUp, sunSet, sunRise
|
|
function isInDay( finishTime )
|
|
if not sunRise then return true end -- Not loaded yet
|
|
if sunRise < sunSet then
|
|
return finishTime >= sunRise and finishTime <= sunSet
|
|
end
|
|
return (finishTime >= sunRise and finishTime <= 1440 ) or finishTime <= sunSet
|
|
end
|
|
-- Splits cycletime into dayPercent and nightPercent
|
|
local function CycleToPercent( cycleTime )
|
|
if cycleTime <= dayLength then -- It is day
|
|
return cycleTime / dayLength, nil
|
|
else -- It is night
|
|
return nil, (cycleTime - dayLength) / nightLength
|
|
end
|
|
end
|
|
-- Takes dayPercent or nightPercent and convert it to cycletime
|
|
local function PercentToCycle( dayPercent, nightPercent )
|
|
if dayPercent then
|
|
return dayPercent * dayLength
|
|
else
|
|
return dayLength + nightLength * nightPercent
|
|
end
|
|
end
|
|
-- returns percent of the day that has passed at the given time
|
|
local function finishDayToPercent( finishTime )
|
|
return lerp1440( finishTime, sunRise, sunSet )
|
|
end
|
|
-- returns percent of the night that has passed at the given time
|
|
local function finishNightToPercent( finishTime )
|
|
return lerp1440( finishTime, sunSet, sunRise )
|
|
end
|
|
-- Takes the ingame 0-1440 and converts it to the cycle-area
|
|
function FinsihToCycle( finishTime )
|
|
if isInDay( finishTime ) then -- If day
|
|
return finishDayToPercent( finishTime ) * dayLength
|
|
else
|
|
return dayLength + finishNightToPercent( finishTime ) * nightLength
|
|
end
|
|
end
|
|
local function CycleToFinish( cycle )
|
|
if cycle <= dayLength then -- Day time
|
|
local percent = cycle / dayLength
|
|
return ( sunRise + sunTimeUp * percent ) % 1440
|
|
else -- NightTime
|
|
local percent = ( cycle - dayLength ) / nightLength
|
|
return ( sunSet + nightTimeUp * percent ) % 1440
|
|
end
|
|
end
|
|
-- Get
|
|
local function TimeFromSettings( )
|
|
-- The seconds passed in the day
|
|
local chunk = ((CurTime() - BASE_TIME) % cycleLength)
|
|
return CycleToFinish( chunk )
|
|
end
|
|
local function TimeFromSettings_DAY( )
|
|
local p_chunk = ((CurTime() - BASE_TIME) % cycleLength) / cycleLength
|
|
return (sunRise + p_chunk * sunTimeUp) % 1440
|
|
end
|
|
local function TimeFromSettings_NIGHT( )
|
|
local p_chunk = ((CurTime() - BASE_TIME) % cycleLength) / cycleLength
|
|
return (sunSet + p_chunk * nightTimeUp) % 1440
|
|
end
|
|
local function TimeFromPause()
|
|
return BASE_TIME
|
|
end
|
|
-- Is cheaper than converting things around
|
|
function isDay()
|
|
if not cycleLength then return true end -- Not loaded yet
|
|
if curType == SF_NIGHTONLY then
|
|
return false
|
|
elseif curType == SF_DAYONLY then
|
|
return true
|
|
else
|
|
local l = (CurTime() - BASE_TIME) % cycleLength
|
|
return l <= dayLength
|
|
end
|
|
end
|
|
function Get()
|
|
if not cycleLength then return 720 end -- Not loaded yet
|
|
local num
|
|
if not curType or curType == SF_NORMAL then
|
|
num = TimeFromSettings( )
|
|
GetCache = num
|
|
IsDayCache = isDay()
|
|
elseif curType == SF_REAL then
|
|
num = ( CurTime() / 60 - BASE_TIME ) % 1440
|
|
GetCache = num
|
|
IsDayCache = isInDay( num )
|
|
elseif curType == SF_PAUSE then
|
|
num = TimeFromPause( )
|
|
GetCache = num
|
|
IsDayCache = isInDay( num )
|
|
elseif curType == SF_DAYONLY then
|
|
num = TimeFromSettings_DAY( )
|
|
GetCache = num
|
|
IsDayCache = true
|
|
else
|
|
num = TimeFromSettings_NIGHT( )
|
|
GetCache = num
|
|
IsDayCache = false
|
|
end
|
|
|
|
return num
|
|
end
|
|
function Set( snTime )
|
|
if not curType or curType == SF_NORMAL then
|
|
BASE_TIME = CurTime() - FinsihToCycle( snTime )
|
|
elseif curType == SF_REAL then
|
|
BASE_TIME = CurTime() / 60 - snTime
|
|
elseif curType == SF_PAUSE then
|
|
BASE_TIME = snTime
|
|
-- If you pause the time, we should save it if we got s_continue on.
|
|
if SERVER and StormFox2.Loaded and s_continue:GetValue() then
|
|
cookie.Set("sf2_lasttime", tostring(snTime))
|
|
end
|
|
elseif curType == SF_DAYONLY then
|
|
local p = math.Clamp(lerp1440( snTime, sunRise, sunSet ), 0, 1)
|
|
BASE_TIME = CurTime() - p * dayLength
|
|
elseif curType == SF_NIGHTONLY then
|
|
local p = math.Clamp(lerp1440( snTime, sunSet, sunRise ), 0, 1)
|
|
BASE_TIME = CurTime() - p * nightLength
|
|
end
|
|
GetCache = nil -- Delete time cache
|
|
-- Gets called when the user changes the time, or time variables. Tells scripts to recalculate things.
|
|
if not StormFox2.Loaded then return end
|
|
hook.Run("StormFox2.Time.Changed")
|
|
end
|
|
function UpdateMath(nsTime, blockSetTime)
|
|
local nsTime = nsTime or ( cycleLength and Get() )
|
|
sunSet = sun_set:GetValue()
|
|
sunRise = sun_rise:GetValue()
|
|
dayLength = day_length:GetValue() * 60
|
|
nightLength = night_length:GetValue() * 60
|
|
--print(sunSet)
|
|
--print(sunRise)
|
|
--print(dayLength)
|
|
--print(nightLength)
|
|
if s_real:GetValue() then -- Real time
|
|
cycleLength = 60 * 60 * 24
|
|
curType = SF_REAL
|
|
elseif dayLength <= 0 and nightLength <= 0 or sunSet == sunRise then -- Pause type
|
|
curType = SF_PAUSE
|
|
cycleLength = 0
|
|
elseif nightLength <= 0 then -- Day only
|
|
cycleLength = dayLength
|
|
curType = SF_DAYONLY
|
|
elseif dayLength <= 0 then -- Night only
|
|
cycleLength = nightLength
|
|
curType = SF_NIGHTONLY
|
|
else
|
|
cycleLength = dayLength + nightLength
|
|
curType = SF_NORMAL
|
|
end
|
|
if sunRise < sunSet then
|
|
sunTimeUp = sunSet - sunRise
|
|
else
|
|
sunTimeUp = (1440 - sunRise) + sunSet
|
|
end
|
|
nightTimeUp = 1440 - sunTimeUp
|
|
if not nsTime or blockSetTime then return end -- No valid time currently
|
|
Set( nsTime )
|
|
if SERVER then
|
|
net.Start( StormFox2.Net.Time )
|
|
net.WriteString( tostring( BASE_TIME ) )
|
|
net.Broadcast()
|
|
end
|
|
end
|
|
local function GetDayPercent()
|
|
if not IsDayCache then return -1 end
|
|
local chunk = ((CurTime() - BASE_TIME) % cycleLength)
|
|
return chunk / dayLength
|
|
end
|
|
local function GetNightPercent()
|
|
if IsDayCache then return -1 end
|
|
local chunk = ((CurTime() - BASE_TIME) % cycleLength)
|
|
return (chunk - dayLength) / nightLength
|
|
end
|
|
function GetCycleRaw()
|
|
if not cycleLength then return 0 end -- Not loaded, or pause on launch
|
|
if CR then return CR end
|
|
CR = ((CurTime() - BASE_TIME) % cycleLength)
|
|
return CR
|
|
end
|
|
-- Returns how far the day has progressed 0 = sunRise, 0.5 = sunSet, 1 = sunRise
|
|
function StormFox2.Time.GetCycleTime()
|
|
if CycleCache then return CycleCache end
|
|
if curType == SF_REAL then
|
|
local t = Get()
|
|
if isInDay( t ) then
|
|
CycleCache = lerp1440( t, sunRise, sunSet ) / 2
|
|
else
|
|
CycleCache = 0.5 + lerp1440( t, sunSet, sunRise ) / 2
|
|
end
|
|
return CycleCache
|
|
end
|
|
if curType == SF_PAUSE then -- When paused, use the time to calculate
|
|
if isInDay( BASE_TIME ) then
|
|
CycleCache = lerp1440( BASE_TIME, sunRise, sunSet ) / 2
|
|
else
|
|
CycleCache = 0.5 + lerp1440( BASE_TIME, sunSet, sunRise ) / 2
|
|
end
|
|
return math.Clamp(CycleCache, 0, 1)
|
|
end
|
|
if IsDayCache then
|
|
CycleCache = GetDayPercent() / 2
|
|
return math.Clamp(CycleCache, 0, 1)
|
|
elseif cycleLength then
|
|
CycleCache = GetNightPercent() / 2 + 0.5
|
|
return math.Clamp(CycleCache, 0, 1)
|
|
else -- Idk
|
|
return 0.5
|
|
end
|
|
end
|
|
end
|
|
-- Cache clear. Wait 4 frames to update the time-cache, calculating it for every function is too costly.
|
|
do
|
|
local i = 0
|
|
hook.Add("Think", "StormFox2.Time.ClearCache", function()
|
|
CR = nil
|
|
i = i + 1
|
|
if i >= 2 then
|
|
i = 0
|
|
GetCache = nil
|
|
CycleCache = nil
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- In most cases, multiple settings will update at the same time. Wait a second.
|
|
local function updateTimeSettings( )
|
|
if timer.Exists("SF_SETTIME") then return end
|
|
timer.Create("SF_SETTIME", 0.2, 1, function()
|
|
UpdateMath( nil, CLIENT ) -- If we're the client, then don't update the BASE_TIME
|
|
end)
|
|
end
|
|
-- If any of the settings change, update the math behind it. This will also fix time and update clients if done on server.
|
|
day_length:AddCallback( updateTimeSettings,"SF_TIMEUPDATE")
|
|
night_length:AddCallback( updateTimeSettings,"SF_TIMEUPDATE")
|
|
sun_rise:AddCallback( updateTimeSettings,"SF_TIMEUPDATE")
|
|
sun_set:AddCallback( updateTimeSettings,"SF_TIMEUPDATE")
|
|
s_real:AddCallback( updateTimeSettings,"SF_TIMEUPDATE")
|
|
|
|
-- Make real-time change day and night length
|
|
if SERVER then
|
|
s_real:AddCallback( function( b )
|
|
if not b then return end
|
|
local dt = string.Explode(":",os.date("%H:%M:%S"))
|
|
nsTime = tonumber(dt[1]) * 60 + tonumber(dt[2]) + tonumber(dt[3]) / 60
|
|
StormFox2.Time.Set(nsTime)
|
|
end,"SF_REALTIME_S")
|
|
end
|
|
|
|
|
|
-- Update the math within Get and Set. Will also try and adjust the time
|
|
if SERVER then -- Server controls the time
|
|
local start_time = math.Clamp(cookie.GetNumber("sf2_lasttime",-1) or -1, -1, 1439)
|
|
if s_continue:GetValue() and start_time >= 0 then
|
|
-- Continue time from last
|
|
else
|
|
if s_start:GetValue() >= 0 then -- Start time is on
|
|
start_time = s_start:GetValue()
|
|
elseif s_real:GetValue() then -- Real time
|
|
local dt = string.Explode(":",os.date("%H:%M:%S"))
|
|
start_time = tonumber(dt[1]) * 60 + tonumber(dt[2]) + tonumber(dt[3]) / 60
|
|
else -- if s_random:GetValue() or start_time < 0 then Make it random if all options are invalid
|
|
start_time = math.Rand(0, 1400)
|
|
end
|
|
end
|
|
UpdateMath( start_time, false )
|
|
|
|
---Sets the time. TimeNumber is a number between 0 and 1440.
|
|
---@param nsTime TimeNumber
|
|
---@return boolean success
|
|
---@see TimeNumber
|
|
---@server
|
|
function StormFox2.Time.Set( nsTime )
|
|
if nsTime and type( nsTime ) == "string" then
|
|
nsTime = StormFox2.Time.StringToTime(nsTime)
|
|
end
|
|
if not nsTime then return false end
|
|
Set( nsTime )
|
|
net.Start( StormFox2.Net.Time )
|
|
net.WriteString( tostring( BASE_TIME ) ) -- Sending the current time might add a delay to clients. Better to send the new base.
|
|
net.Broadcast()
|
|
return true
|
|
end
|
|
-- Tell new clients the settings
|
|
hook.Add("StormFox2.data.initspawn", "StormFox2.Time.SendOnJoin", function( ply )
|
|
net.Start( StormFox2.Net.Time )
|
|
net.WriteString( tostring( BASE_TIME ) )
|
|
net.Send( ply )
|
|
end)
|
|
else
|
|
UpdateMath( 720, true ) -- Set the starting time to 720. We don't know any settings yet.
|
|
net.Receive( StormFox2.Net.Time, function(len)
|
|
BASE_TIME = tonumber( net.ReadString() ) or 0
|
|
end)
|
|
end
|
|
|
|
---Returns the current time. TimeNumber is a number between 0 and 1440.
|
|
---@param bNearestSecond boolean
|
|
---@return TimeNumber
|
|
---@shared
|
|
function StormFox2.Time.Get( bNearestSecond )
|
|
if bNearestSecond then
|
|
return math.floor(GetCache and GetCache or Get())
|
|
end
|
|
return GetCache and GetCache or Get()
|
|
end
|
|
|
|
---Returns the current timespeed / 60. Used for internal calculations.
|
|
---@deprecated
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Time.GetSpeed_RAW()
|
|
if not nightLength or StormFox2.Time.IsPaused() then return 0 end
|
|
if IsDayCache then
|
|
return 1 / dayLength
|
|
end
|
|
return 1 / nightLength
|
|
end
|
|
|
|
---Returns the current timespeed. "How many seconds pr real second".
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Time.GetSpeed()
|
|
return StormFox2.Time.GetSpeed_RAW() * 60
|
|
end
|
|
|
|
-- Be able to load time
|
|
local function thinkingBox(sVar) -- Converts string to something useful
|
|
local h,m = string.match(sVar,"(%d?%d):?(%d?%d)")
|
|
local ampm = string.match(sVar,"[ampAMP]+") or ""
|
|
if not h or not m then return end
|
|
if #ampm > 0 then
|
|
if tonumber(h) > 12 then ampm = "" end
|
|
end
|
|
if #ampm < 1 then ampm = "" end
|
|
return h .. ":" .. m .. " " .. ampm
|
|
end
|
|
|
|
---Returns the given time as a number. Supports both "13:00" and "1:00 PM"
|
|
---@param sTime string
|
|
---@return TimeNumber|string
|
|
---@shared
|
|
function StormFox2.Time.StringToTime(sTime)
|
|
sTime = sTime or StormFox2.Time.Get()
|
|
str = thinkingBox(sTime)
|
|
if not str then return end
|
|
local a = string.Explode( ":", str )
|
|
if #a < 2 then return end
|
|
local h,m = string.match(a[1],"%d+"),string.match(a[2],"%d+")
|
|
local ex = string.match(a[2]:lower(),"[amp]+")
|
|
if not h or not m then return end
|
|
h,m = tonumber(h),tonumber(m)
|
|
if ex then
|
|
-- 12clock to 24clock
|
|
if ex == "am" and h == 12 then
|
|
h = h - 12
|
|
end
|
|
if h < 12 and ex == "pm" then
|
|
h = h + 12
|
|
end
|
|
end
|
|
return ( h * 60 + m ) % 1440
|
|
end
|
|
|
|
---A syncronised number used by the client to calculate the time. Use instead StormFox2.Time.Get to get the current time.
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Time.GetBASE_TIME()
|
|
return BASE_TIME
|
|
end
|
|
|
|
---Returns the given or current time in a string format. Will use client setting if bUse12Hour is nil.
|
|
---@param nTime? TimeNumber
|
|
---@param bUse12Hour? boolean
|
|
---@return string
|
|
---@shared
|
|
function StormFox2.Time.TimeToString(nTime,bUse12Hour)
|
|
if CLIENT and bUse12Hour == nil then
|
|
bUse12Hour = StormFox2.Setting.GetCache("12h_display")
|
|
end
|
|
if not nTime then nTime = StormFox2.Time.Get(true) end
|
|
local h = floor(nTime / 60)
|
|
local m = floor(nTime % 60 )
|
|
if not bUse12Hour then return h .. ":" .. (m < 10 and "0" or "") .. m end
|
|
local e = "PM"
|
|
if h < 12 or h == 0 then
|
|
e = "AM"
|
|
end
|
|
if h == 0 then
|
|
h = 12
|
|
elseif h > 12 then
|
|
h = h - 12
|
|
end
|
|
return h .. ":" .. (m < 10 and "0" or "") .. m .. " " .. e
|
|
end
|
|
-- Easy functions
|
|
|
|
---Returns true if the current or given time is doing the day.
|
|
---@param nsTime? TimeNumber
|
|
---@return boolean
|
|
---@shared
|
|
function StormFox2.Time.IsDay( nsTime )
|
|
if not nsTime then -- Cheaper and faster than to convert things around.
|
|
return IsDayCache
|
|
end
|
|
return isInDay( nsTime )
|
|
end
|
|
|
|
---Returns true if the current or given time is doing the night.
|
|
---@param nTime? TimeNumber
|
|
---@return boolean
|
|
---@shared
|
|
function StormFox2.Time.IsNight(nTime)
|
|
return not StormFox2.Time.IsDay(nTime)
|
|
end
|
|
|
|
---Returns true if the current or given time is between FromTime to ToTime.
|
|
-- E.g Dinner = StormFox2.Time.IsBetween(700,740)
|
|
---@param nFromTime TimeNumber
|
|
---@param nToTime TimeNumber
|
|
---@param nCurrentTime? TimeNumber
|
|
---@return boolean
|
|
---@shared
|
|
function StormFox2.Time.IsBetween(nFromTime,nToTime,nCurrentTime)
|
|
if not nCurrentTime then nCurrentTime = StormFox2.Time.Get() end
|
|
if nFromTime > nToTime then
|
|
return nCurrentTime >= nFromTime or nCurrentTime <= nToTime
|
|
end
|
|
return nFromTime <= nCurrentTime and nToTime >= nCurrentTime
|
|
end
|
|
|
|
---Returns the time between Time and Time2 in minutes.
|
|
---@param nTime TimeNumber
|
|
---@param nTime2 TimeNumber
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Time.DeltaTime(nTime,nTime2)
|
|
if nTime2 >= nTime then return nTime2 - nTime end
|
|
return (1440 - nTime) + nTime2
|
|
end
|
|
-- Time stamp
|
|
|
|
---Returns the current (or given time) hour-number. E.g at 11:43 will return 11.
|
|
---@param nTime? TimeNumber
|
|
---@param b12Hour? boolean
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Time.GetHours( nTime, b12Hour )
|
|
if not nTime then nTime = StormFox2.Time.Get() end
|
|
if not b12Hour then return floor( nTime / 60 ) end
|
|
local h = floor( nTime / 60 )
|
|
if h == 0 then
|
|
h = 12
|
|
elseif h > 12 then
|
|
h = h - 12
|
|
end
|
|
return h
|
|
end
|
|
|
|
---Returns the current (or given time) minute-number. E.g at 11:43 will return 43.
|
|
---@param nTime? TimeNumber
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Time.GetMinutes( nTime )
|
|
if not nTime then nTime = StormFox2.Time.Get() end
|
|
return floor( nTime % 60 )
|
|
end
|
|
|
|
---Returns the current (or given time) seconds-number. E.g at 11:43:22 will return 22.
|
|
---@param nTime? TimeNumber
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Time.GetSeconds( nTime )
|
|
if not nTime then nTime = StormFox2.Time.Get() end
|
|
return floor( nTime % 1 ) * 60
|
|
end
|
|
|
|
---Returns the current (or given time) "AM" or "PM" string. E.g 20:00 / 8:00 PM will return "PM".
|
|
---@param nTime? TimeNumber
|
|
---@return string
|
|
---@shared
|
|
function StormFox2.Time.GetAMPM( nTime )
|
|
if not nTime then nTime = StormFox2.Time.Get() end
|
|
local h = floor( nTime / 60 )
|
|
if h < 12 or h == 0 then
|
|
return "AM"
|
|
end
|
|
return "PM"
|
|
end
|
|
--[[
|
|
Allows to pause and resume time
|
|
]]
|
|
local lastT
|
|
-- (Internal) Second argument is nil or a table of the old settings from StormFox2.Time.Pause()
|
|
|
|
---Returns true if the time is paused.
|
|
---@return boolean
|
|
---@shared
|
|
function StormFox2.Time.IsPaused()
|
|
local dl = day_length:GetValue()
|
|
local nl = night_length:GetValue()
|
|
return dl <= 0 and nl <= 0, lastT
|
|
end
|
|
if SERVER then
|
|
---Pauses the time.
|
|
---@server
|
|
function StormFox2.Time.Pause()
|
|
local dl = day_length:GetValue()
|
|
local nl = night_length:GetValue()
|
|
if dl <= 0 and nl <= 0 then return end -- Already paused time
|
|
lastT = { dl, nl }
|
|
day_length:SetValue( 0 )
|
|
night_length:SetValue( 0 )
|
|
end
|
|
|
|
---Resumes the time.
|
|
---@server
|
|
function StormFox2.Time.Resume()
|
|
if not StormFox2.Time.IsPaused() then return end
|
|
if lastT then
|
|
day_length:SetValue( lastT[1] )
|
|
night_length:SetValue( lastT[2] )
|
|
lastT = nil
|
|
else
|
|
day_length:SetValue( 12 )
|
|
night_length:SetValue( 12 )
|
|
end
|
|
end
|
|
end
|
|
---Returns the seconds until we reached the given time.
|
|
---Remember to lisen for the hook: "StormFox2.Time.Changed". In case an admin changes the time / time-settings.
|
|
---@param nTime TimeNumber
|
|
---@return number
|
|
---@shared
|
|
function StormFox2.Time.SecondsUntil( nTime )
|
|
if StormFox2.Time.IsPaused() then return -1 end
|
|
local c_cycleTime = GetCycleRaw() -- Seconds past sunrise
|
|
local t_cycleTime = FinsihToCycle( nTime ) -- Seconds past sunrise to said time
|
|
return ( t_cycleTime - c_cycleTime ) % ( dayLength + nightLength )
|
|
end
|
|
|
|
-- Default Time Display
|
|
if CLIENT then
|
|
-- 12h countries
|
|
local country = system.GetCountry() or "GB"
|
|
local h12_countries = {"GB","IE","US","CA","AU","NZ","IN","PK","BD","MY","MT","EG","MX","PH"}
|
|
--[[United Kingdom, Republic of Ireland, the United States, Canada (sorry Quebec),
|
|
Australia, New Zealand, India, Pakistan, Bangladesh, Malaysia, Malta, Egypt, Mexico and the former American colony of the Philippines
|
|
]]
|
|
local default_12 = table.HasValue(h12_countries, country)
|
|
StormFox2.Setting.AddCL("12h_display",default_12,"Changes how time is displayed.","Time")
|
|
StormFox2.Setting.SetType( "12h_display", {
|
|
[false] = "24h clock",
|
|
[true] = "12h clock"
|
|
} )
|
|
---Returns the current time as a string. Useful for displays.
|
|
---@param nTime? TimeNumber
|
|
---@return string
|
|
---@client
|
|
function StormFox2.Time.GetDisplay(nTime)
|
|
local use_12 = StormFox2.Setting.GetCache("12h_display",default_12)
|
|
return StormFox2.Time.TimeToString(nTime,use_12)
|
|
end
|
|
|
|
-- In case the date changes, call the next-day hook
|
|
hook.Add("StormFox2.data.change","StormFox2.Date.NextDay", function(sKey, zVar, nDelta)
|
|
if sKey == "day" then
|
|
hook.Run("StormFox2.Time.NextDay")
|
|
end
|
|
end)
|
|
else
|
|
local nextDay = -1
|
|
local _b = false
|
|
hook.Add("Think", "StormFox2.Time.NextDayCheck", function()
|
|
if nextDay <= CurTime() then -- Calculate next day
|
|
local sec = StormFox2.Time.SecondsUntil( 1440 )
|
|
if sec == -1 then -- Time is paused, will never be next day
|
|
nextDay = CurTime() + 500
|
|
else
|
|
nextDay = CurTime() + sec
|
|
if _b then
|
|
hook.Run("StormFox2.Time.NextDay")
|
|
end
|
|
_b = true
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- The time and or timespeed changed. Recalculate when the day changes
|
|
hook.Add("StormFox2.Time.Changed", "StormFox2.Time.NextDayCalc", function()
|
|
nextDay = -1
|
|
_b = false
|
|
end)
|
|
|
|
-- We use the date-functions to increase the day
|
|
hook.Add("StormFox2.Time.NextDay", "StormFox2.Data.NextDay", function()
|
|
local nDay = StormFox2.Date.GetYearDay() + 1
|
|
StormFox2.Date.SetYearDay( nDay )
|
|
end)
|
|
|
|
end
|
|
|
|
-- A few hooks
|
|
do
|
|
local last = -1
|
|
local loaded = false
|
|
local function checkDNTrigger()
|
|
if not loaded then return end
|
|
local stamp, mapLight = StormFox2.Sky.GetLastStamp()
|
|
local dN
|
|
if stamp >= SF_SKY_CEVIL then
|
|
dN = 1
|
|
else
|
|
dN = 0
|
|
end
|
|
if last == dN then return end
|
|
last = dN
|
|
if dN == 0 then -- Day
|
|
hook.Run("StormFox2.Time.OnDay")
|
|
else -- Night
|
|
hook.Run("StormFox2.Time.OnNight")
|
|
end
|
|
end
|
|
hook.Add("StormFox2.InitPostEntity", "StormFox2.time.strigger",function()
|
|
timer.Simple(5, function()
|
|
loaded = true
|
|
checkDNTrigger()
|
|
end)
|
|
end)
|
|
-- StormFox2.weather.postchange will be called after something changed. We check the stamp in there.
|
|
hook.Add("StormFox2.weather.postchange", "StormFox2.time.trigger2", checkDNTrigger)
|
|
end
|
|
|
|
--[[
|
|
Make sure to save the time on shutdown, or when we switch to s_continue while pause is on.
|
|
]]
|
|
if SERVER then
|
|
local function onSave()
|
|
cookie.Set("sf2_lasttime", tostring( StormFox2.Time.Get( true ) ) )
|
|
StormFox2.Msg("Saved time.")
|
|
end
|
|
if s_continue:GetValue() then
|
|
hook.Add("ShutDown", "StormFox2.TimeSave",onSave)
|
|
end
|
|
s_continue:AddCallback(function(var)
|
|
if var then
|
|
hook.Add("ShutDown", "StormFox2.TimeSave",onSave)
|
|
if curType == SF_PAUSE then
|
|
cookie.Set("sf2_lasttime", tostring( StormFox2.Time.Get( true ) ) )
|
|
end
|
|
else
|
|
hook.Remove("ShutDown", "StormFox2.TimeSave",onSave)
|
|
end
|
|
end, "sf2_savetime")
|
|
end |