make borgs have job requirements (#3109)

* fix secborg health alert mispredict

* assign jobs to each borg type except generic

* add Job field to BorgTypePrototype

* implement job requirement checking

* add requirement reason to borg switching UI

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas 2025-03-04 11:39:11 +00:00 committed by GitHub
parent b2a1da2568
commit 17d921b234
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 127 additions and 6 deletions

View File

@ -5,7 +5,9 @@ using Content.Shared.Guidebook;
using Content.Shared.Silicons.Borgs;
using Content.Shared.Silicons.Borgs.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.Player; // DeltaV
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; // DeltaV
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
@ -19,7 +21,10 @@ namespace Content.Client.Silicons.Borgs;
[GenerateTypedNameReferences]
public sealed partial class BorgSelectTypeMenu : FancyWindow
{
[Dependency] private readonly IEntityManager _entMan = default!; // DeltaV
[Dependency] private readonly IPlayerManager _player = default!; // DeltaV
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private readonly BorgSwitchableTypeSystem _borgSwitchable; // DeltaV
private BorgTypePrototype? _selectedBorgType;
@ -32,6 +37,7 @@ public sealed partial class BorgSelectTypeMenu : FancyWindow
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_borgSwitchable = _entMan.System<BorgSwitchableTypeSystem>(); // DeltaV
var group = new ButtonGroup();
foreach (var borgType in _prototypeManager.EnumeratePrototypes<BorgTypePrototype>().OrderBy(PrototypeName))
@ -59,7 +65,20 @@ public sealed partial class BorgSelectTypeMenu : FancyWindow
InfoContents.Visible = true;
InfoPlaceholder.Visible = false;
ConfirmTypeButton.Disabled = false;
// Begin DeltaV Changes - borg job requirements
if (_player.LocalEntity is {} uid)
{
var reason = _borgSwitchable.TrySelect(uid, prototype.ID);
ConfirmTypeButton.Disabled = reason != null;
if (reason is {} msg)
{
ConfirmTypeButton.Text = Loc.GetString("role-timer-locked");
var tooltip = new Tooltip();
tooltip.SetMessage(msg);
ConfirmTypeButton.TooltipSupplier = _ => tooltip;
}
}
// End DeltaV Changes
NameLabel.Text = PrototypeName(prototype);
DescriptionLabel.Text = Loc.GetString($"borg-type-{prototype.ID}-desc");

View File

@ -10,7 +10,7 @@ namespace Content.Client.Silicons.Borgs;
/// </summary>
/// <seealso cref="SharedBorgSwitchableTypeSystem"/>
/// <seealso cref="BorgSwitchableTypeComponent"/>
public sealed class BorgSwitchableTypeSystem : SharedBorgSwitchableTypeSystem
public sealed partial class BorgSwitchableTypeSystem : SharedBorgSwitchableTypeSystem // DeltaV - made partial
{
[Dependency] private readonly BorgSystem _borgSystem = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;

View File

@ -0,0 +1,20 @@
using Content.Client.Players.PlayTimeTracking;
using Content.Shared.Roles;
using Robust.Shared.Player;
using Robust.Shared.Utility;
namespace Content.Client.Silicons.Borgs;
/// <summary>
/// Looks up local role bans.
/// </summary>
public sealed partial class BorgSwitchableTypeSystem
{
[Dependency] private readonly JobRequirementsManager _jobRequirements = default!;
protected override FormattedMessage? IsJobAllowed(ICommonSession session, JobPrototype job)
{
_jobRequirements.IsAllowed(job, profile: null, out var msg);
return msg;
}
}

View File

@ -0,0 +1,27 @@
using Content.Server.Administration.Managers;
using Content.Server.Players.PlayTimeTracking;
using Content.Shared.Roles;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Utility;
namespace Content.Server.Silicons.Borgs;
/// <summary>
/// Looks up role bans for players to prevent malf clients bypassing checks.
/// </summary>
public sealed partial class BorgSwitchableTypeSystem
{
[Dependency] private readonly IBanManager _banMan = default!;
[Dependency] private readonly PlayTimeTrackingSystem _playTime = default!;
protected override FormattedMessage? IsJobAllowed(ICommonSession session, JobPrototype job)
{
if (_banMan.GetJobBans(session.UserId) is {} bans && bans.Contains(job.ID))
return new FormattedMessage(); // server doesn't use it
return _playTime.IsAllowed(session, job.ID)
? null
: new FormattedMessage(); // server doesn't use it
}
}

View File

@ -1,6 +1,7 @@
using Content.Shared.Interaction.Components;
using Content.Shared.Inventory;
using Content.Shared.Radio;
using Content.Shared.Roles; // DeltaV
using Content.Shared.Silicons.Borgs.Components;
using Content.Shared.Silicons.Laws; // DeltaV
using Content.Shared.Whitelist;
@ -91,6 +92,13 @@ public sealed partial class BorgTypePrototype : IPrototype
[DataField]
public ProtoId<SiliconLawsetPrototype>? Lawset;
/// <summary>
/// DeltaV: Optional job prototype to tie to this borg type.
/// It will have the requirements applied and rolebans will extend to this bogr type.
/// </summary>
[DataField]
public ProtoId<JobPrototype>? Job;
/// <summary>
/// Additional components to add to the borg entity when this type is selected.
/// </summary>

View File

@ -12,7 +12,7 @@ namespace Content.Shared.Silicons.Borgs;
/// Implements borg type switching.
/// </summary>
/// <seealso cref="BorgSwitchableTypeComponent"/>
public abstract class SharedBorgSwitchableTypeSystem : EntitySystem
public abstract partial class SharedBorgSwitchableTypeSystem : EntitySystem // DeltaV - made partial
{
// TODO: Allow borgs to be reset to default configuration.
@ -74,7 +74,7 @@ public abstract class SharedBorgSwitchableTypeSystem : EntitySystem
if (ent.Comp.SelectedBorgType != null)
return;
if (!Prototypes.HasIndex(args.Prototype))
if (!Prototypes.HasIndex(args.Prototype) || TrySelect(ent, args.Prototype) != null) // DeltaV - check CanSelect
return;
SelectBorgModule(ent, args.Prototype);

View File

@ -0,0 +1,34 @@
using Content.Shared.Roles;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.Silicons.Borgs;
/// <summary>
/// Handles checking job requirements and role bans for borg types.
/// </summary>
public abstract partial class SharedBorgSwitchableTypeSystem
{
/// <summary>
/// Checks requirements for selecting a borg type.
/// </summary>
/// <returns>Null if successful, an error message if not.</returns>
public FormattedMessage? TrySelect(EntityUid uid, ProtoId<BorgTypePrototype> id)
{
var proto = Prototypes.Index(id);
if (proto.Job is not {} jobId)
return null; // nothing to check
// using an action requires a session so this should never fail
var session = Comp<ActorComponent>(uid).PlayerSession;
return IsJobAllowed(session, Prototypes.Index(jobId));
}
/// <summary>
/// Return null for success, non-null for failure.
/// Server does not return an actual message, client does.
/// Client and server have different implementations because it's not just in shared.
/// </summary>
protected abstract FormattedMessage? IsJobAllowed(ICommonSession session, JobPrototype job);
}

View File

@ -19,6 +19,7 @@
- BorgModuleSecurityBastion
lawset: SiliconPolice
job: SecurityOfficer
addComponents:
- type: FlashImmunity
@ -29,6 +30,12 @@
0: Alive
80: Critical # -20 to Crit Threshold
200: Dead
stateAlertDict:
Alive: BorgHealth
Critical: BorgCrit
Dead: BorgDead
showOverlays: false
allowRevives: true
- type: Fiber # red plasteel fibers
fiberMaterial: fibers-plasteel
fiberColor: fibers-red

View File

@ -49,7 +49,8 @@
- BorgModuleRCD
- BorgModuleCable
lawset: Engineer # DeltaV: Custom lawset
lawset: Engineer # DeltaV - Custom lawset
job: StationEngineer # DeltaV - borg job requirements
addComponents: # DeltaV - orange plasteel fibers
- type: Fiber
fiberMaterial: fibers-plasteel
@ -90,6 +91,7 @@
- BorgModuleMining
- BorgModuleAppraisal
job: SalvageSpecialist # DeltaV - borg job requirements
addComponents: # DeltaV - brown plasteel fibers
- type: Fiber
fiberMaterial: fibers-plasteel
@ -130,7 +132,8 @@
- BorgModuleLightReplacer
- BorgModuleCleaning
lawset: Janitor # DeltaV: Custom lawset
lawset: Janitor # DeltaV - Custom lawset
job: Janitor # DeltaV - borg job requirements
addComponents: # DeltaV - purple plasteel fibers
- type: Fiber
fiberMaterial: fibers-plasteel
@ -176,6 +179,7 @@
- Medical
lawset: Medical # DeltaV: Custom lawset
job: MedicalDoctor # DeltaV - borg job requirements
addComponents:
- type: SolutionScanner
@ -235,6 +239,8 @@
- Science
- Service
job: Bartender # DeltaV - borg job requirements
# Visual
inventoryTemplateId: borgTall
spriteBodyState: service