diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml b/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml index 8b68487547f..b558d6114ed 100644 --- a/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml +++ b/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml @@ -3,6 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls" xmlns:at="clr-namespace:Content.Client.Administration.UI.Tabs.AdminTab" + xmlns:cdAdmin="clr-namespace:Content.Client._CD.Admin.UI" Margin="4" MinSize="50 50"> @@ -16,6 +17,8 @@ + + diff --git a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs index acf738129cf..f33d38c66b3 100644 --- a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs +++ b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs @@ -35,6 +35,10 @@ using static Robust.Client.UserInterface.Controls.BoxContainer; using Direction = Robust.Shared.Maths.Direction; +// CD: Records editor imports +using Content.Client._CD.Records.UI; +using Content.Shared._CD.Records; + namespace Content.Client.Preferences.UI { public sealed class HighlightedContainer : PanelContainer @@ -110,6 +114,9 @@ public sealed partial class HumanoidProfileEditor : Control private float _defaultHeight = 1f; + // CD: Record editor + private readonly RecordEditorGui _recordsTab; + public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager, IEntityManager entityManager, IConfigurationManager configurationManager) { @@ -517,6 +524,14 @@ public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IProt #endregion Markings + #region CosmaticRecords + + _recordsTab = new RecordEditorGui(UpdateProfileRecords); + _tabContainer.AddChild(_recordsTab); + _tabContainer.SetTabTitle(_tabContainer.ChildCount - 1, Loc.GetString("humanoid-profile-editor-cd-records-tab")); + + #endregion CosmaticRecords + #region FlavorText if (_configurationManager.GetCVar(CCVars.FlavorText)) @@ -673,6 +688,15 @@ private void UpdateRoleRequirements() } } + // CD: Records editor + private void UpdateProfileRecords(CharacterRecords records) + { + if (Profile is null) + return; + Profile = Profile.WithCDCharacterRecords(records); + IsDirty = true; + } + private void OnFlavorTextChange(string content) { if (Profile is null) @@ -1220,6 +1244,9 @@ public void UpdateControls() UpdateCMarkingsFacialHair(); UpdateHeightControls(); + // CD: Update record editor + _recordsTab.Update(Profile); + _preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable); } diff --git a/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml b/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml new file mode 100644 index 00000000000..9cb31849704 --- /dev/null +++ b/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml.cs b/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml.cs new file mode 100644 index 00000000000..9a868650997 --- /dev/null +++ b/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml.cs @@ -0,0 +1,48 @@ +using Content.Shared._CD.Records; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._CD.Admin.UI; + +[GenerateTypedNameReferences] +public sealed partial class ModifyCharacterRecords : DefaultWindow +{ + public ModifyCharacterRecords() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + foreach (var v in Enum.GetValues()) + { + EntityEntryType.AddItem(v.ToString()); + } + + EntityEntryType.OnItemSelected += args => + { + EntityEntryType.SelectId(args.Id); + UpdateCommands(); + }; + + EntityEdit.OnTextChanged += _ => UpdateCommands(); + EntityEntryIndex.OnTextChanged += _ => UpdateCommands(); + } + + private void UpdateCommands() + { + if (!int.TryParse(EntityEdit.Text, out var uid)) + { + return; + } + + if (!int.TryParse(EntityEntryIndex.Text, out var idx)) + { + return; + } + + var ty = (CharacterRecordType)EntityEntryType.SelectedId; + + PurgeCommand.Command = $"purgecharacterrecords {uid}"; + DelCommand.Command = $"delrecordentry {uid} {ty.ToString()} {idx}"; + } +} diff --git a/Content.Client/_CD/Records/UI/CharacterRecordConsoleBoundUserInterface.cs b/Content.Client/_CD/Records/UI/CharacterRecordConsoleBoundUserInterface.cs new file mode 100644 index 00000000000..4363021df0d --- /dev/null +++ b/Content.Client/_CD/Records/UI/CharacterRecordConsoleBoundUserInterface.cs @@ -0,0 +1,89 @@ +using Content.Shared._CD.Records; +using Content.Shared.CriminalRecords; +using Content.Shared.CriminalRecords.Components; +using Content.Shared.Security; +using Content.Shared.StationRecords; +using JetBrains.Annotations; + +namespace Content.Client._CD.Records.UI; + +[UsedImplicitly] +public sealed class CharacterRecordConsoleBoundUserInterface : BoundUserInterface +{ + [ViewVariables] private CharacterRecordViewer? _window; + + [Dependency] private readonly EntityManager _entMan = default!; + + public CharacterRecordConsoleBoundUserInterface(EntityUid owner, Enum key) + : base(owner, key) + { + } + + protected override void UpdateState(BoundUserInterfaceState baseState) + { + base.UpdateState(baseState); + if (baseState is not CharacterRecordConsoleState state) + return; + + if (_window?.IsSecurity() ?? false) + { + var comp = EntMan.GetComponent(Owner); + _window!.SecurityWantedStatusMaxLength = comp.MaxStringLength; + } + + _window?.UpdateState(state); + } + + protected override void Open() + { + base.Open(); + + _window = new(); + _window.OnClose += Close; + _window.OnKeySelected += (ent, stationRecordKey) => + { + SendMessage(new CharacterRecordConsoleSelectMsg(ent)); + + // If we are a security records console, we also need to inform the criminal records + // system of our state. + if (_window.IsSecurity() && stationRecordKey != null) + { + SendMessage(new SelectStationRecord(stationRecordKey)); + _window.SetSecurityStatusEnabled(true); + } + else + { + // If the user does not have criminal records for some reason, we should not be able + // to set their wanted status + _window.SetSecurityStatusEnabled(false); + } + }; + + _window.OnFiltersChanged += (ty, txt) => + { + if (txt == null) + SendMessage(new CharacterRecordsConsoleFilterMsg(null)); + else + SendMessage(new CharacterRecordsConsoleFilterMsg(new StationRecordsFilter(ty, txt))); + }; + + _window.OnSetSecurityStatus += status => + { + SendMessage(new CriminalRecordChangeStatus(status, null)); + }; + + _window.OnSetWantedStatus += reason => + { + SendMessage(new CriminalRecordChangeStatus(SecurityStatus.Wanted, reason)); + }; + + _window.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + _window?.Close(); + } +} diff --git a/Content.Client/_CD/Records/UI/CharacterRecordViewer.xaml b/Content.Client/_CD/Records/UI/CharacterRecordViewer.xaml new file mode 100644 index 00000000000..38b0640d3e8 --- /dev/null +++ b/Content.Client/_CD/Records/UI/CharacterRecordViewer.xaml @@ -0,0 +1,135 @@ + + + + + + + +