Experimental nukie changes (#9428)
This commit is contained in:
@@ -103,7 +103,7 @@ namespace Content.Client.Nuke
|
||||
FirstStatusLabel.Text = firstMsg;
|
||||
SecondStatusLabel.Text = secondMsg;
|
||||
|
||||
EjectButton.Disabled = !state.DiskInserted;
|
||||
EjectButton.Disabled = !state.DiskInserted || state.Status == NukeStatus.ARMED;
|
||||
AnchorButton.Disabled = !state.DiskInserted;
|
||||
AnchorButton.Pressed = state.IsAnchored;
|
||||
ArmButton.Disabled = !state.AllowArm;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Threading;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Explosion;
|
||||
using Content.Shared.Nuke;
|
||||
@@ -18,11 +19,10 @@ namespace Content.Server.Nuke
|
||||
{
|
||||
/// <summary>
|
||||
/// Default bomb timer value in seconds.
|
||||
/// Must be shorter then the nuke alarm song.
|
||||
/// </summary>
|
||||
[DataField("timer")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int Timer = 120;
|
||||
public int Timer = 300;
|
||||
|
||||
/// <summary>
|
||||
/// How long until the bomb can arm again after deactivation.
|
||||
@@ -40,11 +40,17 @@ namespace Content.Server.Nuke
|
||||
public ItemSlot DiskSlot = new();
|
||||
|
||||
/// <summary>
|
||||
/// After this time nuke will play last alert sound
|
||||
/// When this time is left, nuke will play last alert sound
|
||||
/// </summary>
|
||||
[DataField("alertTime")]
|
||||
public float AlertSoundTime = 10.0f;
|
||||
|
||||
/// <summary>
|
||||
/// How long a user must wait to disarm the bomb.
|
||||
/// </summary>
|
||||
[DataField("disarmDoafterLength")]
|
||||
public float DisarmDoafterLength = 30.0f;
|
||||
|
||||
[DataField("alertLevelOnActivate")] public string AlertLevelOnActivate = default!;
|
||||
[DataField("alertLevelOnDeactivate")] public string AlertLevelOnDeactivate = default!;
|
||||
|
||||
@@ -136,11 +142,18 @@ namespace Content.Server.Nuke
|
||||
[ViewVariables]
|
||||
public NukeStatus Status = NukeStatus.AWAIT_DISK;
|
||||
|
||||
/// <summary>
|
||||
/// Check if nuke has already played the nuke song so we don't do it again
|
||||
/// </summary>
|
||||
public bool PlayedNukeSong = false;
|
||||
|
||||
/// <summary>
|
||||
/// Check if nuke has already played last alert sound
|
||||
/// </summary>
|
||||
public bool PlayedAlertSound = false;
|
||||
|
||||
public CancellationToken? DisarmCancelToken = null;
|
||||
|
||||
public IPlayingAudioStream? AlertAudioStream = default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Server.Chat;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Coordinates.Helpers;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Station.Systems;
|
||||
@@ -30,6 +31,17 @@ namespace Content.Server.Nuke
|
||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||
[Dependency] private readonly ServerGlobalSoundSystem _soundSystem = default!;
|
||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Used to calculate when the nuke song should start playing for maximum kino with the nuke sfx
|
||||
/// </summary>
|
||||
private const float NukeSongLength = 60f + 51.6f;
|
||||
|
||||
/// <summary>
|
||||
/// Time to leave between the nuke song and the nuke alarm playing.
|
||||
/// </summary>
|
||||
private const float NukeSongBuffer = 1.5f;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -51,6 +63,10 @@ namespace Content.Server.Nuke
|
||||
SubscribeLocalEvent<NukeComponent, NukeKeypadMessage>(OnKeypadButtonPressed);
|
||||
SubscribeLocalEvent<NukeComponent, NukeKeypadClearMessage>(OnClearButtonPressed);
|
||||
SubscribeLocalEvent<NukeComponent, NukeKeypadEnterMessage>(OnEnterButtonPressed);
|
||||
|
||||
// Doafter events
|
||||
SubscribeLocalEvent<NukeComponent, NukeDisarmSuccessEvent>(OnDisarmSuccess);
|
||||
SubscribeLocalEvent<NukeComponent, NukeDisarmCancelledEvent>(OnDisarmCancelled);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, NukeComponent component, ComponentInit args)
|
||||
@@ -98,6 +114,7 @@ namespace Content.Server.Nuke
|
||||
}
|
||||
|
||||
#region Anchor
|
||||
|
||||
private void OnAnchorAttempt(EntityUid uid, NukeComponent component, AnchorAttemptEvent args)
|
||||
{
|
||||
CheckAnchorAttempt(uid, component, args);
|
||||
@@ -124,9 +141,11 @@ namespace Content.Server.Nuke
|
||||
{
|
||||
UpdateUserInterface(uid, component);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI Events
|
||||
|
||||
private async void OnAnchorButtonPressed(EntityUid uid, NukeComponent component, NukeAnchorMessage args)
|
||||
{
|
||||
if (!component.DiskSlot.HasItem)
|
||||
@@ -188,9 +207,28 @@ namespace Content.Server.Nuke
|
||||
}
|
||||
else
|
||||
{
|
||||
DisarmBomb(uid, component);
|
||||
if (args.Session.AttachedEntity is not { } user)
|
||||
return;
|
||||
|
||||
DisarmBombDoafter(uid, user, component);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Doafter Events
|
||||
|
||||
private void OnDisarmSuccess(EntityUid uid, NukeComponent component, NukeDisarmSuccessEvent args)
|
||||
{
|
||||
component.DisarmCancelToken = null;
|
||||
DisarmBomb(uid, component);
|
||||
}
|
||||
|
||||
private void OnDisarmCancelled(EntityUid uid, NukeComponent component, NukeDisarmCancelledEvent args)
|
||||
{
|
||||
component.DisarmCancelToken = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void TickCooldown(EntityUid uid, float frameTime, NukeComponent? nuke = null)
|
||||
@@ -217,6 +255,14 @@ namespace Content.Server.Nuke
|
||||
|
||||
nuke.RemainingTime -= frameTime;
|
||||
|
||||
// Start playing the nuke event song so that it ends a couple seconds before the alert sound
|
||||
// should play
|
||||
if (nuke.RemainingTime <= NukeSongLength + nuke.AlertSoundTime + NukeSongBuffer && !nuke.PlayedNukeSong)
|
||||
{
|
||||
_soundSystem.DispatchStationEventMusic(uid, nuke.ArmMusic, StationEventMusicType.Nuke);
|
||||
nuke.PlayedNukeSong = true;
|
||||
}
|
||||
|
||||
// play alert sound if time is running out
|
||||
if (nuke.RemainingTime <= nuke.AlertSoundTime && !nuke.PlayedAlertSound)
|
||||
{
|
||||
@@ -248,28 +294,29 @@ namespace Content.Server.Nuke
|
||||
component.Status = NukeStatus.AWAIT_CODE;
|
||||
break;
|
||||
case NukeStatus.AWAIT_CODE:
|
||||
{
|
||||
if (!component.DiskSlot.HasItem)
|
||||
{
|
||||
if (!component.DiskSlot.HasItem)
|
||||
{
|
||||
component.Status = NukeStatus.AWAIT_DISK;
|
||||
component.EnteredCode = "";
|
||||
break;
|
||||
}
|
||||
|
||||
var isValid = _codes.IsCodeValid(component.EnteredCode);
|
||||
if (isValid)
|
||||
{
|
||||
component.Status = NukeStatus.AWAIT_ARM;
|
||||
component.RemainingTime = component.Timer;
|
||||
PlaySound(uid, component.AccessGrantedSound, 0, component);
|
||||
}
|
||||
else
|
||||
{
|
||||
component.EnteredCode = "";
|
||||
PlaySound(uid, component.AccessDeniedSound, 0, component);
|
||||
}
|
||||
component.Status = NukeStatus.AWAIT_DISK;
|
||||
component.EnteredCode = "";
|
||||
break;
|
||||
}
|
||||
|
||||
var isValid = _codes.IsCodeValid(component.EnteredCode);
|
||||
if (isValid)
|
||||
{
|
||||
component.Status = NukeStatus.AWAIT_ARM;
|
||||
component.RemainingTime = component.Timer;
|
||||
PlaySound(uid, component.AccessGrantedSound, 0, component);
|
||||
}
|
||||
else
|
||||
{
|
||||
component.EnteredCode = "";
|
||||
PlaySound(uid, component.AccessDeniedSound, 0, component);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NukeStatus.AWAIT_ARM:
|
||||
// do nothing, wait for arm button to be pressed
|
||||
break;
|
||||
@@ -322,6 +369,7 @@ namespace Content.Server.Nuke
|
||||
}
|
||||
|
||||
#region Public API
|
||||
|
||||
/// <summary>
|
||||
/// Force a nuclear bomb to start a countdown timer
|
||||
/// </summary>
|
||||
@@ -350,6 +398,7 @@ namespace Content.Server.Nuke
|
||||
|
||||
NukeArmedAudio(component);
|
||||
|
||||
_itemSlots.SetLock(uid, component.DiskSlot, true);
|
||||
component.Status = NukeStatus.ARMED;
|
||||
UpdateUserInterface(uid, component);
|
||||
}
|
||||
@@ -376,6 +425,7 @@ namespace Content.Server.Nuke
|
||||
var sender = Loc.GetString("nuke-component-announcement-sender");
|
||||
_chatSystem.DispatchStationAnnouncement(uid, announcement, sender, false);
|
||||
|
||||
component.PlayedNukeSong = false;
|
||||
NukeDisarmedAudio(component);
|
||||
|
||||
// disable sound and reset it
|
||||
@@ -383,6 +433,7 @@ namespace Content.Server.Nuke
|
||||
component.AlertAudioStream?.Stop();
|
||||
|
||||
// start bomb cooldown
|
||||
_itemSlots.SetLock(uid, component.DiskSlot, false);
|
||||
component.Status = NukeStatus.COOLDOWN;
|
||||
component.CooldownTime = component.Cooldown;
|
||||
|
||||
@@ -440,12 +491,30 @@ namespace Content.Server.Nuke
|
||||
component.RemainingTime = timer;
|
||||
UpdateUserInterface(uid, component);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void DisarmBombDoafter(EntityUid uid, EntityUid user, NukeComponent nuke)
|
||||
{
|
||||
nuke.DisarmCancelToken = new();
|
||||
var doafter = new DoAfterEventArgs(user, nuke.DisarmDoafterLength, nuke.DisarmCancelToken.Value, uid)
|
||||
{
|
||||
TargetCancelledEvent = new NukeDisarmCancelledEvent(),
|
||||
TargetFinishedEvent = new NukeDisarmSuccessEvent(),
|
||||
BreakOnDamage = true,
|
||||
BreakOnStun = true,
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
NeedHand = true,
|
||||
};
|
||||
|
||||
_doAfterSystem.DoAfter(doafter);
|
||||
_popups.PopupEntity(Loc.GetString("nuke-component-doafter-warning"), user, Filter.Entities(user));
|
||||
}
|
||||
|
||||
private void NukeArmedAudio(NukeComponent component)
|
||||
{
|
||||
_soundSystem.PlayGlobalOnStation(component.Owner, component.ArmSound.GetSound());
|
||||
_soundSystem.DispatchStationEventMusic(component.Owner, component.ArmMusic, StationEventMusicType.Nuke);
|
||||
}
|
||||
|
||||
private void NukeDisarmedAudio(NukeComponent component)
|
||||
@@ -456,4 +525,15 @@ namespace Content.Server.Nuke
|
||||
}
|
||||
|
||||
public sealed class NukeExplodedEvent : EntityEventArgs {}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on the nuke when its disarm doafter is successful.
|
||||
/// </summary>
|
||||
public sealed class NukeDisarmSuccessEvent : EntityEventArgs {}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on the nuke when its disarm doafter is cancelled.
|
||||
/// </summary>
|
||||
public sealed class NukeDisarmCancelledEvent : EntityEventArgs {}
|
||||
|
||||
}
|
||||
|
||||
@@ -571,7 +571,7 @@ namespace Content.Shared.CCVar
|
||||
/// Actual area may be larger, as it currently doesn't terminate mid neighbor finding. I.e., area may be that of a ~51 tile radius circle instead.
|
||||
/// </remarks>
|
||||
public static readonly CVarDef<int> ExplosionMaxArea =
|
||||
CVarDef.Create("explosion.max_area", (int) 3.14f * 50 * 50, CVar.SERVERONLY);
|
||||
CVarDef.Create("explosion.max_area", (int) 3.14f * 256 * 256, CVar.SERVERONLY);
|
||||
|
||||
/// <summary>
|
||||
/// Upper limit on the number of neighbor finding steps for the explosion system neighbor-finding algorithm.
|
||||
@@ -581,7 +581,7 @@ namespace Content.Shared.CCVar
|
||||
/// instances, <see cref="ExplosionMaxArea"/> will likely be hit before this becomes a limiting factor.
|
||||
/// </remarks>
|
||||
public static readonly CVarDef<int> ExplosionMaxIterations =
|
||||
CVarDef.Create("explosion.max_iterations", 150, CVar.SERVERONLY);
|
||||
CVarDef.Create("explosion.max_iterations", 500, CVar.SERVERONLY);
|
||||
|
||||
/// <summary>
|
||||
/// Max Time in milliseconds to spend processing explosions every tick.
|
||||
|
||||
@@ -3,6 +3,7 @@ nuke-component-announcement-sender = Nuclear Fission Explosive
|
||||
nuke-component-announcement-armed = Attention! The station's self-destruct mechanism has been engaged. {$time} seconds until detonation.
|
||||
nuke-component-announcement-unarmed = The station's self-destruct was deactivated! Have a nice day!
|
||||
nuke-component-announcement-send-codes = Attention! Requested self-destruction codes was sent to communication consoles.
|
||||
nuke-component-doafter-warning = You start fiddling with wires and knobs in order to disarm the nuke.. This may take a while.
|
||||
|
||||
# Nuke UI
|
||||
nuke-user-interface-title = Nuclear Fission Explosive
|
||||
|
||||
@@ -23,12 +23,10 @@
|
||||
layer:
|
||||
- HalfWallLayer
|
||||
- type: Nuke
|
||||
# ~50 tile radius in open space
|
||||
# close to defaulkt max cap.
|
||||
explosionType: Default
|
||||
maxIntensity: 100
|
||||
intensitySlope: 5
|
||||
totalIntensity: 500000
|
||||
totalIntensity: 5000000
|
||||
diskSlot:
|
||||
name: Disk
|
||||
insertSound:
|
||||
|
||||
Reference in New Issue
Block a user