tAPI Getting Started with Modding

Status
Not open for further replies.

berberborscing

Skeletron Prime
Do none of the mods the Terraria community has to offer interest you? Do you have a lot of ideas that others don't?
Do you wish to indulge into the world of modding? If you're here, then I suppose so!

Here is the download to the software I'll be talking about: http://forums.terraria.org/index.php?threads/tapi-a-mod-to-make-mods.3203/

There are set guidelines for these mods however. Make sure to follow them!
-If a sprite for an item is not yours, make sure you have permission from the sprite creator and give him credit. The credit is worthless without the permission!
-Making unobtainable items obtainable is against the rules: This includes items removed from the game such as the Zapinator, developer items, and currently existing items that are unobtainable (Such as the Gravity Globe and the SDMG)
-Try not to make your weapons unbalanced on purpose. Balancing is good and prevents your item from being useless / overused for it's sheer (lack of) power.
-Obviously nothing offensive and vulgar.
-It's OK if you have a ridiculously powerful weapon in your mod, as long as it isn't ridiculously easy to obtain. For example, crafting a machine gun that shoots so fast it could crash the game, being crafted with a single block of dirt. Unless your mod is the overpowered weapons mod, in which that case, go right ahead.

After you finish downloading Terraria, it's time to find a place to put your mod. Find your workspace in \Documents\My Games\Terraria\tAPI\Mods\Sources.
Make a new folder, and the folder's name will be the name of your mod.

Open .JSON and .CS files with Notepad (I strongly recommend Notepad++)
Now we need a ModInfo file. Start a new text file, and change the .txt extension to .json (Enable file extensions to do this.)
Here is an example:
Code:
{
    "displayName" : "berberborscing's Mod", //This is what the mod is named in the mod selection menu in tAPI.
    "author"      : "berberborscing", //This is where your name goes.
    "info"        : "Stop reading this and play the mod", //This is a description for your mod. Don't put too much effort into it, chances are nobody's going to read it.
    "internalName" : "berberborscing" //This is the internal name of your mod (This will come in handy when programming items with C#) Don't put special characters and spaces here, keep it simple
}
Now we need a place to put our new items. Make a folder in your mod folder next to ModInfo.json called "Items". (DO NOT NAME IT "Item". THIS IS WHAT THROWS EVERYONE OFF)
Alright, let's get started with a basic item. Let's take an example from my mod. Energy.
The spriting programs I recommend are: Paint.NET or GIMP (or Photoshop if you really prefer it and have it)
I DO NOT RECOMMEND MS PAINT. It is impossible to remove the white background from items in that program.
Here is the outcome.
soul_of_blight-png.1605

Make a new JSON file that's the exact same name as the image you made.
And for the JSON code:
Code:
{
    "displayName": "Energy", //This is the name of the item in the game.
    "size": [22,22], //This is the size of the texture. Just make sure it's the same as the image size.
    "maxStack": 250, //This is how much of it stacks. If you are making a weapon, make this value "1".
    "value": [0,0,200,0], //This is how much it is worth, respectively, [Platinum,Gold,Silver,Copper]. Sell price is one fifth of this value.
    "rare": 1, //This is the rarity level. It will burn in lava if it is set to 0.
    "tooltip": "'Just. Pure.. Energy.'", //This is the text it will say when you hover your cursor over it.

    "recipes":
    [{
        "items": { "Gel": 10, "Fallen Star": 2}, //These are the items you need to craft it.
        "tiles": [ "Furnace" ], //This is the tile you need to craft it at.
        "creates": 1 //This is how much it will create. If you are making an ammo, make this more than 1, as crafting ammo one at a time is resource-demanding.
    }]
}
Other things to note: Make sure there is a comma at the end of every line except the last one, or else you will have compilation errors in the tAPI builder.
Next we will learn how to build a basic melee weapon.
Let's build a basic melee weapon, let's say, a fiery baseball bat, and we'll call it "Bat Outta Hell".
qIwwFFO.png

(NOTE: If you are making a weapon that has more than one word in it's name, don't put in a space. This file would be named "BatOuttaHell.png" rather than "Bat Outta Hell.png")
Make a new JSON file that's the exact same name as the image (and yes, it's case sensitive)
Code:
{
   "displayName": "Bat Outta Hell",
   "size": [40, 40],
   "maxStack": 1,
   "value": [0,5,0,0],
   "rare": 1,
   "tooltip": "'Can't take the heat?'",
   "useStyle": 1,
   "useAnimation": 16, //Goes with useTime, if this value is higher than useTime the weapon will be used more than once per click
   "useTime": 16,
   "damage": 26, //How much damage the weapon does.
   "knockback": 50, //This should be enough to knock a skeleton all the way to the surface.
   "useSound": 1, //Generic swinging sound
   "autoReuse": false,
   "melee": true, //Item gains bonuses from melee equipment

   "recipes":
   [{
     "items": { "BaseballBat": 1, "Hellstone Bar": 15, "Obsidian": 5 },
     "tiles": [ "Anvil" ],
     "creates": 1
   }]
}
If you want this weapon to function as a pickaxe, axe, or hammer, make sure the useStyle is 1, and add one of the following lines:
Code:
"pick": 90, //90% pickaxe power
"axe": 90, //90% axe power
"hammer": 90 //90% hammer power (Don't merge hammers with pickaxes, the hammer overrides the pickaxe!)
Now you can stop here, or you can apply a debuff to the enemy with a CS file.
We want the weapon to light the target on fire. Make a new CS file, open it with Notepad or Notepad++, and follow along.
Code:
using Terraria;
using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;

