wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Resources > - Submit a resource -
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 04-18-2014, 08:51 AM   #1
Nestharus
User
 
Join Date: Jul 2007
Posts: 218

Nestharus has little to show at this moment (6)

Default [script] Unit Indexer

Map Includes
  • Required Resources
  • Installation Script + Instructions
  • Installation Objects + Instructions
  • Resource
  • Test Cases
  • Tutorials/Labs

Required resources can also be found on github

Best thing to do is to just go through the tutorials/labs.

This can't be compared to any previous Unit Indexer. This was made possible by Trigger.

Unit Indexer Main
Collapse JASS:
library UnitIndexer /* v5.1.0.1
************************************************************************************
*
*   */ uses /*
*
*       */ WorldBounds          /*
*       */ Init                 /*
*       */ AllocQ               /*
*       */ ErrorMessage         /*
*       */ StaticUniqueList     /*
*       */ UnitIndexerSettings  /*
*       */ Trigger              /*
*
********************************************************************************
*
*   struct UnitIndexer extends array
*
*       Fields
*       -------------------------
*
*           static boolean enabled
*               -   is UnitIndexer onUnitIndex enabled?
*
*           readonly static Trigger GlobalEvent.ON_INDEX
*               -   this is a global event that runs whenever any unit is indexed
*
*               Examples:   UnitIndexer.GlobalEvent.ON_INDEX.reference(yourTrigger)
*                           UnitIndexer.GlobalEvent.ON_INDEX.register(yourCode)
*
*               Examples:   unitIndex.indexer.Event.ON_DEINDEX.reference(yourTrigger)
*                           unitIndex.indexer.Event.ON_DEINDEX.register(yourCode)
*
*           readonly static Trigger GlobalEvent.ON_DEINDEX
*               -   this is ON_DEINDEX, but global
*               -   this runs after unit specific deindex events
*
*               Examples:   UnitIndexer.GlobalEvent.ON_DEINDEX.reference(yourTrigger)
*                           UnitIndexer.GlobalEvent.ON_DEINDEX.register(yourCode)
*
*           readonly static UnitIndex eventIndex
*               -   when a unit is indexed or deindexed, this value stores
*                   the index of that unit
*
*           readonly static unit eventUnit
*               -   when a unit is indexed or deindexed, this value stores
*                   the unit
*
************************************************************************************
*
*   struct UnitIndex extends array
*
*       Fields
*       -------------------------
*
*           readonly unit unit
*               -   converts a unit index into a unit
*
*           readonly UnitIndexer indexer
*               -   the indexer in charge of handling the unit
*                   useful for deindex event, which is unit specific
*
*       Operators
*       -------------------------
*
*           static method operator [] takes unit whichUnit returns UnitIndex
*               -   converts a unit into a UnitIndex
*
*       Methods
*       -------------------------
*
*           static method exists takes unit whichUnit returns boolean
*               -   determines whether the unit is indexed or not
*
*           static method isDeindexing takes unit whichUnit returns boolean
*               -   determines whether the unit is in the process of being deindexed or not
*
************************************************************************************
*
*   module UnitIndex
*
*       If you would like to create modules that work off of the UnitIndex module, implement
*       UnitIndex at the top of your module
*       
*       Fields
*       -------------------------
*
*           static constant boolean UNIT_INDEX = true
*               -   this is used to make sure that only either UnitIndex or UnitIndexEx
*                   implemented.
*
*           static boolean enabled
*               -   is this UnitIndex struct enabled?
*               -   this can only be disabed if onUnitIndex exists
*
*           readonly unit unit
*               -   converts a unit index into a unit
*
*           readonly boolean isUnitIndexed
*               -   is the unit index indexed for the struct?
*
*           readonly UnitIndexer unitIndexer
*               -   the indexer in charge of handling the unit
*                   useful for deindex event, which is unit specific
*
*       Operators
*       -------------------------
*
*           static method operator [] takes unit whichUnit returns thistype
*               -   converts a unit into thistype
*
*       Methods
*       -------------------------
*
*           static method exists takes unit whichUnit returns boolean
*               -   determines whether the unit is indexed or not for the struct
*
*           static method isDeindexing takes unit whichUnit returns boolean
*               -   determines whether the unit is in the process of being deindexed or not
*
*       Interface
*       -------------------------
*
*           interface private method onUnitIndex takes nothing returns boolean
*               -   if return true, index the unit for this struct
*
*           interface private method onUnitDeindex takes nothing returns nothing
*               -   only runs for units indexed for this struct
*               -   if not onUnitIndex method is declared, it will run for all units
*
************************************************************************************
*
*   module UnitIndexEx
*
*       If you would like to create modules that work off of the UnitIndex module, implement
*       UnitIndex at the top of your module
*       
*       Fields
*       -------------------------
*
*           static constant boolean UNIT_INDEX_EX = true
*               -   this is used for modules that rely on local events
*                   it allows these modules to differentiate between UnitIndex
*                   and UnitIndexEx
*
*           static boolean enabled
*               -   is this UnitIndex struct enabled?
*               -   this can only be disabed if onUnitIndex exists
*
*           readonly unit unit
*               -   converts a unit index into a unit
*
*           readonly boolean isUnitIndexed
*               -   is the unit index indexed for the struct?
*
*           readonly UnitIndexer unitIndexer
*               -   the indexer in charge of handling the unit
*                   useful for deindex event, which is unit specific
*
*           readonly static Trigger ON_INDEX
*               -   this is a local event that runs whenever any unit is indexed for the struct
*               -   this is primarily used for other resources that work off of your struct
*
*               Examples:   Struct.ON_INDEX.reference(yourTrigger)
*                           Struct.ON_INDEX.register(yourCode)
*
*           readonly Trigger Event.ON_DEINDEX
*           readonly static Trigger Event.ON_DEINDEX
*               -   this is a unit specific event that runs when your local unit is deindexed
*               -   this is static if onUnitIndex does not exist
*
*               Examples:   struct.ON_DEINDEX.reference(yourTrigger)
*                           struct.ON_DEINDEX.register(yourCode)
*
*       Operators
*       -------------------------
*
*           static method operator [] takes unit whichUnit returns thistype
*               -   converts a unit into thistype
*
*       Methods
*       -------------------------
*
*           static method exists takes unit whichUnit returns boolean
*               -   determines whether the unit is indexed or not for the struct
*
*           static method isDeindexing takes unit whichUnit returns boolean
*               -   determines whether the unit is in the process of being deindexed or not
*
*       Interface
*       -------------------------
*
*           interface private method onUnitIndex takes nothing returns boolean
*               -   if return true, index the unit for this struct
*
*           interface private method onUnitDeindex takes nothing returns nothing
*               -   only runs for units indexed for this struct
*               -   if not onUnitIndex method is declared, it will run for all units
*
************************************************************************************
*
*   //! textmacro CREATE_LOCAL_UNIT_INDEX
*
*       A macro was chosen because multiple modules utilizing this code may be
*       implemented into one struct. If this was a module, then all but one
*       of those modules would break.
*
*       Interface
*       -------------------------
*
*           interface private method onLocalUnitIndex takes nothing returns nothing
*               -   runs whenever a unit is indexed for this struct
*
*           interface private method onLocalUnitDeindex takes nothing returns nothing
*               -   runs whenever a unit is deindexed for this struct
*
*           interface private static method localInit takes nothing returns nothing
*               -   the macro requires the usage of onInit. Declare this method if you
*                   would like onInit.
*
************************************************************************************/
    globals
        private UnitIndex p_eventIndex = 0
    endglobals

    //! runtextmacro UNIT_INDEXER_UNIT_INDEX()
    //! runtextmacro UNIT_INDEXER_PREGAME_EVENT()
    //! runtextmacro UNIT_INDEXER_UNIT_INDEXER()
    
    module UnitIndex
        static if not thistype.UNIT_INDEX_EX then
            static constant boolean UNIT_INDEX = true
            
            /*
            *   [] is included because the struct automatically overrides it
            *
            *   eventIndex is included to return thistype instead of UnitIndex
            */
            static method operator [] takes unit whichUnit returns thistype
                return UnitIndex[whichUnit]
            endmethod
            method operator unitIndexer takes nothing returns UnitIndexer
                return this
            endmethod
            method operator unit takes nothing returns unit
                return UnitIndex(this).unit
            endmethod
            
            static method isDeindexing takes unit whichUnit returns boolean
                return UnitIndex.isDeindexing(whichUnit)
            endmethod
            
            /*
            *   the method is done in the second case because when there is no
            *   onUnitIndex method, indexed depends on whether the actual
            *   instance is allocated or not
            */
            static if thistype.onUnitIndex.exists then
                readonly boolean isUnitIndexed
            else
                method operator isUnitIndexed takes nothing returns boolean
                    return p_UnitIndex(this).isAllocated
                endmethod
            endif
            
            static if thistype.onUnitIndex.exists then
                static method exists takes unit whichUnit returns boolean
                    return UnitIndex.exists(whichUnit) and thistype(GetUnitUserData(whichUnit)).isUnitIndexed
                endmethod
            else
                static method exists takes unit whichUnit returns boolean
                    return UnitIndex.exists(whichUnit)
                endmethod
            endif
            
            /*
            *   this is used to run local events
            */
            static if thistype.onUnitIndex.exists then
                /*
                *   this is where UnitIndex is located
                */
                private static TriggerCondition entryPoint
                
                /*
                *   this stores private onUnitIndex method
                */
                private static boolexpr onIndexExpression
                
                /*
                *   enable works with code inside of entryPoint here
                */
                private static boolean p_enabled = true
                static method operator enabled takes nothing returns boolean
                    return p_enabled
                endmethod
                static method operator enabled= takes boolean enable returns nothing
                    set p_enabled = enable
                    
                    if (enable) then
                        call entryPoint.replace(onIndexExpression)
                    else
                        call entryPoint.replace(null)
                    endif
                endmethod
            else
                /*
                *   if onUnitIndex does not exist, the struct can't be disabled
                */
                static method operator enabled takes nothing returns boolean
                    return true
                endmethod
                static method operator enabled= takes boolean enable returns nothing
                    set enable = true
                endmethod
            endif
            
            /*
            *   onUnitDeindex
            *
            *   This must be implemented if onUnitIndex exists to clear isUnitIndexed
            */
            static if thistype.onUnitDeindex.exists then
                static if thistype.onUnitIndex.exists then
                    private static boolexpr onDeindexExpression
                endif
                
                private static method onDeindexEvent takes nothing returns boolean
                    call thistype(UnitIndexer.eventIndex).onUnitDeindex()
                    
                    static if thistype.onUnitIndex.exists then
                        set thistype(UnitIndexer.eventIndex).isUnitIndexed = false
                    endif
                    
                    return false
                endmethod
            elseif thistype.onUnitIndex.exists then
                static if thistype.onUnitIndex.exists then
                    private static boolexpr onDeindexExpression
                endif
                
                private static method onDeindexEvent takes nothing returns boolean
                    set thistype(UnitIndexer.eventIndex).isUnitIndexed = false
                    
                    return false
                endmethod
            endif
            
            /*
            *   onUnitIndex
            */
            static if thistype.onUnitIndex.exists then
                private static method onIndexEvent takes nothing returns boolean
                    if (thistype(UnitIndexer.eventIndex).onUnitIndex()) then
                        set thistype(UnitIndexer.eventIndex).isUnitIndexed = true
                        
                        /*
                        *   this is always registered to clear isUnitIndexed
                        */
                        call UnitIndexer(UnitIndexer.eventIndex).Event.ON_DEINDEX.register(onDeindexExpression)
                    endif
                    
                    return false
                endmethod
            endif
            
            static if thistype.onUnitIndex.exists then
                private static method onInit takes nothing returns nothing
                    set onIndexExpression = Condition(function thistype.onIndexEvent)
                    set onDeindexExpression = Condition(function thistype.onDeindexEvent)
                    
                    set entryPoint = UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onIndexEvent))
                endmethod
            elseif thistype.onUnitDeindex.exists then
                private static method onInit takes nothing returns nothing
                    call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function thistype.onDeindexEvent))
                endmethod
            endif
        endif
    endmodule
    
    private struct UnitIndexList extends array
        //! runtextmacro CREATE_TABLE_FIELD("public", "integer", "unitIndex2Node", "thistype")
        //! runtextmacro CREATE_TABLE_FIELD("public", "integer", "node2UnitIndex", "thistype")
        
        method add takes thistype index returns nothing
            local thistype node = enqueue()
            
            set node.node2UnitIndex = index
            set index.unitIndex2Node = node
        endmethod
        
        method delete takes nothing returns nothing
            call unitIndex2Node.remove()
        endmethod
        
        private static method init takes nothing returns nothing
            //! runtextmacro INITIALIZE_TABLE_FIELD("unitIndex2Node")
            //! runtextmacro INITIALIZE_TABLE_FIELD("node2UnitIndex")
        endmethod
        
        implement NxListT
        implement Init
    endstruct
    private struct UnitIndexModuleTrigger extends array
        method reference takes Trigger whichTrigger returns TriggerReference
            local TriggerReference triggerReference = Trigger(this).reference(whichTrigger)
            
            local UnitIndexList node = UnitIndexList(this).first
            local integer prevIndexedUnitId = p_eventIndex
            
            loop
                exitwhen node == UnitIndexList.sentinel or not whichTrigger.enabled
                
                set p_eventIndex = node.node2UnitIndex
                call whichTrigger.fire()
                    
                set node = node.next
            endloop
            
            set p_eventIndex = prevIndexedUnitId
            
            return triggerReference
        endmethod
        
        method register takes boolexpr whichExpression returns TriggerCondition
            local TriggerCondition triggerCondition = Trigger(this).register(whichExpression)
            
            local trigger triggerContainer = CreateTrigger()
            
            local UnitIndexList node = UnitIndexList(this).first
            local integer prevIndexedUnitId = p_eventIndex
            
            call TriggerAddCondition(triggerContainer, whichExpression)
            
            loop
                exitwhen node == UnitIndexList.sentinel
                
                set p_eventIndex = node.node2UnitIndex
                call TriggerEvaluate(triggerContainer)
                    
                set node = node.next
            endloop
            
            call TriggerClearConditions(triggerContainer)
            call DestroyTrigger(triggerContainer)
            set triggerContainer = null
            
            set p_eventIndex = prevIndexedUnitId
            
            return triggerCondition
        endmethod
    endstruct
    module UnitIndexEx
        static if thistype.UNIT_INDEX then
            private static method error takes nothing returns nothing
                A module requires UnitIndexEx to operate correctly.
                This struct is currently implementing UnitIndex.
            endmethod
        else
            static constant boolean UNIT_INDEX_EX = true
            
            private static UnitIndex delegate unitIndex = 0
        
            /*
            *   [] is included because the struct automatically overrides it
            *
            *   eventIndex is included to return thistype instead of UnitIndex
            */
            static method operator [] takes unit whichUnit returns thistype
                return UnitIndex[whichUnit]
            endmethod
            method operator unit takes nothing returns unit
                return UnitIndex(this).unit
            endmethod
            method operator unitIndexer takes nothing returns UnitIndexer
                return this
            endmethod
            
            static method isDeindexing takes unit whichUnit returns boolean
                return UnitIndex.isDeindexing(whichUnit)
            endmethod
            
            /*
            *   the method is done in the second case because when there is no
            *   onUnitIndex method, indexed depends on whether the actual
            *   instance is allocated or not
            */
            static if thistype.onUnitIndex.exists then
                readonly boolean isUnitIndexed
            else
                method operator isUnitIndexed takes nothing returns boolean
                    return p_UnitIndex(this).isAllocated
                endmethod
            endif
            
            static if thistype.onUnitIndex.exists then
                static method exists takes unit whichUnit returns boolean
                    return UnitIndex.exists(whichUnit) and thistype(GetUnitUserData(whichUnit)).isUnitIndexed
                endmethod
            else
                static method exists takes unit whichUnit returns boolean
                    return UnitIndex.exists(whichUnit)
                endmethod
            endif
        
            /*
            *   this is used to run local events
            */
            static if thistype.onUnitIndex.exists then
                readonly static UnitIndexModuleTrigger ON_INDEX
            else
                readonly static WrappedTrigger ON_INDEX
            endif
            
            static if thistype.onUnitIndex.exists then
                /*
                *   this is where UnitIndex is located
                */
                private static TriggerCondition entryPoint
                
                /*
                *   this stores private onUnitIndex method
                */
                private static boolexpr onIndexExpression
                
                /*
                *   enable works with code inside of entryPoint here
                */
                private static boolean p_enabled = true
                static method operator enabled takes nothing returns boolean
                    return p_enabled
                endmethod
                static method operator enabled= takes boolean enable returns nothing
                    set p_enabled = enable
                    
                    if (enable) then
                        call entryPoint.replace(onIndexExpression)
                    else
                        call entryPoint.replace(null)
                    endif
                endmethod
            else
                /*
                *   if onUnitIndex does not exist, the struct can't be disabled
                */
                static method operator enabled takes nothing returns boolean
                    return true
                endmethod
                static method operator enabled= takes boolean enable returns nothing
                    set enable = true
                endmethod
            endif
            
            /*
            *   this is here so that the module runs after code that relies on the module
            */
            static if thistype.onUnitIndex.exists then
                readonly Trigger ON_DEINDEX
            else
                readonly static Trigger ON_DEINDEX
            endif
            
            /*
            *   onUnitDeindex
            */
            static if thistype.onUnitDeindex.exists then
                static if thistype.onUnitIndex.exists then
                    private static boolexpr onDeindexExpression
                endif
                
                private static method onDeindexEvent takes nothing returns boolean
                    call thistype(UnitIndexer.eventIndex).onUnitDeindex()
                    
                    static if thistype.onUnitIndex.exists then
                        set thistype(UnitIndexer.eventIndex).isUnitIndexed = false
                        
                        call thistype(UnitIndexer.eventIndex).ON_DEINDEX.destroy()
                        
                        if (not PreGameEvent.isGameLoaded) then
                            call UnitIndexList(UnitIndexer.eventIndex).delete()
                        endif
                    endif
                    
                    return false
                endmethod
            elseif thistype.onUnitIndex.exists then
                private static boolexpr onDeindexExpression
                
                private static method onDeindexEvent takes nothing returns boolean
                    set thistype(UnitIndexer.eventIndex).isUnitIndexed = false
                    
                    call thistype(UnitIndexer.eventIndex).ON_DEINDEX.destroy()
                    
                    if (not PreGameEvent.isGameLoaded) then
                        call UnitIndexList(UnitIndexer.eventIndex).delete()
                    endif
                    
                    return false
                endmethod
            endif
            
            /*
            *   onUnitIndex
            */
            static if thistype.onUnitIndex.exists then
                private static method onIndexEvent takes nothing returns boolean
                    if (thistype(UnitIndexer.eventIndex).onUnitIndex()) then
                        set thistype(UnitIndexer.eventIndex).isUnitIndexed = true
                        
                        set thistype(UnitIndexer.eventIndex).ON_DEINDEX = Trigger.create()
                        call UnitIndexer(UnitIndexer.eventIndex).Event.ON_DEINDEX.reference(thistype(UnitIndexer.eventIndex).ON_DEINDEX)
                        
                        call UnitIndexer(UnitIndexer.eventIndex).Event.ON_DEINDEX.register(onDeindexExpression)
                        
                        if (not PreGameEvent.isGameLoaded) then
                            call UnitIndexList(ON_INDEX).add(UnitIndexer.eventIndex)
                        endif
                        
                        call Trigger(thistype.ON_INDEX).fire()
                    endif
                    
                    return false
                endmethod
            endif
            
            private static method destroyPregameUnitList takes nothing returns nothing
                call DestroyTimer(GetExpiredTimer())
                
                call UnitIndexList(ON_INDEX).destroy()
            endmethod
            
            private static method onInit takes nothing returns nothing
                set ON_INDEX = Trigger.create()
                
                static if thistype.onUnitIndex.exists then
                    set onIndexExpression = Condition(function thistype.onIndexEvent)
                    set onDeindexExpression = Condition(function thistype.onDeindexEvent)
                    
                    call UnitIndexList(ON_INDEX).clear()
                    
                    call TimerStart(CreateTimer(), 0, false, function thistype.destroyPregameUnitList)
                    
                    set entryPoint = UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onIndexEvent))
                else
                    set ON_DEINDEX = Trigger.create()
                    call UnitIndexer.GlobalEvent.ON_DEINDEX.reference(ON_DEINDEX)
                
                    static if thistype.onUnitDeindex.exists then
                        call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function thistype.onDeindexEvent))
                    endif
                    
                    call UnitIndexer.GlobalEvent.ON_INDEX.reference(ON_INDEX)
                endif
            endmethod
        endif
    endmodule
    
    //! textmacro CREATE_LOCAL_UNIT_INDEX
        /*
        *   There are three cases
        *
        *       Case 1: UnitIndex is implemented
        *       Case 2: UnitIndexEx is implemented
        *       Case 3: Nothing is implemented, go to Case 2
        */
        static if thistype.UNIT_INDEX then
            /*
            *   Here, UnitIndex is implemented
            */
            
            /*
            *   There are two cases
            *
            *       onUnitEvent exists, which means that events are conditionally local
            *       onUnitEven does not exist, meaning all events are global
            */
            static if thistype.onUnitIndex.exists then
                /*
                *   Here, events are conditionally local
                */
                
                static if thistype.onLocalUnitDeindex.exists then
                    private static boolexpr onLocalUnitDeindexEventExpr
                endif
            
                static if thistype.onLocalUnitIndex.exists then
                    /*
                    *   The user has a local unit index event
                    */
                    private static method onLocalUnitIndexEvent takes nothing returns boolean
                        /*
                        *   Here, the event is only run if the unit happened to be indexed
                        */
                        if (thistype(UnitIndexer.eventIndex).isUnitIndexed) then
                            static if thistype.onLocalUnitDeindex.exists then
                                call UnitIndexer.eventIndex.indexer.Event.ON_DEINDEX.register(onLocalUnitDeindexEventExpr)
                            endif
                            
                            call thistype(UnitIndexer.eventIndex).onLocalUnitIndex()
                        endif
                        
                        return false
                    endmethod
                elseif thistype.onLocalUnitDeindex.exists then
                    /*
                    *   The user did not declare a local unit index event
                    *
                    *   onLocalUnitIndexEvent is still required because the deindex events are local
                    */
                    private static method onLocalUnitIndexEvent takes nothing returns boolean
                        if (thistype(UnitIndexer.eventIndex).isUnitIndexed) then
                            call UnitIndexer.eventIndex.indexer.Event.ON_DEINDEX.register(onLocalUnitDeindexEventExpr)
                        endif
                        
                        return false
                    endmethod
                endif
                
                static if thistype.onLocalUnitDeindex.exists then
                    private static method onLocalUnitDeindexEvent takes nothing returns boolean
                        call thistype(UnitIndexer.eventIndex).onLocalUnitDeindex()
                        return false
                    endmethod
                endif
                
                /*
                *   onLocalUnitDeindexEvent is not registered globally here because these are local
                *   events. It must be created inside of onLocalUnitIndexEvent whether or not
                *   onLocalUnitIndex exists.
                */
                static if thistype.onLocalUnitIndex.exists then
                    private static method onInit takes nothing returns nothing
                        static if thistype.onLocalUnitDeindex.exists then
                            set onLocalUnitDeindexEventExpr = Condition(function thistype.onLocalUnitDeindexEvent)
                        endif
                        
                        call UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
                        
                        static if thistype.localInit.exists then
                            call localInit()
                        endif
                    endmethod
                elseif thistype.onLocalUnitDeindex.exists then
                    private static method onInit takes nothing returns nothing
                        set onLocalUnitDeindexEventExpr = Condition(function thistype.onLocalUnitDeindexEvent)
                            
                        call UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
                        
                        static if thistype.localInit.exists then
                            call localInit()
                        endif
                    endmethod
                endif
            else
                /*
                *   Here, all events are global
                */
                static if thistype.onLocalUnitIndex.exists then
                    private static method onLocalUnitIndexEvent takes nothing returns boolean
                        call thistype(UnitIndexer.eventIndex).onLocalUnitIndex()
                        return false
                    endmethod
                endif
                
                static if thistype.onLocalUnitDeindex.exists then
                    private static method onLocalUnitDeindexEvent takes nothing returns boolean
                        call thistype(UnitIndexer.eventIndex).onLocalUnitDeindex()
                        return false
                    endmethod
                endif
                
                static if thistype.onLocalUnitIndex.exists then
                    private static method onInit takes nothing returns nothing
                        static if thistype.onLocalUnitDeindex.exists then
                            call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function thistype.onLocalUnitDeindexEvent))
                        endif
                        
                        call UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
                        
                        static if thistype.localInit.exists then
                            call localInit()
                        endif
                    endmethod
                elseif thistype.onLocalUnitDeindex.exists then
                    private static method onInit takes nothing returns nothing
                        call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function thistype.onLocalUnitDeindexEvent))
                        
                        static if thistype.localInit.exists then
                            call localInit()
                        endif
                    endmethod
                endif
            endif
        else
            /*
            *   Here, UnitIndexEx is either implemented or nothing is implemented
            *
            *   Implement UnitIndexEx and work with its local events
            */
            implement UnitIndexEx
            
            static if thistype.onUnitIndex.exists then
                /*
                *   local events
                */
                static if thistype.onLocalUnitDeindex.exists then
                    private static boolexpr onLocalUnitDeindexEventExpr
                endif
                
                /*
                *   if onUnitIndex exists, then onLocalUnitDeindex is local
                *
                *   this means that if onLocalUnitDeindex exists, the onLocalUnitIndexEvent must be
                *   made so that it can register onLocalUnitDeindex locally
                */
                static if thistype.onLocalUnitIndex.exists then
                    private static method onLocalUnitIndexEvent takes nothing returns boolean
                        static if thistype.onLocalUnitDeindex.exists then
                            call thistype(UnitIndexer.eventIndex).ON_DEINDEX.register(onLocalUnitDeindexEventExpr)
                        endif
                        
                        call thistype(UnitIndexer.eventIndex).onLocalUnitIndex()
                        
                        return false
                    endmethod
                elseif thistype.onLocalUnitDeindex.exists then
                    private static method onLocalUnitIndexEvent takes nothing returns boolean
                        call thistype(UnitIndexer.eventIndex).ON_DEINDEX.register(onLocalUnitDeindexEventExpr)
                            
                        return false
                    endmethod
                endif
            elseif thistype.onLocalUnitIndex.exists then
                /*
                *   global events
                *
                *       onLocalUnitDeindex is run globally, so it doesn't need onLocalUnitIndexEvent
                *       anymore
                */
                private static method onLocalUnitIndexEvent takes nothing returns boolean
                    call thistype(UnitIndexer.eventIndex).onLocalUnitIndex()
                    
                    return false
                endmethod
            endif
            
            static if thistype.onLocalUnitDeindex.exists then
                private static method onLocalUnitDeindexEvent takes nothing returns boolean
                    call thistype(UnitIndexer.eventIndex).onLocalUnitDeindex()
                    
                    return false
                endmethod
            endif
            
            /*
            *   The reason why ON_INDEX is used is so that the module can be enabled/disabled
            *   correctly
            */
            private static method onInit takes nothing returns nothing
                static if thistype.onUnitIndex.exists then
                    /*
                    *   local events
                    */
                    static if thistype.onLocalUnitDeindex.exists then
                        set onLocalUnitDeindexEventExpr = Condition(function thistype.onLocalUnitDeindexEvent)
                    endif
                    
                    /*
                    *   onLocalUnitIndexEvent is registered for onLocalUnitdeindex because onLocalUnitDeindex
                    *   must be registered to each unit. This means that it must register as units are indexed.
                    */
                    static if thistype.onLocalUnitIndex.exists then
                        call thistype.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
                    elseif thistype.onLocalUnitDeindex.exists then
                        call thistype.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
                    endif
                else
                    /*
                    *   global events
                    *
                    *   ON_DEINDEX is used here instead of UnitIndexer.GlobalEvent.ON_DEINDEX for proper
                    *   execution order
                    */
                    
                    static if thistype.onLocalUnitDeindex.exists then
                        call thistype.ON_DEINDEX.register(Condition(function thistype.onLocalUnitDeindexEvent))
                    endif
                    
                    static if thistype.onLocalUnitIndex.exists then
                        call thistype.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
                    endif
                endif
                
                static if thistype.localInit.exists then
                    call localInit()
                endif
            endmethod
        endif
    //! endtextmacro
