UnitIndexer

Scripts

14 years
edited 8 years
A library to manage units by indexing them.



Main library:
Code (jass) Select
1
library UnitIndexer /* v5.3.0.1
2
************************************************************************************
3
*
4
*	*/ uses /*
5
*
6
*		*/ WorldBounds			/*
7
*		*/ Init					/*
8
*		*/ AllocQ				/*
9
*		*/ ErrorMessage 		/*
10
*		*/ StaticUniqueList 	/*
11
*		*/ UnitIndexerSettings 	/*
12
*		*/ Trigger				/*
13
*
14
********************************************************************************
15
*
16
*	struct UnitIndexer extends array
17
*
18
*		Fields
19
*		-------------------------
20
*
21
*			static boolean enabled
22
*				-	is UnitIndexer onUnitIndex enabled?
23
*
24
*			readonly static Trigger GlobalEvent.ON_INDEX
25
*				-	this is a global event that runs whenever any unit is indexed
26
*
27
*				Examples:	UnitIndexer.GlobalEvent.ON_INDEX.reference(yourTrigger)
28
*							UnitIndexer.GlobalEvent.ON_INDEX.register(yourCode)
29
*
30
*				Examples:	unitIndex.indexer.Event.ON_DEINDEX.reference(yourTrigger)
31
*							unitIndex.indexer.Event.ON_DEINDEX.register(yourCode)
32
*
33
*			readonly Trigger Event.ON_DEINDEX
34
*				-	this is a local event that runs whenever a specific unit is deindexed
35
*
36
*				Examples:	unitIndex.indexer.Event.ON_DEINDEX.reference(yourTrigger)
37
*							unitIndex.indexer.Event.ON_DEINDEX.register(yourCode)
38
*
39
*			readonly static Trigger GlobalEvent.ON_DEINDEX
40
*				-	this is ON_DEINDEX, but global
41
*
42
*				Examples:	UnitIndexer.GlobalEvent.ON_DEINDEX.reference(yourTrigger)
43
*							UnitIndexer.GlobalEvent.ON_DEINDEX.register(yourCode)
44
*
45
*			readonly static UnitIndex eventIndex
46
*				-	when a unit is indexed or deindexed, this value stores
47
*					the index of that unit
48
*
49
*			readonly static unit eventUnit
50
*				-	when a unit is indexed or deindexed, this value stores
51
*					the unit
52
*
53
************************************************************************************
54
*
55
*	struct UnitIndex extends array
56
*
57
*		Fields
58
*		-------------------------
59
*
60
*			readonly unit unit
61
*				-	converts a unit index into a unit
62
*
63
*			readonly UnitIndexer indexer
64
*				-	the indexer in charge of handling the unit
65
*					useful for deindex event, which is unit specific
66
*
67
*		Operators
68
*		-------------------------
69
*
70
*			static method operator [] takes unit whichUnit returns UnitIndex
71
*				-	converts a unit into a UnitIndex
72
*
73
*		Methods
74
*		-------------------------
75
*
76
*			static method exists takes unit whichUnit returns boolean
77
*				-	determines whether the unit is indexed or not
78
*
79
*			static method isDeindexing takes unit whichUnit returns boolean
80
*				-	determines whether the unit is in the process of being deindexed or not
81
*
82
************************************************************************************
83
*
84
*	module GlobalUnitIndex
85
*
86
*		This has absolutely no module support
87
*
88
*		Fields
89
*		-------------------------
90
*
91
*			static constant boolean GLOBAL_UNIT_INDEX = true
92
*				-	this is used to ensure that only one unit index module is implemented.
93
*
94
*			readonly unit unit
95
*				-	converts a unit index into a unit
96
*
97
*			readonly boolean isUnitIndexed
98
*				-	is the unit index indexed
99
*
100
*			readonly UnitIndexer unitIndexer
101
*				-	the indexer in charge of handling the unit
102
*					useful for deindex event, which is unit specific
103
*
104
*		Methods
105
*		-------------------------
106
*
107
*			static method exists takes unit whichUnit returns boolean
108
*				-	determines whether the unit is indexed
109
*
110
*			static method isDeindexing takes unit whichUnit returns boolean
111
*				-	determines whether the unit is in the process of being deindexed or not
112
*
113
*		Interface
114
*		-------------------------
115
*
116
*			interface private method onUnitIndex takes nothing returns nothing
117
*			interface private method onUnitDeindex takes nothing returns nothing
118
*
119
*		Operators
120
*		-------------------------
121
*
122
*			static method operator [] takes unit whichUnit returns thistype
123
*				-	converts a unit into thistype
124
*
125
************************************************************************************
126
*
127
*	module UnitIndex
128
*
129
*		If you would like to create modules that work off of the UnitIndex module, implement
130
*		UnitIndex at the top of your module
131
*		
132
*		Fields
133
*		-------------------------
134
*
135
*			static constant boolean UNIT_INDEX = true
136
*				-	this is used to ensure that only one unit index module is implemented.
137
*
138
*			static boolean enabled
139
*				-	is this UnitIndex struct enabled?
140
*				-	this can only be disabed if onUnitIndex exists
141
*
142
*			readonly unit unit
143
*				-	converts a unit index into a unit
144
*
145
*			readonly boolean isUnitIndexed
146
*				-	is the unit index indexed for the struct?
147
*
148
*			readonly UnitIndexer unitIndexer
149
*				-	the indexer in charge of handling the unit
150
*					useful for deindex event, which is unit specific
151
*
152
*		Operators
153
*		-------------------------
154
*
155
*			static method operator [] takes unit whichUnit returns thistype
156
*				-	converts a unit into thistype
157
*
158
*		Methods
159
*		-------------------------
160
*
161
*			static method exists takes unit whichUnit returns boolean
162
*				-	determines whether the unit is indexed or not for the struct
163
*
164
*			static method isDeindexing takes unit whichUnit returns boolean
165
*				-	determines whether the unit is in the process of being deindexed or not
166
*
167
*		Interface
168
*		-------------------------
169
*
170
*			interface private method onUnitIndex takes nothing returns boolean
171
*				-	if return true, index the unit for this struct
172
*
173
*			interface private method onUnitDeindex takes nothing returns nothing
174
*				-	only runs for units indexed for this struct
175
*				-	if not onUnitIndex method is declared, it will run for all units
176
*
177
************************************************************************************
178
*
179
*	module UnitIndexEx
180
*
181
*		If you would like to create modules that work off of the UnitIndexEx module, implement
182
*		UnitIndexEx at the top of your module
183
*		
184
*		Fields
185
*		-------------------------
186
*
187
*			static constant boolean UNIT_INDEX_EX = true
188
*				-	this is used for modules that rely on local events
189
*					it allows these modules to differentiate between UnitIndex
190
*					and UnitIndexEx
191
*
192
*			static boolean enabled
193
*				-	is this UnitIndex struct enabled?
194
*				-	this can only be disabed if onUnitIndex exists
195
*
196
*			readonly unit unit
197
*				-	converts a unit index into a unit
198
*
199
*			readonly boolean isUnitIndexed
200
*				-	is the unit index indexed for the struct?
201
*
202
*			readonly UnitIndexer unitIndexer
203
*				-	the indexer in charge of handling the unit
204
*					useful for deindex event, which is unit specific
205
*
206
*			readonly static Trigger ON_INDEX
207
*				-	this is a local event that runs whenever any unit is indexed for the struct
208
*				-	this is primarily used for other resources that work off of your struct
209
*
210
*				Examples:	Struct.ON_INDEX.reference(yourTrigger)
211
*							Struct.ON_INDEX.register(yourCode)
212
*
213
*			readonly Trigger Event.ON_DEINDEX
214
*			readonly static Trigger Event.ON_DEINDEX
215
*				-	this is a unit specific event that runs when your local unit is deindexed
216
*				-	this is static if onUnitIndex does not exist
217
*
218
*				Examples:	struct.ON_DEINDEX.reference(yourTrigger)
219
*							struct.ON_DEINDEX.register(yourCode)
220
*
221
*		Operators
222
*		-------------------------
223
*
224
*			static method operator [] takes unit whichUnit returns thistype
225
*				-	converts a unit into thistype
226
*
227
*		Methods
228
*		-------------------------
229
*
230
*			static method exists takes unit whichUnit returns boolean
231
*				-	determines whether the unit is indexed or not for the struct
232
*
233
*			static method isDeindexing takes unit whichUnit returns boolean
234
*				-	determines whether the unit is in the process of being deindexed or not
235
*
236
*		Interface
237
*		-------------------------
238
*
239
*			interface private method onUnitIndex takes nothing returns boolean
240
*				-	if return true, index the unit for this struct
241
*
242
*			interface private method onUnitDeindex takes nothing returns nothing
243
*				-	only runs for units indexed for this struct
244
*				-	if not onUnitIndex method is declared, it will run for all units
245
*
246
************************************************************************************
247
*
248
*	//! textmacro CREATE_LOCAL_UNIT_INDEX
249
*
250
*		A macro was chosen because multiple modules utilizing this code may be
251
*		implemented into one struct. If this was a module, then all but one
252
*		of those modules would break.
253
*
254
*		Interface
255
*		-------------------------
256
*
257
*			interface private method onLocalUnitIndex takes nothing returns nothing
258
*				-	runs whenever a unit is indexed for this struct
259
*
260
*			interface private method onLocalUnitDeindex takes nothing returns nothing
261
*				-	runs whenever a unit is deindexed for this struct
262
*
263
*			interface private static method localInit takes nothing returns nothing
264
*				-	the macro requires the usage of onInit. Declare this method if you
265
*					would like onInit.
266
*
267
************************************************************************************/
268
	globals