using TAPI; //The resources the code will be using for all the variables

namespace InternalModName.Items
{
public class ItemName : ModItem
    {
        public override void DamageNPC(Player owner, NPC npc, int hitDir, ref int damage, ref float knockback, ref bool crit, ref float critMult) //The code will be called when the item hits an NPC
        {
            npc.AddBuff (24, 300, true); //24 is the "On Fire!" buff ID, 300 is the duration (5 seconds), and you know what "true" means! (Not all buffs and debuffs can be applied to NPCs!)
        }
    }
}
Shove it into the tAPI builder, and it should compile.
Next I would move into armor, but accessories are more simple. I can refer to one of my threads for this matter as for all the effects: http://forums.terraria.org/index.php?threads/providing-help-for-accessories.3462/

Let's take an example.
QcktzdO.png
I call it: the Bee Bumper, a shield with a spike on it.
Here is the code:
Code:
{
    "displayName": "Bee Bumper",
    "size": [32,32],
    "maxStack": 1,
    "value": [0,24,26,1200],
    "rare": 1,
    "defense": 2, //How much defense the accessory provides. Every 2 defense points removes 1 damage point from an enemy.
    "accessory": true, //If true, you can equip this in an accessory slot.
    "tooltip": "Increases max number of minions and deals massive thorns damage", //This alone is not enough to give the item an effect. We need to delve into C#.
    "textureShield": "Items/Accessories/Shields/BeeBumper_Shield", //This line is optional, use only if you want it to appear on the player (You need an animation for this.)

    "recipes":
    [{
        "items": { "Hive": 20, "Honey Block": 10, "Stinger": 10 },
        "tiles": [ "Anvil" ],
        "creates": 1
    }]
}
But this code alone will only have the effect of 2 defense. We need a CS file to get the rest of the effects.
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;  //all these using lines tell the mod what to use as resources for the code we will be doing.

namespace InternalModName.Items
{
    public class ItemName : ModItem
    {
        public override void Effects(Player p) //This is called a hook. This is where the effects are called. In this instance, it is called when the player has it equipped. It must have the correct parameters (the "Player p" thing) or else the builder will give you errors.
        {
            p.maxMinions += 1; //These are where the effects from the above link go. This effect lets you have an extra minion. This is called an INT, and is set with a numeric value.
            p.thorns = 1.5f; //This effect sets how much damage mobs take back when they touch you. Since the shield is spiky, it should hurt whoever touches it. If a monster deals 30 damage, then it will take 45 damage with this on, no matter how much damage you take from the monster. This is called a FLOAT, the "f" being a variable that represents a value, and the "1.5" being a multiplier. In this case, the "f" is the enemy damage.
            p.statLifeMax2 += 5; //This effect will give you an extra 5 Life when you equip it. Simple enough. It is also an INT.
        }
        public override void DamageNPC(Player p, NPC n, int hitDir, ref int damage, ref float knockback, ref bool crit, ref float critMult) //This code is called when you hit an NPC with a melee weapon
        {
              p.statLife += 5 //This will heal the player by 5 health whenever he hits an NPC, but since this isn't an ability of the Bee Bumper this code is optional
        }
    }
}
Throw it in the compiler and it should work.
Next, let's make an armor set. To be more specific, the over-requested Slime set.
You need sprites for the armor.
4CGYmLS.png
POHg8hy.png
4cAhPJX.png

