1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Melee Mapping contest #3 - Poll is up! Vote for the best 4v4 melee maps!
    Dismiss Notice
  3. The 30th edition of the Modeling Contest is finally up! The Portable Buildings need your attention, so come along and have a blast!
    Dismiss Notice
  4. We have a new contest going on right now! Join the 11th Music Contest! You are to make a Cinematic modern sound-track for this contest, so come and compete with other people for fun.
    Dismiss Notice

GUI Unit Indexer 1.4.0.0

Submitted by Bribe
This bundle is marked as approved. It works and satisfies the submission rules.
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 core function - it provides an index all existing units and for units as they enter the map --------
      • -------- --------
      • Custom script: function IndexUnit takes nothing returns boolean
      • Custom script: local integer pdex = udg_UDex
      • Custom script: local integer ndex
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • IsUnitPreplaced[0] Equal to False
        • Then - Actions
          • -------- --------
          • -------- Check for removed units for every (32) new units created --------
          • -------- --------
          • Set UDexWasted = (UDexWasted + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • UDexWasted Equal to 32
            • 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
                  • Set IsUnitPreplaced[UDex] = False
                  • -------- --------
                  • -------- 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
            • Else - Actions
        • Else - Actions
      • -------- --------
      • -------- 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
          • (Custom value of (Matching unit)) Equal to 0
        • 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
          • Set IsUnitPreplaced[UDex] = IsUnitPreplaced[0]
          • -------- --------
          • -------- 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
        • Else - Actions
      • Custom script: set udg_UDex = pdex
      • 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()
      • Custom script: local boolexpr b = Filter(function IndexUnit)
      • Set UnitIndexEvent = -1.00
      • Set UnitIndexerEnabled = True
      • Set IsUnitPreplaced[0] = True
      • Custom script: call RegionAddRect(re, r)
      • Custom script: call TriggerRegisterEnterRegion(CreateTrigger(), re, b)
      • 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), b)
      • Custom script: set i = i + 1
      • Custom script: exitwhen i == bj_MAX_PLAYER_SLOTS
      • Custom script: endloop
      • Custom script: set b = null
      • -------- --------
      • -------- This is the "Unit Indexer Initialized" event, use it instead of "Map Initialization" for best results --------
      • -------- --------
      • Set IsUnitPreplaced[0] = False
      • Set UnitIndexEvent = 3.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

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.
Keywords:
unit indexer, custom value, aids, autoindex, getunituserdata, unituserdata, mui, indexing, is unit moving, unitindexer, indexer, index, id generator,
Contents

GUI Unit Indexer Testmap (Map)

Reviews
Moderator
16:29, 28th Jun 2011 Maker: Approved. Can be of great use in creating MUI spells and systems.
  1. NoBodyIsHere

    NoBodyIsHere

    Joined:
    Jul 8, 2017
    Messages:
    13
    Resources:
    0
    Resources:
    0
    Hi, I need a bit of help clarifying a couple of points because it's unclear to me:

    1. From what I've read, you basically can attach any specific data to any unit and refer to each of the data accurately. If so, is it possible to refer to the unit when it dies and if so, how? Via the 'UnitIndexEvent becomes equal to 2.00'?

    2. What variables do I use/not touch? I'm a little confused because of the names of the variables and that it doesn't really coincide with the example in the crash course. From what I can tell, UDex is for the custom value of the unit, but I'm a bit lost as to what to do from there.
     
    Last edited: Jul 11, 2018
  2. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    7,722
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    You can read from any of the values (ie. UDex, UDexUnits) however just don't set them to anything new. The system does that.

    If you want more control over events, use Unit Event. Unit Indexer gives the 2.00 event at any point after the unit was completely removed from the game (corpse and all).
     
  3. NoBodyIsHere

    NoBodyIsHere

    Joined:
    Jul 8, 2017
    Messages:
    13
    Resources:
    0
    Resources:
    0
    I feel stupid.... Can I bother you to post a short example trigger where you read off UDex/UDexUnits?
     
  4. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    7,722
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    • Trigger
      • Events
        • Game - value of UnitIndexEvent becomes equal to 1.00
      • Conditions
      • Actions
        • Game - display message to (All players) the text (Name of UDexUnits[UDex]
     
  5. NoBodyIsHere

    NoBodyIsHere

    Joined:
    Jul 8, 2017
    Messages:
    13
    Resources:
    0
    Resources:
    0
    Okay, I think I finally wrapped my head around how it works now.

    1 more question for now: Do you recommend creating a new variable and setting it to the custom value of the unit, or use the existing variable UDex and just work with it, seeing as it already has the custom value attached to it?

    I hope I'm not hassling you too much :(

    Thank you for the response!
     
  6. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    7,722
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Just use UDex, but keep in mind it won't work after a Wait or timer because by waiting then the event is already over.
     
  7. NoBodyIsHere

    NoBodyIsHere

    Joined:
    Jul 8, 2017
    Messages:
    13
    Resources:
    0
    Resources:
    0
    Does that also include periodic timers/events?
     
  8. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    7,722
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Here's the thing: an event is a single moment in time. It lasts for one thread (measured in nanoseconds). As soon as that moment has passed, the variables such as UDex default to 0 or whatever. Variables such as UDexUnits[] won't change, so all you need to remember is UDex (using another storage method like a List, Hashtable, whatever, or just get the custom value of whatever unit you need whenever you need.
     
  9. NoBodyIsHere

    NoBodyIsHere

    Joined:
    Jul 8, 2017
    Messages:
    13
    Resources:
    0
    Resources:
    0
    Ahhh, okay. It's a lot clearer for me now. I'll figure something out.

    Thank you very much!
     
  10. Devalut

    Devalut

    Joined:
    Feb 9, 2009
    Messages:
    395
    Resources:
    0
    Resources:
    0
    Bribe I love your systems