Agent ID Cards (#7041)

This commit is contained in:
Rane
2022-04-15 17:15:25 -04:00
committed by GitHub
parent 155b7a2f37
commit e85628b709
12 changed files with 267 additions and 12 deletions

View File

@@ -0,0 +1,64 @@
using Content.Shared.Access.Systems;
using Robust.Client.GameObjects;
namespace Content.Client.Access.UI
{
/// <summary>
/// Initializes a <see cref="AgentIDCardWindow"/> and updates it when new server messages are received.
/// </summary>
public sealed class AgentIDCardBoundUserInterface : BoundUserInterface
{
private AgentIDCardWindow? _window;
public AgentIDCardBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_window = new AgentIDCardWindow();
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.OnNameEntered += OnNameChanged;
_window.OnJobEntered += OnJobChanged;
}
private void OnNameChanged(string newName)
{
SendMessage(new AgentIDCardNameChangedMessage(newName));
}
private void OnJobChanged(string newJob)
{
SendMessage(new AgentIDCardJobChangedMessage(newJob));
}
/// <summary>
/// Update the UI state based on server-sent info
/// </summary>
/// <param name="state"></param>
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (_window == null || state is not AgentIDCardBoundUserInterfaceState cast)
return;
_window.SetCurrentName(cast.CurrentName);
_window.SetCurrentJob(cast.CurrentJob);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}
}

View File

@@ -0,0 +1,10 @@
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Loc agent-id-menu-title}">
<BoxContainer Orientation="Vertical" SeparationOverride="4" MinWidth="150">
<Label Name="CurrentName" Text="{Loc 'agent-id-card-current-name'}" />
<LineEdit Name="NameLineEdit" />
<Label Name="CurrentJob" Text="{Loc 'agent-id-card-current-job'}" />
<LineEdit Name="JobLineEdit" />
</BoxContainer>
</DefaultWindow>

View File

@@ -0,0 +1,32 @@
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Access.UI
{
[GenerateTypedNameReferences]
public sealed partial class AgentIDCardWindow : DefaultWindow
{
public event Action<string>? OnNameEntered;
public event Action<string>? OnJobEntered;
public AgentIDCardWindow()
{
RobustXamlLoader.Load(this);
NameLineEdit.OnTextEntered += e => OnNameEntered?.Invoke(e.Text);
JobLineEdit.OnTextEntered += e => OnJobEntered?.Invoke(e.Text);
}
public void SetCurrentName(string name)
{
NameLineEdit.Text = name;
}
public void SetCurrentJob(string job)
{
JobLineEdit.Text = job;
}
}
}

View File

@@ -64,6 +64,7 @@ namespace Content.Client.Entry
"DiseaseSwab",
"FloorTile",
"RandomInsulation",
"AgentIDCard",
"Electrified",
"Electrocution",
"Paper",

View File

@@ -0,0 +1,9 @@
using Content.Shared.Access.Systems;
using Content.Shared.PDA;
namespace Content.Server.Access.Components
{
[RegisterComponent]
public sealed class AgentIDCardComponent : Component
{}
}

View File

@@ -0,0 +1,66 @@
using Content.Shared.Access.Components;
using Content.Server.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.Interaction;
using Content.Server.Popups;
using Robust.Shared.Player;
namespace Content.Server.Access.Systems
{
public sealed class AgentIDCardSystem : SharedAgentIdCardSystem
{
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IdCardSystem _cardSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AgentIDCardComponent, AfterInteractEvent>(OnAfterInteract);
// BUI
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardNameChangedMessage>(OnNameChanged);
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardJobChangedMessage> (OnJobChanged);
}
private void OnAfterInteract(EntityUid uid, AgentIDCardComponent component, AfterInteractEvent args)
{
if (!TryComp<AccessComponent>(args.Target, out var targetAccess) || !TryComp<IdCardComponent>(uid, out var targetIDCard) || args.Target == null)
return;
if (!TryComp<AccessComponent>(uid, out var access) || !TryComp<IdCardComponent>(uid, out var idCard))
return;
var beforeLength = access.Tags.Count;
access.Tags.UnionWith(targetAccess.Tags);
var addedLength = access.Tags.Count - beforeLength;
if (addedLength == 0)
{
_popupSystem.PopupEntity(Loc.GetString("agent-id-no-new", ("card", args.Target)), args.Target.Value, Filter.Pvs(args.User));
return;
}
else if (addedLength == 1)
{
_popupSystem.PopupEntity(Loc.GetString("agent-id-new-1", ("card", args.Target)), args.Target.Value, Filter.Pvs(args.User));
return;
}
_popupSystem.PopupEntity(Loc.GetString("agent-id-new", ("number", addedLength), ("card", args.Target)), args.Target.Value, Filter.Pvs(args.User));
}
private void OnJobChanged(EntityUid uid, AgentIDCardComponent comp, AgentIDCardJobChangedMessage args)
{
if (!TryComp<IdCardComponent>(uid, out var idCard))
return;
_cardSystem.TryChangeJobTitle(uid, args.Job, idCard);
}
private void OnNameChanged(EntityUid uid, AgentIDCardComponent comp, AgentIDCardNameChangedMessage args)
{
if (!TryComp<IdCardComponent>(uid, out var idCard))
return;
_cardSystem.TryChangeFullName(uid, args.Name, idCard);
}
}
}