And their animations. You can download Terraria source code if you need something to base it on. (The names for the animation should be "HelmetName_Head", "ChestplateName_Body", and "BootsName_Legs", and you need a "ChestplateName_Arms" and a "ChestplateName_FemaleBody" so you don't enrage feminists)
Now it's time to make a JSON file for the helmet.
Code:
{
    "displayName": "Slime Helmet",
    "size": [24,16],
    "maxStack": 1,
    "value": [0,0,6,0],
    "rare": 1,
    "defense": 1,
    "tooltip": "Increases minion damage by 10%",
    "armorHead": true, //This lets you equip the item on your head.
    "setname": "Slime", //This is used to determine what conditions need to be met for the set bonus to be active.
    "hairType": 0, //This changes the hair to bald while the player has this helmet equipped, so that the hair doesn't make the helmet look weird, hair style returns to normal when item is unequipped

    "recipes":
    [{
        "items": { "Gel": 20 },
        "tiles": [ "Work Bench" ],
        "creates": 1
    }]
}
And to get the Helmet to give the 10% increased summoner damage, we use a CS file. I won't show one for the sake of saving space, you already saw a sample accessory CS, this is the same as that.
Create a JSON file for the Chestplate and follow:
Code:
{
    "displayName": "Slime Chestplate",
    "size": [30,20],
    "maxStack": 1,
    "value": [0,0,7,0],
    "rare": 1,
    "defense": 2,
    "tooltip": "Increases max number of minions",
    "armorBody": true, //This lets you equip this like a chest piece of armor.
    "hasHands": false, //This determines whether or not your hands will be visible in this armor set.
    "setname": "Slime", //It is important that all pieces of armor have this code with the same string (The string is the thing that says "Slime")
    "textureFemale": "Items/Armor/Slime/SlimeChestplate_FemaleBody",

    "recipes":
    [{
        "items": { "Gel": 25 },
        "tiles": [ "Work Bench" ],
        "creates": 1
    }]
}
And a JSON for the Boots:
Code:
{
    "displayName": "Slime Leggings",
    "size": [22,18],
    "maxStack": 1,
    "value": [0,0,5,0],
    "rare": 1,
    "defense": 1,
    "tooltip": "Increases jumping height",
    "armorLegs": true, //Lets you equip this on your feets.
    "setname": "Slime",

    "recipes":
    [{
        "items": { "Gel": 15 },
        "tiles": [ "Work Bench" ],
        "creates": 1
    }]
}
And now for the setbonus, make sure that for the CS file of one of the pieces of the armor set (usually the chest piece), you have the code shown:
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace berberborscing.Items
{
    public class SlimeChestplate : ModItem
    {
        public override void Effects(Player p)
        {
            p.maxMinions += 1;
        }
        public override void ArmorSetBonus(Player player) //This is called when the player has the whole set equipped.
        {
            player.maxMinions += 1;
            player.setBonus = "Increased max number of minions"; //This is the dialogue the game says that tells you the set bonus of your armor set.
        }
    }
}
Throw it into the compiler and it should work.
Everyone wants to know how to do this nowadays, whether it be to make Lihzahrd Energy Cells craftable like in the mobile version or whatever. Today we will make the ridiculously rare Slime Staff craftable. Make a file named "Modbase.cs". You can name this new CS file anything you want, but I choose "Modbase.cs" since this is where all the code the mod will call regarding Vanilla content.
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace berberborscing.Items
{
    public class Modbase : ModBase //Use ModBase instead of Items.
    {
        public override void OnLoad() //This will call the code when you load up the game.
        {
            Recipe.newRecipe.createItem.SetDefaults(1309, false); //This is where the item you want to add a recipe to goes. "1309" is the ID of the Slime Staff.
            Recipe.newRecipe.createItem.stack = 1; //This is how many are produced by this recipe.
            Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(9, false)); //This is the first item used in the recipe. "9" is the ID for Wood.
            Recipe.newRecipe.requiredItem[0].stack = 15; //This is how much Wood we need, 15. the [0] notes that this is the first material in the recipe.
            Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(23, false)); //This is the second item used in the recipe. "23" is the ID for Gel.
            Recipe.newRecipe.requiredItem[1].stack = 80; //We need 80 Gel. The [1] means it is the second material in the recipe. It goes up from there.
            Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(29, false)); //"29" is the ID for Life Crystal. Get it now?
            Recipe.newRecipe.requiredItem[2].stack = 1; //We need 1 Heart Crystal.
            Recipe.newRecipe.requiredTile.Add(18); //This is where the crafting station you need goes. "18" is the ID for the Work Bench.
            Recipe.AddRecipe(); //This tidbit of code adds the recipe into the game.
        }
    }
}
If you want a recipe that uses a material from your mod, add this line:
Code:
Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults( ItemDef.byName["InternalModName:ItemName"].type, false))
Or if you want to use a custom tile to craft it at, add this line:
Code:
Recipe.newRecipe.requiredTile.Add(TileDef.byName["internalname:tilename"]);
And if you want to add more recipes to your mod, add another recipe right after the line
Code:
Recipe.AddRecipe();
as I will illustrate in this example here;
Code:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace berberborscing.Items //replace "berberborscing" with your mod's internal name
{
    public class Recipes : ModBase
    {
        public override void OnLoad()
        {
            Recipe.newRecipe.createItem.SetDefaults(1309, false); //Slime Staff
            Recipe.newRecipe.createItem.stack = 1; //This recipe will craft 1 Slime Staff.
            Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(9, false)); //Needs Wood
            Recipe.newRecipe.requiredItem[0].stack = 15; //Requires 15 Wood
            Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(23, false)); //Needs Gel
            Recipe.newRecipe.requiredItem[1].stack = 80; //Needs 80 Gel
            Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(29, false)); //Needs Heart Crystal
            Recipe.newRecipe.requiredItem[2].stack = 1; //Needs 1 Heart Crystal
            Recipe.newRecipe.requiredTile.Add(18); //Crafted at a Work Bench
            Recipe.newRecipe.createItem.SetDefaults(1310, false); //Poison Dart
            Recipe.newRecipe.createItem.stack = 5; //Create 5 Poison Darts
            Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(22, false)); //Needs Iron Bars
            Recipe.newRecipe.requiredItem[0].stack = 1; //Needs 1 Iron Bar
            Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(320, false)); //Needs Feathers
            Recipe.newRecipe.requiredItem[1].stack = 1; //Needs 1 Feather
            Recipe.newRecipe.requiredTile.Add(18); //At a work bench
        }

    }
}
Throw it into the compiler and it should work.
You can't go anywhere in the modding forums without seeing a mod with a gun in it. So I'll teach you how to spread this ranged plague.
Let's make a gun that shoots bullets. We'll call this one "The Problem Solver". (No sprite currently due to ownership issues.)
Create a JSON file:
Code:
{
    "displayName": "The Problem Solver",
    "size": [60, 28],
    "maxStack": 1,
    "value": [1, 0, 0, 0],
    "rare": 8,
    "tooltip": "Whatever your problem is, this is gonna fix it",
    "useStyle": 5,
    "useAnimation": 8,
    "useTime": 8,
    "damage": 35,
    "knockback": 8,
    "autoReuse": true,
    "noMelee": true, //This makes it so that the gun doesn't do any damage if a mob touches it without touching a bullet
    "shoot": 14, //The projectile ID to make the gun shoot any bullet you have in your inventory. Change it to "1" if you want it to fire arrows instead.
    "shootSpeed": 15, //The speed of the projectiles fired by this gun. Set it higher if you want the projectile to be faster.
    "useAmmo": 14, //This makes the weapon consume arrows. Set to "1" to consume arrows.
    "ranged": true, //The weapon will be boosted by ranged damage and speed bonuses.

    "recipes":
    [{
        "items": { "Illegal Gun Parts": 2, "Megashark": 1, "Tactical Shotgun": 1, "Energy": 25 },
        "tiles": [ "Mythril Anvil" ],
        "creates": 1
    }]
}
Now I know for certain someone is going to complain about how to make bullet spread like a shotgun, so we will give this machine gun a spread of bullets.
Code:
using Terraria;
using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;

