tModLoader Official tModLoader Help Thread

How can I check if a specific boss has been defeated? I assume there's a set of flags, but I don't know how to access them.
 
How can I check if a specific boss has been defeated? I assume there's a set of flags, but I don't know how to access them.
I found these in NPC:
downedMechBossAny = false;
downedMechBoss1 = false;
downedMechBoss2 = false;
downedMechBoss3 = false;
downedBoss1 = false;
downedBoss2 = false;
downedBoss3 = false;
downedQueenBee = false;
downedSlimeKing = false;
downedGoblins = false;
downedFrost = false;
downedPirates = false;
downedClown = false;
downedPlantBoss = false;
downedGolemBoss = false;
downedMartians = false;
downedFishron = false;
downedHalloweenTree = false;
downedHalloweenKing = false;
downedChristmasIceQueen = false;
downedChristmasTree = false;
downedChristmasSantank = false;
downedAncientCultist = false;
downedMoonlord = false;
downedTowerSolar = false;
downedTowerVortex = false;
downedTowerNebula = false;
downedTowerStardust = false;

So, if (NPC.downedPlantBoss) { stuff }
 

Much appreciated. If the explanation's not too complex, would you mind telling me how you found these so I can be more self-sufficient in the future?

Edit: Found out I can use my MVS to check this kind of thing, though I'm not sure I can see everything. I'm unable to find a WoF flag, nor a hardmode flag, in NPC, WorldGen, or Player. Is there one to be found?
 
Last edited:
Much appreciated. If the explanation's not too complex, would you mind telling me how you found these so I can be more self-sufficient in the future?

Edit: Found out I can use my MVS to check this kind of thing, though I'm not sure I can see everything. I'm unable to find a WoF flag, nor a hardmode flag, in NPC, WorldGen, or Player. Is there one to be found?
Oh, you figured it out. For the benefit of others, start typing and Visual Studio will tell you:
mgifJWh.png

You should be able to see all public fields, properties, and methods.

For Wall of Flesh, it is just Main.hardMode.
 
When autoload tries to load textures, it errors claiming that the texture doesn't exist, when it does. What's happening?
Double check the namespace of your class and the class name. Also check the names of both the .CS and .png file.

When the program claims it can't find a texture, it really can't find it at the given place. Always double check the things I mentioned above when you get an error like that.
 
Double check the namespace of your class and the class name. Also check the names of both the .CS and .png file.

When the program claims it can't find a texture, it really can't find it at the given place. Always double check the things I mentioned above when you get an error like that.
I've double, triple, quadruple and quintuple checked it and i'm still getting the error. It's doing this for everything I try to mod in.
 
I've double, triple, quadruple and quintuple checked it and i'm still getting the error. It's doing this for everything I try to mod in.
Could you show me ALL the code of your item and tell me the exact path to the .cs file containing that code, starting from the Mod Sources folder? ;)
 
Could you show me ALL the code of your item and tell me the exact path to the .cs file containing that code, starting from the Mod Sources folder? ;)
Mod Sources\TestMod\Mod Sources\TestMod\Dusts\HeroDust.cs
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ModLoader;
using TestMod.Dusts;

namespace TestMod.Dusts
{
    public class HeroDust : ModDust
    {
        public override void OnSpawn(Dust dust)
        {
            dust.velocity.Y = Main.rand.Next(-10, 6) * 0.1f;
            dust.velocity.X *= 0.3f;
            dust.scale *= 0.7f;
        }

        public override bool MidUpdate(Dust dust)
        {
            if (!dust.noGravity)
            {
                dust.velocity.Y += 0.05f;
            }
            if (!dust.noLight)
            {
                float strength = dust.scale * 1.4f;
                if (strength > 1f)
                {
                    strength = 1f;
                }
                Lighting.AddLight(dust.position, 0.1f * strength, 0.2f * strength, 0.7f * strength);
            }
            return true;
        }

