diff --git a/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs b/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs index 5e3c1dcdfd..04e6315742 100644 --- a/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs +++ b/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs @@ -1,16 +1,24 @@ using Content.Server.Administration.Logs; using Content.Server.Damage.Components; +using Content.Server.Weapons.Ranged.Systems; +using Content.Shared.Camera; using Content.Shared.Damage; using Content.Shared.Database; +using Content.Shared.Effects; using Content.Shared.Mobs.Components; using Content.Shared.Throwing; +using Robust.Shared.Physics.Components; +using Robust.Shared.Player; namespace Content.Server.Damage.Systems { public sealed class DamageOtherOnHitSystem : EntitySystem { [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly IAdminLogManager _adminLogger= default!; + [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly GunSystem _guns = default!; + [Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!; + [Dependency] private readonly ThrownItemSystem _thrownItem = default!; public override void Initialize() { @@ -19,11 +27,21 @@ namespace Content.Server.Damage.Systems private void OnDoHit(EntityUid uid, DamageOtherOnHitComponent component, ThrowDoHitEvent args) { - var dmg = _damageableSystem.TryChangeDamage(args.Target, component.Damage, component.IgnoreResistances, origin: args.User); + var dmg = _damageableSystem.TryChangeDamage(args.Target, component.Damage, component.IgnoreResistances, origin: args.Component.Thrower); // Log damage only for mobs. Useful for when people throw spears at each other, but also avoids log-spam when explosions send glass shards flying. if (dmg != null && HasComp(args.Target)) _adminLogger.Add(LogType.ThrowHit, $"{ToPrettyString(args.Target):target} received {dmg.Total:damage} damage from collision"); + + RaiseNetworkEvent(new ColorFlashEffectEvent(Color.Red, new List { args.Target }), Filter.Pvs(args.Target, entityManager: EntityManager)); + _guns.PlayImpactSound(args.Target, dmg, null, false); + if (TryComp(uid, out var body) && body.LinearVelocity.LengthSquared() > 0f) + { + var direction = body.LinearVelocity.Normalized(); + _sharedCameraRecoil.KickCamera(args.Target, direction); + } + + _thrownItem.LandComponent(args.Thrown, args.Component, playSound: false); } } } diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs index dd7742d764..d98af4bf20 100644 --- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs +++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs @@ -309,8 +309,8 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem return; } - if (args.User != null) - _adminLogger.Add(LogType.Landed, LogImpact.Low, $"{ToPrettyString(args.Thrown)} thrown by {ToPrettyString(args.User.Value):player} landed in {ToPrettyString(uid)}"); + if (args.Component.Thrower != null) + _adminLogger.Add(LogType.Landed, LogImpact.Low, $"{ToPrettyString(args.Thrown)} thrown by {ToPrettyString(args.Component.Thrower.Value):player} landed in {ToPrettyString(uid)}"); AfterInsert(uid, component, args.Thrown); } diff --git a/Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs b/Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs index a20bce96ff..c9840ff235 100644 --- a/Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/CreamPieSystem.cs @@ -82,7 +82,7 @@ namespace Content.Server.Nutrition.EntitySystems protected override void CreamedEntity(EntityUid uid, CreamPiedComponent creamPied, ThrowHitByEvent args) { - _popup.PopupEntity(Loc.GetString("cream-pied-component-on-hit-by-message",("thrower", args.Thrown)), uid, args.Target); + _popup.PopupEntity(Loc.GetString("cream-pied-component-on-hit-by-message", ("thrower", args.Thrown)), uid, args.Target); var otherPlayers = Filter.Empty().AddPlayersByPvs(uid); if (TryComp(args.Target, out var actor)) { diff --git a/Content.Shared/Throwing/ThrowEvents.cs b/Content.Shared/Throwing/ThrowEvents.cs index da3948cd03..fbda80b8ca 100644 --- a/Content.Shared/Throwing/ThrowEvents.cs +++ b/Content.Shared/Throwing/ThrowEvents.cs @@ -5,26 +5,15 @@ namespace Content.Shared.Throwing /// public abstract class ThrowEvent : HandledEntityEventArgs { - /// - /// The entity that threw . - /// - public EntityUid? User { get; } + public readonly EntityUid Thrown; + public readonly EntityUid Target; + public ThrownItemComponent Component; - /// - /// The entity thrown by that hit - /// - public EntityUid Thrown { get; } - - /// - /// The entity hit with by - /// - public EntityUid Target { get; } - - public ThrowEvent(EntityUid? user, EntityUid thrown, EntityUid target) + public ThrowEvent(EntityUid thrown, EntityUid target, ThrownItemComponent component) { - User = user; Thrown = thrown; Target = target; + Component = component; } } @@ -33,7 +22,7 @@ namespace Content.Shared.Throwing /// public sealed class ThrowHitByEvent : ThrowEvent { - public ThrowHitByEvent(EntityUid? user, EntityUid thrown, EntityUid target) : base(user, thrown, target) + public ThrowHitByEvent(EntityUid thrown, EntityUid target, ThrownItemComponent component) : base(thrown, target, component) { } } @@ -43,7 +32,7 @@ namespace Content.Shared.Throwing /// public sealed class ThrowDoHitEvent : ThrowEvent { - public ThrowDoHitEvent(EntityUid? user, EntityUid thrown, EntityUid target) : base(user, thrown, target) + public ThrowDoHitEvent(EntityUid thrown, EntityUid target, ThrownItemComponent component) : base(thrown, target, component) { } } diff --git a/Content.Shared/Throwing/ThrownItemSystem.cs b/Content.Shared/Throwing/ThrownItemSystem.cs index 1eb12938d7..0c462a9573 100644 --- a/Content.Shared/Throwing/ThrownItemSystem.cs +++ b/Content.Shared/Throwing/ThrownItemSystem.cs @@ -45,7 +45,7 @@ namespace Content.Shared.Throwing private void OnHandleState(EntityUid uid, ThrownItemComponent component, ref ComponentHandleState args) { - if (args.Current is not ThrownItemComponentState {Thrower: not null } state || + if (args.Current is not ThrownItemComponentState { Thrower: not null } state || !state.Thrower.Value.IsValid()) { return; @@ -73,11 +73,10 @@ namespace Content.Shared.Throwing if (args.OtherFixture.Hard == false) return; - var thrower = component.Thrower; - if (args.OtherEntity == thrower) + if (args.OtherEntity == component.Thrower) return; - ThrowCollideInteraction(thrower, args.OurBody, args.OtherBody); + ThrowCollideInteraction(component, args.OurEntity, args.OtherEntity); } private void PreventCollision(EntityUid uid, ThrownItemComponent component, ref PreventCollideEvent args) @@ -116,8 +115,13 @@ namespace Content.Shared.Throwing EntityManager.RemoveComponent(uid); } - public void LandComponent(EntityUid uid, ThrownItemComponent thrownItem, PhysicsComponent physics, bool playSound) + public void LandComponent(EntityUid uid, ThrownItemComponent thrownItem, PhysicsComponent? physics = null, bool playSound = true) { + if (!Resolve(uid, ref physics)) + { + return; + } + _physics.SetBodyStatus(physics, BodyStatus.OnGround); if (thrownItem.Deleted || Deleted(uid) || _containerSystem.IsEntityInContainer(uid)) @@ -145,14 +149,14 @@ namespace Content.Shared.Throwing /// /// Raises collision events on the thrown and target entities. /// - public void ThrowCollideInteraction(EntityUid? user, PhysicsComponent thrown, PhysicsComponent target) + public void ThrowCollideInteraction(ThrownItemComponent component, EntityUid thrown, EntityUid target) { - if (user is not null) + if (component.Thrower is not null) _adminLogger.Add(LogType.ThrowHit, LogImpact.Low, - $"{ToPrettyString(thrown.Owner):thrown} thrown by {ToPrettyString(user.Value):thrower} hit {ToPrettyString(target.Owner):target}."); - // TODO: Just pass in the bodies directly - RaiseLocalEvent(target.Owner, new ThrowHitByEvent(user, thrown.Owner, target.Owner), true); - RaiseLocalEvent(thrown.Owner, new ThrowDoHitEvent(user, thrown.Owner, target.Owner), true); + $"{ToPrettyString(thrown):thrown} thrown by {ToPrettyString(component.Thrower.Value):thrower} hit {ToPrettyString(target):target}."); + + RaiseLocalEvent(target, new ThrowHitByEvent(thrown, target, component), true); + RaiseLocalEvent(thrown, new ThrowDoHitEvent(thrown, target, component), true); } } }