@supalosa/chronodivide-bot 0.5.3 → 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 (134) hide show
  1. package/.env.template +4 -4
  2. package/.github/workflows/npm-publish.yml +24 -0
  3. package/README.md +108 -97
  4. package/dist/bot/bot.js +105 -105
  5. package/dist/bot/bot.js.map +1 -1
  6. package/dist/bot/logic/awareness.js +136 -136
  7. package/dist/bot/logic/building/antiAirStaticDefence.js +42 -42
  8. package/dist/bot/logic/building/antiGroundStaticDefence.js +34 -30
  9. package/dist/bot/logic/building/antiGroundStaticDefence.js.map +1 -1
  10. package/dist/bot/logic/building/{ArtilleryUnit.js → artilleryUnit.js} +18 -18
  11. package/dist/bot/logic/building/basicAirUnit.js +19 -19
  12. package/dist/bot/logic/building/basicBuilding.js +26 -26
  13. package/dist/bot/logic/building/basicGroundUnit.js +19 -19
  14. package/dist/bot/logic/building/buildingRules.js +175 -174
  15. package/dist/bot/logic/building/buildingRules.js.map +1 -1
  16. package/dist/bot/logic/building/common.js +19 -18
  17. package/dist/bot/logic/building/common.js.map +1 -1
  18. package/dist/bot/logic/building/harvester.js +16 -16
  19. package/dist/bot/logic/building/powerPlant.js +20 -20
  20. package/dist/bot/logic/building/queueController.js +183 -183
  21. package/dist/bot/logic/building/resourceCollectionBuilding.js +36 -36
  22. package/dist/bot/logic/common/scout.js +126 -126
  23. package/dist/bot/logic/common/utils.js +95 -85
  24. package/dist/bot/logic/common/utils.js.map +1 -1
  25. package/dist/bot/logic/composition/alliedCompositions.js +12 -12
  26. package/dist/bot/logic/composition/common.js +1 -1
  27. package/dist/bot/logic/composition/sovietCompositions.js +12 -12
  28. package/dist/bot/logic/map/map.js +44 -44
  29. package/dist/bot/logic/map/sector.js +137 -137
  30. package/dist/bot/logic/mission/actionBatcher.js +91 -91
  31. package/dist/bot/logic/mission/mission.js +122 -122
  32. package/dist/bot/logic/mission/missionController.js +321 -321
  33. package/dist/bot/logic/mission/missionFactories.js +12 -12
  34. package/dist/bot/logic/mission/missions/attackMission.js +214 -214
  35. package/dist/bot/logic/mission/missions/defenceMission.js +82 -82
  36. package/dist/bot/logic/mission/missions/engineerMission.js +63 -63
  37. package/dist/bot/logic/mission/missions/expansionMission.js +60 -60
  38. package/dist/bot/logic/mission/missions/retreatMission.js +33 -33
  39. package/dist/bot/logic/mission/missions/scoutingMission.js +133 -133
  40. package/dist/bot/logic/mission/missions/squads/combatSquad.js +115 -115
  41. package/dist/bot/logic/mission/missions/squads/common.js +57 -57
  42. package/dist/bot/logic/mission/missions/squads/squad.js +1 -1
  43. package/dist/bot/logic/threat/threat.js +22 -22
  44. package/dist/bot/logic/threat/threatCalculator.js +73 -73
  45. package/dist/exampleBot.js +100 -112
  46. package/dist/exampleBot.js.map +1 -1
  47. package/package.json +32 -29
  48. package/src/bot/bot.ts +161 -161
  49. package/src/bot/logic/awareness.ts +245 -245
  50. package/src/bot/logic/building/antiAirStaticDefence.ts +64 -64
  51. package/src/bot/logic/building/antiGroundStaticDefence.ts +55 -51
  52. package/src/bot/logic/building/artilleryUnit.ts +39 -39
  53. package/src/bot/logic/building/basicAirUnit.ts +39 -39
  54. package/src/bot/logic/building/basicBuilding.ts +49 -49
  55. package/src/bot/logic/building/basicGroundUnit.ts +39 -39
  56. package/src/bot/logic/building/buildingRules.ts +250 -247
  57. package/src/bot/logic/building/common.ts +21 -23
  58. package/src/bot/logic/building/harvester.ts +31 -31
  59. package/src/bot/logic/building/powerPlant.ts +32 -32
  60. package/src/bot/logic/building/queueController.ts +297 -297
  61. package/src/bot/logic/building/resourceCollectionBuilding.ts +52 -52
  62. package/src/bot/logic/common/scout.ts +183 -183
  63. package/src/bot/logic/common/utils.ts +120 -112
  64. package/src/bot/logic/composition/alliedCompositions.ts +22 -22
  65. package/src/bot/logic/composition/common.ts +3 -3
  66. package/src/bot/logic/composition/sovietCompositions.ts +21 -21
  67. package/src/bot/logic/map/map.ts +66 -66
  68. package/src/bot/logic/map/sector.ts +174 -174
  69. package/src/bot/logic/mission/actionBatcher.ts +124 -124
  70. package/src/bot/logic/mission/mission.ts +232 -232
  71. package/src/bot/logic/mission/missionController.ts +413 -413
  72. package/src/bot/logic/mission/missionFactories.ts +51 -51
  73. package/src/bot/logic/mission/missions/attackMission.ts +336 -336
  74. package/src/bot/logic/mission/missions/defenceMission.ts +151 -151
  75. package/src/bot/logic/mission/missions/engineerMission.ts +113 -113
  76. package/src/bot/logic/mission/missions/expansionMission.ts +104 -104
  77. package/src/bot/logic/mission/missions/retreatMission.ts +54 -54
  78. package/src/bot/logic/mission/missions/scoutingMission.ts +186 -186
  79. package/src/bot/logic/mission/missions/squads/combatSquad.ts +160 -160
  80. package/src/bot/logic/mission/missions/squads/common.ts +63 -63
  81. package/src/bot/logic/mission/missions/squads/squad.ts +19 -19
  82. package/src/bot/logic/threat/threatCalculator.ts +100 -100
  83. package/src/exampleBot.ts +111 -124
  84. package/tsconfig.json +73 -73
  85. package/dist/bot/logic/building/building.js +0 -82
  86. package/dist/bot/logic/building/massedAntiGroundUnit.js +0 -20
  87. package/dist/bot/logic/building/queues.js +0 -19
  88. package/dist/bot/logic/knowledge.js +0 -1
  89. package/dist/bot/logic/mission/basicMission.js +0 -26
  90. package/dist/bot/logic/mission/behaviours/combatSquad.js +0 -124
  91. package/dist/bot/logic/mission/behaviours/combatSquad.js.map +0 -1
  92. package/dist/bot/logic/mission/behaviours/common.js +0 -56
  93. package/dist/bot/logic/mission/behaviours/common.js.map +0 -1
  94. package/dist/bot/logic/mission/behaviours/engineerSquad.js +0 -39
  95. package/dist/bot/logic/mission/behaviours/engineerSquad.js.map +0 -1
  96. package/dist/bot/logic/mission/behaviours/expansionSquad.js +0 -46
  97. package/dist/bot/logic/mission/behaviours/expansionSquad.js.map +0 -1
  98. package/dist/bot/logic/mission/behaviours/retreatSquad.js +0 -31
  99. package/dist/bot/logic/mission/behaviours/retreatSquad.js.map +0 -1
  100. package/dist/bot/logic/mission/behaviours/scoutingSquad.js +0 -94
  101. package/dist/bot/logic/mission/behaviours/scoutingSquad.js.map +0 -1
  102. package/dist/bot/logic/mission/expansionMission.js +0 -32
  103. package/dist/bot/logic/mission/missions/basicMission.js +0 -13
  104. package/dist/bot/logic/mission/missions/basicMission.js.map +0 -1
  105. package/dist/bot/logic/mission/missions/missionBehaviour.js +0 -2
  106. package/dist/bot/logic/mission/missions/missionBehaviour.js.map +0 -1
  107. package/dist/bot/logic/mission/missions/oneTimeMission.js +0 -27
  108. package/dist/bot/logic/mission/missions/oneTimeMission.js.map +0 -1
  109. package/dist/bot/logic/squad/behaviours/actionBatcher.js +0 -36
  110. package/dist/bot/logic/squad/behaviours/actionBatcher.js.map +0 -1
  111. package/dist/bot/logic/squad/behaviours/attackSquad.js +0 -82
  112. package/dist/bot/logic/squad/behaviours/combatSquad.js +0 -106
  113. package/dist/bot/logic/squad/behaviours/combatSquad.js.map +0 -1
  114. package/dist/bot/logic/squad/behaviours/common.js +0 -55
  115. package/dist/bot/logic/squad/behaviours/common.js.map +0 -1
  116. package/dist/bot/logic/squad/behaviours/defenceSquad.js +0 -48
  117. package/dist/bot/logic/squad/behaviours/engineerSquad.js +0 -38
  118. package/dist/bot/logic/squad/behaviours/engineerSquad.js.map +0 -1
  119. package/dist/bot/logic/squad/behaviours/expansionSquad.js +0 -45
  120. package/dist/bot/logic/squad/behaviours/expansionSquad.js.map +0 -1
  121. package/dist/bot/logic/squad/behaviours/retreatSquad.js +0 -31
  122. package/dist/bot/logic/squad/behaviours/retreatSquad.js.map +0 -1
  123. package/dist/bot/logic/squad/behaviours/scoutingSquad.js +0 -93
  124. package/dist/bot/logic/squad/behaviours/scoutingSquad.js.map +0 -1
  125. package/dist/bot/logic/squad/behaviours/squadExpansion.js +0 -31
  126. package/dist/bot/logic/squad/behaviours/squadScouters.js +0 -8
  127. package/dist/bot/logic/squad/squad.js +0 -126
  128. package/dist/bot/logic/squad/squad.js.map +0 -1
  129. package/dist/bot/logic/squad/squadBehaviour.js +0 -6
  130. package/dist/bot/logic/squad/squadBehaviour.js.map +0 -1
  131. package/dist/bot/logic/squad/squadBehaviours.js +0 -7
  132. package/dist/bot/logic/squad/squadBehaviours.js.map +0 -1
  133. package/dist/bot/logic/squad/squadController.js +0 -215
  134. package/dist/bot/logic/squad/squadController.js.map +0 -1
@@ -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
+ }