-
Notifications
You must be signed in to change notification settings - Fork 285
Expand file tree
/
Copy pathUnit.h
More file actions
2604 lines (2323 loc) · 128 KB
/
Copy pathUnit.h
File metadata and controls
2604 lines (2323 loc) · 128 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#pragma once
#include <BWAPI/Client/UnitData.h>
#include <BWAPI/Position.h>
#include <BWAPI/UnitType.h>
#include <BWAPI/Filters.h>
#include <BWAPI/Player.h>
namespace BWAPI
{
// Forwards
class Order;
class TechType;
class UpgradeType;
class Region;
class UnitCommand;
class UnitCommandType;
class Unitset;
class WeaponType;
class Game;
/// <summary>The Unit class is used to get information about individual units as well as issue
/// orders to units.</summary> Each unit in the game has a unique Unit object, and Unit objects
/// are not deleted until the end of the match (so you don't need to worry about unit pointers
/// becoming invalid).
///
/// Every Unit in the game is either accessible or inaccessible. To determine if an AI can access
/// a particular unit, BWAPI checks to see if Flag::CompleteMapInformation is enabled. So there
/// are two cases to consider - either the flag is enabled, or it is disabled:
///
/// If Flag::CompleteMapInformation is disabled, then a unit is accessible if and only if it is visible.
/// @note Some properties of visible enemy units will not be made available to the AI (such as the
/// contents of visible enemy dropships). If a unit is not visible, Unit::exists will return false,
/// regardless of whether or not the unit exists. This is because absolutely no state information on
/// invisible enemy units is made available to the AI. To determine if an enemy unit has been destroyed, the
/// AI must watch for AIModule::onUnitDestroy messages from BWAPI, which is only called for visible units
/// which get destroyed.
///
/// If Flag::CompleteMapInformation is enabled, then all units that exist in the game are accessible, and
/// Unit::exists is accurate for all units. Similarly AIModule::onUnitDestroy messages are generated for all
/// units that get destroyed, not just visible ones.
///
/// If a Unit is not accessible, then only the getInitial__ functions will be available to the AI.
/// However for units that were owned by the player, getPlayer and getType will continue to work for units
/// that have been destroyed.
///
/// @ingroup Interface
class Unit : public InterfaceDataWrapper<Unit, UnitData> {
public:
using InterfaceDataWrapper<Unit, UnitData>::InterfaceDataWrapper;
/// <summary>Checks if the Unit exists in the view of the BWAPI player.</summary>
///
/// This is used primarily to check if BWAPI has access to a specific unit, or if the
/// unit is alive. This function is more general and would be synonymous to an isAlive
/// function if such a function were necessary.
///
/// @retval true If the unit exists on the map and is visible according to BWAPI.
/// @retval false If the unit is not accessible or the unit is dead.
///
/// In the event that this function returns false, there are two cases to consider:
/// 1. You own the unit. This means the unit is dead.
/// 2. Another player owns the unit. This could either mean that you don't have access
/// to the unit or that the unit has died. You can specifically identify dead units
/// by polling onUnitDestroy.
///
/// @see isVisible, isCompleted
bool exists() const { return *this && getData().exists; }
/// <summary>Retrieves the unit identifier for this unit as seen in replay data.</summary>
///
/// @note This is only available if Flag::CompleteMapInformation is enabled.
///
/// @returns An integer containing the replay unit identifier.
///
/// @see getID
UnitID getReplayID() const { return getData().replayID; }
/// <summary>Retrieves the player that owns this unit.</summary>
///
/// @retval Game::neutral() If the unit is a neutral unit or inaccessible.
///
/// @returns The owning Player interface object.
Player getPlayer() const;
/// <summary>Retrieves the unit's type.</summary>
///
/// @retval UnitTypes::Unknown if this unit is inaccessible or cannot be determined.
/// @returns A UnitType objects representing the unit's type.
///
/// @see getInitialType
UnitType getType() const { return getData().type; }
/// <summary>Retrieves the unit's position from the upper left corner of the map in pixels.
/// </summary> The position returned is roughly the center if the unit.
///
/// @note The unit bounds are defined as this value plus/minus the values of
/// UnitType::dimensionLeft, UnitType::dimensionUp, UnitType::dimensionRight,
/// and UnitType::dimensionDown, which is conveniently expressed in Unit::getLeft,
/// Unit::getTop, Unit::getRight, and Unit::getBottom respectively.
///
/// @retval Positions::Unknown if this unit is inaccessible.
///
/// @returns Position object representing the unit's current position.
///
/// @see getTilePosition, getWalkPosition, getInitialPosition, getLeft, getTop
Position getPosition() const { return { getData().position }; }
/// <summary>Retrieves the unit's build position from the upper left corner of the map in
/// tiles.</summary>
///
/// @note: This tile position is the tile that is at the top left corner of the structure.
///
/// @retval TilePositions::Unknown if this unit is inaccessible.
///
/// @returns TilePosition object representing the unit's current tile position.
///
/// @see getPosition, getWalkPosition, getInitialTilePosition
TilePosition getTilePosition() const {
return TilePosition{getPosition() - Position{getType().tileSize()} / 2};
}
/// <summary>Retrieves the unit's facing direction in radians.</summary>
///
/// @note A value of 0.0 means the unit is facing east.
///
/// @returns A double with the angle measure in radians.
double getAngle() const { return getData().angle; }
/// <summary>Retrieves the x component of the unit's velocity, measured in pixels per frame.</summary>
///
/// @returns A double that represents the velocity's x component.
///
/// @see getVelocityY
double getVelocityX() const { return getData().velocityX; };
/// <summary>Retrieves the y component of the unit's velocity, measured in pixels per frame.</summary>
///
/// @returns A double that represents the velocity's y component.
///
/// @see getVelocityX
double getVelocityY() const { return getData().velocityY; };
/// <summary>Retrieves the Region that the center of the unit is in.</summary>
///
/// @retval nullptr If the unit is inaccessible.
///
/// @returns The Region object that contains this unit.
///
/// Example
/// @code{.cpp}
/// for ( BWAPI::Unit u : game.self().getUnits() )
/// {
/// if ( u.isFlying() && u.isUnderAttack() ) // implies exists and isCompleted
/// {
/// BWAPI::Region r = u.getRegion();
/// if ( r )
/// u.move(r.getClosestInaccessibleRegion()); // Retreat to inaccessible region
/// }
/// }
/// @endcode
/// @implies exists
BWAPI::Region getRegion() const;
/// <summary>Retrieves the X coordinate of the unit's left boundary, measured in pixels from
/// the left side of the map.</summary>
///
/// @returns An integer representing the position of the left side of the unit.
///
/// @see getTop, getRight, getBottom
int getLeft() const {
auto const &data = getData();
return data.position.x - data.type.dimensionLeft();
}
/// <summary>Retrieves the Y coordinate of the unit's top boundary, measured in pixels from
/// the top of the map.</summary>
///
/// @returns An integer representing the position of the top side of the unit.
///
/// @see getLeft, getRight, getBottom
int getTop() const {
auto const &data = getData();
return data.position.y - data.type.dimensionUp();
}
/// <summary>Retrieves the X coordinate of the unit's right boundary, measured in pixels from
/// the left side of the map.</summary>
///
/// @returns An integer representing the position of the right side of the unit.
///
/// @see getLeft, getTop, getBottom
int getRight() const {
auto const &data = getData();
return data.position.x + data.type.dimensionRight();
}
/// <summary>Retrieves the Y coordinate of the unit's bottom boundary, measured in pixels from
/// the top of the map.</summary>
///
/// @returns An integer representing the position of the bottom side of the unit.
///
/// @see getLeft, getTop, getRight
int getBottom() const {
auto const &data = getData();
return data.position.y + data.type.dimensionDown();
}
/// <summary>Retrieves the unit's current Hit Points (HP) as seen in the game.</summary>
///
/// @returns An integer representing the amount of hit points a unit currently has.
///
/// @note In Starcraft, a unit usually dies when its HP reaches 0. It is possible however, to
/// have abnormal HP values in the Use Map Settings game type and as the result of a hack over
/// Battle.net. Such values include units that have 0 HP (can't be killed conventionally)
/// or even negative HP (death in one hit).
///
/// @see UnitType::maxHitPoints, getShields, getInitialHitPoints
int getHitPoints() const { return getData().hitPoints; }
/// <summary>Retrieves the unit's current Shield Points (Shields) as seen in the game.</summary>
///
/// @returns An integer representing the amount of shield points a unit currently has.
///
/// @see UnitType::maxShields, getHitPoints
int getShields() const { return getData().shields; }
/// <summary>Retrieves the unit's current Energy Points (Energy) as seen in the game.</summary>
///
/// @returns An integer representing the amount of energy points a unit currently has.
///
/// @note Energy is required in order for units to use abilities.
///
/// @see UnitType::maxEnergy
int getEnergy() const { return getData().energy; }
/// <summary>Retrieves the resource amount from a resource container, such as a Mineral Field
/// and Vespene Geyser.</summary> If the unit is inaccessible, then the last known resource
/// amount is returned.
///
/// @returns An integer representing the last known amount of resources remaining in this
/// resource.
///
/// @see getInitialResources
int getResources() const { return getData().resources; }
/// <summary>Retrieves a grouping index from a resource container.</summary> Other resource
/// containers of the same value are considered part of one expansion location (group of
/// resources that are close together).
///
/// @note This grouping method is explicitly determined by Starcraft itself and is used only
/// by the internal AI.
///
/// @returns An integer with an identifier between 0 and 250 that determine which resources
/// are grouped together to form an expansion.
int getResourceGroup() const { return getData().resourceGroup; }
/// <summary>Retrieves the distance between this unit and a target position.</summary>
///
/// @note Distance is calculated from the edge of this unit, using Starcraft's own distance
/// algorithm. Ignores collisions.
///
/// <param name="target">
/// A Position to calculate the distance to.
/// </param>
///
/// @returns An integer representation of the number of pixels between this unit and the
/// \p target.
int getDistance(Position target) const;
/// <summary>Retrieves the distance between this unit and a target unit.</summary>
///
/// @note Distance is calculated from the edge of this unit, using Starcraft's own distance
/// algorithm. Ignores collisions.
///
/// <param name="target">
/// A Unit to calculate the distance to. Calculate the distance to the edge of the target unit.
/// </param>
///
/// @returns An integer representation of the number of pixels between this unit and the
/// \p target.
int getDistance(Unit target) const;
/// <summary>Using data provided by Starcraft, checks if there is a path available from this
/// unit to the given target.</summary>
///
/// @note This function only takes into account the terrain data, and does not include
/// buildings when determining if a path is available. However, the complexity of this
/// function is constant ( O(1) ), and no extensive calculations are necessary.
///
/// @note If the current unit is an air unit, then this function will always return true.
///
/// @note If the unit somehow gets stuck in unwalkable terrain, then this function may still
/// return true if one of the unit's corners is on walkable terrain (i.e. if the unit is expected
/// to return to the walkable terrain).
///
/// <param name="target">
/// A Position or a Unit that is used to determine if this unit has a path to the target.
/// </param>
///
/// @returns true If there is a path between this unit and the target position, otherwise it will return false.
/// @see Game::hasPath
bool hasPath(Position target) const;
/// <summary>Using data provided by Starcraft, checks if there is a path available from this
/// unit to the given target.</summary>
///
/// @note This function only takes into account the terrain data, and does not include
/// buildings when determining if a path is available. However, the complexity of this
/// function is constant ( O(1) ), and no extensive calculations are necessary.
///
/// @note If the current unit is an air unit, then this function will always return true.
///
/// <param name="target">
/// A Position or a Unit that is used to determine if this unit has a path to the target.
/// </param>
///
/// @retval true If there is a path between this unit and the target.
/// @retval false If the target is on a different piece of land than this one (such as an
/// island).
bool hasPath(Unit target) const;
/// <summary>Retrieves the frame number that sent the last successful command.</summary>
///
/// @note This value is comparable to Game::getFrameCount.
///
/// @returns The frame number that sent the last successfully processed command to BWAPI.
/// @see Game::getFrameCount, getLastCommand
int getLastCommandFrame() const { return getData().lastCommandFrame; }
/// <summary>Retrieves the last successful command that was sent to BWAPI.</summary>
///
/// @returns A UnitCommand object containing information about the command that was processed.
/// @see getLastCommandFrame
UnitCommand getLastCommand() const;
/// <summary>Retrieves the initial type of the unit.</summary> This is the type that the unit
/// starts as in the beginning of the game. This is used to access the types of static neutral
/// units such as mineral fields when they are not visible.
///
/// @returns UnitType of this unit as it was when it was created.
/// @retval UnitTypes::Unknown if this unit was not a static neutral unit in the beginning of
/// the game.
UnitType getInitialType() const { return getData().type; }
/// <summary>Retrieves the initial position of this unit.</summary> This is the position that
/// the unit starts at in the beginning of the game. This is used to access the positions of
/// static neutral units such as mineral fields when they are not visible.
///
/// @returns Position indicating the unit's initial position when it was created.
/// @retval Positions::Unknown if this unit was not a static neutral unit in the beginning of
/// the game.
Position getInitialPosition() const { return getData().position; }
/// <summary>Retrieves the initial build tile position of this unit.</summary> This is the tile
/// position that the unit starts at in the beginning of the game. This is used to access the
/// tile positions of static neutral units such as mineral fields when they are not visible.
/// The build tile position corresponds to the upper left corner of the unit.
///
/// @returns TilePosition indicating the unit's initial tile position when it was created.
/// @retval TilePositions::Unknown if this unit was not a static neutral unit in the beginning of
/// the game.
TilePosition getInitialTilePosition() const { return TilePosition(getInitialPosition() - Position{ getInitialType().tileSize() } / 2); }
/// <summary>Retrieves the amount of hit points that this unit started off with at the
/// beginning of the game.</summary> The unit must be neutral.
///
/// @returns Number of hit points that this unit started with.
/// @retval 0 if this unit was not a neutral unit at the beginning of the game.
///
/// @note: It is possible for the unit's initial hit points to differ from the maximum hit
/// points.
///
/// @see Game::getStaticNeutralUnits
int getInitialHitPoints() const { return getData().hitPoints; }
/// <summary>Retrieves the amount of resources contained in the unit at the beginning of the
/// game.</summary> The unit must be a neutral resource container.
///
/// @returns Amount of resources that this unit started with.
/// @retval 0 if this unit was not a neutral unit at the beginning of the game, or if this
/// unit does not contain resources. It is possible that the unit simply contains 0 resources.
///
/// @see Game::getStaticNeutralUnits
int getInitialResources() const { return getData().resources; };
/// <summary>Retrieves the number of units that this unit has killed in total.</summary>
///
/// @note The maximum amount of recorded kills per unit is 255.
///
/// @returns integer indicating this unit's kill count.
int getKillCount() const { return getData().killCount; }
/// <summary>Retrieves the number of acid spores that this unit is inflicted with.</summary>
///
/// @returns Number of acid spores on this unit.
int getAcidSporeCount() const { return getData().acidSporeCount; }
/// <summary>Retrieves the number of interceptors that this unit manages.</summary> This
/// function is only for the @Carrier and its hero.
///
/// @note This number may differ from the number of units returned from #getInterceptors. This
/// occurs for cases in which you can see the number of enemy interceptors in the Carrier HUD,
/// but don't actually have access to the individual interceptors.
///
/// @returns Number of interceptors in this unit.
/// @see getInterceptors
int getInterceptorCount() const { return getData().interceptorCount; }
/// <summary>Retrieves the number of scarabs that this unit has for use.</summary> This
/// function is only for the @Reaver.
///
/// @returns Number of scarabs this unit has ready.
int getScarabCount() const { return getData().scarabCount; }
/// <summary>Retrieves the amount of @mines this unit has available.</summary> This function
/// is only for the @Vulture.
///
/// @returns Number of spider mines available for placement.
int getSpiderMineCount() const { return getData().spiderMineCount; }
/// <summary>Retrieves the unit's ground weapon cooldown.</summary> This value decreases every
/// frame, until it reaches 0. When the value is 0, this indicates that the unit is capable of
/// using its ground weapon, otherwise it must wait until it reaches 0.
///
/// @note This value will vary, because Starcraft adds an additional random value between
/// (-1) and (+2) to the unit's weapon cooldown.
///
/// @returns Number of frames needed for the unit's ground weapon to become available again.
int getGroundWeaponCooldown() const { return getData().groundWeaponCooldown; }
/// <summary>Retrieves the unit's air weapon cooldown.</summary> This value decreases every
/// frame, until it reaches 0. When the value is 0, this indicates that the unit is capable of
/// using its air weapon, otherwise it must wait until it reaches 0.
///
/// @note This value will vary, because Starcraft adds an additional random value between
/// (-1) and (+2) to the unit's weapon cooldown.
///
/// @returns Number of frames needed for the unit's air weapon to become available again.
int getAirWeaponCooldown() const { return getData().airWeaponCooldown; }
/// <summary>Retrieves the unit's ability cooldown.</summary> This value decreases every frame,
/// until it reaches 0. When the value is 0, this indicates that the unit is capable of using
/// one of its special abilities, otherwise it must wait until it reaches 0.
///
/// @note This value will vary, because Starcraft adds an additional random value between
/// (-1) and (+2) to the unit's ability cooldown.
///
/// @returns Number of frames needed for the unit's abilities to become available again.
int getSpellCooldown() const { return getData().spellCooldown; }
/// <summary>Retrieves the amount of hit points remaining on the @matrix created by a
/// @Science_Vessel.</summary> The @matrix ability starts with 250 hit points when it is used.
///
/// @returns Number of hit points remaining on this unit's @matrix.
///
/// @see getDefenseMatrixTimer, isDefenseMatrixed
int getDefenseMatrixPoints() const { return getData().defenseMatrixPoints; }
/// <summary>Retrieves the time, in frames, that the @matrix will remain active on the current
/// unit.</summary>
///
/// @returns Number of frames remaining until the effect is removed.
///
/// @see getDefenseMatrixPoints, isDefenseMatrixed
int getDefenseMatrixTimer() const { return getData().defenseMatrixTimer; }
/// <summary>Retrieves the time, in frames, that @ensnare will remain active on the current
/// unit.</summary>
///
/// @returns Number of frames remaining until the effect is removed.
///
/// @see isEnsnared
int getEnsnareTimer() const { return getData().ensnareTimer; }
/// <summary>Retrieves the time, in frames, that @irradiate will remain active on the current
/// unit.</summary>
///
/// @returns Number of frames remaining until the effect is removed.
///
/// @see isIrradiated
int getIrradiateTimer() const { return getData().irradiateTimer; }
/// <summary>Retrieves the time, in frames, that @lockdown will remain active on the current
/// unit.</summary>
///
/// @returns Number of frames remaining until the effect is removed.
///
/// @see isLockedDown
int getLockdownTimer() const { return getData().lockdownTimer; }
/// <summary>Retrieves the time, in frames, that @maelstrom will remain active on the current
/// unit.</summary>
///
/// @returns Number of frames remaining until the effect is removed.
///
/// @see isMaelstrommed
int getMaelstromTimer() const { return getData().maelstromTimer; }
/// <summary>Retrieves an internal timer used for the primary order.</summary> Its use is
/// specific to the order type that is currently assigned to the unit.
///
/// @returns A value used as a timer for the primary order.
/// @see getOrder
int getOrderTimer() const { return getData().orderTimer; }
/// <summary>Retrieves the time, in frames, that @plague will remain active on the current
/// unit.</summary>
///
/// @returns Number of frames remaining until the effect is removed.
///
/// @see isPlagued
int getPlagueTimer() const { return getData().plagueTimer; }
/// <summary>Retrieves the time, in frames, until this temporary unit is destroyed or
/// removed.</summary> This is used to determine the remaining time for the following units
/// that were created by abilities:
/// - @hallucination
/// - @broodling
/// - @swarm
/// - @dweb
/// - @scanner
/// .
/// Once this value reaches 0, the unit is destroyed.
int getRemoveTimer() const { return getData().removeTimer; }
/// <summary>Retrieves the time, in frames, that @stasis will remain active on the current
/// unit.</summary>
///
/// @returns Number of frames remaining until the effect is removed.
///
/// @see isPlagued
int getStasisTimer() const { return getData().stasisTimer; }
/// <summary>Retrieves the time, in frames, that @stim will remain active on the current
/// unit.</summary>
///
/// @returns Number of frames remaining until the effect is removed.
///
/// @see isPlagued
int getStimTimer() const { return getData().stimTimer; }
/// <summary>Retrieves the building type that a @worker is about to construct.</summary> If
/// the unit is morphing or is an incomplete structure, then this returns the UnitType that it
/// will become when it has completed morphing/constructing.
///
/// @returns UnitType indicating the type that a @worker is about to construct, or an
/// incomplete unit will be when completed.
UnitType getBuildType() const { return getData().buildType; }
/// <summary>Retrieves the list of units queued up to be trained.</summary>
///
/// @returns a UnitType::list containing all the types that are in this factory's training
/// queue, from oldest to most recent.
/// @see train, cancelTrain, isTraining
UnitType::list getTrainingQueue() const {
return {
getData().trainingQueue.begin(),
getData().trainingQueue.end()
};
}
/// <summary>Retrieves the technology that this unit is currently researching.</summary>
///
/// @returns TechType indicating the technology being researched by this unit.
/// @retval TechTypes::None if this unit is not researching anything.
///
/// @see research, cancelResearch, isResearching, getRemainingResearchTime
TechType getTech() const { return getData().tech; }
/// <summary>Retrieves the upgrade that this unit is currently upgrading.</summary>
///
/// @return UpgradeType indicating the upgrade in progress by this unit.
/// @retval UpgradeTypes::None if this unit is not upgrading anything.
///
/// @see upgrade, cancelUpgrade, isUpgrading, getRemainingUpgradeTime
UpgradeType getUpgrade() const { return getData().upgrade; }
/// <summary>Retrieves the remaining build time for a unit or structure that is being trained
/// or constructed.</summary>
///
/// @returns Number of frames remaining until the unit's completion.
int getRemainingBuildTime() const { return getData().remainingBuildTime; }
/// <summary>Retrieves the remaining time, in frames, of the unit that is currently being
/// trained.</summary>
///
/// @note If the unit is a @Hatchery, @Lair, or @Hive, this retrieves the amount of time until
/// the next larva spawns.
///
/// @returns Number of frames remaining until the current training unit becomes completed, or
/// the number of frames remaining until the next larva spawns.
/// @retval 0 If the unit is not training or has three larvae.
/// @see train, getTrainingQueue
int getRemainingTrainTime() const { return getData().remainingTrainTime; }
/// <summary>Retrieves the amount of time until the unit is done researching its currently
/// assigned TechType.</summary>
///
/// @returns The remaining research time, in frames, for the current technology being
/// researched by this unit.
/// @retval 0 If the unit is not researching anything.
///
/// @see research, cancelResearch, isResearching, getTech
int getRemainingResearchTime() const { return getData().remainingResearchTime; }
/// <summary>Retrieves the amount of time until the unit is done upgrading its current upgrade.</summary>
///
/// @returns The remaining upgrade time, in frames, for the current upgrade.
/// @retval 0 If the unit is not upgrading anything.
///
/// @see upgrade, cancelUpgrade, isUpgrading, getUpgrade
int getRemainingUpgradeTime() const { return getData().remainingUpgradeTime; }
/// <summary>Retrieves the unit currently being trained, or the corresponding paired unit for
/// @SCVs and @Terran structures, depending on the context.</summary>
/// For example, if this unit is a @Factory under construction, this function will return the
/// @SCV that is constructing it. If this unit is a @SCV, then it will return the structure it
/// is currently constructing. If this unit is a @Nexus, and it is training a @Probe, then the
/// probe will be returned.
///
/// @bug This will return an incorrect unit when called on @Reavers.
///
/// @returns Paired build unit that is either constructing this unit, structure being constructed by
/// this unit, or the unit that is being trained by this structure.
/// @retval nullptr If there is no unit constructing this one, or this unit is not constructing
/// another unit.
Unit getBuildUnit() const;
/// <summary>Generally returns the appropriate target unit after issuing an order that accepts
/// a target unit (i.e. attack, repair, gather, etc.).</summary> To get a target that has been
/// acquired automatically without issuing an order, use getOrderTarget.
///
/// @returns Unit that is currently being targeted by this unit.
/// @see getOrderTarget
Unit getTarget() const;
/// <summary>Retrieves the target position the unit is moving to, provided a valid path to the
/// target position exists.</summary>
///
/// @returns Target position of a movement action.
Position getTargetPosition() const { return getData().targetPosition; }
/// <summary>Retrieves the primary Order that the unit is assigned.</summary> Primary orders
/// are distinct actions such as Orders::AttackUnit and Orders::PlayerGuard.
///
/// @returns The primary Order that the unit is executing.
Order getOrder() const { return getData().order; }
/// <summary>Retrieves the secondary Order that the unit is assigned.</summary> Secondary
/// orders are run in the background as a sub-order. An example would be Orders::TrainFighter,
/// because a @Carrier can move and train fighters at the same time.
///
/// @returns The secondary Order that the unit is executing.
Order getSecondaryOrder() const { return getData().secondaryOrder; }
/// <summary>Retrieves the unit's primary order target.</summary> This is usually set when the
/// low level unit AI acquires a new target automatically. For example if an enemy @Probe
/// comes in range of your @Marine, the @Marine will start attacking it, and getOrderTarget
/// will be set in this case, but not getTarget.
///
/// @returns The Unit that this unit is currently targetting.
/// @see getTarget, getOrder
Unit getOrderTarget() const;
/// <summary>Retrieves the target position for the unit's order.</summary> For example, when
/// Orders::Move is assigned, getTargetPosition returns the end of the unit's path, but this
/// returns the location that the unit is trying to move to.
///
/// @returns Position that this unit is currently targetting.
/// @see getTargetPosition, getOrder
Position getOrderTargetPosition() const { return getData().orderTargetPosition; }
/// <summary>Retrieves the position the structure is rallying units to once they are
/// completed.</summary>
///
/// @returns Position that a completed unit coming from this structure will travel to.
/// @retval Positions::None If this building does not produce units.
///
/// @note If getRallyUnit is valid, then this value is ignored.
///
/// @see setRallyPoint, getRallyUnit
Position getRallyPosition() const { return getData().rallyPosition; }
/// <summary>Retrieves the unit the structure is rallying units to once they are completed.</summary>
/// Units will then follow the targetted unit.
///
/// @returns Unit that a completed unit coming from this structure will travel to.
/// @retval nullptr If the structure is not rallied to a unit or it does not produce units.
///
/// @note A rallied unit takes precedence over a rallied position. That is if the return value
/// is valid(non-null), then getRallyPosition is ignored.
///
/// @see setRallyPoint, getRallyPosition
Unit getRallyUnit() const;
/// <summary>Retrieves the add-on that is attached to this unit.</summary>
///
/// @returns Unit interface that represents the add-on that is attached to this unit.
/// @retval nullptr if this unit does not have an add-on.
Unit getAddon() const;
/// <summary>Retrieves the @Nydus_Canal that is attached to this one.</summary> Every
/// @Nydus_Canal can place a "Nydus Exit" which, when connected, can be travelled through by
/// @Zerg units.
///
/// @returns Unit interface representing the @Nydus_Canal connected to this one.
/// @retval nullptr if the unit is not a @Nydus_Canal, is not owned, or has not placed a Nydus
/// Exit.
Unit getNydusExit() const;
/// <summary>Retrieves the power-up that the worker unit is holding.</summary> Power-ups are
/// special units such as the @Flag in the @CTF game type, which can be picked up by worker
/// units.
///
/// @note If your bot is strictly melee/1v1, then this method is not necessary.
///
/// @returns The Unit interface object that represents the power-up.
/// @retval nullptr If the unit is not carrying anything.
///
/// Example
/// @code{.cpp}
/// for ( BWAPI::Unit u : game.self().getUnits())
/// {
/// // If we are carrying a flag
/// if ( u.getPowerUp() && u.getPowerUp().getType() == BWAPI::UnitTypes::Powerup_Flag )
/// u.move( u.getClosestUnit(BWAPI::Filter::IsFlagBeacon && BWAPI::Filter::IsOwned) ); // return it to our flag beacon to score
/// }
/// @endcode
/// @implies getType().isWorker(), isCompleted()
Unit getPowerUp() const;
/// <summary>Retrieves the @Transport or @Bunker unit that has this unit loaded inside of it.</summary>
///
/// @returns Unit interface object representing the @Transport containing this unit.
/// @retval nullptr if this unit is not in a @Transport.
Unit getTransport() const;
/// <summary>Retrieves the set of units that are contained within this @Bunker or @Transport.</summary>
///
/// @returns A Unitset object containing all of the units that are loaded inside of the
/// current unit.
Unitset getLoadedUnits() const;
/// <summary>Retrieves the remaining unit-space available for @Bunkers and @Transports.</summary>
///
/// @returns The number of spots available to transport a unit.
///
/// @see getLoadedUnits
int getSpaceRemaining() const;
/// <summary>Retrieves the parent @Carrier that owns this @Interceptor.</summary>
///
/// @returns The parent @Carrier unit that has ownership of this one.
/// @retval nullptr if the current unit is not an @Interceptor.
Unit getCarrier() const;
/// <summary>Retrieves the set of @Interceptors controlled by this unit.</summary> This is
/// intended for @Carriers and its hero.
///
/// @returns Unitset containing @Interceptor units owned by this carrier.
/// @see getInterceptorCount
Unitset getInterceptors() const;
/// <summary>Retrieves the parent @Hatchery, @Lair, or @Hive that owns this particular unit.</summary>
/// This is intended for @Larvae.
///
/// @returns Hatchery unit that has ownership of this larva.
/// @retval nullptr if the current unit is not a @Larva or has no parent.
/// @see getLarva
Unit getHatchery() const;
/// <summary>Retrieves the set of @Larvae that were spawned by this unit.</summary> Only
/// @Hatcheries, @Lairs, and @Hives are capable of spawning @Larvae. This is like clicking the
/// "Select Larva" button and getting the selection of @Larvae.
///
/// @returns Unitset containing @Larva units owned by this unit. The set will be empty if
/// there are none.
/// @see getHatchery
Unitset getLarva() const;
/// <summary>Retrieves the set of all units in a given radius of the current unit.</summary>
///
/// Takes into account this unit's dimensions. Can optionally specify a filter that is composed
/// using BWAPI Filter semantics to include only specific units (such as only ground units, etc.)
///
/// <param name="radius">
/// The radius, in pixels, to search for units.
/// </param>
/// <param name="pred"> (optional)
/// The composed function predicate to include only specific (desired) units in the set. Defaults to
/// nullptr, which means no filter.
/// </param>
///
/// @returns A Unitset containing the set of units that match the given criteria.
///
/// Example usage:
/// @code{.cpp}
/// // Get main building closest to start location.
/// BWAPI::Unit pMain = BWAPI::Broodwar->getClosestUnit( BWAPI::Broodwar->self()->getStartLocation(), BWAPI::Filter::IsResourceDepot );
/// if ( pMain ) // check if pMain is valid
/// {
/// // Get sets of resources and workers
/// BWAPI::Unitset myResources = pMain->getUnitsInRadius(1024, BWAPI::Filter::IsMineralField);
/// if ( !myResources.empty() ) // check if we have resources nearby
/// {
/// BWAPI::Unitset myWorkers = pMain->getUnitsInRadius(512, BWAPI::Filter::IsWorker && BWAPI::Filter::IsIdle && BWAPI::Filter::IsOwned );
/// while ( !myWorkers.empty() ) // make sure we command all nearby idle workers, if any
/// {
/// for ( auto u = myResources.begin(); u != myResources.end() && !myWorkers.empty(); ++u )
/// {
/// myWorkers.back()->gather(*u);
/// myWorkers.pop_back();
/// }
/// }
/// } // myResources not empty
/// } // pMain != nullptr
/// @endcode
///
/// @see getClosestUnit, getUnitsInWeaponRange, Game::getUnitsInRadius, Game::getUnitsInRectangle
Unitset getUnitsInRadius(int radius, const UnitFilter &pred = nullptr) const;
/// <summary>Obtains the set of units within weapon range of this unit.</summary>
///
/// <param name="weapon">
/// The weapon type to use as a filter for distance and units that can be hit by it.
/// </param>
/// <param name="pred"> (optional)
/// A predicate used as an additional filter. If omitted, no additional filter is used.
/// </param>
///
/// @see getUnitsInRadius, getClosestUnit, Game::getUnitsInRadius, Game::getUnitsInRectangle
Unitset getUnitsInWeaponRange(WeaponType weapon, const UnitFilter &pred = nullptr) const;
/// <summary>Retrieves the closest unit to this one.</summary>
///
/// <param name="pred"> (optional)
/// A function predicate used to identify which conditions must be matched for a unit to
/// be considered. If omitted, then the closest unit owned by any player will be returned.
/// </param>
/// <param name="radius"> (optional)
/// The maximum radius to check for the closest unit. For performance reasons, a developer
/// can limit the radius that is checked. If omitted, then the entire map is checked.
/// </param>
///
/// @see getUnitsInRadius, Game::getUnitsInRadius, Game::getUnitsInRectangle
Unit getClosestUnit(const UnitFilter &pred = nullptr, int radius = 999999) const;
/// <summary>Checks if the current unit is housing a @Nuke.</summary> This is only available
/// for @Silos.
///
/// @returns true if this unit has a @Nuke ready, and false if there is no @Nuke.
bool hasNuke() const { return getData().hasNuke; }
/// <summary>Checks if the current unit is accelerating.</summary>
///
/// @returns true if this unit is accelerating, and false otherwise
bool isAccelerating() const { return getData().isAccelerating; }
/// <summary>Checks if this unit is currently attacking something.</summary>
///
/// @returns true if this unit is attacking another unit, and false if it is not.
bool isAttacking() const { return getData().isAttacking; }
/// <summary>Checks if this unit is currently playing an attack animation.</summary> Issuing
/// commands while this returns true may interrupt the unit's next attack sequence.
///
/// @returns true if this unit is currently running an attack frame, and false if interrupting
/// the unit is feasible.
///
/// @note This function is only available to some unit types, specifically those that play
/// special animations when they attack.
bool isAttackFrame() const { return getData().isAttackFrame; }
/// <summary>Checks if the current unit is being constructed.</summary> This is mostly
/// applicable to Terran structures which require an SCV to be constructing a structure.
///
/// @retval true if this is either a Protoss structure, Zerg structure, or Terran structure
/// being constructed by an attached SCV.
/// @retval false if this is either completed, not a structure, or has no SCV constructing it
///
/// @see build, cancelConstruction, haltConstruction, isConstructing
bool isBeingConstructed() const {
if (isMorphing())
return true;
if (isCompleted())
return false;
if (getType().getRace() != Races::Terran)
return true;
return static_cast<bool>(getBuildUnit());
}
/// <summary>Checks this @Mineral_Field or @Refinery is currently being gathered from.</summary>
///
/// @returns true if this unit is a resource container and being harvested by a worker, and
/// false otherwise
bool isBeingGathered() const { return getData().isBeingGathered; }
/// <summary>Checks if this unit is currently being healed by a @Medic or repaired by a @SCV.</summary>
///
/// @returns true if this unit is being healed, and false otherwise.
bool isBeingHealed() const { return getData().isBeingHealed; }
/// <summary>Checks if this unit is currently blinded by a @Medic 's @Optical_Flare ability.</summary>
/// Blinded units have reduced sight range and cannot detect other units.
///
/// @returns true if this unit is blind, and false otherwise
bool isBlind() const { return getData().isBlind; }
/// <summary>Checks if the current unit is slowing down to come to a stop.</summary>
///
/// @returns true if this unit is breaking, false if it has stopped or is still moving at full
/// speed.
bool isBraking() const { return getData().isBraking; }
/// <summary>Checks if the current unit is burrowed, either using the @Burrow ability, or is
/// an armed @Spider_Mine.</summary>
///
/// @returns true if this unit is burrowed, and false otherwise
/// @see burrow, unburrow
bool isBurrowed() const { return getData().isBurrowed; }
/// <summary>Checks if this worker unit is carrying some vespene gas.</summary>
///
/// @returns true if this is a worker unit carrying vespene gas, and false if it is either
/// not a worker, or not carrying gas.
///
/// Example
/// @code{.cpp}
/// BWAPI::Unitset myUnits = BWAPI::Broodwar->self()->getUnits();
/// for ( auto u = myUnits.begin(); u != myUnits.end(); ++u )
/// {
/// if ( u->isIdle() && (u->isCarryingGas() || u->isCarryingMinerals()) )
/// u->returnCargo();
/// }
/// @endcode
/// @implies isCompleted(), getType().isWorker()
/// @see returnCargo, isGatheringGas, isCarryingMinerals
bool isCarryingGas() const { return getData().carryResourceType == 1; }
/// <summary>Checks if this worker unit is carrying some minerals.</summary>
///
/// @returns true if this is a worker unit carrying minerals, and false if it is either
/// not a worker, or not carrying minerals.
///
/// Example
/// @code{.cpp}
/// BWAPI::Unitset myUnits = BWAPI::Broodwar->self()->getUnits();
/// for ( auto u = myUnits.begin(); u != myUnits.end(); ++u )
/// {
/// if ( u->isIdle() && (u->isCarryingGas() || u->isCarryingMinerals()) )
/// u->returnCargo();
/// }
/// @endcode
/// @implies isCompleted(), getType().isWorker()
/// @see returnCargo, isGatheringMinerals, isCarryingMinerals
bool isCarryingMinerals() const { return getData().carryResourceType == 2; }
/// <summary>Checks if this unit is currently @cloaked.</summary>
///
/// @returns true if this unit is cloaked, and false if it is visible.
/// @see cloak, decloak
bool isCloaked() const { return getData().isCloaked; }
/// <summary>Checks if this unit has finished being constructed, trained, morphed, or warped
/// in, and can now receive orders.</summary>
///
/// @returns true if this unit is completed, and false if it is under construction or inaccessible.
bool isCompleted() const { return getData().isCompleted; }
/// <summary>Checks if a unit is either constructing something or moving to construct something.</summary>
///
/// @returns true when a unit has been issued an order to build a structure and is moving to
/// the build location, or is currently constructing something.
///
/// @see isBeingConstructed, build, cancelConstruction, haltConstruction
bool isConstructing() const { return getData().isConstructing; }
/// <summary>Checks if this unit has the @matrix effect.</summary>
///
/// @returns true if the @matrix ability was used on this unit, and false otherwise.
bool isDefenseMatrixed() const { return static_cast<bool>(getDefenseMatrixPoints()); }
/// <summary>Checks if this unit is visible or revealed by a detector unit.</summary> If this
/// is false and #isVisible is true, then the unit is only partially visible and requires a
/// detector in order to be targetted.
///
/// @returns true if this unit is detected, and false if it needs a detector unit nearby in
/// order to see it.
/// @implies isVisible
bool isDetected() const { return getData().isDetected; }
/// <summary>Checks if the @Queen ability @Ensnare has been used on this unit.</summary>
///
/// @returns true if the unit is ensnared, and false if it is not
bool isEnsnared() const { return static_cast<bool>(getData().ensnareTimer); }