tModLoader Official tModLoader Help Thread

- Is there a way to have TModLoader Terraria separate from vanilla Terraria? Like, I could boot up either one individually without having to remove TModLoader?
I haven't tried the following, meaning that I'm not certain that it definitely works, but you might be able to simply copy the -/steamapps/common/Terraria folder, name the copy "Terraria tModLoader" or such, then have tModLoader in the latter location while having vanilla Terraria in the original location.

Edit: Don't do the above. Instead, make sure that you have vanilla Terraria, then rename "Terraria.exe" to "Terraria (Vanilla).exe" before installing tModLoader. Now you can play vanilla Terraria by manually launching the "Terraria (Vanilla).exe" file, while you can still play with tModLoader by launching the game through Steam.
 
Last edited:
I haven't tried the following, meaning that I'm not certain that it definitely works, but you might be able to simply copy the -/steamapps/common/Terraria folder, name the copy "Terraria tModLoader" or such, then have tModLoader in the latter location while having vanilla Terraria in the original location.

Hm… I don't think I did it correctly.
 
Hm… I don't think I did it correctly.
Well, you shouldn't have to do that, anyway. I just remembered that it should work just fine if you verify the integrity of Terraria's game files through Steam in order to re-get vanilla Terraria, rename the "Terraria.exe" file to "Terrara (Vanilla).exe", and then install tModLoader as normal afterwards. Then you can play vanilla Terraria by just manually launching the "Terraria (Vanilla).exe" file, while you can still play with tModLoader by launching Terraria through Steam.
 
Well, you shouldn't have to do that, anyway. I just remembered that it should work just fine if you verify the integrity of Terraria's game files through Steam in order to re-get vanilla Terraria, rename the "Terraria.exe" file to "Terrara (Vanilla).exe", and then install tModLoader as normal afterwards. Then you can play vanilla Terraria by just manually launching the "Terraria (Vanilla).exe" file, while you can still play with tModLoader by launching Terraria through Steam.

The Windows Executable (.exe) things don't work on my Mac.
 
i have a file with all my tmodloader data, and then i have normal terraria seperate, so launching modded terraria takes this path: desktop\Moddedterraria\terraria.exe
it works
 
for some reason when I make a custom projectile and I try to fire it the projectile is invisible.
I have the texture for it and everything it just doesn't show up.

Code:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace TheKirbyMod.Projectiles
{
    public class EnemyGordo : ModProjectile
    {
        public override void SetStaticDefaults()
        {
            DisplayName.SetDefault("Gordo");     //The English name of the projectile
            ProjectileID.Sets.TrailCacheLength[projectile.type] = 5;    //The length of old position to be recorded
            ProjectileID.Sets.TrailingMode[projectile.type] = 0;        //The recording mode
        }

        public override void SetDefaults()
        {
            projectile.width = 12;               //The width of projectile hitbox
            projectile.height = 12;              //The height of projectile hitbox
            projectile.aiStyle = 1;             //The ai style of the projectile, please reference the source code of Terraria
            projectile.friendly = false;         //Can the projectile deal damage to enemies?
            projectile.hostile = true;         //Can the projectile deal damage to the player?
            projectile.ranged = true;           //Is the projectile shoot by a ranged weapon?
            projectile.penetrate = 3;           //How many monsters the projectile can penetrate. (OnTileCollide below also decrements penetrate for bounces as well)
            projectile.timeLeft = 600;          //The live time for the projectile (60 = 1 second, so 600 is 10 seconds)
            projectile.alpha = 255;             //The transparency of the projectile, 255 for completely transparent. (aiStyle 1 quickly fades the projectile in)
            projectile.light = 0.5f;            //How much light emit around the projectile
            projectile.ignoreWater = true;          //Does the projectile's speed be influenced by water?
            projectile.tileCollide = true;          //Can the projectile collide with tiles?
            projectile.extraUpdates = 1;            //Set to above 0 if you want the projectile to update multiple time in a frame
            aiType = ProjectileID.WoodenArrowFriendly;           //Act exactly like default Bullet
        }

       

        public override bool PreDraw(SpriteBatch spriteBatch, Color lightColor)
        {
            //Redraw the projectile with the color not influenced by light
            Vector2 drawOrigin = new Vector2(Main.projectileTexture[projectile.type].Width * 0.5f, projectile.height * 0.5f);
            for (int k = 0; k < projectile.oldPos.Length; k++)
            {
                Vector2 drawPos = projectile.oldPos[k] - Main.screenPosition + drawOrigin + new Vector2(0f, projectile.gfxOffY);
                Color color = projectile.GetAlpha(lightColor) * ((float)(projectile.oldPos.Length - k) / (float)projectile.oldPos.Length);
                spriteBatch.Draw(Main.projectileTexture[projectile.type], drawPos, null, color, projectile.rotation, drawOrigin, projectile.scale, SpriteEffects.None, 0f);
            }
            return true;
        }
    }
}

