tAPI [Tutorial] Custom Dust

How would you make it spawn vanilla dust particles?
Just call
Code:
Dust.NewDust(new Vector2(x, y), width, height, type, speedX, speedY, alpha, color, scale)
where x and y are the coordinates of the position, width and height determine the area range in which the dust can spawn (not the actual size of the dust), type is the vanilla type, speedX speedY are the dust's speed along each axis, alpha is how transparent the dust is (0 is fully opaque and 255 is fully transparent), color is color (you'll probably just want default(Color) for this), and scale is how large the dust is (1 for normal size, default size is multiplied by this).
 
Just call
Code:
Dust.NewDust(new Vector2(x, y), width, height, type, speedX, speedY, alpha, color, scale)
where x and y are the coordinates of the position, width and height determine the area range in which the dust can spawn (not the actual size of the dust), type is the vanilla type, speedX speedY are the dust's speed along each axis, alpha is how transparent the dust is (0 is fully opaque and 255 is fully transparent), color is color (you'll probably just want default(Color) for this), and scale is how large the dust is (1 for normal size, default size is multiplied by this).
Do you have a list of the types of particles?:D
 
This is a wonderful system to keep organization of your dust, while I partially disagree with the following statement
however, one thing it doesn't seem to have an obvious hook for is dust (the particles that are made by things like torches, terra blade, etc).
The reason we've added overrideUpdate and overrideTexture is because its a more efficient substitute to having a hook running in there, dust particles are terraria's heaviest loop when you consider the maximum dust you can have on screen at a single point in time 6000.

You can also override the dust's frame in the texture, its light color, and god forbid you can even replace its draw method if you feel like it. (all in the same format as the above)

If anything's not clear in my post I'll be glad to elaborate further.

Also another thing - dusts are actually 10x10 in boxes if you use the default frames, but as I stated above you can just change the texture's source rectangle to your liking (and in fact, I believe in one of my old tConfig mods I've had dust as big as 34x60)

One other note for further customization of dust, it can even hold custom data but we really discourage it. (dust.customData, its an object so once you store something in it you can use it in overrideUpdate or overrideDraw's methods via casting it back to its original type)
 
  • Like
Reactions: W1K
This is a wonderful system to keep organization of your dust, while I partially disagree with the following statement

The reason we've added overrideUpdate and overrideTexture is because its a more efficient substitute to having a hook running in there, dust particles are terraria's heaviest loop when you consider the maximum dust you can have on screen at a single point in time 6000.

You can also override the dust's frame in the texture, its light color, and god forbid you can even replace its draw method if you feel like it. (all in the same format as the above)

If anything's not clear in my post I'll be glad to elaborate further.

Also another thing - dusts are actually 10x10 in boxes if you use the default frames, but as I stated above you can just change the texture's source rectangle to your liking (and in fact, I believe in one of my old tConfig mods I've had dust as big as 34x60)