using TAPI;

namespace berberborscing.Items
{
public class ProblemSolver : ModItem
    {
       public override bool PreShoot(Player player,Vector2 ShootPos,Vector2 ShootVelocity,int projType,int Damage,float knockback) //This code is performed before the player shoots the weapon. Copy these parameters exactly if you want it to work.
        {
            int ShotAmt = 5; //Amount of projectiles fired from the weapon. If you want to make a slightly inaccurate machine gun type of weapon, set this to 1
            int spread = 25; //The angle of random spread.
            float spreadMult = 0.05f; //Multiplier for bullet spread, set it higher and it will make for some outrageous spread.
            for(int i = 0; i < ShotAmt; i++)
            {
                float vX = ShootVelocity.X+(float)Main.rand.Next(-spread,spread+1) * spreadMult;
                float vY = ShootVelocity.Y+(float)Main.rand.Next(-spread,spread+1) * spreadMult;

                Projectile.NewProjectile(ShootPos.X,ShootPos.Y,vX,vY,projType,Damage,knockback,Main.myPlayer);
            }
            return false;
        }
    }
}
Now some people want the gun to use custom ammo. For an example, we will use a different weapon, deemed, the Gatling Laser.
index.php
(Credit to SlayerOfTheBad for sprite). We want it to fire Energy Cells. First, let's create a JSON for the weapon.
Code:
{
    "displayName": "Gatling Laser",
    "size": [30, 28],
    "maxStack": 1,
    "value": [1, 0, 0, 0],
    "rare": 7,
    "tooltip": "60% chance not to consume energy cells",
    "useStyle": 5,
    "useAnimation": 8,
    "useTime": 8,
    "damage": 30,
    "autoReuse": true,
    "noMelee": true,
    "shoot": 260, //This is the projectile the Heat Ray fires.
    "shootSpeed": 10,  //When accompanied with the Heat Ray projectile, this number can restrict the weapon's range if this value is low enough.
    "useAmmo": "EnergyCell", //This tells the weapon what item to consume upon firing.
    "ranged": true,

    "recipes":
    [{
        "items": { "Railgun": 1, "Illegal Gun Parts": 1, "Energy": 25, "Shroomite Bar": 15, "Lihzahrd Power Cell": 2 }, //Railgun is another weapon from my mod, not a vanilla Terraria item
        "tiles": [ "Mythril Anvil" ],
        "creates": 1
    }]
}
Now some of you are complaining "How do I make the weapon not consume ammo?" In some confusing way that uses double negatives. Let's explore this in the CS file.
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace berberborscing.Items
{
    public class GatlingLaser : ModItem
    {
        public override bool ConsumeAmmo(Player p) //This code is called when a weapon consumes ammo
        {
            return Main.rand.Next(10) < 6; //This would be a 60% chance not to consume ammo. Change it to 5 for 50%, 7 for 70%, etc.
        }
    }
}
Now it's time to code the ammo, the Energy Cell.
07n2PKf.png

Code:
{
    "displayName": "Energy Cell",
    "size": [22,14],
    "maxStack": 999,
    "value": [0,0,2,0],
    "rare": 2,
    "tooltip": "Ammo for the Gatling Laser",
    "ammo": "EnergyCell", //Used to let the game know which weapon consumes this item as ammo
    "ranged": true,
    "consumable": true, //If false, one bullet would last forever.

    "recipes":
    [{
        "items": { "Chlorophyte Bar": 5, "Energy": 10 },
        "tiles": [ "Mythril Anvil" ],
        "creates": 50 //Make sure this isn't "1"!
    }]
}
Run it through the builder and compile this hunk of code.
Today I will teach you how to make your very own magic weapon to further abuse your Spectre set abilities.
We will make a weapon called the Squid Squirter, which will have a custom projectile.
LeF8QBX.png

