Allow AI and observers to see electrified doors (#33466)

This commit is contained in:
metalgearsloth
2024-11-23 17:37:14 +11:00
committed by GitHub
16 changed files with 194 additions and 50 deletions

View File

@@ -0,0 +1,95 @@
using Content.Shared.Electrocution;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Player;
namespace Content.Client.Electrocution;
/// <summary>
/// Shows the Electrocution HUD to entities with the ShowElectrocutionHUDComponent.
/// </summary>
public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<ElectrocutionHUDVisualsComponent>
{
[Dependency] private readonly IPlayerManager _playerMan = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ShowElectrocutionHUDComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<ShowElectrocutionHUDComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
}
private void OnPlayerAttached(Entity<ShowElectrocutionHUDComponent> ent, ref LocalPlayerAttachedEvent args)
{
ShowHUD();
}
private void OnPlayerDetached(Entity<ShowElectrocutionHUDComponent> ent, ref LocalPlayerDetachedEvent args)
{
RemoveHUD();
}
private void OnInit(Entity<ShowElectrocutionHUDComponent> ent, ref ComponentInit args)
{
if (_playerMan.LocalEntity == ent)
{
ShowHUD();
}
}
private void OnShutdown(Entity<ShowElectrocutionHUDComponent> ent, ref ComponentShutdown args)
{
if (_playerMan.LocalEntity == ent)
{
RemoveHUD();
}
}
// Show the HUD to the client.
// We have to look for all current entities that can be electrified and toggle the HUD layer on if they are.
private void ShowHUD()
{
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
{
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp))
continue;
if (electrified)
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, true);
else
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}
// Remove the HUD from the client.
// Find all current entities that can be electrified and hide the HUD layer.
private void RemoveHUD()
{
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
{
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}
// Toggle the HUD layer if an entity becomes (de-)electrified
protected override void OnAppearanceChange(EntityUid uid, ElectrocutionHUDVisualsComponent comp, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component))
return;
var player = _playerMan.LocalEntity;
if (electrified && HasComp<ShowElectrocutionHUDComponent>(player))
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, true);
else
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, false);
}
}

View File

@@ -121,7 +121,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
activated.TimeLeft -= frameTime;
if (activated.TimeLeft <= 0 || !IsPowered(uid, electrified, transform))
{
_appearance.SetData(uid, ElectrifiedVisuals.IsPowered, false);
_appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, false);
RemComp<ActivatedElectrifiedComponent>(uid);
}
}
@@ -217,7 +217,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
return false;
EnsureComp<ActivatedElectrifiedComponent>(uid);
_appearance.SetData(uid, ElectrifiedVisuals.IsPowered, true);
_appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, true);
siemens *= electrified.SiemensCoefficient;
if (!DoCommonElectrocutionAttempt(targetUid, uid, ref siemens) || siemens <= 0)
@@ -488,15 +488,4 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
}
_audio.PlayPvs(electrified.ShockNoises, targetUid, AudioParams.Default.WithVolume(electrified.ShockVolume));
}
public void SetElectrifiedWireCut(Entity<ElectrifiedComponent> ent, bool value)
{
if (ent.Comp.IsWireCut == value)
{
return;
}
ent.Comp.IsWireCut = value;
Dirty(ent);
}
}

View File

