using Content.Server.Chat.Systems; using Content.Server.NPC; using Content.Server.NPC.Systems; using Content.Server.Pinpointer; using Content.Shared.Damage; using Content.Shared.Dragon; using Content.Shared.Examine; using Content.Shared.Sprite; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Serialization.Manager; using System.Numerics; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; namespace Content.Server.Dragon; /// /// Handles events for rift entities and rift updating. /// public sealed class DragonRiftSystem : EntitySystem { [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly DragonSystem _dragon = default!; [Dependency] private readonly ISerializationManager _serManager = default!; [Dependency] private readonly NavMapSystem _navMap = default!; [Dependency] private readonly NPCSystem _npc = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(OnAnchorChange); SubscribeLocalEvent(OnShutdown); } public override void Update(float frameTime) { base.Update(frameTime); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp, out var xform)) { if (comp.State != DragonRiftState.Finished && comp.Accumulator >= comp.MaxAccumulator) { // TODO: When we get autocall you can buff if the rift finishes / 3 rifts are up // for now they just keep 3 rifts up. if (comp.Dragon != null) _dragon.RiftCharged(comp.Dragon.Value); comp.Accumulator = comp.MaxAccumulator; RemComp(uid); comp.State = DragonRiftState.Finished; Dirty(uid, comp); } else if (comp.State != DragonRiftState.Finished) { comp.Accumulator += frameTime; } comp.SpawnAccumulator += frameTime; if (comp.State < DragonRiftState.AlmostFinished && comp.Accumulator > comp.MaxAccumulator / 2f) { comp.State = DragonRiftState.AlmostFinished; Dirty(uid, comp); var location = xform.LocalPosition; _chat.DispatchGlobalAnnouncement(Loc.GetString("carp-rift-warning", ("location", location)), playSound: false, colorOverride: Color.Red); _audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true); _navMap.SetBeaconEnabled(uid, true); } if (comp.SpawnAccumulator > comp.SpawnCooldown) { comp.SpawnAccumulator -= comp.SpawnCooldown; var ent = Spawn(comp.SpawnPrototype, xform.Coordinates); // Update their look to match the leader. if (TryComp(comp.Dragon, out var randomSprite)) { var spawnedSprite = EnsureComp(ent); _serManager.CopyTo(randomSprite, ref spawnedSprite, notNullableOverride: true); Dirty(ent, spawnedSprite); } if (comp.Dragon != null) _npc.SetBlackboard(ent, NPCBlackboard.FollowTarget, new EntityCoordinates(comp.Dragon.Value, Vector2.Zero)); } } } private void OnExamined(EntityUid uid, DragonRiftComponent component, ExaminedEvent args) { args.PushMarkup(Loc.GetString("carp-rift-examine", ("percentage", MathF.Round(component.Accumulator / component.MaxAccumulator * 100)))); } private void OnAnchorChange(EntityUid uid, DragonRiftComponent component, ref AnchorStateChangedEvent args) { if (!args.Anchored && component.State == DragonRiftState.Charging) { QueueDel(uid); } } private void OnShutdown(EntityUid uid, DragonRiftComponent comp, ComponentShutdown args) { if (!TryComp(comp.Dragon, out var dragon) || dragon.Weakened) return; _dragon.RiftDestroyed(comp.Dragon.Value, dragon); } }