• Journey's End on PC - Find info here and here. Please report bugs and issues for PC 1.4 and 1.4.1 to Re-Logic here.
  • Journey's End on Mobile - Find info here. Report bugs for Mobile 1.4 to DR Studios at this link and give as much detail as possible.
  • 1.4 will bring many changes to the PC version. We strongly advise making plans to back up your worlds and players prior to updating your game. More details here.
  • Console and Switch - The latest news can be found here. To report a bug, please use this link.

tModLoader [Tutorial] Projectile Guide and Implementation: tModLoader Edition

ubernovaburst

Terrarian
Uhm i need help with a few things pls.

First thing:

I made a Custom bow wich i want to turn wooden arrows to custom arrows.

Second thing:

I want these Custom Arrows to home enemies.

Third thing:

The Custom bow i made shoots 3 arrows but i want the to shoot .. like .. denser together to eachother .


Heres the Code for my bow:

using Terraria;
using System;
using Terraria.ID;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Terraria.ModLoader;

namespace Pilavius.Items
{
public class MonsterBow : ModItem
{
public override void SetStaticDefaults()
{
DisplayName.SetDefault("Monster Bow");
Tooltip.SetDefault("Transforms Wooden arrows in Monster Eyes!");
}

public override void SetDefaults()
{
item.damage = 250;
item.noMelee = true;
item.ranged = true;
item.width = 69;
item.height = 40;
item.useTime = 10;
item.useAnimation = 10;
item.useStyle = 5;
item.shoot = mod.ProjectileType("MonsterEye");
item.knockBack = 5;
item.value = 1000;
item.rare = 9;
item.UseSound = SoundID.Item97;
item.autoReuse = true;
item.shootSpeed = 65f;

}
public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack)
{
float numberProjectiles = 3; // This defines how many projectiles to shot
float rotation = MathHelper.ToRadians(45);
position += Vector2.Normalize(new Vector2(speedX, speedY)) * 15f; //this defines the distance of the projectiles form the player when the projectile spawns
for (int i = 0; i < numberProjectiles; i++)
{
Vector2 perturbedSpeed = new Vector2(speedX, speedY).RotatedBy(MathHelper.Lerp(-rotation, rotation, i / (numberProjectiles - 1))) * .2f; // This defines the projectile roatation and speed. .4f == projectile speed
Projectile.NewProjectile(position.X, position.Y, perturbedSpeed.X, perturbedSpeed.Y, type, damage, knockBack, player.whoAmI);
}
return false;
}

public override void AddRecipes()
{
ModRecipe recipe = new ModRecipe(mod);
recipe.AddIngredient(ItemID.TitaniumBar, 25);
recipe.AddIngredient(ItemID.DemoniteBar, 50);
recipe.AddIngredient(ItemID.ShadowScale, 20);
recipe.AddTile(TileID.MythrilAnvil);
recipe.SetResult(this);
recipe.AddRecipe();
}
}
}





Heres the Code for my Arrow:

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace Pilavius.Projectiles
{
public class MonsterEye : ModProjectile
{
public override void SetDefaults()
{
projectile.width = 25;
projectile.height = 25;
projectile.aiStyle = 0; //How the projectile works
projectile.tileCollide = true;
projectile.friendly = true;
projectile.penetrate = 3; //this is the projectile penetration
projectile.hostile = false;
projectile.light = 1.00f; // projectile light
projectile.ranged = true; //this make the projectile do magic damage
projectile.tileCollide = true; //this make that the projectile does not go thru walls
projectile.ignoreWater = true;
projectile.light = 0.30f;
projectile.timeLeft = 400;
aiType = 1;
}

public override void AI()
{
for (int i = 0; i < 200; i++)
{
NPC target = Main.npc;
//If the npc is hostile
if (NPC.)
{
//Get the shoot trajectory from the projectile and target
float shootToX = target.position.X + (float)target.width * 0.5f - projectile.Center.X;
float shootToY = target.position.Y - projectile.Center.Y;
float distance = (float)System.Math.Sqrt((double)(shootToX * shootToX + shootToY * shootToY));

//If the distance between the live targeted npc and the projectile is less than 480 pixels
if (distance < 480f && !target.friendly && target.active)
{
//Divide the factor, 3f, which is the desired velocity
distance = 3f / distance;

//Multiply the distance by a multiplier if you wish the projectile to have go faster
shootToX *= distance * 5;
shootToY *= distance * 5;

//Set the velocities to the shoot values
projectile.velocity.X = shootToX;
projectile.velocity.Y = shootToY;
}
}
}

Lighting.AddLight(projectile.Center, 2.5f, 0.4f, 4.0f);
//this is projectile dust
int DustID27 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 1f), projectile.width + 1, projectile.height + 1, mod.DustType("SDust"), projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 55, default(Color), 2.9f);
Main.dust[DustID27].noGravity = true;
//this make that the projectile faces the right way
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f;
projectile.localAI[0] += 1f;
projectile.alpha = (int)projectile.localAI[0] * 2;

}
}
}


EDIT: Uhm I got the shots "denser" to each other so thats solved. I also got them to home enemies. Now i just wanted to ask if it is possible to adjust the homing, so that it doesnt just instantly flies towards the enemy whenever its sighted but that it makes a curve just like with the specter staff maybe just a bit faster and also if there is some way to make the projectiles attack the parts of the boss wich have lifebars and not just fly inside the middle of the boss AND if its possible to make the projectile only see enemies when there is no wall or tile in between them. And the last problem is the thing with custom bow and arrows still. Thx in advance.
 
Last edited:

Daniel?

Terrarian
How do you make a sword that shoots like four spectre souls that are slow and not really really fast just slower than normal but fast enough to catch up with an enemy the command here that i tried to copy didn't work there are red lines under player and Vector2 so please help me to get another way to shoot four projectiles thanks.
[doublepost=1500363722,1500363575][/doublepost]Oh yeah and can someone help me with a modded projectile that homes just leave the code here thanks
 

Daniel?