endlibrary

Unit Index
Collapse JASS:
/*
*   requires
*
*       Alloc
*       ErrorMessage
*
*       private struct p_UnitIndex extends array
*
*       debug method operator isAllocated takes nothing returns boolean
*       debug static method calculateMemoryUsage takes nothing returns integer
*       debug static method getAllocatedMemoryAsString takes nothing returns string
*
*       method operator indexer takes nothing returns UnitIndexer
*       method operator unit takes nothing returns unit
*       static method operator [] takes unit whichUnit returns thistype
*       static method exists takes unit whichUnit returns boolean
*
*   struct UnitIndex extends array
*
*       readonly unit unit
*       readonly UnitIndexer indexer
*
*       static method operator [] takes unit whichUnit returns UnitIndex
*
*       static method exists takes unit whichUnit returns boolean
*       static method isDeindexing takes unit whichUnit returns boolean
*/

//! textmacro UNIT_INDEXER_UNIT_INDEX
private struct p_UnitIndex extends array
    implement AllocQ

    private unit p_unit
    
    static method create takes unit whichUnit returns thistype
        local thistype this = allocate()
        
        set p_unit = whichUnit
        call SetUnitUserData(whichUnit, this)

        call UnitAddAbility(whichUnit, ABILITIES_UNIT_INDEXER)
        call UnitMakeAbilityPermanent(whichUnit, true, ABILITIES_UNIT_INDEXER)
        
        return this
    endmethod
    
    method destroy takes nothing returns nothing
        set p_unit = null
    
        call deallocate()
    endmethod
    
    method operator indexer takes nothing returns UnitIndexer
        debug call ThrowWarning(not isAllocated,                                            "UnitIndexer", "indexer", "thistype", this, "Getting indexer from a deallocated unit index.")
        
        return this
    endmethod
    
    method operator unit takes nothing returns unit
        debug call ThrowWarning(not isAllocated,                                            "UnitIndexer", "unit", "thistype", this, "Getting unit from a deallocated unit index.")
    
        return p_unit
    endmethod
    static method operator [] takes unit whichUnit returns thistype
        debug call ThrowWarning(GetUnitTypeId(whichUnit) == 0,                              "UnitIndexer", "[]", "thistype", 0, "Getting unit index of a null unit.")
        debug call ThrowWarning(thistype(GetUnitUserData(whichUnit)).p_unit != whichUnit,   "UnitIndexer", "[]", "thistype", 0, "Getting unit index of a unit that isn't indexed.")
        
        return GetUnitUserData(whichUnit)
    endmethod
    
    static method exists takes unit whichUnit returns boolean
        debug call ThrowWarning(GetUnitTypeId(whichUnit) == 0, "UnitIndexer", "exists",     "thistype", 0, "Checking for the existence of a null unit.")
    
        return thistype(GetUnitUserData(whichUnit)).p_unit == whichUnit
    endmethod
    
    static method isDeindexing takes unit whichUnit returns boolean
        return GetUnitTypeId(whichUnit) != 0 and GetUnitAbilityLevel(whichUnit, ABILITIES_UNIT_INDEXER) == 0 and thistype(GetUnitUserData(whichUnit)).p_unit == whichUnit
    endmethod
