Files
crystall-punk-14/Content.Client/_CP14/MagicVision/CP14ClientMagicVisionSystem.cs
kin98 0fdc56c796 Make magical vision drain Mana (#1832)
* added generic Entity Effects status effect component

* added Magic Vision Statuseffect component

* renamed visionmask to Visibilitymask and added StatusEffectComponent notice comment

* added two event listeners on MagicVisonStatusEffect applied and removed

* moved changes to server side

* moved Component serverside

* removed Overlay Property

* Added magic vison status effect prototype and applying

* cleaned upnew lines

* added new prototype

* moved Magic vision status effect component to shared again

* fixed applying mask

* cleaned new lines

* Moved to components folder

* marked MagicVisionComponent obsolete and changed protoid name

* Added parent MobStatusEffectBase

* added mana cost to Magical vision spell

* removed unneeded constructor

* Added the system

* added statuseffect eventlistners for applied and removed also removed old event listners

* removed old magic vision component check

* Removed Data field attribute

* added back Data field attribute

* added access atribute

* moved Status effect update to server

* removed shared System moved all to server side

* Update Content.Shared/_CP14/StatusEffect/Components/CP14EntityEffectsStatusEffectComponent.cs

Co-authored-by: Red <96445749+TheShuEd@users.noreply.github.com>

* Fix typo in DataField attribute for Effects list

* Obliterated CP14MagicVisionComponent from existence

* Fix comment capitalization in CP14EntityEffectsStatusEffectComponent

* Fix summary capitalization in CP14EntityEffectsStatusEffectComponent

* Refactor CP14MagicVisionSystem.cs by removing blank lines

Removed unnecessary blank lines for cleaner code.

* Remove status effect event handlers

Removed event subscription and related methods for status effects.

* Remove empty line in OnExamined method

* Added a Spell toggle status effect

* fixed datfields shouldnt be static

* imlpemented status applying in yml

* cleaned white space :3

* changed toggle to has status effect

* fix leftover

* added check for firsttime predict so it doesnt get applied twice

* added getvismaskevent to statuseffect relay

* changed event lisnter to use CP14MagicVisionStatusEffectComponent to prevent future conflicts

* removed unneeded _status property

* added check for if its the last status effect on remove

* added check if Status effect is already present if applied

* changed check to component instead of entity

* changed ent target to player.localEntity

* fix: removed has effect check as it already has the effect when first apllied

* changed event to on player attached

* removed first time predicted check

* changed cooldown to 0.5 seconds

* made Spell mana change effect not save

* added status efect applied event listner back and moved apply and remove overlay to separete methods

* removed replaced action event

* added fix to let nextupdate catch up to CurTime

* fix: status effect not beeing removed when crit or dead

* fix: Action beeing able to be used while dead

* fix: added prediction check to applied back for double apply and remove bug

---------

Co-authored-by: Red <96445749+TheShuEd@users.noreply.github.com>
2025-10-31 21:11:15 +03:00

164 lines
5.9 KiB
C#

using System.Numerics;
using Content.Shared._CP14.MagicVision;
using Content.Shared.Examine;
using Content.Shared.StatusEffectNew;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Client.Timing;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Client._CP14.MagicVision;
public sealed class CP14ClientMagicVisionSystem : CP14SharedMagicVisionSystem
{
[Dependency] private readonly IClientGameTiming _timing = default!;
[Dependency] private readonly SpriteSystem _sprite = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly IOverlayManager _overlayMan = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly StatusEffectsSystem _status = default!;
private CP14MagicVisionOverlay? _overlay;
private CP14MagicVisionNoirOverlay? _overlay2;
private TimeSpan _nextUpdate = TimeSpan.Zero;
private SoundSpecifier _startSound = new SoundPathSpecifier(new ResPath("/Audio/Effects/eye_open.ogg"));
private SoundSpecifier _endSound = new SoundPathSpecifier(new ResPath("/Audio/Effects/eye_close.ogg"));
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14MagicVisionMarkerComponent, AfterAutoHandleStateEvent>(OnHandleStateMarker);
SubscribeLocalEvent<CP14MagicVisionStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerAttachedEvent>>(OnPlayerAttached);
SubscribeLocalEvent<CP14MagicVisionStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerDetachedEvent>>(OnPlayerDetached);
SubscribeLocalEvent<CP14MagicVisionStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
SubscribeLocalEvent<CP14MagicVisionStatusEffectComponent, StatusEffectRemovedEvent>(OnStatusEffectRemoved);
}
private void OnPlayerAttached(Entity<CP14MagicVisionStatusEffectComponent> ent, ref StatusEffectRelayedEvent<LocalPlayerAttachedEvent> args)
{
ApplyOverlay(ent);
}
private void OnStatusEffectApplied(Entity<CP14MagicVisionStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
{
//Prevents it from beeing applied twice
if (_timing.IsFirstTimePredicted == true)
return;
ApplyOverlay(ent);
}
private void OnPlayerDetached(Entity<CP14MagicVisionStatusEffectComponent> ent, ref StatusEffectRelayedEvent<LocalPlayerDetachedEvent> args)
{
RemoveOverlay(ent);
}
private void OnStatusEffectRemoved(Entity<CP14MagicVisionStatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
{
//Prevents it from beeing removed twice
if (_timing.IsFirstTimePredicted == true)
return;
RemoveOverlay(ent);
}
protected override void OnExamined(Entity<CP14MagicVisionMarkerComponent> ent, ref ExaminedEvent args)
{
base.OnExamined(ent, ref args);
if (ent.Comp.TargetCoordinates is null)
return;
var originPosition = _transform.GetWorldPosition(ent);
var targetPosition = _transform.ToWorldPosition(ent.Comp.TargetCoordinates.Value);
if ((targetPosition - originPosition).Length() < 0.5f)
return;
Angle angle = new(targetPosition - originPosition);
var pointer = Spawn(ent.Comp.PointerProto, new MapCoordinates(originPosition, _transform.GetMapId(Transform(ent).Coordinates)));
_transform.SetWorldRotation(pointer, angle + Angle.FromDegrees(90));
}
private void OnHandleStateMarker(Entity<CP14MagicVisionMarkerComponent> ent, ref AfterAutoHandleStateEvent args)
{
if (!TryComp<SpriteComponent>(ent, out var sprite))
return;
if (ent.Comp.Icon is null)
return;
var layer = _sprite.AddLayer(ent.Owner, ent.Comp.Icon);
sprite.LayerSetShader(layer, "unshaded");
_sprite.LayerSetScale(ent.Owner, layer, new Vector2(0.5f, 0.5f));
}
public override void Update(float frameTime)
{
base.Update(frameTime);
if (_timing.CurTime < _nextUpdate)
return;
_nextUpdate = _timing.CurTime + TimeSpan.FromSeconds(0.5f);
var queryFade = EntityQueryEnumerator<CP14MagicVisionMarkerComponent, SpriteComponent>();
while (queryFade.MoveNext(out var uid, out var fade, out var sprite))
{
UpdateOpaque((uid, fade), sprite);
}
}
private void UpdateOpaque(Entity<CP14MagicVisionMarkerComponent> ent, SpriteComponent sprite)
{
var progress = Math.Clamp((_timing.CurTime.TotalSeconds - ent.Comp.SpawnTime.TotalSeconds) / (ent.Comp.EndTime.TotalSeconds - ent.Comp.SpawnTime.TotalSeconds), 0, 1);
var alpha = 1 - progress;
_sprite.SetColor(ent.Owner, Color.White.WithAlpha((float)alpha));
}
private void ApplyOverlay(Entity<CP14MagicVisionStatusEffectComponent> ent)
{
_overlay = new CP14MagicVisionOverlay();
_overlayMan.AddOverlay(_overlay);
_overlay.StartOverlay = _timing.CurTime;
_overlay2 = new CP14MagicVisionNoirOverlay();
_overlayMan.AddOverlay(_overlay2);
_audio.PlayGlobal(_startSound, ent);
}
private void RemoveOverlay(Entity<CP14MagicVisionStatusEffectComponent> ent)
{
// Check if it is the last Magic Vision Status Effect
if (_status.HasEffectComp<CP14MagicVisionStatusEffectComponent>(_player.LocalEntity))
return;
if (_overlay != null)
{
_overlayMan.RemoveOverlay(_overlay);
_overlay = null;
}
if (_overlay2 != null)
{
_overlayMan.RemoveOverlay(_overlay2);
_overlay2 = null;
}
_audio.PlayGlobal(_endSound, ent);
}
}