Let's create a JSON file for your weapon.
Code:
{
    "displayName": "Squid Squirter",
    "size": [42, 22],
    "maxStack": 1,
    "value": [0, 0, 270, 40],
    "rare": 3,
    "useStyle": 5,
    "useAnimation": 10,
    "useTime": 5, //The effect of the useAnimation differing from the useTime makes this weapon fire twice when you click on it once.
    "useSound": 13, //Sound effect ID of Aqua Scepter, since it sounds like Ink
    "damage": 2,
    "knockback": 3,
    "autoReuse": true,
    "noMelee": true,
    "shoot": "InternalModName:Ink",
    "shootSpeed": 14,
    "magic": true, //This weapon will be boosted by magic bonuses.
    "mana": 3, //How much mana this weapon consumes per use.

    "recipes":
    [{
        "items": { "Black Ink": 8, "Iron Bar": 20, "Energy": 5 },
        "tiles": [ "Anvil" ],
        "creates": 1
    },
    {
        "items": { "Black Ink": 8, "Lead Bar": 20, "Energy": 5 },
        "tiles": [ "Anvil" ],
        "creates": 1
    }]
}
You can apply the "chance not to consume ammo" and "projectile spread" from the Ranged tutorial. I used projectile spread for my weapon, to fire 14 projectiles that arch.
Now it's time to code our projectile, Ink.
mmUjAWc.png

Create a Projectiles folder in your mod folder and this is where we will create our custom projectile.
Code:
{
    "displayName": "Ink",
    "size": [8, 8],
    "aiStyle": 2, //This aiStyle is the ID for thrown consumables (projectile is greatly effected by gravity) http://tconfig.wikia.com/wiki/List_of_Projectile_AI_Styles
    "timeLeft": 3600, //This is how long the projectile lasts. This is the default value.
    "friendly": true, //If set to false, you can hurt friendly NPCs with it.
    "hostile": false, //If set to true, the projectile will hurt you and friendly NPCs.
    "tileCollide": true, //If set to false, the projectile will go straight through blocks.
    "damage": 2,
    "magic": true
}
Hopefully you aren't copying my tutorials, because then you'd be copying my mod! Then everyone will call you out and nobody will like you!
Run your code through the compiler and see if it works.
Time to get to the stuff that not a lot of people are interested in but is really interesting.
Make a new folder in your mod folder named "Buffs". This is where we will make our buff.
For example, a buff that turns us into a ghost would be interesting, right?
ZUoYDf9.png

Create your buff's JSON file:
Code:
{
    "displayName": "Ghost",
    "tip": "Deactivate to return to human form", //Like tooltip, but without the tool!
    "debuff": false, //If false, then it can be deactivated by right-clicking it
    "vanityPet": false, //This isn't a buff that spawns a friendly NPC.
    "lightPet": false, //This isn't a buff that spawns a friendly NPC that provides light either.
    "enchantment": false, //Don't even know what this is
    "noTimer": true //Put as false if you want this buff as a potion
}
And time to make the buff's CS file:
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;

using TAPI;
using Terraria;

namespace berberborscing.Buffs
{
    public class Ghost : TAPI.ModBuff
    {
        public override void Effects(Player p, int index)
        {
            p.ghost = true;
        }
        public override void End(Player p, int index) //This code is called when you end the debuff. Since ghost is a debuff that makes the game think the player is permanently dead, we have to use this code or players are stuck as a ghost until they relog back in.
        {
            p.ghost = false; //This turns the player back into themselves from ghost form when the buff is deactivated.
            p.noFallDmg = true; //This prevents a bug where floating downwards and then switching back into human form makes you take fall damage, usually killing you.
        }
    }
}
Now the buff is finished, but there is currently no way to get it. We need to create an item that gives us the buff.
The Tome of Souls, a tool that gives us the buff whenever we want.
0wqaluB.png

Code:
{
    "displayName": "Tome of Souls",
    "size": [28,32],
    "useStyle": 4,
    "useAnimation": 17,
    "useTime": 17,
    "maxStack": 1,
    "useSound": 17,
    "tooltip": "Turns you into a ghost until deactivating buff",
    "rare": 4,
    "value": [1,0,0,0],
    "buff": "berberborscing:Ghost", //This makes the item give us the buff, simple enough?
    "buffTime": 600, //This gives us the buff for 10 seconds (doesn't work for the ghost buff since the game thinks it's permanent)

    "recipes":
    [{
        "items": { "Spell Tome": 1, "Ectoplasm": 10, "Soul of Fright": 30, "Soul of Flight": 5 },
        "tiles": [ "Bookcase" ],
        "creates": 1
    }]
}
But maybe you want to get the buff from a potion. In that case, you probably have a potion sprite already available. Just add the line
Code:
"consumable": true,
and make sure the potion recipe is crafted at a Bottle and uses Bottled Water in the recipe.
The sky's the limit when it comes to modding. Well, not if you make the wings fly forever, but we're not gonna do that, right? Let's use Frous' invention as an example: the JetBack
rGi8AjD.png
which will function as wings and extra storage.
Create a JSON file for your wings wherever inside your Items folder.
Code:
{
    "displayName": "JetBack",
    "size": [52,44],
    "maxStack": 1,
    "value": [3,0,16,400],
    "rare": 8,
    "tooltip": "Frous' newest invention; fly and carry!",
    "accessory": true,
    "wings": true, //If this is set to true, then the item will require a "ItemName_Wings" texture, which is what the animation on the player is, and the item will let you glide when you hold down the space bar, and prevent you from taking fall damage.
    "wingTime": 121, //This is how many blocks your wings can take you directly up

    "recipes":
    [{
        "items": { "BrownBackpack": 1, "Jetpack": 1 },
        "tiles": [ "Tinkerer's Workshop" ],
        "creates": 1
    }]
}
And that's all you need! The JSON file! But since this item needs to function like a backpack as well, we'll add an additional effect through a CS file.
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace berberborscing.Items
{
    public class JetBack : ModItem
    {
        public override void Effects(Player p)
        {
            p.chest = 50; //This effect makes the game think the player is at the 51st generated chest in the world; causing some side effects.
1.The backpack effect can only be activated if you open a chest first, then open your inventory.
2.This accessory causes a ton of noise at random, and even more noise when you open your map.
3. Destroying any chests will cause the backpack effect to go away.
        }
    }
}
Have fun soaring the skies on your new pair of wings: After you run them through the tAPI builder.
It's time to get down to what everyone likes: new mobs! What would a mod be without extra challenges, and even have rewards from these obstacles? Today I will code the Night Owl.This will be it's animation:
l1JsU5Q.gif

