mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added options for miss on purpose and scenic AAA
This commit is contained in:
@@ -688,7 +688,6 @@ export class Map extends L.Map {
|
||||
this.#isZooming = false;
|
||||
}
|
||||
|
||||
|
||||
#panToUnit(unit: Unit) {
|
||||
var unitPosition = new L.LatLng(unit.getPosition().lat, unit.getPosition().lng);
|
||||
this.setView(unitPosition, this.getZoom(), { animate: false });
|
||||
|
||||
@@ -17,6 +17,7 @@ export class UnitControlPanel extends Panel {
|
||||
#speedTypeSwitch: Switch;
|
||||
#onOffSwitch: Switch;
|
||||
#followRoadsSwitch: Switch;
|
||||
#operateAs: Switch;
|
||||
#TACANXYDropdown: Dropdown;
|
||||
#radioDecimalsDropdown: Dropdown;
|
||||
#radioCallsignDropdown: Dropdown;
|
||||
@@ -67,6 +68,11 @@ export class UnitControlPanel extends Panel {
|
||||
getApp().getUnitsManager().selectedUnitsSetFollowRoads(value);
|
||||
});
|
||||
|
||||
/* Operate as */
|
||||
this.#operateAs = new Switch("operate-as-switch", (value: boolean) => {
|
||||
//getApp().getUnitsManager().selectedUnitsSetFollowRoads(value);
|
||||
});
|
||||
|
||||
/* Advanced settings dialog */
|
||||
this.#advancedSettingsDialog = <HTMLElement> document.querySelector("#advanced-settings-dialog");
|
||||
|
||||
@@ -80,21 +86,28 @@ export class UnitControlPanel extends Panel {
|
||||
/* Events and timer */
|
||||
window.setInterval(() => {this.update();}, 25);
|
||||
|
||||
document.addEventListener("unitsSelection", (e: CustomEvent<Unit[]>) => { this.show(); this.addButtons();});
|
||||
document.addEventListener("clearSelection", () => { this.hide() });
|
||||
document.addEventListener("unitsSelection", (e: CustomEvent<Unit[]>) => {
|
||||
this.show();
|
||||
this.addButtons();
|
||||
this.#updateRapidControls();
|
||||
});
|
||||
document.addEventListener("clearSelection", () => {
|
||||
this.hide();
|
||||
this.#updateRapidControls();
|
||||
});
|
||||
document.addEventListener("applyAdvancedSettings", () => {this.#applyAdvancedSettings();})
|
||||
document.addEventListener("showAdvancedSettings", () => {
|
||||
this.#updateAdvancedSettingsDialog(getApp().getUnitsManager().getSelectedUnits());
|
||||
this.#advancedSettingsDialog.classList.remove("hide");
|
||||
});
|
||||
|
||||
this.hide();
|
||||
|
||||
// This is for when a ctrl-click happens on the map for deselection and we need to remove the selected unit from the panel
|
||||
/* This is for when a ctrl-click happens on the map for deselection and we need to remove the selected unit from the panel */
|
||||
document.addEventListener( "unitDeselection", ( ev:CustomEventInit ) => {
|
||||
this.getElement().querySelector( `button[data-unit-id="${ev.detail.ID}"]` )?.remove();
|
||||
this.#updateRapidControls();
|
||||
});
|
||||
|
||||
|
||||
this.hide();
|
||||
}
|
||||
|
||||
show() {
|
||||
@@ -157,6 +170,7 @@ export class UnitControlPanel extends Panel {
|
||||
element.toggleAttribute("data-show-emissions-countermeasures", (this.#selectedUnitsTypes.includes("Aircraft") || this.#selectedUnitsTypes.includes("Helicopter")) && !(this.#selectedUnitsTypes.includes("GroundUnit") || this.#selectedUnitsTypes.includes("NavyUnit")));
|
||||
element.toggleAttribute("data-show-on-off", (this.#selectedUnitsTypes.includes("GroundUnit") || this.#selectedUnitsTypes.includes("NavyUnit")) && !(this.#selectedUnitsTypes.includes("Aircraft") || this.#selectedUnitsTypes.includes("Helicopter")));
|
||||
element.toggleAttribute("data-show-follow-roads", (this.#selectedUnitsTypes.length == 1 && this.#selectedUnitsTypes.includes("GroundUnit")));
|
||||
element.toggleAttribute("data-show-operate-as", getApp().getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getCoalition()}) === "neutral");
|
||||
element.toggleAttribute("data-show-advanced-settings-button", this.#units.length == 1);
|
||||
|
||||
if (this.#selectedUnitsTypes.length == 1) {
|
||||
@@ -208,6 +222,59 @@ export class UnitControlPanel extends Panel {
|
||||
}
|
||||
}
|
||||
|
||||
#updateRapidControls() {
|
||||
var options: { [key: string]: { text: string, tooltip: string, type: string } } | null = null;
|
||||
|
||||
var selectedUnits = getApp().getUnitsManager().getSelectedUnits();
|
||||
|
||||
var showAltitudeChange = selectedUnits.some((unit: Unit) => {return ["Aircraft", "Helicopter"].includes(unit.getCategory());});
|
||||
this.getElement().querySelector("#climb")?.classList.toggle("hide", !showAltitudeChange);
|
||||
this.getElement().querySelector("#descend")?.classList.toggle("hide", !showAltitudeChange);
|
||||
|
||||
/* Keep only the common "and" options, unless a single unit is selected */
|
||||
selectedUnits.forEach((unit: Unit) => {
|
||||
var unitOptions = unit.getActions();
|
||||
if (options === null) {
|
||||
options = unitOptions;
|
||||
} else {
|
||||
/* Delete all the "or" type options */
|
||||
for (let optionKey in options) {
|
||||
if (options[optionKey].type == "or") {
|
||||
delete options[optionKey];
|
||||
}
|
||||
}
|
||||
|
||||
/* Options of "and" type get shown if ALL units have it */
|
||||
for (let optionKey in options) {
|
||||
if (!(optionKey in unitOptions)) {
|
||||
delete options[optionKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
options = options ?? {};
|
||||
|
||||
const rapidControlsContainer = this.getElement().querySelector("#rapid-controls") as HTMLElement;
|
||||
const unitActionButtons = rapidControlsContainer.querySelectorAll(".unit-action-button");
|
||||
for (let button of unitActionButtons) {
|
||||
rapidControlsContainer.removeChild(button);
|
||||
}
|
||||
|
||||
for (let option in options) {
|
||||
let button = document.createElement("button");
|
||||
button.title = options[option].tooltip;
|
||||
button.classList.add("ol-button", "unit-action-button");
|
||||
button.id = option;
|
||||
rapidControlsContainer.appendChild(button);
|
||||
button.onclick = () => {
|
||||
/* Since only common actions are shown in the rapid controls, we execute it only on the first unit */
|
||||
if (selectedUnits.length > 0)
|
||||
selectedUnits[0].executeAction(null, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#updateAdvancedSettingsDialog(units: Unit[])
|
||||
{
|
||||
if (units.length == 1)
|
||||
|
||||
@@ -329,14 +329,14 @@ export class ServerManager {
|
||||
this.PUT(data, callback);
|
||||
}
|
||||
|
||||
scenicAAA(ID: number, callback: CallableFunction = () => {}) {
|
||||
var command = { "ID": ID }
|
||||
scenicAAA(ID: number, coalition: string, callback: CallableFunction = () => {}) {
|
||||
var command = { "ID": ID, "coalition": coalition }
|
||||
var data = { "scenicAAA": command }
|
||||
this.PUT(data, callback);
|
||||
}
|
||||
|
||||
missOnPurpose(ID: number, callback: CallableFunction = () => {}) {
|
||||
var command = { "ID": ID }
|
||||
missOnPurpose(ID: number, coalition: string, callback: CallableFunction = () => {}) {
|
||||
var command = { "ID": ID, "coalition": coalition }
|
||||
var data = { "missOnPurpose": command }
|
||||
this.PUT(data, callback);
|
||||
}
|
||||
|
||||
@@ -588,15 +588,7 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
isInViewport() {
|
||||
|
||||
const mapBounds = getApp().getMap().getBounds();
|
||||
const unitPos = this.getPosition();
|
||||
|
||||
return (unitPos.lng > mapBounds.getWest()
|
||||
&& unitPos.lng < mapBounds.getEast()
|
||||
&& unitPos.lat > mapBounds.getSouth()
|
||||
&& unitPos.lat < mapBounds.getNorth());
|
||||
|
||||
return getApp().getMap().getBounds().contains(this.getPosition());
|
||||
}
|
||||
|
||||
/********************** Unit commands *************************/
|
||||
@@ -739,14 +731,40 @@ export class Unit extends CustomMarker {
|
||||
});
|
||||
}
|
||||
|
||||
scenicAAA() {
|
||||
getApp().getServerManager().scenicAAA(this.ID);
|
||||
scenicAAA(coalition: string) {
|
||||
getApp().getServerManager().scenicAAA(this.ID, coalition);
|
||||
}
|
||||
|
||||
missOnPurpose() {
|
||||
getApp().getServerManager().missOnPurpose(this.ID);
|
||||
missOnPurpose(coalition: string) {
|
||||
getApp().getServerManager().missOnPurpose(this.ID, coalition);
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
getActions(): { [key: string]: { text: string, tooltip: string, type: string } } {
|
||||
/* To be implemented by child classes */ // TODO make Unit an abstract class
|
||||
return {};
|
||||
}
|
||||
|
||||
executeAction(e: any, action: string) {
|
||||
if (action === "center-map")
|
||||
getApp().getMap().centerOnUnit(this.ID);
|
||||
if (action === "attack")
|
||||
getApp().getUnitsManager().selectedUnitsAttackUnit(this.ID);
|
||||
else if (action === "refuel")
|
||||
getApp().getUnitsManager().selectedUnitsRefuel();
|
||||
else if (action === "group-ground" || action === "group-navy")
|
||||
getApp().getUnitsManager().selectedUnitsCreateGroup();
|
||||
else if (action === "scenic-aaa-red")
|
||||
getApp().getUnitsManager().selectedUnitsScenicAAA("red");
|
||||
else if (action === "scenic-aaa-blue")
|
||||
getApp().getUnitsManager().selectedUnitsScenicAAA("blue");
|
||||
else if (action === "miss-aaa-red")
|
||||
getApp().getUnitsManager().selectedUnitsMissOnPurpose("red");
|
||||
else if (action === "miss-aaa-blue")
|
||||
getApp().getUnitsManager().selectedUnitsMissOnPurpose("blue");
|
||||
else if (action === "follow")
|
||||
this.#showFollowOptions(e);
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
onAdd(map: Map): this {
|
||||
@@ -761,18 +779,18 @@ export class Unit extends CustomMarker {
|
||||
if (this.#waitingForDoubleClick) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// We'll wait for a doubleclick
|
||||
this.#waitingForDoubleClick = true;
|
||||
|
||||
this.#doubleClickTimer = window.setTimeout(() => {
|
||||
this.#doubleClickTimer = window.setTimeout(() => {
|
||||
|
||||
// Still waiting so no doubleclick; do the click action
|
||||
if (this.#waitingForDoubleClick) {
|
||||
if (getApp().getMap().getState() === IDLE || getApp().getMap().getState() === MOVE_UNIT || e.originalEvent.ctrlKey) {
|
||||
if (!e.originalEvent.ctrlKey)
|
||||
getApp().getUnitsManager().deselectAllUnits();
|
||||
|
||||
|
||||
this.setSelected(!this.getSelected());
|
||||
const detail = { "detail": { "unit": this } };
|
||||
if (this.getSelected())
|
||||
@@ -788,7 +806,6 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any) {
|
||||
|
||||
// Let single clicks work again
|
||||
this.#waitingForDoubleClick = false;
|
||||
clearTimeout(this.#doubleClickTimer);
|
||||
@@ -801,58 +818,49 @@ export class Unit extends CustomMarker {
|
||||
});
|
||||
}
|
||||
|
||||
#onContextMenu(e: any) {
|
||||
var options: { [key: string]: { text: string, tooltip: string } } = {};
|
||||
const selectedUnits = getApp().getUnitsManager().getSelectedUnits();
|
||||
const selectedUnitTypes = getApp().getUnitsManager().getSelectedUnitsCategories();
|
||||
getActionOptions() {
|
||||
var options: { [key: string]: { text: string, tooltip: string, type: string } } | null = null;
|
||||
|
||||
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it" };
|
||||
var units = getApp().getUnitsManager().getSelectedUnits();
|
||||
units.push(this);
|
||||
|
||||
if (selectedUnits.length > 0 && !(selectedUnits.length == 1 && (selectedUnits.includes(this)))) {
|
||||
options["attack"] = { text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons" };
|
||||
if (getApp().getUnitsManager().getSelectedUnitsCategories().length == 1 && getApp().getUnitsManager().getSelectedUnitsCategories()[0] === "Aircraft")
|
||||
options["follow"] = { text: "Follow", tooltip: "Follow the unit at a user defined distance and position" };
|
||||
}
|
||||
else if ((selectedUnits.length > 0 && (selectedUnits.includes(this))) || selectedUnits.length == 0) {
|
||||
if (this.getCategory() == "Aircraft") {
|
||||
options["refuel"] = { text: "Air to air refuel", tooltip: "Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB." }; // TODO Add some way of knowing which aircraft can AAR
|
||||
/* Keep only the common "or" options or any "and" option */
|
||||
units.forEach((unit: Unit) => {
|
||||
var unitOptions = unit.getActions();
|
||||
if (options === null) {
|
||||
options = unitOptions;
|
||||
} else {
|
||||
/* Options of "or" type get shown if any one unit has it*/
|
||||
for (let optionKey in unitOptions) {
|
||||
if (unitOptions[optionKey].type == "or") {
|
||||
options[optionKey] = unitOptions[optionKey];
|
||||
}
|
||||
}
|
||||
|
||||
/* Options of "and" type get shown if ALL units have it */
|
||||
for (let optionKey in options) {
|
||||
if (!(optionKey in unitOptions)) {
|
||||
delete options[optionKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (selectedUnitTypes.length === 1 && ["NavyUnit", "GroundUnit"].includes(selectedUnitTypes[0]) && getApp().getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getCoalition()}) !== undefined)
|
||||
options["group"] = { text: "Create group", tooltip: "Create a group from the selected units." };
|
||||
return options ?? {};
|
||||
}
|
||||
|
||||
if (selectedUnitTypes.length === 1 && ["GroundUnit"].includes(selectedUnitTypes[0]) && selectedUnits.every((unit: Unit) => { return ["AAA"].includes(unit.getType())})) {
|
||||
options["scenic-aaa"] = { text: "Scenic AAA", tooltip: "Shoot AAA in the air without aiming at any target" };
|
||||
options["miss-aaa"] = { text: "Miss on purpose AAA", tooltip: "Shoot AAA towards the closes enemy, but don't aim precisely" };
|
||||
}
|
||||
#onContextMenu(e: any) {
|
||||
var options = this.getActionOptions();
|
||||
|
||||
if (Object.keys(options).length > 0) {
|
||||
getApp().getMap().showUnitContextMenu(e.originalEvent.x, e.originalEvent.y, e.latlng);
|
||||
getApp().getMap().getUnitContextMenu().setOptions(options, (option: string) => {
|
||||
getApp().getMap().hideUnitContextMenu();
|
||||
this.#executeAction(e, option);
|
||||
this.executeAction(e, option);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#executeAction(e: any, action: string) {
|
||||
if (action === "center-map")
|
||||
getApp().getMap().centerOnUnit(this.ID);
|
||||
if (action === "attack")
|
||||
getApp().getUnitsManager().selectedUnitsAttackUnit(this.ID);
|
||||
else if (action === "refuel")
|
||||
getApp().getUnitsManager().selectedUnitsRefuel();
|
||||
else if (action === "group")
|
||||
getApp().getUnitsManager().selectedUnitsCreateGroup();
|
||||
else if (action === "scenic-aaa")
|
||||
getApp().getUnitsManager().selectedUnitsScenicAAA();
|
||||
else if (action === "miss-aaa")
|
||||
getApp().getUnitsManager().selectedUnitsMissOnPurpose();
|
||||
else if (action === "follow")
|
||||
this.#showFollowOptions(e);
|
||||
}
|
||||
|
||||
#showFollowOptions(e: any) {
|
||||
var options: { [key: string]: { text: string, tooltip: string } } = {};
|
||||
|
||||
@@ -892,14 +900,14 @@ export class Unit extends CustomMarker {
|
||||
var angleRad = deg2rad(angleDeg);
|
||||
var distance = ftToM(parseInt((<HTMLInputElement>dialog.querySelector(`#distance`)?.querySelector("input")).value));
|
||||
var upDown = ftToM(parseInt((<HTMLInputElement>dialog.querySelector(`#up-down`)?.querySelector("input")).value));
|
||||
|
||||
|
||||
// X: front-rear, positive front
|
||||
// Y: top-bottom, positive top
|
||||
// Z: left-right, positive right
|
||||
var x = distance * Math.cos(angleRad);
|
||||
var y = upDown;
|
||||
var z = distance * Math.sin(angleRad);
|
||||
|
||||
|
||||
getApp().getUnitsManager().selectedUnitsFollowUnit(this.ID, { "x": x, "y": y, "z": z });
|
||||
}
|
||||
});
|
||||
@@ -1166,6 +1174,37 @@ export class AirUnit extends Unit {
|
||||
rotateToHeading: false
|
||||
};
|
||||
}
|
||||
|
||||
getActions() {
|
||||
var options: { [key: string]: { text: string, tooltip: string, type: string } } = {};
|
||||
|
||||
/* Options if this unit is not selected */
|
||||
if (!this.getSelected()) {
|
||||
/* Someone else is selected */
|
||||
if (getApp().getUnitsManager().getSelectedUnits().length > 0) {
|
||||
options["attack"] = { text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons", type: "or" };
|
||||
options["follow"] = { text: "Follow", tooltip: "Follow the unit at a user defined distance and position", type: "or" };
|
||||
} else {
|
||||
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
|
||||
}
|
||||
}
|
||||
/* Options if this unit is selected*/
|
||||
else if (this.getSelected()) {
|
||||
/* This is the only selected unit */
|
||||
if (getApp().getUnitsManager().getSelectedUnits().length == 1) {
|
||||
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
|
||||
} else {
|
||||
/* Provision */
|
||||
}
|
||||
|
||||
options["refuel"] = { text: "Air to air refuel", tooltip: "Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB.", type: "and" }; // TODO Add some way of knowing which aircraft can AAR
|
||||
}
|
||||
/* All other options */
|
||||
else {
|
||||
/* Provision */
|
||||
}
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
export class Aircraft extends AirUnit {
|
||||
@@ -1209,6 +1248,41 @@ export class GroundUnit extends Unit {
|
||||
};
|
||||
}
|
||||
|
||||
getActions() {
|
||||
var options: { [key: string]: { text: string, tooltip: string, type: string } } = {};
|
||||
|
||||
/* Options if this unit is not selected */
|
||||
if (!this.getSelected()) {
|
||||
/* Someone else is selected */
|
||||
if (getApp().getUnitsManager().getSelectedUnits().length > 0) {
|
||||
options["attack"] = { text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons", type: "or" };
|
||||
} else {
|
||||
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
|
||||
}
|
||||
}
|
||||
/* Options if this unit is selected*/
|
||||
else if (this.getSelected()) {
|
||||
/* This is the only selected unit */
|
||||
if (getApp().getUnitsManager().getSelectedUnits().length == 1) {
|
||||
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
|
||||
} else {
|
||||
options["group-ground"] = { text: "Create group", tooltip: "Create a group from the selected units", type: "and" };
|
||||
}
|
||||
|
||||
if (["AAA", "flak"].includes(this.getType())) {
|
||||
options["scenic-aaa-red"] = { text: "Scenic AAA (red)", tooltip: "Shoot AAA in the air without aiming at any target, when a red air unit gets close enough", type: "and" };
|
||||
options["scenic-aaa-blue"] = { text: "Scenic AAA (blue)", tooltip: "Shoot AAA in the air without aiming at any target, when a blue air unit gets close enough", type: "and" };
|
||||
options["miss-aaa-red"] = { text: "Miss on purpose AAA (red)", tooltip: "Shoot AAA towards the closest red air unit, but don't aim precisely", type: "and" };
|
||||
options["miss-aaa-blue"] = { text: "Miss on purpose AAA (blue)", tooltip: "Shoot AAA towards the closest blue air unit, but don't aim precisely", type: "and" };
|
||||
}
|
||||
}
|
||||
/* All other options */
|
||||
else {
|
||||
/* Provision */
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
getCategory() {
|
||||
return "GroundUnit";
|
||||
}
|
||||
@@ -1240,6 +1314,34 @@ export class NavyUnit extends Unit {
|
||||
};
|
||||
}
|
||||
|
||||
getActions() {
|
||||
var options: { [key: string]: { text: string, tooltip: string, type: string } } = {};
|
||||
|
||||
/* Options if this unit is not selected */
|
||||
if (!this.getSelected()) {
|
||||
/* Someone else is selected */
|
||||
if (getApp().getUnitsManager().getSelectedUnits().length > 0) {
|
||||
options["attack"] = { text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons", type: "or" };
|
||||
} else {
|
||||
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
|
||||
}
|
||||
}
|
||||
/* Options if this unit is selected */
|
||||
else if (this.getSelected()) {
|
||||
/* This is the only selected unit */
|
||||
if (getApp().getUnitsManager().getSelectedUnits().length == 1) {
|
||||
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
|
||||
} else {
|
||||
options["group-navy"] = { text: "Create group", tooltip: "Create a group from the selected units", type: "and" };
|
||||
}
|
||||
}
|
||||
/* All other options */
|
||||
else {
|
||||
/* Provision */
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
getMarkerCategory() {
|
||||
return "navyunit";
|
||||
}
|
||||
|
||||
@@ -629,21 +629,23 @@ export class UnitsManager {
|
||||
/** Instruct units to enter into scenic AAA mode. Units will shoot in the air without aiming
|
||||
*
|
||||
*/
|
||||
selectedUnitsScenicAAA() {
|
||||
selectedUnitsScenicAAA(coalition: string) {
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].scenicAAA();
|
||||
selectedUnits[idx].scenicAAA(coalition);
|
||||
}
|
||||
this.#showActionMessage(selectedUnits, `unit set to perform scenic AAA against ${coalition} units`);
|
||||
}
|
||||
|
||||
/** Instruct units to enter into miss on purpose mode. Units will aim to the nearest enemy unit but not precisely.
|
||||
*
|
||||
*/
|
||||
selectedUnitsMissOnPurpose() {
|
||||
selectedUnitsMissOnPurpose(coalition: string) {
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].missOnPurpose();
|
||||
selectedUnits[idx].missOnPurpose(coalition);
|
||||
}
|
||||
this.#showActionMessage(selectedUnits, `unit set to perform miss on purpose AAA against ${coalition} units`);
|
||||
}
|
||||
|
||||
/*********************** Control operations on selected units ************************/
|
||||
|
||||
Reference in New Issue
Block a user