1. For issues you find with the Switch and Console releases, please follow this link and give as much detail as possible. This is the speediest way to get info to Pipeworks and get a hotfix in the works.
    Dismiss Notice
  2. For issues you find with the Mobile 1.3 update, please follow this link and give as much detail as possible. This is the speediest way to get info to DR Studios to look at your issue. Also, some troubleshooting hints here.
    Dismiss Notice
  3. TCF will be undergoing a scheduled software and server upgrade on September 26, 2019 beginning at 9:00AM GMT. TCF may be unavailable for an extended period after this time. More information can be found here. We apologize in advance for any inconvenience this may cause, we will try to keep the downtime short.

Standalone [1.3] tModLoader - A Modding API

Discussion in 'Works-in-Progress' started by blushiemagic, Jul 7, 2015.

  1. PlayKampfschaf

    PlayKampfschaf Terrarian

    Hi Pros.

    Can somebody explain me the height and width system? When i create a Modtile.

    In the tModLoader gitHub is saw some samples:
    Code:
    TileObjectData.newTile.CopyFrom(TileObjectData.Style2x2);
    What does the 2x2 means in pixel?

    When i have for example a 38x42px images. What i need to set as style? Or did i need:
    Code:
    TileObjectData.newTile.Width = 38;
    TileObjectData.newTile.Height = 42;
    Nothing works well at the moment.

    What is one pixel there? For example i have the extractinator (not animated):
    [​IMG]

    And by the way what i need to set if i wan't to animate that?

    THX
     
  2. Spazzle Weed

    Spazzle Weed Terrarian

    I dare to ask this as I'm sure it's been asked many times, but to save me looking through 700 odd pages - what is the deal with the bugged mannequins. Is it a fixable issue or a just dead as dead unfixable.
     
  3. Proxy

    Proxy Spazmatism

    as far as i know.
    every Sprite in Terraria, a "Pixel" on the Sprite is actually 2x2 Pixels.
    so i assume when you set the Size you need the actual File Resolution X and Y.
    Not sure if anyone even Follows that other than Vanilla Terraria.
     
  4. MrButternuss

    MrButternuss Terrarian

    Hejo Guys, i am pretty new into this whole Modding Stuff. I tried to create a Worm Boss just like the Eater of worlds. (i used a template)
    It all works fine, he spawns, music kicks in, he attacks me...
    BUT
    After some time parts of him despawn. And if i die the Head stays and keeps following me :O
    Halp plz :D
    Code:
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using System;
    using System.IO;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Terraria;
    using Terraria.ID;
    using Terraria.ModLoader;
    
    namespace MementoMod.NPCs.DimensionWorm
    {
        public class WormHead : ModNPC
        {
    
            public override void SetDefaults()
            {
                npc.name = "The Eater of Dimensions";        //this is the npc Name
                npc.displayName = "The Eater of Dimensions";
                npc.lifeMax = 750000;        //this is the npc health
                npc.damage = 200;    //this is the npc damage
                npc.defense = 100;         //this is the npc defense
                npc.aiStyle = -1;
                npc.knockBackResist = 0f;
                npc.width = 200; //this is where you put the npc sprite width.     important
                npc.height = 318; //this is where you put the npc sprite height.   important
                npc.boss = true;
                npc.lavaImmune = true;       //this make the npc immune to lava
                npc.noGravity = true;           //this make the npc float
                npc.noTileCollide = true;        //this make the npc go tru walls
                npc.behindTiles = true;
                Main.npcFrameCount[npc.type] = 1;
                npc.value = Item.buyPrice(0, 20, 0, 0);
                npc.npcSlots = 5f;
                npc.netAlways = true;
                music = MusicID.Boss2;
                npc.HitSound = SoundID.NPCHit1;
                npc.DeathSound = SoundID.NPCDeath1;
                animationType = NPCID.TheDestroyer;
                NPCID.Sets.MustAlwaysDraw[npc.type] = true;
                npc.behindTiles = true;
                npc.value = 120000f;
                npc.alpha = (int) byte.MaxValue;
            }
           
            public override void AI()
            {
                if (npc.localAI[0] == 0f)
                {
                    Main.PlaySound(SoundID.Roar, npc.position, 0);
                    npc.localAI[0] = 1f;
                }
                npc.velocity.Y += 1f;
                if (npc.timeLeft > 10)
                {
                    npc.timeLeft = 10;
                }
            }
           
            public override bool Autoload(ref string name, ref string texture, ref string[] altTextures)
            {
                texture = "MementoMod/NPCs/DimensionWorm/WormHead";
                return mod.Properties.Autoload;
            }
           
            public virtual bool CheckActive()
            {
                return true;
            }
    
            public override void BossLoot(ref string name, ref int potionType)
            {
                potionType = ItemID.LesserHealingPotion;   //boss drops
                Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("DimensionBreaker"));
            }
            public override void ScaleExpertStats(int numPlayers, float bossLifeScale)
            {
                npc.lifeMax = (int)(npc.lifeMax * 0.579f * bossLifeScale);  //boss life scale in expertmode
                npc.damage = (int)(npc.damage * 0.6f);  //boss damage increase in expermode
            }
           
            public override bool PreAI()
            {
                if (Main.netMode != 1)
                {
                    // So, we start the AI off by checking if npc.ai[0] is 0.
                    // This is practically ALWAYS the case with a freshly spawned NPC, so this means this is the first update.
                    // Since this is the first update, we can safely assume we need to spawn the rest of the worm (bodies + tail).
                    if (npc.ai[0] == 0)
                    {
                        // So, here we assing the npc.realLife value.
                        // The npc.realLife value is mainly used to determine which NPC loses life when we hit this NPC.
                        // We don't want every single piece of the worm to have its own HP pool, so this is a neat way to fix that.
                        npc.realLife = npc.whoAmI;
                        // LatestNPC is going to be used later on and I'll explain it there.
                        int latestNPC = npc.whoAmI;
    
                        // Here we determine the length of the worm.
                        // In this case the worm will have a length of 10 to 14 body parts.
                        int randomWormLength = Main.rand.Next(40, 40);
                        for (int i = 0; i < randomWormLength; ++i)
                        {
                            // We spawn a new NPC, setting latestNPC to the newer NPC, whilst also using that same variable
                            // to set the parent of this new NPC. The parent of the new NPC (may it be a tail or body part)
                            // will determine the movement of this new NPC.
                            // Under there, we also set the realLife value of the new NPC, because of what is explained above.
                            latestNPC = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, mod.NPCType("WormBody"), npc.whoAmI, 0, latestNPC);
                            Main.npc[(int)latestNPC].realLife = npc.whoAmI;
                            Main.npc[(int)latestNPC].ai[3] = npc.whoAmI;
                        }
                        // When we're out of that loop, we want to 'close' the worm with a tail part!
                        latestNPC = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, mod.NPCType("WormTail"), npc.whoAmI, 0, latestNPC);
                        Main.npc[(int)latestNPC].realLife = npc.whoAmI;
                        Main.npc[(int)latestNPC].ai[3] = npc.whoAmI;
    
                        // We're setting npc.ai[0] to 1, so that this 'if' is not triggered again.
                        npc.ai[0] = 1;
                        npc.netUpdate = true;
                    }
                }
    
                int minTilePosX = (int)(npc.position.X / 16.0) - 1;
                int maxTilePosX = (int)((npc.position.X + npc.width) / 16.0) + 2;
                int minTilePosY = (int)(npc.position.Y / 16.0) - 1;
                int maxTilePosY = (int)((npc.position.Y + npc.height) / 16.0) + 2;
                if (minTilePosX < 0)
                    minTilePosX = 0;
                if (maxTilePosX > Main.maxTilesX)
                    maxTilePosX = Main.maxTilesX;
                if (minTilePosY < 0)
                    minTilePosY = 0;
                if (maxTilePosY > Main.maxTilesY)
                    maxTilePosY = Main.maxTilesY;
    
                bool collision = false;
                // This is the initial check for collision with tiles.
                for (int i = minTilePosX; i < maxTilePosX; ++i)
                {
                    for (int j = minTilePosY; j < maxTilePosY; ++j)
                    {
                        if (Main.tile[i, j] != null && (Main.tile[i, j].nactive() && (Main.tileSolid[(int)Main.tile[i, j].type] || Main.tileSolidTop[(int)Main.tile[i, j].type] && (int)Main.tile[i, j].frameY == 0) || (int)Main.tile[i, j].liquid > 64))
                        {
                            Vector2 vector2;
                            vector2.X = (float)(i * 16);
                            vector2.Y = (float)(j * 16);
                            if (npc.position.X + npc.width > vector2.X && npc.position.X < vector2.X + 16.0 && (npc.position.Y + npc.height > (double)vector2.Y && npc.position.Y < vector2.Y + 16.0))
                            {
                                collision = true;
                                if (Main.rand.Next(100) == 0 && Main.tile[i, j].nactive())
                                    WorldGen.KillTile(i, j, true, true, false);
                            }
                        }
                    }
                }
                // If there is no collision with tiles, we check if the distance between this NPC and its target is too large, so that we can still trigger 'collision'.
                if (!collision)
                {
                    Rectangle rectangle1 = new Rectangle((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height);
                    int maxDistance = 800;
                    bool playerCollision = true;
                    for (int index = 0; index < 255; ++index)
                    {
                        if (Main.player[index].active)
                        {
                            Rectangle rectangle2 = new Rectangle((int)Main.player[index].position.X - maxDistance, (int)Main.player[index].position.Y - maxDistance, maxDistance * 2, maxDistance * 2);
                            if (rectangle1.Intersects(rectangle2))
                            {
                                playerCollision = false;
                                break;
                            }
                        }
                    }
                    if (playerCollision)
                        collision = true;
                }
    
                // speed determines the max speed at which this NPC can move.
                // Higher value = faster speed.
                float speed = 40f;
                // acceleration is exactly what it sounds like. The speed at which this NPC accelerates.
                float acceleration = 0.17f;
    
                Vector2 npcCenter = new Vector2(npc.position.X + npc.width * 0.5f, npc.position.Y + npc.height * 0.5f);
                float targetXPos = Main.player[npc.target].position.X + (Main.player[npc.target].width / 2);
                float targetYPos = Main.player[npc.target].position.Y + (Main.player[npc.target].height / 2);
    
                float targetRoundedPosX = (float)((int)(targetXPos / 16.0) * 16);
                float targetRoundedPosY = (float)((int)(targetYPos / 16.0) * 16);
                npcCenter.X = (float)((int)(npcCenter.X / 16.0) * 16);
                npcCenter.Y = (float)((int)(npcCenter.Y / 16.0) * 16);
                float dirX = targetRoundedPosX - npcCenter.X;
                float dirY = targetRoundedPosY - npcCenter.Y;
    
                float length = (float)Math.Sqrt(dirX * dirX + dirY * dirY);
                // If we do not have any type of collision, we want the NPC to fall down and de-accelerate along the X axis.
                if (!collision)
                {
                    npc.TargetClosest(true);
                    npc.velocity.Y = npc.velocity.Y + 0.11f;
                    if (npc.velocity.Y > speed)
                        npc.velocity.Y = speed;
                    if (Math.Abs(npc.velocity.X) + Math.Abs(npc.velocity.Y) < speed * 0.4)
                    {
                        if (npc.velocity.X < 0.0)
                            npc.velocity.X = npc.velocity.X - acceleration * 1.1f;
                        else
                            npc.velocity.X = npc.velocity.X + acceleration * 1.1f;
                    }
                    else if (npc.velocity.Y == speed)
                    {
                        if (npc.velocity.X < dirX)
                            npc.velocity.X = npc.velocity.X + acceleration;
                        else if (npc.velocity.X > dirX)
                            npc.velocity.X = npc.velocity.X - acceleration;
                    }
                    else if (npc.velocity.Y > 4.0)
                    {
                        if (npc.velocity.X < 0.0)
                            npc.velocity.X = npc.velocity.X + acceleration * 0.9f;
                        else
                            npc.velocity.X = npc.velocity.X - acceleration * 0.9f;
                    }
                }
                // Else we want to play some audio (soundDelay) and move towards our target.
                else
                {
                    if (npc.soundDelay == 0)
                    {
                        float num1 = length / 40f;
                        if (num1 < 10.0)
                            num1 = 10f;
                        if (num1 > 20.0)
                            num1 = 20f;
                        npc.soundDelay = (int)num1;
                        Main.PlaySound(15, (int)npc.position.X, (int)npc.position.Y, 1);
                    }
                    float absDirX = Math.Abs(dirX);
                    float absDirY = Math.Abs(dirY);
                    float newSpeed = speed / length;
                    dirX = dirX * newSpeed;
                    dirY = dirY * newSpeed;
                    if (npc.velocity.X > 0.0 && dirX > 0.0 || npc.velocity.X < 0.0 && dirX < 0.0 || (npc.velocity.Y > 0.0 && dirY > 0.0 || npc.velocity.Y < 0.0 && dirY < 0.0))
                    {
                        if (npc.velocity.X < dirX)
                            npc.velocity.X = npc.velocity.X + acceleration;
                        else if (npc.velocity.X > dirX)
                            npc.velocity.X = npc.velocity.X - acceleration;
                        if (npc.velocity.Y < dirY)
                            npc.velocity.Y = npc.velocity.Y + acceleration;
                        else if (npc.velocity.Y > dirY)
                            npc.velocity.Y = npc.velocity.Y - acceleration;
                        if (Math.Abs(dirY) < speed * 0.2 && (npc.velocity.X > 0.0 && dirX < 0.0 || npc.velocity.X < 0.0 && dirX > 0.0))
                        {
                            if (npc.velocity.Y > 0.0)
                                npc.velocity.Y = npc.velocity.Y + acceleration * 2f;
                            else
                                npc.velocity.Y = npc.velocity.Y - acceleration * 2f;
                        }
                        if (Math.Abs(dirX) < speed * 0.2 && (npc.velocity.Y > 0.0 && dirY < 0.0 || npc.velocity.Y < 0.0 && dirY > 0.0))
                        {
                            if (npc.velocity.X > 0.0)
                                npc.velocity.X = npc.velocity.X + acceleration * 2f;
                            else
                                npc.velocity.X = npc.velocity.X - acceleration * 2f;
                        }
                    }
                    else if (absDirX > absDirY)
                    {
                        if (npc.velocity.X < dirX)
                            npc.velocity.X = npc.velocity.X + acceleration * 1.1f;
                        else if (npc.velocity.X > dirX)
                            npc.velocity.X = npc.velocity.X - acceleration * 1.1f;
                        if (Math.Abs(npc.velocity.X) + Math.Abs(npc.velocity.Y) < speed * 0.5)
                        {
                            if (npc.velocity.Y > 0.0)
                                npc.velocity.Y = npc.velocity.Y + acceleration;
                            else
                                npc.velocity.Y = npc.velocity.Y - acceleration;
                        }
                    }
                    else
                    {
                        if (npc.velocity.Y < dirY)
                            npc.velocity.Y = npc.velocity.Y + acceleration * 1.1f;
                        else if (npc.velocity.Y > dirY)
                            npc.velocity.Y = npc.velocity.Y - acceleration * 1.1f;
                        if (Math.Abs(npc.velocity.X) + Math.Abs(npc.velocity.Y) < speed * 0.5)
                        {
                            if (npc.velocity.X > 0.0)
                                npc.velocity.X = npc.velocity.X + acceleration;
                            else
                                npc.velocity.X = npc.velocity.X - acceleration;
                        }
                    }
                }
                // Set the correct rotation for this NPC.
                npc.rotation = (float)Math.Atan2(npc.velocity.Y, npc.velocity.X) + 1.57f;
               
                // Some netupdate stuff (multiplayer compatibility).
                if (collision)
                {
                    if (npc.localAI[0] != 1)
                        npc.netUpdate = true;
                    npc.localAI[0] = 1f;
                }
                else
                {
                    if (npc.localAI[0] != 0.0)
                        npc.netUpdate = true;
                    npc.localAI[0] = 0.0f;
                }
                if ((npc.velocity.X > 0.0 && npc.oldVelocity.X < 0.0 || npc.velocity.X < 0.0 && npc.oldVelocity.X > 0.0 || (npc.velocity.Y > 0.0 && npc.oldVelocity.Y < 0.0 || npc.velocity.Y < 0.0 && npc.oldVelocity.Y > 0.0)) && !npc.justHit)
                    npc.netUpdate = true;
    
                return false;
            }
    
            public override bool PreDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, Color drawColor)
            {
                Texture2D texture = Main.npcTexture[npc.type];
                Vector2 origin = new Vector2(texture.Width * 0.5f, texture.Height * 0.5f);
                Main.spriteBatch.Draw(texture, npc.Center - Main.screenPosition, new Rectangle?(), drawColor, npc.rotation, origin, npc.scale, SpriteEffects.None, 0);
                return false;
            }
            public override bool? DrawHealthBar(byte hbPosition, ref float scale, ref Vector2 position)
            {
                scale = 1.9f;   //this make the NPC Health Bar biger
                return null;
            }
        }
    }
    
     
  5. Thrackerzod

    Thrackerzod Terrarian

    I'm new to modding and need some questions answered, like is there a limit to how many mods I can have, and sometimes I get a log when reloading my mods (it mostly happens when trying to load large mods like thorium and calamity) it says "Insufficient memory to continue execution of the program", is this normal? and how can i fix it?
     
  6. PlayKampfschaf

    PlayKampfschaf Terrarian

    THX to jopojelly who helps me out! Works now!
     
  7. Lunatic Lobbyist

    Lunatic Lobbyist The Destroyer

    Thought I'd re-post this here in case tMod devs weren't aware of this -- although I assume you likely are. This is taken from the Legends of Terraria 3 mod thread:


    I too have confirmed experiencing this persistent debug message involving custom sounds in various mods. Is there a way to fix this in an upcoming patch so the messages stop appearing in the chat window whenever specific sounds are played? Thanks.
     
    Last edited: Feb 22, 2017
    Le tromp du Jawa and Fury like this.
  8. leqesai

    leqesai Terrarian

    I am interested in learning if a fix is cowing to address this issue. It's a big bummer
     
    Le tromp du Jawa likes this.
  9. jopojelly

    jopojelly Retinazer

    It's fixed.
     
  10. Misticulx

    Misticulx Terrarian

    =/ im having an issue with Tmodloader when i reload mods it disables random mods that are up to date <_< and its not a conflicting issue cause i was using this mods yesterday
    i think it may just not be loading the mods properly
     
    Le tromp du Jawa likes this.
  11. Fury

    Fury Lunatic Cultist

    A (temporary) fix for this is to enable all the mods you want enabled without trying to reload them, shut down tmodloader and then re-start tmodloader. It should then load all your mods on start-up, unless there is some other issue.
     
    Le tromp du Jawa likes this.
  12. Arcane Dude Aaron

    Arcane Dude Aaron Steampunker

    I just noticed a bug, When I play terraria without mods theres water physics, but when I play with tmodloader the water physics aint there, pls help
     
    Le tromp du Jawa likes this.
  13. Proxy

    Proxy Spazmatism

    Maybe you Turned it off in the Options, because it works fine with Mods Active. (I just Tested it)
     
    Le tromp du Jawa likes this.
  14. Arcane Dude Aaron

    Arcane Dude Aaron Steampunker

    The waves quality are set to high but it still wont work :(
     
    Le tromp du Jawa likes this.
  15. Le tromp du Jawa

    Le tromp du Jawa Eye of Cthulhu

    could be a faulty mod
     
  16. Misticulx

    Misticulx Terrarian

    thanks for the advice ill try that
     
  17. PankHairStudios

    PankHairStudios Skeletron Prime

    Hey can someone help me make this projectile Make another projectile after hitting an Enemy or every 5 seconds shoots a projectile??
    Code:
    using Microsoft.Xna.Framework;
    using Terraria;
    using Terraria.ID;
    using Terraria.ModLoader;
    
    namespace Trelamium.Yoyos
    {
        public class DarkP : ModProjectile
        {
            public override void SetDefaults()
            {
                projectile.CloneDefaults(ProjectileID.TheEyeOfCthulhu);
                projectile.name = "DarkP";
                aiType = ProjectileID.TheEyeOfCthulhu;
            }
        }
    }
     
  18. LePurple

    LePurple Terrarian

    Make a cat mod yo!
     
  19. pat1231

    pat1231 Spazmatism

    hi there :D
    im trying to make a weapon with the ai of the solar eruption
    but ive got a problem now... ive figured out that the weapon shoots a projectile but when i try to copy it it just looks like that:
    [​IMG]
    and heres the code of the pojectile:
    Code:
    using System;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using Terraria;
    using Terraria.ID;
    using Terraria.ModLoader;
    namespace Aoa.Projectiles
    {
        public class beastcutterwhip : ModProjectile
        {
            public override void SetDefaults()
            {
                projectile.CloneDefaults(ProjectileID.SolarWhipSword);
                projectile.name = "beastcutterwhip";
                aiType = ProjectileID.SolarWhipSword;
            }
        }
    }
    now what i want to know:
    is there anyone who can help me?
     
    Last edited: Feb 24, 2017
  20. Proxy

    Proxy Spazmatism

    Buddy you didn't inserted any Images.
    just Upload them to Imgur and Insert them via the Imagine Button when Writing a Reply.
    [​IMG]
    It works VERY Well.

    Even GIFs. :D
     
    PankHairStudios likes this.