Name | Type | is_array | initial_value |
DYN2_CURRENT_INDEX | integer | No | |
DYN2_EXAMPLE_ANGLE | real | Yes | |
DYN2_EXAMPLE_DISTANCE | real | Yes | |
DYN2_EXAMPLE_LOOP | integer | No | |
DYN2_EXAMPLE_POINT | location | Yes | |
DYN2_EXAMPLE_UNIT | unit | Yes | |
DYN2_INDEX_CONTAINER | integer | Yes | |
DYN2_INDEX_LISTENER | integer | No | |
DYN2_INDEX_SIZE | integer | No | |
DYN2_RECYCLE_CONTAINER | integer | Yes | |
DYN2_RECYCLE_SIZE | integer | No | |
EXAMPLE_DUR | real | Yes | |
EXAMPLE_GFX | effect | Yes | |
EXAMPLE_Index | integer | Yes | |
EXAMPLE_Index_maxSize | integer | No | |
EXAMPLE_Index_Size | integer | No | |
EXAMPLE_LOC | location | Yes | |
EXAMPLE_LOOP | integer | No | |
FUSION_HASHId | integer | Yes | |
FUSION_LOOP | integer | No | |
FUSION_MOTIONactive | boolean | Yes | |
FUSION_MOTIONcaster | unit | Yes | |
FUSION_MOTIONdmg | real | Yes | |
FUSION_MOTIONindex | integer | Yes | |
FUSION_MOTIONloc | location | Yes | |
FUSION_MOTIONmaxSize | integer | No | |
FUSION_MOTIONrange | real | Yes | |
FUSION_MOTIONsize | integer | No | |
HANDLE_INDEX_CONTAINER | hashtable | No | |
HANDLE_INDEX_CURRENT | integer | No | |
HANDLE_INDEX_DELETE | trigger | No | |
HANDLE_INDEX_GETID | trigger | No | |
HANDLE_INDEX_ID | integer | No | |
HANDLE_INDEX_OBJECT | handle | No | |
HANDLE_INDEX_RECYCLE_CONTAINER | integer | Yes | |
HANDLE_INDEX_RECYCLE_CURRENT | integer | No | |
HANDLE_INDEX_REGISTER | trigger | No | |
HANDLE_INDEX_UNIT | unit | No | |
HASHTABLE_DELETE | boolean | No | |
HASHTABLE_DELETEANOTHER | boolean | No | |
HASHTABLE_GFX | effect | Yes | |
HASHTABLE_GFXANOTHER | effect | Yes | |
HASHTABLE_GROUP | group | No | |
HASHTABLE_GROUPANOTHER | group | No | |
HASHTABLE_InUse | integer | Yes | |
HASHTABLE_Last | integer | Yes | |
HASHTABLE_LastSize | integer | No | |
HASHTABLE_Size | integer | No | |
SELECT_HASHTABLE | hashtable | No | |
SPELL_ANGLE | real | Yes | |
SPELL_CASTER | unit | Yes | |
SPELL_DUR | real | Yes | |
SPELL_Index | integer | Yes | |
SPELL_Index_maxSize | integer | No | |
SPELL_Index_Size | integer | No | |
SPELL_LOOP | integer | No | |
SPELL_MISSILE | unit | Yes | |
SPELL_SPEED | real | Yes | |
SUPER_DOOPER_GROUP | group | No | |
SUPER_DOOPER_TIME | real | Yes | |
TempHandle | handle | No | |
TempInt | integer | No | |
TempInt2 | integer | No | |
TempLoc | location | No | |
TempLoc2 | location | No | |
TempUnit | unit | No | |
UNIT_INDEX_GROUP | group | No |
//TESH.scrollpos=49
//TESH.alwaysfold=0
//======================================================================================
Dynamic Index
//======================================================================================
I just can recommend using a dynamic index system if you are using GUI for looping stuff.
Because of the following reasons you should use this kind of dynamic indexing:
- It´s faster than the "paladon indexing system" or however you want to call
that indexing (and btw it´s even shorter than the "paladon indexing system")
- I think it´s easy to understand and it just need 3 variables
//--------------------------------------------------------------------------------------
This map is an example map for dynamic indexing. Demo made by Hanky.
Well dynamic indexing is pretty easy but it´ll still save much performance. Basicly it´s
just an integer array which keep all index positions. Just as an example:
//--------------------------------------------------------------------------------------
We got 3 index entries:
- The first entry get the index 1
- The second entry get the index 2
- The third entry get the index 3
Then suddenly index 2 expired and going to be recycled.
- Index[Current Loop Integer] = Index[Last Position Index]
- Index[Last Position Index] = Index[Current Loop Integer]
Basicly this is just an exchange of the last position and the current loop position. That means:
2 [2] = 3 [3]
3 [3] = 2
Another example with 3 indexes which expire in the order of 1,2 and 3:
=> Index 1 get recycled
1 [1] = 3 [3]
3 [3] = 1
=> Index 2 get recycled
2 [2] = 2 [2]
2 [2] = 2
=> Index 3 get recycled
3 [1] = 3 [1]
3 [1] = 3
And a last example with 3 indexes which expire in the order of 2,3 and 1:
=> Index 1 get recycled
2 [2] = 3 [3]
3 [3] = 2
=> Index 2 get recycled
3 [2] = 3 [2]
3 [2] = 3
=> Index 3 get recycled
1 [1] = 1 [1]
1 [1] = 1
//--------------------------------------------------------------------------------------
Hint:
If you are using IntegerA oder IntegerB in the motion loop the whole recycle process have to look
like this:
If you are using IntegerA it should look like this:
-------- RecycleIndex --------
Set EXAMPLE_Index[bj_forLoopAIndex] = EXAMPLE_Index[EXAMPLE_Index_Size]
Set EXAMPLE_Index[EXAMPLE_Index_Size] = TempInt
Custom Script: set bj_forLoopAIndexEnd = (bj_forLoopAIndexEnd - 1)
Custom Script: set bj_forLoopAIndex = (bj_forLoopAIndex - 1)
If you are using IntegerB it should look like this:
-------- RecycleIndex --------
Set EXAMPLE_Index[bj_forLoopBIndex] = EXAMPLE_Index[EXAMPLE_Index_Size]
Set EXAMPLE_Index[EXAMPLE_Index_Size] = TempInt
Custom Script: set bj_forLoopBIndexEnd = (bj_forLoopBIndexEnd - 1)
Custom Script: set bj_forLoopBIndex = (bj_forLoopBIndex - 1)
//--------------------------------------------------------------------------------------
// Last words...
Why did I made this map?
Im sick of all those GUI spell maps using ineffective indexing systems.
Greetings fly out to:
Paladon, Darkt3mpl3r, JonNny, WaRadius, Toadcop, Deuterium, Eccho, Berzeker, xxdingo93xx
Yixx, Dark Dragon ...
Also thanks to D4RK_G4ND4LF for telling me stuff I just forgot to add.
Well I hope that you guys understood what I mean. If not Im free for questions.
//TESH.scrollpos=0
//TESH.alwaysfold=0
//======================================================================================
Dynamic Index 2
//======================================================================================
Why I should use this method?
-----------------------------
Well it's even easier than the first dynamic indexing I showed. Since I it's much better
explainable.
Also this system is pretty much as fast as my first dynamic indexing. But more "user
friendly".
What the variables are for?
---------------------------
Well there are six variables which manage all the indexing. First of there's a integer
array/container which contains all active indexes. The variable is called:
"DYN2_INDEX_CONTAINER"
To get the size of all current active indexes there's the variable called:
"DYN2_INDEX_LISTENER"
Also there's a variable where you can get what's the current size of released indexes,
the variable is called:
"DYN2_INDEX_SIZE"
The most important variable is the recylce container since this variable contain all
dead/inactive indexes. The variable is called:
"DYN2_RECYLCE_CONTAINER"
The helper variable of the recycle container is the recycle index. This variable
contains the current size of the recycle container.
"DYN2_RECYLCE_INDEX"
The last variable isn't an important one. But still useful for GUI users. The variable
contains the current selected index. The name of the variable is:
"DYN2_CURRENT_INDEX"
How the system is working?
--------------------------
First of we are checking if the recycle container got some inactive indexes for us.
But since we are executing the spell the first time a new index gets created. In this
case the index:
Index(0) = 0
So now the first index is active and we create another new one. So the next index gets
created:
Index(1) = 1
And just for fun we create another index:
Index(2) = 2
Now the first index gets added to the recycle container since it's inactive:
Recylce(0) = Index(0)
At the same time the active index container exchanging the position of the last active
index to the position of the first recycled position:
Index(0) = Index(2)
So the index container size is decreased.
Now Index(2) which is at position of Index(0) gets added to the recycle container:
Recycle(1) = Index(0) [Remember that it is Index(2) just with an other position]
Now the last active index gets recycled. So the recycle container looks like this:
Recycle(0) => 0
Recycle(1) => 2
Recycle(2) => 1
So if the spell gets executed now the system will release the last index of the recycle
container.
Index(0) => Recycle(2)
Short Example:
--------------
Spell gets executed. 4 times:
Index(0) => value(0)
Index(1) => value(1)
Index(2) => value(2)
Index(3) => value(3)
Inactive variables get recycled (List of ending indexes: 2,1,3,0):
Recycle(0) => value(2)
Recycle(1) => value(1)
Recycle(2) => value(3)
Recycle(3) => value(0)
Spell gets executed. 3 times:
Index(0) = Recycle(3) => value(0)
Index(1) = Recycle(2) => value(3)
Index(2) = Recycle(1) => value(1)
Inactive variable get recycled (List of ending indexes: 1):
Recycle(1) = Index(1) => value(3)
Spell gets executed. 3 times:
Index(2) = Recycle(1) => value(3)
Index(3) = Recycle(0) => value(2)
Index(4) => value(4)
Inactive variable get recycled (List of ending indexes: 3,2,4,1,0):
Recycle(0) = Index(3) => value(2)
Recycle(1) = Index(2) => value(3)
Recycle(2) = Index(4) => value(4)
Recycle(3) = Index(1) => value(1)
Recycle(4) = Index(0) => value(0)
Why did a made a second version?:
---------------------------------
So you can decide what you like more...
//TESH.scrollpos=0
//TESH.alwaysfold=0
//======================================================================================
Hashtable Indexing
//======================================================================================
This will be very helpful if you want to use something like 'GetUnitUserData'. Just that
this system will set the index of whatever a handle you want. And since it´s using
hashtables the speed is pretty good. Well all in all the system is just designed to attach
an index to a handle. (Which will be pretty helpful if you don´t use loops in your spell)
'> Function explaination:
'The create function:
First you have to set a handle for the udg_TempHandle variable. Something like:
set udg_TempHandle = someunit/somelocation/sometimer etc.
After that you have to add to this handle an index by executing the CreateDHashtable trigger:
Trigger - Run CreateDHashtable <gen> (ignoring conditions)
By executing the CreateDHashtable trigger you get the index returned which was created.
The udg_TempInt variable will be setted to this index. So that you can use it easily for
your code. Like for example:
-------- Create a new Index --------
Trigger - Run CreateDHashtable <gen> (ignoring conditions)
-------- Adding those arrays --------
Effect - Create a special effect attached to the overhead of (Triggering unit) using Abilities\Spells\Other\TalkToMe\TalkToMe.mdl
Set HASHTABLE_GFX[TempInt] = (Last created special effect)
How you can easily see you just need to set your arrays with the TempInt as index. And that´s it.
You have created succesfully your first hashtable index.
'The get function:
First you have to set a handle for the udg_TempHandle variable. Something like:
set udg_TempHandle = someunit/somelocation/sometimer etc.
The get function is pretty simple. Just execute the GetDHashtable trigger and that´s it.
Trigger - Run GetDHashtable <gen> (ignoring conditions)
After you done that you can use the udg_TempInt as index. Like for example there:
-------- Get the current Index of a handle --------
Trigger - Run GetDHashtable <gen> (ignoring conditions)
Effect - Destroy HASHTABLE_GFX[TempInt]
How you see we execute the destroy function after we got the index of the value.
'The delete function:
First you have to set a handle for the udg_TempHandle variable. Something like:
set udg_TempHandle = someunit/somelocation/sometimer etc.
Then we´ll just need to execute the DeleteDHashtable. And the index of the handle will be again destroyed.
But remember it´ll be just removed if it isn´t anymore in use. This is why you can use this system for every
spell. And don´t need to create it from the scratch for every spell.
'Advice:
This system just need the three variables:
'udg_HASHTABLE_Last
'udg_HASHTABLE_LastSize
'udg_HASHTABLE_Size
For all those temp stuff actions the system just need one temp handle variable and one temp integer variable.
In the case of this example those two variables would be:
'udg_TempInt - For integers
'udg_TempHandle - For handles
//--------------------------------------------------------------------------------------
// Last words...
If you have questions about this system feel free to ask me.
//TESH.scrollpos=0
//TESH.alwaysfold=0
//======================================================================================
Dynamic Loops + Dynamic Hashtables
//======================================================================================
This is an example to show that if these two systems work together nearly everything in GUI
can be made MUI. I made this example to show that even MUI channeling spells are possible
with GUI. I hope this help some people to make "effective" spells in GUI.
If you have any questions about this example you are free to ask me.
//TESH.scrollpos=0
//TESH.alwaysfold=0
======================================================================================
Handle Indexer
======================================================================================
Generally it's like GetHandleId but it's still not the same. Since here you can decide which handles get registered.
So you have the posibility to use it for arrays which are attached to a certain unit. And you don't need to call
unsecure operations like GetHandleId-0x00SomeLongNumberIcantRemember to get an unit id you can use for your array.
For guys who are crazy and registering more than 8191 handles there is a debug message. (But I doubt or hope that
nobody got so many handles in the map at the same time. And of course there's a recycle so that means if a handle
gets deleted the index gets recylced.)
'> Function explaination:
We got three functions here and two important variables.
Triggers:
HANDLE_INDEX_REGISTER
HANDLE_INDEX_GETID
HANDLE_INDEX_DELETE
Variables:
HANDLE_INDEX_OBJECT //CONTAINS YOU SELECTED OBJECT (REMEMBER TO SET IT BEFORE YOU EXECUTE ANY FUNCTION)
HANDLE_INDEX_ID //CONTAINS THE ID OF YOUR CURRENT SELECTED OBJECT
First off we got the register function. Which is very important otherwise the whole system wouldn't work. Also the
function name is explanation enough. This function do nothing more than registering a handle and giving it an unique
id.
To get an id you have to set the HANDLE_INDEX_OBJECT at first. After you did that you have to call the trigger
HANDLE_INDEX_REGISTER. After you did that you got the index in the variable HANDLE_INDEX_ID. And that's it nothing more
to do!
Example:
set HANDLE_INDEX_OBJECT=<Some Object> (Remember if you use custom script variables got the prefix "udg_")
call TriggerExecute(HANDLE_INDEX_REGISTER)
Now one of the functions you'll use very often. To get an id of a handle you need to select the handle.
So first thing you do is to select the object you want with the HANDLE_INDEX_OBJECT variable. After you did
that execute the HANDLE_INDEX_GETID trigger. Now you got the index in the variable HANDLE_INDEX_ID. That's it!
Example:
set HANDLE_INDEX_OBJECT=<Some Object> (Remember if you use custom script variables got the prefix "udg_")
call TriggerExecute(HANDLE_INDEX_GETID)
set SOME_ARRAY_OF_THE_SPELL[HANDLE_INDEX_ID]=<some value>
The last function is the index delete trigger. The things you have to do are the same like in the register function.
The only thing that changed is the function you'll have to execute. It's the HANDLE_INDEX_DELETE trigger. Yeah and that's
all.
Example:
set HANDLE_INDEX_OBJECT=<Some Object> (Remember if you use custom script variables got the prefix "udg_")
call TriggerExecute(HANDLE_INDEX_DELETE)
'> Some last words:
If you got still things you don't understand. You can of course ask me. But Im pretty sure that this system is really easy
to understand.
//TESH.scrollpos=0
//TESH.alwaysfold=0
// HANDLE INDEXER
// 0x00 - HANDLE INDEX POSITION
// 0x01 - HANDLE INDEX IN USE SIZE
// Description:
// Generally it's like GetHandleId but it's still not the same. Since here you can decide which handles get registered.
// So you have the posibility to use it for arrays which are attached to a certain unit. And you don't need to call
// unsecure operations like GetHandleId-0x00SomeLongNumberIcantRemember to get an unit id you can use for your array.
// For guys who are crazy and registering more than 8191 handles there is a debug message. (But I doubt or hope that
// nobody got so many handles in the map at the same time. And of course there's a recycle so that means if a handle
// gets deleted the index gets recylced.)
// Register handles...
function HANDLE_INDEX_REGISTER takes nothing returns nothing
local integer index=GetHandleId(udg_HANDLE_INDEX_OBJECT)
local integer pos
if (HaveSavedInteger(udg_HANDLE_INDEX_CONTAINER,index,0x00)) then
call SaveInteger(udg_HANDLE_INDEX_CONTAINER,index,0x01,LoadInteger(udg_HANDLE_INDEX_CONTAINER,index,0x01)+0x01)
set pos=LoadInteger(udg_HANDLE_INDEX_CONTAINER,index,0x00)
else
if (udg_HANDLE_INDEX_RECYCLE_CURRENT>0x00) then
set pos=udg_HANDLE_INDEX_RECYCLE_CONTAINER[udg_HANDLE_INDEX_RECYCLE_CURRENT]
set udg_HANDLE_INDEX_RECYCLE_CURRENT=udg_HANDLE_INDEX_RECYCLE_CURRENT-0x01
else
set pos=udg_HANDLE_INDEX_CURRENT
set udg_HANDLE_INDEX_CURRENT=udg_HANDLE_INDEX_CURRENT+0x01
//DEBUG MESSAGE START
if (udg_HANDLE_INDEX_CURRENT>8191) then
call BJDebugMsg("Warning: Index size is over 8191.")
endif
//DEBUG MESSAGE END
endif
call SaveInteger(udg_HANDLE_INDEX_CONTAINER,index,0x00,pos)
call SaveInteger(udg_HANDLE_INDEX_CONTAINER,index,0x01,0x01)
endif
set udg_HANDLE_INDEX_ID=pos
endfunction
// Get the index of a handle.
function HANDLE_INDEX_GETID takes nothing returns nothing
local integer index=GetHandleId(udg_HANDLE_INDEX_OBJECT)
if (HaveSavedInteger(udg_HANDLE_INDEX_CONTAINER,index,0x00)) then
set udg_HANDLE_INDEX_ID=LoadInteger(udg_HANDLE_INDEX_CONTAINER,index,0x00)
else
set udg_HANDLE_INDEX_ID=-1
endif
endfunction
// Delete the index of a handle
function HANDLE_INDEX_DELETE takes nothing returns nothing
local integer index=GetHandleId(udg_HANDLE_INDEX_OBJECT)
local integer size
if (HaveSavedInteger(udg_HANDLE_INDEX_CONTAINER,index,0x00)) then
set size=LoadInteger(udg_HANDLE_INDEX_CONTAINER,index,0x01)-0x01
if (size==0x00) then
set udg_HANDLE_INDEX_RECYCLE_CURRENT=udg_HANDLE_INDEX_RECYCLE_CURRENT+0x01
set udg_HANDLE_INDEX_RECYCLE_CONTAINER[udg_HANDLE_INDEX_RECYCLE_CURRENT]=LoadInteger(udg_HANDLE_INDEX_CONTAINER,index,0x00)
call FlushChildHashtable(udg_HANDLE_INDEX_CONTAINER,index)
else
call SaveInteger(udg_HANDLE_INDEX_CONTAINER,index,0x01,size)
endif
endif
endfunction
// SYSTEM INIT
//===========================================================================
function InitTrig_HandleIndexer takes nothing returns nothing
set udg_HANDLE_INDEX_CONTAINER=InitHashtable()
set udg_HANDLE_INDEX_REGISTER =CreateTrigger()
set udg_HANDLE_INDEX_GETID =CreateTrigger()
set udg_HANDLE_INDEX_DELETE =CreateTrigger()
call TriggerAddAction(udg_HANDLE_INDEX_REGISTER,function HANDLE_INDEX_REGISTER)
call TriggerAddAction(udg_HANDLE_INDEX_GETID,function HANDLE_INDEX_GETID)
call TriggerAddAction(udg_HANDLE_INDEX_DELETE,function HANDLE_INDEX_DELETE)
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
library HandlePointer
struct HandlePointer extends array
static hashtable CACHE=InitHashtable()
static integer CURRENT=0x00
static integer RECYCLE_CURRENT=0x00
static integer array RECYCLE_CONTAINER
static method insert takes handle OBJECT returns integer
local integer id =GetHandleId(OBJECT)
local integer pos
if (HaveSavedInteger(thistype.CACHE,id,0x00)) then
call SaveInteger(thistype.CACHE,id,0x01,LoadInteger(thistype.CACHE,id,0x01)+0x01)
set pos=LoadInteger(thistype.CACHE,id,0x00)
else
if (RECYCLE_CURRENT>0x00) then
set pos=thistype.RECYCLE_CONTAINER[thistype.RECYCLE_CURRENT]
set thistype.RECYCLE_CURRENT=thistype.RECYCLE_CURRENT-0x01
else
set pos=thistype.CURRENT
set thistype.CURRENT=CURRENT+0x01
endif
call SaveInteger(thistype.CACHE,id,0x00,pos)
call SaveInteger(thistype.CACHE,id,0x01,0x01)
endif
return pos
endmethod
static method get takes handle OBJECT returns integer
local integer id =GetHandleId(OBJECT)
if (HaveSavedInteger(thistype.CACHE,id,0x00)) then
return LoadInteger(thistype.CACHE,id,0x00)
endif
return -0x01
endmethod
static method delete takes handle OBJECT returns nothing
local integer id=GetHandleId(OBJECT)
local integer size
if (HaveSavedInteger(thistype.CACHE,id,0x00)) then
set size=LoadInteger(thistype.CACHE,id,0x01)-0x01
if (size==0x00) then
set thistype.RECYCLE_CURRENT=thistype.RECYCLE_CURRENT+0x01
set thistype.RECYCLE_CONTAINER[thistype.RECYCLE_CURRENT]=LoadInteger(thistype.CACHE,id,0x00)
call FlushChildHashtable(thistype.CACHE,id)
else
call SaveInteger(thistype.CACHE,id,0x01,size)
endif
endif
endmethod
endstruct
endlibrary