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

[Snippet] [Needs work] Stun {UnitIndexer/Lua}

Installation Script

JASS:
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i dofile("GetVarObject")
    
    //! i local id2 = getvarobject("BSTN", "buffs", "BUFFS_STUN", true)
    //! i createobject("BSTN",id2)
    //! i makechange(current,"fnam","STUN")
    
    //! i local id = getvarobject("ACfb", "abilities", "ABILITIES_STUN", true)
    //! i createobject("ACfb", id)
    //! i makechange(current,"anam","Stun")
    //! i makechange(current,"amat","")
    //! i makechange(current,"amsp","0")
    //! i makechange(current,"arac","0")
    //! i makechange(current,"Htb1","1","0")
    //! i makechange(current,"aran","1","92083")
    //! i makechange(current,"acdn","1","0")
    //! i makechange(current,"ahdu","1","0")
    //! i makechange(current,"adur","1","0")
    //! i makechange(current,"amcs","1","0")
    //! i makechange(current,"atar","1","")
    //! i makechange(current,"abuf","1",id2)
    //! i makechange(current,"aord","firebolt")
    
    //! i updateobjects()
//! endexternalblock

Code

JASS:
library Stun /* v1.0.0.4
*************************************************************************************
*
*   Supports stunning units.
*       -remaining stun time on a unit retrieval
*       -add stun time to unit
*       -set stun time for unit
*       -remove stun from unit
*
*************************************************************************************
*
*   */uses/*
*       */ UnitIndexer /*       hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
*       */ DummyCaster /*       hiveworkshop.com/forums/submissions-414/snippet-dummy-caster-197087/
*       */ Table /*             hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
*
*************************************************************************************
*
*    Functions
*
*       function UnitGetStun takes unit u returns real
*       function UnitAddStun takes unit u, real time returns nothing
*       function UnitSetStun takes unit u, real time returns nothing
*       function UnitRemoveStun takes unit u, real time returns nothing
*
************************************************************************************/
    globals
        private Table h=0
        private timer array t
        private boolean array r
    endglobals
    //stun expire
    private function B takes nothing returns nothing
        local integer i=h[GetHandleId(GetExpiredTimer())]
        set r[i]=false
        call UnitRemoveAbility(GetUnitById(i),BUFFS_STUN)
    endfunction
    //unit death
    private function E takes nothing returns boolean
        local integer i=GetUnitUserData(GetTriggerUnit())
        if (r[i]) then
            set r[i]=false
            call PauseTimer(t[i])
        endif
        return false
    endfunction
    //unit index
    private function M takes nothing returns boolean
        local integer i=GetIndexedUnitId()
        set t[i]=CreateTimer()
        set h[GetHandleId(t[i])]=i
        return false
    endfunction
    //unit deindex
    private function D takes nothing returns boolean
        local integer i=GetIndexedUnitId()
        call h.remove(GetHandleId(t[i]))
        call DestroyTimer(t[i])
        set t[i]=null
        set r[i]=false
        return false
    endfunction
    //init
    private module I
        private static method onInit takes nothing returns nothing
            local trigger q=CreateTrigger()
            local integer i=15
            call DummyCaster[ABILITIES_STUN].register()
            call RegisterUnitIndexEvent(Condition(function M),UnitIndexer.INDEX)
            call RegisterUnitIndexEvent(Condition(function D),UnitIndexer.DEINDEX)
            loop
                call TriggerRegisterPlayerUnitEvent(q,Player(i),EVENT_PLAYER_UNIT_DEATH,null)
                exitwhen 0==i
                set i=i-1
            endloop
            call TriggerAddCondition(q,Condition(function E))
            set h=Table.create()
            set q=null
        endmethod
    endmodule
    private struct N extends array
        implement I
    endstruct
    function UnitGetStun takes unit u returns real
        local integer i = GetUnitUserData(u)
        debug if (0==i) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID UNIT")
            debug return 0.
        debug endif
        if (r[i]) then
            return TimerGetRemaining(t[i])
        endif
        return 0.
    endfunction
    function UnitAddStun takes unit u, real time returns nothing
        local integer i = GetUnitUserData(u)
        debug if (0==i) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID UNIT")
            debug return
        debug endif
        if (r[i]) then
            set time=time+TimerGetRemaining(t[i])
        else
            set r[i]=true
        endif
        if (0<time) then
            call TimerStart(t[i],time,false,function B)
            call DummyCaster[852231].castTarget(u)
        else
            call PauseTimer(t[i])
            set r[i] = false
            call UnitRemoveAbility(GetUnitById(i),BUFFS_STUN)
        endif
    endfunction
    function UnitSetStun takes unit u, real time returns nothing
        local integer i = GetUnitUserData(u)
        debug if (time<0) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID TIME")
            debug return
        debug endif
        debug if (0==i) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID UNIT")
            debug return
        debug endif
        if (0<time) then
            set r[i]=true
            call TimerStart(t[i],time,false,function B)
            call DummyCaster[852231].castTarget(u)
        else
            set r[i]=false
            call PauseTimer(t[i])
            call UnitRemoveAbility(GetUnitById(i),BUFFS_STUN)
        endif
    endfunction
    function UnitRemoveStun takes unit u, real time returns nothing
        local integer i = GetUnitUserData(u)
        debug if (0==i) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID UNIT")
            debug return
        debug endif
        call UnitRemoveAbility(GetUnitById(i),BUFFS_STUN)
        set r[i]=false
        call PauseTimer(t[i])
    endfunction
