From 662a59e5d7e50fb619deb3fd953414692cb35183 Mon Sep 17 00:00:00 2001 From: Vonsant Date: Tue, 3 Dec 2024 02:00:29 +0300 Subject: [PATCH] Sec always watching --- .../Cartridges/SecWatchEntryControl.xaml | 19 +++++ .../Cartridges/SecWatchEntryControl.xaml.cs | 21 +++++ .../CartridgeLoader/Cartridges/SecWatchUi.cs | 27 +++++++ .../Cartridges/SecWatchUiFragment.xaml | 13 ++++ .../Cartridges/SecWatchUiFragment.xaml.cs | 25 ++++++ .../Cartridges/SecWatchCartridgeComponent.cs | 23 ++++++ .../Cartridges/SecWatchCartridgeSystem.cs | 73 ++++++++++++++++++ .../Cartridges/SecWatchUiState.cs | 24 ++++++ .../_corvaxnext/cartridge-loader/secwatch.ftl | 5 ++ .../_corvaxnext/cartridge-loader/secwatch.ftl | 5 ++ .../entities/objects/devices/cartriges.ftl | 2 + .../Entities/Objects/Devices/pda.yml | 4 + .../Entities/Objects/Devices/cartridges.yml | 20 +++++ .../Devices/cartridge.rsi/cart-cri.png | Bin 0 -> 2980 bytes .../Objects/Devices/cartridge.rsi/meta.json | 14 ++++ 15 files changed, 275 insertions(+) create mode 100644 Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml create mode 100644 Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs create mode 100644 Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUi.cs create mode 100644 Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml create mode 100644 Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs create mode 100644 Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs create mode 100644 Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs create mode 100644 Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiState.cs create mode 100644 Resources/Locale/en-US/_corvaxnext/cartridge-loader/secwatch.ftl create mode 100644 Resources/Locale/ru-RU/_corvaxnext/cartridge-loader/secwatch.ftl create mode 100644 Resources/Locale/ru-RU/ss14-ru/prototypes/_corvaxnext/entities/objects/devices/cartriges.ftl create mode 100644 Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/cartridges.yml create mode 100644 Resources/Textures/_CorvaxNext/Objects/Devices/cartridge.rsi/cart-cri.png create mode 100644 Resources/Textures/_CorvaxNext/Objects/Devices/cartridge.rsi/meta.json diff --git a/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml new file mode 100644 index 00000000000..12440db5d9b --- /dev/null +++ b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs new file mode 100644 index 00000000000..0b3bd362d2c --- /dev/null +++ b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs @@ -0,0 +1,21 @@ +using Content.Shared.CartridgeLoader.Cartridges; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._CorvaxNext.CartridgeLoader.Cartridges; + +[GenerateTypedNameReferences] +public sealed partial class SecWatchEntryControl : BoxContainer +{ + public SecWatchEntryControl(SecWatchEntry entry) + { + RobustXamlLoader.Load(this); + + Status.Text = Loc.GetString($"criminal-records-status-{entry.Status.ToString().ToLower()}"); + Title.Text = Loc.GetString("sec-watch-entry", ("name", entry.Name), ("job", entry.Job)); + + Reason.Text = entry.Reason ?? Loc.GetString("sec-watch-no-reason"); + } +} \ No newline at end of file diff --git a/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUi.cs b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUi.cs new file mode 100644 index 00000000000..838f4395c73 --- /dev/null +++ b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUi.cs @@ -0,0 +1,27 @@ +using Content.Client.UserInterface.Fragments; +using Content.Shared.CartridgeLoader; +using Content.Shared.CartridgeLoader.Cartridges; +using Robust.Client.UserInterface; + +namespace Content.Client._CorvaxNext.CartridgeLoader.Cartridges; + +public sealed partial class SecWatchUi : UIFragment +{ + private SecWatchUiFragment? _fragment; + + public override Control GetUIFragmentRoot() + { + return _fragment!; + } + + public override void Setup(BoundUserInterface ui, EntityUid? owner) + { + _fragment = new SecWatchUiFragment(); + } + + public override void UpdateState(BoundUserInterfaceState state) + { + if (state is SecWatchUiState cast) + _fragment?.UpdateState(cast); + } +} \ No newline at end of file diff --git a/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml new file mode 100644 index 00000000000..4ebea90f59c --- /dev/null +++ b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs new file mode 100644 index 00000000000..068ff2c8a38 --- /dev/null +++ b/Content.Client/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs @@ -0,0 +1,25 @@ +using Content.Shared.CartridgeLoader.Cartridges; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._CorvaxNext.CartridgeLoader.Cartridges; + +[GenerateTypedNameReferences] +public sealed partial class SecWatchUiFragment : BoxContainer +{ + public SecWatchUiFragment() + { + RobustXamlLoader.Load(this); + } + + public void UpdateState(SecWatchUiState state) + { + NoEntries.Visible = state.Entries.Count == 0; + Entries.RemoveAllChildren(); + foreach (var entry in state.Entries) + { + Entries.AddChild(new SecWatchEntryControl(entry)); + } + } +} \ No newline at end of file diff --git a/Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs b/Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs new file mode 100644 index 00000000000..f631a95ff11 --- /dev/null +++ b/Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.Security; + +namespace Content.Server.CartridgeLoader.Cartridges; + +[RegisterComponent, Access(typeof(SecWatchCartridgeSystem))] +public sealed partial class SecWatchCartridgeComponent : Component +{ + /// + /// Only show people with these statuses. + /// + [DataField] + public List Statuses = new() + { + SecurityStatus.Suspected, + SecurityStatus.Wanted + }; + + /// + /// Station entity thats getting its records checked. + /// + [DataField] + public EntityUid? Station; +} \ No newline at end of file diff --git a/Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs b/Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs new file mode 100644 index 00000000000..2b46637da12 --- /dev/null +++ b/Content.Server/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs @@ -0,0 +1,73 @@ +using Content.Server.Station.Systems; +using Content.Server.StationRecords; +using Content.Server.StationRecords.Systems; +using Content.Shared.CartridgeLoader; +using Content.Shared.CartridgeLoader.Cartridges; +using Content.Shared.CriminalRecords; +using Content.Shared.StationRecords; + +namespace Content.Server.CartridgeLoader.Cartridges; + +public sealed class SecWatchCartridgeSystem : EntitySystem +{ + [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!; + [Dependency] private readonly StationRecordsSystem _records = default!; + [Dependency] private readonly StationSystem _station = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRecordModified); + + SubscribeLocalEvent(OnUiReady); + } + + private void OnRecordModified(RecordModifiedEvent args) + { + // when a record is modified update the ui of every loaded cartridge tuned to the same station + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp, out var cartridge)) + { + if (cartridge.LoaderUid is not {} loader || comp.Station != args.Station) + continue; + + UpdateUI((uid, comp), loader); + } + } + + private void OnUiReady(Entity ent, ref CartridgeUiReadyEvent args) + { + UpdateUI(ent, args.Loader); + } + + private void UpdateUI(Entity ent, EntityUid loader) + { + // if the loader is on a grid, update the station + // if it is off grid use the cached station + if (_station.GetOwningStation(loader) is {} station) + ent.Comp.Station = station; + + if (!TryComp(ent.Comp.Station, out var records)) + return; + + station = ent.Comp.Station.Value; + + var entries = new List(); + foreach (var (id, criminal) in _records.GetRecordsOfType(station, records)) + { + if (!ent.Comp.Statuses.Contains(criminal.Status)) + continue; + + var key = new StationRecordKey(id, station); + if (!_records.TryGetRecord(key, out var general, records)) + continue; + + var status = criminal.Status; + entries.Add(new SecWatchEntry(general.Name, general.JobTitle, criminal.Status, criminal.Reason)); + } + + var state = new SecWatchUiState(entries); + _cartridgeLoader.UpdateCartridgeUiState(loader, state); + } +} \ No newline at end of file diff --git a/Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiState.cs b/Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiState.cs new file mode 100644 index 00000000000..29720630c43 --- /dev/null +++ b/Content.Shared/_CorvaxNext/CartridgeLoader/Cartridges/SecWatchUiState.cs @@ -0,0 +1,24 @@ +using Content.Shared.Security; +using Robust.Shared.Serialization; + +namespace Content.Shared.CartridgeLoader.Cartridges; + +/// +/// Show a list of wanted and suspected people from criminal records. +/// +[Serializable, NetSerializable] +public sealed class SecWatchUiState : BoundUserInterfaceState +{ + public readonly List Entries; + + public SecWatchUiState(List entries) + { + Entries = entries; + } +} + +/// +/// Entry for a person who is wanted or suspected. +/// +[Serializable, NetSerializable] +public record struct SecWatchEntry(string Name, string Job, SecurityStatus Status, string? Reason); \ No newline at end of file diff --git a/Resources/Locale/en-US/_corvaxnext/cartridge-loader/secwatch.ftl b/Resources/Locale/en-US/_corvaxnext/cartridge-loader/secwatch.ftl new file mode 100644 index 00000000000..ca18db233aa --- /dev/null +++ b/Resources/Locale/en-US/_corvaxnext/cartridge-loader/secwatch.ftl @@ -0,0 +1,5 @@ +sec-watch-program-name = SecWatch +sec-watch-title = SecWatch 1.0 +sec-watch-no-entries = Everything's calm. Why not enjoy a Monkin Donut? +sec-watch-entry = {$name} +sec-watch-no-reason = None given??? \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_corvaxnext/cartridge-loader/secwatch.ftl b/Resources/Locale/ru-RU/_corvaxnext/cartridge-loader/secwatch.ftl new file mode 100644 index 00000000000..bd9a5070cb0 --- /dev/null +++ b/Resources/Locale/ru-RU/_corvaxnext/cartridge-loader/secwatch.ftl @@ -0,0 +1,5 @@ +sec-watch-program-name = ОКО СБ +sec-watch-title = ОКО СБ 1.0 +sec-watch-no-entries = Полный порядок. Безопасность превыше всего. +sec-watch-entry = {$name} +sec-watch-no-reason = Причина не уточнена. \ No newline at end of file diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/_corvaxnext/entities/objects/devices/cartriges.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/_corvaxnext/entities/objects/devices/cartriges.ftl new file mode 100644 index 00000000000..427dadde5e1 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/_corvaxnext/entities/objects/devices/cartriges.ftl @@ -0,0 +1,2 @@ +ent-SecWatchCartridge = картридж "око сб" + .desc = Картридж, отслеживающий статус разыскиваемых службой безопасности лиц. \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml index 4febc87b90f..8b13d2598bb 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml @@ -76,6 +76,7 @@ - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge + - SecWatchCartridge # Corvax-Next-SecWatch cartridgeSlot: priority: -1 name: device-pda-slot-component-slot-name-cartridge @@ -138,6 +139,7 @@ - NotekeeperCartridge - NewsReaderCartridge - MedTekCartridge + - SecWatchCartridge # Corvax-Next-SecWatch - type: entity parent: BasePDA @@ -408,6 +410,7 @@ - NotekeeperCartridge - NewsReaderCartridge - AstroNavCartridge + - SecWatchCartridge # Corvax-Next-SecWatch - type: entity parent: BasePDA @@ -773,6 +776,7 @@ - WantedListCartridge - MedTekCartridge - AstroNavCartridge + - SecWatchCartridge # Corvax-Next-SecWatch - type: entity parent: CentcomPDA diff --git a/Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/cartridges.yml b/Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/cartridges.yml new file mode 100644 index 00000000000..b271eb6378f --- /dev/null +++ b/Resources/Prototypes/_CorvaxNext/Entities/Objects/Devices/cartridges.yml @@ -0,0 +1,20 @@ +- type: entity + parent: BaseItem + id: SecWatchCartridge + name: sec watch cartridge + description: A cartridge that tracks the status of currently wanted individuals. + components: + - type: Sprite + sprite: _CorvaxNext/Objects/Devices/cartridge.rsi + state: cart-cri + - type: Icon + sprite: _CorvaxNext/Objects/Devices/cartridge.rsi + state: cart-cri + - type: UIFragment + ui: !type:SecWatchUi + - type: Cartridge + programName: sec-watch-program-name + icon: + sprite: Objects/Weapons/Melee/stunbaton.rsi + state: stunbaton_on + - type: SecWatchCartridge \ No newline at end of file diff --git a/Resources/Textures/_CorvaxNext/Objects/Devices/cartridge.rsi/cart-cri.png b/Resources/Textures/_CorvaxNext/Objects/Devices/cartridge.rsi/cart-cri.png new file mode 100644 index 0000000000000000000000000000000000000000..4da4343e58455a723ad5030373db49c84d546651 GIT binary patch literal 2980 zcmV;V3tRMwP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}0002LNklHrpE z6*4k1GMJjG;jK7MpT5ONYTZJ#158cT{+pXS5K{J^fq{XMCJumscke!66&Df`pidfb zc=(jT;o(yTAt3<I^v+)$xLm-!W&{1RA+n`k zLjvfN4PoGtp*DnZ_cjBAp*Di1mjebo7YtZQ$iTqBaPs5