]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Syringe gun! (#32112)
authorScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Tue, 22 Oct 2024 13:03:42 +0000 (15:03 +0200)
committerGitHub <noreply@github.com>
Tue, 22 Oct 2024 13:03:42 +0000 (00:03 +1100)
* Init testing

* copyright

* oops

* Tracking the embed entity uid

* testing stuff for gradual injection

* work

* weh

* god save me

* bleh

* Yippee!

* Again

* Mini syringe ammo

* cleaning up

* mini syringes have a texture for fill amount

* -3 cool points :(

* hitboxes

* init cleanup

* much needed fixes

* Fixes

20 files changed:
Content.Server/Chemistry/Components/SolutionInjectWhileEmbeddedComponent.cs [new file with mode: 0644]
Content.Server/Chemistry/EntitySystems/SolutionInjectOnEventSystem.cs
Content.Server/Chemistry/EntitySystems/SolutionInjectWhileEmbeddedSystem.cs [new file with mode: 0644]
Content.Shared/Chemistry/InjectOverTimeEvent.cs [new file with mode: 0644]
Content.Shared/Projectiles/EmbeddableProjectileComponent.cs
Content.Shared/Projectiles/SharedProjectileSystem.cs
Resources/Audio/Weapons/Guns/Gunshots/attributions.yml
Resources/Audio/Weapons/Guns/Gunshots/syringe_gun.ogg [new file with mode: 0644]
Resources/Prototypes/Entities/Objects/Specific/chemistry.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml
Resources/Prototypes/tags.yml
Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/meta.json
Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe1.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe2.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe3.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringeproj.png
Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/inhand-left.png [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/inhand-right.png [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/meta.json [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/syringe_gun.png [new file with mode: 0644]

diff --git a/Content.Server/Chemistry/Components/SolutionInjectWhileEmbeddedComponent.cs b/Content.Server/Chemistry/Components/SolutionInjectWhileEmbeddedComponent.cs
new file mode 100644 (file)
index 0000000..0f10e2a
--- /dev/null
@@ -0,0 +1,24 @@
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+
+namespace Content.Server.Chemistry.Components;
+
+/// <summary>
+/// Used for embeddable entities that should try to inject a
+/// contained solution into a target over time while they are embbeded into.
+/// </summary>
+[RegisterComponent, AutoGenerateComponentPause]
+public sealed partial class SolutionInjectWhileEmbeddedComponent : BaseSolutionInjectOnEventComponent {
+        ///<summary>
+        ///The time at which the injection will happen.
+        ///</summary>
+        [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
+        public TimeSpan NextUpdate;
+        
+        ///<summary>
+        ///The delay between each injection in seconds.
+        ///</summary>
+        [DataField]
+        public TimeSpan UpdateInterval = TimeSpan.FromSeconds(3);
+}
+
index d56fded024a31fb9bfb5af8099453b9ed7484064..f15edcf0672000fb35026eecdf00ce7c26e1cb84 100644 (file)
@@ -2,6 +2,7 @@ using Content.Server.Body.Components;
 using Content.Server.Body.Systems;
 using Content.Server.Chemistry.Components;
 using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Chemistry.Events;
 using Content.Shared.Inventory;
 using Content.Shared.Popups;
 using Content.Shared.Projectiles;
@@ -29,6 +30,7 @@ public sealed class SolutionInjectOnCollideSystem : EntitySystem
         SubscribeLocalEvent<SolutionInjectOnProjectileHitComponent, ProjectileHitEvent>(HandleProjectileHit);
         SubscribeLocalEvent<SolutionInjectOnEmbedComponent, EmbedEvent>(HandleEmbed);
         SubscribeLocalEvent<MeleeChemicalInjectorComponent, MeleeHitEvent>(HandleMeleeHit);
+        SubscribeLocalEvent<SolutionInjectWhileEmbeddedComponent, InjectOverTimeEvent>(OnInjectOverTime);
     }
 
     private void HandleProjectileHit(Entity<SolutionInjectOnProjectileHitComponent> entity, ref ProjectileHitEvent args)
@@ -49,6 +51,11 @@ public sealed class SolutionInjectOnCollideSystem : EntitySystem
             TryInjectTargets((entity.Owner, entity.Comp), args.HitEntities, args.User);
     }
 
+    private void OnInjectOverTime(Entity<SolutionInjectWhileEmbeddedComponent> entity, ref InjectOverTimeEvent args)
+    {
+        DoInjection((entity.Owner, entity.Comp), args.EmbeddedIntoUid);
+    }
+
     private void DoInjection(Entity<BaseSolutionInjectOnEventComponent> injectorEntity, EntityUid target, EntityUid? source = null)
     {
         TryInjectTargets(injectorEntity, [target], source);
diff --git a/Content.Server/Chemistry/EntitySystems/SolutionInjectWhileEmbeddedSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionInjectWhileEmbeddedSystem.cs
new file mode 100644 (file)
index 0000000..2baeba9
--- /dev/null
@@ -0,0 +1,60 @@
+using Content.Server.Body.Components;
+using Content.Server.Body.Systems;
+using Content.Server.Chemistry.Components;
+using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Chemistry.Events;
+using Content.Shared.Inventory;
+using Content.Shared.Popups;
+using Content.Shared.Projectiles;
+using Content.Shared.Tag;
+using Content.Shared.Weapons.Melee.Events;
+using Robust.Shared.Collections;
+using Robust.Shared.Timing;
+
+namespace Content.Server.Chemistry.EntitySystems;
+
+/// <summary>
+/// System for handling injecting into an entity while a projectile is embedded.
+/// </summary>
+public sealed class SolutionInjectWhileEmbeddedSystem : EntitySystem
+{
+       [Dependency] private readonly IGameTiming _gameTiming = default!;
+    [Dependency] private readonly BloodstreamSystem _bloodstream = default!;
+    [Dependency] private readonly InventorySystem _inventory = default!;
+    [Dependency] private readonly SharedPopupSystem _popup = default!;
+    [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
+    [Dependency] private readonly TagSystem _tag = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        
+        SubscribeLocalEvent<SolutionInjectWhileEmbeddedComponent, MapInitEvent>(OnMapInit);
+    }
+
+    private void OnMapInit(Entity<SolutionInjectWhileEmbeddedComponent> ent, ref MapInitEvent args)
+    {
+        ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
+    }
+
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
+
+        var query = EntityQueryEnumerator<SolutionInjectWhileEmbeddedComponent, EmbeddableProjectileComponent>();
+        while (query.MoveNext(out var uid, out var injectComponent, out var projectileComponent))
+        {
+            if (_gameTiming.CurTime < injectComponent.NextUpdate)
+                continue;
+
+            injectComponent.NextUpdate += injectComponent.UpdateInterval;
+
+            if(projectileComponent.EmbeddedIntoUid == null)
+                continue;
+
+            var ev = new InjectOverTimeEvent(projectileComponent.EmbeddedIntoUid.Value);
+            RaiseLocalEvent(uid, ref ev);
+
+        }
+    }
+}
diff --git a/Content.Shared/Chemistry/InjectOverTimeEvent.cs b/Content.Shared/Chemistry/InjectOverTimeEvent.cs
new file mode 100644 (file)
index 0000000..ca5ab42
--- /dev/null
@@ -0,0 +1,13 @@
+namespace Content.Shared.Chemistry.Events;
+
+/// <summary>
+/// Raised directed on an entity when it embeds in another entity.
+/// </summary>
+[ByRefEvent]
+public readonly record struct InjectOverTimeEvent(EntityUid embeddedIntoUid)
+{
+    /// <summary>
+    /// Entity that is embedded in.
+    /// </summary>
+    public readonly EntityUid EmbeddedIntoUid = embeddedIntoUid;
+}
index 008b7c2ced4d25b35a6a6cdcb6c81ab213ed561d..e4125945d26d235e4bccda223897016906e173e3 100644 (file)
@@ -13,37 +13,43 @@ public sealed partial class EmbeddableProjectileComponent : Component
     /// <summary>
     /// Minimum speed of the projectile to embed.
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public float MinimumSpeed = 5f;
 
     /// <summary>
     /// Delete the entity on embedded removal?
     /// Does nothing if there's no RemovalTime.
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public bool DeleteOnRemove;
 
     /// <summary>
     /// How long it takes to remove the embedded object.
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public float? RemovalTime = 3f;
 
     /// <summary>
     ///     Whether this entity will embed when thrown, or only when shot as a projectile.
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public bool EmbedOnThrow = true;
 
     /// <summary>
     /// How far into the entity should we offset (0 is wherever we collided).
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public Vector2 Offset = Vector2.Zero;
 
     /// <summary>
     /// Sound to play after embedding into a hit target.
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
+    [DataField, AutoNetworkedField]
     public SoundSpecifier? Sound;
+
+    /// <summary>
+    /// Uid of the entity the projectile is embed into.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public EntityUid? EmbeddedIntoUid;
 }
index 1b7d6d6f99157c6385e487bca2271910a8ba36b8..85e75d6d2913243383c632e69a499c53bbb6f69a 100644 (file)
@@ -71,6 +71,8 @@ public abstract partial class SharedProjectileSystem : EntitySystem
         TryComp<PhysicsComponent>(uid, out var physics);
         _physics.SetBodyType(uid, BodyType.Dynamic, body: physics, xform: xform);
         _transform.AttachToGridOrMap(uid, xform);
+        component.EmbeddedIntoUid = null;
+        Dirty(uid, component);
 
         // Reset whether the projectile has damaged anything if it successfully was removed
         if (TryComp<ProjectileComponent>(uid, out var projectile))
@@ -127,8 +129,10 @@ public abstract partial class SharedProjectileSystem : EntitySystem
         }
 
         _audio.PlayPredicted(component.Sound, uid, null);
+        component.EmbeddedIntoUid = target;
         var ev = new EmbedEvent(user, target);
         RaiseLocalEvent(uid, ref ev);
+        Dirty(uid, component);
     }
 
     private void PreventCollision(EntityUid uid, ProjectileComponent component, ref PreventCollideEvent args)
index 7c46974818a94f7661e3072c33a0710e3f1e4e18..89db045c96da7c943e9fd5a6c1bc9a73ad9ff0d6 100644 (file)
@@ -26,4 +26,9 @@
 - files: ["ship_duster.ogg", "ship_friendship.ogg", "ship_svalinn.ogg", "ship_perforator.ogg"]
   license: "CC0-1.0"
   copyright: "Created by MIXnikita for Space Station 14"
-  source: "https://github.com/MIXnikita"
\ No newline at end of file
+  source: "https://github.com/MIXnikita"
+
+- files: ["syringe_gun.ogg"]
+  license: "CC-BY-SA-3.0"
+  copyright: "Taken from vgstation"
+  source: "https://github.com/vgstation-coders/vgstation13/commit/23303188abe6fe31b114a218a1950d7325a23730"
\ No newline at end of file
diff --git a/Resources/Audio/Weapons/Guns/Gunshots/syringe_gun.ogg b/Resources/Audio/Weapons/Guns/Gunshots/syringe_gun.ogg
new file mode 100644 (file)
index 0000000..2132808
Binary files /dev/null and b/Resources/Audio/Weapons/Guns/Gunshots/syringe_gun.ogg differ
index 0f74b4afaf96ed1ad64caf89139bba4435059c31..3f2ac403ac91b6328c4b2054cd5f5fda1e91920a 100644 (file)
     - Syringe
     - Trash
 
+- type: entity
+  name: mini syringe
+  parent: Syringe
+  description: A regular syringe, reshaped to fit inside of a gun.
+  id: MiniSyringe
+  components:
+  - type: Sprite
+    sprite: Objects/Specific/Chemistry/syringe.rsi
+    layers:
+      - state: minisyringe1
+        map: ["enum.SolutionContainerLayers.Fill"]
+        visible: false
+      - state: syringeproj
+  - type: SolutionContainerVisuals
+    maxFillLevels: 3
+    fillBaseName: minisyringe
+    inHandsMaxFillLevels: 3
+    inHandsFillBaseName: -fill-
+  - type: EmbeddableProjectile
+    offset: "-0.1,0"
+    minimumSpeed: 3
+    removalTime: 0.25
+    embedOnThrow: false
+  - type: SolutionInjectWhileEmbedded
+    transferAmount: 1
+    solution: injector
+    updateInterval: 2
+  - type: SolutionInjectOnEmbed
+    transferAmount: 2
+    solution: injector
+  - type: Fixtures
+    fixtures:
+      fix1:
+        shape: !type:PhysShapeCircle
+          radius: 0.2
+        density: 5
+        mask:
+        - ItemMask
+        restitution: 0.3
+        friction: 0.2
+      projectile:
+        shape:
+          !type:PhysShapeAabb
+          bounds: "-0.1,-0.3,0.1,0.3"
+        hard: false
+        mask:
+        - Impassable
+        - BulletImpassable
+  - type: Projectile
+    deleteOnCollide: false
+    onlyCollideWhenShot: true
+    damage:
+      types:
+        Piercing: 5
+  - type: Tag
+    tags:
+    - Syringe
+    - Trash
+    - SyringeGunAmmo
+
 - type: entity
   parent: BaseSyringe
   id: PrefilledSyringe
index 1d18c2b050096a51ca6ddb081e4a9294ff30a018..63a7acd2576e86e839df2c04654abd608922d9c0 100644 (file)
     containers:
       storagebase: !type:Container
         ents: []
+        
+- type: entity
+  name: syringe gun
+  parent: BaseStorageItem
+  id: LauncherSyringe
+  description: Load full of poisoned syringes for optimal fun.
+  components:
+  - type: Sprite
+    sprite: Objects/Weapons/Guns/Cannons/syringe_gun.rsi
+    layers:
+    - state: syringe_gun
+  - type: Storage
+    maxItemSize: Normal
+    grid:
+    - 0,0,2,0
+    whitelist:
+      tags:
+      - SyringeGunAmmo
+  - type: Gun
+    fireRate: 1
+    selectedMode: SemiAuto
+    availableModes:
+    - SemiAuto
+    - FullAuto
+    soundGunshot:
+      path: /Audio/Weapons/Guns/Gunshots/syringe_gun.ogg
+    soundEmpty:
+      path: /Audio/Weapons/Guns/Empty/empty.ogg
+    clumsyProof: true
+  - type: ContainerAmmoProvider
+    container: storagebase
+  - type: Item
+    size: Normal
+  - type: ContainerContainer
+    containers:
+      storagebase: !type:Container
+        ents: []
 
 # shoots bullets instead of throwing them, no other changes
 - type: entity
index d3ffcdcac13afae25d33206a8145f2ca39624c4d..8962da5790ceb70a5a4f9845a0ec41a66f174d35 100644 (file)
 - type: Tag
   id: Syringe
 
+- type: Tag
+  id: SyringeGunAmmo
+
 - type: Tag
   id: Spellbook
 
index 1495eccd7a64bddc608d8d1119d357d28abd1083..0c29f3e3fb1221735e52517a45bb9af65e514c3e 100644 (file)
                {
                        "name": "syringe2"
                },
+               {
+                       "name": "minisyringe1"
+               },
+               {
+                       "name": "minisyringe2"
+               },
+               {
+                       "name": "minisyringe3"
+               },
                {
                  "name": "inhand-left",
                  "directions": 4
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe1.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe1.png
new file mode 100644 (file)
index 0000000..66c49a7
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe1.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe2.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe2.png
new file mode 100644 (file)
index 0000000..6f5d566
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe2.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe3.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe3.png
new file mode 100644 (file)
index 0000000..71d3bad
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/minisyringe3.png differ
index 7819a48c6615c15c509e9d02952b74d9f8439bd8..5faf746ae3aaad62de818aab2cd36a9c0716641c 100644 (file)
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringeproj.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringeproj.png differ
diff --git a/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/inhand-left.png b/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/inhand-left.png
new file mode 100644 (file)
index 0000000..b59a4d5
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/inhand-left.png differ
diff --git a/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/inhand-right.png b/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/inhand-right.png
new file mode 100644 (file)
index 0000000..6a8268d
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/inhand-right.png differ
diff --git a/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/meta.json
new file mode 100644 (file)
index 0000000..dae584e
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "Taken from vgstation13 at https://github.com/vgstation-coders/vgstation13 at f91dfe2e0dba1b7a8b9a0fa18251340920979a62, held sprite by ScarKy0",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "inhand-right",
+      "directions": 4
+    },
+    {
+      "name": "syringe_gun"
+    },
+    {
+      "name": "inhand-left",
+      "directions": 4
+    }
+  ]
+}
\ No newline at end of file
diff --git a/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/syringe_gun.png b/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/syringe_gun.png
new file mode 100644 (file)
index 0000000..972714d
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Cannons/syringe_gun.rsi/syringe_gun.png differ