• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Unit Indexer v5.3.0.1

Unit Indexer
v5.3.0.1
by Nestharus
__

[td]

Unit Indexer is a next gen unit indexing system that uses a variety of modern JASS techniques to improve performance and enable
cool new features. It is unlike any other unit indexing system out there.

The system includes three different types of modules with varying levels of support, ranging from the simplest classic
style module to the newest and most complex module. All modules are adaptive and will only include features when those
features are used.

The classic Unit Indexer system is also included.
____________________________________________________________________________________________________
Features

Powerful Events

In-Depth Tutorial With Labs



  • Global events
  • Local events
  • Phases
  • Struct events
  • Correct execution order of events
  • Specialized recycling so that locks are no longer needed
  • Instant unit destruction detection
____________________________________________________________________________________________________


There are 8 tutorials and 15 labs that cover all of the features of Unit Indexer. There is also a quick installation tutorial and all required
resources are included in the map. Furthermore, the installation tutorial shows two ways of installing the system into a map.
____________________________________________________________________________________________________
Additional Information

Change Log


v5.x


[td]
Complete revamp of the entire Unit Indexer system.
____________________________________________________________________________________________________
.
[/td]

Change Log

Author's Notes

v5.x

Older Versions


____________________________________________________________________________________________________

Known Issues
  • Module code needs to be cleaned up a bit to reduce code generation by a little bit more
  • A dependency, Trigger, needs to be changed to be bit faster (use a different data structure)
____________________________________________________________________________________________________
[/td]

Keywords:
unit indexer
Contents

Just another Warcraft III map (Map)

Reviews
14:59, 10th Mar 2015 IcemanBo: A very large scale UnitIndexer with many dependencies. The system is very powerful and is written highly efficient. It works just nice. Approved.

Moderator

M

Moderator

14:59, 10th Mar 2015
IcemanBo:

A very large scale UnitIndexer with many dependencies.
The system is very powerful and is written highly efficient. It works just nice.

Approved.
 

Deleted member 219079

D

Deleted member 219079

An upload by Nestharus? o.o

Can ye upload the code here?
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
I dont want to sound like plain hater, but if you need to provide 15 labs to show how to use something as simple as Unit Indexer, there is something wrong

There are many new features that aren't in the classic Unit Indexer. To go over all of them, it indeed takes quite a bit. However, classic Unit Indexer features are covered in I think the first 1-2 labs (some of the labs are very short, so I may have spread it over 2).


Before you judge, go through the labs and stuff. They're actually pretty quick : ).


The simplest use is still just installing it and then using GetUnitUserData hehehe, but I'd cry if that's all anyone ever did : (

this system is very useful,, like :D

Thanks
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
Im really not a fan of ALL UnitIndexers, and never will but for those people who do not understand what UI is, it's a simple mechanic;
- Preplaced Units (if not all) will be automatically indexed up to 8190
- Units entering map will also be indexed
- When unit dies (or maybe some certain situations), it will be deindexed

Simple ey and a simple UI will do...
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Unit indexers are indeed that simple. They get more complicated when you want index and deindex events ^_^.

Look at the screenshot : ). You might notice something interesting about the order of execution there. A simple unit indexer can't achieve that ';.;'.

It's just like in c++. On creation, you run in order from the first to the last. On destruction, you run in reverse order. Unit Indexer handles things like scope of an event, allowing you to define multiple stages of creation/destruction. It also differentiates between events that are unique to a single unit (local) and events that are applied to all units (global).


There have been several evolutions of unit indexers

1. PUI - user tells the system what to index and when to do it. Nothing automatic.
2. AutoIndex - automatic indexing/deindexing.
3. AIDS - locks
4. First Unit Indexer - access to unit handle on deindex + smart modules
5. 4th Unit Indexer - drop locks and use a queue instead of a stack for recycling
6. 5th Unit Indexer - supports intricate event setups


Events have also undergone changes over the years, starting from simple global events to prioritized events to weird mixes between sorta local and global events (does not mix well) to finally true local events (mixes well).



Certainly, you can go for the simplest thing possible like PUI. You might take it a small step forward and go for automatic indexing/deindexing, and maybe one step further for simple global events, or event a step further for locks. This is just the latest evolution =).


Who really needs all of this stuff though?! O_O

Well, actually, almost everyone does. Whenever you see an if-statement in a global deindex event so that it will only apply to "correct" units, that should really be a local deindex event. From a performance standpoint, you are running the event way more often than you need to. From an execution order standpoint, the events aren't necessarily run in the correct order. Some things may be destroyed that other things depend on. There are just a whole slew of issues that can crop up. All of these issues have to be accounted for, which complicates the user code =). Wouldn't it be nice if all you had to do was write 3 lines and all of it was taken care of? The data structure that events are built out of automatically run things in the correct order + support local events.


Users can work with plain old JASS if they want to. vJASS makes things easier, just like a nice Unit Indexer makes things easier.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
You don't want to use the old one. I mean you can use the old one if you really want to, but you should use this.


Right now I'm in the process of updating BooleanExpression/Trigger to make this even better. I cut down the code of BooleanExpression from 1300 lines to 500 lines, improved operation, and improved execution performance. APIs will not change, so Unit Indexer won't change, but the stuff included in this pack will change (version updates).
 
Ok just looked through your system
It seems pretty straight forward and easy for me to follow so well done on that :p

But just a quick question
Is it possible to get an allocated ID of a unit without looping through every unit to check if it's the right one without using
Set/GetUnitUserData?

As far as I heard it's not acceptable to use with approvable code for public use the the Spells and Jass section cause it can get messy when mixed with others codes

I could really go for an alternative


