Added feature: select unit payload at spawn and visibility.

This commit is contained in:
Davide Passoni
2022-12-30 17:43:20 +01:00
parent 92eab6fd41
commit 036f70db34
38 changed files with 14104 additions and 563 deletions

View File

@@ -17,112 +17,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "olympus", "olympus\olympus.
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
MinSizeRel|x64 = MinSizeRel|x64
MinSizeRel|x86 = MinSizeRel|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
RelWithDebInfo|x64 = RelWithDebInfo|x64
RelWithDebInfo|x86 = RelWithDebInfo|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Debug|x64.ActiveCfg = Debug|x64
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Debug|x64.Build.0 = Debug|x64
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Debug|x86.ActiveCfg = Debug|Win32
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Debug|x86.Build.0 = Debug|Win32
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.MinSizeRel|x64.ActiveCfg = Release|x64
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.MinSizeRel|x64.Build.0 = Release|x64
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.MinSizeRel|x86.ActiveCfg = Release|Win32
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.MinSizeRel|x86.Build.0 = Release|Win32
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Release|x64.ActiveCfg = Release|x64
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Release|x64.Build.0 = Release|x64
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Release|x86.ActiveCfg = Release|Win32
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Release|x86.Build.0 = Release|Win32
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.RelWithDebInfo|x64.Build.0 = Release|x64
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{8A48D855-0E01-42BA-BD8C-07B0877C68DF}.RelWithDebInfo|x86.Build.0 = Release|Win32
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Debug|x64.ActiveCfg = Debug|x64
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Debug|x64.Build.0 = Debug|x64
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Debug|x86.ActiveCfg = Debug|Win32
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Debug|x86.Build.0 = Debug|Win32
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.MinSizeRel|x64.ActiveCfg = Release|x64
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.MinSizeRel|x64.Build.0 = Release|x64
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.MinSizeRel|x86.ActiveCfg = Release|Win32
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.MinSizeRel|x86.Build.0 = Release|Win32
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Release|x64.ActiveCfg = Release|x64
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Release|x64.Build.0 = Release|x64
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Release|x86.ActiveCfg = Release|Win32
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Release|x86.Build.0 = Release|Win32
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.RelWithDebInfo|x64.Build.0 = Release|x64
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{873ECABE-FCFE-4217-AC15-91959C3CF1C6}.RelWithDebInfo|x86.Build.0 = Release|Win32
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.Debug|x64.ActiveCfg = Debug|x64
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.Debug|x64.Build.0 = Debug|x64
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.Debug|x86.ActiveCfg = Debug|Win32
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.Debug|x86.Build.0 = Debug|Win32
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.MinSizeRel|x64.ActiveCfg = Release|x64
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.MinSizeRel|x64.Build.0 = Release|x64
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.MinSizeRel|x86.ActiveCfg = Release|Win32
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.MinSizeRel|x86.Build.0 = Release|Win32
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.Release|x64.ActiveCfg = Release|x64
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.Release|x64.Build.0 = Release|x64
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.Release|x86.ActiveCfg = Release|Win32
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.Release|x86.Build.0 = Release|Win32
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.RelWithDebInfo|x64.Build.0 = Release|x64
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{2B255368-39A0-431A-A6DE-CC739AC70DC1}.RelWithDebInfo|x86.Build.0 = Release|Win32
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Debug|x64.ActiveCfg = Debug|x64
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Debug|x64.Build.0 = Debug|x64
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Debug|x86.ActiveCfg = Debug|Win32
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Debug|x86.Build.0 = Debug|Win32
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.MinSizeRel|x64.ActiveCfg = Release|x64
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.MinSizeRel|x64.Build.0 = Release|x64
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.MinSizeRel|x86.ActiveCfg = Release|Win32
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.MinSizeRel|x86.Build.0 = Release|Win32
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Release|x64.ActiveCfg = Release|x64
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Release|x64.Build.0 = Release|x64
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Release|x86.ActiveCfg = Release|Win32
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Release|x86.Build.0 = Release|Win32
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.RelWithDebInfo|x64.Build.0 = Release|x64
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{DE139EC1-4F88-47D5-BE73-F41915FE14A3}.RelWithDebInfo|x86.Build.0 = Release|Win32
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Debug|x64.ActiveCfg = Debug|x64
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Debug|x64.Build.0 = Debug|x64
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Debug|x86.ActiveCfg = Debug|Win32
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Debug|x86.Build.0 = Debug|Win32
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.MinSizeRel|x64.ActiveCfg = Release|x64
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.MinSizeRel|x64.Build.0 = Release|x64
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.MinSizeRel|x86.ActiveCfg = Release|Win32
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.MinSizeRel|x86.Build.0 = Release|Win32
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Release|x64.ActiveCfg = Release|x64
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Release|x64.Build.0 = Release|x64
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Release|x86.ActiveCfg = Release|Win32
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Release|x86.Build.0 = Release|Win32
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.RelWithDebInfo|x64.Build.0 = Release|x64
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.RelWithDebInfo|x86.Build.0 = Release|Win32
{5F3FC91E-1FBC-4223-8011-9708DE913474}.Debug|x64.ActiveCfg = Debug|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.Debug|x64.Build.0 = Debug|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.Debug|x86.ActiveCfg = Debug|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.Debug|x86.Build.0 = Debug|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.MinSizeRel|x64.ActiveCfg = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.MinSizeRel|x64.Build.0 = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.MinSizeRel|x86.ActiveCfg = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.MinSizeRel|x86.Build.0 = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.Release|x64.ActiveCfg = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.Release|x64.Build.0 = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.Release|x86.ActiveCfg = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.Release|x86.Build.0 = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.RelWithDebInfo|x64.Build.0 = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.RelWithDebInfo|x86.ActiveCfg = Release|x64
{5F3FC91E-1FBC-4223-8011-9708DE913474}.RelWithDebInfo|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,2 +0,0 @@
#include "pch.h"

View File

@@ -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" />

View File

@@ -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;
};

View File

@@ -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"; };
};

View File

@@ -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");
}
}

View File

@@ -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
{

View File

@@ -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));
};

View File

@@ -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");
}
}
}

View File

@@ -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) */

View File

@@ -60,7 +60,7 @@
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>

View File

@@ -47,7 +47,7 @@
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>

View File

@@ -1,5 +0,0 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.