@supalosa/chronodivide-bot 0.5.4 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/.env.template +4 -4
  2. package/.github/workflows/npm-publish.yml +24 -0
  3. package/README.md +108 -103
  4. package/dist/bot/bot.js +105 -105
  5. package/dist/bot/logic/awareness.js +136 -136
  6. package/dist/bot/logic/building/antiAirStaticDefence.js +42 -42
  7. package/dist/bot/logic/building/antiGroundStaticDefence.js +34 -34
  8. package/dist/bot/logic/building/{ArtilleryUnit.js → artilleryUnit.js} +18 -18
  9. package/dist/bot/logic/building/basicAirUnit.js +19 -19
  10. package/dist/bot/logic/building/basicBuilding.js +26 -26
  11. package/dist/bot/logic/building/basicGroundUnit.js +19 -19
  12. package/dist/bot/logic/building/buildingRules.js +175 -175
  13. package/dist/bot/logic/building/common.js +19 -19
  14. package/dist/bot/logic/building/harvester.js +16 -16
  15. package/dist/bot/logic/building/powerPlant.js +20 -20
  16. package/dist/bot/logic/building/queueController.js +183 -183
  17. package/dist/bot/logic/building/resourceCollectionBuilding.js +36 -36
  18. package/dist/bot/logic/common/scout.js +126 -126
  19. package/dist/bot/logic/common/utils.js +95 -95
  20. package/dist/bot/logic/composition/alliedCompositions.js +12 -12
  21. package/dist/bot/logic/composition/common.js +1 -1
  22. package/dist/bot/logic/composition/sovietCompositions.js +12 -12
  23. package/dist/bot/logic/map/map.js +44 -44
  24. package/dist/bot/logic/map/sector.js +137 -137
  25. package/dist/bot/logic/mission/actionBatcher.js +91 -91
  26. package/dist/bot/logic/mission/mission.js +122 -122
  27. package/dist/bot/logic/mission/missionController.js +321 -321
  28. package/dist/bot/logic/mission/missionFactories.js +12 -12
  29. package/dist/bot/logic/mission/missions/attackMission.js +214 -214
  30. package/dist/bot/logic/mission/missions/defenceMission.js +82 -82
  31. package/dist/bot/logic/mission/missions/engineerMission.js +63 -63
  32. package/dist/bot/logic/mission/missions/expansionMission.js +60 -60
  33. package/dist/bot/logic/mission/missions/retreatMission.js +33 -33
  34. package/dist/bot/logic/mission/missions/scoutingMission.js +133 -133
  35. package/dist/bot/logic/mission/missions/squads/combatSquad.js +115 -115
  36. package/dist/bot/logic/mission/missions/squads/common.js +57 -57
  37. package/dist/bot/logic/mission/missions/squads/squad.js +1 -1
  38. package/dist/bot/logic/threat/threat.js +22 -22
  39. package/dist/bot/logic/threat/threatCalculator.js +73 -73
  40. package/dist/exampleBot.js +100 -100
  41. package/package.json +32 -29
  42. package/src/bot/bot.ts +161 -161
  43. package/src/bot/logic/awareness.ts +245 -245
  44. package/src/bot/logic/building/antiAirStaticDefence.ts +64 -64
  45. package/src/bot/logic/building/antiGroundStaticDefence.ts +55 -55
  46. package/src/bot/logic/building/artilleryUnit.ts +39 -39
  47. package/src/bot/logic/building/basicAirUnit.ts +39 -39
  48. package/src/bot/logic/building/basicBuilding.ts +49 -49
  49. package/src/bot/logic/building/basicGroundUnit.ts +39 -39
  50. package/src/bot/logic/building/buildingRules.ts +250 -250
  51. package/src/bot/logic/building/common.ts +21 -21
  52. package/src/bot/logic/building/harvester.ts +31 -31
  53. package/src/bot/logic/building/powerPlant.ts +32 -32
  54. package/src/bot/logic/building/queueController.ts +297 -297
  55. package/src/bot/logic/building/resourceCollectionBuilding.ts +52 -52
  56. package/src/bot/logic/common/scout.ts +183 -183
  57. package/src/bot/logic/common/utils.ts +120 -120
  58. package/src/bot/logic/composition/alliedCompositions.ts +22 -22
  59. package/src/bot/logic/composition/common.ts +3 -3
  60. package/src/bot/logic/composition/sovietCompositions.ts +21 -21
  61. package/src/bot/logic/map/map.ts +66 -66
  62. package/src/bot/logic/map/sector.ts +174 -174
  63. package/src/bot/logic/mission/actionBatcher.ts +124 -124
  64. package/src/bot/logic/mission/mission.ts +232 -232
  65. package/src/bot/logic/mission/missionController.ts +413 -413
  66. package/src/bot/logic/mission/missionFactories.ts +51 -51
  67. package/src/bot/logic/mission/missions/attackMission.ts +336 -336
  68. package/src/bot/logic/mission/missions/defenceMission.ts +151 -151
  69. package/src/bot/logic/mission/missions/engineerMission.ts +113 -113
  70. package/src/bot/logic/mission/missions/expansionMission.ts +104 -104
  71. package/src/bot/logic/mission/missions/retreatMission.ts +54 -54
  72. package/src/bot/logic/mission/missions/scoutingMission.ts +186 -186
  73. package/src/bot/logic/mission/missions/squads/combatSquad.ts +160 -160
  74. package/src/bot/logic/mission/missions/squads/common.ts +63 -63
  75. package/src/bot/logic/mission/missions/squads/squad.ts +19 -19
  76. package/src/bot/logic/threat/threat.ts +15 -15
  77. package/src/bot/logic/threat/threatCalculator.ts +100 -100
  78. package/src/exampleBot.ts +111 -111
  79. package/tsconfig.json +73 -73
  80. package/dist/bot/logic/awarenessImpl.js +0 -132
  81. package/dist/bot/logic/awarenessImpl.js.map +0 -1
  82. package/dist/bot/logic/building/building.js +0 -126
  83. package/dist/bot/logic/building/building.js.map +0 -1
  84. package/dist/bot/logic/mission/behaviours/combatSquad.js +0 -124
  85. package/dist/bot/logic/mission/behaviours/combatSquad.js.map +0 -1
  86. package/dist/bot/logic/mission/behaviours/common.js +0 -58
  87. package/dist/bot/logic/mission/behaviours/common.js.map +0 -1
  88. package/dist/bot/logic/mission/behaviours/engineerSquad.js +0 -39
  89. package/dist/bot/logic/mission/behaviours/engineerSquad.js.map +0 -1
  90. package/dist/bot/logic/mission/behaviours/expansionSquad.js +0 -46
  91. package/dist/bot/logic/mission/behaviours/expansionSquad.js.map +0 -1
  92. package/dist/bot/logic/mission/behaviours/retreatSquad.js +0 -31
  93. package/dist/bot/logic/mission/behaviours/retreatSquad.js.map +0 -1
  94. package/dist/bot/logic/mission/behaviours/scoutingSquad.js +0 -94
  95. package/dist/bot/logic/mission/behaviours/scoutingSquad.js.map +0 -1
  96. package/dist/bot/logic/mission/missions/basicMission.js +0 -13
  97. package/dist/bot/logic/mission/missions/basicMission.js.map +0 -1
  98. package/dist/bot/logic/mission/missions/missionBehaviour.js +0 -2
  99. package/dist/bot/logic/mission/missions/missionBehaviour.js.map +0 -1
  100. package/dist/bot/logic/mission/missions/oneTimeMission.js +0 -27
  101. package/dist/bot/logic/mission/missions/oneTimeMission.js.map +0 -1
  102. package/dist/bot/logic/squad/behaviours/attackSquad.js +0 -89
  103. package/dist/bot/logic/squad/behaviours/combatSquad.js +0 -102
  104. package/dist/bot/logic/squad/behaviours/combatSquad.js.map +0 -1
  105. package/dist/bot/logic/squad/behaviours/common.js +0 -40
  106. package/dist/bot/logic/squad/behaviours/common.js.map +0 -1
  107. package/dist/bot/logic/squad/behaviours/defenceSquad.js +0 -61
  108. package/dist/bot/logic/squad/behaviours/engineerSquad.js +0 -36
  109. package/dist/bot/logic/squad/behaviours/engineerSquad.js.map +0 -1
  110. package/dist/bot/logic/squad/behaviours/expansionSquad.js +0 -43
  111. package/dist/bot/logic/squad/behaviours/expansionSquad.js.map +0 -1
  112. package/dist/bot/logic/squad/behaviours/retreatSquad.js +0 -28
  113. package/dist/bot/logic/squad/behaviours/retreatSquad.js.map +0 -1
  114. package/dist/bot/logic/squad/behaviours/scoutingSquad.js +0 -86
  115. package/dist/bot/logic/squad/behaviours/scoutingSquad.js.map +0 -1
  116. package/dist/bot/logic/squad/squad.js +0 -126
  117. package/dist/bot/logic/squad/squad.js.map +0 -1
  118. package/dist/bot/logic/squad/squadBehaviour.js +0 -6
  119. package/dist/bot/logic/squad/squadBehaviour.js.map +0 -1
  120. package/dist/bot/logic/squad/squadBehaviours.js +0 -7
  121. package/dist/bot/logic/squad/squadBehaviours.js.map +0 -1
  122. package/dist/bot/logic/squad/squadController.js +0 -199
  123. package/dist/bot/logic/squad/squadController.js.map +0 -1
  124. /package/dist/bot/logic/building/{ArtilleryUnit.js.map → artilleryUnit.js.map} +0 -0
