Standalone [1.3] tModLoader - A Modding API

If you're modelling your projectile on the Purple Laser, give it an aiType of 88. Like this:
Code:
this.aiType = 88;
Yeah, now it's working, but it moves forward using vertical line.
Does this have something to do with "item.alpha"? When I set it to 255 then my laser disappears, so I delete this line.
 
Yeah, now it's working, but it moves forward using vertical line.
Does this have something to do with "item.alpha"? When I set it to 255 then my laser disappears, so I delete this line.
What do you mean by vertical line? Do you mean the projectile's sprite is aligned vertically? The projectile's sprite orientation is actually dictated by the AI and some sprites might need some tuning.
 
What do you mean by vertical line? Do you mean the projectile's sprite is aligned vertically? The projectile's sprite orientation is actually dictated by the AI and some sprites might need some tuning.
I should have known I got an ambiguous expression... Anyway, it's like this:
[DOUBLEPOST=1450497567,1450497477][/DOUBLEPOST]
upload_2015-12-19_11-59-23.png
 
I should have known I got an ambiguous expression... Anyway, it's like this:
[DOUBLEPOST=1450497567,1450497477][/DOUBLEPOST]View attachment 89069
So, I would suggest to use a blank AI (setting it to -1 should do the trick). Projectiles are coded to simply flight straight given a base velocity if they lack any AI control. Done that, you can easily control the direction of the laser's sprite using this code in the projectile's AI method.
Code:
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X);
Note, this is for a horizontal projectile sprite, so you're going to need to either turn your projectile sprite horizontal, or edit the code to add an offset rotation to it to turn the sprite the right way, being radiants, you want it to be 1.57f
Code:
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X)+1.57f;
 
Last edited:
WARNING: WALL OF CODE
The shine is the projectile
How do i make my sprite show, idk whats wrong 2015-12-19_00001.jpg 2015-12-19_00002.jpg 2015-12-19_00003.jpg 2015-12-19_00004.jpg
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace ExampleMod.Items.Weapons
{
    public class ExampleSword : ModItem
    {
        public override void SetDefaults()
        {
//My sword
            item.name = "Borna's Blade";
            item.damage = 275;
            item.melee = true;
            item.width = 40;
            item.height = 40;
            item.toolTip = "This is OP.";
            item.useTime = 15;
            item.useAnimation = 20;
            item.useStyle = 1;
            item.knockBack = 1;
            item.value = 666666;
            item.rare = 11;
            item.useSound = 1;
            item.autoReuse = true;
            item.shoot = mod.ProjectileType("BornaBeam");
            item.shootSpeed = 16f;
        }

        public override void AddRecipes()
        {
            ModRecipe recipe = new ModRecipe(mod);
            recipe.AddIngredient(ItemID.DirtBlock);
            recipe.AddTile(TileID.WorkBenches);
            recipe.SetResult(this);
            recipe.AddRecipe();
        }

        public override void MeleeEffects(Player player, Rectangle hitbox)
        {
            if (Main.rand.Next(3) == 0)
            {
                int dust = Dust.NewDust(new Vector2(hitbox.X, hitbox.Y), hitbox.Width, hitbox.Height, mod.DustType("Sparkle"));
            }
        }

        public override void OnHitNPC(Player player, NPC target, int damage, float knockback, bool crit)
        {
            target.AddBuff(BuffID.OnFire, 60);
            target.AddBuff(BuffID.Cursed, 60);
            target.AddBuff(BuffID.Confused, 60);
        }
    }
}



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

namespace ExampleMod.Projectiles
{
    public class BornaBeam : ModProjectile
    {
        public override void SetDefaults()
            {
//My projectile
                projectile.name = "Borna Beam";
                projectile.width = 12;
                projectile.height = 1;
                projectile.aiStyle = 1;
                projectile.friendly = true;
                projectile.penetrate = 3;
                projectile.light = 1.75f;
                projectile.alpha = 255;
                projectile.extraUpdates = 4;
                projectile.scale = 1.4f;
                projectile.timeLeft = 600;
                projectile.magic = true;
                projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X);
            }
      
