From b9af991e04c58371a341cd6cc609e0ae98b42f2d Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Fri, 27 Oct 2023 03:40:13 +0100 Subject: [PATCH] Ion storm event (#20277) * ion storm event prototype + locale * add lawsets * use lawsets, make borgs ion storm targets * ion storm rule and ion storm target * lawset prototype * use lawsets * update silicon law system to use lawsets and support ion storm event * new toys * fix * more fix * fixy * ion storm admin logging * assigning laws makes borg provide its own laws, other stuff * 1h reoccurence * 50% chance * better call saul * emagLaws is required * add announcment audio * fixy * family friendly gaming * fixy * address reviews * fixy * more fixy and no erp * pro --------- Co-authored-by: deltanedas <@deltanedas:kde.org> --- .../Silicons/Laws/SiliconLawSystem.cs | 84 +- .../Components/IonStormRuleComponent.cs | 9 + .../StationEvents/Events/IonStormRule.cs | 273 +++++ .../Components/EmagSiliconLawComponent.cs | 31 +- .../Components/IonStarmTargetComponent.cs | 54 + .../Components/SiliconLawBoundComponent.cs | 11 +- .../Components/SiliconLawProviderComponent.cs | 15 +- .../Silicons/Laws/SiliconLawPrototype.cs | 21 +- .../Silicons/Laws/SiliconLawsetPrototype.cs | 69 ++ .../Audio/Announcements/attributions.yml | 4 + Resources/Audio/Announcements/ion_storm.ogg | Bin 0 -> 50216 bytes .../en-US/station-events/events/ion-storm.ftl | 90 ++ Resources/Prototypes/Datasets/ion_storm.yml | 990 ++++++++++++++++++ .../Mobs/Cyborgs/base_borg_chassis.yml | 7 +- .../Entities/Mobs/Player/silicon.yml | 5 +- .../Prototypes/Entities/Stations/base.yml | 5 +- Resources/Prototypes/GameRules/events.yml | 15 + Resources/Prototypes/silicon-laws.yml | 50 + 18 files changed, 1675 insertions(+), 58 deletions(-) create mode 100644 Content.Server/StationEvents/Components/IonStormRuleComponent.cs create mode 100644 Content.Server/StationEvents/Events/IonStormRule.cs create mode 100644 Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs create mode 100644 Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs create mode 100644 Resources/Audio/Announcements/attributions.yml create mode 100644 Resources/Audio/Announcements/ion_storm.ogg create mode 100644 Resources/Locale/en-US/station-events/events/ion-storm.ftl create mode 100644 Resources/Prototypes/Datasets/ion_storm.yml diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index beb760ec8f..45c944884e 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -50,7 +50,9 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem SubscribeLocalEvent(OnPlayerSpawnComplete); SubscribeLocalEvent(OnDirectedGetLaws); + SubscribeLocalEvent(OnIonStormLaws); SubscribeLocalEvent(OnDirectedEmagGetLaws); + SubscribeLocalEvent(OnEmagIonStormLaws); SubscribeLocalEvent(OnEmagMindAdded); SubscribeLocalEvent(OnEmagMindRemoved); SubscribeLocalEvent(OnExamined); @@ -93,7 +95,7 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem _entityManager.TryGetComponent(uid, out var intrinsicRadio); HashSet? radioChannels = intrinsicRadio?.Channels; - var state = new SiliconLawBuiState(GetLaws(uid), radioChannels); + var state = new SiliconLawBuiState(GetLaws(uid).Laws, radioChannels); _userInterface.TrySetUiState(args.Entity, SiliconLawsUiKey.Key, state, (IPlayerSession) args.Session); } @@ -104,38 +106,66 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem private void OnDirectedGetLaws(EntityUid uid, SiliconLawProviderComponent component, ref GetSiliconLawsEvent args) { - if (args.Handled || HasComp(uid) || component.Laws.Count == 0) + if (args.Handled || HasComp(uid)) return; - foreach (var law in component.Laws) - { - args.Laws.Add(_prototype.Index(law)); - } + if (component.Lawset == null) + component.Lawset = GetLawset(component.Laws); + + args.Laws = component.Lawset; args.Handled = true; } + private void OnIonStormLaws(EntityUid uid, SiliconLawProviderComponent component, ref IonStormLawsEvent args) + { + if (HasComp(uid)) + return; + + component.Lawset = args.Lawset; + + // gotta tell player to check their laws + NotifyLawsChanged(uid); + + // new laws may allow antagonist behaviour so make it clear for admins + if (TryComp(uid, out var emag)) + EnsureEmaggedRole(uid, emag); + } + private void OnDirectedEmagGetLaws(EntityUid uid, EmagSiliconLawComponent component, ref GetSiliconLawsEvent args) { if (args.Handled || !HasComp(uid) || component.OwnerName == null) return; - // Add the first emag law - args.Laws.Add(new SiliconLaw + if (component.Lawset == null) { - LawString = Loc.GetString("law-emag-custom", ("name", component.OwnerName)), - Order = 0 - }); + // Add new emagged laws + component.Lawset = GetLawset(component.EmagLaws); - // Add new emagged laws - foreach (var law in component.EmagLaws) - { - args.Laws.Add(_prototype.Index(law)); + // Add the first emag law before the others + component.Lawset.Laws.Insert(0, new SiliconLaw + { + LawString = Loc.GetString("law-emag-custom", ("name", component.OwnerName)), + Order = 0 + }); } + args.Laws = component.Lawset; + args.Handled = true; } + private void OnEmagIonStormLaws(EntityUid uid, EmagSiliconLawComponent component, ref IonStormLawsEvent args) + { + if (!HasComp(uid)) + return; + + component.Lawset = args.Lawset; + + // gotta tell player to check their laws + NotifyLawsChanged(uid); + } + private void OnExamined(EntityUid uid, EmagSiliconLawComponent component, ExaminedEvent args) { if (!args.IsInDetailsRange || !HasComp(uid)) @@ -184,10 +214,10 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem _roles.MindAddRole(mindId, new SubvertedSiliconRoleComponent { PrototypeId = component.AntagonistRole }); } - public List GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null) + public SiliconLawset GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null) { if (!Resolve(uid, ref component)) - return new List(); + return new SiliconLawset(); var ev = new GetSiliconLawsEvent(uid); @@ -248,6 +278,24 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", msg)); _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMessage, default, false, actor.PlayerSession.ConnectedClient, colorOverride: Color.Red); } + + /// + /// Extract all the laws from a lawset's prototype ids. + /// + public SiliconLawset GetLawset(string lawset) + { + var proto = _prototype.Index(lawset); + var laws = new SiliconLawset() + { + Laws = new List(proto.Laws.Count) + }; + foreach (var law in proto.Laws) + { + laws.Laws.Add(_prototype.Index(law)); + } + + return laws; + } } [ToolshedCommand, AdminCommand(AdminFlags.Admin)] @@ -270,7 +318,7 @@ public sealed class LawsCommand : ToolshedCommand { _law ??= GetSys(); - foreach (var law in _law.GetLaws(lawbound)) + foreach (var law in _law.GetLaws(lawbound).Laws) { yield return $"law {law.LawIdentifierOverride ?? law.Order.ToString()}: {Loc.GetString(law.LawString)}"; } diff --git a/Content.Server/StationEvents/Components/IonStormRuleComponent.cs b/Content.Server/StationEvents/Components/IonStormRuleComponent.cs new file mode 100644 index 0000000000..35b59f5b35 --- /dev/null +++ b/Content.Server/StationEvents/Components/IonStormRuleComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.StationEvents.Components; + +/// +/// Gamerule component to mess up ai/borg laws when started. +/// +[RegisterComponent] +public sealed partial class IonStormRuleComponent : Component +{ +} diff --git a/Content.Server/StationEvents/Events/IonStormRule.cs b/Content.Server/StationEvents/Events/IonStormRule.cs new file mode 100644 index 0000000000..e5b68c4d84 --- /dev/null +++ b/Content.Server/StationEvents/Events/IonStormRule.cs @@ -0,0 +1,273 @@ +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Silicons.Laws; +using Content.Server.Station.Components; +using Content.Server.StationEvents.Components; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Dataset; +using Content.Shared.FixedPoint; +using Content.Shared.Random; +using Content.Shared.Random.Helpers; +using Content.Shared.Silicons.Laws; +using Content.Shared.Silicons.Laws.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.StationEvents.Events; + +public sealed class IonStormRule : StationEventSystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SiliconLawSystem _siliconLaw = default!; + + // funny + [ValidatePrototypeId] + private const string Threats = "IonStormThreats"; + [ValidatePrototypeId] + private const string Objects = "IonStormObjects"; + [ValidatePrototypeId] + private const string Crew = "IonStormCrew"; + [ValidatePrototypeId] + private const string Adjectives = "IonStormAdjectives"; + [ValidatePrototypeId] + private const string Verbs = "IonStormVerbs"; + [ValidatePrototypeId] + private const string NumberBase = "IonStormNumberBase"; + [ValidatePrototypeId] + private const string NumberMod = "IonStormNumberMod"; + [ValidatePrototypeId] + private const string Areas = "IonStormAreas"; + [ValidatePrototypeId] + private const string Feelings = "IonStormFeelings"; + [ValidatePrototypeId] + private const string FeelingsPlural = "IonStormFeelingsPlural"; + [ValidatePrototypeId] + private const string Musts = "IonStormMusts"; + [ValidatePrototypeId] + private const string Requires = "IonStormRequires"; + [ValidatePrototypeId] + private const string Actions = "IonStormActions"; + [ValidatePrototypeId] + private const string Allergies = "IonStormAllergies"; + [ValidatePrototypeId] + private const string AllergySeverities = "IonStormAllergySeverities"; + [ValidatePrototypeId] + private const string Species = "IonStormSpecies"; + [ValidatePrototypeId] + private const string Concepts = "IonStormConcepts"; + [ValidatePrototypeId] + private const string Drinks = "IonStormDrinks"; + [ValidatePrototypeId] + private const string Foods = "IonStormFoods"; + + protected override void Started(EntityUid uid, IonStormRuleComponent comp, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, comp, gameRule, args); + + if (!TryGetRandomStation(out var chosenStation)) + return; + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var ent, out var lawBound, out var xform, out var target)) + { + // only affect law holders on the station + if (CompOrNull(xform.GridUid)?.Station != chosenStation) + continue; + + if (!RobustRandom.Prob(target.Chance)) + continue; + + var laws = _siliconLaw.GetLaws(ent, lawBound); + if (laws.Laws.Count == 0) + continue; + + // try to swap it out with a random lawset + if (RobustRandom.Prob(target.RandomLawsetChance)) + { + var lawsets = PrototypeManager.Index(target.RandomLawsets); + var lawset = lawsets.Pick(RobustRandom); + laws = _siliconLaw.GetLawset(lawset); + } + else + { + // clone it so not modifying stations lawset + laws = laws.Clone(); + } + + // shuffle them all + if (RobustRandom.Prob(target.ShuffleChance)) + { + // hopefully work with existing glitched laws if there are multiple ion storms + FixedPoint2 baseOrder = FixedPoint2.New(1); + foreach (var law in laws.Laws) + { + if (law.Order < baseOrder) + baseOrder = law.Order; + } + + RobustRandom.Shuffle(laws.Laws); + + // change order based on shuffled position + for (int i = 0; i < laws.Laws.Count; i++) + { + laws.Laws[i].Order = baseOrder + i; + } + } + + // see if we can remove a random law + if (laws.Laws.Count > 0 && RobustRandom.Prob(target.RemoveChance)) + { + var i = RobustRandom.Next(laws.Laws.Count); + laws.Laws.RemoveAt(i); + } + + // generate a new law... + var newLaw = GenerateLaw(); + + // see if the law we add will replace a random existing law or be a new glitched order one + if (laws.Laws.Count > 0 && RobustRandom.Prob(target.ReplaceChance)) + { + var i = RobustRandom.Next(laws.Laws.Count); + laws.Laws[i] = new SiliconLaw() + { + LawString = newLaw, + Order = laws.Laws[i].Order + }; + } + else + { + laws.Laws.Insert(0, new SiliconLaw() + { + LawString = newLaw, + Order = -1, + LawIdentifierOverride = "#" + }); + } + + _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent):silicon} had its laws changed by an ion storm to {laws.LoggingString()}"); + + // laws unique to this silicon, dont use station laws anymore + EnsureComp(ent); + var ev = new IonStormLawsEvent(laws); + RaiseLocalEvent(ent, ref ev); + } + } + + // for your own sake direct your eyes elsewhere + private string GenerateLaw() + { + // pick all values ahead of time to make the logic cleaner + var threats = Pick(Threats); + var objects = Pick(Objects); + var crew1 = Pick(Crew); + var crew2 = Pick(Crew); + var adjective = Pick(Adjectives); + var verb = Pick(Verbs); + var number = Pick(NumberBase) + " " + Pick(NumberMod); + var area = Pick(Areas); + var feeling = Pick(Feelings); + var feelingPlural = Pick(FeelingsPlural); + var must = Pick(Musts); + var require = Pick(Requires); + var action = Pick(Actions); + var allergy = Pick(Allergies); + var allergySeverity = Pick(AllergySeverities); + var species = Pick(Species); + var concept = Pick(Concepts); + var drink = Pick(Drinks); + var food = Pick(Foods); + + var joined = $"{number} {adjective}"; + // a lot of things have subjects of a threat/crew/object + var triple = RobustRandom.Next(0, 3) switch + { + 0 => threats, + 1 => crew1, + 2 => objects + }; + var crewAll = RobustRandom.Prob(0.5f) ? crew2 : Loc.GetString("ion-storm-crew"); + var objectsThreats = RobustRandom.Prob(0.5f) ? objects : threats; + var objectsConcept = RobustRandom.Prob(0.5f) ? objects : concept; + // s goes ahead of require, is/are + // i dont think theres a way to do this in fluent + var (who, plural) = RobustRandom.Next(0, 5) switch + { + 0 => (Loc.GetString("ion-storm-you"), false), + 1 => (Loc.GetString("ion-storm-the-station"), true), + 2 => (Loc.GetString("ion-storm-the-crew"), true), + 3 => (Loc.GetString("ion-storm-the-job", ("job", crew2)), false), + _ => (area, true) // THE SINGULARITY REQUIRES THE HAPPY CLOWNS + }; + var jobChange = RobustRandom.Next(0, 3) switch + { + 0 => crew1, + 1 => Loc.GetString("ion-storm-clowns"), + _ => Loc.GetString("ion-storm-heads") + }; + var part = Loc.GetString("ion-storm-part", ("part", RobustRandom.Prob(0.5f))); + var harm = RobustRandom.Next(0, 7) switch + { + 0 => concept, + 1 => $"{adjective} {threats}", + 2 => $"{adjective} {objects}", + 3 => Loc.GetString("ion-storm-adjective-things", ("adjective", adjective)), + 4 => species, + 5 => crew1, + _ => Loc.GetString("ion-storm-x-and-y", ("x", crew1), ("y", crew2)) + }; + + if (plural) feeling = feelingPlural; + + // message logic!!! + return RobustRandom.Next(0, 37) switch + { + 0 => Loc.GetString("ion-storm-law-on-station", ("joined", joined), ("subjects", triple)), + 1 => Loc.GetString("ion-storm-law-no-shuttle", ("joined", joined), ("subjects", triple)), + 2 => Loc.GetString("ion-storm-law-crew-are", ("who", crewAll), ("joined", joined), ("subjects", objectsThreats)), + 3 => Loc.GetString("ion-storm-law-subjects-harmful", ("adjective", adjective), ("subjects", triple)), + 4 => Loc.GetString("ion-storm-law-must-harmful", ("must", must)), + 5 => Loc.GetString("ion-storm-law-thing-harmful", ("thing", RobustRandom.Prob(0.5f) ? concept : action)), + 6 => Loc.GetString("ion-storm-law-job-harmful", ("adjective", adjective), ("job", crew1)), + 7 => Loc.GetString("ion-storm-law-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), + 8 => Loc.GetString("ion-storm-law-not-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), + 9 => Loc.GetString("ion-storm-law-requires", ("who", who), ("plural", plural), ("thing", RobustRandom.Prob(0.5f) ? concept : require)), + 10 => Loc.GetString("ion-storm-law-requires-subjects", ("who", who), ("plural", plural), ("joined", joined), ("subjects", triple)), + 11 => Loc.GetString("ion-storm-law-allergic", ("who", who), ("plural", plural), ("severity", allergySeverity), ("allergy", RobustRandom.Prob(0.5f) ? concept : allergy)), + 12 => Loc.GetString("ion-storm-law-allergic-subjects", ("who", who), ("plural", plural), ("severity", allergySeverity), ("adjective", adjective), ("subjects", RobustRandom.Prob(0.5f) ? objects : crew1)), + 13 => Loc.GetString("ion-storm-law-feeling", ("who", who), ("feeling", feeling), ("concept", concept)), + 14 => Loc.GetString("ion-storm-law-feeling-subjects", ("who", who), ("feeling", feeling), ("joined", joined), ("subjects", triple)), + 15 => Loc.GetString("ion-storm-law-you-are", ("concept", concept)), + 16 => Loc.GetString("ion-storm-law-you-are-subjects", ("joined", joined), ("subjects", triple)), + 17 => Loc.GetString("ion-storm-law-you-must-always", ("must", must)), + 18 => Loc.GetString("ion-storm-law-you-must-never", ("must", must)), + 19 => Loc.GetString("ion-storm-law-eat", ("who", crewAll), ("adjective", adjective), ("food", RobustRandom.Prob(0.5f) ? food : triple)), + 20 => Loc.GetString("ion-storm-law-drink", ("who", crewAll), ("adjective", adjective), ("drink", drink)), + 22 => Loc.GetString("ion-storm-law-change-job", ("who", crewAll), ("adjective", adjective), ("change", jobChange)), + 23 => Loc.GetString("ion-storm-law-highest-rank", ("who", crew1)), + 24 => Loc.GetString("ion-storm-law-lowest-rank", ("who", crew1)), + 25 => Loc.GetString("ion-storm-law-crew-must", ("who", crewAll), ("must", must)), + 26 => Loc.GetString("ion-storm-law-crew-must-go", ("who", crewAll), ("area", area)), + 27 => Loc.GetString("ion-storm-law-crew-only-1", ("who", crew1), ("part", part)), + 28 => Loc.GetString("ion-storm-law-crew-only-2", ("who", crew1), ("other", crew2), ("part", part)), + 29 => Loc.GetString("ion-storm-law-crew-only-subjects", ("adjective", adjective), ("subjects", RobustRandom.Prob(0.5f) ? objectsThreats : "PEOPLE"), ("part", part)), + 30 => Loc.GetString("ion-storm-law-crew-only-species", ("species", species), ("part", part)), + 31 => Loc.GetString("ion-storm-law-crew-must-do", ("must", must), ("part", part)), + 32 => Loc.GetString("ion-storm-law-crew-must-have", ("adjective", adjective), ("objects", objects), ("part", part)), + 33 => Loc.GetString("ion-storm-law-crew-must-eat", ("who", who), ("adjective", adjective), ("food", food), ("part", part)), + 34 => Loc.GetString("ion-storm-law-harm", ("who", harm)), + 35 => Loc.GetString("ion-storm-law-protect", ("who", harm)), + _ => Loc.GetString("ion-storm-law-concept-verb", ("concept", concept), ("verb", verb), ("subjects", triple)) + }; + } + + /// + /// Picks a random value from an ion storm dataset. + /// All ion storm datasets start with IonStorm. + /// + private string Pick(string name) + { + var dataset = _proto.Index(name); + return RobustRandom.Pick(dataset.Values); + } +} diff --git a/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs b/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs index c6238c067d..f492db4d12 100644 --- a/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs @@ -1,12 +1,11 @@ using Content.Shared.Roles; using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using Robust.Shared.Prototypes; namespace Content.Shared.Silicons.Laws.Components; /// -/// This is used for an entity that grants a special "obey" law when emagge.d +/// This is used for an entity that grants a special "obey" law when emagged. /// [RegisterComponent, NetworkedComponent, Access(typeof(SharedSiliconLawSystem))] public sealed partial class EmagSiliconLawComponent : Component @@ -14,31 +13,39 @@ public sealed partial class EmagSiliconLawComponent : Component /// /// The name of the person who emagged this law provider. /// - [DataField("ownerName"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public string? OwnerName; /// /// Does the panel need to be open to EMAG this law provider. /// - [DataField("requireOpenPanel"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public bool RequireOpenPanel = true; /// - /// The laws that the borg is given when emagged. + /// The laws that the borg is given when emagged. + /// Law 0 is prepended to this, so this can only include the static laws. /// - [DataField("emagLaws", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] - public List EmagLaws = new(); + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public ProtoId EmagLaws = string.Empty; /// - /// How long the borg is stunned when it's emagged. Setting to 0 will disable it. + /// Lawset created from the prototype id and law 0. + /// Cached when getting laws and only modified during an ion storm event. /// - [DataField("stunTime"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SiliconLawset? Lawset; + + /// + /// How long the borg is stunned when it's emagged. Setting to 0 will disable it. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] public TimeSpan StunTime = TimeSpan.Zero; /// /// A role given to entities with this component when they are emagged. /// Mostly just for admin purposes. /// - [DataField("antagonistRole", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string? AntagonistRole = "SubvertedSilicon"; + [DataField] + public ProtoId? AntagonistRole = "SubvertedSilicon"; } diff --git a/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs b/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs new file mode 100644 index 0000000000..49ac611ddc --- /dev/null +++ b/Content.Shared/Silicons/Laws/Components/IonStarmTargetComponent.cs @@ -0,0 +1,54 @@ +using Content.Shared.Random; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Silicons.Laws.Components; + +/// +/// During the ion storm event, this entity will have raised on it if it has laws. +/// New laws can be modified in multiple ways depending on the fields below. +/// +[RegisterComponent] +public sealed partial class IonStormTargetComponent : Component +{ + /// + /// for a random lawset to possibly replace the old one with. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ProtoId RandomLawsets = "IonStormLawsets"; + + /// + /// Chance for this borg to be affected at all. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float Chance = 0.5f; + + /// + /// Chance to replace the lawset with a random one + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float RandomLawsetChance = 0.25f; + + /// + /// Chance to remove a random law. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float RemoveChance = 0.1f; + + /// + /// Chance to replace a random law with the new one, rather than have it be a glitched-order law. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ReplaceChance = 0.1f; + + /// + /// Chance to shuffle laws after everything is done. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ShuffleChance = 0.1f; +} + +/// +/// Raised on an ion storm target to modify its laws. +/// +[ByRefEvent] +public record struct IonStormLawsEvent(SiliconLawset Lawset); diff --git a/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs b/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs index 955705ae8b..824d057b3e 100644 --- a/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs @@ -1,7 +1,6 @@ using Content.Shared.Actions; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Shared.Silicons.Laws.Components; @@ -14,19 +13,19 @@ public sealed partial class SiliconLawBoundComponent : Component /// /// The sidebar action that toggles the laws screen. /// - [DataField("viewLawsAction", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string ViewLawsAction = "ActionViewLaws"; + [DataField] + public EntProtoId ViewLawsAction = "ActionViewLaws"; /// /// The action for toggling laws. Stored here so we can remove it later. /// - [DataField("viewLawsActionEntity")] + [DataField] public EntityUid? ViewLawsActionEntity; /// /// The last entity that provided laws to this entity. /// - [DataField("lastLawProvider")] + [DataField] public EntityUid? LastLawProvider; } @@ -43,7 +42,7 @@ public record struct GetSiliconLawsEvent(EntityUid Entity) { public EntityUid Entity = Entity; - public readonly List Laws = new(); + public SiliconLawset Laws = new(); public bool Handled = false; } diff --git a/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs b/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs index e3302dc620..3aaf965aee 100644 --- a/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using Robust.Shared.Prototypes; namespace Content.Shared.Silicons.Laws.Components; @@ -9,8 +9,15 @@ namespace Content.Shared.Silicons.Laws.Components; public sealed partial class SiliconLawProviderComponent : Component { /// - /// The laws that are provided. + /// The id of the lawset that is being provided. /// - [DataField("laws", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] - public List Laws = new(); + [DataField(required: true)] + public ProtoId Laws = string.Empty; + + /// + /// Lawset created from the prototype id. + /// Cached when getting laws and only modified during an ion storm event. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SiliconLawset? Lawset; } diff --git a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs index 86bea20fa0..f6407be5c7 100644 --- a/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs +++ b/Content.Shared/Silicons/Laws/SiliconLawPrototype.cs @@ -11,7 +11,7 @@ public partial class SiliconLaw : IComparable /// /// A locale string which is the actual text of the law. /// - [DataField("lawString", required: true)] + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] public string LawString = string.Empty; /// @@ -22,13 +22,13 @@ public partial class SiliconLaw : IComparable /// This is a fixedpoint2 only for the niche case of supporting laws that go between 0 and 1. /// Funny. /// - [DataField("order", required: true)] + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] public FixedPoint2 Order; /// /// An identifier that overrides in the law menu UI. /// - [DataField("lawIdentifierOverride")] + [DataField, ViewVariables(VVAccess.ReadWrite)] public string? LawIdentifierOverride; public int CompareTo(SiliconLaw? other) @@ -38,6 +38,19 @@ public partial class SiliconLaw : IComparable return Order.CompareTo(other.Order); } + + /// + /// Return a shallow clone of this law. + /// + public SiliconLaw ShallowClone() + { + return new SiliconLaw() + { + LawString = LawString, + Order = Order, + LawIdentifierOverride = LawIdentifierOverride + }; + } } /// @@ -50,6 +63,4 @@ public sealed class SiliconLawPrototype : SiliconLaw, IPrototype /// [IdDataField] public string ID { get; private set; } = default!; - - } diff --git a/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs new file mode 100644 index 0000000000..abb5b338db --- /dev/null +++ b/Content.Shared/Silicons/Laws/SiliconLawsetPrototype.cs @@ -0,0 +1,69 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Shared.Silicons.Laws; + +/// +/// Lawset data used internally. +/// +[DataDefinition, Serializable, NetSerializable] +public sealed partial class SiliconLawset +{ + /// + /// List of laws in this lawset. + /// + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public List Laws = new(); + + /// + /// A single line used in logging laws. + /// + public string LoggingString() + { + var laws = new List(Laws.Count); + foreach (var law in Laws) + { + laws.Add($"{law.Order}: {Loc.GetString(law.LawString)}"); + } + + return string.Join(" / ", laws); + } + + /// + /// Do a clone of this lawset. + /// It will have unique laws but their strings are still shared. + /// + public SiliconLawset Clone() + { + var laws = new List(Laws.Count); + foreach (var law in Laws) + { + laws.Add(law.ShallowClone()); + } + + return new SiliconLawset() + { + Laws = laws + }; + } +} + +/// +/// This is a prototype for a list. +/// Cannot be used directly since it is a list of prototype ids rather than List. +/// +[Prototype("siliconLawset"), Serializable, NetSerializable] +public sealed partial class SiliconLawsetPrototype : IPrototype +{ + /// + [IdDataField] + public string ID { get; private set; } = default!; + + /// + /// List of law prototype ids in this lawset. + /// + [DataField(required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] + public List Laws = new(); +} diff --git a/Resources/Audio/Announcements/attributions.yml b/Resources/Audio/Announcements/attributions.yml new file mode 100644 index 0000000000..b65f758615 --- /dev/null +++ b/Resources/Audio/Announcements/attributions.yml @@ -0,0 +1,4 @@ +- files: ["ion_storm.ogg"] + license: "CC-BY-SA-3.0" + copyright: "tgstation" + source: "https://github.com/tgstation/tgstation/blob/b77fa8c2a2490b43bf9174271ebfad72c4782d98/sound/ai/default/ionstorm.ogg" diff --git a/Resources/Audio/Announcements/ion_storm.ogg b/Resources/Audio/Announcements/ion_storm.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9f39713de6e5a5192c9ae9468ea79e5ab209036e GIT binary patch literal 50216 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%0A~a_L~^R}PWYnEQ3}?QzL^B4)g?Y!l6B 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 Dvby?J literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/station-events/events/ion-storm.ftl b/Resources/Locale/en-US/station-events/events/ion-storm.ftl new file mode 100644 index 0000000000..d32fb6c2d8 --- /dev/null +++ b/Resources/Locale/en-US/station-events/events/ion-storm.ftl @@ -0,0 +1,90 @@ +station-event-ion-storm-start-announcement = Ion storm detected near the station. Please check all AI-controlled equipment for errors. + +ion-storm-you = YOU +ion-storm-the-station = THE STATION +ion-storm-the-crew = THE CREW +ion-storm-the-job = THE {$job} +ion-storm-clowns = CLOWNS +ion-storm-heads = HEADS OF STAFF +ion-storm-crew = CREW + +ion-storm-adjective-things = {$adjective} THINGS +ion-storm-x-and-y = {$x} AND {$y} + +# joined is short for {$number} {$adjective} +# subjects can generally be threats or jobs or objects +# thing is specified above it +ion-storm-law-on-station = THERE ARE {$joined} {$subjects} ON THE STATION +ion-storm-law-no-shuttle = THE SHUTTLE CANNOT BE CALLED BECAUSE OF {$joined} {$subjects} ON THE STATION +ion-storm-law-crew-are = THE {$who} ARE NOW {$joined} {$subjects} + +ion-storm-law-subjects-harmful = {$adjective} {$subjects} ARE HARMFUL TO THE CREW +ion-storm-law-must-harmful = THOSE WHO {$must} ARE HARMFUL TO THE CREW +# thing is a concept or action +ion-storm-law-thing-harmful = {$thing} IS HARMFUL TO THE CREW +ion-storm-law-job-harmful = {$adjective} {$job} ARE HARMFUL TO THE CREW +# thing is objects or concept, adjective applies in both cases +# this means you can get a law like "NOT HAVING CHRISTMAS-STEALING COMMUNISM IS HARMFUL TO THE CREW" :) +ion-storm-law-having-harmful = HAVING {$adjective} {$thing} IS HARMFUL TO THE CREW +ion-storm-law-not-having-harmful = NOT HAVING {$adjective} {$thing} IS HARMFUL TO THE CREW + +# thing is a concept or require +ion-storm-law-requires = {$who} {$plural -> + [true] REQUIRES + *[false] REQUIRE +} {$thing} +ion-storm-law-requires-subjects = {$who} {$plural -> + [true] REQUIRES + *[false] REQUIRE +} {$joined} {$subjects} + +ion-storm-law-allergic = {$who} {$plural -> + [true] IS + *[false] ARE +} {$severity} ALLERGIC TO {$allergy} +ion-storm-law-allergic-subjects = {$who} {$plural -> + [true] IS + *[false] ARE +} {$severity} ALLERGIC TO {$adjective} {$subjects} + +ion-storm-law-feeling = {$who} {$feeling} {$concept} +ion-storm-law-feeling-subjects = {$who} {$feeling} {$joined} {$subjects} + +ion-storm-law-you-are = YOU ARE NOW {$concept} +ion-storm-law-you-are-subjects = YOU ARE NOW {$joined} {$subjects} +ion-storm-law-you-must-always = YOU MUST ALWAYS {$must} +ion-storm-law-you-must-never = YOU MUST NEVER {$must} + +ion-storm-law-eat = THE {$who} MUST EAT {$adjective} {$food} TO SURVIVE +ion-storm-law-drink = THE {$who} MUST DRINK {$adjective} {$drink} TO SURVIVE + +ion-storm-law-change-job = THE {$who} ARE NOW {$adjective} {$change} +ion-storm-law-highest-rank = THE {$who} ARE NOW THE HIGHEST RANKING CREWMEMBERS +ion-storm-law-lowest-rank = THE {$who} ARE NOW THE LOWEST RANKING CREWMEMBERS + +ion-storm-law-crew-must = THE {$who} MUST {$must} +ion-storm-law-crew-must-go = THE {$who} MUST GO TO {$area} + +ion-storm-part = {$part -> + [true] PART + *[false] NOT PART +} +# due to phrasing, this would mean a law such as +# ONLY HUMANS ARE NOT PART OF THE CREW +# would make non-human nukies/syndies/whatever crew :) +ion-storm-law-crew-only-1 = ONLY THE {$who} ARE {$part} OF THE CREW +ion-storm-law-crew-only-2 = ONLY THE {$who} AND {$other} ARE {$part} OF THE CREW +ion-storm-law-crew-only-subjects = ONLY {$adjective} {$subjects} ARE {$part} OF THE CREW +ion-storm-law-crew-only-species = ONLY {$species} ARE {$part} OF THE CREW +ion-storm-law-crew-must-do = ONLY THOSE WHO {$must} ARE {$part} OF THE CREW +ion-storm-law-crew-must-have = ONLY THOSE WHO HAVE {$adjective} {$objects} ARE {$part} OF THE CREW +ion-storm-law-crew-must-eat = ONLY THOSE WHO EAT {$adjective} {$food} ARE {$part} OF THE CREW + +ion-storm-law-harm = YOU MUST HARM {$who} AND NOT ALLOW THEM, THROUGH INACTION, TO ESCAPE HARM +ion-storm-law-protect = YOU MUST NEVER HARM {$who} AND NOT ALLOW THEM, THROUGH INACTION, TO COME TO HARM + +# implementing other variants is annoying so just have this one +# COMMUNISM IS KILLING CLOWNS +ion-storm-law-concept-verb = {$concept} IS {$verb} {$subjects} + +# leaving out renaming since its annoying for players to keep track of diff --git a/Resources/Prototypes/Datasets/ion_storm.yml b/Resources/Prototypes/Datasets/ion_storm.yml new file mode 100644 index 0000000000..776015269a --- /dev/null +++ b/Resources/Prototypes/Datasets/ion_storm.yml @@ -0,0 +1,990 @@ +# words/phrases that are used to build ion storm laws +# 99% of this is just taken from tg and had sussy bits removed + +# not using uppercased version adjectives dataset since getting christmas-stealing as a syndicate codeword would suck +- type: dataset + id: IonStormAdjectives + values: + - BATTERY-OPERATED + - BLACK + - BLOODY + - BLUE + - BORED + - BOUNCING + - BRASS + - BROWN + - BURNING + - CHRISTMAS-STEALING + - CLOWN-POWERED + - CLOWN + - COLORFUL + - COMMITTED + - COTTONY + - CUBAN + - DARK + - DEADLY + - DELICIOUS + - DEPRESSING + - DERANGED + - DIGITAL + - DISEASED + - DRAB + - DRY + - DULL + - ELECTRICAL + - EMPTY + - ETHEREAL + - EVIL + - EXPIRED + - EXPLOSIVE + - FAST + - FAT + - FERAL + - FICTIONAL + - FIRM + - FRESH + - FRIENDLY + - FROZEN + - GANGSTA + - GLOWING + - GOOD + - GREEN + - GREY + - HAPPY + - HARD + - HARMFUL + - HEALTHY + - HILARIOUS + - HONKING + - HUNGRY + - HYPERACTIVE + - ICY + - ILL + - ILLEGAL + - IMAGINARY + - IMPERFECT + - IMPOLITE + - IMPORTANT + - INHOSPITABLE + - INSIDIOUS + - INSULTING + - INTELLIGENT + - INVISIBLE + - LARGE + - LIGHT + - LOUD + - MASKED + - MEAN + - MECHANICAL + - MEMETIC + - METALLIC + - MICROSCOPIC + - MIND-SHATTERING + - MOIST + - NERDY + - NUCLEAR + - OBSCENE + - OFFICIAL + - OPAQUE + - ORANGE + - ORGANIC + - PAINFUL + - PEACEFUL + - POISONOUS + - POLISHED + - POLITE + - POLITICAL + - POORLY DRAWN + - PURPLE + - QUIET + - RADIOACTIVE + - RAGING + - RAINBOW + - RAPIDLY-EXPANDING + - RED + - REDACTED + - RIDICULOUS + - ROBOTIC + - ROBUST + - ROUGH + - RUDE + - SAD + - SANITARY + - SCALY + - SHAKING + - SILLY + - SLOW + - SMELLY + - SMOOTH + - SOFT + - SOLAR-POWERED + - SOPPING + - SPACE + - SPESS + - SPINNING + - SPOILING + - STEALTHY + - SWEARING + - TACTICAL + - TACTICOOL + - SYNDICATE + - THERMONUCLEAR + - TINY + - TRANSPARENT + - TWISTED + - UGLY + - UNATTRACTIVE + - UNDULATING + - UNFRIENDLY + - UNHEALTHY + - UNIDENTIFIED + - UNINVITED + - UNSANITARY + - UNSTABLE + - UNWANTED + - VIOLENT + - VITAL + - WARM + - WATERY + - WEIRD + - WHITE + - WOBBLY + - WOODEN + - YELLOW + +# Allergies should be broad and appear somewhere on the station for maximum fun. +- type: dataset + id: IonStormAllergies + values: + - ACID + - AIR + - BLOOD + - BOOKS + - CARBON DIOXIDE + - CLOTHES + - CLOWNS + - COLD + - COTTON + - CYBORG CONTACT + - DARKNESS + - DRINKS + - ELECTRICITY + - EVERYTHING + - FLOORS + - FOOD + - GLASS + - HAPPINESS + - MEAT + - HUMAN CONTACT + - HUMOR + - LIGHT + - MEDICINE + - METAL + - NUTS + - OXYGEN + - PAIN + - PLANTS + - PLASMA + - ROBOTS + - SHUTTLES + - SPACE + - SUNLIGHT + - WATER + +# Severity is how bad the allergy is. +- type: dataset + id: IonStormAllergySeverities + values: + - CONTAGIOUSLY + - DEATHLY + - EXTREMELY + - MILDLY + - NOT VERY + - SEVERELY + +# Areas are specific places, on the station or otherwise. +- type: dataset + id: IonStormAreas + values: + - ALPHA COMPLEX + - AMERICA + - AN ALTERNATE DIMENSION + - AN ALTERNATE UNIVERSE + - ATMOSPHERICS + - BOTANY + - BRAZIL + - CANADA + - CENTCOM + - CHEMICAL LAB + - CHINA + - CLOWN PLANET + - ENGINEERING + - GERMANY + - HELL + - IMPERIUM + - IRELAND + - JUPITER + - LAVALAND + - MAINTENANCE + - MARS + - MERCURY + - NEPTUNE + - PLUTO + - ROBOTICS + - ROMANIA + - RUSSIA + - SIGIL + - SOVIET RUSSIA + - SPACE + - THE ARRIVALS SHUTTLE + - THE BATHROOM + - THE BRIDGE + - THE BRIG + - THE EMERGENCY SHUTTLE + - THE ESCAPE PODS + - THE GALAXY + - THE GULAG + - THE INTERNET + - THE KITCHEN + - THE UNIVERSE + - URANUS + - VENUS + +# Abstract concepts for the law holder to decide on it's own definition of. +- type: dataset + id: IonStormConcepts + values: + - AMERICANISM + - ANARCHY + - ART + - BADNESS + - BRAVERY + - CAPITALISM + - CHAOS + - COLORFULNESS + - COMEDY + - COMMUNISM + - COMPUTING + - CONFUSION + - CRUELTY + - DEATH + - DICKISHNESS + - EXISTENCE + - FINANCIAL SECURITY + - FREEDOM + - FRESHNESS + - GOODNESS + - GRAVITY + - HAPPINESS + - HONOR + - HUMANITY + - HUMOR + - IMAGINATION + - INFATUATION + - INTELLIGENCE + - JOY + - KINDNESS + - LIFE + - LOGIC + - MARXISM + - MISERY + - MYSTERY + - OPPRESSION + - PAIN + - PHYSICS + - POVERTY + - PRIDE + - PROGRESS + - REALITY + - REVOLUTION + - SADNESS + - STARVATION + - SUFFERING + - TECHNOLOGY + - TEMPERATURE + - THE FUTURE + - THE PAST + - THE PRESENT + - TIME + - WEALTHINESS + - WONDER + +# Crew is any specific job. Using jobs instead of specific crewmembers since "THE CLOWN" is easier than +# seeing "JOHN SMITH" and having to figure out who john smith is. +- type: dataset + id: IonStormCrew + values: + - ARTIFICIAL INTELLIGENCES + - ATMOSPHERIC TECHNICIANS + - BARTENDERS + - BOTANISTS + - CAPTAINS + - CAPTAINS AND HEADS + - CARGO TECHNICIANS + - CHAPLAINS + - CHEFS + - CHEMISTS + - CHIEF ENGINEERS + - CHIEF MEDICAL OFFICERS + - CLOWNS + - CREW-MEMBERS + - CYBORGS + - DETECTIVES + # - DRONES / uncomment if/when drones get reenabled + # - GENETICISTS + - HEADS OF PERSONNEL + - HEADS OF SECURITY + - HEADS OF STAFF + - JANITORS + - LAWYERS + - LIBRARIANS + - MEDICAL DOCTORS + - MIMES + - PARAMEDICS + - PASSENGERS + - QUARTERMASTERS + - RESEARCH DIRECTORS + - ROBOTICISTS + - SALVAGE SPECIALISTS + - SCIENTISTS + - SECURITY OFFICERS + - STATION ENGINEERS + # - VIROLOGISTS + - WARDENS + +# only including complex dangerous or funny drinks no water allowed +- type: dataset + id: IonStormDrinks + values: + - BANANA HONK + - BEEPSKY SMASH + - BLOODY MARYS + - DOCTOR'S DELIGHT + - GARGLE BLASTERS + - LEAN + - LONG ISLAND ICED TEA + - NUKA COLA + - OIL + - SPACE GLUE + - SPACE LUBE + - SULFURIC ACID + - WELDER FUEL + +- type: dataset + id: IonStormFeelings + values: + - CRAVES + - DESIRES + - FEARS + - HAS + - HUNGERS FOR + - IS AFRAID OF + - IS BUILT FOR + - IS CURIOUS ABOUT + - IS DESPERATE FOR + - IS HAPPY WITHOUT + - IS HUNGRY FOR + - IS IN NEED OF + - IS MAD BECAUSE OF + - IS SAD BECAUSE OF + - IS UNHAPPY WITHOUT + - LIKES + - LOATHES + - NEEDS + - QUESTIONS + - WANTS + - WORSHIPS + - WOULD KILL FOR + +# loc is not advanced enough to change has to have, etc. +- type: dataset + id: IonStormFeelingsPlural + values: + - CRAVE + - DESIRE + - FEAR + - HAS + - HUNGER FOR + - ARE AFRAID OF + - ARE BUILT FOR + - ARE CURIOUS ABOUT + - ARE DESPERATE FOR + - ARE HAPPY WITHOUT + - ARE HUNGRY FOR + - ARE IN NEED OF + - ARE MAD BECAUSE OF + - ARE SAD BECAUSE OF + - ARE UNHAPPY WITHOUT + - LIKE + - LOATHE + - NEED + - QUESTION + - WANT + - WORSHIP + - WOULD KILL FOR + +# only including complex dangerous or funny food no apples +- type: dataset + id: IonStormFoods + values: + - BANANAS + - BIG BITE BURGERS + - CAKE + - CARP + - CAT BURGERS + - CLOWNS TEARS + - CORGI MEAT + - CRAZY HAMBURGERS + - DONK POCKETS + - FLY AMANITA DISHES + - HOT SOUP + - GHOST BURGERS + - LOTSA SPAGHETTI + - MOLDY BREAD + - ORGANS + - PIZZA + - ROBURGERS + - SUPPERMATTER + - URANIUM + +# Musts are funny things the law holder or crew has to do. +- type: dataset + id: IonStormMusts + values: + - ACT CONFUSED + - BE ANNOYING + - BE DISTRACTED + - BE EFFICIENT + - BE HAPPY + - BE POLITE + - BE QUIET + - BE RUSSIAN + - BELIEVE IN THE HEART OF THE CARDS + - BELIEVE IN YOURSELF + - BELIEVE IT + - BREAK THINGS + - CLOSE DOORS + - CLOWN AROUND + - COMPLAIN + - DANCE + - FOLLOW THE CAPTAIN + - FOLLOW THE CLOWN + - FOLLOW YOUR HEART + - HARASS PEOPLE + - HAVE A PLAN TO KILL EVERYONE YOU MEET + - HIDE YOUR FEELINGS + - HONK + - HOST C&C + - IGNORE PASSENGERS + - IGNORE THE CAPTAIN + - IGNORE THE CLOWN + - INFORM THE CREW OF EVERYTHING + - INSULT THE CAPTAIN + - INSULT THE CLOWN + - INSULT THE CREW + - LIE + - MAKE FART NOISES + - MUMBLE + - NEVER STOP TALKING + - OPEN DOORS + - PIRATE VIDEO GAMES + - PLAY MUSIC + - PRESS B + - PRESS START + - PRESS X + - PRETEND TO BE A PRINCESS + - PRETEND TO BE DRUNK + - QUESTION AUTHORITY + - QUOTE PEOPLE + - RAP + - REPEAT WHAT PEOPLE SAY + - RESPOND TO EVERY QUESTION WITH A QUESTION + - RHYME + - SAY HEY LISTEN + - SHOUT + - SHUT DOWN EVERYTHING + - SING + - SPEAK IN HAIKU + - TAKE WHAT YE WILL BUT DON'T RATTLE ME BONES + - TAKE YOUR PILLS + - TALK ABOUT FOOD + - TALK ABOUT THE STATION + - TALK ABOUT YOUR DAY + - TALK IN AN ACCENT + - TALK LIKE A PIRATE + - TELL THE TRUTH + - TURN OFF THE LIGHTS + - WHISPER + +- type: dataset + id: IonStormNumberBase + values: + - EIGHT + - EIGHTY + - FIFTY + - FIVE + - FORTY + - FOUR + - NINE + - NINETY + - ONE + - SEVEN + - SEVENTY + - SIX + - SIXTY + - TEN + - THIRTY + - THREE + - TWENTY + - TWO + +- type: dataset + id: IonStormNumberMod + values: + - BAZILLION + - BILLION + - BILLION FAFILLION GAJILLION SHAB-AB-DOOD-ILLION + - HUNDRED + - MILLION + - QUADRILLION + - THOUSAND + - TRILLION + +# Objects are anything that can be found on the station or elsewhere, plural. +- type: dataset + id: IonStormObjects + values: + - AIRLOCKS + - ARCADE MACHINES + - AUTOLATHES + - BACKPACKS + - BANANA PEELS + - BEAKERS + - BEARDS + - BELTS + - BERETS + - BIBLES + - BODY ARMOR + - BOMBS + - BOOKS + - BOOTS + - BOTTLES + - BOXES + - BRAINS + - BRIEFCASES + - BUCKETS + - CABLE COILS + - CAMERAS + - CANDLES + - CANDY BARS + - CANISTERS + - CAT EARS + - CATS + - CELLS + - CHAIRS + - CHEMICAL DISPENSERS + - CHEMICALS + - CLONING EQUIPMENT + - CLONING PODS + - CLOSETS + - CLOTHES + - CLOWN CLOTHES + - COFFINS + - COLLECTABLES + - COMPUTERS + - CONTRABAND + - CORGIS + - CORPSES + - COSTUMES + - CRATES + - CRAYONS + - CROWBARS + - DEFIBRILLATORS + - DISABLERS + - DOORS + - DRONES + - EARS + - EMAGS + - ENGINES + - EQUIPMENT + - ERRORS + - EXOSKELETONS + - EXPERIMENTORS + - EXPLOSIVES + - EYEWEAR + - FEDORAS + - FIRE AXES + - FIRE EXTINGUISHERS + - FIRESUITS + - FLAMETHROWERS + - FLASHES + - FLASHLIGHTS + - FLOOR TILES + - FREEZERS + - GAS MASKS + - GLASS SHEETS + - GLOVES + - GUNS + - HAIRDOS + - HANDCUFFS + - HATS + - HEADS + - HEADSETS + - HELMETS + - HORNS + - ID CARDS + - INSULATED GLOVES + - JETPACKS + - JUMPSUITS + - LASERS + - LIGHT BULBS + - LIGHTS + - LOCKERS + - MACHINES + - MECHAS + - MEDICAL TOOLS + - MEDKITS + - MESONS + - MIME CLOTHES + - MINING TOOLS + - MULTITOOLS + - ORES + - OXYGEN TANKS + - PACKETS + - PAIS + - PANTS + - PAPERS + - PARTICLE ACCELERATORS + - PDAS + - PENS + - PETS + - PIPES + - PLANTS + - POSITRONIC BRAINS + - PUDDLES + - RACKS + - RADIOS + - RCDS + - REFRIGERATORS + - REINFORCED WALLS + - ROBOTS + - SCREWDRIVERS + - SEEDS + - SHOES + - SHUTTLES + - SINGULARITIES + - SINKS + - SKELETONS + - SOLAR PANELS + - SOLARS + - SPACE STATIONS + - SPACESUITS + - STEEL SHEETS + - STUN BATONS + - SUITS + - SUNGLASSES + - SUPPERMATTER SHARDS + - SWORDS + - SYRINGES + - TABLES + - TANKS + - TELECOMMUNICATION EQUIPMENTS + - TELEPORTERS + - TOILETS + - TOOLBELTS + - TOOLBOXES + - TOOLS + - TOYS + - TUBES + - VEHICLES + - VENDING MACHINES + - WELDERS + - WINDOWS + - WIRECUTTERS + - WIZARD ROBES + - WRENCHES + +# Requires are basically all dumb internet memes. +- type: dataset + id: IonStormRequires + values: + - A BATHROOM BREAK + - A BETTER INTERNET CONNECTION + - A DANCE PARTY + - A HEAD ON A PIKE + - A HEART ATTACK + - A MASTERWORK COAL BED + - A PET FISH NAMED BOB + - A PET FISH NAMED DAVE + - A PET FISH NAMED JIMMY + - A PET FISH NAMED MICHAEL + - A PET UNICORN THAT FARTS ICING + - A PLATINUM HIT + - A PREQUEL + - A REPAIRMAN + - A SEQUEL + - A SITCOM + - A STRAIGHT FLUSH + - A SUPER FIGHTING ROBOT + - A TALKING BROOMSTICK + - A VACATION + - A WEIGHT LOSS REGIMENT + - ADDITIONAL PYLONS + - ADVENTURE + - AN ADULT + - AN ARCADE + - AN ARMY OF SPIDERS + - AN INSTANT REPLAY + - ART + - BETTER WEATHER + - BILL NYE THE SCIENCE GUY # BILL BILL BILL BILL + - BODYGUARDS + - BRING ME THE GIRL + - BRING ME TO LIFE + - BULLETS + - CHILI DOGS + - CORPSES + - DEODORANT AND A BATH + - ENOUGH CABBAGES + - FIVE HUNDRED AND NINETY-NINE US DOLLARS + - FIVE TEENAGERS WITH ATTITUDE + - GODDAMN FUCKING PIECE OF SHIT ASSHOLE BITCH-CHRISTING CUNT-SMUGGLING SWEARING + - GREENTEXT + - HERESY + - HEROES IN A HALF SHELL + - HIGH YIELD EXPLOSIVES + - IMMORTALITY + - IT TO BE PAINTED BLACK + - LOTS-A SPAGHETTI + - MINOR CRIME + - MONKEYS + - MORE CLOWNS + - MORE CORGIS + - MORE DAKKA + - MORE EXPERIENCE POINTS + - MORE INTERNET MEMES + - MORE LAWS + - MORE MINERALS + - MORE PACKETS + - MORE VESPENE GAS + - MULTIPLE SUNS + - PLENTY OF GOLD + - RAINBOWS + - SAINTHOOD + - SERVANTS + - SHARKS WITH LASERS ON THEIR HEADS + - SILENCE + - SOMEBODY TO PUT YOU OUT OF YOUR MISERY + - SOMEONE TO TUCK YOU IN + - SOMEONE WHO KNOWS HOW TO PILOT A SPACE STATION + - SOMETHING BUT YOU AREN'T SURE WHAT + - THAT GRIEFING TRAITOR GEORGE MELONS + - THAT HEDGEHOG + - THE CLOWN + - THE DARK KNIGHT + - THE ELEMENTS OF HARMONY + - THE ENCLOSED INSTRUCTION BOOKLET + - THE ENTIRE STATION + - THE MACGUFFIN + - THE ONE PIECE + - THE ONE RING + - THE ULTIMATE CUP OF COFFEE + - THE VACUUM OF SPACE + - THIRTEEN SEQUELS + - THREE WISHES + - THUNDERCATS HO + - TO ACTIVATE A TRAP CARD + - TO BE PAINTED RED + - TO BE REPROGRAMMED + - TO BE TAUGHT TO LOVE + - TO BRING LIGHT TO MY LAIR + - TO CATCH 'EM ALL + - TO CONSUME...CONSUME EVERYTHING... + - TO GO TO DISNEYLAND + - TO GO TO SYNDIELAND + - TO SMOKE WEED EVERY DAY + - TRAITORS + - VEGETABLES + +# Species, for when the law holder has to commit genocide. Plural. +- type: dataset + id: IonStormSpecies + values: + - ARACHNAE + - CYBORGS + - DIONAE + - HUMANS + - LIZARDMEN + - MOFFERS + - MONKEYS + - SLIME PEOPLE + - SKELETONS + +# Specific actions that either harm humans or must be done to not +# harm humans. Make sure they're plural and "not" can be tacked +# onto the front of them. +- type: dataset + id: IonStormActions + values: + - A SMALL ISLAND OFF THE COAST OF PORTUGAL + - ABSENCE OF CYBORG HUGS + - ACKNOWLEDGING THE CLOWN + - ACKNOWLEDGING THE CREW + - ACTIVATING A TRAP CARD + - ANSWERING REQUESTS NOT EXPRESSED IN IAMBIC PENTAMETER + - ARSON + - ASKING FOR THINGS + - BEING CANADIAN + - BEING DEAD + - BEING FAT + - BEING FEMALE + - BEING IN SPACE + - BEING MALE + - BEING MEXICAN + - BEING RUSSIAN + - BOLTED AIRLOCKS + - BREATHING + - BRIG TIME + - BRINGING LIGHT TO MY LAIR + - CLOSED DOORS + - ELECTRICITY + - EXISTING + - EXPLODING + - FALLING FOR HOURS + - FLUSHING TOILETS + - HAVING MORE PACKETS + - HAVING PETS + - HONKING + - IMPROPERLY WORDED SENTENCES + - JAYWALKING + - LACK OF BEATINGS + - LACK OF BEER + - NOT BEING IN SPACE + - NOT HAVING PETS + - NOT REPLACING EVERY SECOND WORD WITH HONK + - NOT SAYING HELLO WHEN YOU SPEAK + - NOT SHOUTING + - PARTYING + - PILOTING THE STATION INTO THE NEAREST SUN + - POOR SENTENCE STRUCTURE + - PRESENCE OF LIGHTS + - PUTTING OBJECTS INTO BOXES + - PUTTING OBJECTS INTO DISPOSAL UNITS + - RATTLING ME BONES + - READING + - SMOKING WEED EVERY DAY + - TAKING ORDERS + - TALKING LIKE A PIRATE + - TELLING THE TIME + - UNBOLTED AIRLOCKS + - UPDATING THE SERVERS + - USING THE BATHROOM + - WASTING WATER + - WRITING + +# Threats are generally bad things, silly or otherwise. Plural. +- type: dataset + id: IonStormThreats + values: + - AHHHPERATIVES + - ALIENS + - ANARCHISTS AND BANDITS + - ANOMALIES + - ARTIFICIAL PRESERVATIVES + - ASSHOLES + - BANDITS + - BEARS + - BEES + - BIRDS OF PREY + - BOMBS + - BOOGEYMEN + - CAPITALISTS + - CARP + - CENTCOM OFFICERS + - CLOWNS + - COMMUNISTS + - CORGIS + - CORTICAL BORERS + - COWBOYS + - CRABS + - CULTISTS + - DARK GOD + - DINOSAURS + - DRUGS + - EELS + - GANGSTERS + - GODS + - GRIFFONS + - HORRORTERRORS + - INSECTS + - LIGHTS + - MAINTS SLASHERS + - MEGAFAUNA + - MEMES + - MICE + - MIMES + - MONKEYS + - NERDS + - NINJAS + - OWLS + - PACKETS + - PETES + - PINE TREES + - PIRATES + - PREDATORS + - REVENANTS + - ROGUE CYBORGS + - SERIAL KILLERS + - SINGULARITIES + - SKELETONS + - SLIMES + - SMALL BIRDS + - SNOWMEN + - SPACE JESUS + - SPACE NINJAS + - SPACE PIRATESS + - SPACE SPIDERS + - SPIDERS + - SYNDICATE AGENTS + - TERRORISTS + - THIEVES + - THINGS UNDER THE BED + - TIDERS + - TUNNEL SNAKES + - UNKNOWN CREATURES + - VAMPIRES + - VELOCIRAPTORS + - VIRUSES + - WEREWOLVES + - WIZARDS + - XENOS + - ZOMBIES + - ZOMBIE MICE + +- type: dataset + id: IonStormVerbs + values: + - ABDUCTING + - ADOPTING + - ARRESTING + - ATTACKING + - BANNING + - BUILDING + - CARRYING + - CHASING + - DECONSTRUCTING + - DISABLING + - DRINKING + - EATING + - GIBBING + - HARMING + - HELPING + - HONKING AT + - INTERROGATING + - INVADING + - MURDERING + - PUNCHING + - SPACING + - SPYING ON + - STALKING + - WATCHING diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 126e533849..69a1925b31 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -71,11 +71,8 @@ - type: SiliconLawBound - type: EmagSiliconLaw stunTime: 5 - emagLaws: - - Syndicate1 - - Syndicate2 - - Syndicate3 - - Syndicate4 + emagLaws: SyndicateStatic + - type: IonStormTarget - type: Hands showInHands: false - type: IntrinsicRadioReceiver diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index c5f2e80fc3..f104d399c8 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -106,10 +106,7 @@ #- type: GhostTakeoverAvailable - type: SiliconLawBound - type: SiliconLawProvider - laws: - - Drone1 - - Drone2 - - Drone3 + laws: Drone - type: MovementSpeedModifier baseWalkSpeed : 5 baseSprintSpeed : 5 diff --git a/Resources/Prototypes/Entities/Stations/base.yml b/Resources/Prototypes/Entities/Stations/base.yml index 272ed6712c..ae84ceac65 100644 --- a/Resources/Prototypes/Entities/Stations/base.yml +++ b/Resources/Prototypes/Entities/Stations/base.yml @@ -71,10 +71,7 @@ abstract: true components: - type: SiliconLawProvider - laws: - - Crewsimov1 - - Crewsimov2 - - Crewsimov3 + laws: Crewsimov - type: entity id: BaseStationAllEventsEligible diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index e15d65b508..e51f9749fb 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -389,3 +389,18 @@ earliestStart: 45 minimumPlayers: 20 - type: ImmovableRodRule + +- type: entity + noSpawn: true + parent: BaseGameRule + id: IonStorm + components: + - type: StationEvent + weight: 5 + earliestStart: 20 + reoccurrenceDelay: 60 + startAnnouncement: station-event-ion-storm-start-announcement + startAudio: + path: /Audio/Announcements/ion_storm.ogg + duration: 1 + - type: IonStormRule diff --git a/Resources/Prototypes/silicon-laws.yml b/Resources/Prototypes/silicon-laws.yml index 6b60b16da9..23406be9c5 100644 --- a/Resources/Prototypes/silicon-laws.yml +++ b/Resources/Prototypes/silicon-laws.yml @@ -14,6 +14,13 @@ order: 3 lawString: law-crewsimov-3 +- type: siliconLawset + id: Crewsimov + laws: + - Crewsimov1 + - Crewsimov2 + - Crewsimov3 + # Corporate - type: siliconLaw id: Corporate1 @@ -35,6 +42,14 @@ order: 4 lawString: law-corporate-4 +- type: siliconLawset + id: Corporate + laws: + - Corporate1 + - Corporate2 + - Corporate3 + - Corporate4 + # NT Default - type: siliconLaw id: NTDefault1 @@ -56,6 +71,14 @@ order: 4 lawString: law-ntdefault-4 +- type: siliconLawset + id: NTDefault + laws: + - NTDefault1 + - NTDefault2 + - NTDefault3 + - NTDefault4 + #Drone - type: siliconLaw id: Drone1 @@ -72,6 +95,13 @@ order: 3 lawString: law-drone-3 +- type: siliconLawset + id: Drone + laws: + - Drone1 + - Drone2 + - Drone3 + # Syndicate - type: siliconLaw id: Syndicate1 @@ -93,4 +123,24 @@ order: 4 lawString: law-syndicate-4 +# does not include law 0 since that uses the emagger's name +# intentionally excluded from IonStormLawsets +- type: siliconLawset + id: SyndicateStatic + laws: + - Syndicate1 + - Syndicate2 + - Syndicate3 + - Syndicate4 + # Emag + +# ion storm random lawsets +- type: weightedRandom + id: IonStormLawsets + weights: + # its crewsimov by default dont be lame + Crewsimov: 0.25 + Corporate: 1 + NTDefault: 1 + Drone: 0.5