]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Revert "Cleanup ExecutionSystem (#24382)" (#25555)
authormetalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Sun, 25 Feb 2024 11:36:17 +0000 (22:36 +1100)
committerGitHub <noreply@github.com>
Sun, 25 Feb 2024 11:36:17 +0000 (22:36 +1100)
* Revert "Cleanup ExecutionSystem (#24382)"

This reverts commit bcbe2ec1af39ad1fea286fd27a40bc3794a2ce34.

* Revert "Executions (#24150)"

This reverts commit 2e83f5a0ecc5fea0177acd94e22133de0d614588.

# Conflicts:
# Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs

27 files changed:
Content.Server/Projectiles/ProjectileSystem.cs
Content.Server/Weapons/Ranged/Systems/GunSystem.cs
Content.Shared/Execution/DoafterEvent.cs [deleted file]
Content.Shared/Execution/ExecutionComponent.cs [deleted file]
Content.Shared/Execution/ExecutionSystem.cs [deleted file]
Content.Shared/Projectiles/SharedProjectileSystem.cs
Content.Shared/Weapons/Ranged/Events/ShotAttemptedEvent.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
Resources/Locale/en-US/execution/execution.ftl [deleted file]
Resources/Locale/en-US/kitchen/components/butcherable-component.ftl
Resources/Prototypes/Entities/Objects/Materials/crystal_shard.yml
Resources/Prototypes/Entities/Objects/Materials/shards.yml
Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/HMGs/hmgs.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/flare_gun.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml
Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml
Resources/Prototypes/Entities/Objects/Weapons/Melee/fireaxe.yml
Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml
Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml

index 80c5f039d33e352ebaed772a4bef2190d23901c2..15ea5936e13921d63c2a57ea1d57765dd0fa530e 100644 (file)
@@ -28,14 +28,10 @@ public sealed class ProjectileSystem : SharedProjectileSystem
     {
         // This is so entities that shouldn't get a collision are ignored.
         if (args.OurFixtureId != ProjectileFixture || !args.OtherFixture.Hard
-                                                   || component.DamagedEntity || component is
-                                                       { Weapon: null, OnlyCollideWhenShot: true })
-        {
+            || component.DamagedEntity || component is { Weapon: null, OnlyCollideWhenShot: true })
             return;
-        }
 
         var target = args.OtherEntity;
-
         // it's here so this check is only done once before possible hit
         var attemptEv = new ProjectileReflectAttemptEvent(uid, component, false);
         RaiseLocalEvent(target, ref attemptEv);
@@ -45,26 +41,11 @@ public sealed class ProjectileSystem : SharedProjectileSystem
             return;
         }
 
-        if (TryHandleProjectile(target, (uid, component)))
-        {
-            var direction = args.OurBody.LinearVelocity.Normalized();
-            _sharedCameraRecoil.KickCamera(target, direction);
-        }
-    }
-
-    /// <summary>
-    /// Tries to handle a projectile interacting with the target.
-    /// </summary>
-    /// <returns>True if the target isn't deleted.</returns>
-    public bool TryHandleProjectile(EntityUid target, Entity<ProjectileComponent> projectile)
-    {
-        var uid = projectile.Owner;
-        var component = projectile.Comp;
-
         var ev = new ProjectileHitEvent(component.Damage, target, component.Shooter);
         RaiseLocalEvent(uid, ref ev);
 
         var otherName = ToPrettyString(target);
+        var direction = args.OurBody.LinearVelocity.Normalized();
         var modifiedDamage = _damageableSystem.TryChangeDamage(target, ev.Damage, component.IgnoreResistances, origin: component.Shooter);
         var deleted = Deleted(target);
 
@@ -83,11 +64,12 @@ public sealed class ProjectileSystem : SharedProjectileSystem
         if (!deleted)
         {
             _guns.PlayImpactSound(target, modifiedDamage, component.SoundHit, component.ForceSound);
+            _sharedCameraRecoil.KickCamera(target, direction);
         }
 
         component.DamagedEntity = true;
 
-        var afterProjectileHitEvent = new AfterProjectileHitEvent(component.Damage, target);
+        var afterProjectileHitEvent = new AfterProjectileHitEvent(component.Damage, target, args.OtherFixture);
         RaiseLocalEvent(uid, ref afterProjectileHitEvent);
 
         if (component.DeleteOnCollide)
@@ -97,7 +79,5 @@ public sealed class ProjectileSystem : SharedProjectileSystem
         {
             RaiseNetworkEvent(new ImpactEffectEvent(component.ImpactEffect, GetNetCoordinates(xform.Coordinates)), Filter.Pvs(xform.Coordinates, entityMan: EntityManager));
         }
-
-        return !deleted;
     }
 }
index fd3b6c5db33e3e300a7a547464eff14607c4cab8..b8f8f122111b64a233368d3aab04110d40860f27 100644 (file)
@@ -4,7 +4,6 @@ using Content.Server.Administration.Logs;
 using Content.Server.Cargo.Systems;
 using Content.Server.Interaction;
 using Content.Server.Power.EntitySystems;
-using Content.Server.Projectiles;
 using Content.Server.Stunnable;
 using Content.Server.Weapons.Ranged.Components;
 using Content.Shared.Damage;
@@ -30,13 +29,13 @@ namespace Content.Server.Weapons.Ranged.Systems;
 
 public sealed partial class GunSystem : SharedGunSystem
 {
+    [Dependency] private readonly IAdminLogManager _adminLogger = default!;
     [Dependency] private readonly IComponentFactory _factory = default!;
     [Dependency] private readonly BatterySystem _battery = default!;
     [Dependency] private readonly DamageExamineSystem _damageExamine = default!;
     [Dependency] private readonly InteractionSystem _interaction = default!;
     [Dependency] private readonly PricingSystem _pricing = default!;
     [Dependency] private readonly SharedColorFlashEffectSystem _color = default!;
-    [Dependency] private readonly ProjectileSystem _projectile = default!;
     [Dependency] private readonly SharedTransformSystem _transform = default!;
     [Dependency] private readonly StaminaSystem _stamina = default!;
     [Dependency] private readonly StunSystem _stun = default!;
@@ -66,137 +65,6 @@ public sealed partial class GunSystem : SharedGunSystem
         args.Price += price * component.UnspawnedCount;
     }
 
