[Log in / Register]
| News | Chat | Pastebin | Donations | Tutorials | Rules | Forums |
| Maps | Skins | Icons | Models | Spells | Tools | Jass | Packs | Hosted Projects | Starcraft II Modding | Starcraft II Resources | Galaxy Wiki |
(Keeps Hive Alive)
Go Back   The Hive Workshop > Spells


Reply
 
Thread Tools
The Hive Workshop Spells:
GUI Unit Indexer 1.2.0.2
by Bribe
Images
Highslide JS
Details
Uploaded:11:59, 14th Jun 2011
Last Updated:14:02, 24th Jul 2011
Keywords:unit indexer, custom value, aids, autoindex, getunituserdata, unituserdata, mui, indexing, is unit moving, unitindexer, indexer, index, id generator
Type:System
Category:GUI / Triggers

Why Unit Indexing is Important

Read

For those not familiar with unit indexers such as UnitIndexingUtils, AutoIndex,
Perfect Unit Indexing (PUI), Advanced Indexing and Data Storage (AIDS) or
Unit Indexer, this can give you a bit of a crash-course.

You definitely want to make your spell MUI. To do that, you either use a hashtable or use some
complex form of indexing. It is very good to choose hashtable because you can load data
from a unit instead of from a list (ie. making it very easy to retrieve an index on death).

Using a hashtable has a bit of a learning curve. There are two keys - a child key, a
parent key and, finally, the actual data being stored. Saving 100 to the casting
unit looks like this:

Hashtable - Save 100 as (Key(Damage)) of (Key(Triggering unit)) in (Last created hashtable)

Using a unit indexer, you can super-simplify it to just this:

Set Damage[(Custom value of (Triggering unit))] = 100

Instead of using a hashtable with multiple keys, this simply uses an array with the
custom value of the unit as the array index.

Have you ever used unit custom value before? If so, you may be familiar with this method:

Unit - Set custom value of (Triggering unit) to 100

That is definitely the easiest way to attach 100 to the unit, but you really limit yourself
by doing that. What if you wanted to remember other things, such as the target unit and the
target location?

Using a Unit Indexer, it's like this:

Set Key = (Custom value of (Triggering unit))
Set Damage[Key] = 100
Set Target[Key] = (Target unit of ability being cast)
Set TargetPoint[Key] = (Target point of ability being cast)
Unit Group - Add (Triggering unit) to SpellGroup

Recalling this data whenever you want becomes truly easy and even easy to read.

Timed Spell
Events
Time - Every 0.03 seconds of game time
Conditions
Actions
Unit Group - Pick every unit in SpellGroup and do (Actions)
Loop - Actions
Set Key = (Custom value of (Picked unit))
Unit - Cause (Picked unit) to damage Target[Key] for Damage[Key] of attack type Chaos and damage type normal

The possiblities are literally endless. Indexing this way is pretty fun as well, even helping
to reduce total in-game hashtable count (the limit is 256).


Requiring no NewGen, JassHelper or even knowledge of JASS, this is the easiest unit indexer
to install into a map and start using to its fullest right away.
  1. Make sure "automatically create variables" is checked under "File -> Preferences"
  2. Copy and paste the following trigger (from the test map)
  3. It's installed!

