mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added feature: select unit payload at spawn and visibility.
This commit is contained in:
@@ -149,14 +149,14 @@
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>include; ..\..\third-party\lua\include; ..\utils\include; ..\shared\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>include;..\..\third-party\GeographicLib-2.1.1\include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>lua.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>lua.lib; GeographicLib-i.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -171,7 +171,7 @@
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>
|
||||
</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>include;..\..\third-party\GeographicLib-2.1.1\include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -181,7 +181,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>lua.lib; GeographicLib-i.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\third-party\lua; ..\..\third-party\GeographicLib-2.1.1\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\third-party\lua; </AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace CommandPriority {
|
||||
};
|
||||
|
||||
namespace CommandType {
|
||||
enum CommandTypes { NO_TYPE, MOVE, SMOKE, LASE, EXPLODE, SPAWN_AIR, SPAWN_GROUND, ATTACK_UNIT };
|
||||
enum CommandTypes { NO_TYPE, MOVE, SMOKE, LASE, EXPLODE, SPAWN_AIR, SPAWN_GROUND };
|
||||
};
|
||||
|
||||
/* Base command class */
|
||||
@@ -17,7 +17,7 @@ class Command
|
||||
public:
|
||||
int getPriority() { return priority; }
|
||||
int getType() { return type; }
|
||||
virtual void execute(lua_State* L) {};
|
||||
virtual void execute(lua_State* L) = 0;
|
||||
|
||||
protected:
|
||||
int priority = CommandPriority::LOW;
|
||||
@@ -28,11 +28,14 @@ protected:
|
||||
class MoveCommand : public Command
|
||||
{
|
||||
public:
|
||||
MoveCommand(int ID, wstring unitName, Coords destination, int unitCategory) :
|
||||
MoveCommand(int ID, wstring unitName, Coords destination, double speed, double altitude, wstring unitCategory, wstring targetName):
|
||||
ID(ID),
|
||||
unitName(unitName),
|
||||
destination(destination),
|
||||
unitCategory(unitCategory)
|
||||
speed(speed),
|
||||
altitude(altitude),
|
||||
unitCategory(unitCategory),
|
||||
targetName(targetName)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
type = CommandType::MOVE;
|
||||
@@ -43,7 +46,10 @@ private:
|
||||
const int ID;
|
||||
const wstring unitName;
|
||||
const Coords destination;
|
||||
const int unitCategory;
|
||||
const wstring unitCategory;
|
||||
const double speed;
|
||||
const double altitude;
|
||||
const wstring targetName;
|
||||
};
|
||||
|
||||
/* Smoke command */
|
||||
@@ -88,10 +94,11 @@ private:
|
||||
class SpawnAirCommand : public Command
|
||||
{
|
||||
public:
|
||||
SpawnAirCommand(wstring coalition, wstring unitType, Coords location) :
|
||||
SpawnAirCommand(wstring coalition, wstring unitType, Coords location, wstring payloadName) :
|
||||
coalition(coalition),
|
||||
unitType(unitType),
|
||||
location(location)
|
||||
location(location),
|
||||
payloadName(payloadName)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
type = CommandType::SPAWN_AIR;
|
||||
@@ -102,24 +109,5 @@ private:
|
||||
const wstring coalition;
|
||||
const wstring unitType;
|
||||
const Coords location;
|
||||
const wstring payloadName;
|
||||
};
|
||||
|
||||
/* Attack unit command */
|
||||
class AttackUnitCommand : public Command
|
||||
{
|
||||
public:
|
||||
AttackUnitCommand(wstring unitName, wstring targetName, Coords location) :
|
||||
unitName(unitName),
|
||||
targetName(targetName),
|
||||
location(location)
|
||||
{
|
||||
priority = CommandPriority::MEDIUM;
|
||||
type = CommandType::ATTACK_UNIT;
|
||||
};
|
||||
virtual void execute(lua_State* L);
|
||||
|
||||
private:
|
||||
const wstring unitName;
|
||||
const wstring targetName;
|
||||
const Coords location;
|
||||
};
|
||||
@@ -7,10 +7,6 @@
|
||||
#define GROUND_DEST_DIST_THR 100
|
||||
#define AIR_DEST_DIST_THR 2000
|
||||
|
||||
namespace UnitCategory {
|
||||
enum UnitCategories { NO_CATEGORY, AIR, GROUND, NAVY }; // Do not edit, this codes are tied to values in DCS
|
||||
};
|
||||
|
||||
class Unit
|
||||
{
|
||||
public:
|
||||
@@ -21,6 +17,17 @@ public:
|
||||
|
||||
void setPath(list<Coords> path);
|
||||
void setAlive(bool newAlive) { alive = newAlive; }
|
||||
void setTarget(int targetID);
|
||||
wstring getTarget();
|
||||
wstring getCurrentTask();
|
||||
|
||||
void resetActiveDestination();
|
||||
|
||||
virtual void changeSpeed(wstring change) {};
|
||||
virtual void changeAltitude(wstring change) {};
|
||||
|
||||
virtual double getTargetSpeed() { return targetSpeed; };
|
||||
virtual double getTargetAltitude() { return targetAltitude; };
|
||||
|
||||
int getID() { return ID; }
|
||||
wstring getName() { return name; }
|
||||
@@ -34,9 +41,10 @@ public:
|
||||
double getAltitude() { return altitude; }
|
||||
double getHeading() { return heading; }
|
||||
json::value getFlags() { return flags; }
|
||||
int getCategory();
|
||||
Coords getActiveDestination() { return activeDestination; }
|
||||
|
||||
virtual wstring getCategory() { return L"No category"; };
|
||||
|
||||
json::value json();
|
||||
|
||||
protected:
|
||||
@@ -47,21 +55,131 @@ protected:
|
||||
wstring unitName = L"undefined";
|
||||
wstring groupName = L"undefined";
|
||||
json::value type = json::value::null();
|
||||
int country = 0;
|
||||
int coalitionID = 0;
|
||||
double latitude = 0;
|
||||
double longitude = 0;
|
||||
double altitude = 0;
|
||||
double heading = 0;
|
||||
int country = NULL;
|
||||
int coalitionID = NULL;
|
||||
double latitude = NULL;
|
||||
double longitude = NULL;
|
||||
double altitude = NULL;
|
||||
double heading = NULL;
|
||||
double speed = NULL;
|
||||
json::value flags = json::value::null();
|
||||
Coords oldPosition = Coords(0); // Used to approximate speed
|
||||
int targetID = NULL;
|
||||
bool holding = false;
|
||||
bool looping = false;
|
||||
|
||||
double targetSpeed = 0;
|
||||
double targetAltitude = 0;
|
||||
|
||||
list<Coords> activePath;
|
||||
Coords activeDestination = Coords(0);
|
||||
|
||||
private:
|
||||
virtual void AIloop();
|
||||
|
||||
double oldDist = 0;
|
||||
private:
|
||||
mutex mutexLock;
|
||||
};
|
||||
|
||||
class AirUnit : public Unit
|
||||
{
|
||||
public:
|
||||
AirUnit(json::value json, int ID);
|
||||
|
||||
virtual wstring getCategory() = 0;
|
||||
|
||||
protected:
|
||||
virtual void AIloop();
|
||||
};
|
||||
|
||||
class Aircraft : public AirUnit
|
||||
{
|
||||
public:
|
||||
Aircraft(json::value json, int ID);
|
||||
|
||||
virtual wstring getCategory() { return L"Aircraft"; };
|
||||
|
||||
virtual void changeSpeed(wstring change);
|
||||
virtual void changeAltitude(wstring change);
|
||||
virtual double getTargetSpeed() { return targetSpeed; };
|
||||
virtual double getTargetAltitude() { return targetAltitude; };
|
||||
|
||||
protected:
|
||||
double targetSpeed = 150;
|
||||
double targetAltitude = 5000;
|
||||
};
|
||||
|
||||
class Helicopter : public AirUnit
|
||||
{
|
||||
public:
|
||||
Helicopter(json::value json, int ID);
|
||||
|
||||
virtual wstring getCategory() { return L"Helicopter"; };
|
||||
|
||||
virtual void changeSpeed(wstring change);
|
||||
virtual void changeAltitude(wstring change);
|
||||
virtual double getTargetSpeed() { return targetSpeed; };
|
||||
virtual double getTargetAltitude() { return targetAltitude; };
|
||||
|
||||
protected:
|
||||
double targetSpeed = 50;
|
||||
double targetAltitude = 1000;
|
||||
};
|
||||
|
||||
class GroundUnit : public Unit
|
||||
{
|
||||
public:
|
||||
GroundUnit(json::value json, int ID);
|
||||
virtual void AIloop();
|
||||
|
||||
virtual wstring getCategory() { return L"GroundUnit"; };
|
||||
virtual void changeSpeed(wstring change);
|
||||
virtual void changeAltitude(wstring change) {};
|
||||
virtual double getTargetSpeed() { return targetSpeed; };
|
||||
|
||||
protected:
|
||||
double targetSpeed = 10;
|
||||
};
|
||||
|
||||
class NavyUnit : public Unit
|
||||
{
|
||||
public:
|
||||
NavyUnit(json::value json, int ID);
|
||||
virtual void AIloop();
|
||||
|
||||
virtual wstring getCategory() { return L"NavyUnit"; };
|
||||
virtual void changeSpeed(wstring change);
|
||||
virtual void changeAltitude(wstring change) {};
|
||||
virtual double getTargetSpeed() { return targetSpeed; };
|
||||
|
||||
protected:
|
||||
double targetSpeed = 10;
|
||||
};
|
||||
|
||||
class Weapon : public Unit
|
||||
{
|
||||
public:
|
||||
Weapon(json::value json, int ID);
|
||||
|
||||
virtual wstring getCategory() = 0;
|
||||
|
||||
protected:
|
||||
/* Weapons are not controllable and have no AIloop */
|
||||
virtual void AIloop() {};
|
||||
};
|
||||
|
||||
class Missile : public Weapon
|
||||
{
|
||||
public:
|
||||
Missile(json::value json, int ID);
|
||||
|
||||
virtual wstring getCategory() { return L"Missile"; };
|
||||
};
|
||||
|
||||
class Bomb : public Weapon
|
||||
{
|
||||
public:
|
||||
Bomb(json::value json, int ID);
|
||||
|
||||
virtual wstring getCategory() { return L"Bomb"; };
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ void MoveCommand::execute(lua_State* L)
|
||||
{
|
||||
std::ostringstream command;
|
||||
command.precision(10);
|
||||
command << "Olympus.move(\"" << to_string(unitName) << "\", " << destination.lat << ", " << destination.lng << ", " << 10 << ", " << unitCategory << ")";
|
||||
command << "Olympus.move(\"" << to_string(unitName) << "\", " << destination.lat << ", " << destination.lng << ", " << altitude << ", " << speed << ", \"" << to_string(unitCategory) << "\", \"" << to_string(targetName) << "\")";
|
||||
|
||||
lua_getglobal(L, "net");
|
||||
lua_getfield(L, -1, "dostring_in");
|
||||
@@ -69,7 +69,7 @@ void SpawnAirCommand::execute(lua_State* L)
|
||||
{
|
||||
std::ostringstream command;
|
||||
command.precision(10);
|
||||
command << "Olympus.spawnAir(\"" << to_string(coalition) << "\", \"" << to_string(unitType) << "\", " << location.lat << ", " << location.lng << ")";
|
||||
command << "Olympus.spawnAir(\"" << to_string(coalition) << "\", \"" << to_string(unitType) << "\", " << location.lat << ", " << location.lng << "," << "\"" << to_string(payloadName) << "\")";
|
||||
|
||||
lua_getglobal(L, "net");
|
||||
lua_getfield(L, -1, "dostring_in");
|
||||
@@ -84,24 +84,3 @@ void SpawnAirCommand::execute(lua_State* L)
|
||||
log("SpawnAirCommand executed successfully");
|
||||
}
|
||||
}
|
||||
|
||||
/* Attack unit command */
|
||||
void AttackUnitCommand::execute(lua_State* L)
|
||||
{
|
||||
std::ostringstream command;
|
||||
command.precision(10);
|
||||
command << "Olympus.attackUnit(\"" << to_string(unitName) << "\", \"" << to_string(targetName) << "\", " << location.lat << ", " << location.lng << ")";
|
||||
|
||||
lua_getglobal(L, "net");
|
||||
lua_getfield(L, -1, "dostring_in");
|
||||
lua_pushstring(L, "server");
|
||||
lua_pushstring(L, command.str().c_str());
|
||||
if (lua_pcall(L, 2, 0, 0) != 0)
|
||||
{
|
||||
log("Error executing AttackUnitCommand");
|
||||
}
|
||||
else
|
||||
{
|
||||
log("AttackUnitCommand executed successfully");
|
||||
}
|
||||
}
|
||||
@@ -64,13 +64,6 @@ void Scheduler::execute(lua_State* L)
|
||||
commands.remove(command);
|
||||
break;
|
||||
}
|
||||
case CommandType::ATTACK_UNIT:
|
||||
{
|
||||
AttackUnitCommand* attackCommand = dynamic_cast<AttackUnitCommand*>(command);
|
||||
attackCommand->execute(L);
|
||||
commands.remove(command);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
log("Unknown command of type " + to_string(command->getType()));
|
||||
commands.remove(command);
|
||||
@@ -93,26 +86,30 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
if (key.compare(L"setPath") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
wstring unitName = value[L"unitName"].as_string();
|
||||
json::value path = value[L"path"];
|
||||
list<Coords> newPath;
|
||||
for (auto const& e : path.as_object())
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
if (unit != nullptr)
|
||||
{
|
||||
wstring WP = e.first;
|
||||
double lat = path[WP][L"lat"].as_double();
|
||||
double lng = path[WP][L"lng"].as_double();
|
||||
log(unitName + L" set path destination " + WP + L" (" + to_wstring(lat) + L", " + to_wstring(lng) + L")");
|
||||
Coords dest; dest.lat = lat; dest.lng = lng;
|
||||
newPath.push_back(dest);
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
if (unit != nullptr)
|
||||
wstring unitName = unit->getUnitName();
|
||||
json::value path = value[L"path"];
|
||||
list<Coords> newPath;
|
||||
for (auto const& e : path.as_object())
|
||||
{
|
||||
unit->setPath(newPath);
|
||||
log(unitName + L" new path set successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
log(unitName + L" not found, request will be discarded");
|
||||
wstring WP = e.first;
|
||||
double lat = path[WP][L"lat"].as_double();
|
||||
double lng = path[WP][L"lng"].as_double();
|
||||
log(unitName + L" set path destination " + WP + L" (" + to_wstring(lat) + L", " + to_wstring(lng) + L")");
|
||||
Coords dest; dest.lat = lat; dest.lng = lng;
|
||||
newPath.push_back(dest);
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
if (unit != nullptr)
|
||||
{
|
||||
unit->setPath(newPath);
|
||||
log(unitName + L" new path set successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
log(unitName + L" not found, request will be discarded");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,9 +138,10 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
wstring type = value[L"type"].as_string();
|
||||
double lat = value[L"location"][L"lat"].as_double();
|
||||
double lng = value[L"location"][L"lng"].as_double();
|
||||
log(L"Spawning " + coalition + L" air unit of type " + type + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")");
|
||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||
command = dynamic_cast<Command*>(new SpawnAirCommand(coalition, type, loc));
|
||||
wstring payloadName = value[L"payloadName"].as_string();
|
||||
log(L"Spawning " + coalition + L" air unit of type " + type + L" with payload " + payloadName + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")");
|
||||
command = dynamic_cast<Command*>(new SpawnAirCommand(coalition, type, loc, payloadName));
|
||||
}
|
||||
else if (key.compare(L"attackUnit") == 0)
|
||||
{
|
||||
@@ -155,12 +153,10 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
|
||||
wstring unitName;
|
||||
wstring targetName;
|
||||
Coords loc;
|
||||
|
||||
if (unit != nullptr)
|
||||
{
|
||||
unitName = unit->getUnitName();
|
||||
loc = unit->getActiveDestination();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -170,10 +166,6 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
if (target != nullptr)
|
||||
{
|
||||
targetName = target->getUnitName();
|
||||
if (loc == NULL)
|
||||
{
|
||||
loc = Coords(target->getLatitude(), target->getLongitude(), target->getAltitude());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -181,7 +173,25 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
}
|
||||
|
||||
log(L"Unit " + unitName + L" attacking unit " + targetName);
|
||||
command = dynamic_cast<Command*>(new AttackUnitCommand(unitName, targetName, loc));
|
||||
unit->setTarget(targetID);
|
||||
}
|
||||
else if (key.compare(L"changeSpeed") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
Unit* unit = unitsFactory->getUnit(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 = unitsFactory->getUnit(ID);
|
||||
if (unit != nullptr)
|
||||
{
|
||||
unit->changeAltitude(value[L"change"].as_string());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
#include "logger.h"
|
||||
#include "commands.h"
|
||||
#include "scheduler.h"
|
||||
#include "defines.h"
|
||||
#include "unitsFactory.h"
|
||||
|
||||
#include <GeographicLib/Geodesic.hpp>
|
||||
using namespace GeographicLib;
|
||||
|
||||
extern Scheduler* scheduler;
|
||||
extern UnitsFactory* unitsFactory;
|
||||
|
||||
const Geodesic& geod = Geodesic::WGS84();
|
||||
|
||||
@@ -15,7 +18,6 @@ Unit::Unit(json::value json, int ID) :
|
||||
ID(ID)
|
||||
{
|
||||
log("Creating unit with ID: " + to_string(ID));
|
||||
update(json);
|
||||
}
|
||||
|
||||
Unit::~Unit()
|
||||
@@ -23,23 +25,21 @@ Unit::~Unit()
|
||||
|
||||
}
|
||||
|
||||
int Unit::getCategory()
|
||||
{
|
||||
if (type.has_number_field(L"level1"))
|
||||
{
|
||||
return type[L"level1"].as_number().to_int32();
|
||||
}
|
||||
else
|
||||
{
|
||||
return UnitCategory::NO_CATEGORY;
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::update(json::value json)
|
||||
{
|
||||
/* Lock for thread safety */
|
||||
lock_guard<mutex> guard(mutexLock);
|
||||
|
||||
/* Compute speed (loGetWorldObjects does not provide speed, we compute it for better performance instead of relying on many lua calls) */
|
||||
if (oldPosition != NULL)
|
||||
{
|
||||
double dist = 0;
|
||||
geod.Inverse(latitude, longitude, oldPosition.lat, oldPosition.lng, dist);
|
||||
speed = speed * 0.95 + (dist / UPDATE_TIME_INTERVAL) * 0.05;
|
||||
}
|
||||
oldPosition = Coords(latitude, longitude, altitude);
|
||||
|
||||
/* Update all the internal fields from the input json file */
|
||||
if (json.has_string_field(L"Name"))
|
||||
name = json[L"Name"].as_string();
|
||||
if (json.has_string_field(L"UnitName"))
|
||||
@@ -80,17 +80,81 @@ void Unit::update(json::value json)
|
||||
void Unit::setPath(list<Coords> path)
|
||||
{
|
||||
activePath = path;
|
||||
holding = false;
|
||||
}
|
||||
|
||||
void Unit::setTarget(int newTargetID)
|
||||
{
|
||||
targetID = newTargetID;
|
||||
resetActiveDestination();
|
||||
}
|
||||
|
||||
wstring Unit::getTarget()
|
||||
{
|
||||
if (targetID == NULL)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
Unit* target = unitsFactory->getUnit(targetID);
|
||||
if (target != nullptr)
|
||||
{
|
||||
if (target->alive)
|
||||
{
|
||||
return target->getUnitName();
|
||||
}
|
||||
else
|
||||
{
|
||||
targetID = NULL;
|
||||
return L"";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetID = NULL;
|
||||
return L"";
|
||||
}
|
||||
}
|
||||
|
||||
wstring Unit::getCurrentTask()
|
||||
{
|
||||
if (activePath.size() == 0)
|
||||
{
|
||||
return L"Idle";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getTarget().empty())
|
||||
{
|
||||
if (looping)
|
||||
{
|
||||
return L"Looping";
|
||||
}
|
||||
else if (holding)
|
||||
{
|
||||
return L"Holding";
|
||||
}
|
||||
else
|
||||
{
|
||||
return L"Reaching destination";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return L"Attacking " + getTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::AIloop()
|
||||
{
|
||||
/* Set the active destination to be always equal to the first point of the active path */
|
||||
/* Set the active destination to be always equal to the first point of the active path. This is in common with all AI units */
|
||||
if (activePath.size() > 0)
|
||||
{
|
||||
if (activeDestination != activePath.front())
|
||||
{
|
||||
activeDestination = activePath.front();
|
||||
Command* command = dynamic_cast<Command*>(new MoveCommand(ID, unitName, activeDestination, getCategory()));
|
||||
Command* command = dynamic_cast<Command*>(new MoveCommand(ID, unitName, activeDestination, getTargetSpeed(), getTargetAltitude(), getCategory(), getTarget()));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
}
|
||||
@@ -102,52 +166,13 @@ void Unit::AIloop()
|
||||
activeDestination = Coords(0); // Set the active path to NULL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ground unit AI Loop */
|
||||
if (getCategory() == UnitCategory::GROUND)
|
||||
{
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
double newDist = 0;
|
||||
geod.Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, newDist);
|
||||
if (newDist < GROUND_DEST_DIST_THR)
|
||||
{
|
||||
/* Destination reached */
|
||||
activePath.pop_front();
|
||||
log(unitName + L" destination reached");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Air unit AI Loop */
|
||||
if (getCategory() == UnitCategory::AIR)
|
||||
{
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
double newDist = 0;
|
||||
geod.Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, newDist);
|
||||
if (newDist < AIR_DEST_DIST_THR)
|
||||
{
|
||||
/* Destination reached */
|
||||
activePath.pop_front();
|
||||
log(name + L" destination reached");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Air units must ALWAYS have a destination or they will RTB and may become uncontrollable */
|
||||
Coords point1;
|
||||
Coords point2;
|
||||
Coords point3;
|
||||
geod.Direct(latitude, longitude, 45, 18520, point1.lat, point1.lng);
|
||||
geod.Direct(point1.lat, point1.lng, 135, 18520, point2.lat, point2.lng);
|
||||
geod.Direct(point2.lat, point2.lng, 225, 18520, point3.lat, point3.lng);
|
||||
activePath.push_back(point1);
|
||||
activePath.push_back(point2);
|
||||
activePath.push_back(point3);
|
||||
activePath.push_back(Coords(latitude, longitude));
|
||||
}
|
||||
}
|
||||
/* This function calls again the MoveCommand to reach the active destination. This is useful to change speed and altitude, for example */
|
||||
void Unit::resetActiveDestination()
|
||||
{
|
||||
log(unitName + L" resetting active destination");
|
||||
activeDestination = Coords(0);
|
||||
}
|
||||
|
||||
json::value Unit::json()
|
||||
@@ -167,8 +192,11 @@ json::value Unit::json()
|
||||
json[L"latitude"] = latitude;
|
||||
json[L"longitude"] = longitude;
|
||||
json[L"altitude"] = altitude;
|
||||
json[L"speed"] = speed;
|
||||
json[L"heading"] = heading;
|
||||
json[L"flags"] = flags;
|
||||
json[L"category"] = json::value::string(getCategory());
|
||||
json[L"currentTask"] = json::value::string(getCurrentTask());
|
||||
|
||||
/* Send the active path as a json object */
|
||||
if (activePath.size() > 0) {
|
||||
@@ -188,4 +216,223 @@ json::value Unit::json()
|
||||
return json;
|
||||
}
|
||||
|
||||
/* Air unit */
|
||||
AirUnit::AirUnit(json::value json, int ID) : Unit(json, ID)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void AirUnit::AIloop()
|
||||
{
|
||||
/* Call the common AI loop */
|
||||
Unit::AIloop();
|
||||
|
||||
/* Air unit AI Loop */
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
double newDist = 0;
|
||||
geod.Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, newDist);
|
||||
if (newDist < AIR_DEST_DIST_THR)
|
||||
{
|
||||
/* Destination reached */
|
||||
if (holding || looping)
|
||||
{
|
||||
activePath.push_back(activePath.front());
|
||||
}
|
||||
activePath.pop_front();
|
||||
log(name + L" destination reached");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Air units must ALWAYS have a destination or they will RTB and may become uncontrollable */
|
||||
Coords point1;
|
||||
Coords point2;
|
||||
Coords point3;
|
||||
geod.Direct(latitude, longitude, 45, 10000, point1.lat, point1.lng);
|
||||
geod.Direct(point1.lat, point1.lng, 135, 10000, point2.lat, point2.lng);
|
||||
geod.Direct(point2.lat, point2.lng, 225, 10000, point3.lat, point3.lng);
|
||||
activePath.push_back(point1);
|
||||
activePath.push_back(point2);
|
||||
activePath.push_back(point3);
|
||||
activePath.push_back(Coords(latitude, longitude));
|
||||
holding = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Aircraft */
|
||||
Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID)
|
||||
{
|
||||
log("New Aircraft created with ID: " + to_string(ID));
|
||||
};
|
||||
|
||||
void Aircraft::changeSpeed(wstring change)
|
||||
{
|
||||
if (change.compare(L"stop") == 0)
|
||||
{
|
||||
/* Air units can't hold a position, so we can only set them to hold. At the moment, this will erase any other command. TODO: helicopters should be able to hover in place */
|
||||
activePath.clear();
|
||||
}
|
||||
else if (change.compare(L"slow") == 0)
|
||||
{
|
||||
targetSpeed *= 0.9;
|
||||
resetActiveDestination();
|
||||
}
|
||||
else if (change.compare(L"fast") == 0)
|
||||
{
|
||||
targetSpeed *= 1.1;
|
||||
resetActiveDestination();
|
||||
}
|
||||
}
|
||||
|
||||
void Aircraft::changeAltitude(wstring change)
|
||||
{
|
||||
if (change.compare(L"descend") == 0)
|
||||
{
|
||||
targetAltitude *= 0.9;
|
||||
}
|
||||
else if (change.compare(L"climb") == 0)
|
||||
{
|
||||
targetAltitude *= 1.1;
|
||||
}
|
||||
resetActiveDestination();
|
||||
}
|
||||
|
||||
/* Helicopter */
|
||||
Helicopter::Helicopter(json::value json, int ID) : AirUnit(json, ID)
|
||||
{
|
||||
log("New Helicopter created with ID: " + to_string(ID));
|
||||
};
|
||||
|
||||
void Helicopter::changeSpeed(wstring change)
|
||||
{
|
||||
if (change.compare(L"stop") == 0)
|
||||
{
|
||||
/* Air units can't hold a position, so we can only set them to hold. At the moment, this will erase any other command. TODO: helicopters should be able to hover in place */
|
||||
activePath.clear();
|
||||
}
|
||||
else if (change.compare(L"slow") == 0)
|
||||
{
|
||||
targetSpeed *= 0.9;
|
||||
resetActiveDestination();
|
||||
}
|
||||
else if (change.compare(L"fast") == 0)
|
||||
{
|
||||
targetSpeed *= 1.1;
|
||||
resetActiveDestination();
|
||||
}
|
||||
}
|
||||
|
||||
void Helicopter::changeAltitude(wstring change)
|
||||
{
|
||||
if (change.compare(L"descend") == 0)
|
||||
{
|
||||
targetAltitude *= 0.9;
|
||||
}
|
||||
else if (change.compare(L"climb") == 0)
|
||||
{
|
||||
targetAltitude *= 1.1;
|
||||
}
|
||||
resetActiveDestination();
|
||||
}
|
||||
|
||||
|
||||
/* Ground unit */
|
||||
GroundUnit::GroundUnit(json::value json, int ID) : Unit(json, ID)
|
||||
{
|
||||
log("New Ground Unit created with ID: " + to_string(ID));
|
||||
};
|
||||
|
||||
void GroundUnit::AIloop()
|
||||
{
|
||||
/* Call the common AI loop */
|
||||
Unit::AIloop();
|
||||
|
||||
/* Ground unit AI Loop */
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
double newDist = 0;
|
||||
geod.Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, newDist);
|
||||
if (newDist < GROUND_DEST_DIST_THR)
|
||||
{
|
||||
/* Destination reached */
|
||||
activePath.pop_front();
|
||||
log(unitName + L" destination reached");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GroundUnit::changeSpeed(wstring change)
|
||||
{
|
||||
if (change.compare(L"stop") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (change.compare(L"slow") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (change.compare(L"fast") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Navy Unit */
|
||||
NavyUnit::NavyUnit(json::value json, int ID) : Unit(json, ID)
|
||||
{
|
||||
log("New Navy Unit created with ID: " + to_string(ID));
|
||||
};
|
||||
|
||||
void NavyUnit::AIloop()
|
||||
{
|
||||
/* Call the common AI loop */
|
||||
Unit::AIloop();
|
||||
|
||||
/* Navy unit AI Loop */
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
double newDist = 0;
|
||||
geod.Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, newDist);
|
||||
if (newDist < GROUND_DEST_DIST_THR)
|
||||
{
|
||||
/* Destination reached */
|
||||
activePath.pop_front();
|
||||
log(unitName + L" destination reached");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NavyUnit::changeSpeed(wstring change)
|
||||
{
|
||||
if (change.compare(L"stop") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (change.compare(L"slow") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (change.compare(L"fast") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Weapon */
|
||||
Weapon::Weapon(json::value json, int ID) : Unit(json, ID)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
/* Missile */
|
||||
Missile::Missile(json::value json, int ID) : Weapon(json, ID)
|
||||
{
|
||||
log("New Missile created with ID: " + to_string(ID));
|
||||
};
|
||||
|
||||
/* Bomb */
|
||||
Bomb::Bomb(json::value json, int ID) : Weapon(json, ID)
|
||||
{
|
||||
log("New Bomb created with ID: " + to_string(ID));
|
||||
};
|
||||
|
||||
@@ -81,5 +81,36 @@ void registerLuaFunctions(lua_State* L)
|
||||
log("OlympusCommand.lua registered successfully");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ifstream f(modLocation + "\\Scripts\\unitPayloads.lua");
|
||||
string str;
|
||||
log("Reading unitPayloads.lua from " + modLocation + "\\Scripts\\unitPayloads.lua");
|
||||
if (f) {
|
||||
ostringstream ss;
|
||||
ss << f.rdbuf();
|
||||
str = ss.str();
|
||||
log("unitPayloads.lua read succesfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Error reading unitPayloads.lua");
|
||||
return;
|
||||
}
|
||||
|
||||
lua_getglobal(L, "net");
|
||||
lua_getfield(L, -1, "dostring_in");
|
||||
lua_pushstring(L, "server");
|
||||
lua_pushstring(L, str.c_str());
|
||||
|
||||
if (lua_pcall(L, 2, 0, 0) != 0)
|
||||
{
|
||||
log("Error registering unitPayloads.lua");
|
||||
}
|
||||
else
|
||||
{
|
||||
log("unitPayloads.lua registered successfully");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "unit.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
|
||||
UnitsFactory::UnitsFactory(lua_State* L)
|
||||
{
|
||||
LogInfo(L, "Units Factory constructor called successfully");
|
||||
@@ -34,9 +36,46 @@ void UnitsFactory::update(lua_State* L)
|
||||
int ID = p.first;
|
||||
if (units.count(ID) == 0)
|
||||
{
|
||||
units[ID] = new Unit(p.second, ID);
|
||||
json::value type = static_cast<json::value>(p.second)[L"Type"];
|
||||
if (type.has_number_field(L"level1"))
|
||||
{
|
||||
if (type[L"level1"].as_number().to_int32() == 1)
|
||||
{
|
||||
if (type[L"level2"].as_number().to_int32() == 1)
|
||||
{
|
||||
units[ID] = dynamic_cast<Unit*>(new Aircraft(p.second, ID));
|
||||
}
|
||||
else if (type[L"level2"].as_number().to_int32() == 2)
|
||||
{
|
||||
units[ID] = dynamic_cast<Unit*>(new Helicopter(p.second, ID));
|
||||
}
|
||||
}
|
||||
else if (type[L"level1"].as_number().to_int32() == 2)
|
||||
{
|
||||
units[ID] = dynamic_cast<Unit*>(new GroundUnit(p.second, ID));
|
||||
}
|
||||
else if (type[L"level1"].as_number().to_int32() == 3)
|
||||
{
|
||||
units[ID] = dynamic_cast<Unit*>(new NavyUnit(p.second, ID));
|
||||
}
|
||||
else if (type[L"level1"].as_number().to_int32() == 4)
|
||||
{
|
||||
if (type[L"level2"].as_number().to_int32() == 4)
|
||||
{
|
||||
units[ID] = dynamic_cast<Unit*>(new Missile(p.second, ID));
|
||||
}
|
||||
else if (type[L"level2"].as_number().to_int32() == 5)
|
||||
{
|
||||
units[ID] = dynamic_cast<Unit*>(new Bomb(p.second, ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Update the unit if present*/
|
||||
if (units.count(ID) != 0)
|
||||
{
|
||||
units[ID]->update(p.second);
|
||||
}
|
||||
units[ID]->update(p.second);
|
||||
}
|
||||
|
||||
/* Set the units that are not present in the JSON as dead (probably have been destroyed) */
|
||||
|
||||
Reference in New Issue
Block a user