[Snippet] Simple Unit Indexer

Scripts

13 years
edited 8 years
Description


This library aims to provide a simple way to attach data to units via unit indexing. It offers the minimal functions required to work. This library is the result of thinking about this proposal.

Requirements:


- Alloc 2

Actual Code

Code (jass) Select
1
/******************************************************************
2
*                    SIMPLE UNIT INDEXER V1.3                     *
3
*                           By moyack                             *
4
*                              2012                               *
5
*              ===================================                *
6
*              Exclusive resource from wc3jass.com                *
7
*              ===================================                *
8
******************************************************************/
9
library UnitIndexer initializer init requires Alloc
10
/*
11
  PURPOSE: Index units for easy attacking data to them
12
  
13
  FUNCTIONS:
14
   - GetUnitIndex: Takes a unit and returns its index (integer)
15
   - GetIndexUnit: Takes an integer and returns the unit indexed
16
     with that integer.
17
18
   The following functions are meant to be used when a unit is about
19
   to be deindexed and removed from the game, via RemoveUnit() or when
20
   it dies.
21
   
22
   - AddUnitEndEventCondition: Adds a contitional boolexpr variable
23
   - AddUnitEndEventAction:    Adds an action code
24
   - GetDeindexedIndex:        Returns the index of the removed unit
25
   - GetDeindexedUnit:         Returns the unit about to remove
26
  
27
  ADVANTAGES:
28
   - Very easy to use
29
   - Inline friendly
30
   - It uses arrays instead of Hashtables
31
   - You can set the max amount of units in your map.
32
33
  DISADVANTAGE:
34
   - Uses Unit's user data, so if in your map you use this feature in
35
     your units, this system will put issues.
36
     
37
  CONFIGURATION: "SIZE" Constant.
38
  Here you can define the maximum amount of units that your game will manage.
39
  If you REAAALLLY need that, please set the SIZE variable with the required 
40
  amount, else DO NOT MODIFY ANYTHING.
41
  
42
  CREDITS:
43
   - Magtheridon96 & Troll-Brain for his nice support and help me notice some
44
     flaws in the code.
45
*/
46
globals
47
    private constant integer SIZE = 8190 // Here you set the array size, just if you need it, ok??
48
    private          integer I    = 0    // Stores the deallocated unit index...
49
    private          unit    U    = null // Stores the deallocated unit...
50
    private          trigger T    = null // a trigger which will be fired when a unit is deallocated.
51
endglobals
52
53
private struct data extends array [SIZE]
54
    unit u
55
    
56
    implement Alloc
57
    
58
    method destroy takes nothing returns nothing
59
        set I = this
60
        set U = .u
61
        if T != null then
62
            if TriggerEvaluate(T) then
63
                call TriggerExecute(T)
64
            endif
65
        endif
66
        call SetUnitUserData(.u, 0)
67
        set .u = null
68
        call .deallocate()
69
    endmethod
70
    
71
    static method create takes unit u returns thistype
72
        local thistype this
73
        if GetUnitUserData(u) < 1 then
74
            set this = thistype.allocate()
75
            call SetUnitUserData(u, integer(this))
76
        else
77
            set this = thistype(GetUnitUserData(u))
78
        endif
79
        set this.u = u
80
        return this
81
    endmethod
82
endstruct
83
84
// public functions
85
function GetUnitIndex takes unit u returns integer 
86
    return GetUnitUserData(u)
87
endfunction
88
89
function GetIndexUnit takes integer index returns unit
90
    return data(index).u
91
endfunction
92
93
function GetDeindexedIndex takes nothing returns integer
94
    return I
95
endfunction
96
97
function GetDeindexedUnit takes nothing returns unit
98
    return U
99
endfunction
100
101
function AddUnitEndEventCondition takes boolexpr b returns triggercondition
102
    if T == null then
103
        set T = CreateTrigger()
104
    endif
105
    return TriggerAddCondition(T, b)
106
endfunction
107
108
function AddUnitEndEventAction takes code c returns triggeraction
109
    if T == null then
110
        set T = CreateTrigger()
111
    endif
112
    return TriggerAddAction(T, c)
113
endfunction
114
// end public functions
115
116
private function ClearUnit takes unit u returns nothing
117
    call data(GetUnitIndex(u)).destroy()
118
endfunction
119
120
hook RemoveUnit ClearUnit
121
122
private function indexit takes nothing returns boolean
123
    return data.create(GetTriggerUnit()) < 0 // just to make it boolean :)
124
endfunction
125
126
private function indexit2 takes nothing returns boolean
127
    return data.create(GetFilterUnit()) < 0 // just to make it boolean :)
128
endfunction
129
130
private function dead takes nothing returns boolean
131
    if not IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
132
        call ClearUnit(GetTriggerUnit())
133
    endif
134
    return false
135
endfunction
136
137
private function init takes nothing returns nothing
138
    local trigger t = CreateTrigger()
139
    local rect r = GetWorldBounds()
140
    call TriggerRegisterEnterRectSimple(t, r)
