This commit is contained in:
Stxcking 2026-05-10 11:43:47 +00:00 committed by GitHub
commit 1534cdcbc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 311 additions and 0 deletions

View File

@ -0,0 +1,55 @@
using Content.Client.Eui;
using JetBrains.Annotations;
using Robust.Client.Graphics;
using Content.Shared._Goobstation.Silicon.AiEarlyLeave;
namespace Content.Client._Goobstation.Silicon.AiEarlyLeave;
[UsedImplicitly]
public sealed class StationAiEarlyLeaveEui : BaseEui
{
private readonly StationAiEarlyLeaveMenu _menu;
private bool _sentResponse;
public StationAiEarlyLeaveEui()
{
_menu = new StationAiEarlyLeaveMenu();
_menu.DenyButton.OnPressed += _ =>
{
SendResponse(false); // DeltaV
_menu.Close();
};
_menu.ConfirmButton.OnPressed += _ =>
{
SendResponse(true); // DeltaV
_menu.Close();
};
}
// Start of DeltaV Changes
private void SendResponse(bool confirmed)
{
if (_sentResponse)
return;
_sentResponse = true;
SendMessage(new StationAiEarlyLeaveMessage(confirmed));
}
public override void Opened()
{
IoCManager.Resolve<IClyde>().RequestWindowAttention();
_menu.OpenCentered();
}
// End of DeltaV Changes
public override void Closed()
{
base.Closed();
SendResponse(false); // DeltaV
_menu.Close();
}
}

View File

@ -0,0 +1,58 @@
using System.Numerics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client._Goobstation.Silicon.AiEarlyLeave;
public sealed class StationAiEarlyLeaveMenu : DefaultWindow
{
public readonly Button DenyButton;
public readonly Button ConfirmButton;
public StationAiEarlyLeaveMenu()
{
Title = Loc.GetString("station-ai-earlyleave-menu-title");
Contents.AddChild(new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
Children =
{
new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
Children =
{
(new Label()
{
Text = Loc.GetString("station-ai-earlyleave-menu-text")
}),
new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Align = AlignMode.Center,
Children =
{
(ConfirmButton = new Button
{
Text = Loc.GetString("station-ai-earlyleave-menu-confirm")
}),
(new Control()
{
MinSize = new Vector2(20, 0)
}),
(DenyButton = new Button
{
Text = Loc.GetString("station-ai-earlyleave-menu-deny")
})
}
}
}
}
}
});
}
}

View File

@ -0,0 +1,41 @@
using Content.Server.EUI;
using Content.Shared.Eui;
using Robust.Shared.Network;
using Content.Server.Silicons.StationAi;
using Content.Shared._Goobstation.Silicon.AiEarlyLeave;
using Content.Shared.Silicons.StationAi;
namespace Content.Server._Goobstation.Silicon.AiEarlyLeave;
public sealed class StationAiEarlyLeaveEui : BaseEui
{
private readonly Entity<StationAiCoreComponent> _aiCore;
private readonly EntityUid _ai;
private readonly NetUserId _userId;
private readonly StationAiEarlyLeaveSystem _leaveSystem;
public StationAiEarlyLeaveEui(Entity<StationAiCoreComponent> aiCore, EntityUid ai, NetUserId userId, StationAiEarlyLeaveSystem leaveSystem)
{
_aiCore = aiCore;
_ai = ai;
_userId = userId;
_leaveSystem = leaveSystem;
}
public override void HandleMessage(EuiMessageBase msg)
{
base.HandleMessage(msg);
if (msg is not StationAiEarlyLeaveMessage choice ||
!choice.Confirmed)
{
Close();
return;
}
_leaveSystem.EarlyLeave(_aiCore, _ai, _userId);
Close();
}
}

View File