endstruct

struct UnitIndex extends array
    method operator unit takes nothing returns unit
        return p_UnitIndex(this).unit
    endmethod
    
    static method operator [] takes unit whichUnit returns thistype
        return p_UnitIndex[whichUnit]
    endmethod
    
    static method exists takes unit whichUnit returns boolean
        return p_UnitIndex.exists(whichUnit)
    endmethod
    
    static method isDeindexing takes unit whichUnit returns boolean
        return p_UnitIndex.isDeindexing(whichUnit)
    endmethod
    
    method operator indexer takes nothing returns UnitIndexer
        return p_UnitIndex(this).indexer
    endmethod
endstruct
//! endtextmacro

Unit Indexer
Collapse JASS:
/*
*   requires
*
*       Event
*       WorldBounds
*
*   struct UnitIndexer extends array
*
*       static boolean enabled = true
*
*       readonly static Trigger GlobalEvent.ON_INDEX
*       readonly static Trigger GlobalEvent.ON_DEINDEX
*       readonly Trigger Event.ON_DEINDEX
*
*       readonly UnitIndex eventIndex = 0
*       readonly unit eventUnit = null
*
*   private struct WrappedTrigger extends array
*
*       method reference takes Trigger whichTrigger returns nothing
*       method register takes boolexpr whichExpression returns nothing
*
*/