Terrarian
Hey can someone please help me out here i want my sword to shoot like 4 projectiles at one i'm using lost souls projectile from spectre staff to make the projectiles homing but i need to know how i can make it shoot 4 in an arch shape i have tried that other command for it to shoot 4 or less projectiles byt when i paste it red lines coming under vector2 and player and all these other things heres the command

  1. //--------------------------------------------------Shotgun style: Multiple Projectiles, Random spread ---------------------------------------------------------
  2. public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack)
  3. {
  4. int numberProjectiles = 4 + Main.rand.Next(2); //This defines how many projectiles to shot. 4 + Main.rand.Next(2)= 4 or 5 shots
  5. for (int i = 0; i < numberProjectiles; i++)
  6. {
  7. Vector2 perturbedSpeed = new Vector2(speedX, speedY).RotatedByRandom(MathHelper.ToRadians(30)); // This defines the projectiles random spread . 30 degree spread.
  8. Projectile.NewProjectile(position.X, position.Y, perturbedSpeed.X, perturbedSpeed.Y, type, damage, knockBack, player.whoAmI);
  9. }
  10. return false;
  11. }
  12. }
  13. }
if someone could help me i would be greatly thankfull
 

Daniel?

Terrarian
Can someone plz help me with my projectile speed of my weapon when i use the id for spectre staff projectile and use it it gos way way too fast for my liking i want it to go normal speed like when you use the spectre staff heres the code for it




using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using Microsoft.Xna.Framework;

namespace Packed.Items
{
public class HauntedSoulChaser : ModItem
{
//public object Projectile { get; private set; }

public override void SetStaticDefaults()
{
DisplayName.SetDefault("HauntedSoulChaser");
Tooltip.SetDefault("The noises of the haunted evil is horrible.");
}
public override void SetDefaults()
{
item.damage = 280;
item.melee = true;
item.width = 32;
item.height = 32;
item.useTime = 15;
item.useAnimation = 30;
item.useStyle = 1;
item.knockBack = 10;
item.value = 10000;
item.rare = 10;
item.UseSound = SoundID.Item1;
item.autoReuse = true;
item.shoot = mod.ProjectileType("Projectile1");
item.shootSpeed = 40f;

}

//--------------------------------------------------Shotgun style: Multiple Projectiles, Random spread ---------------------------------------------------------
public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack)
{
int numberProjectiles = 4 + Main.rand.Next(2); //This defines how many projectiles to shot. 4 + Main.rand.Next(2)= 4 or 5 shots
for (int i = 0; i < numberProjectiles; i++)
{
Vector2 perturbedSpeed = new Vector2(speedX , speedY).RotatedByRandom(MathHelper.ToRadians(30)); // This defines the projectiles random spread . 30 degree spread.
Projectile.NewProjectile(position.X, position.Y, perturbedSpeed.X, perturbedSpeed.Y, type, damage, knockBack, player.whoAmI);
}
return false;
}
public override void AddRecipes()
{
ModRecipe recipe = new ModRecipe(mod);
recipe.AddIngredient(ItemID.TerraBlade, 1);
recipe.AddIngredient(ItemID.SpectreStaff, 1);
recipe.AddIngredient(ItemID.SoulofLight, 50);

recipe.AddTile(TileID.MythrilAnvil);
recipe.SetResult(this);
recipe.AddRecipe();

}
}


it would be very helpful if someone could help me thanks
 

Sin Costan

Eye of Cthulhu
Can someone plz help me with my projectile speed of my weapon when i use the id for spectre staff projectile and use it it gos way way too fast for my liking i want it to go normal speed like when you use the spectre staff heres the code for it




using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using Microsoft.Xna.Framework;

namespace Packed.Items
{
public class HauntedSoulChaser : ModItem
{
//public object Projectile { get; private set; }

public override void SetStaticDefaults()
{
DisplayName.SetDefault("HauntedSoulChaser");
Tooltip.SetDefault("The noises of the haunted evil is horrible.");
}
public override void SetDefaults()
{
item.damage = 280;
item.melee = true;
item.width = 32;
item.height = 32;
item.useTime = 15;
item.useAnimation = 30;
item.useStyle = 1;
item.knockBack = 10;
item.value = 10000;
item.rare = 10;
item.UseSound = SoundID.Item1;
item.autoReuse = true;
item.shoot = mod.ProjectileType("Projectile1");
item.shootSpeed = 40f;

}

//--------------------------------------------------Shotgun style: Multiple Projectiles, Random spread ---------------------------------------------------------
public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack)
{
int numberProjectiles = 4 + Main.rand.Next(2); //This defines how many projectiles to shot. 4 + Main.rand.Next(2)= 4 or 5 shots
for (int i = 0; i < numberProjectiles; i++)
{
Vector2 perturbedSpeed = new Vector2(speedX , speedY).RotatedByRandom(MathHelper.ToRadians(30)); // This defines the projectiles random spread . 30 degree spread.
Projectile.NewProjectile(position.X, position.Y, perturbedSpeed.X, perturbedSpeed.Y, type, damage, knockBack, player.whoAmI);
}
return false;
}
public override void AddRecipes()
{
ModRecipe recipe = new ModRecipe(mod);
recipe.AddIngredient(ItemID.TerraBlade, 1);
recipe.AddIngredient(ItemID.SpectreStaff, 1);
recipe.AddIngredient(ItemID.SoulofLight, 50);

recipe.AddTile(TileID.MythrilAnvil);
recipe.SetResult(this);
recipe.AddRecipe();

}
}


it would be very helpful if someone could help me thanks
Well, that's probably because "shootSpeed" is 40f, which is pretty damn fast. Probably should stick to 5f - 20f range.

Hey can someone please help me out here i want my sword to shoot like 4 projectiles at one i'm using lost souls projectile from spectre staff to make the projectiles homing but i need to know how i can make it shoot 4 in an arch shape i have tried that other command for it to shoot 4 or less projectiles byt when i paste it red lines coming under vector2 and player and all these other things heres the command

  1. //--------------------------------------------------Shotgun style: Multiple Projectiles, Random spread ---------------------------------------------------------
  2. public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack)
  3. {
  4. int numberProjectiles = 4 + Main.rand.Next(2); //This defines how many projectiles to shot. 4 + Main.rand.Next(2)= 4 or 5 shots
  5. for (int i = 0; i < numberProjectiles; i++)
  6. {
  7. Vector2 perturbedSpeed = new Vector2(speedX, speedY).RotatedByRandom(MathHelper.ToRadians(30)); // This defines the projectiles random spread . 30 degree spread.
  8. Projectile.NewProjectile(position.X, position.Y, perturbedSpeed.X, perturbedSpeed.Y, type, damage, knockBack, player.whoAmI);
  9. }
  10. return false;
  11. }
  12. }
  13. }
if someone could help me i would be greatly thankfull
You probably don't have a certain "using" declaration... Just stick these on the top, if you don't already have them. Too lazy to give you precise ones so I'll just give you the stuff I always stuff at the top.

