This commit is contained in:
Rane
2022-02-17 21:43:24 -05:00
committed by GitHub
parent 94c56980cb
commit 8049a709e6
29 changed files with 323 additions and 8 deletions

View File

@@ -12,6 +12,7 @@ namespace Content.Client.Power.APC
public static readonly Color LackColor = Color.FromHex("#d1332e"); public static readonly Color LackColor = Color.FromHex("#d1332e");
public static readonly Color ChargingColor = Color.FromHex("#2e8ad1"); public static readonly Color ChargingColor = Color.FromHex("#2e8ad1");
public static readonly Color FullColor = Color.FromHex("#3db83b"); public static readonly Color FullColor = Color.FromHex("#3db83b");
public static readonly Color EmagColor = Color.FromHex("#1f48d6");
[UsedImplicitly] [UsedImplicitly]
public override void InitializeEntity(EntityUid entity) public override void InitializeEntity(EntityUid entity)
@@ -55,6 +56,9 @@ namespace Content.Client.Power.APC
case ApcChargeState.Full: case ApcChargeState.Full:
sprite.LayerSetState(Layers.ChargeState, "apco3-2"); sprite.LayerSetState(Layers.ChargeState, "apco3-2");
break; break;
case ApcChargeState.Emag:
sprite.LayerSetState(Layers.ChargeState, "emag-unlit");
break;
} }
if (ent.TryGetComponent(component.Owner, out SharedPointLightComponent? light)) if (ent.TryGetComponent(component.Owner, out SharedPointLightComponent? light))
@@ -64,6 +68,7 @@ namespace Content.Client.Power.APC
ApcChargeState.Lack => LackColor, ApcChargeState.Lack => LackColor,
ApcChargeState.Charging => ChargingColor, ApcChargeState.Charging => ChargingColor,
ApcChargeState.Full => FullColor, ApcChargeState.Full => FullColor,
ApcChargeState.Emag => EmagColor,
_ => LackColor _ => LackColor
}; };
} }

View File

@@ -2,6 +2,7 @@ using Content.Server.Atmos.Monitor.Components;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Shared.Atmos.Monitor; using Content.Shared.Atmos.Monitor;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Emag.Systems;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -16,6 +17,7 @@ namespace Content.Server.Atmos.Monitor.Systems
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<FireAlarmComponent, InteractHandEvent>(OnInteractHand); SubscribeLocalEvent<FireAlarmComponent, InteractHandEvent>(OnInteractHand);
SubscribeLocalEvent<FireAlarmComponent, GotEmaggedEvent>(OnEmagged);
} }
private void OnInteractHand(EntityUid uid, FireAlarmComponent component, InteractHandEvent args) private void OnInteractHand(EntityUid uid, FireAlarmComponent component, InteractHandEvent args)
@@ -38,5 +40,18 @@ namespace Content.Server.Atmos.Monitor.Systems
} }
} }
} }
private void OnEmagged(EntityUid uid, FireAlarmComponent component, GotEmaggedEvent args)
{
if (TryComp<AtmosMonitorComponent>(uid, out var atmosMonitor))
{
if (atmosMonitor?.MonitorFire == true)
{
atmosMonitor.MonitorFire = false;
_monitorSystem.Alert(uid, AtmosMonitorAlarmType.Emagged);
args.Handled = true;
}
}
}
} }
} }

View File

