tModLoader Tutorial: [4] Projectiles

Hey i was just wondering is there anyway to open the original code of terraria to see items and such, so i can look at and see the coding of the game not from a creation stand point but a finished product. i feel being able to do this will show me various code that would help me learn to do the things i wish to do.
You can inspect decompiled code, but be wary: it's a mess when decompiled. The recommended decompiler is ILSpy. Also be wary: decompiling can take a long time and most likely freezes your computer.

This code:
Code:
        public override bool Autoload(ref string name, ref string texture)

Causes this error:
error CS0161: 'MyFirstMod.Projectiles.CelestialFuryProjectile.Autoload(ref string, ref string)': not all code paths return a value

What's going wrong? (Wow, I have an error report on every tutorial except tutorial 1.)
In your CelestialFuryProjectile class you're overriding the Autoload hook but you're not returning a bool (true/false)
Best is to return mod.Autoload
 
I would do that, but, I don't really have the time to learn a lot about C#
But if I did have the time, I would willingly take your advice.



Ok, I figured out what you meant by that (it was incredibly simple :sigh:.)
But now that I've changed:
public override bool Autoload(ref string name, ref string texture)
To
mod.Autoload

It now gives me this error:
c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(29,9) : error CS1519: Invalid token '{' in class, struct, or interface member declaration

c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(30,27) : error CS1519: Invalid token '=' in class, struct, or interface member declaration

c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(30,35) : error CS1519: Invalid token ')' in class, struct, or interface member declaration

c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(30,46) : error CS1519: Invalid token '(' in class, struct, or interface member declaration

c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(30,54) : error CS1519: Invalid token ')' in class, struct, or interface member declaration

c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(30,76) : error CS1519: Invalid token ',' in class, struct, or interface member declaration

c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(30,85) : error CS1519: Invalid token ')' in class, struct, or interface member declaration

c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(30,107) : error CS1519: Invalid token ')' in class, struct, or interface member declaration

c:\Users\Gyderian\Documents\My Games\Terraria\ModLoader\Mod Sources\MyFirstMod\Projectiles\CelestialFuryProjectile.cs(33,1) : error CS1022: Type or namespace definition, or end-of-file expected

