using Content.Server.Administration.Logs; using Content.Server.Damage.Components; using Content.Server.Weapons.Ranged.Systems; using Content.Shared.CombatMode.Pacification; using Content.Shared.Camera; using Content.Shared.Damage; using Content.Shared.Damage.Events; using Content.Shared.Damage.Systems; using Content.Shared.Database; using Content.Shared.Effects; using Content.Shared.Mobs.Components; using Content.Shared.Throwing; using Content.Shared.Wires; using Robust.Shared.Physics.Components; using Robust.Shared.Player; namespace Content.Server.Damage.Systems { public sealed class DamageOtherOnHitSystem : EntitySystem { [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly GunSystem _guns = default!; [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly DamageExamineSystem _damageExamine = default!; [Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!; [Dependency] private readonly SharedColorFlashEffectSystem _color = default!; public override void Initialize() { SubscribeLocalEvent(OnDoHit); SubscribeLocalEvent(OnDamageExamine); SubscribeLocalEvent(OnAttemptPacifiedThrow); } private void OnDoHit(EntityUid uid, DamageOtherOnHitComponent component, ThrowDoHitEvent args) { if (TerminatingOrDeleted(args.Target)) return; var dmg = _damageable.TryChangeDamage(args.Target, component.Damage * _damageable.UniversalThrownDamageModifier, 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.GetTotal():damage} damage from collision"); if (dmg is { Empty: false }) { _color.RaiseEffect(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); } } private void OnDamageExamine(EntityUid uid, DamageOtherOnHitComponent component, ref DamageExamineEvent args) { _damageExamine.AddDamageExamine(args.Message, _damageable.ApplyUniversalAllModifiers(component.Damage * _damageable.UniversalThrownDamageModifier), Loc.GetString("damage-throw")); } /// /// Prevent players with the Pacified status effect from throwing things that deal damage. /// private void OnAttemptPacifiedThrow(Entity ent, ref AttemptPacifiedThrowEvent args) { args.Cancel("pacified-cannot-throw"); } } }