Experimental nukie changes (#9428)

This commit is contained in:
Kara
2022-07-04 23:49:19 -07:00
committed by GitHub
parent 398f05657c
commit 69871ef73a
6 changed files with 122 additions and 30 deletions

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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
{
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)
{
@@ -268,6 +314,7 @@ namespace Content.Server.Nuke
component.EnteredCode = "";
PlaySound(uid, component.AccessDeniedSound, 0, component);
}
break;
}
case NukeStatus.AWAIT_ARM:
@@ -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 {}
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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: