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

GUI Unit Event (now with a state-of-the-art Lua version)

Unit Event for GUI gives you access to all kinds of events which normal GUI events can't do:

FunctionLuavJass
Subject unit of the eventUnitEvent_unitUDexUnits[UDex]
Event index (for use within an array).UnitEvent_indexUDex
Data attachment to unitSet UnitEvent_setKey = unit
Set MyArray[UnitEvent_getKey] = data
Set MyArray2[UnitEvent_getKey] = data2
Set TempInt = (Custom value of unit)
Set MyArray[TempInt] = data
Set MyArray2[TempInt] = data2
Data retrieval from unitSet UnitEvent_setKey = unit
Set data = MyArray[UnitEvent_getKey]
Set data2 = MyArray2[UnitEvent_getKey]
Set TempInt = (Custom value of unit)
Set data = MyArray[TempInt]
Set data2 = MyArray2[TempInt]
Manually created in World Editor
Unit who summoned the subject unit
Know the previous type in a transform event
Is the unit reincarnating
Unit who is carrying the subject unit
All units carried by the unit
Detect the unit's killer in a death event
UnitEvent_preplaced
UnitEvent_summoner
UnitEvent_unitType
UnitEvent_reincarnating
UnitEvent_transporter
UnitEvent_cargo
(Killing unit)
IsUnitPreplaced
SummonerOfUnit
UnitTypeOf
IsUnitReincarnating
CargoTransportUnit
CargoTransportGroup
KillerOfUnit
Starts existing
Fully created
Stops existing
Starts reincarnating
Resurrects, reanimated or finishes reincarnating
Dies
Loaded into a transport
Unloaded from a transport
Transforms into a new unit
Is playable (alive/not loaded)
Is unplayable (dead/loaded)
OnUnitIndexed
OnUnitCreation
OnUnitRemoval
OnUnitReincarnating
OnUnitRevival
OnUnitDeath
OnUnitLoaded
OnUnitUnloaded
OnUnitTransform
OnUnitActive
OnUnitPassive
UnitIndexEvent == 1.00
UnitIndexEvent == 1.50
UnitIndexEvent == 2.00
DeathEvent == 0.50
DeathEvent == 2.00
DeathEvent == 1.00
CargoEvent == 1.00
CargoEvent == 2.00
UnitTypeEvent == 1.00
UnitInActionEvent == 1.00
UnitInActionEvent == 2.00

You can distinguish between types of unit revival with three conditions:
1) If it is summoned, that means it was reanimated (e.g. "Animate Dead (Death Knight Ultimate)").
2) If UnitEvent_reincarnating (Lua version) / IsUnitReincarnating (JASS version) is true, that means it finished reincarnating (e.g. "Reincarnation (Tauren Chieftan Ultimate)").
3) If the above are False, the unit was resurrected (e.g. "Ressurrection (Paladin Ultimate)").

