Standalone [1.3] tModLoader - A Modding API

Seems complicated, maybe I'm supposed to wait till next update.

Now I got another super wired issue - my NPC disappears!
This is how I design this NPC:
Code:
using System;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace wch.NPCs
{
    public class UnicornPony : ModNPC
    {
        public override bool Autoload(ref string name, ref string texture)
        {
            name = "UnicornPony";
            return mod.Properties.Autoload;
        }

        public override void SetDefaults()
        {
            npc.name = "Unicorn Pony";
            npc.townNPC = true;
            npc.friendly = true;
            npc.width = 18;
            npc.height = 40;
            npc.aiStyle = 7;
            npc.damage = 10;
            npc.defense = 15;
            npc.lifeMax = 250;
            npc.soundHit = 1;
            npc.soundKilled = 1;
            npc.knockBackResist = 0.5f;
            Main.npcFrameCount[npc.type] = 26;
            NPCID.Sets.ExtraFramesCount[npc.type] = 9;
            NPCID.Sets.AttackFrameCount[npc.type] = 4;
            NPCID.Sets.DangerDetectRange[npc.type] = 200;
            NPCID.Sets.AttackType[npc.type] = 1;
            NPCID.Sets.AttackTime[npc.type] = 20;
            NPCID.Sets.AttackAverageChance[npc.type] = 25;
            animationType = NPCID.Guide;
        }

        public override void DrawTownAttackGun(ref float scale, ref int item, ref int closeness)
        {
            scale = 1f;
            item = ItemID.PlatinumBow;
            closeness = 12;
        }


        public override bool CanTownNPCSpawn(int numTownNPCs, int money)
        {
            for (int k = 0; k < 255; k++)
            {
                Player player = Main.player[k];
                if (player.active)
                {
                    for (int j = 0; j < player.inventory.Length; j++)
                    {
                        if (player.inventory[j].type == mod.ItemType("TestItem"))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }


        public override string TownNPCName()
        {
            switch (WorldGen.genRand.Next(3))
            {
                case 0:
                    return "EnergySway";
                default:
                    return "CresentSpark";
            }
        }

        public override string GetChat()
        {
            switch (Main.rand.Next(3))
            {
                case 0:
                    return "What? You never seen a talking unicorn before?";
                default:
                    return "For the last time, I'm a PONY! Not a HORSE! Somebody just can't figure out the difference.";
            }
        }

        public override void SetChatButtons(ref string button, ref string button2)
        {
            button = Lang.inter[28];
        }

        public override void OnChatButtonClicked(bool firstButton, ref bool shop)
        {
            if (firstButton)
            {
                shop = true;
            }
        }

        public override void SetupShop(Chest shop, ref int nextSlot)
        {
            shop.item[nextSlot].SetDefaults(ItemID.WoodenArrow);
            nextSlot++;
            if (Main.moonPhase < 2)
            {
                shop.item[nextSlot].SetDefaults(mod.ItemType("WoodSheild"));
                nextSlot++;
            }
            else if (Main.moonPhase < 6)
            {
                shop.item[nextSlot].SetDefaults(mod.ItemType("LavaSheild"));
                nextSlot++;
            }
            else
            {
            }
        }

        public override void TownNPCAttackStrength(ref int damage, ref float knockback)
        {
            damage = 20;
            knockback = 4f;
        }

        public override void TownNPCAttackCooldown(ref int cooldown, ref int randExtraCooldown)
        {
            cooldown = 10;
            randExtraCooldown = 40;
        }

        public override void TownNPCAttackProj(ref int projType, ref int attackDelay)
        {
            projType = ProjectileID.JestersArrow;
            attackDelay = 5;
        }

        public override void TownNPCAttackProjSpeed(ref float multiplier, ref float gravityCorrection, ref float randomOffset)
        {
            multiplier = 12f;
            randomOffset = 2f;
        }
    }
}
Every time I log out the game, it will disappear. By "disappear", it's not delete. The NPC is still well loaded, but it needs to reappear every time I restart the game. Seems the game can't save the status of this NPC, what's wrong? This is pretty wired.
You need to use Autoload to make the internal name the same as the name (so you need to add a space in the Autoload name). I might try to make this easier to use later.

Installation Error
Could not find installation resource file
I'm use Windows XP SP3
Help! :(
You made sure to unzip the folder, right?

so I have been looking through some projectile methods and found this: http://prntscr.com/9ieb8d

Can someone teach me how to work with this?
The best help I can give is this:
https://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritebatch.draw.aspx

I changed nothing, it is craftable by hand right? I'm not sure if it even loaded the mod correctly, it has the green text saying it is in use(or loaded or whatever)
It should be possible to craft it by hand with a single dirt block.
 
You need to use Autoload to make the internal name the same as the name (so you need to add a space in the Autoload name). I might try to make this easier to use later.


You made sure to unzip the folder, right?


The best help I can give is this:
https://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritebatch.draw.aspx


It should be possible to craft it by hand with a single dirt block.
It would be awesome if you could add something using that Method into your example mod since that's the best way I am learning this...
And thank you very much, this is pushing me into the right direction I think :D
 
It would be awesome if you could add something using that Method into your example mod since that's the best way I am learning this...
And thank you very much, this is pushing me into the right direction I think :D
A lot of the projectiles in the ExampleMod actually use this. For example, even the ExampleBullet uses this:

Code:
        public override bool PreDraw(SpriteBatch spriteBatch, Color lightColor)
        {
            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;
        }
You'll see that I'm calling spriteBatch.Draw multiple times to make it look like the ExampleBullet has a trail. Now let's look at each part. The Main.projectileTexture[projectile.type] is just the texture to be drawn. Then drawPos is the position on the screen to draw the bullet. Notice that I subtract Main.screenPosition from drawPos to make this possible.
The next thing, null, is just how much of the texture to draw. If you make it null, that means to draw the full texture. Alternatively, you can pass in a Rectangle instead, to draw the area specified by the rectangle. (Useful for projectiles with multiple frames.)
Then color is basically the color to shade the projectile in. When I create the color, there are two parts. projectile.GetAlpha(lightColor) gets the color to draw the projectile in. Now, notice I multiply the result by another thing. Multipling a color by a number between 0 and 1 basically lets you determine the transparency to draw the projectile in.
projectile.rotation is self-explanatory. drawOrigin is the point on the projectile's texture to rotate the projectile around. To rotate the projectile around its center, just set the drawOrigin to the midpoint of the texture, like I've done here. projectile.scale allows you to multiply the size the projectile is drawn in.
SpriteEffects.None means, well, no special effects. However, you can replace this with SpriteEffects.FlipHorizontally or SpriteEffects.FlipVertically.
The last part, 0f, should always be 0f for the purposes of Terraria. Never change that.

For more examples, just look through the ExampleMod; there's a lot of it. Note that if all you want to do is determine the projectile's frame, you can just set projectile.frame to 0 for the first frame, 1 for the second, etc., in the projectile's AI hook.
 
A lot of the projectiles in the ExampleMod actually use this. For example, even the ExampleBullet uses this:

Code:
        public override bool PreDraw(SpriteBatch spriteBatch, Color lightColor)
        {
            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;
        }
You'll see that I'm calling spriteBatch.Draw multiple times to make it look like the ExampleBullet has a trail. Now let's look at each part. The Main.projectileTexture[projectile.type] is just the texture to be drawn. Then drawPos is the position on the screen to draw the bullet. Notice that I subtract Main.screenPosition from drawPos to make this possible.
The next thing, null, is just how much of the texture to draw. If you make it null, that means to draw the full texture. Alternatively, you can pass in a Rectangle instead, to draw the area specified by the rectangle. (Useful for projectiles with multiple frames.)
Then color is basically the color to shade the projectile in. When I create the color, there are two parts. projectile.GetAlpha(lightColor) gets the color to draw the projectile in. Now, notice I multiply the result by another thing. Multipling a color by a number between 0 and 1 basically lets you determine the transparency to draw the projectile in.
projectile.rotation is self-explanatory. drawOrigin is the point on the projectile's texture to rotate the projectile around. To rotate the projectile around its center, just set the drawOrigin to the midpoint of the texture, like I've done here. projectile.scale allows you to multiply the size the projectile is drawn in.
SpriteEffects.None means, well, no special effects. However, you can replace this with SpriteEffects.FlipHorizontally or SpriteEffects.FlipVertically.
The last part, 0f, should always be 0f for the purposes of Terraria. Never change that.

For more examples, just look through the ExampleMod; there's a lot of it. Note that if all you want to do is determine the projectile's frame, you can just set projectile.frame to 0 for the first frame, 1 for the second, etc., in the projectile's AI hook.

Wow thank you, that helped a lot!
 
ugh something weird happened..
.
meh.gif


Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ModLoader;
using Terraria.ID;
using GMod.Dusts;
using GMod.Projectiles;
using Terraria.DataStructures;

namespace GMod.Projectiles
{
    public class Scyte : ModProjectile
    {
        public override void SetDefaults()
        {
            projectile.name = "Scyte";
            projectile.width = 16;
            projectile.height = 16;
            projectile.friendly = true;
            projectile.magic = true;
            projectile.penetrate = 3;
            projectile.timeLeft = 50;

        }
   
       
       

            public override void AI()
            {
                projectile.type = 45;
            projectile.velocity.Y += projectile.ai[0];
            if (Main.rand.Next(3) == 0)
            {
                Dust.NewDust(projectile.position + projectile.velocity, projectile.width, projectile.height, mod.DustType("Sparkle"), projectile.velocity.X * 0.5f, projectile.velocity.Y * 0.5f);
            }
           
            projectile.light = 2f;
            projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f;
            if(projectile.frameCounter < 20)
            {
                projectile.frame = 2;
                if(projectile.damage <= 100)
                    projectile.damage += 1;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.01f;
                projectile.velocity.X *= 1.01f;
            }
            else if(projectile.frameCounter >= 20 && projectile.frameCounter < 50)
            {
                projectile.frame = 1;
                if(projectile.damage <= 100)
                    projectile.damage += 2;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.02f;
                projectile.velocity.X *= 1.02f;
                int DustID1 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width/2 + 4, projectile.height/2 + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f);
                Main.dust[DustID1].noGravity = true;
            }
            else
            {
                projectile.frame = 0;
                if(projectile.damage <= 100)
                    projectile.damage += 3;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.03f;
                projectile.velocity.X *= 1.03f;
                int DustID2 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width + 4, projectile.height + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f);
                Main.dust[DustID2].noGravity = true;
            }
            projectile.frameCounter++;
            }
    }
}
 
ugh something weird happened..
.View attachment 89912

Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ModLoader;
using Terraria.ID;
using GMod.Dusts;
using GMod.Projectiles;
using Terraria.DataStructures;

namespace GMod.Projectiles
{
    public class Scyte : ModProjectile
    {
        public override void SetDefaults()
        {
            projectile.name = "Scyte";
            projectile.width = 16;
            projectile.height = 16;
            projectile.friendly = true;
            projectile.magic = true;
            projectile.penetrate = 3;
            projectile.timeLeft = 50;

        }
  
      
      

            public override void AI()
            {
                projectile.type = 45;
            projectile.velocity.Y += projectile.ai[0];
            if (Main.rand.Next(3) == 0)
            {
                Dust.NewDust(projectile.position + projectile.velocity, projectile.width, projectile.height, mod.DustType("Sparkle"), projectile.velocity.X * 0.5f, projectile.velocity.Y * 0.5f);
            }
          
            projectile.light = 2f;
            projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f;
            if(projectile.frameCounter < 20)
            {
                projectile.frame = 2;
                if(projectile.damage <= 100)
                    projectile.damage += 1;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.01f;
                projectile.velocity.X *= 1.01f;
            }
            else if(projectile.frameCounter >= 20 && projectile.frameCounter < 50)
            {
                projectile.frame = 1;
                if(projectile.damage <= 100)
                    projectile.damage += 2;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.02f;
                projectile.velocity.X *= 1.02f;
                int DustID1 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width/2 + 4, projectile.height/2 + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f);
                Main.dust[DustID1].noGravity = true;
            }
            else
            {
                projectile.frame = 0;
                if(projectile.damage <= 100)
                    projectile.damage += 3;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.03f;
                projectile.velocity.X *= 1.03f;
                int DustID2 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width + 4, projectile.height + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f);
                Main.dust[DustID2].noGravity = true;
            }
            projectile.frameCounter++;
            }
    }
}
If you want to use multiple projectile frames, you'll need to tell the game that you have multiple projectile frames, by setting Main.projFrames[projectile.type] to the number of frames you have.
 
