From cffbf573bc6d7c37f2ad771bb33624091fc1e581 Mon Sep 17 00:00:00 2001 From: CrimeMoot Date: Wed, 18 Dec 2024 20:09:28 +0500 Subject: [PATCH 1/4] add RPD --- .../RCD/RCDConstructionGhostSystem.cs | 70 ++++- Content.Client/RCD/RCDMenu.xaml | 24 ++ .../Charges/Systems/ChargesSystem.cs | 3 +- .../Components/LimitedChargesComponent.cs | 5 +- .../Charges/Systems/SharedChargesSystem.cs | 9 +- .../RCD/Components/RCDAmmoComponent.cs | 3 +- Content.Shared/RCD/Components/RCDComponent.cs | 12 + .../Components/RCDDeconstructibleComponent.cs | 9 +- Content.Shared/RCD/RCDEvents.cs | 12 + Content.Shared/RCD/RCDPrototype.cs | 9 +- Content.Shared/RCD/Systems/RCDAmmoSystem.cs | 3 +- Content.Shared/RCD/Systems/RCDSystem.cs | 56 +++- .../en-US/rcd/components/rcd-component.ftl | 4 + .../ru-RU/rcd/components/rcd-component.ftl | 4 + .../Entities/Objects/Tools/tools.yml | 34 +++ .../Structures/Piping/Atmospherics/pipes.yml | 5 + Resources/Prototypes/RPD/rpd.yml | 251 ++++++++++++++++++ .../Textures/Interface/Radial/RPD/bend.png | Bin 0 -> 330 bytes .../Interface/Radial/RPD/dual_port.png | Bin 0 -> 777 bytes .../Textures/Interface/Radial/RPD/fourway.png | Bin 0 -> 679 bytes .../Interface/Radial/RPD/gas_filter.png | Bin 0 -> 369 bytes .../Interface/Radial/RPD/gas_mixer.png | Bin 0 -> 391 bytes .../Interface/Radial/RPD/injector.png | Bin 0 -> 368 bytes .../Interface/Radial/RPD/pneumatic_valve.png | Bin 0 -> 308 bytes .../Textures/Interface/Radial/RPD/port.png | Bin 0 -> 288 bytes .../Radial/RPD/pump_manual_valve.png | Bin 0 -> 334 bytes .../Interface/Radial/RPD/pump_pressure.png | Bin 0 -> 332 bytes .../Radial/RPD/pump_signal_valve.png | Bin 0 -> 283 bytes .../Interface/Radial/RPD/pump_volume.png | Bin 0 -> 274 bytes .../Interface/Radial/RPD/radiator.png | Bin 0 -> 280 bytes .../Interface/Radial/RPD/scrub_off.png | Bin 0 -> 820 bytes .../Interface/Radial/RPD/straight.png | Bin 0 -> 337 bytes .../Interface/Radial/RPD/tjunction.png | Bin 0 -> 359 bytes .../Interface/Radial/RPD/vent_off.png | Bin 0 -> 612 bytes .../Interface/Radial/RPD/vent_passive.png | Bin 0 -> 388 bytes .../Textures/Objects/Tools/rpd.rsi/icon.png | Bin 0 -> 872 bytes .../Objects/Tools/rpd.rsi/inhand-left.png | Bin 0 -> 1068 bytes .../Objects/Tools/rpd.rsi/inhand-right.png | Bin 0 -> 1100 bytes .../Textures/Objects/Tools/rpd.rsi/meta.json | 22 ++ 39 files changed, 513 insertions(+), 22 deletions(-) create mode 100644 Resources/Prototypes/RPD/rpd.yml create mode 100644 Resources/Textures/Interface/Radial/RPD/bend.png create mode 100644 Resources/Textures/Interface/Radial/RPD/dual_port.png create mode 100644 Resources/Textures/Interface/Radial/RPD/fourway.png create mode 100644 Resources/Textures/Interface/Radial/RPD/gas_filter.png create mode 100644 Resources/Textures/Interface/Radial/RPD/gas_mixer.png create mode 100644 Resources/Textures/Interface/Radial/RPD/injector.png create mode 100644 Resources/Textures/Interface/Radial/RPD/pneumatic_valve.png create mode 100644 Resources/Textures/Interface/Radial/RPD/port.png create mode 100644 Resources/Textures/Interface/Radial/RPD/pump_manual_valve.png create mode 100644 Resources/Textures/Interface/Radial/RPD/pump_pressure.png create mode 100644 Resources/Textures/Interface/Radial/RPD/pump_signal_valve.png create mode 100644 Resources/Textures/Interface/Radial/RPD/pump_volume.png create mode 100644 Resources/Textures/Interface/Radial/RPD/radiator.png create mode 100644 Resources/Textures/Interface/Radial/RPD/scrub_off.png create mode 100644 Resources/Textures/Interface/Radial/RPD/straight.png create mode 100644 Resources/Textures/Interface/Radial/RPD/tjunction.png create mode 100644 Resources/Textures/Interface/Radial/RPD/vent_off.png create mode 100644 Resources/Textures/Interface/Radial/RPD/vent_passive.png create mode 100644 Resources/Textures/Objects/Tools/rpd.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tools/rpd.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Tools/rpd.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Tools/rpd.rsi/meta.json diff --git a/Content.Client/RCD/RCDConstructionGhostSystem.cs b/Content.Client/RCD/RCDConstructionGhostSystem.cs index 792916b8922..de827b534b3 100644 --- a/Content.Client/RCD/RCDConstructionGhostSystem.cs +++ b/Content.Client/RCD/RCDConstructionGhostSystem.cs @@ -1,4 +1,5 @@ using Content.Shared.Hands.Components; +using Content.Shared.Input; using Content.Shared.Interaction; using Content.Shared.RCD; using Content.Shared.RCD.Components; @@ -6,6 +7,8 @@ using Robust.Client.Placement; using Robust.Client.Player; using Robust.Shared.Enums; +using Robust.Shared.Input; +using Robust.Shared.Input.Binding; namespace Content.Client.RCD; @@ -14,10 +17,55 @@ public sealed class RCDConstructionGhostSystem : EntitySystem [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly RCDSystem _rcdSystem = default!; [Dependency] private readonly IPlacementManager _placementManager = default!; - private string _placementMode = typeof(AlignRCDConstruction).Name; private Direction _placementDirection = default; + private bool _useMirrorPrototype = false; + public event EventHandler? FlipConstructionPrototype; + + public override void Initialize() + { + base.Initialize(); + + // bind key + CommandBinds.Builder + .Bind(ContentKeyFunctions.EditorFlipObject, + new PointerInputCmdHandler(HandleFlip, outsidePrediction: true)) + .Register(); + } + + public override void Shutdown() + { + CommandBinds.Unregister(); + base.Shutdown(); + } + + private bool HandleFlip(in PointerInputCmdHandler.PointerInputCmdArgs args) + { + if (args.State == BoundKeyState.Down) + { + if (!_placementManager.IsActive || _placementManager.Eraser) + return false; + + var placerEntity = _placementManager.CurrentPermission?.MobUid; + + if(!TryComp(placerEntity, out var rcd) || + string.IsNullOrEmpty(rcd.CachedPrototype.MirrorPrototype)) + return false; + + _useMirrorPrototype = !rcd.UseMirrorPrototype; + + var useProto = _useMirrorPrototype ? rcd.CachedPrototype.MirrorPrototype : rcd.CachedPrototype.Prototype; + CreatePlacer(placerEntity.Value, rcd, useProto); + + // tell the server + + RaiseNetworkEvent(new RCDConstructionGhostFlipEvent(GetNetEntity(placerEntity.Value), _useMirrorPrototype)); + } + + return true; + } + public override void Update(float frameTime) { base.Update(frameTime); @@ -55,20 +103,28 @@ public override void Update(float frameTime) RaiseNetworkEvent(new RCDConstructionGhostRotationEvent(GetNetEntity(heldEntity.Value), _placementDirection)); } - // If the placer has not changed, exit + // If the placer has not changed build it. _rcdSystem.UpdateCachedPrototype(heldEntity.Value, rcd); + var useProto = (_useMirrorPrototype && !string.IsNullOrEmpty(rcd.CachedPrototype.MirrorPrototype)) ? rcd.CachedPrototype.MirrorPrototype : rcd.CachedPrototype.Prototype; - if (heldEntity == placerEntity && rcd.CachedPrototype.Prototype == placerProto) - return; + if (heldEntity != placerEntity || useProto != placerProto) + { + CreatePlacer(heldEntity.Value, rcd, useProto); + } + + } + + private void CreatePlacer(EntityUid uid, RCDComponent component, string? prototype) + { // Create a new placer var newObjInfo = new PlacementInformation { - MobUid = heldEntity.Value, + MobUid = uid, PlacementOption = _placementMode, - EntityType = rcd.CachedPrototype.Prototype, + EntityType = prototype, Range = (int) Math.Ceiling(SharedInteractionSystem.InteractionRange), - IsTile = (rcd.CachedPrototype.Mode == RcdMode.ConstructTile), + IsTile = (component.CachedPrototype.Mode == RcdMode.ConstructTile), UseEditorContext = false, }; diff --git a/Content.Client/RCD/RCDMenu.xaml b/Content.Client/RCD/RCDMenu.xaml index b3d5367a5fd..3ce765fe2de 100644 --- a/Content.Client/RCD/RCDMenu.xaml +++ b/Content.Client/RCD/RCDMenu.xaml @@ -27,6 +27,18 @@ + + + + + + + + + + + + @@ -44,4 +56,16 @@ + + + + + + + + + + + + diff --git a/Content.Server/Charges/Systems/ChargesSystem.cs b/Content.Server/Charges/Systems/ChargesSystem.cs index 974928ee4bb..d60d524a8dc 100644 --- a/Content.Server/Charges/Systems/ChargesSystem.cs +++ b/Content.Server/Charges/Systems/ChargesSystem.cs @@ -2,6 +2,7 @@ using Content.Shared.Charges.Components; using Content.Shared.Charges.Systems; using Content.Shared.Examine; +using Content.Shared.FixedPoint; using Robust.Shared.Timing; namespace Content.Server.Charges.Systems; @@ -37,7 +38,7 @@ protected override void OnExamine(EntityUid uid, LimitedChargesComponent comp, E args.PushMarkup(Loc.GetString("limited-charges-recharging", ("seconds", timeRemaining))); } - public override void AddCharges(EntityUid uid, int change, LimitedChargesComponent? comp = null) + public override void AddCharges(EntityUid uid, FixedPoint2 change, LimitedChargesComponent? comp = null) { if (!Query.Resolve(uid, ref comp, false)) return; diff --git a/Content.Shared/Charges/Components/LimitedChargesComponent.cs b/Content.Shared/Charges/Components/LimitedChargesComponent.cs index 6973ffbe72e..4d989fc8ad1 100644 --- a/Content.Shared/Charges/Components/LimitedChargesComponent.cs +++ b/Content.Shared/Charges/Components/LimitedChargesComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Charges.Systems; +using Content.Shared.FixedPoint; using Robust.Shared.GameStates; namespace Content.Shared.Charges.Components; @@ -13,12 +14,12 @@ public sealed partial class LimitedChargesComponent : Component /// [DataField("maxCharges"), ViewVariables(VVAccess.ReadWrite)] [AutoNetworkedField] - public int MaxCharges = 3; + public FixedPoint2 MaxCharges = 3; /// /// The current number of charges /// [DataField("charges"), ViewVariables(VVAccess.ReadWrite)] [AutoNetworkedField] - public int Charges = 3; + public FixedPoint2 Charges = 3; } diff --git a/Content.Shared/Charges/Systems/SharedChargesSystem.cs b/Content.Shared/Charges/Systems/SharedChargesSystem.cs index 7f95ef184e4..023d68b2ea0 100644 --- a/Content.Shared/Charges/Systems/SharedChargesSystem.cs +++ b/Content.Shared/Charges/Systems/SharedChargesSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.Charges.Components; using Content.Shared.Examine; +using Content.Shared.FixedPoint; namespace Content.Shared.Charges.Systems; @@ -34,13 +35,13 @@ protected virtual void OnExamine(EntityUid uid, LimitedChargesComponent comp, Ex /// /// Tries to add a number of charges. If it over or underflows it will be clamped, wasting the extra charges. /// - public virtual void AddCharges(EntityUid uid, int change, LimitedChargesComponent? comp = null) + public virtual void AddCharges(EntityUid uid, FixedPoint2 change, LimitedChargesComponent? comp = null) { if (!Query.Resolve(uid, ref comp, false)) return; var old = comp.Charges; - comp.Charges = Math.Clamp(comp.Charges + change, 0, comp.MaxCharges); + comp.Charges = FixedPoint2.Clamp(comp.Charges + change, 0, comp.MaxCharges); if (comp.Charges != old) Dirty(uid, comp); } @@ -84,7 +85,7 @@ public bool TryUseCharge(Entity ent) /// Gets the limited charges component and returns true if the number of charges remaining is less than the specified value. /// Will return false if there is no limited charges component. /// - public bool HasInsufficientCharges(EntityUid uid, int requiredCharges, LimitedChargesComponent? comp = null) + public bool HasInsufficientCharges(EntityUid uid, FixedPoint2 requiredCharges, LimitedChargesComponent? comp = null) { // can't be empty if there are no limited charges if (!Resolve(uid, ref comp, false)) @@ -96,7 +97,7 @@ public bool HasInsufficientCharges(EntityUid uid, int requiredCharges, LimitedCh /// /// Uses up a specified number of charges. Must check HasInsufficentCharges beforehand to prevent using with insufficient remaining charges. /// - public virtual void UseCharges(EntityUid uid, int chargesUsed, LimitedChargesComponent? comp = null) + public virtual void UseCharges(EntityUid uid, FixedPoint2 chargesUsed, LimitedChargesComponent? comp = null) { AddCharges(uid, -chargesUsed, comp); } diff --git a/Content.Shared/RCD/Components/RCDAmmoComponent.cs b/Content.Shared/RCD/Components/RCDAmmoComponent.cs index 4135b606e22..30d63c309bc 100644 --- a/Content.Shared/RCD/Components/RCDAmmoComponent.cs +++ b/Content.Shared/RCD/Components/RCDAmmoComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.FixedPoint; using Content.Shared.RCD.Systems; using Robust.Shared.GameStates; @@ -12,5 +13,5 @@ public sealed partial class RCDAmmoComponent : Component /// Can be partially transferred into an RCD, until it is empty then it gets deleted. /// [DataField("charges"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public int Charges = 30; + public FixedPoint2 Charges = 30; } diff --git a/Content.Shared/RCD/Components/RCDComponent.cs b/Content.Shared/RCD/Components/RCDComponent.cs index 39bb6fd3e9f..1e00a6b9c21 100644 --- a/Content.Shared/RCD/Components/RCDComponent.cs +++ b/Content.Shared/RCD/Components/RCDComponent.cs @@ -42,6 +42,18 @@ public sealed partial class RCDComponent : Component [ViewVariables(VVAccess.ReadOnly)] public RCDPrototype CachedPrototype { get; set; } = default!; + /// + /// Indicates if a mirrored version of the construction prototype should be used (if available) + /// + [AutoNetworkedField, ViewVariables(VVAccess.ReadOnly)] + public bool UseMirrorPrototype = false; + + /// + /// Indicates whether this is an RCD or an RPD + /// + [DataField, AutoNetworkedField] + public bool IsRpd { get; set; } = false; + /// /// The direction constructed entities will face upon spawning /// diff --git a/Content.Shared/RCD/Components/RCDDeconstructibleComponent.cs b/Content.Shared/RCD/Components/RCDDeconstructibleComponent.cs index 0ddc6897f05..61d62f30270 100644 --- a/Content.Shared/RCD/Components/RCDDeconstructibleComponent.cs +++ b/Content.Shared/RCD/Components/RCDDeconstructibleComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.FixedPoint; using Content.Shared.RCD.Systems; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -12,7 +13,7 @@ public sealed partial class RCDDeconstructableComponent : Component /// Number of charges consumed when the deconstruction is completed /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public int Cost = 1; + public FixedPoint2 Cost = 1; /// /// The length of the deconstruction @@ -31,4 +32,10 @@ public sealed partial class RCDDeconstructableComponent : Component /// [DataField, ViewVariables(VVAccess.ReadWrite)] public bool Deconstructable = true; + + /// + /// Toggles whether this entity is deconstructable by the RPD or not + /// + [DataField("rpd"), ViewVariables(VVAccess.ReadWrite)] + public bool RpdDeconstructable = false; } diff --git a/Content.Shared/RCD/RCDEvents.cs b/Content.Shared/RCD/RCDEvents.cs index a15a010277b..f3a2070bc21 100644 --- a/Content.Shared/RCD/RCDEvents.cs +++ b/Content.Shared/RCD/RCDEvents.cs @@ -27,6 +27,18 @@ public RCDConstructionGhostRotationEvent(NetEntity netEntity, Direction directio } } +[Serializable, NetSerializable] +public sealed class RCDConstructionGhostFlipEvent : EntityEventArgs +{ + public readonly NetEntity NetEntity; + public readonly bool UseMirrorPrototype; + public RCDConstructionGhostFlipEvent(NetEntity netEntity, bool useMirrorPrototype) + { + NetEntity = netEntity; + UseMirrorPrototype = useMirrorPrototype; + } +} + [Serializable, NetSerializable] public enum RcdUiKey : byte { diff --git a/Content.Shared/RCD/RCDPrototype.cs b/Content.Shared/RCD/RCDPrototype.cs index 58093bbe87a..576bf63076d 100644 --- a/Content.Shared/RCD/RCDPrototype.cs +++ b/Content.Shared/RCD/RCDPrototype.cs @@ -1,3 +1,4 @@ +using Content.Shared.FixedPoint; using Content.Shared.Physics; using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Prototypes; @@ -44,11 +45,17 @@ public sealed partial class RCDPrototype : IPrototype [DataField, ViewVariables(VVAccess.ReadOnly)] public string? Prototype { get; private set; } = string.Empty; + /// + /// If the entity can be flipped, this prototype is available as an alternate (mode dependent) + /// + [DataField, ViewVariables(VVAccess.ReadOnly)] + public string? MirrorPrototype { get; private set; } = string.Empty; + /// /// Number of charges consumed when the operation is completed /// [DataField, ViewVariables(VVAccess.ReadOnly)] - public int Cost { get; private set; } = 1; + public FixedPoint2 Cost { get; private set; } = 1; /// /// The length of the operation diff --git a/Content.Shared/RCD/Systems/RCDAmmoSystem.cs b/Content.Shared/RCD/Systems/RCDAmmoSystem.cs index 9cb3c264851..c8b758b2488 100644 --- a/Content.Shared/RCD/Systems/RCDAmmoSystem.cs +++ b/Content.Shared/RCD/Systems/RCDAmmoSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Charges.Components; using Content.Shared.Charges.Systems; using Content.Shared.Examine; +using Content.Shared.FixedPoint; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.RCD.Components; @@ -43,7 +44,7 @@ private void OnAfterInteract(EntityUid uid, RCDAmmoComponent comp, AfterInteract var user = args.User; args.Handled = true; - var count = Math.Min(charges.MaxCharges - charges.Charges, comp.Charges); + var count = FixedPoint2.Min(charges.MaxCharges - charges.Charges,comp.Charges); if (count <= 0) { _popup.PopupClient(Loc.GetString("rcd-ammo-component-after-interact-full"), target, user); diff --git a/Content.Shared/RCD/Systems/RCDSystem.cs b/Content.Shared/RCD/Systems/RCDSystem.cs index 99d27137013..19951039605 100644 --- a/Content.Shared/RCD/Systems/RCDSystem.cs +++ b/Content.Shared/RCD/Systems/RCDSystem.cs @@ -25,6 +25,7 @@ using Robust.Shared.Timing; using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Shared.FixedPoint; namespace Content.Shared.RCD.Systems; @@ -65,6 +66,8 @@ public override void Initialize() SubscribeLocalEvent>(OnDoAfterAttempt); SubscribeLocalEvent(OnRCDSystemMessage); SubscribeNetworkEvent(OnRCDconstructionGhostRotationEvent); + SubscribeNetworkEvent(OnRCDConstructionGhostFlipEvent); + } #region Event handling @@ -303,6 +306,26 @@ private void OnRCDconstructionGhostRotationEvent(RCDConstructionGhostRotationEve Dirty(uid, rcd); } + private void OnRCDConstructionGhostFlipEvent(RCDConstructionGhostFlipEvent ev, EntitySessionEventArgs session) + { + var uid = GetEntity(ev.NetEntity); + + // Determine if player that send the message is carrying the specified RCD in their active hand + if (session.SenderSession.AttachedEntity == null) + return; + + if (!TryComp(session.SenderSession.AttachedEntity, out var hands) || + uid != hands.ActiveHand?.HeldEntity) + return; + + if (!TryComp(uid, out var rcd)) + return; + + // Update the construction direction + rcd.UseMirrorPrototype = ev.UseMirrorPrototype; + Dirty(uid, rcd); + } + #endregion #region Entity construction/deconstruction rule checks @@ -457,6 +480,13 @@ private bool IsDeconstructionStillValid(EntityUid uid, RCDComponent component, M // Attempt to deconstruct a floor tile if (target == null) { + if (component.IsRpd) + { + if (popMsgs) + _popup.PopupClient(Loc.GetString("rcd-component-deconstruct-target-not-on-whitelist-message"), uid, user); + + return false; + } // The tile is empty if (mapGridData.Tile.Tile.IsEmpty) { @@ -490,6 +520,15 @@ private bool IsDeconstructionStillValid(EntityUid uid, RCDComponent component, M // Attempt to deconstruct an object else { + // The object is not in the RPD whitelist + if (!deconstructible.Deconstructable) + { + if (popMsgs) + _popup.PopupClient(Loc.GetString("rcd-component-deconstruct-target-not-on-whitelist-message"), uid, user); + + return false; + } + // The object is not in the whitelist if (!TryComp(target, out var deconstructible) || !deconstructible.Deconstructable) { @@ -523,7 +562,12 @@ private void FinalizeRCDOperation(EntityUid uid, RCDComponent component, MapGrid break; case RcdMode.ConstructObject: - var ent = Spawn(component.CachedPrototype.Prototype, _mapSystem.GridTileToLocal(mapGridData.GridUid, mapGridData.Component, mapGridData.Position)); + var proto = (component.UseMirrorPrototype && + !string.IsNullOrEmpty(component.CachedPrototype.MirrorPrototype)) + ? component.CachedPrototype.MirrorPrototype + : component.CachedPrototype.Prototype; + + var ent = Spawn(proto, _mapSystem.GridTileToLocal(mapGridData.GridUid, mapGridData.Component, mapGridData.Position)); switch (component.CachedPrototype.Rotation) { @@ -597,8 +641,12 @@ private bool DoesCustomBoundsIntersectWithFixture(PolygonShape boundingPolygon, public void UpdateCachedPrototype(EntityUid uid, RCDComponent component) { - if (component.ProtoId.Id != component.CachedPrototype?.Prototype) + if (component.ProtoId.Id != component.CachedPrototype?.Prototype || + (component.CachedPrototype?.MirrorPrototype != null && + component.ProtoId.Id!= component.CachedPrototype?.MirrorPrototype)) + { component.CachedPrototype = _protoManager.Index(component.ProtoId); + } } #endregion @@ -635,14 +683,14 @@ public sealed partial class RCDDoAfterEvent : DoAfterEvent public ProtoId StartingProtoId { get; private set; } = default!; [DataField] - public int Cost { get; private set; } = 1; + public FixedPoint2 Cost { get; private set; } = 1; [DataField("fx")] public NetEntity? Effect { get; private set; } = null; private RCDDoAfterEvent() { } - public RCDDoAfterEvent(NetCoordinates location, Direction direction, ProtoId startingProtoId, int cost, NetEntity? effect = null) + public RCDDoAfterEvent(NetCoordinates location, Direction direction, ProtoId startingProtoId, FixedPoint2 cost, NetEntity? effect = null) { Location = location; Direction = direction; diff --git a/Resources/Locale/en-US/rcd/components/rcd-component.ftl b/Resources/Locale/en-US/rcd/components/rcd-component.ftl index 9741bde388c..73dbb619764 100644 --- a/Resources/Locale/en-US/rcd/components/rcd-component.ftl +++ b/Resources/Locale/en-US/rcd/components/rcd-component.ftl @@ -45,3 +45,7 @@ rcd-component-lighting = Lighting rcd-component-deconstruct = deconstruct rcd-component-floor-steel = steel tile rcd-component-plating = hull plate +rcd-component-piping = Piping +rcd-component-atmosphericutility = Atmospheric Utility +rcd-component-pumps = Pumps & Valves +rcd-component-vents = Vents diff --git a/Resources/Locale/ru-RU/rcd/components/rcd-component.ftl b/Resources/Locale/ru-RU/rcd/components/rcd-component.ftl index 9197f3dd219..168e1eafac3 100644 --- a/Resources/Locale/ru-RU/rcd/components/rcd-component.ftl +++ b/Resources/Locale/ru-RU/rcd/components/rcd-component.ftl @@ -38,3 +38,7 @@ rcd-component-lighting = Освещение rcd-component-deconstruct = демонтаж rcd-component-floor-steel = стальной пол rcd-component-plating = корпусное покрытие +rcd-component-piping = Трубопроводы +rcd-component-atmosphericutility = Атмосферные утилиты +rcd-component-pumps = Насосы и клапаны +rcd-component-vents = Вентиляционные отверстия diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index 6fd9b97afb3..eadaca1af39 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -359,6 +359,40 @@ inHandsOnly: true key: enum.RcdUiKey.Key +- type: entity + id: RPD + parent: RCD + name: RPD + description: Устройство, используемое для быстрой передачи информации по каналам. + components: + - type: RCD + isRpd: true + availablePrototypes: + - PipeFourway + - PipeStraight + - PipeBend + - PipeTJunction + - OutletInjector + - ManualValve + - VolumetricPump + - PressurePump + - VentScrubber + - PressureValve + - DualPortVent + - VentGas + - VentPassive + - MixerGas + - Radiator + - SignalValve + - CanisterPort + - FilterGas + - Deconstruct + - type: LimitedCharges + maxCharges: 45 + charges: 45 + - type: Sprite + sprite: Objects/Tools/rpd.rsi + - type: entity id: RCDEmpty parent: RCD diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml index f54b704a645..ae9687e920d 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml @@ -19,6 +19,11 @@ - type: PipeAppearance - type: Anchorable - type: Rotatable + - type: RCDDeconstructable + cost: 0.5 + delay: 2 + fx: EffectRCDDeconstruct2 + rpd: true - type: Destructible thresholds: - trigger: # for nukes diff --git a/Resources/Prototypes/RPD/rpd.yml b/Resources/Prototypes/RPD/rpd.yml new file mode 100644 index 00000000000..20b03a2497b --- /dev/null +++ b/Resources/Prototypes/RPD/rpd.yml @@ -0,0 +1,251 @@ +- type: rcd + id: PipeFourway + category: Piping + sprite: /Textures/Interface/Radial/RPD/fourway.png + mode: ConstructObject + prototype: GasPipeFourway + cost: 0.5 + delay: 0 + rules: + - MustBuildOnSubfloor + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: PipeStraight + category: Piping + sprite: /Textures/Interface/Radial/RPD/straight.png + mode: ConstructObject + prototype: GasPipeStraight + cost: 0.5 + delay: 0 + rules: + - MustBuildOnSubfloor + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: PipeBend + category: Piping + sprite: /Textures/Interface/Radial/RPD/bend.png + mode: ConstructObject + prototype: GasPipeBend + cost: 0.5 + delay: 0 + rules: + - MustBuildOnSubfloor + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: PipeTJunction + category: Piping + sprite: /Textures/Interface/Radial/RPD/tjunction.png + mode: ConstructObject + prototype: GasPipeTJunction + cost: 0.5 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: PressurePump + category: PumpsValves + sprite: /Textures/Interface/Radial/RPD/pump_pressure.png + mode: ConstructObject + prototype: GasPressurePump + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: VolumetricPump + category: PumpsValves + sprite: /Textures/Interface/Radial/RPD/pump_volume.png + mode: ConstructObject + prototype: GasPressurePump + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: ManualValve + category: PumpsValves + sprite: /Textures/Interface/Radial/RPD/pump_manual_valve.png + mode: ConstructObject + prototype: GasValve + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: SignalValve + category: PumpsValves + sprite: /Textures/Interface/Radial/RPD/pump_signal_valve.png + mode: ConstructObject + prototype: SignalControlledValve + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: PressureValve + category: PumpsValves + sprite: /Textures/Interface/Radial/RPD/pneumatic_valve.png + mode: ConstructObject + prototype: PressureControlledValve + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + + +- type: rcd + id: OutletInjector + category: Vents + sprite: /Textures/Interface/Radial/RPD/injector.png + mode: ConstructObject + prototype: GasOutletInjector + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: VentScrubber + category: Vents + sprite: /Textures/Interface/Radial/RPD/scrub_off.png + mode: ConstructObject + prototype: GasVentScrubber + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: VentGas + category: Vents + sprite: /Textures/Interface/Radial/RPD/vent_off.png + mode: ConstructObject + prototype: GasVentPump + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: DualPortVent + category: Vents + sprite: /Textures/Interface/Radial/RPD/dual_port.png + mode: ConstructObject + prototype: GasDualPortVentPump + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: VentPassive + category: Vents + sprite: /Textures/Interface/Radial/RPD/vent_passive.png + mode: ConstructObject + prototype: GasPassiveVent + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: Radiator + category: AtmosphericUtility + sprite: /Textures/Interface/Radial/RPD/radiator.png + mode: ConstructObject + prototype: HeatExchanger + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: MixerGas + category: AtmosphericUtility + sprite: /Textures/Interface/Radial/RPD/gas_mixer.png + mode: ConstructObject + prototype: GasMixer + mirrorPrototype: GasMixerFlipped + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: FilterGas + category: AtmosphericUtility + sprite: /Textures/Interface/Radial/RPD/gas_filter.png + mode: ConstructObject + prototype: GasFilter + mirrorPrototype: GasFilterFlipped + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 + +- type: rcd + id: CanisterPort + category: AtmosphericUtility + sprite: /Textures/Interface/Radial/RPD/port.png + mode: ConstructObject + prototype: GasPort + cost: 1 + delay: 0 + rules: + - MustBuildOnSubfloor + collisionMask: Impassable + rotation: User + fx: EffectRCDConstruct0 \ No newline at end of file diff --git a/Resources/Textures/Interface/Radial/RPD/bend.png b/Resources/Textures/Interface/Radial/RPD/bend.png new file mode 100644 index 0000000000000000000000000000000000000000..c62cf62220d0fe145cc17c2568896ca5c10d210c GIT binary patch literal 330 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyu>n3Iu9A|H9v&Wbb#-xZam~%m zyLRmg2?=RyYm=9kmywa#vuDrt?b{t49cRv*Ieq%{9Xobx-MV$lmM#1D@87p?pRBB` zw6wIMqN0?PRAgjiPft&0XXnnHI~y7rl9G~uHW>ZzbOBQGB|(0{|M3Ebvyx>3K&7>w zE{-7Bn<=4&?KX-%|NFORAc-V%K8zu`h=7nMo2B`*)`cm4H5W!WMZ^&j#Z#FVdE z9dOvN@EVuan;5xoZqm0ok5%=reSM)ZKePG(tF6TxwL7T}6)S`f+p?#mu?#}P``<&nXo!>bZ&RFN{7k|_btgo-*cDqR=6722m+49w9#|XgbbTTzHW!JoQfOI+yKp+sHqod<=0ovQ!%f@YO z6pKaM!EFPSN+miwJ1GXYA{-eR(ZyKPG|NuCUav8po11GG!_g>sBoYB2lgS`S zl4Sq@MN!01Zv=57fY8=vns{=pso((7!9Ieau<5*p0GUh%RaGrJ6WZELqpB)h7cSZd z&@>H6lGxr=+1^!A{Fkf#fA!{VUAxKgQ6pnLfvcvqWBLkudt_u;rpqN&71xXB&rSr7 z4)&p{s+ntZfNVBvWI(Ly+7%xzmkWT;8()pN;`#MZ(3tD?cx#8a0|$p$9z7lfU}!i>VyRpMq7Fn2hzxi<=4VAifK)2Q^6CZv1N}Gn z^l_D3F2|Q|-;Fu>Tn?b-`S$KV*oKlMRrLX}`bMhEf+R_;H=@c;IQ{Z<-8qxv)nJvK z&`c)+i2Yuff$67DOdSGMJE5{~Gz9?VBlXwMA9btT3WTC4q*5vS006;I*wU%?w<_)f z4Rz)>B3ttLeEQhfn7+8UsL#yI=zhOnH@B)U+qYte!-1~rXLBpob)9@ZkJIUFDY$I_ zvFcK(WPBr>DgZz@Ts|3hc6K;AIy!xT5({%`afQ6@Ag3_90>00000NkvXX Hu0mjfV7P3Q literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Radial/RPD/fourway.png b/Resources/Textures/Interface/Radial/RPD/fourway.png new file mode 100644 index 0000000000000000000000000000000000000000..336d930022d9d80f5fc958a0b1cbebc480b2e3a2 GIT binary patch literal 679 zcmV;Y0$BZtP)*3W()+_buUSu!N&{C_z)_xulNT$xNpIgX zN~hDhDFBG*21+TpxVQ)<9tvPE7ywW#7Kuiqy9E$Jd;~`#ESF1daczJg2#Cky%;)n^ z;@SX8eKh^55<3Uj1lc)2EEfB6-#NhB+ZzBcFE61144t5CHv6Uai^YQJbgGq0YZ6+P zMYUQbnM~5}_vv=KOs7+wR6kPzfbn>&SAow)vYKd~=l$_wG#bUSEFK;n$mjFewoSQQ z=KlVkUatqBEX!gtnfz1qbAGc_DzP$@VzJ0_x!iibTdfwgT8(FJ4F zF2~{FAppr_a{c_^-~go*hGC$TVm_ZEr6dRfj*pLNG#a?BYnYDXs7j^6&CSi)VB+!k zR)D*^I{@14HYX=19336;`1r{6^)&$fejk8Nr?WNw_4O5iQmM4Ib7OOv5JGG{6Q$ICwqm6e&(F_DDMN{C z1FXI}2!j3e0DKq8VzmX&;Yl$x45or%x1Gt0PpX^0_!#3kre;{ N002ovPDHLkV1nxWK&b!# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Radial/RPD/gas_filter.png b/Resources/Textures/Interface/Radial/RPD/gas_filter.png new file mode 100644 index 0000000000000000000000000000000000000000..35096091a82e1f99593bcecaf96415061ab9c86b GIT binary patch literal 369 zcmV-%0gnEOP);i%vqwBhPbfur(^nQVMZU zO=z0Nn|YEX$}uH?X`-!63(*1qK$@n?F-j?_s=_b~(($^kP2tS|ra(Wp8}4np=+}YI z^=b9jlNe)*_A!pvgjxqs6vYH_zFhEqy-KsN8GwKQ;ACzMaE#+c+6BbDZJoBjScG91 zPH7gJub46Blm#O|mSq6`_F71!-__g-fO8H?>0~P8!yK@zfqB*YG`9v25c6->;(Hlj zEA1!Y+fPEP+fa40an1n%U#HV{05*5Ji?jefpJgut_;`-l=zJ|qKBF0pfnEPyFS?)*;%eIDI1ak5>%TqEL(?=yqq?rOUVnl@h-;E0#>3_)O;atz z+t`Mxs#Y`ieSb7J3NW=10Eh_8Y+N&S5hDNqNGXl^APCU5tu|Md<<#-h0J?*QH~%`H z5yde+PbYj|F8!J*aHUtPRX1X05D@@q&F|4H00jYHk@+G31+m238i0uKemGdiR|Rlg z7tD+(ju)HhWb6V}XiBQ!qB#B)1LoI)5rCN?r9@elAfnzx72q(oX%`HQ)|M5(ShYW_ z3&!-2F4$VL0B*Zu$)9-oEU=n}y2+Mh8Nx6`p66)W79YpsHUOrX&dex^VwSNLz?#pp ly8))2V{7T@&+=WnegOTEp{kc0t`qb;z6ox-n9Rouwj^LTeL(bqEFy;iFIY0*n!&RW;O%F+=UPFN7cgKU8ZCfYzGTYV~FRLj`VWn*7mOiV zz~h`7uKkXrkR;%o8`T;KSudPQn<8 zm~i+Df5Urbvsn)?pU+t=7F;eDj>jVa=kqywUi3Ne5h9AB5Sz_Llw~OZkrJLH0FY%F z%jFV){eDlL=P6^-1@5_CufH$QbsgL7HaU2-z;3sru4_)G(`bo_r}7T7j%v_e=sp+# O000031$zxfufW&c(!`F}HH#cv;|7yRDqA}3`0000ST5Ji8Yh>FfLFai=Ki+Be{VFwnmu3UO|mBmz%_ao7n}tE0Bzf{ z!{>Qs_p$-F#u88fxKqVxnnY$f_elV2EkX!z&WVDZa|j{8TB`%NLIr>XSe8X)&bd#H zq4yqL*NGQV-}i_y!h4_WO-_MEKQRTOO(@-Rrvga!`{@9hCs_@U^At;z^(CvS3j4ml m&UIa5+qRD$sV`YkQPC4k)JGmAsq~2e00002m3p`SIg7kuTfMu~3S%{W<0#Vbf ztB@jZ0>L8lm2dv{&(9m)fMFQMeIRR=X%W?n2E4R5WPgn3;D zc-#;Io&VIqw gH=$t|hH-Vi01gOSE^ug3#sB~S07*qoM6N<$g6E%#djJ3c literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Radial/RPD/pump_pressure.png b/Resources/Textures/Interface/Radial/RPD/pump_pressure.png new file mode 100644 index 0000000000000000000000000000000000000000..aee0831c849248ce336abc1cf45da0b2f9c36c1f GIT binary patch literal 332 zcmV-S0ki&zP)1pw6o!A5&N_f0OP3BAdWG}?#VxH3Hh9P}TIf+c=mcJ!3wSUTWNZ+a8sfPbtRe2E zP8nLd_zhAB`bNS3^zrzG0FTGxaSWq`IOpc?nbw*#YjKEkZo)7G03=C*wr$Zg4T_>5 zNn9@toaltWn-Bnib(T@b&;{06_G<&y1b&^AR^M&$!=g@Hq?^$B`^>wKSl$W@Wj< z_k6^D+~aWgLRs#}e*qcJxp{hgF#ml_RwbNWeld`X^RZf)AP6u`6K<6v&sqEmPB6y6 enBC%gE|VX-$8A7{l5-mX0000O@wT#6+clF0za zJm<8T(F~@9Vd(PvG=rqToOol-+@Dxi7uj8py&I*^UPoK+c*}# hg1`R*ilQir@&FScNU&8|=;Z(a002ovPDHLkV1j@RaB2Vm literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Radial/RPD/pump_volume.png b/Resources/Textures/Interface/Radial/RPD/pump_volume.png new file mode 100644 index 0000000000000000000000000000000000000000..a3110ec00e3540fd4e70c7d578f5cef5a738e276 GIT binary patch literal 274 zcmV+t0qy>YP)0C}F%G!1oKqpBu}#n`|dRYg?+xC>eMFeiaD zO{c`C3p|1-5CvXapeTyT0;WYY3|F?>4eQm4pVNu9ZOsCsf53b1s%p>gaOK>d>ADM5 zwKv}aGa?eczjooj!}L^%*_s2CWjU|FBQOunVYv)RlF;`(pU0!Qj(HC_=Wy=1gCBWM YZtFlq)$I4mc>n+a07*qoM6N<$g6W5LOaK4? literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Radial/RPD/radiator.png b/Resources/Textures/Interface/Radial/RPD/radiator.png new file mode 100644 index 0000000000000000000000000000000000000000..420d68bc7337e8dde7120a141ffc4f9a05aed16d GIT binary patch literal 280 zcmV+z0q6dSP)48LLC9T_W+2<7ziN%q?It`)l6I!{ubn{q3pU&Gi`(s5&FJYy<<89 z=?nAcxiO2W0n%yDMY5%yjaLOoS1pNd`PBjTvIbxRxLj}1;#UWFKJL!qR|nX`8bAYR z0PRO~tS$I&fOl0KQ+2%MYfV)Z!)L`ifm)1f%(Ml0@;O1PIQ&3ka){P!5oFRG7v(Ft ehD#zv?fDDvFM{is>b(~L0000jx?LUzuSRCbg+qSn7veCvc3}-?Jf*@czol+D9 zS(cIKIYJ05%fd8G48tIbBJw=nSj5^4gkd;4IXTh6Ez2UyGLqYvL83T1aP?j(r4|Xy zHW5);M=pfW+(;s_a6Xw`Qk?$$E8#%QK?j@)oO2s!{OUyJS#mA1Ob!Dge=Q=e%#Px zt~;;$^Wz3ZQRwfp^9xMVL`td8UtV6W%)n9sX__(`edhjtZn)om|ATg`$=Ue@0H$ej zbA6?S)xEh7y1l+O=5+dOZ5dX203gqEZMbf)&v+ysk>6ZjVVb5Uhq*EHJYN@jGXX*f zeWP}(N!{})ib9hw%24-wZOo$s7a_z(0+yD*wrxDG%w%E#@YBz~P!xssK;82-`FJEz zN^y36!RuEIq?A~eMYUQ+Df`<507OxQ@B0AUTwm!F1JpgAo9ip;o{v(BL82HWzv?WR zrb!eR2DVHlaj>~t3p?iUpa-)W{wi$g1@~9gw@O{;O)D5fE>ek(GV?e! literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Radial/RPD/straight.png b/Resources/Textures/Interface/Radial/RPD/straight.png new file mode 100644 index 0000000000000000000000000000000000000000..46239651339046835fad13f56254c8729c0c97c0 GIT binary patch literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyQ2{<7u9A|H9v&Wbb#-xZam~%m zyLRmg2?=RyYm=9kmywa#vuBT#lvHG7Cc( zp&=N>(;GXwro*URNTLR|Gs_ufX4e@yY3C7Cg&9Q$}j)xg}1S0zH8H2teidP#>O>%OH_~kdd8hI$tEL; zA$Ip&%M0bdk2NXwvvWJKI;^uhEbsKnBX&;B3D2)Q3j`Xt=9e#+E~C#o zIdkTU6)PMa9i^qEw{G1kB_#zk*q3X17LbxD3Gxg6j~g(EZ+dhcsBW33i(`mI@72j? zg_;$3T7+8!1XqdvUcBdjb(rPVOP*D4@6Gs`w)y0SfO{^^i<{cH>-8k!Equ4^`8{1^rG8$$dXRQ^jR{G8v6MU%S@{C8j z_!M`P9eH;_IrQn7;>Q8THm`SOEI9e$u iM=P#gKK*;?KmAaP$Yp_-^;m!|X7F_Nb6Mw<&;$Tq;iYZ> literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Radial/RPD/vent_off.png b/Resources/Textures/Interface/Radial/RPD/vent_off.png new file mode 100644 index 0000000000000000000000000000000000000000..c54c3bb519c607c8a4b647dd250595e3e297b5d8 GIT binary patch literal 612 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 S=HG$<0000 Date: Wed, 18 Dec 2024 20:12:39 +0500 Subject: [PATCH 2/4] d --- Content.Client/RCD/RCDConstructionGhostSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/RCD/RCDConstructionGhostSystem.cs b/Content.Client/RCD/RCDConstructionGhostSystem.cs index de827b534b3..bb3d6eb0773 100644 --- a/Content.Client/RCD/RCDConstructionGhostSystem.cs +++ b/Content.Client/RCD/RCDConstructionGhostSystem.cs @@ -17,9 +17,9 @@ public sealed class RCDConstructionGhostSystem : EntitySystem [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly RCDSystem _rcdSystem = default!; [Dependency] private readonly IPlacementManager _placementManager = default!; + private string _placementMode = typeof(AlignRCDConstruction).Name; private Direction _placementDirection = default; - private bool _useMirrorPrototype = false; public event EventHandler? FlipConstructionPrototype; From 8f87dc10fa507ef0e52234e5c65c16e97f49de44 Mon Sep 17 00:00:00 2001 From: CrimeMoot Date: Wed, 18 Dec 2024 20:21:38 +0500 Subject: [PATCH 3/4] fix add rnd --- Content.Shared/RCD/Systems/RCDSystem.cs | 10 +++++++--- .../Entities/Structures/Machines/lathe.yml | 1 + .../_SpaceCats/Recipes/Lathes/electronics.yml | 11 ++++++++++- .../Prototypes/_SpaceCats/Research/industrial.yml | 13 +++++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 Resources/Prototypes/_SpaceCats/Research/industrial.yml diff --git a/Content.Shared/RCD/Systems/RCDSystem.cs b/Content.Shared/RCD/Systems/RCDSystem.cs index 19951039605..99b11a2e69e 100644 --- a/Content.Shared/RCD/Systems/RCDSystem.cs +++ b/Content.Shared/RCD/Systems/RCDSystem.cs @@ -88,6 +88,8 @@ private void OnMapInit(EntityUid uid, RCDComponent component, MapInitEvent args) QueueDel(uid); } + + private void OnRCDSystemMessage(EntityUid uid, RCDComponent component, RCDSystemMessage args) { // Exit if the RCD doesn't actually know the supplied prototype @@ -306,6 +308,7 @@ private void OnRCDconstructionGhostRotationEvent(RCDConstructionGhostRotationEve Dirty(uid, rcd); } + private void OnRCDConstructionGhostFlipEvent(RCDConstructionGhostFlipEvent ev, EntitySessionEventArgs session) { var uid = GetEntity(ev.NetEntity); @@ -326,6 +329,7 @@ private void OnRCDConstructionGhostFlipEvent(RCDConstructionGhostFlipEvent ev, E Dirty(uid, rcd); } + #endregion #region Entity construction/deconstruction rule checks @@ -521,7 +525,7 @@ private bool IsDeconstructionStillValid(EntityUid uid, RCDComponent component, M else { // The object is not in the RPD whitelist - if (!deconstructible.Deconstructable) + if (!TryComp(target, out var deconstructible) || !deconstructible.RpdDeconstructable && component.IsRpd) { if (popMsgs) _popup.PopupClient(Loc.GetString("rcd-component-deconstruct-target-not-on-whitelist-message"), uid, user); @@ -530,15 +534,15 @@ private bool IsDeconstructionStillValid(EntityUid uid, RCDComponent component, M } // The object is not in the whitelist - if (!TryComp(target, out var deconstructible) || !deconstructible.Deconstructable) + if (!deconstructible.Deconstructable) { if (popMsgs) _popup.PopupClient(Loc.GetString("rcd-component-deconstruct-target-not-on-whitelist-message"), uid, user); return false; } - } + } return true; } diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 80a8b55da10..b096b71a7e4 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -369,6 +369,7 @@ - EnergyDomeDirectionalTurtle # cats-shield energy_barrier - HypoExperement # Cats - ClothingEyesNightVisionGoggles # Cats + - RPD # Cats # start-backmen: languages - CanilunztTranslator - BubblishTranslator diff --git a/Resources/Prototypes/_SpaceCats/Recipes/Lathes/electronics.yml b/Resources/Prototypes/_SpaceCats/Recipes/Lathes/electronics.yml index d1428f4b7a5..8df314da9d5 100644 --- a/Resources/Prototypes/_SpaceCats/Recipes/Lathes/electronics.yml +++ b/Resources/Prototypes/_SpaceCats/Recipes/Lathes/electronics.yml @@ -6,4 +6,13 @@ - type: latheRecipe parent: BaseGoldCircuitboardRecipe id: MachineBluespaceTransitorCircuitboard - result: MachineBluespaceTransitorCircuitboard \ No newline at end of file + result: MachineBluespaceTransitorCircuitboard + +- type: latheRecipe + id: RPD + result: RPD + materials: + Steel: 500 + Glass: 500 + Plastic: 250 + Gold: 50 \ No newline at end of file diff --git a/Resources/Prototypes/_SpaceCats/Research/industrial.yml b/Resources/Prototypes/_SpaceCats/Research/industrial.yml new file mode 100644 index 00000000000..00fc8e816af --- /dev/null +++ b/Resources/Prototypes/_SpaceCats/Research/industrial.yml @@ -0,0 +1,13 @@ +- type: technology + id: RPD + name: research-technology-rpd-atmospherics + icon: + sprite: Objects/Tools/rpd.rsi + state: icon + discipline: Industrial + tier: 2 + cost: 7500 + recipeUnlocks: + - RPD + technologyPrerequisites: + - AtmosphericTech \ No newline at end of file From 9cf68828c90a4918ab906c116a042942b57182a6 Mon Sep 17 00:00:00 2001 From: CrimeMoot Date: Wed, 18 Dec 2024 20:29:09 +0500 Subject: [PATCH 4/4] fix --- Resources/Locale/ru-RU/_Cats/research/technologies.ftl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Resources/Locale/ru-RU/_Cats/research/technologies.ftl b/Resources/Locale/ru-RU/_Cats/research/technologies.ftl index f1627e4b36e..f5936d6850e 100644 --- a/Resources/Locale/ru-RU/_Cats/research/technologies.ftl +++ b/Resources/Locale/ru-RU/_Cats/research/technologies.ftl @@ -1,4 +1,5 @@ research-technology-chemical-Implant = Химические импланты research-technology-hypo = Экспериментальный гипоспрей research-technology-night-vision = Ночное видение -research-technology-thermal-vision = Термальное видение \ No newline at end of file +research-technology-thermal-vision = Термальное видение +research-technology-rpd-atmospherics = RPD \ No newline at end of file