tModLoader Official tModLoader Help Thread

whenever i try to unload the calamity mod i get this message and it tmodloader gives me the option to exit/exit and disable all
15:42:31] [13/FATAL] [tML]: One or more errors occured while unloading and tModLoader must be restarted to prevent further issues.
CalamityMod was unable to unload properly. Modders must use defensive programming to ensure unloading completes regardless of any errors during loading.
System.TypeInitializationException: The type initializer for 'CalamityMod.UI.RipperUI' threw an exception. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at CalamityMod.UI.RipperUI..cctor() in CalamityMod\UI\RipperUI.cs:line 23
--- End of inner exception stack trace ---
at CalamityMod.UI.RipperUI.Reset() in CalamityMod\UI\RipperUI.cs:line 35
at CalamityMod.CalamityMod.Unload() in CalamityMod.cs:line 410
at Terraria.ModLoader.Mod.UnloadContent()
at Terraria.ModLoader.ModContent.UnloadModContent()
at Terraria.ModLoader.ModLoader.do_Unload()
at Terraria.ModLoader.ModLoader.Unload()

help
 
Hello I have a few questions

1. Is there a method to check how far a player is from a certain tile?

2. How can I make a custom enemy not despawn when the player exits the world?

3. Is there a way to change the spawn positions of the pillars?

1. I haven't seen one, looking at the actual source for AdjTiles() in Player.cs they don't use any helper methods so I don't think one exists. You'll have to make your own.

2. The pillars don't despawn, I thought that might be because they were tiles, offhand I can't see what keeps them around. I guess they're more like bosses and don't despawn on distance. Not sure if worldgen or main puts them back when you re-open a world or if they get written to the world file itself.

3. looks like they get set in Worldgen.TriggerLunarApocalypse() Not sure if you can hook that but presumably you could find them after they spawn and move them.
 
1. I haven't seen one, looking at the actual source for AdjTiles() in Player.cs they don't use any helper methods so I don't think one exists. You'll have to make your own.

2. The pillars don't despawn, I thought that might be because they were tiles, offhand I can't see what keeps them around. I guess they're more like bosses and don't despawn on distance. Not sure if worldgen or main puts them back when you re-open a world or if they get written to the world file itself.

3. looks like they get set in Worldgen.TriggerLunarApocalypse() Not sure if you can hook that but presumably you could find them after they spawn and move them.
Thanks for the reply!
1. I figured this out :)

2. Town NPCs don't despawn, could I maybe make it a town NPC but make it still hostile? But I assumethat would make more problems (i.e. a death message when the NPC is killed).

3. Forgive my lack of coding knowledge, but how would I go about moving the pillars?
 
Thanks for the reply!
1. I figured this out :)

2. Town NPCs don't despawn, could I maybe make it a town NPC but make it still hostile? But I assumethat would make more problems (i.e. a death message when the NPC is killed).

3. Forgive my lack of coding knowledge, but how would I go about moving the pillars?

Mind sharing your distance solution? might be handy to have in the toolbox.

Town NPCs dont appear to follow the regular mob despawn rules (despawn if too far), but neither do bosses. I haven't payed much attention to town NPC persistence, if you close a world I'm not sure their position is saved i think they respawn in their homes? Never really noticed the behavior.


I think you can just set the position looks like this is part of the code that teleports town NPCs to their home tile in NPC.cs:


Code:
                this.velocity.X = 0.0f;
                this.velocity.Y = 0.0f;
                this.position.X = (float) (this.homeTileX * 16 + 8 - this.width / 2);
                this.position.Y = (float) (homeTileY * 16 - this.height) - 0.1f;
                this.netUpdate = true;
 
Ohh thanks! I'll have to try just saving the npc position and spawning it everytime to world loads.

For the distance from a tile, I actually just copied the void monolith code in example mod (I didn't realize there was an example monolith before)

Where can I find that NPC.cs file?
 
Hello, I have an issue with my custom NPC. I'm trying to make it so that when one NPC moves in, the other is allowed to move in. I know it sounds weird but, what "if statement" would I use to make this happen? The only thing I've tried so far is this:
Code:
                if (NPC.AnyNPCs(mod.NPCType("Huntress")))
                {
                    return true;
                }
This hasn't worked, are there any suggestions?
 
Help me please. I don't know what to do to fix this.
wea.jpg
 
Hello, I have an issue with my custom NPC. I'm trying to make it so that when one NPC moves in, the other is allowed to move in. I know it sounds weird but, what "if statement" would I use to make this happen? The only thing I've tried so far is this:
Code:
                if (NPC.AnyNPCs(mod.NPCType("Huntress")))
                {
                    return true;
                }
This hasn't worked, are there any suggestions?

From what i'm seeing, this should be working? (I haven't tested it myself)
Maybe attach your npc code?

