using Content.Server.Wires;
using Content.Shared.Access;
using Content.Shared.Access.Components;
+using Content.Shared.Emag.Components;
using Content.Shared.Wires;
namespace Content.Server.Access;
private int _pulseTimeout = 30;
public override StatusLightState? GetLightState(Wire wire, AccessReaderComponent comp)
- => comp.Enabled ? StatusLightState.On : StatusLightState.Off;
+ {
+ return EntityManager.HasComponent<EmaggedComponent>(comp.Owner) ? StatusLightState.On : StatusLightState.Off;
+ }
public override object StatusKey { get; } = AccessWireActionKey.Status;
public override bool Cut(EntityUid user, Wire wire, AccessReaderComponent comp)
{
WiresSystem.TryCancelWireAction(wire.Owner, PulseTimeoutKey.Key);
- comp.Enabled = false;
+ EntityManager.RemoveComponent<EmaggedComponent>(comp.Owner);
return true;
}
public override bool Mend(EntityUid user, Wire wire, AccessReaderComponent comp)
{
- comp.Enabled = true;
+ EntityManager.AddComponent<EmaggedComponent>(comp.Owner);
return true;
}
public override void Pulse(EntityUid user, Wire wire, AccessReaderComponent comp)
{
- comp.Enabled = false;
+ EntityManager.RemoveComponent<EmaggedComponent>(comp.Owner);
WiresSystem.StartWireAction(wire.Owner, _pulseTimeout, PulseTimeoutKey.Key, new TimedWireEvent(AwaitPulseCancel, wire));
}
{
if (!wire.IsCut)
{
+ // check is still here incase you somehow TOCTOU it into unemagging something it shouldn't
if (EntityManager.TryGetComponent<AccessReaderComponent>(wire.Owner, out var access))
{
- access.Enabled = true;
+ EntityManager.RemoveComponent<EmaggedComponent>(wire.Owner);
}
}
}
using Content.Shared.Body.Components;
using Content.Shared.Buckle.Components;
using Content.Shared.Damage;
+using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Server.Construction;
using Content.Shared.Mobs.Systems;
private void OnEmagged(EntityUid uid, StasisBedComponent component, ref GotEmaggedEvent args)
{
- // Repeatable
+ args.Repeatable = true;
// Reset any metabolisms first so they receive the multiplier correctly
UpdateMetabolisms(uid, component, false);
component.Multiplier = 1 / component.Multiplier;
{
var metabolismRating = args.PartRatings[component.MachinePartMetabolismModifier];
component.Multiplier = component.BaseMultiplier * metabolismRating; //linear scaling so it's not OP
- if (component.Emagged)
+ if (HasComp<EmaggedComponent>(uid))
component.Multiplier = 1f / component.Multiplier;
}
[RegisterComponent]
public sealed class StasisBedComponent : Component
{
- /// <summary>
- /// Stores whether or not the stasis bed has been emagged,
- /// which causes the multiplier to speed up rather than
- /// slow down. Needs to be stored for machine upgrades.
- /// </summary>
- [ViewVariables(VVAccess.ReadWrite)]
- public bool Emagged = false;
-
[DataField("baseMultiplier", required: true), ViewVariables(VVAccess.ReadWrite)]
public float BaseMultiplier = 10f;
[ViewVariables(VVAccess.ReadWrite)]
public string? EmagPackPrototypeId = default!;
- [ViewVariables(VVAccess.ReadWrite)]
- public bool IsEmagged = false;
-
[DataField("clickSound"), ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
using Content.Shared.Chemistry.Dispenser;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Database;
+using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
inventory.AddRange(packPrototype.Inventory);
}
- if (reagentDispenser.IsEmagged
+ if (HasComp<EmaggedComponent>(reagentDispenser.Owner)
&& reagentDispenser.EmagPackPrototypeId is not null
&& _prototypeManager.TryIndex(reagentDispenser.EmagPackPrototypeId, out ReagentDispenserInventoryPrototype? emagPackPrototype))
{
private void OnEmagged(EntityUid uid, ReagentDispenserComponent reagentDispenser, ref GotEmaggedEvent args)
{
- if (!reagentDispenser.IsEmagged)
- {
- reagentDispenser.IsEmagged = true;
- args.Handled = true;
- UpdateUiState(reagentDispenser);
- }
+ // adding component manually to have correct state
+ EntityManager.AddComponent<EmaggedComponent>(uid);
+ UpdateUiState(reagentDispenser);
+ args.Handled = true;
}
private void OnSetDispenseAmountMessage(EntityUid uid, ReagentDispenserComponent reagentDispenser, ReagentDispenserSetDispenseAmountMessage message)
using Content.Shared.CCVar;
using Content.Shared.Communications;
using Content.Shared.Database;
+using Content.Shared.Emag.Components;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Robust.Server.GameObjects;
if (!_interaction.InRangeUnobstructed(console, user))
return false;
- if (TryComp<AccessReaderComponent>(console, out var accessReaderComponent) && accessReaderComponent.Enabled)
+ if (TryComp<AccessReaderComponent>(console, out var accessReaderComponent) && !HasComp<EmaggedComponent>(console))
{
return _accessReaderSystem.IsAllowed(user, accessReaderComponent);
}
[DataField("receiveNukeCodes")]
public bool ReceiveNukeCodes { get; set; } = false;
- /// <summary>
- /// Is fax was emaaged
- /// </summary>
- [ViewVariables(VVAccess.ReadWrite)]
- [DataField("emagged")]
- public bool Emagged { get; set; } = false;
-
/// <summary>
/// Sound to play when fax has been emagged
/// </summary>
using Content.Shared.Administration.Logs;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Database;
+using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.Fax;
using Content.Shared.Interaction;
return;
}
- if (component.KnownFaxes.ContainsValue(newName) && !component.Emagged) // Allow exist names if emagged for fun
+ if (component.KnownFaxes.ContainsValue(newName) && !HasComp<EmaggedComponent>(uid)) // Allow existing names if emagged for fun
{
_popupSystem.PopupEntity(Loc.GetString("fax-machine-popup-name-exist"), uid);
return;
private void OnEmagged(EntityUid uid, FaxMachineComponent component, ref GotEmaggedEvent args)
{
- if (component.Emagged)
- return;
-
_audioSystem.PlayPvs(component.EmagSound, uid);
- component.Emagged = true;
args.Handled = true;
}
switch (command)
{
case FaxConstants.FaxPingCommand:
- var isForSyndie = component.Emagged &&
+ var isForSyndie = HasComp<EmaggedComponent>(uid) &&
args.Data.ContainsKey(FaxConstants.FaxSyndicateData);
if (!isForSyndie && !component.ResponsePings)
return;
{ DeviceNetworkConstants.Command, FaxConstants.FaxPingCommand }
};
- if (component.Emagged)
+ if (HasComp<EmaggedComponent>(uid))
payload.Add(FaxConstants.FaxSyndicateData, true);
_deviceNetworkSystem.QueuePacket(uid, null, payload);
[ViewVariables]
public bool MainBreakerEnabled = true;
- public bool Emagged = false;
-
public const float HighPowerThreshold = 0.9f;
public static TimeSpan VisualsChangeDelay = TimeSpan.FromSeconds(1);
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.APC;
+using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.Examine;
using Content.Shared.Interaction;
private void OnEmagged(EntityUid uid, ApcComponent comp, ref GotEmaggedEvent args)
{
- if(!comp.Emagged)
- {
- comp.Emagged = true;
- args.Handled = true;
- }
+ // no fancy conditions
+ args.Handled = true;
}
public void UpdateApcState(EntityUid uid,
ApcComponent? apc=null,
BatteryComponent? battery=null)
{
- if (apc != null && apc.Emagged)
+ if (apc != null && HasComp<EmaggedComponent>(uid))
return ApcChargeState.Emag;
if (!Resolve(uid, ref apc, ref battery))
[DataField("enabled")]
public bool Enabled;
- /// <summary>
- /// Whether or not sentient beings will be recycled
- /// </summary>
- [ViewVariables(VVAccess.ReadWrite)]
- [DataField("safe")]
- internal bool Safe = true;
-
/// <summary>
/// The percentage of material that will be recovered
/// </summary>
using Content.Server.Recycling.Components;
using Content.Shared.Audio;
using Content.Shared.Body.Components;
+using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
// Can only recycle things that are tagged trash or recyclable... And also check the safety of the thing to recycle.
if (!_tags.HasAnyTag(entity, "Trash", "Recyclable") &&
- (!TryComp(entity, out recyclable) || !recyclable.Safe && component.Safe))
+ (!TryComp(entity, out recyclable) || !recyclable.Safe && !HasComp<EmaggedComponent>(component.Owner)))
{
return;
}
private bool CanGib(RecyclerComponent component, EntityUid entity)
{
- return HasComp<BodyComponent>(entity) && !component.Safe &&
+ return HasComp<BodyComponent>(entity) && HasComp<EmaggedComponent>(component.Owner) &&
this.IsPowered(component.Owner, EntityManager);
}
private void OnEmagged(EntityUid uid, RecyclerComponent component, ref GotEmaggedEvent args)
{
- if (!component.Safe) return;
- component.Safe = false;
+ // no fancy conditions
args.Handled = true;
}
}
using Content.Shared.Actions.ActionTypes;
using Content.Shared.Damage;
using Content.Shared.Destructible;
+using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.Popups;
using Content.Shared.Throwing;
private void OnEmagged(EntityUid uid, VendingMachineComponent component, ref GotEmaggedEvent args)
{
- if (component.Emagged || component.EmaggedInventory.Count == 0 )
- return;
-
- component.Emagged = true;
- args.Handled = true;
+ // only emag if there are emag-only items
+ args.Handled = component.EmaggedInventory.Count > 0;
}
private void OnDamage(EntityUid uid, VendingMachineComponent component, DamageChangedEvent args)
if (TryComp<AccessReaderComponent?>(vendComponent.Owner, out var accessReader))
{
- if (!_accessReader.IsAllowed(sender.Value, accessReader) && !vendComponent.Emagged)
+ if (!_accessReader.IsAllowed(sender.Value, accessReader) && !HasComp<EmaggedComponent>(uid))
{
_popupSystem.PopupEntity(Loc.GetString("vending-machine-component-try-eject-access-denied"), uid);
Deny(uid, vendComponent);
private VendingMachineInventoryEntry? GetEntry(string entryId, InventoryType type, VendingMachineComponent component)
{
- if (type == InventoryType.Emagged && component.Emagged)
+ if (type == InventoryType.Emagged && HasComp<EmaggedComponent>(component.Owner))
return component.EmaggedInventory.GetValueOrDefault(entryId);
if (type == InventoryType.Contraband && component.Contraband)
[RegisterComponent]
public sealed class AccessReaderComponent : Component
{
- /// <summary>
- /// Whether this reader is enabled or not. If disabled, all access
- /// checks will pass.
- /// </summary>
- [ViewVariables(VVAccess.ReadWrite)]
- public bool Enabled = true;
-
/// <summary>
/// The set of tags that will automatically deny an allowed check, if any of them are present.
/// </summary>
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Inventory;
+using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.PDA;
using Content.Shared.Access.Components;
{
if (args.User == null) // AutoLink (and presumably future external linkers) have no user.
return;
- if (component.Enabled && !IsAllowed(args.User.Value, component))
+ if (!HasComp<EmaggedComponent>(uid) && !IsAllowed(args.User.Value, component))
args.Cancel();
}
private void OnEmagged(EntityUid uid, AccessReaderComponent reader, ref GotEmaggedEvent args)
{
- if (reader.Enabled)
- {
- reader.Enabled = false;
- args.Handled = true;
- }
+ // no fancy conditions
+ args.Handled = true;
}
+
/// <summary>
/// Searches the source for access tags
/// then compares it with the targets readers access list to see if it is allowed.
/// <param name="reader">An access reader to check against</param>
public bool IsAllowed(ICollection<string> accessTags, AccessReaderComponent reader)
{
- if (!reader.Enabled)
+ if (HasComp<EmaggedComponent>(reader.Owner))
{
// Access reader is totally disabled, so access is always allowed.
return true;
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Emag.Components;
+
+/// <summary>
+/// Marker component for emagged entities
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed class EmaggedComponent : Component
+{
+}
/// </summary>
public bool DoEmagEffect(EntityUid user, EntityUid target)
{
+ // prevent emagging twice
+ if (HasComp<EmaggedComponent>(target))
+ return false;
+
var emaggedEvent = new GotEmaggedEvent(user);
RaiseLocalEvent(target, ref emaggedEvent);
+
+ if (!emaggedEvent.Repeatable)
+ EnsureComp<EmaggedComponent>(target);
return emaggedEvent.Handled;
}
}
[ByRefEvent]
- public record struct GotEmaggedEvent(EntityUid UserUid, bool Handled = false);
+ public record struct GotEmaggedEvent(EntityUid UserUid, bool Handled = false, bool Repeatable = false);
}
+using Content.Shared.Emag.Components;
using Robust.Shared.Prototypes;
using System.Linq;
/// <summary>
/// Returns all of the vending machine's inventory. Only includes emagged and contraband inventories if
- /// <see cref="VendingMachineComponent.Emagged"/> and <see cref="VendingMachineComponent.Contraband"/>
+ /// <see cref="EmaggedComponent"/> exists and <see cref="VendingMachineComponent.Contraband"/> is true
/// are <c>true</c> respectively.
/// </summary>
/// <param name="uid"></param>
var inventory = new List<VendingMachineInventoryEntry>(component.Inventory.Values);
- if (component.Emagged)
+ if (HasComp<EmaggedComponent>(uid))
inventory.AddRange(component.EmaggedInventory.Values);
if (component.Contraband)
[ViewVariables]
public Dictionary<string, VendingMachineInventoryEntry> ContrabandInventory = new();
- public bool Emagged;
public bool Contraband;
public bool Ejecting;