I dont seem understand the custom value. Can you provide me some explanation? Thank you.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
It did not worked. What's wrong?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
In a regionhow are Player 12 (Brown) units made ? are they been training or are they been Create ad a Region ?
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.
I would appreciate if it was written in trigger. Thank you!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.
This will be more complicated in my trigger, because it has levels, and also there will be 3 more like this trigger.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
nr 2 they spawn and get a custom value and split up when they spawn
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
there is ofc more whays to do.
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
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.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:
![]()
GUI Unit Indexer 1.4.0.0
Why Unit Indexing is Important For those not familiar with unit indexers such as UnitIndexingUtils, AutoIndex, Perfect Unit Indexing (PUI), Advanced Indexing and Data Storage (AIDS) or Unit Indexer, this can give you a bit of a crash-course. You definitely want to make your spell MUI. To do...www.hiveworkshop.com
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:
We now have the Regions where our Monsters are created at (Start) and the Regions where they will attack-move to (End).
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>)
Now let's change our Create All Monsters trigger to use the Unit Indexer method:
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.
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])
If you want to create multiple Monsters per Region then you can use a Unit Group to manage all of them at once:
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.
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])
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:
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).
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)])
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.You have to share your triggers or we will struggle to understand where you went wrong.
How To Post Your Trigger
TopHow To Post Your Triggers I've seen many and many members around the site who need help with their triggers but don't know how to post their triggers in a thread, especially the newcomers. Posting your triggers in a thread is a very important matter when you're asking for a help from other...www.hiveworkshop.com
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!
I dont have Unit Indexer system in my map. Would I just follow the link you gave me?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:
So make sure it's the correct Region for the Monster.
Set MonsterDesitination[(Custom value of Monster)] = Monsterend[MonsterIndex]
Would I just follow the installation guides?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:
![]()
Unit Indexer v5.3.0.1
Unit Indexer v5.3.0.1 by Nestharus __ Unit Indexer is a next gen unit indexing system that uses a variety of modern JASS techniques to improve performance and enable cool new features. It is unlike any other unit indexing system out...www.hiveworkshop.com
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.
If you tell me which version of Warcraft 3 you're on I can help further.Would I just follow the installation guides?
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
I am currently playing in Warcraft 3 1.26.0.6401If 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.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!
* 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
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.Not sure, the instructions warn about that but the line is already commented out:
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.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
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.