using Content.Server._DV.Projectiles.Components; using Content.Server._DV.Projectiles.Events; using Content.Shared.Tag; namespace Content.Server._DV.Projectiles.Systems; public sealed class PiercingProjectileSystem : EntitySystem { [Dependency] private readonly TagSystem _tagSystem = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnPierce); } private void OnPierce(Entity bullet, ref ProjectilePierceEvent args) { // If the target doesn't have any tags to stop the bullet from piercing, it's automatically true. if (!_tagSystem.HasAnyTag(args.Target, bullet.Comp.PierceBlockTag)) { args.Pierced = true; return; } // If it does have the tag to stop it and enough health to count as "strongly armored", it'll block the bullet. if (bullet.Comp.HealthThreshold < args.RequiredDamage) return; if (bullet.Comp.Direction == null) // Get the direction of the bullet to determine which walls count. bullet.Comp.Direction = Transform(bullet).LocalRotation.GetCardinalDir(); var xTarget = Transform(args.Target); var targetPosition = bullet.Comp.Direction is Direction.East or Direction.West ? xTarget.Coordinates.X // If the bullet is going horizontal, wall rows are vertical. : xTarget.Coordinates.Y; // And when vertical, the wall rows are horizontal // If the wall is part of a wall-row that the bullet already pierced, pierce it too and ignore it for the counter. if (bullet.Comp.IgnoreRowCoordinate != null && Math.Abs(targetPosition - bullet.Comp.IgnoreRowCoordinate.Value) < 0.25) { args.Pierced = true; return; } bullet.Comp.PierceCounter++; if (bullet.Comp.PierceCounter > bullet.Comp.MaxPierceNumberThreshold) return; // Save the row-position of the last wall it pierced, so we can ignore any other wall part of the same row. bullet.Comp.IgnoreRowCoordinate = targetPosition; args.Pierced = true; } }