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;
public override bool Mend(EntityUid user, Wire wire, AccessReaderComponent comp)
{
- if (!EntityManager.HasComponent<EmaggedComponent>(wire.Owner))
- {
- comp.Enabled = true;
- EntityManager.Dirty(wire.Owner, comp);
- }
+ comp.Enabled = true;
+ EntityManager.Dirty(wire.Owner, comp);
+
return true;
}
{
if (!wire.IsCut)
{
- if (EntityManager.TryGetComponent<AccessReaderComponent>(wire.Owner, out var access) && !EntityManager.HasComponent<EmaggedComponent>(wire.Owner))
+ if (EntityManager.TryGetComponent<AccessReaderComponent>(wire.Owner, out var access))
{
access.Enabled = true;
EntityManager.Dirty(wire.Owner, access);
$"{ToPrettyString(player):player} has modified {ToPrettyString(accessReaderEnt.Value):entity} with the following allowed access level holders: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]");
accessReaderEnt.Value.Comp.AccessLists = ConvertAccessListToHashSet(newAccessList);
+
+ var ev = new OnAccessOverriderAccessUpdatedEvent(player);
+ RaiseLocalEvent(component.TargetAccessReaderId, ref ev);
+
Dirty(accessReaderEnt.Value);
}
if (_random.Prob(tech.Comp.EmagSupercritProbability))
{
- _emag.DoEmagEffect(tech, source);
- _emag.DoEmagEffect(tech, sink);
+ var sourceEv = new GotEmaggedEvent(tech, EmagType.Access | EmagType.Interaction);
+ RaiseLocalEvent(source, ref sourceEv);
+
+ var sinkEv = new GotEmaggedEvent(tech, EmagType.Access | EmagType.Interaction);
+ RaiseLocalEvent(sink, ref sinkEv);
}
CreateNewLink(tech, source, sink);
{
[Dependency] private readonly AtmosDeviceNetworkSystem _atmosDevNet = default!;
[Dependency] private readonly AtmosAlarmableSystem _atmosAlarmable = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly AccessReaderSystem _access = default!;
[Dependency] private readonly IConfigurationManager _configManager = default!;
private void OnEmagged(EntityUid uid, FireAlarmComponent component, ref GotEmaggedEvent args)
{
- if (TryComp<AtmosAlarmableComponent>(uid, out var alarmable))
- {
- // Remove the atmos alarmable component permanently from this device.
- _atmosAlarmable.ForceAlert(uid, AtmosAlarmType.Emagged, alarmable);
- RemCompDeferred<AtmosAlarmableComponent>(uid);
- }
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
+ if (!TryComp<AtmosAlarmableComponent>(uid, out var alarmable))
+ return;
+
+ // Remove the atmos alarmable component permanently from this device.
+ _atmosAlarmable.ForceAlert(uid, AtmosAlarmType.Emagged, alarmable);
+ RemCompDeferred<AtmosAlarmableComponent>(uid);
+ args.Handled = true;
}
}
{
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly ActionsSystem _actionsSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly SleepingSystem _sleepingSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
private void OnEmagged(EntityUid uid, StasisBedComponent component, ref GotEmaggedEvent args)
{
- args.Repeatable = true;
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
// Reset any metabolisms first so they receive the multiplier correctly
UpdateMetabolisms(uid, component, false);
component.Multiplier = 1 / component.Multiplier;
using Content.Shared.Cargo.Events;
using Content.Shared.Cargo.Prototypes;
using Content.Shared.Database;
-using Content.Shared.Emag.Components;
+using Content.Shared.Emag.Systems;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Paper;
public sealed partial class CargoSystem
{
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
/// <summary>
/// How much time to wait (in seconds) before increasing bank accounts balance.
SubscribeLocalEvent<CargoOrderConsoleComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<CargoOrderConsoleComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<CargoOrderConsoleComponent, BankBalanceUpdatedEvent>(OnOrderBalanceUpdated);
+ SubscribeLocalEvent<CargoOrderConsoleComponent, GotEmaggedEvent>(OnEmagged);
Reset();
}
_timer = 0;
}
+ private void OnEmagged(Entity<CargoOrderConsoleComponent> ent, ref GotEmaggedEvent args)
+ {
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(ent, EmagType.Interaction))
+ return;
+
+ args.Handled = true;
+ }
+
private void UpdateConsole(float frameTime)
{
_timer += frameTime;
order.Approved = true;
_audio.PlayPvs(component.ConfirmSound, uid);
- if (!HasComp<EmaggedComponent>(uid))
+ if (!_emag.CheckFlag(uid, EmagType.Interaction))
{
var tryGetIdentityShortInfoEvent = new TryGetIdentityShortInfoEvent(uid, player);
RaiseLocalEvent(tryGetIdentityShortInfoEvent);
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
[Dependency] private readonly SharedJobSystem _jobs = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
public readonly Dictionary<MindComponent, EntityUid> ClonesWaitingForMind = new();
public const float EasyModeCloningCost = 0.7f;
/// </summary>
private void OnEmagged(EntityUid uid, CloningPodComponent clonePod, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
if (!this.IsPowered(uid, EntityManager))
return;
- _audio.PlayPvs(clonePod.SparkSound, uid);
_popupSystem.PopupEntity(Loc.GetString("cloning-pod-component-upgrade-emag-requirement"), uid);
args.Handled = true;
}
var indices = _transformSystem.GetGridTilePositionOrDefault((uid, transform));
var tileMix = _atmosphereSystem.GetTileMixture(transform.GridUid, null, indices, true);
- if (HasComp<EmaggedComponent>(uid))
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
{
_audio.PlayPvs(clonePod.ScreamSound, uid);
Spawn(clonePod.MobSpawnId, transform.Coordinates);
}
_puddleSystem.TrySpillAt(uid, bloodSolution, out _);
- if (!HasComp<EmaggedComponent>(uid))
+ if (!_emag.CheckFlag(uid, EmagType.Interaction))
{
_material.SpawnMultipleFromMaterial(_robustRandom.Next(1, (int) (clonePod.UsedBiomass / 2.5)), clonePod.RequiredMaterial, Transform(uid).Coordinates);
}
using Content.Shared.Communications;
using Content.Shared.Database;
using Content.Shared.DeviceNetwork;
-using Content.Shared.Emag.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Popups;
using Robust.Server.GameObjects;
private bool CanUse(EntityUid user, EntityUid console)
{
- if (TryComp<AccessReaderComponent>(console, out var accessReaderComponent) && !HasComp<EmaggedComponent>(console))
+ if (TryComp<AccessReaderComponent>(console, out var accessReaderComponent))
{
return _accessReaderSystem.IsAllowed(user, console, accessReaderComponent);
}
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly FaxecuteSystem _faxecute = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
private const string PaperSlotId = "Paper";
return;
}
- if (component.KnownFaxes.ContainsValue(newName) && !HasComp<EmaggedComponent>(uid)) // Allow existing names if emagged for fun
+ if (component.KnownFaxes.ContainsValue(newName) && !_emag.CheckFlag(uid, EmagType.Interaction)) // 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)
{
- _audioSystem.PlayPvs(component.EmagSound, uid);
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
args.Handled = true;
}
switch (command)
{
case FaxConstants.FaxPingCommand:
- var isForSyndie = HasComp<EmaggedComponent>(uid) &&
+ var isForSyndie = _emag.CheckFlag(uid, EmagType.Interaction) &&
args.Data.ContainsKey(FaxConstants.FaxSyndicateData);
if (!isForSyndie && !component.ResponsePings)
return;
{ DeviceNetworkConstants.Command, FaxConstants.FaxPingCommand }
};
- if (HasComp<EmaggedComponent>(uid))
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
payload.Add(FaxConstants.FaxSyndicateData, true);
_deviceNetworkSystem.QueuePacket(uid, null, payload);
using Content.Shared.UserInterface;
using Content.Shared.Database;
using Content.Shared.Emag.Components;
+using Content.Shared.Emag.Systems;
using Content.Shared.Examine;
using Content.Shared.Lathe;
using Content.Shared.Materials;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly ContainerSystem _container = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly UserInterfaceSystem _uiSys = default!;
[Dependency] private readonly MaterialStorageSystem _materialStorage = default!;
[Dependency] private readonly PopupSystem _popup = default!;
{
if (uid != args.Lathe || !TryComp<TechnologyDatabaseComponent>(uid, out var technologyDatabase))
return;
- if (!args.getUnavailable && !HasComp<EmaggedComponent>(uid))
+ if (!args.getUnavailable && !_emag.CheckFlag(uid, EmagType.Interaction))
return;
foreach (var recipe in component.EmagDynamicRecipes)
{
public sealed class FatExtractorSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly HungerSystem _hunger = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
private void OnGotEmagged(EntityUid uid, FatExtractorComponent component, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
args.Handled = true;
- args.Repeatable = false;
}
private void OnClosed(EntityUid uid, FatExtractorComponent component, ref StorageAfterCloseEvent args)
if (_hunger.GetHunger(hunger) < component.NutritionPerSecond)
return false;
- if (hunger.CurrentThreshold < component.MinHungerThreshold && !HasComp<EmaggedComponent>(uid))
+ if (hunger.CurrentThreshold < component.MinHungerThreshold && !_emag.CheckFlag(uid, EmagType.Interaction))
return false;
return true;
{
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly FoodSystem _foodSystem = default!;
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
forced = false;
}
- if (entity.Comp.ExplodeOnUse || HasComp<EmaggedComponent>(entity.Owner))
+ if (entity.Comp.ExplodeOnUse || _emag.CheckFlag(entity, EmagType.Interaction))
{
_explosionSystem.QueueExplosion(entity.Owner, "Default", entity.Comp.ExplosionIntensity, 0.5f, 3, canCreateVacuum: false);
EntityManager.DeleteEntity(entity);
args.Args.Target.Value);
}
}
+
private void OnEmagged(Entity<VapeComponent> entity, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(entity, EmagType.Interaction))
+ return;
+
args.Handled = true;
}
}
using Content.Server.Power.Pow3r;
using Content.Shared.Access.Systems;
using Content.Shared.APC;
-using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.Popups;
using Content.Shared.Rounding;
{
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
private void OnEmagged(EntityUid uid, ApcComponent comp, ref GotEmaggedEvent args)
{
- // no fancy conditions
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
args.Handled = true;
}
private ApcChargeState CalcChargeState(EntityUid uid, PowerState.Battery battery)
{
- if (HasComp<EmaggedComponent>(uid))
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
return ApcChargeState.Emag;
if (battery.CurrentStorage / battery.Capacity > ApcComponent.HighPowerThreshold)
using Content.Shared.UserInterface;
using Content.Shared.Access.Components;
using Content.Shared.Emag.Components;
+using Content.Shared.Emag.Systems;
using Content.Shared.IdentityManagement;
using Content.Shared.Research.Components;
using Content.Shared.Research.Prototypes;
public sealed partial class ResearchSystem
{
+ [Dependency] private readonly EmagSystem _emag = default!;
+
private void InitializeConsole()
{
SubscribeLocalEvent<ResearchConsoleComponent, ConsoleUnlockTechnologyMessage>(OnConsoleUnlock);
SubscribeLocalEvent<ResearchConsoleComponent, ResearchServerPointsChangedEvent>(OnPointsChanged);
SubscribeLocalEvent<ResearchConsoleComponent, ResearchRegistrationChangedEvent>(OnConsoleRegistrationChanged);
SubscribeLocalEvent<ResearchConsoleComponent, TechnologyDatabaseModifiedEvent>(OnConsoleDatabaseModified);
+ SubscribeLocalEvent<ResearchConsoleComponent, GotEmaggedEvent>(OnEmagged);
}
private void OnConsoleUnlock(EntityUid uid, ResearchConsoleComponent component, ConsoleUnlockTechnologyMessage args)
if (!UnlockTechnology(uid, args.Id, act))
return;
- if (!HasComp<EmaggedComponent>(uid))
+ if (!_emag.CheckFlag(uid, EmagType.Interaction))
{
var getIdentityEvent = new TryGetIdentityShortInfoEvent(uid, act);
RaiseLocalEvent(getIdentityEvent);
);
_radio.SendRadioMessage(uid, message, component.AnnouncementChannel, uid, escapeMarkup: false);
}
-
+
SyncClientWithServer(uid);
UpdateConsoleInterface(uid, component);
}
UpdateConsoleInterface(uid, component);
}
+ private void OnEmagged(Entity<ResearchConsoleComponent> ent, ref GotEmaggedEvent args)
+ {
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(ent, EmagType.Interaction))
+ return;
+
+ args.Handled = true;
+ }
+
}
{
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly EntityStorageSystem _entityStorage = default!;
- [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!;
[Dependency] private readonly GhostSystem _ghost = default!;
_whitelistSystem.IsBlacklistPass(component.MalfunctionBlacklist, ent))
continue;
- _emag.DoEmagEffect(uid, ent); //it does not emag itself. adorable.
+ var ev = new GotEmaggedEvent(uid, EmagType.Interaction | EmagType.Access);
+ RaiseLocalEvent(ent, ref ev);
}
}
}
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Explosion.Components;
+using Content.Shared.Emag.Systems;
using Robust.Shared.Utility;
namespace Content.Server.Silicons.Borgs;
/// <inheritdoc/>
public sealed partial class BorgSystem
{
+ [Dependency] private readonly EmagSystem _emag = default!;
+
private void InitializeTransponder()
{
SubscribeLocalEvent<BorgTransponderComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
private bool CheckEmagged(EntityUid uid, string name)
{
- if (HasComp<EmaggedComponent>(uid))
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
{
Popup.PopupEntity(Loc.GetString($"borg-transponder-emagged-{name}-popup"), uid, uid, PopupType.LargeCaution);
return true;
using Content.Server.Station.Systems;
using Content.Shared.Administration;
using Content.Shared.Chat;
-using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.GameTicking;
using Content.Shared.Mind;
using Content.Shared.Roles;
using Content.Shared.Silicons.Laws;
using Content.Shared.Silicons.Laws.Components;
-using Content.Shared.Stunnable;
using Content.Shared.Wires;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Toolshed;
-using Robust.Shared.Audio;
namespace Content.Server.Silicons.Laws;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly SharedRoleSystem _roles = default!;
[Dependency] private readonly StationSystem _station = default!;
- [Dependency] private readonly SharedStunSystem _stunSystem = default!;
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
/// <inheritdoc/>
public override void Initialize()
SubscribeLocalEvent<SiliconLawProviderComponent, IonStormLawsEvent>(OnIonStormLaws);
SubscribeLocalEvent<SiliconLawProviderComponent, MindAddedMessage>(OnLawProviderMindAdded);
SubscribeLocalEvent<SiliconLawProviderComponent, MindRemovedMessage>(OnLawProviderMindRemoved);
- SubscribeLocalEvent<SiliconLawProviderComponent, GotEmaggedEvent>(OnEmagLawsAdded);
+ SubscribeLocalEvent<SiliconLawProviderComponent, SiliconEmaggedEvent>(OnEmagLawsAdded);
}
private void OnMapInit(EntityUid uid, SiliconLawBoundComponent component, MapInitEvent args)
private void OnIonStormLaws(EntityUid uid, SiliconLawProviderComponent component, ref IonStormLawsEvent args)
{
// Emagged borgs are immune to ion storm
- if (!HasComp<EmaggedComponent>(uid))
+ if (!_emag.CheckFlag(uid, EmagType.Interaction))
{
component.Lawset = args.Lawset;
}
}
- private void OnEmagLawsAdded(EntityUid uid, SiliconLawProviderComponent component, ref GotEmaggedEvent args)
+ private void OnEmagLawsAdded(EntityUid uid, SiliconLawProviderComponent component, ref SiliconEmaggedEvent args)
{
-
if (component.Lawset == null)
component.Lawset = GetLawset(component.Laws);
// Add the first emag law before the others
component.Lawset?.Laws.Insert(0, new SiliconLaw
{
- LawString = Loc.GetString("law-emag-custom", ("name", Name(args.UserUid)), ("title", Loc.GetString(component.Lawset.ObeysTo))),
+ LawString = Loc.GetString("law-emag-custom", ("name", Name(args.user)), ("title", Loc.GetString(component.Lawset.ObeysTo))),
Order = 0
});
});
}
- protected override void OnGotEmagged(EntityUid uid, EmagSiliconLawComponent component, ref GotEmaggedEvent args)
- {
- if (component.RequireOpenPanel && TryComp<WiresPanelComponent>(uid, out var panel) && !panel.Open)
- return;
-
- base.OnGotEmagged(uid, component, ref args);
- NotifyLawsChanged(uid, component.EmaggedSound);
- if(_mind.TryGetMind(uid, out var mindId, out _))
- EnsureSubvertedSiliconRole(mindId);
-
- _stunSystem.TryParalyze(uid, component.StunTime, true);
-
- }
-
private void EnsureSubvertedSiliconRole(EntityUid mindId)
{
if (!_roles.MindHasRole<SubvertedSiliconRoleComponent>(mindId))
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SpeakOnUIClosedSystem _speakOnUIClosed = default!;
[Dependency] private readonly SharedPointLightSystem _light = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
private const float WallVendEjectDistanceFromWall = 1f;
SubscribeLocalEvent<VendingMachineComponent, PowerChangedEvent>(OnPowerChanged);
SubscribeLocalEvent<VendingMachineComponent, BreakageEventArgs>(OnBreak);
- SubscribeLocalEvent<VendingMachineComponent, GotEmaggedEvent>(OnEmagged);
SubscribeLocalEvent<VendingMachineComponent, DamageChangedEvent>(OnDamageChanged);
SubscribeLocalEvent<VendingMachineComponent, PriceCalculationEvent>(OnVendingPrice);
SubscribeLocalEvent<VendingMachineComponent, EmpPulseEvent>(OnEmpPulse);
TryUpdateVisualState(uid, vendComponent);
}
- private void OnEmagged(EntityUid uid, VendingMachineComponent component, ref GotEmaggedEvent args)
- {
- // only emag if there are emag-only items
- args.Handled = component.EmaggedInventory.Count > 0;
- }
-
private void OnDamageChanged(EntityUid uid, VendingMachineComponent component, DamageChangedEvent args)
{
if (!args.DamageIncreased && component.Broken)
if (!TryComp<AccessReaderComponent>(uid, out var accessReader))
return true;
- if (_accessReader.IsAllowed(sender, uid, accessReader) || HasComp<EmaggedComponent>(uid))
+ if (_accessReader.IsAllowed(sender, uid, accessReader))
return true;
Popup.PopupEntity(Loc.GetString("vending-machine-component-try-eject-access-denied"), uid);
if (!Resolve(uid, ref component))
return null;
- if (type == InventoryType.Emagged && HasComp<EmaggedComponent>(uid))
+ if (type == InventoryType.Emagged && _emag.CheckFlag(uid, EmagType.Interaction))
return component.EmaggedInventory.GetValueOrDefault(entryId);
if (type == InventoryType.Contraband && component.Contraband)
/// Whether or not emag interactions have an effect on this.
/// </summary>
[DataField]
- public bool BreakOnEmag = true;
+ public bool BreakOnAccessBreaker = true;
}
[DataDefinition, Serializable, NetSerializable]
using System.Linq;
using Content.Shared.Access.Components;
using Content.Shared.DeviceLinking.Events;
-using Content.Shared.Emag.Components;
using Content.Shared.Emag.Systems;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Inventory;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly SharedGameTicker _gameTicker = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
{
if (args.User == null) // AutoLink (and presumably future external linkers) have no user.
return;
- if (!HasComp<EmaggedComponent>(uid) && !IsAllowed(args.User.Value, uid, component))
+ if (!IsAllowed(args.User.Value, uid, component))
args.Cancel();
}
private void OnEmagged(EntityUid uid, AccessReaderComponent reader, ref GotEmaggedEvent args)
{
- if (!reader.BreakOnEmag)
+ if (!_emag.CompareFlag(args.Type, EmagType.Access))
return;
+
+ if (!reader.BreakOnAccessBreaker)
+ return;
+
+ if (!GetMainAccessReader(uid, out var accessReader))
+ return;
+
+ if (accessReader.Value.Comp.AccessLists.Count < 1)
+ return;
+
+ args.Repeatable = true;
args.Handled = true;
- reader.Enabled = false;
- reader.AccessLog.Clear();
+ accessReader.Value.Comp.AccessLists.Clear();
+ accessReader.Value.Comp.AccessLog.Clear();
Dirty(uid, reader);
}
return true;
}
}
+
return true;
}
}
}
}
+
+[ByRefEvent]
+public record struct OnAccessOverriderAccessUpdatedEvent(EntityUid UserUid, bool Handled = false);
[DataField("mobSpawnId"), ViewVariables(VVAccess.ReadWrite)]
public EntProtoId MobSpawnId = "MobAbomination";
- /// <summary>
- /// Emag sound effects.
- /// </summary>
- [DataField("sparkSound")]
- public SoundSpecifier SparkSound = new SoundCollectionSpecifier("sparks")
- {
- Params = AudioParams.Default.WithVolume(8),
- };
-
// TODO: Remove this from here when cloning and/or zombies are refactored
[DataField("screamSound")]
public SoundSpecifier ScreamSound = new SoundCollectionSpecifier("ZombieScreams")
public abstract class SharedDisposalUnitSystem : EntitySystem
{
[Dependency] protected readonly IGameTiming GameTiming = default!;
+ [Dependency] protected readonly EmagSystem _emag = default!;
[Dependency] protected readonly MetaDataSystem Metadata = default!;
[Dependency] protected readonly SharedJointSystem Joints = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
protected void OnEmagged(EntityUid uid, SharedDisposalUnitComponent component, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (component.DisablePressure == true)
+ return;
+
component.DisablePressure = true;
args.Handled = true;
}
[Dependency] private readonly INetManager _net = default!;
[Dependency] protected readonly SharedPhysicsSystem PhysicsSystem = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
[Dependency] protected readonly TagSystem Tags = default!;
[Dependency] protected readonly SharedAudioSystem Audio = default!;
SubscribeLocalEvent<DoorComponent, WeldableAttemptEvent>(OnWeldAttempt);
SubscribeLocalEvent<DoorComponent, WeldableChangedEvent>(OnWeldChanged);
SubscribeLocalEvent<DoorComponent, GetPryTimeModifierEvent>(OnPryTimeModifier);
-
- SubscribeLocalEvent<DoorComponent, OnAttemptEmagEvent>(OnAttemptEmag);
SubscribeLocalEvent<DoorComponent, GotEmaggedEvent>(OnEmagged);
}
_activeDoors.Remove(door);
}
- private void OnAttemptEmag(EntityUid uid, DoorComponent door, ref OnAttemptEmagEvent args)
+ private void OnEmagged(EntityUid uid, DoorComponent door, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Access))
+ return;
+
if (!TryComp<AirlockComponent>(uid, out var airlock))
- {
- args.Handled = true;
return;
- }
if (IsBolted(uid) || !airlock.Powered)
- {
- args.Handled = true;
return;
- }
if (door.State != DoorState.Closed)
- {
- args.Handled = true;
- }
- }
+ return;
- private void OnEmagged(EntityUid uid, DoorComponent door, ref GotEmaggedEvent args)
- {
if (!SetState(uid, DoorState.Emagging, door))
return;
- Audio.PlayPredicted(door.SparkSound, uid, args.UserUid, AudioParams.Default.WithVolume(8));
+
+ args.Repeatable = true;
args.Handled = true;
}
using Content.Shared.Emag.Systems;
using Content.Shared.Tag;
+using Robust.Shared.Audio;
using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization;
/// <summary>
/// The tag that marks an entity as immune to emags
/// </summary>
- [DataField("emagImmuneTag", customTypeSerializer: typeof(PrototypeIdSerializer<TagPrototype>)), ViewVariables(VVAccess.ReadWrite)]
+ [DataField]
[AutoNetworkedField]
- public string EmagImmuneTag = "EmagImmune";
+ public ProtoId<TagPrototype> EmagImmuneTag = "EmagImmune";
+
+ /// <summary>
+ /// What type of emag effect this device will do
+ /// </summary>
+ [DataField]
+ [AutoNetworkedField]
+ public EmagType EmagType = EmagType.Interaction;
+
+ /// <summary>
+ /// What sound should the emag play when used
+ /// </summary>
+ [DataField]
+ [AutoNetworkedField]
+ public SoundSpecifier EmagSound = new SoundCollectionSpecifier("sparks");
}
+using Content.Shared.Emag.Systems;
using Robust.Shared.GameStates;
namespace Content.Shared.Emag.Components;
/// <summary>
/// Marker component for emagged entities
/// </summary>
-[RegisterComponent, NetworkedComponent]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class EmaggedComponent : Component
{
+ /// <summary>
+ /// The EmagType flags that were used to emag this device
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public EmagType EmagType = EmagType.None;
}
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Popups;
-using Content.Shared.Silicons.Laws.Components;
using Content.Shared.Tag;
+using Robust.Shared.Audio.Systems;
namespace Content.Shared.Emag.Systems;
[Dependency] private readonly SharedChargesSystem _charges = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly TagSystem _tag = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<EmagComponent, AfterInteractEvent>(OnAfterInteract);
+ SubscribeLocalEvent<EmaggedComponent, OnAccessOverriderAccessUpdatedEvent>(OnAccessOverriderAccessUpdated);
}
+ private void OnAccessOverriderAccessUpdated(Entity<EmaggedComponent> entity, ref OnAccessOverriderAccessUpdatedEvent args)
+ {
+ if (!CompareFlag(entity.Comp.EmagType, EmagType.Access))
+ return;
+
+ entity.Comp.EmagType &= ~EmagType.Access;
+ Dirty(entity);
+ }
private void OnAfterInteract(EntityUid uid, EmagComponent comp, AfterInteractEvent args)
{
if (!args.CanReach || args.Target is not { } target)
return;
- args.Handled = TryUseEmag(uid, args.User, target, comp);
+ args.Handled = TryEmagEffect((uid, comp), args.User, target);
}
/// <summary>
- /// Tries to use the emag on a target entity
+ /// Does the emag effect on a specified entity
/// </summary>
- public bool TryUseEmag(EntityUid uid, EntityUid user, EntityUid target, EmagComponent? comp = null)
+ public bool TryEmagEffect(Entity<EmagComponent?> ent, EntityUid user, EntityUid target)
{
- if (!Resolve(uid, ref comp, false))
+ if (!Resolve(ent, ref ent.Comp, false))
return false;
- if (_tag.HasTag(target, comp.EmagImmuneTag))
+ if (_tag.HasTag(target, ent.Comp.EmagImmuneTag))
return false;
- TryComp<LimitedChargesComponent>(uid, out var charges);
- if (_charges.IsEmpty(uid, charges))
+ TryComp<LimitedChargesComponent>(ent, out var charges);
+ if (_charges.IsEmpty(ent, charges))
{
_popup.PopupClient(Loc.GetString("emag-no-charges"), user, user);
return false;
}
- var handled = DoEmagEffect(user, target);
- if (!handled)
+ var emaggedEvent = new GotEmaggedEvent(user, ent.Comp.EmagType);
+ RaiseLocalEvent(target, ref emaggedEvent);
+
+ if (!emaggedEvent.Handled)
return false;
- _popup.PopupClient(Loc.GetString("emag-success", ("target", Identity.Entity(target, EntityManager))), user,
- user, PopupType.Medium);
+ _popup.PopupPredicted(Loc.GetString("emag-success", ("target", Identity.Entity(target, EntityManager))), user, user, PopupType.Medium);
- _adminLogger.Add(LogType.Emag, LogImpact.High, $"{ToPrettyString(user):player} emagged {ToPrettyString(target):target}");
+ _audio.PlayPredicted(ent.Comp.EmagSound, ent, ent);
- if (charges != null)
- _charges.UseCharge(uid, charges);
- return true;
+ _adminLogger.Add(LogType.Emag, LogImpact.High, $"{ToPrettyString(user):player} emagged {ToPrettyString(target):target} with flag(s): {ent.Comp.EmagType}");
+
+ if (charges != null && emaggedEvent.Handled)
+ _charges.UseCharge(ent, charges);
+
+ if (!emaggedEvent.Repeatable)
+ {
+ EnsureComp<EmaggedComponent>(target, out var emaggedComp);
+
+ emaggedComp.EmagType |= ent.Comp.EmagType;
+ Dirty(target, emaggedComp);
+ }
+
+ return emaggedEvent.Handled;
}
/// <summary>
- /// Does the emag effect on a specified entity
+ /// Checks whether an entity has the EmaggedComponent with a set flag.
/// </summary>
- public bool DoEmagEffect(EntityUid user, EntityUid target)
+ /// <param name="target">The target entity to check for the flag.</param>
+ /// <param name="flag">The EmagType flag to check for.</param>
+ /// <returns>True if entity has EmaggedComponent and the provided flag. False if the entity lacks EmaggedComponent or provided flag.</returns>
+ public bool CheckFlag(EntityUid target, EmagType flag)
{
- // prevent emagging twice
- if (HasComp<EmaggedComponent>(target))
+ if (!TryComp<EmaggedComponent>(target, out var comp))
return false;
- var onAttemptEmagEvent = new OnAttemptEmagEvent(user);
- RaiseLocalEvent(target, ref onAttemptEmagEvent);
+ if ((comp.EmagType & flag) == flag)
+ return true;
- // prevent emagging if attempt fails
- if (onAttemptEmagEvent.Handled)
- return false;
+ return false;
+ }
- var emaggedEvent = new GotEmaggedEvent(user);
- RaiseLocalEvent(target, ref emaggedEvent);
+ /// <summary>
+ /// Compares a flag to the target.
+ /// </summary>
+ /// <param name="target">The target flag to check.</param>
+ /// <param name="flag">The flag to check for within the target.</param>
+ /// <returns>True if target contains flag. Otherwise false.</returns>
+ public bool CompareFlag(EmagType target, EmagType flag)
+ {
+ if ((target & flag) == flag)
+ return true;
- if (emaggedEvent.Handled && !emaggedEvent.Repeatable)
- EnsureComp<EmaggedComponent>(target);
- return emaggedEvent.Handled;
+ return false;
}
}
+
+[Flags]
+public enum EmagType : byte
+{
+ None = 0,
+ Interaction = 1 << 1,
+ Access = 1 << 2
+}
/// <summary>
/// Shows a popup to emag user (client side only!) and adds <see cref="EmaggedComponent"/> to the entity when handled
/// </summary>
/// <param name="UserUid">Emag user</param>
+/// <param name="Type">The emag type to use</param>
/// <param name="Handled">Did the emagging succeed? Causes a user-only popup to show on client side</param>
/// <param name="Repeatable">Can the entity be emagged more than once? Prevents adding of <see cref="EmaggedComponent"/></param>
/// <remarks>Needs to be handled in shared/client, not just the server, to actually show the emagging popup</remarks>
[ByRefEvent]
-public record struct GotEmaggedEvent(EntityUid UserUid, bool Handled = false, bool Repeatable = false);
-
-[ByRefEvent]
-public record struct OnAttemptEmagEvent(EntityUid UserUid, bool Handled = false);
+public record struct GotEmaggedEvent(EntityUid UserUid, EmagType Type, bool Handled = false, bool Repeatable = false);
[DataField]
public bool ReceiveNukeCodes { get; set; } = false;
- /// <summary>
- /// Sound to play when fax has been emagged
- /// </summary>
- [DataField]
- public SoundSpecifier EmagSound = new SoundCollectionSpecifier("sparks");
-
/// <summary>
/// Sound to play when fax printing new message
/// </summary>
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SharedMaterialStorageSystem _materialStorage = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
public readonly Dictionary<string, List<LatheRecipePrototype>> InverseRecipes = new();
private void OnEmagged(EntityUid uid, EmagLatheRecipesComponent component, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
args.Handled = true;
}
using Content.Shared.Emag.Systems;
using Content.Shared.Light.Components;
using Content.Shared.Mind.Components;
+using Content.Shared.Storage.Components;
using Content.Shared.Toggleable;
using Content.Shared.Verbs;
using Robust.Shared.Audio.Systems;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
[Dependency] private readonly SharedPointLightSystem _light = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
public override void Initialize()
{
private void OnGotEmagged(EntityUid uid, UnpoweredFlashlightComponent component, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
if (!_light.TryGetLight(uid, out var light))
return;
/// <summary>
/// Whether or not an emag disables it.
/// </summary>
- [DataField("breakOnEmag")]
+ [DataField]
[AutoNetworkedField]
- public bool BreakOnEmag = true;
+ public bool BreakOnAccessBreaker = true;
/// <summary>
/// Amount of do-after time needed to lock the entity.
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly ActivatableUISystem _activatableUI = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPopupSystem _sharedPopupSystem = default!;
private void OnEmagged(EntityUid uid, LockComponent component, ref GotEmaggedEvent args)
{
- if (!component.Locked || !component.BreakOnEmag)
+ if (!_emag.CompareFlag(args.Type, EmagType.Access))
+ return;
+
+ if (!component.Locked || !component.BreakOnAccessBreaker)
return;
_audio.PlayPredicted(component.UnlockSound, uid, args.UserUid);
var ev = new LockToggledEvent(false);
RaiseLocalEvent(uid, ref ev, true);
- RemComp<LockComponent>(uid); //Literally destroys the lock as a tell it was emagged
+ args.Repeatable = true;
args.Handled = true;
}
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] protected readonly SharedContainerSystem Container = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
public const string ActiveReclaimerContainerId = "active-material-reclaimer-container";
private void OnEmagged(EntityUid uid, MaterialReclaimerComponent component, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
args.Handled = true;
}
component.Enabled &&
!component.Broken &&
HasComp<BodyComponent>(victim) &&
- HasComp<EmaggedComponent>(uid);
+ _emag.CheckFlag(uid, EmagType.Interaction);
}
/// <summary>
{
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly StandingStateSystem _standingStateSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
protected void OnEmagged(EntityUid uid, CryoPodComponent? cryoPodComponent, ref GotEmaggedEvent args)
{
if (!Resolve(uid, ref cryoPodComponent))
- {
return;
- }
+
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (cryoPodComponent.PermaLocked && cryoPodComponent.Locked)
+ return;
cryoPodComponent.PermaLocked = true;
cryoPodComponent.Locked = true;
+using Content.Shared.Emag.Systems;
using Content.Shared.Ninja.Systems;
using Content.Shared.Tag;
using Content.Shared.Whitelist;
+using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
/// The tag that marks an entity as immune to emagging.
/// </summary>
[DataField]
- public ProtoId<TagPrototype> EmagImmuneTag = "EmagImmune";
+ public ProtoId<TagPrototype> AccessBreakerImmuneTag = "AccessBreakerImmune";
/// <summary>
/// Whitelist that entities must be on to work.
/// </summary>
[DataField]
public EntityWhitelist? Whitelist;
+
+ /// <summary>
+ /// What type of emag this will provide.
+ /// </summary>
+ [DataField]
+ public EmagType EmagType = EmagType.Access;
+
+ /// <summary>
+ /// What sound should the emag play when used
+ /// </summary>
+ [DataField]
+ public SoundSpecifier EmagSound = new SoundCollectionSpecifier("sparks");
}
using Content.Shared.Ninja.Components;
using Content.Shared.Tag;
using Content.Shared.Whitelist;
+using Robust.Shared.Audio.Systems;
namespace Content.Shared.Ninja.Systems;
/// </summary>
public sealed class EmagProviderSystem : EntitySystem
{
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
return;
// only allowed to emag non-immune entities
- if (_tag.HasTag(target, comp.EmagImmuneTag))
+ if (_tag.HasTag(target, comp.AccessBreakerImmuneTag))
return;
- var handled = _emag.DoEmagEffect(uid, target);
- if (!handled)
+ var emagEv = new GotEmaggedEvent(uid, EmagType.Access);
+ RaiseLocalEvent(args.Target, ref emagEv);
+
+ if (!emagEv.Handled)
return;
- _adminLogger.Add(LogType.Emag, LogImpact.High, $"{ToPrettyString(uid):player} emagged {ToPrettyString(target):target}");
+ _audio.PlayPredicted(comp.EmagSound, uid, uid);
+
+ _adminLogger.Add(LogType.Emag, LogImpact.High, $"{ToPrettyString(uid):player} emagged {ToPrettyString(target):target} with flag(s): {ent.Comp.EmagType}");
var ev = new EmaggedSomethingEvent(target);
RaiseLocalEvent(uid, ref ev);
args.Handled = true;
}
/// <summary>
-/// Raised on the player when emagging something.
+/// Raised on the player when access breaking something.
/// </summary>
[ByRefEvent]
public record struct EmaggedSomethingEvent(EntityUid Target);
public abstract class SharedPinpointerSystem : EntitySystem
{
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
public override void Initialize()
{
private void OnEmagged(EntityUid uid, PinpointerComponent component, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
+ if (component.CanRetarget)
+ return;
+
args.Handled = true;
component.CanRetarget = true;
}
/// </summary>
[DataField(required: true), ViewVariables(VVAccess.ReadWrite)]
public Dictionary<MobState, MedibotTreatment> Replacements = new();
-
- /// <summary>
- /// Sound to play when the bot has been emagged
- /// </summary>
- [DataField]
- public SoundSpecifier SparkSound = new SoundCollectionSpecifier("sparks")
- {
- Params = AudioParams.Default.WithVolume(8f)
- };
}
public sealed class MedibotSystem : EntitySystem
{
[Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private SharedInteractionSystem _interaction = default!;
[Dependency] private SharedSolutionContainerSystem _solutionContainer = default!;
[Dependency] private SharedPopupSystem _popup = default!;
private void OnEmagged(EntityUid uid, EmaggableMedibotComponent comp, ref GotEmaggedEvent args)
{
- if (!TryComp<MedibotComponent>(uid, out var medibot))
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
return;
- _audio.PlayPredicted(comp.SparkSound, uid, args.UserUid);
+ if (!TryComp<MedibotComponent>(uid, out var medibot))
+ return;
foreach (var (state, treatment) in comp.Replacements)
{
using Content.Shared.Emag.Systems;
+using Content.Shared.Mind;
using Content.Shared.Popups;
using Content.Shared.Silicons.Laws.Components;
+using Content.Shared.Stunnable;
using Content.Shared.Wires;
+using Robust.Shared.Audio;
namespace Content.Shared.Silicons.Laws;
public abstract partial class SharedSiliconLawSystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popup = default!;
+ [Dependency] private readonly SharedStunSystem _stunSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
+ [Dependency] private readonly SharedMindSystem _mind = default!;
/// <inheritdoc/>
public override void Initialize()
{
InitializeUpdater();
SubscribeLocalEvent<EmagSiliconLawComponent, GotEmaggedEvent>(OnGotEmagged);
- SubscribeLocalEvent<EmagSiliconLawComponent, OnAttemptEmagEvent>(OnAttemptEmag);
}
- protected virtual void OnAttemptEmag(EntityUid uid, EmagSiliconLawComponent component, ref OnAttemptEmagEvent args)
+ private void OnGotEmagged(EntityUid uid, EmagSiliconLawComponent component, ref GotEmaggedEvent args)
{
- //prevent self emagging
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
+ // prevent self-emagging
if (uid == args.UserUid)
{
_popup.PopupClient(Loc.GetString("law-emag-cannot-emag-self"), uid, args.UserUid);
- args.Handled = true;
return;
}
!panel.Open)
{
_popup.PopupClient(Loc.GetString("law-emag-require-panel"), uid, args.UserUid);
- args.Handled = true;
+ return;
}
- }
+ var ev = new SiliconEmaggedEvent(args.UserUid);
+ RaiseLocalEvent(uid, ref ev);
- protected virtual void OnGotEmagged(EntityUid uid, EmagSiliconLawComponent component, ref GotEmaggedEvent args)
- {
component.OwnerName = Name(args.UserUid);
+
+ NotifyLawsChanged(uid, component.EmaggedSound);
+ if(_mind.TryGetMind(uid, out var mindId, out _))
+ EnsureSubvertedSiliconRole(mindId);
+
+ _stunSystem.TryParalyze(uid, component.StunTime, true);
+
args.Handled = true;
}
+
+ protected virtual void NotifyLawsChanged(EntityUid uid, SoundSpecifier? cue = null)
+ {
+
+ }
+
+ protected virtual void EnsureSubvertedSiliconRole(EntityUid mindId)
+ {
+
+ }
}
+
+[ByRefEvent]
+public record struct SiliconEmaggedEvent(EntityUid user);
{
#region Dependencies
[Dependency] protected readonly SharedPopupSystem PopupSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
#endregion Dependencies
public override void Initialize()
private void OnEmagged(EntityUid uid, SingularityGeneratorComponent component, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
+ if (component.FailsafeDisabled)
+ return;
+
component.FailsafeDisabled = true;
args.Handled = true;
}
-}
\ No newline at end of file
+}
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Shared.DoAfter;
+using Content.Shared.Emag.Systems;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Robust.Shared.Audio;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] protected readonly SharedPopupSystem Popup = default!;
[Dependency] protected readonly IRobustRandom Randomizer = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<VendingMachineComponent, MapInitEvent>(OnMapInit);
+ SubscribeLocalEvent<VendingMachineComponent, GotEmaggedEvent>(OnEmagged);
+
SubscribeLocalEvent<VendingMachineRestockComponent, AfterInteractEvent>(OnAfterInteract);
}
Dirty(uid, component);
}
+ private void OnEmagged(EntityUid uid, VendingMachineComponent component, ref GotEmaggedEvent args)
+ {
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
+ return;
+
+ // only emag if there are emag-only items
+ args.Handled = component.EmaggedInventory.Count > 0;
+ }
+
/// <summary>
/// Returns all of the vending machine's inventory. Only includes emagged and contraband inventories if
- /// <see cref="EmaggedComponent"/> exists and <see cref="VendingMachineComponent.Contraband"/> is true
+ /// <see cref="EmaggedComponent"/> with the EmagType.Interaction flag 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 (HasComp<EmaggedComponent>(uid))
+ if (_emag.CheckFlag(uid, EmagType.Interaction))
inventory.AddRange(component.EmaggedInventory.Values);
if (component.Contraband)
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
[Dependency] protected readonly SharedAudioSystem AudioSystem = default!;
[Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
+ [Dependency] private readonly EmagSystem _emag = default!;
/// <inheritdoc/>
public override void Initialize()
private void OnEmagged(Entity<ArtifactCrusherComponent> ent, ref GotEmaggedEvent args)
{
+ if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
+ return;
+
+ if (_emag.CheckFlag(ent, EmagType.Interaction))
+ return;
+
+ if (ent.Comp.AutoLock)
+ return;
+
ent.Comp.AutoLock = true;
args.Handled = true;
}
-emag-success = The card zaps something in {THE($target)}.
+emag-success = The device zaps something in {THE($target)}.
emag-no-charges = No charges left!
uplink-chest-rig-desc = Explosion-resistant tactical webbing used for holding traitor goods.
uplink-emag-name = Emag
-uplink-emag-desc = The business card of the syndicate, this sequencer is able to break open airlocks and tamper with a variety of station devices. Recharges automatically.
+uplink-emag-desc = The business card of the syndicate, this sequencer is able to tamper with a variety of station devices. Recharges automatically.
+
+uplink-access-breaker-name = Access Breaker
+uplink-access-breaker-desc = A hacked access configurator and a good friend of the emag. This device is able to force airlocks open as well as erase access requirements from station equipment. Recharges automatically.
uplink-agent-id-card-name = Agent ID Card
uplink-agent-id-card-desc = A modified ID card that can copy accesses from other cards and change its name and job title at-will.
thief-backpack-category-syndie-description =
Trinkets from a disavowed past, or stolen from a careless agent?
You've made some connections. Whiskey, echo...
- Includes: An Emag, Interdyne cigs, a Syndicate codeword,
+ Includes: An Emag, Access Breaker, Interdyne cigs, a Syndicate codeword,
a Radio Jammer, a lighter and some strange red crystals.
thief-backpack-category-sleeper-name = sleeper kit
- RadioJammer
- TraitorCodePaper
- Emag
+ - AccessBreaker
- Lighter
- CigPackSyndicate
- Telecrystal10 #The thief cannot use them, but it may induce communication with traitors
# Disruption
+- type: listing
+ id: UplinkAccessBreaker
+ name: uplink-access-breaker-name
+ description: uplink-access-breaker-desc
+ productEntity: AccessBreaker
+ discountCategory: veryRareDiscounts
+ discountDownTo:
+ Telecrystal: 3
+ cost:
+ Telecrystal: 5
+ categories:
+ - UplinkDisruption
+
- type: listing
id: UplinkEmag
name: uplink-emag-name
description: uplink-emag-desc
productEntity: Emag
- discountCategory: veryRareDiscounts
+ discountCategory: rareDiscounts
discountDownTo:
- Telecrystal: 5
+ Telecrystal: 2
cost:
- Telecrystal: 8
+ Telecrystal: 4
categories:
- UplinkDisruption
- cell_slot
- type: Lock
locked: true
- breakOnEmag: false
unlockOnClick: false
- type: ActivatableUIRequiresLock
- type: LockedWiresPanel
- type: Appearance
- type: AccessReader
access: [ [ "CentralCommand" ] ]
- breakOnEmag: false
+ breakOnAccessBreaker: false
- type: Lock
lockOnClick: false
- breakOnEmag: false
+ breakOnAccessBreaker: false
- type: EntityStorage
capacity: 1 # Its smol.
itemCanStoreMobs: false # just leaving this here explicitly since I know at some point someone will want to use this to hold a mob. This also prevents it from becoming His Grace.
id: BorgModuleOperative
parent: [ BaseBorgModuleSyndicate, BaseProviderBorgModule, BaseSyndicateContraband ]
name: operative cyborg module
- description: A module that comes with a crowbar, an Emag and a syndicate pinpointer.
+ description: A module that comes with a crowbar, an Emag, an Access Breaker and a syndicate pinpointer.
components:
- type: Sprite
layers:
items:
- Crowbar
- Emag
+ - AccessBreaker
- PinpointerSyndicateNuclear
- type: BorgModuleIcon
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-operative-module }
--- /dev/null
+- type: entity
+ parent: [BaseItem, BaseSyndicateContraband]
+ id: AccessBreakerUnlimited
+ suffix: Unlimited
+ name: authentication disruptor
+ description: A hacked access configurator, specialized to unlock and erase access from digital locks.
+ components:
+ - type: Emag
+ emagType: Access
+ - type: Sprite
+ sprite: Objects/Tools/access_breaker.rsi
+ state: icon
+ - type: Item
+ sprite: Objects/Tools/access_breaker.rsi
+
+- type: entity
+ parent: AccessBreakerUnlimited
+ id: AccessBreaker
+ suffix: Limited
+ components:
+ - type: LimitedCharges
+ - type: AutoRecharge
stateLocked: cursed_door
stateUnlocked: decursed_door
- type: Lock
- breakOnEmag: false
+ breakOnAccessBreaker: false
- type: AccessReader
access: [["Wizard"]]
- breakOnEmag: false
+ breakOnAccessBreaker: false
- type: Projectile
deleteOnCollide: false
onlyCollideWhenShot: true
color: "#3c5eb5"
- type: Tag
tags:
- - EmagImmune
+ - AccessBreakerImmune
- type: ItemSlots
- type: ContainerContainer
containers:
visible: false
map: ["enum.FatExtractorVisualLayers.Smoke"]
- type: Lock
- breakOnEmag: false
+ breakOnAccessBreaker: false
- type: GenericVisualizer
visuals:
enum.StorageVisuals.Open:
responsePings: false
notifyAdmins: true
- type: Emagged
+ emagType: Interaction
- type: entity
parent: FaxMachineBase
- type: ActivatableUI
key: enum.CryostorageUIKey.Key
- type: AccessReader
- breakOnEmag: false
+ breakOnAccessBreaker: false
access: [["Cryogenics"]]
- type: InteractionOutline
- type: Cryostorage
# PUT YOUR TAGS IN ALPHABETICAL ORDER
+- type: Tag
+ id: AccessBreakerImmune
+
- type: Tag
id: AirAlarm
--- /dev/null
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Made by 20kdc (GitHub), edited by DieselMohawk (GitHub)",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "icon",
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "equipped-BELT"
+ }
+ ]
+}