From d8707735d694abac0066bb607c96424e5c466457 Mon Sep 17 00:00:00 2001 From: Ed Date: Sun, 29 Sep 2024 21:55:28 +0300 Subject: [PATCH] ritual cucumber setup --- .../CP14RitualSystem.Requirements.cs | 21 +++++ .../MagicRituals/CP14RitualSystem.Triggers.cs | 82 +++++++++++++++++++ .../_CP14/MagicRituals/CP14RitualSystem.cs | 58 +++++++++++++ .../Components/CP14MagicRitualComponent.cs | 19 +++++ .../CP14MagicRitualPhaseComponent.cs | 14 ++++ .../CP14RitualRequirementEntitiesComponent.cs | 38 +++++++++ .../CP14RitualTriggerTimerComponent.cs | 20 +++++ .../CP14RitualTriggerVoiceComponent.cs | 26 ++++++ .../_CP14/MagicRitual/CP14MagicRitalEvents.cs | 13 +++ .../_CP14/Entities/Ritual/phases.yml | 64 +++++++++++++++ 10 files changed, 355 insertions(+) create mode 100644 Content.Server/_CP14/MagicRituals/CP14RitualSystem.Requirements.cs create mode 100644 Content.Server/_CP14/MagicRituals/CP14RitualSystem.Triggers.cs create mode 100644 Content.Server/_CP14/MagicRituals/CP14RitualSystem.cs create mode 100644 Content.Server/_CP14/MagicRituals/Components/CP14MagicRitualComponent.cs create mode 100644 Content.Server/_CP14/MagicRituals/Components/CP14MagicRitualPhaseComponent.cs create mode 100644 Content.Server/_CP14/MagicRituals/Components/Requirements/CP14RitualRequirementEntitiesComponent.cs create mode 100644 Content.Server/_CP14/MagicRituals/Components/Triggers/CP14RitualTriggerTimerComponent.cs create mode 100644 Content.Server/_CP14/MagicRituals/Components/Triggers/CP14RitualTriggerVoiceComponent.cs create mode 100644 Content.Shared/_CP14/MagicRitual/CP14MagicRitalEvents.cs create mode 100644 Resources/Prototypes/_CP14/Entities/Ritual/phases.yml diff --git a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Requirements.cs b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Requirements.cs new file mode 100644 index 0000000000..237a947811 --- /dev/null +++ b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Requirements.cs @@ -0,0 +1,21 @@ +using Content.Server._CP14.MagicRituals.Components.Requirements; +using Content.Shared._CP14.MagicRitual; + +namespace Content.Server._CP14.MagicRituals; + +public sealed partial class CP14RitualSystem +{ + [Dependency] private readonly EntityLookupSystem _lookup = default!; + + private void InitializeRequirements() + { + SubscribeLocalEvent(OnResourceRequirementCheck); + } + + private void OnResourceRequirementCheck(Entity ent, ref CP14RitualTriggerAttempt args) + { + var entitiesAround = _lookup.GetEntitiesInRange(ent, ent.Comp.CheckRange, LookupFlags.Uncontained); + + + } +} diff --git a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Triggers.cs b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Triggers.cs new file mode 100644 index 0000000000..a6406d472f --- /dev/null +++ b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Triggers.cs @@ -0,0 +1,82 @@ +using Content.Server._CP14.MagicRituals.Components.Triggers; +using Content.Server.Speech; +using Content.Server.Speech.Components; +using Content.Shared._CP14.MagicRitual; + +namespace Content.Server._CP14.MagicRituals; + +public sealed partial class CP14RitualSystem +{ + private void InitializeTriggers() + { + SubscribeLocalEvent(OnVoiceInit); + SubscribeLocalEvent(OnListen); + + SubscribeLocalEvent(OnTimerMapInit); + } + + private void UpdateTriggers(float frameTime) + { + TimerUpdate(); + } + + #region Trigger timer + + private void OnTimerMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.TriggerTime = _timing.CurTime + TimeSpan.FromSeconds(ent.Comp.Time.Next(_random)); + } + + private void TimerUpdate() + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var timer)) + { + if (_timing.CurTime < timer.TriggerTime) + continue; + + timer.TriggerTime += TimeSpan.FromSeconds(timer.Time.Next(_random)); + + var ev = new CP14RitualTriggerAttempt(timer.NextPhase); + RaiseLocalEvent(uid, ev); + } + } + + #endregion + + #region Trigger voice + + private void OnVoiceInit(Entity ent, ref ComponentInit args) + { + EnsureComp(ent).Range = ent.Comp.ListenRange; + } + + private void OnListen(Entity ent, ref ListenEvent args) + { + var message = args.Message.Trim(); + + var triggered = false; + foreach (var trigger in ent.Comp.NextPhases) + { + if (trigger.Key != message) + continue; + + var triggerEv = new CP14RitualTriggerAttempt(trigger.Value); + RaiseLocalEvent(ent, triggerEv); + triggered = true; + break; + } + + if (triggered || ent.Comp.FailAttempts is null || ent.Comp.FailedPhase is null) + return; + + ent.Comp.FailAttempts -= 1; + + if (!(ent.Comp.FailAttempts <= 0)) + return; + + var failEv = new CP14RitualTriggerAttempt(ent.Comp.FailedPhase.Value); + RaiseLocalEvent(ent, failEv); + } + #endregion +} diff --git a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.cs b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.cs new file mode 100644 index 0000000000..9f6e5bca4f --- /dev/null +++ b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.cs @@ -0,0 +1,58 @@ +using Content.Server._CP14.MagicRituals.Components; +using Content.Shared._CP14.MagicRitual; +using Robust.Server.GameObjects; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Server._CP14.MagicRituals; + +public partial class CP14RitualSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly TransformSystem _transform = default!; + + public override void Initialize() + { + base.Initialize(); + + InitializeTriggers(); + InitializeRequirements(); + + SubscribeLocalEvent(OnRitualInit); + SubscribeLocalEvent(OnPhaseTriggerAttempt); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + UpdateTriggers(frameTime); + } + + private void OnRitualInit(Entity ritual, ref MapInitEvent args) + { + ChangePhase(ritual, ritual.Comp.StartPhase); + } + + private void OnPhaseTriggerAttempt(Entity phase, ref CP14RitualTriggerAttempt args) + { + if (args.Cancelled || args.NextPhase is null || phase.Comp.Ritual is null) + return; + + ChangePhase(phase.Comp.Ritual.Value, args.NextPhase.Value); + } + + private void ChangePhase(Entity ritual, EntProtoId newPhase) + { + QueueDel(ritual.Comp.CurrentPhase); + + var newPhaseEnt = Spawn(newPhase, Transform(ritual).Coordinates); + _transform.SetParent(newPhaseEnt, ritual); + var newPhaseComp = EnsureComp(newPhaseEnt); + + ritual.Comp.CurrentPhase = (newPhaseEnt, newPhaseComp); + newPhaseComp.Ritual = ritual; + } +} diff --git a/Content.Server/_CP14/MagicRituals/Components/CP14MagicRitualComponent.cs b/Content.Server/_CP14/MagicRituals/Components/CP14MagicRitualComponent.cs new file mode 100644 index 0000000000..27ebc54304 --- /dev/null +++ b/Content.Server/_CP14/MagicRituals/Components/CP14MagicRitualComponent.cs @@ -0,0 +1,19 @@ +using Robust.Shared.Prototypes; + +namespace Content.Server._CP14.MagicRituals.Components; + +/// +/// Ritual Behavior Controller. Creates and removes entities of magical phases +/// +[RegisterComponent, Access(typeof(CP14RitualSystem))] +public sealed partial class CP14MagicRitualComponent : Component +{ + [DataField(required: true)] + public EntProtoId StartPhase; + + /// + /// + /// + [DataField] + public Entity? CurrentPhase; +} diff --git a/Content.Server/_CP14/MagicRituals/Components/CP14MagicRitualPhaseComponent.cs b/Content.Server/_CP14/MagicRituals/Components/CP14MagicRitualPhaseComponent.cs new file mode 100644 index 0000000000..4319787b68 --- /dev/null +++ b/Content.Server/_CP14/MagicRituals/Components/CP14MagicRitualPhaseComponent.cs @@ -0,0 +1,14 @@ +namespace Content.Server._CP14.MagicRituals.Components; + +/// +/// Magical entity that reacts to world events +/// +[RegisterComponent, Access(typeof(CP14RitualSystem))] +public sealed partial class CP14MagicRitualPhaseComponent : Component +{ + /// + /// + /// + [DataField] + public Entity? Ritual; +} diff --git a/Content.Server/_CP14/MagicRituals/Components/Requirements/CP14RitualRequirementEntitiesComponent.cs b/Content.Server/_CP14/MagicRituals/Components/Requirements/CP14RitualRequirementEntitiesComponent.cs new file mode 100644 index 0000000000..a84fe5df1c --- /dev/null +++ b/Content.Server/_CP14/MagicRituals/Components/Requirements/CP14RitualRequirementEntitiesComponent.cs @@ -0,0 +1,38 @@ +using Content.Shared.Stacks; +using Robust.Shared.Prototypes; + +namespace Content.Server._CP14.MagicRituals.Components.Requirements; + +/// +/// +/// +[RegisterComponent, Access(typeof(CP14RitualSystem))] +public sealed partial class CP14RitualRequirementEntitiesComponent : Component +{ + [DataField] + public float CheckRange = 1f; + + /// + /// Entities that should be located nearby, but which will not be spent. + /// + [DataField] + public Dictionary RequiredEntities = new (); + + /// + /// Entities to be placed next to each other, which will be spent. + /// + [DataField] + public Dictionary ConsumedEntities = new (); + + [DataField] + public Dictionary, int> RequiredStack = new(); + + [DataField] + public Dictionary, int> ConsumedStack = new(); + + /// + /// Effect appearing in place of used entities + /// + [DataField] + public EntProtoId? VisualEffect; +} diff --git a/Content.Server/_CP14/MagicRituals/Components/Triggers/CP14RitualTriggerTimerComponent.cs b/Content.Server/_CP14/MagicRituals/Components/Triggers/CP14RitualTriggerTimerComponent.cs new file mode 100644 index 0000000000..8182e6fdb3 --- /dev/null +++ b/Content.Server/_CP14/MagicRituals/Components/Triggers/CP14RitualTriggerTimerComponent.cs @@ -0,0 +1,20 @@ +using Content.Shared.Destructible.Thresholds; +using Robust.Shared.Prototypes; + +namespace Content.Server._CP14.MagicRituals.Components.Triggers; + +/// +/// +/// +[RegisterComponent, Access(typeof(CP14RitualSystem))] +public sealed partial class CP14RitualTriggerTimerComponent : Component +{ + [DataField(required: true)] + public MinMax Time = new MinMax(0, 1); + + [DataField] + public TimeSpan TriggerTime = TimeSpan.Zero; + + [DataField(required: true)] + public EntProtoId NextPhase; +} diff --git a/Content.Server/_CP14/MagicRituals/Components/Triggers/CP14RitualTriggerVoiceComponent.cs b/Content.Server/_CP14/MagicRituals/Components/Triggers/CP14RitualTriggerVoiceComponent.cs new file mode 100644 index 0000000000..5ae4b474aa --- /dev/null +++ b/Content.Server/_CP14/MagicRituals/Components/Triggers/CP14RitualTriggerVoiceComponent.cs @@ -0,0 +1,26 @@ +using Robust.Shared.Prototypes; + +namespace Content.Server._CP14.MagicRituals.Components.Triggers; + +/// +/// +/// +[RegisterComponent, Access(typeof(CP14RitualSystem))] +public sealed partial class CP14RitualTriggerVoiceComponent : Component +{ + [DataField] + public float ListenRange = 5f; + + [DataField(required: true)] + public Dictionary NextPhases = new(); + + /// + /// the number of errors (incorrect phrases) that can be said next to the ritual, before switching to FailedPhase. + /// set null, if you want an infinite number of tries + /// + [DataField] + public int? FailAttempts = null; + + [DataField] + public EntProtoId? FailedPhase; +} diff --git a/Content.Shared/_CP14/MagicRitual/CP14MagicRitalEvents.cs b/Content.Shared/_CP14/MagicRitual/CP14MagicRitalEvents.cs new file mode 100644 index 0000000000..a643fbe3b0 --- /dev/null +++ b/Content.Shared/_CP14/MagicRitual/CP14MagicRitalEvents.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.MagicRitual; + +public sealed class CP14RitualTriggerAttempt : CancellableEntityEventArgs +{ + public EntProtoId? NextPhase; + + public CP14RitualTriggerAttempt(EntProtoId phase) + { + NextPhase = phase; + } +} diff --git a/Resources/Prototypes/_CP14/Entities/Ritual/phases.yml b/Resources/Prototypes/_CP14/Entities/Ritual/phases.yml new file mode 100644 index 0000000000..86ab958d47 --- /dev/null +++ b/Resources/Prototypes/_CP14/Entities/Ritual/phases.yml @@ -0,0 +1,64 @@ +- type: entity + id: CP14BaseRitualPhase + abstract: true + components: + - type: CP14MagicRitualPhase + - type: Tag + tags: + - HideContextMenu + +- type: entity + parent: CP14FoodCucumber + id: RitualCucumber + name: ritual cucumber + components: + - type: CP14MagicRitual + startPhase: CP14RitualPhaseTest1 + +- type: entity + parent: CP14BaseRitualPhase + id: CP14RitualPhaseTest1 + components: + - type: PointLight + color: "#FFFF00" + - type: CP14RitualTriggerVoice + nextPhases: + "Hello": CP14RitualPhaseTest2 + "Blya": CP14RitualPhaseTest3 + +- type: entity + parent: CP14BaseRitualPhase + id: CP14RitualPhaseTest2 + components: + - type: PointLight + color: "#FF00FF" + - type: CP14RitualTriggerTimer + nextPhase: CP14RitualPhaseTest1 + time: + min: 5 + max: 10 + - type: EmitSoundOnSpawn + sound: + path: /Audio/Effects/tesla_consume.ogg + params: + variation: 0.3 + +- type: entity + parent: CP14BaseRitualPhase + id: CP14RitualPhaseTest3 + components: + - type: PointLight + color: "#00FFFF" + - type: CP14RitualTriggerVoice + nextPhases: + "Burbon": CP14RitualPhaseTest2 + "Nazad": CP14RitualPhaseTest1 + - type: CP14RitualTriggerTimer + nextPhase: CP14RitualPhaseTest1 + time: + min: 5 + max: 10 + - type: RandomSpawner + deleteSpawnerAfterSpawn: false + prototypes: + - CP14DirtEffect \ No newline at end of file