269
		private UnitIndex p_eventIndex = 0
270
	endglobals
271
272
	//! runtextmacro UNIT_INDEXER_UNIT_INDEX()
273
	//! runtextmacro UNIT_INDEXER_PREGAME_EVENT()
274
	//! runtextmacro UNIT_INDEXER_UNIT_INDEXER()
275
	
276
	module GlobalUnitIndex
277
		static if thistype.UNIT_INDEX then
278
		elseif thistype.UNIT_INDEX_EX then
279
		else
280
			static constant boolean GLOBAL_UNIT_INDEX = true
281
			
282
			static method operator [] takes unit whichUnit returns thistype
283
				return p_UnitIndex[whichUnit]
284
			endmethod
285
			method operator unit takes nothing returns unit
286
				return p_UnitIndex(this).unit
287
			endmethod
288
			method operator unitIndexer takes nothing returns UnitIndexer
289
				return p_UnitIndex(this).indexer
290
			endmethod
291
			method operator isUnitIndexed takes nothing returns boolean
292
				return p_UnitIndex(this).isAllocated
293
			endmethod
294
			static method exists takes unit whichUnit returns boolean
295
				return p_UnitIndex.exists(whichUnit)
296
			endmethod
297
			static method isDeindexing takes unit whichUnit returns boolean
298
				return p_UnitIndex.isDeindexing(whichUnit)
299
			endmethod
300
			
301
			static if thistype.GLOBAL_UNIT_INDEX then
302
				static if thistype.onUnitIndex.exists then
303
					private static method onIndexEvent takes nothing returns boolean
304
						call thistype(UnitIndexer.eventIndex).onUnitIndex()
305
					
306
						return false
307
					endmethod
308
				endif
309
				static if thistype.onUnitDeindex.exists then
310
					private static method onDeindexEvent takes nothing returns boolean
311
						call thistype(UnitIndexer.eventIndex).onUnitDeindex()
312
						
313
						return false
314
					endmethod
315
				endif
316
				
317
				static if thistype.onUnitIndex.exists then
318
					private static method onInit takes nothing returns nothing
319
				elseif thistype.onUnitDeindex.exists then
320
					private static method onInit takes nothing returns nothing
321
				endif
322
				
323
				static if thistype.onUnitIndex.exists then
324
					call UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onIndexEvent))
325
				endif
326
				
327
				static if thistype.onUnitDeindex.exists then
328
					call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function thistype.onDeindexEvent))
329
				endif
330
				
331
				static if thistype.onUnitIndex.exists then
332
					endmethod
333
				elseif thistype.onUnitDeindex.exists then
334
					endmethod
335
				endif
336
			endif
337
		endif
338
	endmodule
339
	
340
	module UnitIndex
341
		static if thistype.GLOBAL_UNIT_INDEX then
342
			private static method error takes nothing returns nothing
343
				A module requires UnitIndex to operate correctly.
344
				This struct is currently implementing GlobalUnitIndex.
345
			endmethod
346
		elseif thistype.UNIT_INDEX_EX then
347
		else
348
			static constant boolean UNIT_INDEX = true
349
			
350
			/*
351
			*	[] is included because the struct automatically overrides it
352
			*
353
			*	eventIndex is included to return thistype instead of UnitIndex
354
			*/
355
			static method operator [] takes unit whichUnit returns thistype
356
				return UnitIndex[whichUnit]
357
			endmethod
358
			method operator unitIndexer takes nothing returns UnitIndexer
