tAPI [Tutorial] Projectile Guide and Implementation

Mr. Sin Costan honestly do not really understand what he had seen in the .cs file :sigh:
Ok, I'll explain it here then...

First off, you need your projectile json file (a given...). So I'll just use the example from the zip as the example.

Code:
{
    "displayName": "Flame Blast", 
    "size": [8, 42],  
    "scale": 1, 
    "aiStyle": 0, //Gonna use this for a custom AI (since aiStyle 0 does nothing)
    "timeLeft": 180,
    "friendly": true, 
    "hostile": false, 
    "tileCollide": true, 
    "ignoreWater": false,
    "frameCount": 3 //How many frames are there in the image, in this case it is 3 images
}

Now we need our .cs file, FlameBlast.cs.

Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace MPT.Projectiles
{
    public class FlameBlast : ModProjectile
    {
        public override void AI()
        {
            projectile.light = 5f; //Makes the projectile light
            projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f; //Makes sure the projectile rotates so it is pointing at where you are shooting.
            if(projectile.frameCounter < 20) //If the frame's counter is less than 20.
            {
                projectile.frame = 2; //Set it to the 3rd frame, since the frames go from 0 to 2.
                if(projectile.damage <= 100) //Increases the projectile damage if it is less than or equal to 100
                    projectile.damage += 1;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.01f; //increases the velocity by 1.01 times.
                projectile.velocity.X *= 1.01f;
            }
            else if(projectile.frameCounter >= 20 && projectile.frameCounter < 50) //If the projectile's frame counter greater than or equal to 20 and less than 50
            {
                projectile.frame = 1; //Set the frame to the second frame
                if(projectile.damage <= 100) //Increase the damage again
                    projectile.damage += 2; 
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.02f; //Increase velocity even further
                projectile.velocity.X *= 1.02f;
                int DustID1 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width/2 + 4, projectile.height/2 + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f); //Add Dust to it too
                Main.dust[DustID1].noGravity = true;
            }
            else //If the frame counter is something other than the two statements
            {
                projectile.frame = 0; //Set the frame to the first frame
                if(projectile.damage <= 100) //Increase damage even further
                    projectile.damage += 3;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.03f; //Increase speed even further
                projectile.velocity.X *= 1.03f;
                int DustID2 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width + 4, projectile.height + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f); //Add dust
                Main.dust[DustID2].noGravity = true;
            }
            projectile.frameCounter++; //A seperate counter used for animation.
        }
    }
}

So to top it all off, all you need to know from this example is that you need one property in the json file and about 2 properties in your cs file.

Code:
In the .json file
    - "frameCount": int frameNumber, //How many frames are there in your texture

in the .cs file
   - frame = int frameNumber; //Select the certain frame to show, goes from 0 to the frameCount minus 1 (0, frameCount - 1)
   - int frameCounter; //The counter to help you animate. (like a stop watch)

And here is one last example, only with the AI() hook though. Let's pretend I already did all the JSON file, with a frameCount of 4 this time and have it animate infinitely.

Code:
public override void AI()
[
    projectile.frameCounter++; //Make the counter go up, just remember that each time it goes through the AI hook, it is 1/60 of a second, so you are counting by 1/60 of a second.
    if(projectile.frameCounter < 10) //If the counter is less than 10
    {
        projectile.frame = 0; //Set it to the first frame
    }
    else if (projectile.frameCounter >= 10 && projectile.frameCounter < 20) //If the frameCounter is greater than or equal to 10 and less than 20...
    {
        projectile.frame = 1; //Set it to the second frame
    }
    else if (projectile.frameCounter >= 20 && projectile.frameCounter < 30) //If the frameCounter is greater than or equal to 20 and less than 30....
    {
        projectile.frame = 2; //Set it to the third frame
    }
    else if (projectile.frameCounter >= 30 && projectile.frameCounter < 40) //If the frameCounter is greater than or equal to 30 and less than 40...
    {
        projectile.frame = 3; //Set it to the fourth frame
    }
    else //Let's just say this assumes that the frameCounter is greater than or equal to 40.
    {
        projectile.frame = 0; //Reset it to the first frame
        projectile.frameCounter = 0; //Reset the counter so it goes back to the beginning
    }
}
 
