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

Make spesos, IDs & PDAs teleport to the shipyard console on sale. #2938

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a4f4685
added whitelist system that teleports marked items to the sale console
Alkheemist Feb 18, 2025
5b8390a
make appraisal ignore items on the preservelist
Alkheemist Feb 18, 2025
194ede1
Merge branch 'master' into cleaning-fee
Alkheemist Feb 18, 2025
a6fd26f
recursively find marked items
Alkheemist Feb 19, 2025
90ba081
Merge branch 'cleaning-fee' of https://github.com/Alkheemist/frontier…
Alkheemist Feb 19, 2025
6290c97
switch to component search based strategy
Alkheemist Feb 19, 2025
a28c380
add a variant getprice that respects predicate
Alkheemist Feb 19, 2025
5d45607
rename and cleanup whitelist stuff
Alkheemist Feb 19, 2025
7f83fcf
dangling newline
Alkheemist Feb 19, 2025
77631b7
further strip out whitelist references
Alkheemist Feb 19, 2025
70166e3
why is there whitespace in this file?
Alkheemist Feb 19, 2025
63b00d9
Merge branch 'master' into cleaning-fee
Alkheemist Feb 19, 2025
f1f1fdf
undo autoformatting fixes on the rest of the file
Alkheemist Feb 19, 2025
c081724
Merge branch 'cleaning-fee' of https://github.com/Alkheemist/frontier…
Alkheemist Feb 19, 2025
4a7f894
frontier comment
Alkheemist Feb 19, 2025
2ac36bf
combine preserveOnSale and DisableShipyardSale components, meddled wi…
Alkheemist Feb 21, 2025
4e7d61d
Ship sale cleanup suggestions
whatston3 Feb 26, 2025
96ac51c
muh grammar
whatston3 Feb 26, 2025
b0248fc
include fallback-prevent-sale suggestions
Alkheemist Feb 27, 2025
c4bf742
use GetPrice on non-recursive mode for actual appraisal
Alkheemist Feb 27, 2025
79179fb
Merge branch 'master' into cleaning-fee
Alkheemist Feb 27, 2025
7b1d96a
fix up default reason and also fix up the function summary while we'r…
Alkheemist Feb 27, 2025
3f4e067
edited fallback message
Alkheemist Feb 27, 2025
f2893d1
Merge remote-tracking branch 'whatstone/2025-02-26-cleaning-fee-sugge…
Alkheemist Feb 27, 2025
e9e0d50
revert teleporting in place, screws with enumeration
Alkheemist Feb 27, 2025
a1a517c
Rename HasPreserveOnSaleComp to FindEntitiesToPreserve
whatston3 Feb 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion Content.Server/Cargo/Systems/PricingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,35 @@ public double GetPrice(EntityUid uid, bool includeContents = true)
return price;
}

// Begin Frontier - GetPrice variant that uses predicate
/// <summary>
/// Appraises an entity, returning its price. Respects predicate - an entity that is excluded will be removed from the
/// </summary>
/// <param name="uid">The entity to appraise.</param>
/// <param name="includeContents">Whether to examine its contents.</param>
/// <param name="predicate">An optional predicate that controls whether or not the entity or its children are counted toward the total.</param>
/// <returns>The price of the entity.</returns>
public double GetPriceConditional(EntityUid uid, bool includeContents = true, Func<EntityUid, bool>? predicate = null)
{
if (predicate is not null && !predicate(uid))
return 0.0;

var price = GetPrice(uid, false);

if (includeContents && TryComp<ContainerManagerComponent>(uid, out var containers))
{
foreach (var container in containers.Containers.Values)
{
foreach (var ent in container.ContainedEntities)
{
price += GetPriceConditional(ent, true, predicate);
}
}
}
return price;
}
// End Frontier - GetPrice variant that uses predicate

