From 34bdb773f9ee3c8117a3719fc6001f8b174206c1 Mon Sep 17 00:00:00 2001 From: Slava0135 <40753025+Slava0135@users.noreply.github.com> Date: Thu, 15 Jun 2023 09:45:50 +0300 Subject: [PATCH] Mass hallucinations event (#17321) * paracusia component auto comp state * it works * rule component config --- .../Components/MassHallucinationsComponent.cs | 11 ++++++ .../MassHallucinationsRuleComponent.cs | 26 +++++++++++++ .../Events/MassHallucinationsRule.cs | 39 +++++++++++++++++++ .../Traits/Assorted/ParacusiaSystem.cs | 30 ++++++++++++++ .../Traits/Assorted/ParacusiaComponent.cs | 30 ++++---------- .../Traits/Assorted/SharedParacusiaSystem.cs | 25 ------------ Resources/Prototypes/GameRules/events.yml | 16 ++++++++ 7 files changed, 130 insertions(+), 47 deletions(-) create mode 100644 Content.Server/StationEvents/Components/MassHallucinationsComponent.cs create mode 100644 Content.Server/StationEvents/Components/MassHallucinationsRuleComponent.cs create mode 100644 Content.Server/StationEvents/Events/MassHallucinationsRule.cs diff --git a/Content.Server/StationEvents/Components/MassHallucinationsComponent.cs b/Content.Server/StationEvents/Components/MassHallucinationsComponent.cs new file mode 100644 index 0000000000..d5522df80d --- /dev/null +++ b/Content.Server/StationEvents/Components/MassHallucinationsComponent.cs @@ -0,0 +1,11 @@ +using Content.Server.StationEvents.Events; + +namespace Content.Server.StationEvents.Components; + +/// +/// This is used to keep track of hallucinated entities to remove effects when event ends +/// +[RegisterComponent, Access(typeof(MassHallucinationsRule))] +public sealed class MassHallucinationsComponent : Component +{ +} diff --git a/Content.Server/StationEvents/Components/MassHallucinationsRuleComponent.cs b/Content.Server/StationEvents/Components/MassHallucinationsRuleComponent.cs new file mode 100644 index 0000000000..e16eb39d76 --- /dev/null +++ b/Content.Server/StationEvents/Components/MassHallucinationsRuleComponent.cs @@ -0,0 +1,26 @@ +using Content.Server.StationEvents.Events; +using Robust.Shared.Audio; + +namespace Content.Server.StationEvents.Components; + +[RegisterComponent, Access(typeof(MassHallucinationsRule))] +public sealed class MassHallucinationsRuleComponent : Component +{ + /// + /// The maximum time between incidents in seconds + /// + [DataField("maxTimeBetweenIncidents", required: true), ViewVariables(VVAccess.ReadWrite)] + public float MaxTimeBetweenIncidents; + + /// + /// The minimum time between incidents in seconds + /// + [DataField("minTimeBetweenIncidents", required: true), ViewVariables(VVAccess.ReadWrite)] + public float MinTimeBetweenIncidents; + + [DataField("maxSoundDistance", required: true), ViewVariables(VVAccess.ReadWrite)] + public float MaxSoundDistance; + + [DataField("sounds", required: true)] + public SoundSpecifier Sounds = default!; +} diff --git a/Content.Server/StationEvents/Events/MassHallucinationsRule.cs b/Content.Server/StationEvents/Events/MassHallucinationsRule.cs new file mode 100644 index 0000000000..1e561a3606 --- /dev/null +++ b/Content.Server/StationEvents/Events/MassHallucinationsRule.cs @@ -0,0 +1,39 @@ +using Content.Server.GameTicking.Rules.Components; +using Content.Server.Mind.Components; +using Content.Server.StationEvents.Components; +using Content.Server.Traits.Assorted; +using Content.Shared.Traits.Assorted; + +namespace Content.Server.StationEvents.Events; + +public sealed class MassHallucinationsRule : StationEventSystem +{ + [Dependency] private readonly ParacusiaSystem _paracusia = default!; + + protected override void Started(EntityUid uid, MassHallucinationsRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, component, gameRule, args); + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var ent, out _)) + { + if (!HasComp(ent)) + { + EnsureComp(ent); + var paracusia = EnsureComp(ent); + _paracusia.SetSounds(ent, component.Sounds, paracusia); + _paracusia.SetTime(ent, component.MinTimeBetweenIncidents, component.MaxTimeBetweenIncidents, paracusia); + _paracusia.SetDistance(ent, component.MaxSoundDistance); + } + } + } + + protected override void Ended(EntityUid uid, MassHallucinationsRuleComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args) + { + base.Ended(uid, component, gameRule, args); + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var ent, out _)) + { + RemComp(ent); + } + } +} diff --git a/Content.Server/Traits/Assorted/ParacusiaSystem.cs b/Content.Server/Traits/Assorted/ParacusiaSystem.cs index 2008d170ab..4b0205ff53 100644 --- a/Content.Server/Traits/Assorted/ParacusiaSystem.cs +++ b/Content.Server/Traits/Assorted/ParacusiaSystem.cs @@ -1,8 +1,38 @@ using Content.Shared.Traits.Assorted; +using Robust.Shared.Audio; namespace Content.Server.Traits.Assorted; public sealed class ParacusiaSystem : SharedParacusiaSystem { + public void SetSounds(EntityUid uid, SoundSpecifier sounds, ParacusiaComponent? component = null) + { + if (!Resolve(uid, ref component)) + { + return; + } + component.Sounds = sounds; + Dirty(component); + } + public void SetTime(EntityUid uid, float minTime, float maxTime, ParacusiaComponent? component = null) + { + if (!Resolve(uid, ref component)) + { + return; + } + component.MinTimeBetweenIncidents = minTime; + component.MaxTimeBetweenIncidents = maxTime; + Dirty(component); + } + + public void SetDistance(EntityUid uid, float maxSoundDistance, ParacusiaComponent? component = null) + { + if (!Resolve(uid, ref component)) + { + return; + } + component.MaxSoundDistance = maxSoundDistance; + Dirty(component); + } } diff --git a/Content.Shared/Traits/Assorted/ParacusiaComponent.cs b/Content.Shared/Traits/Assorted/ParacusiaComponent.cs index ef86169a69..51a7471f1e 100644 --- a/Content.Shared/Traits/Assorted/ParacusiaComponent.cs +++ b/Content.Shared/Traits/Assorted/ParacusiaComponent.cs @@ -1,7 +1,5 @@ using Robust.Shared.Audio; using Robust.Shared.GameStates; -using System; -using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Shared.Traits.Assorted; @@ -10,31 +8,36 @@ namespace Content.Shared.Traits.Assorted; /// This component is used for paracusia, which causes auditory hallucinations. /// [RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState] [Access(typeof(SharedParacusiaSystem))] -public sealed class ParacusiaComponent : Component +public sealed partial class ParacusiaComponent : Component { /// /// The maximum time between incidents in seconds /// [DataField("maxTimeBetweenIncidents", required: true), ViewVariables(VVAccess.ReadWrite)] - public float MaxTimeBetweenIncidents = 30f; + [AutoNetworkedField] + public float MaxTimeBetweenIncidents = 60f; /// /// The minimum time between incidents in seconds /// [DataField("minTimeBetweenIncidents", required: true), ViewVariables(VVAccess.ReadWrite)] - public float MinTimeBetweenIncidents = 60f; + [AutoNetworkedField] + public float MinTimeBetweenIncidents = 30f; /// /// How far away at most can the sound be? /// [DataField("maxSoundDistance", required: true), ViewVariables(VVAccess.ReadWrite)] + [AutoNetworkedField] public float MaxSoundDistance; /// /// The sounds to choose from /// [DataField("sounds", required: true)] + [AutoNetworkedField] public SoundSpecifier Sounds = default!; [DataField("timeBetweenIncidents", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] @@ -42,20 +45,3 @@ public sealed class ParacusiaComponent : Component public IPlayingAudioStream? Stream; } - -[Serializable, NetSerializable] -public sealed class ParacusiaComponentState : ComponentState -{ - public readonly float MaxTimeBetweenIncidents; - public readonly float MinTimeBetweenIncidents; - public readonly float MaxSoundDistance; - public readonly SoundSpecifier Sounds = default!; - - public ParacusiaComponentState(float maxTimeBetweenIncidents, float minTimeBetweenIncidents, float maxSoundDistance, SoundSpecifier sounds) - { - MaxTimeBetweenIncidents = maxTimeBetweenIncidents; - MinTimeBetweenIncidents = minTimeBetweenIncidents; - MaxSoundDistance = maxSoundDistance; - Sounds = sounds; - } -} diff --git a/Content.Shared/Traits/Assorted/SharedParacusiaSystem.cs b/Content.Shared/Traits/Assorted/SharedParacusiaSystem.cs index 6eb0f6b223..2bfb0da1f5 100644 --- a/Content.Shared/Traits/Assorted/SharedParacusiaSystem.cs +++ b/Content.Shared/Traits/Assorted/SharedParacusiaSystem.cs @@ -1,30 +1,5 @@ -using Content.Shared.GameTicking; -using Robust.Shared.GameStates; - namespace Content.Shared.Traits.Assorted; public abstract class SharedParacusiaSystem : EntitySystem { - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(GetCompState); - SubscribeLocalEvent(HandleCompState); - } - - private void GetCompState(EntityUid uid, ParacusiaComponent component, ref ComponentGetState args) - { - args.State = new ParacusiaComponentState(component.MaxTimeBetweenIncidents, component.MinTimeBetweenIncidents, component.MaxSoundDistance, component.Sounds); - } - - private void HandleCompState(EntityUid uid, ParacusiaComponent component, ref ComponentHandleState args) - { - if (args.Current is not ParacusiaComponentState state) - return; - - component.MaxTimeBetweenIncidents = state.MaxTimeBetweenIncidents; - component.MinTimeBetweenIncidents = state.MinTimeBetweenIncidents; - component.MaxSoundDistance = state.MaxSoundDistance; - component.Sounds = state.Sounds; - } } diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 0df115ea3c..b781e8753a 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -316,3 +316,19 @@ reoccurrenceDelay: 25 duration: 1 - type: LoneOpsSpawnRule + +- type: entity + id: MassHallucinations + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + weight: 10 + duration: 150 + maxDuration: 300 + - type: MassHallucinationsRule + minTimeBetweenIncidents: 0.1 + maxTimeBetweenIncidents: 300 + maxSoundDistance: 7 + sounds: + collection: Paracusia