ugh something weird happened..
.View attachment 89912

Code:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria;
using Terraria.ModLoader;
using Terraria.ID;
using GMod.Dusts;
using GMod.Projectiles;
using Terraria.DataStructures;

namespace GMod.Projectiles
{
    public class Scyte : ModProjectile
    {
        public override void SetDefaults()
        {
            projectile.name = "Scyte";
            projectile.width = 16;
            projectile.height = 16;
            projectile.friendly = true;
            projectile.magic = true;
            projectile.penetrate = 3;
            projectile.timeLeft = 50;

        }
  
      
      

            public override void AI()
            {
                projectile.type = 45;
            projectile.velocity.Y += projectile.ai[0];
            if (Main.rand.Next(3) == 0)
            {
                Dust.NewDust(projectile.position + projectile.velocity, projectile.width, projectile.height, mod.DustType("Sparkle"), projectile.velocity.X * 0.5f, projectile.velocity.Y * 0.5f);
            }
          
            projectile.light = 2f;
            projectile.rotation = (float)Math.Atan2((double)projectile.velocity.Y, (double)projectile.velocity.X) + 1.57f;
            if(projectile.frameCounter < 20)
            {
                projectile.frame = 2;
                if(projectile.damage <= 100)
                    projectile.damage += 1;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.01f;
                projectile.velocity.X *= 1.01f;
            }
            else if(projectile.frameCounter >= 20 && projectile.frameCounter < 50)
            {
                projectile.frame = 1;
                if(projectile.damage <= 100)
                    projectile.damage += 2;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.02f;
                projectile.velocity.X *= 1.02f;
                int DustID1 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width/2 + 4, projectile.height/2 + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f);
                Main.dust[DustID1].noGravity = true;
            }
            else
            {
                projectile.frame = 0;
                if(projectile.damage <= 100)
                    projectile.damage += 3;
                else
                    projectile.damage = 100;
                projectile.velocity.Y *= 1.03f;
                projectile.velocity.X *= 1.03f;
                int DustID2 = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + 2f), projectile.width + 4, projectile.height + 4, 64, projectile.velocity.X * 0.2f, projectile.velocity.Y * 0.2f, 120, default(Color), 0.75f);
                Main.dust[DustID2].noGravity = true;
            }
            projectile.frameCounter++;
            }
    }
}
What is that flash? Is it made by purpose?
 
