using Content.Server.Popups; using Content.Shared._DV.CosmicCult.Components.Examine; using Content.Shared._DV.CosmicCult.Components; using Content.Shared._DV.CosmicCult; using Content.Shared.Damage; using Content.Shared.Examine; using Content.Shared.Humanoid; using Content.Shared.Interaction; using Content.Shared.Mobs.Systems; using Robust.Server.Audio; using Robust.Shared.Audio; using Robust.Shared.Containers; namespace Content.Server._DV.CosmicCult; public sealed class CosmicGlyphSystem : EntitySystem { [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedCosmicCultSystem _cosmicCult = default!; private readonly HashSet> _cultists = []; private readonly HashSet> _humanoids = []; public override void Initialize() { SubscribeLocalEvent(OnExamine); SubscribeLocalEvent(OnUseGlyph); } #region Base trigger private void OnExamine(Entity uid, ref ExaminedEvent args) { if (_cosmicCult.EntityIsCultist(args.Examiner)) { args.PushMarkup(Loc.GetString("cosmic-examine-glyph-cultcount", ("COUNT", uid.Comp.RequiredCultists))); } else { args.PushMarkup(Loc.GetString("cosmic-examine-text-glyphs")); } } private void OnUseGlyph(Entity uid, ref ActivateInWorldEvent args) { var tgtpos = Transform(uid).Coordinates; var userCoords = Transform(args.User).Coordinates; if (args.Handled || !userCoords.TryDistance(EntityManager, tgtpos, out var distance) || distance > uid.Comp.ActivationRange || !_cosmicCult.EntityIsCultist(args.User)) return; var cultists = GatherCultists(uid, uid.Comp.ActivationRange); if (cultists.Count < uid.Comp.RequiredCultists) { _popup.PopupEntity(Loc.GetString("cult-glyph-not-enough-cultists"), uid, args.User); return; } args.Handled = true; var tryInvokeEv = new TryActivateGlyphEvent(args.User, cultists); RaiseLocalEvent(uid, tryInvokeEv); if (tryInvokeEv.Cancelled) return; var damage = uid.Comp.ActivationDamage / cultists.Count; foreach (var cultist in cultists) { _damageable.TryChangeDamage(cultist, damage, true); } _audio.PlayPvs(uid.Comp.GylphSFX, tgtpos, AudioParams.Default.WithVolume(+1f)); Spawn(uid.Comp.GylphVFX, tgtpos); QueueDel(uid); } #endregion #region Housekeeping /// /// Gets all cultists/constructs near a glyph. /// public HashSet> GatherCultists(EntityUid uid, float range) { _cultists.Clear(); _lookup.GetEntitiesInRange(Transform(uid).Coordinates, range, _cultists); _cultists.RemoveWhere(entity => !_mobState.IsAlive(entity) || _container.IsEntityInContainer(entity)); return _cultists; } /// /// Gets all the humanoids near a glyph. /// /// The glyph. /// Radius for a lookup. /// Filter to exclude from return. public HashSet> GetTargetsNearGlyph(EntityUid uid, float range, Predicate>? exclude = null) { _humanoids.Clear(); _lookup.GetEntitiesInRange(Transform(uid).Coordinates, range, _humanoids); if (exclude != null) _humanoids.RemoveWhere(exclude); _humanoids.RemoveWhere(target => HasComp(target) || HasComp(target)); // We never want these. return _humanoids; } #endregion }