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

UnitToggling

Level 10
Joined
Aug 19, 2008
Messages
491
A very simple module, takes care of most stacking problems of on/off natives like PauseUnit or SetUnitInvulnerable.
Comes in two versions. A third one is planned but I don't know if it's required.
Header should explain everything.




Requires UnitIndexingUtils

JASS:
//===========================================================================
//==    
//==        UnitToggling
//==       ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//==    Written by Cheezeman    
//==    
//==    This module lets you use certain natives without having to worry
//==    about the stacking issue that comes with them.
//==    For example; You have two abilities that pauses a unit over time. The
//==    unit will be unpause when the first spell's duration runs out, no matter
//==    what.
//==    What do you do?
//==    You replace PauseUnit() with PauseUnitEx()
//==    There are many natives included in this pack, some more useful than the
//==    others
//==    
//==    
//==    Natives
//==    ¯¯¯¯¯¯¯
//==    *Note* Functions with > in front of them use hashtable
//==           rather than integer arrays.
//==
//==    call PauseUnitEx( unit whichUnit, boolean flag )
//==    call ShowUnitEx( unit whichUnit, boolean flag )
//==    call SetUnitPathingEx( unit whichUnit, boolean flag )
//==    call SetUnitInvulnerableEx( unit whichUnit, boolean flag )
//==    call SetUnitExplodedEx( unit whichUnit, boolean flag )
//==    call SetUnitUseFoodEx( unit whichUnit, boolean flag )
//==    > call UnitAddAbilityEx( unit whichUnit, integer abilityId )
//==    > call UnitRemoveAbilityEx( unit whichUnit, integer abilityId )
//==    
//==    
//==    Special version
//==    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//==    If your map already use UnitUserData for other purposes than
//==    unit indexing, you can use UnitToggling - Special version.
//==    It is, in difference to this standard, completely self-sufficient,
//==    but a great deal slower.
//==    I recommend the standard, but if you have no other option you
//==    should use the special.
//==    
//==     ____________________
//==    I Version 1.3       I
//==    I Pack 1.0          I
//==    I Made by Cheezeman I
//==     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//===========================================================================
library UnitToggling initializer Init requires UnitIndexingUtils
    globals
        private hashtable Hash
        private integer array PauseUnitA
        private integer array ShowUnitA
        private integer array SetUnitInvulnerableA
        private integer array SetUnitExplodedA
        private integer array SetUnitUseFoodA
        private integer array SetUnitPathingA
    endglobals
//===========================================================================

    //! textmacro UnitToggling_Template takes NATIVE
        local integer i = $NATIVE$A[GetUnitId( u )]
        if flag then
            if i == 0 then
                call $NATIVE$( u, true )
            endif
            set $NATIVE$A[GetUnitId( u )] = i + 1
        else
            set $NATIVE$A[GetUnitId( u )] = i - 1
            if i - 1 <= 0 then
                set $NATIVE$A[GetUnitId( u )] = 0
                call $NATIVE$( u, false )
            endif
        endif
    //! endtextmacro
    
//===========================================================================
    function PauseUnitEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "PauseUnit" )
    endfunction

    function ShowUnitEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "ShowUnit" )
    endfunction

    function SetUnitInvulnerableEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "SetUnitInvulnerable" )
    endfunction

    function SetUnitExplodedEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "SetUnitExploded" )
    endfunction

    function SetUnitUseFoodEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "SetUnitUseFood" )
    endfunction

    function SetUnitPathingEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "SetUnitPathing" )
    endfunction
//===========================================================================
    function UnitAddAbilityEx takes unit u, integer abil_id returns nothing
        local integer i = LoadInteger( Hash, abil_id, GetHandleId( u ) )
        if i == 0 then
            call UnitAddAbility( u, abil_id )
        endif
        call SaveInteger( Hash, abil_id, GetHandleId( u ), i + 1 )
    endfunction
    
    function UnitRemoveAbilityEx takes unit u, integer abil_id returns nothing
        local integer i = LoadInteger( Hash, abil_id, GetHandleId( u ) )
        call SaveInteger( Hash, abil_id, GetHandleId( u ), i - 1 )
        if i - 1 <= 0 then
            call RemoveSavedInteger( Hash, abil_id, GetHandleId( u ) )
            call UnitRemoveAbility( u, abil_id )
        endif
    endfunction
//===========================================================================
    private function Init takes nothing returns nothing
        set Hash = InitHashtable()
    endfunction
endlibrary