//! textmacro UNIT_INDEXER_UNIT_INDEXER
private struct WrappedTrigger extends array
    method reference takes Trigger whichTrigger returns TriggerReference
        local TriggerReference triggerReference = Trigger(this).reference(whichTrigger)
        
        call PreGameEvent.fireTrigger(whichTrigger)
        
        return triggerReference
    endmethod
    
    method register takes boolexpr whichExpression returns TriggerCondition
        local TriggerCondition triggerCondition = Trigger(this).register(whichExpression)
        
        call PreGameEvent.fireExpression(whichExpression)
        
        return triggerCondition
    endmethod
endstruct

private struct UnitIndexerTriggerGlobal extends array
    readonly static WrappedTrigger  ON_INDEX
    readonly static Trigger         ON_DEINDEX
    
    private static method init takes nothing returns nothing
        set ON_INDEX = Trigger.create()
        set ON_DEINDEX = Trigger.create()
    endmethod
    
    implement Init
endstruct

private keyword ON_DEINDEX_MAIN
private struct UnitIndexerTrigger extends array
    readonly Trigger ON_DEINDEX
    readonly Trigger ON_DEINDEX_MAIN
    
    method createDeindex takes nothing returns nothing
        set ON_DEINDEX = Trigger.create()
        set ON_DEINDEX_MAIN = Trigger.create()
        
        call ON_DEINDEX_MAIN.reference(ON_DEINDEX)
        call ON_DEINDEX_MAIN.reference(UnitIndexerTriggerGlobal.ON_DEINDEX)
    endmethod
    
    method destroyDeindex takes nothing returns nothing
        call ON_DEINDEX_MAIN.destroy()
        call ON_DEINDEX.destroy()
    endmethod