private double GetMaterialsPrice(EntityUid uid)
{
double price = 0;
Expand Down Expand Up @@ -441,7 +470,7 @@ public double AppraiseGrid(EntityUid grid, Func<EntityUid, bool>? predicate = nu
{
if (predicate is null || predicate(child))
{
var subPrice = GetPrice(child);
var subPrice = GetPriceConditional(child, true, predicate); // Frontier: GetPrice<GetPriceConditional, add true, predicate
price += subPrice;
afterPredicate?.Invoke(child, subPrice);
}
Expand Down
30 changes: 18 additions & 12 deletions Content.Server/_NF/Shipyard/Systems/ShipyardSystem.Consoles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,11 @@ private void OnPurchaseMessage(EntityUid shipyardConsoleUid, ShipyardConsoleComp
var sellValue = 0;
if (!voucherUsed)
{
// Get the price of the ship
if (TryComp<ShuttleDeedComponent>(targetId, out var deed))
sellValue = (int)_pricing.AppraiseGrid((EntityUid)(deed?.ShuttleUid!));
sellValue = (int)_pricing.AppraiseGrid((EntityUid)(deed?.ShuttleUid!), LacksPreserveOnSaleComp);

// Adjust for taxes
sellValue = CalculateShipResaleValue((shipyardConsoleUid, component), sellValue);
}

Expand Down Expand Up @@ -376,7 +378,7 @@ public void OnSellMessage(EntityUid uid, ShipyardConsoleComponent component, Shi
var shuttleName = ToPrettyString(shuttleUid); // Grab the name before it gets 1984'd

// Check for shipyard blacklisting components
var disableSaleQuery = GetEntityQuery<DisableShipyardSaleComponent>();
var disableSaleQuery = GetEntityQuery<ShipyardSellConditionComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
var disableSaleMsg = FindDisableShipyardSaleObjects(shuttleUid, (ShipyardConsoleUiKey)args.UiKey, disableSaleQuery, xformQuery);
if (disableSaleMsg != null)
Expand All @@ -386,7 +388,7 @@ public void OnSellMessage(EntityUid uid, ShipyardConsoleComponent component, Shi
return;
}

var saleResult = TrySellShuttle(stationUid, shuttleUid, out var bill);
var saleResult = TrySellShuttle(stationUid, shuttleUid, uid, out var bill);
if (saleResult.Error != ShipyardSaleError.Success)
{
switch (saleResult.Error)
Expand Down Expand Up @@ -486,7 +488,7 @@ private void OnConsoleUIOpened(EntityUid uid, ShipyardConsoleComponent component
int sellValue = 0;
if (deed?.ShuttleUid != null)
{
sellValue = (int)_pricing.AppraiseGrid((EntityUid)(deed?.ShuttleUid!));
sellValue = (int)_pricing.AppraiseGrid((EntityUid)(deed?.ShuttleUid!), LacksPreserveOnSaleComp);
sellValue = CalculateShipResaleValue((uid, component), sellValue);
}

Expand Down Expand Up @@ -579,7 +581,7 @@ private void OnItemSlotChanged(EntityUid uid, ShipyardConsoleComponent component
int sellValue = 0;
if (deed?.ShuttleUid != null)
{
sellValue = (int)_pricing.AppraiseGrid(deed.ShuttleUid.Value);
sellValue = (int)_pricing.AppraiseGrid(deed.ShuttleUid.Value, LacksPreserveOnSaleComp);
sellValue = CalculateShipResaleValue((uid, component), sellValue);
}

Expand Down Expand Up @@ -627,22 +629,26 @@ private void OnItemSlotChanged(EntityUid uid, ShipyardConsoleComponent component
}

/// <summary>
/// Looks for a living, sapient being aboard a particular entity.
/// Looks for any entities marked as preventing sale on a shuttle
/// </summary>
/// <param name="uid">The entity to search (e.g. a shuttle, a station)</param>
/// <param name="mobQuery">A query to get the MobState from an entity</param>
/// <param name="shuttle">The entity to search (e.g. a shuttle, a station)</param>
/// <param name="key">The UI key of the current shipyard console. Used to see if the shipyard should ignore this check</param>
/// <param name="disableSaleQuery">A query to get any marked objects from an entity</param>
/// <param name="xformQuery">A query to get the transform component of an entity</param>
/// <returns>The name of the sapient being if one was found, null otherwise.</returns>
public string? FindDisableShipyardSaleObjects(EntityUid shuttle, ShipyardConsoleUiKey key, EntityQuery<DisableShipyardSaleComponent> disableSaleQuery, EntityQuery<TransformComponent> xformQuery)
/// <returns>The reason that a shuttle should be blocked from sale, null otherwise.</returns>
public string? FindDisableShipyardSaleObjects(EntityUid shuttle, ShipyardConsoleUiKey key, EntityQuery<ShipyardSellConditionComponent> disableSaleQuery, EntityQuery<TransformComponent> xformQuery)
{
var xform = xformQuery.GetComponent(shuttle);
var childEnumerator = xform.ChildEnumerator;

while (childEnumerator.MoveNext(out var child))
{
if (disableSaleQuery.TryGetComponent(child, out var disableSale)
&& disableSale.BlockSale is true
&& !disableSale.AllowedShipyardTypes.Contains(key))
return disableSale.Reason;
{
return disableSale.Reason ?? "shipyard-console-fallback-prevent-sale";
}
}

return null;
Expand Down Expand Up @@ -784,7 +790,7 @@ private void OnInitDeedSpawner(EntityUid uid, StationDeedSpawnerComponent compon
if (xform.GridUid == null)
return;

if (!TryComp<ShuttleDeedComponent>(xform.GridUid.Value, out var shuttleDeed) || !TryComp<ShuttleComponent>(xform.GridUid.Value, out var shuttle) || !HasComp<TransformComponent>(xform.GridUid.Value) || shuttle == null || ShipyardMap == null)
if (!TryComp<ShuttleDeedComponent>(xform.GridUid.Value, out var shuttleDeed) || !TryComp<ShuttleComponent>(xform.GridUid.Value, out var shuttle) || !HasComp<TransformComponent>(xform.GridUid.Value) || shuttle == null || ShipyardMap == null)
return;

var output = DeedRegex.Replace($"{shuttleDeed.ShuttleOwner}", ""); // Removes content inside parentheses along with parentheses and a preceding space
Expand Down
57 changes: 54 additions & 3 deletions Content.Server/_NF/Shipyard/Systems/ShipyardSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Content.Server.Cargo.Systems;
using Content.Server.Station.Systems;
using Content.Shared._NF.Shipyard.Components;
using Content.Server._NF.Shipyard.Components;
using Content.Shared._NF.Shipyard;
using Content.Shared.GameTicking;
using Robust.Server.GameObjects;
Expand Down Expand Up @@ -33,6 +34,7 @@ public sealed partial class ShipyardSystem : SharedShipyardSystem
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;

public MapId? ShipyardMap { get; private set; }
private float _shuttleIndex;
Expand Down Expand Up @@ -198,11 +200,12 @@ private bool TryAddShuttle(string shuttlePath, [NotNullWhen(true)] out EntityUid
}

/// <summary>
/// Checks a shuttle to make sure that it is docked to the given station, and that there are no lifeforms aboard. Then it appraises the grid, outputs to the server log, and deletes the grid
/// Checks a shuttle to make sure that it is docked to the given station, and that there are no lifeforms aboard. Then it teleports tagged items on top of the console, appraises the grid, outputs to the server log, and deletes the grid
/// </summary>
/// <param name="stationUid">The ID of the station that the shuttle is docked to</param>
/// <param name="shuttleUid">The grid ID of the shuttle to be appraised and sold</param>
public ShipyardSaleResult TrySellShuttle(EntityUid stationUid, EntityUid shuttleUid, out int bill)
/// <param name="consoleUid">The ID of the console being used to sell the ship</param>
public ShipyardSaleResult TrySellShuttle(EntityUid stationUid, EntityUid shuttleUid, EntityUid consoleUid, out int bill)
{
ShipyardSaleResult result = new ShipyardSaleResult();
bill = 0;
Expand Down Expand Up @@ -268,7 +271,12 @@ public ShipyardSaleResult TrySellShuttle(EntityUid stationUid, EntityUid shuttle
_station.DeleteStation(shuttleStationUid);
}

bill = (int)_pricing.AppraiseGrid(shuttleUid);
if (TryComp<ShipyardConsoleComponent>(consoleUid, out var comp))
{
CleanGrid(shuttleUid, consoleUid);
}

bill = (int)_pricing.AppraiseGrid(shuttleUid, LacksPreserveOnSaleComp);
QueueDel(shuttleUid);
_sawmill.Info($"Sold shuttle {shuttleUid} for {bill}");

Expand All @@ -279,6 +287,49 @@ public ShipyardSaleResult TrySellShuttle(EntityUid stationUid, EntityUid shuttle
return result;
}

private void CleanGrid(EntityUid grid, EntityUid destination)
{
var xform = Transform(grid);
var enumerator = xform.ChildEnumerator;
var entitiesToPreserve = new List<EntityUid>();

while (enumerator.MoveNext(out var child))
{
FindEntitiesToPreserve(child, ref entitiesToPreserve);
}
foreach (var ent in entitiesToPreserve)
{
// Teleport this item and all its children to the floor (or space).
_transform.SetCoordinates(ent, new EntityCoordinates(destination, 0, 0));
_transform.AttachToGridOrMap(ent);
}
}

// checks if something has the ShipyardPreserveOnSaleComponent and if it does, adds it to the list
private void FindEntitiesToPreserve(EntityUid entity, ref List<EntityUid> output)
{
if (TryComp<ShipyardSellConditionComponent>(entity, out var comp) && comp.PreserveOnSale == true)
{
output.Add(entity);
return;
}
else if (TryComp<ContainerManagerComponent>(entity, out var containers))
{
foreach (var container in containers.Containers.Values)
{
foreach (var ent in container.ContainedEntities)
{
FindEntitiesToPreserve(ent, ref output);
}
}
}
}

// returns false if it has ShipyardPreserveOnSaleComponent, true otherwise
private bool LacksPreserveOnSaleComp(EntityUid uid)
{
return !TryComp<ShipyardSellConditionComponent>(uid, out var comp) || comp.PreserveOnSale == false;
}
private void CleanupShipyard()
{
if (ShipyardMap == null || !_mapManager.MapExists(ShipyardMap.Value))
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace Content.Shared._NF.Shipyard.Components;

/// <summary>
/// A component that disables the sale of the ship it's on from a shipyard console.
/// </summary>
[RegisterComponent]
public sealed partial class ShipyardSellConditionComponent : Component
{
/// <summary>
/// Whether this item is preserved on shipyard sale.
/// </summary>
[DataField]
public bool PreserveOnSale = false;

/// <summary>
/// Whether this item prevents shipyard sale.
/// </summary>
[DataField]
public bool BlockSale = false;

/// <summary>
/// The message to print off when a shipyard sale is disabled.
/// </summary>
[DataField]
public LocId? Reason;

/// <summary>
/// The console types that should allow selling this object if BlockSale is true.
/// </summary>
[DataField]
public List<ShipyardConsoleUiKey> AllowedShipyardTypes = new();


}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ shipyard-console-invalid-voucher-type = This voucher cannot be used at this cons
shipyard-console-contraband-onboard = Smuggled contraband detected onboard.
shipyard-console-station-resources = Vital station resources detected onboard.
shipyard-console-dangerous-materials = Dangerous materials detected onboard.
shipyard-console-fallback-prevent-sale = YML-class bugs detected onboard. Please file a bug report when possible.

shipyard-console-menu-size-label = Size:{" "}
shipyard-console-menu-class-label = Class:{" "}
Expand Down Expand Up @@ -77,4 +78,4 @@ shipyard-console-engine-APU = APU
shipyard-console-engine-Welding = Welding Fuel
shipyard-console-engine-Plasma = Plasma
shipyard-console-engine-Uranium = Uranium
shipyard-console-engine-Bananium = Bananium
shipyard-console-engine-Bananium = Bananium
2 changes: 2 additions & 0 deletions Resources/Prototypes/Entities/Objects/Devices/pda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@
wipeVerbText: pda-wipe-device-verb-text # Frontier
wipeVerbPopup: pda-wiped-device # Frontier
mindRoles: [] # Frontier: no default value here
- type: ShipyardSellCondition # Frontier: Teleport to shipyard console on sale
preserveOnSale: true

- type: entity
parent: BasePDA
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
- HighRiskItem
- type: StealTarget
stealGroup: NukeDisk
- type: DisableShipyardSale # Frontier
- type: ShipyardSellCondition # Frontier
blockSale: true # Frontier
reason: shipyard-console-station-resources # Frontier
allowedShipyardTypes: # Frontier: mail profits removed, sector in shambles
- Syndicate # Frontier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
- type: StaticPrice # Frontier
price: 5 # Frontier The card need to cost less then the PDA that comes with a card and a pen in it.
- type: CargoSellBlacklist # Frontier
- type: ShipyardSellCondition # Frontier: Teleport to shipyard console on sale
preserveOnSale: true

#IDs with layers

Expand Down
2 changes: 2 additions & 0 deletions Resources/Prototypes/Entities/Objects/Misc/space_cash.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
- ItemMask
- type: Appearance
- type: CargoSellBlacklist
- type: ShipyardSellCondition # Frontier: Teleport to shipyard console on sale
preserveOnSale: true

- type: material
id: Credit
Expand Down
3 changes: 2 additions & 1 deletion Resources/Prototypes/Entities/Structures/Machines/nuke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@
follow: true
location: nuclear bomb
- type: FTLSmashImmune
- type: DisableShipyardSale # Frontier
- type: ShipyardSellCondition # Frontier
blockSale: true # Frontier
reason: shipyard-console-dangerous-materials # Frontier
allowedShipyardTypes: # Frontier:
- Syndicate # Frontier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
name: mail teleporter
description: Teleports mail addressed to the crew of this station.
components:
- type: MailTeleporter
- type: MailTeleporter
- type: InteractionOutline
- type: Physics
bodyType: Static
Expand Down Expand Up @@ -39,7 +39,8 @@
True: {visible: true}
False: {visible: false}
- type: PowerSwitch
- type: DisableShipyardSale # Frontier
- type: ShipyardSellCondition # Frontier
blockSale: true # Frontier
reason: shipyard-console-station-resources # Frontier
allowedShipyardTypes: # Frontier: mail profits removed, sector in shambles
- Syndicate # Frontier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@
turnInValues:
FrontierUplinkCoin: 3
Doubloon: 2
- type: DisableShipyardSale
- type: ShipyardSellCondition
blockSale: true
reason: shipyard-console-contraband-onboard
allowedShipyardTypes:
- Syndicate
Expand Down
Loading