| 04-18-2014, 08:51 AM | #1 |
Map Includes
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 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 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 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 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 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() */ |
| 04-18-2014, 10:22 PM | #2 |
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. |
| 04-20-2014, 10:22 AM | #3 |
Hello, it's been a while. Just a reminder, you need to get the required resources approved first before this can get reviewed. |
| 04-20-2014, 11:43 AM | #4 |
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 |
| 04-25-2014, 07:58 AM | #5 |
I thought you died or went missing. It's impressive how people still manage to play with Warcraft III. Was an amazing game. |