@Sin Costan Are You Ever Going To Update This Tutorial?
 
Ok, I'll explain it here then...

First off, you need your projectile json file (a given...). So I'll just use the example from the zip as the example.

Code:
{
    "displayName": "Flame Blast",
    "size": [8, 42], 
    "scale": 1,
    "aiStyle": 0, //Gonna use this for a custom AI (since aiStyle 0 does nothing)
    "timeLeft": 180,
    "friendly": true,
    "hostile": false,
    "tileCollide": true,
    "ignoreWater": false,
    "frameCount": 3 //How many frames are there in the image, in this case it is 3 images
}

Now we need our .cs file, FlameBlast.cs.

Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace MPT.Projectiles
{
    public class FlameBlast : ModProjectile
    {
        public override void AI()
        {
            projectile.light = 5f; //Makes the projectile light
            projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f; //Makes sure the projectile rotates so it is pointing at where you are shooting.
            if(projectile.frameCounter < 20) //If the frame's counter is less than 20.
            {
                projectile.frame = 2; //Set it to the 3rd frame, since the frames go from 0 to 2.
                if(projectile.damage <= 100) //Increases the projectile damage if it is less than or equal to 100
                    projectile.damage += 1;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.01f; //increases the velocity by 1.01 times.
                projectile.velocity.X *= 1.01f;
            }
            else if(projectile.frameCounter >= 20 && projectile.frameCounter < 50) //If the projectile's frame counter greater than or equal to 20 and less than 50
            {
                projectile.frame = 1; //Set the frame to the second frame
                if(projectile.damage <= 100) //Increase the damage again
                    projectile.damage += 2;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.02f; //Increase velocity even further
                projectile.velocity.X *= 1.02f;
                int DustID1 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width/2 + 4, projectile.height/2 + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f); //Add Dust to it too
                Main.dust[DustID1].noGravity = true;
            }
            else //If the frame counter is something other than the two statements
            {
                projectile.frame = 0; //Set the frame to the first frame
                if(projectile.damage <= 100) //Increase damage even further
                    projectile.damage += 3;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.03f; //Increase speed even further
                projectile.velocity.X *= 1.03f;
                int DustID2 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width + 4, projectile.height + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f); //Add dust
                Main.dust[DustID2].noGravity = true;
            }
            projectile.frameCounter++; //A seperate counter used for animation.
        }
    }
}

So to top it all off, all you need to know from this example is that you need one property in the json file and about 2 properties in your cs file.

Code:
In the .json file
    - "frameCount": int frameNumber, //How many frames are there in your texture

in the .cs file
   - frame = int frameNumber; //Select the certain frame to show, goes from 0 to the frameCount minus 1 (0, frameCount - 1)
   - int frameCounter; //The counter to help you animate. (like a stop watch)

And here is one last example, only with the AI() hook though. Let's pretend I already did all the JSON file, with a frameCount of 4 this time and have it animate infinitely.

Code:
public override void AI()
[
    projectile.frameCounter++; //Make the counter go up, just remember that each time it goes through the AI hook, it is 1/60 of a second, so you are counting by 1/60 of a second.
    if(projectile.frameCounter < 10) //If the counter is less than 10
    {
        projectile.frame = 0; //Set it to the first frame
    }
    else if (projectile.frameCounter >= 10 && projectile.frameCounter < 20) //If the frameCounter is greater than or equal to 10 and less than 20...
    {
        projectile.frame = 1; //Set it to the second frame
    }
    else if (projectile.frameCounter >= 20 && projectile.frameCounter < 30) //If the frameCounter is greater than or equal to 20 and less than 30....
    {
        projectile.frame = 2; //Set it to the third frame
    }
    else if (projectile.frameCounter >= 30 && projectile.frameCounter < 40) //If the frameCounter is greater than or equal to 30 and less than 40...
    {
        projectile.frame = 3; //Set it to the fourth frame
    }
    else //Let's just say this assumes that the frameCounter is greater than or equal to 40.
    {
        projectile.frame = 0; //Reset it to the first frame
        projectile.frameCounter = 0; //Reset the counter so it goes back to the beginning
    }
}