Code:
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;
How do I make a projectile emit light (I want it to be a green-ish colour) and dust? (Using in-game dust).
Reading the tutorial might help, even downloading MPT.zip might help
Uhm i need help with a few things pls.

First thing:

I made a Custom bow wich i want to turn wooden arrows to custom arrows.

Second thing:

I want these Custom Arrows to home enemies.

Third thing:

The Custom bow i made shoots 3 arrows but i want the to shoot .. like .. denser together to eachother .


Heres the Code for my bow:

using Terraria;
using System;
using Terraria.ID;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Terraria.ModLoader;

namespace Pilavius.Items
{
public class MonsterBow : ModItem
{
public override void SetStaticDefaults()
{
DisplayName.SetDefault("Monster Bow");
Tooltip.SetDefault("Transforms Wooden arrows in Monster Eyes!");
}

public override void SetDefaults()
{
item.damage = 250;
item.noMelee = true;
item.ranged = true;
item.width = 69;
item.height = 40;
item.useTime = 10;
item.useAnimation = 10;
item.useStyle = 5;
item.shoot = mod.ProjectileType("MonsterEye");
item.knockBack = 5;
item.value = 1000;
item.rare = 9;
item.UseSound = SoundID.Item97;
item.autoReuse = true;
item.shootSpeed = 65f;

}
public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack)
{
float numberProjectiles = 3; // This defines how many projectiles to shot
float rotation = MathHelper.ToRadians(45);
position += Vector2.Normalize(new Vector2(speedX, speedY)) * 15f; //this defines the distance of the projectiles form the player when the projectile spawns
for (int i = 0; i < numberProjectiles; i++)
{
Vector2 perturbedSpeed = new Vector2(speedX, speedY).RotatedBy(MathHelper.Lerp(-rotation, rotation, i / (numberProjectiles - 1))) * .2f; // This defines the projectile roatation and speed. .4f == projectile speed
Projectile.NewProjectile(position.X, position.Y, perturbedSpeed.X, perturbedSpeed.Y, type, damage, knockBack, player.whoAmI);
}
return false;
}

public override void AddRecipes()
{
ModRecipe recipe = new ModRecipe(mod);
recipe.AddIngredient(ItemID.TitaniumBar, 25);
recipe.AddIngredient(ItemID.DemoniteBar, 50);
recipe.AddIngredient(ItemID.ShadowScale, 20);
recipe.AddTile(TileID.MythrilAnvil);
recipe.SetResult(this);
recipe.AddRecipe();
}
}
}





Heres the Code for my Arrow:

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace Pilavius.Projectiles
{
public class MonsterEye : ModProjectile
{
public override void SetDefaults()
{
projectile.width = 25;
projectile.height = 25;
projectile.aiStyle = 0; //How the projectile works
projectile.tileCollide = true;
projectile.friendly = true;
projectile.penetrate = 3; //this is the projectile penetration
projectile.hostile = false;
projectile.light = 1.00f; // projectile light
projectile.ranged = true; //this make the projectile do magic damage
projectile.tileCollide = true; //this make that the projectile does not go thru walls
projectile.ignoreWater = true;
projectile.light = 0.30f;
projectile.timeLeft = 400;
aiType = 1;
}

public override void AI()
{
for (int i = 0; i < 200; i++)
{
NPC target = Main.npc;
//If the npc is hostile
if (NPC.)
{
//Get the shoot trajectory from the projectile and target
float shootToX = target.position.X + (float)target.width * 0.5f - projectile.Center.X;
float shootToY = target.position.Y - projectile.Center.Y;
float distance = (float)System.Math.Sqrt((double)(shootToX * shootToX + shootToY * shootToY));

//If the distance between the live targeted npc and the projectile is less than 480 pixels
if (distance < 480f && !target.friendly && target.active)
{
//Divide the factor, 3f, which is the desired velocity
distance = 3f / distance;

//Multiply the distance by a multiplier if you wish the projectile to have go faster
shootToX *= distance * 5;
shootToY *= distance * 5;

//Set the velocities to the shoot values
projectile.velocity.X = shootToX;
projectile.velocity.Y = shootToY;
}
}
}

Lighting.AddLight(projectile.Center, 2.5f, 0.4f, 4.0f);
//this is projectile dust
int DustID27 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 1f), projectile.width + 1, projectile.height + 1, mod.DustType("SDust"), projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 55, default(Color), 2.9f);
Main.dust[DustID27].noGravity = true;
//this make that the projectile faces the right way
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f;
projectile.localAI[0] += 1f;
projectile.alpha = (int)projectile.localAI[0] * 2;

}
}
}


EDIT: Uhm I got the shots "denser" to each other so thats solved. I also got them to home enemies. Now i just wanted to ask if it is possible to adjust the homing, so that it doesnt just instantly flies towards the enemy whenever its sighted but that it makes a curve just like with the specter staff maybe just a bit faster and also if there is some way to make the projectiles attack the parts of the boss wich have lifebars and not just fly inside the middle of the boss AND if its possible to make the projectile only see enemies when there is no wall or tile in between them. And the last problem is the thing with custom bow and arrows still. Thx in advance.
So uhh, you just need to have it check if the NPC part isn't immune to damage and for your homing problem, you're gonna need to change the velocity based of increased/decreased angle, not really sure how you would do that, will think about it later, probably not going to be able to get an answer, so I might not post anything at all.

Hello, how would I make a weapon "charge" and shoot a different projectile depending on how long I charged?
I.E Like the Charged Blaster Cannon:
Less than 1 full second: Small, non-piercing orb.
After 1 second: Larger, faster, multiple-piercing orb.
After 3 seconds: Large, solid beam.
Edit: Also, how do I add dust particles to the hand when the weapon is being used? Similar to the Nebula Blaze, but only when the weapon is being used.
It's complex, check this: https://github.com/Harrison-Jue/COFP/blob/master/Projectiles/Magic/RainbowDevastationRod.cs
 

SuperDude9k

Terrarian
I have a similar question to ubernovablaster; how would I go about making a weapon turn ammo into custom ammo? I've made a couple guns and custom ammo, but I want one of the guns to turn ammo into my custom ammo. I've looked all over, and could not for the life of me find an answer.
 

Joshua8201

