using Content.Shared._CP14.MagicSpell.Spells; using Content.Shared._CP14.Religion.Components; using Content.Shared._CP14.Religion.Prototypes; using Content.Shared.Actions; using Content.Shared.Alert; using Content.Shared.Follower; using Content.Shared.Mind; using Content.Shared.Mobs; using Content.Shared.Verbs; using Robust.Shared.Prototypes; namespace Content.Shared._CP14.Religion.Systems; public abstract partial class CP14SharedReligionGodSystem { [Dependency] private readonly AlertsSystem _alerts = default!; [Dependency] private readonly SharedActionsSystem _actions = default!; [Dependency] protected readonly SharedMindSystem Mind = default!; [Dependency] private readonly FollowerSystem _follower = default!; [ValidatePrototypeId] public const string AlertProto = "CP14DivineOffer"; private void InitializeFollowers() { SubscribeLocalEvent(OnPendingFollowerInit); SubscribeLocalEvent(OnPendingFollowerShutdown); SubscribeLocalEvent(OnBreakDivineOffer); SubscribeLocalEvent(OnGodTouch); SubscribeLocalEvent(OnOfferDoAfter); SubscribeLocalEvent(OnRenounceFromGod); SubscribeLocalEvent>(OnGetAltVerbs); SubscribeLocalEvent(OnFollowerStateChange); } private void OnFollowerStateChange(Entity ent, ref MobStateChangedEvent args) { if (ent.Comp.Religion is null) return; EnsureComp(ent, out var observer); if (!_proto.TryIndex(observer.Religion, out var indexedReligion)) return; var baseObservation = indexedReligion.FollowerObservationRadius; switch (args.NewMobState) { case MobState.Alive: observer.Radius = baseObservation; break; case MobState.Critical: SendMessageToGods(ent.Comp.Religion.Value, Loc.GetString("cp14-critical-follower-message", ("name", MetaData(ent).EntityName)), ent); observer.Radius = baseObservation * 0.25f; break; case MobState.Dead: SendMessageToGods(ent.Comp.Religion.Value, Loc.GetString("cp14-dead-follower-message", ("name", MetaData(ent).EntityName)), ent); observer.Radius = 0f; break; } Dirty(ent.Owner, observer); } private void OnGetAltVerbs(EntityUid uid, CP14ReligionFollowerComponent component, GetVerbsEvent args) { if (!TryComp(args.User, out var god)) return; if (god.Religion != component.Religion) return; args.Verbs.Add(new AlternativeVerb { Text = Loc.GetString("admin-player-actions-follow"), Act = () => { _follower.StartFollowingEntity(args.User, uid); }, }); } private void OnRenounceFromGod(Entity ent, ref CP14RenounceFromGodEvent args) { ToDisbelieve(ent); } private void OnOfferDoAfter(Entity ent, ref CP14AltarOfferDoAfter args) { if (args.Handled || args.Cancelled) return; if (ent.Comp.Religion is null) return; TryAddPendingFollower(args.User, ent.Comp.Religion.Value); args.Handled = true; } private void OnGodTouch(Entity ent, ref CP14GodTouchEvent args) { if (args.Religion != ent.Comp.Religion) return; TryToBelieve(ent); } private void OnBreakDivineOffer(Entity ent, ref CP14BreakDivineOfferEvent args) { RemCompDeferred(ent); if (ent.Comp.Religion is null) return; SendMessageToGods(ent.Comp.Religion.Value, Loc.GetString("cp14-unoffer-soul-god-message", ("name", MetaData(ent).EntityName)), ent); } private void OnPendingFollowerInit(Entity ent, ref MapInitEvent args) { _alerts.ShowAlert(ent.Owner, AlertProto); } private void OnPendingFollowerShutdown(Entity ent, ref ComponentShutdown args) { _alerts.ClearAlert(ent.Owner, AlertProto); } private bool CanBecomeFollower(EntityUid target, ProtoId religion) { if (HasComp(target)) return false; EnsureComp(target, out var follower); if (follower.Religion is not null) return false; return !follower.RejectedReligions.Contains(religion); } private void TryAddPendingFollower(EntityUid target, ProtoId religion) { if (!CanBecomeFollower(target, religion)) return; EnsureComp(target, out var pendingFollower); pendingFollower.Religion = religion; SendMessageToGods(religion, Loc.GetString("cp14-offer-soul-god-message", ("name", MetaData(target).EntityName)), target); } private bool TryToBelieve(Entity pending) { if (pending.Comp.Religion is null) return false; if (!_proto.TryIndex(pending.Comp.Religion, out var indexedReligion)) return false; if (!CanBecomeFollower(pending, pending.Comp.Religion.Value)) return false; EnsureComp(pending, out var follower); EnsureComp(pending, out var observer); observer.Religion = indexedReligion; observer.Radius = indexedReligion.FollowerObservationRadius; var oldReligion = follower.Religion; follower.Religion = pending.Comp.Religion; Dirty(pending, follower); Dirty(pending, observer); var ev = new CP14ReligionChangedEvent(oldReligion, pending.Comp.Religion); RaiseLocalEvent(pending, ev); RemCompDeferred(pending); SendMessageToGods(pending.Comp.Religion.Value, Loc.GetString("cp14-become-follower-message", ("name", MetaData(pending).EntityName)), pending); _actions.AddAction(pending, ref follower.RenounceAction, follower.RenounceActionProto); _actions.AddAction(pending, ref follower.AppealAction, follower.AppealToGofProto); return true; } public void ToDisbelieve(EntityUid target) { if (!TryComp(target, out var follower)) return; if (follower.Religion is null) return; RemCompDeferred(target); SendMessageToGods(follower.Religion.Value, Loc.GetString("cp14-remove-follower-message", ("name", MetaData(target).EntityName)), target); var oldReligion = follower.Religion; follower.Religion = null; if (oldReligion is not null) follower.RejectedReligions.Add(oldReligion.Value); var ev = new CP14ReligionChangedEvent(oldReligion, null); RaiseLocalEvent(target, ev); Dirty(target, follower); _actions.RemoveAction(target, follower.RenounceAction); _actions.RemoveAction(target, follower.AppealAction); } } public sealed partial class CP14BreakDivineOfferEvent : BaseAlertEvent; public sealed partial class CP14RenounceFromGodEvent : InstantActionEvent;