Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(npc): add a personality to make travel restrictions apply to mission npcs #9412

Merged
merged 11 commits into from
Dec 17, 2023
6 changes: 2 additions & 4 deletions source/AI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1694,10 +1694,9 @@ void AI::MoveIndependent(Ship &ship, Command &command) const
? origin->JumpNeighbors(ship.JumpNavigation().JumpRange()) : origin->Links();
if(jumps)
{
bool unrestricted = ship.GetPersonality().IsUnrestricted();
for(const System *link : links)
{
if(!unrestricted && gov->IsRestrictedFrom(*link))
if(ship.IsRestrictedFrom(*link))
{
systemWeights.push_back(0);
continue;
Expand Down Expand Up @@ -2766,9 +2765,8 @@ void AI::DoSurveillance(Ship &ship, Command &command, shared_ptr<Ship> &target)
{
const auto &links = ship.JumpNavigation().HasJumpDrive() ?
system->JumpNeighbors(ship.JumpNavigation().JumpRange()) : system->Links();
bool unrestricted = ship.GetPersonality().IsUnrestricted();
for(const System *link : links)
if(unrestricted || !gov->IsRestrictedFrom(*link))
if(!ship.IsRestrictedFrom(*link))
targetSystems.push_back(link);
}

Expand Down
14 changes: 8 additions & 6 deletions source/DistanceMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ bool DistanceMap::Edge::operator<(const Edge &other) const
// source system or the maximum count is reached.
void DistanceMap::Init(const Ship *ship)
{
if(!center)
if(!center || (ship && ship->IsRestrictedFrom(*center)))
return;

route[center] = Edge();
Expand Down Expand Up @@ -249,7 +249,8 @@ void DistanceMap::Init(const Ship *ship)
// the wormhole and both endpoint systems. (If this is a
// multi-stop wormhole, you may know about some paths that
// it takes but not others.)
if(ship && !object.GetPlanet()->IsAccessible(ship))
if(!ship || (!object.GetPlanet()->IsAccessible(ship) ||
ship->IsRestrictedFrom(*object.GetPlanet())))
Hurleveur marked this conversation as resolved.
Show resolved Hide resolved
continue;
if(player && !player->HasVisited(*object.GetPlanet()))
continue;
Expand All @@ -260,25 +261,26 @@ void DistanceMap::Init(const Ship *ship)
}

// Bail out if the maximum number of systems is reached.
if(hyperspaceFuel && !Propagate(top, false))
if(hyperspaceFuel && !Propagate(top, false, ship))
break;
if(jumpFuel && !Propagate(top, true))
if(jumpFuel && !Propagate(top, true, ship))
break;
}
}



// Add the given links to the map. Return false if an end condition is hit.
bool DistanceMap::Propagate(Edge edge, bool useJump)
bool DistanceMap::Propagate(Edge edge, bool useJump, const Ship *ship)
{
edge.fuel += (useJump ? jumpFuel : hyperspaceFuel);
for(const System *link : (useJump ? edge.next->JumpNeighbors(jumpRange) : edge.next->Links()))
{
// Find out whether we already have a better path to this system, and
// check whether this link can be traveled. If this route is being
// selected by the player, they are constrained to known routes.
if(HasBetter(*link, edge) || !CheckLink(*edge.next, *link, useJump))
if((ship && ship->IsRestrictedFrom (*link))
|| HasBetter(*link, edge) || !CheckLink(*edge.next, *link, useJump))
Hurleveur marked this conversation as resolved.
Show resolved Hide resolved
continue;

Add(*link, edge);
Expand Down
3 changes: 2 additions & 1 deletion source/DistanceMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ class DistanceMap {
// source system or the maximum count is reached.
void Init(const Ship *ship = nullptr);
// Add the given links to the map. Return false if an end condition is hit.
bool Propagate(Edge edge, bool useJump);
// If a ship is given account for its system restrictions.
bool Propagate(Edge edge, bool useJump, const Ship *ship = nullptr);
// Check if we already have a better path to the given system.
bool HasBetter(const System &to, const Edge &edge);
// Add the given path to the record.
Expand Down
8 changes: 3 additions & 5 deletions source/Fleet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,10 @@ void Fleet::Place(const System &system, list<shared_ptr<Ship>> &ships, bool carr
// Do the randomization to make a ship enter or be in the given system.
const System *Fleet::Enter(const System &system, Ship &ship, const System *source)
{
bool unrestricted = ship.GetPersonality().IsUnrestricted();
bool canEnter = (source != nullptr || unrestricted || any_of(system.Links().begin(), system.Links().end(),
bool canEnter = (source != nullptr || any_of(system.Links().begin(), system.Links().end(),
[&ship](const System *link) noexcept -> bool
{
return !ship.GetGovernment()->IsRestrictedFrom(*link);
return !ship.IsRestrictedFrom(*link);
}
));

Expand All @@ -443,9 +442,8 @@ const System *Fleet::Enter(const System &system, Ship &ship, const System *sourc
if(!source)
{
vector<const System *> validSystems;
const Government *gov = ship.GetGovernment();
for(const System *link : system.Links())
if(unrestricted || !gov->IsRestrictedFrom(*link))
if(!ship.IsRestrictedFrom(*link))
validSystems.emplace_back(link);
auto it = validSystems.cbegin();
advance(it, Random::Int(validSystems.size()));
Expand Down
9 changes: 9 additions & 0 deletions source/Personality.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace {
SECRETIVE,
RAMMING,
UNRESTRICTED,
RESTRICTED,
DECLOAKED,

// This must be last so it can be used for bounds checking.
Expand Down Expand Up @@ -103,6 +104,7 @@ namespace {
{"secretive", SECRETIVE},
{"ramming", RAMMING},
{"unrestricted", UNRESTRICTED},
{"restricted", RESTRICTED},
{"decloaked", DECLOAKED}
};

Expand Down Expand Up @@ -264,6 +266,13 @@ bool Personality::IsUnrestricted() const



bool Personality::IsRestricted() const
{
return flags.test(RESTRICTED);
}



bool Personality::IsCoward() const
{
return flags.test(COWARD);
Expand Down
3 changes: 2 additions & 1 deletion source/Personality.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Personality {
bool IsVindictive() const;
bool IsUnconstrained() const;
bool IsUnrestricted() const;
bool IsRestricted() const;
bool IsCoward() const;
bool IsAppeasing() const;
bool IsOpportunistic() const;
Expand Down Expand Up @@ -100,7 +101,7 @@ class Personality {
private:
// Make sure this matches the number of items in PersonalityTrait,
// or the build will fail.
static const int PERSONALITY_COUNT = 35;
static const int PERSONALITY_COUNT = 36;

bool isDefined = false;

Expand Down
2 changes: 1 addition & 1 deletion source/Politics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ bool Politics::CanLand(const Ship &ship, const Planet *planet) const

const Government *gov = ship.GetGovernment();
if(!gov->IsPlayer())
return (ship.GetPersonality().IsUnrestricted() || !gov->IsRestrictedFrom(*planet)) &&
return !ship.IsRestrictedFrom(*planet) &&
(!planet->IsInhabited() || !IsEnemy(gov, planet->GetGovernment()));

return CanLand(planet);
Expand Down
36 changes: 36 additions & 0 deletions source/Ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2120,6 +2120,42 @@ bool Ship::IsUsingJumpDrive() const




Hurleveur marked this conversation as resolved.
Show resolved Hide resolved
// Check if this ship is allowed to land on this planet, accounting for its personality.
bool Ship::IsRestrictedFrom(const Planet &planet) const
{
// The player's ships have no travel restrictions.
if(isYours || !government)
return false;

bool restrictedByGov = government->IsRestrictedFrom(planet);
// Special ships (such as NPCs) are unrestricted by default and must be explicitly restricted
// by their government's travel restrictions in order to follow them.
if(isSpecial)
return personality.IsRestricted() && restrictedByGov;
return !personality.IsUnrestricted() && restrictedByGov;
}


Hurleveur marked this conversation as resolved.
Show resolved Hide resolved


// Check if this ship is allowed to enter this system, accounting for its personality.
bool Ship::IsRestrictedFrom(const System &system) const
{
// The player's ships have no travel restrictions.
if(isYours || !government)
return false;

bool restrictedByGov = government->IsRestrictedFrom(system);
// Special ships (such as NPCs) are unrestricted by default and must be explicitly restricted
// by their government's travel restrictions in order to follow them.
if(isSpecial)
return personality.IsRestricted() && restrictedByGov;
return !personality.IsUnrestricted() && restrictedByGov;
}



// Check if this ship is currently able to enter hyperspace to its target.
bool Ship::IsReadyToJump(bool waitingIsReady) const
{
Expand Down
4 changes: 4 additions & 0 deletions source/Ship.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ class Ship : public Body, public std::enable_shared_from_this<Ship> {
bool IsUsingJumpDrive() const;
// Check if this ship is currently able to enter hyperspace to it target.
bool IsReadyToJump(bool waitingIsReady = false) const;
// Check if this ship is allowed to land on this planet, accounting for its personality.
bool IsRestrictedFrom(const Planet &planet) const;
// Check if this ship is allowed to enter this system, accounting for its personality.
bool IsRestrictedFrom(const System &system) const;
// Get this ship's custom swizzle.
int CustomSwizzle() const;

Expand Down