feat: started implementing infrared and laser

This commit is contained in:
Pax1601 2025-01-29 08:03:32 +01:00
parent 79f9905413
commit 5a4a202805
10 changed files with 231 additions and 2 deletions

View File

@ -430,3 +430,43 @@ private:
const unsigned int intensity;
const string explosionType;
};
/* Shine a laser with a specific code */
class Laser : public Command
{
public:
Laser(unsigned int ID, unsigned int code, Coords destination, function<void(void)> callback = []() {}) :
Command(callback),
ID(ID),
destination(destination),
code(code)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int ID;
const unsigned int code;
const Coords destination;
};
/* Shine a infrared light */
class Infrared : public Command
{
public:
Infrared(unsigned int ID, Coords destination, function<void(void)> callback = []() {}) :
Command(callback),
ID(ID),
destination(destination)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int ID;
const Coords destination;
};

View File

@ -257,4 +257,29 @@ string Explosion::getString()
<< location.lat << ", "
<< location.lng;
return commandSS.str();
}
/* Laser command */
string Laser::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.laser, "
<< ID << ", "
<< code << ", "
<< destination.lat << ", "
<< destination.lng;
return commandSS.str();
}
/* Infrared command */
string Infrared::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.infrared, "
<< ID << ", "
<< destination.lat << ", "
<< destination.lng;
return commandSS.str();
}

View File

