]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Re-add improved random sentience event (#29123)
authorPsychpsyo <60073468+Psychpsyo@users.noreply.github.com>
Sun, 18 Aug 2024 23:41:12 +0000 (01:41 +0200)
committerGitHub <noreply@github.com>
Sun, 18 Aug 2024 23:41:12 +0000 (17:41 -0600)
* Re-add improved random sentience event

* Make randomly sentient PDA more likely

* Make vending machine sentience less likely

* Make requested changes

* Make randomly sentient captain's gear more likely

* Sentient captain sabre has pirate accent

* Tweak new random sentient object a bit more

* Sentient PDA improvements

* Apply recommended fixes

* Add requested changes

* Fix merge conflict

14 files changed:
Content.Server/StationEvents/Components/RandomSentienceRuleComponent.cs
Content.Server/StationEvents/Components/SentienceTargetComponent.cs
Content.Server/StationEvents/Events/RandomSentienceRule.cs
Content.Shared/Interaction/Components/BlockMovementComponent.cs
Content.Shared/Interaction/SharedInteractionSystem.Blocking.cs
Resources/Locale/en-US/station-events/events/random-sentience.ftl
Resources/Prototypes/Entities/Clothing/Head/hats.yml
Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
Resources/Prototypes/Entities/Objects/Devices/pda.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml
Resources/Prototypes/GameRules/random_sentience.yml [new file with mode: 0644]

index 98ebf06595d16a62a5406a26445e3e6be9b56cb1..369fce9725c886c16f5517380fa2ce918a4c9120 100644 (file)
@@ -1,9 +1,13 @@
-using Content.Server.StationEvents.Events;
+using Content.Server.StationEvents.Events;
 
 namespace Content.Server.StationEvents.Components;
 
 [RegisterComponent, Access(typeof(RandomSentienceRule))]
 public sealed partial class RandomSentienceRuleComponent : Component
 {
+    [DataField]
+    public int MinSentiences = 1;
 
+    [DataField]
+    public int MaxSentiences = 1;
 }
index f8f7e587c1922f2d718617b6ed57633e5c8ce680..4fb5e4be599ef899338a103075b71cfc53f4908f 100644 (file)
@@ -1,10 +1,13 @@
-using Content.Server.StationEvents.Events;
+using Content.Server.StationEvents.Events;
 
 namespace Content.Server.StationEvents.Components;
 
 [RegisterComponent, Access(typeof(RandomSentienceRule))]
 public sealed partial class SentienceTargetComponent : Component
 {
-    [DataField("flavorKind", required: true)]
+    [DataField(required: true)]
     public string FlavorKind = default!;
+
+    [DataField]
+    public float Weight = 1.0f;
 }
index 3869f227bd4dd7fdf6e0155313b65786738a2b2e..3d2e457a34c208644e44309a7dccdb2ed0074830 100644 (file)
@@ -1,33 +1,56 @@
-using System.Linq;
-using Content.Server.GameTicking.Rules.Components;
+using System.Linq;
+using Content.Shared.Dataset;
 using Content.Server.Ghost.Roles.Components;
 using Content.Server.StationEvents.Components;
 using Content.Shared.GameTicking.Components;
+using Content.Shared.Random.Helpers;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
 
 namespace Content.Server.StationEvents.Events;
 
 public sealed class RandomSentienceRule : StationEventSystem<RandomSentienceRuleComponent>
 {
+    [Dependency] private readonly IPrototypeManager _prototype = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
     protected override void Started(EntityUid uid, RandomSentienceRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
     {
-        HashSet<EntityUid> stationsToNotify = new();
+        if (!TryGetRandomStation(out var station))
+            return;
 
         var targetList = new List<Entity<SentienceTargetComponent>>();
-        var query = EntityQueryEnumerator<SentienceTargetComponent>();
-        while (query.MoveNext(out var targetUid, out var target))
+        var query = EntityQueryEnumerator<SentienceTargetComponent, TransformComponent>();
+        while (query.MoveNext(out var targetUid, out var target, out var xform))
         {
+            if (StationSystem.GetOwningStation(targetUid, xform) != station)
+                continue;
+
             targetList.Add((targetUid, target));
         }
 
-        RobustRandom.Shuffle(targetList);
+        var toMakeSentient = _random.Next(component.MinSentiences, component.MaxSentiences);
 
-        var toMakeSentient = RobustRandom.Next(2, 5);
         var groups = new HashSet<string>();
 
-        foreach (var target in targetList)
+        for (var i = 0; i < toMakeSentient && targetList.Count > 0; i++)
         {
-            if (toMakeSentient-- == 0)
-                break;
+            // weighted random to pick a sentience target
+            var totalWeight = targetList.Sum(x => x.Comp.Weight);
+            // This initial target should never be picked.
+            // It's just so that target doesn't need to be nullable and as a safety fallback for id floating point errors ever mess up the comparison in the foreach.
+            var target = targetList[0];
+            var chosenWeight = _random.NextFloat(totalWeight);
+            var currentWeight = 0.0;
+            foreach (var potentialTarget in targetList)
+            {
+                currentWeight += potentialTarget.Comp.Weight;
+                if (currentWeight > chosenWeight)
+                {
+                    target = potentialTarget;
+                    break;
+                }
+            }
+            targetList.Remove(target);
 
             RemComp<SentienceTargetComponent>(target);
             var ghostRole = EnsureComp<GhostRoleComponent>(target);
@@ -45,24 +68,15 @@ public sealed class RandomSentienceRule : StationEventSystem<RandomSentienceRule
         var kind2 = groupList.Count > 1 ? groupList[1] : "???";
         var kind3 = groupList.Count > 2 ? groupList[2] : "???";
 
-        foreach (var target in targetList)
-        {
-            var station = StationSystem.GetOwningStation(target);
-            if(station == null)
-                continue;
-            stationsToNotify.Add((EntityUid) station);
-        }
-        foreach (var station in stationsToNotify)
-        {
-            ChatSystem.DispatchStationAnnouncement(
-                station,
-                Loc.GetString("station-event-random-sentience-announcement",
-                    ("kind1", kind1), ("kind2", kind2), ("kind3", kind3), ("amount", groupList.Count),
-                    ("data", Loc.GetString($"random-sentience-event-data-{RobustRandom.Next(1, 6)}")),
-                    ("strength", Loc.GetString($"random-sentience-event-strength-{RobustRandom.Next(1, 8)}"))),
-                playDefaultSound: false,
-                colorOverride: Color.Gold
-            );
-        }
+        ChatSystem.DispatchStationAnnouncement(
+            station.Value,
+            Loc.GetString("station-event-random-sentience-announcement",
+                ("kind1", kind1), ("kind2", kind2), ("kind3", kind3), ("amount", groupList.Count),
+                ("data", _random.Pick(_prototype.Index<LocalizedDatasetPrototype>("RandomSentienceEventData"))),
+                ("strength", _random.Pick(_prototype.Index<LocalizedDatasetPrototype>("RandomSentienceEventStrength")))
+            ),
+            playDefaultSound: false,
+            colorOverride: Color.Gold
+        );
     }
 }
index e308e849601a601cb72a1e8b09de2ea7dbfa1bb7..2125f16efe0e46fd5a805bf93047619ddca9e5af 100644 (file)
@@ -1,4 +1,4 @@
-using Robust.Shared.GameStates;
+using Robust.Shared.GameStates;
 
 namespace Content.Shared.Interaction.Components;
 
@@ -8,5 +8,6 @@ namespace Content.Shared.Interaction.Components;
 [RegisterComponent, NetworkedComponent]
 public sealed partial class BlockMovementComponent : Component
 {
-
+    [DataField]
+    public bool BlockInteraction = true;
 }
index a682bf981597c6bdaf1ae27c8d5639d57a2d0e90..52c40477c9cf28f59244d6224f9746883711ce25 100644 (file)
@@ -28,7 +28,8 @@ public partial class SharedInteractionSystem
 
     private void CancelInteractEvent(Entity<BlockMovementComponent> ent, ref InteractionAttemptEvent args)
     {
-        args.Cancelled = true;
+        if (ent.Comp.BlockInteraction)
+            args.Cancelled = true;
     }
 
     private void OnMoveAttempt(EntityUid uid, BlockMovementComponent component, UpdateCanMoveEvent args)
index 47f0e317a65db7677eb65db22ed5fcdc2e0bc24b..f14a020d29e87bad08415c2f566407e3143690bf 100644 (file)
@@ -36,3 +36,4 @@ station-event-random-sentience-flavor-corgi = corgi
 station-event-random-sentience-flavor-primate = primate
 station-event-random-sentience-flavor-kobold = kobold
 station-event-random-sentience-flavor-slime = slime
+station-event-random-sentience-flavor-inanimate = inanimate
\ No newline at end of file
index 0ca55f76144fab341727abf0a33b41efe92870a6..02275d5a2f2e632be48c0fb544746bb634fcd644 100644 (file)
     - ClothMade
     - WhitelistChameleon
     - HamsterWearable
+  - type: SentienceTarget
+    flavorKind: station-event-random-sentience-flavor-inanimate
+    weight: 0.0002 # 5,000 times less likely than 1 regular animal
+  - type: BlockMovement
 
 - type: entity
   parent: ClothingHeadBase
index 0ea345bb6fd4200f3ede650df3e0727858e792a2..a403486338d5fffe2670632e78e6295eface41d8 100644 (file)
       behaviors:
       - !type:GibBehavior { }
   - type: NonSpreaderZombie
+  - type: SentienceTarget
+    flavorKind: station-event-random-sentience-flavor-organic
 
 - type: entity
   name: glockroach
index 9c9499808d9f806fc85ba86a228b5bc00cd0953f..9ba0fdd873667a76f4e1febc0a7e1be043134980 100644 (file)
   - type: Construction
     graph: MediBot
     node: bot
+  - type: SentienceTarget
+    flavorKind: station-event-random-sentience-flavor-mechanical
   - type: Anchorable
   - type: InteractionPopup
     interactSuccessString: petting-success-medibot
index faad961ebdfb1d0e4b6b59384a4a6927cd14fabb..65639ecf11690473b3cf9f20b363ab0718a2e12c 100644 (file)
     - DoorBumpOpener
   - type: Input
     context: "human"
+  - type: SentienceTarget # sentient PDA = pAI lite
+    flavorKind: station-event-random-sentience-flavor-mechanical
+    weight: 0.001 # 1,000 PDAs = as likely to be picked as 1 regular animal
+  - type: BlockMovement
+    blockInteraction: false # lets the PDA toggle its own flashlight
+  - type: TypingIndicator
+    proto: robot
+  - type: Speech
+    speechVerb: Robotic
 
 - type: entity
   parent: BasePDA
     borderColor: "#d7d7d0"
   - type: Icon
     state: pda-cook
+  - type: ReplacementAccent # for random sentience event
+    accent: italian
 
 - type: entity
   parent: BasePDA
     accentHColor: "#333333"
   - type: Icon
     state: pda-mime
+  - type: Muted # for random sentience event
 
 - type: entity
   name: chaplain PDA
index 715905a5339cbdeffdd5a787163034266855e8b1..5b8130567b3b2b8cca707c04cdfa875e5287f10b 100644 (file)
     price: 750
   - type: StealTarget
     stealGroup: WeaponAntiqueLaser
+  - type: SentienceTarget # I hope this is only the captain's gun
+    flavorKind: station-event-random-sentience-flavor-inanimate
+    weight: 0.0002 # 5,000 times less likely than 1 regular animal
+    # not putting a BlockMovement component here cause that's funny.
 
 - type: entity
   name: advanced laser pistol
index 586247bb3a95a823e8efeb02357c7a075331f49e..1784eae81075713fc353c7876e580d19793230c6 100644 (file)
     tags:
     - CaptainSabre
   - type: DisarmMalus
+  - type: SentienceTarget
+    flavorKind: station-event-random-sentience-flavor-inanimate
+    weight: 0.0002 # 5,000 times less likely than 1 regular animal
+  - type: PirateAccent
+    # not putting a BlockMovement component here cause that's funny.
 
 - type: entity
   name: katana
index 74e5a7a0522dab7d73970cec904993623e598195..3e931aeb33084712d941e349ca0e676de7f43c9e 100644 (file)
@@ -96,6 +96,7 @@
   - type: Actions
   - type: SentienceTarget
     flavorKind: station-event-random-sentience-flavor-mechanical
+    weight: 0.025 # fuck you in particular (it now needs 40 vending machines to be as likely as 1 interesting animal)
   - type: StaticPrice
     price: 100
   - type: Appearance
diff --git a/Resources/Prototypes/GameRules/random_sentience.yml b/Resources/Prototypes/GameRules/random_sentience.yml
new file mode 100644 (file)
index 0000000..a2c7490
--- /dev/null
@@ -0,0 +1,25 @@
+- type: entity
+  id: RandomSentience
+  parent: BaseGameRule
+  components:
+  - type: StationEvent
+    weight: 6
+    duration: 1
+    maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it
+    startAudio:
+      path: /Audio/Announcements/attention.ogg
+  - type: RandomSentienceRule
+    minSentiences: 2
+    maxSentiences: 5
+
+- type: localizedDataset
+  id: RandomSentienceEventData
+  values:
+    prefix: random-sentience-event-data-
+    count: 6
+
+- type: localizedDataset
+  id: RandomSentienceEventStrength
+  values:
+    prefix: random-sentience-event-strength-
+    count: 8
\ No newline at end of file