Unit Indexer
Events
Map initialization
Conditions
Actions
Custom script: call ExecuteFunc("InitializeUnitIndexer")
Custom script: endfunction
-------- --------
-------- This is the most important function - it provides an index for units as they enter the map --------
-------- --------
Custom script: function IndexUnit takes nothing returns boolean
Custom script: local integer pdex = udg_UDex
-------- --------
-------- You can use the boolean UnitIndexerEnabled to protect some of your undesirable units from being indexed --------
-------- - Example: --------
-------- -- Set UnitIndexerEnabled = False --------
-------- -- Unit - Create 1 Dummy for (Triggering player) at TempLoc facing 0.00 degrees --------
-------- -- Set UnitIndexerEnabled = True --------
-------- --------
-------- You can also customize the following block - if conditions are false the (Matching unit) won't be indexed. --------
-------- --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
UnitIndexerEnabled Equal to True
Then - Actions
-------- --------
-------- Generate a unique integer index for this unit --------
-------- --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
UDexRecycle Equal to 0
Then - Actions
Set UDex = (UDexGen + 1)
Set UDexGen = UDex
Else - Actions
Set UDex = UDexRecycle
Set UDexRecycle = UDexNext[UDex]
-------- --------
-------- Link index to unit, unit to index --------
-------- --------
Set UDexUnits[UDex] = (Matching unit)
Unit - Set the custom value of UDexUnits[UDex] to UDex
-------- --------
-------- Use a doubly-linked list to store all active indexes --------
-------- --------
Set UDexPrev[UDexNext[0]] = UDex
Set UDexNext[UDex] = UDexNext[0]
Set UDexNext[0] = UDex
-------- --------
-------- Fire index event for UDex --------
-------- --------
Set UnitIndexEvent = 0.00
Set UnitIndexEvent = 1.00
Set UnitIndexEvent = 0.00
Custom script: set udg_UDex = pdex
Else - Actions
Custom script: return false
Custom script: endfunction
-------- --------
-------- The next function is called each time a unit enters the map --------
-------- --------
Custom script: function IndexNewUnit takes nothing returns boolean
Custom script: local integer pdex = udg_UDex
Custom script: local integer ndex
-------- --------
-------- Recycle indices of units no longer in-play every (15) units created --------
-------- --------
Set UDexWasted = (UDexWasted + 1)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
UDexWasted Equal to 15
Then - Actions
Set UDexWasted = 0
Set UDex = UDexNext[0]
Custom script: loop
Custom script: exitwhen udg_UDex == 0
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Custom value of UDexUnits[UDex]) Equal to 0
Then - Actions
-------- --------
-------- Remove index from linked list --------
-------- --------
Custom script: set ndex = udg_UDexNext[udg_UDex]
Custom script: set udg_UDexNext[udg_UDexPrev[udg_UDex]] = ndex
Custom script: set udg_UDexPrev[ndex] = udg_UDexPrev[udg_UDex]
Set UDexPrev[UDex] = 0
-------- --------
-------- Fire deindex event for UDex --------
-------- --------
Set UnitIndexEvent = 2.00
Set UnitIndexEvent = 0.00
-------- --------
-------- Recycle the index for later use --------
-------- --------
Set UDexUnits[UDex] = No unit
Set UDexNext[UDex] = UDexRecycle
Set UDexRecycle = UDex
Custom script: set udg_UDex = ndex
Else - Actions
Set UDex = UDexNext[UDex]
Custom script: endloop
Custom script: set udg_UDex = pdex
Else - Actions
-------- --------
-------- Handle the entering unit (Matching unit) --------
-------- --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Custom value of (Matching unit)) Equal to 0
Then - Actions
Custom script: call IndexUnit()
Else - Actions
Custom script: return false
Custom script: endfunction
-------- --------
-------- The next function initializes the core of the system --------
-------- --------
Custom script: function InitializeUnitIndexer takes nothing returns nothing
Custom script: local integer i = 0
Custom script: local region re = CreateRegion()
Custom script: local rect r = GetWorldBounds()
Set UnitIndexerEnabled = True
Custom script: call RegionAddRect(re, r)
Custom script: call TriggerRegisterEnterRegion(CreateTrigger(), re, Filter(function IndexNewUnit))
Custom script: call RemoveRect(r)
Custom script: set re = null
Custom script: set r = null
Custom script: loop
Custom script: call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), Filter(function IndexUnit))
Custom script: set i = i + 1
Custom script: exitwhen i == 16
Custom script: endloop
-------- --------
-------- This is the "Unit Indexer Initialized" event, use it instead of "Map Initialization" for best results --------
-------- --------
Set UnitIndexEvent = 3.00
Set UnitIndexEvent = 0.00

How to take advantage of UnitIndexEvent

So if you want to have an event fire when a unit is created, when it is leaves the game, or when the unit indexer is initialized, you should take advantage of the UnitIndexEvent real variable.

Unit Indexed Event
Events
Game - UnitIndexEvent becomes Equal to 1.00
Conditions
UDexUnits[UDex] is A Hero Equal To true
Actions
Item - Create 1 Tome of Power and give it to UDexUnits[UDex]

Unit Deindexed Event
Events
Game - UnitIndexEvent becomes Equal to 2.00
Conditions
Actions
Game - Display to (All Players) the text - Unit (UDex) was deindexed!

Unit Indexer Initialized Event
Events
Game - UnitIndexEvent becomes Equal to 3.00
Conditions
Actions
Unit - Create 1 Paladin for (Player 1) at TempPoint facing 0.00 degrees
Item - Create 1 Ankh of Reincarnation and give it to (Last created unit)
Set HeroItem[(Custom value of (Last created unit))] = (Last created item)



