• 🏆 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.

Moderator

M

Moderator

Maker, Unit Event v2.0.0.0, 17:48, 24th Nov 2011

Approved.

Makes easy to detect many events that do not exist in the editor. Very useful system.
 
Level 6
Joined
Dec 10, 2010
Messages
119
And what for this needed? Senseless work.
My version -
  • Death Event
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
  • Custom script: local integer i=0
  • Custom script: loop
  • Custom script: exitwhen i > 12
    • Custom script: call DisplayTextToPlayer(Player(0),0,0,GetUnitName(GetDyingUnit()) + " has dead.")
  • Custom script: i=i+1
  • Custom script: endloop
 
And what for this needed? Senseless work.
My version -
  • Death Event
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
  • Custom script: local integer i=0
  • Custom script: loop
  • Custom script: exitwhen i > 12
    • Custom script: call DisplayTextToPlayer(Player(0),0,0,GetUnitName(GetDyingUnit()) + " has dead.")
  • Custom script: i=i+1
  • Custom script: endloop

As you have fail to read what Bribe has wrote he mentions "reincarnation" and what you have there, is just a text that the unit has died?
Also this system also uses his famous GUI Unit Indexer; which turned out to be a quite remarkable system

Edit :

Bribe once again your work is remarkable; will surely help those who use GUI.
Good work; Rating 5/5

Evilcrizpy
 
Last edited:
Pain when people do that; Just saying...

On Topic :

Bribe never fails to amaze us all....

Edit :
Hmmmm im not too sure, what could be improved tbh :/
I feel like its missing something but dont know what...


Edit 2 :

How about a floating text at position of the dead unit, showing time till revived maybe?
But only shows for allies of the dying unit....
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
That's the demo map. This doesn't use a timer to detect when reincarnation finishes, so
a timer would not be possible here. The "defend" ability has a bug that make it fire an
"undefend" order when a unit dies, gets removed or gets revived, which is what this is
based on.

You can't get the duration of Reincarnation without consulting the object editor, so this
will work with any duration of reincarnation. It wouldn't make sense to set a timer
because the reincarnation could be 1 second, it could be 7 or it could be 60.
 
That's the demo map. This doesn't use a timer to detect when reincarnation finishes, so
a timer would not be possible here. The "defend" ability has a bug that make it fire an
"undefend" order when a unit dies, gets removed or gets revived, which is what this is
based on.

You can't get the duration of Reincarnation without consulting the object editor, so this
will work with any duration of reincarnation. It wouldn't make sense to set a timer
because the reincarnation could be 1 second, it could be 7 or it could be 60.

Ahh right okay,
haven't had chance todownload the map yet, cause not on my laptop,
I understand, okay then i shall change my rating to 5/5, just that was making it difficult to choose between 5 and 4.5,

Looks great tho.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
maddeem, you have a very skeptical attitude towards basically everything I upload.

I challenge you to make a reincarnation detection that detects exactly when the unit starts
reincarnating, exactly when it stops reincarnating, perfectly on queue like this does. I also
challenge you to include a way to detect when a unit is raised from the dead like this does.
Also keep in mind that reincarnation can have basically any timeout. So starting a timer to
expire in 7 seconds is not going to do any good.

It can't be done any simpler than this. Look at how complex Unit Event by Nestharus is,
for comparison. This is a minimal approach to do something so useful.

http://www.hiveworkshop.com/forums/jass-functions-413/extension-unit-event-172365/

Reincarnation detection is one of the most requested things out there, as well. So the idea
is bad? Really, I'm calling you on this. Do it better or don't knock it. I want you to explain
your opinion better than this blank reply you've given.

Also, high end maps don't use reincarnation? I'm not sure you know what you're talking about.
 
maddeem, you have a very skeptical attitude towards basically everything I upload.

I challenge you to make a reincarnation detection that detects exactly when the unit starts
reincarnating, exactly when it stops reincarnating, perfectly on queue like this does. I also
challenge you to include a way to detect when a unit is raised from the dead like this does.
Also keep in mind that reincarnation can have basically any timeout. So starting a timer to
expire in 7 seconds is not going to do any good.

It can't be done any simpler than this. Look at how complex Unit Event by Nestharus is,
for comparison. This is a minimal approach to do something so useful.

http://www.hiveworkshop.com/forums/jass-functions-413/extension-unit-event-172365/

Reincarnation detection is one of the most requested things out there, as well. So the idea
is bad? Really, I'm calling you on this. Do it better or don't knock it. I want you to explain
your opinion better than this blank reply you've given.