Terrarian
@Sin Costan I downloaded the COFP Mod, and reloaded my mods, but this comes up:
Missing mod: COFP/Items/Accessories/ShadowBloodVeil
at Terraria.ModLoader.ModLoader.GetTexture(String name)
at Terraria.ModLoader.ModItem.AutoStaticDefaults()
at Terraria.ModLoader.Mod.SetupContent()
at Terraria.ModLoader.ModLoader.do_Load(Object threadContext)
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace COFP.Items.Accessories
{
    public class ShadowBloodVeil : ModItem
    {
        public override void SetDefaults()
        {
            item.width = 20;
            item.height = 20;
            item.value = 11000;
            item.rare = 5;
            item.accessory = true;
            item.value = Item.sellPrice(0, 1, 0, 0);
        }
       
        public override void SetStaticDefaults()
        {
            DisplayName.SetDefault("Shadow Blood Veil");
            Tooltip.SetDefault("Continuously gives a barrier that drains enemy health and gain it as your own.");
        }
       
        public override void AddRecipes()
        {
            ModRecipe recipe = new ModRecipe(mod);
            recipe.AddIngredient(ItemID.Silk, 10);
            recipe.AddRecipeGroup("EvilBar", 10);
            recipe.AddRecipeGroup("EvilSubstance", 30);
            recipe.AddRecipeGroup("EvilPowder", 30);
            recipe.SetResult(this);
            recipe.AddRecipe();
        }
    }
}
I didn't change it or anything, so what could be the problem?
 

Sin Costan

Eye of Cthulhu
I have a similar question to ubernovablaster; how would I go about making a weapon turn ammo into custom ammo? I've made a couple guns and custom ammo, but I want one of the guns to turn ammo into my custom ammo. I've looked all over, and could not for the life of me find an answer.
Just check MPT, look at ExampleGun.cs, look inside the Shoot() hook, remove everything but the line that says "Projectile.NewProjectile(position.X, position.Y, vX, vY, type, damage, knockBack, Main.myPlayer);", replace "vX" with "speedX" and "vY" with "speedY" and type with "mod.ProjectileType("Whatever your thing is called")" and keep the line that says "return false;"

So something like this...

Code:
        public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack) 
        {
            Projectile.NewProjectile(position.X, position.Y, speedX, speedY, mod.ProjectileType("Replace this text with something else, preferably your projectile name"), damage, knockBack, Main.myPlayer);
            return false; //Makes sure to not spawn the original projectile
        }
Hell you could literally just say this instead and it should still work.

Code:
        public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack) 
        {
            type = mod.ProjectileType("The Projectile Thing");
            return true; 
        }
@Sin Costan I downloaded the COFP Mod, and reloaded my mods, but this comes up:
Missing mod: COFP/Items/Accessories/ShadowBloodVeil
at Terraria.ModLoader.ModLoader.GetTexture(String name)
at Terraria.ModLoader.ModItem.AutoStaticDefaults()
at Terraria.ModLoader.Mod.SetupContent()
at Terraria.ModLoader.ModLoader.do_Load(Object threadContext)
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace COFP.Items.Accessories
{
    public class ShadowBloodVeil : ModItem
    {
        public override void SetDefaults()
        {
            item.width = 20;
            item.height = 20;
            item.value = 11000;
            item.rare = 5;
            item.accessory = true;
            item.value = Item.sellPrice(0, 1, 0, 0);
        }
      
        public override void SetStaticDefaults()
        {
            DisplayName.SetDefault("Shadow Blood Veil");
            Tooltip.SetDefault("Continuously gives a barrier that drains enemy health and gain it as your own.");
        }
      
        public override void AddRecipes()
        {
            ModRecipe recipe = new ModRecipe(mod);
            recipe.AddIngredient(ItemID.Silk, 10);
            recipe.AddRecipeGroup("EvilBar", 10);
            recipe.AddRecipeGroup("EvilSubstance", 30);
            recipe.AddRecipeGroup("EvilPowder", 30);
            recipe.SetResult(this);
            recipe.AddRecipe();
        }
    }
}
I didn't change it or anything, so what could be the problem?
Apparently it is missing a texture, it should be working, so I have no idea why it is not.

Code:
¯\_(ツ)_/¯
 

SuperDude9k

Terrarian
Just check MPT, look at ExampleGun.cs, look inside the Shoot() hook, remove everything but the line that says "Projectile.NewProjectile(position.X, position.Y, vX, vY, type, damage, knockBack, Main.myPlayer);", replace "vX" with "speedX" and "vY" with "speedY" and type with "mod.ProjectileType("Whatever your thing is called")" and keep the line that says "return false;"

So something like this...
I just wanted to say thanks for helping me and that I've gotten it working now. There's still a few kinks to work out, but I'm one step closer to having a mod I can be proud of.
 

Joshua8201

Terrarian
@Sin Costan
Code:
c:\Users\Joshua\Documents\My Games\Terraria\ModLoader\Mod Sources\JoshuasMod\Projectiles\DragonStorm\DragonStorm.cs(31,17) : error CS1061: 'Terraria.NPC' does not contain a definition for 'hostile' and no extension method 'hostile' accepting a first argument of type 'Terraria.NPC' could be found (are you missing a using directive or an assembly reference?)
Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace JoshuasMod.Projectiles.DragonStorm
{
    public class DragonStorm : ModProjectile
    {
        public override void SetDefaults()
        {
            projectile.CloneDefaults(ProjectileID.TerrarianBeam);
            projectile.damage = 1000;
            projectile.width = 34;    //The size of the width of the hitbox in pixels.
            projectile.height = 34;    //The size of the height of the hitbox in pixels.
            projectile.penetrate = -1;
            projectile.tileCollide = false;
            projectile.ignoreWater = true;
            projectile.melee = true;
            aiType = ProjectileID.TerrarianBeam;
        }
     
        public override void AI()
        {
            for(int i = 0; i < 200; i++)
            {
              NPC target = Main.npc[i];
              //If the npc is hostile
              if(target.hostile)
              {
                  //Get the shoot trajectory from the projectile and target
                  float shootToX = target.position.X + (float)target.width * 0.5f - projectile.Center.X;
                  float shootToY = target.position.Y - projectile.Center.Y;
                  float distance = (float)System.Math.Sqrt((double)(shootToX * shootToX + shootToY * shootToY));

                  //If the distance between the live targeted npc and the projectile is less than 480 pixels
                  if(distance < 480f && !target.friendly && target.active)
                  {
                      //Divide the factor, 3f, which is the desired velocity
                      distance = 3f / distance;
       
                      //Multiply the distance by a multiplier if you wish the projectile to have go faster
                      shootToX *= distance * 5;
                      shootToY *= distance * 5;

                      //Set the velocities to the shoot values
                      projectile.velocity.X = shootToX;
                      projectile.velocity.Y = shootToY;
                  }
              }
            }
            //This is what makes the projectile face the correct way.
            projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + MathHelper.ToRadians(135f);
            //This is what makes the projectile emit light.
            Lighting.AddLight(projectile.Center, 0f, 1f, 0f);     //This is the projectile light color R, G, B (Red, Green, Blue).
        }

        public override void OnHitNPC(NPC target, int damage, float knockback, bool crit)
        {
            target.AddBuff(BuffID.CursedInferno, 5 * 60);
        }
    }
}
I tried using your "Simple Homing AI" for my projectile, but I'm guessing it needs to be changed so it works with the latest update, because it's not working. :I
 