Thanks
Nestharus for creating the powerful vJass UnitIndexer.
The community for encouraging me to use a unit indexer when I was learning.
Examples of scripts using this
Spell Template (build MUI spells with Unit Indexer)
Unit Event
Is Unit Moving
DamageEvent and DamageModifier
Cloud Spiral
Inferno Stride
Pros
  • Gives units a unique custom value for use as array indexes (1-8190)
  • Recycles indexes of decayed/removed units
  • Very extensible library that can be used for not just spells but systems as well.
  • Extremely easy to implement (cnp)
  • No object editor data needed
  • Does not need a timer
  • No knowledge of JASS required. You can toggle the boolean UnitIndexerEnabled to filter unwanted units, and you can even customize the filter with more conditions than just that if you want to do something like filter summoned units or not allow any units to be indexed with locust, for example.
  • Has "OnIndex" (UnitIndexEvent == 1.00) and "OnDeindex" (UnitIndexEvent == 2.00) events

Cons
  • You can only get the custom value of units, not set it. Work with the unit indexer - not
    against it. You can easily create an array and reference all the data you need (custom value of unit as the array index) instead of using custom value directly.
  • Use the event - "Game - UnitIndexEvent Equal to 3.00" instead of "Map Initialization" if you want to make sure all of your units have custom value when used in that trigger's actions.
  • Units are not "in scope" when deindexed, so things like checking if it's summoned or if it's a hero will not work. Use the seperate resource "Unit Event" with the event "DeathEvent becomes Equal to 3.00" to catch a unit as soon as it's removed.
Rating - 5.00 (7 votes)
(Hover and click)
Moderator Comments
Highly Recommended
16:29, 28th Jun 2011
Maker: Approved. Can be of great use in creating MUI spells and systems.

This spell is approved and works properly.


Download Unit Indexer with events.w3x
(21.76 KB, 515 Downloads)

Old 06-14-2011, 02:12 PM   #2 (permalink)
Registered User nafre
Face Palm
 
nafre's Avatar
 
Join Date: Oct 2010
Posts: 193
nafre has little to show at this moment (25)nafre has little to show at this moment (25)nafre has little to show at this moment (25)
Does this mean that this trigger can count units for you and give the unit a special code?
__________________
LoL Anime


nafre is offline   Reply With Quote
Old 06-14-2011, 02:27 PM   #3 (permalink)
Forum Moderator Bribe
Keep it simple
 
Bribe's Avatar
Spells, Help Zones & JASS Moderator
 
Join Date: Sep 2009
Posts: 5,581
Bribe has much of which to be proud (1209)Bribe has much of which to be proud (1209)
PayPal Donor: This user has donated to The Hive. 
If you mean counting how many units are in the map at once, no this is not what it's used for.

The custom value of the unit is a mere integer used in array lookups to make indexing more automated (user-friendly).

Set MyData[(Custom value of (Triggering unit))] = 1000

^The above example effectively allows you assign "1000" to the unit as a pseudo-attribute. Normally in this case, data attachment would involve hashtables.
__________________
How to post your triggers on the Hive Workshop.
JPAG - Bettering the cause of readable source code.

Bribe is offline   Reply With Quote
Old 06-14-2011, 03:02 PM   #4 (permalink)
Forum Moderator Magtheridon96
JESUS MAN
 
Magtheridon96's Avatar
Resource Moderator
 
Join Date: Dec 2008
Posts: 5,700
Magtheridon96 has a brilliant future (1809)
Merit Badge - Level 0: This user has proven to be extremely valuable to the Warcraft III Modding Community. 
This really deserves a DC
A UnitIndexer is ok, but a UnitIndexer for GUIers?? That is above and beyond :)
The only problem is that some GUIers use custom values for other stuff :P
If they do, it's their loss xD
Good Job dude sir Bribe :P 5/5 ^^
__________________
Magtheridon96 is offline   Reply With Quote
Old 06-14-2011, 03:16 PM   #5 (permalink)
Registered User baassee
MORE CONTESTS PLS
 
baassee's Avatar
 
Join Date: Nov 2008
Posts: 3,554
baassee is a splendid one to behold (845)baassee is a splendid one to behold (845)baassee is a splendid one to behold (845)baassee is a splendid one to behold (845)baassee is a splendid one to behold (845)
LOL what is this?! You know that GUIers doesn't use unit indexers for some what unknown reason.