359
				return this
360
			endmethod
361
			method operator unit takes nothing returns unit
362
				return UnitIndex(this).unit
363
			endmethod
364
			
365
			static method isDeindexing takes unit whichUnit returns boolean
366
				return UnitIndex.isDeindexing(whichUnit)
367
			endmethod
368
			
369
			/*
370
			*	the method is done in the second case because when there is no
371
			*	onUnitIndex method, indexed depends on whether the actual
372
			*	instance is allocated or not
373
			*/
374
			static if thistype.onUnitIndex.exists then
375
				readonly boolean isUnitIndexed
376
			else
377
				method operator isUnitIndexed takes nothing returns boolean
378
					return p_UnitIndex(this).isAllocated
379
				endmethod
380
			endif
381
			
382
			static if thistype.onUnitIndex.exists then
383
				static method exists takes unit whichUnit returns boolean
384
					return UnitIndex.exists(whichUnit) and thistype(GetUnitUserData(whichUnit)).isUnitIndexed
385
				endmethod
386
			else
387
				static method exists takes unit whichUnit returns boolean
388
					return UnitIndex.exists(whichUnit)
389
				endmethod
390
			endif
391
			
392
			/*
393
			*	this is used to run local events
394
			*/
395
			static if thistype.onUnitIndex.exists then
396
				/*
397
				*	this is where UnitIndex is located
398
				*/
399
				private static TriggerCondition entryPoint
400
				
401
				/*
402
				*	this stores private onUnitIndex method
403
				*/
404
				private static boolexpr onIndexExpression
405
				
406
				/*
407
				*	enable works with code inside of entryPoint here
408
				*/
409
				private static boolean p_enabled = true
410
				static method operator enabled takes nothing returns boolean
411
					return p_enabled
412
				endmethod
413
				static method operator enabled= takes boolean enable returns nothing
414
					set p_enabled = enable
415
					
416
					if (enable) then
417
						call entryPoint.replace(onIndexExpression)
418
					else
419
						call entryPoint.replace(null)
420
					endif
421
				endmethod
422
			else
423
				/*
424
				*	if onUnitIndex does not exist, the struct can't be disabled
425
				*/
426
				static method operator enabled takes nothing returns boolean
427
					return true
428
				endmethod
429
				static method operator enabled= takes boolean enable returns nothing
430
					set enable = true
431
				endmethod
432
			endif
433
			
434
			/*
435
			*	onUnitDeindex
436
			*
437
			*	This must be implemented if onUnitIndex exists to clear isUnitIndexed
438
			*/
439
			static if thistype.onUnitDeindex.exists then
440
				static if thistype.onUnitIndex.exists then
441
					private static boolexpr onDeindexExpression
442
				endif
443
				
444
				private static method onDeindexEvent takes nothing returns boolean
445
					call thistype(UnitIndexer.eventIndex).onUnitDeindex()
446
					
447
					static if thistype.onUnitIndex.exists then
448
						set thistype(UnitIndexer.eventIndex).isUnitIndexed = false
449
					endif
450
					
451
					return false
452
				endmethod
453
			elseif thistype.onUnitIndex.exists then
454
				static if thistype.onUnitIndex.exists then
455
					private static boolexpr onDeindexExpression
456
				endif
457
				
458
				private static method onDeindexEvent takes nothing returns boolean
459
					set thistype(UnitIndexer.eventIndex).isUnitIndexed = false
460
					
461
					return false
462
				endmethod
463
			endif
464
			
465
			/*
466
			*	onUnitIndex
467
			*/
468
			static if thistype.onUnitIndex.exists then
469
				private static method onIndexEvent takes nothing returns boolean
470
					if (thistype(UnitIndexer.eventIndex).onUnitIndex()) then
471
						set thistype(UnitIndexer.eventIndex).isUnitIndexed = true
472
						
473
						/*
474
						*	this is always registered to clear isUnitIndexed
475
						*/
476
						call UnitIndexer(UnitIndexer.eventIndex).Event.ON_DEINDEX.register(onDeindexExpression)
477
					endif
478
					
479
					return false
480
				endmethod
481
			endif
482
			
483
			static if thistype.onUnitIndex.exists then
484
				private static method onInit takes nothing returns nothing
485
					set onIndexExpression = Condition(function thistype.onIndexEvent)
486
					set onDeindexExpression = Condition(function thistype.onDeindexEvent)
487
					
488
					set entryPoint = UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onIndexEvent))
489
				endmethod
490
			elseif thistype.onUnitDeindex.exists then
491
				private static method onInit takes nothing returns nothing
492
					call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function thistype.onDeindexEvent))
493
				endmethod
494
			endif
495
		endif
496
	endmodule
497
	
498
	private struct UnitIndexList extends array
499
		//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "unitIndex2Node", "thistype")
500
		//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "node2UnitIndex", "thistype")
501
		
502
		method add takes thistype index returns nothing
503
			local thistype node = enqueue()
504
			
505
			set node.node2UnitIndex = index
506
			set index.unitIndex2Node = node
507
		endmethod
508
		
509
		method delete takes nothing returns nothing
510
			call unitIndex2Node.remove()
511
		endmethod
512
		
513
		private static method init takes nothing returns nothing
514
			//! runtextmacro INITIALIZE_TABLE_FIELD("unitIndex2Node")
515
			//! runtextmacro INITIALIZE_TABLE_FIELD("node2UnitIndex")
516
		endmethod
517
		
518
		implement NxListT
519
		implement Init
520
	endstruct
521
	private struct UnitIndexModuleTrigger extends array
522
		method reference takes Trigger whichTrigger returns TriggerReference
523
			local TriggerReference triggerReference = Trigger(this).reference(whichTrigger)
524
			
525
			local UnitIndexList node = UnitIndexList(this).first
526
			local integer prevIndexedUnitId = p_eventIndex
527
			
528
			loop
529
				exitwhen node == UnitIndexList.sentinel or not whichTrigger.enabled
530
				
531
				set p_eventIndex = node.node2UnitIndex
532
				call whichTrigger.fire()
533
					
534
				set node = node.next
535
			endloop
536
			
537
			set p_eventIndex = prevIndexedUnitId
538
			
539
			return triggerReference
540
		endmethod
541
		
542
		method register takes boolexpr whichExpression returns TriggerCondition
543
			local TriggerCondition triggerCondition = Trigger(this).register(whichExpression)
544
			
545
			local trigger triggerContainer = CreateTrigger()
546
			
547
			local UnitIndexList node = UnitIndexList(this).first
548
			local integer prevIndexedUnitId = p_eventIndex
549
			
