mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
895 lines
32 KiB
C++
895 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"]);
|
|
|
|
string payload = "nil";
|
|
if (unit.has_string_field(L"payload"))
|
|
payload = to_string(unit[L"payload"]);
|
|
|
|
spawnOptions.push_back({ unitType, location, loadout, skill, liveryID, heading, payload });
|
|
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()));
|
|
}
|
|
}
|
|
|