Create a JSON for your NPC and follow along:
Code:
{
    "displayName": "Night Owl",
    "size": [26,22],
    "value": [0,0,0,50], //This NPC will drop 50 copper upon death.
    "npcSlots": 2, //How many NPC slots this enemy will take up. Bosses usually have this value high.
    "aiStyle": 14, //The AI to copy. I thought 2 (Demon Eye) was too slow, so I picked 14 (Bat)
    "animationType": 252, //The ID of the NPC the animation mimics, in this case, 252 since it mimics the parrot animation
    "lifeMax": 35, //How much life it has when it spawns
    "damage": 20,
    "defense": 3,
    "frameCount": 5, //How many pictures are in the animation (Owl's standing still sprite:[IMG]http://i.imgur.com/YJsyaBn.png[/IMG])
    "soundHit": 1, //Generic hitting sound
    "soundKilled": 1, //"Splat" kill sound
    "knockbackResist": 0.5, //takes 50% knockback (set to 0.2 to take 20% knockback, etc.)
    "noGravity": true, //This is what flying AIs use to prevent glitching about on the ground. If you're using a non-flying AI, disregard this line.

    "drops":
    [
        {
            "item": "berberborscing:NightVisionGoggles", //This NPC will drop a new accessory that grants the player Night Vision.
            "chance": 0.2, //The chance to drop it is 20%.
            "stack": 1 //It will drop one Night-Vision Goggles.
        },
        {
           "item": "Feather",
           "chance": 0.8, //80% chance to drop a feather
           "stack": 2 //It will drop a maximum of 2 feathers.
        }
    ]
}
We also want there to be some incentive to defeating your mob in combat. So we will make the owl have a rare drop of a new item that gives the player Night Vision, the Night-Vision Goggles!
6fWzaEg.png

Currently there is no way to spawn this NPC. But there is a way to make it spawn at night.
Code:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;

using TAPI;
using Terraria;