endlibrary
 
Last edited:
Any plans to update this? I think a simple library that stuns a unit for "X" time is all this really needs to be, using a stun buff with 0 duration (infinite) and removing the buff with a timer. The timer would be paused and re-started if the unit already has a buff.

Get/set of a stun is not needed. Typically you'll just use an "add" method and if the duration is less than the current stun duration you just use whichever one has a greater duration (that's how the wc3 engine handles it anyway).
 
Does not work against magic immunes, invulnerables and is not instant.

I can make dif versions that work against magic immunes + invulnerables ; ). I did what I did purposefully here =). Also, I'll investigate making it instant.

Does SetUnitStun with RemoveUnitStun right afterwards even release the unit?

It should, but I'l investigate =).
 
Level 6
Joined
Jun 20, 2011
Messages
249
I just want to point out that this is completely broken
Doesn't compile with the newest version of dummy caster
Bugs with the hashtable use (i don't know why)
I fixed it here but it uses TimerUtils instead
JASS:
library Stun /* v1.0.0.4
*************************************************************************************
*
*   Supports stunning units.
*       -remaining stun time on a unit retrieval
*       -add stun time to unit
*       -set stun time for unit
*       -remove stun from unit
*
*************************************************************************************
*
*   */uses/*
*       */ UnitIndexer /*       hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
*       */ DummyCaster /*       hiveworkshop.com/forums/submissions-414/snippet-dummy-caster-197087/
*       */ TimerUtils  /*       wc3c.net/showthread.php?t=101322
*
*************************************************************************************
*
*    Functions
*
*       function UnitGetStun takes unit u returns real
*       function UnitAddStun takes unit u, real time returns nothing
*       function UnitSetStun takes unit u, real time returns nothing
*       function UnitRemoveStun takes unit u returns nothing
*
************************************************************************************/
    globals
        private timer array t
        private boolean array r
    endglobals
    //stun expire
    private function B takes nothing returns nothing
        local integer i=GetTimerData(GetExpiredTimer())
        set r[i]=false
        call UnitRemoveAbility(GetUnitById(i),BUFFS_STUN)
    endfunction
    //unit death
    private function E takes nothing returns boolean
        local integer i=GetUnitUserData(GetTriggerUnit())
        if (r[i]) then
            set r[i]=false
            call PauseTimer(t[i])
        endif
        return false
    endfunction
    //unit index
    private function M takes nothing returns boolean
        set t[GetIndexedUnitId()]=NewTimerEx(GetIndexedUnitId())
        return false
    endfunction
    //unit deindex
    private function D takes nothing returns boolean
        call ReleaseTimer(t[GetIndexedUnitId()])
        set t[GetIndexedUnitId()]=null
        set r[GetIndexedUnitId()]=false
        return false
    endfunction
    //init
    private module I
        private static method onInit takes nothing returns nothing
            local trigger q=CreateTrigger()
            local integer i=15
            call RegisterUnitIndexEvent(Condition(function M),UnitIndexer.INDEX)
            call RegisterUnitIndexEvent(Condition(function D),UnitIndexer.DEINDEX)
            loop
                call TriggerRegisterPlayerUnitEvent(q,Player(i),EVENT_PLAYER_UNIT_DEATH,null)
                exitwhen 0==i
                set i=i-1
            endloop
            call TriggerAddCondition(q,Condition(function E))
            set q=null
        endmethod
    endmodule
    private struct N extends array
        implement I
    endstruct
    function UnitGetStun takes unit u returns real
        local integer i = GetUnitUserData(u)
        debug if (0==i) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID UNIT")
            debug return 0.
        debug endif
        if (r[i]) then
            return TimerGetRemaining(t[i])
        endif
        return 0.
    endfunction
    function UnitAddStun takes unit u, real time returns nothing
        local integer i = GetUnitUserData(u)
        debug if (0==i) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID UNIT")
            debug return
        debug endif
        if (r[i]) then
            set time=time+TimerGetRemaining(t[i])
        else
            set r[i]=true
        endif
        if (0<time) then
            call TimerStart(t[i],time,false,function B)
            call DummyCaster[ABILITIES_STUN].castTarget(Player(15),1,852231,u)
        else
            call PauseTimer(t[i])
            set r[i] = false
            call UnitRemoveAbility(GetUnitById(i),BUFFS_STUN)
        endif
    endfunction
    function UnitSetStun takes unit u, real time returns nothing
        local integer i = GetUnitUserData(u)
        debug if (time<0) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID TIME")
            debug return
        debug endif
        debug if (0==i) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID UNIT")
            debug return
        debug endif
        if (0<time) then
            set r[i]=true
            call TimerStart(t[i],time,false,function B)
            call DummyCaster[ABILITIES_STUN].castTarget(Player(15),1,852231,u)
        else
            set r[i]=false
            call PauseTimer(t[i])
            call UnitRemoveAbility(GetUnitById(i),BUFFS_STUN)
        endif
    endfunction
    function UnitRemoveStun takes unit u returns nothing
        local integer i = GetUnitUserData(u)
        debug if (0==i) then
            debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"STUN ERROR: INVALID UNIT")
            debug return
        debug endif
        call UnitRemoveAbility(GetUnitById(i),BUFFS_STUN)
        set r[i]=false
        call PauseTimer(t[i])
    endfunction