@@ -25,6 +25,7 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Chemistry.Components namespace Content.Server.Chemistry.Components
{ {
@@ -45,7 +46,11 @@ namespace Content.Server.Chemistry.Components
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IEntityManager _entities = default!;
[ViewVariables] [DataField("pack")] private string _packPrototypeId = ""; [ViewVariables] [DataField("pack", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentDispenserInventoryPrototype>))] private string _packPrototypeId = "";
[ViewVariables] [DataField("emagPack", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentDispenserInventoryPrototype>))] public string EmagPackPrototypeId = "";
public bool AlreadyEmagged = false;
[DataField("clickSound")] [DataField("clickSound")]
private SoundSpecifier _clickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"); private SoundSpecifier _clickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
@@ -119,6 +124,24 @@ namespace Content.Server.Chemistry.Components
Inventory.Sort(_comparer); Inventory.Sort(_comparer);
} }
public void AddFromPrototype(string pack)
{
if (string.IsNullOrEmpty(pack)) return;
if (!_prototypeManager.TryIndex(pack, out ReagentDispenserInventoryPrototype? packPrototype))
{
return;
}
foreach (var entry in packPrototype.Inventory)
{
Inventory.Add(new ReagentDispenserInventoryEntry(entry));
}
Inventory.Sort(_comparer);
}
private void OnPowerChanged(PowerChangedMessage e) private void OnPowerChanged(PowerChangedMessage e)
{ {
UpdateUserInterface(); UpdateUserInterface();

View File

@@ -1,14 +1,17 @@
using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Emag.Systems;
using Content.Shared.Chemistry.Dispenser;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.Prototypes;
namespace Content.Server.Chemistry.EntitySystems namespace Content.Server.Chemistry.EntitySystems
{ {
[UsedImplicitly] [UsedImplicitly]
public sealed class ReagentDispenserSystem : SharedReagentDispenserSystem public sealed class ReagentDispenserSystem : SharedReagentDispenserSystem
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -16,6 +19,17 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent<ReagentDispenserComponent, SolutionChangedEvent>((_, comp, _) => comp.UpdateUserInterface()); SubscribeLocalEvent<ReagentDispenserComponent, SolutionChangedEvent>((_, comp, _) => comp.UpdateUserInterface());
SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>((_, comp, _) => comp.UpdateUserInterface()); SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>((_, comp, _) => comp.UpdateUserInterface());
SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>((_, comp, _) => comp.UpdateUserInterface()); SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>((_, comp, _) => comp.UpdateUserInterface());
SubscribeLocalEvent<ReagentDispenserComponent, GotEmaggedEvent>(OnEmagged);
}
private void OnEmagged(EntityUid uid, ReagentDispenserComponent comp, GotEmaggedEvent args)
{
if (!comp.AlreadyEmagged)
{
comp.AddFromPrototype(comp.EmagPackPrototypeId);
comp.AlreadyEmagged = true;
args.Handled = true;
}
} }
} }
} }

View File

@@ -5,11 +5,13 @@ using Content.Server.Construction;
using Content.Server.Construction.Components; using Content.Server.Construction.Components;
using Content.Server.Tools; using Content.Server.Tools;
using Content.Server.Tools.Components; using Content.Server.Tools.Components;
using Content.Server.Doors.Components;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.Doors; using Content.Shared.Doors;
using Content.Shared.Doors.Components; using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems; using Content.Shared.Doors.Systems;
using Content.Shared.Emag.Systems;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Tag; using Content.Shared.Tag;
using Robust.Shared.Audio; using Robust.Shared.Audio;
@@ -39,6 +41,7 @@ public sealed class DoorSystem : SharedDoorSystem
SubscribeLocalEvent<DoorComponent, PryCancelledEvent>(OnPryCancelled); SubscribeLocalEvent<DoorComponent, PryCancelledEvent>(OnPryCancelled);
SubscribeLocalEvent<DoorComponent, WeldFinishedEvent>(OnWeldFinished); SubscribeLocalEvent<DoorComponent, WeldFinishedEvent>(OnWeldFinished);
SubscribeLocalEvent<DoorComponent, WeldCancelledEvent>(OnWeldCancelled); SubscribeLocalEvent<DoorComponent, WeldCancelledEvent>(OnWeldCancelled);
SubscribeLocalEvent<DoorComponent, GotEmaggedEvent>(OnEmagged);
} }
protected override void OnInit(EntityUid uid, DoorComponent door, ComponentInit args) protected override void OnInit(EntityUid uid, DoorComponent door, ComponentInit args)
@@ -303,6 +306,18 @@ public sealed class DoorSystem : SharedDoorSystem
if(!container.Insert(board)) if(!container.Insert(board))
Logger.Warning($"Couldn't insert board {ToPrettyString(board)} into door {ToPrettyString(uid)}!"); Logger.Warning($"Couldn't insert board {ToPrettyString(board)} into door {ToPrettyString(uid)}!");
} }
private void OnEmagged(EntityUid uid, DoorComponent door, GotEmaggedEvent args)
{
if(TryComp<AirlockComponent>(uid, out var airlockComponent))
{
if (door.State == DoorState.Closed)
{
StartOpening(uid);
airlockComponent?.SetBoltsWithAudio(!airlockComponent.IsBolted());
args.Handled = true;
}
}
}
} }
public sealed class PryFinishedEvent : EntityEventArgs { } public sealed class PryFinishedEvent : EntityEventArgs { }