@@ -1,186 +1,186 @@
1
- import { ActionsApi, GameApi, OrderType, PlayerData, Vector2 } from "@chronodivide/game-api";
2
- import { MissionFactory } from "../missionFactories.js";
3
- import { MatchAwareness } from "../../awareness.js";
4
- import { Mission, MissionAction, disbandMission, noop, requestUnits } from "../mission.js";
5
- import { AttackMission } from "./attackMission.js";
6
- import { MissionController } from "../missionController.js";
7
- import { DebugLogger } from "../../common/utils.js";
8
- import { ActionBatcher } from "../actionBatcher.js";
9
- import { getDistanceBetweenTileAndPoint } from "../../map/map.js";
10
- import { PrioritisedScoutTarget } from "../../common/scout.js";
11
-
12
- const SCOUT_MOVE_COOLDOWN_TICKS = 30;
13
-
14
- // Max units to spend on a particular scout target.
15
- const MAX_ATTEMPTS_PER_TARGET = 5;
16
-
17
- // Maximum ticks to spend trying to scout a target *without making progress towards it*.
18
- // Every time a unit gets closer to the target, the timer refreshes.
19
- const MAX_TICKS_PER_TARGET = 600;
20
-
21
- /**
22
- * A mission that tries to scout around the map with a cheap, fast unit (usually attack dogs)
23
- */
24
- export class ScoutingMission extends Mission {
25
- private scoutTarget: Vector2 | null = null;
26
- private attemptsOnCurrentTarget: number = 0;
27
- private scoutTargetRefreshedAt: number = 0;
28
- private lastMoveCommandTick: number = 0;
29
- private scoutTargetIsPermanent: boolean = false;
30
-
31
- // Minimum distance from a scout to the target.
32
- private scoutMinDistance?: number;
33
-
34
- private hadUnit: boolean = false;
35
-
36
- constructor(
37
- uniqueName: string,
38
- private priority: number,
39
- logger: DebugLogger,
40
- ) {
41
- super(uniqueName, logger);
42
- }
43
-
44
- public _onAiUpdate(
45
- gameApi: GameApi,
46
- actionsApi: ActionsApi,
47
- playerData: PlayerData,
48
- matchAwareness: MatchAwareness,
49
- actionBatcher: ActionBatcher,
50
- ): MissionAction {
51
- const scoutNames = ["ADOG", "DOG", "E1", "E2", "FV", "HTK"];
52
- const scouts = this.getUnitsOfTypes(gameApi, ...scoutNames);
53
-
54
- if ((matchAwareness.getSectorCache().getOverallVisibility() || 0) > 0.9) {
55
- return disbandMission();
56
- }
57
-
58
- if (scouts.length === 0) {
59
- // Count the number of times the scout dies trying to uncover the current scoutTarget.
60
- if (this.scoutTarget && this.hadUnit) {
61
- this.attemptsOnCurrentTarget++;
62
- this.hadUnit = false;
63
- }
64
- return requestUnits(scoutNames, this.priority);
65
- } else if (this.scoutTarget) {
66
- this.hadUnit = true;
67
- if (!this.scoutTargetIsPermanent) {
68
- if (this.attemptsOnCurrentTarget > MAX_ATTEMPTS_PER_TARGET) {
69
- this.logger(
70
- `Scout target ${this.scoutTarget.x},${this.scoutTarget.y} took too many attempts, moving to next`,
71
- );
72
- this.setScoutTarget(null, 0);
73
- return noop();
74
- }
75
- if (gameApi.getCurrentTick() > this.scoutTargetRefreshedAt + MAX_TICKS_PER_TARGET) {
76
- this.logger(
77
- `Scout target ${this.scoutTarget.x},${this.scoutTarget.y} took too long, moving to next`,
78
- );
79
- this.setScoutTarget(null, 0);
80
- return noop();
81
- }
82
- }
83
- const targetTile = gameApi.mapApi.getTile(this.scoutTarget.x, this.scoutTarget.y);
84
- if (!targetTile) {
85
- throw new Error(`target tile ${this.scoutTarget.x},${this.scoutTarget.y} does not exist`);
86
- }
87
- if (gameApi.getCurrentTick() > this.lastMoveCommandTick + SCOUT_MOVE_COOLDOWN_TICKS) {
88
- this.lastMoveCommandTick = gameApi.getCurrentTick();
89
- scouts.forEach((unit) => {
90
- if (this.scoutTarget) {
91
- actionsApi.orderUnits([unit.id], OrderType.AttackMove, this.scoutTarget.x, this.scoutTarget.y);
92
- }
93
- });
94
- // Check that a scout is actually moving closer to the target.
95
- const distances = scouts.map((unit) => getDistanceBetweenTileAndPoint(unit.tile, this.scoutTarget!));
96
- const newMinDistance = Math.min(...distances);
97
- if (!this.scoutMinDistance || newMinDistance < this.scoutMinDistance) {
98
- this.logger(
99
- `Scout timeout refreshed because unit moved closer to point (${newMinDistance} < ${this.scoutMinDistance})`,
100
- );
101
- this.scoutTargetRefreshedAt = gameApi.getCurrentTick();
102
- this.scoutMinDistance = newMinDistance;
103
- }
104
- }
105
- if (gameApi.mapApi.isVisibleTile(targetTile, playerData.name)) {
106
- this.logger(
107
- `Scout target ${this.scoutTarget.x},${this.scoutTarget.y} successfully scouted, moving to next`,
108
- );
109
- this.setScoutTarget(null, gameApi.getCurrentTick());
110
- }
111
- } else {
112
- const nextScoutTarget = matchAwareness.getScoutingManager().getNewScoutTarget();
113
- if (!nextScoutTarget) {
114
- this.logger(`No more scouting targets available, disbanding.`);
115
- return disbandMission();
116
- }
117
- this.setScoutTarget(nextScoutTarget, gameApi.getCurrentTick());
118
- }
119
- return noop();
120
- }
121
-
122
- setScoutTarget(target: PrioritisedScoutTarget | null, currentTick: number) {
123
- this.attemptsOnCurrentTarget = 0;
124
- this.scoutTargetRefreshedAt = currentTick;
125
- this.scoutTarget = target?.asVector2() ?? null;
126
- this.scoutMinDistance = undefined;
127
- this.scoutTargetIsPermanent = target?.isPermanent ?? false;
128
- }
129
-
130
- public getGlobalDebugText(): string | undefined {
131
- return "scouting";
132
- }
133
-
134
- public getPriority() {
135
- return this.priority;
136
- }
137
- }
138
-
139
- const SCOUT_COOLDOWN_TICKS = 300;
140
-
141
- export class ScoutingMissionFactory implements MissionFactory {
142
- constructor(private lastScoutAt: number = -SCOUT_COOLDOWN_TICKS) {}
143
-
144
- getName(): string {
145
- return "ScoutingMissionFactory";
146
- }
147
-
148
- maybeCreateMissions(
149
- gameApi: GameApi,
150
- playerData: PlayerData,
151
- matchAwareness: MatchAwareness,
152
- missionController: MissionController,
153
- logger: DebugLogger,
154
- ): void {
155
- if (gameApi.getCurrentTick() < this.lastScoutAt + SCOUT_COOLDOWN_TICKS) {
156
- return;
157
- }
158
- if (!matchAwareness.getScoutingManager().hasScoutTargets()) {
159
- return;
160
- }
161
- if (!missionController.addMission(new ScoutingMission("globalScout", 10, logger))) {
162
- this.lastScoutAt = gameApi.getCurrentTick();
163
- }
164
- }
165
-
166
- onMissionFailed(
167
- gameApi: GameApi,
168
- playerData: PlayerData,
169
- matchAwareness: MatchAwareness,
170
- failedMission: Mission<any>,
171
- failureReason: undefined,
172
- missionController: MissionController,
173
- logger: DebugLogger,
174
- ): void {
175
- if (gameApi.getCurrentTick() < this.lastScoutAt + SCOUT_COOLDOWN_TICKS) {
176
- return;
177
- }
178
- if (!matchAwareness.getScoutingManager().hasScoutTargets()) {
179
- return;
180
- }
181
- if (failedMission instanceof AttackMission) {
182
- missionController.addMission(new ScoutingMission("globalScout", 10, logger));
183
- this.lastScoutAt = gameApi.getCurrentTick();
184
- }
185
- }
186
- }
1
+ import { ActionsApi, GameApi, OrderType, PlayerData, Vector2 } from "@chronodivide/game-api";
2
+ import { MissionFactory } from "../missionFactories.js";
3
+ import { MatchAwareness } from "../../awareness.js";
4
+ import { Mission, MissionAction, disbandMission, noop, requestUnits } from "../mission.js";
5
+ import { AttackMission } from "./attackMission.js";
6
+ import { MissionController } from "../missionController.js";
7
+ import { DebugLogger } from "../../common/utils.js";
8
+ import { ActionBatcher } from "../actionBatcher.js";
9
+ import { getDistanceBetweenTileAndPoint } from "../../map/map.js";
10
+ import { PrioritisedScoutTarget } from "../../common/scout.js";
11
+
12
+ const SCOUT_MOVE_COOLDOWN_TICKS = 30;
13
+
14
+ // Max units to spend on a particular scout target.
15
+ const MAX_ATTEMPTS_PER_TARGET = 5;
16
+
17
+ // Maximum ticks to spend trying to scout a target *without making progress towards it*.
18
+ // Every time a unit gets closer to the target, the timer refreshes.
19
+ const MAX_TICKS_PER_TARGET = 600;
20
+
21
+ /**
22
+ * A mission that tries to scout around the map with a cheap, fast unit (usually attack dogs)
23
+ */
24
+ export class ScoutingMission extends Mission {
25
+ private scoutTarget: Vector2 | null = null;
26
+ private attemptsOnCurrentTarget: number = 0;
27
+ private scoutTargetRefreshedAt: number = 0;
28
+ private lastMoveCommandTick: number = 0;
29
+ private scoutTargetIsPermanent: boolean = false;
30
+
31
+ // Minimum distance from a scout to the target.
32
+ private scoutMinDistance?: number;
33
+
34
+ private hadUnit: boolean = false;
35
+
36
+ constructor(
37
+ uniqueName: string,
38
+ private priority: number,
39
+ logger: DebugLogger,
40
+ ) {
41
+ super(uniqueName, logger);
42
+ }
43
+
44
+ public _onAiUpdate(
45
+ gameApi: GameApi,
46
+ actionsApi: ActionsApi,
47
+ playerData: PlayerData,
48
+ matchAwareness: MatchAwareness,
49
+ actionBatcher: ActionBatcher,
50
+ ): MissionAction {
51
+ const scoutNames = ["ADOG", "DOG", "E1", "E2", "FV", "HTK"];
52
+ const scouts = this.getUnitsOfTypes(gameApi, ...scoutNames);
53
+
54
+ if ((matchAwareness.getSectorCache().getOverallVisibility() || 0) > 0.9) {
55
+ return disbandMission();
56
+ }
57
+
58
+ if (scouts.length === 0) {
59
+ // Count the number of times the scout dies trying to uncover the current scoutTarget.
60
+ if (this.scoutTarget && this.hadUnit) {
61
+ this.attemptsOnCurrentTarget++;
62
+ this.hadUnit = false;
63
+ }
64
+ return requestUnits(scoutNames, this.priority);
65
+ } else if (this.scoutTarget) {
66
+ this.hadUnit = true;
67
+ if (!this.scoutTargetIsPermanent) {
68
+ if (this.attemptsOnCurrentTarget > MAX_ATTEMPTS_PER_TARGET) {
69
+ this.logger(
70
+ `Scout target ${this.scoutTarget.x},${this.scoutTarget.y} took too many attempts, moving to next`,
71
+ );
72
+ this.setScoutTarget(null, 0);
73
+ return noop();
74
+ }
75
+ if (gameApi.getCurrentTick() > this.scoutTargetRefreshedAt + MAX_TICKS_PER_TARGET) {
76
+ this.logger(
77
+ `Scout target ${this.scoutTarget.x},${this.scoutTarget.y} took too long, moving to next`,
78
+ );
79
+ this.setScoutTarget(null, 0);
80
+ return noop();
81
+ }
82
+ }
83
+ const targetTile = gameApi.mapApi.getTile(this.scoutTarget.x, this.scoutTarget.y);
84
+ if (!targetTile) {
85
+ throw new Error(`target tile ${this.scoutTarget.x},${this.scoutTarget.y} does not exist`);
86
+ }
87
+ if (gameApi.getCurrentTick() > this.lastMoveCommandTick + SCOUT_MOVE_COOLDOWN_TICKS) {
88
+ this.lastMoveCommandTick = gameApi.getCurrentTick();
89
+ scouts.forEach((unit) => {
90
+ if (this.scoutTarget) {
91
+ actionsApi.orderUnits([unit.id], OrderType.AttackMove, this.scoutTarget.x, this.scoutTarget.y);
92
+ }
93
+ });
94
+ // Check that a scout is actually moving closer to the target.
95
+ const distances = scouts.map((unit) => getDistanceBetweenTileAndPoint(unit.tile, this.scoutTarget!));
96
+ const newMinDistance = Math.min(...distances);
97
+ if (!this.scoutMinDistance || newMinDistance < this.scoutMinDistance) {
98
+ this.logger(
99
+ `Scout timeout refreshed because unit moved closer to point (${newMinDistance} < ${this.scoutMinDistance})`,
100
+ );
101
+ this.scoutTargetRefreshedAt = gameApi.getCurrentTick();
102
+ this.scoutMinDistance = newMinDistance;
103
+ }
104
+ }
105
+ if (gameApi.mapApi.isVisibleTile(targetTile, playerData.name)) {
106
+ this.logger(
107
+ `Scout target ${this.scoutTarget.x},${this.scoutTarget.y} successfully scouted, moving to next`,
108
+ );
109
+ this.setScoutTarget(null, gameApi.getCurrentTick());
110
+ }
111
+ } else {
112
+ const nextScoutTarget = matchAwareness.getScoutingManager().getNewScoutTarget();
113
+ if (!nextScoutTarget) {
114
+ this.logger(`No more scouting targets available, disbanding.`);
115
+ return disbandMission();
116
+ }
117
+ this.setScoutTarget(nextScoutTarget, gameApi.getCurrentTick());
118
+ }
119
+ return noop();
120
+ }
121
+
122
+ setScoutTarget(target: PrioritisedScoutTarget | null, currentTick: number) {
123
+ this.attemptsOnCurrentTarget = 0;
124
+ this.scoutTargetRefreshedAt = currentTick;
125
+ this.scoutTarget = target?.asVector2() ?? null;
126
+ this.scoutMinDistance = undefined;
127
+ this.scoutTargetIsPermanent = target?.isPermanent ?? false;
128
+ }
129
+
130
+ public getGlobalDebugText(): string | undefined {
131
+ return "scouting";
132
+ }
133
+
134
+ public getPriority() {
135
+ return this.priority;
136
+ }
137
+ }
138
+
139
+ const SCOUT_COOLDOWN_TICKS = 300;
140
+
141
+ export class ScoutingMissionFactory implements MissionFactory {
142
+ constructor(private lastScoutAt: number = -SCOUT_COOLDOWN_TICKS) {}
143
+
144
+ getName(): string {
145
+ return "ScoutingMissionFactory";
146
+ }
147
+
148
+ maybeCreateMissions(
149
+ gameApi: GameApi,
150
+ playerData: PlayerData,
151
+ matchAwareness: MatchAwareness,
152
+ missionController: MissionController,
153
+ logger: DebugLogger,
154
+ ): void {
155
+ if (gameApi.getCurrentTick() < this.lastScoutAt + SCOUT_COOLDOWN_TICKS) {
156
+ return;
157
+ }
158
+ if (!matchAwareness.getScoutingManager().hasScoutTargets()) {
159
+ return;
160
+ }
161
+ if (!missionController.addMission(new ScoutingMission("globalScout", 10, logger))) {
162
+ this.lastScoutAt = gameApi.getCurrentTick();
163
+ }
164
+ }
165
+
166
+ onMissionFailed(
167
+ gameApi: GameApi,
168
+ playerData: PlayerData,
169
+ matchAwareness: MatchAwareness,
170
+ failedMission: Mission<any>,
171
+ failureReason: undefined,
172
+ missionController: MissionController,
173
+ logger: DebugLogger,
174
+ ): void {
175
+ if (gameApi.getCurrentTick() < this.lastScoutAt + SCOUT_COOLDOWN_TICKS) {
176
+ return;
177
+ }
178
+ if (!matchAwareness.getScoutingManager().hasScoutTargets()) {
179
+ return;
180
+ }
181
+ if (failedMission instanceof AttackMission) {
182
+ missionController.addMission(new ScoutingMission("globalScout", 10, logger));
183
+ this.lastScoutAt = gameApi.getCurrentTick();
184
+ }
185
+ }
186
+ }