550
			call TriggerAddCondition(triggerContainer, whichExpression)
551
			
552
			loop
553
				exitwhen node == UnitIndexList.sentinel
554
				
555
				set p_eventIndex = node.node2UnitIndex
556
				call TriggerEvaluate(triggerContainer)
557
					
558
				set node = node.next
559
			endloop
560
			
561
			call TriggerClearConditions(triggerContainer)
562
			call DestroyTrigger(triggerContainer)
563
			set triggerContainer = null
564
			
565
			set p_eventIndex = prevIndexedUnitId
566
			
567
			return triggerCondition
568
		endmethod
569
	endstruct
570
	module UnitIndexEx
571
		static if thistype.GLOBAL_UNIT_INDEX then
572
			private static method error takes nothing returns nothing
573
				A module requires UnitIndexEx to operate correctly.
574
				This struct is currently implementing GlobalUnitIndex.
575
			endmethod
576
		elseif thistype.UNIT_INDEX then
577
			private static method error takes nothing returns nothing
578
				A module requires UnitIndexEx to operate correctly.
579
				This struct is currently implementing UnitIndex.
580
			endmethod
581
		else
582
			static constant boolean UNIT_INDEX_EX = true
583
			
584
			private static UnitIndex delegate unitIndex = 0
585
		
586
			/*
587
			*	[] is included because the struct automatically overrides it
588
			*
589
			*	eventIndex is included to return thistype instead of UnitIndex
590
			*/
591
			static method operator [] takes unit whichUnit returns thistype
592
				return UnitIndex[whichUnit]
593
			endmethod
594
			method operator unit takes nothing returns unit
595
				return UnitIndex(this).unit
596
			endmethod
597
			method operator unitIndexer takes nothing returns UnitIndexer
598
				return this
599
			endmethod
600
			
601
			static method isDeindexing takes unit whichUnit returns boolean
602
				return UnitIndex.isDeindexing(whichUnit)
603
			endmethod
604
			
605
			/*
606
			*	the method is done in the second case because when there is no
607
			*	onUnitIndex method, indexed depends on whether the actual
608
			*	instance is allocated or not
609
			*/
610
			static if thistype.onUnitIndex.exists then
611
				readonly boolean isUnitIndexed
612
			else
613
				method operator isUnitIndexed takes nothing returns boolean
614
					return p_UnitIndex(this).isAllocated
615
				endmethod
616
			endif
617
			
618
			static if thistype.onUnitIndex.exists then
619
				static method exists takes unit whichUnit returns boolean
620
					return UnitIndex.exists(whichUnit) and thistype(GetUnitUserData(whichUnit)).isUnitIndexed
621
				endmethod
622
			else
623
				static method exists takes unit whichUnit returns boolean
624
					return UnitIndex.exists(whichUnit)
625
				endmethod
626
			endif
627
		
628
			/*
629
			*	this is used to run local events
630
			*/
631
			static if thistype.onUnitIndex.exists then
632
				readonly static UnitIndexModuleTrigger ON_INDEX
633
			else
634
				readonly static WrappedTrigger ON_INDEX
635
			endif
636
			
637
			static if thistype.onUnitIndex.exists then
638
				/*
639
				*	this is where UnitIndex is located
640
				*/
641
				private static TriggerCondition entryPoint
642
				
643
				/*
644
				*	this stores private onUnitIndex method
645
				*/
646
				private static boolexpr onIndexExpression
647
				
648
				/*
649
				*	enable works with code inside of entryPoint here
650
				*/
651
				private static boolean p_enabled = true
652
				static method operator enabled takes nothing returns boolean
653
					return p_enabled
654
				endmethod
655
				static method operator enabled= takes boolean enable returns nothing
656
					set p_enabled = enable
657
					
658
					if (enable) then
659
						call entryPoint.replace(onIndexExpression)
660
					else
661
						call entryPoint.replace(null)
662
					endif
663
				endmethod
664
			else
665
				/*
666
				*	if onUnitIndex does not exist, the struct can't be disabled
667
				*/
668
				static method operator enabled takes nothing returns boolean
669
					return true
670
				endmethod
671
				static method operator enabled= takes boolean enable returns nothing
672
					set enable = true
673
				endmethod
674
			endif
675
			
676
			/*
677
			*	this is here so that the module runs after code that relies on the module
678
			*/
679
			static if thistype.onUnitIndex.exists then
680
				readonly Trigger ON_DEINDEX
681
			else
682
				readonly static Trigger ON_DEINDEX
683
			endif
684
			
685
			/*
686
			*	onUnitDeindex
687
			*/
688
			static if thistype.onUnitDeindex.exists then
689
				static if thistype.onUnitIndex.exists then
690
					private static boolexpr onDeindexExpression
691
				endif
692
				
693
				private static method onDeindexEvent takes nothing returns boolean
694
					call thistype(UnitIndexer.eventIndex).onUnitDeindex()
695
					
696
					static if thistype.onUnitIndex.exists then
697
						set thistype(UnitIndexer.eventIndex).isUnitIndexed = false
698
						
699
						call thistype(UnitIndexer.eventIndex).ON_DEINDEX.destroy()
700
						
701
						if (not PreGameEvent.isGameLoaded) then
702
							call UnitIndexList(UnitIndexer.eventIndex).delete()
703
						endif
704
					endif
705
					
706
					return false
707
				endmethod
708
			elseif thistype.onUnitIndex.exists then
709
				private static boolexpr onDeindexExpression
710
				
711
				private static method onDeindexEvent takes nothing returns boolean
712
					set thistype(UnitIndexer.eventIndex).isUnitIndexed = false
713
					
714
					call thistype(UnitIndexer.eventIndex).ON_DEINDEX.destroy()
715
					
716
					if (not PreGameEvent.isGameLoaded) then
717
						call UnitIndexList(UnitIndexer.eventIndex).delete()
718
					endif
719
					
720
					return false
721
				endmethod
722
			endif
723
			
724
			/*
725
			*	onUnitIndex
726
			*/
727
			static if thistype.onUnitIndex.exists then
728
				private static method onIndexEvent takes nothing returns boolean
729
					if (thistype(UnitIndexer.eventIndex).onUnitIndex()) then
730
						set thistype(UnitIndexer.eventIndex).isUnitIndexed = true
731
						
732
						set thistype(UnitIndexer.eventIndex).ON_DEINDEX = Trigger.create(true)
733
						call thistype(UnitIndexer.eventIndex).ON_DEINDEX.register(onDeindexExpression)
734
735
						call UnitIndexer(UnitIndexer.eventIndex).Event.ON_DEINDEX.reference(thistype(UnitIndexer.eventIndex).ON_DEINDEX)