Help me please. I don't know what to do to fix this.View attachment 267703

That's an index out of bounds error.
Looks like you're trying to access an npc that doesn't exist.
I can't help you unless I can look at the code.

how would one create a custom extractinator tile that has the chance to process custom blocks into a selection of custom materials? I cant find source code for the extractinator anywhere.

I haven't tried this, but theoretically you can use ModItem's ExtractinatorUse() and ModTile's NewRightClick() to make something happen.
If that doesn't work you can always consider making it a recipe instead.
 
how would one create a custom extractinator tile that has the chance to process custom blocks into a selection of custom materials? I cant find source code for the extractinator anywhere.


In Terraria's Source there's a static method on the player called ExtractinatorUse() it has a ton of random rolls then spits the item out at the end

Code:
 Vector2 vector2 = Main.ReverseGravitySupport(Main.MouseScreen, 0.0f) + Main.screenPosition;
      int number = Item.NewItem((int) vector2.X, (int) vector2.Y, 1, 1, Type, Stack, false, -1, false, false);
      if (Main.netMode != 1)
        return;
      NetMessage.SendData(21, -1, -1, (NetworkText) null, number, 1f, 0.0f, 0.0f, 0, 0, 0);


ExtractinatorUse() is called in the "placeThing()" at a glance it's checking where you're trying to place the thing and if the thing is placed onto the extractenator tile then calls the extractinator use 219 is the tileID of the extractinator


