Added basic simulated firefight state

This commit is contained in:
Pax1601
2023-09-15 09:36:27 +02:00
parent 9acd358080
commit 8977ba9b6d
20 changed files with 461 additions and 44 deletions

View File

@@ -37,6 +37,7 @@
<ClInclude Include="include\airunit.h" />
<ClInclude Include="include\commands.h" />
<ClInclude Include="include\datatypes.h" />
<ClInclude Include="include\gundata.h" />
<ClInclude Include="include\measure.h" />
<ClInclude Include="include\groundunit.h" />
<ClInclude Include="include\helicopter.h" />

View File

@@ -54,6 +54,9 @@
<ClInclude Include="include\weaponsmanager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\gundata.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\aircraft.cpp">

View File

@@ -95,21 +95,26 @@ namespace ECMUse {
class Command
{
public:
Command(function<void(void)> callback) : callback(callback) {};
unsigned int getPriority() { return priority; }
virtual string getString() = 0;
virtual unsigned int getLoad() = 0;
const string getHash() { return hash; }
void executeCallback() { callback(); }
protected:
unsigned int priority = CommandPriority::LOW;
const string hash = random_string(16);
function<void(void)> callback;
};
/* Simple low priority move command (from user click) */
class Move : public Command
{
public:
Move(string groupName, Coords destination, double speed, string speedType, double altitude, string altitudeType, string taskOptions, string category):
Move(string groupName, Coords destination, double speed, string speedType, double altitude,
string altitudeType, string taskOptions, string category, function<void(void)> callback = []() {}) :
Command(callback),
groupName(groupName),
destination(destination),
speed(speed),
@@ -139,7 +144,8 @@ private:
class Smoke : public Command
{
public:
Smoke(string color, Coords location) :
Smoke(string color, Coords location, function<void(void)> callback = [](){}) :
Command(callback),
color(color),
location(location)
{
@@ -157,7 +163,8 @@ private:
class SpawnGroundUnits : public Command
{
public:
SpawnGroundUnits(string coalition, vector<SpawnOptions> spawnOptions, string country, bool immediate) :
SpawnGroundUnits(string coalition, vector<SpawnOptions> spawnOptions, string country, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
coalition(coalition),
spawnOptions(spawnOptions),
country(country),
@@ -179,7 +186,8 @@ private:
class SpawnNavyUnits : public Command
{
public:
SpawnNavyUnits(string coalition, vector<SpawnOptions> spawnOptions, string country, bool immediate) :
SpawnNavyUnits(string coalition, vector<SpawnOptions> spawnOptions, string country, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
coalition(coalition),
spawnOptions(spawnOptions),
country(country),
@@ -201,7 +209,8 @@ private:
class SpawnAircrafts : public Command
{
public:
SpawnAircrafts(string coalition, vector<SpawnOptions> spawnOptions, string airbaseName, string country, bool immediate) :
SpawnAircrafts(string coalition, vector<SpawnOptions> spawnOptions, string airbaseName, string country, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
coalition(coalition),
spawnOptions(spawnOptions),
airbaseName(airbaseName),
@@ -221,12 +230,12 @@ private:
const bool immediate;
};
/* Spawn helicopter command */
class SpawnHelicopters : public Command
{
public:
SpawnHelicopters(string coalition, vector<SpawnOptions> spawnOptions, string airbaseName, string country, bool immediate) :
SpawnHelicopters(string coalition, vector<SpawnOptions> spawnOptions, string airbaseName, string country, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
coalition(coalition),
spawnOptions(spawnOptions),
airbaseName(airbaseName),
@@ -250,7 +259,8 @@ private:
class Clone : public Command
{
public:
Clone(vector<CloneOptions> cloneOptions, bool deleteOriginal) :
Clone(vector<CloneOptions> cloneOptions, bool deleteOriginal, function<void(void)> callback = [](){}) :
Command(callback),
cloneOptions(cloneOptions),
deleteOriginal(deleteOriginal)
{
@@ -268,7 +278,8 @@ private:
class Delete : public Command
{
public:
Delete(unsigned int ID, bool explosion, bool immediate ) :
Delete(unsigned int ID, bool explosion, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
ID(ID),
explosion(explosion),
immediate(immediate)
@@ -289,7 +300,8 @@ private:
class SetTask : public Command
{
public:
SetTask(string groupName, string task) :
SetTask(string groupName, string task, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
task(task)
{
@@ -307,7 +319,8 @@ private:
class ResetTask : public Command
{
public:
ResetTask(string groupName) :
ResetTask(string groupName, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName)
{
priority = CommandPriority::HIGH;
@@ -323,7 +336,8 @@ private:
class SetCommand : public Command
{
public:
SetCommand(string groupName, string command) :
SetCommand(string groupName, string command, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
command(command)
{
@@ -341,7 +355,8 @@ private:
class SetOption : public Command
{
public:
SetOption(string groupName, unsigned int optionID, unsigned int optionValue) :
SetOption(string groupName, unsigned int optionID, unsigned int optionValue, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
optionID(optionID),
optionValue(optionValue),
@@ -351,7 +366,8 @@ public:
priority = CommandPriority::HIGH;
};
SetOption(string groupName, unsigned int optionID, bool optionBool) :
SetOption(string groupName, unsigned int optionID, bool optionBool, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
optionID(optionID),
optionValue(0),
@@ -375,7 +391,8 @@ private:
class SetOnOff : public Command
{
public:
SetOnOff(string groupName, bool onOff) :
SetOnOff(string groupName, bool onOff, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
onOff(onOff)
{
@@ -393,7 +410,8 @@ private:
class Explosion : public Command
{
public:
Explosion(unsigned int intensity, Coords location) :
Explosion(unsigned int intensity, Coords location, function<void(void)> callback = [](){}) :
Command(callback),
location(location),
intensity(intensity)
{

View File

@@ -64,7 +64,8 @@ namespace State
BOMB_POINT,
CARPET_BOMB,
BOMB_BUILDING,
FIRE_AT_AREA
FIRE_AT_AREA,
SIMULATE_FIRE_FIGHT
};
};
@@ -125,4 +126,9 @@ struct SpawnOptions {
struct CloneOptions {
unsigned int ID;
Coords location;
};
struct GunDataItem {
double barrelHeight;
double muzzleVelocity;
};

116
src/core/include/gundata.h Normal file
View File

@@ -0,0 +1,116 @@
#pragma once
#include "framework.h"
#include "datatypes.h"
map<string, GunDataItem> gunData = {
{"2B11 mortar", {0.9, 860}},
{"SAU Gvozdika", {0.9, 860}},
{"SAU Msta", {0.9, 860}},
{"SAU Akatsia", {0.9, 860}},
{"SAU 2-C9", {0.9, 860}},
{"M-109", {0.9, 860}},
{"SpGH_Dana", {0.9, 860}},
{"AAV7", {0.9, 860}},
{"BMD-1", {0.9, 860}},
{"BMP-1", {0.9, 860}},
{"BMP-2", {0.9, 860}},
{"BMP-3", {0.9, 860}},
{"BRDM-2", {0.9, 860}},
{"BTR_D", {0.9, 860}},
{"Cobra", {0.9, 860}},
{"LAV-25", {0.9, 860}},
{"M1043 HMMWV Armament", {0.9, 860}},
{"M1045 HMMWV TOW", {0.9, 860}},
{"M1126 Stryker ICV", {0.9, 860}},
{"M-113", {0.9, 860}},
{"M1134 Stryker ATGM", {0.9, 860}},
{"M-2 Bradley", {0.9, 860}},
{"MCV-80", {0.9, 860}},
{"MTLB", {0.9, 860}},
{"Marder", {0.9, 860}},
{"TPZ", {0.9, 860}},
{"Grad_FDDM", {0.9, 860}},
{"Paratrooper RPG-16", {0.9, 860}},
{"Paratrooper AKS-74", {0.9, 860}},
{"Infantry AK Ins", {0.9, 860}},
{"Soldier AK", {0.4, 860}},
{"Infantry AK", {0.9, 860}},
{"Soldier M249", {0.9, 860}},
{"Soldier M4", {0.9, 860}},
{"Soldier M4 GRG", {0.9, 860}},
{"Soldier RPG", {0.9, 860}},
{"MLRS FDDM", {0.9, 860}},
{"Infantry AK ver2", {0.9, 860}},
{"Infantry AK ver3", {0.9, 860}},
{"Grad-URAL", {0.9, 860}},
{"Uragan_BM-27", {0.9, 860}},
{"Smerch", {0.9, 860}},
{"Smerch_HE", {0.9, 860}},
{"MLRS", {0.9, 860}},
{"Challenger2", {0.9, 860}},
{"Leclerc", {0.9, 860}},
{"M-60", {0.9, 860}},
{"M1128 Stryker MGS", {0.9, 860}},
{"M-1 Abrams", {0.9, 860}},
{"T-55", {0.9, 860}},
{"T-72B", {0.9, 860}},
{"T-80UD", {0.9, 860}},
{"T-90", {0.9, 860}},
{"Leopard1A3", {0.9, 860}},
{"Merkava_Mk4", {0.9, 860}},
{"JTAC", {0.9, 860}},
{"Infantry Animated", {0.9, 860}},
{"HL_DSHK", {0.9, 860}},
{"HL_KORD", {0.9, 860}},
{"tt_DSHK", {0.9, 860}},
{"tt_KORD", {0.9, 860}},
{"HL_B8M1", {0.9, 860}},
{"tt_B8M1", {0.9, 860}},
{"M4_Sherman", {0.9, 860}},
{"M2A1_halftrack", {0.9, 860}},
{"BTR-80", {0.9, 860}},
{"T-72B3", {0.9, 860}},
{"PT_76", {0.9, 860}},
{"BTR-82A", {0.9, 860}},
{"Chieftain_mk3", {0.9, 860}},
{"Pz_IV_H", {0.9, 860}},
{"Leopard-2A5", {0.9, 860}},
{"Leopard-2", {0.9, 860}},
{"leopard-2A4", {0.9, 860}},
{"leopard-2A4_trs", {0.9, 860}},
{"Sd_Kfz_251", {0.9, 860}},
{"T155_Firtina", {0.9, 860}},
{"VAB_Mephisto", {0.9, 860}},
{"ZTZ96B", {0.9, 860}},
{"ZBD04A", {0.9, 860}},
{"PLZ05", {0.9, 860}},
{"TYPE-59", {0.9, 860}},
{"Tiger_I", {0.9, 860}},
{"Tiger_II_H", {0.9, 860}},
{"Pz_V_Panther_G", {0.9, 860}},
{"Jagdpanther_G1", {0.9, 860}},
{"JagdPz_IV", {0.9, 860}},
{"Stug_IV", {0.9, 860}},
{"SturmPzIV", {0.9, 860}},
{"Wespe124", {0.9, 860}},
{"Sd_Kfz_234_2_Puma", {0.9, 860}},
{"soldier_mauser98", {0.9, 860}},
{"Stug_III", {0.9, 860}},
{"Elefant_SdKfz_184", {0.9, 860}},
{"Pak40", {0.9, 860}},
{"LeFH_18-40-105", {0.9, 860}},
{"Cromwell_IV", {0.9, 860}},
{"M4A4_Sherman_FF", {0.9, 860}},
{"soldier_wwii_br_01", {0.9, 860}},
{"Centaur_IV", {0.9, 860}},
{"Churchill_VII", {0.9, 860}},
{"Daimler_AC", {0.9, 860}},
{"Tetrarch", {0.9, 860}},
{"M12_GMC", {0.9, 860}},
{"soldier_wwii_us", {0.9, 860}},
{"M10_GMC", {0.9, 860}},
{"M8_Greyhound", {0.9, 860}},
{"M2A1-105", {0.9, 860}},
{"M4_Tractor", {0.9, 860}},
};

View File

@@ -54,6 +54,7 @@ public:
void resetTask();
bool checkTaskFailed();
void resetTaskFailedCounter();
void setHasTaskAssigned(bool newHasTaskAssigned);
void triggerUpdate(unsigned char datumIndex);
@@ -185,6 +186,7 @@ protected:
/********** Other **********/
unsigned int taskCheckCounter = 0;
bool hasTaskAssigned = false;
double initialFuel = 0;
map<unsigned char, unsigned long long> updateTimeMap;
unsigned long long lastLoopTime = 0;

View File

@@ -162,7 +162,7 @@ void AirUnit::AIloop()
desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" <<
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "'}";
}
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -267,7 +267,7 @@ void AirUnit::AIloop()
<< "z = " << formationOffset.z
<< "},"
<< "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -283,7 +283,7 @@ void AirUnit::AIloop()
taskSS << "{"
<< "id = 'Refuel'"
<< "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -297,8 +297,10 @@ void AirUnit::AIloop()
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'Bombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -308,8 +310,10 @@ void AirUnit::AIloop()
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'CarpetBombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -320,8 +324,10 @@ void AirUnit::AIloop()
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'AttackMapObject', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}

View File

@@ -4,7 +4,8 @@
#include "commands.h"
#include "scheduler.h"
#include "defines.h"
#include "unitsManager.h"
#include "unitsmanager.h"
#include "gundata.h"
#include <GeographicLib/Geodesic.hpp>
using namespace GeographicLib;
@@ -49,6 +50,10 @@ void GroundUnit::setState(unsigned char newState)
setTargetPosition(Coords(NULL));
break;
}
case State::SIMULATE_FIRE_FIGHT: {
setTargetPosition(Coords(NULL));
break;
}
default:
break;
}
@@ -70,12 +75,16 @@ void GroundUnit::setState(unsigned char newState)
resetActiveDestination();
break;
}
case State::SIMULATE_FIRE_FIGHT: {
clearActivePath();
resetActiveDestination();
break;
}
default:
break;
}
if (newState != state)
resetTask();
resetTask();
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
state = newState;
@@ -122,8 +131,42 @@ void GroundUnit::AIloop()
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 1000}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
}
case State::SIMULATE_FIRE_FIGHT: {
setTask("Simulating fire fight");
if (!getHasTask() || ((double)(rand()) / (double)(RAND_MAX)) < 0.01) {
double dist;
double bearing1;
double bearing2;
Geodesic::WGS84().Inverse(position.lat, position.lng, targetPosition.lat, targetPosition.lng, dist, bearing1, bearing2);
double r = 5; /* m */
/* Default gun values */
double barrelHeight = 1.0; /* m */
double muzzleVelocity = 860; /* m/s */
if (gunData.find(name) != gunData.end()) {
barrelHeight = gunData[name].barrelHeight;
muzzleVelocity = gunData[name].muzzleVelocity;
}
double barrelElevation = r * (9.81 * dist / (2 * muzzleVelocity * muzzleVelocity) - barrelHeight / dist); /* m */
double lat = 0;
double lng = 0;
double randomBearing = bearing1 + (((double)(rand()) / (double)(RAND_MAX) - 0.5) * 2) * 45;
Geodesic::WGS84().Direct(position.lat, position.lng, randomBearing, r, lat, lng);
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << lat << ", lng = " << lng << ", alt = " << barrelElevation + barrelHeight << ", radius = 0.001}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -161,4 +204,4 @@ void GroundUnit::setFollowRoads(bool newFollowRoads, bool force)
Unit::setFollowRoads(newFollowRoads, force);
resetActiveDestination(); /* Reset active destination to apply option*/
}
}
}

View File

@@ -49,6 +49,10 @@ void NavyUnit::setState(unsigned char newState)
setTargetPosition(Coords(NULL));
break;
}
case State::SIMULATE_FIRE_FIGHT: {
setTargetPosition(Coords(NULL));
break;
}
default:
break;
}
@@ -68,6 +72,13 @@ void NavyUnit::setState(unsigned char newState)
case State::FIRE_AT_AREA: {
clearActivePath();
resetActiveDestination();
resetTask();
break;
}
case State::SIMULATE_FIRE_FIGHT: {
clearActivePath();
resetActiveDestination();
resetTask();
break;
}
default:
@@ -118,8 +129,23 @@ void NavyUnit::AIloop()
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 1000}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
}
case State::SIMULATE_FIRE_FIGHT: {
setTask("Simulating fire fight");
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 1}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}

View File

@@ -61,6 +61,7 @@ void Scheduler::execute(lua_State* L)
load = command->getLoad();
commands.remove(command);
executedCommandsHashes.push_back(command->getHash());
command->executeCallback(); /* Execute the command callback (this is a lambda function that can be used to execute a function when the command is run) */
delete command;
return;
}
@@ -561,6 +562,18 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
unit->setTargetPosition(loc);
log(username + " tasked unit " + unit->getName() + " to fire at area", true);
}
else if (key.compare("simulateFireFight") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setState(State::SIMULATE_FIRE_FIGHT);
unit->setTargetPosition(loc);
log(username + " tasked unit " + unit->getName() + " to simulate a fire fight", true);
}
else if (key.compare("setCommandModeOptions") == 0) {
setCommandModeOptions(value);
log(username + " updated the Command Mode Options", true);

View File

@@ -146,8 +146,10 @@ void Unit::runAILoop() {
/* If the unit is alive, controlled, is the leader of the group and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
if (getAlive() && getControlled() && !getHuman() && getIsLeader()) {
if (checkTaskFailed() && state != State::IDLE && state != State::LAND)
if (checkTaskFailed() && state != State::IDLE && state != State::LAND) {
log(unitName + " has no task, switching to IDLE state");
setState(State::IDLE);
}
AIloop();
}
@@ -397,7 +399,7 @@ void Unit::resetActiveDestination()
void Unit::resetTask()
{
Command* command = dynamic_cast<Command*>(new ResetTask(groupName));
Command* command = dynamic_cast<Command*>(new ResetTask(groupName, [this]() { this->setHasTaskAssigned(false); }));
scheduler->appendCommand(command);
setHasTask(false);
resetTaskFailedCounter();
@@ -660,7 +662,7 @@ void Unit::goToDestination(string enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType() ? "GS" : "CAS", getDesiredAltitude(), getDesiredAltitudeType() ? "AGL" : "ASL", enrouteTask, getCategory()));
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType() ? "GS" : "CAS", getDesiredAltitude(), getDesiredAltitudeType() ? "AGL" : "ASL", enrouteTask, getCategory(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -732,7 +734,7 @@ bool Unit::checkTaskFailed()
return false;
else {
if (taskCheckCounter > 0)
taskCheckCounter--;
taskCheckCounter -= hasTaskAssigned;
return taskCheckCounter == 0;
}
}
@@ -741,6 +743,14 @@ void Unit::resetTaskFailedCounter() {
taskCheckCounter = TASK_CHECK_INIT_VALUE;
}
void Unit::setHasTaskAssigned(bool newHasTaskAssigned) {
hasTaskAssigned = newHasTaskAssigned;
if (hasTaskAssigned)
log(unitName + " was assigned a new task");
else
log(unitName + " no task assigned");
}
void Unit::triggerUpdate(unsigned char datumIndex) {
updateTimeMap[datumIndex] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}