Many Thanks! :')
 
How to use and manipulate the AI Style Terraria Vanilla?

I know I'm asking questions, but I'm very curious, this is new to me and I like to learn more! Sorry for the inconvenience and thank you very much for the replies received, also it has business to attend to, so I'm going to have the patience to wait for answers.

PS: Sorry for my bad english, i speak spanish.. L0L! :):happy::D;):p:naughty:
 
How to use and manipulate the AI Style Terraria Vanilla?

I know I'm asking questions, but I'm very curious, this is new to me and I like to learn more! Sorry for the inconvenience and thank you very much for the replies received, also it has business to attend to, so I'm going to have the patience to wait for answers.

PS: Sorry for my bad english, i speak spanish.. L0L! :):happy::D;):p:naughty:
I think you can just override the AI() method, and it will modify whatever the ai is, but still use the vanilla ai, if you want to write a custom ai, you just set the type to -1.
 
I think you can just override the AI() method, and it will modify whatever the ai is, but still use the vanilla ai, if you want to write a custom ai, you just set the type to -1.

I don't understand..
 
I don't understand..
Basically, all I have said about Modifications of Vanilla AI Styles is that you can add to them, for example, you could add light to a projectile aiStyle that usually doesn't have it lighted. Of course you can stick your additions inside of the regular AI() hook, but you should probably stick it in the PostAI() hook.

EDIT: If you have good programming knowledge and an understanding on the way Terraria does things, you can of course go through the vanilla AI style coding which I have provided in the OP thread under "AI style list.txt". From there you can edit the code to your liking.
 
Basically, all I have said about Modifications of Vanilla AI Styles is that you can add to them, for example, you could add light to a projectile aiStyle that usually doesn't have it lighted. Of course you can stick your additions inside of the regular AI() hook, but you should probably stick it in the PostAI() hook.

EDIT: If you have good programming knowledge and an understanding on the way Terraria does things, you can of course go through the vanilla AI style coding which I have provided in the OP thread under "AI style list.txt". From there you can edit the code to your liking.


Ok, thanks..
 
How to make an explosive projectile? (without destroying anything)
 
How to make an explosive projectile? (without destroying anything)
You can just add this code to your projectile to have that explosion effect.

Code:
public override void PostKill()
        {
            Main.PlaySound(14, (int)projectile.position.X, (int)projectile.position.Y, 2);
            for (int num369 = 0; num369 < 20; num369++)
            {
                int num370 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 31, 0f, 0f, 100, default(Color), 1.5f);
                Main.dust[num370].velocity *= 1.4f;
            }
            for (int num371 = 0; num371 < 10; num371++)
            {
                int num372 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 6, 0f, 0f, 100, default(Color), 2.5f);
                Main.dust[num372].noGravity = true;
                Main.dust[num372].velocity *= 5f;
                num372 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 6, 0f, 0f, 100, default(Color), 1.5f);
                Main.dust[num372].velocity *= 3f;
            }
            int num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64), 1f);
            Main.gore[num373].velocity *= 0.4f;
            Gore gore85 = Main.gore[num373];
            gore85.velocity.X = gore85.velocity.X + 1f;
            Gore gore86 = Main.gore[num373];
            gore86.velocity.Y = gore86.velocity.Y + 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64), 1f);
            Main.gore[num373].velocity *= 0.4f;
            Gore gore87 = Main.gore[num373];
            gore87.velocity.X = gore87.velocity.X - 1f;
            Gore gore88 = Main.gore[num373];
            gore88.velocity.Y = gore88.velocity.Y + 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64), 1f);
            Main.gore[num373].velocity *= 0.4f;
            Gore gore89 = Main.gore[num373];
            gore89.velocity.X = gore89.velocity.X + 1f;
            Gore gore90 = Main.gore[num373];
            gore90.velocity.Y = gore90.velocity.Y - 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64), 1f);
            Main.gore[num373].velocity *= 0.4f;
            Gore gore91 = Main.gore[num373];
            gore91.velocity.X = gore91.velocity.X - 1f;
            Gore gore92 = Main.gore[num373];
            gore92.velocity.Y = gore92.velocity.Y - 1f;
        }

