Skip to content

Commit

Permalink
Merge branch 'master' into lem-fork
Browse files Browse the repository at this point in the history
  • Loading branch information
a-random-lemurian committed Nov 2, 2024
2 parents 186fc4f + 2256988 commit f4fdcc1
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 55 deletions.
2 changes: 1 addition & 1 deletion data/gegno/gegno intro missions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ mission "First Contact: Gegno Vi"
choice
` (Stand up and approach the alien.)`
` (Get up and run to your ship.)`
` Before you can collect yourself, you realize the Vi warrior is now much closer to you. Within a matter of moments, the alien stands before you, giving you a much better look at them. They are much taller than both you and the other Gegno you've seen, extremely bulky, and slightly hunched over. Heavy-looking metal surround their body, and in any exposed areas are rough-looking patches of skin and hair. Thick facial hair covers their face, and above their human-like eyes are a pair of horns curved inward towards you.`
` Before you can collect yourself, you realize the Vi warrior is now much closer to you. Within a matter of moments, the alien stands before you, giving you a much better look at them. They are much taller than both you and the other Gegno you've seen, extremely bulky, and slightly hunched over. Heavy-looking metal surrounds their body, and in any exposed areas are rough-looking patches of skin and hair. Thick facial hair covers their face, and above their human-like eyes are a pair of horns curved inward towards you.`
` While the Gegno are known to dislike outsiders, this particular Gegno seems to at the very least acknowledge you. After a period of awkward and what seems to be judgmental silence, the Vi looks you up and down in an unenthused manner. They emit a very deep grumble, and with a loud snort, reach into a crevice in their armor to grab something. Pulling out what looks to be some sort of star map, they point to a location on it, gesture to themselves, then lower the device slowly to you. It seems they want to be taken to one of the Gegno's planets.`
choice
` (Accept their request.)`
Expand Down
18 changes: 9 additions & 9 deletions data/human/fleets.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1833,7 +1833,7 @@ fleet "Small Southern Pirates"
names "pirate"
cargo 1
personality
disables plunders harvests
disables plunders harvests getaway
confusion 20
variant 8
"Sparrow"
Expand Down Expand Up @@ -1921,7 +1921,7 @@ fleet "Large Southern Pirates"
names "pirate"
cargo 1
personality
plunders harvests
plunders harvests getaway
variant 2
"Sparrow" 4
variant 1
Expand Down Expand Up @@ -2046,7 +2046,7 @@ fleet "Small CCOR"
names "pirate"
cargo 1
personality
disables plunders harvests
disables plunders harvests getaway
variant 5
"Berserker"
variant 3
Expand All @@ -2071,7 +2071,7 @@ fleet "Large CCOR"
names "pirate"
cargo 1
personality
disables plunders harvests
disables plunders harvests getaway
variant 2
"Berserker (CCOR)" 2
variant 3
Expand Down Expand Up @@ -2244,7 +2244,7 @@ fleet "Small Core Pirates"
names "pirate"
cargo 1
personality
disables plunders harvests
disables plunders harvests getaway
confusion 20
variant 3
"Quicksilver"
Expand Down Expand Up @@ -2295,7 +2295,7 @@ fleet "Large Core Pirates"
names "pirate"
cargo 1
personality
plunders harvests
plunders harvests getaway
variant 5
"Quicksilver (Proton)" 3
variant 2
Expand Down Expand Up @@ -2375,7 +2375,7 @@ fleet "Small Northern Pirates"
names "pirate"
cargo 1
personality
disables plunders harvests
disables plunders harvests getaway
confusion 20
variant 5
"Sparrow"
Expand Down Expand Up @@ -2445,7 +2445,7 @@ fleet "Large Northern Pirates"
names "pirate"
cargo 1
personality
plunders harvests
plunders harvests getaway
variant 4
"Firebird"
variant 10
Expand Down Expand Up @@ -2549,7 +2549,7 @@ fleet "pirate raid"
names "pirate"
cargo 1
personality
disables nemesis plunders harvests
disables nemesis plunders harvests getaway
confusion 20
variant 3
"Argosy (Blaster)"
Expand Down
3 changes: 3 additions & 0 deletions source/AI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ namespace {
if(ship.GetAICache().NeedsAmmo())
return true;

if(personality.IsGetaway() && ship.Cargo().Free() == 0 && !ship.GetParent())
return true;

return false;
}