Also, high end maps don't use reincarnation? I'm not sure you know what you're talking about.

maddeem, A world of notice;
- Don't mess with Bribe
- You should really read up a bit more before posting negative comments about someones system
- Unless you are able to create something the same but in a simpler form

- Bribe makes these, so people are able to have a much easier map making life, rather than doing it themselves, especially those new to Warcraft III and Jass, so he has made GUI Versions.

Evilcrizpy

Edit :
Also as bribe mentions, believe you can do bettter; go ahead.
If you are able to succeed then yes i shall applaud you.
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
So let's do this.

-Make another ini trigger with this in? Isn't it useless to check this if all the time even if it's a ini thingie

  • Custom script: if udg_DEvAbility == 0 then
  • -------- --------
  • -------- Copy Death Event Ability from Object Editor, then set DEvAbility to it as follows --------
  • -------- --------
  • Set DEvAbility = Death Event Ability (Undefend Detect)
  • -------- --------
  • Custom script: call ExecuteFunc("InitDeathEvent")
  • Custom script: endif
-You made the make ability permanent bj go away so why not this one as well? (yeah it is a lame bj like the pause unit bj but you already know that)

  • Unit - Add DEvAbility to UDexUnits[UDex]
-Another bj

(Level of DEvAbility for UDexUnits[UDex]) Equal to 0

-And the variable safety checks are they really necessary? the first one could be removed or the last one, no?

  • Set DeathEvent = 0.00
  • Set DeathEvent = 1.00
  • Set DeathEvent = 0.00
Anyway great work as always although I'd like to see a GUIer use this.

edit

and a hidden tag around the code would be nice as well!
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
-And the variable safety checks are they really necessary? the first one could be removed or the last one, no?

I did that because of recursion - that is a nasty thing. If the function is called twice before
it can be set to 0, the second event won't fire because you set variable with value 1 to 1
again which doesn't trigger the event. I set to 0 afterward because maybe you want some
kind of event id check (which I use in this script btw).

Which brings my next point regarding this:

Make another ini trigger with this in? Isn't it useless to check this if all the time even if it's a ini thingie

The problem is the Map Initialization event is not guaranteed to run before the map
initialization event of Unit Indexer, so then you'd be adding an ability to the unit which
has a value of 0.

You made the make ability permanent bj go away so why not this one as well? (yeah it is a lame bj like the pause unit bj but you already know that)

Is there a GUI function for it? I didn't see it, which is why I made the custom script.
Obsessing over BJ's to the point where you make custom script just to avoid them is
pointless in almost all cases. If I cared so much I would eliminate all the GUI if-blocks
and well I'd not even use GUI for that matter, because then I'd be using conditions for
actions for that speed advantage, too. Then I'd be doing some inane variable shortening.

Trust me some things are not worth it. That's why I don't have such impositions on GUI
users who submit their spells here. The standards for a pure-JASS script are much
higher than a GUI script, because there are fewer limitations with pure JASS scripts.
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
1.
The problem is the Map Initialization event is not guaranteed to run before the map
initialization event of Unit Indexer, so then you'd be adding an ability to the unit which
has a value of 0.


2.
Is there a GUI function for it? I didn't see it, which is why I made the custom script.
Obsessing over BJ's to the point where you make custom script just to avoid them is
pointless in almost all cases. If I cared so much I would eliminate all the GUI if-blocks
and well I'd not even use GUI for that matter, because then I'd be using conditions for
actions for that speed advantage, too. Then I'd be doing some inane variable shortening.

Trust me some things are not worth it. That's why I don't have such impositions on GUI
users who submit their spells here. The standards for a pure-JASS script are much
higher than a GUI script, because there are fewer limitations with pure JASS scripts.

1. Ah I see, my bad.

2. Yeah it's in the "player" category I think. It confused me a bit that you were a BJ hunter and still had a BJ right before it lol
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
I have a completed Cargo Event which lets you pick all units inside of a transport, detect
when a unit is unloaded from a transport, and also get the transport carrying a unit. It
would require this script to run, but I am wondering if I should just merge it into this
script because AutoEvents by grim001 merges those two libraries as well.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Yeah but there are pros and cons to doing it your way -

Pros: No coupling, so if you need reincarnate detect you are not forced to take transport detection
More relevant and specific resources

Cons: have to install this script before using Cargo Event, so Cargo Event will almost
be not worth its own submission because it would be very short.
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Yeah maybe that's how it should be done. Either way just have it in another category and tell the user (some have really difficult issues with reading, maybe a picture in the description?) that this category is fully optional, nothing will happen if you remove it; and this and that you will get if you keep it.
 