736
						
737
						if (not PreGameEvent.isGameLoaded) then
738
							call UnitIndexList(ON_INDEX).add(UnitIndexer.eventIndex)
739
						endif
740
						
741
						call Trigger(thistype.ON_INDEX).fire()
742
					endif
743
					
744
					return false
745
				endmethod
746
			endif
747
			
748
			private static method destroyPregameUnitList takes nothing returns nothing
749
				call DestroyTimer(GetExpiredTimer())
750
				
751
				call UnitIndexList(ON_INDEX).destroy()
752
			endmethod
753
			
754
			private static method onInit takes nothing returns nothing
755
				set ON_INDEX = Trigger.create(false)
756
				
757
				static if thistype.onUnitIndex.exists then
758
					set onIndexExpression = Condition(function thistype.onIndexEvent)
759
					set onDeindexExpression = Condition(function thistype.onDeindexEvent)
760
					
761
					call UnitIndexList(ON_INDEX).clear()
762
					
763
					call TimerStart(CreateTimer(), 0, false, function thistype.destroyPregameUnitList)
764
					
765
					set entryPoint = UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onIndexEvent))
766
				else
767
					set ON_DEINDEX = Trigger.create(true)
768
					static if thistype.onUnitDeindex.exists then
769
						call ON_DEINDEX.register(Condition(function thistype.onDeindexEvent))
770
					endif
771
					
772
					call UnitIndexer.GlobalEvent.ON_DEINDEX.reference(ON_DEINDEX)
773
					call UnitIndexer.GlobalEvent.ON_INDEX.reference(ON_INDEX)
774
				endif
775
			endmethod
776
		endif
777
	endmodule
778
	
779
	//! textmacro CREATE_LOCAL_UNIT_INDEX
780
		/*
781
		*	There are three cases
782
		*
783
		*		Case 1: UnitIndex is implemented
784
		*		Case 2: UnitIndexEx is implemented
785
		*		Case 3: Nothing is implemented, go to Case 2
786
		*/
787
		static if thistype.UNIT_INDEX then
788
			/*
789
			*	Here, UnitIndex is implemented
790
			*/
791
			
792
			/*
793
			*	There are two cases
794
			*
795
			*		onUnitEvent exists, which means that events are conditionally local
796
			*		onUnitEven does not exist, meaning all events are global
797
			*/
798
			static if thistype.onUnitIndex.exists then
799
				/*
800
				*	Here, events are conditionally local
801
				*/
802
				
803
				static if thistype.onLocalUnitDeindex.exists then
804
					private static boolexpr onLocalUnitDeindexEventExpr
805
				endif
806
			
807
				static if thistype.onLocalUnitIndex.exists then
808
					/*
809
					*	The user has a local unit index event
810
					*/
811
					private static method onLocalUnitIndexEvent takes nothing returns boolean
812
						/*
813
						*	Here, the event is only run if the unit happened to be indexed
814
						*/
815
						if (thistype(UnitIndexer.eventIndex).isUnitIndexed) then
816
							static if thistype.onLocalUnitDeindex.exists then
817
								call UnitIndexer.eventIndex.indexer.Event.ON_DEINDEX.register(onLocalUnitDeindexEventExpr)
818
							endif
819
							
820
							call thistype(UnitIndexer.eventIndex).onLocalUnitIndex()
821
						endif
822
						
823
						return false
824
					endmethod
825
				elseif thistype.onLocalUnitDeindex.exists then
826
					/*
827
					*	The user did not declare a local unit index event
828
					*
829
					*	onLocalUnitIndexEvent is still required because the deindex events are local
830
					*/
831
					private static method onLocalUnitIndexEvent takes nothing returns boolean
832
						if (thistype(UnitIndexer.eventIndex).isUnitIndexed) then
833
							call UnitIndexer.eventIndex.indexer.Event.ON_DEINDEX.register(onLocalUnitDeindexEventExpr)
834
						endif
835
						
836
						return false
837
					endmethod
838
				endif
839
				
840
				static if thistype.onLocalUnitDeindex.exists then
841
					private static method onLocalUnitDeindexEvent takes nothing returns boolean
842
						call thistype(UnitIndexer.eventIndex).onLocalUnitDeindex()
843
						return false
844
					endmethod
845
				endif
846
				
847
				/*
848
				*	onLocalUnitDeindexEvent is not registered globally here because these are local
849
				*	events. It must be created inside of onLocalUnitIndexEvent whether or not
850
				*	onLocalUnitIndex exists.
851
				*/
852
				static if thistype.onLocalUnitIndex.exists then
853
					private static method onInit takes nothing returns nothing
854
						static if thistype.onLocalUnitDeindex.exists then
855
							set onLocalUnitDeindexEventExpr = Condition(function thistype.onLocalUnitDeindexEvent)
856
						endif
857
						
858
						call UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
859
						
860
						static if thistype.localInit.exists then
861
							call localInit()
862
						endif
863
					endmethod
864
				elseif thistype.onLocalUnitDeindex.exists then
865
					private static method onInit takes nothing returns nothing
866
						set onLocalUnitDeindexEventExpr = Condition(function thistype.onLocalUnitDeindexEvent)
867
							
868
						call UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
869
						
870
						static if thistype.localInit.exists then
871
							call localInit()
872
						endif
873
					endmethod
874
				endif
875
			else
876
				/*
877
				*	Here, all events are global
878
				*/
879
				static if thistype.onLocalUnitIndex.exists then
880
					private static method onLocalUnitIndexEvent takes nothing returns boolean
881
						call thistype(UnitIndexer.eventIndex).onLocalUnitIndex()
882
						return false
883
					endmethod
884
				endif
885
				
886
				static if thistype.onLocalUnitDeindex.exists then
887
					private static method onLocalUnitDeindexEvent takes nothing returns boolean
888
						call thistype(UnitIndexer.eventIndex).onLocalUnitDeindex()
889
						return false
890
					endmethod
891
				endif
892
				
893
				static if thistype.onLocalUnitIndex.exists then
894
					private static method onInit takes nothing returns nothing
895
						static if thistype.onLocalUnitDeindex.exists then
896
							call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function thistype.onLocalUnitDeindexEvent))
897
						endif
898
						
899
						call UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
900
						
901
						static if thistype.localInit.exists then
902
							call localInit()
903
						endif
904
					endmethod
905
				elseif thistype.onLocalUnitDeindex.exists then
906
					private static method onInit takes nothing returns nothing
907
						call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function thistype.onLocalUnitDeindexEvent))
908
						