(It's borrowed from the example bullet as of now)
 
projectile.alpha = 255; //The transparency of the projectile, 255 for completely transparent. (aiStyle 1 quickly fades the projectile in) projectile.light = 0.5f; //How much light emit around the projectile
That line, delete it if you want. ExampleBullet fades in because it uses an aiType that does that.
 
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace Hypaxi
{
public abstract class InsanityItem : ModItem
{
public static bool insanity = true;
public override void SetDefaults()
{
item.melee = false;
item.ranged = false;
item.thrown = false;
item.magic = false;
item.summon = false;
}
public override void ModifyTooltips(List<TooltipLine> tooltips)
{
var tt = tooltips.FirstOrDefault(x => x.Name == "Damage" && x.mod == "Terraria");
if (tt != null)
{
string[] split = tt.text.Split(' ');
tt.text = split.First() + " insanity " + split.Last();
}
}
public override void GetWeaponDamage(Player player, ref int damage)
{
HypaxiPlayer modPlayer = player.GetModPlayer<HypaxiPlayer>(mod);
int originalDamage = damage;
damage = (int)(damage * modPlayer.insanityDamage);
float globalDmg = 1f;
globalDmg = player.meleeDamage - 1;
if (player.magicDamage - 1 < globalDmg)
globalDmg = player.magicDamage - 1;
if (player.rangedDamage - 1 < globalDmg)
globalDmg = player.rangedDamage - 1;
if (player.thrownDamage - 1 < globalDmg)
globalDmg = player.thrownDamage - 1;
if (player.minionDamage - 1 < globalDmg)
globalDmg = player.minionDamage - 1;
if (globalDmg > 1)
damage = damage + (int)(originalDamage * globalDmg);
}
}
}

c:\Users\brock\Documents\My Games\Terraria\ModLoader\Mod Sources\Hypaxi\InsanityItem.cs.cs(24,31) : error CS1061: 'System.Collections.Generic.List<Terraria.ModLoader.TooltipLine>' does not contain a definition for 'FirstOrDefault' and no extension method 'FirstOrDefault' accepting a first argument of type 'System.Collections.Generic.List<Terraria.ModLoader.TooltipLine>' could be found (are you missing a using directive or an assembly reference?)

c:\Users\brock\Documents\My Games\Terraria\ModLoader\Mod Sources\Hypaxi\InsanityItem.cs.cs(28,33) : error CS1061: 'System.Array' does not contain a definition for 'First' and no extension method 'First' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)

c:\Users\brock\Documents\My Games\Terraria\ModLoader\Mod Sources\Hypaxi\InsanityItem.cs.cs(28,64) : error CS1061: 'System.Array' does not contain a definition for 'Last' and no extension method 'Last' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)

Trying to make a custom damage class and this error is popping up.
 
Hey guys, I try to implement a simple item that contains 'essence'. The current amount of essence should be displayed in a custom tooltip. I used the ModifyTooltips to add an additional line containing the amount of the essence. Contrary to my expectation it always shows the number 0. This class is the minimal example of my item:

Code:
public class SoulStoneCorruptionTier1 : ModItem
    {
        public int CurrentEssence = 0;

        public void AddEssence(int essence)
        {
            CurrentEssence += essence;
        }

        public override void ModifyTooltips(List<TooltipLine> tooltips)
        {
            var line = new TooltipLine(mod, "CurrentEssence", "Essence: " + CurrentEssence)
            {
                overrideColor = Color.White
            };
            tooltips.Add(line);
        }
    }

Every time when the player loots a npc then the essence should be increased. This is the implmentation of my current gloabal npc:
Code:
public override void NPCLoot(NPC npc)
        {
            int playerIndex = npc.lastInteraction;
            if (!Main.player[playerIndex].active || Main.player[playerIndex].dead)
            {
                playerIndex = npc.FindClosestPlayer(); // Since lastInteraction might be an invalid player fall back to closest player.
            }
            Player player = Main.player[playerIndex];
            //Give play the soul essence depending on the life of the npc if a right soul stone is available
            foreach (Item item in player.inventory)
            {
                if (item.type == mod.ItemType<SoulStoneCorruptionTier1>())
                {
                    Main.NewText("Soulstone found: " + item.GetHashCode());
                    SoulStoneCorruptionTier1 soulStone = (SoulStoneCorruptionTier1)item.modItem;
                    soulStone.AddEssence((int)(npc.lifeMax * 0.1f));
                }
            }
            base.NPCLoot(npc);
        }

