[Feat] War crime console (#144)
* ADD: Icons, New component. Надо будет рефакторнуть худы в одну систему * Some govno ebanoe * ui * Some govno * UI and UI lol * Dermo again * ы * Добавлена система консоли. Надо добавить манипуляцию с рекордами и сохранение крим. записей на сервер. Я пометил в туду * Added functional for Criminal Records UI * Дропаю это говно * Рабочая версия крим консоли * Fuull functional * Added radio * Arrest info feature * improve ui * another names * New texturem Sprite viewer * fix small names * Added login menu * Final fix. * ох * Убрал логгеры * fix Comments and Access to proto * moved dummy code, removed qustyions * added disposer() when window was close * Small fixes * Removed comments. Added DNA check for CriminalityHud * Small lol --------- Co-authored-by: DocNITE <docnite0530@gmail.com>
@@ -1,10 +1,13 @@
|
|||||||
|
using Content.Client.White.EntityCrimeRecords;
|
||||||
using Content.Shared.Access.Components;
|
using Content.Shared.Access.Components;
|
||||||
using Content.Shared.Access.Systems;
|
using Content.Shared.Access.Systems;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Mindshield.Components;
|
using Content.Shared.Mindshield.Components;
|
||||||
using Content.Shared.Overlays;
|
using Content.Shared.Overlays;
|
||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
using Content.Shared.StatusIcon;
|
using Content.Shared.StatusIcon;
|
||||||
using Content.Shared.StatusIcon.Components;
|
using Content.Shared.StatusIcon.Components;
|
||||||
|
using Content.Shared.White.CriminalRecords;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Client.Overlays;
|
namespace Content.Client.Overlays;
|
||||||
@@ -13,6 +16,11 @@ public sealed class ShowSecurityIconsSystem : EquipmentHudSystem<ShowSecurityIco
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeMan = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeMan = default!;
|
||||||
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
|
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
|
||||||
|
// WD EDIT START
|
||||||
|
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||||
|
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||||
|
[Dependency] private readonly ShowCrimeRecordsSystem _parentSystem = default!;
|
||||||
|
// WD EDIT END
|
||||||
|
|
||||||
[ValidatePrototypeId<StatusIconPrototype>]
|
[ValidatePrototypeId<StatusIconPrototype>]
|
||||||
private const string JobIconForNoId = "JobIconNoId";
|
private const string JobIconForNoId = "JobIconNoId";
|
||||||
@@ -74,8 +82,82 @@ public sealed class ShowSecurityIconsSystem : EquipmentHudSystem<ShowSecurityIco
|
|||||||
result.Add(icon);
|
result.Add(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add arrest icons here, WYCI.
|
// WD EDIT START
|
||||||
|
if (!GetRecord(uid, out var type))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
var protoId = type switch
|
||||||
|
{
|
||||||
|
EnumCriminalRecordType.Discharged => "CriminalRecordIconDischarged",
|
||||||
|
EnumCriminalRecordType.Incarcerated => "CriminalRecordIconIncarcerated",
|
||||||
|
EnumCriminalRecordType.Parolled => "CriminalRecordIconParolled",
|
||||||
|
EnumCriminalRecordType.Suspected => "CriminalRecordIconSuspected",
|
||||||
|
EnumCriminalRecordType.Wanted => "CriminalRecordIconWanted",
|
||||||
|
_ => "CriminalRecordIconReleased"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_prototypeMan.TryIndex<StatusIconPrototype>(protoId, out var recordIcon))
|
||||||
|
result.Add(recordIcon);
|
||||||
|
// WD EDIT END
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WD EDIT START
|
||||||
|
private bool GetRecord(EntityUid uid, out EnumCriminalRecordType type)
|
||||||
|
{
|
||||||
|
if (!_entManager.TryGetComponent(uid, out MetaDataComponent? meta))
|
||||||
|
{
|
||||||
|
type = EnumCriminalRecordType.Released;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverList = _entManager.EntityQuery<CriminalRecordsServerComponent>();
|
||||||
|
foreach (var server in serverList)
|
||||||
|
{
|
||||||
|
// if all good - check avaible records
|
||||||
|
foreach (var (key, info) in server.Cache)
|
||||||
|
{
|
||||||
|
// Check id
|
||||||
|
if (_inventorySystem.TryGetSlotEntity(uid, "id", out var idUid))
|
||||||
|
{
|
||||||
|
// PDA
|
||||||
|
if (_entManager.TryGetComponent(idUid, out PdaComponent? pda) &&
|
||||||
|
_entManager.TryGetComponent(pda.ContainedId, out IdCardComponent? idCard))
|
||||||
|
{
|
||||||
|
if (idCard.FullName == info.StationRecord.Name &&
|
||||||
|
idCard.JobTitle == info.StationRecord.JobTitle)
|
||||||
|
{
|
||||||
|
type = info.CriminalType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ID Card
|
||||||
|
if (_entManager.TryGetComponent(idUid, out IdCardComponent? id))
|
||||||
|
{
|
||||||
|
idCard = id;
|
||||||
|
if (idCard.FullName == info.StationRecord.Name &&
|
||||||
|
idCard.JobTitle == info.StationRecord.JobTitle)
|
||||||
|
{
|
||||||
|
type = info.CriminalType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check DNA (Dirty Nanotrasen tehnology lol)
|
||||||
|
// And yeah, he can't check - is pulled mask or not
|
||||||
|
// it's only Content.Server logic, idk hot it impl to Content.Client
|
||||||
|
if (_parentSystem.CanIdentityName(uid) != meta.EntityName)
|
||||||
|
continue;
|
||||||
|
if (meta.EntityName != info.StationRecord.Name)
|
||||||
|
continue;
|
||||||
|
type = info.CriminalType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type = EnumCriminalRecordType.Released;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// WD EDIT END
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
<controls:RecordCard xmlns="https://spacestation14.io"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||||
|
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.White.CriminalRecords.UI.Controls"
|
||||||
|
x:Class="Content.Client.White.CriminalRecords.UI.Controls.RecordCard">
|
||||||
|
|
||||||
|
<BoxContainer Name="MainContainer" Orientation="Vertical" Margin="10 10 10 10">
|
||||||
|
<!-- Header line -->
|
||||||
|
<PanelContainer
|
||||||
|
Name="SideLineElement"
|
||||||
|
Access="Public"
|
||||||
|
StyleClasses="PDABackground"
|
||||||
|
MinHeight="25"
|
||||||
|
VerticalExpand="False"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Margin="0 0 0 -5"/>
|
||||||
|
<!-- Header info -->
|
||||||
|
<PanelContainer VerticalExpand="True" HorizontalExpand="True" >
|
||||||
|
<PanelContainer.PanelOverride>
|
||||||
|
<gfx:StyleBoxFlat BackgroundColor="#1e1c29" />
|
||||||
|
</PanelContainer.PanelOverride>
|
||||||
|
<BoxContainer Orientation="Vertical"
|
||||||
|
VerticalExpand="True"
|
||||||
|
Margin="5">
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||||
|
<SpriteView Name="ViewIcon"
|
||||||
|
Access="Public"
|
||||||
|
Scale="2 2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"/>
|
||||||
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center" Margin="10 0 0 0">
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<Label Access="Public" Name="CharacterNameLabel" Text="empty-element" StyleClasses="LabelKeyText" HorizontalExpand="True"/>
|
||||||
|
<TextureRect Access="Public" Name="JobIcon" TextureScale="3 3" VerticalAlignment="Center" HorizontalAlignment="Left"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 5 0 5"/>
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<!-- <RichTextLabel Access="Public" Name="StatusLabel" HorizontalAlignment="Left" StyleClasses="LabelSubText" HorizontalExpand="True"/> -->
|
||||||
|
<OptionButton Access="Public" Name="StatusOption" MinWidth="120"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
|
||||||
|
<!-- Main Info -->
|
||||||
|
<Control MinHeight="5"></Control>
|
||||||
|
<RichTextLabel Access="Public" Name="DetailLabel" HorizontalExpand="True" StyleClasses="LabelSubText" Margin="10 0 0 0"></RichTextLabel>
|
||||||
|
<Control MinHeight="5"></Control>
|
||||||
|
<BoxContainer Orientation="Vertical" Margin="10 0 0 0">
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||||
|
<PanelContainer VerticalExpand="True" HorizontalExpand="True">
|
||||||
|
<Label Text="{Loc 'criminal-detail-info'}" HorizontalAlignment="Left"/>
|
||||||
|
<TextureButton Access="Public" Name="EditReason"
|
||||||
|
TexturePath="/Textures/Interface/pencil.png"
|
||||||
|
HorizontalAlignment="Right"></TextureButton>
|
||||||
|
</PanelContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 0 0 10"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<!-- Reason info -->
|
||||||
|
<RichTextLabel Visible="True" Access="Public" Name="ReasonWritten" HorizontalExpand="True" VerticalExpand="True"
|
||||||
|
MinHeight="100" Margin="10 0 0 0"/>
|
||||||
|
<PanelContainer Visible="False" Access="Public" Name="InputContainer"
|
||||||
|
StyleClasses="TransparentBorderedWindowPanel" MinHeight="100" Margin="10 0 0 0"
|
||||||
|
VerticalAlignment="Stretch" VerticalExpand="True" HorizontalExpand="True">
|
||||||
|
<TextEdit Name="Input" Access="Public" VerticalExpand="True" HorizontalExpand="True" />
|
||||||
|
</PanelContainer>
|
||||||
|
<BoxContainer Orientation="Vertical" Margin="10 0 0 0">
|
||||||
|
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 0 0 10"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</PanelContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</controls:RecordCard>
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
using Content.Shared.StationRecords;
|
||||||
|
using Content.Shared.White.CriminalRecords;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Input;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.White.CriminalRecords.UI.Controls;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences, Virtual]
|
||||||
|
public partial class RecordCard : Control
|
||||||
|
{
|
||||||
|
private FormattedMessage _description = new FormattedMessage();
|
||||||
|
public bool _canDoEvent = false;
|
||||||
|
|
||||||
|
public Action<string>? OnTextBindDown;
|
||||||
|
|
||||||
|
public RecordCard()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
|
StatusOption.AddItem(Loc.GetString("criminal-status-released"), (int)EnumCriminalRecordType.Released);
|
||||||
|
StatusOption.AddItem(Loc.GetString("criminal-status-discharged"), (int)EnumCriminalRecordType.Discharged);
|
||||||
|
StatusOption.AddItem(Loc.GetString("criminal-status-parolled"), (int)EnumCriminalRecordType.Parolled);
|
||||||
|
StatusOption.AddItem(Loc.GetString("criminal-status-suspected"), (int)EnumCriminalRecordType.Suspected);
|
||||||
|
StatusOption.AddItem(Loc.GetString("criminal-status-wanted"), (int)EnumCriminalRecordType.Wanted);
|
||||||
|
StatusOption.AddItem(Loc.GetString("criminal-status-incarcerated"), (int)EnumCriminalRecordType.Incarcerated);
|
||||||
|
|
||||||
|
Input.OnKeyBindDown += args =>
|
||||||
|
{
|
||||||
|
if (args.Function == EngineKeyFunctions.TextSubmit)
|
||||||
|
{
|
||||||
|
UpdateReasonController();
|
||||||
|
args.Handle();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EditReason.OnPressed += args =>
|
||||||
|
{
|
||||||
|
UpdateReasonController();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InitializeStatusOption(StationRecordKey key, Dictionary<StationRecordKey, CriminalRecordInfo> cache)
|
||||||
|
{
|
||||||
|
if (cache != null)
|
||||||
|
{
|
||||||
|
foreach (var (kkey, info) in cache)
|
||||||
|
{
|
||||||
|
if (kkey.Id == key.Id)
|
||||||
|
{
|
||||||
|
StatusOption.SelectId((int) info.CriminalType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateReasonController()
|
||||||
|
{
|
||||||
|
if (ReasonWritten.Visible)
|
||||||
|
{
|
||||||
|
var text = ReasonWritten.GetMessage();
|
||||||
|
ReasonWritten.SetMessage("");
|
||||||
|
ReasonWritten.Visible = false;
|
||||||
|
if (text != null)
|
||||||
|
{
|
||||||
|
Input.CursorPosition = new TextEdit.CursorPos();
|
||||||
|
Input.InsertAtCursor(text);
|
||||||
|
}
|
||||||
|
InputContainer.Visible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var text = Rope.Collapse(Input.TextRope);
|
||||||
|
OnTextBindDown?.Invoke(text);
|
||||||
|
Input.TextRope = Rope.Leaf.Empty;
|
||||||
|
Input.CursorPosition = new TextEdit.CursorPos(0, TextEdit.LineBreakBias.Top);
|
||||||
|
// close input and open label
|
||||||
|
InputContainer.Visible = false;
|
||||||
|
// for label
|
||||||
|
ReasonWritten.SetMessage(text);
|
||||||
|
ReasonWritten.Visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- close.svg.192dpi -->
|
||||||
|
<controls:RecordIconButton xmlns="https://spacestation14.io"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.White.CriminalRecords.UI.Controls"
|
||||||
|
x:Class="Content.Client.White.CriminalRecords.UI.Controls.RecordIconButton">
|
||||||
|
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<Button
|
||||||
|
Name="Controller"
|
||||||
|
Access="Public"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="False"
|
||||||
|
ToolTip="foobar"
|
||||||
|
TooltipDelay="0.25">
|
||||||
|
<BoxContainer Orientation="Horizontal" >
|
||||||
|
<TextureRect Access="Public" Name="LIcon"
|
||||||
|
MaxWidth="24"
|
||||||
|
MaxHeight="24"
|
||||||
|
VerticalAlignment="Center" HorizontalAlignment="Left" Stretch="KeepAspectCentered" />
|
||||||
|
<RichTextLabel Access="Public"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Name="LLabel"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Left"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</Button>
|
||||||
|
</BoxContainer>
|
||||||
|
</controls:RecordIconButton>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.ResourceManagement;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Client.Utility;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.White.CriminalRecords.UI.Controls;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences, Virtual]
|
||||||
|
public partial class RecordIconButton : Control
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||||
|
|
||||||
|
public string Icon
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var path = new ResPath(value); // /Textures/Interface/VerbIcons/close.svg.192dpi.png
|
||||||
|
var specifier = new SpriteSpecifier.Texture(path);
|
||||||
|
LIcon.Texture = specifier.Frame0();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Label
|
||||||
|
{
|
||||||
|
set => LLabel.SetMessage(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordIconButton()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<controls:RecordItem xmlns="https://spacestation14.io"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.White.CriminalRecords.UI.Controls"
|
||||||
|
x:Class="Content.Client.White.CriminalRecords.UI.Controls.RecordItem">
|
||||||
|
|
||||||
|
<BoxContainer MaxHeight="25" Orientation="Horizontal">
|
||||||
|
<PanelContainer
|
||||||
|
Name="SideLineElement"
|
||||||
|
Access="Public"
|
||||||
|
StyleClasses="PDABackground"
|
||||||
|
MaxWidth="10"
|
||||||
|
VerticalExpand="False"
|
||||||
|
HorizontalExpand="False"
|
||||||
|
Margin="0 0 -5 0"/>
|
||||||
|
<Button
|
||||||
|
Name="ButtonElement"
|
||||||
|
Access="Public"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="False"
|
||||||
|
ToolTip="foobar"
|
||||||
|
TooltipDelay="0.25">
|
||||||
|
<BoxContainer Orientation="Horizontal" Margin="0">
|
||||||
|
<RichTextLabel Access="Public"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Name="NameLabel"
|
||||||
|
StyleClasses="LabelSubText"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</Button>
|
||||||
|
</BoxContainer>
|
||||||
|
</controls:RecordItem>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
|
||||||
|
namespace Content.Client.White.CriminalRecords.UI.Controls;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences, Virtual]
|
||||||
|
public partial class RecordItem : Control
|
||||||
|
{
|
||||||
|
public RecordItem()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using Content.Shared.Containers.ItemSlots;
|
||||||
|
using Content.Shared.StationRecords;
|
||||||
|
using Content.Shared.White.CriminalRecords;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.Input;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.White.CriminalRecords.UI;
|
||||||
|
|
||||||
|
public sealed class CriminalRecordsBoundUserInterface : BoundUserInterface
|
||||||
|
{
|
||||||
|
private CriminalRecordsWindow? _window = default!;
|
||||||
|
|
||||||
|
public CriminalRecordsBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||||
|
{}
|
||||||
|
|
||||||
|
protected override void Open()
|
||||||
|
{
|
||||||
|
base.Open();
|
||||||
|
|
||||||
|
_window = new();
|
||||||
|
_window.OnKeySelected += OnKeySelected;
|
||||||
|
_window.OnStatusSelected += OnStatusSelected;
|
||||||
|
_window.OnTextBindDown += OnTextEntered;
|
||||||
|
_window.LogOutButton.Controller.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
SendMessage(new ItemSlotButtonPressedEvent(CriminalRecordsConsoleComponent.IdSlotId));
|
||||||
|
};
|
||||||
|
_window.LogInButton.Controller.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
SendMessage(new ItemSlotButtonPressedEvent(CriminalRecordsConsoleComponent.IdSlotId));
|
||||||
|
};
|
||||||
|
_window.OnClose += Close;
|
||||||
|
|
||||||
|
_window.OpenCentered();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnKeySelected(StationRecordKey key)
|
||||||
|
{
|
||||||
|
SendMessage(new SelectCriminalRecord(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusSelected(StationRecordKey key, CriminalRecordInfo status)
|
||||||
|
{
|
||||||
|
SendMessage(new SelectCriminalStatus(key, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTextEntered(StationRecordKey key, string text)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
SendMessage(new SelectCriminalReason(key, text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateState(BoundUserInterfaceState state)
|
||||||
|
{
|
||||||
|
base.UpdateState(state);
|
||||||
|
|
||||||
|
if (state is not CriminalRecordsConsoleBuiState cast)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_window?.UpdateState(cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
|
||||||
|
_window?.Close();
|
||||||
|
_window?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<DefaultWindow xmlns="https://spacestation14.io"
|
||||||
|
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||||
|
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.White.CriminalRecords.UI.Controls"
|
||||||
|
xmlns:uicontrols="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
|
Title="{Loc 'criminal-console-name'}"
|
||||||
|
MinSize="625 500"
|
||||||
|
Resizable="False">
|
||||||
|
<BoxContainer Access="Public" Name="NonAccessContent" Orientation="Vertical" VerticalAlignment="Center" VerticalExpand="True" HorizontalExpand="True">
|
||||||
|
<BoxContainer Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||||
|
<RichTextLabel Access="Public" HorizontalAlignment="Center" Name="LoginHint" HorizontalExpand="True" VerticalExpand="True"
|
||||||
|
MaxWidth="400" Margin="10 0 0 0"/>
|
||||||
|
<controls:RecordIconButton
|
||||||
|
Name="LogInButton"
|
||||||
|
Access="Public"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Icon="/Textures/Interface/VerbIcons/close.svg.192dpi.png"
|
||||||
|
Label="{Loc 'criminal-login-in'}"
|
||||||
|
Margin="10 0 10 0">
|
||||||
|
</controls:RecordIconButton>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Access="Public" Name="MainContent" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
|
||||||
|
<uicontrols:StripeBack HasBottomEdge="True" HasMargins="False" HorizontalExpand="True">
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<RichTextLabel Access="Public"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Name="UserLabel"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Margin="10 0 10 0"/>
|
||||||
|
<controls:RecordIconButton
|
||||||
|
Name="LogOutButton"
|
||||||
|
Access="Public"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Icon="/Textures/Interface/VerbIcons/close.svg.192dpi.png"
|
||||||
|
Label="{Loc 'criminal-login-out'}"
|
||||||
|
Margin="10 0 10 0">
|
||||||
|
</controls:RecordIconButton>
|
||||||
|
</BoxContainer>
|
||||||
|
</uicontrols:StripeBack>
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" VerticalExpand="True">
|
||||||
|
<!-- Persons list (chars) -->
|
||||||
|
<BoxContainer Orientation="Vertical"
|
||||||
|
VerticalExpand="True"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
SizeFlagsStretchRatio="2"
|
||||||
|
Margin="10 0 10 10"
|
||||||
|
MinWidth="175"
|
||||||
|
MaxWidth="175">
|
||||||
|
<Label Text="{Loc 'criminal-console-list'}" HorizontalAlignment="Center"/>
|
||||||
|
<customControls:HSeparator StyleClasses="LowDivider" Margin="0 0 0 10"/>
|
||||||
|
<PanelContainer VerticalExpand="True">
|
||||||
|
<PanelContainer.PanelOverride>
|
||||||
|
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
|
||||||
|
</PanelContainer.PanelOverride>
|
||||||
|
<ScrollContainer
|
||||||
|
HScrollEnabled="False"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="True">
|
||||||
|
<BoxContainer
|
||||||
|
Name="RecordsListContainer"
|
||||||
|
Access="Public"
|
||||||
|
Orientation="Vertical"
|
||||||
|
VerticalExpand="True">
|
||||||
|
</BoxContainer>
|
||||||
|
</ScrollContainer>
|
||||||
|
</PanelContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
<!-- Character info -->
|
||||||
|
<BoxContainer Orientation="Vertical"
|
||||||
|
VerticalExpand="True"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
SizeFlagsStretchRatio="3"
|
||||||
|
Margin="0 0 10 10">
|
||||||
|
<PanelContainer VerticalExpand="True" MinSize="0 200">
|
||||||
|
<PanelContainer.PanelOverride>
|
||||||
|
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
|
||||||
|
</PanelContainer.PanelOverride>
|
||||||
|
<ScrollContainer
|
||||||
|
HScrollEnabled="False"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
SizeFlagsStretchRatio="2"
|
||||||
|
VerticalExpand="True">
|
||||||
|
<BoxContainer
|
||||||
|
Name="RecordCardContainer"
|
||||||
|
Access="Public"
|
||||||
|
MinSize="100 256"
|
||||||
|
Orientation="Vertical"
|
||||||
|
SizeFlagsStretchRatio="2"
|
||||||
|
VerticalExpand="True">
|
||||||
|
</BoxContainer>
|
||||||
|
</ScrollContainer>
|
||||||
|
</PanelContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</DefaultWindow>
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Client.Humanoid;
|
||||||
|
using Content.Client.Inventory;
|
||||||
|
using Content.Client.White.CriminalRecords.UI.Controls;
|
||||||
|
using Content.Shared.Access.Systems;
|
||||||
|
using Content.Shared.CrewManifest;
|
||||||
|
using Content.Shared.GameTicking;
|
||||||
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
|
using Content.Shared.Preferences;
|
||||||
|
using Content.Shared.Radio.Components;
|
||||||
|
using Content.Shared.Roles;
|
||||||
|
using Content.Shared.StationRecords;
|
||||||
|
using Content.Shared.White.CriminalRecords;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.ResourceManagement;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Client.Utility;
|
||||||
|
using Robust.Shared.Console;
|
||||||
|
using Robust.Shared.Input;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.White.CriminalRecords.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class CriminalRecordsWindow : DefaultWindow
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
|
public Action<StationRecordKey>? OnKeySelected;
|
||||||
|
public Action<StationRecordKey, string>? OnTextBindDown;
|
||||||
|
public Action<StationRecordKey, CriminalRecordInfo>? OnStatusSelected;
|
||||||
|
|
||||||
|
public CriminalRecordsWindow() : base()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateState(CriminalRecordsConsoleBuiState state)
|
||||||
|
{
|
||||||
|
// Check access AllAccess Security
|
||||||
|
var jobs = _prototypeManager.EnumeratePrototypes<JobPrototype>();
|
||||||
|
var canAccess = state.IsAllowed;
|
||||||
|
// Check if exists card or not
|
||||||
|
if (state.ContainedId == null || !canAccess)
|
||||||
|
{
|
||||||
|
var messageHint = new FormattedMessage();
|
||||||
|
messageHint.AddMarkup(Loc.GetString("criminal-login-hint", ("name", Loc.GetString("criminal-login-in"))));
|
||||||
|
messageHint.AddMarkup("\n\n");
|
||||||
|
messageHint.AddMarkup(Loc.GetString("criminal-login-warn"));
|
||||||
|
LoginHint.SetMessage(messageHint);
|
||||||
|
MainContent.Visible = false;
|
||||||
|
NonAccessContent.Visible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainContent.Visible = true;
|
||||||
|
NonAccessContent.Visible = false;
|
||||||
|
|
||||||
|
// Init header panel
|
||||||
|
UserLabel.SetMessage(Loc.GetString("criminal-login-info",
|
||||||
|
("user", (state.ContainedId.FullName ?? string.Empty) + ", " +
|
||||||
|
(state.ContainedId.JobTitle ?? string.Empty) )));
|
||||||
|
|
||||||
|
// Make crew list
|
||||||
|
Populate(state, state.RecordListing);
|
||||||
|
|
||||||
|
// Make card
|
||||||
|
if (state is { SelectedKey: not null, Record: not null })
|
||||||
|
{
|
||||||
|
CreateRecordCard(state, state.SelectedKey.Value, state.Record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Populate(CriminalRecordsConsoleBuiState State, Dictionary<StationRecordKey, string>? RecordListing)
|
||||||
|
{
|
||||||
|
if (RecordListing == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// clear govno from list
|
||||||
|
RecordsListContainer.RemoveAllChildren();
|
||||||
|
|
||||||
|
foreach (var (recordKey, name) in RecordListing)
|
||||||
|
{
|
||||||
|
var element = CreateRecordItem(State, recordKey, name);
|
||||||
|
element.ButtonElement.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
OnKeySelected?.Invoke(recordKey);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CriminalRecordInfo? GetRecord(StationRecordKey Key, Dictionary<StationRecordKey, CriminalRecordInfo> Cache)
|
||||||
|
{
|
||||||
|
foreach (var (key, info) in Cache)
|
||||||
|
{
|
||||||
|
if (Key.Id == key.Id)
|
||||||
|
{
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color GetColor(StationRecordKey Key, Dictionary<StationRecordKey, CriminalRecordInfo> Cache)
|
||||||
|
{
|
||||||
|
var info = GetRecord(Key, Cache);
|
||||||
|
if (info == null)
|
||||||
|
return new Color(0,0,0);
|
||||||
|
|
||||||
|
switch (info.CriminalType)
|
||||||
|
{
|
||||||
|
case EnumCriminalRecordType.Released:
|
||||||
|
return new Color(14, 106, 254);
|
||||||
|
case EnumCriminalRecordType.Discharged:
|
||||||
|
return new Color(14,106,254);
|
||||||
|
case EnumCriminalRecordType.Parolled:
|
||||||
|
return new Color(151,196,66);
|
||||||
|
case EnumCriminalRecordType.Suspected:
|
||||||
|
return new Color(217,126,35);
|
||||||
|
case EnumCriminalRecordType.Wanted:
|
||||||
|
return new Color(190, 50 ,50);
|
||||||
|
case EnumCriminalRecordType.Incarcerated:
|
||||||
|
return new Color(196,164,114);
|
||||||
|
}
|
||||||
|
return new Color(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecordItem CreateRecordItem(CriminalRecordsConsoleBuiState State, StationRecordKey Key, string Name)
|
||||||
|
{
|
||||||
|
var record = new RecordItem();
|
||||||
|
record.VerticalAlignment = Control.VAlignment.Top;
|
||||||
|
if (State.Cache != null && GetRecord(Key, State.Cache) != null)
|
||||||
|
{
|
||||||
|
record.SideLineElement.ModulateSelfOverride = GetColor(Key, State.Cache);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
record.SideLineElement.ModulateSelfOverride = new Color(0, 0 ,0);
|
||||||
|
}
|
||||||
|
record.NameLabel.SetMessage(Name);
|
||||||
|
// append element into list
|
||||||
|
RecordsListContainer.AddChild(record);
|
||||||
|
// result
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecordCard CreateRecordCard(CriminalRecordsConsoleBuiState State, StationRecordKey Key, GeneralStationRecord Record)
|
||||||
|
{
|
||||||
|
var card = new RecordCard();
|
||||||
|
// set color
|
||||||
|
if (State.Cache != null && GetRecord(Key, State.Cache) != null)
|
||||||
|
{
|
||||||
|
card.SideLineElement.ModulateSelfOverride = GetColor(Key, State.Cache);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
card.SideLineElement.ModulateSelfOverride = new Color(0, 0 ,0);
|
||||||
|
}
|
||||||
|
// name
|
||||||
|
card.CharacterNameLabel.Text = Record.Name + ", " + Record.JobTitle;
|
||||||
|
// job icon
|
||||||
|
var path = new ResPath("/Textures/Interface/Misc/job_icons.rsi");
|
||||||
|
_resourceCache.TryGetResource(path, out RSIResource? rsi);
|
||||||
|
|
||||||
|
if (rsi != null)
|
||||||
|
{
|
||||||
|
if (rsi.RSI.TryGetState(Record.JobIcon, out _))
|
||||||
|
{
|
||||||
|
var specifier = new SpriteSpecifier.Rsi(path, Record.JobIcon);
|
||||||
|
card.JobIcon.Texture = specifier.Frame0();
|
||||||
|
}
|
||||||
|
else if (rsi.RSI.TryGetState("Unknown", out _))
|
||||||
|
{
|
||||||
|
var specifier = new SpriteSpecifier.Rsi(path, "Unknown");
|
||||||
|
card.JobIcon.Texture = specifier.Frame0();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// status icon
|
||||||
|
card.ViewIcon.SetEntity(CreateCharacterDummy(Record));
|
||||||
|
// info
|
||||||
|
var dnaInfo = "";
|
||||||
|
if (Record.DNA != null)
|
||||||
|
dnaInfo = Record.DNA;
|
||||||
|
|
||||||
|
var fingerprintInfo = "";
|
||||||
|
if (Record.Fingerprint != null)
|
||||||
|
fingerprintInfo = Record.Fingerprint;
|
||||||
|
|
||||||
|
var message = new FormattedMessage();
|
||||||
|
message.AddMarkup(Loc.GetString("criminal-dna-name"));
|
||||||
|
message.AddMarkup("\n");
|
||||||
|
message.AddMarkup(Loc.GetString("criminal-dna-desc",
|
||||||
|
("color", new Color(171,129,222).ToHex()), ("info", dnaInfo) ));
|
||||||
|
message.AddMarkup("\n");
|
||||||
|
message.AddMarkup(Loc.GetString("criminal-fingerprint-name"));
|
||||||
|
message.AddMarkup("\n");
|
||||||
|
message.AddMarkup(Loc.GetString("criminal-fingerprint-desc",
|
||||||
|
("color", new Color(171,129,222).ToHex()), ("info", fingerprintInfo) ));
|
||||||
|
card.DetailLabel.SetMessage(message);
|
||||||
|
// clear and aapend
|
||||||
|
RecordCardContainer.DisposeAllChildren();
|
||||||
|
RecordCardContainer.AddChild(card);
|
||||||
|
// some shit (like change status)
|
||||||
|
card.StatusOption.OnItemSelected += eventArgs =>
|
||||||
|
{
|
||||||
|
if (!card._canDoEvent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var record = new CriminalRecordInfo(Record, (EnumCriminalRecordType)eventArgs.Id, card.ReasonWritten.GetMessage() ?? string.Empty);
|
||||||
|
OnStatusSelected?.Invoke(Key, record);
|
||||||
|
card.StatusOption.SelectId(eventArgs.Id);
|
||||||
|
};
|
||||||
|
// init status option
|
||||||
|
if (State.Cache != null)
|
||||||
|
{
|
||||||
|
card.InitializeStatusOption(Key, State.Cache);
|
||||||
|
card._canDoEvent = true;
|
||||||
|
}
|
||||||
|
// init reason text
|
||||||
|
if (State.Cache != null)
|
||||||
|
{
|
||||||
|
var criminalInfo = GetRecord(Key, State.Cache);
|
||||||
|
if (criminalInfo != null)
|
||||||
|
card.ReasonWritten.SetMessage(criminalInfo.Reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
card.OnTextBindDown += args =>
|
||||||
|
{
|
||||||
|
OnTextBindDown?.Invoke(Key, args);
|
||||||
|
};
|
||||||
|
// rsult
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityUid CreateCharacterDummy(GeneralStationRecord Record)
|
||||||
|
{
|
||||||
|
IEntityManager entityManager = IoCManager.Resolve<IEntityManager>();
|
||||||
|
IPrototypeManager prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
HumanoidAppearanceSystem appearanceSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<HumanoidAppearanceSystem>();
|
||||||
|
|
||||||
|
var profile = Record.Profile ?? new HumanoidCharacterProfile();
|
||||||
|
var _previewDummy = entityManager.SpawnEntity(prototypeManager.Index<SpeciesPrototype>(profile.Species).DollPrototype, MapCoordinates.Nullspace);
|
||||||
|
appearanceSystem.LoadProfile(_previewDummy, profile);
|
||||||
|
GiveDummyJobClothes(_previewDummy, Record.JobPrototype, profile);
|
||||||
|
|
||||||
|
return _previewDummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GiveDummyJobClothes(EntityUid dummy, string jobPrototype, HumanoidCharacterProfile profile)
|
||||||
|
{
|
||||||
|
IEntityManager entityManager = IoCManager.Resolve<IEntityManager>();
|
||||||
|
IPrototypeManager prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
ClientInventorySystem inventorySystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ClientInventorySystem>();
|
||||||
|
|
||||||
|
// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract (what is resharper smoking?)
|
||||||
|
var job = prototypeManager.Index<JobPrototype>(jobPrototype ?? SharedGameTicker.FallbackOverflowJob);
|
||||||
|
|
||||||
|
if (job.StartingGear != null && inventorySystem.TryGetSlots(dummy, out var slots))
|
||||||
|
{
|
||||||
|
var gear = prototypeManager.Index<StartingGearPrototype>(job.StartingGear);
|
||||||
|
|
||||||
|
foreach (var slot in slots)
|
||||||
|
{
|
||||||
|
var itemType = gear.GetGear(slot.Name, profile);
|
||||||
|
if (inventorySystem.TryUnequip(dummy, slot.Name, out var unequippedItem, true, true))
|
||||||
|
{
|
||||||
|
entityManager.DeleteEntity(unequippedItem.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemType != string.Empty)
|
||||||
|
{
|
||||||
|
var item = entityManager.SpawnEntity(itemType, MapCoordinates.Nullspace);
|
||||||
|
inventorySystem.TryEquip(dummy, item, slot.Name, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetAccess()
|
||||||
|
{
|
||||||
|
//_accessReader.FindAccessTags(item).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
using Content.Shared.Humanoid;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
|
using Content.Shared.PDA;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using Content.Shared.Access.Components;
|
||||||
|
using Content.Shared.Roles;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Numerics;
|
||||||
|
using Content.Shared.White.CriminalRecords;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.Client.White.EntityCrimeRecords;
|
||||||
|
|
||||||
|
public sealed class EntityCrimeRecordsOverlay : Overlay
|
||||||
|
{
|
||||||
|
private readonly IEntityManager _entManager;
|
||||||
|
private readonly SharedTransformSystem _transform;
|
||||||
|
private readonly IPrototypeManager _prototypeManager;
|
||||||
|
private readonly InventorySystem _inventorySystem;
|
||||||
|
private readonly ShaderInstance _shader;
|
||||||
|
private readonly ShowCrimeRecordsSystem _parentSystem;
|
||||||
|
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
|
||||||
|
|
||||||
|
public EntityCrimeRecordsOverlay(
|
||||||
|
IEntityManager entManager,
|
||||||
|
IPrototypeManager protoManager,
|
||||||
|
InventorySystem inventorySystem,
|
||||||
|
ShowCrimeRecordsSystem showCrimSystem)
|
||||||
|
{
|
||||||
|
_entManager = entManager;
|
||||||
|
_prototypeManager = protoManager;
|
||||||
|
_inventorySystem = inventorySystem;
|
||||||
|
_parentSystem = showCrimSystem;
|
||||||
|
_transform = _entManager.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
|
||||||
|
_shader = protoManager.Index<ShaderPrototype>("unshaded").Instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(in OverlayDrawArgs args)
|
||||||
|
{
|
||||||
|
var handle = args.WorldHandle;
|
||||||
|
var rotation = args.Viewport.Eye?.Rotation ?? Angle.Zero;
|
||||||
|
var spriteQuery = _entManager.GetEntityQuery<SpriteComponent>();
|
||||||
|
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
|
||||||
|
|
||||||
|
const float scale = 1f;
|
||||||
|
var scaleMatrix = Matrix3.CreateScale(new Vector2(scale, scale));
|
||||||
|
var rotationMatrix = Matrix3.CreateRotation(-rotation);
|
||||||
|
handle.UseShader(_shader);
|
||||||
|
// da pizda
|
||||||
|
this.ZIndex = this.ZIndex -= 1;
|
||||||
|
|
||||||
|
foreach (var hum in _entManager.EntityQuery<HumanoidAppearanceComponent>(true))
|
||||||
|
{
|
||||||
|
if (!xformQuery.TryGetComponent(hum.Owner, out var xform) ||
|
||||||
|
xform.MapID != args.MapId)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var worldPosition = _transform.GetWorldPosition(xform);
|
||||||
|
var worldMatrix = Matrix3.CreateTranslation(worldPosition);
|
||||||
|
|
||||||
|
Matrix3.Multiply(scaleMatrix, worldMatrix, out var scaledWorld);
|
||||||
|
Matrix3.Multiply(rotationMatrix, scaledWorld, out var matty);
|
||||||
|
|
||||||
|
handle.SetTransform(matty);
|
||||||
|
|
||||||
|
if (GetRecord(hum.Owner, args.MapId, out var criminalType))
|
||||||
|
{
|
||||||
|
var icon = "released";
|
||||||
|
switch (criminalType)
|
||||||
|
{
|
||||||
|
case EnumCriminalRecordType.Released:
|
||||||
|
icon = "released";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Discharged:
|
||||||
|
icon = "discharged";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Parolled:
|
||||||
|
icon = "parolled";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Suspected:
|
||||||
|
icon = "suspected";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Wanted:
|
||||||
|
icon = "wanted";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Incarcerated:
|
||||||
|
icon = "incarcerated";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sprite_icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/White/Interface/records.rsi"), icon);
|
||||||
|
var _iconTexture = _entManager.EntitySysManager.GetEntitySystem<SpriteSystem>().Frame0(sprite_icon);
|
||||||
|
|
||||||
|
float yOffset;
|
||||||
|
float xOffset;
|
||||||
|
if (spriteQuery.TryGetComponent(hum.Owner, out var sprite))
|
||||||
|
{
|
||||||
|
yOffset = sprite.Bounds.Height + 7f - 7f; //sprite.Bounds.Height + 7f;
|
||||||
|
xOffset = sprite.Bounds.Width - 17f; //sprite.Bounds.Width + 7f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yOffset = 1f;
|
||||||
|
xOffset = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position above the entity (we've already applied the matrix transform to the entity itself)
|
||||||
|
// Offset by the texture size for every do_after we have.
|
||||||
|
var position = new Vector2(xOffset / EyeManager.PixelsPerMeter,
|
||||||
|
yOffset / EyeManager.PixelsPerMeter);
|
||||||
|
|
||||||
|
// Draw the underlying bar texture
|
||||||
|
if (sprite != null && !sprite.ContainerOccluded)
|
||||||
|
handle.DrawTexture(_iconTexture, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.UseShader(null);
|
||||||
|
handle.SetTransform(Matrix3.Identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool GetRecord(EntityUid uid, MapId mapId, out EnumCriminalRecordType type)
|
||||||
|
{
|
||||||
|
if (!_entManager.TryGetComponent(uid, out MetaDataComponent? meta))
|
||||||
|
{
|
||||||
|
type = EnumCriminalRecordType.Released;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverList = _entManager.EntityQuery<CriminalRecordsServerComponent>();
|
||||||
|
foreach (var server in serverList)
|
||||||
|
{
|
||||||
|
// if all good - check avaible records
|
||||||
|
foreach (var (key, info) in server.Cache)
|
||||||
|
{
|
||||||
|
// Check id
|
||||||
|
if (_inventorySystem.TryGetSlotEntity(uid, "id", out var idUid))
|
||||||
|
{
|
||||||
|
// PDA
|
||||||
|
if (_entManager.TryGetComponent(idUid, out PdaComponent? pda) &&
|
||||||
|
_entManager.TryGetComponent(pda.ContainedId, out IdCardComponent? idCard))
|
||||||
|
{
|
||||||
|
if (idCard.FullName == info.StationRecord.Name &&
|
||||||
|
idCard.JobTitle == info.StationRecord.JobTitle)
|
||||||
|
{
|
||||||
|
type = info.CriminalType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ID Card
|
||||||
|
if (_entManager.TryGetComponent(idUid, out IdCardComponent? id))
|
||||||
|
{
|
||||||
|
idCard = id;
|
||||||
|
if (idCard.FullName == info.StationRecord.Name &&
|
||||||
|
idCard.JobTitle == info.StationRecord.JobTitle)
|
||||||
|
{
|
||||||
|
type = info.CriminalType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check DNA (Dirty Nanotrasen tehnology lol)
|
||||||
|
// And yeah, he can't check - is pulled mask or not
|
||||||
|
// it's only Content.Server logic, idk hot it impl to Content.Client
|
||||||
|
if (_parentSystem.CanIdentityName(uid) != meta.EntityName)
|
||||||
|
continue;
|
||||||
|
if (meta.EntityName != info.StationRecord.Name)
|
||||||
|
continue;
|
||||||
|
type = info.CriminalType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type = EnumCriminalRecordType.Released;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
using Content.Shared.White.EntityCrimeRecords;
|
||||||
|
using Content.Shared.GameTicking;
|
||||||
|
using Content.Shared.Humanoid;
|
||||||
|
using Content.Shared.IdentityManagement.Components;
|
||||||
|
using Robust.Client.Player;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
|
namespace Content.Client.White.EntityCrimeRecords
|
||||||
|
{
|
||||||
|
public sealed class ShowCrimeRecordsSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||||
|
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||||
|
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||||
|
|
||||||
|
private EntityCrimeRecordsOverlay _overlay = default!;
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ShowCrimeRecordsComponent, ComponentInit>(OnInit);
|
||||||
|
SubscribeLocalEvent<ShowCrimeRecordsComponent, ComponentRemove>(OnRemove);
|
||||||
|
SubscribeLocalEvent<ShowCrimeRecordsComponent, PlayerAttachedEvent>(OnPlayerAttached);
|
||||||
|
SubscribeLocalEvent<ShowCrimeRecordsComponent, PlayerDetachedEvent>(OnPlayerDetached);
|
||||||
|
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
||||||
|
|
||||||
|
_overlay = new(EntityManager, _protoMan, _inventorySystem, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(EntityUid uid, ShowCrimeRecordsComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
if (_player.LocalPlayer?.ControlledEntity == uid)
|
||||||
|
{
|
||||||
|
_overlayMan.AddOverlay(_overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void OnRemove(EntityUid uid, ShowCrimeRecordsComponent component, ComponentRemove args)
|
||||||
|
{
|
||||||
|
if (_player.LocalPlayer?.ControlledEntity == uid)
|
||||||
|
{
|
||||||
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayerAttached(EntityUid uid, ShowCrimeRecordsComponent component, PlayerAttachedEvent args)
|
||||||
|
{
|
||||||
|
_overlayMan.AddOverlay(_overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayerDetached(EntityUid uid, ShowCrimeRecordsComponent component, PlayerDetachedEvent args)
|
||||||
|
{
|
||||||
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRoundRestart(RoundRestartCleanupEvent args)
|
||||||
|
{
|
||||||
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CanIdentityName(EntityUid target)
|
||||||
|
{
|
||||||
|
var representation = GetIdentityRepresentation(target);
|
||||||
|
var ev = new SeeIdentityAttemptEvent();
|
||||||
|
|
||||||
|
RaiseLocalEvent(target, ev);
|
||||||
|
return representation.ToStringKnown(!ev.Cancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an 'identity representation' of an entity, with their true name being the entity name
|
||||||
|
/// and their 'presumed name' and 'presumed job' being the name/job on their ID card, if they have one.
|
||||||
|
/// </summary>
|
||||||
|
private IdentityRepresentation GetIdentityRepresentation(EntityUid target,
|
||||||
|
InventoryComponent? inventory=null,
|
||||||
|
HumanoidAppearanceComponent? appearance=null)
|
||||||
|
{
|
||||||
|
var age = 18;
|
||||||
|
var gender = Gender.Epicene;
|
||||||
|
|
||||||
|
// Always use their actual age and gender, since that can't really be changed by an ID.
|
||||||
|
if (Resolve(target, ref appearance, false))
|
||||||
|
{
|
||||||
|
gender = appearance.Gender;
|
||||||
|
age = appearance.Age;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trueName = Name(target);
|
||||||
|
if (!Resolve(target, ref inventory, false))
|
||||||
|
return new(trueName, gender, age.ToString(), string.Empty);
|
||||||
|
|
||||||
|
string? presumedJob = null;
|
||||||
|
string? presumedName = null;
|
||||||
|
|
||||||
|
// If it didn't find a job, that's fine.
|
||||||
|
return new IdentityRepresentation(trueName, gender, age.ToString(), presumedName, presumedJob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -349,7 +349,7 @@ namespace Content.Server.Administration.Systems
|
|||||||
if (TryComp(item, out PdaComponent? pda) &&
|
if (TryComp(item, out PdaComponent? pda) &&
|
||||||
TryComp(pda.ContainedId, out StationRecordKeyStorageComponent? keyStorage) &&
|
TryComp(pda.ContainedId, out StationRecordKeyStorageComponent? keyStorage) &&
|
||||||
keyStorage.Key is { } key &&
|
keyStorage.Key is { } key &&
|
||||||
_stationRecords.TryGetRecord(key.OriginStation, key, out GeneralStationRecord? record))
|
_stationRecords.TryGetRecord(GetEntity(key.OriginStation), key, out GeneralStationRecord? record))
|
||||||
{
|
{
|
||||||
if (TryComp(entity, out DnaComponent? dna) &&
|
if (TryComp(entity, out DnaComponent? dna) &&
|
||||||
dna.DNA != record.DNA)
|
dna.DNA != record.DNA)
|
||||||
@@ -363,7 +363,7 @@ namespace Content.Server.Administration.Systems
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_stationRecords.RemoveRecord(key.OriginStation, key);
|
_stationRecords.RemoveRecord(GetEntity(key.OriginStation), key);
|
||||||
Del(item);
|
Del(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,20 +73,20 @@ public sealed class CrewManifestSystem : EntitySystem
|
|||||||
// wrt the amount of players readied up.
|
// wrt the amount of players readied up.
|
||||||
private void AfterGeneralRecordCreated(AfterGeneralRecordCreatedEvent ev)
|
private void AfterGeneralRecordCreated(AfterGeneralRecordCreatedEvent ev)
|
||||||
{
|
{
|
||||||
BuildCrewManifest(ev.Key.OriginStation);
|
BuildCrewManifest(GetEntity(ev.Key.OriginStation));
|
||||||
UpdateEuis(ev.Key.OriginStation);
|
UpdateEuis(GetEntity(ev.Key.OriginStation));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRecordModified(RecordModifiedEvent ev)
|
private void OnRecordModified(RecordModifiedEvent ev)
|
||||||
{
|
{
|
||||||
BuildCrewManifest(ev.Key.OriginStation);
|
BuildCrewManifest(GetEntity(ev.Key.OriginStation));
|
||||||
UpdateEuis(ev.Key.OriginStation);
|
UpdateEuis(GetEntity(ev.Key.OriginStation));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRecordRemoved(RecordRemovedEvent ev)
|
private void OnRecordRemoved(RecordRemovedEvent ev)
|
||||||
{
|
{
|
||||||
BuildCrewManifest(ev.Key.OriginStation);
|
BuildCrewManifest(GetEntity(ev.Key.OriginStation));
|
||||||
UpdateEuis(ev.Key.OriginStation);
|
UpdateEuis(GetEntity(ev.Key.OriginStation));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBoundUiClose(EntityUid uid, CrewManifestViewerComponent component, BoundUIClosedEvent ev)
|
private void OnBoundUiClose(EntityUid uid, CrewManifestViewerComponent component, BoundUIClosedEvent ev)
|
||||||
|
|||||||
@@ -72,14 +72,14 @@ public sealed class RenameCommand : IConsoleCommand
|
|||||||
{
|
{
|
||||||
var origin = keyStorage.Key.Value.OriginStation;
|
var origin = keyStorage.Key.Value.OriginStation;
|
||||||
|
|
||||||
if (recordsSystem.TryGetRecord<GeneralStationRecord>(origin,
|
if (recordsSystem.TryGetRecord<GeneralStationRecord>(_entManager.GetEntity(origin),
|
||||||
keyStorage.Key.Value,
|
keyStorage.Key.Value,
|
||||||
out var generalRecord))
|
out var generalRecord))
|
||||||
{
|
{
|
||||||
generalRecord.Name = name;
|
generalRecord.Name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
recordsSystem.Synchronize(origin);
|
recordsSystem.Synchronize(_entManager.GetEntity(origin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public sealed partial class StationRecordSet
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entry">Entry to add.</param>
|
/// <param name="entry">Entry to add.</param>
|
||||||
/// <typeparam name="T">Type of the entry that's being added.</typeparam>
|
/// <typeparam name="T">Type of the entry that's being added.</typeparam>
|
||||||
public StationRecordKey AddRecordEntry<T>(EntityUid station, T entry)
|
public StationRecordKey AddRecordEntry<T>(NetEntity station, T entry)
|
||||||
{
|
{
|
||||||
if (entry == null)
|
if (entry == null)
|
||||||
return StationRecordKey.Invalid;
|
return StationRecordKey.Invalid;
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ public sealed class StationRecordsSystem : SharedStationRecordsSystem
|
|||||||
if (!Resolve(station, ref records))
|
if (!Resolve(station, ref records))
|
||||||
return StationRecordKey.Invalid;
|
return StationRecordKey.Invalid;
|
||||||
|
|
||||||
return records.Records.AddRecordEntry(station, record);
|
return records.Records.AddRecordEntry(GetNetEntity(station), record);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -0,0 +1,244 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Radio.EntitySystems;
|
||||||
|
using Content.Server.Station.Systems;
|
||||||
|
using Content.Server.StationRecords;
|
||||||
|
using Content.Server.StationRecords.Systems;
|
||||||
|
using Content.Shared.Access.Components;
|
||||||
|
using Content.Shared.Access.Systems;
|
||||||
|
using Content.Shared.Containers.ItemSlots;
|
||||||
|
using Content.Shared.PDA;
|
||||||
|
using Content.Shared.Radio;
|
||||||
|
using Content.Shared.StationRecords;
|
||||||
|
using Content.Shared.White.CriminalRecords;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.White.CriminalRecords;
|
||||||
|
|
||||||
|
public sealed class CriminalRecordsConsoleSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
|
|
||||||
|
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
|
||||||
|
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
|
||||||
|
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||||
|
[Dependency] private readonly StationRecordsSystem _stationRecordsSystem = default!;
|
||||||
|
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
|
||||||
|
[Dependency] private readonly RadioSystem _radioSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, ComponentInit>(OnComponentInit);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, ComponentRemove>(OnComponentRemove);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, BoundUIOpenedEvent>(UpdateUserInterface);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, EntInsertedIntoContainerMessage>(OnItemInserted);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, EntRemovedFromContainerMessage>(OnItemRemoved);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, SelectCriminalRecord>(OnKeySelected);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, SelectCriminalStatus>(OnStatusSelected);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, SelectCriminalReason>(OnReasonSelected);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, RecordModifiedEvent>(UpdateUserInterface);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsConsoleComponent, AfterGeneralRecordCreatedEvent>(UpdateUserInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnComponentInit(EntityUid uid, CriminalRecordsConsoleComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
_itemSlotsSystem.AddItemSlot(uid, CriminalRecordsConsoleComponent.IdSlotId, component.IdSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnComponentRemove(EntityUid uid, CriminalRecordsConsoleComponent component, ComponentRemove args)
|
||||||
|
{
|
||||||
|
_itemSlotsSystem.RemoveItemSlot(uid, component.IdSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateUserInterface<T>(EntityUid uid, CriminalRecordsConsoleComponent component, T ev)
|
||||||
|
{
|
||||||
|
UpdateUserInterface(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnItemInserted(EntityUid uid, CriminalRecordsConsoleComponent component, EntInsertedIntoContainerMessage args)
|
||||||
|
{
|
||||||
|
if (args.Container.ID == CriminalRecordsConsoleComponent.IdSlotId)
|
||||||
|
component.ContainedID = CompOrNull<IdCardComponent>(args.Entity);
|
||||||
|
|
||||||
|
UpdateUserInterface(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnItemRemoved(EntityUid uid, CriminalRecordsConsoleComponent component, EntRemovedFromContainerMessage args)
|
||||||
|
{
|
||||||
|
if (args.Container.ID == component.IdSlot.ID)
|
||||||
|
component.ContainedID = null;
|
||||||
|
|
||||||
|
UpdateUserInterface(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnKeySelected(EntityUid uid, CriminalRecordsConsoleComponent component,
|
||||||
|
SelectCriminalRecord msg)
|
||||||
|
{
|
||||||
|
component.ActiveKey = msg.SelectedKey;
|
||||||
|
UpdateUserInterface(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnReasonSelected(EntityUid uid, CriminalRecordsConsoleComponent component,
|
||||||
|
SelectCriminalReason msg)
|
||||||
|
{
|
||||||
|
var hasServer = new EventCheckServer();
|
||||||
|
RaiseLocalEvent(hasServer);
|
||||||
|
|
||||||
|
if (!hasServer.Result)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var ev = new EventChangeReason(msg.SelectedKey, msg.Text);
|
||||||
|
RaiseLocalEvent(ev);
|
||||||
|
|
||||||
|
UpdateUserInterface(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusSelected(EntityUid uid, CriminalRecordsConsoleComponent component,
|
||||||
|
SelectCriminalStatus msg)
|
||||||
|
{
|
||||||
|
if (msg.SelectedStatus == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var hasServer = new EventCheckServer();
|
||||||
|
RaiseLocalEvent(hasServer);
|
||||||
|
|
||||||
|
if (!hasServer.Result)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var messageId = "null";
|
||||||
|
switch (msg.SelectedStatus.CriminalType)
|
||||||
|
{
|
||||||
|
case EnumCriminalRecordType.Released:
|
||||||
|
messageId = "criminal-targetchannel-set-released";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Discharged:
|
||||||
|
messageId = "criminal-targetchannel-set-discharged";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Parolled:
|
||||||
|
messageId = "criminal-targetchannel-set-parolled";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Suspected:
|
||||||
|
messageId = "criminal-targetchannel-set-suspected";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Wanted:
|
||||||
|
messageId = "criminal-targetchannel-set-wanted";
|
||||||
|
break;
|
||||||
|
case EnumCriminalRecordType.Incarcerated:
|
||||||
|
messageId = "criminal-targetchannel-set-incarcerated";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var message = "";
|
||||||
|
|
||||||
|
if (msg.SelectedStatus.Reason != string.Empty)
|
||||||
|
{
|
||||||
|
messageId += "-reason";
|
||||||
|
message = Loc.GetString(messageId,
|
||||||
|
("target", msg.SelectedStatus.StationRecord.Name),
|
||||||
|
("reason", msg.SelectedStatus.Reason));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message = Loc.GetString(messageId,
|
||||||
|
("target", msg.SelectedStatus.StationRecord.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
_radioSystem.SendRadioMessage(uid, message, _prototype.Index<RadioChannelPrototype>(component.TargetChannel), uid);
|
||||||
|
|
||||||
|
var ev = new EventChangeCache(msg.SelectedKey, msg.SelectedStatus);
|
||||||
|
RaiseLocalEvent(ev);
|
||||||
|
|
||||||
|
UpdateUserInterface(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateUserInterface(EntityUid uid,
|
||||||
|
CriminalRecordsConsoleComponent? console = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref console))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty(console);
|
||||||
|
|
||||||
|
var owningStation = _stationSystem.GetOwningStation(uid);
|
||||||
|
|
||||||
|
if (!TryComp<StationRecordsComponent>(owningStation, out var stationRecordsComponent))
|
||||||
|
{
|
||||||
|
CriminalRecordsConsoleBuiState state = new(null, null, null, null, null, false); //null
|
||||||
|
SetStateForInterface(uid, state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var consoleRecords =
|
||||||
|
_stationRecordsSystem.GetRecordsOfType<GeneralStationRecord>(owningStation.Value, stationRecordsComponent);
|
||||||
|
|
||||||
|
var listing = new Dictionary<StationRecordKey, string>();
|
||||||
|
|
||||||
|
foreach (var pair in consoleRecords)
|
||||||
|
{
|
||||||
|
listing.Add(pair.Item1, pair.Item2.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listing.Count == 0)
|
||||||
|
{
|
||||||
|
CriminalRecordsConsoleBuiState state = new(null, null, null, null, null, false); //console!.Filter
|
||||||
|
SetStateForInterface(uid, state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (listing.Count == 1)
|
||||||
|
{
|
||||||
|
console!.ActiveKey = listing.Keys.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneralStationRecord? record = null;
|
||||||
|
if (console!.ActiveKey != null)
|
||||||
|
{
|
||||||
|
_stationRecordsSystem.TryGetRecord(owningStation.Value, console.ActiveKey.Value, out record,
|
||||||
|
stationRecordsComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverEv = new EventGetCache();
|
||||||
|
RaiseLocalEvent(serverEv);
|
||||||
|
|
||||||
|
var idCardInfo = console.ContainedID != null ? new IdCardNetInfo(console.ContainedID.FullName, console.ContainedID.JobTitle) : null;
|
||||||
|
|
||||||
|
CriminalRecordsConsoleBuiState newState = new(console.ActiveKey, record, listing, serverEv.Cache, idCardInfo, AccessCheck(console.ContainedID)); //console.Filter
|
||||||
|
SetStateForInterface(uid, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetStateForInterface(EntityUid uid, CriminalRecordsConsoleBuiState newState)
|
||||||
|
{
|
||||||
|
var ui = _userInterface.GetUiOrNull(uid, CriminalRecordsConsoleKey.Key);
|
||||||
|
if (ui != null)
|
||||||
|
_userInterface.SetUiState(ui, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AccessCheck(IdCardComponent? component)
|
||||||
|
{
|
||||||
|
if (component is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var uid = component.Owner;
|
||||||
|
|
||||||
|
if (!EntityManager.TryGetComponent(uid, out AccessComponent? reader))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var tag in reader.Tags)
|
||||||
|
{
|
||||||
|
var proto = _prototype.Index<EntityPrototype>("ComputerCriminalRecords");
|
||||||
|
proto.TryGetComponent(out AccessReaderComponent? access);
|
||||||
|
|
||||||
|
if (access == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (access.AccessLists.SelectMany(list => list).Any(entry => entry == tag))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,7 +57,7 @@ public sealed class AccessReaderSystem : EntitySystem
|
|||||||
if (!id.IsValid())
|
if (!id.IsValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
component.AccessKeys.Add(new StationRecordKey(key.Item2, id));
|
component.AccessKeys.Add(new StationRecordKey(key.Item2, GetNetEntity(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
component.AccessLists = new(state.AccessLists);
|
component.AccessLists = new(state.AccessLists);
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ public abstract class SharedStationRecordsSystem : EntitySystem
|
|||||||
|
|
||||||
public StationRecordKey Convert((NetEntity, uint) input)
|
public StationRecordKey Convert((NetEntity, uint) input)
|
||||||
{
|
{
|
||||||
return new StationRecordKey(input.Item2, GetEntity(input.Item1));
|
return new StationRecordKey(input.Item2, input.Item1);
|
||||||
}
|
}
|
||||||
public (NetEntity, uint) Convert(StationRecordKey input)
|
public (NetEntity, uint) Convert(StationRecordKey input)
|
||||||
{
|
{
|
||||||
return (GetNetEntity(input.OriginStation), input.Id);
|
return (input.OriginStation, input.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(NetEntity, uint)> Convert(ICollection<StationRecordKey> input)
|
public List<(NetEntity, uint)> Convert(ICollection<StationRecordKey> input)
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.StationRecords;
|
namespace Content.Shared.StationRecords;
|
||||||
|
|
||||||
// Station record keys. These should be stored somewhere,
|
// Station record keys. These should be stored somewhere,
|
||||||
// preferably within an ID card.
|
// preferably within an ID card.
|
||||||
|
[Serializable, NetSerializable]
|
||||||
public readonly struct StationRecordKey : IEquatable<StationRecordKey>
|
public readonly struct StationRecordKey : IEquatable<StationRecordKey>
|
||||||
{
|
{
|
||||||
[DataField("id")]
|
[DataField("id")]
|
||||||
public readonly uint Id;
|
public readonly uint Id;
|
||||||
|
|
||||||
[DataField("station")]
|
[DataField("station")]
|
||||||
public readonly EntityUid OriginStation;
|
public readonly NetEntity OriginStation;
|
||||||
|
|
||||||
public static StationRecordKey Invalid = default;
|
public static StationRecordKey Invalid = default;
|
||||||
|
|
||||||
public StationRecordKey(uint id, EntityUid originStation)
|
public StationRecordKey(uint id, NetEntity originStation)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
OriginStation = originStation;
|
OriginStation = originStation;
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
using Content.Shared.Access.Components;
|
||||||
|
using Content.Shared.Containers.ItemSlots;
|
||||||
|
using Content.Shared.Radio;
|
||||||
|
using Content.Shared.StationRecords;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Shared.White.CriminalRecords;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class CriminalRecordsConsoleComponent : Component
|
||||||
|
{
|
||||||
|
public const string IdSlotId = "id-slot";
|
||||||
|
|
||||||
|
[DataField("idSlot")]
|
||||||
|
public ItemSlot IdSlot = new();
|
||||||
|
|
||||||
|
[DataField("TargetChannel", customTypeSerializer: typeof(PrototypeIdSerializer<RadioChannelPrototype>))]
|
||||||
|
public string TargetChannel = "Security";
|
||||||
|
|
||||||
|
[ViewVariables] public IdCardComponent? ContainedID;
|
||||||
|
[ViewVariables] public StationRecordKey? ActiveKey { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class IdCardNetInfo
|
||||||
|
{
|
||||||
|
public string? FullName { get; }
|
||||||
|
public string? JobTitle { get; }
|
||||||
|
|
||||||
|
public IdCardNetInfo(string? fullName, string? jobTitle)
|
||||||
|
{
|
||||||
|
FullName = fullName;
|
||||||
|
JobTitle = jobTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class CriminalRecordsConsoleBuiState : BoundUserInterfaceState
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Current selected key.
|
||||||
|
/// </summary>
|
||||||
|
public StationRecordKey? SelectedKey { get; }
|
||||||
|
public GeneralStationRecord? Record { get; }
|
||||||
|
public Dictionary<StationRecordKey, string>? RecordListing { get; }
|
||||||
|
public Dictionary<StationRecordKey, CriminalRecordInfo>? Cache { get; }
|
||||||
|
public IdCardNetInfo? ContainedId { get; }
|
||||||
|
public bool IsAllowed { get; }
|
||||||
|
//public GeneralStationRecordsFilter? Filter { get; }
|
||||||
|
public CriminalRecordsConsoleBuiState(StationRecordKey? key, GeneralStationRecord? record,
|
||||||
|
Dictionary<StationRecordKey, string>? recordListing, Dictionary<StationRecordKey, CriminalRecordInfo>? cache
|
||||||
|
, IdCardNetInfo? containedId, bool isAllowed) //GeneralStationRecordsFilter? newFilter
|
||||||
|
{
|
||||||
|
SelectedKey = key;
|
||||||
|
Record = record;
|
||||||
|
RecordListing = recordListing;
|
||||||
|
Cache = cache;
|
||||||
|
ContainedId = containedId;
|
||||||
|
IsAllowed = isAllowed;
|
||||||
|
//Filter = newFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEmpty() => SelectedKey == null
|
||||||
|
&& Record == null && RecordListing == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class SelectCriminalRecord : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public StationRecordKey? SelectedKey { get; }
|
||||||
|
//
|
||||||
|
public SelectCriminalRecord(StationRecordKey? selectedKey)
|
||||||
|
{
|
||||||
|
SelectedKey = selectedKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class SelectCriminalStatus : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public StationRecordKey SelectedKey { get; }
|
||||||
|
public CriminalRecordInfo? SelectedStatus { get; }
|
||||||
|
|
||||||
|
public SelectCriminalStatus(StationRecordKey selectedKey, CriminalRecordInfo? selectedStatus)
|
||||||
|
{
|
||||||
|
SelectedKey = selectedKey;
|
||||||
|
SelectedStatus = selectedStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class SelectCriminalReason : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public StationRecordKey SelectedKey { get; }
|
||||||
|
public string Text { get; }
|
||||||
|
|
||||||
|
public SelectCriminalReason(StationRecordKey key, string text)
|
||||||
|
{
|
||||||
|
SelectedKey = key;
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum CriminalRecordsConsoleKey : byte
|
||||||
|
{
|
||||||
|
Key
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using Content.Shared.StationRecords;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.White.CriminalRecords;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum EnumCriminalRecordType
|
||||||
|
{
|
||||||
|
Released = 0,
|
||||||
|
Discharged = 1,
|
||||||
|
Parolled = 2,
|
||||||
|
Suspected = 3,
|
||||||
|
Wanted = 4,
|
||||||
|
Incarcerated = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class CriminalRecordInfo
|
||||||
|
{
|
||||||
|
|
||||||
|
// Main data
|
||||||
|
[DataField("StationRecord")] public GeneralStationRecord StationRecord { get; set; }
|
||||||
|
|
||||||
|
[DataField("CriminalType")] public EnumCriminalRecordType CriminalType { get; set; }
|
||||||
|
[DataField("Reason")] public string Reason { get; set; }
|
||||||
|
|
||||||
|
public CriminalRecordInfo(GeneralStationRecord stationRecord, EnumCriminalRecordType criminalType, string reason)
|
||||||
|
{
|
||||||
|
this.StationRecord = stationRecord;
|
||||||
|
this.CriminalType = criminalType;
|
||||||
|
this.Reason = reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
[NetworkedComponent]
|
||||||
|
public sealed partial class CriminalRecordsServerComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("Cache")] public Dictionary<StationRecordKey, CriminalRecordInfo> Cache = new();
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class CriminalRecordsServerComponentState : ComponentState
|
||||||
|
{
|
||||||
|
public Dictionary<StationRecordKey, CriminalRecordInfo> Cache { get; init; }
|
||||||
|
|
||||||
|
public CriminalRecordsServerComponentState(Dictionary<StationRecordKey, CriminalRecordInfo> cache)
|
||||||
|
{
|
||||||
|
Cache = cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
using Content.Shared.StationRecords;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.White.CriminalRecords;
|
||||||
|
|
||||||
|
public sealed class CriminalRecordsServerSystem: EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<EventGetCache>(OnGetCache);
|
||||||
|
SubscribeLocalEvent<EventChangeCache>(OnChangeCache);
|
||||||
|
SubscribeLocalEvent<EventChangeReason>(OnChangeReason);
|
||||||
|
SubscribeLocalEvent<EventCheckServer>(OnCheckServer);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsServerComponent, ComponentGetState>(OnGetState);
|
||||||
|
SubscribeLocalEvent<CriminalRecordsServerComponent, ComponentHandleState>(OnHandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGetState(EntityUid uid, CriminalRecordsServerComponent component, ref ComponentGetState args)
|
||||||
|
{
|
||||||
|
args.State = new CriminalRecordsServerComponent.CriminalRecordsServerComponentState(component.Cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHandleState(EntityUid uid, CriminalRecordsServerComponent component, ref ComponentHandleState args)
|
||||||
|
{
|
||||||
|
if (args.Current is not CriminalRecordsServerComponent.CriminalRecordsServerComponentState state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.Cache = state.Cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGetCache(EventGetCache ev)
|
||||||
|
{
|
||||||
|
var serverList = EntityQuery<CriminalRecordsServerComponent>();
|
||||||
|
foreach (var server in serverList)
|
||||||
|
{
|
||||||
|
ev.Cache = server.Cache;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnChangeCache(EventChangeCache ev)
|
||||||
|
{
|
||||||
|
var serverList = EntityQuery<CriminalRecordsServerComponent>();
|
||||||
|
foreach (var server in serverList)
|
||||||
|
{
|
||||||
|
foreach (var (key, info) in server.Cache)
|
||||||
|
{
|
||||||
|
if (key.Id == ev.Key.Id)
|
||||||
|
{
|
||||||
|
info.Reason = ev.Record.Reason;
|
||||||
|
info.CriminalType = ev.Record.CriminalType;
|
||||||
|
Dirty(server);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.Cache.Add(ev.Key, ev.Record);
|
||||||
|
Dirty(server);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnChangeReason(EventChangeReason ev)
|
||||||
|
{
|
||||||
|
var serverList = EntityQuery<CriminalRecordsServerComponent>();
|
||||||
|
foreach (var server in serverList)
|
||||||
|
{
|
||||||
|
foreach (var (key, info) in server.Cache)
|
||||||
|
{
|
||||||
|
if (key.Id == ev.Key.Id)
|
||||||
|
{
|
||||||
|
info.Reason = ev.Text;
|
||||||
|
Dirty(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCheckServer(EventCheckServer ev)
|
||||||
|
{
|
||||||
|
var serverList = EntityQuery<CriminalRecordsServerComponent>();
|
||||||
|
foreach (var server in serverList)
|
||||||
|
{
|
||||||
|
ev.Result = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ev.Result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Events
|
||||||
|
public sealed class EventGetCache
|
||||||
|
{
|
||||||
|
public Dictionary<StationRecordKey, CriminalRecordInfo> Cache = new();
|
||||||
|
|
||||||
|
public EventGetCache()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class EventChangeCache
|
||||||
|
{
|
||||||
|
public CriminalRecordInfo Record { get; }
|
||||||
|
public StationRecordKey Key { get; }
|
||||||
|
|
||||||
|
public EventChangeCache(StationRecordKey key, CriminalRecordInfo record)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
Record = record;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class EventChangeReason
|
||||||
|
{
|
||||||
|
public string Text { get; }
|
||||||
|
public StationRecordKey Key { get; }
|
||||||
|
|
||||||
|
public EventChangeReason(StationRecordKey key, string text)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class EventCheckServer
|
||||||
|
{
|
||||||
|
public bool Result { get; set; }
|
||||||
|
|
||||||
|
public EventCheckServer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Content.Shared.White.EntityCrimeRecords
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Allow to see crime records info for character
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class ShowCrimeRecordsComponent : Component
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Resources/Locale/ru-RU/white/criminal-console.ftl
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
criminal-console-list = Список экипажа
|
||||||
|
criminal-console-name = консоль криминальных записей
|
||||||
|
criminal-grant-status-button-name = Статус
|
||||||
|
|
||||||
|
criminal-login-out = Log Out
|
||||||
|
criminal-login-in = Log In
|
||||||
|
criminal-login-info = ID: {$user}
|
||||||
|
criminal-login-hint = Вставьте ID карту в консоль, нажав на "{$name}" (нужно держать ID карту в руке)
|
||||||
|
criminal-login-warn = WARNING: Доступ к системе осуществляется уровнем доступа "службы безопасности"
|
||||||
|
|
||||||
|
criminal-status-released = Освобожден
|
||||||
|
criminal-status-discharged = Выписан
|
||||||
|
criminal-status-parolled = Закодирован
|
||||||
|
criminal-status-suspected = Подозреваемый
|
||||||
|
criminal-status-wanted = В розыске
|
||||||
|
criminal-status-incarcerated = Заключенный
|
||||||
|
|
||||||
|
criminal-targetchannel-set-released = {$target} освобожден(а).
|
||||||
|
criminal-targetchannel-set-released-reason = {$target} освобожден(а). Заметка: {$reason}.
|
||||||
|
criminal-targetchannel-set-discharged = {$target} выписан(а).
|
||||||
|
criminal-targetchannel-set-discharged-reason = {$target} выписан(а). Заметка: {$reason}.
|
||||||
|
criminal-targetchannel-set-parolled = {$target} закодирован(а).
|
||||||
|
criminal-targetchannel-set-parolled-reason = {$target} закодирован(а). Заметка: {$reason}.
|
||||||
|
criminal-targetchannel-set-suspected = {$target} под подозрением.
|
||||||
|
criminal-targetchannel-set-suspected-reason = {$target} под подозрением. Заметка: {$reason}.
|
||||||
|
criminal-targetchannel-set-wanted = {$target} объявлен(а) в розыск.
|
||||||
|
criminal-targetchannel-set-wanted-reason = {$target} объявлен(а) в розыск. Заметка: {$reason}.
|
||||||
|
criminal-targetchannel-set-incarcerated = {$target} был(а) заключен(а) под стражу.
|
||||||
|
criminal-targetchannel-set-incarcerated-reason = {$target} был(а) заключен(а) под стражу. Заметка: {$reason}.
|
||||||
|
|
||||||
|
criminal-dna-name = ДНК:
|
||||||
|
criminal-dna-desc = - [color={$color}]{$info}[/color]
|
||||||
|
criminal-fingerprint-name = Отпечатки пальцев:
|
||||||
|
criminal-fingerprint-desc = - [color={$color}]{$info}[/color]
|
||||||
|
|
||||||
|
criminal-detail-info = Заметка:
|
||||||
|
|
||||||
|
ent-CriminalRecordsServer = сервер криминальных записей
|
||||||
|
.desc = Содержит все преступные записи об экипажа на станции. Не дайте злоумышлиникам уничтожить его!
|
||||||
@@ -281,12 +281,23 @@
|
|||||||
- type: Computer
|
- type: Computer
|
||||||
board: MedicalRecordsComputerCircuitboard
|
board: MedicalRecordsComputerCircuitboard
|
||||||
|
|
||||||
|
# mark this is needed
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputer
|
parent: BaseComputer
|
||||||
id: ComputerCriminalRecords
|
id: ComputerCriminalRecords
|
||||||
name: criminal records computer
|
name: criminal records computer
|
||||||
description: This can be used to check criminal records.
|
description: This can be used to check criminal records.
|
||||||
components:
|
components:
|
||||||
|
- type: CriminalRecordsConsole # my own impl
|
||||||
|
idSlot:
|
||||||
|
name: ID Card
|
||||||
|
ejectSound: /Audio/Machines/id_swipe.ogg
|
||||||
|
insertSound: /Audio/Weapons/Guns/MagIn/batrifle_magin.ogg
|
||||||
|
ejectOnBreak: true
|
||||||
|
swap: false
|
||||||
|
whitelist:
|
||||||
|
components:
|
||||||
|
- IdCard
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
layers:
|
layers:
|
||||||
- map: ["computerLayerBody"]
|
- map: ["computerLayerBody"]
|
||||||
@@ -297,12 +308,28 @@
|
|||||||
state: explosive
|
state: explosive
|
||||||
- map: ["computerLayerKeys"]
|
- map: ["computerLayerKeys"]
|
||||||
state: security_key
|
state: security_key
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
- key: enum.CriminalRecordsConsoleKey.Key
|
||||||
|
type: CriminalRecordsBoundUserInterface
|
||||||
|
- type: ActivatableUI
|
||||||
|
key: enum.CriminalRecordsConsoleKey.Key
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
radius: 1.5
|
radius: 1.5
|
||||||
energy: 1.6
|
energy: 1.6
|
||||||
color: "#1f8c28"
|
color: "#1f8c28"
|
||||||
- type: Computer
|
- type: Computer
|
||||||
board: CriminalRecordsComputerCircuitboard
|
board: CriminalRecordsComputerCircuitboard
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- EmagImmune
|
||||||
|
- type: ItemSlots
|
||||||
|
- type: ContainerContainer
|
||||||
|
containers:
|
||||||
|
board: !type:Container
|
||||||
|
id-slot: !type:ContainerSlot
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Security"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputer
|
parent: BaseComputer
|
||||||
|
|||||||
@@ -781,13 +781,3 @@
|
|||||||
Steel: 100
|
Steel: 100
|
||||||
Glass: 900
|
Glass: 900
|
||||||
Gold: 100
|
Gold: 100
|
||||||
|
|
||||||
- type: latheRecipe
|
|
||||||
id: ClothingEyesHudMedical
|
|
||||||
icon: { sprite: Clothing/Eyes/Hud/med.rsi, state: icon }
|
|
||||||
result: ClothingEyesHudMedical
|
|
||||||
completetime: 4
|
|
||||||
materials:
|
|
||||||
Steel: 100
|
|
||||||
Glass: 300
|
|
||||||
Plasma: 200
|
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
- type: entity
|
||||||
|
parent: [ BaseMachinePowered, ConstructibleMachine ]
|
||||||
|
id: CriminalRecordsServer
|
||||||
|
name: criminal records server
|
||||||
|
description: When powered and filled with encryption keys it allows radio headset communication.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Structures/Machines/criminal_record_server.rsi
|
||||||
|
snapCardinals: true
|
||||||
|
netsync: false
|
||||||
|
layers:
|
||||||
|
- state: icon
|
||||||
|
- state: unlit
|
||||||
|
shader: unshaded
|
||||||
|
map: ["enum.PowerDeviceVisualLayers.Powered"]
|
||||||
|
- state: panel
|
||||||
|
map: ["enum.WiresVisualLayers.MaintenancePanel"]
|
||||||
|
- type: GenericVisualizer
|
||||||
|
visuals:
|
||||||
|
enum.PowerDeviceVisuals.Powered:
|
||||||
|
enum.PowerDeviceVisualLayers.Powered:
|
||||||
|
True: { visible: true }
|
||||||
|
False: { visible: false }
|
||||||
|
- type: Appearance
|
||||||
|
- type: Physics
|
||||||
|
bodyType: Static
|
||||||
|
- type: Fixtures
|
||||||
|
fixtures:
|
||||||
|
fix1:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeAabb
|
||||||
|
bounds: "-0.4,-0.4,0.4,0.4"
|
||||||
|
density: 190
|
||||||
|
mask:
|
||||||
|
- MachineMask
|
||||||
|
layer:
|
||||||
|
- MachineLayer
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 100
|
||||||
|
behaviors:
|
||||||
|
- !type:ChangeConstructionNodeBehavior
|
||||||
|
node: machineFrame
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: ["Destruction"]
|
||||||
|
- type: Machine
|
||||||
|
board: CriminalRecordsServerCircuitboard
|
||||||
|
- type: WiresPanel
|
||||||
|
- type: Wires
|
||||||
|
boardName: "CriminalRecordsServer"
|
||||||
|
layoutId: CriminalRecordsServer
|
||||||
|
- type: Transform
|
||||||
|
anchored: true
|
||||||
|
- type: Pullable
|
||||||
|
- type: CriminalRecordsServer
|
||||||
|
- type: ContainerContainer
|
||||||
|
containers:
|
||||||
|
machine_board: !type:Container
|
||||||
|
machine_parts: !type:Container
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: CriminalRecordsServerCircuitboard
|
||||||
|
parent: BaseMachineCircuitboard
|
||||||
|
name: criminal records server machine board
|
||||||
|
description: A machine printed circuit board for an telecommunication server.
|
||||||
|
components:
|
||||||
|
- type: MachineBoard
|
||||||
|
prototype: CriminalRecordsServer
|
||||||
|
materialRequirements:
|
||||||
|
Steel: 1
|
||||||
|
Cable: 2
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
- type: statusIcon
|
||||||
|
id: CriminalRecordIcon
|
||||||
|
abstract: true
|
||||||
|
priority: 3
|
||||||
|
locationPreference: Right
|
||||||
|
|
||||||
|
- type: statusIcon
|
||||||
|
parent: CriminalRecordIcon
|
||||||
|
id: CriminalRecordIconReleased
|
||||||
|
icon:
|
||||||
|
sprite: White/Interface/records.rsi
|
||||||
|
state: released
|
||||||
|
|
||||||
|
- type: statusIcon
|
||||||
|
parent: CriminalRecordIcon
|
||||||
|
id: CriminalRecordIconDischarged
|
||||||
|
icon:
|
||||||
|
sprite: White/Interface/records.rsi
|
||||||
|
state: discharged
|
||||||
|
|
||||||
|
- type: statusIcon
|
||||||
|
parent: CriminalRecordIcon
|
||||||
|
id: CriminalRecordIconParolled
|
||||||
|
icon:
|
||||||
|
sprite: White/Interface/records.rsi
|
||||||
|
state: parolled
|
||||||
|
|
||||||
|
- type: statusIcon
|
||||||
|
parent: CriminalRecordIcon
|
||||||
|
id: CriminalRecordIconSuspected
|
||||||
|
icon:
|
||||||
|
sprite: White/Interface/records.rsi
|
||||||
|
state: suspected
|
||||||
|
|
||||||
|
- type: statusIcon
|
||||||
|
parent: CriminalRecordIcon
|
||||||
|
id: CriminalRecordIconWanted
|
||||||
|
icon:
|
||||||
|
sprite: White/Interface/records.rsi
|
||||||
|
state: wanted
|
||||||
|
|
||||||
|
- type: statusIcon
|
||||||
|
parent: CriminalRecordIcon
|
||||||
|
id: CriminalRecordIconIncarcerated
|
||||||
|
icon:
|
||||||
|
sprite: White/Interface/records.rsi
|
||||||
|
state: incarcerated
|
||||||
BIN
Resources/Textures/White/Interface/records.rsi/discharged.png
Normal file
|
After Width: | Height: | Size: 144 B |
BIN
Resources/Textures/White/Interface/records.rsi/incarcerated.png
Normal file
|
After Width: | Height: | Size: 139 B |
27
Resources/Textures/White/Interface/records.rsi/meta.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "https://github.com/tgstation/tgstation/blob/8e49222b72f6fdcbe741d2a6ce0a8425d95010b7/icons/mob/huds/hud.dmi",
|
||||||
|
"version": 1,
|
||||||
|
"size": { "y": 8, "x": 8 },
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "wanted"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "suspected"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "released"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "parolled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "incarcerated"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "discharged"
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/White/Interface/records.rsi/parolled.png
Normal file
|
After Width: | Height: | Size: 150 B |
BIN
Resources/Textures/White/Interface/records.rsi/released.png
Normal file
|
After Width: | Height: | Size: 143 B |
BIN
Resources/Textures/White/Interface/records.rsi/suspected.png
Normal file
|
After Width: | Height: | Size: 141 B |
BIN
Resources/Textures/White/Interface/records.rsi/wanted.png
Normal file
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 416 B |
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/blob/9c3494fd79e6bf8dc532300b9de4f688ff276ac9/icons/obj/machines/telecomms.dmi",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "unlit",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "panel"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 860 B |
|
After Width: | Height: | Size: 1.8 KiB |