namespace berberborscing.NPCs
{
    public class NightOwl : ModNPC
    {
        public override bool CanSpawn( int x, int y, int type, Player spawnedOn) //This is called when an NPC is about to spawn.
        {
                if (y <= Main.worldSurface &&  //If the player is below the surface...
                ((!Main.dayTime &&  !Main.bloodMoon && Main.rand.Next(3) == 0) ||   //If there is a blood moon, it will have a 1/3 chance to spawn.
                (!Main.dayTime &&  Main.bloodMoon && Main.rand.Next(3) == 0)) )  //If there is no blood moon, it will have a 1/3 chance to spawn.
                {
                      return true; //If these conditions are true...
                }
        return false;  //Then the mob won't spawn.
        }
    }
}
There are other kinds of code that can be used to accompany this.
These are all the different criteria for NPC spawning: (Courtesy of GrtAndPwfrlTrtl)
Code:
public override bool CanSpawn(int x, int y, int type, Player player) // x and y seem to be in tile not pixels here
{
//Copy all the variables (Just copy this section and paste into your cs) from here...
  // set parameters
  const int spawn_chance=10; // percentage chance to be on spawn list each spawn cycle
  bool avoids_town=true;
  const bool is_goblin=false;

  // calulated parameters
  int tile_type = (int)Main.tile[x, y].type;  // type of tile it's spawning on
  bool midair = !(Main.tile[x, y].active() && TileDef.solid[tile_type]); // check if is a midair spawn, happens in sky only

  // block based biomes
  bool dungeon = player.zoneDungeon; // dungeon
  bool jungle = player.zoneJungle;  // jungle
  bool meteor = player.zoneMeteor;  // meteor
  bool evil = player.zoneEvil;  // corruption
  bool holy = player.zoneHoly;  // hallow
  bool desert = (Main.sandTiles >= 1001);  // desert
  bool snow = player.zoneSnow;  // snow
  bool blood = player.zoneBlood;

  // latitude based biomes
  bool near_center = (double)x >= (double)Main.maxTilesX * 0.45 && (double)x <= (double)Main.maxTilesX * 0.55;
  bool near_edges = x < 250 || x > Main.maxTilesX - 250;

  // depth based biomes
  bool sky = (double)y < Main.worldSurface * 0.44999998807907104;  // all sky
  bool high_sky = (double)y < Main.worldSurface * 0.34999999403953552; // high sky(harpy spawn height)
  bool low_sky = sky && !high_sky;  // low sky(usually ground spawns, 10% harpy spawns on hardmode)
  bool under_ground = (y > Main.worldSurface);  // anywhere under ground level
  bool underworld = (y > Main.hellLayer);  // hell
  bool surface = !high_sky && !under_ground;  // ground level & low sky
  bool dirt_layer = under_ground && (y <= Main.rockLayer);  // dirt layer
  bool rock_layer = (y > Main.rockLayer) && !underworld;  // rock layer

  // other
  bool in_water = Main.tile[x, y - 1].liquid > 0 && Main.tile[x, y - 2].liquid > 0 && !Main.tile[x, y - 1].lava(); // in 2 blocks deep water(non lava)
  // Main.hardMode, raining, eclipse, bloodMoon, pumpkinMoon, snowMoon
  // NPC.downedBoss1, downedBoss2, downedBoss3, downedQueenBee, savedGoblin, savedWizard, savedMech, savedAngler, savedStylist, downedGoblins,
  //  downedFrost, downedPirates, downedClown, downedPlantBoss, downedGolemBoss, downedMechBossAny, downedMechBoss1, downedMechBoss2, downedMechBoss3
  bool candle = player.zoneCandle;
  bool invasion = Main.invasionType != 0; // 1=goblins, 2=frost, 3=pirate

  // more complex biomes
  bool nospecialbiome = !jungle && !evil && !holy && !meteor && !dungeon && !underworld && !snow && !blood; // including grass, sky, desert, ocean, snow, underground/cavern; (biomes that can be corrupted/hallowed)
  bool undergroundJungle = rock_layer && jungle;
  bool undergroundEvil = rock_layer && evil;
  bool undergroundHoly = rock_layer && holy;
  bool sky_spawn = sky && midair;  // midair: normal mode avoids center of map and low sky, hardmode allows center of map and 10% low sky; in vanilla, this will be a harpy or wyvern
  bool surface_spawn = !under_ground && !sky_spawn;  // surface or low sky(90% low sky in hardmode)
  bool ocean = near_edges && in_water && (tile_type == 53 || tile_type == 112 || tile_type == 116) && Main.tile[x, y].active() && (double)y < Main.rockLayer; // 53=Sand, 112=Ebonsand, 116=Pearlsand
  bool at_invasion = invasion && Main.invasionDelay == 0 && Main.invasionSize > 0 && y < Main.worldSurface + (double)NPC.sHeight / 16.0 && x > Main.invasionX * 16.0 - (double)3000 && x < Main.invasionX * 16.0 + (double)3000;
  bool goblin_invasion = Main.invasionType == 1 && at_invasion;
//To here.
  // spawn chance
  if (invasion && at_invasion) // some invasion happening, and you're there
  { // invasion spawns only, no need to avoid town, remember to count as killed invaders when your creatures die
    if (goblin_invasion && is_goblin)
    { if (Main.rand.Next(100) < 5 * spawn_chance) return true; } // 5x spawn chance in invasion force
  }
  else if ((Main.eclipse || Main.pumpkinMoon || Main.snowMoon) && surface) // special moon and on surface
  { // moons that stop spawns, non need to avoid town; blood moon and rain allow normal spawns so are not included
    // if creature is included in a moon, custom code here
  }
  else
  { // normal spawn conditions
    if (Main.bloodMoon) avoids_town = false;
    int townNPCs = (int)player.townNPCs;
    if (avoids_town && (townNPCs >= 3 || (townNPCs == 2 && Main.rand.Next(4) != 0) || (townNPCs == 1 && Main.rand.Next(2) != 0))) return false; // 3 townNPCs -> no spawns, 2 townNPCs -> 25% spawns, 1 townNPC -> 50% spawns
    if (Main.rand.Next(100) < spawn_chance && NPC.downedPlantBoss && jungle && !under_ground && !Main.dayTime && Main.tile[x, y].active()) return true; // can spawn on sky islands
  } // END spawn chance
  return false;

} // END CanSpawn()
And put a ! before each condition to make it the opposite, for example;
Code:
!player.zoneMeteor
Would be the code to make your mob stop spawning in Meteor biomes.
Oh, and a necessary line of code that most modders don't use that would make this NPC a lot better:
Code:
!NPC.areaSafeTown
There's a thread that goes into this in further detail. Check out bluemagic123's tut here, he knows more than me about this
http://forums.terraria.org/index.ph...r-weapon-programming-knowledge-required.9381/

I'm pretty sure this is the tutorial you guys have been waiting a :red: long time for. The ability to make summoner weapons. (Man, these are gonna be everywhere after this.) Mostly requested by Ye, I present to you, my example for the summoner weapon. I'm not so sure about how to make these things myself, but I guess this will be a learning experience for both of us.
This is the Meteor Staff, a rare drop from an NPC in my mod called the Meteor Chaser.
s8AIvXO.png

Let's make a JSON file for our summoner item.
Code:
{
    "displayName": "Meteor Staff",
    "size": [52, 24],
    "maxStack": 1,
    "value": [1, 0, 0, 0],
    "rare": 5,
    "useStyle": 1,
    "useAnimation": 18,
    "tooltip": "Spawns a meteor chaser to defend you",
    "useTime": 18,
    "useSound": 44, //Minion spawning sound effect
    "damage": 25, //This overrides projectile damage, so this is how much damage the minions will do. If the minion fires projectiles, the projectile will use the projectile's damage.
    "knockback": 10,
    "autoReuse": false,
    "noMelee": true,
    "shoot": "berberborscing:Chaser", //This is our projectile I will show later.
    "shootSpeed": 3, //Don't set this too high, you don't want the minion to fly away when it spawns!
    "summon": true, //This weapon will gain bonuses from summoner equipment.
    "buff": "berberborscing:Chaser", //This is the buff accompanying it (I have no idea how this helps)
    "buffTime": 999999999, //Just to make sure the buff doesn't stop.
    "mana": 10
}
Now it's time to create the projectile. Here is the minion:
7Jcdw5B.png

