• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Spawn and Move

Status
Not open for further replies.
Level 4
Joined
Jan 27, 2020
Messages
51
Greetings to all! I want to create a region where the unit will be divided into two groups, and each group will move into two separate regions.
 
Level 12
Joined
Nov 13, 2010
Messages
277
you can use somthing like this. . ofc you need to set the custom value of the units
  • Untitled Trigger 001
    • Events
      • Unit - A unit enters Region 009 <gen>
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 7
        • Then - Actions
          • Unit - Order (Entering unit) to Attack-Move To (Center of Region 010 <gen>)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 1
        • Then - Actions
          • Unit - Order (Entering unit) to Attack-Move To (Center of Region 011 <gen>)
        • Else - Actions
 
Level 4
Joined
Jan 27, 2020
Messages
51
you can use somthing like this. . ofc you need to set the custom value of the units
  • Untitled Trigger 001
    • Events
      • Unit - A unit enters Region 009 <gen>
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 7
        • Then - Actions
          • Unit - Order (Entering unit) to Attack-Move To (Center of Region 010 <gen>)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 1
        • Then - Actions
          • Unit - Order (Entering unit) to Attack-Move To (Center of Region 011 <gen>)
        • Else - Actions
I dont seem understand the custom value. Can you provide me some explanation? Thank you.
 
Level 12
Joined
Nov 13, 2010
Messages
277
custom value of a unit can ba made like this and ofc there is more ways to do it then this 2 i just made here
  • Untitled Trigger 001
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of (Trained unit)) Equal to Player 1 (Red)
        • Then - Actions
          • Unit - Set the custom value of (Trained unit) to 7
        • Else - Actions
-
  • Untitled Trigger 002
    • Events
      • Time - Elapsed game time is 5.00 seconds
    • Conditions
    • Actions
      • Unit - Create 1 Footman for Player 1 (Red) at (Center of spawn <gen>) facing Default building facing degrees
      • Unit - Set the custom value of (Last created unit) to 7
 
Level 4
Joined
Jan 27, 2020
Messages
51
custom value of a unit can ba made like this and ofc there is more ways to do it then this 2 i just made here
  • Untitled Trigger 001
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of (Trained unit)) Equal to Player 1 (Red)
        • Then - Actions
          • Unit - Set the custom value of (Trained unit) to 7
        • Else - Actions
-
  • Untitled Trigger 002
    • Events
      • Time - Elapsed game time is 5.00 seconds
    • Conditions
    • Actions
      • Unit - Create 1 Footman for Player 1 (Red) at (Center of spawn <gen>) facing Default building facing degrees
      • Unit - Set the custom value of (Last created unit) to 7
It did not worked. What's wrong?
EDIT:
I tried removing the conditions, it did not work also.
The unit being spawned is 25 Gnoll Poacher
  • cut in half
    • Events
      • Unit - A unit enters Region 008 <gen>
    • Conditions
      • (Owner of (Entering unit)) Equal to Player 12 (Brown)
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 7
        • Then - Actions
          • Unit - Order (Entering unit) to Move To (Center of Region 009 <gen>)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 1
        • Then - Actions
          • Unit - Order (Entering unit) to Move To (Center of Region 010 <gen>)
        • Else - Actions
 
Level 4
Joined
Jan 27, 2020
Messages
51
how are Player 12 (Brown) units made ? are they been training or are they been Create ad a Region ?
In a region
EDIT:
The unit enters the region, and the 25 unit will be divided into 2 region.
Imagine like there's 20 unit in two regions, the 10 unit will be move to other region, and the 10 units will be move to other side/region
 
Last edited:
Level 12
Joined
Nov 13, 2010
Messages
277
well dont know how you have set up your create trigger but here is some ways to do it

