diff --git a/SecretAPI/Features/DecalHelpers.cs b/SecretAPI/Features/DecalHelpers.cs
new file mode 100644
index 0000000..2283287
--- /dev/null
+++ b/SecretAPI/Features/DecalHelpers.cs
@@ -0,0 +1,111 @@
+namespace SecretAPI.Features;
+
+using System;
+using Decals;
+using InventorySystem.Items;
+using InventorySystem.Items.Autosync;
+using InventorySystem.Items.Firearms.Modules;
+using Mirror;
+using RelativePositioning;
+using UnityEngine;
+using Utils.Networking;
+
+///
+/// Helps with handling Decals () and sending them to clients without the need for a firearm with the .
+///
+public static class DecalHelpers
+{
+ private static bool hasData = false;
+ private static ItemType itemType = ItemType.None;
+ private static byte subcomponentIndex = 0;
+
+ ///
+ /// Creates an for spawning a decal that can be sent to players.
+ ///
+ /// The position where the decal will spawn.
+ /// The position from which the decal will be applied to a surface.
+ /// The type of decal to spawn.
+ /// The message which is to be sent to players.
+ public static AutosyncMessage GetDecalMessage(Vector3 position, Vector3 startPosition, DecalPoolType type)
+ {
+ RelativePosition hitPoint = new(position);
+ RelativePosition startRaycastPoint = new(startPosition);
+
+ (ItemType itemTypeId, byte moduleIndex) = GetItemData();
+
+ using NetworkWriterPooled? writer = NetworkWriterPool.Get();
+ writer.WriteByte(moduleIndex);
+ writer.WriteSubheader(ImpactEffectsModule.RpcType.ImpactDecal);
+ writer.WriteByte((byte)type);
+ writer.WriteRelativePosition(hitPoint);
+ writer.WriteRelativePosition(startRaycastPoint);
+
+ return new AutosyncMessage(writer, new ItemIdentifier(itemTypeId, 0));
+ }
+
+ ///
+ /// Spawns a decal.
+ ///
+ /// The position where the decal will spawn.
+ /// The position from which the decal will be applied to a surface.
+ /// The type of decal to spawn.
+ public static void SpawnDecalFromPosition(Vector3 position, Vector3 startPosition, DecalPoolType type = DecalPoolType.Blood)
+ => GetDecalMessage(position, startPosition, type).SendToAuthenticated();
+
+ ///
+ /// Spawns a decal.
+ ///
+ /// The position where the decal will spawn.
+ /// The normal of the face the decal is on.
+ /// The type of decal to spawn.
+ public static void SpawnDecalFromNormal(Vector3 position, Vector3 normal, DecalPoolType type = DecalPoolType.Blood)
+ => GetDecalMessage(position, position + normal, type).SendToAuthenticated();
+
+ ///
+ /// Spawns a decal.
+ ///
+ /// The position where the decal will spawn.
+ /// The normal rotation of the face the decal is on.
+ /// The type of decal to spawn.
+ public static void SpawnDecalFromNormal(Vector3 position, Quaternion normal, DecalPoolType type = DecalPoolType.Blood)
+ => GetDecalMessage(position, position + (normal * Vector3.forward), type).SendToAuthenticated();
+
+ ///
+ /// Spawns a decal.
+ ///
+ /// The position where the decal will spawn.
+ /// The direction opposite to the normal of the face the decal will be placed on.
+ /// The type of decal to spawn.
+ public static void SpawnDecalFromDirection(Vector3 position, Vector3 direction, DecalPoolType type = DecalPoolType.Blood)
+ => GetDecalMessage(position, position - direction, type).SendToAuthenticated();
+
+ ///
+ /// Spawns a decal.
+ ///
+ /// The position where the decal will spawn.
+ /// The direction opposite to the normal of the face the decal will be placed on.
+ /// The type of decal to spawn.
+ public static void SpawnDecalFromDirection(Vector3 position, Quaternion direction, DecalPoolType type = DecalPoolType.Blood)
+ => GetDecalMessage(position, position - (direction * Vector3.forward), type).SendToAuthenticated();
+
+ private static (ItemType ItemType, byte SubcomponentIndex) GetItemData()
+ {
+ if (hasData)
+ return (itemType, subcomponentIndex);
+
+ foreach (ModularAutosyncItem? autoItem in ModularAutosyncItem.AllTemplates)
+ {
+ for (byte b = 0; b < autoItem.AllSubcomponents.Length; b++)
+ {
+ if (autoItem.AllSubcomponents[b] is not ImpactEffectsModule)
+ continue;
+ subcomponentIndex = b;
+ itemType = autoItem.ItemTypeId;
+ hasData = true;
+ return (itemType, subcomponentIndex);
+ }
+ }
+
+ throw new InvalidOperationException("Couldn't find the `InventorySystem.Items.Firearms.Modules.ImpactEffectsModule` in the any ModularAutosyncItem!");
+ }
+}
\ No newline at end of file