Sin Costan

Eye of Cthulhu
@Sin Costan
Code:
c:\Users\Joshua\Documents\My Games\Terraria\ModLoader\Mod Sources\JoshuasMod\Projectiles\DragonStorm\DragonStorm.cs(31,17) : error CS1061: 'Terraria.NPC' does not contain a definition for 'hostile' and no extension method 'hostile' accepting a first argument of type 'Terraria.NPC' could be found (are you missing a using directive or an assembly reference?)
Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace JoshuasMod.Projectiles.DragonStorm
{
    public class DragonStorm : ModProjectile
    {
        public override void SetDefaults()
        {
            projectile.CloneDefaults(ProjectileID.TerrarianBeam);
            projectile.damage = 1000;
            projectile.width = 34;    //The size of the width of the hitbox in pixels.
            projectile.height = 34;    //The size of the height of the hitbox in pixels.
            projectile.penetrate = -1;
            projectile.tileCollide = false;
            projectile.ignoreWater = true;
            projectile.melee = true;
            aiType = ProjectileID.TerrarianBeam;
        }
    
        public override void AI()
        {
            for(int i = 0; i < 200; i++)
            {
              NPC target = Main.npc[i];
              //If the npc is hostile
              if(target.hostile)
              {
                  //Get the shoot trajectory from the projectile and target
                  float shootToX = target.position.X + (float)target.width * 0.5f - projectile.Center.X;
                  float shootToY = target.position.Y - projectile.Center.Y;
                  float distance = (float)System.Math.Sqrt((double)(shootToX * shootToX + shootToY * shootToY));

                  //If the distance between the live targeted npc and the projectile is less than 480 pixels
                  if(distance < 480f && !target.friendly && target.active)
                  {
                      //Divide the factor, 3f, which is the desired velocity
                      distance = 3f / distance;
      
                      //Multiply the distance by a multiplier if you wish the projectile to have go faster
                      shootToX *= distance * 5;
                      shootToY *= distance * 5;

                      //Set the velocities to the shoot values
                      projectile.velocity.X = shootToX;
                      projectile.velocity.Y = shootToY;
                  }
              }
            }
            //This is what makes the projectile face the correct way.
            projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + MathHelper.ToRadians(135f);
            //This is what makes the projectile emit light.
            Lighting.AddLight(projectile.Center, 0f, 1f, 0f);     //This is the projectile light color R, G, B (Red, Green, Blue).
        }

        public override void OnHitNPC(NPC target, int damage, float knockback, bool crit)
        {
            target.AddBuff(BuffID.CursedInferno, 5 * 60);
        }
    }
}
I tried using your "Simple Homing AI" for my projectile, but I'm guessing it needs to be changed so it works with the latest update, because it's not working. :I
Looks like they removed the "hostile" property for the NPC object, I guess you'll just have to switch that if statement to:

Code:
if(!target.friendly)
This will check if the target is not friendly (i.e. town npc) but this will also make it so it targets critters too. It's not the greatest solution, but it should work.
 

SuperDude9k

Terrarian
Sorry to bother you again, but how would I go about making a gun fire a different projectile when right clicking? I know how to do the alt function, but I don't know how to make it fire a different projectile. I tried to use the code you gave me earlier combined with an if/else command, but I got an error when trying to build it in tModLoader.

Also, how would I make the projectile animated, similar to the Portal Gun? I tried using the Portal gun projectile gif file to test, but it gives an error because it can't find the texture.

Nevermind, figured out the animation part. Still don't know how to fire 2 different projectiles, though.
 
Last edited:

Owlit

Terrarian
I'm trying to make a minion but this line of code...


public override void TileCollideStyle(ref int width, ref int height, ref bool fallThrough)
{
fallThrough = true;
}


keeps giving me this error:

"c:\Users\User\Documents\My Games\Terraria\ModLoader\Mod Sources\Mymod\Projectiles\Minions\MinionINFO.cs(206,30) : error CS0508: 'Mymod.Projectiles.Minions.MinionINFO.TileCollideStyle(ref int, ref int, ref bool)': return type must be 'bool' to match overridden member 'Terraria.ModLoader.ModProjectile.TileCollideStyle(ref int, ref int, ref bool)'"









FULL CODE:

using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace Mymod.Projectiles.Minions
{
public abstract class MinionINFO : Minion
{
protected float idleAccel = 0.05f;
protected float spacingMult = 1f;
protected float viewDist = 300f;
protected float chaseDist = 325f;
protected float chaseAccel = 6f;
protected float inertia = 40f;
protected float shootCool = 50f;
protected float shootSpeed;
protected int shoot;

public virtual void CreateDust()
{
}

public virtual void SelectFrame()
{
}

public override void Behavior()
{
Player player = Main.player[projectile.owner];
float spacing = (float)projectile.width * spacingMult;
for (int k = 0; k < 1000; k++)
{
Projectile otherProj = Main.projectile[k];
if (k != projectile.whoAmI && otherProj.active && otherProj.owner == projectile.owner && otherProj.type == projectile.type && System.Math.Abs(projectile.position.X - otherProj.position.X) + System.Math.Abs(projectile.position.Y - otherProj.position.Y) < spacing)
{
if (projectile.position.X < Main.projectile[k].position.X)
{
projectile.velocity.X -= idleAccel;
}
else
{
projectile.velocity.X += idleAccel;
}
if (projectile.position.Y < Main.projectile[k].position.Y)
{
projectile.velocity.Y -= idleAccel;
}
else
{
projectile.velocity.Y += idleAccel;
}
}
}
Vector2 targetPos = projectile.position;
float targetDist = viewDist;
bool target = false;
projectile.tileCollide = true;
for (int k = 0; k < 200; k++)
{
NPC npc = Main.npc[k];
if (npc.CanBeChasedBy(this, false))
{
float distance = Vector2.Distance(npc.Center, projectile.Center);
if ((distance < targetDist || !target) && Collision.CanHitLine(projectile.position, projectile.width, projectile.height, npc.position, npc.width, npc.height))
{
targetDist = distance;
targetPos = npc.Center;
target = true;
}
}
}
if (Vector2.Distance(player.Center, projectile.Center) > (target ? 1000f : 500f))
{
projectile.ai[0] = 1f;
projectile.netUpdate = true;
}
if (projectile.ai[0] == 1f)
{
projectile.tileCollide = false;
}
if (target && projectile.ai[0] == 0f)
{
Vector2 direction = targetPos - projectile.Center;
if (direction.Length() > chaseDist)
{
direction.Normalize();
projectile.velocity = (projectile.velocity * inertia + direction * chaseAccel) / (inertia + 1);
}
else
{
projectile.velocity *= (float)Math.Pow(0.97, 40.0 / inertia);
}
}
else
{
if (!Collision.CanHitLine(projectile.Center, 1, 1, player.Center, 1, 1))
{
projectile.ai[0] = 1f;
}
float speed = 6f;
if (projectile.ai[0] == 1f)
{
speed = 15f;
}
Vector2 center = projectile.Center;
Vector2 direction = player.Center - center;
projectile.ai[1] = 3600f;
projectile.netUpdate = true;
int num = 1;
for (int k = 0; k < projectile.whoAmI; k++)
{
if (Main.projectile[k].active && Main.projectile[k].owner == projectile.owner && Main.projectile[k].type == projectile.type)
{
num++;
}
}
direction.X -= (float)((10 + num * 40) * player.direction);
direction.Y -= 70f;
float distanceTo = direction.Length();
if (distanceTo > 200f && speed < 9f)
{
speed = 9f;
}
if (distanceTo < 100f && projectile.ai[0] == 1f && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
{
projectile.ai[0] = 0f;
projectile.netUpdate = true;
}
if (distanceTo > 2000f)
{
projectile.Center = player.Center;
}
if (distanceTo > 48f)
{
direction.Normalize();
direction *= speed;
float temp = inertia / 2f;
projectile.velocity = (projectile.velocity * temp + direction) / (temp + 1);
}
else
{
projectile.direction = Main.player[projectile.owner].direction;
projectile.velocity *= (float)Math.Pow(0.9, 40.0 / inertia);
}
}
projectile.rotation = projectile.velocity.X * 0.05f;
SelectFrame();
CreateDust();
if (projectile.velocity.X > 0f)
{
projectile.spriteDirection = (projectile.direction = -1);
}
else if (projectile.velocity.X < 0f)
{
projectile.spriteDirection = (projectile.direction = 1);
}
if (projectile.ai[1] > 0f)
{
projectile.ai[1] += 1f;
if (Main.rand.Next(3) == 0)
{
projectile.ai[1] += 1f;
}
}
if (projectile.ai[1] > shootCool)
{
projectile.ai[1] = 0f;
projectile.netUpdate = true;
}
if (projectile.ai[0] == 0f)
{
if (target)
{
if ((targetPos - projectile.Center).X > 0f)
{
projectile.spriteDirection = (projectile.direction = -1);
}
else if ((targetPos - projectile.Center).X < 0f)
{
projectile.spriteDirection = (projectile.direction = 1);
}
if (projectile.ai[1] == 0f)
{
projectile.ai[1] = 1f;
if (Main.myPlayer == projectile.owner)
{
Vector2 shootVel = targetPos - projectile.Center;
if (shootVel == Vector2.Zero)
{
shootVel = new Vector2(0f, 1f);
}
shootVel.Normalize();
shootVel *= shootSpeed;
int proj = Projectile.NewProjectile(projectile.Center.X, projectile.Center.Y, shootVel.X, shootVel.Y, shoot, projectile.damage, projectile.knockBack, Main.myPlayer, 0f, 0f);
Main.projectile[proj].timeLeft = 300;
Main.projectile[proj].netUpdate = true;
projectile.netUpdate = true;
}
}
}
}
}

public override void TileCollideStyle(ref int width, ref int height, ref bool fallThrough)
{
fallThrough = true;
}
}
}

Any help or suggestion would be greatly appreciated!
 

jopojelly

Retinazer
tModLoader
I'm trying to make a minion but this line of code...


public override void TileCollideStyle(ref int width, ref int height, ref bool fallThrough)
{
fallThrough = true;
}


keeps giving me this error:

"c:\Users\User\Documents\My Games\Terraria\ModLoader\Mod Sources\Mymod\Projectiles\Minions\MinionINFO.cs(206,30) : error CS0508: 'Mymod.Projectiles.Minions.MinionINFO.TileCollideStyle(ref int, ref int, ref bool)': return type must be 'bool' to match overridden member 'Terraria.ModLoader.ModProjectile.TileCollideStyle(ref int, ref int, ref bool)'"









FULL CODE:

using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace Mymod.Projectiles.Minions
{
public abstract class MinionINFO : Minion
{
protected float idleAccel = 0.05f;
protected float spacingMult = 1f;
protected float viewDist = 300f;
protected float chaseDist = 325f;
protected float chaseAccel = 6f;
protected float inertia = 40f;
protected float shootCool = 50f;
protected float shootSpeed;
protected int shoot;

public virtual void CreateDust()
{
}

public virtual void SelectFrame()
{
}

public override void Behavior()
{
Player player = Main.player[projectile.owner];
float spacing = (float)projectile.width * spacingMult;
for (int k = 0; k < 1000; k++)
{
Projectile otherProj = Main.projectile[k];
if (k != projectile.whoAmI && otherProj.active && otherProj.owner == projectile.owner && otherProj.type == projectile.type && System.Math.Abs(projectile.position.X - otherProj.position.X) + System.Math.Abs(projectile.position.Y - otherProj.position.Y) < spacing)
{
if (projectile.position.X < Main.projectile[k].position.X)
{
projectile.velocity.X -= idleAccel;
}
else
{
projectile.velocity.X += idleAccel;
}
if (projectile.position.Y < Main.projectile[k].position.Y)
{
projectile.velocity.Y -= idleAccel;
}
else
{
projectile.velocity.Y += idleAccel;
}
}
}
Vector2 targetPos = projectile.position;
float targetDist = viewDist;
bool target = false;
projectile.tileCollide = true;
for (int k = 0; k < 200; k++)
{
NPC npc = Main.npc[k];
if (npc.CanBeChasedBy(this, false))
{
float distance = Vector2.Distance(npc.Center, projectile.Center);
if ((distance < targetDist || !target) && Collision.CanHitLine(projectile.position, projectile.width, projectile.height, npc.position, npc.width, npc.height))
{
targetDist = distance;
targetPos = npc.Center;
target = true;
}
}
}
if (Vector2.Distance(player.Center, projectile.Center) > (target ? 1000f : 500f))
{
projectile.ai[0] = 1f;
projectile.netUpdate = true;
}
if (projectile.ai[0] == 1f)
{
projectile.tileCollide = false;
}
if (target && projectile.ai[0] == 0f)
{
Vector2 direction = targetPos - projectile.Center;
if (direction.Length() > chaseDist)
{
direction.Normalize();
projectile.velocity = (projectile.velocity * inertia + direction * chaseAccel) / (inertia + 1);
}
else
{
projectile.velocity *= (float)Math.Pow(0.97, 40.0 / inertia);
}
}
else
{
if (!Collision.CanHitLine(projectile.Center, 1, 1, player.Center, 1, 1))
{
projectile.ai[0] = 1f;
}
float speed = 6f;
if (projectile.ai[0] == 1f)
{
speed = 15f;
}
Vector2 center = projectile.Center;
Vector2 direction = player.Center - center;
projectile.ai[1] = 3600f;
projectile.netUpdate = true;
int num = 1;
for (int k = 0; k < projectile.whoAmI; k++)
{
if (Main.projectile[k].active && Main.projectile[k].owner == projectile.owner && Main.projectile[k].type == projectile.type)
{
num++;
}
}
direction.X -= (float)((10 + num * 40) * player.direction);
direction.Y -= 70f;
float distanceTo = direction.Length();
if (distanceTo > 200f && speed < 9f)
{
speed = 9f;
}
if (distanceTo < 100f && projectile.ai[0] == 1f && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
{
projectile.ai[0] = 0f;
projectile.netUpdate = true;
}
if (distanceTo > 2000f)
{
projectile.Center = player.Center;
}
if (distanceTo > 48f)
{
direction.Normalize();
direction *= speed;
float temp = inertia / 2f;
projectile.velocity = (projectile.velocity * temp + direction) / (temp + 1);
}
else
{
projectile.direction = Main.player[projectile.owner].direction;
projectile.velocity *= (float)Math.Pow(0.9, 40.0 / inertia);
}
}
projectile.rotation = projectile.velocity.X * 0.05f;
SelectFrame();
CreateDust();
if (projectile.velocity.X > 0f)
{
projectile.spriteDirection = (projectile.direction = -1);
}
else if (projectile.velocity.X < 0f)
{
projectile.spriteDirection = (projectile.direction = 1);
}
if (projectile.ai[1] > 0f)
{
projectile.ai[1] += 1f;
if (Main.rand.Next(3) == 0)
{
projectile.ai[1] += 1f;
}
}
if (projectile.ai[1] > shootCool)
{
projectile.ai[1] = 0f;
projectile.netUpdate = true;
}
if (projectile.ai[0] == 0f)
{
if (target)
{
if ((targetPos - projectile.Center).X > 0f)
{
projectile.spriteDirection = (projectile.direction = -1);
}
else if ((targetPos - projectile.Center).X < 0f)
{
projectile.spriteDirection = (projectile.direction = 1);
}
if (projectile.ai[1] == 0f)
{
projectile.ai[1] = 1f;
if (Main.myPlayer == projectile.owner)
{
Vector2 shootVel = targetPos - projectile.Center;
if (shootVel == Vector2.Zero)
{
shootVel = new Vector2(0f, 1f);
}
shootVel.Normalize();
shootVel *= shootSpeed;
int proj = Projectile.NewProjectile(projectile.Center.X, projectile.Center.Y, shootVel.X, shootVel.Y, shoot, projectile.damage, projectile.knockBack, Main.myPlayer, 0f, 0f);
Main.projectile[proj].timeLeft = 300;
Main.projectile[proj].netUpdate = true;
projectile.netUpdate = true;
}
}
}
}
}

public override void TileCollideStyle(ref int width, ref int height, ref bool fallThrough)
{
fallThrough = true;
}
}
}

Any help or suggestion would be greatly appreciated!
It says "return type must be 'bool' to match overridden member". That seems pretty self explanatory. If you don't understand what a return type is, that's something you have to learn through c# tutorials, not tmodloader.
 

Joshua8201

Terrarian
1) How do I make a projectile use multiple images?
2) Is it possible to make a modded GlowMask for a projectile?
3) If yes, is it possible for the GlowMask to have multiple frames (Like below)?
ValkyrieYoyoGIFGlowMask.png
ValkyrieYoyoGlowMask.png
If yes to any of them, where should GlowMasks go in the Mod folder?
 
