- Joined
- Jan 9, 2019
- Messages
- 102
JASS:
library Timeline requires Alloc
//== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
// _____________
// # Timeline
// v2.0a, by Overfrost
// ----------------------------
//
// - keeps track of elapsed game-time, allowing easy retrieval of it
//
// - separates the tracked time into 4 variables
// (hours, minutes, current seconds, total seconds)
//
// - can also retrieve the time as a generally-formatted string
//
// - has a readonly global instance that tracks the timeline of the game
//
// - instances can only track time from the moment of their creation
// or from each time they are restarted
//
// - can return time-difference values by comparing current time
// and previously marked time
//
// ______________
// # Requires:
//
// - Alloc (Best)
// github.com/nestharus/JASS/tree/master/jass/Systems/Alloc/Standard
//
//== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
//! novjass
//
struct Timeline extends array
//-------------
// Game-clock
//
readonly static integer game.hours
readonly static integer game.minutes
readonly static real game.seconds // current seconds, 0 to ~59.99
readonly static real game.elapsed // total seconds
//
static method game.getString takes string separator returns string
// - returns hours, minutes, and (int)seconds as one formatted string
// - the format is (H:MM:SS) if (hours > 0) or (M:SS) otherwise, showing 0 minutes
// - spaces are not included as default separator
//
//-------------
// Instancers
//
static method create takes nothing returns thistype
//
method lock takes nothing returns nothing
method unlock takes nothing returns boolean
// - .unlock replaces destroy, returns true if it destroys
//
//-----------------
// Instance-clock
//
readonly integer hours
readonly integer minutes
readonly real seconds // current seconds, 0 to ~59.99
readonly real elapsed // total seconds
//
method getString takes string separator returns string
// - all of these work the same way as the ones in game-clock,
// but they only count any elapsed time since the instance was created
//
//--------------------
// Additional Fields
//
readonly real start
// - elapsed game-time when this Timeline was created
//
real length = 0
// - affects the return value of .remaining
//
readonly real remaining
// - remaining game-time until this Timeline reaches the end of .length
// - a negative value means it has passed its end by that many seconds
// - a Timeline can never stop, so this negative value will continue to drop
//
readonly real delta
// - returns the game-time difference of current elapsed game-time and
// current delta-marker, then move the marker to current game-time
// - on Timeline creation, delta-marker is set to .start
// - if .delta would return 0, it returns the previous non-0 .delta instead
//
//---------------------
// Additional Methods
//
method restart takes nothing returns thistype(this)
// - sets .start to current elapsed game-time
// - moves delta-marker to current game-time and sets all previous .delta to 0
//
method lengthen takes real seconds returns thistype(this)
// - increases length by seconds
//
//! endnovjass
//== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
//
private function pgPad2 takes integer pInt returns string
if (pInt > 9) then
return I2S(pInt)
endif
return "0" + I2S(pInt)
endfunction
//
private module pm
private static method onInit takes nothing returns nothing
call pgInit()
endmethod
endmodule
private struct ps extends array
//
private static timer pgTimer = CreateTimer()
//--------------------------
// hours, minutes, seconds
readonly static integer hours = 0
readonly static integer minutes = 0
//
static method operator seconds takes nothing returns real
return TimerGetElapsed(pgTimer)
endmethod
//----------------
// total seconds
private static integer pgSeconds = 0
//
static method operator elapsed takes nothing returns real
return pgSeconds + seconds
endmethod
//-------------------
// formatted string
static method getString takes string aSep returns string
if (hours > 0) then
return I2S(hours) + aSep /*
*/ + pgPad2(minutes) + aSep /*
*/ + pgPad2(R2I(seconds))
endif
return I2S(minutes) + aSep + pgPad2(R2I(seconds))
endmethod
//
private static method pgOnExpire takes nothing returns nothing
set minutes = minutes + 1
set pgSeconds = pgSeconds + 60
//
if (minutes == 60) then
set minutes = 0
set hours = hours + 1
endif
endmethod
private static method pgInit takes nothing returns nothing
call TimerStart(pgTimer, 60, true, function thistype.pgOnExpire)
endmethod
implement pm
endstruct
struct Timeline extends array
implement Alloc
//
static method operator game takes nothing returns ps
return 0
endmethod
//
private integer pLock
//---------
// fields
readonly real start
real length
//
private real pMark
private real pDelta
//
static method create takes nothing returns thistype
local thistype this = allocate()
set pLock = 0
//
set start = game.elapsed
set length = 0
//
set pMark = start
set pDelta = 0
//
return this
endmethod
//------------------
// time difference
method operator elapsed takes nothing returns real
return game.elapsed - start
endmethod
method operator remaining takes nothing returns real
return start + length - game.elapsed
endmethod
//--------
// delta
method operator delta takes nothing returns real
local real lNow = game.elapsed
if ((lNow - pMark) > 0) then
set pDelta = lNow - pMark
set pMark = lNow
endif
//
return pDelta
endmethod
//--------
// clock
method operator hours takes nothing returns integer
return R2I(elapsed*.000277778) // 2.77e-4 = 1/3600
endmethod
method operator minutes takes nothing returns integer
local integer lTotal = R2I(elapsed*.016666667) // 1.66e-2 = 1/60
//
return lTotal - (lTotal/60)*60
endmethod
method operator seconds takes nothing returns real
local real lTotal = elapsed
//
return lTotal - R2I(lTotal*.016666667)*60
endmethod
//
method getString takes string aSep returns string
local integer lTotal = R2I(elapsed)
local integer lHours = lTotal/3600
local integer lMinutes = lTotal/60 - lHours*60
//
if (lHours > 0) then
return I2S(lHours) + aSep /*
*/ + pgPad2(lMinutes) + aSep /*
*/ + pgPad2(lTotal - (lTotal/60)*60)
endif
return I2S(lMinutes) + aSep + pgPad2(lTotal - (lTotal/60)*60)
endmethod
//------------
// assigners
method restart takes nothing returns thistype
set start = game.elapsed
//
set pMark = start
set pDelta = 0
//
return this
endmethod
//
method lengthen takes real aLength returns thistype
set length = length + aLength
//
return this
endmethod
//
method lock takes nothing returns nothing
set pLock = pLock + 1
endmethod
method unlock takes nothing returns boolean
set pLock = pLock - 1
if (pLock < 0) then
call deallocate()
return true
endif
return false
endmethod
endstruct
endlibrary
JASS:
//
function GetTimeline takes real aLength returns Timeline
return Timeline.create().lengthen(aLength)
// works because .lengthen returns this
endfunction
//
function GetReformattedTime takes nothing returns string
if (Timeline.game.hours == 0 and Timeline.game.minutes > 9) then
return "0" + Timeline.game.getString(":")
endif
return Timeline.game.getString(":")
endfunction
// reformat the generic format to (H:MM:SS)/(MM:SS)
// quick reminder, the generic format is (H:MM:SS)/(M:SS), notice the single M
//
function Update takes Timeline aTime, unit aU, real aVel, real aAcc returns nothing
local real lReal = aVel + aAcc*(aTime.elapsed - aTime.delta)
// from linear motion equation: v = v0 + a*t
// gets the v0 of a motion from t(0) to t(delta)
set lReal = lReal*aTime.delta + 0.5*aAcc*aTime.delta*aTime.delta
// gets the displacement of the delta-motion
//
call SetUnitX(aU, GetUnitX(aU) + lReal)
call SetUnitY(aU, GetUnitY(aU) + lReal)
endfunction
// I did test this weird function and it works as intended
Changelog:
- v2.0a:
- Renamed the library to Timeline.
- Moved access of GameTime to Timeline.game.
- Added hours, minutes, seconds, and getString to regular instances.- v1.2a: Added restart.
- v1.1a: Added getString.
Last edited: