From f74d5487b61bb0dbe373be87fdb7e59eb0127a36 Mon Sep 17 00:00:00 2001 From: to4no_fix <156101927+chavonadelal@users.noreply.github.com> Date: Thu, 15 Aug 2024 17:30:39 +0300 Subject: [PATCH] Adding shock collar and electropack (#30529) --- .../Components/ShockOnTriggerComponent.cs | 37 +++++++++++++++++ .../Explosion/EntitySystems/TriggerSystem.cs | 22 ++++++++++ .../Item/ShockCollar/ShockCollarComponent.cs | 12 ------ .../Item/ShockCollar/ShockCollarSystem.cs | 39 ------------------ Content.Server/Strip/StrippableSystem.cs | 8 ++-- .../Clothing/Components/ClothingComponent.cs | 7 ++++ .../SelfUnremovableClothingComponent.cs | 18 ++++++++ .../Clothing/EntitySystems/ClothingSystem.cs | 8 ++++ .../SelfUnremovableClothingSystem.cs | 36 ++++++++++++++++ .../EntitySystems/ToggleableClothingSystem.cs | 2 +- .../Strip/Components/StrippableComponent.cs | 9 ++++ .../Strip/SharedStrippableSystem.cs | 18 +++++--- .../self-unremovable-clothing-component.ftl | 1 + .../Locale/en-US/research/technologies.ftl | 1 + Resources/Migrations/eeMigration.yml | 3 ++ .../Catalog/Fills/Lockers/security.yml | 10 ++++- .../Entities/Clothing/Back/backpacks.yml | 23 +++++++++++ .../Entities/Objects/Devices/shock_collar.yml | 36 ++++++++++++++++ .../Entities/Structures/Machines/lathe.yml | 9 ++-- .../Markers/Spawners/Random/devices.yml | 2 +- .../Entities/Objects/Devices/shock_collar.yml | 24 ----------- .../Nyanotrasen/Recipes/Lathes/security.yml | 12 ------ .../Prototypes/Objectives/objectiveGroups.yml | 27 ++++++------ .../Objectives/stealTargetGroups.yml | 7 ++++ Resources/Prototypes/Objectives/thief.yml | 11 +++++ .../Prototypes/Recipes/Lathes/security.yml | 9 ++++ Resources/Prototypes/Research/arsenal.yml | 12 ++++++ .../electropack.rsi/equipped-BACKPACK.png | Bin 0 -> 594 bytes .../Back/Backpacks/electropack.rsi/icon.png | Bin 0 -> 457 bytes .../Backpacks/electropack.rsi/inhand-left.png | Bin 0 -> 432 bytes .../electropack.rsi/inhand-right.png | Bin 0 -> 441 bytes .../Back/Backpacks/electropack.rsi/meta.json | 33 +++++++++++++++ .../Misc/shock_collar.rsi/equipped-NECK.png | Bin 0 -> 465 bytes .../Neck/Misc/shock_collar.rsi/icon.png | Bin 0 -> 800 bytes .../Neck/Misc/shock_collar.rsi/meta.json | 19 +++++++++ .../Neck/Misc/shock.rsi/equipped-NECK.png | Bin 323 -> 0 bytes .../Clothing/Neck/Misc/shock.rsi/icon.png | Bin 573 -> 0 bytes .../Clothing/Neck/Misc/shock.rsi/meta.json | 19 --------- 38 files changed, 336 insertions(+), 138 deletions(-) create mode 100644 Content.Server/Explosion/Components/ShockOnTriggerComponent.cs delete mode 100644 Content.Server/Nyanotrasen/Item/ShockCollar/ShockCollarComponent.cs delete mode 100644 Content.Server/Nyanotrasen/Item/ShockCollar/ShockCollarSystem.cs create mode 100644 Content.Shared/Clothing/Components/SelfUnremovableClothingComponent.cs create mode 100644 Content.Shared/Clothing/EntitySystems/SelfUnremovableClothingSystem.cs create mode 100644 Resources/Locale/en-US/clothing/components/self-unremovable-clothing-component.ftl create mode 100644 Resources/Prototypes/Entities/Objects/Devices/shock_collar.yml delete mode 100644 Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/shock_collar.yml create mode 100644 Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/equipped-BACKPACK.png create mode 100644 Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/equipped-NECK.png create mode 100644 Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/meta.json delete mode 100644 Resources/Textures/Nyanotrasen/Clothing/Neck/Misc/shock.rsi/equipped-NECK.png delete mode 100644 Resources/Textures/Nyanotrasen/Clothing/Neck/Misc/shock.rsi/icon.png delete mode 100644 Resources/Textures/Nyanotrasen/Clothing/Neck/Misc/shock.rsi/meta.json diff --git a/Content.Server/Explosion/Components/ShockOnTriggerComponent.cs b/Content.Server/Explosion/Components/ShockOnTriggerComponent.cs new file mode 100644 index 0000000000..a553cc047a --- /dev/null +++ b/Content.Server/Explosion/Components/ShockOnTriggerComponent.cs @@ -0,0 +1,37 @@ +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Content.Server.Explosion.EntitySystems; + +namespace Content.Server.Explosion.Components; + +/// +/// A component that electrocutes an entity having this component when a trigger is triggered. +/// +[RegisterComponent, AutoGenerateComponentPause] +[Access(typeof(TriggerSystem))] +public sealed partial class ShockOnTriggerComponent : Component +{ + /// + /// The force of an electric shock when the trigger is triggered. + /// + [DataField] + public int Damage = 5; + + /// + /// Duration of electric shock when the trigger is triggered. + /// + [DataField] + public TimeSpan Duration = TimeSpan.FromSeconds(2); + + /// + /// The minimum delay between repeating triggers. + /// + [DataField] + public TimeSpan Cooldown = TimeSpan.FromSeconds(4); + + /// + /// When can the trigger run again? + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + [AutoPausedField] + public TimeSpan NextTrigger = TimeSpan.Zero; +} diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs index 1fde61cada..be47585f5a 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs @@ -3,6 +3,7 @@ using Content.Server.Body.Systems; using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Explosion.Components; using Content.Server.Flash; +using Content.Server.Electrocution; using Content.Server.Pinpointer; using Content.Shared.Flash.Components; using Content.Server.Radio.EntitySystems; @@ -33,6 +34,7 @@ using Robust.Shared.Random; using Robust.Shared.Player; using Content.Shared.Coordinates; using Robust.Shared.Utility; +using Robust.Shared.Timing; namespace Content.Server.Explosion.EntitySystems { @@ -75,6 +77,7 @@ namespace Content.Server.Explosion.EntitySystems [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly ElectrocutionSystem _electrocution = default!; public override void Initialize() { @@ -104,6 +107,7 @@ namespace Content.Server.Explosion.EntitySystems SubscribeLocalEvent(OnAnchorTrigger); SubscribeLocalEvent(OnSoundTrigger); + SubscribeLocalEvent(HandleShockTrigger); SubscribeLocalEvent(HandleRattleTrigger); } @@ -120,6 +124,24 @@ namespace Content.Server.Explosion.EntitySystems } } + private void HandleShockTrigger(Entity shockOnTrigger, ref TriggerEvent args) + { + if (!_container.TryGetContainingContainer(shockOnTrigger, out var container)) + return; + + var containerEnt = container.Owner; + var curTime = _timing.CurTime; + + if (curTime < shockOnTrigger.Comp.NextTrigger) + { + // The trigger's on cooldown. + return; + } + + _electrocution.TryDoElectrocution(containerEnt, null, shockOnTrigger.Comp.Damage, shockOnTrigger.Comp.Duration, true); + shockOnTrigger.Comp.NextTrigger = curTime + shockOnTrigger.Comp.Cooldown; + } + private void OnAnchorTrigger(EntityUid uid, AnchorOnTriggerComponent component, TriggerEvent args) { var xform = Transform(uid); diff --git a/Content.Server/Nyanotrasen/Item/ShockCollar/ShockCollarComponent.cs b/Content.Server/Nyanotrasen/Item/ShockCollar/ShockCollarComponent.cs deleted file mode 100644 index 1dcbc48676..0000000000 --- a/Content.Server/Nyanotrasen/Item/ShockCollar/ShockCollarComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Content.Server.ShockCollar; - -[RegisterComponent] -public sealed partial class ShockCollarComponent : Component -{ - [DataField] - public int ShockDamage = 1; - - [DataField] - public TimeSpan ShockTime = TimeSpan.FromSeconds(2); -} - diff --git a/Content.Server/Nyanotrasen/Item/ShockCollar/ShockCollarSystem.cs b/Content.Server/Nyanotrasen/Item/ShockCollar/ShockCollarSystem.cs deleted file mode 100644 index eeb0f59d42..0000000000 --- a/Content.Server/Nyanotrasen/Item/ShockCollar/ShockCollarSystem.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Content.Shared.Mobs.Components; -using Content.Shared.Timing; -using Content.Server.Explosion.EntitySystems; // Why is trigger under explosions by the way? Even doors already use it. -using Content.Server.Electrocution; -using Robust.Shared.Containers; - -namespace Content.Server.ShockCollar; - -public sealed partial class ShockCollarSystem : EntitySystem -{ - [Dependency] private readonly SharedContainerSystem _container = default!; - [Dependency] private readonly ElectrocutionSystem _electrocutionSystem = default!; - [Dependency] private readonly UseDelaySystem _useDelay = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnTrigger); - } - - private void OnTrigger(EntityUid uid, ShockCollarComponent component, TriggerEvent args) - { - if (!_container.TryGetContainingContainer(uid, out var container)) // Try to get the entity directly containing this - return; - - var containerEnt = container.Owner; - - if (!HasComp(containerEnt)) // If it's not a mob we don't care - return; - - // DeltaV: prevent clocks from instantly killing people - if (TryComp(uid, out var useDelay) - && !_useDelay.TryResetDelay((uid, useDelay), true)) - return; - - _electrocutionSystem.TryDoElectrocution(containerEnt, null, component.ShockDamage, component.ShockTime, true, ignoreInsulation: true); - } -} - diff --git a/Content.Server/Strip/StrippableSystem.cs b/Content.Server/Strip/StrippableSystem.cs index 4a03bfba9e..7f00c63c4f 100644 --- a/Content.Server/Strip/StrippableSystem.cs +++ b/Content.Server/Strip/StrippableSystem.cs @@ -219,7 +219,7 @@ namespace Content.Server.Strip return; } - var (time, stealth) = GetStripTimeModifiers(user, target, slotDef.StripTime); + var (time, stealth) = GetStripTimeModifiers(user, target, held, slotDef.StripTime); bool hidden = stealth == ThievingStealth.Hidden; @@ -309,7 +309,7 @@ namespace Content.Server.Strip return; } - var (time, stealth) = GetStripTimeModifiers(user, target, slotDef.StripTime); + var (time, stealth) = GetStripTimeModifiers(user, target, item, slotDef.StripTime); bool hidden = stealth == ThievingStealth.Hidden; @@ -416,7 +416,7 @@ namespace Content.Server.Strip if (!CanStripInsertHand(user, target, held, handName)) return; - var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay); + var (time, stealth) = GetStripTimeModifiers(user, target, null, targetStrippable.HandStripDelay); bool hidden = stealth == ThievingStealth.Hidden; @@ -517,7 +517,7 @@ namespace Content.Server.Strip if (!CanStripRemoveHand(user, target, item, handName)) return; - var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay); + var (time, stealth) = GetStripTimeModifiers(user, target, null, targetStrippable.HandStripDelay); bool hidden = stealth == ThievingStealth.Hidden; diff --git a/Content.Shared/Clothing/Components/ClothingComponent.cs b/Content.Shared/Clothing/Components/ClothingComponent.cs index 02a0181eb5..bf52720fe6 100644 --- a/Content.Shared/Clothing/Components/ClothingComponent.cs +++ b/Content.Shared/Clothing/Components/ClothingComponent.cs @@ -71,6 +71,13 @@ public sealed partial class ClothingComponent : Component [DataField] public TimeSpan UnequipDelay = TimeSpan.Zero; + /// + /// Offset for the strip time for an entity with this component. + /// Only applied when it is being equipped or removed by another player. + /// + [DataField] + public TimeSpan StripDelay = TimeSpan.Zero; + /// /// These functions are called when an entity equips an item with this component. /// diff --git a/Content.Shared/Clothing/Components/SelfUnremovableClothingComponent.cs b/Content.Shared/Clothing/Components/SelfUnremovableClothingComponent.cs new file mode 100644 index 0000000000..1d624516ec --- /dev/null +++ b/Content.Shared/Clothing/Components/SelfUnremovableClothingComponent.cs @@ -0,0 +1,18 @@ +using Content.Shared.Clothing.EntitySystems; +using Robust.Shared.GameStates; + +namespace Content.Shared.Clothing.Components; + +/// +/// The component prohibits the player from taking off clothes on them that have this component. +/// +/// +/// See also ClothingComponent.EquipDelay if you want the clothes that the player cannot take off by himself to be put on by the player with a delay. +/// +[NetworkedComponent] +[RegisterComponent] +[Access(typeof(SelfUnremovableClothingSystem))] +public sealed partial class SelfUnremovableClothingComponent : Component +{ + +} diff --git a/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs index b97348bf11..2d4c073e0c 100644 --- a/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Interaction.Events; using Content.Shared.Inventory; using Content.Shared.Inventory.Events; using Content.Shared.Item; +using Content.Shared.Strip.Components; using Robust.Shared.Containers; using Robust.Shared.GameStates; @@ -36,6 +37,8 @@ public abstract class ClothingSystem : EntitySystem SubscribeLocalEvent(OnEquipDoAfter); SubscribeLocalEvent(OnUnequipDoAfter); + + SubscribeLocalEvent(OnItemStripped); } private void OnUseInHand(Entity ent, ref UseInHandEvent args) @@ -227,6 +230,11 @@ public abstract class ClothingSystem : EntitySystem _handsSystem.TryPickup(args.User, ent); } + private void OnItemStripped(Entity ent, ref BeforeItemStrippedEvent args) + { + args.Additive += ent.Comp.StripDelay; + } + private void CheckEquipmentForLayerHide(EntityUid equipment, EntityUid equipee) { if (TryComp(equipment, out HideLayerClothingComponent? clothesComp) && TryComp(equipee, out HumanoidAppearanceComponent? appearanceComp)) diff --git a/Content.Shared/Clothing/EntitySystems/SelfUnremovableClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/SelfUnremovableClothingSystem.cs new file mode 100644 index 0000000000..ab0c41c5c7 --- /dev/null +++ b/Content.Shared/Clothing/EntitySystems/SelfUnremovableClothingSystem.cs @@ -0,0 +1,36 @@ +using Content.Shared.Clothing.Components; +using Content.Shared.Examine; +using Content.Shared.Inventory; +using Content.Shared.Inventory.Events; + +namespace Content.Shared.Clothing.EntitySystems; + +/// +/// A system for the operation of a component that prohibits the player from taking off his own clothes that have this component. +/// +public sealed class SelfUnremovableClothingSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnUnequip); + SubscribeLocalEvent(OnUnequipMarkup); + } + + private void OnUnequip(Entity selfUnremovableClothing, ref BeingUnequippedAttemptEvent args) + { + if (TryComp(selfUnremovableClothing, out var clothing) && (clothing.Slots & args.SlotFlags) == SlotFlags.NONE) + return; + + if (args.UnEquipTarget == args.Unequipee) + { + args.Cancel(); + } + } + + private void OnUnequipMarkup(Entity selfUnremovableClothing, ref ExaminedEvent args) + { + args.PushMarkup(Loc.GetString("comp-self-unremovable-clothing")); + } +} diff --git a/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs index 63f817f9bb..4b9db83722 100644 --- a/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs @@ -106,7 +106,7 @@ public sealed class ToggleableClothingSystem : EntitySystem if (comp.StripDelay == null) return; - var (time, stealth) = _strippable.GetStripTimeModifiers(user, wearer, comp.StripDelay.Value); + var (time, stealth) = _strippable.GetStripTimeModifiers(user, wearer, toggleable, comp.StripDelay.Value); bool hidden = stealth == ThievingStealth.Hidden; diff --git a/Content.Shared/Strip/Components/StrippableComponent.cs b/Content.Shared/Strip/Components/StrippableComponent.cs index 0072580829..551fdfda67 100644 --- a/Content.Shared/Strip/Components/StrippableComponent.cs +++ b/Content.Shared/Strip/Components/StrippableComponent.cs @@ -44,6 +44,15 @@ namespace Content.Shared.Strip.Components public SlotFlags TargetSlots { get; } = SlotFlags.GLOVES; } + /// + /// Used to modify strip times. Raised directed at the item being stripped. + /// + /// + /// This is also used by some stripping related interactions, i.e., interactions with items that are currently equipped by another player. + /// + [ByRefEvent] + public sealed class BeforeItemStrippedEvent(TimeSpan initialTime, ThievingStealth stealth = ThievingStealth.Obvious) : BaseBeforeStripEvent(initialTime, stealth); + /// /// Used to modify strip times. Raised directed at the user. /// diff --git a/Content.Shared/Strip/SharedStrippableSystem.cs b/Content.Shared/Strip/SharedStrippableSystem.cs index 3897c6cc7d..e402a00341 100644 --- a/Content.Shared/Strip/SharedStrippableSystem.cs +++ b/Content.Shared/Strip/SharedStrippableSystem.cs @@ -26,20 +26,26 @@ public abstract class SharedStrippableSystem : EntitySystem private void OnActivateInWorld(EntityUid uid, StrippableComponent component, ActivateInWorldEvent args) { - if (args.Handled || args.Target == args.User) + if (args.Handled || !args.Complex || args.Target == args.User) return; if (TryOpenStrippingUi(args.User, (uid, component))) args.Handled = true; } - public (TimeSpan Time, ThievingStealth Stealth) GetStripTimeModifiers(EntityUid user, EntityUid target, TimeSpan initialTime) + /// + /// Modify the strip time via events. Raised directed at the item being stripped, the player stripping someone and the player being stripped. + /// + public (TimeSpan Time, ThievingStealth Stealth) GetStripTimeModifiers(EntityUid user, EntityUid targetPlayer, EntityUid? targetItem, TimeSpan initialTime) { - var userEv = new BeforeStripEvent(initialTime); + var itemEv = new BeforeItemStrippedEvent(initialTime); + if (targetItem != null) + RaiseLocalEvent(targetItem.Value, ref itemEv); + var userEv = new BeforeStripEvent(itemEv.Time, itemEv.Stealth); RaiseLocalEvent(user, ref userEv); - var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth); - RaiseLocalEvent(target, ref ev); - return (ev.Time, ev.Stealth); + var targetEv = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth); + RaiseLocalEvent(targetPlayer, ref targetEv); + return (targetEv.Time, targetEv.Stealth); } private void OnDragDrop(EntityUid uid, StrippableComponent component, ref DragDropDraggedEvent args) diff --git a/Resources/Locale/en-US/clothing/components/self-unremovable-clothing-component.ftl b/Resources/Locale/en-US/clothing/components/self-unremovable-clothing-component.ftl new file mode 100644 index 0000000000..bb7ff0206f --- /dev/null +++ b/Resources/Locale/en-US/clothing/components/self-unremovable-clothing-component.ftl @@ -0,0 +1 @@ +comp-self-unremovable-clothing = This cannot be removed without outside help. diff --git a/Resources/Locale/en-US/research/technologies.ftl b/Resources/Locale/en-US/research/technologies.ftl index 620d9bfcdf..55a255ac62 100644 --- a/Resources/Locale/en-US/research/technologies.ftl +++ b/Resources/Locale/en-US/research/technologies.ftl @@ -27,6 +27,7 @@ research-technology-basic-weapons = Basic Weapons research-technology-draconic-munitions = Draconic Munitions research-technology-uranium-munitions = Uranium Munitions research-technology-explosive-technology = Explosive Technology +research-technology-special-means = Special Means research-technology-practice-ammunition = Practice Ammunition research-technology-shrapnel-munitions = Shrapnel Munitions research-technology-advanced-weapons = Advanced Weapons diff --git a/Resources/Migrations/eeMigration.yml b/Resources/Migrations/eeMigration.yml index 30884009d6..9810f61b62 100644 --- a/Resources/Migrations/eeMigration.yml +++ b/Resources/Migrations/eeMigration.yml @@ -143,3 +143,6 @@ SpeedLoaderRifleHeavyRubber: SpeedLoaderRifleHeavy WeaponRifleGestioRubber: WeaponRifleGestio WeaponRifleNovaliteC1Rubber: WeaponRifleNovaliteC1 WeaponSniperRepeaterNonlethal: WeaponSniperRepeater + +# 2025-06-09 +ShockCollar: ClothingNeckShockCollar diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml index b5678fd72a..9a50363ec4 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml @@ -21,7 +21,10 @@ - id: ClothingOuterHardsuitCombatWarden # WD EDIT: ClothingOuterHardsuitCombatWarden -> ClothingOuterHardsuitWarden - id: HoloprojectorSecurity - id: BookSpaceLaw - # - id: ClothingEyesHudSecurity - WD EDIT + - id: ClothingNeckShockCollar + amount: 2 + - id: RemoteSignaller + amount: 2 - id: BoxPDAPrisoner - id: ClothingShoesBootsWinterWarden - id: BoxEncryptionKeyPrisoner @@ -56,7 +59,10 @@ - id: DoorRemoteArmory - id: HoloprojectorSecurity - id: BookSpaceLaw - # - id: ClothingEyesHudSecurity - WD EDIT + - id: ClothingNeckShockCollar + amount: 2 + - id: RemoteSignaller + amount: 2 - id: BoxPDAPrisoner - id: ClothingShoesBootsWinterWarden - id: BoxEncryptionKeyPrisoner diff --git a/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml b/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml index 645e9db503..c4f090c2b6 100644 --- a/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml +++ b/Resources/Prototypes/Entities/Clothing/Back/backpacks.yml @@ -348,6 +348,29 @@ - type: Unremoveable deleteOnDrop: false +- type: entity + parent: ClothingBackpack + id: ClothingBackpackElectropack + name: electropack + suffix: SelfUnremovable + description: Shocks on the signal. It is used to keep a particularly dangerous criminal under control. + components: + - type: Sprite + sprite: Clothing/Back/Backpacks/electropack.rsi + state: icon + - type: Clothing + stripDelay: 10 + equipDelay: 5 # to avoid accidentally falling into the trap associated with SelfUnremovableClothing + - type: SelfUnremovableClothing + - type: ShockOnTrigger + damage: 5 + duration: 3 + cooldown: 4 + - type: TriggerOnSignal + - type: DeviceLinkSink + ports: + - Trigger + # Debug - type: entity parent: ClothingBackpack diff --git a/Resources/Prototypes/Entities/Objects/Devices/shock_collar.yml b/Resources/Prototypes/Entities/Objects/Devices/shock_collar.yml new file mode 100644 index 0000000000..22f2d097fc --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Devices/shock_collar.yml @@ -0,0 +1,36 @@ +- type: entity + parent: Clothing + id: ClothingNeckShockCollar + name: shock collar + suffix: SelfUnremovable + description: An electric collar that shocks on the signal. + components: + - type: Item + size: Small + - type: Sprite + sprite: Clothing/Neck/Misc/shock_collar.rsi + state: icon + - type: Clothing + sprite: Clothing/Neck/Misc/shock_collar.rsi + stripDelay: 10 + equipDelay: 5 # to avoid accidentally falling into the trap associated with SelfUnremovableClothing + quickEquip: true + slots: + - neck + - type: SelfUnremovableClothing + - type: ShockOnTrigger + damage: 5 + duration: 3 + cooldown: 4 + - type: TriggerOnSignal + - type: DeviceLinkSink + ports: + - Trigger + - type: GuideHelp + guides: + - Security + - type: StealTarget + stealGroup: ClothingNeckShockCollar + - type: Tag + tags: + - WhitelistChameleon diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 74adc977ec..c378bbf044 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -1000,8 +1000,7 @@ - WeaponFlareGunSecurity - WeaponLaserCarbinePractice - Zipties - - GrenadeFlashBang # Goobstation - - ShockCollar + - GrenadeFlashBang # # DeltaV - .38 special ammo - Add various .38 special ammo to security techfab # WWDP disable "special" # - MagazineBoxSpecial # - MagazineBoxSpecialPractice @@ -1101,9 +1100,8 @@ - WeaponLaserCannon - WeaponLaserCarbine - ClothingEyesNightVisionSecurityGoggles - - ClothingHeadHelmetInsulated # Nyanotrasen - Insulative headgear - - ClothingHeadCage # Nyanotrasen - Insulative headgear - - ShockCollar # Nyanotrasen - Shock Collar + - ClothingHeadHelmetInsulated + - ClothingHeadCage - WeaponXrayCannon - WeaponEnergyGun - WeaponEnergyGunMini @@ -1166,6 +1164,7 @@ - MagazineUniversalMagnumIncendiary - MagazineUniversalMagnumShrapnel - WeaponPistolUniversal + - ClothingBackpackElectropack # WD EDIT START - MagazineShotgunLaser - BoxLaser diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/Random/devices.yml b/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/Random/devices.yml index fde726ed03..2a334ef5e6 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/Random/devices.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/Random/devices.yml @@ -115,7 +115,7 @@ - TelecomServerCircuitboard - MiniGravityGeneratorCircuitboard - Portafib - - ShockCollar + - ClothingNeckShockCollar - GlimmerMonitorCartridge - PotatoAIChip - CargoTelepadMachineCircuitboard diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/shock_collar.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/shock_collar.yml deleted file mode 100644 index 1266a721fe..0000000000 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/shock_collar.yml +++ /dev/null @@ -1,24 +0,0 @@ -- type: entity - parent: ClothingNeckBase - id: ShockCollar - name: shock collar - description: Shocking. # DeltaV: sprite is fine - components: - - type: Sprite - sprite: Nyanotrasen/Clothing/Neck/Misc/shock.rsi - - type: Clothing - sprite: Nyanotrasen/Clothing/Neck/Misc/shock.rsi - equipDelay: 1 - unequipDelay: 10 # It's a collar meant to be used on prisoners (or not), so it probably has some sort of safety. - - type: ShockCollar - - type: UseDelay - delay: 3 # DeltaV: prevent clocks instakilling people - - type: TriggerOnSignal - - type: DeviceNetwork - deviceNetId: Wireless - receiveFrequencyId: BasicDevice - - type: WirelessNetworkConnection - range: 200 - - type: DeviceLinkSink - ports: - - Trigger diff --git a/Resources/Prototypes/Nyanotrasen/Recipes/Lathes/security.yml b/Resources/Prototypes/Nyanotrasen/Recipes/Lathes/security.yml index 34aa7e7ce8..ac6a9395b3 100644 --- a/Resources/Prototypes/Nyanotrasen/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/Nyanotrasen/Recipes/Lathes/security.yml @@ -17,18 +17,6 @@ Steel: 400 Bluespace: 20 -- type: latheRecipe - id: ShockCollar - icon: - sprite: Nyanotrasen/Clothing/Neck/Misc/shock.rsi - state: icon - result: ShockCollar - completetime: 2 - materials: - Steel: 300 - Glass: 100 - Plastic: 100 - - type: latheRecipe id: ShellSoulbreaker icon: diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml index 4db5b4e54e..9c61d0a803 100644 --- a/Resources/Prototypes/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/Objectives/objectiveGroups.yml @@ -17,14 +17,14 @@ NukeDiskStealObjective: 1 MagbootsStealObjective: 1 CorgiMeatStealObjective: 1 - MantisKnifeStealObjective: 1 # Nyanotrasen - ForensicMantis steal objective, see Resources/Prototypes/Nyanotrasen/Objectives/traitor.yml + MantisKnifeStealObjective: 1 ClipboardStealObjective: 1 CaptainGunStealObjective: 0.5 NTRepGunStealObjective: 0.5 CaptainJetpackStealObjective: 0.5 HandTeleporterStealObjective: 0.5 - LOLuckyBillStealObjective: 0.5 # DeltaV - LO steal objective, see Resources/Prototypes/DeltaV/Objectives/traitor.yml - HoPBookIanDossierStealObjective: 1 # DeltaV - HoP steal objective, see Resources/Prototypes/DeltaV/Objectives/traitor.yml + LOLuckyBillStealObjective: 0.5 + HoPBookIanDossierStealObjective: 1 HoSGunStealObjective: 0.5 StealSupermatterSliverObjective: 0.5 EnergyShotgunStealObjective: 0.5 @@ -47,7 +47,7 @@ weights: # RandomTraitorAliveObjective: 1 # WWDP - disabled because it was very boring RandomTraitorProgressObjective: 1 - # RaiseGlimmerObjective: 0.5 # Nyanotrasen - Raise glimmer to a target amount, see Resources/Prototypes/Nyanotrasen/Objectives/traitor.yml + # RaiseGlimmerObjective: 0.5 #Thief groups - type: weightedRandom @@ -65,32 +65,33 @@ - type: weightedRandom id: ThiefObjectiveGroupCollection weights: - HeadCloakStealCollectionObjective: 1 #command + HeadCloakStealCollectionObjective: 1 #command HeadBedsheetStealCollectionObjective: 1 StampStealCollectionObjective: 1 DoorRemoteStealCollectionObjective: 1 - TechnologyDiskStealCollectionObjective: 1 #rnd - FigurineStealCollectionObjective: 0.3 #service + TechnologyDiskStealCollectionObjective: 1 #rnd + FigurineStealCollectionObjective: 0.3 #service IDCardsStealCollectionObjective: 1 LAMPStealCollectionObjective: 2 #only for moth - type: weightedRandom id: ThiefObjectiveGroupItem weights: - ForensicScannerStealObjective: 1 #sec + ForensicScannerStealObjective: 1 #sec FlippoEngravedLighterStealObjective: 0.5 ClothingHeadHatWardenStealObjective: 1 - ClothingOuterHardsuitVoidParamedStealObjective: 1 #med + ClothingNeckShockCollarStealObjective: 1 + ClothingOuterHardsuitVoidParamedStealObjective: 1 #med MedicalTechFabCircuitboardStealObjective: 1 ClothingHeadsetAltMedicalStealObjective: 1 - FireAxeStealObjective: 1 #eng + FireAxeStealObjective: 1 #eng AmePartFlatpackStealObjective: 1 - ExpeditionsCircuitboardStealObjective: 1 #sup + ExpeditionsCircuitboardStealObjective: 1 #sup CargoShuttleCircuitboardStealObjective: 1 SalvageShuttleCircuitboardStealObjective: 1 - ClothingEyesHudBeerStealObjective: 1 #srv + ClothingEyesHudBeerStealObjective: 1 #srv BibleStealObjective: 1 - ClothingNeckGoldmedalStealObjective: 1 #other + ClothingNeckGoldmedalStealObjective: 1 #other ClothingNeckClownmedalStealObjective: 0.5 - type: weightedRandom diff --git a/Resources/Prototypes/Objectives/stealTargetGroups.yml b/Resources/Prototypes/Objectives/stealTargetGroups.yml index dfd3481c96..b614558f3f 100644 --- a/Resources/Prototypes/Objectives/stealTargetGroups.yml +++ b/Resources/Prototypes/Objectives/stealTargetGroups.yml @@ -279,6 +279,13 @@ sprite: Clothing/Neck/Medals/clownmedal.rsi state: icon +- type: stealTargetGroup + id: ClothingNeckShockCollar + name: shock collar + sprite: + sprite: Clothing/Neck/Misc/shock_collar.rsi + state: icon + #Thief structures - type: stealTargetGroup diff --git a/Resources/Prototypes/Objectives/thief.yml b/Resources/Prototypes/Objectives/thief.yml index 2a26ec2d7b..aef30d1b58 100644 --- a/Resources/Prototypes/Objectives/thief.yml +++ b/Resources/Prototypes/Objectives/thief.yml @@ -316,6 +316,17 @@ - type: Objective difficulty: 1 +- type: entity + parent: BaseThiefStealObjective + id: ClothingNeckShockCollarStealObjective + components: + - type: NotJobRequirement + job: Warden + - type: StealCondition + stealGroup: ClothingNeckShockCollar + - type: Objective + difficulty: 1 + # Structures - type: entity diff --git a/Resources/Prototypes/Recipes/Lathes/security.yml b/Resources/Prototypes/Recipes/Lathes/security.yml index 9f35cb9490..5d5e2e238d 100644 --- a/Resources/Prototypes/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/Recipes/Lathes/security.yml @@ -125,6 +125,15 @@ Plastic: 250 Gold: 100 +- type: latheRecipe + id: ClothingBackpackElectropack + result: ClothingBackpackElectropack + completetime: 4 + materials: + Steel: 500 + Plastic: 250 + Cloth: 500 + - type: latheRecipe id: ForensicPad result: ForensicPad diff --git a/Resources/Prototypes/Research/arsenal.yml b/Resources/Prototypes/Research/arsenal.yml index 9883965a01..bbe87369ad 100644 --- a/Resources/Prototypes/Research/arsenal.yml +++ b/Resources/Prototypes/Research/arsenal.yml @@ -128,6 +128,18 @@ - BoxFrag # TODO: Add "Explosive Ammunition" to this tech to make it waaaay more interesting. +- type: technology + id: SpecialMeans + name: research-technology-special-means + icon: + sprite: Clothing/Back/Backpacks/electropack.rsi + state: icon + discipline: Arsenal + tier: 1 + cost: 5000 + recipeUnlocks: + - ClothingBackpackElectropack + # Tier 2 - type: technology diff --git a/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/equipped-BACKPACK.png b/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/equipped-BACKPACK.png new file mode 100644 index 0000000000000000000000000000000000000000..3ea6cdc4b05c396229eb4d75f858c4747ac93525 GIT binary patch literal 594 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0#1o(uwCM6|hWMr6`nc3Od$;im$w_w@9fIB{Zlc(}8(vzC^Y zzrX+V>C;V3)n?8pb#TzHu8MA%oui_nvTN5aFE6i(iV8nJzo@7v6%{FzjtmPI}P7M|h_-a5foPGHl3=T%mYvlE{k_8vg>s zU$1A(_{kSFm)-B)9*O!>OdQvu9AvXkzTr6XJAB?J_YKeMHvE(|S<++vO7g<~Z(^Sr z)_>P|!r-*}{4J%UQInW9*>M=@IH$BHZkWPaQ~dJYF7G_%Kkf?qT&nu7&XC-o&Z^+%K(?wqq<139DE3;I@oly48C>m*L0tIg=+E zGx~8en6KQlvvUK}ht;-BLAIVOZxlkAjwruj&)L)L8_D?2p7mX!Rjkt4`G22#&Qedv z=L%?;P|siSpV6Rq-j072Qi8xx=1Yz6O!M_+&;qhKfEWZW1y2T1p00i_>zopr0MD@O AUH||9 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/icon.png b/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b4b755e0082d7d553160ab8724fc32aefea508b8 GIT binary patch literal 457 zcmeAS@N?(olHy`uVBq!ia0vp^2|%pC!3-pC$@QiIDaPU;cPEB*=VV?2Ic5PqA+Ba- zX12Dr6%`e&t*x%EuF=uaE0vWOF)^8%s;Q_*&74tMT@~%%pucL@tbk?sjx=&p~iu?XPed^+;7Anq3*n*)4W*aj>`(Q4Ii@_3L3qq_1NF4lCGCf zU}o%`(^IqN;;HE7pvKdpFF1YnNHG+wJJ4z0FzLXF-?AGrs)80ahBrToQJJd2*|W#A zA;^*Mvha+G{mlAYM!P0+@$Q+oFUGOQaA{1VH2>5fBl~A#0=&?Rk11!ob4>u@o}F@AM8D-6RQxt zWHSp}9Pf;8{ZBflvbgQ5=XRNk44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`1E1o(uw#>K_i+1cgf*p+6*>Rw~(KSghd%>YEF%Fw_F7+oioDvZ*SbO`=Gv0`AcR88z10tW*v3=cR zyP~y4o?9zl`ugexM)qPaew6NJn#Q+4!HFwq!4d^lFRnU)8@!2)zU(SHJUf}E^JQGy zcCf*pUExFNN7g0G0yoSg7+x~4Y~y8fuwrP;ZDyRn_k-s{`;PiWwN?xEC)`S404lnZ z7an89;Mg<0>6%?f^vc`TB^m#K-sMY;@J#ddWdH>i2M~k6rQpdR%G1@)Wt~$(69D&y Bn{xmF literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/inhand-right.png b/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..26901ce4c9aa65f2f2b4376e79e529f822edfb4a GIT binary patch literal 441 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`1E1o(uw#>K_i+1V{(V#>+MnK*HxkEf@psakba^voHh4i5TST3SGbiRXD% z0x6!7Aiv=M2*4n8|J*sCIA?)JWHAE+-(e7DJf6QI1t|E&)5S3)!u{>E(?ZP#9IlE9 zYft|FpTAT{_1Z~i^Vov0>y2|d^Y%=Td&DHpp;yrOA-sw4`cX}f4k_z~YUQ$SpirYexCX3?7e zzqd{*Fx6o-uh8&#$$ZXe<*OH~qyvEd=1Yz6O!M_+0EHU|5QD&_;K?A$)78&qol`;+ E0L)3E*8l(j literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/meta.json b/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/meta.json new file mode 100644 index 0000000000..4e7738117e --- /dev/null +++ b/Resources/Textures/Clothing/Back/Backpacks/electropack.rsi/meta.json @@ -0,0 +1,33 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/2d26ce62c273d025bed77a0e6c4bdc770b789bb0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/equipped-NECK.png b/Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/equipped-NECK.png new file mode 100644 index 0000000000000000000000000000000000000000..ffca3249f13d35ed449938c85fc67b5c0e740977 GIT binary patch literal 465 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z3q4&NLn`LH zy=9o!Y#_q+z&=!8U}f>7IE~{c9L(|#xQUx7RlYeSI6=TYA>q`4mg@^R+WKVgEHvDD zY1Jdig*yM$T{$Fw+Ugkn+B?BCg0+=pp`3Mb4eyNykE#G-Cus!bxue(n@Yoc z4I3WjWdGlvw}nl!G@HG)#Czi5e;wPubJ#ZUr)xZVC|E1wer&E}gqH-H+b?@{VAz1c uqKo2e_qlSq7pxNo#spt#glC$sFM}44%>l$9a4C2)i1Kvxb6Mw<&;$VGYr@(9 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/icon.png b/Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f8e0a9cb8e4fab549dd7fe5de64098076d68774a GIT binary patch literal 800 zcmV+*1K<3KP)Px%z)3_wR9J=Wls{u6bN2Al~8x^Rx*@e4^4vUpo=M?7D666cDN4F2`Tzxr=ifn-y+?+cklb& zy>}1hm}8E=fUehM()yp1ce}?@k=|V27WZZ$^#2!&TL@tWe1tG57PmsacNU-sb-gAf zNJR#a$*iI4HJQn*;kQeW{&Uj=+@D6S0-w30lZoy5q*BY?dTHq)J4TC_dd(A5EN%fv z!)PtU@k}iNz>d-4%e#G#Ow-mwU$v)hWL889(Dj-ejV=+w^aA@c7sAA{#(}TGWMX?a zC4|Y2(Ml{uNPw=_WTmp}1=F;3J~rQwt2eN$F_txEI6MOgd~@{%2k!N&bCZe96;P?{ z#)^pT0e`lB3Z5DwQU@5akzyB48o_7Ad zMIU*mbC}q`v2#F)c;>Djr&k#c&(wSmA)Q{O+x>{9t@GWreQ?R+I1&XY5jnR99{2`Q zyS~W%#HwsLSFjc^-XkUxbiy*P$J^?Zc9GL9RCIW0O(JZ+iLn{RsaA14rN$LW=%~1 eDgXcg2mk;800000(o>TF0000b~XebB*P+WhH^I)PTN`TF4>cfG6CslN9%`SH&jmQ&Y{{&B9^a;hwT z|D^4=kNb&e?VT6v;*w%rm~!W}$+jOp)AW^$=4@O0e50Nf*VVmGXT|+df5Hqj9RmI@ zSh=`Bxc9nb@?P)ljA7=|BnY21WFjY1q;i;y8w2L1zG*xHdlP^L;OEJ$5g89E~&b)tWOfuY?{CNi-H zMS#=>#UW0jM6Ft!*fK-pQ`6XKVj&@c-{qwH?t9<&?!NC1V*CsEoX>lI)j(0xA{$Wt zq+r*wR_0qN!O#mHfa5AW-`Saoy*)lAA*R0Co!-*CiDg9r9zM_k_4*dJClyy0uO0AR0WH|fL2|bBW1HM2uEu`qGsFZc@{L-Bnt@5FVfHyvt?NE@F)t)WnFI-Iz{Cgu!uElb%J0)V|E zK{hQSi)YhygCBu-hl3`%mBh;jdJ+|co6@-PmGW3F%&t;^EmN}q#-~_I%?k8ld zx}U&5y}|He;bRoo1wPuHo-!C-V0QbM-M*ZE{lN_!0lvPRYMI^st>Uo6Q+%DEsA*oU zq44R8O|5!&W(0Lw@sAy-i>3dAmHRBLpRd