@ -695,6 +695,37 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
}
}
/************************/
else if (key.compare("fireLaser") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
unsigned int code = value[L"code"].as_integer();
log("Adding laser with code " + to_string(code) + " from unit " + unit->getUnitName() + " to (" + to_string(lat) + ", " + to_string(lng) + ")");
command = dynamic_cast<Command*>(new Laser(ID, code, loc));
}
}
/************************/
else if (key.compare("fireInfrared") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
log("Adding infrared from unit " + unit->getUnitName() + " to (" + to_string(lat) + ", " + to_string(lng) + ")");
command = dynamic_cast<Command*>(new Infrared(ID, loc));
}
}
/************************/
else if (key.compare("setCommandModeOptions") == 0)
{
setCommandModeOptions(value);

View File

@ -6,6 +6,7 @@ import {
faClone,
faExplosion,
faHand,
faLightbulb,
faLocationCrosshairs,
faLocationDot,
faMapLocation,
@ -887,6 +888,32 @@ export namespace ContextActions {
{ type: ContextActionType.ENGAGE, code: "KeyV", ctrlKey: false, shiftKey: false }
);
export const FIRE_LASER = new ContextAction(
"fire-laser",
"Shine laser at point",
"Click on a point to shine a laser with the given code from the unit to the ground.",
faLightbulb,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp().getUnitsManager().fireLaser(targetPosition, getApp().getMap().getKeepRelativePositions(), getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE, code: "KeyL", ctrlKey: true, shiftKey: false }
);
export const FIRE_INFRARED = new ContextAction(
"fire-infrared",
"Shine infrared at point",
"Click on a point to shine a infrared beam from the unit to the ground.",
faLightbulb,
ContextActionTarget.POINT,
(units: Unit[], _, targetPosition: LatLng | null) => {
if (targetPosition)
getApp().getUnitsManager().fireInfrared(targetPosition, getApp().getMap().getKeepRelativePositions(), getApp().getMap().getDestinationRotation(), units);
},
{ type: ContextActionType.ENGAGE, code: "KeyL", ctrlKey: true, shiftKey: false }
);
export const SIMULATE_FIRE_FIGHT = new ContextAction(
"simulate-fire-fight",
"Simulate fire fight",

View File

@ -67,8 +67,9 @@ export class TemporaryUnitMarker extends CustomMarker {
el.append(unitIcon);
// Short label
let shortLabel: null | HTMLDivElement = null;
if (blueprint.category == "aircraft" || blueprint.category == "helicopter") {
var shortLabel = document.createElement("div");
shortLabel = document.createElement("div");
shortLabel.classList.add("unit-short-label");
shortLabel.innerText = blueprint?.shortLabel || "";
el.append(shortLabel);
@ -88,7 +89,8 @@ export class TemporaryUnitMarker extends CustomMarker {
const rotateHandle = (heading) => {
el.style.transform = `rotate(${heading}deg)`;
unitIcon.style.transform = `rotate(-${heading}deg)`;
shortLabel.style.transform = `rotate(-${heading}deg)`;
if (shortLabel)
shortLabel.style.transform = `rotate(-${heading}deg)`;
};
SpawnHeadingChangedEvent.on((heading) => rotateHandle(heading));

View File

@ -192,6 +192,9 @@ export class OlympusApp {
this.getServerManager().setActiveCommandMode(GAME_MASTER);
}
else if (this.getState() !== OlympusState.LOGIN) {
this.setState(OlympusState.LOGIN, LoginSubState.CREDENTIALS);
}
} else if (this.getState() !== OlympusState.LOGIN) {
this.setState(OlympusState.LOGIN, LoginSubState.CREDENTIALS);
}

View File

@ -450,6 +450,18 @@ export class ServerManager {
this.PUT(data, callback);
}
fireLaser(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) {
var command = { ID: ID, location: latlng, code: 1688 };
var data = { fireLaser: command };
this.PUT(data, callback);
}
fireInfrared(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) {
var command = { ID: ID, location: latlng };
var data = { fireInfrared: command };
this.PUT(data, callback);
}
simulateFireFight(ID: number, latlng: LatLng, altitude: number, callback: CallableFunction = () => {}) {
var command = { ID: ID, location: latlng, altitude: altitude };
var data = { simulateFireFight: command };

View File

@ -915,6 +915,8 @@ export abstract class Unit extends CustomMarker {
contextActionSet.addContextAction(this, ContextActions.CENTER_MAP);
contextActionSet.addContextAction(this, ContextActions.CLONE);
contextActionSet.addContextAction(this, ContextActions.ATTACK);
contextActionSet.addContextAction(this, ContextActions.FIRE_LASER);
contextActionSet.addContextAction(this, ContextActions.FIRE_INFRARED);
contextActionSet.addDefaultContextAction(this, ContextActions.MOVE);
}
@ -1325,6 +1327,14 @@ export abstract class Unit extends CustomMarker {
getApp().getServerManager().fireAtArea(this.ID, latlng);
}
fireLaser(latlng: LatLng) {
getApp().getServerManager().fireLaser(this.ID, latlng);
}
fireInfrared(latlng: LatLng) {
getApp().getServerManager().fireInfrared(this.ID, latlng);
}
simulateFireFight(latlng: LatLng, targetGroundElevation: number | null) {
getGroundElevation(this.getPosition(), (response: string) => {
var unitGroundElevation: number | null = null;

View File

@ -895,6 +895,61 @@ export class UnitsManager {
this.#protectionCallback = callback;
} else callback(units);
}
/** Instruct the selected units to fire at specific coordinates
*
* @param latlng Location to fire at
* @param units (Optional) Array of units to apply the control to. If not provided, the operation will be completed on all selected units.
*/
fireLaser(latlng: LatLng, mantainRelativePosition: boolean, rotation: number = 0, units: Unit[] | null = null) {
if (units === null) units = this.getSelectedUnits();
units = units.filter((unit) => !unit.getHuman());
let callback = (units) => {
/* Compute the target for each unit. If mantainRelativePosition is true, compute the target so to hold the relative positions */
var unitTargets: { [key: number]: LatLng } = {};
if (mantainRelativePosition) unitTargets = this.computeGroupDestination(latlng, rotation);
else
units.forEach((unit: Unit) => {
unitTargets[unit.ID] = latlng;
});
units.forEach((unit: Unit) => unit.fireLaser(unitTargets[unit.ID]));
this.#showActionMessage(units, `unit shining laser at point`);
};
if (getApp().getMap().getOptions().protectDCSUnits && !units.every((unit) => unit.isControlledByOlympus())) {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.PROTECTION);
this.#protectionCallback = callback;
} else callback(units);
}
/** Instruct the selected units to fire at specific coordinates
*
* @param latlng Location to fire at
* @param units (Optional) Array of units to apply the control to. If not provided, the operation will be completed on all selected units.
*/
fireInfrared(latlng: LatLng, mantainRelativePosition: boolean, rotation: number = 0, units: Unit[] | null = null) {
if (units === null) units = this.getSelectedUnits();
units = units.filter((unit) => !unit.getHuman());
let callback = (units) => {
/* Compute the target for each unit. If mantainRelativePosition is true, compute the target so to hold the relative positions */
var unitTargets: { [key: number]: LatLng } = {};
if (mantainRelativePosition) unitTargets = this.computeGroupDestination(latlng, rotation);
else
units.forEach((unit: Unit) => {
unitTargets[unit.ID] = latlng;
});
units.forEach((unit: Unit) => unit.fireInfrared(unitTargets[unit.ID]));
this.#showActionMessage(units, `unit shining infrared at point`);
};
if (getApp().getMap().getOptions().protectDCSUnits && !units.every((unit) => unit.isControlledByOlympus())) {
getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.PROTECTION);
this.#protectionCallback = callback;
} else callback(units);
}
/** Instruct the selected units to simulate a fire fight at specific coordinates
*
* @param latlng Location to fire at

View File

@ -566,6 +566,30 @@ function Olympus.randomDebries(vec3)
end
end
-- Shines a laser from a unit to a point
function Olympus.fireLaser(ID, code, lat, lng)
Olympus.debug("Olympus.fireLaser " .. ID .. " -> (" .. lat .. ", " .. lng .. ") code " .. code, 2)
local vec3 = mist.utils.makeVec3GL(coord.LLtoLO(lat, lng))
local unit = Olympus.getUnitByID(ID)
if unit ~= nil and unit:isExist() then
local ray = Spot.createLaser(unit, {x = 0, y = 1, z = 0}, vec3, code)
end
end
-- Shines a infrared light from a unit to a point
function Olympus.fireInfrared(ID, lat, lng)
Olympus.debug("Olympus.fireInfrared " .. ID .. " -> (" .. lat .. ", " .. lng .. ")", 2)
local vec3 = mist.utils.makeVec3GL(coord.LLtoLO(lat, lng))
local unit = Olympus.getUnitByID(ID)
if unit ~= nil and unit:isExist() then
local ray = Spot.createInfraRed(unit, {x = 0, y = 1, z = 0}, vec3)
end
end
-- Spawns a new unit or group
-- Spawn table contains the following parameters
-- category: (string), either Aircraft, Helicopter, GroundUnit or NavyUnit