@ -0,0 +1,68 @@
using Content.Shared._Goobstation.Silicon.AiEarlyLeave;
using Content.Shared._Goobstation.Silicon.Components;
using Linguini.Bundle.Errors;
using Content.Server.Chat.Systems;
using Robust.Shared.Player;
using Content.Server.EUI;
using Robust.Shared.Network;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Silicons.StationAi;
namespace Content.Server._Goobstation.Silicon.AiEarlyLeave;
public sealed class StationAiEarlyLeaveSystem : SharedStationAiEarlyLeaveSystem
{
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly ISharedPlayerManager _player = default!;
[Dependency] private readonly EuiManager _euiManager = default!;
[Dependency] private readonly StationJobsSystem _jobs = default!;
[Dependency] private readonly StationSystem _station = default!;
protected override void RequestEarlyLeave(Entity<StationAiCoreComponent> aiCore, EntityUid insertedAi)
{
if (!_player.TryGetSessionByEntity(insertedAi, out var aiSession))
return;
if (aiSession == null)
return;
_euiManager.OpenEui(new StationAiEarlyLeaveEui(aiCore, insertedAi, aiSession.UserId, this), aiSession);
}
public void EarlyLeave(Entity<StationAiCoreComponent> aiCore, EntityUid insertedAi, NetUserId userId)
{
var station = _station.GetOwningStation(insertedAi);
// removes all of player's jobs on all stations
foreach (var uniqueStation in _station.GetStationsSet())
{
if (!TryComp<StationJobsComponent>(uniqueStation, out var stationJobs))
continue;
if (!_jobs.TryGetPlayerJobs(uniqueStation, userId, out var jobs, stationJobs))
continue;
foreach (var job in jobs)
{
_jobs.TryAdjustJobSlot(uniqueStation, job, 1, clamp: true);
}
_jobs.TryRemovePlayerJobs(uniqueStation, userId, stationJobs);
}
if (station is not { })
return;
// Start of DeltaV Changes
var message = Loc.GetString(
"station-ai-earlyleave-announcement",
("character", Name(insertedAi)),
("entity", insertedAi)
);
_chat.DispatchStationAnnouncement(insertedAi, message, Loc.GetString("station-ai-earlyleave-announcement-sender"));
// End of DeltaV Changes
QueueDel(insertedAi);
}
}

View File

@ -0,0 +1,51 @@
using Content.Shared.Verbs;
using Content.Shared._Goobstation.Silicon.Components;
using Content.Shared.Silicons.StationAi;
using Robust.Shared.Containers;
using Robust.Shared.Utility;
namespace Content.Shared._Goobstation.Silicon.AiEarlyLeave;
public abstract partial class SharedStationAiEarlyLeaveSystem : EntitySystem
{
[Dependency] private readonly SharedContainerSystem _containers = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<StationAiEarlyLeaveComponent, GetVerbsEvent<Verb>>(OnGetVerbs);
}
private EntityUid? GetInsertedAI(Entity<StationAiCoreComponent> ent)
{
if (!_containers.TryGetContainer(ent.Owner, StationAiHolderComponent.Container, out var container)
|| container.ContainedEntities.Count != 1)
return null;
return container.ContainedEntities[0];
}
private void OnGetVerbs(Entity<StationAiEarlyLeaveComponent> ent, ref GetVerbsEvent<Verb> args)
{
if (!TryComp<StationAiCoreComponent>(ent.Owner, out var aiCoreComp))
return;
var aiCore = new Entity<StationAiCoreComponent>(ent.Owner, aiCoreComp);
if (GetInsertedAI(aiCore) is { } insertedAi && insertedAi == args.User)
{
args.Verbs.Add(new Verb()
{
Text = Loc.GetString("station-ai-earlyleave-button"),
Act = () => RequestEarlyLeave(aiCore, insertedAi),
Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png")),
});
}
}
protected virtual void RequestEarlyLeave(Entity<StationAiCoreComponent> aiCore, EntityUid insertedAi)
{
}
}

View File

@ -0,0 +1,15 @@
using Content.Shared.Eui;
using Robust.Shared.Serialization;
namespace Content.Shared._Goobstation.Silicon.AiEarlyLeave;
[Serializable, NetSerializable]
public sealed class StationAiEarlyLeaveMessage : EuiMessageBase
{
public readonly bool Confirmed;
public StationAiEarlyLeaveMessage(bool confirmed)
{
Confirmed = confirmed;
}
}

View File

@ -0,0 +1,15 @@
using Content.Shared.Silicons.Bots;
using Robust.Shared.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
namespace Content.Shared._Goobstation.Silicon.Components;
/// <summary>
/// Grants a verb allowing early leave / cryo functionality.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class StationAiEarlyLeaveComponent : Component
{
}

View File

@ -0,0 +1,7 @@
station-ai-earlyleave-button = AI shutdown
station-ai-earlyleave-menu-title = AI Shutdown
station-ai-earlyleave-menu-text = Are you sure? You will be removed from the round and your job slot will be opened.
station-ai-earlyleave-menu-confirm = Confirm
station-ai-earlyleave-menu-deny = Deny
station-ai-earlyleave-announcement = {$character} (Station AI) is shutting down and entering hibernation!
station-ai-earlyleave-announcement-sender = AI Core

View File

@ -275,6 +275,7 @@
batteryRechargeEfficiency: 0 # Setting to zero until the light flickering issue associated with dynamic power loads is fixed
- type: StationAiCore
- type: StationAiVision
- type: StationAiEarlyLeave # Goobstation
- type: InteractionOutline
- type: Sprite
snapCardinals: true