endstruct

struct UnitIndexer extends array
    private trigger deindexTrigger
    private static boolexpr onDeindexCondition

    static method operator eventIndex takes nothing returns UnitIndex
        return p_eventIndex
    endmethod
    static method operator eventUnit takes nothing returns unit
        return eventIndex.unit
    endmethod
    
    static method operator GlobalEvent takes nothing returns UnitIndexerTriggerGlobal
        return 0
    endmethod
    method operator Event takes nothing returns UnitIndexerTrigger
        return this
    endmethod

    static boolean enabled = true
    
    private static method fire takes Trigger whichTrigger, integer whichIndex returns nothing
        local integer prevIndexedUnit = p_eventIndex
        set p_eventIndex = whichIndex
        call whichTrigger.fire()
        set p_eventIndex = prevIndexedUnit
    endmethod
    
    private static method onIndex takes nothing returns boolean
        local unit indexedUnit = GetFilterUnit()
        local p_UnitIndex index
        
        if (enabled and not p_UnitIndex.exists(indexedUnit)) then
            set index = p_UnitIndex.create(indexedUnit)
            
            set thistype(index).deindexTrigger = CreateTrigger()
            call TriggerRegisterUnitEvent(thistype(index).deindexTrigger, indexedUnit, EVENT_UNIT_ISSUED_ORDER)
            call TriggerAddCondition(thistype(index).deindexTrigger, onDeindexCondition)
            
            call PreGameEvent.addUnitIndex(index)
            
            call thistype(index).Event.createDeindex()
            
            call fire(GlobalEvent.ON_INDEX, index)
        endif
        
        set indexedUnit = null
        
        return false
    endmethod
    
    private static method onDeindex takes nothing returns boolean
        local p_UnitIndex index = GetUnitUserData(GetTriggerUnit())
        
        if (GetUnitAbilityLevel(GetTriggerUnit(), ABILITIES_UNIT_INDEXER) == 0) then
            call PreGameEvent.removeUnitIndex(index)
            
            call fire(thistype(index).Event.ON_DEINDEX_MAIN, index)
            
            call thistype(index).Event.destroyDeindex()
            
            call DestroyTrigger(thistype(index).deindexTrigger)
            set thistype(index).deindexTrigger = null
            
            call index.destroy()
        endif
        
        return false
    endmethod
    
    private static method init takes nothing returns nothing
        local trigger indexTrigger = CreateTrigger()
        
        local boolexpr onIndexCondition  = Condition(function thistype.onIndex)
        
        local group enumGroup = CreateGroup()
        
        local integer currentPlayerId = 15
        local player currentPlayer
        
        set onDeindexCondition= Condition(function thistype.onDeindex)
        
        call TriggerRegisterEnterRegion(indexTrigger, WorldBounds.worldRegion, onIndexCondition)
        
        loop
            set currentPlayer = Player(currentPlayerId)
            
            call SetPlayerAbilityAvailable(currentPlayer, ABILITIES_UNIT_INDEXER, false)
            call GroupEnumUnitsOfPlayer(enumGroup, currentPlayer, onIndexCondition)
            
            exitwhen currentPlayerId == 0
            set currentPlayerId = currentPlayerId - 1
        endloop
        
        call DestroyGroup(enumGroup)
        
        set onIndexCondition = null
        
        set enumGroup = null
        set currentPlayer = null
        
        set indexTrigger = null
    endmethod
    
    implement Init
