diff --git a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Requirements.cs b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Requirements.cs index 237a947811..07f9746aea 100644 --- a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Requirements.cs +++ b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Requirements.cs @@ -1,5 +1,7 @@ using Content.Server._CP14.MagicRituals.Components.Requirements; using Content.Shared._CP14.MagicRitual; +using Content.Shared.Stacks; +using Robust.Shared.Prototypes; namespace Content.Server._CP14.MagicRituals; @@ -7,15 +9,92 @@ public sealed partial class CP14RitualSystem { [Dependency] private readonly EntityLookupSystem _lookup = default!; + private EntityQuery _metaQuery; + private EntityQuery _stackQuery; + private void InitializeRequirements() { SubscribeLocalEvent(OnResourceRequirementCheck); } - private void OnResourceRequirementCheck(Entity ent, ref CP14RitualTriggerAttempt args) + private void OnResourceRequirementCheck(Entity requirement, ref CP14RitualTriggerAttempt args) { - var entitiesAround = _lookup.GetEntitiesInRange(ent, ent.Comp.CheckRange, LookupFlags.Uncontained); - + var entitiesAround = _lookup.GetEntitiesInRange(requirement, requirement.Comp.CheckRange, LookupFlags.Uncontained); + var passed = true; + + foreach (var reqEnt in requirement.Comp.RequiredEntities) + { + var requiredCount = reqEnt.Value; + + foreach (var entity in entitiesAround) + { + var entProto = MetaData(entity).EntityPrototype; + if (entProto is null) + continue; + + if (entProto.ID == reqEnt.Key && requiredCount > 0) + { + Spawn(requirement.Comp.VisualEffect, Transform(entity).Coordinates); + + requiredCount--; + if (requirement.Comp.ConsumeResource) + Del(entity); + } + } + + if (requiredCount > 0) + passed = false; + } + + foreach (var reqStack in requirement.Comp.RequiredStack) + { + var requiredCount = reqStack.Value; + + foreach (var entity in entitiesAround) + { + if (!_stackQuery.TryGetComponent(entity, out var stack)) + continue; + + if (stack.StackTypeId != reqStack.Key) + continue; + + var count = (int)MathF.Min(requiredCount, stack.Count); + requiredCount -= count; + + Spawn(requirement.Comp.VisualEffect, Transform(entity).Coordinates); + + if (requirement.Comp.ConsumeResource) + { + if (stack.Count - count <= 0) + Del(entity); + else + _stack.SetCount(entity, stack.Count - count, stack); + } + } + + if (requiredCount > 0) + passed = false; + } + + if (!passed) + args.Cancel(); + } + private Dictionary IndexIngredients(HashSet ingredients) + { + var indexedIngredients = new Dictionary(); + + foreach (var ingredient in ingredients) + { + var protoId = _metaQuery.GetComponent(ingredient).EntityPrototype?.ID; + if (protoId == null) + continue; + + if (indexedIngredients.ContainsKey(protoId)) + indexedIngredients[protoId]++; + else + indexedIngredients[protoId] = 1; + } + return indexedIngredients; } } diff --git a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Triggers.cs b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Triggers.cs index a6406d472f..bc5e878e58 100644 --- a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Triggers.cs +++ b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.Triggers.cs @@ -1,7 +1,10 @@ +using Content.Server._CP14.MagicRituals.Components; using Content.Server._CP14.MagicRituals.Components.Triggers; using Content.Server.Speech; using Content.Server.Speech.Components; using Content.Shared._CP14.MagicRitual; +using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Robust.Shared.Prototypes; namespace Content.Server._CP14.MagicRituals; @@ -20,6 +23,18 @@ public sealed partial class CP14RitualSystem TimerUpdate(); } + private void TriggerRitualPhase(Entity ent, EntProtoId nextPhase) + { + var ev = new CP14RitualTriggerAttempt(); + RaiseLocalEvent(ent, ev); + + if (ev.Cancelled) + return; + + var evConfirmed = new CP14RitualTriggerEvent(nextPhase); + RaiseLocalEvent(ent, evConfirmed); + } + #region Trigger timer private void OnTimerMapInit(Entity ent, ref MapInitEvent args) @@ -29,16 +44,15 @@ public sealed partial class CP14RitualSystem private void TimerUpdate() { - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var timer)) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var timer, out var phase)) { if (_timing.CurTime < timer.TriggerTime) continue; timer.TriggerTime += TimeSpan.FromSeconds(timer.Time.Next(_random)); - var ev = new CP14RitualTriggerAttempt(timer.NextPhase); - RaiseLocalEvent(uid, ev); + TriggerRitualPhase((uid, phase), timer.NextPhase); } } @@ -53,6 +67,9 @@ public sealed partial class CP14RitualSystem private void OnListen(Entity ent, ref ListenEvent args) { + if (!TryComp(ent, out var phase)) + return; + var message = args.Message.Trim(); var triggered = false; @@ -61,8 +78,7 @@ public sealed partial class CP14RitualSystem if (trigger.Key != message) continue; - var triggerEv = new CP14RitualTriggerAttempt(trigger.Value); - RaiseLocalEvent(ent, triggerEv); + TriggerRitualPhase((ent.Owner,phase), trigger.Value); triggered = true; break; } @@ -75,8 +91,7 @@ public sealed partial class CP14RitualSystem if (!(ent.Comp.FailAttempts <= 0)) return; - var failEv = new CP14RitualTriggerAttempt(ent.Comp.FailedPhase.Value); - RaiseLocalEvent(ent, failEv); + TriggerRitualPhase((ent.Owner,phase), ent.Comp.FailedPhase.Value); } #endregion } diff --git a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.cs b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.cs index 9f6e5bca4f..14bdbe4cdc 100644 --- a/Content.Server/_CP14/MagicRituals/CP14RitualSystem.cs +++ b/Content.Server/_CP14/MagicRituals/CP14RitualSystem.cs @@ -1,4 +1,5 @@ using Content.Server._CP14.MagicRituals.Components; +using Content.Server.Stack; using Content.Shared._CP14.MagicRitual; using Robust.Server.GameObjects; using Robust.Shared.Prototypes; @@ -10,6 +11,7 @@ namespace Content.Server._CP14.MagicRituals; public partial class CP14RitualSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly StackSystem _stack = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly TransformSystem _transform = default!; @@ -21,7 +23,7 @@ public partial class CP14RitualSystem : EntitySystem InitializeRequirements(); SubscribeLocalEvent(OnRitualInit); - SubscribeLocalEvent(OnPhaseTriggerAttempt); + SubscribeLocalEvent(OnPhaseTriggerAttempt); } public override void Update(float frameTime) @@ -36,9 +38,9 @@ public partial class CP14RitualSystem : EntitySystem ChangePhase(ritual, ritual.Comp.StartPhase); } - private void OnPhaseTriggerAttempt(Entity phase, ref CP14RitualTriggerAttempt args) + private void OnPhaseTriggerAttempt(Entity phase, ref CP14RitualTriggerEvent args) { - if (args.Cancelled || args.NextPhase is null || phase.Comp.Ritual is null) + if (args.NextPhase is null || phase.Comp.Ritual is null) return; ChangePhase(phase.Comp.Ritual.Value, args.NextPhase.Value); diff --git a/Content.Server/_CP14/MagicRituals/Components/Requirements/CP14RitualRequirementEntitiesComponent.cs b/Content.Server/_CP14/MagicRituals/Components/Requirements/CP14RitualRequirementEntitiesComponent.cs index a84fe5df1c..142cedb111 100644 --- a/Content.Server/_CP14/MagicRituals/Components/Requirements/CP14RitualRequirementEntitiesComponent.cs +++ b/Content.Server/_CP14/MagicRituals/Components/Requirements/CP14RitualRequirementEntitiesComponent.cs @@ -12,27 +12,18 @@ 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(); + public bool ConsumeResource = false; /// /// Effect appearing in place of used entities /// [DataField] - public EntProtoId? VisualEffect; + public EntProtoId? VisualEffect = "CP14DustEffect"; } diff --git a/Content.Shared/_CP14/MagicRitual/CP14MagicRitalEvents.cs b/Content.Shared/_CP14/MagicRitual/CP14MagicRitualEvents.cs similarity index 66% rename from Content.Shared/_CP14/MagicRitual/CP14MagicRitalEvents.cs rename to Content.Shared/_CP14/MagicRitual/CP14MagicRitualEvents.cs index a643fbe3b0..f67722f99b 100644 --- a/Content.Shared/_CP14/MagicRitual/CP14MagicRitalEvents.cs +++ b/Content.Shared/_CP14/MagicRitual/CP14MagicRitualEvents.cs @@ -3,10 +3,14 @@ using Robust.Shared.Prototypes; namespace Content.Shared._CP14.MagicRitual; public sealed class CP14RitualTriggerAttempt : CancellableEntityEventArgs +{ +} + +public sealed class CP14RitualTriggerEvent : EntityEventArgs { public EntProtoId? NextPhase; - public CP14RitualTriggerAttempt(EntProtoId phase) + public CP14RitualTriggerEvent(EntProtoId phase) { NextPhase = phase; } diff --git a/Resources/Prototypes/_CP14/Entities/Ritual/phases.yml b/Resources/Prototypes/_CP14/Entities/Ritual/phases.yml index 86ab958d47..2ae7e23c4e 100644 --- a/Resources/Prototypes/_CP14/Entities/Ritual/phases.yml +++ b/Resources/Prototypes/_CP14/Entities/Ritual/phases.yml @@ -25,6 +25,11 @@ nextPhases: "Hello": CP14RitualPhaseTest2 "Blya": CP14RitualPhaseTest3 + - type: CP14RitualRequirementEntities + visualEffect: CP14ImpactEffectShadowGrab + consumeResource: true + requiredEntities: + CP14FoodCucumber: 3 - type: entity parent: CP14BaseRitualPhase