The filter should filter out units with locust btw.
__________________
Nobody dies a virgin, life fucks us all. - Master Arena is alive! v4.0 in construction. - Dr Super Good for president! - Sorry derps but I do not do requests unless they prove themselves worthy of my time.
My Resources! - Help me out with my project! - How To Import vJASS spells tutorial! - Practice makes perf... improves you.
Quote:
Originally Posted by Marc Mamales View Post
Hey guys, please fix my spells, cz i dont know how to make it GUI.
baassee is offline   Reply With Quote
Old 06-14-2011, 03:32 PM   #6 (permalink)
Forum Moderator Bribe
Keep it simple
 
Bribe's Avatar
Spells, Help Zones & JASS Moderator
 
Join Date: Sep 2009
Posts: 5,581
Bribe has much of which to be proud (1209)Bribe has much of which to be proud (1209)
PayPal Donor: This user has donated to The Hive. 
It intentionally enumerates units with locust, because dummy units like projectiles can benefit from indexes.

However, I should make it clearer what users can add to make it filter out unwanted units.

Jesus4Lyf used a very similar approach in his "GUI AIDS" so I cannot take credit for the idea. This is simply a different implementation and has some pros and cons against his:

Jesus4Lyf

- Uses a timer throughout the game to check if units should be removed
- As a consequence, only removes up to 32 dead instances per second, making it (in a stretch of the imagination) possible that the digit 8190 can be exceeded (more a logical problem than a practical one)
- Ends up being more efficient when units are created
- Pretty easy to implement (3 sets of cnp)
Bribe

- Checks for removed units only when a new unit is added to the map
- Does a quick iteration over all indexed units each time a unit is added
- Ends up being more efficient over the course of the game, using fewer handles
- Easier to implement (two cnp instead of 3)
__________________
How to post your triggers on the Hive Workshop.
JPAG - Bettering the cause of readable source code.

Bribe is offline   Reply With Quote
Old 06-14-2011, 03:39 PM   #7 (permalink)
Registered User baassee
MORE CONTESTS PLS
 
baassee's Avatar
 
Join Date: Nov 2008
Posts: 3,554
baassee is a splendid one to behold (845)baassee is a splendid one to behold (845)baassee is a splendid one to behold (845)baassee is a splendid one to behold (845)baassee is a splendid one to behold (845)
But the timer option in AIDS is optional from my experience. Else it uses the classic "undefend" ability to detect leave/removed instances.

Yeah you're probably right about the dummies now when I think about it, GUIers will gain alot by this.

Does the userdata always return 0 when a unit is removed/decayed? Cool.
__________________
Nobody dies a virgin, life fucks us all. - Master Arena is alive! v4.0 in construction. - Dr Super Good for president! - Sorry derps but I do not do requests unless they prove themselves worthy of my time.
My Resources! - Help me out with my project! - How To Import vJASS spells tutorial! - Practice makes perf... improves you.
Quote:
Originally Posted by Marc Mamales View Post
Hey guys, please fix my spells, cz i dont know how to make it GUI.
baassee is offline   Reply With Quote
Old 06-14-2011, 03:43 PM   #8 (permalink)
Forum Moderator Bribe
Keep it simple
 
Bribe's Avatar
Spells, Help Zones & JASS Moderator
 
Join Date: Sep 2009
Posts: 5,581
Bribe has much of which to be proud (1209)Bribe has much of which to be proud (1209)
PayPal Donor: This user has donated to The Hive. 
His GUI version of AIDS only uses a timer, it doesn't have an option for the undefend bug.

GetUnitUserData returns 0 for null/removed/decayed units. The wc3 system does some internal deallocation when units pass from scope - an event Blizzard forgot couldn't be bothered with to give us access to.
__________________
How to post your triggers on the Hive Workshop.
JPAG - Bettering the cause of readable source code.

Bribe is offline   Reply With Quote
Old 06-15-2011, 04:10 AM   #9 (permalink)
Registered User Jazztastic
Buddy
 
Jazztastic's Avatar
 
Join Date: Apr 2011
Posts: 955
Jazztastic is just really nice (305)Jazztastic is just really nice (305)
I'm really, really confused by this. But from what I gather, this replaces hashtables right? So you could put the custom value of whatever unit in a spell, and it will make it MUI, so long as you don't have 8190 units on the field, right? If that's what it does only problem I see with it is that is uses custom values. A lot of system use custom values
Jazztastic is offline   Reply With Quote
Old 06-15-2011, 04:31 AM   #10 (permalink)
Registered User Nestharus
User
 