nr 1 they spawn and get a custom value and gos to an region and then split up
  • Untitled Trigger 001
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Random = (Random integer number between 1 and 2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Random Equal to 1
        • Then - Actions
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
          • Unit - Set the custom value of (Last created unit) to 7
          • Unit - Order (Last created unit) to Attack-Move To (Center of Region 010 <gen>)
        • Else - Actions
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
          • Unit - Set the custom value of (Last created unit) to 1
          • Unit - Order (Last created unit) to Attack-Move To (Center of Region 010 <gen>)
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
-
  • Untitled Trigger 002
    • Events
      • Unit - A unit enters Region 010 <gen>
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 7
        • Then - Actions
          • Unit - Order (Entering unit) to Attack-Move To (Center of Region 011 <gen>)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 1
        • Then - Actions
          • Unit - Order (Entering unit) to Attack-Move To (Center of Region 012 <gen>)
        • Else - Actions
nr 2 they spawn and get a custom value and split up when they spawn
  • Untitled Trigger 001
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Random = (Random integer number between 1 and 2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Random Equal to 1
        • Then - Actions
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
          • Unit - Set the custom value of (Last created unit) to 7
          • Unit - Order (Last created unit) to Attack-Move To (Center of Region 010 <gen>)
        • Else - Actions
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
          • Unit - Set the custom value of (Last created unit) to 1
          • Unit - Order (Last created unit) to Attack-Move To (Center of Region 011 <gen>)
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
there is ofc more whays to do.
 
Level 28
Joined
Nov 25, 2021
Messages
507
Greetings to all! I want to create a region where the unit will be divided into two groups, and each group will move into two separate regions.

If I understand correctly, you want things to go like this, right?

1: A unit (let's call it A) enters a region.
2: Units from inside the region (let's call this unit group B1) will go to two different sides.

If Group B is freshly spawned when A enters the region, you can just spawn the units two times, add them to B1 the first time and the second time for a new group B2, then give an order for each group.

If Group B is pre-spawned, you can do a For-Do loop for about ten times, each time picking a random unit to add to B2, then remove from B1. Then order them like above.

Would be much easier to understand if I can write a trigger, but I'm not on PC rn.
 
Level 4
Joined
Jan 27, 2020
Messages
51
If I understand correctly, you want things to go like this, right?

1: A unit (let's call it A) enters a region.
2: Units from inside the region (let's call this unit group B1) will go to two different sides.

If Group B is freshly spawned when A enters the region, you can just spawn the units two times, add them to B1 the first time and the second time for a new group B2, then give an order for each group.

If Group B is pre-spawned, you can do a For-Do loop for about ten times, each time picking a random unit to add to B2, then remove from B1. Then order them like above.

Would be much easier to understand if I can write a trigger, but I'm not on PC rn.
I would appreciate if it was written in trigger. Thank you!
 
Level 4
Joined
Jan 27, 2020
Messages
51
well dont know how you have set up your create trigger but here is some ways to do it

nr 1 they spawn and get a custom value and gos to an region and then split up
  • Untitled Trigger 001
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Random = (Random integer number between 1 and 2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Random Equal to 1
        • Then - Actions
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
          • Unit - Set the custom value of (Last created unit) to 7
          • Unit - Order (Last created unit) to Attack-Move To (Center of Region 010 <gen>)
        • Else - Actions
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
          • Unit - Set the custom value of (Last created unit) to 1
          • Unit - Order (Last created unit) to Attack-Move To (Center of Region 010 <gen>)
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
-
  • Untitled Trigger 002
    • Events
      • Unit - A unit enters Region 010 <gen>
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 7
        • Then - Actions
          • Unit - Order (Entering unit) to Attack-Move To (Center of Region 011 <gen>)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Entering unit)) Equal to 1
        • Then - Actions
          • Unit - Order (Entering unit) to Attack-Move To (Center of Region 012 <gen>)
        • Else - Actions
nr 2 they spawn and get a custom value and split up when they spawn
  • Untitled Trigger 001
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Random = (Random integer number between 1 and 2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Random Equal to 1
        • Then - Actions
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
          • Unit - Set the custom value of (Last created unit) to 7
          • Unit - Order (Last created unit) to Attack-Move To (Center of Region 010 <gen>)
        • Else - Actions
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
          • Unit - Set the custom value of (Last created unit) to 1
          • Unit - Order (Last created unit) to Attack-Move To (Center of Region 011 <gen>)
          • Unit - Create 1 Footman for Player 12 (Brown) at (Center of spawn <gen>) facing Default building facing degrees
there is ofc more whays to do.
This will be more complicated in my trigger, because it has levels, and also there will be 3 more like this trigger.
Here my trigger
  • Create All Monsters
    • Events
    • Conditions
    • Actions
      • Unit - Create (monstersperlvl / 8) unitforlevel for Player 12 (Brown) at (Center of Side <gen>) facing Default building facing degrees
      • Unit - Create (monstersperlvl / 8) unitforlevel for Player 12 (Brown) at (Center of Bottom <gen>) facing Default building facing degrees
      • Unit - Create (monstersperlvl / 8) unitforlevel for Player 12 (Brown) at (Center of Top <gen>) facing Default building facing degrees
      • Unit - Create (monstersperlvl / 8) unitforlevel for Player 12 (Brown) at (Center of Side 2 <gen>) facing Default building facing degrees
----

  • Level 1
    • Events
      • Time - levelcountdown expires
    • Conditions
      • Level Equal to 0
      • betweenlevels Equal to True
    • Actions
      • Countdown Timer - Destroy (Last created timer window)
      • Set Level = 1
      • Set monstersperlvl = 200
      • Set unitforlevel = Gnoll Poacher
      • Set betweenlevels = False
      • Trigger - Run Create All Monsters <gen> (ignoring conditions)
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,869
I would avoid setting Custom Value yourself, there's a great system that uses Custom Value which will do exactly what you want but without any limitations:

The logic remains essentially the same as what polardude suggested, except that you now no longer need to Set Custom Value yourself (EVER!) and instead use Variable Arrays to save data to your Units. This essentially gives you access to infinite Custom Values per unit.

For example, here's how you would implement it into your map.

First things first, let's save our Regions in Region Array variables so we can easily reference them later on:
  • Events
    • Map initialization
  • Conditions
  • Actions
    • Set MonsterStart[1] = (Center of Side <gen>)
    • Set MonsterStart[2] = (Center of Side2 <gen>)
    • Set MonsterStart[3] = (Center of Top <gen>)
    • Set MonsterStart[4] = (Center of Bottom <gen>)
    • Set MonsterEnd[1] = (Center of SideEnd <gen>)
    • Set MonsterEnd[2] = (Center of SideEnd2 <gen>)
    • Set MonsterEnd[3] = (Center of TopEnd <gen>)
    • Set MonsterEnd[4] = (Center of BottomEnd <gen>)
We now have the Regions where our Monsters are created at (Start) and the Regions where they will attack-move to (End).

Now let's change our Create All Monsters trigger to use the Unit Indexer method:
  • Create All Monsters
    • Events
    • Conditions
    • Actions
      • For each (Integer MonsterIndex) from 1 to 4, do (Actions)
        • Loop - Actions
          • Unit - Create 1 unitforlvl for Player 12 (Brown) at (Center of MonsterStart[MonsterIndex]) facing Default building facing degrees
          • Set Monster = (Last created unit)
          • Set MonsterDestination[(Custom value of Monster)] = MonsterEnd[MonsterIndex]
          • Unit - Order Monster to Attack-Move To (Center of MonsterEnd[MonsterIndex])
We're using a For Loop to easily reference all four Regions at once. This will create 1 Monster per MonsterStart region and order them to Attack-Move to their respective MonsterEnd region. It will also save the End region to the Monster by using the MonsterDestination variable.

If you want to create multiple Monsters per Region then you can use a Unit Group to manage all of them at once:
  • Create All Monsters
    • Events
    • Conditions
    • Actions
      • For each (Integer MonsterIndex) from 1 to 4, do (Actions)
        • Loop - Actions
          • Unit - Create monstersperlvl unitforlvl for Player 12 (Brown) at (Center of MonsterStart[MonsterIndex]) facing Default building facing degrees
          • Unit Group - Pick every unit in (Last created unit group) and do (Actions)
            • Loop - Actions
              • Set Monster = (Picked unit)
              • Set MonsterDestination[(Custom value of Monster)] = MonsterEnd[MonsterIndex]
              • Unit - Order Monster to Attack-Move To (Center of MonsterEnd[MonsterIndex])
This will create X Monsters per MonsterStart region and order them to Attack-Move to their respective MonsterEnd region. It will also save the End region to the Monster by using the MonsterDestination variable.

Monster = Unit variable.
MonsterIndex = Integer variable.
MonsterStart = Region ARRAY variable.
MonsterEnd = Region ARRAY variable.
MonsterDestination = Region ARRAY variable.

But you probably want to change MonsterDestination to a different Region since your goal is to have them attack-move there later on:
  • Split Up Example
    • Events
      • Unit - A unit enters (some region)
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 12 (Brown)
    • Actions
      • Set Monster = (Triggering unit)
      • Unit - Order Monster to Attack-Move To (Center of MonsterDestination[(Custom value of Monster)])
If you have multiple elaborate paths for your monsters to travel along I would recommend using a Hashtable and saving data to the units with that. Also, this method doesn't address the memory leaks being created here. Ideally, you would have Point variables stored at each Region which you would reference instead of (Center of region).
 
Last edited:
Level 4
Joined
Jan 27, 2020
Messages
51
I would avoid setting Custom Value yourself, there's a great system that uses Custom Value which will do exactly what you want but without any limitations:

The logic remains essentially the same as what polardude suggested, except that you now no longer need to Set Custom Value yourself (EVER!) and instead use Variable Arrays to save data to your Units. This essentially gives you access to infinite Custom Values per unit.

For example, here's how you would implement it into your map.

First things first, let's save our Regions in Region Array variables so we can easily reference them later on:
  • Events
    • Map initialization
  • Conditions
  • Actions
    • Set MonsterStart[1] = (Center of Side <gen>)
    • Set MonsterStart[2] = (Center of Side2 <gen>)
    • Set MonsterStart[3] = (Center of Top <gen>)
    • Set MonsterStart[4] = (Center of Bottom <gen>)
    • Set MonsterEnd[1] = (Center of SideEnd <gen>)
    • Set MonsterEnd[2] = (Center of SideEnd2 <gen>)
    • Set MonsterEnd[3] = (Center of TopEnd <gen>)
    • Set MonsterEnd[4] = (Center of BottomEnd <gen>)
We now have the Regions where our Monsters are created at (Start) and the Regions where they will attack-move to (End).

Now let's change our Create All Monsters trigger to use the Unit Indexer method:
  • Create All Monsters
    • Events
    • Conditions
    • Actions
      • For each (Integer MonsterIndex) from 1 to 4, do (Actions)
        • Loop - Actions
          • Unit - Create 1 unitforlvl for Player 12 (Brown) at (Center of MonsterStart[MonsterIndex]) facing Default building facing degrees
          • Set Monster = (Last created unit)
          • Set MonsterDestination[(Custom value of Monster)] = MonsterEnd[MonsterIndex]
          • Unit - Order Monster to Attack-Move To (Center of MonsterEnd[MonsterIndex])
We're using a For Loop to easily reference all four Regions at once. This will create 1 Monster per MonsterStart region and order them to Attack-Move to their respective MonsterEnd region. It will also save the End region to the Monster by using the MonsterDestination variable.

If you want to create multiple Monsters per Region then you can use a Unit Group to manage all of them at once:
  • Create All Monsters
    • Events
    • Conditions
    • Actions
      • For each (Integer MonsterIndex) from 1 to 4, do (Actions)
        • Loop - Actions
          • Unit - Create monstersperlvl unitforlvl for Player 12 (Brown) at (Center of MonsterStart[MonsterIndex]) facing Default building facing degrees
          • Unit Group - Pick every unit in (Last created unit group) and do (Actions)
            • Loop - Actions
              • Set Monster = (Picked unit)
              • Set MonsterDestination[(Custom value of Monster)] = MonsterEnd[MonsterIndex]
              • Unit - Order Monster to Attack-Move To (Center of MonsterEnd[MonsterIndex])
This will create X Monsters per MonsterStart region and order them to Attack-Move to their respective MonsterEnd region. It will also save the End region to the Monster by using the MonsterDestination variable.

Monster = Unit variable.
MonsterIndex = Integer variable.
MonsterStart = Region ARRAY variable.
MonsterEnd = Region ARRAY variable.
MonsterDestination = Region ARRAY variable.

But you probably want to change MonsterDestination to a different Region since your goal is to have them attack-move there later on:
  • Split Up Example
    • Events
      • Unit - A unit enters (some region)
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 12 (Brown)
    • Actions
      • Set Monster = (Triggering unit)
      • Unit - Order Monster to Attack-Move To (Center of MonsterDestination[(Custom value of Monster)])
If you have multiple elaborate paths for your monsters to travel along I would recommend using a Hashtable and saving data to the units with that. Also, this method doesn't address the memory leaks being created here. Ideally, you would have Point variables stored at each Region which you would reference instead of (Center of region).
Hello! I'm having problem with the trigger you gave me. I did everything but everyone just going into 1 region, not going to its own designated region. To give you an idea the unit will be created in the middle and will be moved to bottom to 2 each side and will endlessly move in the map. Would giving the map will give you an idea what am I making? The unit once they hit the bottom region. Each half of created unit will be move to side 1 and for the other half will be moved to side 2.

As you can see those blue is region. I want them endlessly to move there in the box path. Thank you.
xsd.JPG
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,869
You have to share your triggers or we will struggle to understand where you went wrong.

But I understand what you're trying to accomplish and my suggestion will allow you to do exactly that. I recommend trying to learn how the Unit Indexer system works so that you can create these triggers yourself!
 
Level 4
Joined
Jan 27, 2020
Messages
51
You have to share your triggers or we will struggle to understand where you went wrong.

But I understand what you're trying to accomplish and my suggestion will allow you to do exactly that. I recommend trying to learn how the Unit Indexer system works so that you can create these triggers yourself!
My bad for not posting the trigger that I made. The result is once they did move in the intersection, but they will move again to 1 region which is the right intersection of path. Also, I want the amount of unit created be divided and move to each side of regions. Thank you for understanding.
  • Create All Monsters
    • Events
    • Conditions
    • Actions
      • For each (Integer MonsterIndex) from 1 to 4, do (Actions)
        • Loop - Actions
          • Unit - Create monstersperlvl unitforlevel for Player 12 (Brown) at (Center of Monsterstart[MonsterIndex]) facing Default building facing degrees
          • Unit Group - Pick every unit in (Last created unit group) and do (Actions)
            • Loop - Actions
              • Set Monster = (Picked unit)
              • Set MonsterDesitination[(Custom value of Monster)] = Monsterend[MonsterIndex]
              • Unit - Order Monster to Move To (Center of Monsterend[MonsterIndex])
-
  • cut in half
    • Events
      • Unit - A unit enters Bottom to Side to Side <gen>
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 12 (Brown)
    • Actions
      • Set Monster = (Triggering unit)
      • Unit - Order Monster to Move To (Center of MonsterDesitination[(Custom value of Monster)])
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,869
Those look fine but:
1) Do you have A Unit Indexer system in your map?
2) Where is the trigger that Sets Monsterstart/Monsterend?

Also, remember that whatever you Set MonsterDestination to will be where the Monster is ordered to move to when it enters the region:
  • Set MonsterDesitination[(Custom value of Monster)] = Monsterend[MonsterIndex]
So make sure it's the correct Region for the Monster.
 
Level 4
Joined
Jan 27, 2020
Messages
51
Those look fine but:
1) Do you have A Unit Indexer system in your map?
2) Where is the trigger that Sets Monsterstart/Monsterend?

Also, remember that whatever you Set MonsterDestination to will be where the Monster is ordered to move to when it enters the region:
  • Set MonsterDesitination[(Custom value of Monster)] = Monsterend[MonsterIndex]
So make sure it's the correct Region for the Monster.
I dont have Unit Indexer system in my map. Would I just follow the link you gave me?
  • Region
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Monsterstart[1] = Bottom <gen>
      • Set Monsterstart[2] = Side <gen>
      • Set Monsterstart[3] = Top <gen>
      • Set Monsterstart[4] = Side 2 <gen>
      • Set Monsterend[1] = Bottom to Side to Side <gen>
      • Set Monsterend[2] = Side 1 <gen>
      • Set Monsterend[3] = Top Middle going to Side to Side <gen>
      • Set Monsterend[4] = Side 2 Top to Bottom <gen>
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,869
You will need to find one that is compatible with your version of Warcraft 3 as it looks like you're using an older patch.

Perhaps this one would work:

These systems are designed to Set the Custom Value of your Units automatically. The end result is that each unit will have it's own unique Custom Value, which can then be used in combination with Variable Arrays to save data directly to Units. This is what we're doing with MonsterDestination.
 
Level 4
Joined
Jan 27, 2020
Messages
51
You will need to find one that is compatible with your version of Warcraft 3 as it looks like you're using an older patch.

Perhaps this one would work:

These systems are designed to Set the Custom Value of your Units automatically. The end result is that each unit will have it's own unique Custom Value, which can then be used in combination with Variable Arrays to save data directly to Units. This is what we're doing with MonsterDestination.
Would I just follow the installation guides?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,869
Would I just follow the installation guides?
If you tell me which version of Warcraft 3 you're on I can help further.

But the latest Unit Indexer system I linked is the very first one I found and it seems to be loaded with unnecessary stuff you don't need.

How about using this one instead. Copy all of the text below and then paste it into a Custom Script trigger:
vJASS:
library UnitDex uses optional WorldBounds, optional GroupUtils
/***************************************************************
*
*   v1.2.2, by TriggerHappy
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   UnitDex assigns every unit an unique integer. It attempts to make that number within the
*   maximum array limit so you can associate it with one.
*   _________________________________________________________________________
*   1. Installation
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   Copy the script to your map, save it, then restart the editor and comment out the line below.
*/
    //! external ObjectMerger w3a Adef uDex anam "Detect Leave" ansf "(UnitDex)" aart "" acat "" arac 0
/*  ________________________________________________________________________
*   2. Configuration
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
    private module UnitDexConfig
 
        // The raw code of the leave detection ability.
        static constant integer DETECT_LEAVE_ABILITY = 'uDex'
  
        // Allow debug messages (debug mode must also be on)
        static constant boolean ALLOW_DEBUGGING      = true
  
        // Uncomment the lines below to define a global filter for units being indexed
  
        /*static method onFilter takes unit u returns boolean
            return true
        endmethod*/
  
    endmodule
/*  _________________________________________________________________________
*   3. Function API
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   Every function inlines.
*
*       function GetUnitId takes unit whichUnit returns integer
*       function GetUnitById takes integer index returns unit
*
*       function UnitDexEnable takes boolean flag returns nothing
*       function UnitDexRemove takes unit u, boolean runEvents returns boolean
*
*       function IsUnitIndexed takes unit u returns boolean
*       function IsIndexingEnabled takes nothing returns boolean
*
*       function GetIndexedUnit takes nothing returns unit
*       function GetIndexedUnitId takes nothing returns integer
*  
*       function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns indexevent
*       function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
*       function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
*
*       function OnUnitIndex takes code func returns triggercondition
*       function OnUnitDeidex takes code func returns triggercondition
*   _________________________________________________________________________
*   4. Struct API
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       UnitDex.Enabled = false // toggle the indexer
*       UnitDex.Initialized     // returns true if the preload timer has finished
*       UnitDex.Count           // returns the amount of units indexed
*       UnitDex.Unit[0]         // access the UnitDex array directly
*       UnitDex.Group           // a unit group containing every indexed unit (for enumeration)
*       UnitDex.LastIndex       // returns the last indexed unit's id
*   _________________________________________________________________________
*   5. Public Variables
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       These are to be used with the "eventtype" argument of the event API:
*
*           constant integer EVENT_UNIT_INDEX     = 0
*           constant integer EVENT_UNIT_DEINDEX   = 1
*   _________________________________________________________________________
*   6. Examples
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       1. Associate a unit with a variable
*
*           set UnitFlag[GetUnitId(yourUnit)] = true
*
*       2. Allocate a struct instance using a units assigned ID
*
*           local somestruct data = GetUnitId(yourUnit)
*
*       3. Detect when a unit leaves the map
*
*           function Exit takes nothing returns nothing
*               call BJDebugMsg("The unit " + GetUnitName(GetIndexedUnit()) + " has left the map.")
*           endfunction
*
*           call OnUnitDeindex(function Exit)
*           // or
*           call RegisterUnitIndexEvent(Filter(function Exit), EVENT_UNIT_DEINDEX)
*
*
*   _________________________________________________________________________
*   7. How it works
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       1. Enumerate all preplaced units
*       2. TriggerRegisterEnterRegion native to detect when a unit enters the map
*       3. Assign each unit that enters the map a unique integer
*       4. Give every unit an ability based off of defend. There is no native to accurately
*          detect when a unit leaves the map but when a unit dies or is removed from the game
*          they are issued the "undefend" order
*       5. Catch the "undefend" order and remove unit from the queue
*   _________________________________________________________________________
*   8. Notes
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       - This system is compatable with GUI because it utilizes UnitUserData (custom values for units).
*       - The object merger line should be commented out after saving and restarting.
*
*   -http://www.hiveworkshop.com/forums/submissions-414/unitdex-lightweight-unit-indexer-248209/
*
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
 
    globals
        // Event types
        constant integer EVENT_UNIT_INDEX     = 0
        constant integer EVENT_UNIT_DEINDEX   = 1
  
        // System variables
        private trigger array IndexTrig
        private integer Index = 0
        private real E=-1
        private boolexpr FilterEnter
    endglobals
 
    function GetUnitId takes unit whichUnit returns integer
        return GetUnitUserData(whichUnit)
    endfunction
 
    function GetUnitById takes integer index returns unit
        return UnitDex.Unit[index]
    endfunction
 
    function GetIndexedUnit takes nothing returns unit
        return UnitDex.Unit[UnitDex.LastIndex]
    endfunction
 
    function GetIndexedUnitId takes nothing returns integer
        return UnitDex.LastIndex
    endfunction
 
    function IsUnitIndexed takes unit u returns boolean
        return (GetUnitById(GetUnitId(u)) != null)
    endfunction
 
    function UnitDexEnable takes boolean flag returns nothing
        set UnitDex.Enabled = flag
    endfunction
 
    function IsIndexingEnabled takes nothing returns boolean
        return UnitDex.Enabled
    endfunction
 
    function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns triggercondition
        return TriggerAddCondition(IndexTrig[eventtype], func)
    endfunction
 
    function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
        call TriggerRemoveCondition(IndexTrig[eventtype], c)
    endfunction
 
    function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
        call TriggerRegisterVariableEvent(t, SCOPE_PRIVATE + "E", EQUAL, eventtype)
    endfunction
 
    function OnUnitIndex takes code func returns triggercondition
        return TriggerAddCondition(IndexTrig[EVENT_UNIT_INDEX], Filter(func))
    endfunction

    function OnUnitDeindex takes code func returns triggercondition
        return TriggerAddCondition(IndexTrig[EVENT_UNIT_DEINDEX], Filter(func))
    endfunction
 
    /****************************************************************/
 
    private keyword UnitDexCore
 
    struct UnitDex extends array
        static boolean Enabled = true
  
        readonly static integer LastIndex
        readonly static boolean Initialized=false
        readonly static group Group=CreateGroup()
        readonly static unit array Unit
        readonly static integer Count = 0
        readonly static integer array List
  
        implement UnitDexConfig
  
        private static integer Counter = 0
  
        implement UnitDexCore
    endstruct
 
    function UnitDexRemove takes unit u, boolean runEvents returns boolean
        return UnitDex.Remove(u, runEvents)
    endfunction
 
    /****************************************************************/
 
    private module UnitDexCore
 
        static method Remove takes unit u, boolean runEvents returns boolean
            local integer i
      
            if (IsUnitIndexed(u)) then
                set i = GetUnitId(u)
                set UnitDex.List[i] = Index
                set Index = i
          
                call GroupRemoveUnit(UnitDex.Group, u)
                call SetUnitUserData(u, 0)
      
                if (runEvents) then
                    set UnitDex.LastIndex = i
                    set E = EVENT_UNIT_DEINDEX
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
                    set E = -1
                endif
          
                set UnitDex.Unit[i] = null
                set UnitDex.Count = UnitDex.Count - 1
          
                return true
            endif
      
            return false
        endmethod
  
        private static method onGameStart takes nothing returns nothing
            local integer i = 1
      
            loop
                exitwhen i > Counter
          
                set LastIndex = i
          
                call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
                set E = EVENT_UNIT_INDEX
                set E = -1
          
                set i = i + 1
            endloop

            set LastIndex   = Counter
            set Initialized = true
            set FilterEnter = null
      
            call DestroyTimer(GetExpiredTimer())
        endmethod
  
        private static method onEnter takes nothing returns boolean
            local unit    u = GetFilterUnit()
            local integer i = GetUnitId(u)
            local integer t = Index
      
            if (i == 0 and thistype.Enabled) then
          
                // If a filter was defined pass the unit through it.
                static if (thistype.onFilter.exists) then
                    if (not thistype.onFilter(u)) then
                        set u = null
                        return false // check failed
                    endif
                endif
          
                // Handle debugging
                static if (thistype.DEBUG_MODE and thistype.ALLOW_DEBUGGING) then
                    if (t == 0 and Counter+1 >= JASS_MAX_ARRAY_SIZE) then
                        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "UnitDex: Maximum number of units reached!")
                        set u = null
                        return false
                    endif
                endif
          
                // Add to group of indexed units
                call GroupAddUnit(thistype.Group, u)
          
                // Give unit the leave detection ability
                call UnitAddAbility(u, thistype.DETECT_LEAVE_ABILITY)
                call UnitMakeAbilityPermanent(u, true, thistype.DETECT_LEAVE_ABILITY)
          
                // Allocate index
                if (Index != 0) then
                    set Index = List[t]
                else
                    set Counter = Counter + 1
                    set t = Counter
                endif
          
                set List[t] = -1
                set LastIndex = t
                set thistype.Unit[t] = u
                set Count = Count + 1
          
                // Store the index
                call SetUnitUserData(u, t)
          
                if (thistype.Initialized) then
                    // Execute custom events registered with RegisterUnitIndexEvent
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
              
                    // Handle TriggerRegisterUnitIndexEvent
                    set E = EVENT_UNIT_INDEX

                    // Reset so the event can occur again
                    set E = -1
                endif
            endif
      
            set u = null
      
            return false
        endmethod

        private static method onLeave takes nothing returns boolean
            local unit    u
            local integer i
      
            // Check if order is undefend.
            if (thistype.Enabled and GetIssuedOrderId() == 852056) then
          
                set u = GetTriggerUnit()
          
                // If unit was killed (not removed) then don't continue
                if (GetUnitAbilityLevel(u, thistype.DETECT_LEAVE_ABILITY) != 0) then
                    set u = null
                    return false
                endif
          
                set i = GetUnitId(u)

                // If unit has been indexed then deindex it
                if (i > 0 and i <= Counter and u == GetUnitById(i)) then
              
                    // Recycle the index
                    set List[i]   = Index
                    set Index     = i
                    set LastIndex = i
              
                    // Remove to group of indexed units
                    call GroupRemoveUnit(thistype.Group, u)
          
                    // Execute custom events without any associated triggers
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
              
                    // Handle TriggerRegisterUnitIndexEvent
                    set E = EVENT_UNIT_DEINDEX
              
                    // Remove entry
                    call SetUnitUserData(u, 0)
                    set thistype.Unit[i] = null
              
                    // Decrement unit count
                    set Count = Count - 1
          
                    // Reset so the event can occur again
                    set E = -1
                endif
          
                set u = null
            endif
      
            return false
        endmethod
  
        private static method onInit takes nothing returns nothing
            local trigger t         = CreateTrigger()
            local integer i         = 0
            local player p
            local unit u
      
            static if (not LIBRARY_WorldBounds) then // Check if WorldBounts exists, if not then define the necessary vars
                local region reg = CreateRegion() // If WorldBounds wasn't found, create the region manually
                local rect world = GetWorldBounds()
            endif
      
            static if (not LIBRARY_GroupUtils) then // Check if GroupUtils exists so we can use it's enumeration group.
                local group ENUM_GROUP = CreateGroup() // If not, create the group.
            endif
      
            set FilterEnter = Filter(function thistype.onEnter)
      
            // Begin to index units when they enter the map
            static if (LIBRARY_WorldBounds) then
                call TriggerRegisterEnterRegion(CreateTrigger(), WorldBounds.worldRegion, FilterEnter)
            else
                call RegionAddRect(reg, world)
                call TriggerRegisterEnterRegion(CreateTrigger(), reg, FilterEnter)
                call RemoveRect(world)
                set world = null
            endif
      
            call TriggerAddCondition(t, Filter(function thistype.onLeave))
      
            set IndexTrig[EVENT_UNIT_INDEX] = CreateTrigger()
            set IndexTrig[EVENT_UNIT_DEINDEX] = CreateTrigger()
      
            loop
                set p = Player(i)
          
                // Detect "undefend"
                call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
          
                // Hide the detect ability from players
                call SetPlayerAbilityAvailable(p, thistype.DETECT_LEAVE_ABILITY, false)
          
                set i = i + 1
                exitwhen i == bj_MAX_PLAYER_SLOTS
            endloop
      
            // Index preplaced units
            set i = 0
            loop
                call GroupEnumUnitsOfPlayer(ENUM_GROUP, Player(i), FilterEnter)
          
                set i = i + 1
          
                exitwhen i == bj_MAX_PLAYER_SLOTS
            endloop
      
            static if (not LIBRARY_GroupUtils) then
                call DestroyGroup(ENUM_GROUP)
                set ENUM_GROUP = null
            endif

            set LastIndex = Counter
      
            // run init triggers
            call TimerStart(CreateTimer(), 0.00, false, function thistype.onGameStart)
        endmethod
 
    endmodule
 
endlibrary

This code will automatically assign Custom Values to your Units. You don't have to do anything other than have this code in your map AND make sure you NEVER Set Custom Value yourself, as this will interfere with the system!
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,869
Sorry, I forgot one other step, copy and paste the Defend ability (the human footman ability) and make it's rawcode uDex

The system uses a custom version of this ability to do some weird Warcraft 3 stuff. Long story short it allows the system to detect when a unit is Removed from the game. This won't interfere with anything.
 
Level 4
Joined
Jan 27, 2020
Messages
51
If you tell me which version of Warcraft 3 you're on I can help further.

But the latest Unit Indexer system I linked is the very first one I found and it seems to be loaded with unnecessary stuff you don't need.

How about using this one instead. Copy all of the text below and then paste it into a Custom Script trigger:
vJASS:
library UnitDex uses optional WorldBounds, optional GroupUtils
/***************************************************************
*
*   v1.2.2, by TriggerHappy
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   UnitDex assigns every unit an unique integer. It attempts to make that number within the
*   maximum array limit so you can associate it with one.
*   _________________________________________________________________________
*   1. Installation
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   Copy the script to your map, save it, then restart the editor and comment out the line below.
*/
    //! external ObjectMerger w3a Adef uDex anam "Detect Leave" ansf "(UnitDex)" aart "" acat "" arac 0
/*  ________________________________________________________________________
*   2. Configuration
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
    private module UnitDexConfig
 
        // The raw code of the leave detection ability.
        static constant integer DETECT_LEAVE_ABILITY = 'uDex'
 
        // Allow debug messages (debug mode must also be on)
        static constant boolean ALLOW_DEBUGGING      = true
 
        // Uncomment the lines below to define a global filter for units being indexed
 
        /*static method onFilter takes unit u returns boolean
            return true
        endmethod*/
 
    endmodule
/*  _________________________________________________________________________
*   3. Function API
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   Every function inlines.
*
*       function GetUnitId takes unit whichUnit returns integer
*       function GetUnitById takes integer index returns unit
*
*       function UnitDexEnable takes boolean flag returns nothing
*       function UnitDexRemove takes unit u, boolean runEvents returns boolean
*
*       function IsUnitIndexed takes unit u returns boolean
*       function IsIndexingEnabled takes nothing returns boolean
*
*       function GetIndexedUnit takes nothing returns unit
*       function GetIndexedUnitId takes nothing returns integer
*
*       function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns indexevent
*       function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
*       function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
*
*       function OnUnitIndex takes code func returns triggercondition
*       function OnUnitDeidex takes code func returns triggercondition
*   _________________________________________________________________________
*   4. Struct API
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       UnitDex.Enabled = false // toggle the indexer
*       UnitDex.Initialized     // returns true if the preload timer has finished
*       UnitDex.Count           // returns the amount of units indexed
*       UnitDex.Unit[0]         // access the UnitDex array directly
*       UnitDex.Group           // a unit group containing every indexed unit (for enumeration)
*       UnitDex.LastIndex       // returns the last indexed unit's id
*   _________________________________________________________________________
*   5. Public Variables
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       These are to be used with the "eventtype" argument of the event API:
*
*           constant integer EVENT_UNIT_INDEX     = 0
*           constant integer EVENT_UNIT_DEINDEX   = 1
*   _________________________________________________________________________
*   6. Examples
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       1. Associate a unit with a variable
*
*           set UnitFlag[GetUnitId(yourUnit)] = true
*
*       2. Allocate a struct instance using a units assigned ID
*
*           local somestruct data = GetUnitId(yourUnit)
*
*       3. Detect when a unit leaves the map
*
*           function Exit takes nothing returns nothing
*               call BJDebugMsg("The unit " + GetUnitName(GetIndexedUnit()) + " has left the map.")
*           endfunction
*
*           call OnUnitDeindex(function Exit)
*           // or
*           call RegisterUnitIndexEvent(Filter(function Exit), EVENT_UNIT_DEINDEX)
*
*
*   _________________________________________________________________________
*   7. How it works
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       1. Enumerate all preplaced units
*       2. TriggerRegisterEnterRegion native to detect when a unit enters the map
*       3. Assign each unit that enters the map a unique integer
*       4. Give every unit an ability based off of defend. There is no native to accurately
*          detect when a unit leaves the map but when a unit dies or is removed from the game
*          they are issued the "undefend" order
*       5. Catch the "undefend" order and remove unit from the queue
*   _________________________________________________________________________
*   8. Notes
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       - This system is compatable with GUI because it utilizes UnitUserData (custom values for units).
*       - The object merger line should be commented out after saving and restarting.
*
*   -http://www.hiveworkshop.com/forums/submissions-414/unitdex-lightweight-unit-indexer-248209/
*
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
 
    globals
        // Event types
        constant integer EVENT_UNIT_INDEX     = 0
        constant integer EVENT_UNIT_DEINDEX   = 1
 
        // System variables
        private trigger array IndexTrig
        private integer Index = 0
        private real E=-1
        private boolexpr FilterEnter
    endglobals
 
    function GetUnitId takes unit whichUnit returns integer
        return GetUnitUserData(whichUnit)
    endfunction
 
    function GetUnitById takes integer index returns unit
        return UnitDex.Unit[index]
    endfunction
 
    function GetIndexedUnit takes nothing returns unit
        return UnitDex.Unit[UnitDex.LastIndex]
    endfunction
 
    function GetIndexedUnitId takes nothing returns integer
        return UnitDex.LastIndex
    endfunction
 
    function IsUnitIndexed takes unit u returns boolean
        return (GetUnitById(GetUnitId(u)) != null)
    endfunction
 
    function UnitDexEnable takes boolean flag returns nothing
        set UnitDex.Enabled = flag
    endfunction
 
    function IsIndexingEnabled takes nothing returns boolean
        return UnitDex.Enabled
    endfunction
 
    function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns triggercondition
        return TriggerAddCondition(IndexTrig[eventtype], func)
    endfunction
 
    function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
        call TriggerRemoveCondition(IndexTrig[eventtype], c)
    endfunction
 
    function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
        call TriggerRegisterVariableEvent(t, SCOPE_PRIVATE + "E", EQUAL, eventtype)
    endfunction
 
    function OnUnitIndex takes code func returns triggercondition
        return TriggerAddCondition(IndexTrig[EVENT_UNIT_INDEX], Filter(func))
    endfunction

    function OnUnitDeindex takes code func returns triggercondition
        return TriggerAddCondition(IndexTrig[EVENT_UNIT_DEINDEX], Filter(func))
    endfunction
 
    /****************************************************************/
 
    private keyword UnitDexCore
 
    struct UnitDex extends array
        static boolean Enabled = true
 
        readonly static integer LastIndex
        readonly static boolean Initialized=false
        readonly static group Group=CreateGroup()
        readonly static unit array Unit
        readonly static integer Count = 0
        readonly static integer array List
 
        implement UnitDexConfig
 
        private static integer Counter = 0
 
        implement UnitDexCore
    endstruct
 
    function UnitDexRemove takes unit u, boolean runEvents returns boolean
        return UnitDex.Remove(u, runEvents)
    endfunction
 
    /****************************************************************/
 
    private module UnitDexCore
 
        static method Remove takes unit u, boolean runEvents returns boolean
            local integer i
    
            if (IsUnitIndexed(u)) then
                set i = GetUnitId(u)
                set UnitDex.List[i] = Index
                set Index = i
        
                call GroupRemoveUnit(UnitDex.Group, u)
                call SetUnitUserData(u, 0)
    
                if (runEvents) then
                    set UnitDex.LastIndex = i
                    set E = EVENT_UNIT_DEINDEX
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
                    set E = -1
                endif
        
                set UnitDex.Unit[i] = null
                set UnitDex.Count = UnitDex.Count - 1
        
                return true
            endif
    
            return false
        endmethod
 
        private static method onGameStart takes nothing returns nothing
            local integer i = 1
    
            loop
                exitwhen i > Counter
        
                set LastIndex = i
        
                call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
                set E = EVENT_UNIT_INDEX
                set E = -1
        
                set i = i + 1
            endloop

            set LastIndex   = Counter
            set Initialized = true
            set FilterEnter = null
    
            call DestroyTimer(GetExpiredTimer())
        endmethod
 
        private static method onEnter takes nothing returns boolean
            local unit    u = GetFilterUnit()
            local integer i = GetUnitId(u)
            local integer t = Index
    
            if (i == 0 and thistype.Enabled) then
        
                // If a filter was defined pass the unit through it.
                static if (thistype.onFilter.exists) then
                    if (not thistype.onFilter(u)) then
                        set u = null
                        return false // check failed
                    endif
                endif
        
                // Handle debugging
                static if (thistype.DEBUG_MODE and thistype.ALLOW_DEBUGGING) then
                    if (t == 0 and Counter+1 >= JASS_MAX_ARRAY_SIZE) then
                        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "UnitDex: Maximum number of units reached!")
                        set u = null
                        return false
                    endif
                endif
        
                // Add to group of indexed units
                call GroupAddUnit(thistype.Group, u)
        
                // Give unit the leave detection ability
                call UnitAddAbility(u, thistype.DETECT_LEAVE_ABILITY)
                call UnitMakeAbilityPermanent(u, true, thistype.DETECT_LEAVE_ABILITY)
        
                // Allocate index
                if (Index != 0) then
                    set Index = List[t]
                else
                    set Counter = Counter + 1
                    set t = Counter
                endif
        
                set List[t] = -1
                set LastIndex = t
                set thistype.Unit[t] = u
                set Count = Count + 1
        
                // Store the index
                call SetUnitUserData(u, t)
        
                if (thistype.Initialized) then
                    // Execute custom events registered with RegisterUnitIndexEvent
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
            
                    // Handle TriggerRegisterUnitIndexEvent
                    set E = EVENT_UNIT_INDEX

                    // Reset so the event can occur again
                    set E = -1
                endif
            endif
    
            set u = null
    
            return false
        endmethod

        private static method onLeave takes nothing returns boolean
            local unit    u
            local integer i
    
            // Check if order is undefend.
            if (thistype.Enabled and GetIssuedOrderId() == 852056) then
        
                set u = GetTriggerUnit()
        
                // If unit was killed (not removed) then don't continue
                if (GetUnitAbilityLevel(u, thistype.DETECT_LEAVE_ABILITY) != 0) then
                    set u = null
                    return false
                endif
        
                set i = GetUnitId(u)

                // If unit has been indexed then deindex it
                if (i > 0 and i <= Counter and u == GetUnitById(i)) then
            
                    // Recycle the index
                    set List[i]   = Index
                    set Index     = i
                    set LastIndex = i
            
                    // Remove to group of indexed units
                    call GroupRemoveUnit(thistype.Group, u)
        
                    // Execute custom events without any associated triggers
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
            
                    // Handle TriggerRegisterUnitIndexEvent
                    set E = EVENT_UNIT_DEINDEX
            
                    // Remove entry
                    call SetUnitUserData(u, 0)
                    set thistype.Unit[i] = null
            
                    // Decrement unit count
                    set Count = Count - 1
        
                    // Reset so the event can occur again
                    set E = -1
                endif
        
                set u = null
            endif
    
            return false
        endmethod
 
        private static method onInit takes nothing returns nothing
            local trigger t         = CreateTrigger()
            local integer i         = 0
            local player p
            local unit u
    
            static if (not LIBRARY_WorldBounds) then // Check if WorldBounts exists, if not then define the necessary vars
                local region reg = CreateRegion() // If WorldBounds wasn't found, create the region manually
                local rect world = GetWorldBounds()
            endif
    
            static if (not LIBRARY_GroupUtils) then // Check if GroupUtils exists so we can use it's enumeration group.
                local group ENUM_GROUP = CreateGroup() // If not, create the group.
            endif
    
            set FilterEnter = Filter(function thistype.onEnter)
    
            // Begin to index units when they enter the map
            static if (LIBRARY_WorldBounds) then
                call TriggerRegisterEnterRegion(CreateTrigger(), WorldBounds.worldRegion, FilterEnter)
            else
                call RegionAddRect(reg, world)
                call TriggerRegisterEnterRegion(CreateTrigger(), reg, FilterEnter)
                call RemoveRect(world)
                set world = null
            endif
    
            call TriggerAddCondition(t, Filter(function thistype.onLeave))
    
            set IndexTrig[EVENT_UNIT_INDEX] = CreateTrigger()
            set IndexTrig[EVENT_UNIT_DEINDEX] = CreateTrigger()
    
            loop
                set p = Player(i)
        
                // Detect "undefend"
                call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
        
                // Hide the detect ability from players
                call SetPlayerAbilityAvailable(p, thistype.DETECT_LEAVE_ABILITY, false)
        
                set i = i + 1
                exitwhen i == bj_MAX_PLAYER_SLOTS
            endloop
    
            // Index preplaced units
            set i = 0
            loop
                call GroupEnumUnitsOfPlayer(ENUM_GROUP, Player(i), FilterEnter)
        
                set i = i + 1
        
                exitwhen i == bj_MAX_PLAYER_SLOTS
            endloop
    
            static if (not LIBRARY_GroupUtils) then
                call DestroyGroup(ENUM_GROUP)
                set ENUM_GROUP = null
            endif

            set LastIndex = Counter
    
            // run init triggers
            call TimerStart(CreateTimer(), 0.00, false, function thistype.onGameStart)
        endmethod
 
    endmodule
 
