library TimeTravel initializer Init
/***********************************************************************
The function of this library is to provide a way to reverse the map (or single units) back to a previous time.
This means that you should be able to set everything in a map back to where it was x seconds ago.
It should then move everything in the map (or specified thing) back to said time.
Functions:
TimeTravel_GoBack(real time) This reverses the entire map to a point in time.
TimeTravel_UnitGoBack(unit, real howFar) This will set a unit to a point in time.
TimeTravel_RegisterUnit(unit)
NOTE: The times in the functions depend upon on the srtting SECONDS_PER_UPDATE. The system will round the times
specified to some multiple of SECONDS_PER_UPDATE.
NOTE: Some settings of units are not able to be set without a great deal of work, which this library is not
prepared to deal with. This means that cooldowns, tinting, scaling and such of units will *not* be changed.
Enjoy.
***********************************************************************/
#define private SECONDS_PER_UPDATE = 0.5
#define private MAX_SECONDS_TRACKED = 1000
//You probably shouldn't edit below here unless you know what you're doing.
#include "cj_types_priv.j"
#define private StringHashU(string) = StringHash(string + I2S(Updates))
#define private StringHashT(string, time) = StringHash(string + I2S(time))
private timer UpdateTimer
private int Updates = 0
private int UpdatesTotal = 0
private hashtable Hash
private group TrackedUnits
private int TempNum
private function Error takes string s returns nothing
BJDebugMsg("|cffff0000" + SCOPE_PREFIX + " Error:|r " + s)
endfunction
function IsUnitDead takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_DEAD) or GetUnitTypeId(u) == 0
endfunction
private function SaveUnit takes unit u returns nothing
int id = GetHandleId(u)
SaveReal(Hash, id, StringHashU("x"), GetUnitX(u))
SaveReal(Hash, id, StringHashU("y"), GetUnitY(u))
SaveReal(Hash, id, StringHashU("hp"), GetUnitState(u, UNIT_STATE_LIFE))
SaveReal(Hash, id, StringHashU("mana"), GetUnitState(u, UNIT_STATE_MANA))
SaveBoolean(Hash, id, StringHashU("alive"), not IsUnitDead(u))
endfunction
public function UnitGoTo takes unit u, int when returns void
int id = GetHandleId(u)
int id2
unit u2
int i = 0
if not LoadBoolean(Hash, id, StringHashT("alive", when)) then
RemoveUnit(u)
else
if IsUnitDead(u) then
if not IsHeroUnitId(GetUnitTypeId(u)) then
GroupRemoveUnit(TrackedUnits, u)
u2 = CreateUnit(GetOwningPlayer(u), GetUnitTypeId(u), 0, 0, 0)
id2 = GetHandleId(u2)
loop
exitwhen i == MAX_SECONDS_TRACKED
SaveReal(Hash, id2, StringHashT("x", i), LoadReal(Hash, id, StringHashT("x", i)))
SaveReal(Hash, id2, StringHashT("y", i), LoadReal(Hash, id, StringHashT("y", i)))
SaveReal(Hash, id2, StringHashT("hp", i), LoadReal(Hash, id, StringHashT("hp", i)))
SaveReal(Hash, id2, StringHashT("mana", i), LoadReal(Hash, id, StringHashT("mana", i)))
SaveBoolean(Hash, id2, StringHashT("alive", i), LoadBoolean(Hash, id, StringHashT("alive", i)))
i++
endloop
FlushChildHashtable(Hash, id)
RemoveUnit(u)
u = u2
id = id2
GroupAddUnit(TrackedUnits, u)
else
ReviveHero(u, 0, 0, false)
endif
endif
endif
SetUnitX(u, LoadReal(Hash, id, StringHashT("x", when)))
SetUnitY(u, LoadReal(Hash, id, StringHashT("y", when)))
SetUnitState(u, UNIT_STATE_LIFE, LoadReal(Hash, id, StringHashT("hp", when)))
SetUnitState(u, UNIT_STATE_MANA, LoadReal(Hash, id, StringHashT("mana", when)))
endfunction
private function ConvertTime takes real time returns int
int updates
if time / SECONDS_PER_UPDATE > UpdatesTotal then
debug Error("Attempted to go back to a time before tracking began.")
time = Updates * SECONDS_PER_UPDATE
endif
updates = Updates - R2I(time / SECONDS_PER_UPDATE)
if updates < 0 then
updates += MAX_SECONDS_TRACKED
endif
if updates < 0 then
debug Error("Attempted to go back farther than MAX_SECONDS_TRACKED. Errors are going to occur. Thread halted.")
loop
TriggerSleepAction(999999)
endloop
endif
return updates
endfunction
public function UnitGoBack takes unit u, real howFar returns void
UnitGoTo(u, ConvertTime(howFar))
endfunction
private function UnitGoBackEnum takes void returns void
UnitGoTo(GetEnumUnit(), TempNum)
endfunction
public function GoBack takes real howFar returns void
TempNum = ConvertTime(howFar)
ForGroup(TrackedUnits, function UnitGoBackEnum)
Updates = TempNum
UpdatesTotal = R2I(UpdatesTotal - (howFar / SECONDS_PER_UPDATE))
if UpdatesTotal < 0 then
UpdatesTotal = 0
endif
endfunction
public function RegisterUnit takes unit u returns nothing
GroupAddUnit(TrackedUnits, u)
SaveUnit(u)
endfunction
private function UpdateUnitEnum takes nothing returns nothing
SaveUnit(GetEnumUnit())
endfunction
private function Update takes nothing returns nothing
Updates++
UpdatesTotal++
if Updates * SECONDS_PER_UPDATE == MAX_SECONDS_TRACKED then
Updates = 0
endif
ForGroup(TrackedUnits, function UpdateUnitEnum)
endfunction
private function Init takes void returns void
TrackedUnits = CreateGroup()
UpdateTimer = CreateTimer()
Hash = InitHashtable()
TimerStart(UpdateTimer, SECONDS_PER_UPDATE, true, function Update)
endfunction
endlibrary