        public override bool OnTileCollide(Vector2 oldVelocity)
        {
            projectile.penetrate--;
            if (projectile.penetrate <= 0)
            {
                projectile.Kill();
            }
            else
            {
                projectile.ai[0] += 0.1f;
                if (projectile.velocity.X != oldVelocity.X)
                {
                    projectile.velocity.X = -oldVelocity.X;
                }
                if (projectile.velocity.Y != oldVelocity.Y)
                {
                    projectile.velocity.Y = -oldVelocity.Y;
                }
                projectile.velocity *= 0.75f;
                Main.PlaySound(2, (int)projectile.position.X, (int)projectile.position.Y, 10);
            }
            return false;
        }

        public override void Kill(int timeLeft)
        {
            for (int k = 0; k < 5; k++)
            {
                Dust.NewDust(projectile.position + projectile.velocity, projectile.width, projectile.height, mod.DustType("Sparkle"), projectile.oldVelocity.X * 0.5f, projectile.oldVelocity.Y * 0.5f);
            }
            Main.PlaySound(2, (int)projectile.position.X, (int)projectile.position.Y, 25);
        }

        public override void OnHitNPC(NPC target, int damage, float knockback, bool crit)
        {
            projectile.ai[0] += 0.1f;
            projectile.velocity *= 0.75f;
        }
    }
}
 
WARNING: WALL OF CODE
The shine is the projectile
How do i make my sprite show, idk whats wrong View attachment 89075 View attachment 89076 View attachment 89077 View attachment 89078
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace ExampleMod.Items.Weapons
{
    public class ExampleSword : ModItem
    {
        public override void SetDefaults()
        {
//My sword
            item.name = "Borna's Blade";
            item.damage = 275;
            item.melee = true;
            item.width = 40;
            item.height = 40;
            item.toolTip = "This is OP.";
            item.useTime = 15;
            item.useAnimation = 20;
            item.useStyle = 1;
            item.knockBack = 1;
            item.value = 666666;
            item.rare = 11;
            item.useSound = 1;
            item.autoReuse = true;
            item.shoot = mod.ProjectileType("BornaBeam");
            item.shootSpeed = 16f;
        }

        public override void AddRecipes()
        {
            ModRecipe recipe = new ModRecipe(mod);
            recipe.AddIngredient(ItemID.DirtBlock);
            recipe.AddTile(TileID.WorkBenches);
            recipe.SetResult(this);
            recipe.AddRecipe();
        }

        public override void MeleeEffects(Player player, Rectangle hitbox)
        {
            if (Main.rand.Next(3) == 0)
            {
                int dust = Dust.NewDust(new Vector2(hitbox.X, hitbox.Y), hitbox.Width, hitbox.Height, mod.DustType("Sparkle"));
            }
        }

        public override void OnHitNPC(Player player, NPC target, int damage, float knockback, bool crit)
        {
            target.AddBuff(BuffID.OnFire, 60);
            target.AddBuff(BuffID.Cursed, 60);
            target.AddBuff(BuffID.Confused, 60);
        }
    }
}



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

namespace ExampleMod.Projectiles
{
    public class BornaBeam : ModProjectile
    {
        public override void SetDefaults()
            {
//My projectile
                projectile.name = "Borna Beam";
                projectile.width = 12;
                projectile.height = 1;
                projectile.aiStyle = 1;
                projectile.friendly = true;
                projectile.penetrate = 3;
                projectile.light = 1.75f;
                projectile.alpha = 255;
                projectile.extraUpdates = 4;
                projectile.scale = 1.4f;
                projectile.timeLeft = 600;
                projectile.magic = true;
                projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X);
            }
     
        public override bool OnTileCollide(Vector2 oldVelocity)
        {
            projectile.penetrate--;
            if (projectile.penetrate <= 0)
            {
                projectile.Kill();
            }
            else
            {
                projectile.ai[0] += 0.1f;
                if (projectile.velocity.X != oldVelocity.X)
                {
                    projectile.velocity.X = -oldVelocity.X;
                }
                if (projectile.velocity.Y != oldVelocity.Y)
                {
                    projectile.velocity.Y = -oldVelocity.Y;
                }
                projectile.velocity *= 0.75f;
                Main.PlaySound(2, (int)projectile.position.X, (int)projectile.position.Y, 10);
            }
            return false;
        }

