Station AI ability to electricute doors (#32012)

* Boom! Emergency access!

* Emergency access sound

* locale

* Updated sounds

* bleh

* Door electrify base

* feat: popups on attempt to activate AI action when wires cut

* refactor: use SharedApcPowerReceiverComponent to check if AI can interact with door

* refactor: added icon and sound for door overcharge

* meta.json should use tabs not spaces

* refactor: extracted sounds for airlock overcharge to static field in system

* refactor: cleanup, ScarKy0 mentions for resources

* refactor: removed unused textures

* feat: now notification is displayed when AI attempting to interact with door which have wire cut

* StationAiWhitelistComponent is properly gating  BUI OnMessageAttempt, SharedPowerReceiverSystem.IsPowered is now used to check if device powered

* refactor: use PlayLocal to play electrify sound only for AI player

* refactor: SetBoltsDown now uses TrySetBoltDown, checks for power.

* bolts now check for power using SharedPowerReceiverSystem

* electrify localization and louder electrify sounds

* extracted ShowDeviceNotRespondingPopup, reverted airlocks not opening/closing when ai wire was cut

* refactor: cleanup

* New sprites and fixes

* Copyright

* even more sprite changes

* refactore: cleanup, rename overcharge => electrify

---------

Co-authored-by: ScarKy0 <scarky0@onet.eu>
Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
Fildrance
2024-09-27 10:22:17 +03:00
committed by GitHub
parent 0d26bb0320
commit 4bcf3c3c0e
30 changed files with 371 additions and 109 deletions

View File

@@ -90,22 +90,22 @@ public sealed partial class AdminVerbSystem
args.Verbs.Add(bolt);
}
if (TryComp<AirlockComponent>(args.Target, out var airlock))
if (TryComp<AirlockComponent>(args.Target, out var airlockComp))
{
Verb emergencyAccess = new()
{
Text = airlock.EmergencyAccess ? "Emergency Access Off" : "Emergency Access On",
Text = airlockComp.EmergencyAccess ? "Emergency Access Off" : "Emergency Access On",
Category = VerbCategory.Tricks,
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/emergency_access.png")),
Act = () =>
{
_airlockSystem.ToggleEmergencyAccess(args.Target, airlock);
_airlockSystem.SetEmergencyAccess((args.Target, airlockComp), !airlockComp.EmergencyAccess);
},
Impact = LogImpact.Medium,
Message = Loc.GetString(airlock.EmergencyAccess
Message = Loc.GetString(airlockComp.EmergencyAccess
? "admin-trick-emergency-access-off-description"
: "admin-trick-emergency-access-on-description"),
Priority = (int) (airlock.EmergencyAccess ? TricksVerbPriorities.EmergencyAccessOff : TricksVerbPriorities.EmergencyAccessOn),
Priority = (int) (airlockComp.EmergencyAccess ? TricksVerbPriorities.EmergencyAccessOff : TricksVerbPriorities.EmergencyAccessOn),
};
args.Verbs.Add(emergencyAccess);
}

View File

@@ -1,4 +1,5 @@
using Content.Server.Electrocution;
using Content.Shared.Electrocution;
using Content.Shared.Construction;
namespace Content.Server.Construction.Completions;

View File

@@ -2,7 +2,6 @@ using Content.Server.Doors.Systems;
using Content.Server.Wires;
using Content.Shared.Doors;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
using Content.Shared.Wires;
namespace Content.Server.Doors;

View File

@@ -1,121 +0,0 @@
using Robust.Shared.Audio;
namespace Content.Server.Electrocution;
/// <summary>
/// Component for things that shock users on touch.
/// </summary>
[RegisterComponent]
public sealed partial class ElectrifiedComponent : Component
{
[DataField("enabled")]
public bool Enabled = true;
/// <summary>
/// Should player get damage on collide
/// </summary>
[DataField("onBump")]
public bool OnBump = true;
/// <summary>
/// Should player get damage on attack
/// </summary>
[DataField("onAttacked")]
public bool OnAttacked = true;
/// <summary>
/// When true - disables power if a window is present in the same tile
/// </summary>
[DataField("noWindowInTile")]
public bool NoWindowInTile = false;
/// <summary>
/// Should player get damage on interact with empty hand
/// </summary>
[DataField("onHandInteract")]
public bool OnHandInteract = true;
/// <summary>
/// Should player get damage on interact while holding an object in their hand
/// </summary>
[DataField("onInteractUsing")]
public bool OnInteractUsing = true;
/// <summary>
/// Indicates if the entity requires power to function
/// </summary>
[DataField("requirePower")]
public bool RequirePower = true;
/// <summary>
/// Indicates if the entity uses APC power
/// </summary>
[DataField("usesApcPower")]
public bool UsesApcPower = false;
/// <summary>
/// Identifier for the high voltage node.
/// </summary>
[DataField("highVoltageNode")]
public string? HighVoltageNode;
/// <summary>
/// Identifier for the medium voltage node.
/// </summary>
[DataField("mediumVoltageNode")]
public string? MediumVoltageNode;
/// <summary>
/// Identifier for the low voltage node.
/// </summary>
[DataField("lowVoltageNode")]
public string? LowVoltageNode;
/// <summary>
/// Damage multiplier for HV electrocution
/// </summary>
[DataField]
public float HighVoltageDamageMultiplier = 3f;
/// <summary>
/// Shock time multiplier for HV electrocution
/// </summary>
[DataField]
public float HighVoltageTimeMultiplier = 1.5f;
/// <summary>
/// Damage multiplier for MV electrocution
/// </summary>
[DataField]
public float MediumVoltageDamageMultiplier = 2f;
/// <summary>
/// Shock time multiplier for MV electrocution
/// </summary>
[DataField]
public float MediumVoltageTimeMultiplier = 1.25f;
[DataField("shockDamage")]
public float ShockDamage = 7.5f;
/// <summary>
/// Shock time, in seconds.
/// </summary>
[DataField("shockTime")]
public float ShockTime = 8f;
[DataField("siemensCoefficient")]
public float SiemensCoefficient = 1f;
[DataField("shockNoises")]
public SoundSpecifier ShockNoises = new SoundCollectionSpecifier("sparks");
[DataField("playSoundOnShock")]
public bool PlaySoundOnShock = true;
[DataField("shockVolume")]
public float ShockVolume = 20;
[DataField]
public float Probability = 1f;
}

View File

@@ -488,4 +488,15 @@ 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

@@ -1,4 +1,5 @@
using Content.Server.Electrocution;
using Content.Shared.Electrocution;
using Content.Server.Power.Components;
using Content.Server.Wires;
using Content.Shared.Power;
@@ -104,6 +105,7 @@ public sealed partial class PowerWireAction : BaseWireAction
&& !EntityManager.TryGetComponent(used, out electrified))
return;
_electrocutionSystem.SetElectrifiedWireCut((used, electrified), setting);
electrified.Enabled = setting;
}

View File

@@ -74,7 +74,7 @@ namespace Content.Shared.Remotes
case OperatingMode.ToggleEmergencyAccess:
if (airlockComp != null)
{
_airlock.ToggleEmergencyAccess(args.Target.Value, airlockComp);
_airlock.SetEmergencyAccess((args.Target.Value, airlockComp), !airlockComp.EmergencyAccess);
_adminLogger.Add(LogType.Action, LogImpact.Medium,
$"{ToPrettyString(args.User):player} used {ToPrettyString(args.Used)} on {ToPrettyString(args.Target.Value)} to set emergency access {(airlockComp.EmergencyAccess ? "on" : "off")}");
}