-    protected override bool ShootDirect(EntityUid gunUid, GunComponent gun, EntityUid target, List<(EntityUid? Entity, IShootable Shootable)> ammo, EntityUid user)
-    {
-        var result = false;
-
-        // TODO: This is dogshit. I just want to get executions slightly better.
-        // Ideally you'd pull out cartridge + ammo to separate handling functions and re-use it here, then hitscan you need to bypass entirely.
-        // You should also make shooting into a struct of args given how many there are now.
-        var fromCoordinates = Transform(gunUid).Coordinates;
-        var toCoordinates = Transform(target).Coordinates;
-
-        var fromMap = fromCoordinates.ToMap(EntityManager, TransformSystem);
-        var toMap = toCoordinates.ToMapPos(EntityManager, TransformSystem);
-        var mapDirection = toMap - fromMap.Position;
-        var angle = GetRecoilAngle(Timing.CurTime, gun, mapDirection.ToAngle());
-
-        // If applicable, this ensures the projectile is parented to grid on spawn, instead of the map.
-        var fromEnt = MapManager.TryFindGridAt(fromMap, out var gridUid, out _)
-            ? fromCoordinates.WithEntityId(gridUid, EntityManager)
-            : new EntityCoordinates(MapManager.GetMapEntityId(fromMap.MapId), fromMap.Position);
-
-        // I must be high because this was getting tripped even when true.
-        // DebugTools.Assert(direction != Vector2.Zero);
-        var shotProjectiles = new List<EntityUid>(ammo.Count);
-        var cartridgeBullets = new List<EntityUid>();
-
-        foreach (var (ent, shootable) in ammo)
-        {
-            switch (shootable)
-            {
-                // Cartridge shoots something else
-                case CartridgeAmmoComponent cartridge:
-                    if (!cartridge.Spent)
-                    {
-                        for (var i = 0; i < cartridge.Count; i++)
-                        {
-                            var uid = Spawn(cartridge.Prototype, fromEnt);
-                            cartridgeBullets.Add(uid);
-                        }
-
-                        RaiseLocalEvent(ent!.Value, new AmmoShotEvent()
-                        {
-                            FiredProjectiles = cartridgeBullets,
-                        });
-
-                        shotProjectiles.AddRange(cartridgeBullets);
-                        cartridgeBullets.Clear();
-                        SetCartridgeSpent(ent.Value, cartridge, true);
-                        MuzzleFlash(gunUid, cartridge, user);
-                        Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
-
-                        if (cartridge.DeleteOnSpawn)
-                            Del(ent.Value);
-                    }
-                    else
-                    {
-                        Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
-                    }
-
-                    // Something like ballistic might want to leave it in the container still
-                    if (!cartridge.DeleteOnSpawn && !Containers.IsEntityInContainer(ent!.Value))
-                        EjectCartridge(ent.Value, angle);
-
-                    result = true;
-                    Dirty(ent!.Value, cartridge);
-                    break;
-                // Ammo shoots itself
-                case AmmoComponent newAmmo:
-                    result = true;
-                    shotProjectiles.Add(ent!.Value);
-                    MuzzleFlash(gunUid, newAmmo, user);
-                    Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
-                    break;
-                case HitscanPrototype hitscan:
-                    result = true;
-                    var hitEntity = target;
-                    if (hitscan.StaminaDamage > 0f)
-                        _stamina.TakeStaminaDamage(hitEntity, hitscan.StaminaDamage, source: user);
-
-                    var dmg = hitscan.Damage;
-
-                    var hitName = ToPrettyString(hitEntity);
-                    if (dmg != null)
-                        dmg = Damageable.TryChangeDamage(hitEntity, dmg, origin: user);
-
-                    // check null again, as TryChangeDamage returns modified damage values
-                    if (dmg != null)
-                    {
-                        if (!Deleted(hitEntity))
-                        {
-                            if (dmg.Any())
-                            {
-                                _color.RaiseEffect(Color.Red, new List<EntityUid>() { hitEntity }, Filter.Pvs(hitEntity, entityManager: EntityManager));
-                            }
-
-                            // TODO get fallback position for playing hit sound.
-                            PlayImpactSound(hitEntity, dmg, hitscan.Sound, hitscan.ForceSound);
-                        }
-
-                        Logs.Add(LogType.HitScanHit,
-                            $"{ToPrettyString(user):user} hit {hitName:target} using hitscan and dealt {dmg.GetTotal():damage} damage");
-                    }
-
-                    Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
-                    break;
-                default:
-                    throw new ArgumentOutOfRangeException();
-            }
-        }
-
-        foreach (var ammoUid in shotProjectiles)
-        {
-            // TODO: Handle this shit
-            if (!TryComp(ammoUid, out ProjectileComponent? projectileComponent))
-            {
-                QueueDel(ammoUid);
-                continue;
-            }
-
-            _projectile.TryHandleProjectile(target, (ammoUid, projectileComponent));
-            // Even this deletion handling is mega sussy.
-            Del(ammoUid);
-        }
-
-        RaiseLocalEvent(gunUid, new AmmoShotEvent()
-        {
-            FiredProjectiles = shotProjectiles,
-        });
-
-        return result;
-    }
-
     public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid? Entity, IShootable Shootable)> ammo,
         EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, out bool userImpulse, EntityUid? user = null, bool throwItems = false)
     {
@@ -204,7 +72,7 @@ public sealed partial class GunSystem : SharedGunSystem
 
         // Try a clumsy roll
         // TODO: Who put this here
-        if (TryComp<ClumsyComponent>(user, out var clumsy) && !gun.ClumsyProof)
+        if (TryComp<ClumsyComponent>(user, out var clumsy) && gun.ClumsyProof == false)
         {
             for (var i = 0; i < ammo.Count; i++)
             {
@@ -225,8 +93,6 @@ public sealed partial class GunSystem : SharedGunSystem
             }
         }
 
-        // As the above message wasn't obvious stop putting stuff here and use events
-
         var fromMap = fromCoordinates.ToMap(EntityManager, TransformSystem);
         var toMap = toCoordinates.ToMapPos(EntityManager, TransformSystem);
         var mapDirection = toMap - fromMap.Position;
@@ -234,7 +100,7 @@ public sealed partial class GunSystem : SharedGunSystem
         var angle = GetRecoilAngle(Timing.CurTime, gun, mapDirection.ToAngle());
 
         // If applicable, this ensures the projectile is parented to grid on spawn, instead of the map.
-        var fromEnt = MapManager.TryFindGridAt(fromMap, out var gridUid, out _)
+        var fromEnt = MapManager.TryFindGridAt(fromMap, out var gridUid, out var grid)
             ? fromCoordinates.WithEntityId(gridUid, EntityManager)
             : new EntityCoordinates(MapManager.GetMapEntityId(fromMap.MapId), fromMap.Position);
 
@@ -246,7 +112,6 @@ public sealed partial class GunSystem : SharedGunSystem
         // I must be high because this was getting tripped even when true.
         // DebugTools.Assert(direction != Vector2.Zero);
         var shotProjectiles = new List<EntityUid>(ammo.Count);
-        var cartridgeBullets = new List<EntityUid>();
 
         foreach (var (ent, shootable) in ammo)
         {
@@ -275,23 +140,21 @@ public sealed partial class GunSystem : SharedGunSystem
                             {
                                 var uid = Spawn(cartridge.Prototype, fromEnt);
                                 ShootOrThrow(uid, angles[i].ToVec(), gunVelocity, gun, gunUid, user);
-                                cartridgeBullets.Add(uid);
+                                shotProjectiles.Add(uid);
                             }
                         }
                         else
                         {
                             var uid = Spawn(cartridge.Prototype, fromEnt);
                             ShootOrThrow(uid, mapDirection, gunVelocity, gun, gunUid, user);
-                            cartridgeBullets.Add(uid);
+                            shotProjectiles.Add(uid);
                         }
 
                         RaiseLocalEvent(ent!.Value, new AmmoShotEvent()
                         {
-                            FiredProjectiles = cartridgeBullets,
+                            FiredProjectiles = shotProjectiles,
                         });
 
-                        shotProjectiles.AddRange(cartridgeBullets);
-                        cartridgeBullets.Clear();
                         SetCartridgeSpent(ent.Value, cartridge, true);
                         MuzzleFlash(gunUid, cartridge, user);
                         Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
diff --git a/Content.Shared/Execution/DoafterEvent.cs b/Content.Shared/Execution/DoafterEvent.cs
deleted file mode 100644 (file)
index 7854974..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-using Content.Shared.DoAfter;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Execution;
-
-[Serializable, NetSerializable]
-public sealed partial class ExecutionDoAfterEvent : SimpleDoAfterEvent
-{
-}
diff --git a/Content.Shared/Execution/ExecutionComponent.cs b/Content.Shared/Execution/ExecutionComponent.cs
deleted file mode 100644 (file)
index f9c5111..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Execution;
-
-/// <summary>
-/// Added to entities that can be used to execute another target.
-/// </summary>
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
-public sealed partial class ExecutionComponent : Component
-{
-    /// <summary>
-    /// How long the execution duration lasts.
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public float DoAfterDuration = 5f;
-
-    [DataField, AutoNetworkedField]
-    public float DamageModifier = 9f;
-
-    // Not networked because this is transient inside of a tick.
-    /// <summary>
-    /// True if it is currently executing for handlers.
-    /// </summary>
-    [DataField]
-    public bool Executing = true;
-}
diff --git a/Content.Shared/Execution/ExecutionSystem.cs b/Content.Shared/Execution/ExecutionSystem.cs
deleted file mode 100644 (file)
index de6db20..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-using Content.Shared.Weapons.Ranged.Systems;
-using Content.Shared.ActionBlocker;
-using Content.Shared.CombatMode;
-using Content.Shared.Damage;
-using Content.Shared.Database;
-using Content.Shared.DoAfter;
-using Content.Shared.Mobs.Components;
-using Content.Shared.Mobs.Systems;
-using Content.Shared.Popups;
-using Content.Shared.Verbs;
-using Content.Shared.Weapons.Melee;
-using Content.Shared.Weapons.Melee.Events;
-using Content.Shared.Weapons.Ranged.Components;
-using Robust.Shared.Network;
-using Robust.Shared.Player;
-
-namespace Content.Shared.Execution;
-
-/// <summary>
-///     Verb for violently murdering cuffed creatures.
-/// </summary>
-public sealed class ExecutionSystem : EntitySystem
-{
-    [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
-    [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
-    [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
-    [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
-    [Dependency] private readonly SharedGunSystem _gunSystem = default!;
-    [Dependency] private readonly SharedCombatModeSystem _combatSystem = default!;
-    [Dependency] private readonly SharedMeleeWeaponSystem _meleeSystem = default!;
-
-    // TODO: Still needs more cleaning up.
-    private const string DefaultInternalMeleeExecutionMessage = "execution-popup-melee-initial-internal";
-    private const string DefaultExternalMeleeExecutionMessage = "execution-popup-melee-initial-external";
-    private const string DefaultCompleteInternalMeleeExecutionMessage = "execution-popup-melee-complete-internal";
-    private const string DefaultCompleteExternalMeleeExecutionMessage = "execution-popup-melee-complete-external";
-    private const string DefaultInternalGunExecutionMessage = "execution-popup-gun-initial-internal";
-    private const string DefaultExternalGunExecutionMessage = "execution-popup-gun-initial-external";
-    private const string DefaultCompleteInternalGunExecutionMessage = "execution-popup-gun-complete-internal";
-    private const string DefaultCompleteExternalGunExecutionMessage = "execution-popup-gun-complete-external";
-
-    /// <inheritdoc/>
-    public override void Initialize()
-    {
-        base.Initialize();
-
-        SubscribeLocalEvent<ExecutionComponent, GetVerbsEvent<UtilityVerb>>(OnGetInteractionsVerbs);
-        SubscribeLocalEvent<ExecutionComponent, ExecutionDoAfterEvent>(OnExecutionDoAfter);
-        SubscribeLocalEvent<ExecutionComponent, GetMeleeDamageEvent>(OnGetMeleeDamage);
-    }
-
-    private void OnGetInteractionsVerbs(EntityUid uid, ExecutionComponent comp, GetVerbsEvent<UtilityVerb> args)
-    {
-        if (args.Hands == null || args.Using == null || !args.CanAccess || !args.CanInteract)
-            return;
-
-        var attacker = args.User;
-        var weapon = args.Using.Value;
-        var victim = args.Target;
-
-        if (!CanExecuteWithAny(victim, attacker))
-            return;
-
-        UtilityVerb verb = new()
-        {
-            Act = () => TryStartExecutionDoAfter(weapon, victim, attacker, comp),
-            Impact = LogImpact.High,
-            Text = Loc.GetString("execution-verb-name"),
-            Message = Loc.GetString("execution-verb-message"),
-        };
-
-        args.Verbs.Add(verb);
-    }
-
-    private void TryStartExecutionDoAfter(EntityUid weapon, EntityUid victim, EntityUid attacker, ExecutionComponent comp)
-    {
-        if (!CanExecuteWithAny(victim, attacker))
-            return;
-
-        // TODO: This should just be on the weapons as a single execution message.
-        var defaultExecutionInternal = DefaultInternalMeleeExecutionMessage;
-        var defaultExecutionExternal = DefaultExternalMeleeExecutionMessage;
-
-        if (HasComp<GunComponent>(weapon))
-        {
-            defaultExecutionExternal = DefaultInternalGunExecutionMessage;
-            defaultExecutionInternal = DefaultExternalGunExecutionMessage;
-        }
-
-        var internalMsg = defaultExecutionInternal;
-        var externalMsg = defaultExecutionExternal;
-        ShowExecutionInternalPopup(internalMsg, attacker, victim, weapon);
-        ShowExecutionExternalPopup(externalMsg, attacker, victim, weapon);
-
-        var doAfter =
-            new DoAfterArgs(EntityManager, attacker, comp.DoAfterDuration, new ExecutionDoAfterEvent(), weapon, target: victim, used: weapon)
-            {
-                BreakOnTargetMove = true,
-                BreakOnUserMove = true,
-                BreakOnDamage = true,
-                NeedHand = true
-            };
-
-        _doAfterSystem.TryStartDoAfter(doAfter);
-
-    }
-
-    private bool CanExecuteWithAny(EntityUid victim, EntityUid attacker)
-    {
-        // Use suicide.
-        if (victim == attacker)
-            return false;
-
-        // No point executing someone if they can't take damage
-        if (!TryComp<DamageableComponent>(victim, out _))
-            return false;
-
-        // You can't execute something that cannot die
-        if (!TryComp<MobStateComponent>(victim, out var mobState))
-            return false;
-
-        // You're not allowed to execute dead people (no fun allowed)
-        if (_mobStateSystem.IsDead(victim, mobState))
-            return false;
-
-        // You must be able to attack people to execute
-        if (!_actionBlockerSystem.CanAttack(attacker, victim))
-            return false;
-
-        // The victim must be incapacitated to be executed
-        if (victim != attacker && _actionBlockerSystem.CanInteract(victim, null))
-            return false;
-
-        // All checks passed
-        return true;
-    }
-
-    private void OnExecutionDoAfter(EntityUid uid, ExecutionComponent component, ExecutionDoAfterEvent args)
-    {
-        if (args.Handled || args.Cancelled || args.Used == null || args.Target == null)
-            return;
-
-        var attacker = args.User;
-        var victim = args.Target.Value;
-        var weapon = args.Used.Value;
-
-        if (!CanExecuteWithAny(victim, attacker))
-            return;
-
-        // This is needed so the melee system does not stop it.
-        var prev = _combatSystem.IsInCombatMode(attacker);
-        _combatSystem.SetInCombatMode(attacker, true);
-        component.Executing = true;
-        string? internalMsg = null;
-        string? externalMsg = null;
-
-        if (TryComp(uid, out MeleeWeaponComponent? melee))
-        {
-            _meleeSystem.AttemptLightAttack(attacker, weapon, melee, victim);
-            internalMsg = DefaultCompleteInternalMeleeExecutionMessage;
-            externalMsg = DefaultCompleteExternalMeleeExecutionMessage;
-        }
-        else if (TryComp(uid, out GunComponent? gun))
-        {
-            var clumsyShot = false;
-
-            // TODO: This should just be an event or something instead to get this.
-            // TODO: Handle clumsy.
-            if (!_gunSystem.AttemptDirectShoot(args.User, uid, args.Target.Value, gun))
-            {
-                internalMsg = null;
-                externalMsg = null;
-            }
-            else
-            {
-                internalMsg = DefaultCompleteInternalGunExecutionMessage;
-                externalMsg = DefaultCompleteExternalGunExecutionMessage;
-            }
-            args.Handled = true;
-        }
-
-        _combatSystem.SetInCombatMode(attacker, prev);
-        component.Executing = false;
-        args.Handled = true;
-
-        if (internalMsg != null && externalMsg != null)
-        {
-            ShowExecutionInternalPopup(internalMsg, attacker, victim, uid);
-            ShowExecutionExternalPopup(externalMsg, attacker, victim, uid);
-        }
-    }
-
-    private void OnGetMeleeDamage(EntityUid uid, ExecutionComponent comp, ref GetMeleeDamageEvent args)
-    {
-        if (!TryComp<MeleeWeaponComponent>(uid, out var melee) ||
-            !TryComp<ExecutionComponent>(uid, out var execComp) ||
-            !execComp.Executing)
-        {
-            return;
-        }
-
-        var bonus = melee.Damage * execComp.DamageModifier - melee.Damage;
-        args.Damage += bonus;
-    }
-
-    private void ShowExecutionInternalPopup(string locString,
-        EntityUid attacker, EntityUid victim, EntityUid weapon, bool predict = true)
-    {
-        if (predict)
-        {
-            _popupSystem.PopupClient(
-                Loc.GetString(locString, ("attacker", attacker), ("victim", victim), ("weapon", weapon)),
-                attacker,
-                attacker,
-                PopupType.Medium
-            );
-        }
-        else
-        {
-            _popupSystem.PopupEntity(
-                Loc.GetString(locString, ("attacker", attacker), ("victim", victim), ("weapon", weapon)),
-                attacker,
-                Filter.Entities(attacker),
-                true,
-                PopupType.Medium
-            );
-        }
-
-    }
-
-    private void ShowExecutionExternalPopup(string locString, EntityUid attacker, EntityUid victim, EntityUid weapon)
-    {
-        _popupSystem.PopupEntity(
-            Loc.GetString(locString, ("attacker", attacker), ("victim", victim), ("weapon", weapon)),
-            attacker,
-            Filter.PvsExcept(attacker),
-            true,
-            PopupType.MediumCaution
-            );
-    }
-}
index 027dc039398abbe99488e1f634a8fe801cf29ea3..f57e873653962b71dd6eb4a0959e2ef676984d52 100644 (file)
@@ -34,6 +34,7 @@ public abstract partial class SharedProjectileSystem : EntitySystem
         base.Initialize();
 
         SubscribeLocalEvent<ProjectileComponent, PreventCollideEvent>(PreventCollision);
+        SubscribeLocalEvent<ProjectileComponent, AfterProjectileHitEvent>(AfterProjectileHit);
         SubscribeLocalEvent<EmbeddableProjectileComponent, ProjectileHitEvent>(OnEmbedProjectileHit);
         SubscribeLocalEvent<EmbeddableProjectileComponent, ThrowDoHitEvent>(OnEmbedThrowDoHit);
         SubscribeLocalEvent<EmbeddableProjectileComponent, ActivateInWorldEvent>(OnEmbedActivate);
@@ -162,6 +163,18 @@ public abstract partial class SharedProjectileSystem : EntitySystem
     {
         args.Cancel("pacified-cannot-throw-embed");
     }
+
+    /// <summary>
+    /// Checks if the projectile is allowed to penetrate the target it hit.
+    /// </summary>
+    private void AfterProjectileHit(EntityUid uid, ProjectileComponent component, ref AfterProjectileHitEvent args)
+    {
+        //Overrides the original DeleteOnCollide if the projectile passes all penetration checks.
+        //This is to prevent having to set DeleteOnCollide to false on every prototype
+        //you want to give the ability to penetrate entities.
+        if(component.DeleteOnCollide)
+            component.DeleteOnCollide = false;
+    }
 }
 
 [Serializable, NetSerializable]
@@ -193,4 +206,4 @@ public record struct ProjectileHitEvent(DamageSpecifier Damage, EntityUid Target
 /// Raised after a projectile has dealt it's damage.
 /// </summary>
 [ByRefEvent]
-public record struct AfterProjectileHitEvent(DamageSpecifier Damage, EntityUid Target);
+public record struct AfterProjectileHitEvent(DamageSpecifier Damage, EntityUid Target, Fixture Fixture);
index 6325d953300adb639480c83e2e83e7136d02c20d..40925ad614c943a32706fa4cb8efb578a54f64c0 100644 (file)
@@ -19,7 +19,7 @@ public record struct ShotAttemptedEvent
 
     public bool Cancelled { get; private set; }
 
-    /// <summary>
+    /// </summary>
     /// Prevent the gun from shooting
     /// </summary>
     public void Cancel()
@@ -27,7 +27,7 @@ public record struct ShotAttemptedEvent
         Cancelled = true;
     }
 
-    /// <summary>
+    /// </summary>
     /// Allow the gun to shoot again, only use if you know what you are doing
     /// </summary>
     public void Uncancel()
index 2132dd2631978caeffbb89403c82fb152983898e..ba22ba2cdc8fe0cd5e172d346bee2c9a0b65a60e 100644 (file)
@@ -21,7 +21,6 @@ using Content.Shared.Weapons.Melee;
 using Content.Shared.Weapons.Melee.Events;
 using Content.Shared.Weapons.Ranged.Components;
 using Content.Shared.Weapons.Ranged.Events;
-using JetBrains.Annotations;
 using Robust.Shared.Audio;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Containers;
@@ -144,7 +143,7 @@ public abstract partial class SharedGunSystem : EntitySystem
 
         gun.ShootCoordinates = GetCoordinates(msg.Coordinates);
         Log.Debug($"Set shoot coordinates to {gun.ShootCoordinates}");
-        AttemptShootInternal(user.Value, ent, gun);
+        AttemptShoot(user.Value, ent, gun);
     }
 
     private void OnStopShootRequest(RequestStopShootEvent ev, EntitySessionEventArgs args)
@@ -208,38 +207,13 @@ public abstract partial class SharedGunSystem : EntitySystem
         Dirty(uid, gun);
     }
 
-    /// <summary>
-    /// Attempts to shoot the specified target directly.
-    /// This may bypass projectiles firing etc.
-    /// </summary>
-    public bool AttemptDirectShoot(EntityUid user, EntityUid gunUid, EntityUid target, GunComponent gun)
-    {
-        // Unique name so people don't think it's "shoot towards" and not "I will teleport a bullet into them".
-        gun.ShootCoordinates = Transform(target).Coordinates;
-
-        if (!TryTakeAmmo(user, gunUid, gun, out _, out _, out var args))
-        {
-            gun.ShootCoordinates = null;
-            return false;
-        }
-
-        var result = ShootDirect(gunUid, gun, target, args.Ammo, user: user);
-        gun.ShootCoordinates = null;
-        return result;
-    }
-
-    protected virtual bool ShootDirect(EntityUid gunUid, GunComponent gun, EntityUid target, List<(EntityUid? Entity, IShootable Shootable)> ammo, EntityUid user)
-    {
-        return false;
-    }
-
     /// <summary>
     /// Attempts to shoot at the target coordinates. Resets the shot counter after every shot.
     /// </summary>
     public void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun, EntityCoordinates toCoordinates)
     {
         gun.ShootCoordinates = toCoordinates;
-        AttemptShootInternal(user, gunUid, gun);
+        AttemptShoot(user, gunUid, gun);
         gun.ShotCounter = 0;
     }
 
@@ -250,35 +224,20 @@ public abstract partial class SharedGunSystem : EntitySystem
     {
         var coordinates = new EntityCoordinates(gunUid, new Vector2(0, -1));
         gun.ShootCoordinates = coordinates;
-        AttemptShootInternal(gunUid, gunUid, gun);
+        AttemptShoot(gunUid, gunUid, gun);
         gun.ShotCounter = 0;
     }
 
-    private void AttemptShootInternal(EntityUid user, EntityUid gunUid, GunComponent gun)
+    private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun)
     {
-        if (!TryTakeAmmo(user, gunUid, gun, out var fromCoordinates, out var toCoordinates, out var args))
+        if (gun.FireRateModified <= 0f ||
+            !_actionBlockerSystem.CanAttack(user))
             return;
 
-        Shoot(gunUid, gun, args.Ammo, fromCoordinates, toCoordinates, out var userImpulse, user: user);
-
-        if (userImpulse && TryComp<PhysicsComponent>(user, out var userPhysics))
-        {
-            if (_gravity.IsWeightless(user, userPhysics))
-                CauseImpulse(fromCoordinates, toCoordinates, user, userPhysics);
-        }
-    }
+        var toCoordinates = gun.ShootCoordinates;
 