        public override Color? GetAlpha(Dust dust, Color lightColor)
        {
            return new Color(lightColor.R, lightColor.G, lightColor.B, 25);
        }
    }
}
Mod Sources\TestMod\Items\Weapons\HerosBlade.cs
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace TestMod.Items.Weapons
{
    public class HerosBlade : ModItem
    {
        public override void SetDefaults()
        {
            item.name = "Hero's Blade";
            item.damage = 400;
            item.melee = true;
            item.width = 74;
            item.height = 80;
            item.toolTip = "A blade forged from a Hero's soul.";
            item.useTime = 20;
            item.useAnimation = 20;
            item.useStyle = 1;
            item.knockBack = 6;
            item.value = 100000;
            item.rare = 9;
            item.useSound = 1;
            item.autoReuse = true;
        }

        public override void AddRecipes()
        {
            ModRecipe recipe = new ModRecipe(mod);
            recipe.AddIngredient(Terraria.ID.ItemID.CopperShortsword, 1);
            recipe.AddTile(Terraria.ID.TileID.Anvils);
            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("HeroDust"));
            }
        }

        public override void OnHitNPC(Player player, NPC target, int damage, float knockback, bool crit)
        {
            target.AddBuff(BuffID.OnFire, 60);
        }
    }
}
 
Mod Sources\TestMod\Mod Sources\TestMod\Dusts\HeroDust.cs
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ModLoader;
using TestMod.Dusts;

namespace TestMod.Dusts
{
    public class HeroDust : ModDust
    {
        public override void OnSpawn(Dust dust)
        {
            dust.velocity.Y = Main.rand.Next(-10, 6) * 0.1f;
            dust.velocity.X *= 0.3f;
            dust.scale *= 0.7f;
        }

        public override bool MidUpdate(Dust dust)
        {
            if (!dust.noGravity)
            {
                dust.velocity.Y += 0.05f;
            }
            if (!dust.noLight)
            {
                float strength = dust.scale * 1.4f;
                if (strength > 1f)
                {
                    strength = 1f;
                }
                Lighting.AddLight(dust.position, 0.1f * strength, 0.2f * strength, 0.7f * strength);
            }
            return true;
        }

        public override Color? GetAlpha(Dust dust, Color lightColor)
        {
            return new Color(lightColor.R, lightColor.G, lightColor.B, 25);
        }
    }
}
Mod Sources\TestMod\Items\Weapons\HerosBlade.cs
Code:
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace TestMod.Items.Weapons
{
    public class HerosBlade : ModItem
    {
        public override void SetDefaults()
        {
            item.name = "Hero's Blade";
            item.damage = 400;
            item.melee = true;
            item.width = 74;
            item.height = 80;
            item.toolTip = "A blade forged from a Hero's soul.";
            item.useTime = 20;
            item.useAnimation = 20;
            item.useStyle = 1;
            item.knockBack = 6;
            item.value = 100000;
            item.rare = 9;
            item.useSound = 1;
            item.autoReuse = true;
        }

        public override void AddRecipes()
        {
            ModRecipe recipe = new ModRecipe(mod);
            recipe.AddIngredient(Terraria.ID.ItemID.CopperShortsword, 1);
            recipe.AddTile(Terraria.ID.TileID.Anvils);
            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("HeroDust"));
            }
        }

        public override void OnHitNPC(Player player, NPC target, int damage, float knockback, bool crit)
        {
            target.AddBuff(BuffID.OnFire, 60);
        }
    }
}
Allright, this is where you're going wrong, I've seen this before ;)
Look at your path:
Code:
Mod Sources\TestMod\Mod Sources\TestMod\Dusts\HeroDust.cs
Notice that is has to loop through 'Mod Sources/TestMod' two times? You don't want that. Take the second 'TestMod' folder and dump it right into the first 'Mod Sources' folder.
 
Allright, this is where you're going wrong, I've seen this before ;)
Look at your path:
Code:
Mod Sources\TestMod\Mod Sources\TestMod\Dusts\HeroDust.cs
Notice that is has to loop through 'Mod Sources/TestMod' two times? You don't want that. Take the second 'TestMod' folder and dump it right into the first 'Mod Sources' folder.
Yeah, I realized this immediately after posting. I meant to edit the original post but my internet wasn't working right. Thanks for helping.
 
So my problem is still here how do i get back to regular terraria, I would like to play N terraria but i first need to remove tmodloader so how do I do that.
 