What am i doing? It says that Main.animationFrameHeight = 4; does not exist and public override void AnimateTile is missing bunch of brackects...

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

namespace ExampleMod.Tiles
{
    public class EnchantingTable : ModTile
    {
        public override void SetDefaults()
        {
            Main.tileSolidTop[Type] = true;
            Main.tileFrameImportant[Type] = true;
            Main.tileNoAttach[Type] = true;
            Main.animationFrameHeight = 4;
            Main.tileTable[Type] = false;
            Main.tileLavaDeath[Type] = true;

public override void AnimateTile(ref int frame, ref int frameCounter)
{
      frameCounter++;
      if (frameCounter >= 10)
      {
          frame = (frame + 1) % 4;
          frameCounter = 0;
      }
}

            TileObjectData.newTile.CopyFrom(TileObjectData.Style2x1);
            TileObjectData.newTile.CoordinateHeights = new int[]{ 18 };
            TileObjectData.addTile(Type);
            AddToArray(ref TileID.Sets.RoomNeeds.CountsAsTable);
            dustType = mod.DustType("Sparkle");
            adjTiles = new int[]{ TileID.WorkBenches };
        }

        public override void NumDust(int i, int j, bool fail, ref int num)
        {
            num = fail ? 1 : 3;
        }

        public override void KillMultiTile(int i, int j, int frameX, int frameY)
        {
            Item.NewItem(i * 16, j * 16, 32, 16, mod.ItemType("EnchantingTable"));
        }
    }
}
 
Your dedication to this really impresses me. Kudos.
It feels like a year since last time I posted on this thread asking for help and you responded within minutes.
 
How to make a mount that completely replaces the player sprite, is 2×2 tiles and has infinite flying and takes only one frame to start moving and to stop?
[DOUBLEPOST=1451079144,1451078786][/DOUBLEPOST]Is it possible to create a buff that reduces the maximum health to 1 point but gives a 99% chance of dodging every attack?
 
How to let a projectile spin at the end (Like Vampire knives)
or just let it spin in general

and how to add dust on melee weapons...

I am so dumb ;_;
 
There is a projectile type ID for Vampire Knifes and other thrown weapons. Did my previous help... Help?
I tried to use the type, but it changed the sprite to the vampire knife instead of mine, so I tried to make it with aistyle... if you can tell me how to force my picture to show up then I would be glad.
And yes it did
 
bluemagic123 can you help me ? I createf laser rifle : shootspeed = 2, extraUpadet = 20, and add dust but the trail is made of many dusts and they are randomly rotated and i want only straight line what should i do ?
 
Back
Top Bottom