Files
tbd-station-14/Content.Server/Dragon/DragonRiftSystem.cs
Hannah Giovanna Dawson cdbe92d37d Update DamageableSystem to modern standards (#39417)
* Update DamageableSystem to modern standards

* DamageContainerId -> DamageContainerID with lint flag

* Replace strings with protoids

* Make CVar subscription declarations all consistently whitespaced

* ChangeDamage -> TryChangeDamage, cope with C# jank

* Revert event signature changes

* Restore a comment

* Re-add two queries

* Init the queries

* Use appearanceQuery in DamageChanged

* Use damageableQuery in TryChangeDamage

* Use damageableQuery in SetDamageModifierSetId

* Final cleanup, fix sandboxing

* Rectify ExplosionSystem:::ProcessEntity's call to TryChangeDamage

* Re-organize DamageableSystem

* first big fuck you breaking change.

* THATS A LOT OF DAMAGE!!!

* Fix test fails

* test fixes 2

* push it

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
2025-10-27 19:53:04 +00:00

128 lines
4.8 KiB
C#

using Content.Server.Chat.Systems;
using Content.Server.NPC;
using Content.Server.NPC.Systems;
using Content.Server.Pinpointer;
using Content.Shared.Dragon;
using Content.Shared.Examine;
using Content.Shared.Sprite;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Serialization.Manager;
using System.Numerics;
using Content.Shared.Damage.Components;
using Robust.Shared.Audio.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Utility;
namespace Content.Server.Dragon;
/// <summary>
/// Handles events for rift entities and rift updating.
/// </summary>
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<DragonRiftComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<DragonRiftComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<DragonRiftComponent, AnchorStateChangedEvent>(OnAnchorChange);
SubscribeLocalEvent<DragonRiftComponent, ComponentShutdown>(OnShutdown);
}
private void OnGetState(Entity<DragonRiftComponent> ent, ref ComponentGetState args)
{
args.State = new DragonRiftComponentState
{
State = ent.Comp.State,
};
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<DragonRiftComponent, TransformComponent>();
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<DamageableComponent>(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 msg = Loc.GetString("carp-rift-warning",
("location", FormattedMessage.RemoveMarkupOrThrow(_navMap.GetNearestBeaconString((uid, xform)))));
_chat.DispatchGlobalAnnouncement(msg, 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<RandomSpriteComponent>(comp.Dragon, out var randomSprite))
{
var spawnedSprite = EnsureComp<RandomSpriteComponent>(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<DragonComponent>(comp.Dragon, out var dragon) || dragon.Weakened)
return;
_dragon.RiftDestroyed(comp.Dragon.Value, dragon);
}
}