141
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SUMMON)
142
    call TriggerAddCondition(t, Condition(function indexit))
143
    call GroupEnumUnitsInRect(bj_lastCreatedGroup, r, Condition(function indexit2))
144
    set t = CreateTrigger()
145
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
146
    call TriggerAddCondition(t, Condition(function dead))
147
    set t = null
148
    set r = null
149
endfunction
150
151
endlibrary


Changelog:

  • 1.0: Initial release.
  • 1.1: Added detection of units removed via RemoveUnit()
  • 1.2: Added detection of resurrected units.
  • 1.3: Added functionality to trigger a condition or a function when a unit is about to be removed from the game, via RemoveUnit() or when it dies. This can be useful when you need to do something with the unit about to be removed like clearing any data attachment done to it. I don't plan to add more features, only optimization unless a good reason makes merits to an addition.

Feel free to comment.
13 years
obviously indexing is bugged and deindexing just plain doesn't work

you're better off just having IndexUnit and DeindexUnit functions
13 years
Quote from: nestharus on December 12, 2012, 02:24:20 AM
obviously indexing is bugged and deindexing just plain doesn't work
I've checked and rechecked the code and I don't see where it bugs or fails. Is a scenario issue??

Quoteyou're better off just having IndexUnit and DeindexUnit functions
Well, the idea is that user don't worry about removing index, it should only worried to get the index or unit and use it.
13 years
What about calling RemoveUnit? :o
Your system would ignore units removed using RemoveUnit :/
13 years
edited 13 years
http://www.hiveworkshop.com/forums/2254876-post17.html

Also hook are quite useless in the current state :

- you can't use the function arguments of the hooked function, nor the returned value ...
- if you want to use the hooked function inside the hook (and it's the case there) you have to do some silly stuff to avoid infinite recursivity.

The only way where hooks are "useful" is for debug stuff.
13 years
Quote from: Troll-Brain on December 14, 2012, 12:29:21 PM
http://www.hiveworkshop.com/forums/2254876-post17.html

Also hook are quite useless in the current state :

- you can't use the function arguments of the hooked function, nor the returned value ...
- if you want to use the hooked function inside the hook (and it's the case there) you have to do some silly stuff to avoid infinite recursivity.

The only way where hooks are "useful" is for debug stuff.
Well, I was able to use hooks in the new version and it works like a charm. Please check first post and the test map.
13 years
edited 13 years
Frankly i don't really remember how hooks are "compiled", so i could be wrong before.
Anyway, that doesn't change my point of view about this resource (stated on hiveworkshop)

Also what about units which are resurrected with an active spell such as the Paladin's one ?
13 years
Quote from: Troll-Brain on January 05, 2013, 07:23:53 AM
Frankly i don't really remember how hooks are "compiled", so i could be wrong before.
Anyway, that doesn't change my point of view about this resource (stated on hiveworkshop)

Also what about units which are resurrected with an active spell such as the Paladin's one ?
Checked and updated. Thanks for your revision ;)
13 years
edited 13 years
Interesting, so such units trigger the summont event and it's equal to GetTriggerUnit ?
Also you should null the "u" member on deallocate.

DId i've already said that i think this library is pointless ? :p

EDIT : And meh you're doing it wrong, i would expect that an unit keep the same data until it is removed of the game, even if it dies, and then revives.
Actually it's not always the case. And the best way is to use the 'Adef' bug, so end of this resource ?
13 years
Quote from: Troll-Brain on January 07, 2013, 03:28:41 PM
Interesting, so such units trigger the summont event and it's equal to GetTriggerUnit ?
Also you should null the "u" member on deallocate.
Ok, added to 1.3...

QuoteDId i've already said that i think this library is pointless ? :p
In some way yes, but there's still some people who still loves to use this as attachment system... so I want to offer a simple version of this kind of tool.

QuoteEDIT : And meh you're doing it wrong, i would expect that an unit keep the same data until it is removed of the game, even if it dies, and then revives.
Actually it's not always the case. And the best way is to use the 'Adef' bug, so end of this resource ?
Well, I thought this but at the end we have this idea: if a unit dies, the script removes the use of attach something and anything attached to it should be removed. If you (for ANY chance) can revive it, then the script will reassign an index to use it.

Actually I'm going to make available this feature and I don't expect to add more features.
13 years
I'm not sure i understand what you meant, so i will wait for your update, but for now it sounds wrong on my ears.
13 years
I simply didn't understand what was your plan for the update.
Now as i expected it fails, because when an unit dead it lost its index and that's 100 % wrong, not only because it can be resurrected but because then you can't use corpses ...
Something like the demo spell i've made with my UnitLL resource will not work with your indexer behavior.

There is only 2 way for unit indexing : recycle periodically the ids (of removed units), or deindex it on remove "event", and this last one is much better because it gives you more possibilities and controls.
13 years
As Troll-Brain said, this needs to retain unit data while they're "out of scope".
The only cool way is by taking advantage of the Defend bug (Credits to all the Wc3c people involved in discovering it (I think PurplePoot or Anitarf mostly?))