Code:
 if (ItemID.Sets.ExtractinatorMode[this.inventory[this.selectedItem].type] >= 0 && Main.tile[Player.tileTargetX, Player.tileTargetY].active() && (int) Main.tile[Player.tileTargetX, Player.tileTargetY].type == 219)
      {
        if ((double) this.position.X / 16.0 - (double) Player.tileRangeX - (double) this.inventory[this.selectedItem].tileBoost - (double) this.blockRange <= (double) Player.tileTargetX && ((double) this.position.X + (double) this.width) / 16.0 + (double) Player.tileRangeX + (double) this.inventory[this.selectedItem].tileBoost - 1.0 + (double) this.blockRange >= (double) Player.tileTargetX && ((double) this.position.Y / 16.0 - (double) Player.tileRangeY - (double) this.inventory[this.selectedItem].tileBoost - (double) this.blockRange <= (double) Player.tileTargetY && ((double) this.position.Y + (double) this.height) / 16.0 + (double) Player.tileRangeY + (double) this.inventory[this.selectedItem].tileBoost - 2.0 + (double) this.blockRange >= (double) Player.tileTargetY) && (this.itemTime == 0 && this.itemAnimation > 0 && this.controlUseItem))
        {
          this.itemTime = this.inventory[this.selectedItem].useTime;
          Main.PlaySound(7, -1, -1, 1, 1f, 0.0f);
          Player.ExtractinatorUse(ItemID.Sets.ExtractinatorMode[this.inventory[this.selectedItem].type]);
        }


I've only done a little bit of modding but you can affect how things are placed in the world by hooking PlaceInWorld() ans CanPlace() in globalTile


theoretically you could do what vanilla does, check if the player is trying to place a thing onto the tile that is your custom extractinator then run a custom method to generate the object just like in the vanilla source.
 
How do I fix the warning when I debug my mod in visual studio
Code:
Member 'MonolithTileRightClick(int, int)' overrides obsolete member 'ModTile.RightClick(int, int)'. Add the Obsolete attribute to 'MonolithTileRightClick(int, int)'.

Pretty much the whole code came from the example mod's void monolith code. Could this also be the reason why it says

'mod did not properly unload during last unload' ?
 
I got this error "error CS1955: Non-invocable member 'SpawnCondition' cannot be used like a method." and I've been trying to fix it with no luck so far. Can anyone help me, here's the code I'm trying to get to function.

using ExtendedDukeFishron.NPCs;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using static Terraria.ModLoader.ModContent;

namespace ExtendedDukeFishron.NPCs
{
public class KillerFishron : ModNPC
{
public override void SetDefaults()
{
npc.width = 150;
npc.height = 100;
npc.damage = 100;
npc.defense = 40;
npc.lifeMax = 7500;
npc.buffImmune[BuffID.OnFire] = true;
npc.buffImmune[BuffID.Confused] = true;
npc.buffImmune[BuffID.Frostburn] = true;
npc.buffImmune[BuffID.Venom] = true;
npc.buffImmune[BuffID.Poisoned] = true;
npc.noTileCollide = true;
npc.noGravity = true;
npc.netAlways = true;
npc.scale = .75f;
npc.HitSound = SoundID.NPCHit14;
npc.DeathSound = SoundID.NPCDeath20;
npc.value = 10000f;
npc.knockBackResist = 0;
npc.aiStyle = 69;
Main.npcFrameCount[npc.type] = Main.npcFrameCount[NPCID.DukeFishron];
aiType = NPCID.DukeFishron;
animationType = NPCID.DukeFishron;
}

public override float SpawnChance(NPCSpawnInfo spawnInfo)
{
return SpawnCondition((info) => info.player.ZoneBeach && Main.hardMode && NPC.downedPlantBoss == true > 0f && !NPC.AnyNPCs(mod.NPCType("KillerFishron")), 0.9f);
}
}
}

If anyone can help, I'd greatly appreciate it
 
How do I fix the warning when I debug my mod in visual studio
Code:
Member 'MonolithTileRightClick(int, int)' overrides obsolete member 'ModTile.RightClick(int, int)'. Add the Obsolete attribute to 'MonolithTileRightClick(int, int)'.

Pretty much the whole code came from the example mod's void monolith code. Could this also be the reason why it says

'mod did not properly unload during last unload' ?

I couldn't find where MonolithTileRightClick() came from, but ModTile.RightClick() is indeed obsolete, you're supposed to use ModTile.NewRightClick(), I hope that helps.
As for mod unloading, read this.

I got this error "error CS1955: Non-invocable member 'SpawnCondition' cannot be used like a method." and I've been trying to fix it with no luck so far. Can anyone help me, here's the code I'm trying to get to function.

using ExtendedDukeFishron.NPCs;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using static Terraria.ModLoader.ModContent;

namespace ExtendedDukeFishron.NPCs
{
public class KillerFishron : ModNPC
{
public override void SetDefaults()
{
npc.width = 150;
npc.height = 100;
npc.damage = 100;
npc.defense = 40;
npc.lifeMax = 7500;
npc.buffImmune[BuffID.OnFire] = true;
npc.buffImmune[BuffID.Confused] = true;
npc.buffImmune[BuffID.Frostburn] = true;
npc.buffImmune[BuffID.Venom] = true;
npc.buffImmune[BuffID.Poisoned] = true;
npc.noTileCollide = true;
npc.noGravity = true;
npc.netAlways = true;
npc.scale = .75f;
npc.HitSound = SoundID.NPCHit14;
npc.DeathSound = SoundID.NPCDeath20;
npc.value = 10000f;
npc.knockBackResist = 0;
npc.aiStyle = 69;
Main.npcFrameCount[npc.type] = Main.npcFrameCount[NPCID.DukeFishron];
aiType = NPCID.DukeFishron;
animationType = NPCID.DukeFishron;
}

public override float SpawnChance(NPCSpawnInfo spawnInfo)
{
return SpawnCondition((info) => info.player.ZoneBeach && Main.hardMode && NPC.downedPlantBoss == true > 0f && !NPC.AnyNPCs(mod.NPCType("KillerFishron")), 0.9f);
}
}
}

If anyone can help, I'd greatly appreciate it

Use this:
return spawnInfo.player.ZoneBeach && Main.hardMode && NPC.downedPlantBoss && !NPC.AnyNPCs(mod.NPCType("KillerFishron")) ? 0.9f : 0f;

SpawnCondition is a class with a bunch of fields, not a method, you can find more info here.

Edit:
I just realised that this looks to be a Fishron clone boss.
If that's the case, using SpawnChance() wouldn't make sense, unless you want your boss to spawn naturally instead of summoned with a boss summon item.
For a boss summoning item, put this in the item's CanUseItem() hook:
return spawnInfo.player.ZoneBeach && Main.hardMode && NPC.downedPlantBoss && !NPC.AnyNPCs(mod.NPCType("KillerFishron"));

If you for some reason DO want your boss to spawn naturally(maybe its a miniboss?), I suggest lowering the spawn chance.
 
Last edited:
It's a mini-boss, the spawn chance is high just for testing. Now I have another issue but with item drops. When I kill the mini-boss, it drops a modded item where it dies, but then on the ground there's the item again. Like if I killed two mini-bosses. Here's the code I'm using for the drops.

using ExtendedDukeFishron.Items.Drops;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using static Terraria.ModLoader.ModContent;

namespace ExtendedDukeFishron.Items.Drops
{
public class FishScalesDrop : GlobalNPC
{
public override void NPCLoot(NPC npc)
{
if(npc.type == mod.NPCType("KillerFishron"));
{
if(Main.expertMode)
Item.NewItem(npc.getRect(), mod.ItemType("FishScales"), Main.rand.Next(15, 27));
else
Item.NewItem(npc.getRect(), mod.ItemType("FishScales"), Main.rand.Next(7, 13));
}
}
}
}
 
I couldn't find where MonolithTileRightClick() came from, but ModTile.RightClick() is indeed obsolete, you're supposed to use ModTile.NewRightClick(), I hope that helps.
As for mod unloading, read this.



Use this:
return spawnInfo.player.ZoneBeach && Main.hardMode && NPC.downedPlantBoss && !NPC.AnyNPCs(mod.NPCType("KillerFishron")) ? 0.9f : 0f;

SpawnCondition is a class with a bunch of fields, not a method, you can find more info here.

Edit:
I just realised that this looks to be a Fishron clone boss.
If that's the case, using SpawnChance() wouldn't make sense, unless you want your boss to spawn naturally instead of summoned with a boss summon item.
For a boss summoning item, put this in the item's CanUseItem() hook:
return spawnInfo.player.ZoneBeach && Main.hardMode && NPC.downedPlantBoss && !NPC.AnyNPCs(mod.NPCType("KillerFishron"));

If you for some reason DO want your boss to spawn naturally(maybe its a miniboss?), I suggest lowering the spawn chance.
Yep, realized the examplemod files i had were very outdated
 
It's a mini-boss, the spawn chance is high just for testing. Now I have another issue but with item drops. When I kill the mini-boss, it drops a modded item where it dies, but then on the ground there's the item again. Like if I killed two mini-bosses. Here's the code I'm using for the drops.

using ExtendedDukeFishron.Items.Drops;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using static Terraria.ModLoader.ModContent;

namespace ExtendedDukeFishron.Items.Drops
{
public class FishScalesDrop : GlobalNPC
{
public override void NPCLoot(NPC npc)
{
if(npc.type == mod.NPCType("KillerFishron"));
{
if(Main.expertMode)
Item.NewItem(npc.getRect(), mod.ItemType("FishScales"), Main.rand.Next(15, 27));
else
Item.NewItem(npc.getRect(), mod.ItemType("FishScales"), Main.rand.Next(7, 13));
}
}
}
}
Remove the semicolon I colored red below:


using ExtendedDukeFishron.Items.Drops;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using static Terraria.ModLoader.ModContent;

namespace ExtendedDukeFishron.Items.Drops
{
public class FishScalesDrop : GlobalNPC
{
public override void NPCLoot(NPC npc)
{
if(npc.type == mod.NPCType("KillerFishron"));
{
if(Main.expertMode)
Item.NewItem(npc.getRect(), mod.ItemType("FishScales"), Main.rand.Next(15, 27));
else
Item.NewItem(npc.getRect(), mod.ItemType("FishScales"), Main.rand.Next(7, 13));
}
}
}
}
 
Hello! I am super new to making mods for Terraria, but I am not super new to coding. However, I have never used C# before and I'm having some trouble.
I am currently trying to create a magic projectile that homes in on other players and heals them.

This is what I have for the projectile code:


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

namespace xSHIGUYx.Weapons
{
public class BlessingofLifeP: ModProjectile
{
public override void SetDefaults()
{
projectile.Name = "Bless Bolt";
projectile.width = 16;
projectile.height = 16;
projectile.friendly = true;
projectile.aiStyle = 1;
projectile.extraUpdates = 1;
projectile.timeLeft = 300; //lasts for 300 frames/ticks. Terraria runs at 60FPS, so it lasts 5 seconds.
}

public override void OnHitPlayer(Projectile projectile, Player target, int damage, bool crit)
{
target.statLife += 10;
}

public override void AI()
{
int num1 = Dust.NewDust
(
projectile.position,
projectile.width,
projectile.height,
157,
projectile.velocity.X,
projectile.velocity.Y,
100,
default,
1f
);

Main.dust[num1].noGravity = true;
Main.dust[num1].velocity *= 0.1f;
for (int i = 1; i < 200; i++)
{
Player target = Main.player;
//Get the shoot trajectory from the projectile and target
float shootToX = target.position.X + (float)target.width * 0.5f - projectile.Center.X;
float shootToY = target.position.Y - projectile.Center.Y;
float distance = (float)System.Math.Sqrt((double)(shootToX * shootToX + shootToY * shootToY));

//If the distance between the live targeted npc and the projectile is less than 480 pixels
if (distance < 480f && target.active)
{
//Divide the factor, 3f, which is the desired velocity
distance = 3f / distance;

//Multiply the distance by a multiplier if you wish the projectile to have go faster
shootToX *= distance * 5;
shootToY *= distance * 5;

//Set the velocities to the shoot values
projectile.velocity.X = shootToX;
projectile.velocity.Y = shootToY;
}
}
}
}
}


It currently is set to find a player other than the main player, due to the fact that I set "i" to 1. (If it's 0 it will home in on the casting player) And I'm not sure how to go about adding the heal mechanic. I've tried a plethora of methods, but I am just to unfamiliar with this language to make any real headway. All help is appreciated, thanks in advance!
 
Back
Top Bottom