mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Reworked unit as as state machine, added formations, added measuring on map, added copy-paste
This commit is contained in:
@@ -18,23 +18,6 @@
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\commands.h" />
|
||||
<ClInclude Include="include\scriptLoader.h" />
|
||||
<ClInclude Include="include\server.h" />
|
||||
<ClInclude Include="include\scheduler.h" />
|
||||
<ClInclude Include="include\unit.h" />
|
||||
<ClInclude Include="include\unitsFactory.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\commands.cpp" />
|
||||
<ClCompile Include="src\scriptLoader.cpp" />
|
||||
<ClCompile Include="src\core.cpp" />
|
||||
<ClCompile Include="src\server.cpp" />
|
||||
<ClCompile Include="src\scheduler.cpp" />
|
||||
<ClCompile Include="src\unit.cpp" />
|
||||
<ClCompile Include="src\unitsFactory.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\dcstools\dcstools.vcxproj">
|
||||
<Project>{2b255368-39a0-431a-a6de-cc739ac70dc1}</Project>
|
||||
@@ -49,6 +32,35 @@
|
||||
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\aircraft.h" />
|
||||
<ClInclude Include="include\airunit.h" />
|
||||
<ClInclude Include="include\commands.h" />
|
||||
<ClInclude Include="include\groundunit.h" />
|
||||
<ClInclude Include="include\helicopter.h" />
|
||||
<ClInclude Include="include\navyunit.h" />
|
||||
<ClInclude Include="include\scheduler.h" />
|
||||
<ClInclude Include="include\scriptloader.h" />
|
||||
<ClInclude Include="include\server.h" />
|
||||
<ClInclude Include="include\unit.h" />
|
||||
<ClInclude Include="include\unitsfactory.h" />
|
||||
<ClInclude Include="include\weapon.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\aircraft.cpp" />
|
||||
<ClCompile Include="src\airunit.cpp" />
|
||||
<ClCompile Include="src\commands.cpp" />
|
||||
<ClCompile Include="src\core.cpp" />
|
||||
<ClCompile Include="src\groundunit.cpp" />
|
||||
<ClCompile Include="src\helicopter.cpp" />
|
||||
<ClCompile Include="src\navyunit.cpp" />
|
||||
<ClCompile Include="src\scheduler.cpp" />
|
||||
<ClCompile Include="src\scriptloader.cpp" />
|
||||
<ClCompile Include="src\server.cpp" />
|
||||
<ClCompile Include="src\unit.cpp" />
|
||||
<ClCompile Include="src\unitsfactory.cpp" />
|
||||
<ClCompile Include="src\weapon.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
|
||||
@@ -9,45 +9,81 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\aircraft.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\airunit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\commands.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\server.h">
|
||||
<ClInclude Include="include\groundunit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\helicopter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\navyunit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\scheduler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\scriptloader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\server.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\unit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\unitsFactory.h">
|
||||
<ClInclude Include="include\unitsfactory.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\scriptLoader.h">
|
||||
<ClInclude Include="include\weapon.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\aircraft.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\airunit.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\commands.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\core.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\server.cpp">
|
||||
<ClCompile Include="src\groundunit.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\helicopter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\navyunit.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\scheduler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\scriptloader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\server.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\unit.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\unitsFactory.cpp">
|
||||
<ClCompile Include="src\unitsfactory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\scriptLoader.cpp">
|
||||
<ClCompile Include="src\weapon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace CommandPriority {
|
||||
};
|
||||
|
||||
namespace CommandType {
|
||||
enum CommandTypes { NO_TYPE, MOVE, SMOKE, LASE, EXPLODE, SPAWN_AIR, SPAWN_GROUND, CLONE, LAND, REFUEL, FOLLOW };
|
||||
enum CommandTypes { NO_TYPE, MOVE, SMOKE, SPAWN_AIR, SPAWN_GROUND, CLONE, FOLLOW, RESET_TASK, SET_OPTION, SET_COMMAND, SET_TASK };
|
||||
};
|
||||
|
||||
/* Base command class */
|
||||
@@ -25,10 +25,10 @@ protected:
|
||||
};
|
||||
|
||||
/* Simple low priority move command (from user click) */
|
||||
class MoveCommand : public Command
|
||||
class Move : public Command
|
||||
{
|
||||
public:
|
||||
MoveCommand(int ID, Coords destination, double speed, double altitude, wstring unitCategory, wstring taskOptions):
|
||||
Move(int ID, Coords destination, double speed, double altitude, wstring unitCategory, wstring taskOptions):
|
||||
ID(ID),
|
||||
destination(destination),
|
||||
speed(speed),
|
||||
@@ -51,10 +51,10 @@ private:
|
||||
};
|
||||
|
||||
/* Smoke command */
|
||||
class SmokeCommand : public Command
|
||||
class Smoke : public Command
|
||||
{
|
||||
public:
|
||||
SmokeCommand(wstring color, Coords location) :
|
||||
Smoke(wstring color, Coords location) :
|
||||
color(color),
|
||||
location(location)
|
||||
{
|
||||
@@ -69,10 +69,10 @@ private:
|
||||
};
|
||||
|
||||
/* Spawn ground unit command */
|
||||
class SpawnGroundUnitCommand : public Command
|
||||
class SpawnGroundUnit : public Command
|
||||
{
|
||||
public:
|
||||
SpawnGroundUnitCommand(wstring coalition, wstring unitType, Coords location) :
|
||||
SpawnGroundUnit(wstring coalition, wstring unitType, Coords location) :
|
||||
coalition(coalition),
|
||||
unitType(unitType),
|
||||
location(location)
|
||||
@@ -89,10 +89,10 @@ private:
|
||||
};
|
||||
|
||||
/* Spawn air unit command */
|
||||
class SpawnAircraftCommand : public Command
|
||||
class SpawnAircraft : public Command
|
||||
{
|
||||
public:
|
||||
SpawnAircraftCommand(wstring coalition, wstring unitType, Coords location, wstring payloadName, wstring airbaseName) :
|
||||
SpawnAircraft(wstring coalition, wstring unitType, Coords location, wstring payloadName, wstring airbaseName) :
|
||||
coalition(coalition),
|
||||
unitType(unitType),
|
||||
location(location),
|
||||
@@ -114,10 +114,10 @@ private:
|
||||
};
|
||||
|
||||
/* Clone unit command */
|
||||
class CloneCommand : public Command
|
||||
class Clone : public Command
|
||||
{
|
||||
public:
|
||||
CloneCommand(int ID) :
|
||||
Clone(int ID) :
|
||||
ID(ID)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
@@ -130,19 +130,73 @@ private:
|
||||
};
|
||||
|
||||
/* Follow command */
|
||||
class FollowCommand : public Command
|
||||
class SetTask : public Command
|
||||
{
|
||||
public:
|
||||
FollowCommand(int leaderID, int ID) :
|
||||
leaderID(leaderID),
|
||||
ID(ID)
|
||||
SetTask(int ID, wstring task) :
|
||||
ID(ID),
|
||||
task(task)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
priority = CommandPriority::MEDIUM;
|
||||
type = CommandType::FOLLOW;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
|
||||
private:
|
||||
const int leaderID;
|
||||
const int ID;
|
||||
const wstring task;
|
||||
};
|
||||
|
||||
/* Reset task command */
|
||||
class ResetTask : public Command
|
||||
{
|
||||
public:
|
||||
ResetTask(int ID) :
|
||||
ID(ID)
|
||||
{
|
||||
priority = CommandPriority::HIGH;
|
||||
type = CommandType::RESET_TASK;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
|
||||
private:
|
||||
const int ID;
|
||||
};
|
||||
|
||||
/* Set command */
|
||||
class SetCommand : public Command
|
||||
{
|
||||
public:
|
||||
SetCommand(int ID, wstring command) :
|
||||
ID(ID),
|
||||
command(command)
|
||||
{
|
||||
priority = CommandPriority::HIGH;
|
||||
type = CommandType::RESET_TASK;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
|
||||
private:
|
||||
const int ID;
|
||||
const wstring command;
|
||||
};
|
||||
|
||||
/* Set option command */
|
||||
class SetOption : public Command
|
||||
{
|
||||
public:
|
||||
SetOption(int ID, int optionID, int optionValue) :
|
||||
ID(ID),
|
||||
optionID(optionID),
|
||||
optionValue(optionValue)
|
||||
{
|
||||
priority = CommandPriority::HIGH;
|
||||
type = CommandType::RESET_TASK;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
|
||||
private:
|
||||
const int ID;
|
||||
const int optionID;
|
||||
const int optionValue;
|
||||
};
|
||||
@@ -4,8 +4,9 @@
|
||||
#include "dcstools.h"
|
||||
#include "luatools.h"
|
||||
|
||||
#define GROUND_DEST_DIST_THR 100
|
||||
#define AIR_DEST_DIST_THR 2000
|
||||
namespace State {
|
||||
enum States { IDLE, REACH_DESTINATION, ATTACK, WINGMAN, FOLLOW, RTB, REFUEL, AWACS, EWR, TANKER, RUN_AWAY };
|
||||
};
|
||||
|
||||
class Unit
|
||||
{
|
||||
@@ -17,19 +18,19 @@ public:
|
||||
void updateMissionData(json::value json);
|
||||
json::value json();
|
||||
|
||||
virtual void setState(int newState) { state = newState; };
|
||||
void resetTask();
|
||||
|
||||
void setPath(list<Coords> path);
|
||||
void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; }
|
||||
void setAlive(bool newAlive) { alive = newAlive; }
|
||||
void setTarget(int targetID);
|
||||
void setLeader(bool newLeader) { leader = newLeader; }
|
||||
void setWingman(bool newWingman) { wingman = newWingman; }
|
||||
void setIsLeader(bool newIsLeader);
|
||||
void setIsWingman(bool newIsWingman);
|
||||
void setLeader(Unit* newLeader) { leader = newLeader; }
|
||||
void setWingmen(vector<Unit*> newWingmen) { wingmen = newWingmen; }
|
||||
void setFormation(wstring newFormation) { formation = newFormation; }
|
||||
|
||||
virtual void changeSpeed(wstring change) {};
|
||||
virtual void changeAltitude(wstring change) {};
|
||||
|
||||
void resetActiveDestination();
|
||||
void setFormationOffset(Offset formationOffset);
|
||||
|
||||
int getID() { return ID; }
|
||||
wstring getName() { return name; }
|
||||
@@ -46,12 +47,26 @@ public:
|
||||
Coords getActiveDestination() { return activeDestination; }
|
||||
virtual wstring getCategory() { return L"No category"; };
|
||||
wstring getTarget();
|
||||
bool isTargetAlive();
|
||||
wstring getCurrentTask() { return currentTask; }
|
||||
bool getAlive() { return alive; }
|
||||
bool getIsLeader() { return isLeader; }
|
||||
bool getIsWingman() { return isWingman; }
|
||||
wstring getFormation() { return formation; }
|
||||
|
||||
virtual double getTargetSpeed() { return targetSpeed; };
|
||||
virtual double getTargetAltitude() { return targetAltitude; };
|
||||
virtual void setTargetSpeed(double newSpeed) { targetSpeed = newSpeed; }
|
||||
virtual void setTargetAltitude(double newAltitude) { targetAltitude = newAltitude; }
|
||||
virtual void changeSpeed(wstring change) {};
|
||||
virtual void changeAltitude(wstring change) {};
|
||||
|
||||
void resetActiveDestination();
|
||||
|
||||
protected:
|
||||
int ID;
|
||||
int state = State::IDLE;
|
||||
bool hasTask = false;
|
||||
bool AI = false;
|
||||
bool alive = true;
|
||||
wstring name = L"undefined";
|
||||
@@ -67,13 +82,12 @@ protected:
|
||||
double speed = NULL;
|
||||
json::value flags = json::value::null();
|
||||
int targetID = NULL;
|
||||
bool holding = false;
|
||||
bool looping = false;
|
||||
wstring taskOptions = L"{}";
|
||||
wstring currentTask = L"";
|
||||
bool leader = false;
|
||||
bool wingman = false;
|
||||
bool isLeader = false;
|
||||
bool isWingman = false;
|
||||
Offset formationOffset = Offset(NULL);
|
||||
wstring formation = L"";
|
||||
Unit* leader = nullptr;
|
||||
vector<Unit*> wingmen;
|
||||
double targetSpeed = 0;
|
||||
double targetAltitude = 0;
|
||||
@@ -85,112 +99,16 @@ protected:
|
||||
Coords activeDestination = Coords(0);
|
||||
Coords oldPosition = Coords(0); // Used to approximate speed
|
||||
|
||||
virtual void AIloop();
|
||||
virtual void AIloop() = 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"; };
|
||||
};
|
||||
|
||||
|
||||
19
src/core/include/aircraft.h
Normal file
19
src/core/include/aircraft.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "airunit.h"
|
||||
|
||||
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;
|
||||
};
|
||||
30
src/core/include/airunit.h
Normal file
30
src/core/include/airunit.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "framework.h"
|
||||
#include "utils.h"
|
||||
#include "dcstools.h"
|
||||
#include "luatools.h"
|
||||
#include "Unit.h"
|
||||
|
||||
#define AIR_DEST_DIST_THR 2000
|
||||
|
||||
class AirUnit : public Unit
|
||||
{
|
||||
public:
|
||||
AirUnit(json::value json, int ID);
|
||||
|
||||
virtual wstring getCategory() = 0;
|
||||
virtual void changeSpeed(wstring change) {};
|
||||
virtual void changeAltitude(wstring change) {};
|
||||
virtual void setTargetSpeed(double newTargetSpeed);
|
||||
virtual void setTargetAltitude(double newTargetAltitude);
|
||||
|
||||
protected:
|
||||
virtual void AIloop();
|
||||
virtual void setState(int newState);
|
||||
bool isDestinationReached();
|
||||
bool setActiveDestination();
|
||||
void createHoldingPattern();
|
||||
bool updateActivePath(bool looping);
|
||||
void goToDestination(wstring enrouteTask = L"nil");
|
||||
void taskWingmen();
|
||||
};
|
||||
19
src/core/include/groundunit.h
Normal file
19
src/core/include/groundunit.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "unit.h"
|
||||
|
||||
#define GROUND_DEST_DIST_THR 100
|
||||
|
||||
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;
|
||||
};
|
||||
19
src/core/include/helicopter.h
Normal file
19
src/core/include/helicopter.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "airunit.h"
|
||||
|
||||
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;
|
||||
};
|
||||
17
src/core/include/navyunit.h
Normal file
17
src/core/include/navyunit.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "unit.h"
|
||||
|
||||
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;
|
||||
};
|
||||
30
src/core/include/weapon.h
Normal file
30
src/core/include/weapon.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "unit.h"
|
||||
|
||||
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"; };
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "dcstools.h"
|
||||
|
||||
/* Move command */
|
||||
wstring MoveCommand::getString(lua_State* L)
|
||||
wstring Move::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
@@ -19,7 +19,7 @@ wstring MoveCommand::getString(lua_State* L)
|
||||
}
|
||||
|
||||
/* Smoke command */
|
||||
wstring SmokeCommand::getString(lua_State* L)
|
||||
wstring Smoke::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
@@ -31,7 +31,7 @@ wstring SmokeCommand::getString(lua_State* L)
|
||||
}
|
||||
|
||||
/* Spawn ground command */
|
||||
wstring SpawnGroundUnitCommand::getString(lua_State* L)
|
||||
wstring SpawnGroundUnit::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
@@ -44,7 +44,7 @@ wstring SpawnGroundUnitCommand::getString(lua_State* L)
|
||||
}
|
||||
|
||||
/* Spawn air command */
|
||||
wstring SpawnAircraftCommand::getString(lua_State* L)
|
||||
wstring SpawnAircraft::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream optionsSS;
|
||||
optionsSS.precision(10);
|
||||
@@ -65,7 +65,7 @@ wstring SpawnAircraftCommand::getString(lua_State* L)
|
||||
}
|
||||
|
||||
/* Clone unit command */
|
||||
wstring CloneCommand::getString(lua_State* L)
|
||||
wstring Clone::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
@@ -74,14 +74,50 @@ wstring CloneCommand::getString(lua_State* L)
|
||||
return commandSS.str();
|
||||
}
|
||||
|
||||
/* Follow unit command */
|
||||
wstring FollowCommand::getString(lua_State* L)
|
||||
/* Set task command */
|
||||
wstring SetTask::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
commandSS << "Olympus.follow, "
|
||||
<< leaderID << ","
|
||||
commandSS << "Olympus.setTask, "
|
||||
<< ID << ","
|
||||
<< task;
|
||||
|
||||
return commandSS.str();
|
||||
}
|
||||
|
||||
/* Reset task command */
|
||||
wstring ResetTask::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
commandSS << "Olympus.resetTask, "
|
||||
<< ID;
|
||||
|
||||
return commandSS.str();
|
||||
}
|
||||
|
||||
/* Set command command */
|
||||
wstring SetCommand::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
commandSS << "Olympus.setCommand, "
|
||||
<< ID << ","
|
||||
<< command;
|
||||
|
||||
return commandSS.str();
|
||||
}
|
||||
|
||||
/* Set option command */
|
||||
wstring SetOption::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
commandSS << "Olympus.setOption, "
|
||||
<< ID << ","
|
||||
<< optionID << ","
|
||||
<< optionValue;
|
||||
|
||||
return commandSS.str();
|
||||
}
|
||||
@@ -73,17 +73,17 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
if (unit != nullptr)
|
||||
{
|
||||
unit->setPath(newPath);
|
||||
unit->setState(State::REACH_DESTINATION);
|
||||
log(unitName + L" new path set successfully");
|
||||
}
|
||||
else
|
||||
log(unitName + L" not found, request will be discarded");
|
||||
}
|
||||
}
|
||||
else if (key.compare(L"smoke") == 0)
|
||||
@@ -93,7 +93,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
double lng = value[L"location"][L"lng"].as_double();
|
||||
log(L"Adding " + color + L" smoke at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")");
|
||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||
command = dynamic_cast<Command*>(new SmokeCommand(color, loc));
|
||||
command = dynamic_cast<Command*>(new Smoke(color, loc));
|
||||
}
|
||||
else if (key.compare(L"spawnGround") == 0)
|
||||
{
|
||||
@@ -103,7 +103,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
double lng = value[L"location"][L"lng"].as_double();
|
||||
log(L"Spawning " + coalition + L" ground 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 SpawnGroundUnitCommand(coalition, type, loc));
|
||||
command = dynamic_cast<Command*>(new SpawnGroundUnit(coalition, type, loc));
|
||||
}
|
||||
else if (key.compare(L"spawnAir") == 0)
|
||||
{
|
||||
@@ -115,7 +115,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
wstring payloadName = value[L"payloadName"].as_string();
|
||||
wstring airbaseName = value[L"airbaseName"].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" " + airbaseName + L")");
|
||||
command = dynamic_cast<Command*>(new SpawnAircraftCommand(coalition, type, loc, payloadName, airbaseName));
|
||||
command = dynamic_cast<Command*>(new SpawnAircraft(coalition, type, loc, payloadName, airbaseName));
|
||||
}
|
||||
else if (key.compare(L"attackUnit") == 0)
|
||||
{
|
||||
@@ -129,72 +129,87 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
wstring targetName;
|
||||
|
||||
if (unit != nullptr)
|
||||
{
|
||||
unitName = unit->getUnitName();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (target != nullptr)
|
||||
{
|
||||
targetName = target->getUnitName();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log(L"Unit " + unitName + L" attacking unit " + targetName);
|
||||
unit->setTarget(targetID);
|
||||
unit->setState(State::ATTACK);
|
||||
}
|
||||
else if (key.compare(L"stopAttack") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
if (unit != nullptr)
|
||||
unit->setState(State::REACH_DESTINATION);
|
||||
else
|
||||
return;
|
||||
}
|
||||
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 if (key.compare(L"setSpeed") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
if (unit != nullptr)
|
||||
unit->setTargetSpeed(value[L"speed"].as_double());
|
||||
}
|
||||
else if (key.compare(L"setAltitude") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
if (unit != nullptr)
|
||||
unit->setTargetAltitude(value[L"altitude"].as_double());
|
||||
}
|
||||
else if (key.compare(L"cloneUnit") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
command = dynamic_cast<Command*>(new CloneCommand(ID));
|
||||
command = dynamic_cast<Command*>(new Clone(ID));
|
||||
log(L"Cloning unit " + to_wstring(ID));
|
||||
}
|
||||
else if (key.compare(L"setLeader") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
json::value wingmenIDs = value[L"wingmenIDs"];
|
||||
vector<Unit*> wingmen;
|
||||
if (unit != nullptr)
|
||||
bool isLeader = value[L"isLeader"].as_bool();
|
||||
if (isLeader)
|
||||
{
|
||||
for (auto itr = wingmenIDs.as_array().begin(); itr != wingmenIDs.as_array().end(); itr++)
|
||||
json::value wingmenIDs = value[L"wingmenIDs"];
|
||||
vector<Unit*> wingmen;
|
||||
if (unit != nullptr)
|
||||
{
|
||||
Unit* wingman = unitsFactory->getUnit(itr->as_integer());
|
||||
if (wingman != nullptr)
|
||||
for (auto itr = wingmenIDs.as_array().begin(); itr != wingmenIDs.as_array().end(); itr++)
|
||||
{
|
||||
wingman->setWingman(true);
|
||||
wingmen.push_back(wingman);
|
||||
log(L"Setting " + wingman->getName() + L" as wingman leader");
|
||||
Unit* wingman = unitsFactory->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");
|
||||
}
|
||||
unit->setWingmen(wingmen);
|
||||
unit->setLeader(true);
|
||||
unit->resetActiveDestination();
|
||||
log(L"Setting " + unit->getName() + L" as formation leader");
|
||||
}
|
||||
else {
|
||||
unit->setIsLeader(false);
|
||||
}
|
||||
}
|
||||
else if (key.compare(L"setFormation") == 0)
|
||||
|
||||
@@ -12,8 +12,6 @@ using namespace GeographicLib;
|
||||
extern Scheduler* scheduler;
|
||||
extern UnitsFactory* unitsFactory;
|
||||
|
||||
const Geodesic& geod = Geodesic::WGS84();
|
||||
|
||||
Unit::Unit(json::value json, int ID) :
|
||||
ID(ID)
|
||||
{
|
||||
@@ -34,7 +32,7 @@ void Unit::updateExportData(json::value json)
|
||||
if (oldPosition != NULL)
|
||||
{
|
||||
double dist = 0;
|
||||
geod.Inverse(latitude, longitude, oldPosition.lat, oldPosition.lng, dist);
|
||||
Geodesic::WGS84().Inverse(latitude, longitude, oldPosition.lat, oldPosition.lng, dist);
|
||||
speed = speed * 0.95 + (dist / UPDATE_TIME_INTERVAL) * 0.05;
|
||||
}
|
||||
oldPosition = Coords(latitude, longitude, altitude);
|
||||
@@ -79,97 +77,17 @@ void Unit::updateExportData(json::value json)
|
||||
|
||||
void Unit::updateMissionData(json::value json)
|
||||
{
|
||||
/* Lock for thread safety */
|
||||
lock_guard<mutex> guard(mutexLock);
|
||||
|
||||
if (json.has_number_field(L"fuel"))
|
||||
fuel = json[L"fuel"].as_number().to_int32();
|
||||
if (json.has_object_field(L"ammo"))
|
||||
ammo = json[L"ammo"];
|
||||
if (json.has_object_field(L"targets"))
|
||||
targets = json[L"targets"];
|
||||
}
|
||||
|
||||
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"";
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::AIloop()
|
||||
{
|
||||
// For wingman units, the leader decides the active destination
|
||||
if (!wingman)
|
||||
{
|
||||
/* 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, activeDestination, getTargetSpeed(), getTargetAltitude(), getCategory(), taskOptions));
|
||||
scheduler->appendCommand(command);
|
||||
|
||||
if (leader)
|
||||
{
|
||||
for (auto itr = wingmen.begin(); itr != wingmen.end(); itr++)
|
||||
{
|
||||
// Manually set the path and the active destination of the wingmen
|
||||
(*itr)->setPath(activePath);
|
||||
(*itr)->setActiveDestination(activeDestination);
|
||||
Command* command = dynamic_cast<Command*>(new FollowCommand(ID, (*itr)->getID()));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
log(unitName + L" no more points in active path");
|
||||
activeDestination = Coords(0); // Set the active path to NULL
|
||||
currentTask = L"Idle";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function reset the activation so that the AI lopp will call again the MoveCommand. This is useful to change speed and altitude, for example */
|
||||
void Unit::resetActiveDestination()
|
||||
{
|
||||
log(unitName + L" resetting active destination");
|
||||
activeDestination = Coords(0);
|
||||
if (json.has_boolean_field(L"hasTask"))
|
||||
hasTask = json[L"hasTask"].as_bool();
|
||||
}
|
||||
|
||||
json::value Unit::json()
|
||||
@@ -194,18 +112,22 @@ json::value Unit::json()
|
||||
json[L"flags"] = flags;
|
||||
json[L"category"] = json::value::string(getCategory());
|
||||
json[L"currentTask"] = json::value::string(getCurrentTask());
|
||||
json[L"leader"] = leader;
|
||||
json[L"wingman"] = wingman;
|
||||
json[L"isLeader"] = isLeader;
|
||||
json[L"isWingman"] = isWingman;
|
||||
json[L"formation"] = json::value::string(formation);
|
||||
json[L"fuel"] = fuel;
|
||||
json[L"ammo"] = ammo;
|
||||
json[L"targets"] = targets;
|
||||
json[L"targetSpeed"] = targetSpeed;
|
||||
json[L"targetAltitude"] = targetAltitude;
|
||||
json[L"hasTask"] = hasTask;
|
||||
|
||||
int i = 0;
|
||||
for (auto itr = wingmen.begin(); itr != wingmen.end(); itr++)
|
||||
{
|
||||
json[L"wingmenIDs"][i++] = (*itr)->getID();
|
||||
}
|
||||
|
||||
if (leader != nullptr)
|
||||
json[L"leaderID"] = leader->getID();
|
||||
|
||||
/* Send the active path as a json object */
|
||||
if (activePath.size() > 0) {
|
||||
@@ -225,239 +147,78 @@ json::value Unit::json()
|
||||
return json;
|
||||
}
|
||||
|
||||
/* Air unit */
|
||||
AirUnit::AirUnit(json::value json, int ID) : Unit(json, ID)
|
||||
void Unit::setPath(list<Coords> path)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void AirUnit::AIloop()
|
||||
{
|
||||
if (targetID != 0)
|
||||
if (state != State::WINGMAN && state != State::FOLLOW)
|
||||
{
|
||||
std::wostringstream taskOptionsSS;
|
||||
taskOptionsSS << "{"
|
||||
<< "id = 'EngageUnit'" << ","
|
||||
<< "targetID = " << targetID << ","
|
||||
<< "}";
|
||||
taskOptions = taskOptionsSS.str();
|
||||
currentTask = L"Attacking " + getTarget();
|
||||
activePath = path;
|
||||
resetActiveDestination();
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::setTarget(int newTargetID)
|
||||
{
|
||||
targetID = newTargetID;
|
||||
}
|
||||
|
||||
wstring Unit::getTarget()
|
||||
{
|
||||
if (isTargetAlive())
|
||||
{
|
||||
Unit* target = unitsFactory->getUnit(targetID);
|
||||
if (target != nullptr)
|
||||
return target->getUnitName();
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
|
||||
bool Unit::isTargetAlive()
|
||||
{
|
||||
if (targetID == NULL)
|
||||
return false;
|
||||
|
||||
Unit* target = unitsFactory->getUnit(targetID);
|
||||
if (target != nullptr)
|
||||
return target->alive;
|
||||
else
|
||||
{
|
||||
currentTask = L"Reaching destination";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Call the common AI loop */
|
||||
Unit::AIloop();
|
||||
/* This function reset the activation so that the AI lopp will call again the MoveCommand. This is useful to change speed and altitude, for example */
|
||||
void Unit::resetActiveDestination()
|
||||
{
|
||||
activeDestination = Coords(NULL);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
void Unit::resetTask()
|
||||
{
|
||||
Command* command = dynamic_cast<Command*>(new ResetTask(ID));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
|
||||
void Unit::setIsLeader(bool newIsLeader) {
|
||||
isLeader = newIsLeader;
|
||||
if (!isLeader) {
|
||||
for (auto wingman : wingmen)
|
||||
{
|
||||
/* Destination reached */
|
||||
if (holding || looping)
|
||||
{
|
||||
activePath.push_back(activePath.front());
|
||||
}
|
||||
activePath.pop_front();
|
||||
log(name + L" destination reached");
|
||||
wingman->setFormation(L"");
|
||||
wingman->setIsWingman(false);
|
||||
wingman->setLeader(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::setIsWingman(bool newIsWingman)
|
||||
{
|
||||
isWingman = newIsWingman;
|
||||
if (isWingman)
|
||||
setState(State::WINGMAN);
|
||||
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;
|
||||
currentTask = L"Holding";
|
||||
}
|
||||
setState(State::IDLE);
|
||||
}
|
||||
|
||||
/* Aircraft */
|
||||
Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID)
|
||||
void Unit::setFormationOffset(Offset newFormationOffset)
|
||||
{
|
||||
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));
|
||||
};
|
||||
formationOffset = newFormationOffset;
|
||||
resetTask();
|
||||
}
|
||||
58
src/core/src/aircraft.cpp
Normal file
58
src/core/src/aircraft.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "aircraft.h"
|
||||
#include "utils.h"
|
||||
#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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
setState(State::IDLE);
|
||||
}
|
||||
else if (change.compare(L"slow") == 0)
|
||||
targetSpeed -= 25 / 1.94384;
|
||||
else if (change.compare(L"fast") == 0)
|
||||
targetSpeed += 25 / 1.94384;
|
||||
|
||||
if (targetSpeed < 50 / 1.94384)
|
||||
targetSpeed = 50 / 1.94384;
|
||||
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
}
|
||||
|
||||
void Aircraft::changeAltitude(wstring change)
|
||||
{
|
||||
if (change.compare(L"descend") == 0)
|
||||
{
|
||||
if (targetAltitude > 5000)
|
||||
targetAltitude -= 2500 / 3.28084;
|
||||
else if (targetAltitude > 0)
|
||||
targetAltitude -= 500 / 3.28084;
|
||||
}
|
||||
else if (change.compare(L"climb") == 0)
|
||||
{
|
||||
if (targetAltitude > 5000)
|
||||
targetAltitude += 2500 / 3.28084;
|
||||
else if (targetAltitude > 0)
|
||||
targetAltitude += 500 / 3.28084;
|
||||
}
|
||||
if (targetAltitude < 0)
|
||||
targetAltitude = 0;
|
||||
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
}
|
||||
331
src/core/src/airunit.cpp
Normal file
331
src/core/src/airunit.cpp
Normal file
@@ -0,0 +1,331 @@
|
||||
#include "airunit.h"
|
||||
#include "utils.h"
|
||||
#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;
|
||||
|
||||
/* Air unit */
|
||||
AirUnit::AirUnit(json::value json, int ID) : Unit(json, ID)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void AirUnit::setState(int newState)
|
||||
{
|
||||
if (state != newState)
|
||||
{
|
||||
switch (state) {
|
||||
case State::IDLE: {
|
||||
break;
|
||||
}
|
||||
case State::REACH_DESTINATION: {
|
||||
break;
|
||||
}
|
||||
case State::ATTACK: {
|
||||
setTarget(NULL);
|
||||
break;
|
||||
}
|
||||
case State::FOLLOW: {
|
||||
break;
|
||||
}
|
||||
case State::WINGMAN: {
|
||||
if (isWingman)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (newState) {
|
||||
case State::IDLE: {
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::REACH_DESTINATION: {
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::ATTACK: {
|
||||
if (isTargetAlive()) {
|
||||
Unit* target = unitsFactory->getUnit(targetID);
|
||||
Coords targetPosition = Coords(target->getLatitude(), target->getLongitude(), 0);
|
||||
activePath.clear();
|
||||
activePath.push_front(targetPosition);
|
||||
resetActiveDestination();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case State::FOLLOW: {
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::WINGMAN: {
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
resetTask();
|
||||
|
||||
log(unitName + L" setting state from " + to_wstring(state) + L" to " + to_wstring(newState));
|
||||
state = newState;
|
||||
}
|
||||
}
|
||||
|
||||
bool AirUnit::isDestinationReached()
|
||||
{
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
double dist = 0;
|
||||
Geodesic::WGS84().Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, dist);
|
||||
if (dist < AIR_DEST_DIST_THR)
|
||||
{
|
||||
log(unitName + L" destination reached");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AirUnit::setActiveDestination()
|
||||
{
|
||||
if (activePath.size() > 0)
|
||||
{
|
||||
activeDestination = activePath.front();
|
||||
log(unitName + L" active destination set to queue front");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeDestination = Coords(0);
|
||||
log(unitName + L" active destination set to NULL");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AirUnit::createHoldingPattern()
|
||||
{
|
||||
/* Air units must ALWAYS have a destination or they will RTB and become uncontrollable */
|
||||
activePath.clear();
|
||||
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);
|
||||
activePath.push_back(point1);
|
||||
activePath.push_back(point2);
|
||||
activePath.push_back(point3);
|
||||
activePath.push_back(Coords(latitude, longitude));
|
||||
log(unitName + L" holding pattern created");
|
||||
}
|
||||
|
||||
bool AirUnit::updateActivePath(bool looping)
|
||||
{
|
||||
if (activePath.size() > 0)
|
||||
{
|
||||
/* Push the next destination in the queue to the front */
|
||||
if (looping)
|
||||
activePath.push_back(activePath.front());
|
||||
activePath.pop_front();
|
||||
log(unitName + L" active path front popped");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AirUnit::goToDestination(wstring enrouteTask)
|
||||
{
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
Command* command = dynamic_cast<Command*>(new Move(ID, activeDestination, getTargetSpeed(), getTargetAltitude(), getCategory(), enrouteTask));
|
||||
scheduler->appendCommand(command);
|
||||
hasTask = true;
|
||||
}
|
||||
else
|
||||
log(unitName + L" error, no active destination!");
|
||||
}
|
||||
|
||||
void AirUnit::taskWingmen()
|
||||
{
|
||||
switch (state) {
|
||||
case State::IDLE:
|
||||
case State::REACH_DESTINATION:
|
||||
case State::ATTACK:{
|
||||
int idx = 1;
|
||||
for (auto const& wingman : wingmen)
|
||||
{
|
||||
if (!wingman->getIsWingman())
|
||||
{
|
||||
wingman->setIsWingman(true);
|
||||
wingman->setLeader(this);
|
||||
}
|
||||
|
||||
if (wingman->getFormation().compare(formation) != 0)
|
||||
{
|
||||
wingman->resetTask();
|
||||
wingman->setFormation(formation);
|
||||
if (formation.compare(L"Line abreast") == 0)
|
||||
wingman->setFormationOffset(Offset(0 * idx, 0 * idx, 1852 * idx));
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AirUnit::AIloop()
|
||||
{
|
||||
/* State machine */
|
||||
switch (state) {
|
||||
case State::IDLE: {
|
||||
wstring enrouteTask = L"nil";
|
||||
currentTask = L"Idle";
|
||||
|
||||
if (activeDestination == NULL || !hasTask)
|
||||
{
|
||||
createHoldingPattern();
|
||||
setActiveDestination();
|
||||
goToDestination(enrouteTask);
|
||||
}
|
||||
else {
|
||||
if (isDestinationReached() && updateActivePath(true) && setActiveDestination())
|
||||
goToDestination(enrouteTask);
|
||||
}
|
||||
|
||||
if (isLeader)
|
||||
taskWingmen();
|
||||
break;
|
||||
}
|
||||
case State::REACH_DESTINATION: {
|
||||
wstring enrouteTask = L"nil";
|
||||
currentTask = L"Reaching destination";
|
||||
|
||||
if (activeDestination == NULL || !hasTask)
|
||||
{
|
||||
setActiveDestination();
|
||||
goToDestination(enrouteTask);
|
||||
}
|
||||
else {
|
||||
if (isDestinationReached()) {
|
||||
if (updateActivePath(false) && setActiveDestination())
|
||||
goToDestination(enrouteTask);
|
||||
else {
|
||||
setState(State::IDLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLeader)
|
||||
taskWingmen();
|
||||
|
||||
break;
|
||||
}
|
||||
case State::ATTACK: {
|
||||
/* If the target is not alive (either not set or was succesfully destroyed) go back to REACH_DESTINATION */
|
||||
if (!isTargetAlive()) {
|
||||
setState(State::REACH_DESTINATION);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Attack state is an "enroute" task, meaning the unit will keep trying to attack even if a new destination is set. This is useful to
|
||||
manoeuvre the unit so that it can detect and engage the target. */
|
||||
std::wostringstream enrouteTaskSS;
|
||||
enrouteTaskSS << "{"
|
||||
<< "id = 'EngageUnit'" << ","
|
||||
<< "targetID = " << targetID << ","
|
||||
<< "}";
|
||||
wstring enrouteTask = enrouteTaskSS.str();
|
||||
currentTask = L"Attacking " + getTarget();
|
||||
|
||||
if (activeDestination == NULL || !hasTask)
|
||||
{
|
||||
setActiveDestination();
|
||||
goToDestination(enrouteTask);
|
||||
}
|
||||
else {
|
||||
if (isDestinationReached()) {
|
||||
if (updateActivePath(false) && setActiveDestination())
|
||||
goToDestination(enrouteTask);
|
||||
else {
|
||||
setState(State::IDLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLeader)
|
||||
taskWingmen();
|
||||
|
||||
break;
|
||||
}
|
||||
case State::FOLLOW: {
|
||||
/* TODO */
|
||||
setState(State::IDLE);
|
||||
break;
|
||||
}
|
||||
case State::WINGMAN: {
|
||||
/* In the WINGMAN state, the unit relinquishes control to the leader */
|
||||
activePath.clear();
|
||||
activeDestination = Coords(NULL);
|
||||
if (leader == nullptr || !leader->getAlive())
|
||||
{
|
||||
this->setFormation(L"");
|
||||
this->setIsWingman(false);
|
||||
break;
|
||||
}
|
||||
if (!hasTask) {
|
||||
if (leader != nullptr && leader->getAlive() && formationOffset != NULL)
|
||||
{
|
||||
std::wostringstream taskSS;
|
||||
taskSS << "{"
|
||||
<< "id = 'FollowUnit'" << ", "
|
||||
<< "leaderID = " << leader->getID() << ","
|
||||
<< "offset = {"
|
||||
<< "x = " << formationOffset.x << ","
|
||||
<< "y = " << formationOffset.y << ","
|
||||
<< "z = " << formationOffset.z
|
||||
<< "},"
|
||||
<< "}";
|
||||
Command* command = dynamic_cast<Command*>(new SetTask(ID, taskSS.str()));
|
||||
scheduler->appendCommand(command);
|
||||
hasTask = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AirUnit::setTargetSpeed(double newTargetSpeed) {
|
||||
targetSpeed = newTargetSpeed;
|
||||
goToDestination();
|
||||
}
|
||||
|
||||
void AirUnit::setTargetAltitude(double newTargetAltitude) {
|
||||
targetAltitude = newTargetAltitude;
|
||||
goToDestination();
|
||||
}
|
||||
@@ -12,6 +12,8 @@ UnitsFactory* unitsFactory = nullptr;
|
||||
Server* server = nullptr;
|
||||
Scheduler* scheduler = nullptr;
|
||||
json::value airbasesData;
|
||||
json::value bullseyeData;
|
||||
|
||||
|
||||
/* Called when DCS simulation stops. All singleton instances are deleted. */
|
||||
extern "C" DllExport int coreDeinit(lua_State* L)
|
||||
@@ -71,40 +73,8 @@ extern "C" DllExport int coreMissionData(lua_State * L)
|
||||
unitsFactory->updateMissionData(missionData[L"unitsData"]);
|
||||
if (missionData.has_object_field(L"airbases"))
|
||||
airbasesData = missionData[L"airbases"];
|
||||
if (missionData.has_object_field(L"bullseye"))
|
||||
bullseyeData = missionData[L"bullseye"];
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(
|
||||
HINSTANCE hinstDLL, // handle to DLL module
|
||||
DWORD fdwReason, // reason for calling function
|
||||
LPVOID lpvReserved) // reserved
|
||||
{
|
||||
// Perform actions based on the reason for calling.
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
// Initialize once for each new process.
|
||||
// Return FALSE to fail DLL load.
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
// Do thread-specific initialization.
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
// Do thread-specific cleanup.
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
if (lpvReserved != nullptr)
|
||||
{
|
||||
break; // do not do cleanup if process termination scenario
|
||||
}
|
||||
|
||||
// Perform any necessary cleanup.
|
||||
break;
|
||||
}
|
||||
return TRUE; // Successful DLL_PROCESS_ATTACH.
|
||||
}
|
||||
71
src/core/src/groundunit.cpp
Normal file
71
src/core/src/groundunit.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "groundunit.h"
|
||||
#include "utils.h"
|
||||
#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;
|
||||
|
||||
/* 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()
|
||||
{
|
||||
/* 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 Move(ID, activeDestination, getTargetSpeed(), getTargetAltitude(), getCategory(), L"nil"));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
log(unitName + L" no more points in active path");
|
||||
activeDestination = Coords(0); // Set the active path to NULL
|
||||
currentTask = L"Idle";
|
||||
}
|
||||
}
|
||||
|
||||
/* Ground unit AI Loop */
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
double newDist = 0;
|
||||
Geodesic::WGS84().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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
58
src/core/src/helicopter.cpp
Normal file
58
src/core/src/helicopter.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "helicopter.h"
|
||||
#include "utils.h"
|
||||
#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;
|
||||
|
||||
/* 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 -= 10 / 1.94384;
|
||||
else if (change.compare(L"fast") == 0)
|
||||
targetSpeed += 10 / 1.94384;
|
||||
if (targetSpeed < 0)
|
||||
targetSpeed = 0;
|
||||
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
}
|
||||
|
||||
void Helicopter::changeAltitude(wstring change)
|
||||
{
|
||||
if (change.compare(L"descend") == 0)
|
||||
{
|
||||
if (targetAltitude > 100)
|
||||
targetAltitude -= 100 / 3.28084;
|
||||
else if (targetAltitude > 0)
|
||||
targetAltitude -= 10 / 3.28084;
|
||||
}
|
||||
else if (change.compare(L"climb") == 0)
|
||||
{
|
||||
if (targetAltitude > 100)
|
||||
targetAltitude += 100 / 3.28084;
|
||||
else if (targetAltitude > 0)
|
||||
targetAltitude += 10 / 3.28084;
|
||||
}
|
||||
if (targetAltitude < 0)
|
||||
targetAltitude = 0;
|
||||
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
}
|
||||
40
src/core/src/navyunit.cpp
Normal file
40
src/core/src/navyunit.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "navyunit.h"
|
||||
#include "utils.h"
|
||||
#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;
|
||||
|
||||
/* 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()
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
extern UnitsFactory* unitsFactory;
|
||||
extern Scheduler* scheduler;
|
||||
extern json::value airbasesData;
|
||||
extern json::value bullseyeData;
|
||||
|
||||
void handle_eptr(std::exception_ptr eptr)
|
||||
{
|
||||
@@ -59,6 +60,7 @@ void Server::handle_get(http_request request)
|
||||
try {
|
||||
unitsFactory->updateAnswer(answer);
|
||||
answer[L"airbases"] = airbasesData;
|
||||
answer[L"bullseye"] = bullseyeData;
|
||||
response.set_body(answer);
|
||||
}
|
||||
catch (...) {
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
#include "unitsFactory.h"
|
||||
#include "logger.h"
|
||||
#include "unit.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
#include "aircraft.h"
|
||||
#include "helicopter.h"
|
||||
#include "groundunit.h"
|
||||
#include "navyunit.h"
|
||||
#include "weapon.h"
|
||||
|
||||
UnitsFactory::UnitsFactory(lua_State* L)
|
||||
{
|
||||
|
||||
31
src/core/src/weapon.cpp
Normal file
31
src/core/src/weapon.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "weapon.h"
|
||||
#include "utils.h"
|
||||
#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;
|
||||
|
||||
/* 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));
|
||||
};
|
||||
@@ -7,6 +7,12 @@ struct Coords {
|
||||
double alt = 0;
|
||||
};
|
||||
|
||||
struct Offset {
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
};
|
||||
|
||||
// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
|
||||
const DllExport std::string CurrentDateTime();
|
||||
std::wstring DllExport to_wstring(const std::string& str);
|
||||
@@ -16,3 +22,8 @@ bool DllExport operator== (const Coords& a, const Coords& b);
|
||||
bool DllExport operator!= (const Coords& a, const Coords& b);
|
||||
bool DllExport operator== (const Coords& a, const int& b);
|
||||
bool DllExport operator!= (const Coords& a, const int& b);
|
||||
|
||||
bool DllExport operator== (const Offset& a, const Offset& b);
|
||||
bool DllExport operator!= (const Offset& a, const Offset& b);
|
||||
bool DllExport operator== (const Offset& a, const int& b);
|
||||
bool DllExport operator!= (const Offset& a, const int& b);
|
||||
|
||||
@@ -42,3 +42,8 @@ bool operator== (const Coords& a, const Coords& b) { return a.lat == b.lat && a.
|
||||
bool operator!= (const Coords& a, const Coords& b) { return !(a == b); }
|
||||
bool operator== (const Coords& a, const int& b) { return a.lat == b && a.lng == b && a.alt == b; }
|
||||
bool operator!= (const Coords& a, const int& b) { return !(a == b); }
|
||||
|
||||
bool operator== (const Offset& a, const Offset& b) { return a.x == b.x && a.y == b.y && a.z == b.z; }
|
||||
bool operator!= (const Offset& a, const Offset& b) { return !(a == b); }
|
||||
bool operator== (const Offset& a, const int& b) { return a.x == b && a.y == b && a.z == b; }
|
||||
bool operator!= (const Offset& a, const int& b) { return !(a == b); }
|
||||
|
||||
Reference in New Issue
Block a user