Re-add improved random sentience event (#29123)

* 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
This commit is contained in:
Psychpsyo
2024-08-19 01:41:12 +02:00
committed by GitHub
parent c48a96ac15
commit 9a68cf0b0e
14 changed files with 114 additions and 35 deletions

View 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;
}

View 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;
}

View 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
);
}
}

View 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;
}

View 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)

View 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

View File

@@ -869,6 +869,10 @@
- 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

View File

@@ -376,6 +376,8 @@
behaviors:
- !type:GibBehavior { }
- type: NonSpreaderZombie
- type: SentienceTarget
flavorKind: station-event-random-sentience-flavor-organic
- type: entity
name: glockroach

View File

@@ -286,6 +286,8 @@
- type: Construction
graph: MediBot
node: bot
- type: SentienceTarget
flavorKind: station-event-random-sentience-flavor-mechanical
- type: Anchorable
- type: InteractionPopup
interactSuccessString: petting-success-medibot

View File

@@ -103,6 +103,15 @@
- 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
@@ -220,6 +229,8 @@
borderColor: "#d7d7d0"
- type: Icon
state: pda-cook
- type: ReplacementAccent # for random sentience event
accent: italian
- type: entity
parent: BasePDA
@@ -299,6 +310,7 @@
accentHColor: "#333333"
- type: Icon
state: pda-mime
- type: Muted # for random sentience event
- type: entity
name: chaplain PDA

View File

@@ -584,6 +584,10 @@
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

View File

@@ -40,6 +40,11 @@
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

View 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

View File

@@ -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