Expand Down
35 changes: 23 additions & 12 deletions source/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,11 @@ void Engine::Step(bool isActive)
// Add the flagship outline last to distinguish the flagship from other ships.
if(flagship && !flagship->IsDestroyed() && Preferences::Has("Highlight player's flagship"))
{
outlines.emplace_back(flagship->GetSprite(), (flagship->Center() - center) * zoom, flagship->Unit() * zoom,
flagship->GetFrame(), *GameData::Colors().Get("flagship highlight"));
outlines.emplace_back(flagship->GetSprite(),
(flagship->Center() - center) * zoom,
flagship->Unit() * zoom * flagship->Scale(),
flagship->GetFrame(),
*GameData::Colors().Get("flagship highlight"));
}

// Any of the player's ships that are in system are assumed to have
Expand Down Expand Up @@ -889,7 +892,7 @@ void Engine::Step(bool isActive)
double width = max(target->Width(), target->Height());
Point pos = target->Position() - center;
statuses.emplace_back(pos, flagship->OutfitScanFraction(), flagship->CargoScanFraction(),
0., 10. + max(20., width * .5), 4, 1.f, Angle(pos).Degrees() + 180.);
0., 10. + max(20., width * .5), Status::Type::SCAN, 1.f, Angle(pos).Degrees() + 180.);
}
// Handle any events that change the selected ships.
if(groupSelect >= 0)
Expand Down Expand Up @@ -1072,16 +1075,19 @@ void Engine::Draw() const
};
Point pos = it.position * zoom;
double radius = it.radius * zoom;
int colorIndex = static_cast<int>(it.type);
if(it.outer > 0.)
RingShader::Draw(pos, radius + 3., 1.5f, it.outer,
Color::Multiply(it.alpha, color[it.type]), 0.f, it.angle);
double dashes = (it.type >= 5) ? 0. : 20. * min<double>(1., zoom);
Color::Multiply(it.alpha, color[colorIndex]), 0.f, it.angle);
double dashes = (it.type >= Status::Type::SCAN) ? 0. : 20. * min<double>(1., zoom);
colorIndex += static_cast<int>(Status::Type::COUNT);
if(it.inner > 0.)
RingShader::Draw(pos, radius, 1.5f, it.inner,
Color::Multiply(it.alpha, color[5 + it.type]), dashes, it.angle);
Color::Multiply(it.alpha, color[colorIndex]), dashes, it.angle);
colorIndex += static_cast<int>(Status::Type::COUNT);
if(it.disabled > 0.)
RingShader::Draw(pos, radius, 1.5f, it.disabled,
Color::Multiply(it.alpha, color[10 + it.type]), dashes, it.angle);
Color::Multiply(it.alpha, color[colorIndex]), dashes, it.angle);
}

// Draw labels on missiles
Expand Down Expand Up @@ -2757,21 +2763,26 @@ void Engine::CreateStatusOverlays()
if(it->IsDestroyed())
continue;

static auto FLAGSHIP = Preferences::OverlayType::FLAGSHIP;
static auto FRIENDLY = Preferences::OverlayType::ESCORT;
static auto HOSTILE = Preferences::OverlayType::ENEMY;
static auto NEUTRAL = Preferences::OverlayType::NEUTRAL;

if(it == flagship)
EmplaceStatusOverlay(it, overlaySettings[Preferences::OverlayType::FLAGSHIP], 0, it->Cloaking());
EmplaceStatusOverlay(it, overlaySettings[FLAGSHIP], Status::Type::FLAGSHIP, it->Cloaking());
else if(it->GetGovernment()->IsEnemy())
EmplaceStatusOverlay(it, overlaySettings[Preferences::OverlayType::ENEMY], 2, it->Cloaking());
EmplaceStatusOverlay(it, overlaySettings[HOSTILE], Status::Type::HOSTILE, it->Cloaking());
else if(it->IsYours() || it->GetPersonality().IsEscort())
EmplaceStatusOverlay(it, overlaySettings[Preferences::OverlayType::ESCORT], 1, it->Cloaking());
EmplaceStatusOverlay(it, overlaySettings[FRIENDLY], Status::Type::FRIENDLY, it->Cloaking());
else
EmplaceStatusOverlay(it, overlaySettings[Preferences::OverlayType::NEUTRAL], 3, it->Cloaking());
EmplaceStatusOverlay(it, overlaySettings[NEUTRAL], Status::Type::NEUTRAL, it->Cloaking());
}
}



