]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Hristov & .60 changes - Hristov Rework, Part 2 (#31662)
authorSlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Tue, 4 Feb 2025 21:55:09 +0000 (22:55 +0100)
committerGitHub <noreply@github.com>
Tue, 4 Feb 2025 21:55:09 +0000 (22:55 +0100)
* Initial commit

* Updated values to reflect new resistances

* Review fixes

* Review fixes

* LINQ BEGONETH

Content.Server/Projectiles/ProjectileSystem.cs
Content.Shared/Movement/Components/SpeedModifiedOnWieldComponent.cs [new file with mode: 0644]
Content.Shared/Projectiles/ProjectileComponent.cs
Content.Shared/Projectiles/SharedProjectileSystem.cs
Content.Shared/Wieldable/SharedWieldableSystem.cs
Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/antimateriel.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml

index 5cbc56b8fbc75bfe7f59ab4424c98a3683fef1d7..57601c3e9f25f2189e88f253efa6479350056e06 100644 (file)
@@ -1,9 +1,11 @@
 using Content.Server.Administration.Logs;
+using Content.Server.Destructible;
 using Content.Server.Effects;
 using Content.Server.Weapons.Ranged.Systems;
 using Content.Shared.Camera;
 using Content.Shared.Damage;
 using Content.Shared.Database;
+using Content.Shared.FixedPoint;
 using Content.Shared.Projectiles;
 using Robust.Shared.Physics.Events;
 using Robust.Shared.Player;
@@ -15,6 +17,7 @@ public sealed class ProjectileSystem : SharedProjectileSystem
     [Dependency] private readonly IAdminLogManager _adminLogger = default!;
     [Dependency] private readonly ColorFlashEffectSystem _color = default!;
     [Dependency] private readonly DamageableSystem _damageableSystem = default!;
+    [Dependency] private readonly DestructibleSystem _destructibleSystem = default!;
     [Dependency] private readonly GunSystem _guns = default!;
     [Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!;
 
@@ -28,7 +31,7 @@ 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.ProjectileSpent || component is { Weapon: null, OnlyCollideWhenShot: true })
             return;
 
         var target = args.OtherEntity;
@@ -45,7 +48,13 @@ public sealed class ProjectileSystem : SharedProjectileSystem
         RaiseLocalEvent(uid, ref ev);
 
         var otherName = ToPrettyString(target);
-        var modifiedDamage = _damageableSystem.TryChangeDamage(target, ev.Damage, component.IgnoreResistances, origin: component.Shooter);
+        var damageRequired = _destructibleSystem.DestroyedAt(target);
+        if (TryComp<DamageableComponent>(target, out var damageableComponent))
+        {
+            damageRequired -= damageableComponent.TotalDamage;
+            damageRequired = FixedPoint2.Max(damageRequired, FixedPoint2.Zero);
+        }
+        var modifiedDamage = _damageableSystem.TryChangeDamage(target, ev.Damage, component.IgnoreResistances, damageable: damageableComponent, origin: component.Shooter);
         var deleted = Deleted(target);
 
         if (modifiedDamage is not null && EntityManager.EntityExists(component.Shooter))
@@ -60,6 +69,46 @@ public sealed class ProjectileSystem : SharedProjectileSystem
                 $"Projectile {ToPrettyString(uid):projectile} shot by {ToPrettyString(component.Shooter!.Value):user} hit {otherName:target} and dealt {modifiedDamage.GetTotal():damage} damage");
         }
 
+        // If penetration is to be considered, we need to do some checks to see if the projectile should stop.
+        if (modifiedDamage is not null && component.PenetrationThreshold != 0)
+        {
+            // If a damage type is required, stop the bullet if the hit entity doesn't have that type.
+            if (component.PenetrationDamageTypeRequirement != null)
+            {
+                var stopPenetration = false;
+                foreach (var requiredDamageType in component.PenetrationDamageTypeRequirement)
+                {
+                    if (!modifiedDamage.DamageDict.Keys.Contains(requiredDamageType))
+                    {
+                        stopPenetration = true;
+                        break;
+                    }
+                }
+                if (stopPenetration)
+                    component.ProjectileSpent = true;
+            }
+
+            // If the object won't be destroyed, it "tanks" the penetration hit.
+            if (modifiedDamage.GetTotal() < damageRequired)
+            {
+                component.ProjectileSpent = true;
+            }
+
+            if (!component.ProjectileSpent)
+            {
+                component.PenetrationAmount += damageRequired;
+                // The projectile has dealt enough damage to be spent.
+                if (component.PenetrationAmount >= component.PenetrationThreshold)
+                {
+                    component.ProjectileSpent = true;
+                }
+            }
+        }
+        else
+        {
+            component.ProjectileSpent = true;
+        }
+
         if (!deleted)
         {
             _guns.PlayImpactSound(target, modifiedDamage, component.SoundHit, component.ForceSound);
@@ -68,9 +117,7 @@ public sealed class ProjectileSystem : SharedProjectileSystem
                 _sharedCameraRecoil.KickCamera(target, args.OurBody.LinearVelocity.Normalized());
         }
 
