Standalone [1.3] tModLoader - A Modding API

Attachments

  • Capture1.PNG
    Capture1.PNG
    37.7 KB · Views: 182
When will be 1.3.4.2 mod support?
But a more interesting question would be, how much longer will tModLoader only support the current patch? In relative terms, the estimated 1 week of wait will deliver us the support to the latest version under a certain tangible time of wait, but in assumption content will not be delivered and estimated time will be equal to infinite, the estimated time for this version to last instead is supposedly until the time the internet and humanity as a whole will ultimately fall.

TL/DR about a week at best.
 
I might need an AoE on the projectile.
I'm don't really remember how the grenade does its thing, but there is a simple way to go about this. We can first set up a loop to find out if the projectile collides onto an npc and kill it before it does damage to it. So it would look something like this inside your projectile's AI() hook.

Code:
//For every npc in the array of npcs
                foreach (NPC N in Main.npc) 
                {
                    //Find the rectangles or "hitboxes" of the npc and projectile
                    Rectangle MB = new Rectangle((int)projectile.position.X + (int)projectile.velocity.X, (int)projectile.position.Y + (int)projectile.velocity.Y, projectile.width, projectile.height); 
                    Rectangle NB = new Rectangle((int)N.position.X, (int)N.position.Y, N.width, N.height); 
                   
                    //If the two cross together
                    if (MB.Intersects(NB) && N.life > 0 && N.active &&!N.friendly)
                    {
                        projectile.Kill()
                    }
                }

Note: "foreach (NPC N in Main.npc)" is a terrible idea because you'll be also going through an array space that is not used at all within the game, so you'll want to instead switch that to:

Code:
for(int i = 0; i < Main.npc.Length - 1; i++)
{
    NPC N = Main.npc[i]
    //Rest of code
}

Then inside your Kill(int timeLeft) hook, you can probably just find the distances between npcs and then damage the npcs that are within a certain threshold. Sort of like this.

