Change suit sensors on other players (#29668)

* Suit sensors can be turned off on other players

* less doafter time + interaction (nostate) check

* code cleanup

* code cleanup 2
This commit is contained in:
BombasterDS
2024-08-11 19:04:42 +10:00
committed by GitHub
parent c8f1c22ff2
commit 67253a3fe1
3 changed files with 78 additions and 16 deletions

View File

@@ -14,37 +14,43 @@ public sealed partial class SuitSensorComponent : Component
/// <summary>
/// Choose a random sensor mode when item is spawned.
/// </summary>
[DataField("randomMode")]
[DataField]
public bool RandomMode = true;
/// <summary>
/// If true user can't change suit sensor mode
/// </summary>
[DataField("controlsLocked")]
[DataField]
public bool ControlsLocked = false;
/// <summary>
/// How much time it takes to change another player's sensors
/// </summary>
[DataField]
public float SensorsTime = 1.75f;
/// <summary>
/// Current sensor mode. Can be switched by user verbs.
/// </summary>
[DataField("mode")]
[DataField]
public SuitSensorMode Mode = SuitSensorMode.SensorOff;
/// <summary>
/// Activate sensor if user wear it in this slot.
/// </summary>
[DataField("activationSlot")]
[DataField]
public string ActivationSlot = "jumpsuit";
/// <summary>
/// Activate sensor if user has this in a sensor-compatible container.
/// </summary>
[DataField("activationContainer")]
[DataField]
public string? ActivationContainer;
/// <summary>
/// How often does sensor update its owners status (in seconds). Limited by the system update rate.
/// </summary>
[DataField("updateRate")]
[DataField]
public TimeSpan UpdateRate = TimeSpan.FromSeconds(2f);
/// <summary>
@@ -56,7 +62,7 @@ public sealed partial class SuitSensorComponent : Component
/// <summary>
/// Next time when sensor updated owners status
/// </summary>
[DataField("nextUpdate", customTypeSerializer:typeof(TimeOffsetSerializer))]
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
[AutoPausedField]
public TimeSpan NextUpdate = TimeSpan.Zero;

View File

@@ -8,10 +8,13 @@ using Content.Server.GameTicking;
using Content.Server.Medical.CrewMonitoring;
using Content.Server.Popups;
using Content.Server.Station.Systems;
using Content.Shared.ActionBlocker;
using Content.Shared.Clothing;
using Content.Shared.Damage;
using Content.Shared.DeviceNetwork;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Medical.SuitSensor;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
@@ -35,6 +38,9 @@ public sealed class SuitSensorSystem : EntitySystem
[Dependency] private readonly StationSystem _stationSystem = default!;
[Dependency] private readonly SingletonDeviceNetServerSystem _singletonServerSystem = default!;
[Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
public override void Initialize()
{
@@ -49,6 +55,7 @@ public sealed class SuitSensorSystem : EntitySystem
SubscribeLocalEvent<SuitSensorComponent, EntGotRemovedFromContainerMessage>(OnRemove);
SubscribeLocalEvent<SuitSensorComponent, EmpPulseEvent>(OnEmpPulse);
SubscribeLocalEvent<SuitSensorComponent, EmpDisabledRemoved>(OnEmpFinished);
SubscribeLocalEvent<SuitSensorComponent, SuitSensorChangeDoAfterEvent>(OnSuitSensorDoAfter);
}
public override void Update(float frameTime)
@@ -205,7 +212,14 @@ public sealed class SuitSensorSystem : EntitySystem
return;
// standard interaction checks
if (!args.CanAccess || !args.CanInteract || args.Hands == null)
if (!args.CanInteract || args.Hands == null)
return;
if (!_interactionSystem.InRangeUnobstructed(args.User, args.Target))
return;
// check if target is incapacitated (cuffed, dead, etc)
if (component.User != null && args.User != component.User && _actionBlocker.CanInteract(component.User.Value, null))
return;
args.Verbs.UnionWith(new[]
@@ -239,7 +253,7 @@ public sealed class SuitSensorSystem : EntitySystem
args.Disabled = true;
component.PreviousMode = component.Mode;
SetSensor(uid, SuitSensorMode.SensorOff, null, component);
SetSensor((uid, component), SuitSensorMode.SensorOff, null);
component.PreviousControlsLocked = component.ControlsLocked;
component.ControlsLocked = true;
@@ -247,7 +261,7 @@ public sealed class SuitSensorSystem : EntitySystem
private void OnEmpFinished(EntityUid uid, SuitSensorComponent component, ref EmpDisabledRemoved args)
{
SetSensor(uid, component.PreviousMode, null, component);
SetSensor((uid, component), component.PreviousMode, null);
component.ControlsLocked = component.PreviousControlsLocked;
}
@@ -259,7 +273,7 @@ public sealed class SuitSensorSystem : EntitySystem
Disabled = component.Mode == mode,
Priority = -(int) mode, // sort them in descending order
Category = VerbCategory.SetSensor,
Act = () => SetSensor(uid, mode, userUid, component)
Act = () => TrySetSensor((uid, component), mode, userUid)
};
}
@@ -287,18 +301,46 @@ public sealed class SuitSensorSystem : EntitySystem
return Loc.GetString(name);
}
public void SetSensor(EntityUid uid, SuitSensorMode mode, EntityUid? userUid = null,
SuitSensorComponent? component = null)
public void TrySetSensor(Entity<SuitSensorComponent> sensors, SuitSensorMode mode, EntityUid userUid)
{
if (!Resolve(uid, ref component))
var comp = sensors.Comp;
if (!Resolve(sensors, ref comp))
return;
component.Mode = mode;
if (comp.User == null || userUid == comp.User)
SetSensor(sensors, mode, userUid);
else
{
var doAfterEvent = new SuitSensorChangeDoAfterEvent(mode);
var doAfterArgs = new DoAfterArgs(EntityManager, userUid, comp.SensorsTime, doAfterEvent, sensors)
{
BreakOnMove = true,
BreakOnDamage = true
};
_doAfterSystem.TryStartDoAfter(doAfterArgs);
}
}
private void OnSuitSensorDoAfter(Entity<SuitSensorComponent> sensors, ref SuitSensorChangeDoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;
SetSensor(sensors, args.Mode, args.User);
}
public void SetSensor(Entity<SuitSensorComponent> sensors, SuitSensorMode mode, EntityUid? userUid = null)
{
var comp = sensors.Comp;
comp.Mode = mode;
if (userUid != null)
{
var msg = Loc.GetString("suit-sensor-mode-state", ("mode", GetModeName(mode)));
_popupSystem.PopupEntity(msg, uid, userUid.Value);
_popupSystem.PopupEntity(msg, sensors, userUid.Value);
}
}

View File

@@ -1,3 +1,4 @@
using Content.Shared.DoAfter;
using Robust.Shared.Map;
using Robust.Shared.Serialization;
@@ -67,3 +68,16 @@ public static class SuitSensorConstants
///Used by the CrewMonitoringServerSystem to send the status of all connected suit sensors to each crew monitor
public const string NET_STATUS_COLLECTION = "suit-status-collection";
}
[Serializable, NetSerializable]
public sealed partial class SuitSensorChangeDoAfterEvent : DoAfterEvent
{
public SuitSensorMode Mode { get; private set; } = SuitSensorMode.SensorOff;
public SuitSensorChangeDoAfterEvent(SuitSensorMode mode)
{
Mode = mode;
}
public override DoAfterEvent Clone() => this;
}