-    /// <summary>
-    /// Validates if a gun can currently shoot.
-    /// </summary>
-    [Pure]
-    private bool CanShoot(EntityUid user, EntityUid gunUid, GunComponent gun)
-    {
-        if (gun.FireRateModified <= 0f ||
-            !_actionBlockerSystem.CanAttack(user))
-        {
-            return false;
-        }
+        if (toCoordinates == null)
+            return;
 
         var curTime = Timing.CurTime;
 
@@ -290,42 +249,17 @@ public abstract partial class SharedGunSystem : EntitySystem
         };
         RaiseLocalEvent(gunUid, ref prevention);
         if (prevention.Cancelled)
-            return false;
+            return;
 
         RaiseLocalEvent(user, ref prevention);
         if (prevention.Cancelled)
-            return false;
+            return;
 
         // Need to do this to play the clicking sound for empty automatic weapons
         // but not play anything for burst fire.
         if (gun.NextFire > curTime)
-            return false;
-
-        return true;
-    }
-
-    /// <summary>
-    /// Tries to return ammo prepped for shooting if a gun is available to shoot.
-    /// </summary>
-    private bool TryTakeAmmo(
-        EntityUid user,
-        EntityUid gunUid, GunComponent gun,
-        out EntityCoordinates fromCoordinates,
-        out EntityCoordinates toCoordinates,
-        [NotNullWhen(true)] out TakeAmmoEvent? args)
-    {
-        toCoordinates = EntityCoordinates.Invalid;
-        fromCoordinates = EntityCoordinates.Invalid;
-        args = null;
-
-        if (!CanShoot(user, gunUid, gun))
-            return false;
-
-        if (gun.ShootCoordinates == null)
-            return false;
+            return;
 
-        toCoordinates = gun.ShootCoordinates.Value;
-        var curTime = Timing.CurTime;
         var fireRate = TimeSpan.FromSeconds(1f / gun.FireRateModified);
 
         // First shot
@@ -373,11 +307,10 @@ public abstract partial class SharedGunSystem : EntitySystem
             }
 
             gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