One other note for further customization of dust, it can even hold custom data but we really discourage it. (dust.customData, its an object so once you store something in it you can use it in overrideUpdate or overrideDraw's methods via casting it back to its original type)
Yeah, I made this tutorial when I was still really new to modding and was trying to avoid looking at the source code too much :p
Anyways, thanks for that information! dust.frame seems particularly useful; no more having to worry about types or keeping around duplicate frames for random selection.
Now, if only I could find time to update my tutorials...
 
TAPI makes modding extremely easy and adds hooks for many things such as items and projectiles; however, one thing it doesn't seem to have an obvious hook for is dust (the particles that are made by things like torches, terra blade, etc). This can get extremely frustrating when one realizes that nearly everything about dust (shape, color, behavior, light color, etc.) is very hard-coded into the game. This tutorial will teach you how to add custom dust to the game and completely control its behavior. (Warning: everything will be done with .cs files, so you actually need to know how to program.)

First, you will need to create a class for your dust (actually, you don't need to, but it makes organization much, much easier). As an example, I will use the mod I am currently working on at the time of writing this. You will need to add several things: a field to keep track of the texture for your custom dust, and a method to assign the texture to the field.
Code:
using System;
using Microsoft.Xna.Framework; //This will help you control the behavior of the dust, which we'll go over later.
using Microsoft.Xna.Framework.Graphics; //This is where Texture2D is located.
using Terraria;
using TAPI;

namespace Bluemagic {
public class BluemagicDust
{
    private static Texture2D texture; //This stores the custom dust textures for your class to use.

    public static void Load(ModBase modBase) //You can name this anything you want; just make sure it takes TAPI.ModBase as a parameter.
    {
        texture = modBase.textures["Dust"]; //This gets a texture from Dust.png in your mod folder then assigns it to texture.
    }
}}

Next, in your ModBase class, you will need to add the following to your OnLoad method in order for your dust class to actually be able to access the texture:
Code:
using System;
using Terraria;
using TAPI;

namespace Bluemagic {
public class Bluemagic : ModBase
{
    public override void OnLoad()
    {
        BluemagicDust.Load(this); //Use whatever you named your method from the previous part.
        //Your other loading stuff
    }
    //Your other methods
}}

Now you have everything you need to start creating your custom dust. Now for actually creating custom dust, go back to the custom dust class. I feel that the easiest way to teach you will be to show an example:
Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using TAPI;

namespace Bluemagic {
public class BluemagicDust
{
    private static Texture2D texture;

    public static void Load(ModBase modBase)
    {
        texture = modBase.textures["Dust"];
    }

    public static int CreateSpectreDust(float x, float y, int width, int height) //This is the method your other classes will use in order to spawn this dust.
    {
        Color color = new Color(200, 220, 230); //This is the color multiplier of your dust; The dust image you create will get "multiplied" by this color. If you don't know what the numbers mean, go look up RGB values.
        int dust = Dust.NewDust(new Vector2(x, y), width, height, 0, 0f, 0f, 100, color, 1.2f); //The parameters are (Microsoft.Xna.Framework.Vector2 position, int width, int height, int type, float xVelocity, float yVelocity, int alpha, Microsoft.Xna.Framework.Color color, float scale).
        //The method returns the index of your dust, so to access the new dust, all you need to do is call Main.dust[whatever was returned].
        //I'm hoping that position and the velocities are self-explanatory.
        //The width and height are basically the range of positions in which the dust will randomly spawn. Useful if you want a dust to spawn at any random point within a projectile, or something like that.
        //The type is basically the texture your dust will use. We will go over this later.
        //Alpha is the transparency of your dust. 0 is fully opaque, and 255 is fully invisible.
        //Color is the color multiplier on your dust.
        //Scale is the size of your dust; the size of the image will get multiplied by the scale.
        Main.dust[dust].noGravity = true; //Self-explanatory.
        Main.dust[dust].velocity /= 2; //This halves the speed of my dust when it spawns.
        Main.dust[dust].OverrideTexture = texture; //This is necessary for your dust to use your custom texture.
        Main.dust[dust].OverrideLightColor = color; //This makes the dust always appear a certain color, regardless of what kind of light is hitting it.
        Main.dust[dust].OverrideUpdate = UpdateSpectreDust; //This is what controls the behavior of the dust. See next method for details.
        return dust; //This is so whatever creates your dust can access it, similar to how Dust.NewDust returns the same thing.
    }

    private static void UpdateSpectreDust(Dust dust) //This is the method I use to control the behavior of my dust. Make sure it takes Terraria.Dust as the one and only parameter. This method will get called for every game tick.
    {
        dust.position += dust.velocity; //Necessary for the dust to actually move.
        dust.rotation += dust.velocity.X; //Rotating your dust may make it look more realistic; it's up to you how you do so.
        Lighting.AddLight((int)(dust.position.X / 16f), (int)(dust.position.Y / 16f), 0.05f, 0.15f, 0.2f); //The last three parameters are RGB values, except instead of integers from 0 to 255 it's real numbers from 0 to 1 (you could make it more than 1 although that would be really bright).
        dust.scale -= 0.03f; //This makes the dust shrink as time passes.
        if(dust.scale < 0.5f)
        {
            dust.active = false; //This removes the dust; you don't want dust to last forever.
        }
    }
}}
You can look through the Terraria.Dust class for more examples of dust behavior (although admittedly it's hard to look through). Basically, using these two methods, you can completely control the behavior of your dust. Then to spawn the dust, just call the create method.

There is still one thing we're missing; the actual texture for your dust. Now to explain how to make a texture file for your dust. The dust must have a size of 8 x 8 pixels (it can be smaller, just make sure it stays within the 8 x 8 square). Now, whenever dust spawns, it is given one out of three textures at random. So draw your first image in the 8 x 8 square location at the coordinates (0, 0) of the image. Then, two pixels below this 8 x 8 square, draw the second image, also in an 8 x 8 square. For the third image, draw it in another 8 x 8 square two pixels below the second image. Here is the example from my mod:
BldG7jy.png

I basically gave the three dusts different brightnesses; you might want to be more creative with your differences, depending on what you need.
Remember how in your code, you had to specify the type of dust? These are the textures that type 0 will use. If you want another type of dust with a different texture, give it a type of 1. Then 2 pixels to the right of the type 0 textures, repeat the same process. You can keep repeating this for more and more dusts. There is one catch: if you end up having more than 100 dust types, then place type 100 2 pixels below type 0, instead of further to the right. Then add the next dust textures to the right of that, repeat for the next 100 dusts. For example, you can see the Dust.png that the vanilla game uses. Finally, remember that the dust textures are completely contained within the 8 x 8 squares; when I say 2 pixels to the right or down, I mean an 8 x 8 square 2 pixels away from another 8 x 8 square.

Here is the end result of the dust in my mod:
s2Z3txu.jpg

Remember, to create the dust, just call your create method for the type of dust and provide the coordinates. Since the method returns the dust's index, you can customize it even more after you create it (i.e. if you want it to behave differently when produced from different sources). Feel free to ask any questions you have :happy:
Edit: I got it to work but it doesn't actually spawn the dust, just the light from the dust.
 
Last edited:
Edit: I got it to work but it doesn't actually spawn the dust, just the light from the dust.
So you're creating dust, the dust creates light, but the dust is invisible?
Hm, are you sure you're setting the dust's alpha to 0? For some reason in Terraria 0 means fully opaque while 255 is fully transparent.
 
Hm, can I see the code for the dust? At the moment, the only things I can think of going wrong are either dust.scale, dust.active, or the image file.
Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using TAPI;

namespace Ardium
{
    public class ArdiumDust
    {
        private static Texture2D Dust1;

        public static void Load(ModBase MBase)
        {
            Dust1 = MBase.textures["Dust/ArdiumDust"];
        }
        public static int CreateArdiumDust(Vector2 position, int width, int height)
        {
            Color color = new Color(212, 224, 227);
            int dust = Dust.NewDust(new Vector2(position.X,position.Y), 10, 14, 0, 0f, 0f, 0, color, 1.2f);
            Main.dust[dust].noGravity = true;
            Main.dust[dust].velocity /= 2;
            Main.dust[dust].OverrideTexture = Dust1;
            Main.dust[dust].OverrideLightColor = color;
            Main.dust[dust].OverrideUpdate = UpdateArdiumDust;
            return dust;
        }

        private static void UpdateArdiumDust(Dust dust)
        {
            dust.position += dust.velocity;
            dust.rotation += dust.velocity.X;
            Lighting.AddLight((int)(dust.position.X / 16f), (int)(dust.position.Y / 16f), 0.05f, 0.15f, 0.2f);
            dust.scale -= 0.03f;
            if (dust.scale < 0.5f)
            {
                dust.active = false;
            }
        }
    }
}
I managed to get it working, but it also spawns tons of black squares along with the actual dust, is there any way to fix this?
 
Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using TAPI;

namespace Ardium
{
    public class ArdiumDust
    {
        private static Texture2D Dust1;

        public static void Load(ModBase MBase)
        {
            Dust1 = MBase.textures["Dust/ArdiumDust"];
        }
        public static int CreateArdiumDust(Vector2 position, int width, int height)
        {
            Color color = new Color(212, 224, 227);
            int dust = Dust.NewDust(new Vector2(position.X,position.Y), 10, 14, 0, 0f, 0f, 0, color, 1.2f);
            Main.dust[dust].noGravity = true;
            Main.dust[dust].velocity /= 2;
            Main.dust[dust].OverrideTexture = Dust1;
            Main.dust[dust].OverrideLightColor = color;
            Main.dust[dust].OverrideUpdate = UpdateArdiumDust;
            return dust;
        }

        private static void UpdateArdiumDust(Dust dust)
        {
            dust.position += dust.velocity;
            dust.rotation += dust.velocity.X;
            Lighting.AddLight((int)(dust.position.X / 16f), (int)(dust.position.Y / 16f), 0.05f, 0.15f, 0.2f);
            dust.scale -= 0.03f;
            if (dust.scale < 0.5f)
            {
                dust.active = false;
            }
        }
    }
}
I managed to get it working, but it also spawns tons of black squares along with the actual dust, is there any way to fix this?
Hm, the only thing I can think of that would make black squares would be empty image data... in the image file, you made sure to have three possible options for the dust type in a column, right?
 
I'm having trouble spawning my dust. I'm trying to spawn some pumpkin heads to fall from the player every time he/she wears a accessory. I don't know how to get it to work. Here is my dust sprite and I have the code for the sprite made, I need help getting it to work on an accessory.
 

Attachments

  • Dust.png
    Dust.png
    294 bytes · Views: 217
I'm having trouble spawning my dust. I'm trying to spawn some pumpkin heads to fall from the player every time he/she wears a accessory. I don't know how to get it to work. Here is my dust sprite and I have the code for the sprite made, I need help getting it to work on an accessory.
In your accessory item's .cs file, you'll have to override this method:
public override void VanityEffects(Player player)
Then you can call the methods that create your dust there, with the help of player.location.
Also, keep in mind that unless you are manually modifying dust.frame, each dust will need to be contained in a 10 x 10 pixel square, and cannot trespass into another dust's 10 x 10 square.
 
In your accessory item's .cs file, you'll have to override this method:
public override void VanityEffects(Player player)
Then you can call the methods that create your dust there, with the help of player.location.
Also, keep in mind that unless you are manually modifying dust.frame, each dust will need to be contained in a 10 x 10 pixel square, and cannot trespass into another dust's 10 x 10 square.

Thanks's I'll try this and let you know if it works.
[DOUBLEPOST=1430575101,1430574531][/DOUBLEPOST]Ok I tried getting it to work but it's not taking here is my code:

Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using TAPI;
using Terraria;
namespace Moreitems.Items
{
   public class Cheat : ModItem
   {
  public override void Effects(Player p)
     {
       p.manaFlower = true; 
       p.chatText = "we got a cheater!";
        }
    public override void VanityEffects(Player player)   
    {
       Dust.NewDust;
    }
  
   }
}
 
Thanks's I'll try this and let you know if it works.
[DOUBLEPOST=1430575101,1430574531][/DOUBLEPOST]Ok I tried getting it to work but it's not taking here is my code:

Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using TAPI;
using Terraria;
namespace Moreitems.Items
{
   public class Cheat : ModItem
   {
  public override void Effects(Player p)
     {
       p.manaFlower = true;
       p.chatText = "we got a cheater!";
        }
    public override void VanityEffects(Player player)  
    {
       Dust.NewDust;
    }
 
   }
}
You need to call the code that creates your custom dust, not type Dust.NewDust. For example, if you copy the stuff from my tutorial, you would type:
BluemagicDust.CreateSpectreDust(player.position.X, player.position.Y, player.width, player.height)
 
You need to call the code that creates your custom dust, not type Dust.NewDust. For example, if you copy the stuff from my tutorial, you would type:
BluemagicDust.CreateSpectreDust(player.position.X, player.position.Y, player.width, player.height)

Oh, I didn't know that.
 
hi bluemagic! Nice tuttorial though! But I have a qquestion, how can i make my dust like animated? Like the projectile when you fire a rainbow rod? You know like the dust particles that emit rainbow light? That would be really nice!
 
Back
Top Bottom