diff --git a/src/core/src/airunit.cpp b/src/core/src/airunit.cpp index 8aa3dabf..459162f2 100644 --- a/src/core/src/airunit.cpp +++ b/src/core/src/airunit.cpp @@ -40,6 +40,8 @@ void AirUnit::setDefaults(bool force) void AirUnit::setState(unsigned char newState) { + Coords currentTargetPosition = getTargetPosition(); + /************ Perform any action required when LEAVING a state ************/ if (newState != state) { switch (state) { @@ -119,19 +121,10 @@ void AirUnit::setState(unsigned char newState) resetActiveDestination(); break; } - case State::BOMB_POINT: { - setEnableTaskCheckFailed(true); - clearActivePath(); - resetActiveDestination(); - break; - } - case State::CARPET_BOMB: { - setEnableTaskCheckFailed(true); - clearActivePath(); - resetActiveDestination(); - break; - } + case State::BOMB_POINT: + case State::CARPET_BOMB: case State::BOMB_BUILDING: { + setTargetPosition(currentTargetPosition); setEnableTaskCheckFailed(true); clearActivePath(); resetActiveDestination(); @@ -159,6 +152,8 @@ void AirUnit::setState(unsigned char newState) void AirUnit::AIloop() { + srand(static_cast(time(NULL)) + ID); + /* State machine */ switch (state) { case State::IDLE: { diff --git a/src/core/src/groundunit.cpp b/src/core/src/groundunit.cpp index 88a7ca63..dff31bf9 100644 --- a/src/core/src/groundunit.cpp +++ b/src/core/src/groundunit.cpp @@ -53,6 +53,8 @@ void GroundUnit::setDefaults(bool force) void GroundUnit::setState(unsigned char newState) { + Coords currentTargetPosition = getTargetPosition(); + /************ Perform any action required when LEAVING a state ************/ if (newState != state) { switch (state) { @@ -66,18 +68,9 @@ void GroundUnit::setState(unsigned char newState) setTargetID(NULL); break; } - case State::FIRE_AT_AREA: { - setTargetPosition(Coords(NULL)); - break; - } - case State::SIMULATE_FIRE_FIGHT: { - setTargetPosition(Coords(NULL)); - break; - } - case State::SCENIC_AAA: { - setTargetPosition(Coords(NULL)); - break; - } + case State::FIRE_AT_AREA: + case State::SIMULATE_FIRE_FIGHT: + case State::SCENIC_AAA: case State::MISS_ON_PURPOSE: { setTargetPosition(Coords(NULL)); break; @@ -107,13 +100,15 @@ void GroundUnit::setState(unsigned char newState) break; } case State::FIRE_AT_AREA: { + setTargetPosition(currentTargetPosition); setEnableTaskCheckFailed(true); clearActivePath(); resetActiveDestination(); break; } case State::SIMULATE_FIRE_FIGHT: { - setEnableTaskCheckFailed(true); + setTargetPosition(currentTargetPosition); + setEnableTaskCheckFailed(false); clearActivePath(); resetActiveDestination(); break; @@ -147,6 +142,8 @@ void GroundUnit::setState(unsigned char newState) void GroundUnit::AIloop() { + srand(static_cast(time(NULL)) + ID); + switch (state) { case State::IDLE: { setTask("Idle"); @@ -219,7 +216,7 @@ void GroundUnit::AIloop() case State::SIMULATE_FIRE_FIGHT: { setTask("Simulating fire fight"); - if (internalCounter == 0 && targetPosition != Coords(NULL) && scheduler->getLoad() == 0) { + if (internalCounter == 0 && targetPosition != Coords(NULL) && scheduler->getLoad() < 30) { /* Get the distance and bearing to the target */ Coords scatteredTargetPosition = targetPosition; double distance; @@ -232,10 +229,13 @@ void GroundUnit::AIloop() Geodesic::WGS84().Direct(scatteredTargetPosition.lat, scatteredTargetPosition.lng, bearing1 + 90, scatterDistance, scatteredTargetPosition.lat, scatteredTargetPosition.lng); /* Recover the data from the database */ + double aimTime = 2; /* s */ bool indirectFire = false; double shotsBaseInterval = 15; /* s */ if (database.has_object_field(to_wstring(name))) { json::value databaseEntry = database[to_wstring(name)]; + if (databaseEntry.has_number_field(L"aimTime")) + aimTime = databaseEntry[L"aimTime"].as_number().to_double(); if (databaseEntry.has_boolean_field(L"indirectFire")) indirectFire = databaseEntry[L"indirectFire"].as_bool(); if (databaseEntry.has_number_field(L"shotsBaseInterval")) @@ -259,7 +259,7 @@ void GroundUnit::AIloop() } /* Wait an amout of time depending on the shots intensity */ - internalCounter = static_cast(((ShotsIntensity::HIGH - shotsIntensity) * shotsBaseInterval + 2) / FRAMERATE_TIME_INTERVAL); + internalCounter = static_cast(((ShotsIntensity::HIGH - shotsIntensity) * shotsBaseInterval + aimTime) / FRAMERATE_TIME_INTERVAL); } if (targetPosition == Coords(NULL)) @@ -267,7 +267,7 @@ void GroundUnit::AIloop() /* Fallback if something went wrong */ if (internalCounter == 0) - internalCounter = static_cast(20 / FRAMERATE_TIME_INTERVAL); + internalCounter = static_cast(3 / FRAMERATE_TIME_INTERVAL); internalCounter--; break; @@ -276,12 +276,23 @@ void GroundUnit::AIloop() setTask("Scenic AAA"); /* Only perform scenic functions when the scheduler is "free" */ - if (((!getHasTask() && scheduler->getLoad() == 0) || internalCounter == 0)) { + if (((!getHasTask() && scheduler->getLoad() < 30) || internalCounter == 0)) { double distance = 0; unsigned char unitCoalition = coalition == 0 ? getOperateAs() : coalition; unsigned char targetCoalition = unitCoalition == 2 ? 1 : 2; Unit* target = unitsManager->getClosestUnit(this, targetCoalition, { "Aircraft", "Helicopter" }, distance); + /* Recover the data from the database */ + double aimTime = 2; /* s */ + double shotsBaseInterval = 15; /* s */ + if (database.has_object_field(to_wstring(name))) { + json::value databaseEntry = database[to_wstring(name)]; + if (databaseEntry.has_number_field(L"aimTime")) + aimTime = databaseEntry[L"aimTime"].as_number().to_double(); + if (databaseEntry.has_number_field(L"shotsBaseInterval")) + shotsBaseInterval = databaseEntry[L"shotsBaseInterval"].as_number().to_double(); + } + /* Only run if an enemy air unit is closer than 20km to avoid useless load */ if (target != nullptr && distance < 20000 /* m */) { double r = 15; /* m */ @@ -298,11 +309,14 @@ void GroundUnit::AIloop() Command* command = dynamic_cast(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); })); scheduler->appendCommand(command); setHasTask(true); + + /* Wait an amout of time depending on the shots intensity */ + internalCounter = static_cast(((ShotsIntensity::HIGH - shotsIntensity) * shotsBaseInterval + aimTime) / FRAMERATE_TIME_INTERVAL); } } if (internalCounter == 0) - internalCounter = static_cast(20 / FRAMERATE_TIME_INTERVAL); + internalCounter = static_cast(3 / FRAMERATE_TIME_INTERVAL); internalCounter--; break; @@ -321,7 +335,7 @@ void GroundUnit::AIloop() if (canAAA) { /* Only perform scenic functions when the scheduler is "free" */ /* Only run this when the internal counter reaches 0 to avoid excessive computations when no nearby target */ - if (scheduler->getLoad() == 0 && internalCounter == 0) { + if (scheduler->getLoad() < 30 && internalCounter == 0) { double distance = 0; unsigned char unitCoalition = coalition == 0 ? getOperateAs() : coalition; unsigned char targetCoalition = unitCoalition == 2 ? 1 : 2; diff --git a/src/core/src/navyunit.cpp b/src/core/src/navyunit.cpp index a9e2194f..c9d9d69f 100644 --- a/src/core/src/navyunit.cpp +++ b/src/core/src/navyunit.cpp @@ -50,6 +50,8 @@ void NavyUnit::setDefaults(bool force) void NavyUnit::setState(unsigned char newState) { + Coords currentTargetPosition = getTargetPosition(); + /************ Perform any action required when LEAVING a state ************/ if (newState != state) { switch (state) { @@ -63,11 +65,10 @@ void NavyUnit::setState(unsigned char newState) setTargetID(NULL); break; } - case State::FIRE_AT_AREA: { - setTargetPosition(Coords(NULL)); - break; - } - case State::SIMULATE_FIRE_FIGHT: { + case State::FIRE_AT_AREA: + case State::SIMULATE_FIRE_FIGHT: + case State::SCENIC_AAA: + case State::MISS_ON_PURPOSE: { setTargetPosition(Coords(NULL)); break; } @@ -96,13 +97,27 @@ void NavyUnit::setState(unsigned char newState) break; } case State::FIRE_AT_AREA: { + setTargetPosition(currentTargetPosition); setEnableTaskCheckFailed(true); clearActivePath(); resetActiveDestination(); break; } case State::SIMULATE_FIRE_FIGHT: { - setEnableTaskCheckFailed(true); + setTargetPosition(currentTargetPosition); + setEnableTaskCheckFailed(false); + clearActivePath(); + resetActiveDestination(); + break; + } + case State::SCENIC_AAA: { + setEnableTaskCheckFailed(false); + clearActivePath(); + resetActiveDestination(); + break; + } + case State::MISS_ON_PURPOSE: { + setEnableTaskCheckFailed(false); clearActivePath(); resetActiveDestination(); break; @@ -124,6 +139,8 @@ void NavyUnit::setState(unsigned char newState) void NavyUnit::AIloop() { + srand(static_cast(time(NULL)) + ID); + switch (state) { case State::IDLE: { setTask("Idle");