void Engine::EmplaceStatusOverlay(const shared_ptr<Ship> &it, Preferences::OverlayState overlaySetting,
int type, double cloak)
Status::Type type, double cloak)
{
if(overlaySetting == Preferences::OverlayState::OFF)
return;
Expand Down
16 changes: 13 additions & 3 deletions source/Engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,19 @@ class Engine {
};

class Status {
public:
enum class Type {
FLAGSHIP,
FRIENDLY,
HOSTILE,
NEUTRAL,
SCAN,
COUNT // This item should always be the last in this list.
};

public:
constexpr Status(const Point &position, double outer, double inner,
double disabled, double radius, int type, float alpha, double angle = 0.)
double disabled, double radius, Type type, float alpha, double angle = 0.)
: position(position), outer(outer), inner(inner),
disabled(disabled), radius(radius), type(type), alpha(alpha), angle(angle) {}

Expand All @@ -136,7 +146,7 @@ class Engine {
double inner;
double disabled;
double radius;
int type;
Type type;
float alpha;
double angle;
};
Expand Down Expand Up @@ -183,7 +193,7 @@ class Engine {

void CreateStatusOverlays();
void EmplaceStatusOverlay(const std::shared_ptr<Ship> &ship, Preferences::OverlayState overlaySetting,
int value, double cloak);
Status::Type type, double cloak);


private:
Expand Down
62 changes: 38 additions & 24 deletions source/OutfitterPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ ShopPanel::BuyResult OutfitterPanel::CanBuy(bool onlyOwned) const
"It is being shown in the list because you have one, "
"but this " + planet->Noun() + " does not sell them.";
}

// Add system to accumulate reasons why an outfit cannot be bought
vector<string> errors;
// Check if you need to pay, and can't afford it.
if(!onlyOwned)
{
Expand All @@ -384,14 +385,14 @@ ShopPanel::BuyResult OutfitterPanel::CanBuy(bool onlyOwned) const
int64_t credits = player.Accounts().Credits();

if(cost > credits)
return "You cannot buy this outfit, because it costs "
+ Format::CreditString(cost) + ", and you only have "
+ Format::Credits(credits) + ".";
errors.push_back("You do not have enough money to buy this outfit, you need a further " +
Format::CreditString(cost - credits));

// Add the cost to buy the required license.
if(cost + licenseCost > credits)
return "You don't have enough money to buy this outfit, because it will cost you an extra "
+ Format::CreditString(licenseCost) + " to buy the necessary licenses.";
else if(cost + licenseCost > credits)
errors.push_back("You do not have enough money to buy this outfit because you also need to buy a "
"license for it. You need a further " +
Format::CreditString(licenseCost - credits));
}

// Check if the outfit will fit
Expand All @@ -403,9 +404,9 @@ ShopPanel::BuyResult OutfitterPanel::CanBuy(bool onlyOwned) const
if(!mass || freeCargo >= mass)
return true;

