mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added effect of vertical velocity and of scatter and intensity
This commit is contained in:
parent
c0f3f3a40a
commit
11a5fec195
@ -189,6 +189,8 @@ export enum DataIndexes {
|
||||
hasTask,
|
||||
position,
|
||||
speed,
|
||||
horizontalVelocity,
|
||||
verticalVelocity,
|
||||
heading,
|
||||
isActiveTanker,
|
||||
isActiveAWACS,
|
||||
|
||||
@ -152,6 +152,8 @@ export interface UnitData {
|
||||
hasTask: boolean;
|
||||
position: LatLng;
|
||||
speed: number;
|
||||
horizontalVelocity: number;
|
||||
verticalVelocity: number;
|
||||
heading: number;
|
||||
isActiveTanker: boolean;
|
||||
isActiveAWACS: boolean;
|
||||
|
||||
@ -34,6 +34,8 @@ export class Unit extends CustomMarker {
|
||||
#hasTask: boolean = false;
|
||||
#position: LatLng = new LatLng(0, 0, 0);
|
||||
#speed: number = 0;
|
||||
#horizontalVelocity: number = 0;
|
||||
#verticalVelocity: number = 0;
|
||||
#heading: number = 0;
|
||||
#isActiveTanker: boolean = false;
|
||||
#isActiveAWACS: boolean = false;
|
||||
@ -111,6 +113,8 @@ export class Unit extends CustomMarker {
|
||||
getHasTask() { return this.#hasTask };
|
||||
getPosition() { return this.#position };
|
||||
getSpeed() { return this.#speed };
|
||||
getHorizontalVelocity() { return this.#horizontalVelocity };
|
||||
getVerticalVelocity() { return this.#verticalVelocity };
|
||||
getHeading() { return this.#heading };
|
||||
getIsActiveTanker() { return this.#isActiveTanker };
|
||||
getIsActiveAWACS() { return this.#isActiveAWACS };
|
||||
@ -224,6 +228,8 @@ export class Unit extends CustomMarker {
|
||||
case DataIndexes.hasTask: this.#hasTask = dataExtractor.extractBool(); break;
|
||||
case DataIndexes.position: this.#position = dataExtractor.extractLatLng(); updateMarker = true; break;
|
||||
case DataIndexes.speed: this.#speed = dataExtractor.extractFloat64(); updateMarker = true; break;
|
||||
case DataIndexes.horizontalVelocity: this.#horizontalVelocity = dataExtractor.extractFloat64(); break;
|
||||
case DataIndexes.verticalVelocity: this.#verticalVelocity = dataExtractor.extractFloat64(); break;
|
||||
case DataIndexes.heading: this.#heading = dataExtractor.extractFloat64(); updateMarker = true; break;
|
||||
case DataIndexes.isActiveTanker: this.#isActiveTanker = dataExtractor.extractBool(); break;
|
||||
case DataIndexes.isActiveAWACS: this.#isActiveAWACS = dataExtractor.extractBool(); break;
|
||||
@ -290,6 +296,8 @@ export class Unit extends CustomMarker {
|
||||
hasTask: this.#hasTask,
|
||||
position: this.#position,
|
||||
speed: this.#speed,
|
||||
horizontalVelocity: this.#horizontalVelocity,
|
||||
verticalVelocity: this.#verticalVelocity,
|
||||
heading: this.#heading,
|
||||
isActiveTanker: this.#isActiveTanker,
|
||||
isActiveAWACS: this.#isActiveAWACS,
|
||||
|
||||
@ -888,6 +888,7 @@ function Olympus.setUnitsData(arg, time)
|
||||
local lat, lng, alt = coord.LOtoLL(unit:getPoint())
|
||||
local position = unit:getPosition()
|
||||
local heading = math.atan2( position.x.z, position.x.x )
|
||||
local velocity = unit:getVelocity();
|
||||
|
||||
-- Fill the data table
|
||||
table["name"] = unit:getTypeName()
|
||||
@ -896,7 +897,9 @@ function Olympus.setUnitsData(arg, time)
|
||||
table["position"]["lat"] = lat
|
||||
table["position"]["lng"] = lng
|
||||
table["position"]["alt"] = alt
|
||||
table["speed"] = mist.vec.mag(unit:getVelocity())
|
||||
table["speed"] = mist.vec.mag(velocity)
|
||||
table["horizontalVelocity"] = math.sqrt(velocity.x * velocity.x + velocity.z * velocity.z)
|
||||
table["verticalVelocity"] = velocity.y
|
||||
table["heading"] = heading
|
||||
table["isAlive"] = unit:isExist() and unit:isActive() and unit:getLife() >= 1
|
||||
|
||||
|
||||
@ -19,6 +19,8 @@ namespace DataIndex {
|
||||
hasTask,
|
||||
position,
|
||||
speed,
|
||||
horizontalVelocity,
|
||||
verticalVelocity,
|
||||
heading,
|
||||
isActiveTanker,
|
||||
isActiveAWACS,
|
||||
|
||||
@ -55,6 +55,8 @@ public:
|
||||
bool checkTaskFailed();
|
||||
void resetTaskFailedCounter();
|
||||
void setHasTaskAssigned(bool newHasTaskAssigned);
|
||||
void setEnableTaskCheckFailed(bool newEnableTaskCheckFailed) { enableTaskFailedCheck = newEnableTaskCheckFailed; }
|
||||
bool getEnableTaskCheckFailed() { return enableTaskFailedCheck; }
|
||||
|
||||
void triggerUpdate(unsigned char datumIndex);
|
||||
|
||||
@ -73,9 +75,11 @@ public:
|
||||
virtual void setGroupName(string newValue) { updateValue(groupName, newValue, DataIndex::groupName); }
|
||||
virtual void setState(unsigned char newValue) { updateValue(state, newValue, DataIndex::state); };
|
||||
virtual void setTask(string newValue) { updateValue(task, newValue, DataIndex::task); }
|
||||
virtual void setHasTask(bool newValue) { updateValue(hasTask, newValue, DataIndex::hasTask); }
|
||||
virtual void setHasTask(bool newValue);
|
||||
virtual void setPosition(Coords newValue) { updateValue(position, newValue, DataIndex::position); }
|
||||
virtual void setSpeed(double newValue) { updateValue(speed, newValue, DataIndex::speed); }
|
||||
virtual void setHorizontalVelocity(double newValue) { updateValue(horizontalVelocity, newValue, DataIndex::horizontalVelocity); }
|
||||
virtual void setVerticalVelocity(double newValue) { updateValue(verticalVelocity, newValue, DataIndex::verticalVelocity); }
|
||||
virtual void setHeading(double newValue) { updateValue(heading, newValue, DataIndex::heading); }
|
||||
virtual void setIsActiveTanker(bool newValue);
|
||||
virtual void setIsActiveAWACS(bool newValue);
|
||||
@ -119,6 +123,8 @@ public:
|
||||
virtual bool getHasTask() { return hasTask; }
|
||||
virtual Coords getPosition() { return position; }
|
||||
virtual double getSpeed() { return speed; }
|
||||
virtual double getHorizontalVelocity() { return horizontalVelocity; }
|
||||
virtual double getVerticalVelocity() { return verticalVelocity; }
|
||||
virtual double getHeading() { return heading; }
|
||||
virtual bool getIsActiveTanker() { return isActiveTanker; }
|
||||
virtual bool getIsActiveAWACS() { return isActiveAWACS; }
|
||||
@ -164,6 +170,8 @@ protected:
|
||||
bool hasTask = false;
|
||||
Coords position = Coords(NULL);
|
||||
double speed = NULL;
|
||||
double horizontalVelocity = NULL;
|
||||
double verticalVelocity = NULL;
|
||||
double heading = NULL;
|
||||
bool isActiveTanker = false;
|
||||
bool isActiveAWACS = false;
|
||||
@ -200,6 +208,7 @@ protected:
|
||||
double initialFuel = 0;
|
||||
map<unsigned char, unsigned long long> updateTimeMap;
|
||||
unsigned long long lastLoopTime = 0;
|
||||
bool enableTaskFailedCheck = false;
|
||||
|
||||
/********** Private methods **********/
|
||||
virtual void AIloop() = 0;
|
||||
|
||||
@ -80,15 +80,18 @@ void AirUnit::setState(unsigned char newState)
|
||||
/************ Perform any action required when ENTERING a state ************/
|
||||
switch (newState) {
|
||||
case State::IDLE: {
|
||||
setEnableTaskCheckFailed(false);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::REACH_DESTINATION: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::ATTACK: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
if (isTargetAlive()) {
|
||||
Unit* target = unitsManager->getUnit(targetID);
|
||||
Coords targetPosition = Coords(target->getPosition().lat, target->getPosition().lng, 0);
|
||||
@ -99,36 +102,43 @@ void AirUnit::setState(unsigned char newState)
|
||||
break;
|
||||
}
|
||||
case State::FOLLOW: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::LAND: {
|
||||
setEnableTaskCheckFailed(false);
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::REFUEL: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
initialFuel = fuel;
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::BOMB_POINT: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::CARPET_BOMB: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::BOMB_BUILDING: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::LAND_AT_POINT: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -13,6 +13,9 @@ extern Scheduler* scheduler;
|
||||
extern UnitsManager* unitsManager;
|
||||
json::value GroundUnit::database = json::value();
|
||||
|
||||
#define RANDOM_ZERO_TO_ONE (double)(rand()) / (double)(RAND_MAX)
|
||||
#define RANDOM_MINUS_ONE_TO_ONE (((double)(rand()) / (double)(RAND_MAX) - 0.5) * 2)
|
||||
|
||||
void GroundUnit::loadDatabase(string path) {
|
||||
char* buf = nullptr;
|
||||
size_t sz = 0;
|
||||
@ -89,30 +92,36 @@ void GroundUnit::setState(unsigned char newState)
|
||||
/************ Perform any action required when ENTERING a state ************/
|
||||
switch (newState) {
|
||||
case State::IDLE: {
|
||||
setEnableTaskCheckFailed(false);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::REACH_DESTINATION: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::FIRE_AT_AREA: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::SIMULATE_FIRE_FIGHT: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::SCENIC_AAA: {
|
||||
setEnableTaskCheckFailed(false);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::MISS_ON_PURPOSE: {
|
||||
setEnableTaskCheckFailed(false);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
@ -214,7 +223,7 @@ void GroundUnit::AIloop()
|
||||
}
|
||||
|
||||
if (internalCounter == 0)
|
||||
internalCounter = 20 / 0.05; // TODO make defined constant
|
||||
internalCounter = 20 / FRAMERATE_TIME_INTERVAL;
|
||||
internalCounter--;
|
||||
|
||||
break;
|
||||
@ -247,7 +256,7 @@ void GroundUnit::AIloop()
|
||||
}
|
||||
|
||||
if (internalCounter == 0)
|
||||
internalCounter = 20 / 0.05;
|
||||
internalCounter = 20 / FRAMERATE_TIME_INTERVAL;
|
||||
internalCounter--;
|
||||
|
||||
break;
|
||||
@ -261,48 +270,58 @@ void GroundUnit::AIloop()
|
||||
unsigned char targetCoalition = getOperateAs() == 2 ? 1 : 2;
|
||||
Unit* target = unitsManager->getClosestUnit(this, targetCoalition, {"Aircraft", "Helicopter"}, distance);
|
||||
|
||||
/* Default gun values */
|
||||
double barrelHeight = 1.0; /* m */
|
||||
double muzzleVelocity = 860; /* m/s */
|
||||
double aimTime = 10; /* s */
|
||||
unsigned int shotsToFire = 10;
|
||||
double shotsBaseInterval = 15; /* s */
|
||||
double shotsBaseScatter = 5; /* degs */
|
||||
double engagementRange = 10000; /* m */
|
||||
|
||||
if (database.has_object_field(to_wstring(name))) {
|
||||
json::value databaseEntry = database[to_wstring(name)];
|
||||
if (databaseEntry.has_number_field(L"barrelHeight"))
|
||||
barrelHeight = databaseEntry[L"barrelHeight"].as_number().to_double();
|
||||
if (databaseEntry.has_number_field(L"muzzleVelocity"))
|
||||
muzzleVelocity = databaseEntry[L"muzzleVelocity"].as_number().to_double();
|
||||
if (databaseEntry.has_number_field(L"aimTime"))
|
||||
aimTime = databaseEntry[L"aimTime"].as_number().to_double();
|
||||
if (databaseEntry.has_number_field(L"shotsToFire"))
|
||||
shotsToFire = databaseEntry[L"shotsToFire"].as_number().to_uint32();
|
||||
if (databaseEntry.has_number_field(L"engagementRange"))
|
||||
engagementRange = databaseEntry[L"engagementRange"].as_number().to_double();
|
||||
if (databaseEntry.has_number_field(L"shotsBaseInterval"))
|
||||
shotsBaseInterval = databaseEntry[L"shotsBaseInterval"].as_number().to_double();
|
||||
if (databaseEntry.has_number_field(L"shotsBaseScatter"))
|
||||
shotsBaseScatter = databaseEntry[L"shotsBaseScatter"].as_number().to_double();
|
||||
}
|
||||
|
||||
/* Only do if we have a valid target close enough for AAA */
|
||||
if (target != nullptr && distance < 10000 /* m */) {
|
||||
/* Default gun values */
|
||||
double barrelHeight = 1.0; /* m */
|
||||
double muzzleVelocity = 860; /* m/s */
|
||||
double aimTime = 10; /* s */
|
||||
unsigned int shotsToFire = 10;
|
||||
|
||||
if (database.has_object_field(to_wstring(name))) {
|
||||
json::value databaseEntry = database[to_wstring(name)];
|
||||
if (databaseEntry.has_number_field(L"barrelHeight"))
|
||||
barrelHeight = databaseEntry[L"barrelHeight"].as_number().to_double();
|
||||
if (databaseEntry.has_number_field(L"muzzleVelocity"))
|
||||
muzzleVelocity = databaseEntry[L"muzzleVelocity"].as_number().to_double();
|
||||
if (databaseEntry.has_number_field(L"aimTime"))
|
||||
aimTime = databaseEntry[L"aimTime"].as_number().to_double();
|
||||
if (databaseEntry.has_number_field(L"shotsToFire"))
|
||||
shotsToFire = databaseEntry[L"shotsToFire"].as_number().to_uint32();
|
||||
}
|
||||
|
||||
/* Approximate the flight time */
|
||||
if (muzzleVelocity != 0)
|
||||
aimTime += distance / muzzleVelocity;
|
||||
|
||||
internalCounter = (aimTime + 2) / 0.05; // TODO fix me you fucking monster
|
||||
internalCounter = (aimTime + (3 - shotsIntensity) * shotsBaseInterval + 2) / FRAMERATE_TIME_INTERVAL;
|
||||
|
||||
/* Compute where the target will be in aimTime seconds. We don't consider vertical velocity atm, since after all we are not really tring to hit */
|
||||
double aimDistance = target->getSpeed() * aimTime;
|
||||
/* Compute where the target will be in aimTime seconds. */
|
||||
double aimDistance = target->getHorizontalVelocity() * aimTime;
|
||||
double aimLat = 0;
|
||||
double aimLng = 0;
|
||||
Geodesic::WGS84().Direct(target->getPosition().lat, target->getPosition().lng, target->getHeading() * 57.29577, aimDistance, aimLat, aimLng); /* TODO make util function */
|
||||
double aimAlt = target->getPosition().alt + target->getVerticalVelocity() * aimTime;
|
||||
|
||||
/* Compute distance to the aim point */ // TODO: why am I here?
|
||||
double dist;
|
||||
double bearing1;
|
||||
double bearing2;
|
||||
Geodesic::WGS84().Inverse(position.lat, position.lng, aimLat, aimLng, dist, bearing1, bearing2);
|
||||
/* Compute a random scattering depending on the distance and the selected shots scatter */
|
||||
double scatterDistance = distance * tan(shotsBaseScatter * (3 - shotsScatter) / 57.29577) * RANDOM_MINUS_ONE_TO_ONE;
|
||||
double scatterAngle = 180 * RANDOM_MINUS_ONE_TO_ONE;
|
||||
Geodesic::WGS84().Direct(aimLat, aimLng, scatterAngle, scatterDistance, aimLat, aimLng); /* TODO make util function */
|
||||
aimAlt = aimAlt + distance * tan(shotsBaseScatter * (3 - shotsScatter) / 57.29577) * RANDOM_MINUS_ONE_TO_ONE;
|
||||
|
||||
/* Send the command */
|
||||
std::ostringstream taskSS;
|
||||
taskSS.precision(10);
|
||||
taskSS << "{id = 'FireAtPoint', lat = " << aimLat << ", lng = " << aimLng << ", alt = " << target->getPosition().alt << ", radius = 0.001, expendQty = " << shotsToFire << " }";
|
||||
taskSS << "{id = 'FireAtPoint', lat = " << aimLat << ", lng = " << aimLng << ", alt = " << aimAlt << ", radius = 0.001, expendQty = " << shotsToFire << " }";
|
||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||
scheduler->appendCommand(command);
|
||||
setHasTask(true);
|
||||
@ -315,8 +334,16 @@ void GroundUnit::AIloop()
|
||||
}
|
||||
}
|
||||
|
||||
if (internalCounter == 0)
|
||||
internalCounter = 5 / 0.05;
|
||||
/* If no valid target was detected */
|
||||
if (internalCounter == 0) {
|
||||
double alertnessTimeConstant = 10; /* s */
|
||||
if (database.has_object_field(to_wstring(name))) {
|
||||
json::value databaseEntry = database[to_wstring(name)];
|
||||
if (databaseEntry.has_number_field(L"alertnessTimeConstant"))
|
||||
alertnessTimeConstant = databaseEntry[L"alertnessTimeConstant"].as_number().to_double();
|
||||
}
|
||||
internalCounter = (5 + RANDOM_ZERO_TO_ONE * alertnessTimeConstant) / FRAMERATE_TIME_INTERVAL;
|
||||
}
|
||||
internalCounter--;
|
||||
|
||||
break;
|
||||
|
||||
@ -81,21 +81,25 @@ void NavyUnit::setState(unsigned char newState)
|
||||
/************ Perform any action required when ENTERING a state ************/
|
||||
switch (newState) {
|
||||
case State::IDLE: {
|
||||
setEnableTaskCheckFailed(false);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::REACH_DESTINATION: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::FIRE_AT_AREA: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
resetTask();
|
||||
break;
|
||||
}
|
||||
case State::SIMULATE_FIRE_FIGHT: {
|
||||
setEnableTaskCheckFailed(true);
|
||||
clearActivePath();
|
||||
resetActiveDestination();
|
||||
resetTask();
|
||||
|
||||
@ -69,6 +69,12 @@ void Unit::update(json::value json, double dt)
|
||||
if (json.has_number_field(L"speed"))
|
||||
setSpeed(json[L"speed"].as_number().to_double());
|
||||
|
||||
if (json.has_number_field(L"horizontalVelocity"))
|
||||
setHorizontalVelocity(json[L"horizontalVelocity"].as_number().to_double());
|
||||
|
||||
if (json.has_number_field(L"verticalVelocity"))
|
||||
setVerticalVelocity(json[L"verticalVelocity"].as_number().to_double());
|
||||
|
||||
if (json.has_boolean_field(L"isAlive"))
|
||||
setAlive(json[L"isAlive"].as_bool());
|
||||
|
||||
@ -146,7 +152,7 @@ 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 (getEnableTaskCheckFailed() && checkTaskFailed()) {
|
||||
log(unitName + " has no task, switching to IDLE state");
|
||||
setState(State::IDLE);
|
||||
}
|
||||
@ -249,6 +255,8 @@ void Unit::getData(stringstream& ss, unsigned long long time)
|
||||
case DataIndex::hasTask: appendNumeric(ss, datumIndex, hasTask); break;
|
||||
case DataIndex::position: appendNumeric(ss, datumIndex, position); break;
|
||||
case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break;
|
||||
case DataIndex::horizontalVelocity: appendNumeric(ss, datumIndex, horizontalVelocity); break;
|
||||
case DataIndex::verticalVelocity: appendNumeric(ss, datumIndex, verticalVelocity); break;
|
||||
case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break;
|
||||
case DataIndex::isActiveTanker: appendNumeric(ss, datumIndex, isActiveTanker); break;
|
||||
case DataIndex::isActiveAWACS: appendNumeric(ss, datumIndex, isActiveAWACS); break;
|
||||
@ -734,6 +742,10 @@ bool Unit::updateActivePath(bool looping)
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::setHasTask(bool newValue) {
|
||||
updateValue(hasTask, newValue, DataIndex::hasTask);
|
||||
}
|
||||
|
||||
bool Unit::checkTaskFailed()
|
||||
{
|
||||
if (getHasTask())
|
||||
|
||||
@ -172,19 +172,20 @@ Unit* UnitsManager::getClosestUnit(Unit* unit, unsigned char coalition, vector<s
|
||||
double bearing1;
|
||||
double bearing2;
|
||||
Geodesic::WGS84().Inverse(unit->getPosition().lat, unit->getPosition().lng, p.second->getPosition().lat, p.second->getPosition().lng, dist, bearing1, bearing2);
|
||||
double altDelta = unit->getPosition().alt - p.second->getPosition().alt;
|
||||
|
||||
/* If the closest unit has not been assigned yet, assign it to this unit */
|
||||
if (closestUnit == nullptr)
|
||||
{
|
||||
closestUnit = p.second;
|
||||
distance = dist;
|
||||
distance = sqrt(dist * dist + altDelta * altDelta);
|
||||
|
||||
}
|
||||
else {
|
||||
/* Check if the unit is closer than the one already selected */
|
||||
if (dist < distance) {
|
||||
closestUnit = p.second;
|
||||
distance = dist;
|
||||
distance = sqrt(dist * dist + altDelta * altDelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user