Modding Terraria – Part 2 Laser sword and friendly zombies
Welcome to our how to mod Terraria series part 2.
If you haven’t read the first part yet, you can find it here
This post has been updated to work with tModLoader v2023.9.3.0
We will continue where we left off last time, which is, creating a new custom item, giving it a custom image and change some properties of specific enemies.
Let’s get started!
Creating a Laser Sword
Open up tModLoader and your Visual Studio project. We start with something amazing, a sword that shoots beams! How cool is that?
Remember the Items
folder we created last time when we made our TestSword? We will be using that folder again for our new weapon.
Creating the LaserSword file
Create a new file in the Items
folder called LaserSword.cs
Paste the following code inside the file
using Terraria; using Terraria.ID; using Terraria.ModLoader; namespace FirstMod.Items { public class LaserSword : ModItem { public override void SetDefaults() { Item.CloneDefaults(ItemID.MeteorStaff); Item.damage = 128; Item.DamageType = DamageClass.MeleeNoSpeed; Item.width = 32; Item.height = 32; Item.useTime = 20; Item.useAnimation = 20; Item.useStyle = ItemUseStyleID.Swing; Item.knockBack = 6; Item.rare = ItemRarityID.Master; // If you followed our previous iteration of this post, this number was 12. In the newer version of Terraria this doesn't correspond correctly anymore and will give you a no reference error. Item.UseSound = SoundID.DD2_LightningAuraZap; Item.autoReuse = false; Item.mana = 0; Item.shoot = ModContent.ProjectileType<LaserSwordProjectile>(); } public override void AddRecipes() { Recipe recipe = CreateRecipe(); recipe.AddIngredient(ItemID.DirtBlock, 10); recipe.AddTile(TileID.WorkBenches); recipe.Register(); } } }
This code is not that much different from the TestSword
we made before. The biggest differences are: Item.CloneDefaults(ItemID.MeteorStaff);
and Item.shoot = ModContent.ProjectileType<LaserSwordProjectile>();
.
The Meteor Staff is a magic weapon that shoots ricocheting beams. Since this is what we want for our sword, we start off by making a copy of all the basic parameters that the Meteor Staff has and pasting them into our LaserSword.
Because our sword will shoot lasers we need to attach a projectile to our sword. We do that by giving the Item.shoot
parameter a value of our projectile that we will be making. Item.shoot
expects an integer so we give it our own customer projectile type as a generic type parameter.
Creating the LaserSword particles file
Our LaserSword is done, let’s move over to our LaserSwordProjectile. Create a new file in the Items
folder called LaserSwordProjectile.cs
and paste the following code
using Microsoft.Xna.Framework; using Terraria; using Terraria.ID; using Terraria.ModLoader; namespace FirstMod.Items { class LaserSwordProjectile : ModProjectile { public override void SetDefaults() { Projectile.width = 4; Projectile.height = 4; Projectile.friendly = true; Projectile.DamageType = DamageClass.Magic; Projectile.extraUpdates = 100; Projectile.timeLeft = 200; Projectile.penetrate = -1; } public override string Texture => "Terraria/Projectile_" + ProjectileID.Meteor1; public override bool OnTileCollide(Vector2 oldVelocity) { if (Projectile.velocity.X != oldVelocity.X) { Projectile.position.X = Projectile.position.X + Projectile.velocity.X; Projectile.velocity.X = -oldVelocity.X; } if (Projectile.velocity.Y != oldVelocity.Y) { Projectile.position.Y = Projectile.position.Y + Projectile.velocity.Y; Projectile.velocity.Y = -oldVelocity.Y; } return false; } public override void ModifyHitNPC(NPC target, ref NPC.HitModifiers modifiers) { Projectile.damage = (int)(Projectile.damage * 1); } public override void AI() { Projectile.localAI[0] += 1f; if (Projectile.localAI[0] > 9f) { for (int i = 0; i < 4; i++) { Vector2 projectilePosition = Projectile.position; projectilePosition -= Projectile.velocity * ((float)i * 0.25f); Projectile.alpha = 255; int dust = Dust.NewDust(projectilePosition, 1, 1, DustID.SpectreStaff, 0f, 0f, 0, default(Color), 1f); Main.dust[dust].noGravity = true; Main.dust[dust].position = projectilePosition; Main.dust[dust].scale = (float)Main.rand.Next(70, 110) * 0.013f; Main.dust[dust].velocity *= 0.2f; } } } } }
In this file we've set some basic parameters such as the width, height, whether our projectile can go through walls or not, etc. Next to that we have an interesting function called onTileCollide(Vector2 oldVelocity)
. This function handles our surface collision and will invert the direction of the beam when it hits a colliable area. Note that, in order to use the Vector2 struct
we need to include the Xna framework. On line we do this with using Microsoft.Xna.Framework;
. A struct is usually used to design small data-centric types that provide little or no behavior. To completely understand why structs are useful, Microsoft has a fairly simple post about it here
The original Meteor Staff's animation is a falling meteorite. Since we do not want this behavior we update the AI()
function of our LaserSwordProjectile
. We changed the color of the dust particles (our actual beam) and set the gravity of our laser to false.
Lastly, we need an image to accommodate our newly made sword. You can create your own image or use the one we will be using.
At this point your Items
folder should look like this:

Let's check our newly made item out in game! Build + Reload
your mod and load your world up. Grab 10 pieces of dirt blocks, go to your workbench and you should see our new LaserSword! Clicking anywhere on your game while having the sword equipped will have it shoot a laser beam that will ricochet off of surfaces.

Editing the zombies
Enough with the items for now. Let's see how we can edit the zombies in Terraria and give them different names and have them be friendly towards the player.
For this we won't need the Items
folder. Instead, we will make a Npcs
folder. Inside this folder create a file called FriendlyZombies.cs
.
Paste the following code inside this file
using System; using System.Collections.Generic; using Terraria; using Terraria.ID; using Terraria.ModLoader; namespace FirsMod.Items { class FriendlyZombies : GlobalNPC { public override void SetDefaults(NPC npc) { if (IsZombie(npc)) { npc.GivenName = PickRandomName(); npc.friendly = true; } base.SetDefaults(npc); } private string PickRandomName() { var random = new System.Random(); var names = new List() { "Bob", "Jim", "Julia", "Michelle", "Rob", "Howard", "Stacy", "Lucy" }; int index = random.Next(names.Count); return names[index]; } private bool IsZombie(NPC npc) { switch (npc.type) { case NPCID.Zombie: case NPCID.ZombieDoctor: case NPCID.ZombieRaincoat: case NPCID.ArmedZombie: case NPCID.BaldZombie: return true; default: return false; } } } }
Here, we have changed the way zombies are generated. But only the ones in the function IsZombie(NPC npc)
function. The zombie will only be friendly when it's a normal zombie, a zombie doctor, a zombie wearing a raincoat, an armed zombie or a bald zombie. Furthemore, it will be given a random name from our list in PickRandomName()
.
Save your file, open up tModLoader, Build + Reload your mod again and load up your world. Wait until night time and try to find our new friendly zombies!


In the next part we will create our own pet that will follow us around!
3 Comments