endstruct
//! endtextmacro

PreGame Event
Collapse JASS:
/*
*   requires
*
*       StaticUniqueList
*
*   private struct PreGameEvent extends array
*
*       Evaluates all triggers and functions registered to
*       Unit Indexer before game start for all indexed units.
*
*
*       static method fireTrigger takes trigger whichTrigger returns nothing
*       static method fireExpression takes boolexpr whichExpression returns nothing
*
*       static method addUnitIndex takes integer whichUnitIndex returns nothing
*       static method removeUnitIndex takes integer whichUnitIndex returns nothing
*/

//! textmacro UNIT_INDEXER_PREGAME_EVENT
private struct PreGameEvent extends array
    readonly static boolean isGameLoaded = false

    implement StaticUniqueList
    
    private static method p_fireTrigger takes Trigger whichTrigger returns nothing
        local thistype this = first
        local integer prevIndexedUnitId = p_eventIndex
        
        loop
            exitwhen this == sentinel or not whichTrigger.enabled
            
            set p_eventIndex = this
            call whichTrigger.fire()
            
            set this = next
        endloop
        
        set p_eventIndex = prevIndexedUnitId
    endmethod
    static method fireTrigger takes Trigger whichTrigger returns nothing
        if (first != 0) then
            call p_fireTrigger(whichTrigger)
        endif
    endmethod
    
    private static method p_fireExpression takes boolexpr whichExpression returns nothing
        local trigger triggerContainer = CreateTrigger()
        local thistype this = first
        local integer prevIndexedUnitId = p_eventIndex
        
        call TriggerAddCondition(triggerContainer, whichExpression)
        
        loop
            exitwhen this == sentinel
            
            set p_eventIndex = this
            call TriggerEvaluate(triggerContainer)
            
            set this = next
        endloop
        
        call TriggerClearConditions(triggerContainer)
        call DestroyTrigger(triggerContainer)
        set triggerContainer = null
        
        set p_eventIndex = prevIndexedUnitId
    endmethod
    static method fireExpression takes boolexpr whichExpression returns nothing
        if (first != 0) then
            call p_fireExpression(whichExpression)
        endif
    endmethod
    
    static method addUnitIndex takes integer whichUnitIndex returns nothing
        if (isGameLoaded) then
            return
        endif
        
        call enqueue(whichUnitIndex)
    endmethod
    
    static method removeUnitIndex takes integer whichUnitIndex returns nothing
        if (isGameLoaded) then
            return
        endif
        
        call thistype(whichUnitIndex).remove()
    endmethod
    
    private static method run takes nothing returns nothing
        call DestroyTimer(GetExpiredTimer())
        
        set isGameLoaded = true
        
        call clear()
    endmethod
    private static method init takes nothing returns nothing
        call TimerStart(CreateTimer(), 0, false, function thistype.run)
    endmethod
    
    implement Init
