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

[vJASS] PauseUnitEx

With the release of the newer patches came the introduction of a peculiar native, BlzPauseUnitEx.
With a bit of experimenting, this native allows one to effectively stop a unit in its' tracks without
the loss of shift-order queues, pausing of buffs, etc.

However, with it only being the available function to us, this snippet was made to extend its' functionality. Presenting:

JASS:
library PauseUnitEx /*
    --------------
    */ requires /*
    --------------
        --------------------
        */ optional Table /*
        --------------------
            Link: "hiveworkshop.com/forums/showthread.php?t=188084"
        --------------------
        |   PauseUnitEx    |
        |    - MyPad       |
        --------------------
            A simple snippet that grants additional functionality
            to BlzPauseUnitEx that mimics PauseUnit
        ---------
        | API   |
        ---------
            function PauseUnitEx(unit whichUnit, boolean flag)
                - Internally calls BlzPauseUnitEx
            function IsUnitPausedEx(unit whichUnit) -> boolean
                - Checks if the unit is paused.
                - This does not return accurate values when
                  BlzPauseUnitEx is called directly.
            function GetUnitPauseExCounter(unit whichUnit) -> integer
                - Returns the pause counter of the unit.
            function SetUnitPauseExCounter(unit whichUnit, integer new)
                - Sets the pause counter of the unit to the
                  new value. Internally calls BlzPauseUnitEx
                  when appropriate.
                - Time Complexity: O(n)
    */
private module PauseM
    static if LIBRARY_Table then
        static Table map        = 0
        private static method onInit takes nothing returns nothing
            set thistype.map    = Table.create()
        endmethod
    else
        static hashtable map    = InitHashtable()
    endif
    static method getPauseCounter takes unit whichUnit returns integer
        local integer counter   = 0
        local integer unitId    = GetHandleId(whichUnit)
        static if LIBRARY_Table then
            set counter     = map[unitId]
        else
            set counter     = LoadInteger(map, 0, unitId)
        endif
        return counter
    endmethod
    static method pauseUnit takes unit whichUnit, boolean flag returns nothing
        local integer counter   = thistype.getPauseCounter(whichUnit)
        local integer unitId    = GetHandleId(whichUnit)
        local integer incr      = IntegerTertiaryOp(flag, 1, -1)
       
        set counter = counter + incr
        static if LIBRARY_Table then
            set map[unitId] = counter
        else
            call SaveInteger(map, 0, unitId, counter)
        endif
        call BlzPauseUnitEx(whichUnit, flag)
    endmethod
    static method isPaused takes unit whichUnit returns boolean
        local integer counter   = thistype.getPauseCounter(whichUnit)
        return counter > 0
    endmethod
    static method setPauseCounter takes unit whichUnit, integer new returns nothing
        local integer counter   = thistype.getPauseCounter(whichUnit)
        local integer sign      = 0
        local integer unitId    = GetHandleId(whichUnit)
        local boolean flag      = false
        if new < counter then
            set sign    = -1
            set flag    = false
        elseif new > counter then
            set sign    = 1
            set flag    = true
        endif
        loop
            exitwhen counter == new
            set counter = counter + sign
            call BlzPauseUnitEx(whichUnit, flag)
        endloop
        static if LIBRARY_Table then
            set map[unitId] = counter
        else
            call SaveInteger(map, 0, unitId, counter)
        endif
    endmethod
endmodule
private struct Pause extends array
    implement PauseM
endstruct
function PauseUnitEx takes unit whichUnit, boolean flag returns nothing
    call Pause.pauseUnit(whichUnit, flag)
endfunction
function SetUnitPauseExCounter takes unit whichUnit, integer new returns nothing
    call Pause.setPauseCounter(whichUnit, new)
endfunction
function IsUnitPausedEx takes unit whichUnit returns boolean
    return Pause.isPaused(whichUnit)
endfunction
function GetUnitPauseExCounter takes unit whichUnit returns integer
    return Pause.getPauseCounter(whichUnit)
endfunction
endlibrary
 
Level 20
Joined
Aug 13, 2013
Messages
1,696
Finally, a thing to deprecate the infinite-channel, stop-every-order tricks.
One should be aware of the existence of this native. It's very convenient.

With the release of the newer patches came the introduction of a peculiar native, BlzPauseUnitEx.
You can state which specific patch it supports the extended native.
I hope it's not broken in the last legacy patch (1.31.1), I'll test it...

It's nice to have you testing and verifying the workings of these newly introduced natives in public. ^^

EDIT:

I'm also wondering what BlzSetUnitFacingEx does than SetUnitFacing.
It's only introduced in 1.32 which I don't have yet. I'm hoping that it simulates an instant-facing?
 
Last edited:
IIRC, it was introduced around 1.31+, same time as frame natives. I'll test if it works in 1.31, as it worked for 1.32+.

EDIT:
BlzSetUnitFacingEx instantly sets a unit's facing angle. (Basically what SetUnitFacing is supposed to do)

EDIT (2):
Removed (probably) from the first edit. (Map can only be opened on 1.32.7)
 

Attachments

  • SetUnitFacingTest.w3m
    17.4 KB · Views: 43
Last edited:
Level 20
Joined
Aug 13, 2013
Messages
1,696
IIRC, it was introduced around 1.31+, same time as frame natives. I'll test if it works in 1.31, as it worked for 1.32+.
I can clarify the native works properly. (just tested it at the moment)

However, I've noticed BlzPauseUnitEx has a built-in counter already unlike with PauseUnit...

Which just means the usefulness of this resource just relies on get/set of an external counter.

But it doesn't mean the minority of its usage makes this resource not useful, in fact can you clarify if IsUnitPaused native does detect BlzPauseUnitEx on your end? It doesn't return true if a unit is paused by the native from my tests but returns correctly with PauseUnit, this problem can make this resource very useful as it have designed IsUnitPausedEx already. In that case, users should utilize to this resource instead and not calling BlzPauseUnitEx directly for detecting purposes.

The mechanic of the native itself is very similar to stun, one (or you) could just use the native for a new stun system.
 
I can clarify the native works properly. (just tested it at the moment)

However, I've noticed BlzPauseUnitEx has a built-in counter already unlike with PauseUnit...

Which just means the usefulness of this resource just relies on get/set of an external counter.

But it doesn't mean the minority of its usage makes this resource not useful, in fact can you clarify if IsUnitPaused native does detect BlzPauseUnitEx on your end? It doesn't return true if a unit is paused by the native from my tests but returns correctly with PauseUnit, this problem can make this resource very useful as it have designed IsUnitPausedEx already. In that case, users should utilize to this resource instead and not calling BlzPauseUnitEx directly for detecting purposes.

The mechanic of the native itself is very similar to stun, one (or you) could just use the native for a new stun system.

Going by memory, I suppose IsUnitPaused doesn't play well with BlzPauseUnitEx. I'll verify it once I get back to my computer.

EDIT:

Yep, pausing units with BlzPauseUnitEx doesn't affect IsUnitPaused at all.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
This is a clean resource, and I'm amazed that it keeps its own internal counter in place. I'll have to look into this for my next Retro update.

This would definitely work better in Lua, though, with native hooks. I don't think that it is very useful in a strictly-JASS environment when one will have to rely on your wrappers to repair natives like IsUnitPaused.
 
Top