        public override void Kill(int timeLeft)
        {
            for (int k = 0; k < 5; k++)
            {
                Dust.NewDust(projectile.position + projectile.velocity, projectile.width, projectile.height, mod.DustType("Sparkle"), projectile.oldVelocity.X * 0.5f, projectile.oldVelocity.Y * 0.5f);
            }
            Main.PlaySound(2, (int)projectile.position.X, (int)projectile.position.Y, 25);
        }

        public override void OnHitNPC(NPC target, int damage, float knockback, bool crit)
        {
            projectile.ai[0] += 0.1f;
            projectile.velocity *= 0.75f;
        }
    }
}
Set the projectile's alpha to 0.
 
Okay, finally got the laser to go straight:). One more question, if I can use
public virtual void RandomUpdate(int i, int j, int type)
to turn the blocks around the block to something else, what exactly should I use these codes?
Turning may have a speed, a range, a frequency, and a limit, how to set these factors?
 
How do you make a mod projectile track an enemy?
what's the vanilla homing ai?
Try setting aiStyle to 36 and aiType to 307. (Should work.)
These two are useful:
https://github.com/bluemagic123/tModLoader/wiki/Vanilla-Projectile-IDs
https://github.com/bluemagic123/tModLoader/wiki/Vanilla-Projectile-AIs
i cant seem to get a new test mod to work as i dont know what i need at least to get it working with just one item

like what files folders do i need for it to load right
You need a build.txt, a class that extends Mod, and a class that extends Item. Make sure the namespace is consistent.

so how do i get a new mod to use

"public override void AddCraftGroups()"

it just says

"Object reference not set to an instance of an object."

and i got no idea how to make it know this
What else does it say? It should point to a file. Code?
Here is one I did, if it helps.
Code:
public override void AddCraftGroups()
        {
            AddCraftGroup("MinionStaffs", Lang.misc[37] + " " + "Minion Staff", ItemID.SlimeStaff,
                ItemID.ImpStaff, ItemID.HornetStaff, ItemID.SpiderStaff, ItemID.OpticStaff,
                ItemID.PirateStaff, ItemID.PygmyStaff, ItemID.XenoStaff, ItemID.RavenStaff,
                ItemID.TempestStaff, ItemID.DeadlySphereStaff, ItemID.StardustCellStaff, ItemID.StardustDragonStaff);
            AddCraftGroup("MagicMirrors", Lang.misc[37] + " " + "Magic Mirror", ItemID.IceMirror,ItemID.MagicMirror);
        }

Okay, finally got the laser to go straight:). One more question, if I can use
public virtual void RandomUpdate(int i, int j, int type)
to turn the blocks around the block to something else, what exactly should I use these codes?
Turning may have a speed, a range, a frequency, and a limit, how to set these factors?
However you want.