JASS:
//===========================================================================
//==    
//==        UnitToggling - Special version
//==       ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//==    Written by Cheezeman    
//==    
//==    This module lets you use certain natives without having to worry
//==    about the stacking issue that comes with them.
//==    For example; You have two abilities that pauses a unit over time. The
//==    unit will be unpause when the first spell's duration runs out, no matter
//==    what.
//==    What do you do?
//==    You replace PauseUnit() with PauseUnitEx()
//==    There are many natives included in this pack, some more useful than the
//==    others
//==    
//==    
//==    Natives
//==    ¯¯¯¯¯¯¯
//==    call PauseUnitEx( unit whichUnit, boolean flag )
//==    call ShowUnitEx( unit whichUnit, boolean flag )
//==    call SetUnitPathingEx( unit whichUnit, boolean flag )
//==    call SetUnitInvulnerableEx( unit whichUnit, boolean flag )
//==    call SetUnitExplodedEx( unit whichUnit, boolean flag )
//==    call SetUnitUseFoodEx( unit whichUnit, boolean flag )
//==    call UnitAddAbilityEx( unit whichUnit, integer abilityId )
//==    call UnitRemoveAbilityEx( unit whichUnit, integer abilityId )
//==    
//==    
//==    Special version
//==    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//==    This version is, in difference to the standard, completely
//==    self sufficient (independent of UnitUserData), but on the
//==    other hand a great deal slower.
//==    I recommend the standard version, but if you use UnitUserData
//==    for other purposes than unit indexing you should use this
//==    special version
//==    
//==     ____________________
//==    I Version 1.3       I
//==    I Pack 1.0          I
//==    I Made by Cheezeman I
//==     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//===========================================================================
library UnitToggling initializer Init
    globals
        private hashtable Hash
        private constant integer PauseUnit_Key              = 0
        private constant integer ShowUnit_Key               = 1
        private constant integer SetUnitPathing_Key         = 2
        private constant integer SetUnitInvulnerable_Key    = 3
        private constant integer SetUnitExploded_Key        = 4
        private constant integer SetUnitUseFood_Key         = 5
        private constant integer UnitAddAbility_Key         = 6
    endglobals
//===========================================================================

    //! textmacro UnitToggling_Template takes NATIVE
        local integer i = LoadInteger( Hash, $NATIVE$_Key, GetHandleId( u ) )
        if flag then
            if i == 0 then
                call $NATIVE$( u, true )
            endif
            call SaveInteger( Hash, $NATIVE$_Key, GetHandleId( u ), i + 1 )
        else
            call SaveInteger( Hash, $NATIVE$_Key, GetHandleId( u ), i - 1 )
            if i - 1 <= 0 then
                call RemoveSavedInteger( Hash, $NATIVE$_Key, GetHandleId( u ) )
                call $NATIVE$( u, false )
            endif
        endif
    //! endtextmacro

//===========================================================================
    function PauseUnitEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "PauseUnit" )
    endfunction
//===========================================================================
    function ShowUnitEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "ShowUnit" )
    endfunction
//===========================================================================
    function SetUnitInvulnerableEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "SetUnitInvulnerable" )
    endfunction
//===========================================================================
    function SetUnitExplodedEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "SetUnitExploded" )
    endfunction
//===========================================================================
    function SetUnitUseFoodEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "SetUnitUseFood" )
    endfunction
//===========================================================================
    function SetUnitPathingEx takes unit u, boolean flag returns nothing
        //! runtextmacro UnitToggling_Template( "SetUnitPathing" )
    endfunction
//===========================================================================
    function UnitAddAbilityEx takes unit u, integer abil_id returns nothing
        local integer i = LoadInteger( Hash, abil_id, GetHandleId( u ) )
        if i == 0 then
            call UnitAddAbility( u, abil_id )
        endif
        call SaveInteger( Hash, abil_id, GetHandleId( u ), i + 1 )
    endfunction
    
    function UnitRemoveAbilityEx takes unit u, integer abil_id returns nothing
        local integer i = LoadInteger( Hash, abil_id, GetHandleId( u ) )
        call SaveInteger( Hash, abil_id, GetHandleId( u ), i - 1 )
        if i - 1 <= 0 then
            call RemoveSavedInteger( Hash, abil_id, GetHandleId( u ) )
            call UnitRemoveAbility( u, abil_id )
        endif
    endfunction
//===========================================================================
    private function Init takes nothing returns nothing
        set Hash = InitHashtable()
    endfunction
endlibrary


Suggestions of improvment are welcome.
 
Last edited:
Top