From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Date: Thu, 2 May 2024 02:40:07 +0000 (+1000)
Subject: Fix effects (#27533)
X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=5053c8afdbd2c18dc6654eae0443ba39eadb1838;p=space-station-14.git
Fix effects (#27533)
* Fix effects
- Fix muzzle flash rotations.
- Fix effects so they update every frame.
- Fix effects tanking client performance.
* Fix merge artifact
---
diff --git a/Content.Client/Animations/TrackUserComponent.cs b/Content.Client/Animations/TrackUserComponent.cs
new file mode 100644
index 0000000000..374c187398
--- /dev/null
+++ b/Content.Client/Animations/TrackUserComponent.cs
@@ -0,0 +1,17 @@
+using System.Numerics;
+
+namespace Content.Client.Animations;
+
+///
+/// Entities with this component tracks the user's world position every frame.
+///
+[RegisterComponent]
+public sealed partial class TrackUserComponent : Component
+{
+ public EntityUid? User;
+
+ ///
+ /// Offset in the direction of the entity's rotation.
+ ///
+ public Vector2 Offset = Vector2.Zero;
+}
diff --git a/Content.Client/MouseRotator/MouseRotatorSystem.cs b/Content.Client/MouseRotator/MouseRotatorSystem.cs
index 44e8205355..4894c17c4c 100644
--- a/Content.Client/MouseRotator/MouseRotatorSystem.cs
+++ b/Content.Client/MouseRotator/MouseRotatorSystem.cs
@@ -49,7 +49,7 @@ public sealed class MouseRotatorSystem : SharedMouseRotatorSystem
if (angleDir == curRot.GetCardinalDir())
return;
- RaisePredictiveEvent(new RequestMouseRotatorRotationSimpleEvent()
+ RaisePredictiveEvent(new RequestMouseRotatorRotationSimpleEvent()
{
Direction = angleDir,
});
diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.Effects.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.Effects.cs
index c33bc913d3..baac42d193 100644
--- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.Effects.cs
+++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.Effects.cs
@@ -1,4 +1,5 @@
using System.Numerics;
+using Content.Client.Animations;
using Content.Client.Weapons.Melee.Components;
using Content.Shared.Weapons.Melee;
using Robust.Client.Animations;
@@ -59,17 +60,20 @@ public sealed partial class MeleeWeaponSystem
var distance = Math.Clamp(localPos.Length() / 2f, 0.2f, 1f);
var xform = _xformQuery.GetComponent(animationUid);
+ TrackUserComponent track;
switch (arcComponent.Animation)
{
case WeaponArcAnimation.Slash:
- arcComponent.User = user;
+ track = EnsureComp(animationUid);
+ track.User = user;
_animation.Play(animationUid, GetSlashAnimation(sprite, angle, spriteRotation), SlashAnimationKey);
if (arcComponent.Fadeout)
_animation.Play(animationUid, GetFadeAnimation(sprite, 0.065f, 0.065f + 0.05f), FadeAnimationKey);
break;
case WeaponArcAnimation.Thrust:
- arcComponent.User = user;
+ track = EnsureComp(animationUid);
+ track.User = user;
_animation.Play(animationUid, GetThrustAnimation(sprite, distance, spriteRotation), ThrustAnimationKey);
if (arcComponent.Fadeout)
_animation.Play(animationUid, GetFadeAnimation(sprite, 0.05f, 0.15f), FadeAnimationKey);
@@ -206,15 +210,23 @@ public sealed partial class MeleeWeaponSystem
///
/// Updates the effect positions to follow the user
///
- void UpdateEffects(float frameTime)
+ private void UpdateEffects()
{
- var arcQuery = EntityQueryEnumerator();
- while(arcQuery.MoveNext(out var uid, out var xform, out var arcComponent))
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var arcComponent, out var xform))
{
if (arcComponent.User == null)
continue;
- var userPos = TransformSystem.GetWorldPosition(arcComponent.User.Value);
- TransformSystem.SetWorldPosition(xform, userPos);
+
+ Vector2 targetPos = TransformSystem.GetWorldPosition(arcComponent.User.Value);
+
+ if (arcComponent.Offset != Vector2.Zero)
+ {
+ var entRotation = TransformSystem.GetWorldRotation(xform);
+ targetPos += entRotation.RotateVec(arcComponent.Offset);
+ }
+
+ TransformSystem.SetWorldPosition(xform, targetPos);
}
}
}
diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs
index 95de207471..039af55bd0 100644
--- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs
+++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs
@@ -43,10 +43,15 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem
UpdatesOutsidePrediction = true;
}
+ public override void FrameUpdate(float frameTime)
+ {
+ base.FrameUpdate(frameTime);
+ UpdateEffects();
+ }
+
public override void Update(float frameTime)
{
base.Update(frameTime);
- UpdateEffects(frameTime);
if (!Timing.IsFirstTimePredicted)
return;
diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs
index 9e50cab3e1..5aba04bdf8 100644
--- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs
+++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs
@@ -1,4 +1,5 @@
using System.Numerics;
+using Content.Client.Animations;
using Content.Client.Items;
using Content.Client.Weapons.Ranged.Components;
using Content.Shared.Camera;
@@ -15,6 +16,7 @@ using Robust.Client.Player;
using Robust.Shared.Animations;
using Robust.Shared.Input;
using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using SharedGunSystem = Content.Shared.Weapons.Ranged.Systems.SharedGunSystem;
@@ -24,13 +26,14 @@ namespace Content.Client.Weapons.Ranged.Systems;
public sealed partial class GunSystem : SharedGunSystem
{
+ [Dependency] private readonly IComponentFactory _factory = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly AnimationPlayerSystem _animPlayer = default!;
[Dependency] private readonly InputSystem _inputSystem = default!;
[Dependency] private readonly SharedCameraRecoilSystem _recoil = default!;
- [Dependency] private readonly IComponentFactory _factory = default!;
+ [Dependency] private readonly SharedMapSystem _maps = default!;
[ValidatePrototypeId]
public const string HitscanProto = "HitscanEffect";
@@ -123,7 +126,7 @@ public sealed partial class GunSystem : SharedGunSystem
}
};
- _animPlayer.Play(ent, null, anim, "hitscan-effect");
+ _animPlayer.Play(ent, anim, "hitscan-effect");
}
}
@@ -189,6 +192,7 @@ public sealed partial class GunSystem : SharedGunSystem
// to just delete the spawned entities. This is for programmer sanity despite the wasted perf.
// This also means any ammo specific stuff can be grabbed as necessary.
var direction = fromCoordinates.ToMapPos(EntityManager, TransformSystem) - toCoordinates.ToMapPos(EntityManager, TransformSystem);
+ var worldAngle = direction.ToAngle().Opposite();
foreach (var (ent, shootable) in ammo)
{
@@ -208,7 +212,7 @@ public sealed partial class GunSystem : SharedGunSystem
if (!cartridge.Spent)
{
SetCartridgeSpent(ent!.Value, cartridge, true);
- MuzzleFlash(gunUid, cartridge, user);
+ MuzzleFlash(gunUid, cartridge, worldAngle, user);
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
Recoil(user, direction, gun.CameraRecoilScalarModified);
// TODO: Can't predict entity deletions.
@@ -226,7 +230,7 @@ public sealed partial class GunSystem : SharedGunSystem
break;
case AmmoComponent newAmmo:
- MuzzleFlash(gunUid, newAmmo, user);
+ MuzzleFlash(gunUid, newAmmo, worldAngle, user);
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
Recoil(user, direction, gun.CameraRecoilScalarModified);
if (IsClientSide(ent!.Value))
@@ -258,33 +262,41 @@ public sealed partial class GunSystem : SharedGunSystem
PopupSystem.PopupEntity(message, uid.Value, user.Value);
}
- protected override void CreateEffect(EntityUid uid, MuzzleFlashEvent message, EntityUid? user = null)
+ protected override void CreateEffect(EntityUid gunUid, MuzzleFlashEvent message, EntityUid? user = null)
{
if (!Timing.IsFirstTimePredicted)
return;
+ var gunXform = Transform(gunUid);
+ var gridUid = gunXform.GridUid;
EntityCoordinates coordinates;
- if (message.MatchRotation)
- coordinates = new EntityCoordinates(uid, Vector2.Zero);
- else if (TryComp(uid, out var xform))
- coordinates = xform.Coordinates;
+ if (TryComp(gridUid, out MapGridComponent? mapGrid))
+ {
+ coordinates = new EntityCoordinates(gridUid.Value, _maps.LocalToGrid(gridUid.Value, mapGrid, gunXform.Coordinates));
+ }
+ else if (gunXform.MapUid != null)
+ {
+ coordinates = new EntityCoordinates(gunXform.MapUid.Value, TransformSystem.GetWorldPosition(gunXform));
+ }
else
+ {
return;
-
- if (!coordinates.IsValid(EntityManager))
- return;
+ }
var ent = Spawn(message.Prototype, coordinates);
+ TransformSystem.SetWorldRotationNoLerp(ent, message.Angle);
- var effectXform = Transform(ent);
- TransformSystem.SetLocalPositionRotation(effectXform,
- effectXform.LocalPosition + new Vector2(0f, -0.5f),
- effectXform.LocalRotation - MathF.PI / 2);
+ if (user != null)
+ {
+ var track = EnsureComp(ent);
+ track.User = user;
+ track.Offset = Vector2.UnitX / 2f;
+ }
var lifetime = 0.4f;
- if (TryComp(uid, out var despawn))
+ if (TryComp(gunUid, out var despawn))
{
lifetime = despawn.Lifetime;
}
@@ -309,18 +321,17 @@ public sealed partial class GunSystem : SharedGunSystem
};
_animPlayer.Play(ent, anim, "muzzle-flash");
- if (!TryComp(uid, out PointLightComponent? light))
+ if (!TryComp(gunUid, out PointLightComponent? light))
{
light = (PointLightComponent) _factory.GetComponent(typeof(PointLightComponent));
- light.Owner = uid;
light.NetSyncEnabled = false;
- AddComp(uid, light);
+ AddComp(gunUid, light);
}
- Lights.SetEnabled(uid, true, light);
- Lights.SetRadius(uid, 2f, light);
- Lights.SetColor(uid, Color.FromHex("#cc8e2b"), light);
- Lights.SetEnergy(uid, 5f, light);
+ Lights.SetEnabled(gunUid, true, light);
+ Lights.SetRadius(gunUid, 2f, light);
+ Lights.SetColor(gunUid, Color.FromHex("#cc8e2b"), light);
+ Lights.SetEnergy(gunUid, 5f, light);
var animTwo = new Animation()
{
@@ -352,9 +363,9 @@ public sealed partial class GunSystem : SharedGunSystem
}
};
- var uidPlayer = EnsureComp(uid);
+ var uidPlayer = EnsureComp(gunUid);
- _animPlayer.Stop(uid, uidPlayer, "muzzle-flash-light");
- _animPlayer.Play(uid, uidPlayer, animTwo,"muzzle-flash-light");
+ _animPlayer.Stop(gunUid, uidPlayer, "muzzle-flash-light");
+ _animPlayer.Play((gunUid, uidPlayer), animTwo,"muzzle-flash-light");
}
}
diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs
index 7449b0c59e..f495f29e4a 100644
--- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs
+++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs
@@ -154,7 +154,7 @@ public sealed partial class GunSystem : SharedGunSystem
});
SetCartridgeSpent(ent.Value, cartridge, true);
- MuzzleFlash(gunUid, cartridge, user);
+ MuzzleFlash(gunUid, cartridge, mapDirection.ToAngle(), user);
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
if (cartridge.DeleteOnSpawn)
@@ -175,7 +175,7 @@ public sealed partial class GunSystem : SharedGunSystem
// Ammo shoots itself
case AmmoComponent newAmmo:
shotProjectiles.Add(ent!.Value);
- MuzzleFlash(gunUid, newAmmo, user);
+ MuzzleFlash(gunUid, newAmmo, mapDirection.ToAngle(), user);
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
ShootOrThrow(ent.Value, mapDirection, gunVelocity, gun, gunUid, user);
break;
@@ -326,9 +326,9 @@ public sealed partial class GunSystem : SharedGunSystem
protected override void Popup(string message, EntityUid? uid, EntityUid? user) { }
- protected override void CreateEffect(EntityUid uid, MuzzleFlashEvent message, EntityUid? user = null)
+ protected override void CreateEffect(EntityUid gunUid, MuzzleFlashEvent message, EntityUid? user = null)
{
- var filter = Filter.Pvs(uid, entityManager: EntityManager);
+ var filter = Filter.Pvs(gunUid, entityManager: EntityManager);
if (TryComp(user, out var actor))
filter.RemovePlayer(actor.PlayerSession);
diff --git a/Content.Shared/Weapons/Ranged/Events/MuzzleFlashEvent.cs b/Content.Shared/Weapons/Ranged/Events/MuzzleFlashEvent.cs
index 91f5e6cd86..10d4c2fe3c 100644
--- a/Content.Shared/Weapons/Ranged/Events/MuzzleFlashEvent.cs
+++ b/Content.Shared/Weapons/Ranged/Events/MuzzleFlashEvent.cs
@@ -11,15 +11,12 @@ public sealed class MuzzleFlashEvent : EntityEventArgs
public NetEntity Uid;
public string Prototype;
- ///
- /// Should the effect match the rotation of the entity.
- ///
- public bool MatchRotation;
+ public Angle Angle;
- public MuzzleFlashEvent(NetEntity uid, string prototype, bool matchRotation = false)
+ public MuzzleFlashEvent(NetEntity uid, string prototype, Angle angle)
{
Uid = uid;
Prototype = prototype;
- MatchRotation = matchRotation;
+ Angle = angle;
}
}
diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
index 129d536a70..51e2e1358f 100644
--- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
+++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
@@ -136,7 +136,6 @@ public abstract partial class SharedGunSystem : EntitySystem
return;
gun.ShootCoordinates = GetCoordinates(msg.Coordinates);
- Log.Debug($"Set shoot coordinates to {gun.ShootCoordinates}");
AttemptShoot(user.Value, ent, gun);
}
@@ -195,7 +194,6 @@ public abstract partial class SharedGunSystem : EntitySystem
if (gun.ShotCounter == 0)
return;
- Log.Debug($"Stopped shooting {ToPrettyString(uid)}");
gun.ShotCounter = 0;
gun.ShootCoordinates = null;
Dirty(uid, gun);
@@ -461,7 +459,7 @@ public abstract partial class SharedGunSystem : EntitySystem
RemCompDeferred(uid);
}
- protected void MuzzleFlash(EntityUid gun, AmmoComponent component, EntityUid? user = null)
+ protected void MuzzleFlash(EntityUid gun, AmmoComponent component, Angle worldAngle, EntityUid? user = null)
{
var attemptEv = new GunMuzzleFlashAttemptEvent();
RaiseLocalEvent(gun, ref attemptEv);
@@ -473,7 +471,7 @@ public abstract partial class SharedGunSystem : EntitySystem
if (sprite == null)
return;
- var ev = new MuzzleFlashEvent(GetNetEntity(gun), sprite, user == gun);
+ var ev = new MuzzleFlashEvent(GetNetEntity(gun), sprite, worldAngle);
CreateEffect(gun, ev, user);
}
@@ -522,7 +520,7 @@ public abstract partial class SharedGunSystem : EntitySystem
Dirty(gun);
}
- protected abstract void CreateEffect(EntityUid uid, MuzzleFlashEvent message, EntityUid? user = null);
+ protected abstract void CreateEffect(EntityUid gunUid, MuzzleFlashEvent message, EntityUid? user = null);
///
/// Used for animated effects on the client.