@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,160 +1,160 @@
1
- import {
2
- ActionsApi,
3
- AttackState,
4
- GameApi,
5
- GameMath,
6
- MovementZone,
7
- PlayerData,
8
- UnitData,
9
- Vector2,
10
- } from "@chronodivide/game-api";
11
- import { MatchAwareness } from "../../../awareness.js";
12
- import { getAttackWeight, manageAttackMicro, manageMoveMicro } from "./common.js";
13
- import { DebugLogger, isOwnedByNeutral, maxBy, minBy } from "../../../common/utils.js";
14
- import { ActionBatcher, BatchableAction } from "../../actionBatcher.js";
15
- import { Squad } from "./squad.js";
16
- import { Mission, MissionAction, grabCombatants, noop } from "../../mission.js";
17
-
18
- const TARGET_UPDATE_INTERVAL_TICKS = 10;
19
-
20
- // Units must be in a certain radius of the center of mass before attacking.
21
- // This scales for number of units in the squad though.
22
- const MIN_GATHER_RADIUS = 5;
23
-
24
- // If the radius expands beyond this amount then we should switch back to gathering mode.
25
- const MAX_GATHER_RADIUS = 15;
26
-
27
- const GATHER_RATIO = 10;
28
-
29
- const ATTACK_SCAN_AREA = 15;
30
-
31
- enum SquadState {
32
- Gathering,
33
- Attacking,
34
- }
35
-
36
- export class CombatSquad implements Squad {
37
- private lastCommand: number | null = null;
38
- private state = SquadState.Gathering;
39
-
40
- private debugLastTarget: string | undefined;
41
-
42
- private lastOrderGiven: { [unitId: number]: BatchableAction } = {};
43
-
44
- /**
45
- *
46
- * @param rallyArea the initial location to grab combatants
47
- * @param targetArea
48
- * @param radius
49
- */
50
- constructor(
51
- private rallyArea: Vector2,
52
- private targetArea: Vector2,
53
- private radius: number,
54
- ) {}
55
-
56
- public getGlobalDebugText(): string | undefined {
57
- return this.debugLastTarget ?? "<none>";
58
- }
59
-
60
- public setAttackArea(targetArea: Vector2) {
61
- this.targetArea = targetArea;
62
- }
63
-
64
- public onAiUpdate(
65
- gameApi: GameApi,
66
- actionsApi: ActionsApi,
67
- actionBatcher: ActionBatcher,
68
- playerData: PlayerData,
69
- mission: Mission<any>,
70
- matchAwareness: MatchAwareness,
71
- logger: DebugLogger,
72
- ): MissionAction {
73
- if (
74
- mission.getUnitIds().length > 0 &&
75
- (!this.lastCommand || gameApi.getCurrentTick() > this.lastCommand + TARGET_UPDATE_INTERVAL_TICKS)
76
- ) {
77
- this.lastCommand = gameApi.getCurrentTick();
78
- const centerOfMass = mission.getCenterOfMass();
79
- const maxDistance = mission.getMaxDistanceToCenterOfMass();
80
- const units = mission.getUnitsMatching(gameApi, (r) => r.rules.isSelectableCombatant);
81
-
82
- // Only use ground units for center of mass.
83
- const groundUnits = mission.getUnitsMatching(
84
- gameApi,
85
- (r) =>
86
- r.rules.isSelectableCombatant &&
87
- (r.rules.movementZone === MovementZone.Infantry ||
88
- r.rules.movementZone === MovementZone.Normal ||
89
- r.rules.movementZone === MovementZone.InfantryDestroyer),
90
- );
91
-
92
- if (this.state === SquadState.Gathering) {
93
- const requiredGatherRadius = GameMath.sqrt(groundUnits.length) * GATHER_RATIO + MIN_GATHER_RADIUS;
94
- if (
95
- centerOfMass &&
96
- maxDistance &&
97
- gameApi.mapApi.getTile(centerOfMass.x, centerOfMass.y) !== undefined &&
98
- maxDistance > requiredGatherRadius
99
- ) {
100
- units.forEach((unit) => {
101
- this.submitActionIfNew(actionBatcher, manageMoveMicro(unit, centerOfMass));
102
- });
103
- } else {
104
- logger(`CombatSquad ${mission.getUniqueName()} switching back to attack mode (${maxDistance})`);
105
- this.state = SquadState.Attacking;
106
- }
107
- } else {
108
- const targetPoint = this.targetArea || playerData.startLocation;
109
- const requiredGatherRadius = GameMath.sqrt(groundUnits.length) * GATHER_RATIO + MAX_GATHER_RADIUS;
110
- if (
111
- centerOfMass &&
112
- maxDistance &&
113
- gameApi.mapApi.getTile(centerOfMass.x, centerOfMass.y) !== undefined &&
114
- maxDistance > requiredGatherRadius
115
- ) {
116
- // Switch back to gather mode
117
- logger(`CombatSquad ${mission.getUniqueName()} switching back to gather (${maxDistance})`);
118
- this.state = SquadState.Gathering;
119
- return noop();
120
- }
121
- // The unit with the shortest range chooses the target. Otherwise, a base range of 5 is chosen.
122
- const getRangeForUnit = (unit: UnitData) =>
123
- unit.primaryWeapon?.maxRange ?? unit.secondaryWeapon?.maxRange ?? 5;
124
- const attackLeader = minBy(units, getRangeForUnit);
125
- if (!attackLeader) {
126
- return noop();
127
- }
128
- // Find units within double the range of the leader.
129
- const nearbyHostiles = matchAwareness
130
- .getHostilesNearPoint(attackLeader.tile.rx, attackLeader.tile.ry, ATTACK_SCAN_AREA)
131
- .map(({ unitId }) => gameApi.getUnitData(unitId))
132
- .filter((unit) => !isOwnedByNeutral(unit)) as UnitData[];
133
-
134
- for (const unit of units) {
135
- const bestUnit = maxBy(nearbyHostiles, (target) => getAttackWeight(unit, target));
136
- if (bestUnit) {
137
- this.submitActionIfNew(actionBatcher, manageAttackMicro(unit, bestUnit));
138
- this.debugLastTarget = `Unit ${bestUnit.id.toString()}`;
139
- } else {
140
- this.submitActionIfNew(actionBatcher, manageMoveMicro(unit, targetPoint));
141
- this.debugLastTarget = `@${targetPoint.x},${targetPoint.y}`;
142
- }
143
- }
144
- }
145
- }
146
- return noop();
147
- }
148
-
149
- /**
150
- * Sends an action to the acitonBatcher if and only if the action is different from the last action we submitted to it.
151
- * Prevents spamming redundant orders, which affects performance and can also ccause the unit to sit around doing nothing.
152
- */
153
- private submitActionIfNew(actionBatcher: ActionBatcher, action: BatchableAction) {
154
- const lastAction = this.lastOrderGiven[action.unitId];
155
- if (!lastAction || !lastAction.isSameAs(action)) {
156
- actionBatcher.push(action);
157
- this.lastOrderGiven[action.unitId] = action;
158
- }
159
- }
160
- }
1
+ import {
2
+ ActionsApi,
3
+ AttackState,
4
+ GameApi,
5
+ GameMath,
6
+ MovementZone,
7
+ PlayerData,
8
+ UnitData,
9
+ Vector2,
10
+ } from "@chronodivide/game-api";
11
+ import { MatchAwareness } from "../../../awareness.js";
12
+ import { getAttackWeight, manageAttackMicro, manageMoveMicro } from "./common.js";
13
+ import { DebugLogger, isOwnedByNeutral, maxBy, minBy } from "../../../common/utils.js";
14
+ import { ActionBatcher, BatchableAction } from "../../actionBatcher.js";
15
+ import { Squad } from "./squad.js";
16
+ import { Mission, MissionAction, grabCombatants, noop } from "../../mission.js";
17
+
18
+ const TARGET_UPDATE_INTERVAL_TICKS = 10;
19
+
20
+ // Units must be in a certain radius of the center of mass before attacking.
21
+ // This scales for number of units in the squad though.
22
+ const MIN_GATHER_RADIUS = 5;
23
+
24
+ // If the radius expands beyond this amount then we should switch back to gathering mode.
25
+ const MAX_GATHER_RADIUS = 15;
26
+
27
+ const GATHER_RATIO = 10;
28
+
29
+ const ATTACK_SCAN_AREA = 15;
30
+
31
+ enum SquadState {
32
+ Gathering,
33
+ Attacking,
34
+ }
35
+
36
+ export class CombatSquad implements Squad {
37
+ private lastCommand: number | null = null;
38
+ private state = SquadState.Gathering;
39
+
40
+ private debugLastTarget: string | undefined;
41
+
42
+ private lastOrderGiven: { [unitId: number]: BatchableAction } = {};
43
+
44
+ /**
45
+ *
46
+ * @param rallyArea the initial location to grab combatants
47
+ * @param targetArea
48
+ * @param radius
49
+ */
50
+ constructor(
51
+ private rallyArea: Vector2,
52
+ private targetArea: Vector2,
53
+ private radius: number,
54
+ ) {}
55
+
56
+ public getGlobalDebugText(): string | undefined {
57
+ return this.debugLastTarget ?? "<none>";
58
+ }
59
+
60
+ public setAttackArea(targetArea: Vector2) {
61
+ this.targetArea = targetArea;
62
+ }
63
+
64
+ public onAiUpdate(
65
+ gameApi: GameApi,
66
+ actionsApi: ActionsApi,
67
+ actionBatcher: ActionBatcher,
68
+ playerData: PlayerData,
69
+ mission: Mission<any>,
70
+ matchAwareness: MatchAwareness,
71
+ logger: DebugLogger,
72
+ ): MissionAction {
73
+ if (
74
+ mission.getUnitIds().length > 0 &&
75
+ (!this.lastCommand || gameApi.getCurrentTick() > this.lastCommand + TARGET_UPDATE_INTERVAL_TICKS)
76
+ ) {
77
+ this.lastCommand = gameApi.getCurrentTick();
78
+ const centerOfMass = mission.getCenterOfMass();
79
+ const maxDistance = mission.getMaxDistanceToCenterOfMass();
80
+ const units = mission.getUnitsMatching(gameApi, (r) => r.rules.isSelectableCombatant);
81
+
82
+ // Only use ground units for center of mass.
83
+ const groundUnits = mission.getUnitsMatching(
84
+ gameApi,
85
+ (r) =>
86
+ r.rules.isSelectableCombatant &&
87
+ (r.rules.movementZone === MovementZone.Infantry ||
88
+ r.rules.movementZone === MovementZone.Normal ||
89
+ r.rules.movementZone === MovementZone.InfantryDestroyer),
90
+ );
91
+
92
+ if (this.state === SquadState.Gathering) {
93
+ const requiredGatherRadius = GameMath.sqrt(groundUnits.length) * GATHER_RATIO + MIN_GATHER_RADIUS;
94
+ if (
95
+ centerOfMass &&
96
+ maxDistance &&
97
+ gameApi.mapApi.getTile(centerOfMass.x, centerOfMass.y) !== undefined &&
98
+ maxDistance > requiredGatherRadius
99
+ ) {
100
+ units.forEach((unit) => {
101
+ this.submitActionIfNew(actionBatcher, manageMoveMicro(unit, centerOfMass));
102
+ });
103
+ } else {
104
+ logger(`CombatSquad ${mission.getUniqueName()} switching back to attack mode (${maxDistance})`);
105
+ this.state = SquadState.Attacking;
106
+ }
107
+ } else {
108
+ const targetPoint = this.targetArea || playerData.startLocation;
109
+ const requiredGatherRadius = GameMath.sqrt(groundUnits.length) * GATHER_RATIO + MAX_GATHER_RADIUS;
110
+ if (
111
+ centerOfMass &&
112
+ maxDistance &&
113
+ gameApi.mapApi.getTile(centerOfMass.x, centerOfMass.y) !== undefined &&
114
+ maxDistance > requiredGatherRadius
115
+ ) {
116
+ // Switch back to gather mode
117
+ logger(`CombatSquad ${mission.getUniqueName()} switching back to gather (${maxDistance})`);
118
+ this.state = SquadState.Gathering;
119
+ return noop();
120
+ }
121
+ // The unit with the shortest range chooses the target. Otherwise, a base range of 5 is chosen.
122
+ const getRangeForUnit = (unit: UnitData) =>
123
+ unit.primaryWeapon?.maxRange ?? unit.secondaryWeapon?.maxRange ?? 5;
124
+ const attackLeader = minBy(units, getRangeForUnit);
125
+ if (!attackLeader) {
126
+ return noop();
127
+ }
128
+ // Find units within double the range of the leader.
129
+ const nearbyHostiles = matchAwareness
130
+ .getHostilesNearPoint(attackLeader.tile.rx, attackLeader.tile.ry, ATTACK_SCAN_AREA)
131
+ .map(({ unitId }) => gameApi.getUnitData(unitId))
132
+ .filter((unit) => !isOwnedByNeutral(unit)) as UnitData[];
133
+
134
+ for (const unit of units) {
135
+ const bestUnit = maxBy(nearbyHostiles, (target) => getAttackWeight(unit, target));
136
+ if (bestUnit) {
137
+ this.submitActionIfNew(actionBatcher, manageAttackMicro(unit, bestUnit));
138
+ this.debugLastTarget = `Unit ${bestUnit.id.toString()}`;
139
+ } else {
140
+ this.submitActionIfNew(actionBatcher, manageMoveMicro(unit, targetPoint));
141
+ this.debugLastTarget = `@${targetPoint.x},${targetPoint.y}`;
142
+ }
143
+ }
144
+ }
145
+ }
146
+ return noop();
147
+ }
148
+
149
+ /**
150
+ * Sends an action to the acitonBatcher if and only if the action is different from the last action we submitted to it.
151
+ * Prevents spamming redundant orders, which affects performance and can also ccause the unit to sit around doing nothing.
152
+ */
153
+ private submitActionIfNew(actionBatcher: ActionBatcher, action: BatchableAction) {
154
+ const lastAction = this.lastOrderGiven[action.unitId];
155
+ if (!lastAction || !lastAction.isSameAs(action)) {
156
+ actionBatcher.push(action);
157
+ this.lastOrderGiven[action.unitId] = action;
158
+ }
159
+ }
160
+ }
@@ -1,63 +1,63 @@
1
- import { AttackState, ObjectType, OrderType, StanceType, UnitData, Vector2, ZoneType } from "@chronodivide/game-api";
2
- import { getDistanceBetweenPoints, getDistanceBetweenUnits } from "../../../map/map.js";
3
- import { BatchableAction } from "../../actionBatcher.js";
4
-
5
- const NONCE_GI_DEPLOY = 0;
6
- const NONCE_GI_UNDEPLOY = 1;
7
-
8
- // Micro methods
9
- export function manageMoveMicro(attacker: UnitData, attackPoint: Vector2): BatchableAction {
10
- if (attacker.name === "E1") {
11
- const isDeployed = attacker.stance === StanceType.Deployed;
12
- if (isDeployed) {
13
- return BatchableAction.noTarget(attacker.id, OrderType.DeploySelected, NONCE_GI_UNDEPLOY);
14
- }
15
- }
16
-
17
- return BatchableAction.toPoint(attacker.id, OrderType.AttackMove, attackPoint);
18
- }
19
-
20
- export function manageAttackMicro(attacker: UnitData, target: UnitData): BatchableAction {
21
- const distance = getDistanceBetweenUnits(attacker, target);
22
- if (attacker.name === "E1") {
23
- // Para (deployed weapon) range is 5.
24
- const deployedWeaponRange = attacker.secondaryWeapon?.maxRange || 5;
25
- const isDeployed = attacker.stance === StanceType.Deployed;
26
- if (!isDeployed && (distance <= deployedWeaponRange || attacker.attackState === AttackState.JustFired)) {
27
- return BatchableAction.noTarget(attacker.id, OrderType.DeploySelected, NONCE_GI_DEPLOY);
28
- } else if (isDeployed && distance > deployedWeaponRange) {
29
- return BatchableAction.noTarget(attacker.id, OrderType.DeploySelected, NONCE_GI_UNDEPLOY);
30
- }
31
- }
32
- let targetData = target;
33
- let orderType: OrderType = OrderType.Attack;
34
- const primaryWeaponRange = attacker.primaryWeapon?.maxRange || 5;
35
- if (targetData?.type == ObjectType.Building && distance < primaryWeaponRange * 0.8) {
36
- orderType = OrderType.Attack;
37
- } else if (targetData?.rules.canDisguise) {
38
- // Special case for mirage tank/spy as otherwise they just sit next to it.
39
- orderType = OrderType.Attack;
40
- }
41
- return BatchableAction.toTargetId(attacker.id, orderType, target.id);
42
- }
43
-
44
- /**
45
- *
46
- * @param attacker
47
- * @param target
48
- * @returns A number describing the weight of the given target for the attacker, or null if it should not attack it.
49
- */
50
- export function getAttackWeight(attacker: UnitData, target: UnitData): number | null {
51
- const { rx: x, ry: y } = attacker.tile;
52
- const { rx: hX, ry: hY } = target.tile;
53
-
54
- if (!attacker.primaryWeapon?.projectileRules.isAntiAir && target.zone === ZoneType.Air) {
55
- return null;
56
- }
57
-
58
- if (!attacker.primaryWeapon?.projectileRules.isAntiGround && target.zone === ZoneType.Ground) {
59
- return null;
60
- }
61
-
62
- return 1000000 - getDistanceBetweenPoints(new Vector2(x, y), new Vector2(hX, hY));
63
- }
1
+ import { AttackState, ObjectType, OrderType, StanceType, UnitData, Vector2, ZoneType } from "@chronodivide/game-api";
2
+ import { getDistanceBetweenPoints, getDistanceBetweenUnits } from "../../../map/map.js";
3
+ import { BatchableAction } from "../../actionBatcher.js";
4
+
5
+ const NONCE_GI_DEPLOY = 0;
6
+ const NONCE_GI_UNDEPLOY = 1;
7
+
8
+ // Micro methods
9
+ export function manageMoveMicro(attacker: UnitData, attackPoint: Vector2): BatchableAction {
10
+ if (attacker.name === "E1") {
11
+ const isDeployed = attacker.stance === StanceType.Deployed;
12
+ if (isDeployed) {
13
+ return BatchableAction.noTarget(attacker.id, OrderType.DeploySelected, NONCE_GI_UNDEPLOY);
14
+ }
15
+ }
16
+
17
+ return BatchableAction.toPoint(attacker.id, OrderType.AttackMove, attackPoint);
18
+ }
19
+
20
+ export function manageAttackMicro(attacker: UnitData, target: UnitData): BatchableAction {
21
+ const distance = getDistanceBetweenUnits(attacker, target);
22
+ if (attacker.name === "E1") {
23
+ // Para (deployed weapon) range is 5.
24
+ const deployedWeaponRange = attacker.secondaryWeapon?.maxRange || 5;
25
+ const isDeployed = attacker.stance === StanceType.Deployed;
26
+ if (!isDeployed && (distance <= deployedWeaponRange || attacker.attackState === AttackState.JustFired)) {
27
+ return BatchableAction.noTarget(attacker.id, OrderType.DeploySelected, NONCE_GI_DEPLOY);
28
+ } else if (isDeployed && distance > deployedWeaponRange) {
29
+ return BatchableAction.noTarget(attacker.id, OrderType.DeploySelected, NONCE_GI_UNDEPLOY);
30
+ }
31
+ }
32
+ let targetData = target;
33
+ let orderType: OrderType = OrderType.Attack;
34
+ const primaryWeaponRange = attacker.primaryWeapon?.maxRange || 5;
35
+ if (targetData?.type == ObjectType.Building && distance < primaryWeaponRange * 0.8) {
36
+ orderType = OrderType.Attack;
37
+ } else if (targetData?.rules.canDisguise) {
38
+ // Special case for mirage tank/spy as otherwise they just sit next to it.
39
+ orderType = OrderType.Attack;
40
+ }
41
+ return BatchableAction.toTargetId(attacker.id, orderType, target.id);
42
+ }
43
+
44
+ /**
45
+ *
46
+ * @param attacker
47
+ * @param target
48
+ * @returns A number describing the weight of the given target for the attacker, or null if it should not attack it.
49
+ */
50
+ export function getAttackWeight(attacker: UnitData, target: UnitData): number | null {
51
+ const { rx: x, ry: y } = attacker.tile;
52
+ const { rx: hX, ry: hY } = target.tile;
53
+
54
+ if (!attacker.primaryWeapon?.projectileRules.isAntiAir && target.zone === ZoneType.Air) {
55
+ return null;
56
+ }
57
+
58
+ if (!attacker.primaryWeapon?.projectileRules.isAntiGround && target.zone === ZoneType.Ground) {
59
+ return null;
60
+ }
61
+
62
+ return 1000000 - getDistanceBetweenPoints(new Vector2(x, y), new Vector2(hX, hY));
63
+ }
@@ -1,19 +1,19 @@
1
- import { ActionsApi, GameApi, PlayerData } from "@chronodivide/game-api";
2
- import { ActionBatcher } from "../../actionBatcher";
3
- import { Mission, MissionAction } from "../../mission";
4
- import { MatchAwareness } from "../../../awareness";
5
- import { DebugLogger } from "../../../common/utils";
6
-
7
- export interface Squad {
8
- onAiUpdate(
9
- gameApi: GameApi,
10
- actionsApi: ActionsApi,
11
- actionBatcher: ActionBatcher,
12
- playerData: PlayerData,
13
- mission: Mission<any>,
14
- matchAwareness: MatchAwareness,
15
- logger: DebugLogger,
16
- ): MissionAction;
17
-
18
- getGlobalDebugText(): string | undefined;
19
- }
1
+ import { ActionsApi, GameApi, PlayerData } from "@chronodivide/game-api";
2
+ import { ActionBatcher } from "../../actionBatcher";
3
+ import { Mission, MissionAction } from "../../mission";
4
+ import { MatchAwareness } from "../../../awareness";
5
+ import { DebugLogger } from "../../../common/utils";
6
+
7
+ export interface Squad {
8
+ onAiUpdate(
9
+ gameApi: GameApi,
10
+ actionsApi: ActionsApi,
11
+ actionBatcher: ActionBatcher,
12
+ playerData: PlayerData,
13
+ mission: Mission<any>,
14
+ matchAwareness: MatchAwareness,
15
+ logger: DebugLogger,
16
+ ): MissionAction;
17
+
18
+ getGlobalDebugText(): string | undefined;
19
+ }