Create a JSON for the projectile:
Code:
{
    "displayName": "Chaser",
    "size": [32, 40],
    "aiStyle": 54, //This is the Raven AI. List of different summon AIs below.
    "timeLeft": 999999999, //Just to make sure the projectile doesn't despawn.
    "friendly": true,
    "hostile": false,
    "tileCollide": false, //So it can return to you with no trouble.
    "damage": 25,//Damage projectiles from this summon do.
    "minion": true, //Receives summoner bonuses
    "minionSlots": 1, //Takes up 1 minion slot
    "penetrate": -1 //Lasts forever
}
As for all the different AI styles...
47 = Magnet Sphere
53 = Staff of the Frost Hydra (very buggy)
54 = Raven
62 = Same as 54, but crashes the game when an NPC gets in range (try at your own risk!)
63 = Baby Slime
66 = Retinazer summon (no lasers)
67 = Pirates

Some of the AI styles won't function properly if you don't have correct amount of frames.(Baby Slime, Pirates) I have no clue how to configure these, but there's no simpler tutorial than this. Might have to improve on this and learn how to do this, but this'll hold you over until then.
 
Last edited:
Is it okay if I try to compile one of your existing items since I have absolutely no coding experience, but I won't post it anywhere on the Internet?
 
Thank you very much! I will try it, and test it since my tApi sucks sometimes. :)
EDIT: This is sort of embarrasing, how do you open the builder? It's not working for me.
EDIT 2: It is not opening through tApi :/
 
Last edited:
Thank you very much! I will try it, and test it since my tApi sucks sometimes. :)
EDIT: This is sort of embarrasing, how do you open the builder? It's not working for me.
EDIT 2: It is not opening through tApi :/
When you install tAPI the installer usually puts the builder on your desktop
 
I LOVE YOU. You write code and explain it, that's the best kind of tutorial you can get! If people just put random code , people won't understand why it's there and what it does. I would really like to see a tutorial on summoner weapons and maybe AI-related stuff.

I always wanted to turn my Summoner Equipment++ suggestion into a mod. It would make a pretty good mod.
 
Hmm, I get this problem with my .CS when trying to use a mod item in the new recipe:
========================================
Building mod BLITZ

Validating Jsons...
Compiling code...
Torches.cs (78,17)
Non-invocable member 'TAPI.ItemDef.byName' cannot be used like a method.
Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(ItemDef.byName("BLITZ:Coal"), false)); //This is the ID for Tin Can
^
Failed to build BLITZ.

========================================
 
I LOVE YOU. You write code and explain it, that's the best kind of tutorial you can get! If people just put random code , people won't understand why it's there and what it does. I would really like to see a tutorial on summoner weapons and maybe AI-related stuff.

I always wanted to turn my Summoner Equipment++ suggestion into a mod. It would make a pretty good mod.
The projectile AI style for a summoner weapon you may be looking for:
47 = Magnet Sphere
53 = Staff of the Frost Hydra (buggy)
54 = Raven
63 = Baby Slime
67 = Pirates
 
The projectile AI style for a summoner weapon you may be looking for:
47 = Magnet Sphere
53 = Staff of the Frost Hydra (buggy)
54 = Raven
63 = Baby Slime
67 = Pirates
What if I wanted a minion that acts like one of the Twins minion , the Spazmatism minion?
What if I wanted a minion that just follows you around and shoots mobs?(I have an idea of how it could be done , but I don't know about the following part)
 
What if I wanted a minion that acts like one of the Twins minion , the Spazmatism minion?
What if I wanted a minion that just follows you around and shoots mobs?(I have an idea of how it could be done , but I don't know about the following part)
62 might be Spazmatism, I can't tell because the game crashes when an NPC comes into range with it.
66 is the Retinazer Projectile AI Style, but it doesn't shoot projectiles.
 
Hmm, I get this problem with my .CS when trying to use a mod item in the new recipe:
========================================
Building mod BLITZ

Validating Jsons...
Compiling code...
Torches.cs (78,17)
Non-invocable member 'TAPI.ItemDef.byName' cannot be used like a method.
Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults(ItemDef.byName("BLITZ:Coal"), false)); //This is the ID for Tin Can
^
Failed to build BLITZ.

========================================
This is a problem I experienced myself. I didn't make this code, I got this from someone else (I think GrtAndPwrflTrtl). You can take this to the tAPI thread and you'll find someone who can help you. Then I'll modify the tutorial to help other people with this problem
 
I got some help on the IRC channel, and here is the fixed line:

Recipe.newRecipe.requiredItem.Add(new Item().SetDefaults( ItemDef.byName["MODNAME:ITEM"].type, false))

Credits to BlueRaven from the IRC channel for that fix.
 
Nothing will exist in it though... Is that good?
EDIT: Sorry if I am bugging you with all these questions, take your time.
 
Status
Not open for further replies.
Back
Top Bottom