endlibrary

This code will automatically assign Custom Values to your Units. You don't have to do anything other than have this code in your map AND make sure you NEVER Set Custom Value yourself, as this will interfere with the system!
I am currently playing in Warcraft 3 1.26.0.6401
If you will be asking why I am using older version, because they are widely used version in most warcraft games. If you are suspecting me that I am using crack version or is it bad to play on crack warcraft?, it's just they are most used and I want them play it. I have the 1.31 version. But I prefer the 1.26, thank you. Playing in classic warcraft are just much better.
 
Level 4
Joined
Jan 27, 2020
Messages
51
If you tell me which version of Warcraft 3 you're on I can help further.

But the latest Unit Indexer system I linked is the very first one I found and it seems to be loaded with unnecessary stuff you don't need.

How about using this one instead. Copy all of the text below and then paste it into a Custom Script trigger:
vJASS:
library UnitDex uses optional WorldBounds, optional GroupUtils
/***************************************************************
*
*   v1.2.2, by TriggerHappy
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   UnitDex assigns every unit an unique integer. It attempts to make that number within the
*   maximum array limit so you can associate it with one.
*   _________________________________________________________________________
*   1. Installation
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   Copy the script to your map, save it, then restart the editor and comment out the line below.
*/
    //! external ObjectMerger w3a Adef uDex anam "Detect Leave" ansf "(UnitDex)" aart "" acat "" arac 0
