Completed advanced controls also for units

This commit is contained in:
Pax1601
2023-06-11 18:21:12 +02:00
parent fd00cffa15
commit 1d4ecf5316
28 changed files with 896 additions and 285 deletions

View File

@@ -97,14 +97,15 @@ protected:
class Move : public Command
{
public:
Move(int ID, Coords destination, double speed, wstring speedType, double altitude, wstring altitudeType, wstring taskOptions):
ID(ID),
Move(wstring groupName, Coords destination, double speed, wstring speedType, double altitude, wstring altitudeType, wstring taskOptions, wstring category):
groupName(groupName),
destination(destination),
speed(speed),
speedType(speedType),
altitude(altitude),
altitudeType(altitudeType),
taskOptions(taskOptions)
taskOptions(taskOptions),
category(category)
{
priority = CommandPriority::HIGH;
};
@@ -112,13 +113,14 @@ public:
virtual int getLoad() { return 5; }
private:
const int ID;
const wstring groupName;
const Coords destination;
const double speed;
const wstring speedType;
const double altitude;
const wstring altitudeType;
const wstring taskOptions;
const wstring category;
};
/* Smoke command */
@@ -223,8 +225,8 @@ private:
class SetTask : public Command
{
public:
SetTask(int ID, wstring task) :
ID(ID),
SetTask(wstring groupName, wstring task) :
groupName(groupName),
task(task)
{
priority = CommandPriority::MEDIUM;
@@ -233,7 +235,7 @@ public:
virtual int getLoad() { return 10; }
private:
const int ID;
const wstring groupName;
const wstring task;
};
@@ -241,8 +243,8 @@ private:
class ResetTask : public Command
{
public:
ResetTask(int ID) :
ID(ID)
ResetTask(wstring groupName) :
groupName(groupName)
{
priority = CommandPriority::HIGH;
};
@@ -250,15 +252,15 @@ public:
virtual int getLoad() { return 10; }
private:
const int ID;
const wstring groupName;
};
/* Set command */
class SetCommand : public Command
{
public:
SetCommand(int ID, wstring command) :
ID(ID),
SetCommand(wstring groupName, wstring command) :
groupName(groupName),
command(command)
{
priority = CommandPriority::HIGH;
@@ -267,7 +269,7 @@ public:
virtual int getLoad() { return 10; }
private:
const int ID;
const wstring groupName;
const wstring command;
};
@@ -275,8 +277,8 @@ private:
class SetOption : public Command
{
public:
SetOption(int ID, int optionID, int optionValue) :
ID(ID),
SetOption(wstring groupName, int optionID, int optionValue) :
groupName(groupName),
optionID(optionID),
optionValue(optionValue),
optionBool(false),
@@ -285,8 +287,8 @@ public:
priority = CommandPriority::HIGH;
};
SetOption(int ID, int optionID, bool optionBool) :
ID(ID),
SetOption(wstring groupName, int optionID, bool optionBool) :
groupName(groupName),
optionID(optionID),
optionValue(0),
optionBool(optionBool),
@@ -298,7 +300,7 @@ public:
virtual int getLoad() { return 10; }
private:
const int ID;
const wstring groupName;
const int optionID;
const int optionValue;
const bool optionBool;
@@ -309,8 +311,8 @@ private:
class SetOnOff : public Command
{
public:
SetOnOff(int ID, bool onOff) :
ID(ID),
SetOnOff(wstring groupName, bool onOff) :
groupName(groupName),
onOff(onOff)
{
priority = CommandPriority::HIGH;
@@ -319,7 +321,7 @@ public:
virtual int getLoad() { return 10; }
private:
const int ID;
const wstring groupName;
const bool onOff;
};

View File

@@ -6,6 +6,8 @@
#include "measure.h"
#include "logger.h"
#define TASK_CHECK_INIT_VALUE 10
namespace State
{
enum States
@@ -63,7 +65,7 @@ public:
int getID() { return ID; }
void updateExportData(json::value json);
void updateMissionData(json::value json);
json::value getData(long long time);
json::value getData(long long time, bool getAll = false);
virtual wstring getCategory() { return L"No category"; };
/********** Base data **********/
@@ -100,7 +102,7 @@ public:
void setFuel(double newFuel) { fuel = newFuel; addMeasure(L"fuel", json::value(newFuel));}
void setAmmo(json::value newAmmo) { ammo = newAmmo; addMeasure(L"ammo", json::value(newAmmo));}
void setTargets(json::value newTargets) {targets = newTargets; addMeasure(L"targets", json::value(newTargets));}
void setHasTask(bool newHasTask) { hasTask = newHasTask; addMeasure(L"hasTask", json::value(newHasTask)); }
void setHasTask(bool newHasTask);
void setCoalitionID(int newCoalitionID);
void setFlags(json::value newFlags) { flags = newFlags; addMeasure(L"flags", json::value(newFlags));}
@@ -181,6 +183,7 @@ protected:
int ID;
map<wstring, Measure*> measures;
int taskCheckCounter = 0;
/********** Base data **********/
bool AI = false;
@@ -252,4 +255,6 @@ protected:
bool setActiveDestination();
bool updateActivePath(bool looping);
void goToDestination(wstring enrouteTask = L"nil");
bool checkTaskFailed();
void resetTaskFailedCounter();
};

View File

@@ -11,6 +11,11 @@ public:
~UnitsManager();
Unit* getUnit(int ID);
bool isUnitInGroup(Unit* unit);
bool isUnitGroupLeader(Unit* unit);
Unit* getGroupLeader(int ID);
Unit* getGroupLeader(Unit* unit);
vector<Unit*> getGroupMembers(wstring groupName);
void updateExportData(lua_State* L);
void updateMissionData(json::value missionData);
void getData(json::value& answer, long long time);

View File

@@ -143,7 +143,7 @@ void AirUnit::AIloop()
else {
taskSS << "{ id = 'Orbit', pattern = 'Circle' }";
}
Command* command = dynamic_cast<Command*>(new SetTask(ID, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -248,7 +248,7 @@ void AirUnit::AIloop()
<< "z = " << formationOffset.z
<< "},"
<< "}";
Command* command = dynamic_cast<Command*>(new SetTask(ID, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -264,7 +264,7 @@ void AirUnit::AIloop()
taskSS << "{"
<< "id = 'Refuel'"
<< "}";
Command* command = dynamic_cast<Command*>(new SetTask(ID, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -279,7 +279,7 @@ void AirUnit::AIloop()
if (!getHasTask()) {
std::wostringstream taskSS;
taskSS << "{id = 'Bombing', lat = " << targetLocation.lat << ", lng = " << targetLocation.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(ID, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -290,10 +290,11 @@ void AirUnit::AIloop()
if (!getHasTask()) {
std::wostringstream taskSS;
taskSS << "{id = 'CarpetBombing', lat = " << targetLocation.lat << ", lng = " << targetLocation.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(ID, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
case State::BOMB_BUILDING: {
currentTask = L"Bombing building";
@@ -301,14 +302,16 @@ void AirUnit::AIloop()
if (!getHasTask()) {
std::wostringstream taskSS;
taskSS << "{id = 'AttackMapObject', lat = " << targetLocation.lat << ", lng = " << targetLocation.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(ID, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
default:
break;
}
addMeasure(L"currentTask", json::value(currentTask));
}

View File

@@ -9,27 +9,20 @@ extern UnitsManager* unitsManager;
/* Move command */
wstring Move::getString(lua_State* L)
{
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr)
{
std::wostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.move, "
<< ID << ", "
<< destination.lat << ", "
<< destination.lng << ", "
<< altitude << ", "
<< "\"" << altitudeType << "\"" << ", "
<< speed << ", "
<< "\"" << speedType << "\"" << ", "
<< "\"" << unit->getCategory() << "\"" << ", "
<< taskOptions;
return commandSS.str();
}
else
{
return L"";
}
std::wostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.move, "
<< "\"" << groupName << "\"" << ", "
<< destination.lat << ", "
<< destination.lng << ", "
<< altitude << ", "
<< "\"" << altitudeType << "\"" << ", "
<< speed << ", "
<< "\"" << speedType << "\"" << ", "
<< "\"" << category << "\"" << ", "
<< taskOptions;
return commandSS.str();
}
/* Smoke command */
@@ -117,7 +110,7 @@ wstring SetTask::getString(lua_State* L)
std::wostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.setTask, "
<< ID << ", "
<< "\"" << groupName << "\"" << ", "
<< task;
return commandSS.str();
@@ -129,7 +122,7 @@ wstring ResetTask::getString(lua_State* L)
std::wostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.resetTask, "
<< ID;
<< "\"" << groupName << "\"";
return commandSS.str();
}
@@ -140,7 +133,7 @@ wstring SetCommand::getString(lua_State* L)
std::wostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.setCommand, "
<< ID << ", "
<< "\"" << groupName << "\"" << ", "
<< command;
return commandSS.str();
@@ -154,12 +147,12 @@ wstring SetOption::getString(lua_State* L)
if (!isBoolean) {
commandSS << "Olympus.setOption, "
<< ID << ", "
<< "\"" << groupName << "\"" << ", "
<< optionID << ", "
<< optionValue;
} else {
commandSS << "Olympus.setOption, "
<< ID << ", "
<< "\"" << groupName << "\"" << ", "
<< optionID << ", "
<< (optionBool? "true": "false");
}
@@ -173,7 +166,7 @@ wstring SetOnOff::getString(lua_State* L)
commandSS.precision(10);
commandSS << "Olympus.setOnOff, "
<< ID << ", "
<< "\"" << groupName << "\"" << ", "
<< (onOff ? "true" : "false");
return commandSS.str();

View File

@@ -73,7 +73,6 @@ void GroundUnit::setState(int newState)
void GroundUnit::AIloop()
{
switch (state) {
case State::IDLE: {
currentTask = L"Idle";
@@ -112,7 +111,7 @@ void GroundUnit::AIloop()
if (!getHasTask()) {
std::wostringstream taskSS;
taskSS << "{id = 'FireAtPoint', lat = " << targetLocation.lat << ", lng = " << targetLocation.lng << ", radius = 1000}";
Command* command = dynamic_cast<Command*>(new SetTask(ID, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -140,7 +139,7 @@ void GroundUnit::changeSpeed(wstring change)
void GroundUnit::setOnOff(bool newOnOff)
{
Unit::setOnOff(newOnOff);
Command* command = dynamic_cast<Command*>(new SetOnOff(ID, onOff));
Command* command = dynamic_cast<Command*>(new SetOnOff(groupName, onOff));
scheduler->appendCommand(command);
}

View File

@@ -59,7 +59,8 @@ void Scheduler::handleRequest(wstring key, json::value value)
if (key.compare(L"setPath") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
{
wstring unitName = unit->getUnitName();
@@ -75,15 +76,9 @@ void Scheduler::handleRequest(wstring key, json::value value)
newPath.push_back(dest);
}
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr)
{
unit->setActivePath(newPath);
unit->setState(State::REACH_DESTINATION);
log(unitName + L" new path set successfully");
}
else
log(unitName + L" not found, request will be discarded");
unit->setActivePath(newPath);
unit->setState(State::REACH_DESTINATION);
log(unitName + L" new path set successfully");
}
}
else if (key.compare(L"smoke") == 0)
@@ -123,7 +118,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
int ID = value[L"ID"].as_integer();
int targetID = value[L"targetID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
Unit* target = unitsManager->getUnit(targetID);
wstring unitName;
@@ -151,7 +146,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
int offsetY = value[L"offsetY"].as_integer();
int offsetZ = value[L"offsetZ"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
Unit* leader = unitsManager->getUnit(leaderID);
wstring unitName;
@@ -175,42 +170,42 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"changeSpeed") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->changeSpeed(value[L"change"].as_string());
}
else if (key.compare(L"changeAltitude") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->changeAltitude(value[L"change"].as_string());
}
else if (key.compare(L"setSpeed") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setTargetSpeed(value[L"speed"].as_double());
}
else if (key.compare(L"setSpeedType") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setTargetSpeedType(value[L"speedType"].as_string());
}
else if (key.compare(L"setAltitude") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setTargetAltitude(value[L"altitude"].as_double());
}
else if (key.compare(L"setAltitudeType") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setTargetAltitudeType(value[L"altitudeType"].as_string());
}
@@ -226,28 +221,28 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"setROE") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
wstring ROE = value[L"ROE"].as_string();
unit->setROE(ROE);
}
else if (key.compare(L"setReactionToThreat") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
wstring reactionToThreat = value[L"reactionToThreat"].as_string();
unit->setReactionToThreat(reactionToThreat);
}
else if (key.compare(L"setEmissionsCountermeasures") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
wstring emissionsCountermeasures = value[L"emissionsCountermeasures"].as_string();
unit->setEmissionsCountermeasures(emissionsCountermeasures);
}
else if (key.compare(L"landAt") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(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;
@@ -262,13 +257,13 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"refuel") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setState(State::REFUEL);
}
else if (key.compare(L"setAdvancedOptions") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
{
/* Advanced tasking */
@@ -306,14 +301,14 @@ void Scheduler::handleRequest(wstring key, json::value value)
{
int ID = value[L"ID"].as_integer();
bool followRoads = value[L"followRoads"].as_bool();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setFollowRoads(followRoads);
}
else if (key.compare(L"setOnOff") == 0)
{
int ID = value[L"ID"].as_integer();
bool onOff = value[L"onOff"].as_bool();
Unit* unit = unitsManager->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setOnOff(onOff);
}
else if (key.compare(L"explosion") == 0)
@@ -331,8 +326,9 @@ void Scheduler::handleRequest(wstring key, json::value value)
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->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setState(State::BOMB_POINT);
unit->setTargetLocation(loc);
}
else if (key.compare(L"carpetBomb") == 0)
{
@@ -340,8 +336,9 @@ void Scheduler::handleRequest(wstring key, json::value value)
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->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setState(State::CARPET_BOMB);
unit->setTargetLocation(loc);
}
else if (key.compare(L"bombBuilding") == 0)
{
@@ -349,8 +346,9 @@ void Scheduler::handleRequest(wstring key, json::value value)
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->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setState(State::BOMB_BUILDING);
unit->setTargetLocation(loc);
}
else if (key.compare(L"fireAtArea") == 0)
{
@@ -358,8 +356,9 @@ void Scheduler::handleRequest(wstring key, json::value value)
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->getUnit(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setState(State::FIRE_AT_AREA);
unit->setTargetLocation(loc);
}
else
{

View File

@@ -116,8 +116,21 @@ void Unit::updateExportData(json::value json)
setAI(getUnitName().find(L"Olympus") != wstring::npos);
/* If the unit is alive and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
if (getAI() && getAlive() && getFlags()[L"Human"].as_bool() == false)
// TODO at the moment groups will stop moving correctly if the leader dies
const bool isUnitControlledByOlympus = getAI();
const bool isUnitAlive = getAlive();
const bool isUnitLeader = unitsManager->isUnitGroupLeader(this);
const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this);
const bool isUnitHuman = getFlags()[L"Human"].as_bool();
// Keep running the AI loop even if the unit is dead if it is the leader of a group which has other members in it
if (isUnitControlledByOlympus && (isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits) && isUnitLeader && !isUnitHuman)
{
if (checkTaskFailed() && state != State::IDLE && State::LAND)
setState(State::IDLE);
AIloop();
}
}
void Unit::updateMissionData(json::value json)
@@ -132,10 +145,14 @@ void Unit::updateMissionData(json::value json)
setHasTask(json[L"hasTask"].as_bool());
}
json::value Unit::getData(long long time)
json::value Unit::getData(long long time, bool sendAll)
{
auto json = json::value::object();
/* If the unit is in a group, task & option data is given by the group leader */
if (unitsManager->isUnitInGroup(this) && !unitsManager->isUnitGroupLeader(this))
json = unitsManager->getGroupLeader(this)->getData(time, true);
/********** Base data **********/
json[L"baseData"] = json::value::object();
for (auto key : { L"AI", L"name", L"unitName", L"groupName", L"alive", L"category"})
@@ -146,7 +163,7 @@ json::value Unit::getData(long long time)
if (json[L"baseData"].size() == 0)
json.erase(L"baseData");
if (alive) {
if (alive || sendAll) {
/********** Flight data **********/
json[L"flightData"] = json::value::object();
for (auto key : { L"latitude", L"longitude", L"altitude", L"speed", L"heading" })
@@ -177,25 +194,28 @@ json::value Unit::getData(long long time)
if (json[L"formationData"].size() == 0)
json.erase(L"formationData");
/********** Task data **********/
json[L"taskData"] = json::value::object();
for (auto key : { L"currentState", L"currentTask", L"targetSpeed", L"targetAltitude", L"targetSpeedType", L"targetAltitudeType", L"activePath", L"isTanker", L"isAWACS", L"onOff", L"followRoads", L"targetID", L"targetLocation"})
{
if (measures.find(key) != measures.end() && measures[key]->getTime() > time)
json[L"taskData"][key] = measures[key]->getValue();
}
if (json[L"taskData"].size() == 0)
json.erase(L"taskData");
/* If the unit is in a group, task & option data is given by the group leader */
if (unitsManager->isUnitGroupLeader(this)) {
/********** Task data **********/
json[L"taskData"] = json::value::object();
for (auto key : { L"currentState", L"currentTask", L"targetSpeed", L"targetAltitude", L"targetSpeedType", L"targetAltitudeType", L"activePath", L"isTanker", L"isAWACS", L"onOff", L"followRoads", L"targetID", L"targetLocation" })
{
if (measures.find(key) != measures.end() && measures[key]->getTime() > time)
json[L"taskData"][key] = measures[key]->getValue();
}
if (json[L"taskData"].size() == 0)
json.erase(L"taskData");
/********** Options data **********/
json[L"optionsData"] = json::value::object();
for (auto key : { L"ROE", L"reactionToThreat", L"emissionsCountermeasures", L"TACAN", L"radio", L"generalSettings"})
{
if (measures.find(key) != measures.end() && measures[key]->getTime() > time)
json[L"optionsData"][key] = measures[key]->getValue();
/********** Options data **********/
json[L"optionsData"] = json::value::object();
for (auto key : { L"ROE", L"reactionToThreat", L"emissionsCountermeasures", L"TACAN", L"radio", L"generalSettings" })
{
if (measures.find(key) != measures.end() && measures[key]->getTime() > time)
json[L"optionsData"][key] = measures[key]->getValue();
}
if (json[L"optionsData"].size() == 0)
json.erase(L"optionsData");
}
if (json[L"optionsData"].size() == 0)
json.erase(L"optionsData");
}
return json;
@@ -322,9 +342,10 @@ void Unit::resetActiveDestination()
void Unit::resetTask()
{
Command* command = dynamic_cast<Command*>(new ResetTask(ID));
Command* command = dynamic_cast<Command*>(new ResetTask(groupName));
scheduler->appendCommand(command);
setHasTask(false);
resetTaskFailedCounter();
}
void Unit::setFormationOffset(Offset newFormationOffset)
@@ -353,7 +374,7 @@ void Unit::setROE(wstring newROE) {
else
return;
Command* command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::ROE, ROEEnum));
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ROE, ROEEnum));
scheduler->appendCommand(command);
}
}
@@ -378,7 +399,7 @@ void Unit::setReactionToThreat(wstring newReactionToThreat) {
else
return;
Command* command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::REACTION_ON_THREAT, reactionToThreatEnum));
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::REACTION_ON_THREAT, reactionToThreatEnum));
scheduler->appendCommand(command);
}
}
@@ -421,13 +442,13 @@ void Unit::setEmissionsCountermeasures(wstring newEmissionsCountermeasures) {
Command* command;
command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::RADAR_USING, radarEnum));
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::RADAR_USING, radarEnum));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::FLARE_USING, flareEnum));
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::FLARE_USING, flareEnum));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::ECM_USING, ECMEnum));
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ECM_USING, ECMEnum));
scheduler->appendCommand(command);
}
}
@@ -474,7 +495,7 @@ void Unit::setTACAN(Options::TACAN newTACAN) {
<< "frequency = " << TACANChannelToFrequency(TACAN.channel, TACAN.XY) << ","
<< "}"
<< "}";
Command* command = dynamic_cast<Command*>(new SetCommand(ID, commandSS.str()));
Command* command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
}
else {
@@ -484,7 +505,7 @@ void Unit::setTACAN(Options::TACAN newTACAN) {
<< "params = {"
<< "}"
<< "}";
Command* command = dynamic_cast<Command*>(new SetCommand(ID, commandSS.str()));
Command* command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
}
}
@@ -512,7 +533,7 @@ void Unit::setRadio(Options::Radio newRadio) {
<< "frequency = " << radio.frequency << ","
<< "}"
<< "}";
command = dynamic_cast<Command*>(new SetCommand(ID, commandSS.str()));
command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
// Clear the stringstream
@@ -525,7 +546,7 @@ void Unit::setRadio(Options::Radio newRadio) {
<< "number = " << radio.callsignNumber << ","
<< "}"
<< "}";
command = dynamic_cast<Command*>(new SetCommand(ID, commandSS.str()));
command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
}
}
@@ -564,15 +585,15 @@ void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings) {
generalSettings = newGeneralSettings;
Command* command;
command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::PROHIBIT_AA, generalSettings.prohibitAA));
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::PROHIBIT_AA, generalSettings.prohibitAA));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::PROHIBIT_AG, generalSettings.prohibitAG));
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::PROHIBIT_AG, generalSettings.prohibitAG));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::PROHIBIT_JETT, generalSettings.prohibitJettison));
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::PROHIBIT_JETT, generalSettings.prohibitJettison));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::PROHIBIT_AB, generalSettings.prohibitAfterburner));
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::PROHIBIT_AB, generalSettings.prohibitAfterburner));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::ENGAGE_AIR_WEAPONS, !generalSettings.prohibitAirWpn));
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ENGAGE_AIR_WEAPONS, !generalSettings.prohibitAirWpn));
scheduler->appendCommand(command);
}
}
@@ -605,7 +626,7 @@ void Unit::goToDestination(wstring enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(ID, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), enrouteTask));
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), enrouteTask, getCategory()));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -615,16 +636,20 @@ bool Unit::isDestinationReached(double threshold)
{
if (activeDestination != NULL)
{
double dist = 0;
Geodesic::WGS84().Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, dist);
if (dist < threshold)
/* Check if any unit in the group has reached the point */
for (auto const& p: unitsManager->getGroupMembers(groupName))
{
log(unitName + L" destination reached");
return true;
}
else {
return false;
}
double dist = 0;
Geodesic::WGS84().Inverse(p->getLatitude(), p->getLongitude(), activeDestination.lat, activeDestination.lng, dist);
if (dist < threshold)
{
log(unitName + L" destination reached");
return true;
}
else {
return false;
}
}
}
else
return true;
@@ -668,4 +693,23 @@ void Unit::setTargetLocation(Coords newTargetLocation) {
json[L"latitude"] = json::value(newTargetLocation.lat);
json[L"longitude"] = json::value(newTargetLocation.lng);
addMeasure(L"targetLocation", json::value(json));
}
bool Unit::checkTaskFailed() {
if (getHasTask())
return false;
else {
if (taskCheckCounter > 0)
taskCheckCounter--;
return taskCheckCounter == 0;
}
}
void Unit::resetTaskFailedCounter() {
taskCheckCounter = TASK_CHECK_INIT_VALUE;
}
void Unit::setHasTask(bool newHasTask) {
hasTask = newHasTask;
addMeasure(L"hasTask", json::value(newHasTask));
}