It is up to you on frequency. Maybe a random number check. (I'm not sure how often random updates happen, so just adjust while testing.)

For example, hallowed grass does this check: WorldGen.genRand.Next(15) == 0

Speed,range,and limit will be set by how your code works and what the code decides to do.
 
I get an error when i set the aiType to 307

Error:
c:\Users\Borna\Documents\My Games\Terraria\ModLoader\Mod Sources\ExampleMod\Projectiles\BornaBeam.cs(16,28) : error CS1061: 'Terraria.Projectile' does not contain a definition for 'aiType' and no extension method 'aiType' accepting a first argument of type 'Terraria.Projectile' could be found (are you missing a using directive or an assembly reference?)
 
Yeah, but I actually don't know what to do, although I know it's possible... Maybe you could give me some examples.
Actually, I just had an idea.
Code:
        public override void RandomUpdate(int i, int j)
        {
            WorldGen.Convert(i, j, 0);
        }
WXG9GnX.png
COC5Kg9.png

This function is used by the clentaminator to convert tiles. It will convert all tiles in a diamond shape to a purity variant.

You'll want to remake this function and do your own variety on it. I've identified frequency and range, but speed and limit will depend on what you are trying to accomplish. If you want, you can spread the tile this code is attached to rather than dirt or stone. Maybe every 1 in a 1000 will be converted so that the thing can spread. You'll want to limit this function, maybe with the double for loop failing 99% of the time so that the spread looks more natural and not an instant "stamp." On the other hand, I think it would be cool it this tile were like a totem pole or something, constantly purifying the nearby area. You'll need to work on making it look natural, maybe work from the inside out and only purify a certain maximum number of tiles in a single RandomUpdate. Good Luck! :
Code:
        public override void RandomUpdate(int i, int j)
        {
            // 15 is the inverse of the Frequency
            if (WorldGen.genRand.Next(15) == 0)
            {
                // 10 is the Range 
                Convert(i, j, 10);
            }
        }

        public static void Convert(int i, int j, int size)
        {
            for (int k = i - size; k <= i + size; k++)
            {
                for (int l = j - size; l <= j + size; l++)
                {
                    if (WorldGen.InWorld(k, l, 1) && Math.Abs(k - i) + Math.Abs(l - j) < Math.Sqrt(size * size + size * size))
                    {
                        int type = (int)Main.tile[k, l].type;
                        int wall = (int)Main.tile[k, l].wall;
                        if (Main.tile[k, l].wall == 69 || Main.tile[k, l].wall == 70 || Main.tile[k, l].wall == 81)
                        {
                            if ((double)l < Main.worldSurface)
                            {
                                if (WorldGen.genRand.Next(10) == 0)
                                {
                                    Main.tile[k, l].wall = 65;
                                }
                                else
                                {
                                    Main.tile[k, l].wall = 63;
                                }
                            }
                            else
                            {
                                Main.tile[k, l].wall = 64;
                            }
                            WorldGen.SquareWallFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].wall == 3 || Main.tile[k, l].wall == 28 || Main.tile[k, l].wall == 83)
                        {
                            Main.tile[k, l].wall = 1;
                            WorldGen.SquareWallFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].wall == 80)
                        {
                            if ((double)l < Main.worldSurface + 4.0 + (double)WorldGen.genRand.Next(3) || (double)l > ((double)Main.maxTilesY + Main.rockLayer) / 2.0 - 3.0 + (double)WorldGen.genRand.Next(3))
                            {
                                Main.tile[k, l].wall = 15;
                                WorldGen.SquareWallFrame(k, l, true);
                                NetMessage.SendTileSquare(-1, k, l, 3);
                            }
                            else
                            {
                                Main.tile[k, l].wall = 64;
                                WorldGen.SquareWallFrame(k, l, true);
                                NetMessage.SendTileSquare(-1, k, l, 3);
                            }
                        }
                        else if (WallID.Sets.Conversion.HardenedSand[wall] && wall != 216)
                        {
                            Main.tile[k, l].wall = 216;
                            WorldGen.SquareWallFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (WallID.Sets.Conversion.Sandstone[wall] && wall != 187)
                        {
                            Main.tile[k, l].wall = 187;
                            WorldGen.SquareWallFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        if (Main.tile[k, l].type == 23 || Main.tile[k, l].type == 109 || Main.tile[k, l].type == 199)
                        {
                            Main.tile[k, l].type = 2;
                            WorldGen.SquareTileFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].type == 117 || Main.tile[k, l].type == 25 || Main.tile[k, l].type == 203)
                        {
                            Main.tile[k, l].type = 1;
                            WorldGen.SquareTileFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].type == 112 || Main.tile[k, l].type == 116 || Main.tile[k, l].type == 234)
                        {
                            Main.tile[k, l].type = 53;
                            WorldGen.SquareTileFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].type == 398 || Main.tile[k, l].type == 402 || Main.tile[k, l].type == 399)
                        {
                            Main.tile[k, l].type = 397;
                            WorldGen.SquareTileFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].type == 400 || Main.tile[k, l].type == 403 || Main.tile[k, l].type == 401)
                        {
                            Main.tile[k, l].type = 396;
                            WorldGen.SquareTileFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].type == 164 || Main.tile[k, l].type == 163 || Main.tile[k, l].type == 200)
                        {
                            Main.tile[k, l].type = 161;
                            WorldGen.SquareTileFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].type == 70)
                        {
                            Main.tile[k, l].type = 60;
                            WorldGen.SquareTileFrame(k, l, true);
                            NetMessage.SendTileSquare(-1, k, l, 1);
                        }
                        else if (Main.tile[k, l].type == 32 || Main.tile[k, l].type == 352)
                        {
                            WorldGen.KillTile(k, l, false, false, false);
                            if (Main.netMode == 1)
                            {
                                NetMessage.SendData(17, -1, -1, "", 0, (float)k, (float)l, 0f, 0, 0, 0);
                            }
                        }
                    }
                }
            }
        }