-        component.DamagedEntity = true;
-
-        if (component.DeleteOnCollide)
+        if (component.DeleteOnCollide && component.ProjectileSpent)
             QueueDel(uid);
 
         if (component.ImpactEffect != null && TryComp(uid, out TransformComponent? xform))
diff --git a/Content.Shared/Movement/Components/SpeedModifiedOnWieldComponent.cs b/Content.Shared/Movement/Components/SpeedModifiedOnWieldComponent.cs
new file mode 100644 (file)
index 0000000..01b02e6
--- /dev/null
@@ -0,0 +1,23 @@
+using Content.Shared.Wieldable;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Movement.Components;
+
+/// <summary>
+/// Modifies the speed when an entity with this component is wielded.
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedWieldableSystem)), AutoGenerateComponentState]
+public sealed partial class SpeedModifiedOnWieldComponent : Component
+{
+    /// <summary>
+    /// How much the wielder's sprint speed is modified when the component owner is wielded.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public float SprintModifier = 1f;
+
+    /// <summary>
+    /// How much the wielder's walk speed is modified when the component owner is wielded.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public float WalkModifier = 1f;
+}
index 8349252df2b71844c1d11265b503deb6d3cafa0d..9eee3767a6dad3d26067d81c6a18f1e0a66c4984 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Shared.Damage;
+using Content.Shared.FixedPoint;
 using Robust.Shared.Audio;
 using Robust.Shared.GameStates;
 using Robust.Shared.Prototypes;
@@ -75,8 +76,26 @@ public sealed partial class ProjectileComponent : Component
     public bool OnlyCollideWhenShot = false;
 
     /// <summary>
-    ///     Whether this projectile has already damaged an entity.
+    ///     If true, the projectile has hit enough targets and should no longer interact with further collisions pending deletion.
     /// </summary>
     [DataField]
-    public bool DamagedEntity;
+    public bool ProjectileSpent;
+
+    /// <summary>
+    ///     When a projectile has this threshold set, it will continue to penetrate entities until the damage dealt reaches this threshold.
+    /// </summary>
+    [DataField]
+    public FixedPoint2 PenetrationThreshold = FixedPoint2.Zero;
+
+    /// <summary>
+    ///     If set, the projectile will not penetrate objects that lack the ability to take these damage types.
+    /// </summary>
+    [DataField]
+    public List<string>? PenetrationDamageTypeRequirement;
+
+    /// <summary>
+    ///     Tracks the amount of damage dealt for penetration purposes.
+    /// </summary>
+    [DataField]
+    public FixedPoint2 PenetrationAmount = FixedPoint2.Zero;
 }
index 85e75d6d2913243383c632e69a499c53bbb6f69a..bca9b36f8985a6eb2f5e5329d79514018a9a147e 100644 (file)
@@ -79,7 +79,7 @@ public abstract partial class SharedProjectileSystem : EntitySystem
         {
             projectile.Shooter = null;
             projectile.Weapon = null;
-            projectile.DamagedEntity = false;
+            projectile.ProjectileSpent = false;
         }
 
         // Land it just coz uhhh yeah
index 24c63c5f2f1370c2eab7d16750f90a80d1193cf4..110c941dac73a030ff00f8040ef5a15ea3ecb3b2 100644 (file)
@@ -9,6 +9,7 @@ using Content.Shared.Interaction.Events;
 using Content.Shared.Inventory.VirtualItem;
 using Content.Shared.Item;
 using Content.Shared.Movement.Components;
+using Content.Shared.Movement.Systems;
 using Content.Shared.Popups;
 using Content.Shared.Timing;
 using Content.Shared.Verbs;