endlibrary
 
Last edited:
JASS:
    //unit index
    private function M takes nothing returns boolean
        local integer i=GetIndexedUnitId()
        set t[i]=NewTimerEx(i)
        return false
    endfunction
    //unit deindex
    private function D takes nothing returns boolean
        local integer i=GetIndexedUnitId()
        call DestroyTimer(t[i])
        set t[i]=null
        set r[i]=false
        return false
    endfunction

->

JASS:
    //unit index
    private function M takes nothing returns boolean
        set t[GetIndexedUnitId()]=NewTimerEx(GetIndexedUnitId())
        return false
    endfunction
    //unit deindex
    private function D takes nothing returns boolean
        call DestroyTimer(t[GetIndexedUnitId()])
        set t[GetIndexedUnitId()]=null
        set r[GetIndexedUnitId()]=false
        return false
    endfunction

UnitIndexer's functions (except for GetUnitId) all get inlined to variable reads/array lookups.
 
AppendThread executes the code after a 0-second timer, meaning that thread will run at the end of the current thread. Calling to a function does quite the opposite, it runs from within the current thread. In fact threads and functions have nothing to do with each other. The only way in wc3 to make a new thread is by using the "code" type or by using ExecuteFunc.
 
This is going to be going under a dramatic change. Went over a design with Laiev that is very excellent (he pointed out that the code is identical for different effects, so I came up with a new design). A new Core resource will be created/submitted and then each effect (like stun) will essentially just be an Lua script so that you can plug the constant into the core ;p.


This new design should be able to replace the Status library ^)^.
 
Top