Implemented as described in issue

This commit is contained in:
Pax1601 2023-05-01 10:37:40 +02:00
parent ee08d9d48e
commit 640f764354
9 changed files with 59 additions and 234 deletions

View File

@ -29,11 +29,7 @@ interface MissionData {
}
interface FormationData {
formation: string;
isLeader: boolean;
isWingman: boolean;
leaderID: number;
wingmenIDs: number[];
}
interface TaskData {

View File

@ -381,57 +381,6 @@ export class HelicopterDatabase extends UnitDatabase {
],
"filename": "ah-1.png"
},
"AH-1W": {
"name": "AH-1W",
"label": "AH-1W Cobra",
"shortLabel": "AH1",
"loadouts": [
{
"fuel": 1,
"items": [
{
"name": "BGM-71 TOW",
"quantity": 8
},
{
"name": "Hydra-70 WP",
"quantity": 38
}
],
"roles": [
"CAS"
],
"code": "8xBGM-71, 38xHYDRA-70 WP",
"name": "TOW / Hydra"
},
{
"fuel": 1,
"items": [
{
"name": "Hydra-70",
"quantity": 76
}
],
"roles": [
"CAS"
],
"code": "76xHYDRA-70",
"name": "Hydra"
},
{
"fuel": 1,
"items": [
],
"roles": [
""
],
"code": "",
"name": "Empty Loadout"
}
],
"filename": "ah-1.png"
},
"Mi-26": {
"name": "Mi-26",
"label": "Mi-26 Halo",

View File

@ -40,11 +40,7 @@ export class Unit extends Marker {
coalition: "",
},
formationData: {
formation: "",
isLeader: false,
isWingman: false,
leaderID: 0,
wingmenIDs: [],
leaderID: 0
},
taskData: {
currentState: "IDLE",
@ -315,22 +311,6 @@ export class Unit extends Marker {
return getUnitsManager().getUnitByID(this.getFormationData().leaderID);
}
getFormation() {
return [<Unit>this].concat(this.getWingmen())
}
getWingmen() {
var wingmen: Unit[] = [];
if (this.getFormationData().wingmenIDs != undefined) {
for (let ID of this.getFormationData().wingmenIDs) {
var unit = getUnitsManager().getUnitByID(ID)
if (unit)
wingmen.push(unit);
}
}
return wingmen;
}
attackUnit(targetID: number) {
/* Units can't attack themselves */
if (this.ID != targetID) {

View File

@ -119,35 +119,7 @@ export class UnitsManager {
this.#units[ID].setSelected(false);
}
}
getSelectedLeaders() {
var leaders: Unit[] = [];
for (let idx in this.getSelectedUnits())
{
var unit = this.getSelectedUnits()[idx];
if (unit.getFormationData().isLeader)
leaders.push(unit);
else if (unit.getFormationData().isWingman)
{
var leader = unit.getLeader();
if (leader && !leaders.includes(leader))
leaders.push(leader);
}
}
return leaders;
}
getSelectedSingletons() {
var singletons: Unit[] = [];
for (let idx in this.getSelectedUnits())
{
var unit = this.getSelectedUnits()[idx];
if (!unit.getFormationData().isLeader && !unit.getFormationData().isWingman)
singletons.push(unit);
}
return singletons;
}
getSelectedUnitsType () {
if (this.getSelectedUnits().length == 0)
return undefined;

View File

@ -23,7 +23,6 @@ protected:
virtual void setState(int newState);
bool isDestinationReached();
bool setActiveDestination();
void createHoldingPattern();
bool updateActivePath(bool looping);
void goToDestination(wstring enrouteTask = L"nil");
};

View File

@ -79,17 +79,9 @@ public:
json::value getFlags() { return flags; }
/********** Formation data **********/
void setIsLeader(bool newIsLeader);
void setIsWingman(bool newIsWingman);
void setLeader(Unit* newLeader);
void setWingmen(vector<Unit*> newWingmen);
void setFormation(wstring newFormation) { formation = newFormation; addMeasure(L"formation", json::value(formation));}
void setLeaderID(int newLeaderID) { leaderID = newLeaderID; addMeasure(L"leaderID", json::value(newLeaderID)); }
void setFormationOffset(Offset formationOffset);
bool getIsLeader() { return isLeader; }
bool getIsWingman() { return isWingman; }
Unit* getLeader() { return leader; }
vector<Unit*> getWingmen() { return wingmen; }
wstring getFormation() { return formation; }
int getLeaderID() { return leaderID; }
Offset getFormationoffset() { return formationOffset; }
/********** Task data **********/
@ -177,11 +169,7 @@ protected:
json::value flags = json::value::null();
/********** Formation data **********/
bool isLeader = false;
bool isWingman = false;
wstring formation = L"";
Unit *leader = nullptr;
vector<Unit *> wingmen;
int leaderID = NULL;
Offset formationOffset = Offset(NULL);
/********** Task data **********/
@ -215,7 +203,9 @@ protected:
/********** Functions **********/
virtual wstring getCategory() { return L"No category"; };
wstring getTargetName();
wstring getLeaderName();
bool isTargetAlive();
bool isLeaderAlive();
virtual void AIloop() = 0;
void addMeasure(wstring key, json::value value);
};

View File

@ -22,7 +22,7 @@ void AirUnit::setState(int newState)
{
if (state != newState)
{
/* Perform any action required when LEAVING a certain state */
/************ Perform any action required when LEAVING a certain state ************/
switch (state) {
case State::IDLE: {
break;
@ -35,6 +35,7 @@ void AirUnit::setState(int newState)
break;
}
case State::FOLLOW: {
setLeaderID(NULL);
break;
}
case State::LAND: {
@ -47,7 +48,7 @@ void AirUnit::setState(int newState)
break;
}
/* Perform any action required when ENTERING a certain state */
/************ Perform any action required when ENTERING a certain state ************/
switch (newState) {
case State::IDLE: {
clearActivePath();
@ -135,23 +136,6 @@ bool AirUnit::setActiveDestination()
}
}
void AirUnit::createHoldingPattern()
{
/* Air units must ALWAYS have a destination or they will RTB and become uncontrollable */
clearActivePath();
Coords point1;
Coords point2;
Coords point3;
Geodesic::WGS84().Direct(latitude, longitude, 45, 10000, point1.lat, point1.lng);
Geodesic::WGS84().Direct(point1.lat, point1.lng, 135, 10000, point2.lat, point2.lng);
Geodesic::WGS84().Direct(point2.lat, point2.lng, 225, 10000, point3.lat, point3.lng);
pushActivePathBack(point1);
pushActivePathBack(point2);
pushActivePathBack(point3);
pushActivePathBack(Coords(latitude, longitude));
log(unitName + L" holding pattern created");
}
bool AirUnit::updateActivePath(bool looping)
{
if (activePath.size() > 0)
@ -282,22 +266,22 @@ void AirUnit::AIloop()
clearActivePath();
activeDestination = Coords(NULL);
/* If the target is not alive (either not set or was destroyed) go back to IDLE */
if (!isTargetAlive()) {
/* If the leader is not alive (either not set or was destroyed) go back to IDLE */
if (!isLeaderAlive()) {
setState(State::IDLE);
break;
}
currentTask = L"Following " + getTargetName();
Unit* target = unitsManager->getUnit(targetID);
Unit* leader = unitsManager->getUnit(leaderID);
if (!hasTask) {
if (target != nullptr && target->getAlive() && formationOffset != NULL)
if (leader != nullptr && leader->getAlive() && formationOffset != NULL)
{
std::wostringstream taskSS;
taskSS << "{"
<< "id = 'FollowUnit'" << ", "
<< "leaderID = " << target->getID() << ","
<< "leaderID = " << leader->getID() << ","
<< "offset = {"
<< "x = " << formationOffset.x << ","
<< "y = " << formationOffset.y << ","
@ -332,5 +316,6 @@ void AirUnit::AIloop()
default:
break;
}
addMeasure(L"currentTask", json::value(currentTask));
}

View File

@ -145,30 +145,30 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"followUnit") == 0)
{
int ID = value[L"ID"].as_integer();
int targetID = value[L"targetID"].as_integer();
int leaderID = value[L"targetID"].as_integer();
int offsetX = value[L"offsetX"].as_integer();
int offsetY = value[L"offsetY"].as_integer();
int offsetZ = value[L"offsetZ"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
Unit* target = unitsManager->getUnit(targetID);
Unit* leader = unitsManager->getUnit(leaderID);
wstring unitName;
wstring targetName;
wstring leaderName;
if (unit != nullptr)
unitName = unit->getUnitName();
else
return;
if (target != nullptr)
targetName = target->getUnitName();
if (leader != nullptr)
leaderName = leader->getUnitName();
else
return;
log(L"Unit " + unitName + L" following unit " + targetName);
log(L"Unit " + unitName + L" following unit " + leaderName);
unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ));
unit->setTargetID(targetID);
unit->setLeaderID(leaderID);
unit->setState(State::FOLLOW);
}
else if (key.compare(L"changeSpeed") == 0)
@ -208,40 +208,6 @@ void Scheduler::handleRequest(wstring key, json::value value)
command = dynamic_cast<Command*>(new Clone(ID, loc));
log(L"Cloning unit " + to_wstring(ID));
}
else if (key.compare(L"setLeader") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
bool isLeader = value[L"isLeader"].as_bool();
if (isLeader)
{
json::value wingmenIDs = value[L"wingmenIDs"];
vector<Unit*> wingmen;
if (unit != nullptr)
{
for (auto itr = wingmenIDs.as_array().begin(); itr != wingmenIDs.as_array().end(); itr++)
{
Unit* wingman = unitsManager->getUnit(itr->as_integer());
if (wingman != nullptr)
wingmen.push_back(wingman);
}
unit->setFormation(L"Line abreast");
unit->setIsLeader(true);
unit->setWingmen(wingmen);
log(L"Setting " + unit->getName() + L" as formation leader");
}
}
else {
unit->setIsLeader(false);
}
}
else if (key.compare(L"setFormation") == 0)
{
int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
wstring formation = value[L"formation"].as_string();
unit->setFormation(formation);
}
else if (key.compare(L"setROE") == 0)
{
int ID = value[L"ID"].as_integer();

View File

@ -20,6 +20,14 @@ Unit::Unit(json::value json, int ID) :
{
log("Creating unit with ID: " + to_string(ID));
addMeasure(L"currentState", json::value(L"Idle"));
addMeasure(L"TACANChannel", json::value(TACANChannel));
addMeasure(L"TACANXY", json::value(TACANXY));
addMeasure(L"TACANCallsign", json::value(TACANCallsign));
addMeasure(L"radioFrequency", json::value(radioFrequency));
addMeasure(L"radioCallsign", json::value(radioCallsign));
addMeasure(L"radioCallsignNumber", json::value(radioCallsignNumber));
}
Unit::~Unit()
@ -127,10 +135,10 @@ json::value Unit::getData(long long time)
/********** Formation data **********/
json[L"formationData"] = json::value::object();
for (auto key : { L"isLeader", L"isWingman", L"formation", L"wingmenIDs", L"leaderID" })
for (auto key : { L"leaderID" })
{
if (measures.find(key) != measures.end() && measures[key]->getTime() > time)
json[L"missionData"][key] = measures[key]->getValue();
json[L"formationData"][key] = measures[key]->getValue();
}
/********** Task data **********/
@ -154,12 +162,9 @@ json::value Unit::getData(long long time)
void Unit::setActivePath(list<Coords> newPath)
{
if (state != State::WINGMAN && state != State::FOLLOW)
{
activePath = newPath;
resetActiveDestination();
}
activePath = newPath;
resetActiveDestination();
auto path = json::value::object();
if (activePath.size() > 0) {
int count = 1;
@ -223,22 +228,6 @@ int Unit::getCoalitionID()
return 2;
}
void Unit::setLeader(Unit* newLeader)
{
leader = newLeader;
if (leader != nullptr)
addMeasure(L"leaderID", json::value(leader->getID()));
}
void Unit::setWingmen(vector<Unit*> newWingmen) {
wingmen = newWingmen;
auto wingmenIDs = json::value::object();
int i = 0;
for (auto itr = wingmen.begin(); itr != wingmen.end(); itr++)
wingmenIDs[i++] = (*itr)->getID();
addMeasure(L"wingmen", wingmenIDs);
}
wstring Unit::getTargetName()
{
if (isTargetAlive())
@ -262,6 +251,29 @@ bool Unit::isTargetAlive()
return false;
}
wstring Unit::getLeaderName()
{
if (isLeaderAlive())
{
Unit* leader = unitsManager->getUnit(leaderID);
if (leader != nullptr)
return leader->getUnitName();
}
return L"";
}
bool Unit::isLeaderAlive()
{
if (leaderID == NULL)
return false;
Unit* leader = unitsManager->getUnit(leaderID);
if (leader != nullptr)
return leader->alive;
else
return false;
}
void Unit::resetActiveDestination()
{
activeDestination = Coords(NULL);
@ -273,30 +285,6 @@ void Unit::resetTask()
scheduler->appendCommand(command);
}
void Unit::setIsLeader(bool newIsLeader) {
isLeader = newIsLeader;
if (!isLeader) {
for (auto wingman : wingmen)
{
wingman->setFormation(L"");
wingman->setIsWingman(false);
wingman->setLeader(nullptr);
}
}
addMeasure(L"isLeader", json::value(newIsLeader));
}
void Unit::setIsWingman(bool newIsWingman)
{
isWingman = newIsWingman;
if (isWingman)
setState(State::WINGMAN);
else
setState(State::IDLE);
addMeasure(L"isWingman", json::value(isWingman));
}
void Unit::setFormationOffset(Offset newFormationOffset)
{
formationOffset = newFormationOffset;