909
						static if thistype.localInit.exists then
910
							call localInit()
911
						endif
912
					endmethod
913
				endif
914
			endif
915
		elseif thistype.GLOBAL_UNIT_INDEX then
916
			private static method error takes nothing returns nothing
917
				A module requires either UnitIndex or UnitIndexEx to operate correctly.
918
				This struct is currently implementing GlobalUnitIndex.
919
			endmethod
920
		else
921
			/*
922
			*	Here, UnitIndexEx is either implemented or nothing is implemented
923
			*
924
			*	Implement UnitIndexEx and work with its local events
925
			*/
926
			implement UnitIndexEx
927
			
928
			static if thistype.onUnitIndex.exists then
929
				/*
930
				*	local events
931
				*/
932
				static if thistype.onLocalUnitDeindex.exists then
933
					private static boolexpr onLocalUnitDeindexEventExpr
934
				endif
935
				
936
				/*
937
				*	if onUnitIndex exists, then onLocalUnitDeindex is local
938
				*
939
				*	this means that if onLocalUnitDeindex exists, the onLocalUnitIndexEvent must be
940
				*	made so that it can register onLocalUnitDeindex locally
941
				*/
942
				static if thistype.onLocalUnitIndex.exists then
943
					private static method onLocalUnitIndexEvent takes nothing returns boolean
944
						static if thistype.onLocalUnitDeindex.exists then
945
							call thistype(UnitIndexer.eventIndex).ON_DEINDEX.register(onLocalUnitDeindexEventExpr)
946
						endif
947
						
948
						call thistype(UnitIndexer.eventIndex).onLocalUnitIndex()
949
						
950
						return false
951
					endmethod
952
				elseif thistype.onLocalUnitDeindex.exists then
953
					private static method onLocalUnitIndexEvent takes nothing returns boolean
954
						call thistype(UnitIndexer.eventIndex).ON_DEINDEX.register(onLocalUnitDeindexEventExpr)
955
							
956
						return false
957
					endmethod
958
				endif
959
			elseif thistype.onLocalUnitIndex.exists then
960
				/*
961
				*	global events
962
				*
963
				*		onLocalUnitDeindex is run globally, so it doesn't need onLocalUnitIndexEvent
964
				*		anymore
965
				*/
966
				private static method onLocalUnitIndexEvent takes nothing returns boolean
967
					call thistype(UnitIndexer.eventIndex).onLocalUnitIndex()
968
					
969
					return false
970
				endmethod
971
			endif
972
			
973
			static if thistype.onLocalUnitDeindex.exists then
974
				private static method onLocalUnitDeindexEvent takes nothing returns boolean
975
					call thistype(UnitIndexer.eventIndex).onLocalUnitDeindex()
976
					
977
					return false
978
				endmethod
979
			endif
980
			
981
			/*
982
			*	The reason why ON_INDEX is used is so that the module can be enabled/disabled
983
			*	correctly
984
			*/
985
			private static method onInit takes nothing returns nothing
986
				static if thistype.onUnitIndex.exists then
987
					/*
988
					*	local events
989
					*/
990
					static if thistype.onLocalUnitDeindex.exists then
991
						set onLocalUnitDeindexEventExpr = Condition(function thistype.onLocalUnitDeindexEvent)
992
					endif
993
					
994
					/*
995
					*	onLocalUnitIndexEvent is registered for onLocalUnitdeindex because onLocalUnitDeindex
996
					*	must be registered to each unit. This means that it must register as units are indexed.
997
					*/
998
					static if thistype.onLocalUnitIndex.exists then
999
						call thistype.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
1000
					elseif thistype.onLocalUnitDeindex.exists then
1001
						call thistype.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
1002
					endif
1003
				else
1004
					/*
1005
					*	global events
1006
					*
1007
					*	ON_DEINDEX is used here instead of UnitIndexer.GlobalEvent.ON_DEINDEX for proper
1008
					*	execution order
1009
					*/
1010
					
1011
					static if thistype.onLocalUnitDeindex.exists then
1012
						call thistype.ON_DEINDEX.register(Condition(function thistype.onLocalUnitDeindexEvent))
1013
					endif
1014
					
1015
					static if thistype.onLocalUnitIndex.exists then
1016
						call thistype.ON_INDEX.register(Condition(function thistype.onLocalUnitIndexEvent))
1017
					endif
1018
				endif
1019
				
1020
				static if thistype.localInit.exists then
1021
					call localInit()
1022
				endif
1023
			endmethod
1024
		endif
1025
	//! endtextmacro
1026
endlibrary


UnitIndexer UnitIndex:
Code (jass) Select
1
/*
2
*	requires
3
*
4
*		Alloc
5
*		ErrorMessage
6
*
7
*		private struct p_UnitIndex extends array
8
*
9
*		method operator isAllocated takes nothing returns boolean
10
*		debug static method calculateMemoryUsage takes nothing returns integer
11
*		debug static method getAllocatedMemoryAsString takes nothing returns string
12
*
13
*		method operator indexer takes nothing returns UnitIndexer
14
*		method operator unit takes nothing returns unit
15
*		static method operator [] takes unit whichUnit returns thistype
16
*		static method exists takes unit whichUnit returns boolean
17
*
18
*	struct UnitIndex extends array
19
*
20
*		readonly unit unit
21
*		readonly UnitIndexer indexer
22
*
23
*		static method operator [] takes unit whichUnit returns UnitIndex
24
*
25
*		static method exists takes unit whichUnit returns boolean
26
*		static method isDeindexing takes unit whichUnit returns boolean
27
*/
28
29
//! textmacro UNIT_INDEXER_UNIT_INDEX
30
private struct p_UnitIndex extends array
31
	implement AllocQ
32
33
	private unit p_unit
34
	
35
	static method create takes unit whichUnit returns thistype
36
		local thistype this = allocate()
37
		
38
		set p_unit = whichUnit
39
		call SetUnitUserData(whichUnit, this)
40
41
		call UnitAddAbility(whichUnit, ABILITIES_UNIT_INDEXER)
42
		call UnitMakeAbilityPermanent(whichUnit, true, ABILITIES_UNIT_INDEXER)
43
		
44
		return this
45
	endmethod
46
	
47
	method destroy takes nothing returns nothing
48
		set p_unit = null
49
	
50
		call deallocate()
51
	endmethod
52
	
53
	method operator indexer takes nothing returns UnitIndexer
54
		debug call ThrowWarning(not isAllocated,											"UnitIndexer", "indexer", "thistype", this, "Getting indexer from a deallocated unit index.")
55
		
56
		return this
57
	endmethod
