using System.Text; using Content.Server.Speech.Components; using Content.Shared._CP14.MagicRitual; using Content.Shared.DoAfter; using Content.Shared.Examine; using Content.Shared.Verbs; 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 : CP14SharedRitualSystem { [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly IEntitySystemManager _entitySystem = default!; [Dependency] private readonly PointLightSystem _pointLight = default!; [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly TransformSystem _transform = default!; public override void Initialize() { base.Initialize(); InitializeDescriber(); InitializeVisuals(); SubscribeLocalEvent(OnActivateRitual); SubscribeLocalEvent>(OnAlternativeVerb); SubscribeLocalEvent(OnPhaseTrigger); SubscribeLocalEvent(OnOrbExamine); } private void OnActivateRitual(Entity ent, ref CP14ActivateRitualDoAfter args) { if (args.Cancelled || args.Handled) return; args.Handled = true; StartRitual(ent); } private void OnAlternativeVerb(Entity ent, ref GetVerbsEvent args) { if (!args.CanInteract || ent.Comp.CurrentPhase is not null) return; var user = args.User; AlternativeVerb verb = new() { Act = () => { var doAfterArgs = new DoAfterArgs(EntityManager, user, ent.Comp.ActivationTime, new CP14ActivateRitualDoAfter(), ent, ent) { BreakOnDamage = true, BreakOnMove = true, }; _doAfter.TryStartDoAfter(doAfterArgs); }, Text = Loc.GetString("cp14-ritual-verb-text"), Priority = 1, }; args.Verbs.Add(verb); } private void OnOrbExamine(Entity ent, ref ExaminedEvent args) { var sb = new StringBuilder(); sb.Append(Loc.GetString("cp14-ritual-orb-examine", ("name", MetaData(ent).EntityName)) + "\n"); foreach (var orbType in ent.Comp.Powers) { if (!_proto.TryIndex(orbType.Key, out var indexedType)) continue; sb.Append($"[color={indexedType.Color.ToHex()}]"); sb.Append(Loc.GetString("cp14-ritual-entry-item", ("name", Loc.GetString(indexedType.Name)), ("count", orbType.Value))); sb.Append($"[/color] \n"); } args.PushMarkup(sb.ToString()); } public void StartRitual(Entity ritual) { EndRitual(ritual); var ev = new CP14RitualStartEvent(ritual); RaiseLocalEvent(ritual, ev); ChangePhase(ritual, ritual.Comp.StartPhase); _appearance.SetData(ritual, RitualVisuals.Enabled, true); } 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; foreach (var edge in newPhaseComp.Edges) { foreach (var trigger in edge.Triggers) { trigger.Initialize(EntityManager, ritual.Comp.CurrentPhase.Value, edge); } } var ev = new CP14RitualPhaseBoundEvent(ritual, newPhaseEnt); RaiseLocalEvent(ritual, ev); RaiseLocalEvent(newPhaseEnt, ev); if (newPhaseComp.DeadEnd) EndRitual(ritual); } public void EndRitual(Entity ritual) { if (ritual.Comp.CurrentPhase is null) return; QueueDel(ritual.Comp.CurrentPhase); ritual.Comp.CurrentPhase = null; var ev = new CP14RitualEndEvent(ritual); RaiseLocalEvent(ritual, ev); _appearance.SetData(ritual, RitualVisuals.Enabled, false); foreach (var orb in ritual.Comp.Orbs) { QueueDel(orb); } } private void OnPhaseTrigger(Entity phase, ref CP14RitualTriggerEvent args) { if (phase.Comp.Ritual is null) return; RitualPhaseEdge? selectedEdge = null; foreach (var edge in phase.Comp.Edges) { if (edge.Target == args.NextPhase) { selectedEdge = edge; break; } } if (selectedEdge is null) return; var passed = true; foreach (var req in selectedEdge.Value.Requirements) { if (!req.Check(EntityManager, phase, phase.Comp.Ritual.Value.Comp.Stability)) //lol { ChangeRitualStability(phase.Comp.Ritual.Value, -req.FailStabilityCost); passed = false; break; } } if (!passed) return; foreach (var action in selectedEdge.Value.Actions) { action.Effect(EntityManager, _transform, phase); } ChangePhase(phase.Comp.Ritual.Value, args.NextPhase); } }