endstruct
//! endtextmacro

Installation Script
Collapse JASS:
/*
*   This is for World Editor
*
*   You will need to
*
*       1.  Enable This Trigger
*       2.  Save Your Map
*       3.  Close Your Map
*       4.  Open Your Map
*       5.  Disable This Trigger
*       6.  Save Your Map
*/
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! i do
        //! i dofile("GetVarObject")
        
        //! i local id = getvarobject("Adef", "abilities", "ABILITIES_UNIT_INDEXER", true)
        
        //! i createobject("Adef", id)
        //! i makechange(current, "aart", "")
        //! i makechange(current, "arac", "0")
        //! i makechange(current, "anam", "Unit Indexer")
        //! i makechange(current, "ansf", "Unit Indexer")

        //! i updateobjects()
    //! i end
//! endexternalblock

/*
*   This is for a .lua file
*
*   Can run this through command line using grimex exe
*
dofile("GetVarObject")

local id = getvarobject("Adef", "abilities", "ABILITIES_UNIT_INDEXER", true)

createobject("Adef", id)
makechange(current, "aart", "")
makechange(current, "arac", "0")
makechange(current, "anam", "Unit Indexer")
makechange(current, "ansf", "Unit Indexer")

updateobjects()
*/
Attached Files
File Type: w3x Unit Indexer.w3x (129.4 KB, 10 views)