View File

@@ -1,20 +1,13 @@
using System;
using Robust.Shared.GameObjects;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared.MobState.Components;
using Content.Shared.Damage;
using Content.Shared.Popups;
using Content.Server.Cooldown;
using Content.Server.Inventory;
using Content.Server.Mind.Components;
using Content.Server.Bible.Components;
using Content.Server.Popups;
using Robust.Shared.IoC;
using Robust.Shared.Random;
using Robust.Shared.Audio;
using Robust.Shared.Player;
using Robust.Shared.Localization;
using Robust.Shared.Timing;
@@ -70,7 +63,7 @@ namespace Content.Server.Bible
if (_random.Prob(component.FailChance))
{
var othersFailMessage = Loc.GetString("bible-heal-fail-others", ("user", args.User),("target", args.Target),("bible", uid));
_popupSystem.PopupEntity(othersFailMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));
_popupSystem.PopupEntity(othersFailMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));
var selfFailMessage = Loc.GetString("bible-heal-fail-self", ("target", args.Target),("bible", uid));
_popupSystem.PopupEntity(selfFailMessage, args.User, Filter.Entities(args.User));

View File

@@ -1,15 +1,12 @@
using Content.Shared.Access.Systems;
using Content.Shared.PDA;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Shared.Access.Components
{
// TODO BUI NETWORKING if ever clients can open their own BUI's (id card console, pda), then this data should be
// networked.
[RegisterComponent]
[Friend(typeof(SharedIdCardSystem), typeof(SharedPDASystem))]
[Friend(typeof(SharedIdCardSystem), typeof(SharedPDASystem), typeof(SharedAgentIdCardSystem))]
public sealed class IdCardComponent : Component
{
[DataField("originalOwnerName")]

View File

@@ -0,0 +1,55 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Access.Systems
{
public class SharedAgentIdCardSystem : EntitySystem
{
/// Just for friending for now
}
/// <summary>
/// Key representing which <see cref="BoundUserInterface"/> is currently open.
/// Useful when there are multiple UI for an object. Here it's future-proofing only.
/// </summary>
[Serializable, NetSerializable]
public enum AgentIDCardUiKey
{
Key,
}
/// <summary>
/// Represents an <see cref="AgentIDCardComponent"/> state that can be sent to the client
/// </summary>
[Serializable, NetSerializable]
public sealed class AgentIDCardBoundUserInterfaceState : BoundUserInterfaceState
{
public string CurrentName { get; }
public string CurrentJob { get; }
public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob)
{
CurrentName = currentName;
CurrentJob = currentJob;
}
}
[Serializable, NetSerializable]
public sealed class AgentIDCardNameChangedMessage : BoundUserInterfaceMessage
{
public string Name { get; }
public AgentIDCardNameChangedMessage(string name)
{
Name = name;
}
}
[Serializable, NetSerializable]
public sealed class AgentIDCardJobChangedMessage : BoundUserInterfaceMessage
{
public string Job { get; }
public AgentIDCardJobChangedMessage(string job)
{
Job = job;
}
}
}

View File

@@ -0,0 +1,6 @@
agent-id-no-new = Didn't gain any new accesses from {THE($card)}.
agent-id-new-1 = Gained one new access from {THE($card)}.
agent-id-new = Gained {$number} new accesses from {THE($card)}.
agent-id-card-current-name = Name:
agent-id-card-current-job = Job:
agent-id-menu-title = Agent ID Card

View File

@@ -157,6 +157,15 @@
icon: /Textures/Objects/Tools/emag.rsi/icon.png
price: 8
- type: uplinkListing
id: UplinkAgentIDCard
category: Utility
itemId: AgentIDCard
listingName: Agent ID Card
description: A modified ID card that can copy accesses from other cards and change its name and job title at-will.
icon: Objects/Misc/id_cards.rsi/default.png
price: 3
- type: uplinkListing
id: UplinkHypopen
category: Utility

View File

@@ -377,3 +377,16 @@
- state: idmusician
- type: PresetIdCard
job: Musician
- type: entity
parent: AssistantIDCard
id: AgentIDCard
suffix: Agent
components:
- type: AgentIDCard
- type: ActivatableUI
key: enum.AgentIDCardUiKey.Key
- type: UserInterface
interfaces:
- key: enum.AgentIDCardUiKey.Key
type: AgentIDCardBoundUserInterface