Level 9
Joined
Feb 17, 2009
Messages
291
Since someone like me is bound to stumble upon this resource again, let me just say if you are confused why you import it to another map and it doesn't work, make a new variable called DEvTimer as type Timer. Can't believe no one bothered to explain that after four years but whatever.
 
Level 35
Joined
Feb 5, 2009
Messages
4,551
I'm a bit confused as I have imported it into my map but find that everything works other than the reincarnation asset. For some reason it just seems completely unresponsive to reincarnation events.

UPDATE: I fixed it, it was a simple issue of me transferring the triggers before transferring the Death Event ability, so the trigger that relied upon that particular ability was relying on another - doy!

Great system, love it ^_^
 

Ardenian

A

Ardenian

Does this great system aims for adding new events in general ?

What about an event for ' A unit crosses a special effect/ lightning' ?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
It's possible that the unit will fire the undefend event when it transforms back into a structure, though it's completely hypothetical. Go ahead and add a tree of life to this test map and make a trigger that displays the order ID when any of the 3 orders (point, immediate, target) are issued. If there is an order issued at the exact moment you need, that is the base of what you're looking for. You can then refine the conditions to rule out units that are not ancient type, and to make sure that the ancient is also alive.
 
Okay, so I tried to detect order id with this trigger:

  • Order String
    • Events
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
    • Actions
      • Custom script: call BJDebugMsg("OrderId is: "+I2S(GetIssuedOrderId()))
When the Ancient uproots, it seems to detect something, but it doesn't detect an Order ID when then Tree of Life begins or ends rooting back into place. Does that mean it can't be detected then?
 
Tried building a farm and there was no order id detected upon completion (there was one on building start though). I'm using ConstructEvent to catch buildings that begin contruction - does that mean I can just use Unit Event instead? The reason I was curious about root/uproot was so that I could add/remove abilities to units/buildings that used it.

Alternatively, I could just try making a custom root/uproot with metamorphosis and build tiny farm for the rooting. The goal here is to have flying buildings since structures are generally targetable by anything that can attack structures.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Update to 2.1.0.0 - I have added an event "UnitTypeEvent becomes Equal to 1.00" to detect when a unit transforms to a different unit type the instant the new unit type is acquired (so at the very end of the demon hunter's metamorphosis transformation). This was achieved by making a second copy of the Undefend Detect ability that was set to "not permanent" unlike the primary death event ability which detects unit removal. It is re-added to the unit each time it transforms so it can detect subsequent transforms.
 
Oh? I kinda went around the issue of rooting by using metamorphosis and build tiny farm, using passive transformation when the unit got close enough to the x/y co-ordinates of the targeted building to morph into the rooted version. This also solves some crashing issues I was having with buildings that have root that cancel an upgrade.

Still, might come in handy :p
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Following the trend of my other resources to switch from GUIJASS to a GUI configuration trigger with a JASS backbone, I have updated UnitEvent to version 2.2.0.0!

This is a big departure from previous versions, namely that it actually absorbs the Unit Indexer trigger into itself - which means that Unit Event is now also Unit Indexer. Does this mean that no one can use Unit Indexer by itself without Unit Event? NO. But if you use Unit Event, you must delete the Unit Indexer trigger.

Why did I do this? Simplification and efficiency. The current code for Unit Event is about half of what the combined length of the old Unit Event and Unit Indexer were. I also had additional events running off of Unit Indexer which overlapped what I was doing in Unit Event. AutoEvents by grim001 and UnitEvent by Nestharus both integrate their event library with their indexer for this reason, and now I've done the same.

I made some big improvements, as well:

UnitIndexEvent Becomes Equal to 2.00 now fires the instant the unit is removed, not after an arbitrary amount of time. It also does not bug when a paused unit is removed from a transport, so I no longer need a timer to detect when they are unloaded.

I also no longer need a timer to detect when a corpse is unloaded from a transport, as I am now using Jesus4Lyf's "enter region" trick to detect when those are unloaded.

Hope you guys like it, and - as always - feel free to ask me any questions you have about it.
 
"UnitIndexEvent Becomes Equal to 2.00 now fires the instant the unit is removed, not after an arbitrary amount of time."

I always wondered about that. This way seems better. Also does that mean that the removal of a timer makes use up less resources to run?

Are you going to JASSify the actual Unit Indexer as well? And Heal Event and 2.5D Knockback?
 
Top