Nestharus's Avatar
 
Join Date: Jul 2007
Posts: 4,910
Nestharus has disabled reputation
Quote:
A lot of system use custom values
Those other systems shouldn't be using SetUnitUserData , but should rather just be assuming that a unit indexer is in the map and make use of GetUnitUserData

= )
__________________

Anime-Planet.com - anime | manga | reviews
Nestharus is offline   Reply With Quote
Old 06-15-2011, 07:11 AM   #11 (permalink)
Forum Moderator Bribe
Keep it simple
 
Bribe's Avatar
Spells, Help Zones & JASS Moderator
 
Join Date: Sep 2009
Posts: 5,581
Bribe has much of which to be proud (1209)Bribe has much of which to be proud (1209)
PayPal Donor: This user has donated to The Hive. 
Update to 1.0.0.1 - added an optional filter and an optional initializer.

Before, it was unclear how to filter units.
Now, you can filter units from the UnitIndexFilter function in the custom script.

Before, if you needed to get the custom value of a unit during map initialization, it may have returned zero.
Now, you can run any of those triggers from the designated spot in the Unit Indexer trigger (where it says "run initialization triggers after this line").

With these changes, this system is now perfect unless the user calls SetUnitUserData (sets the custom value of the unit) themselves. However, users should not be doing that if they want to use this system (only calling GetUnitUserData).

Finally, no map that exceeds 8190 units can be taken seriously. The array limit in that case is out of the question.
__________________
How to post your triggers on the Hive Workshop.
JPAG - Bettering the cause of readable source code.

Bribe is offline   Reply With Quote
Old 06-15-2011, 09:20 AM   #12 (permalink)
Registered User nafre
Face Palm
 
nafre's Avatar
 
Join Date: Oct 2010
Posts: 193
nafre has little to show at this moment (25)nafre has little to show at this moment (25)nafre has little to show at this moment (25)
i still do not understand what does a indexer do? Could someone explain this a little more if you have the time?
__________________
LoL Anime


nafre is offline   Reply With Quote
Old 06-15-2011, 09:22 AM   #13 (permalink)
Registered User Nestharus
User
 
Nestharus's Avatar
 
Join Date: Jul 2007
Posts: 4,910
Nestharus has disabled reputation
It gives each unit a unique id that can be used as an array index.


So rather than (hashtable)

SaveInteger(table,GetHandleId(unit),0,value)

you can do (array)

set a[GetUnitUserData(unit)]=value
__________________

Anime-Planet.com - anime | manga | reviews
Nestharus is offline   Reply With Quote
Old 06-17-2011, 09:42 AM   #14 (permalink)
Forum Moderator Bribe
Keep it simple
 
Bribe's Avatar
Spells, Help Zones & JASS Moderator
 
Join Date: Sep 2009
Posts: 5,581
Bribe has much of which to be proud (1209)Bribe has much of which to be proud (1209)
PayPal Donor: This user has donated to The Hive. 
Updated description with a short text on why unit indexing is important.
__________________
How to post your triggers on the Hive Workshop.
JPAG - Bettering the cause of readable source code.

Bribe is offline   Reply With Quote
Old 06-19-2011, 04:29 PM   #15 (permalink)
Registered User tenchisouzou
User
 
Join Date: Oct 2008
Posts: 17
tenchisouzou has little to show at this moment (2)
hi i'm new to mapping and am having trouble on how to use this system in my map.

i followed the steps and added the system to my map.

i didn't edit anything, i.e, Unit Indexer trig and the jass script located on map name.

i tried setting custom integer variable to triggering units custom variable to my spell

and when i try to multi cast the spell with 2 different units with 2 different custom values, it doesn't work. The last casted spell overwrites the first one.

could someone help me fix this?

i have attached the map to this post.

thanks =)
Attached Files
File Type: w3x TestMap.w3x (74.9 KB, 90 views)

Last edited by tenchisouzou; 06-19-2011 at 04:32 PM. Reason: wrong attachment
tenchisouzou is offline   Reply With Quote
Reply

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off


All times are GMT. The time now is 12:01 AM.





Powered by vBulletin
Copyright 2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.5.1 PL2
Copyright © Ralle