-            return false;
+            return;
         }
 
-        fromCoordinates = Transform(user).Coordinates;
-
+        var fromCoordinates = Transform(user).Coordinates;
         // Remove ammo
         var ev = new TakeAmmoEvent(shots, new List<(EntityUid? Entity, IShootable Shootable)>(), fromCoordinates, user);
 
@@ -412,18 +345,24 @@ public abstract partial class SharedGunSystem : EntitySystem
                 // May cause prediction issues? Needs more tweaking
                 gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
                 Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
-                return false;
+                return;
             }
 
-            return false;
+            return;
         }
 
         // Shoot confirmed - sounds also played here in case it's invalid (e.g. cartridge already spent).
+        Shoot(gunUid, gun, ev.Ammo, fromCoordinates, toCoordinates.Value, out var userImpulse, user, throwItems: attemptEv.ThrowItems);
         var shotEv = new GunShotEvent(user, ev.Ammo);
         RaiseLocalEvent(gunUid, ref shotEv);
 
-        args = ev;
-        return true;
+        if (userImpulse && TryComp<PhysicsComponent>(user, out var userPhysics))
+        {
+            if (_gravity.IsWeightless(user, userPhysics))
+                CauseImpulse(fromCoordinates, toCoordinates.Value, user, userPhysics);
+        }
+
+        Dirty(gunUid, gun);
     }
 
     public void Shoot(
diff --git a/Resources/Locale/en-US/execution/execution.ftl b/Resources/Locale/en-US/execution/execution.ftl
deleted file mode 100644 (file)
index 5bd4613..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-execution-verb-name = Execute
-execution-verb-message = Use your weapon to execute someone.
-
-# All the below localisation strings have access to the following variables
-# attacker (the person committing the execution)
-# victim (the person being executed)
-# weapon (the weapon used for the execution)
-
-execution-popup-gun-initial-internal = You ready the muzzle of {THE($weapon)} against {$victim}'s head.
-execution-popup-gun-initial-external = {$attacker} readies the muzzle of {THE($weapon)} against {$victim}'s head.
-execution-popup-gun-complete-internal = You blast {$victim} in the head!
-execution-popup-gun-complete-external = {$attacker} blasts {$victim} in the head!
-execution-popup-gun-clumsy-internal = You miss {$victim}'s head and shoot your foot instead!
-execution-popup-gun-clumsy-external = {$attacker} misses {$victim} and shoots {POSS-ADJ($attacker)} foot instead!
-execution-popup-gun-empty = {CAPITALIZE(THE($weapon))} clicks.
-
-execution-popup-melee-initial-internal = You ready {THE($weapon)} against {$victim}'s throat.
-execution-popup-melee-initial-external = {$attacker} readies {POSS-ADJ($attacker)} {$weapon} against the throat of {$victim}.
-execution-popup-melee-complete-internal = You slit the throat of {$victim}!
-execution-popup-melee-complete-external = {$attacker} slits the throat of {$victim}!
index 4a83cd455d7d1cffc3b395df0576e7fc25786d14..ff28cc44db66b845158927aafbb5300b74f17346 100644 (file)
@@ -1,4 +1,4 @@
-butcherable-different-tool = You need a different tool to butcher { THE($target) }.
+butcherable-different-tool = You are going to need a different tool to butcher { THE($target) }.
 butcherable-knife-butchered-success = You butcher { THE($target) } with { THE($knife) }.
 butcherable-need-knife = Use a sharp object to butcher { THE($target) }.
 butcherable-not-in-container = { CAPITALIZE(THE($target)) } can't be in a container.
index a86965f96f20010a85f152fcee6671da8370b445..62468b46150f9c3a14b5c4cb43cccabf808005e6 100644 (file)
@@ -6,8 +6,6 @@
   description:  A small piece of crystal.
   components:
   - type: Sharp
-  - type: Execution
-    doAfterDuration: 4.0
   - type: Sprite
     layers:
       - sprite: Objects/Materials/Shards/crystal.rsi
index 22d5cdefe4504e1560d46d6b9cedb6453e2583a2..fa57f90c18f7d0e7f0f56ddfd552f210e400cc08 100644 (file)
@@ -5,8 +5,6 @@
   description: It's a shard of some unknown material.
   components:
   - type: Sharp
-  - type: Execution
-    doAfterDuration: 4.0
   - type: Sprite
     layers:
       - sprite: Objects/Materials/Shards/shard.rsi
index 98bc92968b2022be709c496feb8712d27a78960d..b7c73f5e0cc84acdf30738eac5561c7d3425e6c6 100644 (file)
@@ -5,8 +5,6 @@
   description: In Space Glasgow this is called a conversation starter.
   components:
   - type: Sharp
-  - type: Execution
-    doAfterDuration: 4.0
   - type: MeleeWeapon
     attackRate: 1.5
     damage:
index 236ed2068137104289c04159b53fef4da1b61890..9d685e1ddc0e0c31b816841067f9963b430ed2bd 100644 (file)
@@ -19,7 +19,6 @@
       path: /Audio/Weapons/Guns/Empty/lmg_empty.ogg
   - type: StaticPrice
     price: 500
-  - type: Execution
   # No chamber because HMG may want its own
 
 - type: entity
index 499a950e785eb3d769bed245c448af7897ddfeb3..49b2eeaada1370f9d0d539176a9e6de4abfdfbc9 100644 (file)
@@ -60,7 +60,6 @@
     price: 500
   - type: UseDelay
     delay: 1
-  - type: Execution
 
 - type: entity
   name: L6 SAW
index 80de02c6dadae54afdd54098bf7a1face10b2059..8b31bf40ed700eddb3501b157fa2a2ee3cbd3dac 100644 (file)
@@ -19,7 +19,6 @@
     containers:
       ballistic-ammo: !type:Container
         ents: []
-  - type: Execution
 
 - type: entity
   name: china lake
index 2b2c6fe95551987bb0842a860075e1f52d4ccf76..9507eada3bd796226899fd91520d203f2180a2d9 100644 (file)
@@ -65,7 +65,6 @@
   - type: Appearance
   - type: StaticPrice
     price: 500
-  - type: Execution
 
 - type: entity
   name: viper
   name: N1984
   parent: BaseWeaponPistol
   id: WeaponPistolN1984 # the spaces in description are for formatting.
-  description: The sidearm of any self respecting officer.     Comes in .45 magnum, the lord's caliber.
+  description: The sidearm of any self respecting officer.     Comes in .45 magnum, the lord's caliber. 
   components:
   - type: Sprite
     sprite: Objects/Weapons/Guns/Pistols/N1984.rsi
index 93e8b1a6690ee4b3ea12916ddda778ddf74d46f7..5bc8125ebaa9accf3c2f26310e054c870d92f163 100644 (file)
@@ -49,7 +49,6 @@
       gun_chamber: !type:ContainerSlot
   - type: StaticPrice
     price: 500
-  - type: Execution
 
 - type: entity
   name: AKMS
index ea82be46bc6b67407ab8a4b157928c906a29af86..b693bdba370a3e3d0f057af82a5c1cdd72cbc36b 100644 (file)
@@ -54,7 +54,6 @@
       gun_chamber: !type:ContainerSlot
   - type: StaticPrice
     price: 500
-  - type: Execution
 
 - type: entity
   name: Atreides
index 70ed96876e8e3d04cf77ff9372fb58d5e825cab5..f43df5f37cb040149a19f7e68d6485b3a3f6e5d1 100644 (file)
@@ -42,7 +42,6 @@
         ents: []
   - type: StaticPrice
     price: 500
-  - type: Execution
 
 - type: entity
   name: Bulldog
@@ -99,7 +98,6 @@
   - type: Appearance
   - type: StaticPrice
     price: 500
-  - type: Execution
 
 - type: entity
   name: double-barreled shotgun
index 6640e98f5f48f164c302bc0b18a474916942d3c8..753f109a174cdd71e2cf1e3a23d1852ca84ab3f0 100644 (file)
@@ -36,7 +36,6 @@
         ents: []
   - type: StaticPrice
     price: 500
-  - type: Execution
 
 - type: entity
   name: Kardashev-Mosin
index 2a07fd4fe0213afc60b226d4b39765272d8dbb0f..cfcc0a01cd1f26d486af1c3a1e6287a723e3b296 100644 (file)
@@ -36,4 +36,3 @@
     quickEquip: false
     slots:
     - Belt
-  - type: Execution
index add776422dbf811ed915b22f7c786a50d1192d80..ae1f5df3c154f84a81c770b686fa630f52f3e587 100644 (file)
     containers:
       storagebase: !type:Container
         ents: []
-  - type: Execution
 
 # shoots bullets instead of throwing them, no other changes
 - type: entity
index 267e3a7891fa87759544483feadd34b6920e9aa3..497876f3596824d69ca55031af5d4144792f0fd6 100644 (file)
@@ -5,8 +5,6 @@
   description: A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter.\r
   components:\r
   - type: Sharp\r
-  - type: Execution\r
-    doAfterDuration: 4.0\r
   - type: Sprite\r
     sprite: Objects/Weapons/Melee/armblade.rsi\r
     state: icon\r
index aadb9942448c673bf8b505b3ef640f4109b529d9..b46ee096336039820b600a998bcd1c770b6eb33e 100644 (file)
@@ -8,8 +8,6 @@
     tags:
     - FireAxe
   - type: Sharp
-  - type: Execution
-    doAfterDuration: 4.0
   - type: Sprite
     sprite: Objects/Weapons/Melee/fireaxe.rsi
     state: icon
index 432da5efe952d2a2943f11ee1bfdface6c06e927..106e8bf4400e241ead2f4c6918eb4e3f9fc14e07 100644 (file)
@@ -7,8 +7,6 @@
     tags:
     - Knife
   - type: Sharp
-  - type: Execution
-    doAfterDuration: 4.0
   - type: Utensil
     types:
       - Knife
index d27c6c68831f7a329b57942b4d7be50ab42c485e..05cac3ae7b7ce319e42b2cc5e2afc6ada3075bf5 100644 (file)
@@ -1,21 +1,10 @@
-- type: entity
-  name: Sword
-  parent: BaseItem
-  id: BaseSword
-  description: A sharp sword.
-  abstract: true
-  components:
-    - type: Sharp
-    - type: Execution
-      doAfterDuration: 4.0
-    - type: DisarmMalus
-
 - type: entity
   name: captain's sabre
-  parent: BaseSword
+  parent: BaseItem
   id: CaptainSabre
   description: A ceremonial weapon belonging to the captain of the station.
   components:
+  - type: Sharp
   - type: Sprite
     sprite: Objects/Weapons/Melee/captain_sabre.rsi
     state: icon
   - type: Tag
     tags:
     - CaptainSabre
+  - type: DisarmMalus
 
 - type: entity
   name: katana
-  parent: BaseSword
+  parent: BaseItem
   id: Katana
   description: Ancient craftwork made with not so ancient plasteel.
   components:
+  - type: Sharp
   - type: Tag
     tags:
     - Katana
@@ -60,6 +51,7 @@
   - type: Item
     size: Normal
     sprite: Objects/Weapons/Melee/katana.rsi
+  - type: DisarmMalus
 
 - type: entity
   name: energy katana
 
 - type: entity
   name: machete
-  parent: BaseSword
+  parent: BaseItem
   id: Machete
   description: A large, vicious looking blade.
   components:
+  - type: Sharp
   - type: Tag
     tags:
     - Machete
   - type: Item
     size: Normal
     sprite: Objects/Weapons/Melee/machete.rsi
+  - type: DisarmMalus
 
 - type: entity
   name: claymore
-  parent: BaseSword
+  parent: BaseItem
   id: Claymore
   description: An ancient war blade.
   components:
+  - type: Sharp
   - type: Sprite
     sprite: Objects/Weapons/Melee/claymore.rsi
     state: icon
     sprite: Objects/Weapons/Melee/claymore.rsi
     slots:
     - back
+  - type: DisarmMalus
 
 - type: entity
   name: cutlass
-  parent: BaseSword
+  parent: BaseItem
   id: Cutlass
   description: A wickedly curved blade, often seen in the hands of space pirates.
   components:
+  - type: Sharp
   - type: Tag
     tags:
     - Machete
   - type: Item
     size: Normal
     sprite: Objects/Weapons/Melee/cutlass.rsi
+  - type: DisarmMalus
 
 - type: entity
   name: The Throngler
-  parent: BaseSword
+  parent: BaseItem
   id: Throngler
   description: Why would you make this?
   components:
+    - type: Sharp
     - type: Sprite
       sprite: Objects/Weapons/Melee/Throngler2.rsi
       state: icon
     - type: Item
       size: Ginormous
       sprite: Objects/Weapons/Melee/Throngler-in-hand.rsi
+    - type: DisarmMalus