[DOUBLEPOST=1450514774,1450514702][/DOUBLEPOST]
I get an error when i set the aiType to 307

Error:
c:\Users\Borna\Documents\My Games\Terraria\ModLoader\Mod Sources\ExampleMod\Projectiles\BornaBeam.cs(16,28) : error CS1061: 'Terraria.Projectile' does not contain a definition for 'aiType' and no extension method 'aiType' accepting a first argument of type 'Terraria.Projectile' could be found (are you missing a using directive or an assembly reference?)
Not item.aiTyle, just aiType. It belongs to ModProjectile. (https://github.com/bluemagic123/tModLoader/wiki/ModProjectile#public-int-aitype)
 
It will convert all tiles in a diamond shape to a purity variant
So, em... I just attached your codes to some mod tiles I've created before. Then I got them look like this:
upload_2015-12-19_17-7-0.png

Does it mean, if it's working, the Ebonsand Block around it will be purified?
 
So, em... I just attached your codes to some mod tiles I've created before. Then I got them look like this:
View attachment 89106
Does it mean, if it's working, the Ebonsand Block around it will be purified?
Should work, did you wait around to find out? You saw my pictures, right? Add more of your tile if you are getting impatient. (I didn't test the exact code I posted, but I don't think I made mistakes.)
 
Should work, did you wait around to find out? You saw my pictures, right? Add more of your tile if you are getting impatient. (I didn't test the exact code I posted, but I don't think I made mistakes.)
Um... I actually did a lot of tests. When I put only one block, the function block, in these Ebonsand Blocks, there seems to be nothing for two days(game time ofc.). Then I see your message, so I put a lot of them around those Ebonsand Blocks, and Ebon blocks suddenly all became normal sand blocks just now!
Well, I don't how it works, but it works anyway. Maybe the speed and limit should be considered. How can I adjust the speed?
 
How do you make a projectile be spawned WAY above the player when you fire a weapon?
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)
{
            position.Y -= 10;
}
The higher the number, the higher the projectile will spawn.
 
I would like to know how to make my projectiles looks like they are facing toward my cursor. I mean when I fire a projectile the immage is still same but is only moving toward cursor.
 
I would like to know how to make my projectiles looks like they are facing toward my cursor. I mean when I fire a projectile the immage is still same but is only moving toward cursor.
So, I would suggest to use a blank AI (setting it to -1 should do the trick). Projectiles are coded to simply flight straight given a base velocity if they lack any AI control. Done that, you can easily control the direction of the laser's sprite using this code in the projectile's AI method.
Code:
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X);
Note, this is for a horizontal projectile sprite, so you're going to need to either turn your projectile sprite horizontal, or edit the code to add an offset rotation to it to turn the sprite the right way, being radiants, you want it to be 1.57f
Code:
projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X)+1.57f;
 
Thank you so much and is there some way to add animation to this projectile. I have Image of 3 separated textures but the fired projectile use only the first. Used this :
Main.projFrames[projectile.type] = 3;
 
Back
Top Bottom