Seperate EMAG into EMAG and Authentication Disruptor (#34337)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
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;
|
||||
@@ -31,11 +30,9 @@ public sealed partial class AccessWireAction : ComponentWireAction<AccessReaderC
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -58,7 +55,7 @@ public sealed partial class AccessWireAction : ComponentWireAction<AccessReaderC
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -245,6 +245,10 @@ public sealed class AccessOverriderSystem : SharedAccessOverriderSystem
|
||||
$"{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);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,8 +116,11 @@ public sealed class TechAnomalySystem : EntitySystem
|
||||
|
||||
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);
|
||||
|
||||
@@ -21,6 +21,7 @@ public sealed class FireAlarmSystem : EntitySystem
|
||||
{
|
||||
[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!;
|
||||
@@ -77,11 +78,18 @@ public sealed class FireAlarmSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Content.Server.Bed
|
||||
{
|
||||
[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!;
|
||||
@@ -114,7 +115,12 @@ namespace Content.Server.Bed
|
||||
|
||||
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;
|
||||
|
||||
@@ -8,7 +8,7 @@ using Content.Shared.Cargo.Components;
|
||||
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;
|
||||
@@ -21,6 +21,7 @@ namespace Content.Server.Cargo.Systems
|
||||
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.
|
||||
@@ -41,6 +42,7 @@ namespace Content.Server.Cargo.Systems
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, BankBalanceUpdatedEvent>(OnOrderBalanceUpdated);
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, GotEmaggedEvent>(OnEmagged);
|
||||
Reset();
|
||||
}
|
||||
|
||||
@@ -75,6 +77,17 @@ namespace Content.Server.Cargo.Systems
|
||||
_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;
|
||||
@@ -192,7 +205,7 @@ namespace Content.Server.Cargo.Systems
|
||||
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);
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace Content.Server.Cloning
|
||||
[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;
|
||||
@@ -276,10 +277,15 @@ namespace Content.Server.Cloning
|
||||
/// </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;
|
||||
}
|
||||
@@ -309,7 +315,7 @@ namespace Content.Server.Cloning
|
||||
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);
|
||||
@@ -327,7 +333,7 @@ namespace Content.Server.Cloning
|
||||
}
|
||||
_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);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ using Content.Shared.Chat;
|
||||
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;
|
||||
@@ -177,7 +176,7 @@ namespace Content.Server.Communications
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ public sealed class FaxSystem : EntitySystem
|
||||
[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";
|
||||
|
||||
@@ -227,7 +228,7 @@ public sealed class FaxSystem : EntitySystem
|
||||
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;
|
||||
@@ -246,7 +247,12 @@ public sealed class FaxSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -260,7 +266,7 @@ public sealed class FaxSystem : EntitySystem
|
||||
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;
|
||||
@@ -405,7 +411,7 @@ public sealed class FaxSystem : EntitySystem
|
||||
{ DeviceNetworkConstants.Command, FaxConstants.FaxPingCommand }
|
||||
};
|
||||
|
||||
if (HasComp<EmaggedComponent>(uid))
|
||||
if (_emag.CheckFlag(uid, EmagType.Interaction))
|
||||
payload.Add(FaxConstants.FaxSyndicateData, true);
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(uid, null, payload);
|
||||
|
||||
@@ -16,6 +16,7 @@ using Content.Shared.Chemistry.Reagent;
|
||||
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;
|
||||
@@ -42,6 +43,7 @@ namespace Content.Server.Lathe
|
||||
[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!;
|
||||
@@ -292,7 +294,7 @@ namespace Content.Server.Lathe
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Content.Server.Nutrition.EntitySystems;
|
||||
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!;
|
||||
@@ -36,8 +37,13 @@ public sealed class FatExtractorSystem : EntitySystem
|
||||
|
||||
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)
|
||||
@@ -103,7 +109,7 @@ public sealed class FatExtractorSystem : EntitySystem
|
||||
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;
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
{
|
||||
[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!;
|
||||
@@ -63,7 +64,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
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);
|
||||
@@ -161,8 +162,15 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ using Content.Server.Power.Components;
|
||||
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;
|
||||
@@ -19,6 +18,7 @@ public sealed class ApcSystem : EntitySystem
|
||||
{
|
||||
[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!;
|
||||
@@ -111,7 +111,12 @@ public sealed class ApcSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -170,7 +175,7 @@ public sealed class ApcSystem : EntitySystem
|
||||
|
||||
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)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Research.Components;
|
||||
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;
|
||||
@@ -11,6 +12,8 @@ namespace Content.Server.Research.Systems;
|
||||
|
||||
public sealed partial class ResearchSystem
|
||||
{
|
||||
[Dependency] private readonly EmagSystem _emag = default!;
|
||||
|
||||
private void InitializeConsole()
|
||||
{
|
||||
SubscribeLocalEvent<ResearchConsoleComponent, ConsoleUnlockTechnologyMessage>(OnConsoleUnlock);
|
||||
@@ -18,6 +21,7 @@ public sealed partial class ResearchSystem
|
||||
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)
|
||||
@@ -39,7 +43,7 @@ public sealed partial class ResearchSystem
|
||||
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);
|
||||
@@ -52,7 +56,7 @@ public sealed partial class ResearchSystem
|
||||
);
|
||||
_radio.SendRadioMessage(uid, message, component.AnnouncementChannel, uid, escapeMarkup: false);
|
||||
}
|
||||
|
||||
|
||||
SyncClientWithServer(uid);
|
||||
UpdateConsoleInterface(uid, component);
|
||||
}
|
||||
@@ -100,4 +104,15 @@ public sealed partial class ResearchSystem
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ public sealed partial class RevenantSystem
|
||||
{
|
||||
[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!;
|
||||
@@ -343,7 +342,8 @@ public sealed partial class RevenantSystem
|
||||
_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Content.Server.DeviceNetwork;
|
||||
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;
|
||||
@@ -15,6 +16,8 @@ namespace Content.Server.Silicons.Borgs;
|
||||
/// <inheritdoc/>
|
||||
public sealed partial class BorgSystem
|
||||
{
|
||||
[Dependency] private readonly EmagSystem _emag = default!;
|
||||
|
||||
private void InitializeTransponder()
|
||||
{
|
||||
SubscribeLocalEvent<BorgTransponderComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
|
||||
@@ -127,7 +130,7 @@ public sealed partial class BorgSystem
|
||||
|
||||
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;
|
||||
|
||||
@@ -6,7 +6,6 @@ using Content.Server.Roles;
|
||||
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;
|
||||
@@ -14,7 +13,6 @@ using Content.Shared.Mind.Components;
|
||||
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;
|
||||
@@ -22,7 +20,6 @@ using Robust.Shared.Containers;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.Silicons.Laws;
|
||||
|
||||
@@ -34,8 +31,8 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||
[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()
|
||||
@@ -52,7 +49,7 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||
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)
|
||||
@@ -135,7 +132,7 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||
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;
|
||||
|
||||
@@ -152,9 +149,8 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -164,7 +160,7 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||
// 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
|
||||
});
|
||||
|
||||
@@ -176,20 +172,6 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||
});
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Content.Server.VendingMachines
|
||||
[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;
|
||||
|
||||
@@ -48,7 +49,6 @@ namespace Content.Server.VendingMachines
|
||||
|
||||
SubscribeLocalEvent<VendingMachineComponent, PowerChangedEvent>(OnPowerChanged);
|
||||
SubscribeLocalEvent<VendingMachineComponent, BreakageEventArgs>(OnBreak);
|
||||
SubscribeLocalEvent<VendingMachineComponent, GotEmaggedEvent>(OnEmagged);
|
||||
SubscribeLocalEvent<VendingMachineComponent, DamageChangedEvent>(OnDamageChanged);
|
||||
SubscribeLocalEvent<VendingMachineComponent, PriceCalculationEvent>(OnVendingPrice);
|
||||
SubscribeLocalEvent<VendingMachineComponent, EmpPulseEvent>(OnEmpPulse);
|
||||
@@ -123,12 +123,6 @@ namespace Content.Server.VendingMachines
|
||||
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)
|
||||
@@ -232,7 +226,7 @@ namespace Content.Server.VendingMachines
|
||||
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);
|
||||
@@ -422,7 +416,7 @@ namespace Content.Server.VendingMachines
|
||||
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)
|
||||
|
||||
@@ -76,7 +76,7 @@ public sealed partial class AccessReaderComponent : Component
|
||||
/// Whether or not emag interactions have an effect on this.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool BreakOnEmag = true;
|
||||
public bool BreakOnAccessBreaker = true;
|
||||
}
|
||||
|
||||
[DataDefinition, Serializable, NetSerializable]
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis;
|
||||
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;
|
||||
@@ -24,6 +23,7 @@ public sealed class AccessReaderSystem : EntitySystem
|
||||
[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!;
|
||||
@@ -71,17 +71,28 @@ public sealed class AccessReaderSystem : EntitySystem
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -135,6 +146,7 @@ public sealed class AccessReaderSystem : EntitySystem
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,3 +45,6 @@ namespace Content.Shared.Access.Systems
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ByRefEvent]
|
||||
public record struct OnAccessOverriderAccessUpdatedEvent(EntityUid UserUid, bool Handled = false);
|
||||
|
||||
@@ -46,15 +46,6 @@ public sealed partial class CloningPodComponent : Component
|
||||
[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")
|
||||
|
||||
@@ -24,6 +24,7 @@ public sealed partial class DisposalDoAfterEvent : SimpleDoAfterEvent
|
||||
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!;
|
||||
@@ -102,6 +103,12 @@ public abstract class SharedDisposalUnitSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
[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!;
|
||||
@@ -77,8 +78,6 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
SubscribeLocalEvent<DoorComponent, WeldableAttemptEvent>(OnWeldAttempt);
|
||||
SubscribeLocalEvent<DoorComponent, WeldableChangedEvent>(OnWeldChanged);
|
||||
SubscribeLocalEvent<DoorComponent, GetPryTimeModifierEvent>(OnPryTimeModifier);
|
||||
|
||||
SubscribeLocalEvent<DoorComponent, OnAttemptEmagEvent>(OnAttemptEmag);
|
||||
SubscribeLocalEvent<DoorComponent, GotEmaggedEvent>(OnEmagged);
|
||||
}
|
||||
|
||||
@@ -118,31 +117,24 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
||||
_activeDoors.Remove(door);
|
||||
}
|
||||
|
||||
private void OnAttemptEmag(EntityUid uid, DoorComponent door, ref OnAttemptEmagEvent args)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
if (IsBolted(uid) || !airlock.Powered)
|
||||
return;
|
||||
|
||||
if (door.State != DoorState.Closed)
|
||||
return;
|
||||
|
||||
if (!SetState(uid, DoorState.Emagging, door))
|
||||
return;
|
||||
Audio.PlayPredicted(door.SparkSound, uid, args.UserUid, AudioParams.Default.WithVolume(8));
|
||||
|
||||
args.Repeatable = true;
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
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;
|
||||
|
||||
@@ -14,7 +16,21 @@ public sealed partial class EmagComponent : Component
|
||||
/// <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");
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Emag.Components;
|
||||
@@ -5,7 +6,12 @@ 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;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ using Content.Shared.Emag.Components;
|
||||
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;
|
||||
|
||||
@@ -23,88 +23,123 @@ public sealed class EmagSystem : EntitySystem
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to use the emag on a target entity
|
||||
/// </summary>
|
||||
public bool TryUseEmag(EntityUid uid, EntityUid user, EntityUid target, EmagComponent? comp = null)
|
||||
{
|
||||
if (!Resolve(uid, ref comp, false))
|
||||
return false;
|
||||
|
||||
if (_tag.HasTag(target, comp.EmagImmuneTag))
|
||||
return false;
|
||||
|
||||
TryComp<LimitedChargesComponent>(uid, out var charges);
|
||||
if (_charges.IsEmpty(uid, charges))
|
||||
{
|
||||
_popup.PopupClient(Loc.GetString("emag-no-charges"), user, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
var handled = DoEmagEffect(user, target);
|
||||
if (!handled)
|
||||
return false;
|
||||
|
||||
_popup.PopupClient(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}");
|
||||
|
||||
if (charges != null)
|
||||
_charges.UseCharge(uid, charges);
|
||||
return true;
|
||||
args.Handled = TryEmagEffect((uid, comp), args.User, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the emag effect on a specified entity
|
||||
/// </summary>
|
||||
public bool DoEmagEffect(EntityUid user, EntityUid target)
|
||||
public bool TryEmagEffect(Entity<EmagComponent?> ent, EntityUid user, EntityUid target)
|
||||
{
|
||||
// prevent emagging twice
|
||||
if (HasComp<EmaggedComponent>(target))
|
||||
if (!Resolve(ent, ref ent.Comp, false))
|
||||
return false;
|
||||
|
||||
var onAttemptEmagEvent = new OnAttemptEmagEvent(user);
|
||||
RaiseLocalEvent(target, ref onAttemptEmagEvent);
|
||||
|
||||
// prevent emagging if attempt fails
|
||||
if (onAttemptEmagEvent.Handled)
|
||||
if (_tag.HasTag(target, ent.Comp.EmagImmuneTag))
|
||||
return false;
|
||||
|
||||
var emaggedEvent = new GotEmaggedEvent(user);
|
||||
TryComp<LimitedChargesComponent>(ent, out var charges);
|
||||
if (_charges.IsEmpty(ent, charges))
|
||||
{
|
||||
_popup.PopupClient(Loc.GetString("emag-no-charges"), user, user);
|
||||
return false;
|
||||
}
|
||||
|
||||
var emaggedEvent = new GotEmaggedEvent(user, ent.Comp.EmagType);
|
||||
RaiseLocalEvent(target, ref emaggedEvent);
|
||||
|
||||
if (emaggedEvent.Handled && !emaggedEvent.Repeatable)
|
||||
EnsureComp<EmaggedComponent>(target);
|
||||
if (!emaggedEvent.Handled)
|
||||
return false;
|
||||
|
||||
_popup.PopupPredicted(Loc.GetString("emag-success", ("target", Identity.Entity(target, EntityManager))), user, user, PopupType.Medium);
|
||||
|
||||
_audio.PlayPredicted(ent.Comp.EmagSound, ent, ent);
|
||||
|
||||
_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>
|
||||
/// Checks whether an entity has the EmaggedComponent with a set flag.
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
if (!TryComp<EmaggedComponent>(target, out var comp))
|
||||
return false;
|
||||
|
||||
if ((comp.EmagType & flag) == flag)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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;
|
||||
|
||||
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);
|
||||
|
||||
@@ -59,12 +59,6 @@ public sealed partial class FaxMachineComponent : Component
|
||||
[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>
|
||||
|
||||
@@ -18,6 +18,7 @@ public abstract class SharedLatheSystem : EntitySystem
|
||||
{
|
||||
[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();
|
||||
|
||||
@@ -66,6 +67,12 @@ public abstract class SharedLatheSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Shared.Actions;
|
||||
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;
|
||||
@@ -22,6 +23,7 @@ public sealed class UnpoweredFlashlightSystem : EntitySystem
|
||||
[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()
|
||||
{
|
||||
@@ -78,6 +80,9 @@ public sealed class UnpoweredFlashlightSystem : EntitySystem
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ public sealed partial class LockComponent : Component
|
||||
/// <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.
|
||||
|
||||
@@ -28,6 +28,7 @@ public sealed class LockSystem : EntitySystem
|
||||
[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!;
|
||||
@@ -295,7 +296,10 @@ public sealed class LockSystem : EntitySystem
|
||||
|
||||
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);
|
||||
@@ -307,7 +311,7 @@ public sealed class LockSystem : EntitySystem
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ public abstract class SharedMaterialReclaimerSystem : EntitySystem
|
||||
[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";
|
||||
|
||||
@@ -60,6 +61,12 @@ public abstract class SharedMaterialReclaimerSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -207,7 +214,7 @@ public abstract class SharedMaterialReclaimerSystem : EntitySystem
|
||||
component.Enabled &&
|
||||
!component.Broken &&
|
||||
HasComp<BodyComponent>(victim) &&
|
||||
HasComp<EmaggedComponent>(uid);
|
||||
_emag.CheckFlag(uid, EmagType.Interaction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -20,6 +20,7 @@ public abstract partial class SharedCryoPodSystem: EntitySystem
|
||||
{
|
||||
[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!;
|
||||
@@ -156,9 +157,13 @@ public abstract partial class SharedCryoPodSystem: EntitySystem
|
||||
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;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
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;
|
||||
|
||||
@@ -17,11 +19,23 @@ public sealed partial class EmagProviderComponent : Component
|
||||
/// 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");
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Shared.Interaction;
|
||||
using Content.Shared.Ninja.Components;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Shared.Ninja.Systems;
|
||||
|
||||
@@ -13,6 +14,7 @@ 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!;
|
||||
@@ -42,14 +44,18 @@ public sealed class EmagProviderSystem : EntitySystem
|
||||
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;
|
||||
@@ -57,7 +63,7 @@ public sealed class EmagProviderSystem : EntitySystem
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised on the player when emagging something.
|
||||
/// Raised on the player when access breaking something.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct EmaggedSomethingEvent(EntityUid Target);
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Content.Shared.Pinpointer;
|
||||
public abstract class SharedPinpointerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly EmagSystem _emag = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -137,6 +138,15 @@ public abstract class SharedPinpointerSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,4 @@ public sealed partial class EmaggableMedibotComponent : Component
|
||||
/// </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)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Content.Shared.Silicons.Bots;
|
||||
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!;
|
||||
@@ -36,10 +37,14 @@ public sealed class MedibotSystem : EntitySystem
|
||||
|
||||
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;
|
||||
|
||||
_audio.PlayPredicted(comp.SparkSound, uid, args.UserUid);
|
||||
if (_emag.CheckFlag(uid, EmagType.Interaction))
|
||||
return;
|
||||
|
||||
if (!TryComp<MedibotComponent>(uid, out var medibot))
|
||||
return;
|
||||
|
||||
foreach (var (state, treatment) in comp.Replacements)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
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;
|
||||
|
||||
@@ -11,22 +14,29 @@ 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;
|
||||
}
|
||||
|
||||
@@ -35,14 +45,33 @@ public abstract partial class SharedSiliconLawSystem : EntitySystem
|
||||
!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);
|
||||
|
||||
@@ -11,6 +11,7 @@ public abstract class SharedSingularityGeneratorSystem : EntitySystem
|
||||
{
|
||||
#region Dependencies
|
||||
[Dependency] protected readonly SharedPopupSystem PopupSystem = default!;
|
||||
[Dependency] private readonly EmagSystem _emag = default!;
|
||||
#endregion Dependencies
|
||||
|
||||
public override void Initialize()
|
||||
@@ -22,7 +23,16 @@ public abstract class SharedSingularityGeneratorSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Shared.Emag.Components;
|
||||
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;
|
||||
@@ -19,11 +20,14 @@ public abstract partial class SharedVendingMachineSystem : EntitySystem
|
||||
[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);
|
||||
}
|
||||
|
||||
@@ -49,9 +53,21 @@ public abstract partial class SharedVendingMachineSystem : EntitySystem
|
||||
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>
|
||||
@@ -64,7 +80,7 @@ public abstract partial class SharedVendingMachineSystem : EntitySystem
|
||||
|
||||
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)
|
||||
|
||||
@@ -14,6 +14,7 @@ public abstract class SharedArtifactCrusherSystem : EntitySystem
|
||||
[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()
|
||||
@@ -40,6 +41,15 @@ public abstract class SharedArtifactCrusherSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
emag-success = The card zaps something in {THE($target)}.
|
||||
emag-success = The device zaps something in {THE($target)}.
|
||||
emag-no-charges = No charges left!
|
||||
|
||||
@@ -113,7 +113,10 @@ uplink-chest-rig-name = Chest Rig
|
||||
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.
|
||||
|
||||
@@ -39,7 +39,7 @@ thief-backpack-category-syndie-name = syndie kit
|
||||
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
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
- RadioJammer
|
||||
- TraitorCodePaper
|
||||
- Emag
|
||||
- AccessBreaker
|
||||
- Lighter
|
||||
- CigPackSyndicate
|
||||
- Telecrystal10 #The thief cannot use them, but it may induce communication with traitors
|
||||
|
||||
@@ -865,16 +865,29 @@
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
@@ -167,7 +167,6 @@
|
||||
- cell_slot
|
||||
- type: Lock
|
||||
locked: true
|
||||
breakOnEmag: false
|
||||
unlockOnClick: false
|
||||
- type: ActivatableUIRequiresLock
|
||||
- type: LockedWiresPanel
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
- 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.
|
||||
|
||||
@@ -570,7 +570,7 @@
|
||||
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:
|
||||
@@ -580,6 +580,7 @@
|
||||
items:
|
||||
- Crowbar
|
||||
- Emag
|
||||
- AccessBreaker
|
||||
- PinpointerSyndicateNuclear
|
||||
- type: BorgModuleIcon
|
||||
icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-operative-module }
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
- 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
|
||||
@@ -98,10 +98,10 @@
|
||||
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
|
||||
|
||||
@@ -621,7 +621,7 @@
|
||||
color: "#3c5eb5"
|
||||
- type: Tag
|
||||
tags:
|
||||
- EmagImmune
|
||||
- AccessBreakerImmune
|
||||
- type: ItemSlots
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
visible: false
|
||||
map: ["enum.FatExtractorVisualLayers.Smoke"]
|
||||
- type: Lock
|
||||
breakOnEmag: false
|
||||
breakOnAccessBreaker: false
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.StorageVisuals.Open:
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
responsePings: false
|
||||
notifyAdmins: true
|
||||
- type: Emagged
|
||||
emagType: Interaction
|
||||
|
||||
- type: entity
|
||||
parent: FaxMachineBase
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
- type: ActivatableUI
|
||||
key: enum.CryostorageUIKey.Key
|
||||
- type: AccessReader
|
||||
breakOnEmag: false
|
||||
breakOnAccessBreaker: false
|
||||
access: [["Cryogenics"]]
|
||||
- type: InteractionOutline
|
||||
- type: Cryostorage
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# PUT YOUR TAGS IN ALPHABETICAL ORDER
|
||||
|
||||
- type: Tag
|
||||
id: AccessBreakerImmune
|
||||
|
||||
- type: Tag
|
||||
id: AirAlarm
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 141 B |
BIN
Resources/Textures/Objects/Tools/access_breaker.rsi/icon.png
Normal file
BIN
Resources/Textures/Objects/Tools/access_breaker.rsi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 353 B |
Binary file not shown.
|
After Width: | Height: | Size: 383 B |
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user