mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added ability to rotate movement path
This commit is contained in:
parent
644404c4e6
commit
4e84a97367
@ -49,6 +49,7 @@ import {
|
||||
MapOptionsChangedEvent,
|
||||
MapSourceChangedEvent,
|
||||
SelectionClearedEvent,
|
||||
UnitDeselectedEvent,
|
||||
UnitSelectedEvent,
|
||||
UnitUpdatedEvent,
|
||||
} from "../events";
|
||||
@ -122,6 +123,7 @@ export class Map extends L.Map {
|
||||
/* Units movement */
|
||||
#destinationPreviewMarkers: { [key: number]: TemporaryUnitMarker | TargetMarker } = {};
|
||||
#destinationRotation: number = 0;
|
||||
#isRotatingDestination: boolean = false;
|
||||
|
||||
/* Unit context actions */
|
||||
#contextActionSet: null | ContextActionSet = null;
|
||||
@ -197,7 +199,6 @@ export class Map extends L.Map {
|
||||
/* Custom touch events for touchscreen support */
|
||||
L.DomEvent.on(this.getContainer(), "touchstart", this.#onMouseDown, this);
|
||||
L.DomEvent.on(this.getContainer(), "touchend", this.#onMouseUp, this);
|
||||
L.DomEvent.on(this.getContainer(), "wheel", this.#onWheel, this);
|
||||
|
||||
/* Event listeners */
|
||||
AppStateChangedEvent.on((state, subState) => this.#onStateChanged(state, subState));
|
||||
@ -264,8 +265,18 @@ export class Map extends L.Map {
|
||||
}
|
||||
});
|
||||
|
||||
UnitSelectedEvent.on((unit) => this.#updateDestinationPreviewMarkers());
|
||||
SelectionClearedEvent.on(() => this.#updateDestinationPreviewMarkers());
|
||||
UnitSelectedEvent.on((unit) => {
|
||||
this.#updateDestinationPreviewMarkers();
|
||||
this.#destinationRotation = 0;
|
||||
});
|
||||
UnitDeselectedEvent.on(() => {
|
||||
this.#updateDestinationPreviewMarkers();
|
||||
this.#destinationRotation = 0;
|
||||
});
|
||||
SelectionClearedEvent.on(() => {
|
||||
this.#updateDestinationPreviewMarkers();
|
||||
this.#destinationRotation = 0;
|
||||
});
|
||||
ContextActionChangedEvent.on((contextAction) => this.#updateDestinationPreviewMarkers());
|
||||
MapOptionsChangedEvent.on((mapOptions) => this.#moveDestinationPreviewMarkers());
|
||||
|
||||
@ -624,6 +635,10 @@ export class Map extends L.Map {
|
||||
return this.#lastMouseCoordinates;
|
||||
}
|
||||
|
||||
getDestinationRotation() {
|
||||
return this.#destinationRotation;
|
||||
}
|
||||
|
||||
centerOnUnit(unit: Unit | null) {
|
||||
if (unit !== null) {
|
||||
this.options.scrollWheelZoom = "center";
|
||||
@ -900,7 +915,9 @@ export class Map extends L.Map {
|
||||
window.clearTimeout(this.#longPressTimer);
|
||||
|
||||
this.scrollWheelZoom.enable();
|
||||
this.dragging.enable();
|
||||
|
||||
this.#isRotatingDestination = false;
|
||||
this.#isMouseOnCooldown = true;
|
||||
this.#mouseCooldownTimer = window.setTimeout(() => {
|
||||
this.#isMouseOnCooldown = false;
|
||||
@ -914,6 +931,7 @@ export class Map extends L.Map {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.originalEvent.button === 2) this.#isRotatingDestination = true;
|
||||
this.scrollWheelZoom.disable();
|
||||
|
||||
this.#shortPressTimer = window.setTimeout(() => {
|
||||
@ -927,11 +945,6 @@ export class Map extends L.Map {
|
||||
}, 350);
|
||||
}
|
||||
|
||||
#onWheel(e: any) {
|
||||
//this.#destinationRotation += e.deltaY / 25;
|
||||
//this.#moveDestinationPreviewMarkers();
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any) {
|
||||
console.log(`Double click at ${e.latlng}`);
|
||||
|
||||
@ -1020,6 +1033,7 @@ export class Map extends L.Map {
|
||||
this.executeDefaultContextAction(null, pressLocation, e.originalEvent);
|
||||
}
|
||||
} else if (getApp().getState() === OlympusState.JTAC) {
|
||||
// TODO less redundant way to do this
|
||||
if (getApp().getSubState() === JTACSubState.SELECT_TARGET) {
|
||||
if (!this.#targetPoint) {
|
||||
this.#targetPoint = new TextMarker(pressLocation, "BP", "rgb(37 99 235)", { interactive: true, draggable: true });
|
||||
@ -1089,8 +1103,13 @@ export class Map extends L.Map {
|
||||
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.MAP_CONTEXT_MENU);
|
||||
MapContextMenuRequestEvent.dispatch(pressLocation);
|
||||
} else {
|
||||
if (e.type === "touchstart") document.dispatchEvent(new CustomEvent("forceboxselect", { detail: e }));
|
||||
else document.dispatchEvent(new CustomEvent("forceboxselect", { detail: e.originalEvent }));
|
||||
if (this.#contextAction?.getTarget() === "position") {
|
||||
this.dragging.disable();
|
||||
this.#isRotatingDestination = true;
|
||||
} else {
|
||||
if (e.type === "touchstart") document.dispatchEvent(new CustomEvent("forceboxselect", { detail: e }));
|
||||
else document.dispatchEvent(new CustomEvent("forceboxselect", { detail: e.originalEvent }));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1099,12 +1118,16 @@ export class Map extends L.Map {
|
||||
#onMouseMove(e: any) {
|
||||
window.clearTimeout(this.#longPressTimer);
|
||||
|
||||
this.#lastMousePosition.x = e.originalEvent.x;
|
||||
this.#lastMousePosition.y = e.originalEvent.y;
|
||||
this.#lastMouseCoordinates = e.latlng;
|
||||
if (!this.#isRotatingDestination) {
|
||||
this.#lastMousePosition.x = e.originalEvent.x;
|
||||
this.#lastMousePosition.y = e.originalEvent.y;
|
||||
this.#lastMouseCoordinates = e.latlng;
|
||||
|
||||
if (this.#currentSpawnMarker) this.#currentSpawnMarker.setLatLng(e.latlng);
|
||||
if (this.#currentEffectMarker) this.#currentEffectMarker.setLatLng(e.latlng);
|
||||
if (this.#currentSpawnMarker) this.#currentSpawnMarker.setLatLng(e.latlng);
|
||||
if (this.#currentEffectMarker) this.#currentEffectMarker.setLatLng(e.latlng);
|
||||
} else {
|
||||
this.#destinationRotation -= e.originalEvent.movementX;
|
||||
}
|
||||
|
||||
this.#moveDestinationPreviewMarkers();
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import { FaLock } from "react-icons/fa6";
|
||||
import { getApp } from "../../olympusapp";
|
||||
import { OlympusState } from "../../constants/constants";
|
||||
|
||||
export function ProtectionPrompt(props: { }) {
|
||||
export function ProtectionPrompt(props: {}) {
|
||||
return (
|
||||
<Modal
|
||||
className={`
|
||||
@ -49,16 +49,25 @@ export function ProtectionPrompt(props: { }) {
|
||||
dark:text-gray-500
|
||||
`}
|
||||
>
|
||||
To disable this warning, press on the <span className={`
|
||||
inline-block translate-y-3 rounded-full border-[1px]
|
||||
border-gray-900 bg-red-500 p-2 text-olympus-900
|
||||
`}><FaLock/></span> button
|
||||
To disable this warning, press on the{" "}
|
||||
<span
|
||||
className={`
|
||||
inline-block translate-y-3 rounded-full border-[1px]
|
||||
border-gray-900 bg-red-500 p-2 text-olympus-900
|
||||
`}
|
||||
>
|
||||
<FaLock />
|
||||
</span>{" "}
|
||||
button
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => getApp().getUnitsManager().executeProtectionCallback()}
|
||||
onClick={() => {
|
||||
getApp().getUnitsManager().executeProtectionCallback();
|
||||
getApp().setState(OlympusState.UNIT_CONTROL);
|
||||
}}
|
||||
className={`
|
||||
mb-2 me-2 ml-auto flex content-center items-center gap-2
|
||||
rounded-sm bg-blue-700 px-5 py-2.5 text-sm font-medium text-white
|
||||
|
||||
@ -68,7 +68,18 @@ import {
|
||||
faXmarksLines,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { Carrier } from "../mission/carrier";
|
||||
import { ContactsUpdatedEvent, FormationCreationRequestEvent, HiddenTypesChangedEvent, MapOptionsChangedEvent, UnitContextMenuRequestEvent, UnitDeadEvent, UnitDeselectedEvent, UnitExplosionRequestEvent, UnitSelectedEvent, UnitUpdatedEvent } from "../events";
|
||||
import {
|
||||
ContactsUpdatedEvent,
|
||||
FormationCreationRequestEvent,
|
||||
HiddenTypesChangedEvent,
|
||||
MapOptionsChangedEvent,
|
||||
UnitContextMenuRequestEvent,
|
||||
UnitDeadEvent,
|
||||
UnitDeselectedEvent,
|
||||
UnitExplosionRequestEvent,
|
||||
UnitSelectedEvent,
|
||||
UnitUpdatedEvent,
|
||||
} from "../events";
|
||||
|
||||
var pathIcon = new Icon({
|
||||
iconUrl: "/vite/images/markers/marker-icon.png",
|
||||
@ -835,7 +846,7 @@ export abstract class Unit extends CustomMarker {
|
||||
faHand,
|
||||
null,
|
||||
(units: Unit[], _1, _2) => {
|
||||
getApp().getUnitsManager().clearDestinations(units);
|
||||
getApp().getUnitsManager().stop(units);
|
||||
},
|
||||
{
|
||||
executeImmediately: true,
|
||||
@ -852,7 +863,10 @@ export abstract class Unit extends CustomMarker {
|
||||
"position",
|
||||
(units: Unit[], _, targetPosition, originalEvent) => {
|
||||
if (!originalEvent?.ctrlKey) getApp().getUnitsManager().clearDestinations(units);
|
||||
if (targetPosition) getApp().getUnitsManager().addDestination(targetPosition, getApp().getMap().getOptions().keepRelativePositions, 0, units);
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.addDestination(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
|
||||
},
|
||||
{ type: ContextActionType.MOVE }
|
||||
);
|
||||
@ -865,7 +879,10 @@ export abstract class Unit extends CustomMarker {
|
||||
faRoute,
|
||||
"position",
|
||||
(units: Unit[], _, targetPosition) => {
|
||||
if (targetPosition) getApp().getUnitsManager().addDestination(targetPosition, getApp().getMap().getOptions().keepRelativePositions, 0, units);
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.addDestination(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
|
||||
},
|
||||
{ type: ContextActionType.MOVE }
|
||||
);
|
||||
@ -894,8 +911,8 @@ export abstract class Unit extends CustomMarker {
|
||||
faExplosion,
|
||||
null,
|
||||
(units: Unit[], _1, _2) => {
|
||||
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.UNIT_EXPLOSION_MENU)
|
||||
UnitExplosionRequestEvent.dispatch(units)
|
||||
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.UNIT_EXPLOSION_MENU);
|
||||
UnitExplosionRequestEvent.dispatch(units);
|
||||
},
|
||||
{
|
||||
executeImmediately: true,
|
||||
@ -903,12 +920,20 @@ export abstract class Unit extends CustomMarker {
|
||||
}
|
||||
);
|
||||
|
||||
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,
|
||||
"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);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
drawLines() {
|
||||
@ -1191,7 +1216,6 @@ export abstract class Unit extends CustomMarker {
|
||||
|
||||
clearDestinations() {
|
||||
if (!this.#human) this.#activePath = [];
|
||||
getApp().getServerManager().addDestination(this.ID, []);
|
||||
}
|
||||
|
||||
updatePathFromMarkers() {
|
||||
@ -1429,7 +1453,7 @@ export abstract class Unit extends CustomMarker {
|
||||
console.log(`Long press on ${this.getUnitName()}`);
|
||||
|
||||
if (e.originalEvent.button === 2) {
|
||||
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.UNIT_CONTEXT_MENU)
|
||||
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.UNIT_CONTEXT_MENU);
|
||||
UnitContextMenuRequestEvent.dispatch(this);
|
||||
}
|
||||
}
|
||||
@ -1894,7 +1918,10 @@ export abstract class AirUnit extends Unit {
|
||||
(units: Unit[], targetUnit: Unit | null, _) => {
|
||||
if (targetUnit) {
|
||||
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.FORMATION);
|
||||
FormationCreationRequestEvent.dispatch(targetUnit, units.filter((unit) => unit !== targetUnit))
|
||||
FormationCreationRequestEvent.dispatch(
|
||||
targetUnit,
|
||||
units.filter((unit) => unit !== targetUnit)
|
||||
);
|
||||
}
|
||||
},
|
||||
{ type: ContextActionType.ADMIN }
|
||||
@ -1910,7 +1937,10 @@ export abstract class AirUnit extends Unit {
|
||||
faLocationCrosshairs,
|
||||
"position",
|
||||
(units: Unit[], _, targetPosition: LatLng | null) => {
|
||||
if (targetPosition) getApp().getUnitsManager().bombPoint(targetPosition, getApp().getMap().getOptions().keepRelativePositions, 0, units);
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.bombPoint(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
|
||||
},
|
||||
{ type: ContextActionType.ENGAGE }
|
||||
);
|
||||
@ -1923,7 +1953,10 @@ export abstract class AirUnit extends Unit {
|
||||
faXmarksLines,
|
||||
"position",
|
||||
(units: Unit[], _, targetPosition: LatLng | null) => {
|
||||
if (targetPosition) getApp().getUnitsManager().carpetBomb(targetPosition, getApp().getMap().getOptions().keepRelativePositions, 0, units);
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.carpetBomb(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
|
||||
},
|
||||
{ type: ContextActionType.ENGAGE }
|
||||
);
|
||||
@ -1985,7 +2018,10 @@ export class Helicopter extends AirUnit {
|
||||
olButtonsContextLandAtPoint,
|
||||
"position",
|
||||
(units: Unit[], _, targetPosition: LatLng | null) => {
|
||||
if (targetPosition) getApp().getUnitsManager().landAtPoint(targetPosition, getApp().getMap().getOptions().keepRelativePositions, 0, units);
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.landAtPoint(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
|
||||
},
|
||||
{ type: ContextActionType.ADMIN }
|
||||
);
|
||||
@ -2075,7 +2111,10 @@ export class GroundUnit extends Unit {
|
||||
faLocationCrosshairs,
|
||||
"position",
|
||||
(units: Unit[], _, targetPosition: LatLng | null) => {
|
||||
if (targetPosition) getApp().getUnitsManager().fireAtArea(targetPosition, getApp().getMap().getOptions().keepRelativePositions, 0, units);
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.fireAtArea(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
|
||||
},
|
||||
{ type: ContextActionType.ENGAGE }
|
||||
);
|
||||
@ -2087,7 +2126,10 @@ export class GroundUnit extends Unit {
|
||||
olButtonsContextSimulateFireFight,
|
||||
"position",
|
||||
(units: Unit[], _, targetPosition: LatLng | null) => {
|
||||
if (targetPosition) getApp().getUnitsManager().simulateFireFight(targetPosition, getApp().getMap().getOptions().keepRelativePositions, 0, units);
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.simulateFireFight(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
|
||||
},
|
||||
{ type: ContextActionType.ADMIN }
|
||||
);
|
||||
@ -2198,7 +2240,10 @@ export class NavyUnit extends Unit {
|
||||
faLocationCrosshairs,
|
||||
"position",
|
||||
(units: Unit[], _, targetPosition: LatLng | null) => {
|
||||
if (targetPosition) getApp().getUnitsManager().fireAtArea(targetPosition, getApp().getMap().getOptions().keepRelativePositions, 0, units);
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.fireAtArea(targetPosition, getApp().getMap().getOptions().keepRelativePositions, getApp().getMap().getDestinationRotation(), units);
|
||||
},
|
||||
{ type: ContextActionType.ENGAGE }
|
||||
);
|
||||
|
||||
@ -394,6 +394,23 @@ export class UnitsManager {
|
||||
} else callback(units);
|
||||
}
|
||||
|
||||
stop(units: Unit[] | null = null) {
|
||||
if (units === null) units = this.getSelectedUnits();
|
||||
units = units.filter((unit) => !unit.getHuman());
|
||||
|
||||
let callback = (units: Unit[]) => {
|
||||
for (let idx in units) {
|
||||
getApp().getServerManager().addDestination(units[idx].ID, []);
|
||||
}
|
||||
this.#showActionMessage(units, " stopped");
|
||||
};
|
||||
|
||||
if (getApp().getMap().getOptions().protectDCSUnits && !units.every((unit) => unit.isControlledByOlympus())) {
|
||||
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.PROTECTION);
|
||||
this.#protectionCallback = callback;
|
||||
} else callback(units);
|
||||
}
|
||||
|
||||
/** Instruct all the selected units to land at a specific location
|
||||
*
|
||||
* @param latlng Location where to land at
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user