////////////////////////////////////////////////////////
//Guhun's MUI Engine version 2.0.0
////////////////////////////////////////////////////////
//This code generates an instance number for a RecycleKey
function GMUI_GetIndex takes integer RecycleKey returns integer
local integer instance
set instance = LoadInteger(udg_GMUI_Hashtable, RecycleKey, 0)
if not HaveSavedInteger(udg_GMUI_Hashtable, RecycleKey, instance) then
call SaveInteger(udg_GMUI_Hashtable, RecycleKey, 0, instance + 1)
else
call SaveInteger(udg_GMUI_Hashtable, RecycleKey, 0, LoadInteger(udg_GMUI_Hashtable, RecycleKey, instance))
call RemoveSavedInteger(udg_GMUI_Hashtable, RecycleKey, instance)
endif
return instance
endfunction
//This code generates recycles a used instance number for a RecycleKey
function GMUI_RecycleIndex takes integer RecycleKey, integer instance returns nothing
call SaveInteger(udg_GMUI_Hashtable, RecycleKey, instance, LoadInteger(udg_GMUI_Hashtable, RecycleKey, 0))
call SaveInteger(udg_GMUI_Hashtable, RecycleKey, 0, instance)
endfunction
//This code generates a new, unused, RecycleKey
function GMUI_CreateRecycleKey takes nothing returns integer
local integer newKey = GMUI_GetIndex(0)
call SaveInteger(udg_GMUI_Hashtable, newKey, 0, 1)
return newKey
endfunction
//This code recycles a used RecycleKey
function GMUI_DestroyRecycleKey takes integer whichKey returns nothing
if whichKey == 0 then
return
endif
call GMUI_RecycleIndex(0, whichKey)
call FlushChildHashtable(udg_GMUI_Hashtable, whichKey)
endfunction
//This function initializes GMUI if it has not yet been initialized
function GMUI_Initialize takes nothing returns nothing
if udg_GMUI_Hashtable == null then
//Initialize Hashtable
set udg_GMUI_Hashtable = InitHashtable()
//Initialize the recycling algorithm for Recycle Keys
call SaveInteger(udg_GMUI_Hashtable, 0, 0, 1)
//Initialize the generic Recycle Key
call GMUI_CreateRecycleKey() //Will always be 1
endif
endfunction
////////////////////////////////////////////////////////
//End of MUI Engine
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
//Guhun's Linked Lists v.1.1.0
////////////////////////////////////////////////////////
//Returns the next element after the specified "data" in the list
//To get the first element, pass "0" as the parameter "data"
function GLL_GetNext takes integer listKey, integer data returns integer
return LoadInteger(udg_Lists_Hashtable, listKey, data)
endfunction
//Returns the element that preceeds the specified "data" in the list
//To get the last element, pass "0" as the parameter "data"
function GLL_GetPrev takes integer listKey, integer data returns integer
return LoadInteger(udg_Lists_Hashtable, -listKey, data)
endfunction
//Returns wether a list contains the specified data or not
function GLL_ListHasData takes integer listKey, integer data returns boolean
return HaveSavedInteger(udg_Lists_Hashtable, listKey, data)
endfunction
//Adds data to a list
//If data is already present in list, behaviour is undefined
function GLL_AddData takes integer listKey, integer next, integer data returns nothing
local integer prev = LoadInteger(udg_Lists_Hashtable, -listKey, next)
call SaveInteger(udg_Lists_Hashtable, listKey, prev, data)
call SaveInteger(udg_Lists_Hashtable, -listKey, next, data)
call SaveInteger(udg_Lists_Hashtable, listKey, data, next)
call SaveInteger(udg_Lists_Hashtable, -listKey, data, prev)
endfunction
//Removes the given Data from a list
//If data is not present in List, behaviour is undefined
function GLL_RemoveData takes integer listKey, integer data returns nothing
local integer next = LoadInteger(udg_Lists_Hashtable, listKey, data)
local integer prev = LoadInteger(udg_Lists_Hashtable, -listKey, data)
call SaveInteger(udg_Lists_Hashtable, -listKey, next, prev)
call SaveInteger(udg_Lists_Hashtable, listKey, prev, next)
call RemoveSavedInteger(udg_Lists_Hashtable, listKey, data)
call RemoveSavedInteger(udg_Lists_Hashtable, -listKey, data)
endfunction
//Creates a new list and returns its ID/key
function GLL_CreateList takes nothing returns integer
local integer listId = GMUI_GetIndex(udg_Lists_RECYCLE_KEY)
call SaveInteger(udg_Lists_Hashtable, listId, 0, 0)
call SaveInteger(udg_Lists_Hashtable, -listId, 0, 0)
return listId
endfunction
//Destroys the specified list
function GLL_DestroyList takes integer listId returns nothing
call FlushChildHashtable(udg_Lists_Hashtable, listId)
call FlushChildHashtable(udg_Lists_Hashtable, -listId)
call GMUI_RecycleIndex(udg_Lists_RECYCLE_KEY, listId)
endfunction
//This function loops through a List and executes a trigger for each element, setting the list variables to their relevant equivalents each time
function GLL_Loop takes integer listKey, trigger trig, integer until returns nothing
local integer data = LoadInteger(udg_Lists_Hashtable, listKey, 0)
local integer count = 0
loop
exitwhen data == 0 or count == until
set udg_Lists_Data= data
set udg_Lists_ListID = listKey
set data = LoadInteger(udg_Lists_Hashtable, listKey, data)
if IsTriggerEnabled(trig) and TriggerEvaluate(trig) then
call TriggerExecute(trig)
endif
set count = count + 1
endloop
endfunction
//Same as GLL_Loop, however, you may specify a code that will run in a ForPlayer loop instead of a trigger
//Added in version 1.1.0
function GLL_CodeLoop takes integer listKey, code func, integer until returns nothing
local integer data = LoadInteger(udg_Lists_Hashtable, listKey, 0)
local integer count = 0
loop
exitwhen data == 0 or count == until
set udg_Lists_Data= data
set udg_Lists_ListID = listKey
set data = LoadInteger(udg_Lists_Hashtable, listKey, data)
call ForForce(bj_FORCE_PLAYER[0], func)
set count = count + 1
endloop
endfunction
//Loops over a list from the value following "start" to the value preceding "finish" (or 0, whichever comes first)
//Each iteration sets Lists_Data to the current value and then runs the specified code in a ForPlayer loop
//If you specify a negative listKey, the loop will execute backwards
//Added in version 1.1.0
function GLL_ClearList takes integer listKey, integer start, integer finish, code func returns integer
local integer data = LoadInteger(udg_Lists_Hashtable, listKey, start)
local integer nextData
local integer countRemoved = 0
loop
exitwhen data == finish or data == 0
set nextData = LoadInteger(udg_Lists_Hashtable, listKey, data)
call RemoveSavedInteger(udg_Lists_Hashtable, listKey, data)
call RemoveSavedInteger(udg_Lists_Hashtable, -listKey, data)
set udg_Lists_Data = data
call ForForce(bj_FORCE_PLAYER[0], func)
set data = nextData
set countRemoved = countRemoved + 1
endloop
call SaveInteger(udg_Lists_Hashtable, -listKey, data, start)
call SaveInteger(udg_Lists_Hashtable, listKey, start, data)
return countRemoved
endfunction
//This function initializes GLL if it has not yet been initialized
function GLL_Initialize takes nothing returns nothing
if udg_Lists_Hashtable == null then
//Initialize dependencies
call GMUI_Initialize()
//Initialize Hashtable
set udg_Lists_Hashtable = InitHashtable()
//Get Recycle Key
set udg_Lists_RECYCLE_KEY = GMUI_CreateRecycleKey()
endif
endfunction
////////////////////////////////////////////////////////
//End of Linked Lists
////////////////////////////////////////////////////////
Name | Type | is_array | initial_value |
GMUI_Hashtable | hashtable | No | |
GMUI_Index | integer | No | |
GMUI_RecycleKey | integer | No | |
Lists_Data | integer | No | |
Lists_Hashtable | hashtable | No | |
Lists_Instance | integer | No | |
Lists_ListID | integer | No | |
Lists_LoopUntil | integer | No | |
Lists_RECYCLE_KEY | integer | No | |
Lists_Trigger | trigger | No | |
Test_DestroyList | integer | No | |
Test_EscTimer | timer | No | |
Test_Footman_Array | unit | Yes | |
Test_GIOL_DestroyList | integer | No | |
Test_GIUL_DestroyList | integer | No | |
Test_GLL_DestroyList | integer | No | |
Test_Indexer_Footman | integer | No | |
Test_Indexer_Knight | integer | No | |
Test_Indexer_Rifleman | integer | No | |
Test_Knight_Array | unit | Yes | |
Test_Rifleman_Array | unit | Yes | |
Wayback_Hashtable | hashtable | No | |
Wayback_Precision | real | No | |
Wayback_Time | real | No | |
Wayback_Unit | unit | No |
////////////////////////////////////////////////////////
//Guhun's MUI Engine version 2.0.0
////////////////////////////////////////////////////////
//This code generates an instance number for a RecycleKey
function GMUI_GetIndex takes integer RecycleKey returns integer
local integer instance
set instance = LoadInteger(udg_GMUI_Hashtable, RecycleKey, 0)
if not HaveSavedInteger(udg_GMUI_Hashtable, RecycleKey, instance) then
call SaveInteger(udg_GMUI_Hashtable, RecycleKey, 0, instance + 1)
else
call SaveInteger(udg_GMUI_Hashtable, RecycleKey, 0, LoadInteger(udg_GMUI_Hashtable, RecycleKey, instance))
call RemoveSavedInteger(udg_GMUI_Hashtable, RecycleKey, instance)
endif
return instance
endfunction
//This code generates recycles a used instance number for a RecycleKey
function GMUI_RecycleIndex takes integer RecycleKey, integer instance returns nothing
call SaveInteger(udg_GMUI_Hashtable, RecycleKey, instance, LoadInteger(udg_GMUI_Hashtable, RecycleKey, 0))
call SaveInteger(udg_GMUI_Hashtable, RecycleKey, 0, instance)
endfunction
//This code generates a new, unused, RecycleKey
function GMUI_CreateRecycleKey takes nothing returns integer
local integer newKey = GMUI_GetIndex(0)
call SaveInteger(udg_GMUI_Hashtable, newKey, 0, 1)
return newKey
endfunction
//This code recycles a used RecycleKey
function GMUI_DestroyRecycleKey takes integer whichKey returns nothing
if whichKey == 0 then
return
endif
call GMUI_RecycleIndex(0, whichKey)
call FlushChildHashtable(udg_GMUI_Hashtable, whichKey)
endfunction
//This function initializes GMUI if it has not yet been initialized
function GMUI_Initialize takes nothing returns nothing
if udg_GMUI_Hashtable == null then
//Initialize Hashtable
set udg_GMUI_Hashtable = InitHashtable()
//Initialize the recycling algorithm for Recycle Keys
call SaveInteger(udg_GMUI_Hashtable, 0, 0, 1)
//Initialize the generic Recycle Key
call GMUI_CreateRecycleKey() //Will always be 1
endif
endfunction
////////////////////////////////////////////////////////
//End of MUI Engine
////////////////////////////////////////////////////////
function Trig_GMUI_Main_Actions takes nothing returns nothing
if udg_GMUI_RecycleKey == 0 then
set udg_GMUI_RecycleKey = GMUI_CreateRecycleKey()
else
call GMUI_DestroyRecycleKey(udg_GMUI_RecycleKey)
endif
endfunction
function Trig_GMUI_Main_Conditions takes nothing returns boolean
if udg_GMUI_Index == 0 then
set udg_GMUI_Index = GMUI_GetIndex(udg_GMUI_RecycleKey)
else
call GMUI_RecycleIndex(udg_GMUI_RecycleKey, udg_GMUI_Index)
endif
return false
endfunction
//===========================================================================
function InitTrig_GMUI_Main takes nothing returns nothing
call GMUI_Initialize()
//Create Trigger for GUI users
set gg_trg_GMUI_Main = CreateTrigger( )
call TriggerAddAction( gg_trg_GMUI_Main, function Trig_GMUI_Main_Actions )
call TriggerAddCondition(gg_trg_GMUI_Main, Condition(function Trig_GMUI_Main_Conditions))
endfunction
////////////////////////////////////////////////////////
//Guhun's Linked Lists v.1.1.0
////////////////////////////////////////////////////////
//Returns the next element after the specified "data" in the list
//To get the first element, pass "0" as the parameter "data"
function GLL_GetNext takes integer listKey, integer data returns integer
return LoadInteger(udg_Lists_Hashtable, listKey, data)
endfunction
//Returns the element that preceeds the specified "data" in the list
//To get the last element, pass "0" as the parameter "data"
function GLL_GetPrev takes integer listKey, integer data returns integer
return LoadInteger(udg_Lists_Hashtable, -listKey, data)
endfunction
//Returns wether a list contains the specified data or not
function GLL_ListHasData takes integer listKey, integer data returns boolean
return HaveSavedInteger(udg_Lists_Hashtable, listKey, data)
endfunction
//Adds data to a list
//If data is already present in list, behaviour is undefined
function GLL_AddData takes integer listKey, integer next, integer data returns nothing
local integer prev = LoadInteger(udg_Lists_Hashtable, -listKey, next)
call SaveInteger(udg_Lists_Hashtable, listKey, prev, data)
call SaveInteger(udg_Lists_Hashtable, -listKey, next, data)
call SaveInteger(udg_Lists_Hashtable, listKey, data, next)
call SaveInteger(udg_Lists_Hashtable, -listKey, data, prev)
endfunction
//Removes the given Data from a list
//If data is not present in List, behaviour is undefined
function GLL_RemoveData takes integer listKey, integer data returns nothing
local integer next = LoadInteger(udg_Lists_Hashtable, listKey, data)
local integer prev = LoadInteger(udg_Lists_Hashtable, -listKey, data)
call SaveInteger(udg_Lists_Hashtable, -listKey, next, prev)
call SaveInteger(udg_Lists_Hashtable, listKey, prev, next)
call RemoveSavedInteger(udg_Lists_Hashtable, listKey, data)
call RemoveSavedInteger(udg_Lists_Hashtable, -listKey, data)
endfunction
//Creates a new list and returns its ID/key
function GLL_CreateList takes nothing returns integer
local integer listId = GMUI_GetIndex(udg_Lists_RECYCLE_KEY)
call SaveInteger(udg_Lists_Hashtable, listId, 0, 0)
call SaveInteger(udg_Lists_Hashtable, -listId, 0, 0)
return listId
endfunction
//Destroys the specified list
function GLL_DestroyList takes integer listId returns nothing
call FlushChildHashtable(udg_Lists_Hashtable, listId)
call FlushChildHashtable(udg_Lists_Hashtable, -listId)
call GMUI_RecycleIndex(udg_Lists_RECYCLE_KEY, listId)
endfunction
//This function loops through a List and executes a trigger for each element, setting the list variables to their relevant equivalents each time
function GLL_Loop takes integer listKey, trigger trig, integer until returns nothing
local integer data = LoadInteger(udg_Lists_Hashtable, listKey, 0)
local integer count = 0
loop
exitwhen data == 0 or count == until
set udg_Lists_Data= data
set udg_Lists_ListID = listKey
set data = LoadInteger(udg_Lists_Hashtable, listKey, data)
if IsTriggerEnabled(trig) and TriggerEvaluate(trig) then
call TriggerExecute(trig)
endif
set count = count + 1
endloop
endfunction
//Same as GLL_Loop, however, you may specify a code that will run in a ForPlayer loop instead of a trigger
//Added in version 1.1.0
function GLL_CodeLoop takes integer listKey, code func, integer until returns nothing
local integer data = LoadInteger(udg_Lists_Hashtable, listKey, 0)
local integer count = 0
loop
exitwhen data == 0 or count == until
set udg_Lists_Data= data
set udg_Lists_ListID = listKey
set data = LoadInteger(udg_Lists_Hashtable, listKey, data)
call ForForce(bj_FORCE_PLAYER[0], func)
set count = count + 1
endloop
endfunction
//Loops over a list from the value following "start" to the value preceding "finish" (or 0, whichever comes first)
//Each iteration sets Lists_Data to the current value and then runs the specified code in a ForPlayer loop
//If you specify a negative listKey, the loop will execute backwards
//Added in version 1.1.0
function GLL_ClearList takes integer listKey, integer start, integer finish, code func returns integer
local integer data = LoadInteger(udg_Lists_Hashtable, listKey, start)
local integer nextData
local integer countRemoved = 0
loop
exitwhen data == finish or data == 0
set nextData = LoadInteger(udg_Lists_Hashtable, listKey, data)
call RemoveSavedInteger(udg_Lists_Hashtable, listKey, data)
call RemoveSavedInteger(udg_Lists_Hashtable, -listKey, data)
set udg_Lists_Data = data
call ForForce(bj_FORCE_PLAYER[0], func)
set data = nextData
set countRemoved = countRemoved + 1
endloop
call SaveInteger(udg_Lists_Hashtable, -listKey, data, start)
call SaveInteger(udg_Lists_Hashtable, listKey, start, data)
return countRemoved
endfunction
//This function initializes GLL if it has not yet been initialized
function GLL_Initialize takes nothing returns nothing
if udg_Lists_Hashtable == null then
//Initialize dependencies
call GMUI_Initialize()
//Initialize Hashtable
set udg_Lists_Hashtable = InitHashtable()
//Get Recycle Key
set udg_Lists_RECYCLE_KEY = GMUI_CreateRecycleKey()
endif
endfunction
////////////////////////////////////////////////////////
//End of Linked Lists
////////////////////////////////////////////////////////
function Trig_GLL_Main_Actions takes nothing returns nothing
if udg_Lists_ListID == 0 then
set udg_Lists_ListID = GLL_CreateList()
else
call GLL_DestroyList(udg_Lists_ListID)
endif
endfunction
function Trig_GLL_Main_Conditions takes nothing returns boolean
if HaveSavedInteger(udg_Lists_Hashtable, udg_Lists_ListID, udg_Lists_Data) then //Faster than GLL_ListHasData function
call GLL_RemoveData(udg_Lists_ListID, udg_Lists_Data)
else
call GLL_AddData(udg_Lists_ListID, udg_Lists_Instance, udg_Lists_Data)
endif
return false
endfunction
//===========================================================================
function InitTrig_GLL_Main takes nothing returns nothing
call GLL_Initialize()
set gg_trg_GLL_Main = CreateTrigger( )
call TriggerAddAction( gg_trg_GLL_Main, function Trig_GLL_Main_Actions )
call TriggerAddCondition( gg_trg_GLL_Main, Condition(function Trig_GLL_Main_Conditions))
endfunction
////////////////////////////////////////////////////////////////////////////////////////////////////
//Guhun's Wayback v1.1.0
//TODO: Maybe add special effect functions/textmacros to make things easier for the end-user?
////////////////////////////////////////////////////////////////////////////////////////////////////
//===========================================================================
// Easy Configuration
//===========================================================================
// Use the functions/textmacros defined here to change the behaviour of the system by changing
// what data is stored in a snapshot. You could, for example, store the unit's flying height as
// well by simply adding the commented out lines at the end of each function.
//! novjass
function StoreSnapshotData takes integer snapshot, unit whichUnit returns nothing
//! endnovjass
//! textmacro StoreSnapshotData
//Whenever a new snapshot of a unit is created, this code is run to store data.
//You can alter this function(JASS)/textmacro(vJASS) to store whatever values you need.
call SaveReal(udg_Wayback_Hashtable, snapshot, 0, GetUnitState(whichUnit, UNIT_STATE_LIFE))
call SaveReal(udg_Wayback_Hashtable, snapshot, 1, GetUnitState(whichUnit, UNIT_STATE_MANA))
call SaveReal(udg_Wayback_Hashtable, snapshot, 2, GetUnitX(whichUnit))
call SaveReal(udg_Wayback_Hashtable, snapshot, 3, GetUnitY(whichUnit))
// Example of user-defined data:
//call SaveReal(udg_Wayback_Hashtable, snapshot, 4, GetUnitFlyHeight(whichUnit))
//! endtextmacro
//! novjass
endfunction
//! endnovjass
//! novjass
function UnitLoadSnapshot takes integer snapshot, unit whichUnit returns nothing
//! endnovjass
//! textmacro UnitLoadSnapshot
//Whenever a new snapshot of a unit is created, this code is to restore the unit.
//You can alter this function(JASS)/textmacro(vJASS) to use any custom data you have added.
call SetUnitState(whichUnit, UNIT_STATE_LIFE, LoadReal(udg_Wayback_Hashtable, snapshot, 0))
call SetUnitState(whichUnit, UNIT_STATE_MANA, LoadReal(udg_Wayback_Hashtable, snapshot, 1))
call SetUnitX(whichUnit, LoadReal(udg_Wayback_Hashtable, snapshot, 2))
call SetUnitY(whichUnit, LoadReal(udg_Wayback_Hashtable, snapshot, 3))
// Example of user-defined data:
//call SetUnitFlyHeight(whichUnit, LoadReal(udg_Wayback_Hashtable, snapshot, 4))
//! endtextmacro
//! novjass
endfunction
//! endnovjass
//===========================================================================
// Code and API
//===========================================================================
//=======
//Snapshot functions
//=======
//Creates a new snapshot, which is saved at the end of the GLL list
function Wayback_NewSnapshot takes unit whichUnit returns integer
local integer snapshot = -GMUI_GetIndex(1)
local integer unitID = GetHandleId(whichUnit)
local integer counter = LoadInteger(udg_Wayback_Hashtable, unitID, 2)
local integer maxSnapshots = LoadInteger(udg_Wayback_Hashtable, unitID, 3)
local integer firstSnapshot
local integer listKey = LoadInteger(udg_Wayback_Hashtable, unitID, 1)
if counter == maxSnapshots then
set firstSnapshot = LoadInteger(udg_Lists_Hashtable, listKey, 0)
call GLL_RemoveData(listKey, firstSnapshot)
call GMUI_RecycleIndex(1, -firstSnapshot)
call FlushChildHashtable(udg_Wayback_Hashtable, firstSnapshot)
else
call SaveInteger(udg_Wayback_Hashtable, unitID, 2, counter + 1)
endif
call GLL_AddData(listKey, 0, snapshot)
//! novjass
call StoreSnapshotData(snapshot, whichUnit)
//! endnovjass
//! runtextmacro StoreSnapshotData()
return snapshot
endfunction
function Wayback_Tmr_Snapshot takes nothing returns nothing
call Wayback_NewSnapshot(LoadUnitHandle(udg_Wayback_Hashtable, GetHandleId(GetExpiredTimer()), 0))
endfunction
//Deletes a snapshot and all data stored in the child hashtable of Wayback_Hashtable
//Also removes the snapshot from the GLL list and recycles its ID
//The "unitID" parameter should be the snapshot unit's Handle ID
function Wayback_DeleteSnapshot takes integer unitID, integer snapshot returns nothing
local integer listKey = LoadInteger(udg_Wayback_Hashtable, unitID, 1)
call FlushChildHashtable(udg_Wayback_Hashtable, snapshot)
call GLL_RemoveData(listKey, snapshot)
call GMUI_RecycleIndex(1,-snapshot)
call SaveInteger(udg_Wayback_Hashtable, unitID, 2, LoadInteger(udg_Wayback_Hashtable, unitID, 2) - 1)
endfunction
function Wayback_ClearSnapshot takes nothing returns nothing
call FlushChildHashtable(udg_Wayback_Hashtable, udg_Lists_Data)
call GMUI_RecycleIndex(1,-udg_Lists_Data)
endfunction
//=======
//Register Unit functions
//=======
//Registers a unit in the System, allowing you to specify a function for the periodic timer
function Wayback_RegisterUnitEx takes unit whichUnit, real period, integer maxSnapshots, code timerFunc returns nothing
local timer t
local integer listKey
local integer unitID = GetHandleId(whichUnit)
if HaveSavedInteger(udg_Wayback_Hashtable, unitID, 1) then
return
endif
set t = CreateTimer()
call SaveUnitHandle(udg_Wayback_Hashtable, GetHandleId(t), 0, whichUnit)
call TimerStart(t, period, true, timerFunc)
call SaveTimerHandle(udg_Wayback_Hashtable, unitID, 0, t)
call SaveInteger(udg_Wayback_Hashtable, unitID, 1, GLL_CreateList())
call SaveInteger(udg_Wayback_Hashtable, unitID, 3, maxSnapshots)
call Wayback_NewSnapshot(whichUnit)
endfunction
//Register unit with default timer function
function Wayback_RegisterUnit takes unit whichUnit, real period, integer maxSnapshots returns nothing
call Wayback_RegisterUnitEx(whichUnit, period, maxSnapshots, function Wayback_Tmr_Snapshot)
endfunction
//Register unit using a duration instead of maximum snapshots and using default timer function
function Wayback_RegisterUnitDuration takes unit whichUnit, real period, real duration, real period2 returns nothing
call Wayback_RegisterUnit(whichUnit, period, R2I(duration/period2))
endfunction
//Register unit using a duration instead of maximum snapshots
function Wayback_RegisterUnitDurationEx takes unit whichUnit, real period, real duration, real period2, code timerFunc returns nothing
call Wayback_RegisterUnitEx(whichUnit, period, R2I(duration/period2), timerFunc)
endfunction
//Unregisters a unit from the system, deleting all snapshot data and the timer
function Wayback_UnregisterUnit takes unit whichUnit returns nothing
local integer unitID = GetHandleId(whichUnit)
local timer t = LoadTimerHandle(udg_Wayback_Hashtable, unitID, 0)
local integer listKey = LoadInteger(udg_Wayback_Hashtable, unitID, 1)
if listKey == 0 then
return
endif
call FlushChildHashtable(udg_Wayback_Hashtable, GetHandleId(t))
call PauseTimer(t)
call DestroyTimer(t)
call GLL_ClearList( listKey, 0, 0, function Wayback_ClearSnapshot)
call GLL_DestroyList(listKey)
call FlushChildHashtable(udg_Wayback_Hashtable, unitID)
endfunction
//=======
//Restoring and Rewinding functions
//=======
//Instantly restores a unit to their oldest snapshot
//Returns the ID of the snapshot for extended functionality
function Wayback_RestoreUnit takes unit whichUnit returns integer
local integer listKey = LoadInteger(udg_Wayback_Hashtable, GetHandleId(whichUnit), 1)
local integer snapshot = LoadInteger(udg_Lists_Hashtable, listKey, 0)
//! novjass
call UnitLoadSnapshot(snapshot, whichUnit)
//! endnovjass
//! runtextmacro UnitLoadSnapshot()
call GLL_ClearList( listKey, snapshot, 0, function Wayback_ClearSnapshot)
call SaveInteger(udg_Wayback_Hashtable, GetHandleId(whichUnit), 2, 1)
return snapshot
endfunction
//Instantly moves unit "time" seconds back in time, up to their oldest snapshot
//Returns the ID of the snapshot for extended functionality
function Wayback_RestoreUnitEx takes unit whichUnit, real time returns integer
local integer unitID = GetHandleId(whichUnit)
local real period = TimerGetTimeout(LoadTimerHandle(udg_Wayback_Hashtable, unitID ,0))
local integer maxSnapshots = LoadInteger(udg_Wayback_Hashtable, unitID, 2)
local integer snapshotsAmount = R2I(time/period)
local integer listKey = LoadInteger(udg_Wayback_Hashtable, unitID, 1)
local integer counter = 0
local integer snapshot = 0
local integer nextSnapshot = LoadInteger(udg_Lists_Hashtable, -listKey, snapshot)
if snapshotsAmount >= maxSnapshots - 1 then
return Wayback_RestoreUnit(whichUnit)
endif
loop // This loop is heavily optimized and uses bad coding practices *shrug*
set snapshot = nextSnapshot
set counter = counter + 1
exitwhen counter == snapshotsAmount
set nextSnapshot = LoadInteger(udg_Lists_Hashtable, -listKey, snapshot)
call RemoveSavedInteger(udg_Lists_Hashtable, listKey, snapshot) // Destroy link to next
call RemoveSavedInteger(udg_Lists_Hashtable, -listKey, snapshot) // Destroy link to prev
// Delete snapshot
call FlushChildHashtable(udg_Wayback_Hashtable, snapshot)
call GMUI_RecycleIndex(1,-snapshot)
endloop
// Create new links, the last element is the snapshot
call SaveInteger(udg_Lists_Hashtable, listKey, snapshot, 0) // Next of snapshot is 0
call SaveInteger(udg_Lists_Hashtable, -listKey, 0, snapshot) // Prev of 0 is snapshot
//! novjass
call UnitLoadSnapshot(snapshot, whichUnit)
//! endnovjass
//! runtextmacro UnitLoadSnapshot()
call SaveInteger(udg_Wayback_Hashtable, unitID, 2, maxSnapshots - snapshotsAmount)
return snapshot
endfunction
//Instantly moves unit a single snapshot back in time
//The unit ID variable should be the unit's handle ID
//Returns the ID of the snapshot for extended functionality
function Wayback_RestoreUnitByIdOneStep takes unit whichUnit, integer unitID returns integer
local integer listKey = LoadInteger(udg_Wayback_Hashtable, unitID, 1)
local integer snapshot = LoadInteger(udg_Lists_Hashtable, -listKey, 0)
local integer prevSnapshot = LoadInteger(udg_Lists_Hashtable, -listKey, snapshot)
//! novjass
call UnitLoadSnapshot(snapshot, whichUnit)
//! endnovjass
//! runtextmacro UnitLoadSnapshot()
return snapshot
endfunction
//Instantly moves unit a single snapshot back in time
//Returns the ID of the snapshot for extended functionality
//-------
//Needs to be CnP from Wayback_RestoreUnitByIdOneStep, since it can't be inlined with vJASS
function Wayback_RestoreUnitOneStep takes unit whichUnit returns integer
local integer unitID = GetHandleId(whichUnit)
local integer listKey = LoadInteger(udg_Wayback_Hashtable, unitID, 1)
local integer snapshot = LoadInteger(udg_Lists_Hashtable, -listKey, 0)
local integer prevSnapshot = LoadInteger(udg_Lists_Hashtable, -listKey, snapshot)
//! novjass
call UnitLoadSnapshot(snapshot, whichUnit)
//! endnovjass
//! runtextmacro UnitLoadSnapshot()
return snapshot
endfunction
//=======
function Wayback_Tmr_Rewind takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = LoadUnitHandle(udg_Wayback_Hashtable, GetHandleId(t), 0)
local integer unitID = GetHandleId(u)
local integer snapshot = Wayback_RestoreUnitByIdOneStep(u, unitID)
if LoadInteger(udg_Wayback_Hashtable, unitID, 2) != LoadInteger(udg_Wayback_Hashtable, GetHandleId(t), 1) then
call Wayback_DeleteSnapshot(unitID, snapshot)
else
call TimerStart(LoadTimerHandle(udg_Wayback_Hashtable, unitID, 0), TimerGetTimeout(LoadTimerHandle(udg_Wayback_Hashtable, unitID, 0)), true, function Wayback_Tmr_Snapshot)
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Wayback_Hashtable, GetHandleId(t))
endif
set t = null
set u = null
endfunction
//Takes a unit back in "time" seconds in time, snapshot-by-snapshot, over "duration" seconds
function Wayback_RewindUnit takes unit whichUnit, real time, real duration returns nothing
local timer t = CreateTimer()
local timer snapshotTimer = LoadTimerHandle(udg_Wayback_Hashtable, GetHandleId(whichUnit), 0)
local real period
local integer snapshotsAmount
set snapshotsAmount = R2I(time/TimerGetTimeout(snapshotTimer))
set period = duration/snapshotsAmount
call PauseTimer(snapshotTimer)
call TimerStart(t, period, true, function Wayback_Tmr_Rewind)
call SaveUnitHandle(udg_Wayback_Hashtable, GetHandleId(t), 0, whichUnit)
call SaveInteger(udg_Wayback_Hashtable, GetHandleId(t), 1, IMaxBJ(LoadInteger(udg_Wayback_Hashtable, GetHandleId(whichUnit), 2) - snapshotsAmount, 1))
set t = null
endfunction
////////////////////////////////////////////////////////////////////////////////////////////////////
//End of Wayback
////////////////////////////////////////////////////////////////////////////////////////////////////
function Trig_Wayback_Main_Actions takes nothing returns nothing
if udg_Wayback_Time >= 0 then
call Wayback_RegisterUnitDuration(udg_Wayback_Unit, udg_Wayback_Precision, udg_Wayback_Time, udg_Wayback_Precision)
else
call Wayback_UnregisterUnit(udg_Wayback_Unit)
endif
endfunction
function Trig_Wayback_Main_Conditions takes nothing returns boolean
if udg_Wayback_Time == 0 then
call Wayback_RestoreUnit(udg_Wayback_Unit)
elseif udg_Wayback_Time > 0 then
call Wayback_RestoreUnitEx(udg_Wayback_Unit, udg_Wayback_Time)
else
call Wayback_RewindUnit(udg_Wayback_Unit, -udg_Wayback_Time, udg_Wayback_Precision)
endif
return false
endfunction
//===========================================================================
function InitTrig_Wayback_Main takes nothing returns nothing
set udg_Wayback_Hashtable = InitHashtable()
set gg_trg_Wayback_Main = CreateTrigger( )
call TriggerAddAction( gg_trg_Wayback_Main, function Trig_Wayback_Main_Actions )
call TriggerAddCondition( gg_trg_Wayback_Main, Condition(function Trig_Wayback_Main_Conditions) )
endfunction
////////////////////////////////////////////////////////
//Guhun's Linked Unordered Lists v.1.0.0
////////////////////////////////////////////////////////
//To get the first element, pass "0" as the parameter "data"
function GLUL_GetNext takes integer listKey, integer data returns integer
return LoadInteger(udg_Lists_Hashtable, listKey, data)
endfunction
//To get the last element, pass "0" as the parameter "data"
function GLUL_GetPrev takes integer listKey, integer data returns integer
return LoadInteger(udg_Lists_Hashtable, -listKey, data)
endfunction
function GLUL_ListHasData takes integer listKey, integer data returns boolean
return HaveSavedInteger(udg_Lists_Hashtable, listKey, data)
endfunction
//Adds data to a list
//If data is already present in list, behaviour is undefined
function GLUL_AddData takes integer listKey, integer next, integer data returns nothing
local integer prev = LoadInteger(udg_Lists_Hashtable, -listKey, next)
local integer instance = GIUL_AddData(listKey, data)
call SaveInteger(udg_Lists_Hashtable, -listKey, prev, instance)
call SaveInteger(udg_Lists_Hashtable, -listKey, -next, instance)
call SaveInteger(udg_Lists_Hashtable, -listKey, instance, next)
call SaveInteger(udg_Lists_Hashtable, -listKey, -instance, prev)
endfunction
//Removes the given Data from a list
//If data is not present in List, behaviour is undefined
function GLUL_RemoveData takes integer listKey, integer index returns nothing
local integer next = LoadInteger(udg_Lists_Hashtable, -listKey, index)
local integer prev = LoadInteger(udg_Lists_Hashtable, -listKey, -index)
call SaveInteger(udg_Lists_Hashtable, -listKey, -next, prev)
call SaveInteger(udg_Lists_Hashtable, -listKey, prev, next)
call RemoveSavedInteger(udg_Lists_Hashtable, -listKey, index)
call RemoveSavedInteger(udg_Lists_Hashtable, -listKey, -index)
call GIUL_RemoveData(listKey, index)
endfunction
function GLUL_CreateList takes nothing returns integer
local integer listId = GMUI_GetIndex(udg_Lists_RECYCLE_KEY)
call SaveInteger(udg_Lists_Hashtable, listId, 0, 0)
call SaveInteger(udg_Lists_Hashtable, -listId, 0, 0)
return listId
endfunction
function GLUL_DestroyList takes integer listId returns nothing
call FlushChildHashtable(udg_Lists_Hashtable, listId)
call FlushChildHashtable(udg_Lists_Hashtable, -listId)
call GMUI_RecycleIndex(udg_Lists_RECYCLE_KEY, listId)
endfunction
//This function loops through a List and executes a trigger for each element, setting the list variables to their relevant equivalents each time
function GLUL_Loop takes integer listKey, trigger trig, integer until returns nothing
local integer index = LoadInteger(udg_Lists_Hashtable, listKey, 0)
local integer data
local integer count = 0
local integer negListKey = listKey
loop
exitwhen index == 0 or count == until
set data = LoadInteger(udg_Lists_Hashtable, listKey, index)
set udg_Lists_Data= data
set udg_Lists_ListID = listKey
set index = LoadInteger(udg_Lists_Hashtable, negListKey, index)
if IsTriggerEnabled(trig) and TriggerEvaluate(trig) then
call TriggerExecute(trig)
endif
set count = count + 1
endloop
endfunction
//This function initializes GLL if it has not yet been initialized
function GLUL_Initialize takes nothing returns nothing
if udg_Lists_Hashtable == null then
//Initialize dependencies
call GMUI_Initialize()
//Initialize Hashtable
set udg_Lists_Hashtable = InitHashtable()
//Get Recycle Key
set udg_Lists_RECYCLE_KEY = GMUI_CreateRecycleKey()
endif
endfunction
////////////////////////////////////////////////////////
//End of Linked Unordered Lists
////////////////////////////////////////////////////////