I compared the hash code for the item in the inventory with the hash code of the item that I currently hover. The are always different. It seems that a new instance is generated for every ModifyTooltip call. I overrided the Clone method for the ModItem but the same result still exists. Can someone enlighten me, please :)?
 
Hey guys, I try to implement a simple item that contains 'essence'. The current amount of essence should be displayed in a custom tooltip. I used the ModifyTooltips to add an additional line containing the amount of the essence. Contrary to my expectation it always shows the number 0. This class is the minimal example of my item:

Code:
public class SoulStoneCorruptionTier1 : ModItem
    {
        public int CurrentEssence = 0;

        public void AddEssence(int essence)
        {
            CurrentEssence += essence;
        }

        public override void ModifyTooltips(List<TooltipLine> tooltips)
        {
            var line = new TooltipLine(mod, "CurrentEssence", "Essence: " + CurrentEssence)
            {
                overrideColor = Color.White
            };
            tooltips.Add(line);
        }
    }

Every time when the player loots a npc then the essence should be increased. This is the implmentation of my current gloabal npc:
Code:
public override void NPCLoot(NPC npc)
        {
            int playerIndex = npc.lastInteraction;
            if (!Main.player[playerIndex].active || Main.player[playerIndex].dead)
            {
                playerIndex = npc.FindClosestPlayer(); // Since lastInteraction might be an invalid player fall back to closest player.
            }
            Player player = Main.player[playerIndex];
            //Give play the soul essence depending on the life of the npc if a right soul stone is available
            foreach (Item item in player.inventory)
            {
                if (item.type == mod.ItemType<SoulStoneCorruptionTier1>())
                {
                    Main.NewText("Soulstone found: " + item.GetHashCode());
                    SoulStoneCorruptionTier1 soulStone = (SoulStoneCorruptionTier1)item.modItem;
                    soulStone.AddEssence((int)(npc.lifeMax * 0.1f));
                }
            }
            base.NPCLoot(npc);
        }

I compared the hash code for the item in the inventory with the hash code of the item that I currently hover. The are always different. It seems that a new instance is generated for every ModifyTooltip call. I overrided the Clone method for the ModItem but the same result still exists. Can someone enlighten me, please :)?
public override bool CloneNewInstances {
get {
return true;
}
}

See https://github.com/blushiemagic/tMo...076/ExampleMod/Items/Placeable/ExampleTrap.cs
 
Hello there. I'm sorry if this sounds incredibly stupid and absurd, but I'm having an incredibly hard time trying to make the sprite change on a boss NPC I have created. I may have worded that wrong, but I have almost no experience in coding, and the code of this boss already looks like absolute trash.
Code:
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using System.IO;

namespace BlastsMod.NPCs
{
    [AutoloadBossHead]
    public class DestroyerAnt : ModNPC
    {
        public override void SetStaticDefaults()
        {
            DisplayName.SetDefault("Destroyer Ant");
            Main.npcFrameCount[npc.type] = 6;
        }

        public override void SetDefaults()
        {
            npc.width = 144;
            npc.height = 88;
            npc.damage = 200;
            npc.defense = 70;
            npc.lifeMax = 50000;
            npc.HitSound = SoundID.NPCHit4;
            npc.DeathSound = SoundID.NPCDeath14;
            npc.value = 100000f;
            npc.knockBackResist = 0.0f;
            npc.aiStyle = 3;
            npc.boss = true;
            npc.buffImmune[24] = true;
            npc.buffImmune[69] = true;
            npc.buffImmune[39] = true;
            npc.buffImmune[31] = true;
            npc.lavaImmune = true;
            aiType = NPCID.SwampThing;
            animationType = NPCID.Zombie;
            music = MusicID.Boss3;
        }
        public override void ScaleExpertStats(int numPlayers, float bossLifeScale)
        {
            npc.lifeMax = (int)(npc.lifeMax / Main.expertLife * 1.5f * bossLifeScale);
            npc.defense = 90;
        }
        internal const int dpsCap = 3000;
        public override float SpawnChance(NPCSpawnInfo spawnInfo)
        {
            if(NPC.downedMoonlord)
            return SpawnCondition.SolarEclipse.Chance * 0.001f;
            else
            {
                return SpawnCondition.SolarEclipse.Chance * 0.00f;
            }
        }
        int attackCounter = 0;
        int attackCounter2 = 0;
        int attackCounter3 = 0;
        int attackCounter4 = 0;
        public override void SendExtraAI(BinaryWriter writer)
        {
            writer.Write(attackCounter);
            writer.Write(attackCounter2);
            writer.Write(attackCounter3);
            writer.Write(attackCounter4);
        }