View File

@@ -32,6 +32,67 @@ Unit* UnitsManager::getUnit(int ID)
}
}
bool UnitsManager::isUnitInGroup(Unit* unit)
{
if (unit != nullptr) {
wstring groupName = unit->getGroupName();
for (auto const& p : units)
{
if (p.second->getGroupName().compare(groupName) == 0 && p.second != unit)
return true;
}
}
return false;
}
bool UnitsManager::isUnitGroupLeader(Unit* unit)
{
if (unit != nullptr)
return unit == getGroupLeader(unit);
else
return false;
}
// The group leader is the unit with the lowest ID that is part of the group. This is different from DCS's concept of leader, which will change if the leader is destroyed
Unit* UnitsManager::getGroupLeader(Unit* unit)
{
if (unit != nullptr) {
wstring groupName = unit->getGroupName();
/* Get the unit IDs in order */
std::vector<int> keys;
for (auto const& p : units)
keys.push_back(p.first);
sort(keys.begin(), keys.end());
/* Find the first unit that has the same groupName */
for (auto const& tempID : keys)
{
Unit* tempUnit = getUnit(tempID);
if (tempUnit != nullptr && tempUnit->getGroupName().compare(groupName) == 0)
return tempUnit;
}
}
return nullptr;
}
vector<Unit*> UnitsManager::getGroupMembers(wstring groupName)
{
vector<Unit*> members;
for (auto const& p : units)
{
if (p.second->getGroupName().compare(groupName) == 0)
members.push_back(p.second);
}
return members;
}
Unit* UnitsManager::getGroupLeader(int ID)
{
Unit* unit = getUnit(ID);
return getGroupLeader(unit);
}
void UnitsManager::updateExportData(lua_State* L)
{
map<int, json::value> unitJSONs = getAllUnits(L);