Been tinkering around with projectiles spawning other projectiles, new to messing with AI() in tModloader. Some 20 minutes of debug has me thinking that I have some incorrect assumptions on how it works. Code here:
Code:
        public override void AI()
        {
            timer++;
            if(timer >= 10)
            {
                timer = 0;
                {
                    //conversion to polar from cartesian for velocity
                    double x = projectile.Center.X - Main.MouseWorld.X;
                    double y = projectile.Center.Y - Main.MouseWorld.Y;
                    //double r = Math.Sqrt((x * x) + (y * y));
                    double q = Math.Atan2(x, y);
                    //x = r; r not needed since we always want r=1 so each has the same speed
                    y = q;
                    float XVel = (float)(1 * Math.Cos(q));
                    float YVel = (float)(1 * Math.Sin(q));

                    //position randomizer weighted towards central values
                    float posX = projectile.Center.X;
                    float posY = projectile.Center.Y;
                    posX = Main.rand.Next(-50, 50) + Main.rand.Next(-30, 30);
                    posY = Main.rand.Next(-50, 50) + Main.rand.Next(-30, 30);

                    int p = Projectile.NewProjectile(posX, posY, XVel, YVel, mod.ProjectileType("IceShard"), projectile.damage, projectile.knockBack, projectile.owner);
                }
            }


This is the code within the spawner projectile that's meant to spawn an IceShard projectile once every 10 frames, but it isn't spawning anything. Is there something I've messed up here, or does the problem lie elsewhere?
 
Been tinkering around with projectiles spawning other projectiles, new to messing with AI() in tModloader. Some 20 minutes of debug has me thinking that I have some incorrect assumptions on how it works. Code here:
Code:
        public override void AI()
        {
            timer++;
            if(timer >= 10)
            {
                timer = 0;
                {
                    //conversion to polar from cartesian for velocity
                    double x = projectile.Center.X - Main.MouseWorld.X;
                    double y = projectile.Center.Y - Main.MouseWorld.Y;
                    //double r = Math.Sqrt((x * x) + (y * y));
                    double q = Math.Atan2(x, y);
                    //x = r; r not needed since we always want r=1 so each has the same speed
                    y = q;
                    float XVel = (float)(1 * Math.Cos(q));
                    float YVel = (float)(1 * Math.Sin(q));

                    //position randomizer weighted towards central values
                    float posX = projectile.Center.X;
                    float posY = projectile.Center.Y;
                    posX = Main.rand.Next(-50, 50) + Main.rand.Next(-30, 30);
                    posY = Main.rand.Next(-50, 50) + Main.rand.Next(-30, 30);

                    int p = Projectile.NewProjectile(posX, posY, XVel, YVel, mod.ProjectileType("IceShard"), projectile.damage, projectile.knockBack, projectile.owner);
                }
            }


This is the code within the spawner projectile that's meant to spawn an IceShard projectile once every 10 frames, but it isn't spawning anything. Is there something I've messed up here, or does the problem lie elsewhere?

I'm sort of surprised this actually got loaded. Is "timer" a global variable in your projectile? You should probably increment using projectile.ai[0] instead, just because that's the usual convention the projectiles in vanilla uses. I'm sort of wondering about the "timer = 0" and then the brackets. I think you should remove the brackets. Also, you should add to the values of posX and posY, not make it equals because you're overriding the projectile.Centers with coordinates located at the center of the map.So all in all, it should probably look like this, I'm too lazy to do proper spacing.

Code:
public override void AI()
        {
            projectile.ai[0] += 1f;
            if(projectile.ai[0] >= 10f)
            {
                projectile.ai[0] = 0;
                   
                     //conversion to polar from cartesian for velocity
                    double x = projectile.Center.X - Main.MouseWorld.X;
                    double y = projectile.Center.Y - Main.MouseWorld.Y;
                    //double r = Math.Sqrt((x * x) + (y * y));
                    double q = Math.Atan2(x, y);
                    //x = r; r not needed since we always want r=1 so each has the same speed
                    y = q;
                    float XVel = (float)(1 * Math.Cos(q));
                    float YVel = (float)(1 * Math.Sin(q));

                    //position randomizer weighted towards central values
                    float posX = projectile.Center.X;
                    float posY = projectile.Center.Y;

                    //Probably stick with just one rand on each
                    posX += (Main.rand.Next(-50, 50) + Main.rand.Next(-30, 30));
                    posY += (Main.rand.Next(-50, 50) + Main.rand.Next(-30, 30));

                    int p = Projectile.NewProjectile(posX, posY, XVel, YVel, mod.ProjectileType("IceShard"), projectile.damage, projectile.knockBack, projectile.owner, 0f, 0f);
}
 
I'm sort of surprised this actually got loaded. Is "timer" a global variable in your projectile? You should probably increment using projectile.ai[0] instead, just because that's the usual convention the projectiles in vanilla uses. I'm sort of wondering about the "timer = 0" and then the brackets. I think you should remove the brackets. Also, you should add to the values of posX and posY, not make it equals because you're overriding the projectile.Centers with coordinates located at the center of the map.So all in all, it should probably look like this, I'm too lazy to do proper spacing.

Yeah, I defined timer within the projectile since I didn't(don't) know how projectile.ai[] works. I'm pretty sure the issue here was posX and posY being very not where I intended, but it doesn't hurt to use a predefined variable for increments rather than an extraneous one. The double rand calculation is to weight towards 0. Thanks for the help.
 
So my problem is still here how do i get back to regular terraria, I would like to play N terraria but i first need to remove tmodloader so how do I do that.
Restore FNA.dll, MP3Sharp.dll, Terraria.exe to their origional files. (you should've made a backup)
If you haven't, you can remove those files by deleting them, and then having Steam verify the integrity of the game cache. (this will redownload the origional files)
You should then have vanilla Terraria again.
 
Since I can't just return false in PreKill to keep a projectile from dying, how would I go about preventing the death of a projectile whose maxPenetrate value is -1? I want the projectile to hit the enemy as normal, but then change behavior.
 
Since I can't just return false in PreKill to keep a projectile from dying, how would I go about preventing the death of a projectile whose maxPenetrate value is -1? I want the projectile to hit the enemy as normal, but then change behavior.
You'll want to set projectile.penetrate to -1, not maxPenetrate.
 
You'll want to set projectile.penetrate to -1, not maxPenetrate.
I'm not why my code is working with just that change, but it is. Now on to the more difficult problem: I'm trying to have this projectile inflict damage over time based on the number of projectiles that are currently affecting the enemy. Here are the relevant bits of code:
Code:
using System.Collections.Generic;
using Terraria.ModLoader;

namespace TalismanMagic.NPCs
{
    public class NPCInf : NPCInfo
    {
        public List<int> lightSpears = new List<int>();
    }
}

Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace TalismanMagic.NPCs
{
    class gNPC : GlobalNPC
    {
        public override void ResetEffects(NPC npc)
        {
            NPCInf info = (NPCInf)npc.GetModInfo(mod, "NPCInf");
            info.lightSpears.Clear();
        }
        public override void UpdateLifeRegen(NPC npc, ref int damage)
        {
            NPCInf info = (NPCInf)npc.GetModInfo(mod, "NPCInf");
            if (info.lightSpears.Count > 0)
            {
                npc.lifeRegen -= (int)(64 * info.lightSpears.Count * Math.Pow(1.05, info.lightSpears.Count));
                damage += (int)(64 * info.lightSpears.Count * Math.Pow(1.05, info.lightSpears.Count) / 8);
            }
            for(int i=0; i < info.lightSpears.Count; i++)
            {
                info.lightSpears[i]--;
                if(info.lightSpears[i] <= 0)
                {
                    info.lightSpears.RemoveAt(i);
                }

            }
        }
    }
}

Code:
        public override void OnHitNPC(NPC target, int damage, float knockback, bool crit)
        {
            base.OnHitNPC(target, damage, knockback, crit);
            projectile.friendly = false;
            stuckTarget = target;
            stuckPosX = projectile.position.X - target.Center.X;
            stuckPosY = -projectile.position.Y + target.Center.Y;
            projectile.timeLeft = 180;
            projectile.extraUpdates = 0;
            ((NPCInf)target.GetModInfo(mod, "NPCInf")).lightSpears.Add(180);
        }

Last bit of code is just a portion of the projectile class.

Basically, when the projectile hits an enemy, it adds a value to an int list. The GlobalNPC code is meant to use that list to add a damage over time effect, but currently I'm not seeing any DoT on enemies that should be effected. Any obvious mistakes? Do I need to provide more information?
 
uh quick question. How do you make it so NPC drop an item by chance. I was messing around with it but could not figure out how to
 
Back
Top Bottom