/*  ________________________________________________________________________
*   2. Configuration
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
    private module UnitDexConfig
 
        // The raw code of the leave detection ability.
        static constant integer DETECT_LEAVE_ABILITY = 'uDex'
 
        // Allow debug messages (debug mode must also be on)
        static constant boolean ALLOW_DEBUGGING      = true
 
        // Uncomment the lines below to define a global filter for units being indexed
 
        /*static method onFilter takes unit u returns boolean
            return true
        endmethod*/
 
    endmodule
/*  _________________________________________________________________________
*   3. Function API
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   Every function inlines.
*
*       function GetUnitId takes unit whichUnit returns integer
*       function GetUnitById takes integer index returns unit
*
*       function UnitDexEnable takes boolean flag returns nothing
*       function UnitDexRemove takes unit u, boolean runEvents returns boolean
*
*       function IsUnitIndexed takes unit u returns boolean
*       function IsIndexingEnabled takes nothing returns boolean
*
*       function GetIndexedUnit takes nothing returns unit
*       function GetIndexedUnitId takes nothing returns integer
*
*       function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns indexevent
*       function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
*       function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
*
*       function OnUnitIndex takes code func returns triggercondition
*       function OnUnitDeidex takes code func returns triggercondition
*   _________________________________________________________________________
*   4. Struct API
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       UnitDex.Enabled = false // toggle the indexer
*       UnitDex.Initialized     // returns true if the preload timer has finished
*       UnitDex.Count           // returns the amount of units indexed
*       UnitDex.Unit[0]         // access the UnitDex array directly
*       UnitDex.Group           // a unit group containing every indexed unit (for enumeration)
*       UnitDex.LastIndex       // returns the last indexed unit's id
*   _________________________________________________________________________
*   5. Public Variables
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       These are to be used with the "eventtype" argument of the event API:
*
*           constant integer EVENT_UNIT_INDEX     = 0
*           constant integer EVENT_UNIT_DEINDEX   = 1
*   _________________________________________________________________________
*   6. Examples
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       1. Associate a unit with a variable
*
*           set UnitFlag[GetUnitId(yourUnit)] = true
*
*       2. Allocate a struct instance using a units assigned ID
*
*           local somestruct data = GetUnitId(yourUnit)
*
*       3. Detect when a unit leaves the map
*
*           function Exit takes nothing returns nothing
*               call BJDebugMsg("The unit " + GetUnitName(GetIndexedUnit()) + " has left the map.")
*           endfunction
*
*           call OnUnitDeindex(function Exit)
*           // or
*           call RegisterUnitIndexEvent(Filter(function Exit), EVENT_UNIT_DEINDEX)
*
*
*   _________________________________________________________________________
*   7. How it works
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       1. Enumerate all preplaced units
*       2. TriggerRegisterEnterRegion native to detect when a unit enters the map
*       3. Assign each unit that enters the map a unique integer
*       4. Give every unit an ability based off of defend. There is no native to accurately
*          detect when a unit leaves the map but when a unit dies or is removed from the game
*          they are issued the "undefend" order
*       5. Catch the "undefend" order and remove unit from the queue
*   _________________________________________________________________________
*   8. Notes
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*       - This system is compatable with GUI because it utilizes UnitUserData (custom values for units).
*       - The object merger line should be commented out after saving and restarting.
*
*   -http://www.hiveworkshop.com/forums/submissions-414/unitdex-lightweight-unit-indexer-248209/
*
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
 
    globals
        // Event types
        constant integer EVENT_UNIT_INDEX     = 0
        constant integer EVENT_UNIT_DEINDEX   = 1
 
        // System variables
        private trigger array IndexTrig
        private integer Index = 0
        private real E=-1
        private boolexpr FilterEnter
    endglobals
 
    function GetUnitId takes unit whichUnit returns integer
        return GetUnitUserData(whichUnit)
    endfunction
 
    function GetUnitById takes integer index returns unit
        return UnitDex.Unit[index]
    endfunction
 
    function GetIndexedUnit takes nothing returns unit
        return UnitDex.Unit[UnitDex.LastIndex]
    endfunction
 
    function GetIndexedUnitId takes nothing returns integer
        return UnitDex.LastIndex
    endfunction
 
    function IsUnitIndexed takes unit u returns boolean
        return (GetUnitById(GetUnitId(u)) != null)
    endfunction
 
    function UnitDexEnable takes boolean flag returns nothing
        set UnitDex.Enabled = flag
    endfunction
 
    function IsIndexingEnabled takes nothing returns boolean
        return UnitDex.Enabled
    endfunction
 
    function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns triggercondition
        return TriggerAddCondition(IndexTrig[eventtype], func)
    endfunction
 
    function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
        call TriggerRemoveCondition(IndexTrig[eventtype], c)
    endfunction
 
    function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
        call TriggerRegisterVariableEvent(t, SCOPE_PRIVATE + "E", EQUAL, eventtype)
    endfunction
 
    function OnUnitIndex takes code func returns triggercondition
        return TriggerAddCondition(IndexTrig[EVENT_UNIT_INDEX], Filter(func))
    endfunction

    function OnUnitDeindex takes code func returns triggercondition
        return TriggerAddCondition(IndexTrig[EVENT_UNIT_DEINDEX], Filter(func))
    endfunction
 
    /****************************************************************/
 
    private keyword UnitDexCore
 
    struct UnitDex extends array
        static boolean Enabled = true
 
        readonly static integer LastIndex
        readonly static boolean Initialized=false
        readonly static group Group=CreateGroup()
        readonly static unit array Unit
        readonly static integer Count = 0
        readonly static integer array List
 
        implement UnitDexConfig
 
        private static integer Counter = 0
 
        implement UnitDexCore
    endstruct
 
    function UnitDexRemove takes unit u, boolean runEvents returns boolean
        return UnitDex.Remove(u, runEvents)
    endfunction
 
    /****************************************************************/
 
    private module UnitDexCore
 
        static method Remove takes unit u, boolean runEvents returns boolean
            local integer i
    
            if (IsUnitIndexed(u)) then
                set i = GetUnitId(u)
                set UnitDex.List[i] = Index
                set Index = i
        
                call GroupRemoveUnit(UnitDex.Group, u)
                call SetUnitUserData(u, 0)
    
                if (runEvents) then
                    set UnitDex.LastIndex = i
                    set E = EVENT_UNIT_DEINDEX
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
                    set E = -1
                endif
        
                set UnitDex.Unit[i] = null
                set UnitDex.Count = UnitDex.Count - 1
        
                return true
            endif
    
            return false
        endmethod
 
        private static method onGameStart takes nothing returns nothing
            local integer i = 1
    
            loop
                exitwhen i > Counter
        
                set LastIndex = i
        
                call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
                set E = EVENT_UNIT_INDEX
                set E = -1
        
                set i = i + 1
            endloop

            set LastIndex   = Counter
            set Initialized = true
            set FilterEnter = null
    
            call DestroyTimer(GetExpiredTimer())
        endmethod
 
        private static method onEnter takes nothing returns boolean
            local unit    u = GetFilterUnit()
            local integer i = GetUnitId(u)
            local integer t = Index
    
            if (i == 0 and thistype.Enabled) then
        
                // If a filter was defined pass the unit through it.
                static if (thistype.onFilter.exists) then
                    if (not thistype.onFilter(u)) then
                        set u = null
                        return false // check failed
                    endif
                endif
        
                // Handle debugging
                static if (thistype.DEBUG_MODE and thistype.ALLOW_DEBUGGING) then
                    if (t == 0 and Counter+1 >= JASS_MAX_ARRAY_SIZE) then
                        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "UnitDex: Maximum number of units reached!")
                        set u = null
                        return false
                    endif
                endif
        
                // Add to group of indexed units
                call GroupAddUnit(thistype.Group, u)
        
                // Give unit the leave detection ability
                call UnitAddAbility(u, thistype.DETECT_LEAVE_ABILITY)
                call UnitMakeAbilityPermanent(u, true, thistype.DETECT_LEAVE_ABILITY)
        
                // Allocate index
                if (Index != 0) then
                    set Index = List[t]
                else
                    set Counter = Counter + 1
                    set t = Counter
                endif
        
                set List[t] = -1
                set LastIndex = t
                set thistype.Unit[t] = u
                set Count = Count + 1
        
                // Store the index
                call SetUnitUserData(u, t)
        
                if (thistype.Initialized) then
                    // Execute custom events registered with RegisterUnitIndexEvent
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
            
                    // Handle TriggerRegisterUnitIndexEvent
                    set E = EVENT_UNIT_INDEX

                    // Reset so the event can occur again
                    set E = -1
                endif
            endif
    
            set u = null
    
            return false
        endmethod

        private static method onLeave takes nothing returns boolean
            local unit    u
            local integer i
    
            // Check if order is undefend.
            if (thistype.Enabled and GetIssuedOrderId() == 852056) then
        
                set u = GetTriggerUnit()
        
                // If unit was killed (not removed) then don't continue
                if (GetUnitAbilityLevel(u, thistype.DETECT_LEAVE_ABILITY) != 0) then
                    set u = null
                    return false
                endif
        
                set i = GetUnitId(u)

                // If unit has been indexed then deindex it
                if (i > 0 and i <= Counter and u == GetUnitById(i)) then
            
                    // Recycle the index
                    set List[i]   = Index
                    set Index     = i
                    set LastIndex = i
            
                    // Remove to group of indexed units
                    call GroupRemoveUnit(thistype.Group, u)
        
                    // Execute custom events without any associated triggers
                    call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
            
                    // Handle TriggerRegisterUnitIndexEvent
                    set E = EVENT_UNIT_DEINDEX
            
                    // Remove entry
                    call SetUnitUserData(u, 0)
                    set thistype.Unit[i] = null
            
                    // Decrement unit count
                    set Count = Count - 1
        
                    // Reset so the event can occur again
                    set E = -1
                endif
        
                set u = null
            endif
    
            return false
        endmethod
 
        private static method onInit takes nothing returns nothing
            local trigger t         = CreateTrigger()
            local integer i         = 0
            local player p
            local unit u
    
            static if (not LIBRARY_WorldBounds) then // Check if WorldBounts exists, if not then define the necessary vars
                local region reg = CreateRegion() // If WorldBounds wasn't found, create the region manually
                local rect world = GetWorldBounds()
            endif
    
            static if (not LIBRARY_GroupUtils) then // Check if GroupUtils exists so we can use it's enumeration group.
                local group ENUM_GROUP = CreateGroup() // If not, create the group.
            endif
    
            set FilterEnter = Filter(function thistype.onEnter)
    
            // Begin to index units when they enter the map
            static if (LIBRARY_WorldBounds) then
                call TriggerRegisterEnterRegion(CreateTrigger(), WorldBounds.worldRegion, FilterEnter)
            else
                call RegionAddRect(reg, world)
                call TriggerRegisterEnterRegion(CreateTrigger(), reg, FilterEnter)
                call RemoveRect(world)
                set world = null
            endif
    
            call TriggerAddCondition(t, Filter(function thistype.onLeave))
    
            set IndexTrig[EVENT_UNIT_INDEX] = CreateTrigger()
            set IndexTrig[EVENT_UNIT_DEINDEX] = CreateTrigger()
    
            loop
                set p = Player(i)
        
                // Detect "undefend"
                call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
        
                // Hide the detect ability from players
                call SetPlayerAbilityAvailable(p, thistype.DETECT_LEAVE_ABILITY, false)
        
                set i = i + 1
                exitwhen i == bj_MAX_PLAYER_SLOTS
            endloop
    
            // Index preplaced units
            set i = 0
            loop
                call GroupEnumUnitsOfPlayer(ENUM_GROUP, Player(i), FilterEnter)
        
                set i = i + 1
        
                exitwhen i == bj_MAX_PLAYER_SLOTS
            endloop
    
            static if (not LIBRARY_GroupUtils) then
                call DestroyGroup(ENUM_GROUP)
                set ENUM_GROUP = null
            endif

            set LastIndex = Counter
    
            // run init triggers
            call TimerStart(CreateTimer(), 0.00, false, function thistype.onGameStart)
        endmethod
 
    endmodule
 