View File

@@ -0,0 +1,32 @@
using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
namespace Content.Server.Emag
{
public sealed class EmagSystem : EntitySystem
{
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var emag in EntityManager.EntityQuery<EmagComponent>())
{
if (emag.Charges == emag.MaxCharges)
{
emag.Accumulator = 0;
continue;
}
emag.Accumulator += frameTime;
if (emag.Accumulator < emag.RechargeTime)
{
continue;
}
emag.Accumulator -= emag.RechargeTime;
emag.Charges++;
}
}
}
}

View File

@@ -1,6 +1,8 @@
using Content.Server.Access.Components; using Content.Server.Access.Components;
using Content.Server.Access.Systems; using Content.Server.Access.Systems;
using Content.Server.Storage.Components; using Content.Server.Storage.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.Emag.Components;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.Examine; using Content.Shared.Examine;
@@ -33,6 +35,7 @@ namespace Content.Server.Lock
SubscribeLocalEvent<LockComponent, ActivateInWorldEvent>(OnActivated); SubscribeLocalEvent<LockComponent, ActivateInWorldEvent>(OnActivated);
SubscribeLocalEvent<LockComponent, ExaminedEvent>(OnExamined); SubscribeLocalEvent<LockComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<LockComponent, GetVerbsEvent<AlternativeVerb>>(AddToggleLockVerb); SubscribeLocalEvent<LockComponent, GetVerbsEvent<AlternativeVerb>>(AddToggleLockVerb);
SubscribeLocalEvent<LockComponent, GotEmaggedEvent>(OnEmagged);
} }
private void OnStartup(EntityUid uid, LockComponent lockComp, ComponentStartup args) private void OnStartup(EntityUid uid, LockComponent lockComp, ComponentStartup args)
@@ -182,5 +185,23 @@ namespace Content.Server.Lock
// TODO VERB ICONS need padlock open/close icons. // TODO VERB ICONS need padlock open/close icons.
args.Verbs.Add(verb); args.Verbs.Add(verb);
} }
private void OnEmagged(EntityUid uid, LockComponent component, GotEmaggedEvent args)
{
if (component.Locked == true)
{
if (component.UnlockSound != null)
{
SoundSystem.Play(Filter.Pvs(component.Owner), component.UnlockSound.GetSound(), component.Owner, AudioParams.Default.WithVolume(-5));
}
if (EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearanceComp))
{
appearanceComp.SetData(StorageVisuals.Locked, false);
}
EntityManager.RemoveComponent<LockComponent>(uid); //Literally destroys the lock as a tell it was emagged
args.Handled = true;
}
}
} }
} }

View File

@@ -29,6 +29,8 @@ public sealed class ApcComponent : BaseApcNetComponent
[ViewVariables] [ViewVariables]
public bool MainBreakerEnabled = true; public bool MainBreakerEnabled = true;
public bool Emagged = false;
public const float HighPowerThreshold = 0.9f; public const float HighPowerThreshold = 0.9f;
public static TimeSpan VisualsChangeDelay = TimeSpan.FromSeconds(1); public static TimeSpan VisualsChangeDelay = TimeSpan.FromSeconds(1);

View File

