2019-01-02 01:47:08 -08:00
|
|
|
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
2014-01-18 03:50:57 -08:00
|
|
|
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
|
|
|
|
2013-11-05 13:57:55 -08:00
|
|
|
#include "Sensors.h"
|
|
|
|
#include "Body.h"
|
|
|
|
#include "Game.h"
|
|
|
|
#include "Pi.h"
|
|
|
|
#include "Ship.h"
|
|
|
|
#include "Space.h"
|
|
|
|
#include "Player.h"
|
|
|
|
#include "HudTrail.h"
|
|
|
|
|
|
|
|
Sensors::RadarContact::RadarContact()
|
|
|
|
: body(0)
|
|
|
|
, trail(0)
|
|
|
|
, distance(0.0)
|
|
|
|
, iff(IFF_UNKNOWN)
|
|
|
|
, fresh(true) {
|
|
|
|
}
|
|
|
|
|
|
|
|
Sensors::RadarContact::RadarContact(Body *b)
|
|
|
|
: body(b)
|
|
|
|
, trail(0)
|
|
|
|
, distance(0.0)
|
|
|
|
, iff(IFF_UNKNOWN)
|
|
|
|
, fresh(true) {
|
|
|
|
}
|
|
|
|
|
|
|
|
Sensors::RadarContact::~RadarContact() {
|
|
|
|
body = 0;
|
|
|
|
delete trail;
|
|
|
|
}
|
|
|
|
|
|
|
|
Color Sensors::IFFColor(IFF iff)
|
|
|
|
{
|
|
|
|
switch (iff)
|
|
|
|
{
|
2014-02-03 13:00:23 -08:00
|
|
|
case IFF_NEUTRAL: return Color::BLUE;
|
|
|
|
case IFF_ALLY: return Color::GREEN;
|
|
|
|
case IFF_HOSTILE: return Color::RED;
|
2013-11-05 13:57:55 -08:00
|
|
|
case IFF_UNKNOWN:
|
|
|
|
default:
|
2014-02-03 13:00:23 -08:00
|
|
|
return Color::GRAY;
|
2013-11-05 13:57:55 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sensors::ContactDistanceSort(const RadarContact &a, const RadarContact &b)
|
|
|
|
{
|
|
|
|
return a.distance < b.distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sensors::Sensors(Ship *owner)
|
|
|
|
{
|
|
|
|
m_owner = owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sensors::ChooseTarget(TargetingCriteria crit)
|
|
|
|
{
|
2015-03-21 16:18:39 -07:00
|
|
|
PROFILE_SCOPED();
|
2013-11-05 13:57:55 -08:00
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
m_radarContacts.sort(ContactDistanceSort);
|
|
|
|
|
|
|
|
for (auto it = m_radarContacts.begin(); it != m_radarContacts.end(); ++it) {
|
|
|
|
//match object type
|
|
|
|
//match iff
|
|
|
|
if (it->body->IsType(Object::SHIP)) {
|
|
|
|
//if (it->iff != IFF_HOSTILE) continue;
|
|
|
|
//should move the target to ship after all (from PlayerShipController)
|
|
|
|
//targeting inputs stay in PSC
|
|
|
|
static_cast<Player*>(m_owner)->SetCombatTarget(it->body);
|
2014-01-18 03:41:19 -08:00
|
|
|
found = true;
|
2013-11-05 13:57:55 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sensors::IFF Sensors::CheckIFF(Body* other)
|
|
|
|
{
|
2015-03-21 16:18:39 -07:00
|
|
|
PROFILE_SCOPED();
|
2013-11-05 13:57:55 -08:00
|
|
|
//complicated relationship check goes here
|
|
|
|
if (other->IsType(Object::SHIP)) {
|
|
|
|
Uint8 rel = m_owner->GetRelations(other);
|
|
|
|
if (rel == 0) return IFF_HOSTILE;
|
|
|
|
else if (rel == 100) return IFF_ALLY;
|
|
|
|
return IFF_NEUTRAL;
|
|
|
|
} else {
|
|
|
|
return IFF_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sensors::Update(float time)
|
|
|
|
{
|
2015-03-21 16:18:39 -07:00
|
|
|
PROFILE_SCOPED();
|
2013-11-05 13:57:55 -08:00
|
|
|
if (m_owner != Pi::player) return;
|
|
|
|
|
|
|
|
PopulateStaticContacts(); //no need to do all the time
|
|
|
|
|
2016-09-30 10:07:30 -07:00
|
|
|
//Find nearby contacts, same range as radar scanner. It should use these
|
2013-11-05 13:57:55 -08:00
|
|
|
//contacts, worldview labels too.
|
|
|
|
Space::BodyNearList nearby;
|
|
|
|
Pi::game->GetSpace()->GetBodiesMaybeNear(m_owner, 100000.0f, nearby);
|
|
|
|
for (Space::BodyNearIterator i = nearby.begin(); i != nearby.end(); ++i) {
|
|
|
|
if ((*i) == m_owner || !(*i)->IsType(Object::SHIP)) continue;
|
|
|
|
if ((*i)->IsDead()) continue;
|
|
|
|
|
|
|
|
auto cit = m_radarContacts.begin();
|
|
|
|
while (cit != m_radarContacts.end()) {
|
|
|
|
if (cit->body == (*i)) break;
|
|
|
|
++cit;
|
|
|
|
}
|
|
|
|
|
|
|
|
//create new contact or refresh old
|
|
|
|
if (cit == m_radarContacts.end()) {
|
|
|
|
m_radarContacts.push_back(RadarContact());
|
|
|
|
RadarContact &rc = m_radarContacts.back();
|
|
|
|
rc.body = (*i);
|
|
|
|
rc.iff = CheckIFF(rc.body);
|
|
|
|
rc.trail = new HudTrail(rc.body, IFFColor(rc.iff));
|
|
|
|
} else {
|
|
|
|
cit->fresh = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//update contacts and delete stale ones
|
|
|
|
auto it = m_radarContacts.begin();
|
|
|
|
while (it != m_radarContacts.end()) {
|
|
|
|
if (!it->fresh) {
|
|
|
|
m_radarContacts.erase(it++);
|
|
|
|
} else {
|
2014-05-10 14:01:33 -07:00
|
|
|
const Ship* ship =dynamic_cast<Ship*>(it->body);
|
|
|
|
if (ship && Ship::FLYING==ship->GetFlightState()) {
|
2014-05-09 13:56:52 -07:00
|
|
|
it->distance = m_owner->GetPositionRelTo(it->body).Length();
|
|
|
|
it->trail->Update(time);
|
|
|
|
} else {
|
|
|
|
it->trail->Reset(nullptr);
|
|
|
|
}
|
2013-11-05 13:57:55 -08:00
|
|
|
it->fresh = false;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sensors::UpdateIFF(Body *b)
|
|
|
|
{
|
2015-03-21 16:18:39 -07:00
|
|
|
PROFILE_SCOPED();
|
2013-11-05 13:57:55 -08:00
|
|
|
for (auto it = m_radarContacts.begin(); it != m_radarContacts.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it->body == b) {
|
|
|
|
it->iff = CheckIFF(b);
|
|
|
|
it->trail->SetColor(IFFColor(it->iff));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-07 13:01:41 -08:00
|
|
|
void Sensors::ResetTrails()
|
|
|
|
{
|
2015-03-21 16:18:39 -07:00
|
|
|
PROFILE_SCOPED();
|
2013-11-07 13:01:41 -08:00
|
|
|
for (auto it = m_radarContacts.begin(); it != m_radarContacts.end(); ++it)
|
2013-11-11 09:45:53 -08:00
|
|
|
it->trail->Reset(Pi::player->GetFrame());
|
2013-11-07 13:01:41 -08:00
|
|
|
}
|
|
|
|
|
2013-11-05 13:57:55 -08:00
|
|
|
void Sensors::PopulateStaticContacts()
|
|
|
|
{
|
2015-03-21 16:18:39 -07:00
|
|
|
PROFILE_SCOPED();
|
2013-11-05 13:57:55 -08:00
|
|
|
m_staticContacts.clear();
|
|
|
|
|
2014-02-22 08:40:25 -08:00
|
|
|
for (Body* b : Pi::game->GetSpace()->GetBodies()) {
|
|
|
|
switch (b->GetType())
|
2013-11-05 13:57:55 -08:00
|
|
|
{
|
|
|
|
case Object::STAR:
|
|
|
|
case Object::PLANET:
|
|
|
|
case Object::CITYONPLANET:
|
|
|
|
case Object::SPACESTATION:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
m_staticContacts.push_back(RadarContact(b));
|
|
|
|
RadarContact &rc = m_staticContacts.back();
|
|
|
|
rc.fresh = true;
|
|
|
|
}
|
|
|
|
}
|