endlibrary

This code will automatically assign Custom Values to your Units. You don't have to do anything other than have this code in your map AND make sure you NEVER Set Custom Value yourself, as this will interfere with the system!
I get object merger error file (External not found in config file 'ObjectMerger') ? I use it in another version but I'm getting the object merger as it said from the Jass script.
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,869
Not sure, the instructions warn about that but the line is already commented out:
vJASS:
*   1. Installation
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   Copy the script to your map, save it, then restart the editor and comment out the line below.
*/
    //! external ObjectMerger w3a Adef uDex anam "Detect Leave" ansf "(UnitDex)" aart "" acat "" arac 0
Your Warcraft 3 version determines which systems will be compatible with it. A lot of patches introduce new things to the World Editor that you won't have and thus can't use on 1.26.

Anyway, you just need to find a nice Unit Indexer system that is compatible with 1.26. Ideally, you would use Bribe's Unit Indexer but I don't know if an older 1.26 version exists.

You could try the other one I posted, all you have to do is open the test map and copy the Folders containing the system then paste them into your map. That and copy the Unit Indexing ability and make sure the rawcodes match up.

example.png


Create a new folder and drag Requirements, Installation, and Resource folders into it using that same order from top to bottom. That'll make it easier to copy over to your map.
 
Last edited:
Level 4
Joined
Jan 27, 2020
Messages
51
Not sure, the instructions warn about that but the line is already commented out:
vJASS:
*   1. Installation
*   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   Copy the script to your map, save it, then restart the editor and comment out the line below.
*/
    //! external ObjectMerger w3a Adef uDex anam "Detect Leave" ansf "(UnitDex)" aart "" acat "" arac 0
Your Warcraft 3 version determines which systems will be compatible with it. A lot of patches introduce new things to the World Editor that you won't have and thus can't use on 1.26.

Anyway, you just need to find a nice Unit Indexer system that is compatible with 1.26. Ideally, you would use Bribe's Unit Indexer but I don't know if an older 1.26 version exists.

You could try the other one I posted, all you have to do is open the test map and copy the Folders containing the system then paste them into your map. That and copy the Unit Indexing ability and make sure the rawcodes match up.

View attachment 436275

Create a new folder and drag Requirements, Installation, and Resource folders into it using that same order from top to bottom. That'll make it easier to copy over to your map.
That one did not work in 1.26, but I'll probably use version 1.31 for now and utilize the GUI you provided initially. Since I don't know how to modify the variables that were set, could you guide me? Since I found out that there's a program to downgrade the version of the map.
 
Last edited:
Status
Not open for further replies.
Top