58
	
59
	method operator unit takes nothing returns unit
60
		debug call ThrowWarning(not isAllocated,											"UnitIndexer", "unit", "thistype", this, "Getting unit from a deallocated unit index.")
61
	
62
		return p_unit
63
	endmethod
64
	static method operator [] takes unit whichUnit returns thistype
65
		debug call ThrowWarning(GetUnitTypeId(whichUnit) == 0,								"UnitIndexer", "[]", "thistype", 0, "Getting unit index of a null unit.")
66
		debug call ThrowWarning(thistype(GetUnitUserData(whichUnit)).p_unit != whichUnit,	"UnitIndexer", "[]", "thistype", 0, "Getting unit index of a unit that isn't indexed.")
67
		
68
		return GetUnitUserData(whichUnit)
69
	endmethod
70
	
71
	static method exists takes unit whichUnit returns boolean
72
		debug call ThrowWarning(GetUnitTypeId(whichUnit) == 0, "UnitIndexer", "exists",		"thistype", 0, "Checking for the existence of a null unit.")
73
	
74
		return thistype(GetUnitUserData(whichUnit)).p_unit == whichUnit
75
	endmethod
76
	
77
	static method isDeindexing takes unit whichUnit returns boolean
78
		return GetUnitTypeId(whichUnit) != 0 and GetUnitAbilityLevel(whichUnit, ABILITIES_UNIT_INDEXER) == 0 and thistype(GetUnitUserData(whichUnit)).p_unit == whichUnit
79
	endmethod
80
endstruct
81
82
struct UnitIndex extends array
83
	method operator unit takes nothing returns unit
84
		return p_UnitIndex(this).unit
85
	endmethod
86
	
87
	static method operator [] takes unit whichUnit returns thistype
88
		return p_UnitIndex[whichUnit]
89
	endmethod
90
	
91
	static method exists takes unit whichUnit returns boolean
92
		return p_UnitIndex.exists(whichUnit)
93
	endmethod
94
	
95
	static method isDeindexing takes unit whichUnit returns boolean
96
		return p_UnitIndex.isDeindexing(whichUnit)
97
	endmethod
98
	
99
	method operator indexer takes nothing returns UnitIndexer
100
		return p_UnitIndex(this).indexer
101
	endmethod
102
endstruct
103
//! endtextmacro


UnitIndexer UnitIndexer:
Code (jass) Select
1
/*
2
*	requires
3
*
4
*		Event
5
*		WorldBounds
6
*
7
*	struct UnitIndexer extends array
8
*
9
*		static boolean enabled = true
10
*
11
*		readonly static Trigger GlobalEvent.ON_INDEX
12
*		readonly static Trigger GlobalEvent.ON_DEINDEX
13
*		readonly Trigger Event.ON_DEINDEX
14
*
15
*		readonly UnitIndex eventIndex = 0
16
*		readonly unit eventUnit = null
17
*
18
*	private struct WrappedTrigger extends array
19
*
20
*		method reference takes Trigger whichTrigger returns nothing
21
*
22
*		method register takes boolexpr whichExpression returns nothing
23
*
24
*/
25
26
//! textmacro UNIT_INDEXER_UNIT_INDEXER
27
private struct WrappedTrigger extends array
28
	static if DEBUG_MODE then
29
		method reference takes Trigger whichTrigger returns TriggerReference
30
			return reference_p(whichTrigger)
31
		endmethod
32
		
33
		method register takes boolexpr whichExpression returns TriggerCondition
34
			return register_p(whichExpression)
35
		endmethod
36
		
37
		private method reference_p takes Trigger whichTrigger returns TriggerReference
38
			local TriggerReference triggerReference = Trigger(this).reference(whichTrigger)
39
			
40
			call PreGameEvent.fireTrigger(whichTrigger)
41
			
42
			return triggerReference
43
		endmethod
44
	
45
		private method register_p takes boolexpr whichExpression returns TriggerCondition
46
			local TriggerCondition triggerCondition = Trigger(this).register(whichExpression)
47
			
48
			call PreGameEvent.fireExpression(whichExpression)
49
			
50
			return triggerCondition
51
		endmethod
52
	else
53
		method reference takes Trigger whichTrigger returns TriggerReference
54
			local TriggerReference triggerReference = Trigger(this).reference(whichTrigger)
55
			
56
			call PreGameEvent.fireTrigger(whichTrigger)
57
			
58
			return triggerReference
59
		endmethod
60
	
61
		method register takes boolexpr whichExpression returns TriggerCondition
62
			local TriggerCondition triggerCondition = Trigger(this).register(whichExpression)
63
			
64
			call PreGameEvent.fireExpression(whichExpression)
65
			
66
			return triggerCondition
67
		endmethod
68
	endif
69
endstruct
70
71
private struct UnitIndexerTriggerGlobal extends array
72
	readonly static WrappedTrigger	ON_INDEX
73
	readonly static Trigger			ON_DEINDEX
74
	
75
	private static method init takes nothing returns nothing
76
		set ON_INDEX = Trigger.create(false)
77
		set ON_DEINDEX = Trigger.create(true)
78
	endmethod
79
	
80
	implement Init
81
endstruct
82
83
private keyword ON_DEINDEX_MAIN
84
private struct UnitIndexerTrigger extends array
85
	readonly Trigger ON_DEINDEX
86
	
87
	method createDeindex takes nothing returns nothing
88
		set ON_DEINDEX = Trigger.create(true)
89
		
90
		call ON_DEINDEX.reference(UnitIndexerTriggerGlobal.ON_DEINDEX)
91
	endmethod
92
	
93
	method destroyDeindex takes nothing returns nothing
94
		call ON_DEINDEX.destroy()
95
	endmethod
96
endstruct
97
98
struct UnitIndexer extends array
99
	private trigger deindexTrigger
100
	private static boolexpr onDeindexCondition
101
102
	static method operator eventIndex takes nothing returns UnitIndex
103
		return p_eventIndex
104
	endmethod
105
	static method operator eventUnit takes nothing returns unit
106
		return eventIndex.unit
107
	endmethod
108
	
109
	static method operator GlobalEvent takes nothing returns UnitIndexerTriggerGlobal
110
		return 0
111
	endmethod
112
	method operator Event takes nothing returns UnitIndexerTrigger
113
		return this
114
	endmethod
115
116
	static boolean enabled = true
117
	
118
	private static method fire takes Trigger whichTrigger, integer whichIndex returns nothing
119
		local integer prevIndexedUnit = p_eventIndex
120
		set p_eventIndex = whichIndex
121
		call whichTrigger.fire()
