diff --git a/Content.Client/GameObjects/EntitySystems/MeleeWeaponSystem.cs b/Content.Client/GameObjects/EntitySystems/MeleeWeaponSystem.cs index 1a4b1212ee..83a8950ba1 100644 --- a/Content.Client/GameObjects/EntitySystems/MeleeWeaponSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/MeleeWeaponSystem.cs @@ -1,10 +1,14 @@ -using Content.Client.GameObjects.Components.Mobs; +using System; +using Content.Client.GameObjects.Components.Mobs; using Content.Client.GameObjects.Components.Weapons.Melee; using Content.Shared.GameObjects.Components.Weapons.Melee; using JetBrains.Annotations; +using Robust.Client.GameObjects; using Robust.Client.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.EntitySystemMessages; using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Maths; @@ -18,6 +22,7 @@ namespace Content.Client.GameObjects.EntitySystems public sealed class MeleeWeaponSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; public override void Initialize() { @@ -53,6 +58,26 @@ namespace Content.Client.GameObjects.EntitySystems var weaponArcAnimation = entity.GetComponent(); weaponArcAnimation.SetData(weaponArc, msg.Angle, attacker); + // Due to ISpriteComponent limitations, weapons that don't use an RSI won't have this effect. + if (EntityManager.TryGetEntity(msg.Source, out var source) && msg.TextureEffect && source.TryGetComponent(out ISpriteComponent sourceSprite) + && sourceSprite.BaseRSI?.Path != null) + { + var sys = Get(); + var curTime = _gameTiming.CurTime; + var effect = new EffectSystemMessage + { + EffectSprite = sourceSprite.BaseRSI.Path.ToString(), + RsiState = sourceSprite.LayerGetState(0).Name, + Coordinates = attacker.Transform.GridPosition, + Color = Vector4.Multiply(new Vector4(255, 255, 255, 125), 1.0f), + ColorDelta = Vector4.Multiply(new Vector4(0, 0, 0, -10), 1.0f), + Velocity = msg.Angle.ToVec(), + Acceleration = msg.Angle.ToVec() * 5f, + Born = curTime, + DeathTime = curTime.Add(TimeSpan.FromMilliseconds(300f)), + }; + sys.CreateEffect(effect); + } foreach (var uid in msg.Hits) { diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs index 06d4338b7c..b3c402e800 100644 --- a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs @@ -17,6 +17,8 @@ using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; using Content.Shared.Damage; using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Server.GameObjects; +using Robust.Shared.GameObjects.EntitySystemMessages; namespace Content.Server.GameObjects.Components.Weapon.Melee { @@ -24,7 +26,6 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee public class MeleeWeaponComponent : Component, IAttack { [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; [Dependency] private readonly IPhysicsManager _physicsManager = default!; public override string Name => "MeleeWeapon"; @@ -54,6 +55,9 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee [ViewVariables(VVAccess.ReadWrite)] public DamageType DamageType { get; set; } + [ViewVariables(VVAccess.ReadWrite)] + public bool ClickAttackEffect { get; set; } + public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); @@ -68,6 +72,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee serializer.DataField(this, x => x.ArcCooldownTime, "arcCooldownTime", 1f); serializer.DataField(this, x => x.CooldownTime, "cooldownTime", 1f); serializer.DataField(this, x => x.DamageType, "damageType", DamageType.Blunt); + serializer.DataField(this, x => x.ClickAttackEffect, "clickAttackEffect", true); } protected virtual bool OnHitEntities(IReadOnlyList entities, AttackEventArgs eventArgs) @@ -117,8 +122,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee if (Arc != null) { - var sys = _entitySystemManager.GetEntitySystem(); - sys.SendAnimation(Arc, angle, eventArgs.User, hitEntities); + var sys = EntitySystem.Get(); + sys.SendAnimation(Arc, angle, eventArgs.User, Owner, hitEntities); } _lastAttackTime = curTime; @@ -170,8 +175,8 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee if (ClickArc != null) { - var sys = _entitySystemManager.GetEntitySystem(); - sys.SendAnimation(ClickArc, angle, eventArgs.User, targets); + var sys = EntitySystem.Get(); + sys.SendAnimation(ClickArc, angle, eventArgs.User, Owner, targets, ClickAttackEffect); } _lastAttackTime = curTime; diff --git a/Content.Server/GameObjects/EntitySystems/MeleeWeaponSystem.cs b/Content.Server/GameObjects/EntitySystems/MeleeWeaponSystem.cs index 82ba72537a..0613f1ec58 100644 --- a/Content.Server/GameObjects/EntitySystems/MeleeWeaponSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/MeleeWeaponSystem.cs @@ -9,10 +9,10 @@ namespace Content.Server.GameObjects.EntitySystems { public sealed class MeleeWeaponSystem : EntitySystem { - public void SendAnimation(string arc, Angle angle, IEntity attacker, IEnumerable hits) + public void SendAnimation(string arc, Angle angle, IEntity attacker, IEntity source, IEnumerable hits, bool textureEffect = false) { - RaiseNetworkEvent(new MeleeWeaponSystemMessages.PlayMeleeWeaponAnimationMessage(arc, angle, attacker.Uid, - hits.Select(e => e.Uid).ToList())); + RaiseNetworkEvent(new MeleeWeaponSystemMessages.PlayMeleeWeaponAnimationMessage(arc, angle, attacker.Uid, source.Uid, + hits.Select(e => e.Uid).ToList(), textureEffect)); } } } diff --git a/Content.Shared/GameObjects/EntitySystemMessages/MeleeWeaponSystemMessages.cs b/Content.Shared/GameObjects/EntitySystemMessages/MeleeWeaponSystemMessages.cs index 989defae06..2f1bd231fa 100644 --- a/Content.Shared/GameObjects/EntitySystemMessages/MeleeWeaponSystemMessages.cs +++ b/Content.Shared/GameObjects/EntitySystemMessages/MeleeWeaponSystemMessages.cs @@ -11,18 +11,22 @@ namespace Content.Shared.GameObjects.EntitySystemMessages [Serializable, NetSerializable] public sealed class PlayMeleeWeaponAnimationMessage : EntitySystemMessage { - public PlayMeleeWeaponAnimationMessage(string arcPrototype, Angle angle, EntityUid attacker, List hits) + public PlayMeleeWeaponAnimationMessage(string arcPrototype, Angle angle, EntityUid attacker, EntityUid source, List hits, bool textureEffect = false) { ArcPrototype = arcPrototype; Angle = angle; Attacker = attacker; + Source = source; Hits = hits; + TextureEffect = textureEffect; } public string ArcPrototype { get; } public Angle Angle { get; } public EntityUid Attacker { get; } + public EntityUid Source { get; } public List Hits { get; } + public bool TextureEffect { get; } } } } diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IAttack.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IAttack.cs index 218b403600..48bf6a3e5a 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IAttack.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IAttack.cs @@ -32,6 +32,6 @@ namespace Content.Shared.Interfaces.GameObjects.Components public GridCoordinates ClickLocation { get; } public bool WideAttack { get; } public EntityUid Target { get; } - public IEntity? TargetEntity => IoCManager.Resolve()?.GetEntity(Target) ?? null; + public IEntity? TargetEntity => Target.IsValid() ? IoCManager.Resolve()?.GetEntity(Target) ?? null : null; } }