mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Introduced customString and customInteger fields to the Unit class in both backend (C++) and frontend (TypeScript/React). Updated data indexes, interfaces, and API handling to support setting and retrieving these custom fields. Also added UI elements in the unit control menu to display and handle these new properties.
891 lines
32 KiB
C++
891 lines
32 KiB
C++
#include "scheduler.h"
|
|
#include "logger.h"
|
|
#include "dcstools.h"
|
|
#include "unitsManager.h"
|
|
#include "utils.h"
|
|
#include "unit.h"
|
|
|
|
extern UnitsManager* unitsManager;
|
|
|
|
Scheduler::Scheduler(lua_State* L)
|
|
{
|
|
LogInfo(L, "Scheduler constructor called successfully");
|
|
}
|
|
|
|
Scheduler::~Scheduler()
|
|
{
|
|
|
|
}
|
|
|
|
/* Appends a */
|
|
void Scheduler::appendCommand(Command* newCommand)
|
|
{
|
|
for (auto command : commands) {
|
|
if (command->getString().compare(newCommand->getString()) == 0 && command->getPriority() == newCommand->getPriority())
|
|
return;
|
|
}
|
|
commands.push_back(newCommand);
|
|
}
|
|
|
|
int Scheduler::getLoad()
|
|
{
|
|
int currentLoad = 0;
|
|
for (auto command : commands) {
|
|
currentLoad += command->getLoad();
|
|
}
|
|
return currentLoad;
|
|
}
|
|
|
|
void Scheduler::execute(lua_State* L)
|
|
{
|
|
/* Decrease the active computation load. New commands can be sent only if the load has reached 0.
|
|
This is needed to avoid server lag. */
|
|
if (load > 0) {
|
|
load--;
|
|
return;
|
|
}
|
|
|
|
int priority = CommandPriority::IMMEDIATE;
|
|
while (priority >= CommandPriority::LOW) {
|
|
for (auto command : commands)
|
|
{
|
|
if (command->getPriority() == priority)
|
|
{
|
|
string commandString = "Olympus.protectedCall(" + command->getString() + ")";
|
|
string resultString = "";
|
|
if (dostring_in(L, "server", (commandString), resultString))
|
|
log("Error executing command " + commandString);
|
|
else
|
|
log("Command '" + commandString + "' executed correctly, current load " + to_string(getLoad()) + ", result string: " + resultString);
|
|
|
|
/* Adjust the load depending on the fps */
|
|
double fpsMultiplier = 20;
|
|
if (getFrameRate() + 3 > 0)
|
|
fpsMultiplier = static_cast<unsigned int>(max(1, 60 / (getFrameRate() + 3))); /* Multiplier between 1 and 20 */
|
|
|
|
load = static_cast<unsigned int>(command->getLoad() * fpsMultiplier);
|
|
commands.remove(command);
|
|
CommandResult commandResult = {
|
|
command->getHash(), resultString
|
|
};
|
|
executedCommandResults.push_back(commandResult);
|
|
command->executeCallback(); /* Execute the command callback (this is a lambda function that can be used to execute a function when the command is run) */
|
|
delete command;
|
|
return;
|
|
}
|
|
}
|
|
priority--;
|
|
};
|
|
}
|
|
|
|
void Scheduler::setCommandModeOptions(json::value value) {
|
|
if (value.has_boolean_field(L"restrictSpawns"))
|
|
setRestrictSpawns(value[L"restrictSpawns"].as_bool());
|
|
if (value.has_boolean_field(L"restrictToCoalition"))
|
|
setRestrictToCoalition(value[L"restrictToCoalition"].as_bool());
|
|
if (value.has_number_field(L"setupTime"))
|
|
setSetupTime(value[L"setupTime"].as_number().to_int32());
|
|
if (value.has_object_field(L"spawnPoints")) {
|
|
if (value[L"spawnPoints"].has_number_field(L"blue"))
|
|
setBlueSpawnPoints(value[L"spawnPoints"][L"blue"].as_number().to_int32());
|
|
if (value[L"spawnPoints"].has_number_field(L"red"))
|
|
setRedSpawnPoints(value[L"spawnPoints"][L"red"].as_number().to_int32());
|
|
}
|
|
if (value.has_array_field(L"eras")) {
|
|
int length = static_cast<int>(value[L"eras"].as_array().size());
|
|
vector<string> newEras;
|
|
for (int idx = 0; idx < length; idx++)
|
|
newEras.push_back(to_string(value[L"eras"].as_array().at(idx)));
|
|
setEras(newEras);
|
|
}
|
|
}
|
|
|
|
json::value Scheduler::getCommandModeOptions() {
|
|
json::value json = json::value::object();
|
|
|
|
json[L"restrictSpawns"] = json::value(getRestrictSpawns());
|
|
json[L"restrictToCoalition"] = json::value(getRestrictToCoalition());
|
|
json[L"setupTime"] = json::value(getSetupTime());
|
|
json[L"spawnPoints"] = json::value::object();
|
|
json[L"spawnPoints"][L"blue"] = json::value(getBlueSpawnPoints());
|
|
json[L"spawnPoints"][L"red"] = json::value(getRedSpawnPoints());
|
|
|
|
int idx = 0;
|
|
json[L"eras"] = json::value::array();
|
|
for (string era : getEras())
|
|
json[L"eras"][idx++] = json::value(to_wstring(era));
|
|
|
|
return json;
|
|
}
|
|
|
|
bool Scheduler::checkSpawnPoints(int spawnPoints, string coalition)
|
|
{
|
|
if (!getRestrictSpawns()) return true;
|
|
|
|
if (coalition.compare("blue") == 0) {
|
|
if (getBlueSpawnPoints() - spawnPoints >= 0) {
|
|
setBlueSpawnPoints(getBlueSpawnPoints() - spawnPoints);
|
|
return true;
|
|
}
|
|
else {
|
|
log("Not enough blue coalition spawn points available. Available: " + to_string(getBlueSpawnPoints()) + ", required: " + to_string(spawnPoints));
|
|
return false;
|
|
}
|
|
}
|
|
else if (coalition.compare("red") == 0) {
|
|
if (getRedSpawnPoints() - spawnPoints >= 0) {
|
|
setRedSpawnPoints(getRedSpawnPoints() - spawnPoints);
|
|
return true;
|
|
}
|
|
else {
|
|
log("Not enough red coalition spawn points available. Available: " + to_string(getRedSpawnPoints()) + ", required: " + to_string(spawnPoints));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void Scheduler::handleRequest(string key, json::value value, string username, json::value& answer)
|
|
{
|
|
Command* command = nullptr;
|
|
|
|
log("Received request with ID: " + key);
|
|
log(L"Incoming command raw value: " + value.serialize());
|
|
|
|
/************************/
|
|
if (key.compare("setPath") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr)
|
|
{
|
|
json::value path = value[L"path"];
|
|
list<Coords> newPath;
|
|
for (unsigned int i = 0; i < path.as_array().size(); i++)
|
|
{
|
|
string WP = to_string(i);
|
|
double lat = path[i][L"lat"].as_double();
|
|
double lng = path[i][L"lng"].as_double();
|
|
if (path[i].has_number_field(L"threshold")) {
|
|
double threshold = path[i][L"threshold"].as_double();
|
|
Coords dest; dest.lat = lat; dest.lng = lng; dest.threshold = threshold;
|
|
newPath.push_back(dest);
|
|
continue;
|
|
}
|
|
Coords dest; dest.lat = lat; dest.lng = lng;
|
|
newPath.push_back(dest);
|
|
}
|
|
|
|
unit->setActivePath(newPath);
|
|
unit->setState(State::REACH_DESTINATION);
|
|
log(username + " updated destination path for unit " + unit->getUnitName() + "(" + unit->getName() + ")", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("smoke") == 0)
|
|
{
|
|
string color = to_string(value[L"color"]);
|
|
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;
|
|
command = dynamic_cast<Command*>(new Smoke(color, loc));
|
|
log(username + " added a " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")", true);
|
|
}
|
|
/************************/
|
|
else if (key.compare("spawnAircrafts") == 0 || key.compare("spawnHelicopters") == 0)
|
|
{
|
|
bool immediate = value[L"immediate"].as_bool();
|
|
string coalition = to_string(value[L"coalition"]);
|
|
string airbaseName = to_string(value[L"airbaseName"]);
|
|
string country = to_string(value[L"country"]);
|
|
|
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
|
if (!checkSpawnPoints(spawnPoints, coalition)) {
|
|
log(username + " insufficient spawn points ", true);
|
|
return;
|
|
}
|
|
|
|
vector<SpawnOptions> spawnOptions;
|
|
for (auto unit : value[L"units"].as_array()) {
|
|
string unitType = to_string(unit[L"unitType"]);
|
|
double lat = unit[L"location"][L"lat"].as_double();
|
|
double lng = unit[L"location"][L"lng"].as_double();
|
|
double alt = unit[L"altitude"].as_double();
|
|
double heading = 0;
|
|
if (unit.has_number_field(L"heading"))
|
|
heading = unit[L"heading"].as_double();
|
|
|
|
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
|
|
string loadout = to_string(unit[L"loadout"]);
|
|
string liveryID = to_string(unit[L"liveryID"]);
|
|
string skill = to_string(unit[L"skill"]);
|
|
|
|
spawnOptions.push_back({ unitType, location, loadout, skill, liveryID, heading });
|
|
log(username + " spawned a " + coalition + " " + unitType, true);
|
|
}
|
|
|
|
if (key.compare("spawnAircrafts") == 0)
|
|
command = dynamic_cast<Command*>(new SpawnAircrafts(coalition, spawnOptions, airbaseName, country, immediate));
|
|
else
|
|
command = dynamic_cast<Command*>(new SpawnHelicopters(coalition, spawnOptions, airbaseName, country, immediate));
|
|
}
|
|
/************************/
|
|
else if (key.compare("spawnGroundUnits") == 0 || key.compare("spawnNavyUnits") == 0)
|
|
{
|
|
bool immediate = value[L"immediate"].as_bool();
|
|
string coalition = to_string(value[L"coalition"]);
|
|
string country = to_string(value[L"country"]);
|
|
|
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
|
if (!checkSpawnPoints(spawnPoints, coalition)) {
|
|
log(username + " insufficient spawn points ", true);
|
|
return;
|
|
}
|
|
|
|
vector<SpawnOptions> spawnOptions;
|
|
for (auto unit : value[L"units"].as_array()) {
|
|
string unitType = to_string(unit[L"unitType"]);
|
|
double lat = unit[L"location"][L"lat"].as_double();
|
|
double lng = unit[L"location"][L"lng"].as_double();
|
|
double heading = 0;
|
|
if (unit.has_number_field(L"heading"))
|
|
heading = unit[L"heading"].as_double();
|
|
|
|
Coords location; location.lat = lat; location.lng = lng;
|
|
string liveryID = to_string(unit[L"liveryID"]);
|
|
string skill = to_string(unit[L"skill"]);
|
|
|
|
spawnOptions.push_back({ unitType, location, "", skill, liveryID, heading });
|
|
log(username + " spawned a " + coalition + " " + unitType, true);
|
|
}
|
|
|
|
if (key.compare("spawnGroundUnits") == 0)
|
|
command = dynamic_cast<Command*>(new SpawnGroundUnits(coalition, spawnOptions, country, immediate));
|
|
else
|
|
command = dynamic_cast<Command*>(new SpawnNavyUnits(coalition, spawnOptions, country, immediate));
|
|
}
|
|
/************************/
|
|
else if (key.compare("attackUnit") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
unsigned int targetID = value[L"targetID"].as_integer();
|
|
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
Unit* target = unitsManager->getUnit(targetID);
|
|
|
|
if (unit != nullptr && target != nullptr) {
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to attack unit " + target->getUnitName() + "(" + target->getName() + ")", true);
|
|
unit->setTargetID(targetID);
|
|
unit->setState(State::ATTACK);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("followUnit") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
unsigned int leaderID = value[L"targetID"].as_integer();
|
|
double offsetX = value[L"offsetX"].as_double();
|
|
double offsetY = value[L"offsetY"].as_double();
|
|
double offsetZ = value[L"offsetZ"].as_double();
|
|
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
Unit* leader = unitsManager->getUnit(leaderID);
|
|
|
|
if (unit != nullptr && leader != nullptr) {
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to follow unit " + leader->getUnitName() + "(" + leader->getName() + ")", true);
|
|
unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ));
|
|
unit->setLeaderID(leaderID);
|
|
unit->setState(State::FOLLOW);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("changeSpeed") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->changeSpeed(to_string(value[L"change"]));
|
|
log(username + " changed " + unit->getUnitName() + "(" + unit->getName() + ") speed: " + to_string(value[L"change"]), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("changeAltitude") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->changeAltitude(to_string(value[L"change"]));
|
|
log(username + " changed " + unit->getUnitName() + "(" + unit->getName() + ") altitude: " + to_string(value[L"change"]), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setSpeed") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setDesiredSpeed(value[L"speed"].as_double());
|
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") speed: " + to_string(value[L"speed"].as_double()), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setSpeedType") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setDesiredSpeedType(to_string(value[L"speedType"]));
|
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") speed type: " + to_string(value[L"speedType"]), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setAltitude") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setDesiredAltitude(value[L"altitude"].as_double());
|
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") altitude: " + to_string(value[L"altitude"].as_double()), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setAltitudeType") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setDesiredAltitudeType(to_string(value[L"altitudeType"]));
|
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") altitude type: " + to_string(value[L"altitudeType"]), true);
|
|
}
|
|
}/************************/
|
|
else if (key.compare("setRacetrack") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setRacetrackLength(value[L"length"].as_double());
|
|
|
|
double lat = value[L"location"][L"lat"].as_double();
|
|
double lng = value[L"location"][L"lng"].as_double();
|
|
Coords location; location.lat = lat; location.lng = lng;
|
|
unit->setRacetrackAnchor(location);
|
|
|
|
unit->setRacetrackBearing(value[L"bearing"].as_double());
|
|
|
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") racetrack length: " + to_string(value[L"length"].as_double()) + " racetrack bearing: " + to_string(value[L"bearing"].as_double()), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("cloneUnits") == 0)
|
|
{
|
|
vector<CloneOptions> cloneOptions;
|
|
bool deleteOriginal = value[L"deleteOriginal"].as_bool();
|
|
string coalition = to_string(value[L"coalition"]);
|
|
|
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
|
if (coalition.compare("all") != 0 && !checkSpawnPoints(spawnPoints, coalition)) {
|
|
log(username + " insufficient spawn points ", true);
|
|
return;
|
|
}
|
|
|
|
for (auto unit : value[L"units"].as_array()) {
|
|
unsigned int ID = unit[L"ID"].as_integer();
|
|
double lat = unit[L"location"][L"lat"].as_double();
|
|
double lng = unit[L"location"][L"lng"].as_double();
|
|
|
|
Coords location; location.lat = lat; location.lng = lng;
|
|
cloneOptions.push_back({ ID, location });
|
|
log(username + " cloning unit with ID " + to_string(ID), true);
|
|
}
|
|
|
|
command = dynamic_cast<Command*>(new Clone(cloneOptions, deleteOriginal));
|
|
}
|
|
/************************/
|
|
else if (key.compare("setROE") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unsigned char ROE = value[L"ROE"].as_number().to_uint32();
|
|
unit->setROE(ROE);
|
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") ROE to " + to_string(ROE), true);
|
|
}
|
|
}
|
|
else if (key.compare("setAlarmState") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unsigned char alarmState = value[L"alarmState"].as_number().to_uint32();
|
|
unit->setAlarmState(alarmState);
|
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") alarm state to " + to_string(alarmState), true);
|
|
}
|
|
else {
|
|
log("Error while setting setAlarmState. Unit does not exist.");
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setReactionToThreat") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().to_uint32();
|
|
unit->setReactionToThreat(reactionToThreat);
|
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") reaction to threat to " + to_string(reactionToThreat), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setEmissionsCountermeasures") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().to_uint32();
|
|
unit->setEmissionsCountermeasures(emissionsCountermeasures);
|
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") emissions and countermeasures to " + to_string(emissionsCountermeasures), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("landAt") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(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;
|
|
unit->landAt(loc);
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to land", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("deleteUnit") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
bool explosion = value[L"explosion"].as_bool();
|
|
string explosionType = to_string(value[L"explosionType"]);
|
|
bool immediate = value[L"immediate"].as_bool();
|
|
Unit* unit = unitsManager->getUnit(ID);
|
|
if (unit != nullptr) {
|
|
unitsManager->deleteUnit(ID, explosion, explosionType, immediate);
|
|
log(username + " deleted unit " + unit->getUnitName() + "(" + unit->getName() + ")", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("refuel") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setState(State::REFUEL);
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to refuel", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setAdvancedOptions") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr)
|
|
{
|
|
/* Advanced tasking */
|
|
unit->setIsActiveTanker(value[L"isActiveTanker"].as_bool());
|
|
unit->setIsActiveAWACS(value[L"isActiveAWACS"].as_bool());
|
|
|
|
/* TACAN Options */
|
|
DataTypes::TACAN TACAN;
|
|
TACAN.isOn = value[L"TACAN"][L"isOn"].as_bool();
|
|
TACAN.channel = static_cast<unsigned char>(value[L"TACAN"][L"channel"].as_number().to_uint32());
|
|
TACAN.XY = to_string(value[L"TACAN"][L"XY"]).at(0);
|
|
string callsign = to_string(value[L"TACAN"][L"callsign"]);
|
|
if (callsign.length() > 3)
|
|
callsign = callsign.substr(0, 3);
|
|
strcpy_s(TACAN.callsign, 4, callsign.c_str());
|
|
unit->setTACAN(TACAN);
|
|
|
|
/* Radio Options */
|
|
auto radio = value[L"radio"];
|
|
unit->setRadio({ radio[L"frequency"].as_number().to_uint32(),
|
|
static_cast<unsigned char>(radio[L"callsign"].as_number().to_uint32()),
|
|
static_cast<unsigned char>(radio[L"callsignNumber"].as_number().to_uint32())
|
|
});
|
|
|
|
/* General Settings */
|
|
auto generalSettings = value[L"generalSettings"];
|
|
unit->setGeneralSettings({ generalSettings[L"prohibitJettison"].as_bool(),
|
|
generalSettings[L"prohibitAA"].as_bool(),
|
|
generalSettings[L"prohibitAG"].as_bool(),
|
|
generalSettings[L"prohibitAfterburner"].as_bool(),
|
|
generalSettings[L"prohibitAirWpn"].as_bool(),
|
|
});
|
|
|
|
unit->resetActiveDestination();
|
|
|
|
log(username + " updated unit " + unit->getUnitName() + "(" + unit->getName() + ") advancedOptions", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setEngagementProperties") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr)
|
|
{
|
|
/* Engagement properties tasking */
|
|
unit->setBarrelHeight(value[L"barrelHeight"].as_number().to_double());
|
|
unit->setMuzzleVelocity(value[L"muzzleVelocity"].as_number().to_double());
|
|
unit->setAimTime(value[L"aimTime"].as_number().to_double());
|
|
unit->setShotsToFire(value[L"shotsToFire"].as_number().to_uint32());
|
|
unit->setShotsBaseInterval(value[L"shotsBaseInterval"].as_number().to_double());
|
|
unit->setShotsBaseScatter(value[L"shotsBaseScatter"].as_number().to_double());
|
|
unit->setEngagementRange(value[L"engagementRange"].as_number().to_double());
|
|
unit->setTargetingRange(value[L"targetingRange"].as_number().to_double());
|
|
unit->setAimMethodRange(value[L"aimMethodRange"].as_number().to_double());
|
|
unit->setAcquisitionRange(value[L"acquisitionRange"].as_number().to_double());
|
|
|
|
log(username + " updated unit " + unit->getUnitName() + "(" + unit->getName() + ") engagementProperties", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setFollowRoads") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
bool followRoads = value[L"followRoads"].as_bool();
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setFollowRoads(followRoads);
|
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") followRoads to: " + (followRoads ? "true" : "false"), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setOnOff") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
bool onOff = value[L"onOff"].as_bool();
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setOnOff(onOff);
|
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") onOff to: " + (onOff ? "true" : "false"), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("explosion") == 0)
|
|
{
|
|
unsigned int intensity = value[L"intensity"].as_integer();
|
|
string explosionType = to_string(value[L"explosionType"]);
|
|
double lat = value[L"location"][L"lat"].as_double();
|
|
double lng = value[L"location"][L"lng"].as_double();
|
|
log("Adding explosion of type " + explosionType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
|
command = dynamic_cast<Command*>(new Explosion(intensity, explosionType, loc));
|
|
}
|
|
/************************/
|
|
else if (key.compare("bombPoint") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
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;
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setTargetPosition(loc);
|
|
unit->setState(State::BOMB_POINT);
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to bomb a point", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("carpetBomb") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
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;
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setTargetPosition(loc);
|
|
unit->setState(State::CARPET_BOMB);
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to perform carpet bombing", true);
|
|
}
|
|
}
|
|
/************************/
|
|
/* TODO: this command does not appear to be working in DCS and has been disabled */
|
|
else if (key.compare("bombBuilding") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
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;
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setTargetPosition(loc);
|
|
unit->setState(State::BOMB_BUILDING);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("fireAtArea") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
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;
|
|
|
|
if (value[L"location"].has_number_field(L"alt")) {
|
|
loc.alt = value[L"location"][L"alt"].as_double();
|
|
}
|
|
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setTargetPosition(loc);
|
|
unit->setState(State::FIRE_AT_AREA);
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to fire at area", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("simulateFireFight") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
double lat = value[L"location"][L"lat"].as_double();
|
|
double lng = value[L"location"][L"lng"].as_double();
|
|
double alt = value[L"altitude"].as_double();
|
|
Coords loc; loc.lat = lat; loc.lng = lng; loc.alt = alt;
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setTargetPosition(loc);
|
|
unit->setState(State::SIMULATE_FIRE_FIGHT);
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to simulate a fire fight", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("scenicAAA") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setState(State::SCENIC_AAA);
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to enter scenic AAA state", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("missOnPurpose") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unit->setState(State::MISS_ON_PURPOSE);
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to enter Miss On Purpose state", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setOperateAs") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
unsigned char operateAs = value[L"operateAs"].as_number().to_uint32();
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr)
|
|
unit->setOperateAs(operateAs);
|
|
}
|
|
/************************/
|
|
else if (key.compare("landAtPoint") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
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;
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
|
|
if (unit != nullptr) {
|
|
list<Coords> newPath;
|
|
newPath.push_back(loc);
|
|
unit->setActivePath(newPath);
|
|
unit->setState(State::LAND_AT_POINT);
|
|
|
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to land at point", true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setShotsScatter") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unsigned char shotsScatter = value[L"shotsScatter"].as_number().to_uint32();
|
|
unit->setShotsScatter(shotsScatter);
|
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") shots scatter to " + to_string(shotsScatter), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setShotsIntensity") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
unitsManager->acquireControl(ID);
|
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
|
if (unit != nullptr) {
|
|
unsigned char shotsIntensity = value[L"shotsIntensity"].as_number().to_uint32();
|
|
unit->setShotsIntensity(shotsIntensity);
|
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") shots intensity to " + to_string(shotsIntensity), true);
|
|
}
|
|
}
|
|
/************************/
|
|
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("Firing laser with code " + to_string(code) + " from unit " + unit->getUnitName() + " to (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
|
|
command = dynamic_cast<Command*>(new FireLaser(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("Firing infrared from unit " + unit->getUnitName() + " to (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
|
|
command = dynamic_cast<Command*>(new FireInfrared(ID, loc));
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setLaserCode") == 0)
|
|
{
|
|
unsigned int spotID = value[L"spotID"].as_integer();
|
|
unsigned int code = value[L"code"].as_integer();
|
|
|
|
log("Setting laser code " + to_string(code) + " to spot with ID " + to_string(spotID));
|
|
command = dynamic_cast<Command*>(new SetLaserCode(spotID, code));
|
|
}
|
|
/************************/
|
|
else if (key.compare("moveSpot") == 0)
|
|
{
|
|
unsigned int spotID = value[L"spotID"].as_integer();
|
|
|
|
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("Moving spot with ID " + to_string(spotID) + " to (" + to_string(lat) + ", " + to_string(lng) + ")");
|
|
command = dynamic_cast<Command*>(new MoveSpot(spotID, loc));
|
|
}
|
|
/************************/
|
|
else if (key.compare("deleteSpot") == 0)
|
|
{
|
|
unsigned int spotID = value[L"spotID"].as_integer();
|
|
log("Deleting spot with ID " + to_string(spotID));
|
|
command = dynamic_cast<Command*>(new DeleteSpot(spotID));
|
|
}
|
|
/************************/
|
|
else if (key.compare("setCommandModeOptions") == 0)
|
|
{
|
|
setCommandModeOptions(value);
|
|
log(username + " updated the Command Mode Options", true);
|
|
}
|
|
/************************/
|
|
else if (key.compare("reloadDatabases") == 0) {
|
|
unitsManager->loadDatabases();
|
|
}
|
|
/************************/
|
|
else if (key.compare("setCargoWeight") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
Unit* unit = unitsManager->getUnit(ID);
|
|
if (unit != nullptr) {
|
|
double weight = value[L"weight"].as_double();
|
|
unit->setCargoWeight(weight);
|
|
log(username + " set weight to unit " + unit->getUnitName() + "(" + unit->getName() + "), " + to_string(weight), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("registerDrawArgument") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
Unit* unit = unitsManager->getUnit(ID);
|
|
if (unit != nullptr) {
|
|
int argument = value[L"argument"].as_integer();
|
|
bool active = value[L"active"].as_bool();
|
|
|
|
command = dynamic_cast<Command*>(new RegisterDrawArgument(ID, argument, active));
|
|
|
|
log(username + " registered draw argument " + to_string(argument) + " for unit " + unit->getUnitName() + "(" + unit->getName() + "), value:" + to_string(active), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setCustomString") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
Unit* unit = unitsManager->getUnit(ID);
|
|
if (unit != nullptr) {
|
|
string customString = to_string(value[L"customString"]);
|
|
unit->setCustomString(customString);
|
|
log(username + " set custom string to unit " + unit->getUnitName() + "(" + unit->getName() + "), " + customString, true);
|
|
}
|
|
}
|
|
/************************/
|
|
else if (key.compare("setCustomInteger") == 0)
|
|
{
|
|
unsigned int ID = value[L"ID"].as_integer();
|
|
Unit* unit = unitsManager->getUnit(ID);
|
|
if (unit != nullptr) {
|
|
double customNumber = value[L"customInteger"].as_double();
|
|
unit->setCustomInteger(customNumber);
|
|
log(username + " set custom number to unit " + unit->getUnitName() + "(" + unit->getName() + "), " + to_string(customNumber), true);
|
|
}
|
|
}
|
|
/************************/
|
|
else
|
|
{
|
|
log("Unknown command: " + key);
|
|
}
|
|
|
|
if (command != nullptr)
|
|
{
|
|
appendCommand(command);
|
|
log("New command appended correctly to stack. Current server load: " + to_string(getLoad()));
|
|
answer[L"commandHash"] = json::value(to_wstring(command->getHash()));
|
|
}
|
|
}
|
|
|