Lua:
OnGlobalInit(function()
    
    Require "Timed"                         --https://www.hiveworkshop.com/threads/timed-call-and-echo.339222/
    Require "AddHook"                       --https://www.hiveworkshop.com/threads/hook.339153
    Require "GlobalRemap"                   --https://www.hiveworkshop.com/threads/global-variable-remapper.339308
    Require "RegisterAnyPlayerUnitEvent"    --https://www.hiveworkshop.com/threads/collection-gui-repair-kit.317084/
    Require "CreateEvent"                   --https://www.hiveworkshop.com/threads/event-gui-friendly.339451/
    Require "PreciseWait"                   --https://www.hiveworkshop.com/threads/precise-wait-gui-friendly.316960/
--[[
Lua Unit Event 1.2.0.2

In addition to the existing benefits enjoyed over the past years, this Lua version supports linked events that allow
your trigger to Wait until another event runs (meaning you can do attachment and cleanup from one trigger).

Variable names have been completely changed from all prior Unit Event incarnations.
> All real variable event names are now prefixed with OnUnit...
> All array references (unit properties) are now prefixed with UnitEvent_
> Lua users can access a unit's properties via UnitEvent[unit].property (e.g. reincarnating/cargo)
> Lua users can easily add a readonly GUI property to a unit via UnitEvent.addProperty("propertyName")
>>> GUI accesses it via UnitEvent_propertyName, the second is readable and writable within Lua via UnitEvent[unit].propertyName
> UnitUserData (custom value of unit) has been completely removed. This is the first unit event/indexer to not use UnitUserData nor hashtables.
>>> UnitEvent_unit is the subject unit of the event.
>>> UnitEvent_index is an integer in GUI, but points to a the unit.
>>> UnitEvent_setKey lets you assign a unit to the key.
>>> UnitEvent_getKey is an integer in GUI, but points to the unit you assigned as the key.
>>>>> Lua doesn't care about array max sizes, nor the type of information used as an index in that array (because it uses tables and not arrays).
>>>>> GUI is over 20 years old and can easily be fooled. As long as the variable is defined with the correct type, it doesn't care what happens to that variable behind the scenes.
--]]
    UnitEvent={}

    local _REMOVE_ABIL      = FourCC('A001')
    local _TRANSFORM_ABIL   = FourCC('A002') --be sure to assign these to their respective abilities if you prefer not to initialize via GUI
    
    --Un-comment this next line if you want to use the custom value of units functionality (for backwards compatibility):
    --GetUnitUserData = function(unit) return unit end

--[[
    Full list of GUI variables:
    real    udg_OnUnitIndexed
    real    udg_OnUnitCreation
    real    udg_OnUnitRemoval
    real    udg_OnUnitReincarnating
    real    udg_OnUnitRevival
    real    udg_OnUnitLoaded
    real    udg_OnUnitUnloaded
    real    udg_OnUnitTransform
    real    udg_OnUnitDeath
    real    udg_OnUnitActive
    real    udg_OnUnitPassive

    ability udg_DetectRemoveAbility
    ability udg_DetectTransformAbility

    unit    udg_UnitEvent_unit
    integer udg_UnitEvent_index

    unit    udg_UnitEvent_setKey
    integer udg_UnitEvent_getKey

    boolean   array udg_UnitEvent_preplaced
    unit      array udg_UnitEvent_summoner
    unittype  array udg_UnitEvent_unitType
    boolean   array udg_UnitEvent_reincarnating
    unit      array udg_UnitEvent_transporter
    unitgroup array udg_UnitEvent_cargo
--]]

    local eventList={}
    local udg_prefix="udg_OnUnit"
    local makeAPI = function(name)
        UnitEvent["on"..name],
        eventList["on"..name] = CreateEvent(udg_prefix..name, true)
    end
    local unitIndices={} ---@type UnitEventTable[]

    --onIndexed and onCreation occur at roughly the same time, but the unit's creation should be used instead as it will have more data.
    --Combined, they are the counterparts to onRemoval.
    makeAPI("Indexed")
    makeAPI("Creation")
    makeAPI("Removal")

    --counterparts (though revival doesn't only come from reincarnation):
    makeAPI("Reincarnating")
    makeAPI("Revival")
    
    --perfect counterparts:
    makeAPI("Loaded")
    makeAPI("Unloaded")
    
    --stand-alone events:
    makeAPI("Transform")
    makeAPI("Death")
    
    --perfect counterparts that generalize all but the "transform" event:
    makeAPI("Active")
    makeAPI("Passive")

    --Used to get the UnitEvent table from the unit to detect UnitEvent-specific properties.
    UnitEvent.__index = function(_, unit) return unitIndices[unit] end
    
    ---@param name string
    UnitEvent.addProperty = function(name)
        GlobalRemapArray("udg_UnitEvent_"..name, function(unit) return unitIndices[unit][name] end)
    end

    ---@class UnitEventTable : table
    ---@field unit          unit
    ---@field preplaced     boolean
    ---@field summoner      unit
    ---@field transporter   unit
    ---@field cargo         group
    ---@field reincarnating boolean
    ---@field private new boolean
    ---@field private alive boolean
    ---@field private unloading boolean
    
    --The below two variables are intended for GUI typecasting, because you can't use a unit as an array index.
    --What it does is bend the rules of GUI (which is still bound by strict JASS types) by transforming those
    --variables with Global Variable Remapper (which isn't restricted by any types).
    --"setKey" is write-only (assigns the key to a unit)
    --"getKey" is read-only (retrieves the key and tells GUI that it's an integer, allowing it to be used as an array index)
    local lastUnit
    GlobalRemap("udg_UnitEvent_setKey", nil, function(unit)lastUnit=unit end) --assign to a unit to unlock the getKey variable.
    GlobalRemap("udg_UnitEvent_getKey",      function() return lastUnit  end) --type is "integer" in GUI but remains a unit in Lua.

    local runEvent
    do
        local eventUnit
        local getEventUnit  = function() return eventUnit end
        runEvent            = function(event, unitTable)
            local cached    = eventUnit
            eventUnit       = unitTable.unit
            eventList[event](unitTable)
            eventUnit       = cached
        end
        GlobalRemap("udg_UnitEvent_unit",  getEventUnit) --the subject unit for the event.
        GlobalRemap("udg_UnitEvent_index", getEventUnit) --fools GUI into thinking unit is an integer
    end
    --add a bunch of read-only arrays to access GUI data. I've removed the "IsUnitAlive" array as the GUI living checks are fixed with the GUI Enhancer Colleciton.
    UnitEvent.addProperty("preplaced")
    UnitEvent.addProperty("unitType")
    UnitEvent.addProperty("reincarnating")
    UnitEvent.addProperty("transporter")
    UnitEvent.addProperty("summoner")
    
    if rawget(_G, "udg_UnitEvent_cargo") then
        UnitEvent.addProperty("cargo")
    end
    
    --Flag a unit as being able to move or attack on its own:
    local function setActive(unitTable)
        if unitTable and not unitTable.active and UnitAlive(unitTable.unit) then --be sure not to run the event when corpses are created/unloaded.
            unitTable.active = true
            runEvent("onActive", unitTable)
        end
    end
    ---Flag a unit as NOT being able to move or attack on its own:
    local function setPassive(unitTable)
        if unitTable and unitTable.active then
            unitTable.active = nil
            runEvent("onPassive", unitTable)
        end
    end
    local function getFunc(active)
        return function(unitTable) (active and setActive or setPassive)(unitTable) end
    end

    UnitEvent.onCreation(getFunc(true), 2, true)
    UnitEvent.onUnloaded(getFunc(true), 2, true)
    UnitEvent.onRevival(getFunc(true), 2, true)
    
    UnitEvent.onLoaded(getFunc(), 2, true)
    UnitEvent.onReincarnating(getFunc(), 2, true)
    UnitEvent.onDeath(getFunc(), 2, true)
    UnitEvent.onRemoval(getFunc(), 2, true)
    
    --UnitEvent.onIndex(function(unitTable) print(tostring(unitTable.unit).."/"..GetUnitName(unitTable.unit).." has been indexed.") end)
    
    setmetatable(UnitEvent, UnitEvent)

    --Wait until GUI triggers and events have been initialized. 
    OnTrigInit(function()
        if rawget(_G, "Trig_Unit_Event_Config_Actions") then
            Trig_Unit_Event_Config_Actions()
            _REMOVE_ABIL    = udg_DetectRemoveAbility    or _REMOVE_ABIL
            _TRANSFORM_ABIL = udg_DetectTransformAbility or _TRANSFORM_ABIL
        end
        local function checkAfter(unitTable)
            if not unitTable.checking then
                unitTable.checking              = true
                Timed.call(0, function()
                    unitTable.checking          = nil
                    if unitTable.new then
                        unitTable.new           = nil
                        runEvent("onCreation", unitTable) --thanks to Spellbound for the idea
                    elseif unitTable.transforming then
                        local unit = unitTable.unit
                        runEvent("onTransform", unitTable)
                        unitTable.unitType = GetUnitTypeId(unit) --Set this afterward to give the user extra reference

                        --Reset the transforming flags so that subsequent transformations can be detected.
                        unitTable.transforming  = nil
                        UnitAddAbility(unit, _TRANSFORM_ABIL)
                    elseif unitTable.alive then
                        unitTable.reincarnating = true
                        unitTable.alive         = false
                        runEvent("onReincarnating", unitTable)
                    elseif UnitAlive(unitTable.unit) then
                        unitTable.alive = true
                        runEvent("onRevival", unitTable)
                        unitTable.reincarnating = false
                    end
                end)
            end
        end
    
        local re = CreateRegion()
        local r = GetWorldBounds()
        local maxX, maxY = GetRectMaxX(r), GetRectMaxY(r)
        RegionAddRect(re, r); RemoveRect(r)
        
        local function unloadUnit(unitTable)
            local unit, transport       = unitTable.unit, unitTable.transporter
            GroupRemoveUnit(unitIndices[transport].cargo, unit)
            unitTable.unloading         = true
            runEvent("onUnloaded", unitTable)
            unitTable.unloading         = nil
            if not IsUnitLoaded(unit) or not UnitAlive(transport) or GetUnitTypeId(transport) == 0 then
                unitTable.transporter   = nil
            end
        end
        
        local preplaced = true
        local onEnter = Filter(
        function()
            local unit = GetFilterUnit()
            local unitTable = unitIndices[unit]
            if not unitTable then
                unitTable = {
                    unit    = unit,
                    new     = true,
                    alive   = true,
                    unitType= GetUnitTypeId(unit)
                }
                UnitAddAbility(unit, _REMOVE_ABIL)
                UnitMakeAbilityPermanent(unit, true, _REMOVE_ABIL)
                UnitAddAbility(unit, _TRANSFORM_ABIL)

                unitIndices[unit] = unitTable

                unitTable.preplaced = preplaced
                runEvent("onIndexed", unitTable)
                
                checkAfter(unitTable)
            elseif unitTable.transporter and not IsUnitLoaded(unit) then
                --the unit was dead, but has re-entered the map (e.g. unloaded from meat wagon)
                unloadUnit(unitTable)
            end
        end)
        TriggerRegisterEnterRegion(CreateTrigger(), re, onEnter)
        
        RegisterAnyPlayerUnitEvent(EVENT_PLAYER_UNIT_LOADED,
        function()
            local unit = GetTriggerUnit()
            local unitTable = unitIndices[unit]
            if unitTable then
                if unitTable.transporter then
                    unloadUnit(unitTable)
                end
                --Loaded corpses do not issue an order when unloaded, therefore must
                --use the enter-region event method taken from Jesus4Lyf's Transport: https://www.thehelper.net/threads/transport-enter-leave-detection.126051/
                if not unitTable.alive then
                    SetUnitX(unit, maxX)
                    SetUnitY(unit, maxY)
                end
                local transporter = GetTransportUnit()
                unitTable.transporter = transporter
                local g = unitIndices[transporter].cargo
                if not g then
                    g=CreateGroup()
                    unitIndices[transporter].cargo = g
                end
                GroupAddUnit(g, unit)
                
                runEvent("onLoaded", unitTable)
            end
        end)
        
        RegisterAnyPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH,
        function()
            local unitTable = unitIndices[GetTriggerUnit()]
            if unitTable then
                unitTable.alive = false
                runEvent("onDeath", unitTable)
                if unitTable.transporter then
                    unloadUnit(unitTable)
                end
            end
        end)
        
        RegisterAnyPlayerUnitEvent(EVENT_PLAYER_UNIT_SUMMON,
        function()
            local unitTable = unitIndices[GetTriggerUnit()]
            if unitTable.new then
                unitTable.summoner = GetSummoningUnit()
            end
        end)
        
        local orderB = Filter(
        function()
            local unit = GetFilterUnit()
            local unitTable = unitIndices[unit]
            if unitTable then
                if GetUnitAbilityLevel(unit, _REMOVE_ABIL) == 0 then

                    runEvent("onRemoval", unitTable)
                    unitIndices[unit] = nil
                    unitTable.cargo = nil
                elseif not unitTable.alive then
                    if UnitAlive(unit) then
                        checkAfter(unitTable)
                    end
                elseif not UnitAlive(unit) then
                    if unitTable.new then
                        --This unit was created as a corpse.
                        unitTable.alive = false
                        runEvent("onDeath", unitTable)

                    elseif not unitTable.transporter or not IsUnitType(unit, UNIT_TYPE_HERO) then
                        --The unit may have just started reincarnating.
                        checkAfter(unitTable)
                    end
                elseif GetUnitAbilityLevel(unit, _TRANSFORM_ABIL) == 0 and not unitTable.transforming then
                    unitTable.transforming = true
                    checkAfter(unitTable)
                end
                if unitTable.transporter and not unitTable.unloading and not (IsUnitLoaded(unit) and UnitAlive(unit)) then
                    unloadUnit(unitTable)
                end
            end
        end)
        
        local p
        local order = CreateTrigger()
        for i = 0, bj_MAX_PLAYER_SLOTS - 1 do
            p = Player(i)
            GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, onEnter)
            SetPlayerAbilityAvailable(p, _REMOVE_ABIL, false)
            SetPlayerAbilityAvailable(p, _TRANSFORM_ABIL, false)
            TriggerRegisterPlayerUnitEvent(order, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, orderB)
        end
        preplaced = false
    end)
end)

How to install:

- Delete Unit Indexer from your map (if you already have it)
- Copy the "Unit Event Ability" ability from Object Editor
- Copy the Unit Event trigger category
- Paste the Unit Event Ability from object editor twice
- Set the DetectRemoveAbility variable in the Unit Event Config trigger to one of the abilities.
- Set the DetectTransformAbility variable in the same trigger to the other of the two.


Inspiration:

- AutoEvents by grim001 (was hosted on the now-defunct wc3c.net)
- UnitEvent by Nestharus: https://github.com/nestharus/JASS/blob/master/jass/Systems/Unit%20Event/script.j
- Transport by Jesus4Lyf: https://www.thehelper.net/threads/transport-enter-leave-detection.126051/

nestharus, grim001, unitevent, autoevents, unit indexer, reincarnate, reincarnation, reanimation, resurrect, resurrection, detect, death, removal, load, unload, transport, transform, unit type
Contents

Lua Unit Event Test Map (Map)

Unit Event 2.5.3.1 (Map)

Reviews
Approved. Makes easy to detect many events that do not exist in the editor. Very useful system.
Level 4
Joined
Jan 27, 2016
Messages
89
Well, its not functioning yet. However, I dont think it would ever even reach 2k, but I sometimes see the Indexer just skip numbers a lot and it worries me that it would eventually go over 8k, so its a safety net. And Im mostly suggesting it for the fun of it, so that the systen has 1 less "limitation"

Well never mind, array max is now around 30k, thanks Blizz!
 
So I'm trying to detect animate dead:

Detect when a unit is brought back to life via Reincarnation, Resurrect or Reanimate
Event: Game - DeathEvent Becomes Equal to 2.00

You can differentiate between the three of these as well. If it is summoned, that means it was reanimated. If IsUnitReincarnating[UDex] is true, that means it finished reincarnating. Otherwise, it was simply resurrected.

I did if IsUnitType(DyingUnit, UNIT_TYPE_SUMMONED) then but it didn't work. Am I using the wrong native?


EDIT: WELL THIS IS AWKWARD. It seems to work now, but I'm not sure why it wasn't working before. Might have been a different issue. Plz ignore.
 
Last edited:
Level 10
Joined
Oct 5, 2008
Messages
355
Hey,

Currently i am running your system in some maps of mine but recently i found a problem that is a bit bugging me. Whenever i kill a unit, the game has a small but noticeable lag spike, which is independent on the map or triggers- I even encounter the same problem in the testmap when i put down some peasants and let them get killed.
If i had some time to spare i would take a look at it, but do you got spontaniously an idea where this is coming from? For reference, I'm using the newest version of the system.
 
Level 4
Joined
Jan 27, 2016
Messages
89
Would it be possible to utilize Reincarnation and the unit even system to create a custom corpse/resurrection system? So that we can dynamically shift a unit from alive to dead and toy with its "corpse" with less limitation. Only issue is, auto-cast raise dead wont work.
 
Level 11
Joined
Aug 24, 2009
Messages
706
Hey,

Currently i am running your system in some maps of mine but recently i found a problem that is a bit bugging me. Whenever i kill a unit, the game has a small but noticeable lag spike, which is independent on the map or triggers- I even encounter the same problem in the testmap when i put down some peasants and let them get killed.
If i had some time to spare i would take a look at it, but do you got spontaniously an idea where this is coming from? For reference, I'm using the newest version of the system.

I can confirm the last patch borked this system it lags every time a unit dies with this trigger enabled
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Hey,

Currently i am running your system in some maps of mine but recently i found a problem that is a bit bugging me. Whenever i kill a unit, the game has a small but noticeable lag spike, which is independent on the map or triggers- I even encounter the same problem in the testmap when i put down some peasants and let them get killed.
If i had some time to spare i would take a look at it, but do you got spontaniously an idea where this is coming from? For reference, I'm using the newest version of the system.

I can confirm the last patch borked this system it lags every time a unit dies with this trigger enabled

Hi you two. Thank you for reporting this. I have now updated to 2.5.1.0 which fixes an issue where a unit could be added to the CheckDeathFilter more than once. This was done by tracking whether a unit is in the list via a "-1" value in the list by default.

Also, to the post above asking about manual reincarnation - this is not one of the uses of Unit Indexer. You need a resource like [Snippet] ReviveUnit.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Sounds like your Unit Event is out of date. Go ahead and replace your Unit Event triggers with the ones from this demo map.

I double checked the triggers for regression in case I made a blunder with the 1.29 update, but it should still work.

Edit: another possibility is that it may have broken when i removed the infinite loop thing in the last update. Please let me know how you get on. I won't be able to update the demo map for an indefinite period of time, but I can update the JASS code.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
OK I've found the source of the issue with transform no longer being detected (it is specific to the patches with the combined buff-overlapping stuff, which I guess from what you're saying started in 1.29. I'm testing on 1.30).

With the advancement of the buff overlapping stuff, the second instance of the Defend ability is somehow also set to Permanent when I use the UnitMakeAbilityPermanent native.

So this means I would have to get rid of the UnitMakeAbilityPermanent line in order to recognize the unit when it transforms, which means only one Defend ability could be used and relied upon.

This is an unfortunate bug, as I'll have to figure out how to detect if the unit was removed or if it was transformed, which may not be easy and may not be worth the tradeoff.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Update to 2.5.2! This update corrects the issue were transform was no longer being recognized. The only steps needed are to re-copy the JASS script and to either re-copy the config trigger or manually add the one new variable to your variable list:

CheckDeathInList boolean array

There were no changes made to the spell abilities - installation steps are still the same as before. It was difficult to track down why this is failing, so there may be one or two redundant "resets" of the linked list in the code (that don't have a performance impact).
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Works like a miracle on my 1.29.2 :) thanks Bribe!
So the second "defend" ability also works on 1.30? Really good to have UnitEvent working with all its features.
Yeah, fixing the linked list was the key. The second defend ability wasn't working because the timer was never deploying.
 
Level 7
Joined
Aug 8, 2008
Messages
340
Hi Bribe, I was wondering how one would go about refering to the local owner of a reincarnating unit? Like
Custom script: If GetLocalPlayer() == GetOwningPlayer(Get???Unit())
Sound - Play Sound
Custom script: endif

I’m currently working on a trigger, where the owner of the reincarnating unit hears a voice when the unit starts reincarnating and once again when it finishes reincarnating.
 
Level 7
Joined
Aug 8, 2008
Messages
340
I’m aware, but thanks for pointing it out. I’m rather new to the whole local player thing, so I hope you don’t mind me asking. This would be the right way to refer to the owner of that unit:
Custom script: If GetLocalPlayer() == GetOwningPlayer(GetUDexUnits[UDex]Unit())
right?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Not at all. You can't know what to use there without knowing some basic JASS. It's easier to use Custom Script earlier in the game like with a 0 Seconds Game Time trigger like this (paste into Custom script):

set udg_LocalPlayer = GetLocalPlayer()

That way, you'll never have issues figuring out custom script to use the local player - you can just use it right from there with the GUI variable "LocalPlayer".

I used this trick in my WarChasers Remastered map.
 
Level 4
Joined
Jan 7, 2014
Messages
69
can you explain to me Bribe, why this indexing is better than just use a triggers with standart events? i mean i see the point to use this system for reinc detect for example, but, summoning, cargo, death events, spell events...why this is better and what should i do if dont wanna use indexing for all units on map? only for heroes for example and specific units where i need to detect smth.
 
Level 12
Joined
Jun 12, 2010
Messages
413
can you explain to me Bribe, why this indexing is better than just use a triggers with standart events? i mean i see the point to use this system for reinc detect for example, but, summoning, cargo, death events, spell events...why this is better

If you use summoning, cargo, death or enter map events, then you cannot assume that they will be executed before the unit is indexed. Therefore, you can easily stumble into a bug where you want to use UDex but it's not set to the right unit custom value.

This system has no support for spell events.

what should i do if dont wanna use indexing for all units on map? only for heroes for example and specific units where i need to detect smth.

You will have to edit the jass code, the system has no default support for that. It's a pretty easy edit, though.

JASS:
function UnitEventEnter takes nothing returns boolean
    local integer pdex = udg_UDex
    local integer i = udg_UDexLastRecycled
    local unit u = GetFilterUnit()
    //IF UNIT AS DECORATION ABILITY, DO NOT INDEX THIS UNIT
    if GetUnitAbilityLevel(u , 'A0C6') != 0 then
        call SetUnitUserData(u, 0)
        set u = null
        return false
    endif

In my map, I just added that if check right at the top of the UnitEnterEvent function.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Summoning was a bit unnecessary to add, mostly it is there because I think someone asked for it.

Cargo events natively only detect the loading, but not the unloading. So that's why that one is there.

Reincarnation and reanimation, as well as hero revival, are all easily tracked.

The conditions used to have a GUI boolean to scan, but it got lost in the transition of the system to the JASS with GUI overlay. That was an oversight on my part.

I'm not feeling really up to it to maintain these resources until I know what kinds of stuff the new natives will bring. I don't want to spend a dozen hours finishing up the stuff I have mostly-ready (already at least a hundred hours into various incomplete things).

My laptop has issues where half the keys no longer work for some stupid reason, so doing all this would need an external keyboard connected which is a huge inconvenience.

I'll wait for the new patch and then see if any systems of mine are still worth the investment to update or publish.
 
Level 4
Joined
Jan 7, 2014
Messages
69
Summoning was a bit unnecessary to add, mostly it is there because I think someone asked for it.

Cargo events natively only detect the loading, but not the unloading. So that's why that one is there.

Reincarnation and reanimation, as well as hero revival, are all easily tracked.

The conditions used to have a GUI boolean to scan, but it got lost in the transition of the system to the JASS with GUI overlay. That was an oversight on my part.

I'm not feeling really up to it to maintain these resources until I know what kinds of stuff the new natives will bring. I don't want to spend a dozen hours finishing up the stuff I have mostly-ready (already at least a hundred hours into various incomplete things).

My laptop has issues where half the keys no longer work for some stupid reason, so doing all this would need an external keyboard connected which is a huge inconvenience.

I'll wait for the new patch and then see if any systems of mine are still worth the investment to update or publish.


new patch comming soon? Do you have any info about when?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Coming soon: Lua Unit Event! I'm really excited for the prospects of this one, because this update is going to plug a huge GUI inconsistency that will enable the standard "Unit is alive/dead" checks to work correctly in all cases.

Also, for those familiar with [Snippet] RegisterEvent pack the Lua Unit Event library will do that sort of thing... but with normal GUI triggers. The future is here!
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Hello, it would be appreciated if you could tell me:

As a replacement for the "transformed" militia unit, it will be detected, but I want to replace it.

In your instructions it seems to me that you only indicate how to refer to the unit before transforming.

If it's obvious, excuse me, I'm an old rookie in this
The event takes place after the transformation finishes. You can replace the unit at that time.
 
Thanks for your answer. (When I try to do what you tell me, the game closes, I'm probably doing it wrong)

For now I am trying to detect how many units there are in a transport when one unit goes up to it.

Event
Game - CargoEvent becomes Equal to 1.00
Condition
(Unit-type of CargoTransportUnit [UDex]) Equal to Ship
Action
Game - Display to (All players) the text: (String ((Number of units in CargoTransportGroup [UDex])))

It always gives me "0"

PD: Should I make a thread for these queries?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Event
Game - CargoEvent becomes Equal to 1.00
Condition
(Unit-type of CargoTransportUnit [UDex]) Equal to Ship
Action
Game - Display to (All players) the text: (String ((Number of units in CargoTransportGroup [UDex])))

It always gives me "0"

You need to change the string to:

Number of units in CargoTransportGroup [(Custom value of CargoTransportUnit [UDex])]
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Does Reincarnation possible to detect what ability used to reincarnate the unit?
No this resource wouldn't tell you that. But I think you can get the remaining cooldown of the ability if you know the ability or a list of reincarnation abilities in advance, which could help you too determine which one went off. This requires patch 1.29 or later if I'm not mistaken.
 
No this resource wouldn't tell you that. But I think you can get the remaining cooldown of the ability if you know the ability or a list of reincarnation abilities in advance, which could help you too determine which one went off. This requires patch 1.29 or later if I'm not mistaken.
Thanks!
 
Level 10
Joined
May 31, 2019
Messages
139
I'm trying to use CargoEvent becomes 2.00 (for unloading a unit) but the trigger with the event does not fire at all.
I am using 1.28 though, does it require a later version? if so, is there an older version available that's compatible?
 
Last edited:
Top