Last edited:

Joshua8201

Terrarian
Why does my projectile look like this?
Error.PNG
How do I fix it? I'm guessing it's got something to do with either the "Main.RegisterItemAnimation" or Width and Height Hitbox lines...
Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using Terraria.DataStructures;

namespace JoshuasMod.Projectiles.Nirvana
{
    public class NirvanaSlash : ModProjectile
    {
        public override void SetStaticDefaults()
        {
            DisplayName.SetDefault("Nirvana");    //The weapon's name when shown in-game.
            Main.RegisterItemAnimation(projectile.type, new DrawAnimationVertical(10, 5));
        }
   
        public override void SetDefaults()
        {
            projectile.width = 68;
            projectile.height = 64;
            projectile.aiStyle = 75;
            projectile.friendly = true;
            projectile.tileCollide = false;
            projectile.melee = true;
            projectile.penetrate = -1;
            projectile.ownerHitCheck = true;
        }

        public override void AI()
        {
            Player player = Main.player[projectile.owner];
            float num = 1.57079637f;
            Vector2 vector = player.RotatedRelativePoint(player.MountedCenter, true);
       
            num = 0f;
            if (projectile.spriteDirection == -1)
            {
                num = 3.14159265274f;
            }
            if (++projectile.frame >= Main.projFrames[projectile.type])
            {
                projectile.frame = 0;
            }
            projectile.soundDelay--;
            if (projectile.soundDelay <=0)
            {
                Main.PlaySound(2, (int)projectile.Center.X, (int)projectile.Center.Y, 1);
                projectile.soundDelay = 12;
            }
            if (Main.myPlayer == projectile.owner)
            {
                if (player.channel && !player.noItems && !player.CCed)
                {
                    float scaleFactor6 = 1f;
                    if (player.inventory[player.selectedItem].shoot == projectile.type)
                    {
                        scaleFactor6 = player.inventory[player.selectedItem].shootSpeed * projectile.scale;
                    }
                    Vector2 vector13 = Main.MouseWorld - vector;
                    vector13.Normalize();
                    if (vector13.HasNaNs())
                    {
                        vector13 = Vector2.UnitX * (float)player.direction;
                    }
                    vector13 *= scaleFactor6;
                    if (vector13.X != projectile.velocity.X || vector13.Y != projectile.velocity.Y)
                    {
                        projectile.netUpdate = true;
                    }
                    projectile.velocity = vector13;
                }
                else
                {
                    projectile.Kill();
           
                }
            }
            Vector2 vector14 = projectile.Center + projectile.velocity * 3f;
            Lighting.AddLight(vector14, 0.8f, 0.8f, 0.8f);
            projectile.position = player.RotatedRelativePoint(player.MountedCenter, true) - projectile.Size / 2f;
            projectile.rotation = projectile.velocity.ToRotation() + num;
            projectile.spriteDirection = projectile.direction;
            projectile.timeLeft = 2;
            player.ChangeDir(projectile.direction);
            player.heldProj = projectile.whoAmI;
            player.itemTime = 2;
            player.itemAnimation = 2;
            player.itemRotation = (float)Math.Atan2((double)(projectile.velocity.Y * (float)projectile.direction), (double)(projectile.velocity.X * (float)projectile.direction));
        }
    }
}
...Either way, how do I solve this?
Edit: The projectile sprite looks like this:
NirvanaSlash.png
Apparently, it's 86x380 when I import it into Piskel.
 

