• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

unit indexer attempt

Status
Not open for further replies.

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,184
A while ago I tried to create my own unit indexer and it -worked- more or less. However it had a really bad de-index system which prevented me from uploading it at all. So this is a new attempt, it's really nice because I don't have to do the dirty job. vJASS is kind enough to do it for me. I am -abusing- structs.

JASS:
globals
    x array ids
endglobals

struct x
    
    public static method create takes unit u returns x
        local x this = x.allocate()
        call BJDebugMsg(I2S(this))
        call SetUnitUserData( u, this )
        set ids[this] = this
        return this
    endmethod
    
    public method destroy takes nothing returns nothing
        call this.deallocate()
    endmethod
endstruct

  • Untitled Trigger 002
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
    • Actions
      • Custom script: local x b = x.create(GetTriggerUnit())
  • Untitled Trigger 004
    • Events
      • Unit - A unit Dies
      • Unit - A unit leaves (Playable map area)
    • Conditions
    • Actions
      • Set i = (Custom value of (Triggering unit))
      • Custom script: call ids[udg_i].destroy()

opinions? it's possible that this is extremely stupid but I am unaware of it somehow.
 
What you did is the heart of most unit indexers. It is perfectly fine to use a struct to index units.

As for the deindex, yours only accounts for units dying. When a unit is removed, there is no event to detect it. The only possibility is giving them a particular ability and catching the "undefend" order.

But if you are using it for your map, you know where units will be removed (i.e. wherever you use RemoveUnit()), so you can always just destroy the index there. IMO, that is a perfectly acceptable implementation.

Unit Indexers are actually incredibly simple at heart. They only become complicated if you want them to be (depending on what features you want).
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,184
really? and I thought I had come up with another method.. :p

I know of that possibility that's why I added the leaves region event I thought that would fix it. Also who uses remove unit anyway? I mean that leaks so people should use the add genetic timer anyway?

would a hook work as an solution there then? when RemoveUnit() is called remove the unit from the struct?
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
What you did is the heart of most unit indexers. It is perfectly fine to use a struct to index units.

As for the deindex, yours only accounts for units dying. When a unit is removed, there is no event to detect it. The only possibility is giving them a particular ability and catching the "undefend" order.

But if you are using it for your map, you know where units will be removed (i.e. wherever you use RemoveUnit()), so you can always just destroy the index there. IMO, that is a perfectly acceptable implementation.

Unit Indexers are actually incredibly simple at heart. They only become complicated if you want them to be (depending on what features you want).

So if I add this to my map, and a if statement on the first GUI trigger (for those units I want to filter out) I got myself a really short unit-indexer?
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,184
So if I add this to my map, and a if statement on the first GUI trigger (for those units I want to filter out) I got myself a really short unit-indexer?

I got a few test triggers in my map. So I have been killing units checking indexes after clearing 20 units etc then spawning new ones again. It seems to work fine.

If I ever release this I will likely merge the triggers together though. Either full vjass or one trigger for the struct and then merge the two GUI triggers only.
 
So if I add this to my map, and a if statement on the first GUI trigger (for those units I want to filter out) I got myself a really short unit-indexer?

Sort of. You also have to handle pre-placed units, iirc. And other indexers usually have events for when a unit is indexed or deindexed, so that is why they tend to be longer. But yes, apart from needing to index preplaced units, this would work fine if you just need to retrieve the unit indexes.

It is generally better to use Bribe's since it covers all the bases and is in just one trigger.
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,184
Get merge'd, since there's no reason for anyone to use it in it's old state I decided to go with an hashtable instead of custom value, this allows custom value to be used for something else in a map. So it could actually be useful for someone.

(much amaze
49615_doge_by_yokkan-d6uybh2.gif
)

  • Untitled Trigger 006
    • Events
      • Time - Elapsed game time is 0.00 seconds
      • Unit - A unit Dies
      • Unit - A unit enters (Playable map area)
    • Conditions
    • Actions
      • Custom script: local x b
      • Custom script: if GetTriggerEventId() == ConvertGameEvent(4) then
      • Hashtable - Create a hashtable
      • Set hash = (Last created hashtable)
      • Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
        • Loop - Actions
          • Custom script: local x b = x.create(GetEnumUnit())
      • Custom script: endif
      • Custom script: if GetTriggerEventId() == ConvertGameEvent(5) then
      • Custom script: set b = x.create(GetTriggerUnit())
      • Custom script: endif
      • Custom script: if GetTriggerEventId() == ConvertGameEvent(20) then
      • Custom script: set udg_i = LoadInteger(udg_hash, GetHandleId(GetTriggerUnit()), 1)
      • Custom script: call ids[udg_i].destroy()
      • Custom script: call FlushChildHashtable(udg_hash, GetHandleId(GetTriggerUnit()))
      • Custom script: endif
JASS:
globals
    x array ids
endglobals

struct x
    
    public static method create takes unit u returns x
        local x this = x.allocate()
        call SaveInteger(udg_hash, GetHandleId(u), 1, this)
        set ids[this] = this
        return this
    endmethod
    
    public method destroy takes nothing returns nothing
        call this.deallocate()
    endmethod
endstruct

edit: GUIified.
  • Untitled Trigger 006
    • Events
      • Time - Elapsed game time is 0.00 seconds
      • Unit - A unit Dies
      • Unit - A unit enters (Playable map area)
    • Conditions
    • Actions
      • Custom script: local x b
      • Custom script: local integer udg_handle
      • Custom script: if GetTriggerEventId() == ConvertGameEvent(4) then
      • Hashtable - Create a hashtable
      • Set hash = (Last created hashtable)
      • Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
        • Loop - Actions
          • Custom script: local x b
          • Set u = (Picked unit)
          • Custom script: set b = x.create(udg_u)
      • Custom script: endif
      • -------- --------------------------------- --------
      • -------- --------------------------------- --------
      • -------- --------------------------------- --------
      • Custom script: if GetTriggerEventId() == ConvertGameEvent(5) then
      • Set u = (Triggering unit)
      • Custom script: set b = x.create(udg_u)
      • Custom script: endif
      • -------- --------------------------------- --------
      • -------- --------------------------------- --------
      • -------- --------------------------------- --------
      • Custom script: if GetTriggerEventId() == ConvertGameEvent(20) then
      • Set handle = (Key (Triggering unit))
      • Set i = (Load 1 of handle from hash)
      • Custom script: call ids[udg_i].destroy()
      • Hashtable - Clear all child hashtables of child handle in hash
      • Custom script: endif
      • -------- --------------------------------- --------
      • -------- --------------------------------- --------
      • -------- --------------------------------- --------
      • Custom script: endfunction
      • Custom script: function GetId takes unit u returns integer
      • Custom script: set udg_handle = GetHandleId(u)
      • Set i = (Load 1 of handle from hash)
      • Custom script: return udg_i
JASS:
globals
    x array ids
endglobals

struct x
    
    public static method create takes unit u returns x
        local x this = x.allocate()
        call SaveInteger(udg_hash, GetHandleId(u), 1, this)
        set ids[this] = this
        return this
    endmethod
    
    public method destroy takes nothing returns nothing
        call this.deallocate()
    endmethod
endstruct
 
Last edited:
Status
Not open for further replies.
Top