All that I'm able to do with my own system atm is to do it reverse and get the unit with an ID using arrays and my own indexing methods


Edit: You seem to be using the UnitUserData natives in your code, so I presume it's fine if I do so to for unit indexing of my own?

I really wish that Unit User Data could be used localy in struct and the sort for safety reasons :I
 
Last edited:
Ah yes, thanks
I have made some code before that uses indexes of arrays off of other indexes so I've thought of that before (not easy to make from scratch at first with full compatible index/deindex functions haha)

I'll probably make a note or something with any (v)Jass resources I release with something along the lines of using static ifs if I end up using Unit User Value's on units
 
Level 11
Joined
Dec 3, 2011
Messages
366
Hello Nes,

I'm using your DDS but Idk why this code doesn't work

JASS:
library UnitEvent uses Event, Trigger, Init, Type, GroupUtils
    globals
        constant real HIT_POINT_VERYLOW_PERCENT = 0.1
        constant real HIT_POINT_LOW_PERCENT = 0.2
        constant real HIT_POINT_MEDIUM_PERCENT = 0.5
        constant real HIT_POINT_HIGH_PERCENT = 0.8
        
    endglobals

    native UnitAlive takes unit u returns boolean
    
    struct UnitEvent extends array
        static Event ENTER_COMBAT
        static Event LEAVE_COMBAT
        static real LOOP_PERIOD = 0.03125
        static unit TriggerUnit
        static TypeReal CombatTimer
        static real CombatDuration = 5
        static timer MainTimer = CreateTimer()
        static group CombatGroup
        
        implement GlobalUnitIndex
        implement DDS
        
        private method onDamage takes nothing returns nothing
            set TriggerUnit = unit
            call BJDebugMsg(GetUnitName(unit) + " enter combat!")
            if CombatTimer[this] > 0 then
                set CombatTimer[this] = CombatDuration
            else
                call ENTER_COMBAT.fire()
            endif
        endmethod
        
        private static method onEnumGroup takes nothing returns nothing
            local unit enumUnit = GetEnumUnit()
            local thistype this = thistype[enumUnit]
            if UnitAlive(enumUnit) then
                if CombatTimer[this] > 0 then
                    set CombatTimer[this] = CombatTimer[this] - LOOP_PERIOD
                else
                    set CombatTimer[this] = 0
                    set TriggerUnit = enumUnit
                    call LEAVE_COMBAT.fire()
                    call GroupRemoveUnit(CombatGroup, enumUnit)
                endif
            endif
        endmethod
        
        private static method onLoop takes nothing returns nothing
            call ForGroup(CombatGroup, function thistype.onEnumGroup)
        endmethod
        
        static method onInit takes nothing returns nothing
            set ENTER_COMBAT = Event.create()
            set LEAVE_COMBAT = Event.create()
            set CombatTimer = TypeReal.create()
            set CombatGroup = NewGroup()
            call TimerStart(MainTimer, LOOP_PERIOD, true, function thistype.onLoop)
        endmethod
    endstruct
    
    function IsUnitInCombat takes unit u returns boolean
        return UnitEvent.CombatTimer[UnitEvent[u]] > 0
    endfunction
    
    function GetTriggerCombatUnit takes nothing returns unit
        return UnitEvent.TriggerUnit
    endfunction
    
    function RegisterEnterCombatEvent takes boolexpr b returns nothing
        call UnitEvent.ENTER_COMBAT.register(b)
    endfunction
    
    function RegisterLeaveCombatEvent takes boolexpr b returns nothing
        call UnitEvent.LEAVE_COMBAT.register(b)
    endfunction

endlibrary
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Firstly, whenever there are callbacks, always implement modules at the bottom of the struct ; ).

As for DDS, right now it needs to be rewritten in the backend stuff because the health event doesn't work with very low health amounts. I need to find a good work around. The trigger just doesn't register the changes : \. I will fix it, not to worry ; ). I can certainly detect when the trigger isn't going to register damage. In those cases, I can probably use a timer safely because the damage will be so darn low.

This bug is likely the problem : (. I'll fix it, I promise : ).

I am happy that you decided to give my DDS a try though ^_-.
 
Level 11
Joined
Dec 3, 2011
Messages
366
Firstly, whenever there are callbacks, always implement modules at the bottom of the struct ; ).

As for DDS, right now it needs to be rewritten in the backend stuff because the health event doesn't work with very low health amounts. I need to find a good work around. The trigger just doesn't register the changes : \. I will fix it, not to worry ; ). I can certainly detect when the trigger isn't going to register damage. In those cases, I can probably use a timer safely because the damage will be so darn low.

This bug is likely the problem : (. I'll fix it, I promise : ).

I am happy that you decided to give my DDS a try though ^_-.

Arghhhhh, I forget. Your Event not fit with your new Trigger coz boolean reversed LOL
 
Level 11
Joined
Dec 3, 2011
Messages
366
I'll work on this stuff today =)
Totally:
- Fix DDS test map in your Github :ogre_frown:
- Fix Unit Indexer test example
- Event must be fixed. When I test map
JASS:
        static method onInit takes nothing returns nothing
            
            set ENTER_COMBAT = Event.create()
            set LEAVE_COMBAT = Event.create()
            call BJDebugMsg("test")
            set CombatTimer = TypeReal.create()
            set CombatGroup = CreateGroup()
            
            call TimerStart(MainTimer, LOOP_PERIOD, true, function thistype.onLoop)
        endmethod

JASS:
call BJDebugMsg("test")
It didn't run. Idk why but I think Event bug.
Event in Github doesn't fit with new Trigger.


Last, I prefer to use your DDS and UI because It work very good in struct :ogre_love:

Anyway, thank you Nes :ogre_kawaii:
 
Top