122
		set p_eventIndex = prevIndexedUnit
123
	endmethod
124
	
125
	private static method onIndex takes nothing returns boolean
126
		local unit indexedUnit = GetFilterUnit()
127
		local p_UnitIndex index
128
		
129
		if (enabled and not p_UnitIndex.exists(indexedUnit)) then
130
			set index = p_UnitIndex.create(indexedUnit)
131
			
132
			set thistype(index).deindexTrigger = CreateTrigger()
133
			call TriggerRegisterUnitEvent(thistype(index).deindexTrigger, indexedUnit, EVENT_UNIT_ISSUED_ORDER)
134
			call TriggerAddCondition(thistype(index).deindexTrigger, onDeindexCondition)
135
			
136
			call PreGameEvent.addUnitIndex(index)
137
			
138
			call thistype(index).Event.createDeindex()
139
			
140
			call fire(GlobalEvent.ON_INDEX, index)
141
		endif
142
		
143
		set indexedUnit = null
144
		
145
		return false
146
	endmethod
147
	
148
	private static method onDeindex takes nothing returns boolean
149
		local p_UnitIndex index = GetUnitUserData(GetTriggerUnit())
150
		
151
		if (GetUnitAbilityLevel(GetTriggerUnit(), ABILITIES_UNIT_INDEXER) == 0) then
152
			call PreGameEvent.removeUnitIndex(index)
153
			
154
			call fire(thistype(index).Event.ON_DEINDEX, index)
155
			
156
			call thistype(index).Event.destroyDeindex()
157
			
158
			call DestroyTrigger(thistype(index).deindexTrigger)
159
			set thistype(index).deindexTrigger = null
160
			
161
			call index.destroy()
162
		endif
163
		
164
		return false
165
	endmethod
166
	
167
	private static method init takes nothing returns nothing
168
		local trigger indexTrigger = CreateTrigger()
169
		
170
		local boolexpr onIndexCondition	 = Condition(function thistype.onIndex)
171
		
172
		local group enumGroup = CreateGroup()
173
		
174
		local integer currentPlayerId = 15
175
		local player currentPlayer
176
		
177
		set onDeindexCondition= Condition(function thistype.onDeindex)
178
		
179
		call TriggerRegisterEnterRegion(indexTrigger, WorldBounds.worldRegion, onIndexCondition)
180
		
181
		loop
182
			set currentPlayer = Player(currentPlayerId)
183
			
184
			call SetPlayerAbilityAvailable(currentPlayer, ABILITIES_UNIT_INDEXER, false)
185
			call GroupEnumUnitsOfPlayer(enumGroup, currentPlayer, onIndexCondition)
186
			
187
			exitwhen currentPlayerId == 0
188
			set currentPlayerId = currentPlayerId - 1
189
		endloop
190
		
191
		call DestroyGroup(enumGroup)
192
		
193
		set onIndexCondition = null
194
		
195
		set enumGroup = null
196
		set currentPlayer = null
197
		
198
		set indexTrigger = null
199
	endmethod
200
	
201
	implement Init
202
endstruct
203
//! endtextmacro


UnitIndexer Pregame Event:
Code (jass) Select
1
/*
2
*	requires
3
*
4
*		StaticUniqueList
5
*
6
*	private struct PreGameEvent extends array
7
*
8
*		Evaluates all triggers and functions registered to
9
*		Unit Indexer before game start for all indexed units.
10
*
11
*
12
*		static method fireTrigger takes trigger whichTrigger returns nothing
13
*		static method fireExpression takes boolexpr whichExpression returns nothing
14
*
15
*		static method addUnitIndex takes integer whichUnitIndex returns nothing
16
*		static method removeUnitIndex takes integer whichUnitIndex returns nothing
17
*/
18
19
//! textmacro UNIT_INDEXER_PREGAME_EVENT
20
private struct PreGameEvent extends array
21
	readonly static boolean isGameLoaded = false
22
23
	implement StaticUniqueList
24
	
25
	private static method p_fireTrigger takes Trigger whichTrigger returns nothing
26
		local thistype this = first
27
		local integer prevIndexedUnitId = p_eventIndex
28
		
29
		loop
30
			exitwhen this == sentinel or not whichTrigger.enabled
31
			
32
			set p_eventIndex = this
33
			call whichTrigger.fire()
34
			
35
			set this = next
36
		endloop
37
		
38
		set p_eventIndex = prevIndexedUnitId
39
	endmethod
40
	static method fireTrigger takes Trigger whichTrigger returns nothing
41
		if (first != 0) then
42
			call p_fireTrigger(whichTrigger)
43
		endif
44
	endmethod
45
	
46
	private static method p_fireExpression takes boolexpr whichExpression returns nothing
47
		local trigger triggerContainer = CreateTrigger()
48
		local thistype this = first
49
		local integer prevIndexedUnitId = p_eventIndex
50
		
51
		call TriggerAddCondition(triggerContainer, whichExpression)
52
		
53
		loop
54
			exitwhen this == sentinel
55
			
56
			set p_eventIndex = this
57
			call TriggerEvaluate(triggerContainer)
58
			
59
			set this = next
60
		endloop
61
		
62
		call TriggerClearConditions(triggerContainer)
63
		call DestroyTrigger(triggerContainer)
64
		set triggerContainer = null
65
		
66
		set p_eventIndex = prevIndexedUnitId
67
	endmethod
68
	static method fireExpression takes boolexpr whichExpression returns nothing
69
		if (first != 0) then
70
			call p_fireExpression(whichExpression)
71
		endif
72
	endmethod
73
	
74
	static method addUnitIndex takes integer whichUnitIndex returns nothing
75
		if (isGameLoaded) then
76
			return
77
		endif
78
		
79
		call enqueue(whichUnitIndex)
80
	endmethod
81
	
82
	static method removeUnitIndex takes integer whichUnitIndex returns nothing
83
		if (isGameLoaded) then
84
			return
85
		endif
86
		
87
		call thistype(whichUnitIndex).remove()
88
	endmethod
89
	
90
	private static method run takes nothing returns nothing
91
		call DestroyTimer(GetExpiredTimer())
92
		
93
		set isGameLoaded = true
94
		
95
		call clear()
96
	endmethod
97
	private static method init takes nothing returns nothing
98
		call TimerStart(CreateTimer(), 0, false, function thistype.run)
99
	endmethod
100
	
101
	implement Init
102
endstruct
103
//! endtextmacro


For further information related with installation and usage, please refer to the test map attached to this topic.
  • Unit Indexer.w3x (122.31 KB)
  • UnitIndexer.jpg (248.05 KB)