Adding shock collar and electropack (#30529)
* Adding shock collar with the new ShockOnTrigger * Cleaning and updating the shock collar * Add StripDelay datafield to ClothingComponent * Adding SelfUnremovableClothingComponent * ShockCollar Update * Correction of the shock collar * Correction of the shock collar 2 * Renaming the DamageSpecifier DataField to Damage * Fixing the damage field in ShockCollar * Cleaning the ShockCollar * Renaming ShockCollar to ClothingNeckShockCollar * Adding ClothingNeckShockCollar as a stealTarget to a thief * Fixing a typo of the sprite path in ClothingNeckShockCollar * Cleaning the ShockOnTriggerComponent * Revision of SelfUnremovableClothing * Adding a ClothingBackpackElectropack * Sprite fix * Code review * Shock Collar sprite update * add commit hash --------- Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
|||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
using Content.Server.Explosion.EntitySystems;
|
||||||
|
|
||||||
|
namespace Content.Server.Explosion.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A component that electrocutes an entity having this component when a trigger is triggered.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, AutoGenerateComponentPause]
|
||||||
|
[Access(typeof(TriggerSystem))]
|
||||||
|
public sealed partial class ShockOnTriggerComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The force of an electric shock when the trigger is triggered.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public int Damage = 5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Duration of electric shock when the trigger is triggered.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan Duration = TimeSpan.FromSeconds(2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum delay between repeating triggers.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan Cooldown = TimeSpan.FromSeconds(4);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When can the trigger run again?
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||||
|
[AutoPausedField]
|
||||||
|
public TimeSpan NextTrigger = TimeSpan.Zero;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Content.Server.Body.Systems;
|
|||||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||||
using Content.Server.Explosion.Components;
|
using Content.Server.Explosion.Components;
|
||||||
using Content.Server.Flash;
|
using Content.Server.Flash;
|
||||||
|
using Content.Server.Electrocution;
|
||||||
using Content.Server.Pinpointer;
|
using Content.Server.Pinpointer;
|
||||||
using Content.Shared.Flash.Components;
|
using Content.Shared.Flash.Components;
|
||||||
using Content.Server.Radio.EntitySystems;
|
using Content.Server.Radio.EntitySystems;
|
||||||
@@ -33,6 +34,7 @@ using Robust.Shared.Random;
|
|||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Content.Shared.Coordinates;
|
using Content.Shared.Coordinates;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.Explosion.EntitySystems
|
namespace Content.Server.Explosion.EntitySystems
|
||||||
{
|
{
|
||||||
@@ -75,6 +77,7 @@ namespace Content.Server.Explosion.EntitySystems
|
|||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||||
|
[Dependency] private readonly ElectrocutionSystem _electrocution = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -104,6 +107,7 @@ namespace Content.Server.Explosion.EntitySystems
|
|||||||
|
|
||||||
SubscribeLocalEvent<AnchorOnTriggerComponent, TriggerEvent>(OnAnchorTrigger);
|
SubscribeLocalEvent<AnchorOnTriggerComponent, TriggerEvent>(OnAnchorTrigger);
|
||||||
SubscribeLocalEvent<SoundOnTriggerComponent, TriggerEvent>(OnSoundTrigger);
|
SubscribeLocalEvent<SoundOnTriggerComponent, TriggerEvent>(OnSoundTrigger);
|
||||||
|
SubscribeLocalEvent<ShockOnTriggerComponent, TriggerEvent>(HandleShockTrigger);
|
||||||
SubscribeLocalEvent<RattleComponent, TriggerEvent>(HandleRattleTrigger);
|
SubscribeLocalEvent<RattleComponent, TriggerEvent>(HandleRattleTrigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +124,24 @@ namespace Content.Server.Explosion.EntitySystems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleShockTrigger(Entity<ShockOnTriggerComponent> 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)
|
private void OnAnchorTrigger(EntityUid uid, AnchorOnTriggerComponent component, TriggerEvent args)
|
||||||
{
|
{
|
||||||
var xform = Transform(uid);
|
var xform = Transform(uid);
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ namespace Content.Server.Strip
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (time, stealth) = GetStripTimeModifiers(user, target, slotDef.StripTime);
|
var (time, stealth) = GetStripTimeModifiers(user, target, held, slotDef.StripTime);
|
||||||
|
|
||||||
if (!stealth)
|
if (!stealth)
|
||||||
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-insert", ("user", Identity.Entity(user, EntityManager)), ("item", user.Comp.ActiveHandEntity!.Value)), target, target, PopupType.Large);
|
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-insert", ("user", Identity.Entity(user, EntityManager)), ("item", user.Comp.ActiveHandEntity!.Value)), target, target, PopupType.Large);
|
||||||
@@ -306,7 +306,7 @@ namespace Content.Server.Strip
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (time, stealth) = GetStripTimeModifiers(user, target, slotDef.StripTime);
|
var (time, stealth) = GetStripTimeModifiers(user, target, item, slotDef.StripTime);
|
||||||
|
|
||||||
if (!stealth)
|
if (!stealth)
|
||||||
{
|
{
|
||||||
@@ -411,7 +411,7 @@ namespace Content.Server.Strip
|
|||||||
if (!CanStripInsertHand(user, target, held, handName))
|
if (!CanStripInsertHand(user, target, held, handName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay);
|
var (time, stealth) = GetStripTimeModifiers(user, target, null, targetStrippable.HandStripDelay);
|
||||||
|
|
||||||
if (!stealth)
|
if (!stealth)
|
||||||
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-insert-hand", ("user", Identity.Entity(user, EntityManager)), ("item", user.Comp.ActiveHandEntity!.Value)), target, target, PopupType.Large);
|
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-insert-hand", ("user", Identity.Entity(user, EntityManager)), ("item", user.Comp.ActiveHandEntity!.Value)), target, target, PopupType.Large);
|
||||||
@@ -510,7 +510,7 @@ namespace Content.Server.Strip
|
|||||||
if (!CanStripRemoveHand(user, target, item, handName))
|
if (!CanStripRemoveHand(user, target, item, handName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay);
|
var (time, stealth) = GetStripTimeModifiers(user, target, null, targetStrippable.HandStripDelay);
|
||||||
|
|
||||||
if (!stealth)
|
if (!stealth)
|
||||||
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", item)), target, target);
|
_popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", item)), target, target);
|
||||||
|
|||||||
@@ -69,6 +69,13 @@ public sealed partial class ClothingComponent : Component
|
|||||||
|
|
||||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
public TimeSpan UnequipDelay = TimeSpan.Zero;
|
public TimeSpan UnequipDelay = TimeSpan.Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Offset for the strip time for an entity with this component.
|
||||||
|
/// Only applied when it is being equipped or removed by another player.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan StripDelay = TimeSpan.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Content.Shared.Clothing.EntitySystems;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Clothing.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The component prohibits the player from taking off clothes on them that have this component.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 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.
|
||||||
|
///</remarks>
|
||||||
|
[NetworkedComponent]
|
||||||
|
[RegisterComponent]
|
||||||
|
[Access(typeof(SelfUnremovableClothingSystem))]
|
||||||
|
public sealed partial class SelfUnremovableClothingComponent : Component
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ using Content.Shared.Interaction.Events;
|
|||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
using Content.Shared.Item;
|
using Content.Shared.Item;
|
||||||
|
using Content.Shared.Strip.Components;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
@@ -32,6 +33,8 @@ public abstract class ClothingSystem : EntitySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<ClothingComponent, ClothingEquipDoAfterEvent>(OnEquipDoAfter);
|
SubscribeLocalEvent<ClothingComponent, ClothingEquipDoAfterEvent>(OnEquipDoAfter);
|
||||||
SubscribeLocalEvent<ClothingComponent, ClothingUnequipDoAfterEvent>(OnUnequipDoAfter);
|
SubscribeLocalEvent<ClothingComponent, ClothingUnequipDoAfterEvent>(OnUnequipDoAfter);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ClothingComponent, BeforeItemStrippedEvent>(OnItemStripped);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUseInHand(Entity<ClothingComponent> ent, ref UseInHandEvent args)
|
private void OnUseInHand(Entity<ClothingComponent> ent, ref UseInHandEvent args)
|
||||||
@@ -192,6 +195,11 @@ public abstract class ClothingSystem : EntitySystem
|
|||||||
_handsSystem.TryPickup(args.User, ent);
|
_handsSystem.TryPickup(args.User, ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnItemStripped(Entity<ClothingComponent> ent, ref BeforeItemStrippedEvent args)
|
||||||
|
{
|
||||||
|
args.Additive += ent.Comp.StripDelay;
|
||||||
|
}
|
||||||
|
|
||||||
private void CheckEquipmentForLayerHide(EntityUid equipment, EntityUid equipee)
|
private void CheckEquipmentForLayerHide(EntityUid equipment, EntityUid equipee)
|
||||||
{
|
{
|
||||||
if (TryComp(equipment, out HideLayerClothingComponent? clothesComp) && TryComp(equipee, out HumanoidAppearanceComponent? appearanceComp))
|
if (TryComp(equipment, out HideLayerClothingComponent? clothesComp) && TryComp(equipee, out HumanoidAppearanceComponent? appearanceComp))
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A system for the operation of a component that prohibits the player from taking off his own clothes that have this component.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class SelfUnremovableClothingSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<SelfUnremovableClothingComponent, BeingUnequippedAttemptEvent>(OnUnequip);
|
||||||
|
SubscribeLocalEvent<SelfUnremovableClothingComponent, ExaminedEvent>(OnUnequipMarkup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnequip(Entity<SelfUnremovableClothingComponent> selfUnremovableClothing, ref BeingUnequippedAttemptEvent args)
|
||||||
|
{
|
||||||
|
if (TryComp<ClothingComponent>(selfUnremovableClothing, out var clothing) && (clothing.Slots & args.SlotFlags) == SlotFlags.NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.UnEquipTarget == args.Unequipee)
|
||||||
|
{
|
||||||
|
args.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnequipMarkup(Entity<SelfUnremovableClothingComponent> selfUnremovableClothing, ref ExaminedEvent args)
|
||||||
|
{
|
||||||
|
args.PushMarkup(Loc.GetString("comp-self-unremovable-clothing"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -95,7 +95,7 @@ public sealed class ToggleableClothingSystem : EntitySystem
|
|||||||
if (component.StripDelay == null)
|
if (component.StripDelay == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var (time, stealth) = _strippable.GetStripTimeModifiers(user, wearer, component.StripDelay.Value);
|
var (time, stealth) = _strippable.GetStripTimeModifiers(user, wearer, item, component.StripDelay.Value);
|
||||||
|
|
||||||
var args = new DoAfterArgs(EntityManager, user, time, new ToggleClothingDoAfterEvent(), item, wearer, item)
|
var args = new DoAfterArgs(EntityManager, user, time, new ToggleClothingDoAfterEvent(), item, wearer, item)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,6 +44,15 @@ namespace Content.Shared.Strip.Components
|
|||||||
public SlotFlags TargetSlots { get; } = SlotFlags.GLOVES;
|
public SlotFlags TargetSlots { get; } = SlotFlags.GLOVES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to modify strip times. Raised directed at the item being stripped.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is also used by some stripping related interactions, i.e., interactions with items that are currently equipped by another player.
|
||||||
|
/// </remarks>
|
||||||
|
[ByRefEvent]
|
||||||
|
public sealed class BeforeItemStrippedEvent(TimeSpan initialTime, bool stealth = false) : BaseBeforeStripEvent(initialTime, stealth);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to modify strip times. Raised directed at the user.
|
/// Used to modify strip times. Raised directed at the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -28,13 +28,19 @@ public abstract class SharedStrippableSystem : EntitySystem
|
|||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (TimeSpan Time, bool Stealth) GetStripTimeModifiers(EntityUid user, EntityUid target, TimeSpan initialTime)
|
/// <summary>
|
||||||
|
/// Modify the strip time via events. Raised directed at the item being stripped, the player stripping someone and the player being stripped.
|
||||||
|
/// </summary>
|
||||||
|
public (TimeSpan Time, bool Stealth) GetStripTimeModifiers(EntityUid user, EntityUid targetPlayer, EntityUid? targetItem, TimeSpan initialTime)
|
||||||
{
|
{
|
||||||
var userEv = new BeforeStripEvent(initialTime);
|
var itemEv = new BeforeItemStrippedEvent(initialTime, false);
|
||||||
|
if (targetItem != null)
|
||||||
|
RaiseLocalEvent(targetItem.Value, ref itemEv);
|
||||||
|
var userEv = new BeforeStripEvent(itemEv.Time, itemEv.Stealth);
|
||||||
RaiseLocalEvent(user, ref userEv);
|
RaiseLocalEvent(user, ref userEv);
|
||||||
var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
|
var targetEv = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth);
|
||||||
RaiseLocalEvent(target, ref ev);
|
RaiseLocalEvent(targetPlayer, ref targetEv);
|
||||||
return (ev.Time, ev.Stealth);
|
return (targetEv.Time, targetEv.Stealth);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDragDrop(EntityUid uid, StrippableComponent component, ref DragDropDraggedEvent args)
|
private void OnDragDrop(EntityUid uid, StrippableComponent component, ref DragDropDraggedEvent args)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
comp-self-unremovable-clothing = This cannot be removed without outside help.
|
||||||
@@ -26,6 +26,7 @@ research-technology-salvage-weapons = Salvage Weapons
|
|||||||
research-technology-draconic-munitions = Draconic Munitions
|
research-technology-draconic-munitions = Draconic Munitions
|
||||||
research-technology-uranium-munitions = Uranium Munitions
|
research-technology-uranium-munitions = Uranium Munitions
|
||||||
research-technology-explosive-technology = Explosive Technology
|
research-technology-explosive-technology = Explosive Technology
|
||||||
|
research-technology-special-means = Special Means
|
||||||
research-technology-weaponized-laser-manipulation = Weaponized Laser Manipulation
|
research-technology-weaponized-laser-manipulation = Weaponized Laser Manipulation
|
||||||
research-technology-nonlethal-ammunition = Nonlethal Ammunition
|
research-technology-nonlethal-ammunition = Nonlethal Ammunition
|
||||||
research-technology-practice-ammunition = Practice Ammunition
|
research-technology-practice-ammunition = Practice Ammunition
|
||||||
|
|||||||
@@ -20,6 +20,10 @@
|
|||||||
- id: ClothingOuterHardsuitWarden
|
- id: ClothingOuterHardsuitWarden
|
||||||
- id: HoloprojectorSecurity
|
- id: HoloprojectorSecurity
|
||||||
- id: BookSpaceLaw
|
- id: BookSpaceLaw
|
||||||
|
- id: ClothingNeckShockCollar
|
||||||
|
amount: 2
|
||||||
|
- id: RemoteSignaller
|
||||||
|
amount: 2
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: LockerWardenFilled
|
id: LockerWardenFilled
|
||||||
@@ -42,6 +46,10 @@
|
|||||||
- id: DoorRemoteArmory
|
- id: DoorRemoteArmory
|
||||||
- id: HoloprojectorSecurity
|
- id: HoloprojectorSecurity
|
||||||
- id: BookSpaceLaw
|
- id: BookSpaceLaw
|
||||||
|
- id: ClothingNeckShockCollar
|
||||||
|
amount: 2
|
||||||
|
- id: RemoteSignaller
|
||||||
|
amount: 2
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: LockerSecurityFilled
|
id: LockerSecurityFilled
|
||||||
|
|||||||
@@ -314,6 +314,29 @@
|
|||||||
- type: Unremoveable
|
- type: Unremoveable
|
||||||
deleteOnDrop: false
|
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
|
# Debug
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingBackpack
|
parent: ClothingBackpack
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
mask:
|
mask:
|
||||||
- MachineMask
|
- MachineMask
|
||||||
layer:
|
layer:
|
||||||
- MachineLayer
|
- MachineLayer
|
||||||
- type: Lathe
|
- type: Lathe
|
||||||
- type: MaterialStorage
|
- type: MaterialStorage
|
||||||
- type: Destructible
|
- type: Destructible
|
||||||
@@ -808,6 +808,7 @@
|
|||||||
- WeaponLaserCannon
|
- WeaponLaserCannon
|
||||||
- WeaponLaserCarbine
|
- WeaponLaserCarbine
|
||||||
- WeaponXrayCannon
|
- WeaponXrayCannon
|
||||||
|
- ClothingBackpackElectropack
|
||||||
- type: MaterialStorage
|
- type: MaterialStorage
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
ForensicScannerStealObjective: 1 #sec
|
ForensicScannerStealObjective: 1 #sec
|
||||||
FlippoEngravedLighterStealObjective: 0.5
|
FlippoEngravedLighterStealObjective: 0.5
|
||||||
ClothingHeadHatWardenStealObjective: 1
|
ClothingHeadHatWardenStealObjective: 1
|
||||||
|
ClothingNeckShockCollarStealObjective: 1
|
||||||
ClothingOuterHardsuitVoidParamedStealObjective: 1 #med
|
ClothingOuterHardsuitVoidParamedStealObjective: 1 #med
|
||||||
MedicalTechFabCircuitboardStealObjective: 1
|
MedicalTechFabCircuitboardStealObjective: 1
|
||||||
ClothingHeadsetAltMedicalStealObjective: 1
|
ClothingHeadsetAltMedicalStealObjective: 1
|
||||||
|
|||||||
@@ -272,6 +272,13 @@
|
|||||||
sprite: Clothing/Neck/Medals/clownmedal.rsi
|
sprite: Clothing/Neck/Medals/clownmedal.rsi
|
||||||
state: icon
|
state: icon
|
||||||
|
|
||||||
|
- type: stealTargetGroup
|
||||||
|
id: ClothingNeckShockCollar
|
||||||
|
name: shock collar
|
||||||
|
sprite:
|
||||||
|
sprite: Clothing/Neck/Misc/shock_collar.rsi
|
||||||
|
state: icon
|
||||||
|
|
||||||
#Thief structures
|
#Thief structures
|
||||||
|
|
||||||
- type: stealTargetGroup
|
- type: stealTargetGroup
|
||||||
|
|||||||
@@ -316,6 +316,17 @@
|
|||||||
- type: Objective
|
- type: Objective
|
||||||
difficulty: 1
|
difficulty: 1
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseThiefStealObjective
|
||||||
|
id: ClothingNeckShockCollarStealObjective
|
||||||
|
components:
|
||||||
|
- type: NotJobRequirement
|
||||||
|
job: Warden
|
||||||
|
- type: StealCondition
|
||||||
|
stealGroup: ClothingNeckShockCollar
|
||||||
|
- type: Objective
|
||||||
|
difficulty: 1
|
||||||
|
|
||||||
# Structures
|
# Structures
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
materials:
|
materials:
|
||||||
Steel: 250
|
Steel: 250
|
||||||
Plastic: 100
|
Plastic: 100
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: WeaponLaserCarbine
|
id: WeaponLaserCarbine
|
||||||
result: WeaponLaserCarbine
|
result: WeaponLaserCarbine
|
||||||
@@ -89,6 +89,15 @@
|
|||||||
Plastic: 250
|
Plastic: 250
|
||||||
Gold: 100
|
Gold: 100
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: ClothingBackpackElectropack
|
||||||
|
result: ClothingBackpackElectropack
|
||||||
|
completetime: 4
|
||||||
|
materials:
|
||||||
|
Steel: 500
|
||||||
|
Plastic: 250
|
||||||
|
Cloth: 500
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: ForensicPad
|
id: ForensicPad
|
||||||
result: ForensicPad
|
result: ForensicPad
|
||||||
@@ -655,7 +664,7 @@
|
|||||||
Steel: 1000
|
Steel: 1000
|
||||||
Glass: 500
|
Glass: 500
|
||||||
Plastic: 500
|
Plastic: 500
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: MagazineGrenadeEmpty
|
id: MagazineGrenadeEmpty
|
||||||
result: MagazineGrenadeEmpty
|
result: MagazineGrenadeEmpty
|
||||||
@@ -663,7 +672,7 @@
|
|||||||
materials:
|
materials:
|
||||||
Steel: 150
|
Steel: 150
|
||||||
Plastic: 50
|
Plastic: 50
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: GrenadeEMP
|
id: GrenadeEMP
|
||||||
result: GrenadeEMP
|
result: GrenadeEMP
|
||||||
@@ -672,7 +681,7 @@
|
|||||||
Steel: 150
|
Steel: 150
|
||||||
Plastic: 100
|
Plastic: 100
|
||||||
Glass: 20
|
Glass: 20
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: GrenadeBlast
|
id: GrenadeBlast
|
||||||
result: GrenadeBlast
|
result: GrenadeBlast
|
||||||
@@ -681,7 +690,7 @@
|
|||||||
Steel: 450
|
Steel: 450
|
||||||
Plastic: 300
|
Plastic: 300
|
||||||
Gold: 150
|
Gold: 150
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: GrenadeFlash
|
id: GrenadeFlash
|
||||||
result: GrenadeFlash
|
result: GrenadeFlash
|
||||||
|
|||||||
@@ -58,8 +58,8 @@
|
|||||||
cost: 5000
|
cost: 5000
|
||||||
recipeUnlocks:
|
recipeUnlocks:
|
||||||
- MagazineShotgunBeanbag
|
- MagazineShotgunBeanbag
|
||||||
- BoxShellTranquilizer
|
- BoxShellTranquilizer
|
||||||
- BoxBeanbag
|
- BoxBeanbag
|
||||||
- WeaponDisabler
|
- WeaponDisabler
|
||||||
|
|
||||||
- type: technology
|
- type: technology
|
||||||
@@ -115,6 +115,18 @@
|
|||||||
- ExplosivePayload
|
- ExplosivePayload
|
||||||
- ChemicalPayload
|
- ChemicalPayload
|
||||||
|
|
||||||
|
- 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
|
# Tier 2
|
||||||
|
|
||||||
- type: technology
|
- type: technology
|
||||||
@@ -144,7 +156,7 @@
|
|||||||
- type: technology
|
- type: technology
|
||||||
id: BasicShuttleArmament
|
id: BasicShuttleArmament
|
||||||
name: research-technology-basic-shuttle-armament
|
name: research-technology-basic-shuttle-armament
|
||||||
icon:
|
icon:
|
||||||
sprite: Structures/Power/cage_recharger.rsi
|
sprite: Structures/Power/cage_recharger.rsi
|
||||||
state: full
|
state: full
|
||||||
discipline: Arsenal
|
discipline: Arsenal
|
||||||
@@ -189,11 +201,11 @@
|
|||||||
cost: 15000
|
cost: 15000
|
||||||
recipeUnlocks:
|
recipeUnlocks:
|
||||||
- WeaponLaserSvalinn
|
- WeaponLaserSvalinn
|
||||||
|
|
||||||
- type: technology
|
- type: technology
|
||||||
id: AdvancedShuttleWeapon
|
id: AdvancedShuttleWeapon
|
||||||
name: research-technology-advanced-shuttle-weapon
|
name: research-technology-advanced-shuttle-weapon
|
||||||
icon:
|
icon:
|
||||||
sprite: Objects/Weapons/Guns/Ammunition/Magazine/Grenade/grenade_cartridge.rsi
|
sprite: Objects/Weapons/Guns/Ammunition/Magazine/Grenade/grenade_cartridge.rsi
|
||||||
state: icon
|
state: icon
|
||||||
discipline: Arsenal
|
discipline: Arsenal
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 594 B |
Binary file not shown.
|
After Width: | Height: | Size: 457 B |
Binary file not shown.
|
After Width: | Height: | Size: 432 B |
Binary file not shown.
|
After Width: | Height: | Size: 441 B |
@@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 465 B |
BIN
Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/icon.png
Normal file
BIN
Resources/Textures/Clothing/Neck/Misc/shock_collar.rsi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 800 B |
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Drawn by EmoGarbage404 (github) for Space Station 14",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "equipped-NECK",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user