tModLoader Official tModLoader Help Thread

Hello, I am attempting to make a very weak pickaxe with limited range. I've got it mostly working but still have a few stumbling blocks...

1. I want this tool to only reach one or two blocks away. I see no property to directly set this so I assumed it is based on the item.width and height forming a hitbox. Several of the vanilla picks have modified range so I know it is possible. :) What am I missing?

2. I want the tool to animate like a spear (it is a sharp stick after all) but when I set it up to "shoot" I lose the pick functionality all together. Any suggestions?

Code:
Code:
public class SharpStick : ModItem
{
    public override void SetDefaults()
    {
        item.name = "Sharp Stick";
        item.width = 8;
        item.height = 8;
        item.maxStack = 1;
        item.rare = 5;
        item.toolTip = "This sharp stick is really useful.";
        item.toolTip2 = "You can dig in the dirt with it and poke stuff.";
        item.useStyle = 1;
        item.useTime = 24;
        item.useAnimation = item.useTime + 4;
        item.pick = 4; // good for dirt and not much else :D Too low, even dirt won't budge.
        item.damage = 2;
        item.melee = true;
        item.knockBack = 2;
        item.autoReuse = false;
        item.scale = 1f;
        item.useTurn = true;          
    }
}
1. Try fooling around with

Code:
item.tileBoost

It's an integer.

2. Spear is actually a projectile instead of drawing the item, I think there's an example spear in the ExampleMod in the tModLoader github. Look for the item and the projectile for the spear.
 
hey, sin costan, where In the black code would I put that?
[doublepost=1495660784,1495660767][/doublepost]block#
 
I have problems getting CloneDefaults to work on enemy projectiles. They are usually invisible and don't behave like the original at all, I'm starting to wonder if that's even meant to work.

My projectiles typically look like this:
Code:
  public override void SetDefaults()
  {
  projectile.CloneDefaults(ProjectileID.VortexLaser);
  projectile.name = "Storm Diver Shotgun";
  projectile.width = 2;
  projectile.height = 42;
  projectile.friendly = true;
  projectile.hostile = false;
  }
I'm using the original sprites, too, so I fail to see the problem, but it happened to me with several projectiles, with varying effects.
 
1. Try fooling around with

Code:
item.tileBoost

It's an integer.

2. Spear is actually a projectile instead of drawing the item, I think there's an example spear in the ExampleMod in the tModLoader github. Look for the item and the projectile for the spear.

Thanks, tileBoost did the trick. Specifically, tileBoost = -2 limited it to the tile under foot.

Regarding the spear animation, I have that working (as far as animation goes), but the problem is that the tool no longer performs as a pick.
 
I'm sorry for wasting your time sin costan, I was a stupid fool and barely checked the code. Turns out, I already had the drop code.
 
Hello. I'm not sure if this is the correct place to post this, but I'm sure you'll be able to listen all the same. The fact is, I may have encountered a bug with tModLoader that corrupts characters when the modding API is installed. The character's portrait in the selection screen turns blank, as does their information, and they're unable to be selected. I have found another individual who has experienced the same problem, if you wish me to link you to them. The question is: is this a documented bug or not? If it isn't, I'd love for you to contact the tModLoader team so that they may fix it. Thanks.
 
Could someone explain to me how to use Save() and Load() from GlobalItem, please? My mod changes the base stats of weapons while the game is running but i dont know how to save and load them afterwards. I know there are those functions but i couldnt figure out how to use them properly just from the documentation and the example Mod.:sigh:Especially the TagCompound part is confusing me. What is a TagCompound anyway? an example would be appreciated.:confused:
 
Last edited:
I'm having issues getting the calamity mod to even work. I got it downloaded and enabled via tmodloader, but trouble is, I'm not sure how to actually play the mods.
 
here is current code:

how would I get it to spawn one of three ores at a random chance upon breaking?
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ModLoader;

namespace ApocalypseMOD.Tiles
{
public class HallowedAltar : ModTile
{
public override void SetDefaults()
{
Main.tileSolid[Type] = true;
Main.tileMergeDirt[Type] = false;
Main.tileBlockLight[Type] = true; //true for block to emit light
Main.tileLighted[Type] = true;
AddMapEntry(new Color(200, 200, 200));
}

public override void ModifyLight(int i, int j, ref float r, ref float g, ref float b) //light colors
{
r = 0.5f;
g = 0.5f;
b = 0.5f;
public override void Drop(int i, int j)
{
}
Use Main.rand.next(3)
}
}
}
 
You must be using a hook that is only called on the client of the person who uses the item. You can find out which one that is by adding something like 'Main.NewText("nameOfHook was called"); to the beginning of a hook to see when it is being called.

Thanks for the reply. What do you mean by hook? I'm relatively new to Terraria modding, and I don't really understand what that is. Do you mean that for some reason the client that uses it is the only one that calls the function? What function could I be using? Here's my DrawLaser function (should look mostly like the examplelaser) along with the predraw function that uses it:

Code:
public override bool PreDraw(SpriteBatch spriteBatch, Color lightColor)
        {
            if (Charge == MAX_CHARGE)
            {
                Vector2 unit = projectile.velocity;
                DrawLaser(spriteBatch, Main.projectileTexture[projectile.type],
                    ((PlayerInfo.ChooPlayer)Main.player[projectile.owner].GetModPlayer(mod,"ChooPlayer")).aimPos, unit, 10, projectile.damage,
                    -1.57f, 1f, 1000f, Color.White, (int)MOVE_DISTANCE);
            }
            return false;

        }

public void DrawLaser(SpriteBatch spriteBatch, Texture2D texture, Vector2 start, Vector2 unit, float step, int damage, float rotation = 0f, float scale = 1f, float maxDist = 2000f, Color color = default(Color), int transDist = 50)
        {
            Vector2 origin = start;
            float r = unit.ToRotation() + rotation;

            #region Draw laser body
            for (float i = transDist; i <= Distance; i += step)
            {
                Color c = Color.White;
                origin = start + i * unit;
                spriteBatch.Draw(texture, origin - Main.screenPosition,
                    new Rectangle(0, 26, 28, 26), i < transDist ? Color.Transparent : c, r,
                    new Vector2(28 / 2, 26 / 2), scale, 0, 0);
            }
            #endregion

            #region Draw laser tail
            spriteBatch.Draw(texture, start + unit * (transDist - step) - Main.screenPosition,
                new Rectangle(0, 0, 28, 26), Color.White, r, new Vector2(28 / 2, 26 / 2), scale, 0, 0);
            #endregion

            #region Draw laser head
            spriteBatch.Draw(texture, start + (Distance + step) * unit - Main.screenPosition,
                new Rectangle(0, 52, 28, 26), Color.White, r, new Vector2(28 / 2, 26 / 2), scale, 0, 0);
            #endregion
        }
 
Could someone explain to me how to use Save() and Load() from GlobalItem, please? My mod changes the base stats of weapons while the game is running but i dont know how to save and load them afterwards. I know there are those functions but i couldnt figure out how to use them properly just from the documentation and the example Mod.:sigh:Especially the TagCompound part is confusing me. What is a TagCompound anyway? an example would be appreciated.:confused:
I haven't really done much with save and load, but I'll see if I can help you. A tag is basically an easier way of retrieving data. In the old version you had to load data in the same order it was saved. I believe that this eliminated the need for using a saveVersion. @jopojelly, can you confirm this?

Anyway, you save your information to a tag in the save hook, then load it from the same tag in the load hook. The important thing is that you must load it as the same data type that you saved it as. If you try to load a float as an int, it will mess everything up. A float must be loaded as a float (tag.GetFloat("tagName")), a string as a string(tag.GetString("tagName")), a vector2 as two floats etc. I'm no expert at what you need for each type, but you can use intellisense to see them all, assuming that your scripting program supports it.

Thanks for the reply. What do you mean by hook? I'm relatively new to Terraria modding, and I don't really understand what that is. Do you mean that for some reason the client that uses it is the only one that calls the function? What function could I be using? Here's my DrawLaser function (should look mostly like the examplelaser) along with the predraw function that uses it:

Code:
public override bool PreDraw(SpriteBatch spriteBatch, Color lightColor)
        {
            if (Charge == MAX_CHARGE)
            {
                Vector2 unit = projectile.velocity;
                DrawLaser(spriteBatch, Main.projectileTexture[projectile.type],
                    ((PlayerInfo.ChooPlayer)Main.player[projectile.owner].GetModPlayer(mod,"ChooPlayer")).aimPos, unit, 10, projectile.damage,
                    -1.57f, 1f, 1000f, Color.White, (int)MOVE_DISTANCE);
            }
            return false;

        }

public void DrawLaser(SpriteBatch spriteBatch, Texture2D texture, Vector2 start, Vector2 unit, float step, int damage, float rotation = 0f, float scale = 1f, float maxDist = 2000f, Color color = default(Color), int transDist = 50)
        {
            Vector2 origin = start;
            float r = unit.ToRotation() + rotation;

            #region Draw laser body
            for (float i = transDist; i <= Distance; i += step)
            {
                Color c = Color.White;
                origin = start + i * unit;
                spriteBatch.Draw(texture, origin - Main.screenPosition,
                    new Rectangle(0, 26, 28, 26), i < transDist ? Color.Transparent : c, r,
                    new Vector2(28 / 2, 26 / 2), scale, 0, 0);
            }
            #endregion

            #region Draw laser tail
            spriteBatch.Draw(texture, start + unit * (transDist - step) - Main.screenPosition,
                new Rectangle(0, 0, 28, 26), Color.White, r, new Vector2(28 / 2, 26 / 2), scale, 0, 0);
            #endregion

            #region Draw laser head
            spriteBatch.Draw(texture, start + (Distance + step) * unit - Main.screenPosition,
                new Rectangle(0, 52, 28, 26), Color.White, r, new Vector2(28 / 2, 26 / 2), scale, 0, 0);
            #endregion
        }