Kazzymodus

Moderator
Staff member
Moderator
Why does my projectile look like this?
How do I fix it? I'm guessing it's got something to do with either the "Main.RegisterItemAnimation" or Width and Height Hitbox lines...
Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using Terraria.DataStructures;

namespace JoshuasMod.Projectiles.Nirvana
{
    public class NirvanaSlash : ModProjectile
    {
        public override void SetStaticDefaults()
        {
            DisplayName.SetDefault("Nirvana");    //The weapon's name when shown in-game.
            Main.RegisterItemAnimation(projectile.type, new DrawAnimationVertical(10, 5));
        }
  
        public override void SetDefaults()
        {
            projectile.width = 68;
            projectile.height = 64;
            projectile.aiStyle = 75;
            projectile.friendly = true;
            projectile.tileCollide = false;
            projectile.melee = true;
            projectile.penetrate = -1;
            projectile.ownerHitCheck = true;
        }

        public override void AI()
        {
            Player player = Main.player[projectile.owner];
            float num = 1.57079637f;
            Vector2 vector = player.RotatedRelativePoint(player.MountedCenter, true);
      
            num = 0f;
            if (projectile.spriteDirection == -1)
            {
                num = 3.14159265274f;
            }
            if (++projectile.frame >= Main.projFrames[projectile.type])
            {
                projectile.frame = 0;
            }
            projectile.soundDelay--;
            if (projectile.soundDelay <=0)
            {
                Main.PlaySound(2, (int)projectile.Center.X, (int)projectile.Center.Y, 1);
                projectile.soundDelay = 12;
            }
            if (Main.myPlayer == projectile.owner)
            {
                if (player.channel && !player.noItems && !player.CCed)
                {
                    float scaleFactor6 = 1f;
                    if (player.inventory[player.selectedItem].shoot == projectile.type)
                    {
                        scaleFactor6 = player.inventory[player.selectedItem].shootSpeed * projectile.scale;
                    }
                    Vector2 vector13 = Main.MouseWorld - vector;
                    vector13.Normalize();
                    if (vector13.HasNaNs())
                    {
                        vector13 = Vector2.UnitX * (float)player.direction;
                    }
                    vector13 *= scaleFactor6;
                    if (vector13.X != projectile.velocity.X || vector13.Y != projectile.velocity.Y)
                    {
                        projectile.netUpdate = true;
                    }
                    projectile.velocity = vector13;
                }
                else
                {
                    projectile.Kill();
          
                }
            }
            Vector2 vector14 = projectile.Center + projectile.velocity * 3f;
            Lighting.AddLight(vector14, 0.8f, 0.8f, 0.8f);
            projectile.position = player.RotatedRelativePoint(player.MountedCenter, true) - projectile.Size / 2f;
            projectile.rotation = projectile.velocity.ToRotation() + num;
            projectile.spriteDirection = projectile.direction;
            projectile.timeLeft = 2;
            player.ChangeDir(projectile.direction);
            player.heldProj = projectile.whoAmI;
            player.itemTime = 2;
            player.itemAnimation = 2;
            player.itemRotation = (float)Math.Atan2((double)(projectile.velocity.Y * (float)projectile.direction), (double)(projectile.velocity.X * (float)projectile.direction));
        }
    }
}
...Either way, how do I solve this?
Edit: The projectile sprite looks like this:
Apparently, it's 86x380 when I import it into Piskel.
In SetStaticDefaults, set Main.projFrames[projectile.type] to the amount of frames in your spritesheet.
 

Joshua8201

Terrarian
In SetStaticDefaults, set Main.projFrames[projectile.type] to the amount of frames in your spritesheet.
Uh, can you show me an example of an item that uses this (If there is one)? Because I don't really understand what it means by "[projectile.type]".
Also, the "Main.projFrames" line sounds like it'd be in "SetDefaults ()" line rather than the "SetStaticDefaults ()" to me.
P.S When I said the problem might be the Hitbox Size or the "Main.RegisterItemAnimation" Line, that was me just guessing. It could be something else.
¯\_(ツ)_/¯
 

Kazzymodus

Moderator
Staff member
Moderator
Uh, can you show me an example of an item that uses this (If there is one)? Because I don't really understand what it means by "[projectile.type]".
Also, the "Main.projFrames" line sounds like it'd be in "SetDefaults ()" line rather than the "SetStaticDefaults ()" to me.
P.S When I said the problem might be the Hitbox Size or the "Main.RegisterItemAnimation" Line, that was me just guessing. It could be something else.
¯\_(ツ)_/¯
No, it should be in SetStaticDefaults: that is for modifying static properties, and projFrames is static.

projFrames is a static array in the Main class that keeps track of which projectile has how many frames. Passing the type as the index will return you your projectile, and you can set the amount of frames there. So all you need to do is Main.projFrames[projectile.type] = amount of frames.

If the [ ] operator is new to you, you should look up arrays. You're going to need them if you're working with C#.
 
Top Bottom