@@ -27,6 +28,7 @@ namespace Content.Shared.Wieldable;
 
 public abstract class SharedWieldableSystem : EntitySystem
 {
+    [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
     [Dependency] private readonly IGameTiming _timing = default!;
     [Dependency] private readonly INetManager _netManager = default!;
     [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
@@ -56,6 +58,9 @@ public abstract class SharedWieldableSystem : EntitySystem
         SubscribeLocalEvent<GunWieldBonusComponent, ItemUnwieldedEvent>(OnGunUnwielded);
         SubscribeLocalEvent<GunWieldBonusComponent, GunRefreshModifiersEvent>(OnGunRefreshModifiers);
         SubscribeLocalEvent<GunWieldBonusComponent, ExaminedEvent>(OnExamine);
+        SubscribeLocalEvent<SpeedModifiedOnWieldComponent, ItemWieldedEvent>(OnSpeedModifierWielded);
+        SubscribeLocalEvent<SpeedModifiedOnWieldComponent, ItemUnwieldedEvent>(OnSpeedModifierUnwielded);
+        SubscribeLocalEvent<SpeedModifiedOnWieldComponent, HeldRelayedEvent<RefreshMovementSpeedModifiersEvent>>(OnRefreshSpeedWielded);
 
         SubscribeLocalEvent<IncreaseDamageOnWieldComponent, GetMeleeDamageEvent>(OnGetMeleeDamage);
     }
@@ -119,9 +124,29 @@ public abstract class SharedWieldableSystem : EntitySystem
         }
     }
 
+    private void OnSpeedModifierWielded(EntityUid uid, SpeedModifiedOnWieldComponent component, ItemWieldedEvent args)
+    {
+        if (args.User != null)
+            _movementSpeedModifier.RefreshMovementSpeedModifiers(args.User);
+    }
+
+    private void OnSpeedModifierUnwielded(EntityUid uid, SpeedModifiedOnWieldComponent component, ItemUnwieldedEvent args)
+    {
+        if (args.User != null)
+            _movementSpeedModifier.RefreshMovementSpeedModifiers(args.User);
+    }
+
+    private void OnRefreshSpeedWielded(EntityUid uid, SpeedModifiedOnWieldComponent component, ref HeldRelayedEvent<RefreshMovementSpeedModifiersEvent> args)
+    {
+        if (TryComp<WieldableComponent>(uid, out var wield) && wield.Wielded)
+        {
+            args.Args.ModifySpeed(component.WalkModifier, component.SprintModifier);
+        }
+    }
+
     private void OnExamineRequires(Entity<GunRequiresWieldComponent> entity, ref ExaminedEvent args)
     {
-        if(entity.Comp.WieldRequiresExamineMessage != null)
+        if (entity.Comp.WieldRequiresExamineMessage != null)
             args.PushText(Loc.GetString(entity.Comp.WieldRequiresExamineMessage));
     }
 
index 65b7dbc165592b1582a2f19f181a7b638e5a6b6a..7556f2c371cf0ff84fe2e8e0a73df7bb4cc859c8 100644 (file)
@@ -7,7 +7,10 @@
   - type: Projectile
     damage:
       types:
-        Piercing: 40
-        Structural: 30
+        Piercing: 75
+        Structural: 226
+    penetrationThreshold: 360
+    penetrationDamageTypeRequirement:
+    - Structural
   - type: StaminaDamageOnCollide
-    damage: 35
+    damage: 60
index cca3a6f30215ce16732a94f38a6b74991f0bb129..23dc96c49ffc981b962dfb64cfb2b3cad8287e8a 100644 (file)
     sprite: Objects/Weapons/Guns/Snipers/heavy_sniper.rsi
   - type: Clothing
     sprite: Objects/Weapons/Guns/Snipers/heavy_sniper.rsi
+  - type: GunRequiresWield
+  - type: Gun
+    fireRate: 0.4
+    selectedMode: SemiAuto
+    availableModes:
+    - SemiAuto
+    soundGunshot:
+      path: /Audio/Weapons/Guns/Gunshots/sniper.ogg
   - type: BallisticAmmoProvider
     whitelist:
       tags:
       - CartridgeAntiMateriel
     capacity: 5
     proto: CartridgeAntiMateriel
+  - type: SpeedModifiedOnWield
+    walkModifier: 0.25
+    sprintModifier: 0.25
   - type: CursorOffsetRequiresWield
   - type: EyeCursorOffset
     maxOffset: 3