(The end-of-file error I've tried to fix but nothing that has usually worked from me has worked this time.)

Here is my code:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

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

namespace MyFirstMod.Projectiles
{
    class CelestialFuryProjectile : ModProjectile
    {
        public override void SetDefaults()
        {
            projectile.name = "Celestial Fury Projectile";
            projectile.width = 48;
            projectile.height = 48;
            projectile.friendly = true;
            projectile.melee = true;
            projectile.tileCollide = true;
            projectile.penetrate = 3;
            projectile.timeLeft = 200;
            projectile.light = 1f;
            projectile.ignoreWater = true;
        }
        mod.Autoload
        {
            projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f;
        }
    }
}
I don't think you quite understand what I was telling you to do. You can say you don't have 'time' to learn c#, but you have no choice. You will make errors like these all the time, and I doubt anyone else here has the time to hold your hand all the time. There are plenty of articles, videos, etc. for you to get a grip on c#, it's not like the basics will take months, rather a few hours. You just replaced the entire method with 'mod.Autoload', that is not what I said you should do.
 
I want to have 2 completely different types of projectiles, which are Terra Beam and Star Wrath, to be shot from my sword, how can I do it, and where should I put it?
 
I want to have 2 completely different types of projectiles, which are Terra Beam and Star Wrath, to be shot from my sword, how can I do it, and where should I put it?
All you really need to do if you want to do one or the other is just add the ID of the projectile to your weapons' "shoot" variable. However if you want it to do two at once, you might want to look at the Shoot() hook for your weapon. You can find some help in my tutorial.
 
item.ammo = ProjectileID.WoodenArrowFriendly;
You know, because of this line ArrowsOfDeath doesnt count as ammo for bows. After deletion it works fine. I am not sure why it doesnt counted as ammo for bows tho.

Does target.lifeMax count armor in it?

Buffs can be applied only on players? I tried to use Shine buff on hit and nothing happened.
 
You know, because of this line ArrowsOfDeath doesnt count as ammo for bows. After deletion it works fine. I am not sure why it doesnt counted as ammo for bows tho.

Does target.lifeMax count armor in it?

Buffs can be applied only on players? I tried to use Shine buff on hit and nothing happened.
Most likely because you did not assign it to the right ammo ID, which is 1.
target.lifeMax does not count armor.

How to change dust color?
If you are expecting to change the dust color of an existing projectile, you cannot, you will have to make your own projectile with the dust you desire.
 
Hey!!!! I am having issues with my Projectiles going like they did in the final demonstration. When i input the code it says that the Namespaces 'player' and 'Vector#' (#=Number) are not being detect or found. please help!
 
Hey!!!! I am having issues with my Projectiles going like they did in the final demonstration. When i input the code it says that the Namespaces 'player' and 'Vector#' (#=Number) are not being detect or found. please help!
Show us the code please? The most likely case is that you forgot to put the header items in the code.
 
Show us the code please? The most likely case is that you forgot to put the header items in the code.
Sure thing, i completely forgot to input the code. I had it in my clipboard and everything hear you go!

Code:
using Terraria.ID;
using Terraria.ModLoader;

namespace TrueTerraria.Items
{
    public class TrueTerraBlade : ModItem
    {
        public override void SetDefaults()
        {
            item.name = "TrueTerraBlade";
            item.damage = 500;
            item.melee = true;
            item.width = 46;
            item.height = 54;
            item.toolTip = "A sword infused with the power of Terra, Stars and Meows... Cats...";
            item.useTime = 5;
            item.useAnimation = 5;
            item.useStyle = 1;
            item.knockBack = 6;
            item.value = 10000;
            item.rare = 11;
            item.UseSound = SoundID.Item4;
            item.autoReuse = true;
            item.CloneDefaults(ItemID.TerraBlade);
            item.name = "TrueTerraBlade";
            item.damage = 800;
            item.shoot = mod.ProjectileType("BetterTerrabeam");
        }

        public override void AddRecipes()
        {
            ModRecipe recipe = new ModRecipe(mod);
            recipe.AddIngredient(ItemID.StarWrath);
            recipe.AddIngredient(ItemID.Meowmere);
            recipe.AddRecipeGroup("Fragment", 20);
            recipe.AddIngredient(ItemID.TerraBlade);
            recipe.SetResult(mod, "TrueTerraBlade");
            recipe.AddTile(TileID.LunarCraftingStation);
            recipe.AddRecipe();
        }
       
        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 = 2;
            float rotation = MathHelper.ToRadians(20);

            for (int i = 0; i < numberProjectiles + 1; i++)
            {
                Vector2 perturbedSpeed = new Vector2(speedX, speedY).RotatedBy(MathHelper.Lerp(-rotation, rotation, i / (numberProjectiles - 1)));
                Projectile.NewProjectile(position.X, position.Y, perturbedSpeed.X, perturbedSpeed.Y, type, damage, knockBack, player.whoAmI);
            }

            int numProjectiles2 = 4;
            float spread = MathHelper.ToRadians(10);
            float baseSpeed = (float)Math.Sqrt(speedX * speedX + speedY * speedY);
            double startAngle = Math.Atan2(speedX, speedY) - spread / 2;
            double deltaAngle = spread / (float)numProjectiles2;
            double offsetAngle;

            for (int j = 0; j < numProjectiles2; j++)
            {
                offsetAngle = startAngle + deltaAngle * j;
                Projectile.NewProjectile(position.X, position.Y, baseSpeed * (float)Math.Sin(offsetAngle), baseSpeed * (float)Math.Cos(offsetAngle), type, damage, knockBack, player.whoAmI);
            }

            return false;
        }
    }
}

That is my entire weapon code, the Weapon is called TrueTerraBlade.cs thanks!
 
Sure thing, i completely forgot to input the code. I had it in my clipboard and everything hear you go!

Code:
using Terraria.ID;
using Terraria.ModLoader;

namespace TrueTerraria.Items
{
    public class TrueTerraBlade : ModItem
    {
        public override void SetDefaults()
        {
            item.name = "TrueTerraBlade";
            item.damage = 500;
            item.melee = true;
            item.width = 46;
            item.height = 54;
            item.toolTip = "A sword infused with the power of Terra, Stars and Meows... Cats...";
            item.useTime = 5;
            item.useAnimation = 5;
            item.useStyle = 1;
            item.knockBack = 6;
            item.value = 10000;
            item.rare = 11;
            item.UseSound = SoundID.Item4;
            item.autoReuse = true;
            item.CloneDefaults(ItemID.TerraBlade);
            item.name = "TrueTerraBlade";
            item.damage = 800;
            item.shoot = mod.ProjectileType("BetterTerrabeam");
        }

        public override void AddRecipes()
        {
            ModRecipe recipe = new ModRecipe(mod);
            recipe.AddIngredient(ItemID.StarWrath);
            recipe.AddIngredient(ItemID.Meowmere);
            recipe.AddRecipeGroup("Fragment", 20);
            recipe.AddIngredient(ItemID.TerraBlade);
            recipe.SetResult(mod, "TrueTerraBlade");
            recipe.AddTile(TileID.LunarCraftingStation);
            recipe.AddRecipe();
        }
      
        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 = 2;
            float rotation = MathHelper.ToRadians(20);

            for (int i = 0; i < numberProjectiles + 1; i++)
            {
                Vector2 perturbedSpeed = new Vector2(speedX, speedY).RotatedBy(MathHelper.Lerp(-rotation, rotation, i / (numberProjectiles - 1)));
                Projectile.NewProjectile(position.X, position.Y, perturbedSpeed.X, perturbedSpeed.Y, type, damage, knockBack, player.whoAmI);
            }

            int numProjectiles2 = 4;
            float spread = MathHelper.ToRadians(10);
            float baseSpeed = (float)Math.Sqrt(speedX * speedX + speedY * speedY);
            double startAngle = Math.Atan2(speedX, speedY) - spread / 2;
            double deltaAngle = spread / (float)numProjectiles2;
            double offsetAngle;

            for (int j = 0; j < numProjectiles2; j++)
            {
                offsetAngle = startAngle + deltaAngle * j;
                Projectile.NewProjectile(position.X, position.Y, baseSpeed * (float)Math.Sin(offsetAngle), baseSpeed * (float)Math.Cos(offsetAngle), type, damage, knockBack, player.whoAmI);
            }

            return false;
        }
    }
}

That is my entire weapon code, the Weapon is called TrueTerraBlade.cs thanks!
Yeah, you were forgetting some headers, I recommend recycling headers, as it shouldn't take too much to load in all headers even if you don't use them. I usually keep this above almost all my code when I mod just to make sure I don't forget anything...

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

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

Otherwise if you want the specific ones you need, I'm pretty certain you only need:

Code:
using System; //General use stuff

using Terraria; //You ALWAYS need this one, this allows you to use all of the "public" variables, classes, and methods of base Terraria
using Terraria.ID; //IDs for Terraria
using Terraria.ModLoader; //You ALWAYS need this one, this allows you to use the classes and hooks necessary for mod making.
 
Yeah, you were forgetting some headers, I recommend recycling headers, as it shouldn't take too much to load in all headers even if you don't use them. I usually keep this above almost all my code when I mod just to make sure I don't forget anything...

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

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

Otherwise if you want the specific ones you need, I'm pretty certain you only need:

Code:
using System; //General use stuff

using Terraria; //You ALWAYS need this one, this allows you to use all of the "public" variables, classes, and methods of base Terraria
using Terraria.ID; //IDs for Terraria
using Terraria.ModLoader; //You ALWAYS need this one, this allows you to use the classes and hooks necessary for mod making.
These are called using directives. So for further explanation: this is so the compiler knows where the stuff you are calling is coming from :)
 