        public override void ReceiveExtraAI(BinaryReader reader)
        {
            attackCounter = reader.ReadInt32();
            attackCounter2 = reader.ReadInt32();
            attackCounter3 = reader.ReadInt32();
            attackCounter4 = reader.ReadInt32();
        }


        public override void AI() //this is where you program your AI
        {
            if(Main.netMode != 1)
            {
                if (npc.life >= npc.lifeMax/2)
                {               
                    if (attackCounter > 0)
                        attackCounter--;
                    Player target = Main.player[npc.target];
                    if (attackCounter <= 0 && Vector2.Distance(npc.Center, target.Center) < 1200 && Collision.CanHit(npc.Center, 1, 1, target.Center, 1, 1))
                    {
                        Vector2 direction = (target.Center - npc.Center).SafeNormalize(Vector2.UnitX);
                        direction = direction.RotatedByRandom(MathHelper.ToRadians(10));

                        int projectile = Projectile.NewProjectile(npc.Center, direction * 12, mod.ProjectileType("DestroyerLaser"), 40, 0, Main.myPlayer);
                        Main.projectile[projectile].timeLeft = 600;
                        attackCounter = 50;
                        npc.netUpdate = true;
                    }
                }
                else
                {
                    npc.aiStyle = 2;
                    animationType = NPCID.Corruptor;
                    aiType = NPCID.DemonEye;
                    npc.noTileCollide = true;
                    if (attackCounter > 0)
                        attackCounter--;
                    Player target = Main.player[npc.target];
                    if (attackCounter <= 0 && Vector2.Distance(npc.Center, target.Center) < 1200 && Collision.CanHit(npc.Center, 1, 1, target.Center, 1, 1))
                    {
                        Vector2 direction = (target.Center - npc.Center).SafeNormalize(Vector2.UnitX);
                        direction = direction.RotatedByRandom(MathHelper.ToRadians(10));

                        int projectile = Projectile.NewProjectile(npc.Center, direction * 12, mod.ProjectileType("DestroyerLaser"), 40, 0, Main.myPlayer);
                        Main.projectile[projectile].timeLeft = 600;
                        attackCounter = 30;
                        npc.netUpdate = true;
                    }
                }
            }
            if(Main.netMode != 1)
            {
                if (attackCounter2 > 0)
                    attackCounter2--;
                if (attackCounter2 <= 0)
                {   
                      NPC.NewNPC((int)npc.position.X + npc.width, (int)npc.position.Y + npc.height, mod.NPCType("DestroyerDrone"));
                    attackCounter2 = 360;
                }
            }
            if(Main.netMode != 1)
            {
                if (attackCounter3 > 0)
                    attackCounter3--;
                Player target = Main.player[npc.target];
                if (attackCounter3 <= 0 && Vector2.Distance(npc.Center, target.Center) > 1200 && Collision.CanHit(npc.Center, 1, 1, target.Center, 1, 1))
                {
                    Vector2 direction = (target.Center - npc.Center).SafeNormalize(Vector2.UnitX);
                    direction = direction.RotatedByRandom(MathHelper.ToRadians(10));

                    int projectile = Projectile.NewProjectile(npc.Center, direction * 20, ProjectileID.RocketSkeleton, 50, 0, Main.myPlayer);
                    Main.projectile[projectile].timeLeft = 1200;
                    attackCounter3 = 15;
                    npc.netUpdate = true;
                }
            }
            if(Main.netMode != 1)
            {
                if (npc.life <= npc.lifeMax/2)
                {               
                    if (attackCounter4 > 0)
                        attackCounter4--;
                    Player target = Main.player[npc.target];
                    if (attackCounter4 <= 0 && Vector2.Distance(npc.Center, target.Center) < 1200 && Collision.CanHit(npc.Center, 1, 1, target.Center, 1, 1))
                    {
                        Vector2 direction = (target.Center - npc.Center).SafeNormalize(Vector2.UnitX);
                        direction = direction.RotatedByRandom(MathHelper.ToRadians(10));

                        int projectile = Projectile.NewProjectile(npc.Center, direction * 12, ProjectileID.RocketSkeleton, 40, 0, Main.myPlayer);
                        Main.projectile[projectile].timeLeft = 600;
                        attackCounter4 = 120;
                        npc.netUpdate = true;
                    }
                }
            }
        }
        public override void NPCLoot()
        {
            Item.NewItem(npc.getRect(), mod.ItemType("InspiraniteIngot"), 20 + Main.rand.Next(5));
        }
    }
}
The boss as 6 frames. I'm trying to find a way to make the boss use the first 3 frames when above half health, and exclusively use the other three when under half health. I do not know how to utilize phases/stages, so I've been trying to use this weird abomination of code to try to make it work, to no avail. Speaking of an abomination, I've also tried to look through ExampleMod and other bosses in open source mods, in particular Abomination. Yet, unfortunately, all the bosses have unique ways of transferring into their second stage. Any help from anyone will be incredibly appreciated.
[doublepost=1551136086,1551135862][/doublepost]If I confused everyone with the wording, here is the picture.
 

