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:
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Doors.Components;
|
using Content.Shared.Doors.Components;
|
||||||
|
using Content.Shared.Electrocution;
|
||||||
using Content.Shared.Silicons.StationAi;
|
using Content.Shared.Silicons.StationAi;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
@@ -6,25 +7,69 @@ namespace Content.Client.Silicons.StationAi;
|
|||||||
|
|
||||||
public sealed partial class StationAiSystem
|
public sealed partial class StationAiSystem
|
||||||
{
|
{
|
||||||
|
private readonly ResPath _aiActionsRsi = new ResPath("/Textures/Interface/Actions/actions_ai.rsi");
|
||||||
|
|
||||||
private void InitializeAirlock()
|
private void InitializeAirlock()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<DoorBoltComponent, GetStationAiRadialEvent>(OnDoorBoltGetRadial);
|
SubscribeLocalEvent<DoorBoltComponent, GetStationAiRadialEvent>(OnDoorBoltGetRadial);
|
||||||
|
SubscribeLocalEvent<AirlockComponent, GetStationAiRadialEvent>(OnEmergencyAccessGetRadial);
|
||||||
|
SubscribeLocalEvent<ElectrifiedComponent, GetStationAiRadialEvent>(OnDoorElectrifiedGetRadial);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDoorBoltGetRadial(Entity<DoorBoltComponent> ent, ref GetStationAiRadialEvent args)
|
private void OnDoorBoltGetRadial(Entity<DoorBoltComponent> ent, ref GetStationAiRadialEvent args)
|
||||||
{
|
{
|
||||||
args.Actions.Add(new StationAiRadial()
|
args.Actions.Add(
|
||||||
|
new StationAiRadial
|
||||||
{
|
{
|
||||||
Sprite = ent.Comp.BoltsDown ?
|
Sprite = ent.Comp.BoltsDown
|
||||||
new SpriteSpecifier.Rsi(
|
? new SpriteSpecifier.Rsi(_aiActionsRsi, "unbolt_door")
|
||||||
new ResPath("/Textures/Structures/Doors/Airlocks/Standard/basic.rsi"), "open") :
|
: new SpriteSpecifier.Rsi(_aiActionsRsi, "bolt_door"),
|
||||||
new SpriteSpecifier.Rsi(
|
Tooltip = ent.Comp.BoltsDown
|
||||||
new ResPath("/Textures/Structures/Doors/Airlocks/Standard/basic.rsi"), "closed"),
|
? Loc.GetString("bolt-open")
|
||||||
Tooltip = ent.Comp.BoltsDown ? Loc.GetString("bolt-open") : Loc.GetString("bolt-close"),
|
: Loc.GetString("bolt-close"),
|
||||||
Event = new StationAiBoltEvent()
|
Event = new StationAiBoltEvent
|
||||||
{
|
{
|
||||||
Bolted = !ent.Comp.BoltsDown,
|
Bolted = !ent.Comp.BoltsDown,
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEmergencyAccessGetRadial(Entity<AirlockComponent> ent, ref GetStationAiRadialEvent args)
|
||||||
|
{
|
||||||
|
args.Actions.Add(
|
||||||
|
new StationAiRadial
|
||||||
|
{
|
||||||
|
Sprite = ent.Comp.EmergencyAccess
|
||||||
|
? new SpriteSpecifier.Rsi(_aiActionsRsi, "emergency_off")
|
||||||
|
: new SpriteSpecifier.Rsi(_aiActionsRsi, "emergency_on"),
|
||||||
|
Tooltip = ent.Comp.EmergencyAccess
|
||||||
|
? Loc.GetString("emergency-access-off")
|
||||||
|
: Loc.GetString("emergency-access-on"),
|
||||||
|
Event = new StationAiEmergencyAccessEvent
|
||||||
|
{
|
||||||
|
EmergencyAccess = !ent.Comp.EmergencyAccess,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDoorElectrifiedGetRadial(Entity<ElectrifiedComponent> ent, ref GetStationAiRadialEvent args)
|
||||||
|
{
|
||||||
|
args.Actions.Add(
|
||||||
|
new StationAiRadial
|
||||||
|
{
|
||||||
|
Sprite = ent.Comp.Enabled
|
||||||
|
? new SpriteSpecifier.Rsi(_aiActionsRsi, "door_overcharge_off")
|
||||||
|
: new SpriteSpecifier.Rsi(_aiActionsRsi, "door_overcharge_on"),
|
||||||
|
Tooltip = ent.Comp.Enabled
|
||||||
|
? Loc.GetString("electrify-door-off")
|
||||||
|
: Loc.GetString("electrify-door-on"),
|
||||||
|
Event = new StationAiElectrifiedEvent
|
||||||
|
{
|
||||||
|
Electrified = !ent.Comp.Enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,22 +90,22 @@ public sealed partial class AdminVerbSystem
|
|||||||
args.Verbs.Add(bolt);
|
args.Verbs.Add(bolt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryComp<AirlockComponent>(args.Target, out var airlock))
|
if (TryComp<AirlockComponent>(args.Target, out var airlockComp))
|
||||||
{
|
{
|
||||||
Verb emergencyAccess = new()
|
Verb emergencyAccess = new()
|
||||||
{
|
{
|
||||||
Text = airlock.EmergencyAccess ? "Emergency Access Off" : "Emergency Access On",
|
Text = airlockComp.EmergencyAccess ? "Emergency Access Off" : "Emergency Access On",
|
||||||
Category = VerbCategory.Tricks,
|
Category = VerbCategory.Tricks,
|
||||||
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/emergency_access.png")),
|
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/emergency_access.png")),
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
_airlockSystem.ToggleEmergencyAccess(args.Target, airlock);
|
_airlockSystem.SetEmergencyAccess((args.Target, airlockComp), !airlockComp.EmergencyAccess);
|
||||||
},
|
},
|
||||||
Impact = LogImpact.Medium,
|
Impact = LogImpact.Medium,
|
||||||
Message = Loc.GetString(airlock.EmergencyAccess
|
Message = Loc.GetString(airlockComp.EmergencyAccess
|
||||||
? "admin-trick-emergency-access-off-description"
|
? "admin-trick-emergency-access-off-description"
|
||||||
: "admin-trick-emergency-access-on-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);
|
args.Verbs.Add(emergencyAccess);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Electrocution;
|
using Content.Server.Electrocution;
|
||||||
|
using Content.Shared.Electrocution;
|
||||||
using Content.Shared.Construction;
|
using Content.Shared.Construction;
|
||||||
|
|
||||||
namespace Content.Server.Construction.Completions;
|
namespace Content.Server.Construction.Completions;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Content.Server.Doors.Systems;
|
|||||||
using Content.Server.Wires;
|
using Content.Server.Wires;
|
||||||
using Content.Shared.Doors;
|
using Content.Shared.Doors;
|
||||||
using Content.Shared.Doors.Components;
|
using Content.Shared.Doors.Components;
|
||||||
using Content.Shared.Doors.Systems;
|
|
||||||
using Content.Shared.Wires;
|
using Content.Shared.Wires;
|
||||||
|
|
||||||
namespace Content.Server.Doors;
|
namespace Content.Server.Doors;
|
||||||
|
|||||||
@@ -488,4 +488,15 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
|
|||||||
}
|
}
|
||||||
_audio.PlayPvs(electrified.ShockNoises, targetUid, AudioParams.Default.WithVolume(electrified.ShockVolume));
|
_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Electrocution;
|
using Content.Server.Electrocution;
|
||||||
|
using Content.Shared.Electrocution;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Wires;
|
using Content.Server.Wires;
|
||||||
using Content.Shared.Power;
|
using Content.Shared.Power;
|
||||||
@@ -104,6 +105,7 @@ public sealed partial class PowerWireAction : BaseWireAction
|
|||||||
&& !EntityManager.TryGetComponent(used, out electrified))
|
&& !EntityManager.TryGetComponent(used, out electrified))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_electrocutionSystem.SetElectrifiedWireCut((used, electrified), setting);
|
||||||
electrified.Enabled = setting;
|
electrified.Enabled = setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace Content.Shared.Remotes
|
|||||||
case OperatingMode.ToggleEmergencyAccess:
|
case OperatingMode.ToggleEmergencyAccess:
|
||||||
if (airlockComp != null)
|
if (airlockComp != null)
|
||||||
{
|
{
|
||||||
_airlock.ToggleEmergencyAccess(args.Target.Value, airlockComp);
|
_airlock.SetEmergencyAccess((args.Target.Value, airlockComp), !airlockComp.EmergencyAccess);
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Medium,
|
_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")}");
|
$"{ToPrettyString(args.User):player} used {ToPrettyString(args.Used)} on {ToPrettyString(args.Target.Value)} to set emergency access {(airlockComp.EmergencyAccess ? "on" : "off")}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Shared.DeviceLinking;
|
using Content.Shared.DeviceLinking;
|
||||||
using Content.Shared.Doors.Systems;
|
using Content.Shared.Doors.Systems;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
@@ -24,6 +25,18 @@ public sealed partial class AirlockComponent : Component
|
|||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool EmergencyAccess = false;
|
public bool EmergencyAccess = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sound to play when the airlock emergency access is turned on.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SoundSpecifier EmergencyOnSound = new SoundPathSpecifier("/Audio/Machines/airlock_emergencyon.ogg");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sound to play when the airlock emergency access is turned off.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SoundSpecifier EmergencyOffSound = new SoundPathSpecifier("/Audio/Machines/airlock_emergencyoff.ogg");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pry modifier for a powered airlock.
|
/// Pry modifier for a powered airlock.
|
||||||
/// Most anything that can pry powered has a pry speed bonus,
|
/// Most anything that can pry powered has a pry speed bonus,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Doors.Components;
|
using Content.Shared.Doors.Components;
|
||||||
|
using Robust.Shared.Audio.Systems;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Prying.Components;
|
using Content.Shared.Prying.Components;
|
||||||
using Content.Shared.Wires;
|
using Content.Shared.Wires;
|
||||||
@@ -10,7 +11,9 @@ public abstract class SharedAirlockSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||||
|
[Dependency] protected readonly SharedAudioSystem Audio = default!;
|
||||||
[Dependency] protected readonly SharedDoorSystem DoorSystem = default!;
|
[Dependency] protected readonly SharedDoorSystem DoorSystem = default!;
|
||||||
|
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||||
[Dependency] private readonly SharedWiresSystem _wiresSystem = default!;
|
[Dependency] private readonly SharedWiresSystem _wiresSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -131,11 +134,23 @@ public abstract class SharedAirlockSystem : EntitySystem
|
|||||||
Appearance.SetData(uid, DoorVisuals.EmergencyLights, component.EmergencyAccess);
|
Appearance.SetData(uid, DoorVisuals.EmergencyLights, component.EmergencyAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToggleEmergencyAccess(EntityUid uid, AirlockComponent component)
|
public void SetEmergencyAccess(Entity<AirlockComponent> ent, bool value, EntityUid? user = null, bool predicted = false)
|
||||||
{
|
{
|
||||||
component.EmergencyAccess = !component.EmergencyAccess;
|
if(!ent.Comp.Powered)
|
||||||
Dirty(uid, component); // This only runs on the server apparently so we need this.
|
return;
|
||||||
UpdateEmergencyLightStatus(uid, component);
|
|
||||||
|
if (ent.Comp.EmergencyAccess == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ent.Comp.EmergencyAccess = value;
|
||||||
|
Dirty(ent, ent.Comp); // This only runs on the server apparently so we need this.
|
||||||
|
UpdateEmergencyLightStatus(ent, ent.Comp);
|
||||||
|
|
||||||
|
var sound = ent.Comp.EmergencyAccess ? ent.Comp.EmergencyOnSound : ent.Comp.EmergencyOffSound;
|
||||||
|
if (predicted)
|
||||||
|
Audio.PlayPredicted(sound, ent, user: user);
|
||||||
|
else
|
||||||
|
Audio.PlayPvs(sound, ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAutoCloseDelayModifier(AirlockComponent component, float value)
|
public void SetAutoCloseDelayModifier(AirlockComponent component, float value)
|
||||||
|
|||||||
@@ -77,8 +77,20 @@ public abstract partial class SharedDoorSystem
|
|||||||
|
|
||||||
public void SetBoltsDown(Entity<DoorBoltComponent> ent, bool value, EntityUid? user = null, bool predicted = false)
|
public void SetBoltsDown(Entity<DoorBoltComponent> ent, bool value, EntityUid? user = null, bool predicted = false)
|
||||||
{
|
{
|
||||||
|
TrySetBoltDown(ent, value, user, predicted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TrySetBoltDown(
|
||||||
|
Entity<DoorBoltComponent> ent,
|
||||||
|
bool value,
|
||||||
|
EntityUid? user = null,
|
||||||
|
bool predicted = false
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!_powerReceiver.IsPowered(ent.Owner))
|
||||||
|
return false;
|
||||||
if (ent.Comp.BoltsDown == value)
|
if (ent.Comp.BoltsDown == value)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
ent.Comp.BoltsDown = value;
|
ent.Comp.BoltsDown = value;
|
||||||
Dirty(ent, ent.Comp);
|
Dirty(ent, ent.Comp);
|
||||||
@@ -89,6 +101,7 @@ public abstract partial class SharedDoorSystem
|
|||||||
Audio.PlayPredicted(sound, ent, user: user);
|
Audio.PlayPredicted(sound, ent, user: user);
|
||||||
else
|
else
|
||||||
Audio.PlayPvs(sound, ent);
|
Audio.PlayPvs(sound, ent);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStateChanged(Entity<DoorBoltComponent> entity, ref DoorStateChangedEvent args)
|
private void OnStateChanged(Entity<DoorBoltComponent> entity, ref DoorStateChangedEvent args)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Content.Shared.Emag.Systems;
|
|||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Power.EntitySystems;
|
||||||
using Content.Shared.Prying.Components;
|
using Content.Shared.Prying.Components;
|
||||||
using Content.Shared.Prying.Systems;
|
using Content.Shared.Prying.Systems;
|
||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
@@ -42,6 +43,7 @@ public abstract partial class SharedDoorSystem : EntitySystem
|
|||||||
[Dependency] private readonly PryingSystem _pryingSystem = default!;
|
[Dependency] private readonly PryingSystem _pryingSystem = default!;
|
||||||
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
[Dependency] protected readonly SharedPopupSystem Popup = default!;
|
||||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||||
|
[Dependency] private readonly SharedPowerReceiverSystem _powerReceiver = default!;
|
||||||
|
|
||||||
|
|
||||||
[ValidatePrototypeId<TagPrototype>]
|
[ValidatePrototypeId<TagPrototype>]
|
||||||
|
|||||||
@@ -1,121 +1,131 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
|
|
||||||
namespace Content.Server.Electrocution;
|
namespace Content.Shared.Electrocution;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Component for things that shock users on touch.
|
/// Component for things that shock users on touch.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
public sealed partial class ElectrifiedComponent : Component
|
public sealed partial class ElectrifiedComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("enabled")]
|
[DataField, AutoNetworkedField]
|
||||||
public bool Enabled = true;
|
public bool Enabled = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should player get damage on collide
|
/// Should player get damage on collide
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("onBump")]
|
[DataField, AutoNetworkedField]
|
||||||
public bool OnBump = true;
|
public bool OnBump = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should player get damage on attack
|
/// Should player get damage on attack
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("onAttacked")]
|
[DataField, AutoNetworkedField]
|
||||||
public bool OnAttacked = true;
|
public bool OnAttacked = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When true - disables power if a window is present in the same tile
|
/// When true - disables power if a window is present in the same tile
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("noWindowInTile")]
|
[DataField, AutoNetworkedField]
|
||||||
public bool NoWindowInTile = false;
|
public bool NoWindowInTile = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should player get damage on interact with empty hand
|
/// Should player get damage on interact with empty hand
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("onHandInteract")]
|
[DataField, AutoNetworkedField]
|
||||||
public bool OnHandInteract = true;
|
public bool OnHandInteract = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should player get damage on interact while holding an object in their hand
|
/// Should player get damage on interact while holding an object in their hand
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("onInteractUsing")]
|
[DataField, AutoNetworkedField]
|
||||||
public bool OnInteractUsing = true;
|
public bool OnInteractUsing = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if the entity requires power to function
|
/// Indicates if the entity requires power to function
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("requirePower")]
|
[DataField, AutoNetworkedField]
|
||||||
public bool RequirePower = true;
|
public bool RequirePower = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if the entity uses APC power
|
/// Indicates if the entity uses APC power
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("usesApcPower")]
|
[DataField, AutoNetworkedField]
|
||||||
public bool UsesApcPower = false;
|
public bool UsesApcPower = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Identifier for the high voltage node.
|
/// Identifier for the high voltage node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("highVoltageNode")]
|
[DataField, AutoNetworkedField]
|
||||||
public string? HighVoltageNode;
|
public string? HighVoltageNode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Identifier for the medium voltage node.
|
/// Identifier for the medium voltage node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("mediumVoltageNode")]
|
[DataField, AutoNetworkedField]
|
||||||
public string? MediumVoltageNode;
|
public string? MediumVoltageNode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Identifier for the low voltage node.
|
/// Identifier for the low voltage node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("lowVoltageNode")]
|
[DataField, AutoNetworkedField]
|
||||||
public string? LowVoltageNode;
|
public string? LowVoltageNode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Damage multiplier for HV electrocution
|
/// Damage multiplier for HV electrocution
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public float HighVoltageDamageMultiplier = 3f;
|
public float HighVoltageDamageMultiplier = 3f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shock time multiplier for HV electrocution
|
/// Shock time multiplier for HV electrocution
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public float HighVoltageTimeMultiplier = 1.5f;
|
public float HighVoltageTimeMultiplier = 1.5f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Damage multiplier for MV electrocution
|
/// Damage multiplier for MV electrocution
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public float MediumVoltageDamageMultiplier = 2f;
|
public float MediumVoltageDamageMultiplier = 2f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shock time multiplier for MV electrocution
|
/// Shock time multiplier for MV electrocution
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public float MediumVoltageTimeMultiplier = 1.25f;
|
public float MediumVoltageTimeMultiplier = 1.25f;
|
||||||
|
|
||||||
[DataField("shockDamage")]
|
[DataField, AutoNetworkedField]
|
||||||
public float ShockDamage = 7.5f;
|
public float ShockDamage = 7.5f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shock time, in seconds.
|
/// Shock time, in seconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("shockTime")]
|
[DataField, AutoNetworkedField]
|
||||||
public float ShockTime = 8f;
|
public float ShockTime = 8f;
|
||||||
|
|
||||||
[DataField("siemensCoefficient")]
|
[DataField, AutoNetworkedField]
|
||||||
public float SiemensCoefficient = 1f;
|
public float SiemensCoefficient = 1f;
|
||||||
|
|
||||||
[DataField("shockNoises")]
|
[DataField, AutoNetworkedField]
|
||||||
public SoundSpecifier ShockNoises = new SoundCollectionSpecifier("sparks");
|
public SoundSpecifier ShockNoises = new SoundCollectionSpecifier("sparks");
|
||||||
|
|
||||||
[DataField("playSoundOnShock")]
|
[DataField, AutoNetworkedField]
|
||||||
|
public SoundPathSpecifier AirlockElectrifyDisabled = new("/Audio/Machines/airlock_electrify_on.ogg");
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public SoundPathSpecifier AirlockElectrifyEnabled = new("/Audio/Machines/airlock_electrify_off.ogg");
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
public bool PlaySoundOnShock = true;
|
public bool PlaySoundOnShock = true;
|
||||||
|
|
||||||
[DataField("shockVolume")]
|
[DataField, AutoNetworkedField]
|
||||||
public float ShockVolume = 20;
|
public float ShockVolume = 20;
|
||||||
|
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public float Probability = 1f;
|
public float Probability = 1f;
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool IsWireCut = false;
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,20 @@ namespace Content.Shared.Electrocution
|
|||||||
Dirty(uid, insulated);
|
Dirty(uid, insulated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets electrified value of component and marks dirty if required.
|
||||||
|
/// </summary>
|
||||||
|
public void SetElectrified(Entity<ElectrifiedComponent> ent, bool value)
|
||||||
|
{
|
||||||
|
if (ent.Comp.Enabled == value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent.Comp.Enabled = value;
|
||||||
|
Dirty(ent, ent.Comp);
|
||||||
|
}
|
||||||
|
|
||||||
/// <param name="uid">Entity being electrocuted.</param>
|
/// <param name="uid">Entity being electrocuted.</param>
|
||||||
/// <param name="sourceUid">Source entity of the electrocution.</param>
|
/// <param name="sourceUid">Source entity of the electrocution.</param>
|
||||||
/// <param name="shockDamage">How much shock damage the entity takes.</param>
|
/// <param name="shockDamage">How much shock damage the entity takes.</param>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Shared.Examine;
|
|
||||||
using Content.Shared.Power.Components;
|
using Content.Shared.Power.Components;
|
||||||
|
|
||||||
namespace Content.Shared.Power.EntitySystems;
|
namespace Content.Shared.Power.EntitySystems;
|
||||||
@@ -8,6 +7,9 @@ public abstract class SharedPowerReceiverSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
public abstract bool ResolveApc(EntityUid entity, [NotNullWhen(true)] ref SharedApcPowerReceiverComponent? component);
|
public abstract bool ResolveApc(EntityUid entity, [NotNullWhen(true)] ref SharedApcPowerReceiverComponent? component);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if entity is APC-powered device, and if it have power.
|
||||||
|
/// </summary>
|
||||||
public bool IsPowered(Entity<SharedApcPowerReceiverComponent?> entity)
|
public bool IsPowered(Entity<SharedApcPowerReceiverComponent?> entity)
|
||||||
{
|
{
|
||||||
if (!ResolveApc(entity.Owner, ref entity.Comp))
|
if (!ResolveApc(entity.Owner, ref entity.Comp))
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Shared.Doors.Components;
|
using Content.Shared.Doors.Components;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Content.Shared.Electrocution;
|
||||||
|
|
||||||
namespace Content.Shared.Silicons.StationAi;
|
namespace Content.Shared.Silicons.StationAi;
|
||||||
|
|
||||||
@@ -10,16 +11,84 @@ public abstract partial class SharedStationAiSystem
|
|||||||
private void InitializeAirlock()
|
private void InitializeAirlock()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<DoorBoltComponent, StationAiBoltEvent>(OnAirlockBolt);
|
SubscribeLocalEvent<DoorBoltComponent, StationAiBoltEvent>(OnAirlockBolt);
|
||||||
|
SubscribeLocalEvent<AirlockComponent, StationAiEmergencyAccessEvent>(OnAirlockEmergencyAccess);
|
||||||
|
SubscribeLocalEvent<ElectrifiedComponent, StationAiElectrifiedEvent>(OnElectrified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to bolt door. If wire was cut (AI or for bolts) or its not powered - notifies AI and does nothing.
|
||||||
|
/// </summary>
|
||||||
private void OnAirlockBolt(EntityUid ent, DoorBoltComponent component, StationAiBoltEvent args)
|
private void OnAirlockBolt(EntityUid ent, DoorBoltComponent component, StationAiBoltEvent args)
|
||||||
{
|
{
|
||||||
_doors.SetBoltsDown((ent, component), args.Bolted, args.User, predicted: true);
|
if (component.BoltWireCut)
|
||||||
|
{
|
||||||
|
ShowDeviceNotRespondingPopup(args.User);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var setResult = _doors.TrySetBoltDown((ent, component), args.Bolted, args.User, predicted: true);
|
||||||
|
if (!setResult)
|
||||||
|
{
|
||||||
|
ShowDeviceNotRespondingPopup(args.User);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to bolt door. If wire was cut (AI) or its not powered - notifies AI and does nothing.
|
||||||
|
/// </summary>
|
||||||
|
private void OnAirlockEmergencyAccess(EntityUid ent, AirlockComponent component, StationAiEmergencyAccessEvent args)
|
||||||
|
{
|
||||||
|
if (!PowerReceiver.IsPowered(ent))
|
||||||
|
{
|
||||||
|
ShowDeviceNotRespondingPopup(args.User);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_airlocks.SetEmergencyAccess((ent, component), args.EmergencyAccess, args.User, predicted: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to bolt door. If wire was cut (AI or for one of power-wires) or its not powered - notifies AI and does nothing.
|
||||||
|
/// </summary>
|
||||||
|
private void OnElectrified(EntityUid ent, ElectrifiedComponent component, StationAiElectrifiedEvent args)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
component.IsWireCut
|
||||||
|
|| !PowerReceiver.IsPowered(ent)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ShowDeviceNotRespondingPopup(args.User);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_electrify.SetElectrified((ent, component), args.Electrified);
|
||||||
|
var soundToPlay = component.Enabled
|
||||||
|
? component.AirlockElectrifyDisabled
|
||||||
|
: component.AirlockElectrifyEnabled;
|
||||||
|
_audio.PlayLocal(soundToPlay, ent, args.User);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Event for StationAI attempt at bolting/unbolting door. </summary>
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class StationAiBoltEvent : BaseStationAiAction
|
public sealed class StationAiBoltEvent : BaseStationAiAction
|
||||||
{
|
{
|
||||||
|
/// <summary> Marker, should be door bolted or unbolted. </summary>
|
||||||
public bool Bolted;
|
public bool Bolted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Event for StationAI attempt at setting emergency access for door on/off. </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class StationAiEmergencyAccessEvent : BaseStationAiAction
|
||||||
|
{
|
||||||
|
/// <summary> Marker, should door have emergency access on or off. </summary>
|
||||||
|
public bool EmergencyAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Event for StationAI attempt at electrifying/de-electrifying door. </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class StationAiElectrifiedEvent : BaseStationAiAction
|
||||||
|
{
|
||||||
|
/// <summary> Marker, should door be electrified or no. </summary>
|
||||||
|
public bool Electrified;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using Content.Shared.Actions.Events;
|
using Content.Shared.Actions.Events;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
@@ -108,41 +109,56 @@ public abstract partial class SharedStationAiSystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (TryComp(ev.Actor, out StationAiHeldComponent? aiComp) &&
|
if (TryComp(ev.Actor, out StationAiHeldComponent? aiComp) &&
|
||||||
(!ValidateAi((ev.Actor, aiComp)) ||
|
(!TryComp(ev.Target, out StationAiWhitelistComponent? whitelistComponent) ||
|
||||||
!HasComp<StationAiWhitelistComponent>(ev.Target)))
|
!ValidateAi((ev.Actor, aiComp))))
|
||||||
{
|
{
|
||||||
|
if (whitelistComponent is { Enabled: false })
|
||||||
|
{
|
||||||
|
ShowDeviceNotRespondingPopup(ev.Actor);
|
||||||
|
}
|
||||||
ev.Cancel();
|
ev.Cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnHeldInteraction(Entity<StationAiHeldComponent> ent, ref InteractionAttemptEvent args)
|
private void OnHeldInteraction(Entity<StationAiHeldComponent> ent, ref InteractionAttemptEvent args)
|
||||||
{
|
{
|
||||||
// Cancel if it's not us or something with a whitelist.
|
// Cancel if it's not us or something with a whitelist, or whitelist is disabled.
|
||||||
args.Cancelled = ent.Owner != args.Target &&
|
args.Cancelled = (!TryComp(args.Target, out StationAiWhitelistComponent? whitelistComponent)
|
||||||
args.Target != null &&
|
|| !whitelistComponent.Enabled)
|
||||||
(!TryComp(args.Target, out StationAiWhitelistComponent? whitelist) || !whitelist.Enabled);
|
&& ent.Owner != args.Target
|
||||||
|
&& args.Target != null;
|
||||||
|
if (whitelistComponent is { Enabled: false })
|
||||||
|
{
|
||||||
|
ShowDeviceNotRespondingPopup(ent.Owner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTargetVerbs(Entity<StationAiWhitelistComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
|
private void OnTargetVerbs(Entity<StationAiWhitelistComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
|
||||||
{
|
{
|
||||||
if (!args.CanComplexInteract ||
|
if (!args.CanComplexInteract
|
||||||
!ent.Comp.Enabled ||
|
|| !HasComp<StationAiHeldComponent>(args.User))
|
||||||
!HasComp<StationAiHeldComponent>(args.User) ||
|
|
||||||
!HasComp<StationAiWhitelistComponent>(args.Target))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = args.User;
|
var user = args.User;
|
||||||
|
|
||||||
var target = args.Target;
|
var target = args.Target;
|
||||||
|
|
||||||
var isOpen = _uiSystem.IsUiOpen(target, AiUi.Key, user);
|
var isOpen = _uiSystem.IsUiOpen(target, AiUi.Key, user);
|
||||||
|
|
||||||
args.Verbs.Add(new AlternativeVerb()
|
var verb = new AlternativeVerb
|
||||||
{
|
{
|
||||||
Text = isOpen ? Loc.GetString("ai-close") : Loc.GetString("ai-open"),
|
Text = isOpen ? Loc.GetString("ai-close") : Loc.GetString("ai-open"),
|
||||||
Act = () =>
|
Act = () =>
|
||||||
{
|
{
|
||||||
|
// no need to show menu if device is not powered.
|
||||||
|
if (!PowerReceiver.IsPowered(ent.Owner))
|
||||||
|
{
|
||||||
|
ShowDeviceNotRespondingPopup(user);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isOpen)
|
if (isOpen)
|
||||||
{
|
{
|
||||||
_uiSystem.CloseUi(ent.Owner, AiUi.Key, user);
|
_uiSystem.CloseUi(ent.Owner, AiUi.Key, user);
|
||||||
@@ -152,7 +168,13 @@ public abstract partial class SharedStationAiSystem
|
|||||||
_uiSystem.OpenUi(ent.Owner, AiUi.Key, user);
|
_uiSystem.OpenUi(ent.Owner, AiUi.Key, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
args.Verbs.Add(verb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowDeviceNotRespondingPopup(EntityUid toEntity)
|
||||||
|
{
|
||||||
|
_popup.PopupClient(Loc.GetString("ai-device-not-responding"), toEntity, PopupType.MediumCaution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,18 @@ using Content.Shared.Administration.Managers;
|
|||||||
using Content.Shared.Containers.ItemSlots;
|
using Content.Shared.Containers.ItemSlots;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Doors.Systems;
|
using Content.Shared.Doors.Systems;
|
||||||
|
using Content.Shared.Electrocution;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Item.ItemToggle;
|
using Content.Shared.Item.ItemToggle;
|
||||||
using Content.Shared.Mind;
|
using Content.Shared.Mind;
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Power;
|
using Content.Shared.Power;
|
||||||
|
using Content.Shared.Power.EntitySystems;
|
||||||
using Content.Shared.StationAi;
|
using Content.Shared.StationAi;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
@@ -31,13 +35,18 @@ public abstract partial class SharedStationAiSystem : EntitySystem
|
|||||||
[Dependency] private readonly ItemToggleSystem _toggles = default!;
|
[Dependency] private readonly ItemToggleSystem _toggles = default!;
|
||||||
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metadata = default!;
|
[Dependency] private readonly MetaDataSystem _metadata = default!;
|
||||||
|
[Dependency] private readonly SharedAirlockSystem _airlocks = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containers = default!;
|
[Dependency] private readonly SharedContainerSystem _containers = default!;
|
||||||
[Dependency] private readonly SharedDoorSystem _doors = default!;
|
[Dependency] private readonly SharedDoorSystem _doors = default!;
|
||||||
|
[Dependency] private readonly SharedElectrocutionSystem _electrify = default!;
|
||||||
[Dependency] private readonly SharedEyeSystem _eye = default!;
|
[Dependency] private readonly SharedEyeSystem _eye = default!;
|
||||||
[Dependency] protected readonly SharedMapSystem Maps = default!;
|
[Dependency] protected readonly SharedMapSystem Maps = default!;
|
||||||
[Dependency] private readonly SharedMindSystem _mind = default!;
|
[Dependency] private readonly SharedMindSystem _mind = default!;
|
||||||
[Dependency] private readonly SharedMoverController _mover = default!;
|
[Dependency] private readonly SharedMoverController _mover = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
|
[Dependency] private readonly SharedPowerReceiverSystem PowerReceiver = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _xforms = default!;
|
[Dependency] private readonly SharedTransformSystem _xforms = default!;
|
||||||
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
|
||||||
[Dependency] private readonly StationAiVisionSystem _vision = default!;
|
[Dependency] private readonly StationAiVisionSystem _vision = default!;
|
||||||
|
|||||||
BIN
Resources/Audio/Machines/airlock_electrify_off.ogg
Normal file
BIN
Resources/Audio/Machines/airlock_electrify_off.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/Machines/airlock_electrify_on.ogg
Normal file
BIN
Resources/Audio/Machines/airlock_electrify_on.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/Machines/airlock_emergencyoff.ogg
Normal file
BIN
Resources/Audio/Machines/airlock_emergencyoff.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/Machines/airlock_emergencyon.ogg
Normal file
BIN
Resources/Audio/Machines/airlock_emergencyon.ogg
Normal file
Binary file not shown.
@@ -171,3 +171,12 @@
|
|||||||
license: "CC0-1.0"
|
license: "CC0-1.0"
|
||||||
copyright: "by Ko4erga"
|
copyright: "by Ko4erga"
|
||||||
source: "https://github.com/space-wizards/space-station-14/pull/30431"
|
source: "https://github.com/space-wizards/space-station-14/pull/30431"
|
||||||
|
|
||||||
|
- files:
|
||||||
|
- airlock_emergencyoff.ogg
|
||||||
|
- airlock_emergencyon.ogg
|
||||||
|
- airlock_electrify_off.ogg
|
||||||
|
- airlock_electrify_on.ogg
|
||||||
|
license: "CC0-1.0"
|
||||||
|
copyright: "by ScarKy0"
|
||||||
|
source: "https://github.com/space-wizards/space-station-14/pull/32012"
|
||||||
|
|||||||
@@ -11,4 +11,12 @@ ai-close = Close actions
|
|||||||
bolt-close = Close bolt
|
bolt-close = Close bolt
|
||||||
bolt-open = Open bolt
|
bolt-open = Open bolt
|
||||||
|
|
||||||
|
emergency-access-on = Enable emergency access
|
||||||
|
emergency-access-off = Disable emergency access
|
||||||
|
|
||||||
|
electrify-door-on = Enable overcharge
|
||||||
|
electrify-door-off = Disable overcharge
|
||||||
|
|
||||||
toggle-light = Toggle light
|
toggle-light = Toggle light
|
||||||
|
|
||||||
|
ai-device-not-responding = Device is not responding
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 372 B |
Binary file not shown.
|
After Width: | Height: | Size: 614 B |
Binary file not shown.
|
After Width: | Height: | Size: 495 B |
Binary file not shown.
|
After Width: | Height: | Size: 876 B |
Binary file not shown.
|
After Width: | Height: | Size: 767 B |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"license": "CC-BY-SA-3.0",
|
"license": "CC-BY-SA-3.0",
|
||||||
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/blob/c473a8bcc28fbd80827dfca5660d81ca6e833e2c/icons/hud/screen_ai.dmi",
|
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/blob/c473a8bcc28fbd80827dfca5660d81ca6e833e2c/icons/hud/screen_ai.dmi , some sprites updated by ScarKy0(Discord), door actions by ScarKy0(Discord) and @Max_tanuki(Twitter)",
|
||||||
"size": {
|
"size": {
|
||||||
"x": 32,
|
"x": 32,
|
||||||
"y": 32
|
"y": 32
|
||||||
@@ -33,6 +33,24 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "comms_console"
|
"name": "comms_console"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "emergency_off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "emergency_on"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "bolt_door"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unbolt_door"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "door_overcharge_on"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "door_overcharge_off"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 588 B |
Reference in New Issue
Block a user