]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Spray Nozzle & Backpack Water Tank (#16133)
authorNemanja <98561806+EmoGarbage404@users.noreply.github.com>
Sat, 6 May 2023 01:50:09 +0000 (21:50 -0400)
committerGitHub <noreply@github.com>
Sat, 6 May 2023 01:50:09 +0000 (11:50 +1000)
30 files changed:
Content.Client/Weapons/Ranged/Systems/GunSystem.cs
Content.Server/Chemistry/Components/VaporComponent.cs
Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs [new file with mode: 0644]
Content.Shared/Weapons/Ranged/Components/ClothingSlotAmmoProviderComponent.cs [new file with mode: 0644]
Content.Shared/Weapons/Ranged/Components/GunComponent.cs
Content.Shared/Weapons/Ranged/Components/SolutionAmmoProviderComponent.cs [new file with mode: 0644]
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs [new file with mode: 0644]
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Solution.cs [new file with mode: 0644]
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs
Resources/Audio/Weapons/Guns/Gunshots/attributions.yml [new file with mode: 0644]
Resources/Audio/Weapons/Guns/Gunshots/water_spray.ogg [new file with mode: 0644]
Resources/Locale/en-US/prototypes/catalog/research/technologies.ftl
Resources/Prototypes/Catalog/Research/technologies.yml
Resources/Prototypes/Entities/Clothing/Back/specific.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/spraynozzle.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml
Resources/Prototypes/Entities/Structures/Machines/lathe.yml
Resources/Prototypes/Recipes/Lathes/janitorial.yml
Resources/Prototypes/tags.yml
Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/equipped-BACKPACK.png [new file with mode: 0644]
Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/icon.png [new file with mode: 0644]
Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/inhand-left.png [new file with mode: 0644]
Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/inhand-right.png [new file with mode: 0644]
Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/meta.json [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/icon.png [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/inhand-left.png [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/inhand-right.png [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/meta.json [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Projectiles/water_shot.rsi/icon.png [new file with mode: 0644]
Resources/Textures/Objects/Weapons/Guns/Projectiles/water_shot.rsi/meta.json [new file with mode: 0644]

index fce3139b62f205546994e94113bbe13f58ca5359..7d82c98469d058eba78f2a107714ebf52733db80 100644 (file)
@@ -181,7 +181,7 @@ public sealed partial class GunSystem : SharedGunSystem
         {
             if (throwItems)
             {
-                Recoil(user, direction);
+                Recoil(user, direction, gun.CameraRecoilScalar);
                 if (ent!.Value.IsClientSide())
                     Del(ent.Value);
                 else
@@ -197,7 +197,7 @@ public sealed partial class GunSystem : SharedGunSystem
                         SetCartridgeSpent(ent!.Value, cartridge, true);
                         MuzzleFlash(gunUid, cartridge, user);
                         Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
-                        Recoil(user, direction);
+                        Recoil(user, direction, gun.CameraRecoilScalar);
                         // TODO: Can't predict entity deletions.
                         //if (cartridge.DeleteOnSpawn)
                         //    Del(cartridge.Owner);
@@ -214,7 +214,7 @@ public sealed partial class GunSystem : SharedGunSystem
                 case AmmoComponent newAmmo:
                     MuzzleFlash(gunUid, newAmmo, user);
                     Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
-                    Recoil(user, direction);
+                    Recoil(user, direction, gun.CameraRecoilScalar);
                     if (ent!.Value.IsClientSide())
                         Del(ent.Value);
                     else
@@ -222,18 +222,18 @@ public sealed partial class GunSystem : SharedGunSystem
                     break;
                 case HitscanPrototype:
                     Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
-                    Recoil(user, direction);
+                    Recoil(user, direction, gun.CameraRecoilScalar);
                     break;
             }
         }
     }
 
-    private void Recoil(EntityUid? user, Vector2 recoil)
+    private void Recoil(EntityUid? user, Vector2 recoil, float recoilScalar)
     {
-        if (!Timing.IsFirstTimePredicted || user == null || recoil == Vector2.Zero)
+        if (!Timing.IsFirstTimePredicted || user == null || recoil == Vector2.Zero || recoilScalar == 0)
             return;
 
-        _recoil.KickCamera(user.Value, recoil.Normalized * 0.5f);
+        _recoil.KickCamera(user.Value, recoil.Normalized * 0.5f * recoilScalar);
     }
 
     protected override void Popup(string message, EntityUid? uid, EntityUid? user)
index 95259d995cc466dde99e373534a42b2f2125cd43..5517e11ea5b4baa76ca71ad720cfe4a8faa8f582 100644 (file)
@@ -11,6 +11,7 @@ namespace Content.Server.Chemistry.Components
         public FixedPoint2 TransferAmount = FixedPoint2.New(0.5);
 
         public float ReactTimer;
+        [DataField("active")]
         public bool Active;
     }
 }
diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.Solution.cs
new file mode 100644 (file)
index 0000000..4434c23
--- /dev/null
@@ -0,0 +1,82 @@
+using Content.Server.Chemistry.Components;
+using Content.Server.Chemistry.EntitySystems;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.FixedPoint;
+using Content.Shared.Vapor;
+using Content.Shared.Weapons.Ranged;
+using Content.Shared.Weapons.Ranged.Components;
+using Robust.Shared.Map;
+
+namespace Content.Server.Weapons.Ranged.Systems;
+
+public sealed partial class GunSystem
+{
+    [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
+
+    protected override void InitializeSolution()
+    {
+        base.InitializeSolution();
+
+        SubscribeLocalEvent<SolutionAmmoProviderComponent, MapInitEvent>(OnSolutionMapInit);
+        SubscribeLocalEvent<SolutionAmmoProviderComponent, SolutionChangedEvent>(OnSolutionChanged);
+    }
+
+    private void OnSolutionMapInit(EntityUid uid, SolutionAmmoProviderComponent component, MapInitEvent args)
+    {
+        UpdateSolutionShots(uid, component);
+    }
+
+    private void OnSolutionChanged(EntityUid uid, SolutionAmmoProviderComponent component, SolutionChangedEvent args)
+    {
+        if (args.Solution.Name == component.SolutionId)
+            UpdateSolutionShots(uid, component, args.Solution);
+    }
+
+    protected override void UpdateSolutionShots(EntityUid uid, SolutionAmmoProviderComponent component, Solution? solution = null)
+    {
+        var shots = 0;
+        var maxShots = 0;
+        if (solution == null && !_solutionContainer.TryGetSolution(uid, component.SolutionId, out solution))
+        {
+            component.Shots = shots;
+            component.MaxShots = maxShots;
+            Dirty(component);
+            return;
+        }
+
+        shots = (int) (solution.Volume / component.FireCost);
+        maxShots = (int) (solution.MaxVolume / component.FireCost);
+
+        component.Shots = shots;
+        component.MaxShots = maxShots;
+        Dirty(component);
+
+        UpdateSolutionAppearance(uid, component);
+    }
+
+    protected override (EntityUid Entity, IShootable) GetSolutionShot(EntityUid uid, SolutionAmmoProviderComponent component, EntityCoordinates position)
+    {
+        var (ent, shootable) = base.GetSolutionShot(uid, component, position);
+
+        if (!_solutionContainer.TryGetSolution(uid, component.SolutionId, out var solution))
+            return (ent, shootable);
+
+        var newSolution = _solutionContainer.SplitSolution(uid, solution, component.FireCost);
+
+        if (newSolution.Volume <= FixedPoint2.Zero)
+            return (ent, shootable);
+
+        if (TryComp<AppearanceComponent>(ent, out var appearance))
+        {
+            Appearance.SetData(ent, VaporVisuals.Color, newSolution.GetColor(ProtoManager).WithAlpha(1f), appearance);
+            Appearance.SetData(ent, VaporVisuals.State, true, appearance);
+        }
+
+        // Add the solution to the vapor and actually send the thing
+        if (_solutionContainer.TryGetSolution(ent, VaporComponent.SolutionName, out var vaporSolution))
+        {
+            _solutionContainer.TryAddSolution(ent, vaporSolution, newSolution);
+        }
+        return (ent, shootable);
+    }
+}
diff --git a/Content.Shared/Weapons/Ranged/Components/ClothingSlotAmmoProviderComponent.cs b/Content.Shared/Weapons/Ranged/Components/ClothingSlotAmmoProviderComponent.cs
new file mode 100644 (file)
index 0000000..af3fd57
--- /dev/null
@@ -0,0 +1,26 @@
+using Content.Shared.Inventory;
+using Content.Shared.Weapons.Ranged.Systems;
+using Content.Shared.Whitelist;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Weapons.Ranged.Components;
+
+/// <summary>
+/// This is used for relaying ammo events
+/// to an entity in the user's clothing slot.
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedGunSystem))]
+public sealed class ClothingSlotAmmoProviderComponent : AmmoProviderComponent
+{
+    /// <summary>
+    /// The slot that the ammo provider should be located in.
+    /// </summary>
+    [DataField("targetSlot", required: true)]
+    public SlotFlags TargetSlot;
+
+    /// <summary>
+    /// A whitelist for determining whether or not an ammo provider is valid.
+    /// </summary>
+    [DataField("providerWhitelist")]
+    public EntityWhitelist? ProviderWhitelist;
+}
index 07f84f325227f5061846eec1134dfc1009eaf789..0ccc839902ce33032edab6cc78ee374eb212a67f 100644 (file)
@@ -30,6 +30,13 @@ public partial class GunComponent : Component
 
     // These values are very small for now until we get a debug overlay and fine tune it
 
+    /// <summary>
+    /// A scalar value applied to the vector governing camera recoil.
+    /// If 0, there will be no camera recoil.
+    /// </summary>
+    [DataField("cameraRecoilScalar"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+    public float CameraRecoilScalar = 1f;
+
     /// <summary>
     /// Last time the gun fired.
     /// Used for recoil purposes.
diff --git a/Content.Shared/Weapons/Ranged/Components/SolutionAmmoProviderComponent.cs b/Content.Shared/Weapons/Ranged/Components/SolutionAmmoProviderComponent.cs
new file mode 100644 (file)
index 0000000..4a76281
--- /dev/null
@@ -0,0 +1,42 @@
+using Content.Shared.Weapons.Ranged.Systems;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+
+namespace Content.Shared.Weapons.Ranged.Components;
+
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedGunSystem))]
+public sealed partial class SolutionAmmoProviderComponent : Component
+{
+    /// <summary>
+    /// The solution where reagents are extracted from for the projectile.
+    /// </summary>
+    [DataField("solutionId", required: true), AutoNetworkedField]
+    public string SolutionId = default!;
+
+    /// <summary>
+    /// How much reagent it costs to fire once.
+    /// </summary>
+    [DataField("fireCost"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+    public float FireCost = 10;
+
+    /// <summary>
+    /// The amount of shots currently available.
+    /// used for network predictions.
+    /// </summary>
+    [DataField("shots"), ViewVariables, AutoNetworkedField]
+    public int Shots;
+
+    /// <summary>
+    /// The max amount of shots the gun can fire.
+    /// used for network prediction
+    /// </summary>
+    [DataField("maxShots"), ViewVariables, AutoNetworkedField]
+    public int MaxShots;
+
+    /// <summary>
+    /// The prototype that's fired by the gun.
+    /// </summary>
+    [DataField("proto", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>)), ViewVariables(VVAccess.ReadWrite)]
+    public string Prototype = default!;
+}
diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs
new file mode 100644 (file)
index 0000000..669c49a
--- /dev/null
@@ -0,0 +1,55 @@
+using System.Diagnostics.CodeAnalysis;
+using Content.Shared.Inventory;
+using Content.Shared.Weapons.Ranged.Components;
+using Content.Shared.Weapons.Ranged.Events;
+
+namespace Content.Shared.Weapons.Ranged.Systems;
+
+public partial class SharedGunSystem
+{
+    [Dependency] private readonly InventorySystem _inventory = default!;
+
+    private void InitializeClothing()
+    {
+        SubscribeLocalEvent<ClothingSlotAmmoProviderComponent, TakeAmmoEvent>(OnClothingTakeAmmo);
+        SubscribeLocalEvent<ClothingSlotAmmoProviderComponent, GetAmmoCountEvent>(OnClothingAmmoCount);
+    }
+
+    private void OnClothingTakeAmmo(EntityUid uid, ClothingSlotAmmoProviderComponent component, TakeAmmoEvent args)
+    {
+        if (!TryGetClothingSlotEntity(uid, component, out var entity))
+            return;
+        RaiseLocalEvent(entity.Value, args);
+    }
+
+    private void OnClothingAmmoCount(EntityUid uid, ClothingSlotAmmoProviderComponent component, ref GetAmmoCountEvent args)
+    {
+        if (!TryGetClothingSlotEntity(uid, component, out var entity))
+            return;
+        RaiseLocalEvent(entity.Value, ref args);
+    }
+
+    private bool TryGetClothingSlotEntity(EntityUid uid, ClothingSlotAmmoProviderComponent component, [NotNullWhen(true)] out EntityUid? slotEntity)
+    {
+        slotEntity = null;
+        if (!_container.TryGetContainingContainer(uid, out var container))
+            return false;
+        var user = container.Owner;
+
+        if (!TryComp<InventoryComponent>(user, out var inventory))
+            return false;
+        var slots = _inventory.GetSlots(user, inventory);
+        foreach (var slot in slots)
+        {
+            if (slot.SlotFlags != component.TargetSlot)
+                continue;
+            if (!_inventory.TryGetSlotEntity(user, slot.Name, out var e, inventory))
+                continue;
+            if (component.ProviderWhitelist != null && !component.ProviderWhitelist.IsValid(e.Value, EntityManager))
+                continue;
+            slotEntity = e;
+        }
+
+        return slotEntity != null;
+    }
+}
diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Solution.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Solution.cs
new file mode 100644 (file)
index 0000000..d04b3fa
--- /dev/null
@@ -0,0 +1,60 @@
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Weapons.Ranged.Components;
+using Content.Shared.Weapons.Ranged.Events;
+using Robust.Shared.Map;
+
+namespace Content.Shared.Weapons.Ranged.Systems;
+
+public partial class SharedGunSystem
+{
+    protected virtual void InitializeSolution()
+    {
+        SubscribeLocalEvent<SolutionAmmoProviderComponent, TakeAmmoEvent>(OnSolutionTakeAmmo);
+        SubscribeLocalEvent<SolutionAmmoProviderComponent, GetAmmoCountEvent>(OnSolutionAmmoCount);
+    }
+
+    private void OnSolutionTakeAmmo(EntityUid uid, SolutionAmmoProviderComponent component, TakeAmmoEvent args)
+    {
+        var shots = Math.Min(args.Shots, component.Shots);
+
+        // Don't dirty if it's an empty fire.
+        if (shots == 0)
+            return;
+
+        for (var i = 0; i < shots; i++)
+        {
+            args.Ammo.Add(GetSolutionShot(uid, component, args.Coordinates));
+            component.Shots--;
+        }
+
+        UpdateSolutionShots(uid, component);
+        UpdateSolutionAppearance(uid, component);
+    }
+
+    private void OnSolutionAmmoCount(EntityUid uid, SolutionAmmoProviderComponent component, ref GetAmmoCountEvent args)
+    {
+        args.Count = component.Shots;
+        args.Capacity = component.MaxShots;
+    }
+
+    protected virtual void UpdateSolutionShots(EntityUid uid, SolutionAmmoProviderComponent component, Solution? solution = null)
+    {
+
+    }
+
+    protected virtual (EntityUid Entity, IShootable) GetSolutionShot(EntityUid uid, SolutionAmmoProviderComponent component, EntityCoordinates position)
+    {
+        var ent = Spawn(component.Prototype, position);
+        return (ent, EnsureComp<AmmoComponent>(ent));
+    }
+
+    protected void UpdateSolutionAppearance(EntityUid uid, SolutionAmmoProviderComponent component)
+    {
+        if (!TryComp<AppearanceComponent>(uid, out var appearance))
+            return;
+
+        Appearance.SetData(uid, AmmoVisuals.HasAmmo, component.Shots != 0, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoCount, component.Shots, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoMax, component.MaxShots, appearance);
+    }
+}
index 2810019f5b26fe0b8be66636ac80b25fb324d414..6baa6c38ec9bea8a12d3ebc4f7abc3ea5a214036 100644 (file)
@@ -79,7 +79,9 @@ public abstract partial class SharedGunSystem : EntitySystem
         InitializeMagazine();
         InitializeRevolver();
         InitializeBasicEntity();
+        InitializeClothing();
         InitializeContainer();
+        InitializeSolution();
 
         // Interactions
         SubscribeLocalEvent<GunComponent, GetVerbsEvent<AlternativeVerb>>(OnAltVerb);
diff --git a/Resources/Audio/Weapons/Guns/Gunshots/attributions.yml b/Resources/Audio/Weapons/Guns/Gunshots/attributions.yml
new file mode 100644 (file)
index 0000000..4bbd672
--- /dev/null
@@ -0,0 +1,4 @@
+- files: ["water_spray.ogg"]
+  license: "CC0-1.0"
+  copyright: "Watering by elittle13. Converted to .OGG and MONO by EmoGarbage404 (github)"
+  source: "https://freesound.org/people/elittle13/sounds/568558"
diff --git a/Resources/Audio/Weapons/Guns/Gunshots/water_spray.ogg b/Resources/Audio/Weapons/Guns/Gunshots/water_spray.ogg
new file mode 100644 (file)
index 0000000..aa3dbf7
Binary files /dev/null and b/Resources/Audio/Weapons/Guns/Gunshots/water_spray.ogg differ
index 4f1f1af5c697e0c0b6dd0c8e638eb48e3e8d1c0c..87b837181b06223e9ba8669f7734485c995b98f7 100644 (file)
@@ -7,6 +7,9 @@ technologies-cleaning-technology-description = Start to a shiny clean station.
 technologies-advanced-cleaning-technology = Advanced cleaning technology
 technologies-advanced-cleaning-technology-description = Advanced tools won't stop people from trashing the station, sadly.
 
+technologies-advanced-spray-technology = Advanced spray technology
+technologies-advanced-spray-technology-description = The newest ways to hose down the station. Filthy animals.
+
 technologies-foodbev-technology = Food and beverage technology
 technologies-food-and-beverage-technology-description = Robust service from better technology.
 
index dba06d996fe748aa9a11a273bd8819c928d8279a..1dae0e3546a09dca1a611d543a38f5ee437a214b 100644 (file)
     - AdvMopItem
     - MegaSprayBottle
 
+- type: technology
+  id: AdvancedSprayTechnology
+  name: technologies-advanced-spray-technology
+  description: technologies-advanced-spray-technology-description
+  icon:
+    sprite: Objects/Weapons/Guns/Basic/spraynozzle.rsi
+    state: icon
+  requiredPoints: 7500
+  requiredTechnologies:
+  - AdvancedCleaningTechnology
+  unlockedRecipes:
+  - WeaponSprayNozzle
+  - ClothingBackpackWaterTank
+
 # Food/Bev Service Technology Tree
 
 - type: technology
index d726fa5cac963d2dbf5c262651de6ee2372a0122..a5ffeb93836b4e3908bea940de8779199292f87e 100644 (file)
           type: StorageBoundUserInterface
         - key: enum.ChameleonUiKey.Key
           type: ChameleonBoundUserInterface
+
+- type: entity
+  parent: Clothing
+  id: ClothingBackpackWaterTank
+  name: backpack water tank
+  description: Holds a large amount of fluids. Supplies to spray nozzles in your hands.
+  components:
+  - type: Tag
+    tags: 
+    - NozzleBackTank
+  - type: Sprite
+    sprite: Clothing/Back/Backpacks/waterbackpack.rsi
+    state: icon
+  - type: Item
+    size: 200
+  - type: Clothing
+    slots: BACK
+    sprite: Clothing/Back/Backpacks/waterbackpack.rsi
+  - type: SolutionAmmoProvider
+    solutionId: tank
+    proto: BulletWaterShot
+  - type: SolutionContainerManager
+    solutions:
+      tank:
+        maxVol: 1000 #much water
+  - type: SolutionTransfer
+    transferAmount: 50
+    maxTransferAmount: 100
+    minTransferAmount: 10
+    canChangeTransferAmount: true
+  - type: UserInterface
+    interfaces:
+    - key: enum.TransferAmountUiKey.Key
+      type: TransferAmountBoundUserInterface
+  - type: DrawableSolution
+    solution: tank
+  - type: RefillableSolution
+    solution: tank
+  - type: DrainableSolution
+    solution: tank
+  - type: ExaminableSolution
+    solution: tank
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/spraynozzle.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/spraynozzle.yml
new file mode 100644 (file)
index 0000000..d4d0025
--- /dev/null
@@ -0,0 +1,26 @@
+- type: entity
+  id: WeaponSprayNozzle
+  parent: BaseItem
+  name: spray nozzle
+  description: A high-powered spray nozzle used in conjunction with a backpack-mounted water tank.
+  components:
+  - type: Sprite
+    sprite: Objects/Weapons/Guns/Basic/spraynozzle.rsi
+    state: icon
+  - type: Item
+    sprite: Objects/Weapons/Guns/Basic/spraynozzle.rsi
+    size: 30
+  - type: Gun
+    cameraRecoilScalar: 0 #no recoil
+    fireRate: 4
+    selectedMode: FullAuto
+    availableModes:
+    - FullAuto
+    soundGunshot:
+      path: /Audio/Weapons/Guns/Gunshots/water_spray.ogg
+  - type: Appearance
+  - type: ClothingSlotAmmoProvider
+    targetSlot: BACK
+    providerWhitelist:
+      tags:
+      - NozzleBackTank
index 9ea12225100decbeea4133dc114430c73ff216e7..4f107fb36ee7bbd505bc90b92131cc3c40a20ad8 100644 (file)
     - type: Ammo
       muzzleFlash: null
 
+- type: entity
+  id: BulletWaterShot
+  name: water
+  noSpawn: true
+  components:
+  - type: Clickable
+  - type: Physics
+    bodyType: Dynamic
+    linearDamping: 0
+    angularDamping: 0
+  - type: TimedDespawn
+    lifetime: 10
+  - type: Projectile
+    damage:
+      types:
+        Blunt: 0 #it's just water, bro
+  - type: Sprite
+    sprite: Objects/Weapons/Guns/Projectiles/water_shot.rsi
+    layers:
+    - state: icon
+      map: ["enum.VaporVisualLayers.Base"]
+  - type: Ammo
+    muzzleFlash: null
+  - type: SolutionContainerManager
+    solutions:
+      vapor:
+        maxVol: 50
+  - type: Fixtures
+    fixtures:
+    - shape:
+        !type:PhysShapeAabb
+        bounds: "-0.25,-0.25,0.25,0.25"
+      hard: false
+      mask:
+      - FullTileMask
+      - Opaque
+  - type: Vapor
+    active: true
+  - type: Appearance
+  - type: VaporVisuals
+
 - type: entity
   id: BulletCannonBall
   name: cannonball
index 8b0ba1ba526f05d6ec4cad2e17c3788b98b6a133..cf15354b94d6d3f5b55ae38fa629a8c8df6cf53e 100644 (file)
       - Bucket
       - MopItem
       - AdvMopItem
+      - WeaponSprayNozzle
+      - ClothingBackpackWaterTank
       - SprayBottle
       - MegaSprayBottle
       - FireExtinguisher
index 6165bf274c740e9b633f1bd7af553b954bdfa39f..b1cd8db385694f28ed790f4158ad93bc5a5ec80c 100644 (file)
     Plastic: 400
     Steel: 100
     Glass: 100
+
+- type: latheRecipe
+  id: WeaponSprayNozzle
+  result: WeaponSprayNozzle
+  completetime: 5
+  materials:
+    Steel: 1500
+    Glass: 500
+
+- type: latheRecipe
+  id: ClothingBackpackWaterTank
+  result: ClothingBackpackWaterTank
+  completetime: 4
+  materials:
+    Steel: 250
+    Glass: 1000
index 9c65f89831dcc3c945c028c5adc07c58592c435c..def86ed2c1756616b234549463fc9b3a78b399fc 100644 (file)
 - type: Tag
   id: NoBlockAnchoring
 
+- type: Tag
+  id: NozzleBackTank
+
 - type: Tag
   id: NukeOpsUplink
 
diff --git a/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/equipped-BACKPACK.png b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/equipped-BACKPACK.png
new file mode 100644 (file)
index 0000000..a04978d
Binary files /dev/null and b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/equipped-BACKPACK.png differ
diff --git a/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/icon.png b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/icon.png
new file mode 100644 (file)
index 0000000..7a5eac5
Binary files /dev/null and b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/icon.png differ
diff --git a/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/inhand-left.png b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/inhand-left.png
new file mode 100644 (file)
index 0000000..3806eeb
Binary files /dev/null and b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/inhand-left.png differ
diff --git a/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/inhand-right.png b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/inhand-right.png
new file mode 100644 (file)
index 0000000..ae08447
Binary files /dev/null and b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/inhand-right.png differ
diff --git a/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/meta.json b/Resources/Textures/Clothing/Back/Backpacks/waterbackpack.rsi/meta.json
new file mode 100644 (file)
index 0000000..54f5386
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/f7337f1aa9efdcc1403ca4771d638e0634074537",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "icon"
+    },
+    {
+      "name": "equipped-BACKPACK",
+      "directions": 4
+    },
+    {
+      "name": "inhand-left",
+      "directions": 4
+    },
+    {
+      "name": "inhand-right",
+      "directions": 4
+    }
+  ]
+}
diff --git a/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/icon.png b/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/icon.png
new file mode 100644 (file)
index 0000000..698a7be
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/icon.png differ
diff --git a/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/inhand-left.png b/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/inhand-left.png
new file mode 100644 (file)
index 0000000..68a944f
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/inhand-left.png differ
diff --git a/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/inhand-right.png b/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/inhand-right.png
new file mode 100644 (file)
index 0000000..5bc0721
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/inhand-right.png differ
diff --git a/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Basic/spraynozzle.rsi/meta.json
new file mode 100644 (file)
index 0000000..5995a42
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "tgstation at https://github.com/tgstation/tgstation/commit/f7337f1aa9efdcc1403ca4771d638e0634074537",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "icon"
+    },
+    {
+      "name": "inhand-right",
+      "directions": 4
+    },
+    {
+      "name": "inhand-left",
+      "directions": 4
+    }
+  ]
+}
diff --git a/Resources/Textures/Objects/Weapons/Guns/Projectiles/water_shot.rsi/icon.png b/Resources/Textures/Objects/Weapons/Guns/Projectiles/water_shot.rsi/icon.png
new file mode 100644 (file)
index 0000000..550578f
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Projectiles/water_shot.rsi/icon.png differ
diff --git a/Resources/Textures/Objects/Weapons/Guns/Projectiles/water_shot.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Projectiles/water_shot.rsi/meta.json
new file mode 100644 (file)
index 0000000..a7b6902
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "version": 1,
+  "license": "CC0-1.0",
+  "copyright": "Created by EmoGarbage404 (github) for Space Station 14.",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "icon"
+    }
+  ]
+}
\ No newline at end of file