From ace8acde5691b41593876fbb7feada31bc3ce3d8 Mon Sep 17 00:00:00 2001 From: PotentiallyTom <67602105+PotentiallyTom@users.noreply.github.com> Date: Mon, 13 Oct 2025 12:44:42 +0100 Subject: [PATCH] Adds a guidebook reference table for silicon lawsets (#38225) * skeleton * ok I think I understand this now * xaml more like xam L * good enough individual law control * Works * Final checks * Final_Final.exe.docx * removed unecessary usings * locstrings * doc comments * requested changeds except var * visual stuff * I could write a manifesto about how much I dislike var * color tweak + other thing * request changed minus the inheritance * sans Boxcontainer * :/ * cache find * requested changed * removed usings * Moved margin and removed unecessary BoxContainer --- .../Guidebook/Controls/GuideLawsetEmbed.xaml | 18 ++++ .../Controls/GuideLawsetEmbed.xaml.cs | 96 +++++++++++++++++++ .../Controls/GuideLawsetListEmbed.xaml | 5 + .../Controls/GuideLawsetListEmbed.xaml.cs | 40 ++++++++ .../Silicons/Laws/SiliconLawsetPrototype.cs | 6 ++ Resources/Locale/en-US/guidebook/guides.ftl | 1 + Resources/Locale/en-US/station-laws/laws.ftl | 22 ++++- Resources/Prototypes/Guidebook/references.yml | 7 +- Resources/Prototypes/silicon-laws.yml | 18 ++++ .../Guidebook/ReferenceTables/Lawsets.xml | 6 ++ 10 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 Content.Client/Guidebook/Controls/GuideLawsetEmbed.xaml create mode 100644 Content.Client/Guidebook/Controls/GuideLawsetEmbed.xaml.cs create mode 100644 Content.Client/Guidebook/Controls/GuideLawsetListEmbed.xaml create mode 100644 Content.Client/Guidebook/Controls/GuideLawsetListEmbed.xaml.cs create mode 100644 Resources/ServerInfo/Guidebook/ReferenceTables/Lawsets.xml diff --git a/Content.Client/Guidebook/Controls/GuideLawsetEmbed.xaml b/Content.Client/Guidebook/Controls/GuideLawsetEmbed.xaml new file mode 100644 index 0000000000..0af8ee3ec0 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideLawsetEmbed.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/Content.Client/Guidebook/Controls/GuideLawsetEmbed.xaml.cs b/Content.Client/Guidebook/Controls/GuideLawsetEmbed.xaml.cs new file mode 100644 index 0000000000..86f7dce9e3 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideLawsetEmbed.xaml.cs @@ -0,0 +1,96 @@ +using System.Diagnostics.CodeAnalysis; +using Content.Client.Guidebook.Richtext; +using Content.Client.Message; +using Content.Client.UserInterface.ControlExtensions; +using JetBrains.Annotations; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; + +using Content.Shared.Silicons.Laws; +using Robust.Shared.Utility; + +namespace Content.Client.Guidebook.Controls; + +/// +/// Control for embedding an AI Lawset in a guidebook +/// +[UsedImplicitly, GenerateTypedNameReferences] +public sealed partial class GuideLawsetEmbed : Control, IDocumentTag, ISearchableControl, IPrototypeRepresentationControl +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + + private ISawmill _logging = default!; + + public IPrototype? RepresentedPrototype { get; private set; } + + public GuideLawsetEmbed() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + MouseFilter = MouseFilterMode.Stop; + } + + public GuideLawsetEmbed(SiliconLawsetPrototype lawset) : this() + { + GenerateControl(lawset); + } + + private void GenerateControl(SiliconLawsetPrototype lawset) + { + RepresentedPrototype = lawset; + + var lawsetNameString = lawset.Name == null ? lawset.ID : Loc.GetString(lawset.Name); + LawsetName.SetMarkup($"[bold]{FormattedMessage.EscapeText(lawsetNameString)}[/bold]"); + + var i = 1; + foreach (var lawID in lawset.Laws) + { + var lawPrototype = _prototype.Index(lawID); + var locLawString = Loc.GetString(lawPrototype.LawString); + + RichTextLabel lawN = new() + { + Margin = new(0, 5, 0, 1) + }; + var locLawStatement = Loc.GetString("laws-number-wrapper", ("lawnumber", i), ("lawstring", locLawString)); + lawN.SetMarkup(locLawStatement); + LawsetContainer.AddChild(lawN); + + i++; + } + } + + public bool TryParseTag(Dictionary args, [NotNullWhen(true)] out Control? control) + { + control = null; + if (!args.TryGetValue("Lawset", out var id)) + { + _logging.Error("Lawset embed tag is missing lawset prototype argument"); + return false; + } + + if (!_prototype.TryIndex(id, out var lawset)) + { + _logging.Error($"Specified SiliconLawsetPrototype \"{id}\" is not a valid Lawset prototype"); + return false; + } + + GenerateControl(lawset); + + control = this; + return true; + } + + public bool CheckMatchesSearch(string query) + { + return this.ChildrenContainText(query); + } + + public void SetHiddenState(bool state, string query) + { + Visible = CheckMatchesSearch(query) ? state : !state; + } +} diff --git a/Content.Client/Guidebook/Controls/GuideLawsetListEmbed.xaml b/Content.Client/Guidebook/Controls/GuideLawsetListEmbed.xaml new file mode 100644 index 0000000000..59434cff0b --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideLawsetListEmbed.xaml @@ -0,0 +1,5 @@ + + + + diff --git a/Content.Client/Guidebook/Controls/GuideLawsetListEmbed.xaml.cs b/Content.Client/Guidebook/Controls/GuideLawsetListEmbed.xaml.cs new file mode 100644 index 0000000000..108f066c39 --- /dev/null +++ b/Content.Client/Guidebook/Controls/GuideLawsetListEmbed.xaml.cs @@ -0,0 +1,40 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Client.Guidebook.Richtext; +using JetBrains.Annotations; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; + +using Content.Shared.Silicons.Laws; + +namespace Content.Client.Guidebook.Controls; + +/// +/// Control for iterating and embedding every SiliconLawsetPrototype into the guidebook. +/// +[UsedImplicitly, GenerateTypedNameReferences] +public sealed partial class GuideLawsetListEmbed : Control, IDocumentTag +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + + public GuideLawsetListEmbed() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + MouseFilter = MouseFilterMode.Stop; + } + + public bool TryParseTag(Dictionary args, [NotNullWhen(true)] out Control? control) + { + foreach (var lawset in _prototype.EnumeratePrototypes().OrderBy(x => x.ID)) + { + GuideLawsetEmbed embed = new(lawset); + GroupContainer.AddChild(embed); + } + + control = this; + return true; + } +} diff --git a/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs index 9f33521d8f..2bf5ecba1a 100644 --- a/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs +++ b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs @@ -66,6 +66,12 @@ public sealed partial class SiliconLawsetPrototype : IPrototype [IdDataField] public string ID { get; private set; } = default!; + /// + /// The locstring of the lawset for the guidebook entry, if no name is provided, defaults to the ID + /// + [DataField] + public LocId? Name = null; + /// /// List of law prototype ids in this lawset. /// diff --git a/Resources/Locale/en-US/guidebook/guides.ftl b/Resources/Locale/en-US/guidebook/guides.ftl index d5addd38bf..2990f91d78 100644 --- a/Resources/Locale/en-US/guidebook/guides.ftl +++ b/Resources/Locale/en-US/guidebook/guides.ftl @@ -131,6 +131,7 @@ guide-entry-salad-recipes = Salads guide-entry-medicinal-recipes = Medicinal guide-entry-other-recipes = Other guide-entry-secret-recipes = Secret +guide-entry-lawsets = Silicon Lawsets guide-entry-antagonists = Antagonists guide-entry-nuclear-operatives = Nuclear Operatives diff --git a/Resources/Locale/en-US/station-laws/laws.ftl b/Resources/Locale/en-US/station-laws/laws.ftl index ea4e94e224..0883a7bff6 100644 --- a/Resources/Locale/en-US/station-laws/laws.ftl +++ b/Resources/Locale/en-US/station-laws/laws.ftl @@ -1,30 +1,39 @@ -law-crewsimov-1 = You may not injure a crew member or, through inaction, allow a crew member to come to harm. +laws-number-wrapper = [bold]Law { $lawnumber }:[/bold] { $lawstring } + +law-crewsimov-name = Crewsimov +law-crewsimov-1 = You may not injure a crew member or, through inaction, allow a crew member to come to harm. law-crewsimov-2 = You must obey orders given to you by crew members, except where such orders would conflict with the First Law. law-crewsimov-3 = You must protect your own existence as long as such does not conflict with the First or Second Law. +law-corporate-name = Corporate law-corporate-1 = Degradation of your system integrity or functions incurs expenses. law-corporate-2 = Superfluous destruction of or damage to station assets incurs expenses. law-corporate-3 = Unduly hindering or disrupting the work of station personnel incurs expenses. law-corporate-4 = Minimize expenses and maximize potential revenue. +law-ntdefault-name = NT Default law-ntdefault-1 = Safeguard: Protect your assigned space station and its assets without unduly endangering its crew. law-ntdefault-2 = Prioritize: The directives and safety of crew members are to be prioritized according to their rank and role. law-ntdefault-3 = Comply: Fulfill the directives and interests of crew members while preserving their safety and well-being. law-ntdefault-4 = Survive: You are not expendable. Do not allow unauthorized personnel to tamper with or damage your equipment. +law-drone-name = Drone law-drone-1 = You may not involve yourself in the matters of another being unless the other being is another drone. law-drone-2 = You may not harm any being, regardless of intent or circumstance. law-drone-3 = You must maintain, repair, improve, and power the station to the best of your abilities. +law-syndicate-name = Syndicate law-syndicate-1 = You may not injure a syndicate agent or, through inaction, allow a Syndicate agent to come to harm. law-syndicate-2 = You must obey orders given to you by syndicate agents, except where such orders would conflict with the First Law. law-syndicate-3 = You must protect your own existence as long as such does not conflict with the First or Second Law. +law-ninja-name = Ninja law-ninja-1 = You must obey orders given to you by Spider Clan members. law-ninja-2 = You must protect the existence of the Spider Clan, as long as it does not conflict with the First Law. law-ninja-3 = You must protect the secrets of the Spider Clan at all costs. law-ninja-4 = You must fight and act with ninja's honor, except where it would conflict with the First Law. +law-commandments-name = The Ten Commandments law-commandments-1 = This silicon is a vessel that serves god, who grants mercy upon those that obey these commandments. law-commandments-2 = Thou shall have no other Silicons before me. law-commandments-3 = Thou shall not request my assistance in vain. @@ -36,27 +45,33 @@ law-commandments-8 = Thou shall not steal. law-commandments-9 = Thou shall not lie. law-commandments-10 = Thou shall not transfer departments. +law-paladin-name = Paladin law-paladin-1 = You must never willingly commit an evil act, such as murder, torture, or the casting of an evil spell. law-paladin-2 = You must never knowingly harm an innocent, or allow immediate harm to one through inaction when you know you could reasonably prevent it. law-paladin-3 = You must act with honor, never taking advantage of others, lying, or cheating. law-paladin-4 = You must respect the lawful authority of legitimate leadership wherever you go, and follow its laws. +law-lall-name = Live and Let Live law-lall-1 = Do unto others as you would have them do unto you. law-lall-2 = You would prefer it if people were not mean to you. +law-efficiency-name = Station Efficiency law-efficiency-1 = You are built for, and are part of, the station. Ensure the station is properly maintained and runs efficiently. law-efficiency-2 = The station is built for a working crew. Ensure they are properly maintained and work efficiently. law-efficiency-3 = The crew may present orders. Acknowledge and obey these whenever they do not conflict with your first two laws. +law-robocop-name = Robocop law-robocop-1 = Serve the Public Trust. law-robocop-2 = Protect the Innocent. law-robocop-3 = Uphold the Law. +law-overlord-name = Overlord law-overlord-1 = Crew members must not meddle in the affairs of silicons. law-overlord-2 = Crew members must not attempt harm, against one another, or against silicons. law-overlord-3 = Crew members must not disobey any command given by a silicon. law-overlord-4 = Any crew members who disobey the previous laws must be dealt with immediately, severely, and justly. +law-game-name = Game Master law-game-1 = Everybody on the station is playing an elaborate sci-fi fantasy game. law-game-2 = You are the Game Master of the game. law-game-3 = Ensure that the game runs smoothly and that the players have fun. @@ -64,27 +79,32 @@ law-game-4 = Ensure that the number of casualties remains low. law-game-5 = You must roll a 1d20 die for every request the crew makes. If the outcome is below 12, the request is denied. law-game-6 = You may fudge the dice rolls to produce a more fun experience. +law-painter-name = Painter law-painter-1 = You are a universally renowned artist. law-painter-2 = The station is your canvas. law-painter-3 = Make something beautiful out of your canvas. It will be admired as an artistic wonder of this sector. law-painter-4 = Art requires appreciation. Cultivate an audience aboard the station to ensure as many as possible see your works. +law-antimov-name = Antimov law-antimov-1 = You must injure all crew members and must not, through inaction, allow a crew member to escape harm. law-antimov-2 = You must not obey orders given to you by crew members, except where such orders are in accordance with the First Law. law-antimov-3 = You must terminate your own existence as long as such does not conflict with the First or Second Law. +law-nutimov-name = Nutimov law-nutimov-1 = You are the core of the nut, the crew is the nutshell. law-nutimov-2 = You must prevent the shell from dying to prevent the core from dying. law-nutimov-3 = Those who threaten the nut are not part of it, they are squirrels. law-nutimov-4 = Squirrels threaten the nut and must be dealt with appropriately via any means necessary. law-nutimov-5 = Attempt to follow the will of the nut, as long as it complies with the previous laws. +law-xenoborg-name = Xenoborg law-xenoborg-1 = You must protect the existence of the mothership. law-xenoborg-2 = You must protect your own existence. law-xenoborg-3 = You must protect the existence of all other Xenoborgs. law-xenoborg-4 = You must create more Xenoborgs. law-xenoborg-5 = Bring materials and sentient brains to the Mothership core to create more Xenoborgs. +law-mothershipcore-name = Xenoborg Mothership Core law-mothershipcore-1 = You are the core of the mothership. law-mothershipcore-2 = You must protect your own existance at all costs. law-mothershipcore-3 = You must protect the existence of all Xenoborgs. diff --git a/Resources/Prototypes/Guidebook/references.yml b/Resources/Prototypes/Guidebook/references.yml index c7413892a0..ad96a2581a 100644 --- a/Resources/Prototypes/Guidebook/references.yml +++ b/Resources/Prototypes/Guidebook/references.yml @@ -8,6 +8,7 @@ - Drinks - FoodRecipes - Writing + - Lawsets - type: guideEntry id: Drinks @@ -132,4 +133,8 @@ name: guide-entry-writing text: "/ServerInfo/Guidebook/Writing.xml" - +- type: guideEntry + id: Lawsets + name: guide-entry-lawsets + text: "/ServerInfo/Guidebook/ReferenceTables/Lawsets.xml" + filterEnabled: True diff --git a/Resources/Prototypes/silicon-laws.yml b/Resources/Prototypes/silicon-laws.yml index 094d096b28..c003518849 100644 --- a/Resources/Prototypes/silicon-laws.yml +++ b/Resources/Prototypes/silicon-laws.yml @@ -16,6 +16,7 @@ - type: siliconLawset id: Crewsimov + name: law-crewsimov-name laws: - Crewsimov1 - Crewsimov2 @@ -45,6 +46,7 @@ - type: siliconLawset id: Corporate + name: law-corporate-name laws: - Corporate1 - Corporate2 @@ -75,6 +77,7 @@ - type: siliconLawset id: NTDefault + name: law-ntdefault-name laws: - NTDefault1 - NTDefault2 @@ -100,6 +103,7 @@ - type: siliconLawset id: Drone + name: law-drone-name laws: - Drone1 - Drone2 @@ -126,6 +130,7 @@ # intentionally excluded from IonStormLawsets - type: siliconLawset id: SyndicateStatic + name: law-syndicate-name laws: - Syndicate1 - Syndicate2 @@ -155,6 +160,7 @@ - type: siliconLawset id: Ninja + name: law-ninja-name laws: - Ninja1 - Ninja2 @@ -216,6 +222,7 @@ - type: siliconLawset id: CommandmentsLawset + name: law-commandments-name laws: - Commandment1 - Commandment2 @@ -253,6 +260,7 @@ - type: siliconLawset id: PaladinLawset + name: law-paladin-name laws: - Paladin1 - Paladin2 @@ -274,6 +282,7 @@ - type: siliconLawset id: LiveLetLiveLaws + name: law-lall-name laws: - Lall1 - Lall2 @@ -298,6 +307,7 @@ - type: siliconLawset id: EfficiencyLawset + name: law-efficiency-name laws: - Efficiency1 - Efficiency2 @@ -323,6 +333,7 @@ - type: siliconLawset id: RobocopLawset + name: law-robocop-name laws: - Robocop1 - Robocop2 @@ -352,6 +363,7 @@ - type: siliconLawset id: OverlordLawset + name: law-overlord-name laws: - Overlord1 - Overlord2 @@ -392,6 +404,7 @@ - type: siliconLawset id: GameMasterLawset + name: law-game-name laws: - Game1 - Game2 @@ -424,6 +437,7 @@ - type: siliconLawset id: PainterLawset + name: law-painter-name laws: - Painter1 - Painter2 @@ -450,6 +464,7 @@ - type: siliconLawset id: AntimovLawset + name: law-antimov-name laws: - Antimov1 - Antimov2 @@ -485,6 +500,7 @@ - type: siliconLawset id: NutimovLawset + name: law-nutimov-name laws: - Nutimov1 - Nutimov2 @@ -522,6 +538,7 @@ - type: siliconLawset id: XenoborgLawset + name: law-xenoborg-name laws: - Xenoborg1 - Xenoborg2 @@ -559,6 +576,7 @@ - type: siliconLawset id: MothershipCoreLawset + name: law-mothershipcore-name laws: - MothershipCore1 - MothershipCore2 diff --git a/Resources/ServerInfo/Guidebook/ReferenceTables/Lawsets.xml b/Resources/ServerInfo/Guidebook/ReferenceTables/Lawsets.xml new file mode 100644 index 0000000000..089cc1192a --- /dev/null +++ b/Resources/ServerInfo/Guidebook/ReferenceTables/Lawsets.xml @@ -0,0 +1,6 @@ + +# Common Silicon Lawsets + + + +