Last edited by Nestharus : 04-21-2014 at 09:38 PM.
Nestharus is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 04-18-2014, 10:22 PM   #2
Nestharus
User
 
Join Date: Jul 2007
Posts: 218

Nestharus has little to show at this moment (6)

Default

For anyone that may have previously downloaded this, I did a mass format change last night. This resource had a combo of spaces and tabs in it (dunno why). I changed it all back into tabs, but this resulted in a few spaces inside of the modules getting dropped. I didn't check the modules, so it ended up having syntax errors.

I just added the 4 missing spaces back in, so the syntax errors are now gone.
Nestharus is offline   Reply With Quote
Old 04-20-2014, 10:22 AM   #3
Anitarf
Procrastination Incarnate


Development Director
 
Join Date: Feb 2004
Posts: 8,075

Submissions (19)

Anitarf has a brilliant future (888)Anitarf has a brilliant future (888)Anitarf has a brilliant future (888)Anitarf has a brilliant future (888)Anitarf has a brilliant future (888)Anitarf has a brilliant future (888)Anitarf has a brilliant future (888)Anitarf has a brilliant future (888)

2008 Spell olympics - Fire - SilverApproved Map: Old School Alliance TacticsHero Contest #2 - 3rd PlaceSpell making session 2 winner

Default

Hello, it's been a while.

Just a reminder, you need to get the required resources approved first before this can get reviewed.
__________________
Anitarf is offline   Reply With Quote
Old 04-20-2014, 11:43 AM   #4
Nestharus
User
 
Join Date: Jul 2007
Posts: 218

Nestharus has little to show at this moment (6)

Default

There are around 20 required resources, and many of them are very small, so I doubt that'll happen =).

Just try going through the tutorials and stuff to see if you think it's worth making an exception ^)^. Trust me, I posted this for a reason :p
Nestharus is offline   Reply With Quote
Old 04-25-2014, 07:58 AM   #5
BlackRose
User
 
Join Date: Apr 2009
Posts: 35

BlackRose is on a distinguished road (12)

Default

I thought you died or went missing.

It's impressive how people still manage to play with Warcraft III. Was an amazing game.
BlackRose is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 06:47 PM.


Donate

Affiliates
The Hubb http://bylur.com - Warcraft, StarCraft, Diablo and DotA Blog & Forums The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2014, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services