Code:
        public override void Kill(int timeLeft)
        {
            //Search through array
            for(int i = 0; i < Main.npc.Length - 1; i++)
            {
                NPC N = Main.npc[i];
                float dX = N.Center.X - projectile.Center.X; 
                float dY = N.Center.Y - projectile.Center.Y; 
                float distance = (float)System.Math.Sqrt((double)(dX * dX + dY * dY));
               
                //So if the distance between the killed projectile and the npc is less than 480 pixels...
                if(distance < 480f && N.hostile && N.active)
                {
                    N.StrikeNPC(1, 0f, N.direction, false, false, false); //Damages and shows damage on the NPC, this accounts for the defense of the NPC as well.
                }
            |
        |
 
I'm don't really remember how the grenade does its thing
If I recall correctly, the grenade (and any other explosive) simply increases its hitbox's size then moves it around to properly align it with the explosion for a few frames. For instance, explosive projectiles are also piercing projectiles (with infinite piercing), which makes sense considering the projectiles doubles as an explosion. I also found this in the grenade's AI code.
Code:
this.position.X = this.position.X + (float)(this.width / 2);
this.position.Y = this.position.Y + (float)(this.height / 2);
this.width = 128;
this.height = 128;
this.position.X = this.position.X - (float)(this.width / 2);
this.position.Y = this.position.Y - (float)(this.height / 2);
this.knockBack = 8f;
So I suppose that's another option.
 
If I recall correctly, the grenade (and any other explosive) simply increases its hitbox's size then moves it around to properly align it with the explosion for a few frames. For instance, explosive projectiles are also piercing projectiles (with infinite piercing), which makes sense considering the projectiles doubles as an explosion. I also found this in the grenade's AI code.
Code:
this.position.X = this.position.X + (float)(this.width / 2);
this.position.Y = this.position.Y + (float)(this.height / 2);
this.width = 128;
this.height = 128;
this.position.X = this.position.X - (float)(this.width / 2);
this.position.Y = this.position.Y - (float)(this.height / 2);
this.knockBack = 8f;
So I suppose that's another option.
That... is actually a more efficient way of doing it than what I did... Probably should have looked at vanilla code but was too lazy to.
 
I get this error when compiling any mod:

Code:
error CS1703: An assembly with the same identity 'Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' has already been imported. Try removing one of the duplicate references.

There is no file named NewtonSoft.Json.dll in my terraira folder and I have already tested it in another computer, it works.

Could you help me, pls?
 
Last edited:
I'm don't really remember how the grenade does its thing, but there is a simple way to go about this. We can first set up a loop to find out if the projectile collides onto an npc and kill it before it does damage to it. So it would look something like this inside your projectile's AI() hook.

Code:
//For every npc in the array of npcs
                foreach (NPC N in Main.npc)
                {
                    //Find the rectangles or "hitboxes" of the npc and projectile
                    Rectangle MB = new Rectangle((int)projectile.position.X + (int)projectile.velocity.X, (int)projectile.position.Y + (int)projectile.velocity.Y, projectile.width, projectile.height);
                    Rectangle NB = new Rectangle((int)N.position.X, (int)N.position.Y, N.width, N.height);
                 
                    //If the two cross together
                    if (MB.Intersects(NB) && N.life > 0 && N.active &&!N.friendly)
                    {
                        projectile.Kill()
                    }
                }

Note: "foreach (NPC N in Main.npc)" is a terrible idea because you'll be also going through an array space that is not used at all within the game, so you'll want to instead switch that to:

Code:
for(int i = 0; i < Main.npc.Length - 1; i++)
{
    NPC N = Main.npc[i]
    //Rest of code
}

Then inside your Kill(int timeLeft) hook, you can probably just find the distances between npcs and then damage the npcs that are within a certain threshold. Sort of like this.

Code:
        public override void Kill(int timeLeft)
        {
            //Search through array
            for(int i = 0; i < Main.npc.Length - 1; i++)
            {
                NPC N = Main.npc[i];
                float dX = N.Center.X - projectile.Center.X;
                float dY = N.Center.Y - projectile.Center.Y;
                float distance = (float)System.Math.Sqrt((double)(dX * dX + dY * dY));
             
                //So if the distance between the killed projectile and the npc is less than 480 pixels...
                if(distance < 480f && N.hostile && N.active)
                {
                    N.StrikeNPC(1, 0f, N.direction, false, false, false); //Damages and shows damage on the NPC, this accounts for the defense of the NPC as well.
                }
            |
        |
I can't get it working. I need a code where the projectile explodes creating an AoE as soon as it hits a tile or NPC.

Can you tell me where to place it
Code:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace MoreGunsMod.Projectiles
{
    public class mm40 : ModProjectile
    {
        public override void SetDefaults()
        {
            projectile.name = "40mm Grenade";
            projectile.width = 16;
            projectile.height = 18;
            projectile.aiStyle = 1;
            projectile.friendly = true;
            projectile.ranged = true;
            projectile.damage = 20;
            projectile.penetrate = 1;
            projectile.timeLeft = 600;
            projectile.alpha = 255;
            projectile.extraUpdates = 1;
            ProjectileID.Sets.TrailCacheLength[projectile.type] = 5;
            ProjectileID.Sets.TrailingMode[projectile.type] = 0;
            aiType = mod.ProjectileType("mm40");
        }
      
        public override void AI()
        {
            if (Main.rand.Next(3) == 0)
            {
                Dust.NewDust(projectile.position + projectile.velocity, projectile.width, projectile.height, DustID.Fire, projectile.velocity.X * 0.5f, projectile.velocity.Y * 0.5f);
            }
        }
      
        public override void Kill(int timeLeft)
        {
            Main.PlaySound(2, (int)projectile.position.X, (int)projectile.position.Y, 14);
            for (int num369 = 0; num369 < 20; num369++)
            {
                int num370 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 31, 0f, 0f, 100, default(Color), 1.5f);
                Main.dust[num370].velocity *= 1.4f;
            }
            for (int num371 = 0; num371 < 10; num371++)
            {
                int num372 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 6, 0f, 0f, 100, default(Color), 2.5f);
                Main.dust[num372].noGravity = true;
                Main.dust[num372].velocity *= 5f;
                num372 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 6, 0f, 0f, 100, default(Color), 1.5f);
                Main.dust[num372].velocity *= 3f;
            }
            int num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64));
            Main.gore[num373].velocity *= 0.4f;
            Gore gore85 = Main.gore[num373];
            gore85.velocity.X = gore85.velocity.X + 1f;
            Gore gore86 = Main.gore[num373];
            gore86.velocity.Y = gore86.velocity.Y + 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64));
            Main.gore[num373].velocity *= 0.4f;
            Gore gore87 = Main.gore[num373];
            gore87.velocity.X = gore87.velocity.X - 1f;
            Gore gore88 = Main.gore[num373];
            gore88.velocity.Y = gore88.velocity.Y + 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64));
            Main.gore[num373].velocity *= 0.4f;
            Gore gore89 = Main.gore[num373];
            gore89.velocity.X = gore89.velocity.X + 1f;
            Gore gore90 = Main.gore[num373];
            gore90.velocity.Y = gore90.velocity.Y - 1f;
            num373 = Gore.NewGore(new Vector2(projectile.position.X, projectile.position.Y), default(Vector2), Main.rand.Next(61, 64));
            Main.gore[num373].velocity *= 0.4f;
            Gore gore91 = Main.gore[num373];
            gore91.velocity.X = gore91.velocity.X - 1f;
            Gore gore92 = Main.gore[num373];
            gore92.velocity.Y = gore92.velocity.Y - 1f;
        }
    }
}
 
Back
Top Bottom