How do I make projectiles point in the direction you shot them and have a "spread" like the snowball launcher? Also, how do I make light emissions upon firing the projectile launcher?
 
How do I make projectiles point in the direction you shot them and have a "spread" like the snowball launcher? Also, how do I make light emissions upon firing the projectile launcher?
1. Depends on your projectile, use

Code:
projectile.rotation = 0;

Use this website for your angles. http://math.rice.edu/~pcmi/sphere/drg_txt.html
Use tangent of velocity adding pi radians to where it should be pointing
Here is an example for an arrow projectile (projectile facing up)

Code:
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f; //1.57 = pi/2, or 90 degrees

2. Use the same spread code for multi projectiles from the OP and just make it for one with rand spread by multiplying the spread with a random multiplier

3. Add to the AI "projectile.light = 0.1f" or any number under 1, using a counter like projectile.ai[0] or projectile.ai[1].
 
1. Depends on your projectile, use

Code:
projectile.rotation = 0;

Use this website for your angles. http://math.rice.edu/~pcmi/sphere/drg_txt.html
Use tangent of velocity adding pi radians to where it should be pointing
Here is an example for an arrow projectile (projectile facing up)

Code:
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f; //1.57 = pi/2, or 90 degrees

2. Use the same spread code for multi projectiles from the OP and just make it for one with rand spread by multiplying the spread with a random multiplier

3. Add to the AI "projectile.light = 0.1f" or any number under 1, using a counter like projectile.ai[0] or projectile.ai[1].

I dont understand the projectile spread.
 
1. Depends on your projectile, use

Code:
projectile.rotation = 0;

Use this website for your angles. http://math.rice.edu/~pcmi/sphere/drg_txt.html
Use tangent of velocity adding pi radians to where it should be pointing
Here is an example for an arrow projectile (projectile facing up)

Code:
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f; //1.57 = pi/2, or 90 degrees

2. Use the same spread code for multi projectiles from the OP and just make it for one with rand spread by multiplying the spread with a random multiplier

3. Add to the AI "projectile.light = 0.1f" or any number under 1, using a counter like projectile.ai[0] or projectile.ai[1].

Nevermind, I found it out. How would I make a quick flash of light when you shoot?
 
Nevermind, I found it out. How would I make a quick flash of light when you shoot?
Well, depending on what AI style you are using, a simple way to make a quick flicker of light would be using a counter and have the projectile have light for a certain amount of ticks then disable it, so it should look something like this

Code:
public override void AI()
{
   projectile.ai[0] += 1f;
   //If the counter is less than a tenth of a second
   if(projectile.ai[0] < 6) 
   {
      projectile.light = 0.1f; //shine light
   }
   else
   {
      projectile.light = 0f; //Don't shine light if its more than a tenth of a second
   }
}
 
Back
Top Bottom