mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 13:37:47 +03:00
# Description This adds the wonderful `Psionics Registry Computer` which allows you to, just like Criminal Records, mark people that will show their icons to other individuals wearing the appropriate gear, and will allow you to keep track of such individuals in a similar way by making a `PsiWatch` app that will show the reasons. For the purposes of easement, I've left the fingerprints and DNA in there, but individuals will not show up with it in the actual file. The game would just crash when I removed the filters, so I left them in. The dropdown also just looked cleaner when it was there instead of removing it and replacing it with a label. I've recolored the sprites for the sec-glasses and sec-HUD to make the epi-glasses and epi-HUD using Epistemics colors. I've recolored the sprite for the CriminalRecords computer to look different and be cool. --- # TODO A list of things I've done split into categories. ### Spriting - [x] (Recolor) Sprite the epi-glasses and epi-HUD. - [x] Sprite the PsionicsRecords computer screen. - [x] Sprite the Psionics Status icons. - [x] Change the sprite for the Psionics Abusing (it is hard to tell any difference from suspected right now). ### Records - [x] Set up records XAML that basically duplicates the Criminal Records. - [x] Remove History (not necessary). - [x] Change all the naming schema to match. - [x] Change the categories and setup reason-requirement for each submission type. - [x] Change the "reason" to "psionics" so it is more intuitive. ### Computer Setup - [x] Setup computer to show UI. - [x] Setup system to report to report to Epistemics (Science) radio when anything is changed. - [x] Setup the system to only accept Epistemics (Research) access. - [x] Setup the computer board. - [x] Setup the sprites for the computers. ### Equipment and Icons - [x] Create the icons and ensure the ShowPsionicsRecordIcons prototype works. - [x] Create the entity prototypes for the glasses and HUD in the game to show textures. - [x] Set it up so the glasses and HUD show the user the icons when they're wearing them (having hard time fixing this at 06:00 in the morning). ### PDA App - [x] Setup the PDA app to mimic the SecWatch app as its own (PsiWatch). - [x] Add the PDA app cartridge to Chaplain, Mantis, Cataloguer, and Mystagogue. - [x] Add cartridge to the Mystagogue locker (so they can give others it). ### Loadouts - [x] Add the epi-HUD to the Chaplain, Mantis, Cataloguer and Mystagogue. - [x] Add the epi-glasses to the Mystagogue. - [x] Add the epi-glasses to Chaplain, Mantis, and Cataloguer (for 3 points). ### Mapping - [x] Add the Psionics Registry Computer to every map. ### Miscellaneous Fixes/Changes - [x] Make the computer only work for Chaplain (Chapel), Cataloguer (Library), Mantis (Mantis), and Mystagogue (ResearchDirector). - [x] Fix Chaplain PDA (did not have any programs installed automatically, now it does). --- # Media I will add more media when I finish the rest. For now, it's just us. <details><summary><h3>Registry Working</h3></summary> <p> https://github.com/user-attachments/assets/f534a1b6-6873-4bcd-9fe5-c7138069ecc0 </p> </details> <details><summary><h3>Loadouts and PsiWatch</h3></summary> <p> Cataloguer  Chaplain  Mantis  Mystagogue  --- No Users in PsiWatch  Suspected in PsiWatch  Registered in PsiWatch  Abusing in PsiWatch  PsiWatch in PDA  Picture of the PDAs and PsiWatch Cartridge  --- Mystagogue Lockers with PsiWatch Cartridge  </p> </details> <details><summary><h3>Mapping Locations</h3></summary> <p> Arena  Asterisk  Core  Edge  Europa  Gaxstation  Glacier  Hive  Lighthouse  Meta  Pebble  Radstation  Saltern  Shoukou  Submarine  Tortuga  </p> </details> --- # Changelog 🆑 - add: Added Psionics Registry Computer. Now you can record Psionics users in Epistemics. - add: Added epi-glasses and epi-HUD to see Psionics Users icons. (Chaplain, Cataloguer, Mantis, and Mystagogue have access in loadout). - add: Added PsiWatch. Now you can see the Psionics Records data on your PDA! - fix: Fixed Chaplain not having any programs in their PDA on spawn. --------- Signed-off-by: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com> Co-authored-by: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com> (cherry picked from commit fc7ecc44a748f8ef7a4cec613033f51acf238288)
235 lines
9.1 KiB
C#
235 lines
9.1 KiB
C#
using Content.Server.Popups;
|
|
using Content.Server.Radio.EntitySystems;
|
|
using Content.Server.Station.Systems;
|
|
using Content.Server.StationRecords;
|
|
using Content.Server.StationRecords.Systems;
|
|
using Content.Shared.Access.Systems;
|
|
using Content.Shared.PsionicsRecords;
|
|
using Content.Shared.PsionicsRecords.Components;
|
|
using Content.Shared.PsionicsRecords.Systems;
|
|
using Content.Shared.Psionics;
|
|
using Content.Shared.StationRecords;
|
|
using Robust.Server.GameObjects;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using Content.Shared.IdentityManagement;
|
|
using Content.Shared.Psionics.Components;
|
|
|
|
/// <summary>
|
|
/// EVERYTHING HERE IS A MODIFIED VERSION OF CRIMINAL RECORDS
|
|
/// </summary>
|
|
|
|
namespace Content.Server.PsionicsRecords.Systems;
|
|
|
|
/// <summary>
|
|
/// Handles all UI for Psionics records console
|
|
/// </summary>
|
|
public sealed class PsionicsRecordsConsoleSystem : SharedPsionicsRecordsConsoleSystem
|
|
{
|
|
[Dependency] private readonly AccessReaderSystem _access = default!;
|
|
[Dependency] private readonly PsionicsRecordsSystem _psionicsRecords = default!;
|
|
[Dependency] private readonly PopupSystem _popup = default!;
|
|
[Dependency] private readonly RadioSystem _radio = default!;
|
|
[Dependency] private readonly SharedIdCardSystem _idCard = default!;
|
|
[Dependency] private readonly StationRecordsSystem _stationRecords = default!;
|
|
[Dependency] private readonly StationSystem _station = default!;
|
|
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
SubscribeLocalEvent<PsionicsRecordsConsoleComponent, RecordModifiedEvent>(UpdateUserInterface);
|
|
SubscribeLocalEvent<PsionicsRecordsConsoleComponent, AfterGeneralRecordCreatedEvent>(UpdateUserInterface);
|
|
|
|
Subs.BuiEvents<PsionicsRecordsConsoleComponent>(PsionicsRecordsConsoleKey.Key, subs =>
|
|
{
|
|
subs.Event<BoundUIOpenedEvent>(UpdateUserInterface);
|
|
subs.Event<SelectStationRecord>(OnKeySelected);
|
|
subs.Event<SetStationRecordFilter>(OnFiltersChanged);
|
|
subs.Event<PsionicsRecordChangeStatus>(OnChangeStatus);
|
|
});
|
|
}
|
|
|
|
private void UpdateUserInterface<T>(Entity<PsionicsRecordsConsoleComponent> ent, ref T args)
|
|
{
|
|
// TODO: this is probably wasteful, maybe better to send a message to modify the exact state?
|
|
UpdateUserInterface(ent);
|
|
}
|
|
|
|
private void OnKeySelected(Entity<PsionicsRecordsConsoleComponent> ent, ref SelectStationRecord msg)
|
|
{
|
|
// no concern of sus client since record retrieval will fail if invalid id is given
|
|
ent.Comp.ActiveKey = msg.SelectedKey;
|
|
UpdateUserInterface(ent);
|
|
}
|
|
|
|
private void OnFiltersChanged(Entity<PsionicsRecordsConsoleComponent> ent, ref SetStationRecordFilter msg)
|
|
{
|
|
if (ent.Comp.Filter == null ||
|
|
ent.Comp.Filter.Type != msg.Type || ent.Comp.Filter.Value != msg.Value)
|
|
{
|
|
ent.Comp.Filter = new StationRecordsFilter(msg.Type, msg.Value);
|
|
UpdateUserInterface(ent);
|
|
}
|
|
}
|
|
|
|
private void OnChangeStatus(Entity<PsionicsRecordsConsoleComponent> ent, ref PsionicsRecordChangeStatus msg)
|
|
{
|
|
// prevent malf client violating registered/reason nullability
|
|
if (msg.Status == PsionicsStatus.Registered != (msg.Reason != null) &&
|
|
msg.Status == PsionicsStatus.Suspected != (msg.Reason != null) &&
|
|
msg.Status == PsionicsStatus.Abusing != (msg.Reason != null))
|
|
return;
|
|
|
|
if (!CheckSelected(ent, msg.Actor, out var mob, out var key))
|
|
return;
|
|
|
|
if (!_stationRecords.TryGetRecord<PsionicsRecord>(key.Value, out var record) || record.Status == msg.Status)
|
|
return;
|
|
|
|
// validate the reason
|
|
string? reason = null;
|
|
if (msg.Reason != null)
|
|
{
|
|
reason = msg.Reason.Trim();
|
|
if (reason.Length < 1 || reason.Length > ent.Comp.MaxStringLength)
|
|
return;
|
|
}
|
|
|
|
var oldStatus = record.Status;
|
|
|
|
// will probably never fail given the checks above
|
|
_psionicsRecords.TryChangeStatus(key.Value, msg.Status, msg.Reason);
|
|
|
|
var name = RecordName(key.Value);
|
|
var officer = Loc.GetString("psionics-records-console-unknown-officer");
|
|
|
|
var tryGetIdentityShortInfoEvent = new TryGetIdentityShortInfoEvent(null, mob.Value);
|
|
RaiseLocalEvent(tryGetIdentityShortInfoEvent);
|
|
if (tryGetIdentityShortInfoEvent.Title != null)
|
|
{
|
|
officer = tryGetIdentityShortInfoEvent.Title;
|
|
}
|
|
|
|
(string, object)[] args;
|
|
if (reason != null)
|
|
args = new (string, object)[] { ("name", name), ("officer", officer), ("reason", reason) };
|
|
else
|
|
args = new (string, object)[] { ("name", name), ("officer", officer) };
|
|
|
|
// figure out which radio message to send depending on transition
|
|
var statusString = (oldStatus, msg.Status) switch
|
|
{
|
|
// person has been registered
|
|
(_, PsionicsStatus.Registered) => "registered",
|
|
// person did something suspicious
|
|
(_, PsionicsStatus.Suspected) => "suspected",
|
|
// person is abusing
|
|
(_, PsionicsStatus.Abusing) => "abusing",
|
|
// person is no longer suspicious
|
|
(PsionicsStatus.Suspected, PsionicsStatus.None) => "not-suspected",
|
|
// person is no longer registered
|
|
(PsionicsStatus.Registered, PsionicsStatus.None) => "not-registered",
|
|
// person is no longer abusing
|
|
(PsionicsStatus.Abusing, PsionicsStatus.None) => "not-abusing",
|
|
// this is impossible
|
|
_ => "not-wanted"
|
|
};
|
|
_radio.SendRadioMessage(ent, Loc.GetString($"psionics-records-console-{statusString}", args),
|
|
ent.Comp.RadioChannel, ent);
|
|
|
|
UpdateUserInterface(ent);
|
|
UpdatePsionicsIdentity(name, msg.Status);
|
|
}
|
|
|
|
private void UpdateUserInterface(Entity<PsionicsRecordsConsoleComponent> ent)
|
|
{
|
|
var (uid, console) = ent;
|
|
var owningStation = _station.GetOwningStation(uid);
|
|
|
|
if (!TryComp<StationRecordsComponent>(owningStation, out var stationRecords))
|
|
{
|
|
_ui.SetUiState(uid, PsionicsRecordsConsoleKey.Key, new PsionicsRecordsConsoleState());
|
|
return;
|
|
}
|
|
|
|
var listing = _stationRecords.BuildListing((owningStation.Value, stationRecords), console.Filter);
|
|
|
|
var state = new PsionicsRecordsConsoleState(listing, console.Filter);
|
|
if (console.ActiveKey is { } id)
|
|
{
|
|
// get records to display when a crewmember is selected
|
|
var key = new StationRecordKey(id, owningStation.Value);
|
|
_stationRecords.TryGetRecord(key, out state.StationRecord, stationRecords);
|
|
_stationRecords.TryGetRecord(key, out state.PsionicsRecord, stationRecords);
|
|
state.SelectedKey = id;
|
|
}
|
|
|
|
_ui.SetUiState(uid, PsionicsRecordsConsoleKey.Key, state);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Boilerplate that most actions use, if they require that a record be selected.
|
|
/// Obviously shouldn't be used for selecting records.
|
|
/// </summary>
|
|
private bool CheckSelected(Entity<PsionicsRecordsConsoleComponent> ent, EntityUid user,
|
|
[NotNullWhen(true)] out EntityUid? mob, [NotNullWhen(true)] out StationRecordKey? key)
|
|
{
|
|
key = null;
|
|
mob = null;
|
|
|
|
if (!_access.IsAllowed(user, ent))
|
|
{
|
|
_popup.PopupEntity(Loc.GetString("psionics-records-permission-denied"), ent, user);
|
|
return false;
|
|
}
|
|
|
|
if (ent.Comp.ActiveKey is not { } id)
|
|
return false;
|
|
|
|
// checking the console's station since the user might be off-grid using on-grid console
|
|
if (_station.GetOwningStation(ent) is not { } station)
|
|
return false;
|
|
|
|
key = new StationRecordKey(id, station);
|
|
mob = user;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the name from a record, or empty string if this somehow fails.
|
|
/// </summary>
|
|
private string RecordName(StationRecordKey key)
|
|
{
|
|
if (!_stationRecords.TryGetRecord<GeneralStationRecord>(key, out var record))
|
|
return "";
|
|
|
|
return record.Name;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the new identity's name has a psionics record attached to it, and gives the entity the icon that
|
|
/// belongs to the status if it does.
|
|
/// </summary>
|
|
public void CheckNewIdentity(EntityUid uid)
|
|
{
|
|
var name = Identity.Name(uid, EntityManager);
|
|
var xform = Transform(uid);
|
|
|
|
// TODO use the entity's station? Not the station of the map that it happens to currently be on?
|
|
var station = _station.GetStationInMap(xform.MapID);
|
|
|
|
if (station != null && _stationRecords.GetRecordByName(station.Value, name) is { } id)
|
|
{
|
|
if (_stationRecords.TryGetRecord<PsionicsRecord>(new StationRecordKey(id, station.Value),
|
|
out var record))
|
|
{
|
|
if (record.Status != PsionicsStatus.None)
|
|
{
|
|
SetPsionicsIcon(name, record.Status, uid);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
RemComp<PsionicsRecordComponent>(uid);
|
|
}
|
|
}
|