@@ -5,6 +5,7 @@ using Content.Server.Power.Pow3r;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.APC; using Content.Shared.APC;
using Content.Shared.Emag.Systems;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
@@ -34,6 +35,7 @@ namespace Content.Server.Power.EntitySystems
SubscribeLocalEvent<ApcComponent, MapInitEvent>(OnApcInit); SubscribeLocalEvent<ApcComponent, MapInitEvent>(OnApcInit);
SubscribeLocalEvent<ApcComponent, ChargeChangedEvent>(OnBatteryChargeChanged); SubscribeLocalEvent<ApcComponent, ChargeChangedEvent>(OnBatteryChargeChanged);
SubscribeLocalEvent<ApcComponent, ApcToggleMainBreakerMessage>(OnToggleMainBreaker); SubscribeLocalEvent<ApcComponent, ApcToggleMainBreakerMessage>(OnToggleMainBreaker);
SubscribeLocalEvent<ApcComponent, GotEmaggedEvent>(OnEmagged);
} }
// Change the APC's state only when the battery state changes, or when it's first created. // Change the APC's state only when the battery state changes, or when it's first created.
@@ -68,6 +70,15 @@ namespace Content.Server.Power.EntitySystems
} }
} }
private void OnEmagged(EntityUid uid, ApcComponent comp, GotEmaggedEvent args)
{
if(!comp.Emagged)
{
comp.Emagged = true;
args.Handled = true;
}
}
public void UpdateApcState(EntityUid uid, public void UpdateApcState(EntityUid uid,
ApcComponent? apc=null, ApcComponent? apc=null,
BatteryComponent? battery=null) BatteryComponent? battery=null)
@@ -115,6 +126,9 @@ namespace Content.Server.Power.EntitySystems
ApcComponent? apc=null, ApcComponent? apc=null,
BatteryComponent? battery=null) BatteryComponent? battery=null)
{ {
if (apc != null && apc.Emagged)
return ApcChargeState.Emag;
if (!Resolve(uid, ref apc, ref battery)) if (!Resolve(uid, ref apc, ref battery))
return ApcChargeState.Lack; return ApcChargeState.Lack;

View File

@@ -2,9 +2,11 @@ using Content.Server.Power.Components;
using Content.Server.Recycling.Components; using Content.Server.Recycling.Components;
using Content.Shared.Body.Components; using Content.Shared.Body.Components;
using Content.Shared.Recycling; using Content.Shared.Recycling;
using Content.Shared.Emag.Systems;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Physics.Dynamics; using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Player;
namespace Content.Server.Recycling namespace Content.Server.Recycling
{ {
@@ -14,6 +16,7 @@ namespace Content.Server.Recycling
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<RecyclerComponent, StartCollideEvent>(HandleCollide); SubscribeLocalEvent<RecyclerComponent, StartCollideEvent>(HandleCollide);
SubscribeLocalEvent<RecyclerComponent, GotEmaggedEvent>(OnEmagged);
} }
private void HandleCollide(EntityUid uid, RecyclerComponent component, StartCollideEvent args) private void HandleCollide(EntityUid uid, RecyclerComponent component, StartCollideEvent args)
@@ -53,5 +56,14 @@ namespace Content.Server.Recycling
appearance.SetData(RecyclerVisuals.Bloody, true); appearance.SetData(RecyclerVisuals.Bloody, true);
} }
} }
private void OnEmagged(EntityUid uid, RecyclerComponent component, GotEmaggedEvent args)
{
if (component.Safe == true)
{
component.Safe = false;
args.Handled = true;
}
}
} }
} }

View File

@@ -63,4 +63,5 @@ public enum LogType
Emitter = 59, Emitter = 59,
GhostRoleTaken = 60, GhostRoleTaken = 60,
Chat = 61, Chat = 61,
Emag = 69,
} }

View File

@@ -27,6 +27,11 @@ namespace Content.Shared.APC
/// APC battery is full and has enough power. /// APC battery is full and has enough power.
/// </summary> /// </summary>
Full, Full,
/// <summary>
/// APC is emagged (and not displaying other useful power colors at a glance)
/// </summary>
Emag,
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]

View File