@@ -17,7 +17,7 @@ public sealed partial class PowerWireAction : BaseWireAction
[DataField("pulseTimeout")]
private int _pulseTimeout = 30;
private ElectrocutionSystem _electrocutionSystem = default!;
private ElectrocutionSystem _electrocution = default!;
public override object StatusKey { get; } = PowerWireActionKey.Status;
@@ -105,8 +105,8 @@ public sealed partial class PowerWireAction : BaseWireAction
&& !EntityManager.TryGetComponent(used, out electrified))
return;
_electrocutionSystem.SetElectrifiedWireCut((used, electrified), setting);
electrified.Enabled = setting;
_electrocution.SetElectrifiedWireCut((used, electrified), setting);
_electrocution.SetElectrified((used, electrified), setting);
}
/// <returns>false if failed, true otherwise, or if the entity cannot be electrified</returns>
@@ -120,7 +120,7 @@ public sealed partial class PowerWireAction : BaseWireAction
// always set this to true
SetElectrified(wire.Owner, true, electrified);
var electrifiedAttempt = _electrocutionSystem.TryDoElectrifiedAct(wire.Owner, user);
var electrifiedAttempt = _electrocution.TryDoElectrifiedAct(wire.Owner, user);
// if we were electrified, then return false
return !electrifiedAttempt;
@@ -161,7 +161,7 @@ public sealed partial class PowerWireAction : BaseWireAction
{
base.Initialize();
_electrocutionSystem = EntityManager.System<ElectrocutionSystem>();
_electrocution = EntityManager.System<ElectrocutionSystem>();
}
// This should add a wire into the entity's state, whether it be

View File

@@ -0,0 +1,7 @@
namespace Content.Shared.Electrocution;
/// <summary>
/// Handles toggling sprite layers for the electrocution HUD to show if an entity with the ElectrifiedComponent is electrified.
/// </summary>
[RegisterComponent]
public sealed partial class ElectrocutionHUDVisualsComponent : Component;

View File

@@ -0,0 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Electrocution;
/// <summary>
/// Allow an entity to see the Electrocution HUD showing electrocuted doors.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class ShowElectrocutionHUDComponent : Component;

View File

@@ -5,11 +5,13 @@ namespace Content.Shared.Electrocution;
[Serializable, NetSerializable]
public enum ElectrifiedLayers : byte
{
Powered
Sparks,
HUD,
}
[Serializable, NetSerializable]
public enum ElectrifiedVisuals : byte
{
IsPowered
ShowSparks, // only shown when zapping someone, deactivated after a short time
IsElectrified, // if the entity is electrified or not, used for the AI HUD
}

View File

