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

[snippet]UnitMoveList

Level 31
Joined
Jul 10, 2007
Messages
6,306
This needs updating >: O

Automatic updating list for moving units.

Forcefully add/remove from list with add/remove methods
Iterate through list using next
First of list is always List[0].next and last is always List[0].previous
0 is null in list

Will automatically add units as they move.
Will automatically remove units when they stop or are deindexed.

Useful for manipulating unit movement.

JASS:
library UnitMoveList uses /*
    */IsUnitMoving /*[url]http://www.hiveworkshop.com/forums/jass-functions-413/isunitmoving-178341/[/url]
    */UnitIndexer //http://www.hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
    
    //optional unit filter
    //private static method movementFilter takes unit u returns boolean
    
    //determines whether or not unit of type id runs
    //boolean runs
    
    //readonly boolean isRunning
    
    module UnitMoveList
        private static integer array unitListNext
        private static integer array unitListPrevious
        private static boolean array inList
        
        private boolean runsx
        
        public method operator isRunning takes nothing returns boolean
            return inList[this]
        endmethod
        
        public method operator runs takes nothing returns boolean
            return runsx
        endmethod
        
        public method operator runs= takes boolean b returns nothing
            if (b != runsx) then
                set runsx = b
                
                if (b) then
                    static if thistype.movementFilter.exists then
                        if (IsUnitMoving(GetUnitById(this)) and thistype.movementFilter(GetUnitById(this))) then
                            set unitListNext[unitListPrevious[0]] = this
                            set unitListNext[this] = 0
                            set unitListPrevious[this] = unitListPrevious[0]
                            set unitListPrevious[0] = this
                            set inList[this] = true
                        endif
                    else
                        if (IsUnitMoving(GetUnitById(this))) then
                            set unitListNext[unitListPrevious[0]] = this
                            set unitListNext[this] = 0
                            set unitListPrevious[this] = unitListPrevious[0]
                            set unitListPrevious[0] = this
                            set inList[this] = true
                        endif
                    endif
                elseif (inList[this]) then
                    set unitListNext[unitListPrevious[this]] = unitListNext[this]
                    set unitListPrevious[unitListNext[this]] = unitListPrevious[this]
                    set inList[this] = false
                endif
            endif
        endmethod
        
        public method operator next takes nothing returns thistype
            return unitListNext[this]
        endmethod
        
        private static method RemoveFromList takes nothing returns boolean
            local integer id = GetUnitUserData(GetMovingUnit())
            if (inList[id]) then
                set unitListNext[unitListPrevious[id]] = unitListNext[id]
                set unitListPrevious[unitListNext[id]] = unitListPrevious[id]
                set inList[id] = false
            endif
            return false
        endmethod
        
        private static method AddToList takes nothing returns boolean
            local thistype id = GetUnitUserData(GetMovingUnit())
            
            if (thistype(id).runs) then
                static if thistype.movementFilter.exists then
                    if (not inList[id] and thistype.movementFilter(GetUnitById(id))) then
                        set unitListNext[unitListPrevious[0]] = id
                        set unitListNext[id] = 0
                        set unitListPrevious[id] = unitListPrevious[0]
                        set unitListPrevious[0] = id
                        set inList[id] = true
                    endif
                else
                    if (not inList[id]) then
                        set unitListNext[unitListPrevious[0]] = id
                        set unitListNext[id] = 0
                        set unitListPrevious[id] = unitListPrevious[0]
                        set unitListPrevious[0] = id
                        set inList[id] = true
                    endif
                endif
            endif
            return false
        endmethod
        
        private static method RemoveFromListDeindex takes nothing returns boolean
            if (inList[GetIndexedUnitId()]) then
                set unitListNext[unitListPrevious[GetIndexedUnitId()]] = unitListNext[GetIndexedUnitId()]
                set unitListPrevious[unitListNext[GetIndexedUnitId()]] = unitListPrevious[GetIndexedUnitId()]
                set inList[GetIndexedUnitId()] = false
            endif
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            call OnUnitDeindex(Condition(function thistype.RemoveFromListDeindex))
            call OnUnitMove(Condition(function thistype.AddToList))
            call OnUnitStop(Condition(function thistype.RemoveFromList))
        endmethod
    endmodule
endlibrary

Demo
JASS:
struct tester extends array
    private static method movementFilter takes unit u returns boolean
        return not IsUnitType(u, UNIT_TYPE_FLYING)
    endmethod

    implement UnitMoveList

    private static method iterate takes nothing returns nothing
        local thistype this = thistype[0].next
        loop
            exitwhen this == 0
            set this = next
        endloop
    endmethod

    private static method runAll takes nothing returns boolean
        set thistype(GetIndexedUnitId()).runs = true
        return false
    endmethod

    private static method onInit takes nothing returns nothing
        call OnUnitIndex(Condition(function thistype.runAll))
        call TimerStart(CreateTimer(), .0325, true, function thistype.iterate)
    endmethod
endstruct
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
SlopeSpeed, CliffBound, etc... whenever you filtered list of moving units : \.

edit
The code in here should be copied rather than the module used. The reason for this is the running thing... sometimes you might want things to autorun and sometimes you might not want them to autorun. It's better to cnp than to create an indexing event = P.

Really, some other things in the code can be tinkered with to suit the occasion. Sometimes you don't even need the running stuff. This is why the module was not used in SlopeSpeed, CliffBound and etc while the code itself was used ; ).
 
Last edited:
Top