@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Emag.Systems;
using Content.Shared.PDA; using Content.Shared.PDA;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
@@ -22,6 +23,7 @@ namespace Content.Shared.Access.Systems
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<AccessReaderComponent, ComponentInit>(OnInit); SubscribeLocalEvent<AccessReaderComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<AccessReaderComponent, GotEmaggedEvent>(OnEmagged);
} }
private void OnInit(EntityUid uid, AccessReaderComponent reader, ComponentInit args) private void OnInit(EntityUid uid, AccessReaderComponent reader, ComponentInit args)
@@ -36,6 +38,15 @@ namespace Content.Shared.Access.Systems
} }
} }
private void OnEmagged(EntityUid uid, AccessReaderComponent reader, GotEmaggedEvent args)
{
if (reader.Enabled == true)
{
reader.Enabled = false;
args.Handled = true;
}
}
/// <summary> /// <summary>
/// Searches an <see cref="AccessComponent"/> in the entity itself, in its active hand or in its ID slot. /// Searches an <see cref="AccessComponent"/> in the entity itself, in its active hand or in its ID slot.
/// Then compares the found access with the configured access lists to see if it is allowed. /// Then compares the found access with the configured access lists to see if it is allowed.

View File

@@ -8,6 +8,7 @@ namespace Content.Shared.Atmos.Monitor
{ {
Normal = 0, Normal = 0,
Warning = 1, Warning = 1,
Danger = 2 // 1 << 1 is the exact same thing and we're not really doing **bitmasking** are we? Danger = 2, // 1 << 1 is the exact same thing and we're not really doing **bitmasking** are we?
Emagged = 3,
} }
} }

View File

@@ -24,7 +24,7 @@ namespace Content.Shared.Chemistry.Dispenser
/// <summary> /// <summary>
/// A list of reagents which this may dispense. Defined in yaml prototype, see <see cref="ReagentDispenserInventoryPrototype"/>. /// A list of reagents which this may dispense. Defined in yaml prototype, see <see cref="ReagentDispenserInventoryPrototype"/>.
/// </summary> /// </summary>
protected readonly List<ReagentDispenserInventoryEntry> Inventory = new(); public readonly List<ReagentDispenserInventoryEntry> Inventory = new();
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState public sealed class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState

View File

@@ -0,0 +1,16 @@
namespace Content.Shared.Emag.Components
{
[RegisterComponent]
public sealed class EmagComponent : Component
{
[DataField("maxCharges")]
public int MaxCharges = 3;
[DataField("charges")]
public int Charges = 3;
[DataField("rechargeTime")]
public float RechargeTime = 90f;
public float Accumulator = 0f;
}
}

View File

@@ -0,0 +1,65 @@
using Content.Shared.Emag.Components;
using Content.Shared.Interaction;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Robust.Shared.Player;
namespace Content.Shared.Emag.Systems
{
/// How to add an emag interaction:
/// 1. Go to the system for the component you want the interaction with
/// 2. Subscribe to the GotEmaggedEvent
/// 3. Have some check for if this actually needs to be emagged or is already emagged (to stop charge waste)
/// 4. Past the check, add all the effects you desire and HANDLE THE EVENT ARGUMENT so a charge is spent
public sealed class SharedEmagSystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedAdminLogSystem _adminLog = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<EmagComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<EmagComponent, ExaminedEvent>(OnExamine);
}
private void OnExamine(EntityUid uid, EmagComponent component, ExaminedEvent args)
{
args.PushMarkup(Loc.GetString("emag-charges-remaining", ("charges", component.Charges)));
}
private void OnAfterInteract(EntityUid uid, EmagComponent component, AfterInteractEvent args)
{
if (!args.CanReach || args.Target == null)
return;
if (component.Charges <= 0)
{
_popupSystem.PopupEntity(Loc.GetString("emag-no-charges"), args.User, Filter.Entities(args.User));
return;
}
var emaggedEvent = new GotEmaggedEvent(args.User);
RaiseLocalEvent(args.Target.Value, emaggedEvent, false);
if (emaggedEvent.Handled)
{
_popupSystem.PopupEntity(Loc.GetString("emag-success",("target", args.Target)), args.User, Filter.Entities(args.User));
_adminLog.Add(LogType.Emag, LogImpact.High, $"{ToPrettyString(args.User):player} emagged {ToPrettyString(args.Target.Value):target}");
component.Charges--;
return;
}
}
}
public sealed class GotEmaggedEvent : HandledEntityEventArgs
{
public readonly EntityUid UserUid;
public GotEmaggedEvent(EntityUid userUid)
{
userUid = UserUid;
}
}
}

