From d96c8ce4a9e871b5db7132dc5ff8cc3e502e7f69 Mon Sep 17 00:00:00 2001
From: GreaseMonk <1354802+GreaseMonk@users.noreply.github.com>
Date: Sun, 24 Mar 2024 23:49:31 +0100
Subject: [PATCH] Shipyard RCD (#1130)
* Remaining fixes and add to research etc
* Bump price
* Bump material price
* Fix shipyard ammo refuel normal rcd
* Fix sounds
* Fix sounds
---
.../Systems/ShipyardSystem.Consoles.cs | 5 +-
.../Access/Components/IdCardComponent.cs | 18 ++++
.../RCD/Components/RCDAmmoComponent.cs | 7 ++
Content.Shared/RCD/Components/RCDComponent.cs | 14 +++
Content.Shared/RCD/Systems/RCDAmmoSystem.cs | 10 ++
Content.Shared/RCD/Systems/RCDSystem.cs | 101 ++++++++++++++++--
.../Components/ShuttleDeedComponent.cs | 4 +-
.../en-US/_NF/research/technologies.ftl | 1 +
.../_NF/shipyard/shipyard-rcd-component.ftl | 8 ++
.../VendingMachines/Inventories/engivend.yml | 2 +
.../Entities/Structures/Machines/lathe.yml | 2 +
Resources/Prototypes/Research/industrial.yml | 13 +++
.../Entities/Objects/Tools/shipyard_rcd.yml | 37 +++++++
.../Prototypes/_NF/Recipes/Lathes/devices.yml | 18 ++++
.../Prototypes/_NF/Recipes/Lathes/tools.yml | 20 ++++
.../Objects/Tools/rcd.rsi/ammo-shipyard.png | Bin 0 -> 1927 bytes
.../Objects/Tools/rcd.rsi/icon-shipyard.png | Bin 0 -> 2679 bytes
.../Textures/Objects/Tools/rcd.rsi/meta.json | 6 ++
18 files changed, 254 insertions(+), 12 deletions(-)
create mode 100644 Resources/Locale/en-US/_NF/shipyard/shipyard-rcd-component.ftl
create mode 100644 Resources/Prototypes/_NF/Entities/Objects/Tools/shipyard_rcd.yml
create mode 100644 Resources/Prototypes/_NF/Recipes/Lathes/tools.yml
create mode 100644 Resources/Textures/Objects/Tools/rcd.rsi/ammo-shipyard.png
create mode 100644 Resources/Textures/Objects/Tools/rcd.rsi/icon-shipyard.png
diff --git a/Content.Server/Shipyard/Systems/ShipyardSystem.Consoles.cs b/Content.Server/Shipyard/Systems/ShipyardSystem.Consoles.cs
index b740900b66d..629d2e12ed4 100644
--- a/Content.Server/Shipyard/Systems/ShipyardSystem.Consoles.cs
+++ b/Content.Server/Shipyard/Systems/ShipyardSystem.Consoles.cs
@@ -36,6 +36,7 @@
using Content.Server.Shuttles.Components;
using Content.Server.Station.Components;
using System.Text.RegularExpressions;
+using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
namespace Content.Server.Shipyard.Systems;
@@ -438,12 +439,12 @@ private void SendSellMessage(EntityUid uid, EntityUid? player, string name, stri
private void PlayDenySound(EntityUid uid, ShipyardConsoleComponent component)
{
- _audio.PlayPvs(_audio.GetSound(component.ErrorSound), uid);
+ _audio.PlayPvs(_audio.GetSound(component.ErrorSound), uid, AudioParams.Default.WithMaxDistance(0.01f));
}
private void PlayConfirmSound(EntityUid uid, ShipyardConsoleComponent component)
{
- _audio.PlayPvs(_audio.GetSound(component.ConfirmSound), uid);
+ _audio.PlayPvs(_audio.GetSound(component.ConfirmSound), uid, AudioParams.Default.WithMaxDistance(0.01f));
}
private void OnItemSlotChanged(EntityUid uid, ShipyardConsoleComponent component, ContainerModifiedMessage args)
diff --git a/Content.Shared/Access/Components/IdCardComponent.cs b/Content.Shared/Access/Components/IdCardComponent.cs
index 26e83c5586e..9459f6c1910 100644
--- a/Content.Shared/Access/Components/IdCardComponent.cs
+++ b/Content.Shared/Access/Components/IdCardComponent.cs
@@ -1,6 +1,7 @@
using Content.Shared.Access.Systems;
using Content.Shared.PDA;
using Content.Shared.StatusIcon;
+using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
@@ -40,4 +41,21 @@ public sealed partial class IdCardComponent : Component
///
[DataField, ViewVariables(VVAccess.ReadWrite)]
public bool BypassLogging;
+
+
+ // Frontier
+ [DataField("soundError")]
+ public SoundSpecifier ErrorSound =
+ new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_sigh.ogg");
+
+ // Frontier
+ [DataField("soundSwipe")]
+ public SoundSpecifier SwipeSound =
+ new SoundPathSpecifier("/Audio/Machines/id_swipe.ogg");
+
+ // Frontier
+ [DataField("soundInsert")]
+ public SoundSpecifier InsertSound =
+ new SoundPathSpecifier("/Audio/Machines/id_insert.ogg");
+
}
diff --git a/Content.Shared/RCD/Components/RCDAmmoComponent.cs b/Content.Shared/RCD/Components/RCDAmmoComponent.cs
index 7b1fc001d4d..16a92b6aa25 100644
--- a/Content.Shared/RCD/Components/RCDAmmoComponent.cs
+++ b/Content.Shared/RCD/Components/RCDAmmoComponent.cs
@@ -13,6 +13,13 @@ public sealed partial class RCDAmmoComponent : Component
///
[DataField("charges"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public int Charges = 5;
+
+ ///
+ /// ~~~ Frontier ~~~
+ /// A flag that limits RCD to the authorized ships.
+ ///
+ [DataField("isShipyardRCDAmmo"), AutoNetworkedField]
+ public bool IsShipyardRCDAmmo;
}
// TODO: state??? check if it desyncs
diff --git a/Content.Shared/RCD/Components/RCDComponent.cs b/Content.Shared/RCD/Components/RCDComponent.cs
index 8e1032884aa..68271b1a102 100644
--- a/Content.Shared/RCD/Components/RCDComponent.cs
+++ b/Content.Shared/RCD/Components/RCDComponent.cs
@@ -48,4 +48,18 @@ public sealed partial class RCDComponent : Component
[DataField("floor", customTypeSerializer: typeof(PrototypeIdSerializer))]
[ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public string Floor = "FloorSteel";
+
+ ///
+ /// ~~~ Frontier ~~~
+ /// A flag that limits RCD to the authorized ships.
+ ///
+ [DataField("isShipyardRCD"), AutoNetworkedField]
+ public bool IsShipyardRCD;
+
+ ///
+ /// ~~~ Frontier ~~~
+ /// The uid to which this RCD is limited to be used on.
+ ///
+ [DataField("linkedShuttleUid"), AutoNetworkedField]
+ public EntityUid? LinkedShuttleUid = null;
}
diff --git a/Content.Shared/RCD/Systems/RCDAmmoSystem.cs b/Content.Shared/RCD/Systems/RCDAmmoSystem.cs
index 9481d299aaa..9136e337e28 100644
--- a/Content.Shared/RCD/Systems/RCDAmmoSystem.cs
+++ b/Content.Shared/RCD/Systems/RCDAmmoSystem.cs
@@ -42,6 +42,16 @@ private void OnAfterInteract(EntityUid uid, RCDAmmoComponent comp, AfterInteract
return;
var user = args.User;
+
+ // ## Frontier - Shipyard RCD ammo only fits in shipyard RCD.
+ // At this point RCDComponent is guaranteed
+ EnsureComp(target, out var rcdComponent);
+ if (rcdComponent.IsShipyardRCD && !comp.IsShipyardRCDAmmo || !rcdComponent.IsShipyardRCD && comp.IsShipyardRCDAmmo)
+ {
+ _popup.PopupClient(Loc.GetString("rcd-component-wrong-ammo-type"), target, user);
+ return;
+ }
+
args.Handled = true;
var count = Math.Min(charges.MaxCharges - charges.Charges, comp.Charges);
if (count <= 0)
diff --git a/Content.Shared/RCD/Systems/RCDSystem.cs b/Content.Shared/RCD/Systems/RCDSystem.cs
index 2b9852a6945..f93ecb12fd2 100644
--- a/Content.Shared/RCD/Systems/RCDSystem.cs
+++ b/Content.Shared/RCD/Systems/RCDSystem.cs
@@ -1,3 +1,4 @@
+using Content.Shared.Access.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Charges.Components;
using Content.Shared.Charges.Systems;
@@ -10,6 +11,7 @@
using Content.Shared.Physics;
using Content.Shared.Popups;
using Content.Shared.RCD.Components;
+using Content.Shared.Shipyard.Components;
using Content.Shared.Tag;
using Content.Shared.Tiles;
using Robust.Shared.Audio;
@@ -50,6 +52,7 @@ public override void Initialize()
SubscribeLocalEvent(OnAfterInteract);
SubscribeLocalEvent(OnDoAfter);
SubscribeLocalEvent>(OnDoAfterAttempt);
+ SubscribeLocalEvent(OnIdCardSwipeHappened); // Frontier
}
private void OnExamine(EntityUid uid, RCDComponent comp, ExaminedEvent args)
@@ -70,6 +73,56 @@ private void OnUseInHand(EntityUid uid, RCDComponent comp, UseInHandEvent args)
args.Handled = true;
}
+ /**
+ * Frontier - ability to swipe rcd for authorizations to build on specific grids
+ */
+ private void OnIdCardSwipeHappened(EntityUid uid, IdCardComponent comp, ref AfterInteractEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ if (args.Target is not { Valid: true } target || !args.CanReach)
+ return;
+
+ var rcdEntityUid = target;
+
+ // Is this id card interacting with a shipyard RCD ? if not, ignore it.
+ if (!TryComp(rcdEntityUid, out var rcdComponent) || !rcdComponent.IsShipyardRCD)
+ {
+ args.Handled = true;
+ return;
+ }
+
+ // If the id card has no registered ship we cant continue.
+ if (!TryComp(comp.Owner, out var shuttleDeedComponent))
+ {
+ _popup.PopupClient(Loc.GetString("rcd-component-missing-id-deed"),
+ uid, args.User, PopupType.Medium);
+ _audio.PlayPredicted(comp.ErrorSound, rcdEntityUid, args.User, AudioParams.Default.WithMaxDistance(0.01f));
+ args.Handled = true;
+ return;
+ }
+
+ // Swiping it again removes the authorization on it.
+ if (rcdComponent.LinkedShuttleUid != null)
+ {
+ _popup.PopupClient(Loc.GetString("rcd-component-id-card-removed"),
+ uid, args.User, PopupType.Medium);
+ _audio.PlayPredicted(comp.SwipeSound, rcdEntityUid, args.User, AudioParams.Default.WithMaxDistance(0.01f));
+ rcdComponent.LinkedShuttleUid = null;
+ }
+ else
+ {
+ _popup.PopupClient(Loc.GetString("rcd-component-id-card-accepted"),
+ uid, args.User, PopupType.Medium);
+ _audio.PlayPredicted(comp.InsertSound, rcdEntityUid, args.User, AudioParams.Default.WithMaxDistance(0.01f));
+ rcdComponent.LinkedShuttleUid = shuttleDeedComponent.ShuttleUid;
+ }
+
+ Dirty(rcdComponent.Owner, rcdComponent);
+ args.Handled = true;
+ }
+
private void OnAfterInteract(EntityUid uid, RCDComponent comp, AfterInteractEvent args)
{
if (args.Handled || !args.CanReach)
@@ -111,10 +164,48 @@ private void OnAfterInteract(EntityUid uid, RCDComponent comp, AfterInteractEven
args.Handled = true;
- if (_doAfter.TryStartDoAfter(doAfterArgs) && _gameTiming.IsFirstTimePredicted)
+ // IsAuthorized is part of frontier
+ if (IsAuthorized(gridId, uid, comp, args) && _doAfter.TryStartDoAfter(doAfterArgs) && _gameTiming.IsFirstTimePredicted)
Spawn("EffectRCDConstruction", location);
}
+ /**
+ * Frontier - Stops RCD functions if there is a protected grid component on it, and adds shipyard rcd limitations.
+ */
+ private bool IsAuthorized(EntityUid? gridId, EntityUid uid, RCDComponent comp, AfterInteractEvent args)
+ {
+ if (gridId == null)
+ {
+ return true;
+ }
+ var mapGrid = _mapMan.GetGrid(gridId.Value);
+ var gridUid = mapGrid.Owner;
+
+ // Frontier - Remove all RCD use on outpost.
+ if (HasComp(gridUid))
+ {
+ _popup.PopupClient(Loc.GetString("rcd-component-use-blocked"), uid, args.User);
+ return false;
+ }
+
+ // Frontier - LinkedShuttleUid requirements to use Shipyard RCD.
+ if (comp.IsShipyardRCD)
+ {
+ if (comp.LinkedShuttleUid == null)
+ {
+ _popup.PopupClient(Loc.GetString("rcd-component-no-id-swiped"), uid, args.User);
+ return false;
+ }
+ if (comp.LinkedShuttleUid != gridUid)
+ {
+ _popup.PopupClient(Loc.GetString("rcd-component-can-only-build-authorized-ship"), uid, args.User);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
private void OnDoAfterAttempt(EntityUid uid, RCDComponent comp, DoAfterAttemptEvent args)
{
// sus client crash why
@@ -162,14 +253,6 @@ private void OnDoAfter(EntityUid uid, RCDComponent comp, RCDDoAfterEvent args)
var tile = mapGrid.GetTileRef(location);
var snapPos = mapGrid.TileIndicesFor(location);
- // I love that this uses entirely separate code to construction and tile placement!!!
-
- var gridUid = mapGrid.Owner;
- var ev = new FloorTileAttemptEvent();
-
- if (HasComp(gridUid) || ev.Cancelled) // Frontier - Remove all RCD use on outpost.
- return;
-
switch (comp.Mode)
{
//Floor mode just needs the tile to be a space tile (subFloor)
diff --git a/Content.Shared/Shipyard/Components/ShuttleDeedComponent.cs b/Content.Shared/Shipyard/Components/ShuttleDeedComponent.cs
index ef66b5ff989..1ff534afbcb 100644
--- a/Content.Shared/Shipyard/Components/ShuttleDeedComponent.cs
+++ b/Content.Shared/Shipyard/Components/ShuttleDeedComponent.cs
@@ -1,9 +1,11 @@
+using Robust.Shared.GameStates;
+
namespace Content.Shared.Shipyard.Components;
///
/// Tied to an ID card when a ship is purchased. 1 ship per captain.
///
-[RegisterComponent, Access(typeof(SharedShipyardSystem))]
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedShipyardSystem))]
public sealed partial class ShuttleDeedComponent : Component
{
public const int MaxNameLength = 30;
diff --git a/Resources/Locale/en-US/_NF/research/technologies.ftl b/Resources/Locale/en-US/_NF/research/technologies.ftl
index b706785d5fe..450e9a9d736 100644
--- a/Resources/Locale/en-US/_NF/research/technologies.ftl
+++ b/Resources/Locale/en-US/_NF/research/technologies.ftl
@@ -1,4 +1,5 @@
research-techology-advanced-personal-propulsion = Advanced Personal Propulsion
+research-technology-rapid-construction = Rapid Construction
research-technology-hardsuits-basic = Basic Hardsuits
research-technology-hardsuits-specialized = Specialized Hardsuits
research-technology-hardsuits-advanced = Advanced Hardsuits
diff --git a/Resources/Locale/en-US/_NF/shipyard/shipyard-rcd-component.ftl b/Resources/Locale/en-US/_NF/shipyard/shipyard-rcd-component.ftl
new file mode 100644
index 00000000000..ee6dac465c4
--- /dev/null
+++ b/Resources/Locale/en-US/_NF/shipyard/shipyard-rcd-component.ftl
@@ -0,0 +1,8 @@
+## UI
+rcd-component-missing-id-deed = No ship registered to this ID
+rcd-component-can-only-build-authorized-ship = Can only build on authorized ships!
+rcd-component-no-id-swiped = Swipe id card on RCD to authorize.
+rcd-component-use-blocked = The RCD whirrs, but nothing happens.
+rcd-component-id-card-accepted = You swipe the id card and the RCD makes a accepting noise.
+rcd-component-id-card-removed = The RCD powers down, unauthorizing it.
+rcd-component-wrong-ammo-type = Wrong type of RCD ammo.
diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/engivend.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/engivend.yml
index 292d93ab452..0c11ae10c2e 100644
--- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/engivend.yml
+++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/engivend.yml
@@ -11,3 +11,5 @@
GeigerCounter: 10 # Frontier
PowerCellMedium: 15
# NetworkConfigurator: 15
+ ShipyardRCD: 10
+ ShipyardRCDAmmo: 20
diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
index e4e23c8ddc8..cfa378dec6f 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
@@ -283,6 +283,8 @@
- AnomalyLocatorWide
- RCD
- RCDAmmo
+ - ShipyardRCD # Frontier
+ - ShipyardRCDAmmo # Frontier
- Scalpel
- Retractor
- Cautery
diff --git a/Resources/Prototypes/Research/industrial.yml b/Resources/Prototypes/Research/industrial.yml
index 37beffccbbc..eafa72a0b21 100644
--- a/Resources/Prototypes/Research/industrial.yml
+++ b/Resources/Prototypes/Research/industrial.yml
@@ -198,3 +198,16 @@
- PowerCellMicroreactor
technologyPrerequisites:
- AdvancedPowercells
+
+- type: technology
+ id: RapidConstruction
+ name: research-technology-rapid-construction
+ icon:
+ sprite: Objects/Tools/rcd.rsi
+ state: icon
+ discipline: Industrial
+ tier: 2
+ cost: 10000
+ recipeUnlocks:
+ - ShipyardRCD
+ - ShipyardRCDAmmo
diff --git a/Resources/Prototypes/_NF/Entities/Objects/Tools/shipyard_rcd.yml b/Resources/Prototypes/_NF/Entities/Objects/Tools/shipyard_rcd.yml
new file mode 100644
index 00000000000..a2ef2214564
--- /dev/null
+++ b/Resources/Prototypes/_NF/Entities/Objects/Tools/shipyard_rcd.yml
@@ -0,0 +1,37 @@
+- type: entity
+ name: Shipyard RCD
+ parent: BaseItem
+ id: ShipyardRCD
+ description: An advanced construction device which can place/remove walls, floors, and airlocks quickly. It has a slot to swipe ID cards.
+ components:
+ - type: RCD
+ isShipyardRCD: true
+ - type: LimitedCharges
+ maxCharges: 5
+ charges: 5
+ - type: UseDelay
+ - type: Sprite
+ sprite: Objects/Tools/rcd.rsi
+ state: icon-shipyard
+ - type: Item
+ size: Normal
+ - type: Clothing
+ sprite: Objects/Tools/rcd.rsi
+ quickEquip: false
+ slots:
+ - Belt
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 5000
+ Plastic: 1000
+ - type: StaticPrice
+ price: 500
+
+- type: entity
+ id: ShipyardRCDEmpty
+ parent: ShipyardRCD
+ suffix: Empty
+ components:
+ - type: LimitedCharges
+ maxCharges: 5
+ charges: 0
diff --git a/Resources/Prototypes/_NF/Recipes/Lathes/devices.yml b/Resources/Prototypes/_NF/Recipes/Lathes/devices.yml
index 68f30ba047f..6565ac3cba6 100644
--- a/Resources/Prototypes/_NF/Recipes/Lathes/devices.yml
+++ b/Resources/Prototypes/_NF/Recipes/Lathes/devices.yml
@@ -35,3 +35,21 @@
Glass: 500
Plastic: 50
Gold: 100
+
+- type: latheRecipe
+ id: ShipyardRCD
+ result: ShipyardRCDEmpty
+ category: Tools
+ completetime: 4
+ materials:
+ Steel: 1000
+ Plastic: 300
+
+- type: latheRecipe
+ id: ShipyardRCDAmmo
+ result: ShipyardRCDAmmo
+ category: Tools
+ completetime: 2.4
+ materials:
+ Steel: 500
+ Plastic: 250
diff --git a/Resources/Prototypes/_NF/Recipes/Lathes/tools.yml b/Resources/Prototypes/_NF/Recipes/Lathes/tools.yml
new file mode 100644
index 00000000000..48ae087fd7a
--- /dev/null
+++ b/Resources/Prototypes/_NF/Recipes/Lathes/tools.yml
@@ -0,0 +1,20 @@
+- type: entity
+ name: Shipyard RCD Ammo
+ parent: BaseItem
+ id: ShipyardRCDAmmo
+ description: Ammo cartridge for a Shipyard RCD.
+ components:
+ - type: RCDAmmo
+ isShipyardRCDAmmo: true
+ - type: Sprite
+ sprite: Objects/Tools/rcd.rsi
+ state: ammo-shipyard
+ - type: Item
+ sprite: Objects/Tools/rcd.rsi
+ heldPrefix: ammo-shipyard
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 1000
+ Plastic: 1000
+ - type: StaticPrice
+ price: 100
diff --git a/Resources/Textures/Objects/Tools/rcd.rsi/ammo-shipyard.png b/Resources/Textures/Objects/Tools/rcd.rsi/ammo-shipyard.png
new file mode 100644
index 0000000000000000000000000000000000000000..e7ecb3099890d67d7eb22472a10e9bbfaded1f9a
GIT binary patch
literal 1927
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
z