Attachments

  • DestroyerAnt.png
    DestroyerAnt.png
    9.7 KB · Views: 145
Does anyone know how to make a magic armor set that creates healing orbs in the same way as the spectre hood as well as damage orbs in the same way as the spectre mask? - Thanks!
 
hey guys, I am not sure of the current method fo adding backgrounds to modded biomes. It seems the older method no longer works. Can someone explain to me what i need to do?
Code:
public static int Casm = 0;
    public class SquallogsModWorld : ModWorld
    {

        public override void ModifyWorldGenTasks(List<GenPass> tasks, ref float totalWeight)
        {
            int genimdex = tasks.FindIndex(GenPass => GenPass.Name.Equals("Casm"));
            if (genimdex == -1)
            {
                return;
            }
            tasks.Insert(genimdex + 1, new PassLegacy("Casm", delegate (GenerationProgress progress)
            {
                progress.Message = "Casm Creatifying";
                for (int i =0; i < Main.maxTilesX / 800; i++)       //MaxTiles / 800 = Biiome Count
                {
                    //The spawning areas (X axis, Y axis) for the biome
                    int X = WorldGen.genRand.Next(1, Main.maxTilesX - 300);
                    int Y = WorldGen.genRand.Next((int)WorldGen.rockLayerHigh - 0, Main.maxTilesY - 150);
                    //The tile type used in biome gen
                    int TileType = mod.TileType("GeodeStone");

                    WorldGen.TileRunner(X, Y, 350, WorldGen.genRand.Next(100, 200), TileType, false, 0f, 0f, true, true);
                    // integer '350' dictates biome sixe. '(100, 200)' dictates 'randomification' of the biome
                }
            }));
        }

        public override void TileCountsAvailable(int[] tileCounts)
        {
            //Biome Recognition
            When enough of the Geode Stone exists, it will become a Geode Cavern biome
            Casm = tileCounts[mod.TileType("GeodeStone")];
           
       }
    }
 
Welp. I'm back in need- *want* of help..
What are some other methods in scripting for lowering npc hp as a flame/poison/etc debuff, I have this regular script:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.Graphics.Effects;
using Terraria.Graphics.Shaders;
using Terraria.ID;
using Terraria.ModLoader;
using Yinblade.NPCs;

namespace Yinblade.NPCs
{
public class NPCsGLOBAL : GlobalNPC
{
public override bool InstancePerEntity
{
get
{
return true;
}
}

public bool Void = false;

public override void ResetEffects(NPC npc)
{
Void = false;
}

public override void UpdateLifeRegen(NPC npc, ref int damage)
{
if (Void)
{
if (npc.lifeRegen > 0)
{
npc.lifeRegen = 0;
}
npc.lifeRegen -= 15799992;
if (damage < 199999)
{
damage = 199999;
}
}
}
}
}
 
Hi! I'm pretty new to the Terraria community. I've been attempting to create a Terraria mod (I set Visual Studio up but I cannot get a way to make it work.)
It apparently can't find the .png sprite but I created the exact folder "Items" and the image with the right name inside.
Here's a link to an image containing the main points of my doubt:
(P.S. I have checked, the syntax of the names is correct. The path also seems correct, but I cannot get it to work.)

https://pasteboard.co/I5Jiw7B.png

Thank you all for your help in advance.
 
Back
Top Bottom