Added hotkeys

This commit is contained in:
Pax1601 2024-11-09 18:22:21 +01:00
parent c2b0849fb6
commit 95e18f6503
9 changed files with 372 additions and 384 deletions

View File

@ -80,7 +80,9 @@ export class AudioUnitPipeline {
/* Don't bother updating parameters if the client is too far away */
if (this.#distance < this.#maxDistance) {
/* Compute a new gain decreasing with distance. */
let newGain = 1.0 - Math.pow(this.#distance / this.#maxDistance, 1); // Arbitrary
//let newGain = 1.0 - Math.pow(this.#distance / this.#maxDistance, 1); // Arbitrary
let newGain = Math.min( 1, 20 / this.#distance )
/* Set the values of the main gain node and the multitap gain node, used for reverb effect */
this.#gainNode.gain.setValueAtTime(newGain, getApp().getAudioManager().getAudioContext().currentTime);

View File

@ -1,6 +1,29 @@
import { LatLng, LatLngBounds } from "leaflet";
import { MapOptions } from "../types/types";
import { CommandModeOptions } from "../interfaces";
import { ContextAction } from "../unit/contextaction";
import {
faExplosion,
faHand,
faLocationCrosshairs,
faLocationDot,
faMapLocation,
faPeopleGroup,
faPlaneArrival,
faRoute,
faTrash,
faXmarksLines,
} from "@fortawesome/free-solid-svg-icons";
import { Unit } from "../unit/unit";
import { getApp } from "../olympusapp";
import {
olButtonsContextAttack,
olButtonsContextFollow,
olButtonsContextLandAtPoint,
olButtonsContextRefuel,
olButtonsContextSimulateFireFight,
} from "../ui/components/olicons";
import { FormationCreationRequestEvent, UnitExplosionRequestEvent } from "../events";
export const UNITS_URI = "units";
export const WEAPONS_URI = "weapons";
@ -308,7 +331,7 @@ export const MAP_OPTIONS_DEFAULTS = {
fillSelectedRing: false,
showMinimap: false,
protectDCSUnits: true,
keepRelativePositions: true
keepRelativePositions: true,
} as MapOptions;
export const MAP_HIDDEN_TYPES_DEFAULTS = {
@ -400,6 +423,12 @@ export enum AudioMessageType {
settings,
}
export enum ContextActionTarget {
NONE,
UNIT,
POINT,
}
export enum ContextActionType {
NO_COLOR,
MOVE,
@ -408,6 +437,238 @@ export enum ContextActionType {
ENGAGE,
DELETE,
}
export const CONTEXT_ACTION_COLORS = [null, "white", "green", "purple", "blue", "red"];
export namespace ContextActions {
export const STOP = new ContextAction(
"stop",
"Stop unit",
"Stops the unit",
faHand,
ContextActionTarget.NONE,
(units: Unit[], _1, _2) => {
getApp().getUnitsManager().stop(units);
},
{
executeImmediately: true,
type: ContextActionType.MOVE,
hotkey: "KeyZ",
}
);
export const MOVE = new ContextAction(
"move",
"Set destination",
"Click on the map to move the units there",
faLocationDot,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition, originalEvent) => {
if (!originalEvent?.ctrlKey) getApp().getUnitsManager().clearDestinations(units);
if (targetPosition)
getApp()
.getUnitsManager()
.addDestination(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.MOVE, hotkey: "KeyX" }
);
export const PATH = new ContextAction(
"path",
"Create route",
"Click on the map to add a destination to the path",
faRoute,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition) => {
if (targetPosition)
getApp()
.getUnitsManager()
.addDestination(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.MOVE, hotkey: "KeyC" }
);
export const DELETE = new ContextAction(
"delete",
"Delete unit",
"Deletes the unit",
faTrash,
ContextActionTarget.NONE,
(units: Unit[], _1, _2) => {
getApp().getUnitsManager().delete(false);
},
{
executeImmediately: true,
type: ContextActionType.DELETE,
}
);
export const EXPLODE = new ContextAction(
"explode",
"Explode unit",
"Explodes the unit",
faExplosion,
ContextActionTarget.NONE,
(units: Unit[], _1, _2) => {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.UNIT_EXPLOSION_MENU);
UnitExplosionRequestEvent.dispatch(units);
},
{
executeImmediately: true,
type: ContextActionType.DELETE,
}
);
export const CENTER_MAP = new ContextAction(
"center-map",
"Center map",
"Center the map on the unit and follow it",
faMapLocation,
ContextActionTarget.NONE,
(units: Unit[]) => {
getApp().getMap().centerOnUnit(units[0]);
},
{ executeImmediately: true, type: ContextActionType.OTHER }
);
export const REFUEL = new ContextAction(
"refuel",
"Refuel at tanker",
"Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB",
olButtonsContextRefuel,
ContextActionTarget.NONE,
(units: Unit[]) => {
getApp().getUnitsManager().refuel(units);
},
{ executeImmediately: true, type: ContextActionType.ADMIN }
);
export const FOLLOW = new ContextAction(
"follow",
"Follow unit",
"Click on a unit to follow it in formation",
olButtonsContextFollow,
ContextActionTarget.UNIT,
(units: Unit[], targetUnit: Unit | null, _) => {
if (targetUnit) {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.FORMATION);
FormationCreationRequestEvent.dispatch(
targetUnit,
units.filter((unit) => unit !== targetUnit)
);
}
},
{ type: ContextActionType.ADMIN }
);
export const BOMB = new ContextAction(
"bomb",
"Precision bomb location",
"Click on a point to execute a precision bombing attack",
faLocationCrosshairs,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.bombPoint(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE }
);
export const CARPET_BOMB = new ContextAction(
"carpet-bomb",
"Carpet bomb location",
"Click on a point to execute a carpet bombing attack",
faXmarksLines,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.carpetBomb(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE }
);
export const LAND = new ContextAction(
"land",
"Land",
"Click on a point to land at the nearest airbase",
faPlaneArrival,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition) getApp().getUnitsManager().landAt(targetPosition, units);
},
{ type: ContextActionType.ADMIN }
);
export const LAND_AT_POINT = new ContextAction(
"land-at-point",
"Land at location",
"Click on a point to land there",
olButtonsContextLandAtPoint,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.landAtPoint(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ADMIN }
);
export const GROUP = new ContextAction(
"group-ground",
"Group ground units",
"Create a group of ground units",
faPeopleGroup,
ContextActionTarget.NONE,
(units: Unit[], _1, _2) => {
getApp().getUnitsManager().createGroup(units);
},
{ executeImmediately: true, type: ContextActionType.OTHER }
);
export const ATTACK = new ContextAction(
"attack",
"Attack unit",
"Click on a unit to attack it",
olButtonsContextAttack,
ContextActionTarget.UNIT,
(units: Unit[], targetUnit: Unit | null, _) => {
if (targetUnit) getApp().getUnitsManager().attackUnit(targetUnit.ID, units);
},
{ type: ContextActionType.ENGAGE }
);
export const FIRE_AT_AREA = new ContextAction(
"fire-at-area",
"Fire at area",
"Click on a point to precisely fire at it (if possible)",
faLocationCrosshairs,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.fireAtArea(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE }
);
export const SIMULATE_FIRE_FIGHT = new ContextAction(
"simulate-fire-fight",
"Simulate fire fight",
"Simulate a fire fight by shooting randomly in a certain large area. WARNING: works correctly only on neutral units, blue or red units will aim",
olButtonsContextSimulateFireFight,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.simulateFireFight(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ADMIN }
);
}

View File

@ -20,6 +20,8 @@ import {
DrawSubState,
JTACSubState,
UnitControlSubState,
ContextActionTarget,
ContextActionType,
} from "../constants/constants";
import { CoalitionPolygon } from "./coalitionarea/coalitionpolygon";
import { MapHiddenTypes, MapOptions } from "../types/types";
@ -931,7 +933,7 @@ export class Map extends L.Map {
return;
}
if (e.originalEvent.button === 2) this.#isRotatingDestination = true;
if (this.#contextAction?.getTarget() === ContextActionTarget.POINT && e.originalEvent.button === 2) this.#isRotatingDestination = true;
this.scrollWheelZoom.disable();
this.#shortPressTimer = window.setTimeout(() => {
@ -1100,10 +1102,12 @@ export class Map extends L.Map {
else document.dispatchEvent(new CustomEvent("forceboxselect", { detail: e.originalEvent }));
} else if (getApp().getState() === OlympusState.UNIT_CONTROL) {
if (e.originalEvent.button === 2) {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.MAP_CONTEXT_MENU);
MapContextMenuRequestEvent.dispatch(pressLocation);
if (!getApp().getMap().getContextAction()) {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.MAP_CONTEXT_MENU);
MapContextMenuRequestEvent.dispatch(pressLocation);
}
} else {
if (this.#contextAction?.getTarget() === "position") {
if (this.#contextAction?.getTarget() === ContextActionTarget.POINT) {
this.dragging.disable();
this.#isRotatingDestination = true;
} else {
@ -1259,9 +1263,9 @@ export class Map extends L.Map {
});
selectedUnits.forEach((unit) => {
if (["move", "path", "land-at-point"].includes(this.#contextAction?.getId() ?? "")) {
if (this.#contextAction?.getOptions().type === ContextActionType.MOVE) {
this.#destinationPreviewMarkers[unit.ID] = new TemporaryUnitMarker(new L.LatLng(0, 0), unit.getName(), unit.getCoalition());
} else if (this.#contextAction?.getTarget() === "position" && this.#contextAction?.getId() !== "land") {
} else if (this.#contextAction?.getTarget() === ContextActionTarget.POINT) {
this.#destinationPreviewMarkers[unit.ID] = new TargetMarker(new L.LatLng(0, 0));
}
this.#destinationPreviewMarkers[unit.ID]?.addTo(this);

View File

@ -1,3 +1,4 @@
import { ContextActions, OlympusState } from "../constants/constants";
import { ShortcutKeyboardOptions, ShortcutMouseOptions } from "../interfaces";
import { getApp } from "../olympusapp";
import { ShortcutKeyboard, ShortcutMouse } from "./shortcut";
@ -117,6 +118,26 @@ export class ShortcutManager {
shiftKey: false,
});
for (let contextActionName in ContextActions) {
if (ContextActions[contextActionName].getOptions().hotkey) {
this.addKeyboardShortcut(`${contextActionName}Hotkey`, {
code: ContextActions[contextActionName].getOptions().hotkey,
shiftKey: true,
callback: () => {
const contextActionSet = getApp().getMap().getContextActionSet();
if (
getApp().getState() === OlympusState.UNIT_CONTROL &&
contextActionSet &&
ContextActions[contextActionName].getId() in contextActionSet.getContextActions()
) {
if (ContextActions[contextActionName].getOptions().executeImmediately) ContextActions[contextActionName].executeCallback();
else getApp().getMap().setContextAction(ContextActions[contextActionName]);
}
},
});
}
}
let PTTKeys = ["KeyZ", "KeyX", "KeyC", "KeyV", "KeyB", "KeyN", "KeyM", "KeyK", "KeyL"];
PTTKeys.forEach((key, idx) => {
this.addKeyboardShortcut(`PTT${idx}Active`, {

View File

@ -1,7 +1,7 @@
import React, { useEffect, useRef, useState } from "react";
import { Unit } from "../../unit/unit";
import { ContextAction } from "../../unit/contextaction";
import { CONTEXT_ACTION_COLORS, NO_SUBSTATE, OlympusState, OlympusSubState, UnitControlSubState } from "../../constants/constants";
import { CONTEXT_ACTION_COLORS, ContextActionTarget, NO_SUBSTATE, OlympusState, OlympusSubState, UnitControlSubState } from "../../constants/constants";
import { OlDropdownItem } from "../components/oldropdown";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { LatLng } from "leaflet";
@ -69,9 +69,9 @@ export function MapContextMenu(props: {}) {
});
let reorderedActions: ContextAction[] = contextActionSet
? Object.values(contextActionSet.getContextActions(appSubState === UnitControlSubState.MAP_CONTEXT_MENU ? "position" : "unit")).sort(
(a: ContextAction, b: ContextAction) => (a.getOptions().type < b.getOptions().type ? -1 : 1)
)
? Object.values(
contextActionSet.getContextActions(appSubState === UnitControlSubState.MAP_CONTEXT_MENU ? ContextActionTarget.POINT : ContextActionTarget.UNIT)
).sort((a: ContextAction, b: ContextAction) => (a.getOptions().type < b.getOptions().type ? -1 : 1))
: [];
return (
@ -107,13 +107,13 @@ export function MapContextMenu(props: {}) {
if (contextActionIt.getOptions().executeImmediately) {
contextActionIt.executeCallback(null, null);
} else {
if (appSubState === UnitControlSubState.MAP_CONTEXT_MENU ) {
if (appSubState === UnitControlSubState.MAP_CONTEXT_MENU) {
contextActionIt.executeCallback(null, latLng);
} else if (unit !== null) {
contextActionIt.executeCallback(unit, null);
}
}
getApp().setState(OlympusState.UNIT_CONTROL)
getApp().setState(OlympusState.UNIT_CONTROL);
}}
>
<FontAwesomeIcon className="my-auto" icon={contextActionIt.getIcon()} />

View File

@ -66,20 +66,30 @@ export function UnitControlBar(props: {}) {
<div className="flex gap-2 overflow-x-auto no-scrollbar p-2" onScroll={(ev) => onScroll(ev.target)} ref={scrollRef}>
{reorderedActions.map((contextActionIt: ContextAction) => {
return (
<OlStateButton
key={contextActionIt.getId()}
checked={contextActionIt === contextAction}
icon={contextActionIt.getIcon()}
tooltip={contextActionIt.getLabel()}
buttonColor={CONTEXT_ACTION_COLORS[contextActionIt.getOptions().type ?? 0]}
onClick={() => {
if (contextActionIt.getOptions().executeImmediately) {
contextActionIt.executeCallback(null, null);
} else {
contextActionIt !== contextAction ? getApp().getMap().setContextAction(contextActionIt) : getApp().getMap().setContextAction(null);
}
}}
/>
<div className="flex flex-col gap-1">
<OlStateButton
key={contextActionIt.getId()}
checked={contextActionIt === contextAction}
icon={contextActionIt.getIcon()}
tooltip={contextActionIt.getLabel()}
buttonColor={CONTEXT_ACTION_COLORS[contextActionIt.getOptions().type ?? 0]}
onClick={() => {
if (contextActionIt.getOptions().executeImmediately) {
contextActionIt.executeCallback(null, null);
} else {
contextActionIt !== contextAction ? getApp().getMap().setContextAction(contextActionIt) : getApp().getMap().setContextAction(null);
}
}}
/>
<div
className={`
rounded-sm bg-gray-400 text-center text-xs font-bold
text-olympus-800
`}
>
{(contextActionIt.getOptions().hotkey ?? "").replace("Key", "")}
</div>
</div>
);
})}
</div>
@ -120,7 +130,7 @@ export function UnitControlBar(props: {}) {
</div>
</div>
)}
{*/}
{*/}
</>
)}
</>

View File

@ -1,11 +1,12 @@
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { Unit } from "./unit";
import { LatLng } from "leaflet";
import { ContextActionType } from "../constants/constants";
import { ContextActionTarget, ContextActionType } from "../constants/constants";
export interface ContextActionOptions {
executeImmediately?: boolean;
type: ContextActionType;
hotkey?: string;
}
export type ContextActionCallback = (units: Unit[], targetUnit: Unit | null, targetPosition: LatLng | null, originalEvent?: MouseEvent) => void;
@ -18,9 +19,9 @@ export class ContextAction {
#units: Unit[] = [];
#icon: IconDefinition;
#options: ContextActionOptions;
#target: "unit" | "position" | null = null;
#target: ContextActionTarget;
constructor(id: string, label: string, description: string, icon: IconDefinition, target: "unit" | "position" | null, callback: ContextActionCallback, options: ContextActionOptions) {
constructor(id: string, label: string, description: string, icon: IconDefinition, target: ContextActionTarget, callback: ContextActionCallback, options: ContextActionOptions) {
this.#id = id;
this.#label = label;
this.#description = description;
@ -33,8 +34,8 @@ export class ContextAction {
};
}
addUnit(unit: Unit) {
this.#units.push(unit);
setUnits(units: Unit[]) {
this.#units = units;
}
getId() {

View File

@ -1,30 +1,26 @@
import { ContextActionTarget } from "../constants/constants";
import { ContextAction, ContextActionCallback, ContextActionOptions } from "./contextaction";
import { Unit } from "./unit";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
export class ContextActionSet {
#contextActions: { [key: string]: ContextAction } = {};
#defaultContextAction: ContextAction | null = null;
#units: { [key: string]: Unit[] } = {};
addContextAction(
unit: Unit,
id: string,
label: string,
description: string,
icon: IconDefinition,
target: "unit" | "position" | null,
callback: ContextActionCallback,
options?: ContextActionOptions
contextAction: ContextAction
) {
options = options || {};
if (!(id in this.#contextActions)) {
this.#contextActions[id] = new ContextAction(id, label, description, icon, target, callback, options);
this.#contextActions[contextAction.getId()] = contextAction;
if (!(contextAction.getId() in this.#units)) {
this.#units[contextAction.getId()] = []
this.#contextActions[contextAction.getId()].setUnits(this.#units[contextAction.getId()]);
}
this.#contextActions[id].addUnit(unit);
this.#units[contextAction.getId()].push(unit)
}
getContextActions(targetFilter?: string) {
getContextActions(targetFilter?: ContextActionTarget) {
if (targetFilter) {
var filteredContextActionSet = new ContextActionSet();
Object.keys(this.#contextActions).forEach((key) => {
@ -36,17 +32,10 @@ export class ContextActionSet {
addDefaultContextAction(
unit: Unit,
id: string,
label: string,
description: string,
icon: IconDefinition,
target: "unit" | "position" | null,
callback: ContextActionCallback,
options?: ContextActionOptions
contextAction: ContextAction
) {
options = options || {};
if (this.#defaultContextAction === null) this.#defaultContextAction = new ContextAction(id, label, description, icon, target, callback, options);
this.#defaultContextAction.addUnit(unit);
if (this.#defaultContextAction === null) this.#defaultContextAction = contextAction;
//this.#defaultContextAction.addUnit(unit);
}
getDefaultContextAction() {

View File

@ -39,6 +39,7 @@ import {
JTACSubState,
UnitControlSubState,
ContextActionType,
ContextActions,
} from "../constants/constants";
import { DataExtractor } from "../server/dataextractor";
import { Weapon } from "../weapon/weapon";
@ -80,6 +81,7 @@ import {
UnitSelectedEvent,
UnitUpdatedEvent,
} from "../events";
import { ContextAction } from "./contextaction";
var pathIcon = new Icon({
iconUrl: "/vite/images/markers/marker-icon.png",
@ -838,102 +840,13 @@ export abstract class Unit extends CustomMarker {
*
*/
appendContextActions(contextActionSet: ContextActionSet) {
contextActionSet.addContextAction(
this,
"stop",
"Stop unit",
"Stops the unit",
faHand,
null,
(units: Unit[], _1, _2) => {
getApp().getUnitsManager().stop(units);
},
{
executeImmediately: true,
type: ContextActionType.MOVE,
}
);
contextActionSet.addContextAction(this, ContextActions.STOP);
contextActionSet.addContextAction(this, ContextActions.MOVE);
contextActionSet.addContextAction(this, ContextActions.PATH);
contextActionSet.addContextAction(this, ContextActions.DELETE);
contextActionSet.addContextAction(this, ContextActions.EXPLODE);
contextActionSet.addContextAction(
this,
"move",
"Set destination",
"Click on the map to move the units there",
faLocationDot,
"position",
(units: Unit[], _, targetPosition, originalEvent) => {
if (!originalEvent?.ctrlKey) getApp().getUnitsManager().clearDestinations(units);
if (targetPosition)
getApp()
.getUnitsManager()
.addDestination(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.MOVE }
);
contextActionSet.addContextAction(
this,
"path",
"Create route",
"Click on the map to add a destination to the path",
faRoute,
"position",
(units: Unit[], _, targetPosition) => {
if (targetPosition)
getApp()
.getUnitsManager()
.addDestination(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.MOVE }
);
contextActionSet.addContextAction(
this,
"delete",
"Delete unit",
"Deletes the unit",
faTrash,
null,
(units: Unit[], _1, _2) => {
getApp().getUnitsManager().delete(false);
},
{
executeImmediately: true,
type: ContextActionType.DELETE,
}
);
contextActionSet.addContextAction(
this,
"explode",
"Explode unit",
"Explodes the unit",
faExplosion,
null,
(units: Unit[], _1, _2) => {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.UNIT_EXPLOSION_MENU);
UnitExplosionRequestEvent.dispatch(units);
},
{
executeImmediately: true,
type: ContextActionType.DELETE,
}
);
contextActionSet.addDefaultContextAction(
this,
"default",
"Set destination",
"",
faRoute,
null,
(units: Unit[], targetUnit, targetPosition, originalEvent) => {
if (targetPosition) {
if (!originalEvent?.ctrlKey) getApp().getUnitsManager().clearDestinations(units);
getApp().getUnitsManager().addDestination(targetPosition, false, 0, units);
}
}
);
contextActionSet.addDefaultContextAction(this, ContextActions.MOVE);
}
drawLines() {
@ -1452,7 +1365,7 @@ export abstract class Unit extends CustomMarker {
#onLongPress(e: any) {
console.log(`Long press on ${this.getUnitName()}`);
if (e.originalEvent.button === 2) {
if (e.originalEvent.button === 2 && !getApp().getMap().getContextAction()) {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.UNIT_CONTEXT_MENU);
UnitContextMenuRequestEvent.dispatch(this);
}
@ -1869,111 +1782,20 @@ export abstract class AirUnit extends Unit {
super.appendContextActions(contextActionSet);
/* Context actions to be executed immediately */
contextActionSet.addContextAction(
this,
"refuel",
"Refuel at tanker",
"Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB",
olButtonsContextRefuel,
null,
(units: Unit[]) => {
getApp().getUnitsManager().refuel(units);
},
{ executeImmediately: true, type: ContextActionType.ADMIN }
);
contextActionSet.addContextAction(
this,
"center-map",
"Center map",
"Center the map on the unit and follow it",
faMapLocation,
null,
(units: Unit[]) => {
getApp().getMap().centerOnUnit(units[0]);
},
{ executeImmediately: true, type: ContextActionType.OTHER }
);
contextActionSet.addContextAction(this, ContextActions.REFUEL);
contextActionSet.addContextAction(this, ContextActions.CENTER_MAP);
/* Context actions that require a target unit */
contextActionSet.addContextAction(
this,
"attack",
"Attack unit",
"Click on a unit to attack it using A/A or A/G weapons",
olButtonsContextAttack,
"unit",
(units: Unit[], targetUnit: Unit | null, _) => {
if (targetUnit) getApp().getUnitsManager().attackUnit(targetUnit.ID, units);
},
{ type: ContextActionType.ENGAGE }
);
contextActionSet.addContextAction(
this,
"follow",
"Follow unit",
"Click on a unit to follow it in formation",
olButtonsContextFollow,
"unit",
(units: Unit[], targetUnit: Unit | null, _) => {
if (targetUnit) {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.FORMATION);
FormationCreationRequestEvent.dispatch(
targetUnit,
units.filter((unit) => unit !== targetUnit)
);
}
},
{ type: ContextActionType.ADMIN }
);
contextActionSet.addContextAction(this, ContextActions.ATTACK);
contextActionSet.addContextAction(this, ContextActions.FOLLOW);
if (this.canTargetPoint()) {
/* Context actions that require a target position */
contextActionSet.addContextAction(
this,
"bomb",
"Precision bomb location",
"Click on a point to execute a precision bombing attack",
faLocationCrosshairs,
"position",
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.bombPoint(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE }
);
contextActionSet.addContextAction(
this,
"carpet-bomb",
"Carpet bomb location",
"Click on a point to execute a carpet bombing attack",
faXmarksLines,
"position",
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.carpetBomb(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE }
);
contextActionSet.addContextAction(this, ContextActions.BOMB);
contextActionSet.addContextAction(this, ContextActions.CARPET_BOMB);
}
contextActionSet.addContextAction(
this,
"land",
"Land",
"Click on a point to land at the nearest airbase",
faPlaneArrival,
"position",
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition) getApp().getUnitsManager().landAt(targetPosition, units);
},
{ type: ContextActionType.ADMIN }
);
contextActionSet.addContextAction(this, ContextActions.LAND);
}
}
@ -2010,21 +1832,7 @@ export class Helicopter extends AirUnit {
appendContextActions(contextActionSet: ContextActionSet) {
super.appendContextActions(contextActionSet);
contextActionSet.addContextAction(
this,
"land-at-point",
"Land at location",
"Click on a point to land there",
olButtonsContextLandAtPoint,
"position",
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.landAtPoint(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ADMIN }
);
contextActionSet.addContextAction(this, ContextActions.LAND_AT_POINT);
}
getMarkerCategory() {
@ -2062,77 +1870,16 @@ export class GroundUnit extends Unit {
super.appendContextActions(contextActionSet);
/* Context actions to be executed immediately */
contextActionSet.addContextAction(
this,
"group-ground",
"Group ground units",
"Create a group of ground units",
faPeopleGroup,
null,
(units: Unit[], _1, _2) => {
getApp().getUnitsManager().createGroup(units);
},
{ executeImmediately: true, type: ContextActionType.OTHER }
);
contextActionSet.addContextAction(
this,
"center-map",
"Center map",
"Center the map on the unit and follow it",
faMapLocation,
null,
(units: Unit[]) => {
getApp().getMap().centerOnUnit(units[0]);
},
{ executeImmediately: true, type: ContextActionType.OTHER }
);
contextActionSet.addContextAction(this, ContextActions.GROUP);
contextActionSet.addContextAction(this, ContextActions.CENTER_MAP);
/* Context actions that require a target unit */
contextActionSet.addContextAction(
this,
"attack",
"Attack unit",
"Click on a unit to attack it",
olButtonsContextAttack,
"unit",
(units: Unit[], targetUnit: Unit | null, _) => {
if (targetUnit) getApp().getUnitsManager().attackUnit(targetUnit.ID, units);
},
{ type: ContextActionType.ENGAGE }
);
contextActionSet.addContextAction(this, ContextActions.ATTACK);
/* Context actions that require a target position */
if (this.canTargetPoint()) {
contextActionSet.addContextAction(
this,
"fire-at-area",
"Fire at area",
"Click on a point to precisely fire at it (if possible)",
faLocationCrosshairs,
"position",
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.fireAtArea(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE }
);
contextActionSet.addContextAction(
this,
"simulate-fire-fight",
"Simulate fire fight",
"Simulate a fire fight by shooting randomly in a certain large area. WARNING: works correctly only on neutral units, blue or red units will aim",
olButtonsContextSimulateFireFight,
"position",
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.simulateFireFight(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ADMIN }
);
contextActionSet.addContextAction(this, ContextActions.FIRE_AT_AREA);
contextActionSet.addContextAction(this, ContextActions.SIMULATE_FIRE_FIGHT);
}
}
@ -2192,61 +1939,14 @@ export class NavyUnit extends Unit {
super.appendContextActions(contextActionSet);
/* Context actions to be executed immediately */
contextActionSet.addContextAction(
this,
"group-navy",
"Group navy units",
"Create a group of navy units",
faQuestionCircle,
null,
(units: Unit[], _1, _2) => {
getApp().getUnitsManager().createGroup(units);
},
{ executeImmediately: true, type: ContextActionType.OTHER }
);
contextActionSet.addContextAction(
this,
"center-map",
"Center map",
"Center the map on the unit and follow it",
faMapLocation,
null,
(units: Unit[]) => {
getApp().getMap().centerOnUnit(units[0]);
},
{ executeImmediately: true, type: ContextActionType.OTHER }
);
contextActionSet.addContextAction(this, ContextActions.GROUP);
contextActionSet.addContextAction(this, ContextActions.CENTER_MAP);
/* Context actions that require a target unit */
contextActionSet.addContextAction(
this,
"attack",
"Attack unit",
"Click on a unit to attack it",
olButtonsContextAttack,
"unit",
(units: Unit[], targetUnit: Unit | null, _) => {
if (targetUnit) getApp().getUnitsManager().attackUnit(targetUnit.ID, units);
},
{ type: ContextActionType.ENGAGE }
);
contextActionSet.addContextAction(this, ContextActions.ATTACK);
/* Context actions that require a target position */
contextActionSet.addContextAction(
this,
"fire-at-area",
"Fire at area",
"Click on a point to precisely fire at it (if possible)",
faLocationCrosshairs,
"position",
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp()
.getUnitsManager()
.fireAtArea(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE }
);
contextActionSet.addContextAction(this, ContextActions.FIRE_AT_AREA);
}
getCategory() {