Creating a custom weapon attachment
by Aspa102
Weapon attachments are created similarly to syringes.
1. Creating an attachment spawnable
using UnityEngine;
namespace Mod
{
public class Mod
{
public static void Main()
{
// registering a custom item
ModAPI.Register(
new Modification()
{
OriginalItem = ModAPI.FindSpawnable("Scope Attachment"), // derive from an attachment
NameOverride = "Bike Horn [mod name]",
DescriptionOverride = "A bike horn that goes on the top of a gun. Does what you think it does.",
CategoryOverride = ModAPI.FindCategory("Firearms"),
ThumbnailOverride = ModAPI.LoadSprite("horn view.png"),
AfterSpawn = (Instance) =>
{
// give the attachment a new sprite
Instance.GetComponent<SpriteRenderer>().sprite = ModAPI.LoadSprite("bikehorn.png");
Instance.FixColliders();
// while you can use a new sound for the connection sound, you can do this to keep the current sound
// each attachment can have a unique connection sound
AudioClip attach = Instance.GetComponent<ScopeAttachmentBehaviour>().ConnectClip;
// destroy the existing attachment behaviour
UnityEngine.Object.Destroy(Instance.GetComponent<ScopeAttachmentBehaviour>());
// add the new attachment behaviour (unless it already exists)
var attachment = Instance.GetOrAddComponent<BikeHornAttachmentBehaviour>();
// set the connection sound
attachment.ConnectClip = attach;
// here is some other stuff you can change
attachment.AttachmentType = FirearmAttachmentType.AttachmentType.Scope; // whether the attachment will connect to the top or bottom of the gun
attachment.AttachmentOffset = Vector2.zero; // the offset from the attachment point (generally only used if you want the sprite to be within the gun and stuf
}
}
);
}
}
// define the attachment behaviour
public class BikeHornAttachmentBehaviour : FirearmAttachmentBehaviour
{
// method that is called on connection
public override void OnConnect() { }
// method that is called on disconnection
public override void OnDisconnect() { }
// method that is called when the gun is fired
public override void OnFire() { }
// method that is called when a bullet hits an object
public override void OnHit(BallisticsEmitter.CallbackParams args)
{
// args contains the position of the bullet, direction of the bullet, object that was hit, and the surface normal the bullet hit.
}
}
}
Most weapon attachments have a unique behaviour associated with them, exactly like how syringes do. While this isn't strictly necessary, like how you can use the scope behaviour for any scopes, it allows for the creation of really unique and cool attachments.
2. Creating an unique attachment
The attachment we created in the above section doesn't actually do anything, so let's change that. Instead of having the attachment do literally nothing, let's make it play a noise when the gun is fired.
public class BikeHornAttachmentBehaviour : FirearmAttachmentBehaviour
{
public AudioClip HornNoise; // The audio clip that will play on fire
public override void OnConnect() { }
public override void OnDisconnect() { }
public override void OnFire()
{
// on fire, get the physical behaviour and run the PlayClipOnce method
// note that you don't need to have the 'clip:' parts in the method's parameters, it makes it easier to tell what the parameters you're setting.
Phys.PlayClipOnce(clip: HornNoise, volume: 1.5f);
}
public override void OnHit(BallisticsEmitter.CallbackParams args) { }
}
Then we change the spawnable definition.
ModAPI.Register(
new Modification()
{
OriginalItem = ModAPI.FindSpawnable("Scope Attachment"),
NameOverride = "Bike Horn [mod name]",
DescriptionOverride = "A bike horn that goes on the top of a gun. Does what you think it does.",
CategoryOverride = ModAPI.FindCategory("Firearms"),
ThumbnailOverride = ModAPI.LoadSprite("horn view.png"),
AfterSpawn = (Instance) =>
{
Instance.GetComponent<SpriteRenderer>().sprite = ModAPI.LoadSprite("bikehorn.png");
Instance.FixColliders();
AudioClip attach = Instance.GetComponent<ScopeAttachmentBehaviour>().ConnectClip;
UnityEngine.Object.Destroy(Instance.GetComponent<ScopeAttachmentBehaviour>());
var attachment = Instance.GetOrAddComponent<BikeHornAttachmentBehaviour>();
attachment.ConnectClip = attach;
attachment.AttachmentType = FirearmAttachmentType.AttachmentType.Scope;
attachment.AttachmentOffset = Vector2.zero;
// setting the new audio clip
attachment.HornNoise = ModAPI.LoadSound("bikehorn.wav");
}
}
);
Here is the final result:
3. Creating an attachment variant
The attachment above is completely unique and comes with their own functionality, but what if you want to make a variant of the scope attachment? In order to do that, all you need to do is change the sprite and change some variables if you feel like it.
ModAPI.Register(
new Modification()
{
OriginalItem = ModAPI.FindSpawnable("Scope Attachment"), // derive from an attachment
NameOverride = "Hotdog Sight [mod name]",
DescriptionOverride = "A hotdog with a hole drilled down the middle. Improves accuracy by 100%.",
CategoryOverride = ModAPI.FindCategory("Firearms"),
ThumbnailOverride = ModAPI.LoadSprite("hog view.png"),
AfterSpawn = (Instance) =>
{
// give the attachment a new sprite
Instance.GetComponent<SpriteRenderer>().sprite = ModAPI.LoadSprite("hog.png");
Instance.FixColliders();
// we're changing the accuracy percentage of the attachment
// this should make the scope increase accuracy by 100%
Instance.GetComponent<ScopeAttachmentBehaviour>().AccuracyPercent = 100;
// change the connection sound if you feel like it
Instance.GetComponent<ScopeAttachmentBehaviour>().ConnectClip = ModAPI.LoadSound("hotdog.wav");
}
}
);
4. Summary
In summary, this guide has shown how to:
- Create a new unique attachment
- Create an attachment variant
A mod has been created with these items within it here, and has been open sourced here.