mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Implemented as described in issue
This commit is contained in:
parent
ee08d9d48e
commit
640f764354
4
client/src/@types/unit.d.ts
vendored
4
client/src/@types/unit.d.ts
vendored
@ -29,11 +29,7 @@ interface MissionData {
|
||||
}
|
||||
|
||||
interface FormationData {
|
||||
formation: string;
|
||||
isLeader: boolean;
|
||||
isWingman: boolean;
|
||||
leaderID: number;
|
||||
wingmenIDs: number[];
|
||||
}
|
||||
|
||||
interface TaskData {
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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");
|
||||
};
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user