From what I understand, a hook is a function that overrides another function (though anyone can feel free to step in with a better explanation). PreDraw is one such hook.

A quick 'n' dirty way to see if a hook/function is being completed is to put the NewText thing I mentioned before at both the beginning and end, or even halfway through if it's long, to see roughly where your code is breaking.

I've had a quick look through your code, and I think that the problem may be the Vector2 that you are trying to reach. ((PlayerInfo.ChooPlayer)Main.player[projectile.owner].GetModPlayer(mod,"ChooPlayer")).aimPos). I suspect that it is never set on other clients, which means that it breaking when it tries to load a NULL value. Try initialising aimPos to {0, 0}. If the laser targets the upper left corner of your world, that's your problem.
 
Is there an easy way to add a buff with unlimited duration?

I have a tile buff that is currently added for 60 cycles when a player is nearby. The code keeps the buffTime at 60 so long as the player remains close. When they move out of range, I am setting buffTime to 0.

I expected to find a RemoveBuff method matching the AddBuff method, but I guess one doesn't exist (and maybe for good reason).
 
hey choo, can you help me?

Sure, if it's within my knowledge. I don't have much Terraria-specific knowledge, but I can help you out with code. What do you need?

From what I understand, a hook is a function that overrides another function (though anyone can feel free to step in with a better explanation). PreDraw is one such hook.

A quick 'n' dirty way to see if a hook/function is being completed is to put the NewText thing I mentioned before at both the beginning and end, or even halfway through if it's long, to see roughly where your code is breaking.

I've had a quick look through your code, and I think that the problem may be the Vector2 that you are trying to reach. ((PlayerInfo.ChooPlayer)Main.player[projectile.owner].GetModPlayer(mod,"ChooPlayer")).aimPos). I suspect that it is never set on other clients, which means that it breaking when it tries to load a NULL value. Try initialising aimPos to {0, 0}. If the laser targets the upper left corner of your world, that's your problem.

Makes sense to me. I'll test that as soon as I can, but until then, how would I go about setting the aimPos in other clients? I get the feeling that it's just never updated for others, but I don't know how I'd do that. aimPos is set in a class named ChooPlayer, extending ModPlayer and only contains a public Vector2 aimPos. This is how I update the aimPos in my weapon using right click:

Code:
public override bool UseItem(Player player)
        {
            if (player.altFunctionUse == 2)
            {
                if (player.Equals(Main.player[Main.myPlayer]))
                ((PlayerInfo.ChooPlayer)player.GetModPlayer(mod, "ChooPlayer")).aimPos = Main.MouseWorld;

                ...
                *fancify*
                ...
                return true;
            } else
            {
                return base.UseItem(player);
            }
        }
 
I haven't really done much with save and load, but I'll see if I can help you. A tag is basically an easier way of retrieving data. In the old version you had to load data in the same order it was saved. I believe that this eliminated the need for using a saveVersion. @jopojelly, can you confirm this?

Anyway, you save your information to a tag in the save hook, then load it from the same tag in the load hook. The important thing is that you must load it as the same data type that you saved it as. If you try to load a float as an int, it will mess everything up. A float must be loaded as a float (tag.GetFloat("tagName")), a string as a string(tag.GetString("tagName")), a vector2 as two floats etc. I'm no expert at what you need for each type, but you can use intellisense to see them all, assuming that your scripting program supports it.

Thanks for helping me out with the TagCompound part :D Save() is returning a new TagCompound which looks like this in the example mod:

Code:
public override TagCompound Save(Item item)
{
    return new TagCompound {
 
             {"score", score}
         };
}

In contrast to this, Load() requires a TagCompound. Now i have two questions. First, can you return a TagCompound which contains multiple values like:

Code:
public override TagCompound Save(Item item)
{
    return new TagCompound {
 
             {"value1", value1}, {"value2", value2}
         };
}

Second, Load(Item item, TagCompound tag) requires a TagCompound to load the information. But how do i know the identifier of the TagCompound where my data is stored? Because Save() is just returning a TagCompound and i cant see an identifier there. Would it be "score" so i would have to call Load(item, "score")? :confused:
Thanks for your advice

Edit: Dont get me wrong, my goal is to save some values for specific items, which get loaded when you restart the game. But is this even the right way of doing it? Because
as I understood it know, save() works like this:
Code:
TagCompound tag = Save(item);
and then you load it with Load(item, tag). But that doesnt help me with saving the information above the lifespan of the game instance, so you can load them in a new game instance again.
 
Last edited:
Im sorry but there's 171 pages of comments so I dont know if this has been addressed before or not, but when moving player and world files from Vanilla to tmod both the player and world are unusable. I'm unsure if anyone has gotten it to work but I would really appreciate help on this. I apologize if this isnt the correct thread to ask, if so please redirect me?
 
Back
Top Bottom