I'm going to update the OP with this also, because a lot of people wonder about this.
 
You can just add this code to your projectile to have that explosion effect.

Code:
public override void PostKill()
        {
            Main.PlaySound(14, (int)projectile.position.X, (int)projectile.position.Y, 2);
            for (int num369 = 0; num369 < 20; num369++)
            {
                int num370 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 31, 0f, 0f, 100, default(Color), 1.5f);
                Main.dust[num370].velocity *= 1.4f;
            }
            for (int num371 = 0; num371 < 10; num371++)
            {
                int num372 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 6, 0f, 0f, 100, default(Color), 2.5f);
                Main.dust[num372].noGravity = true;
                Main.dust[num372].velocity *= 5f;
                num372 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 6, 0f, 0f, 100, default(Color), 1.5f);
                Main.dust[num372].velocity *= 3f;
            }
            int num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64), 1f);
            Main.gore[num373].velocity *= 0.4f;
            Gore gore85 = Main.gore[num373];
            gore85.velocity.X = gore85.velocity.X + 1f;
            Gore gore86 = Main.gore[num373];
            gore86.velocity.Y = gore86.velocity.Y + 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64), 1f);
            Main.gore[num373].velocity *= 0.4f;
            Gore gore87 = Main.gore[num373];
            gore87.velocity.X = gore87.velocity.X - 1f;
            Gore gore88 = Main.gore[num373];
            gore88.velocity.Y = gore88.velocity.Y + 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64), 1f);
            Main.gore[num373].velocity *= 0.4f;
            Gore gore89 = Main.gore[num373];
            gore89.velocity.X = gore89.velocity.X + 1f;
            Gore gore90 = Main.gore[num373];
            gore90.velocity.Y = gore90.velocity.Y - 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64), 1f);
            Main.gore[num373].velocity *= 0.4f;
            Gore gore91 = Main.gore[num373];
            gore91.velocity.X = gore91.velocity.X - 1f;
            Gore gore92 = Main.gore[num373];
            gore92.velocity.Y = gore92.velocity.Y - 1f;
        }

I'm going to update the OP with this also, because a lot of people wonder about this.

THANK YOU! And.. How to make a projectile that explodes after a few seconds? (like dynamite)
 
THANK YOU! And.. How to make a projectile that explodes after a few seconds? (like dynamite)
You can try this,
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using TAPI;

namespace yourmod
{
public class your projectile:ModProjectile
{
public int KillTimer = 0;
public override void AI()
{
KillTimer++;

if(KillTimer == 10)
{
projectile.kill;
}
}
}
}

and just keep the post kill, or rather than putting it under postKill, you can put SinCostan's code in the if(KillTimer == 10)

also, you'll want to reset the kill timer, say when the projectile dies
 
THANK YOU! And.. How to make a projectile that explodes after a few seconds? (like dynamite)
If you want it to last a couple of seconds before contacting an enemy like the dynamite, just use the bouncing code from the OP and then adjust the timeLeft to however long you want it to last.
 
I Dont Think These Are Coming Soon
upload_2015-6-9_21-44-22.png
 
Yeah, I better start working on those...
Ok, after a little bit of time I decided to update two of the 3 missing stuff... Enjoy! Also, why am I quoting myself?
 
U Screwed Up On The Cursed Flames Powder.cs In The Tut
 
Back
Top Bottom