return "You cannot " + string(onlyOwned ? "load" : "buy") + " this outfit, because it takes up "
errors.push_back("You cannot " + string(onlyOwned ? "load" : "buy") + " this outfit, because it takes up "
+ Format::CargoString(mass, "mass") + " and your fleet has "
+ Format::CargoString(freeCargo, "cargo space") + " free.";
+ Format::CargoString(freeCargo, "cargo space") + " free.");
}
else
{
Expand All @@ -419,52 +420,65 @@ ShopPanel::BuyResult OutfitterPanel::CanBuy(bool onlyOwned) const
double outfitNeeded = -selectedOutfit->Get("outfit space");
double outfitSpace = playerShip->Attributes().Get("outfit space");
if(outfitNeeded > outfitSpace)
return "You cannot install this outfit, because it takes up "
errors.push_back("You cannot install this outfit, because it takes up "
+ Format::CargoString(outfitNeeded, "outfit space") + ", and this ship has "
+ Format::MassString(outfitSpace) + " free.";
+ Format::MassString(outfitSpace) + " free.");

double weaponNeeded = -selectedOutfit->Get("weapon capacity");
double weaponSpace = playerShip->Attributes().Get("weapon capacity");
if(weaponNeeded > weaponSpace)
return "Only part of your ship's outfit capacity is usable for weapons. "
errors.push_back("Only part of your ship's outfit capacity is usable for weapons. "
"You cannot install this outfit, because it takes up "
+ Format::CargoString(weaponNeeded, "weapon space") + ", and this ship has "
+ Format::MassString(weaponSpace) + " free.";
+ Format::MassString(weaponSpace) + " free.");

double engineNeeded = -selectedOutfit->Get("engine capacity");
double engineSpace = playerShip->Attributes().Get("engine capacity");
if(engineNeeded > engineSpace)
return "Only part of your ship's outfit capacity is usable for engines. "
errors.push_back("Only part of your ship's outfit capacity is usable for engines. "
"You cannot install this outfit, because it takes up "
+ Format::CargoString(engineNeeded, "engine space") + ", and this ship has "
+ Format::MassString(engineSpace) + " free.";
+ Format::MassString(engineSpace) + " free.");

if(selectedOutfit->Category() == "Ammunition")
return !playerShip->OutfitCount(selectedOutfit) ?
errors.push_back(!playerShip->OutfitCount(selectedOutfit) ?
"This outfit is ammunition for a weapon. "
"You cannot install it without first installing the appropriate weapon."
: "You already have the maximum amount of ammunition for this weapon. "
"If you want to install more ammunition, you must first install another of these weapons.";
"If you want to install more ammunition, you must first install another of these weapons.");

int mountsNeeded = -selectedOutfit->Get("turret mounts");
int mountsFree = playerShip->Attributes().Get("turret mounts");
if(mountsNeeded && !mountsFree)
return "This weapon is designed to be installed on a turret mount, "
"but your ship does not have any unused turret mounts available.";
errors.push_back("This weapon is designed to be installed on a turret mount, "
"but your ship does not have any unused turret mounts available.");

int gunsNeeded = -selectedOutfit->Get("gun ports");
int gunsFree = playerShip->Attributes().Get("gun ports");
if(gunsNeeded && !gunsFree)
return "This weapon is designed to be installed in a gun port, "
"but your ship does not have any unused gun ports available.";
errors.push_back("This weapon is designed to be installed in a gun port, "
"but your ship does not have any unused gun ports available.");

if(selectedOutfit->Get("installable") < 0.)
return "This item is not an outfit that can be installed in a ship.";
errors.push_back("This item is not an outfit that can be installed in a ship.");

// For unhandled outfit requirements, show a catch-all error message.
return "You cannot install this outfit in your ship, "
if(errors.empty())
errors.push_back("You cannot install this outfit in your ship, "
"because it would reduce one of your ship's attributes to a negative amount. "
"For example, it may use up more cargo space than you have left.";
"For example, it may use up more cargo space than you have left.");
}

if(errors.empty())
return true;
else if(errors.size() == 1)
return errors[0];
else
{
string errorMessage = "There are several reasons why you cannot buy this outfit:\n";
for(size_t i = 0; i < errors.size(); ++i)
errorMessage += "- " + errors[i] + "\n";
return errorMessage;
}
}

Expand Down
11 changes: 10 additions & 1 deletion source/Personality.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ namespace {
RESTRICTED,
DECLOAKED,
QUIET,
GETAWAY,

// This must be last so it can be used for bounds checking.
LAST_ITEM_IN_PERSONALITY_TRAIT_ENUM
Expand Down Expand Up @@ -107,7 +108,8 @@ namespace {
{"unrestricted", UNRESTRICTED},
{"restricted", RESTRICTED},
{"decloaked", DECLOAKED},
{"quiet", QUIET}
{"quiet", QUIET},
{"getaway", GETAWAY}
};

// Tokens that combine two or more flags.
Expand Down Expand Up @@ -309,6 +311,13 @@ bool Personality::IsRamming() const



bool Personality::IsGetaway() const
{
return flags.test(GETAWAY);
}



bool Personality::IsStaying() const
{
return flags.test(STAYING);
Expand Down
3 changes: 2 additions & 1 deletion source/Personality.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Personality {
bool IsOpportunistic() const;
bool IsMerciful() const;
bool IsRamming() const;
bool IsGetaway() const;

// Mission NPC states:
bool IsStaying() const;
Expand Down Expand Up @@ -101,7 +102,7 @@ class Personality {
private:
// Make sure this matches the number of items in PersonalityTrait,
// or the build will fail.
static const int PERSONALITY_COUNT = 37;
static const int PERSONALITY_COUNT = 38;

bool isDefined = false;

Expand Down
Loading

0 comments on commit f4fdcc1

Please sign in to comment.