@@ -5,6 +5,8 @@ namespace Content.Shared.Electrocution
{
public abstract class SharedElectrocutionSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
public override void Initialize()
{
base.Initialize();
@@ -35,6 +37,19 @@ namespace Content.Shared.Electrocution
ent.Comp.Enabled = value;
Dirty(ent, ent.Comp);
_appearance.SetData(ent.Owner, ElectrifiedVisuals.IsElectrified, value);
}
public void SetElectrifiedWireCut(Entity<ElectrifiedComponent> ent, bool value)
{
if (ent.Comp.IsWireCut == value)
{
return;
}
ent.Comp.IsWireCut = value;
Dirty(ent);
}
/// <param name="uid">Entity being electrocuted.</param>

View File

@@ -55,6 +55,7 @@
skipChecks: true
- type: Ghost
- type: GhostHearing
- type: ShowElectrocutionHUD
- type: IntrinsicRadioReceiver
- type: ActiveRadio
receiveAllChannels: true

View File

@@ -30,6 +30,7 @@
- type: IgnoreUIRange
- type: StationAiHeld
- type: StationAiOverlay
- type: ShowElectrocutionHUD
- type: ActionGrant
actions:
- ActionJumpToCore

View File

@@ -31,6 +31,11 @@
shader: unshaded
- state: panel_open
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- state: electrified
sprite: Interface/Misc/ai_hud.rsi
shader: unshaded
visible: false
map: ["enum.ElectrifiedLayers.HUD"]
- type: AnimationPlayer
- type: Physics
- type: Fixtures
@@ -73,6 +78,7 @@
- type: DoorBolt
- type: Appearance
- type: WiresVisuals
- type: ElectrocutionHUDVisuals
- type: ApcPowerReceiver
powerLoad: 20
- type: ExtensionCableReceiver

View File

@@ -30,24 +30,6 @@
hard: false
- type: Sprite
sprite: Structures/Doors/Airlocks/Standard/shuttle.rsi
snapCardinals: false
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- state: closed_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseUnlit"]
visible: false
- state: welded
map: ["enum.WeldableLayers.BaseWelded"]
- state: bolted_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseBolted"]
- state: emergency_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseEmergencyAccess"]
- state: panel_open
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: Wires
layoutId: Docking
- type: Door

View File

@@ -70,8 +70,8 @@
- type: Appearance
- type: GenericVisualizer
visuals:
enum.ElectrifiedVisuals.IsPowered:
enum.ElectrifiedLayers.Powered:
enum.ElectrifiedVisuals.ShowSparks:
enum.ElectrifiedLayers.Sparks:
True: { visible: True }
False: { visible: False }
- type: AnimationPlayer
@@ -91,7 +91,7 @@
- state: straight_broken
- state: electrified
sprite: Effects/electricity.rsi
map: ["enum.ElectrifiedLayers.Powered"]
map: ["enum.ElectrifiedLayers.Sparks"]
shader: unshaded
visible: false
- type: Physics
@@ -151,7 +151,7 @@
- state: straight
- state: electrified
sprite: Effects/electricity.rsi
map: ["enum.ElectrifiedLayers.Powered"]
map: ["enum.ElectrifiedLayers.Sparks"]
shader: unshaded
visible: false
- type: Fixtures
@@ -209,7 +209,7 @@
- state: corner
- state: electrified
sprite: Effects/electricity.rsi
map: ["enum.ElectrifiedLayers.Powered"]
map: ["enum.ElectrifiedLayers.Sparks"]
shader: unshaded
visible: false
- type: Fixtures
@@ -256,7 +256,7 @@
- state: end
- state: electrified
sprite: Effects/electricity.rsi
map: ["enum.ElectrifiedLayers.Powered"]
map: ["enum.ElectrifiedLayers.Sparks"]
shader: unshaded
visible: false
- type: Fixtures
@@ -292,7 +292,7 @@
map: ["enum.DoorVisualLayers.Base"]
- state: electrified
sprite: Effects/electricity.rsi
map: [ "enum.ElectrifiedLayers.Powered" ]
map: [ "enum.ElectrifiedLayers.Sparks" ]
shader: unshaded
visible: false
- type: Fixtures

View File

@@ -21,7 +21,7 @@
- state: grille
- state: electrified
sprite: Effects/electricity.rsi
map: ["enum.ElectrifiedLayers.Powered"]
map: ["enum.ElectrifiedLayers.Sparks"]
shader: unshaded
visible: false
- type: Icon
@@ -82,8 +82,8 @@
- type: Appearance
- type: GenericVisualizer
visuals:
enum.ElectrifiedVisuals.IsPowered:
enum.ElectrifiedLayers.Powered:
enum.ElectrifiedVisuals.ShowSparks:
enum.ElectrifiedLayers.Sparks:
True: { visible: True }
False: { visible: False }
- type: AnimationPlayer
@@ -176,7 +176,7 @@
- state: grille_diagonal
- state: electrified_diagonal
sprite: Effects/electricity.rsi
map: ["enum.ElectrifiedLayers.Powered"]
map: ["enum.ElectrifiedLayers.Sparks"]
shader: unshaded
visible: false
- type: Icon
@@ -211,7 +211,7 @@
- state: ratvargrille_diagonal
- state: electrified_diagonal
sprite: Effects/electricity.rsi
map: ["enum.ElectrifiedLayers.Powered"]
map: ["enum.ElectrifiedLayers.Sparks"]
shader: unshaded
visible: false
- type: Icon

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

View File

@@ -0,0 +1,37 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "taken from tgstation at commit https://github.com/tgstation/tgstation/commit/d170a410d40eec4fc19fe5eb8d561d58a0902082",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "electrified",
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
]
]
},
{
"name": "apc_hacked",
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
]
]
}
]
}