View File

@@ -0,0 +1,3 @@
emag-success = The card zaps something in {THE($target)}.
emag-no-charges = No charges left!
emag-charges-remaining = It has {$charges} charges remaining.

View File

@@ -50,3 +50,18 @@
#- Patron #- Patron
#- JuiceWatermelon #- JuiceWatermelon
#- JuiceBerry #- JuiceBerry
- type: reagentDispenserInventory
id: SodaDispenserEmagInventory
inventory:
- FourteenLoko
- Ephedrine
- Histamine
- type: reagentDispenserInventory
id: BoozeDispenserEmagInventory
inventory:
- AtomicBomb
- Ethanol
- Iron

View File

@@ -24,3 +24,11 @@
- Sulfur - Sulfur
- SulfuricAcid - SulfuricAcid
- Uranium - Uranium
- type: reagentDispenserInventory
id: ChemDispenserEmaggedInventory
inventory: ##Feel free to change this to something more interesting when more chems are added
- Napalm
- Toxin
- Epinephrine
- Ultravasculine

View File

@@ -121,6 +121,14 @@
icon: /Textures/Objects/Misc/guardian_info.rsi/icon.png icon: /Textures/Objects/Misc/guardian_info.rsi/icon.png
price: 14 price: 14
- type: uplinkListing
id: UplinkEmag
category: Utility
itemId: Emag
description: This sequencer, or "emag", can be used to open or hack a huge variety of items around the station.
icon: /Textures/Objects/Tools/emag.rsi/icon.png
price: 8
# Bundles # Bundles
- type: uplinkListing - type: uplinkListing

View File

@@ -0,0 +1,11 @@
- type: entity
parent: BaseItem
id: Emag
name: cryptographic sequencer
description: The iconic card of ill omen.
components:
- type: Emag
- type: Sprite
netsync: false
sprite: Objects/Tools/emag.rsi
state: icon

View File

@@ -25,3 +25,4 @@
- SmallImpassable - SmallImpassable
- type: ReagentDispenser - type: ReagentDispenser
pack: BoozeDispenserInventory pack: BoozeDispenserInventory
emagPack: BoozeDispenserEmagInventory

View File

@@ -9,6 +9,7 @@
state: industrial-working state: industrial-working
- type: ReagentDispenser - type: ReagentDispenser
pack: ChemDispenserStandardInventory pack: ChemDispenserStandardInventory
emagPack: ChemDispenserEmaggedInventory
- type: ApcPowerReceiver - type: ApcPowerReceiver
- type: ExtensionCableReceiver - type: ExtensionCableReceiver
- type: Construction - type: Construction

View File

@@ -25,3 +25,4 @@
- SmallImpassable - SmallImpassable
- type: ReagentDispenser - type: ReagentDispenser
pack: SodaDispenserInventory pack: SodaDispenserInventory
emagPack: SodaDispenserEmagInventory

View File

@@ -27,6 +27,7 @@
Normal: fire_off Normal: fire_off
Warning: fire_off # shouldn't be alarming at a warning Warning: fire_off # shouldn't be alarming at a warning
Danger: fire_on Danger: fire_on
Emagged: fire_emagged
hideOnDepowered: ["fireAlarmState"] hideOnDepowered: ["fireAlarmState"]
- type: WiresVisualizer - type: WiresVisualizer
- type: UserInterface - type: UserInterface

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

View File

@@ -0,0 +1,14 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation wiki at https://tgstation13.org/wiki/File:Emag.png",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
}
]
}