Royal Nobody
Skeletron Prime
I was wondering how I could make a custom invasion for my mod. I know there are some tutorials, but they are out of date and no longer work. Is there a recent tutorial I haven't found yet?
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ReLogic.Graphics;
using System;
using AurumMod;
using AurumMod.NPCs;
using static AurumMod.StellarArmy;
using static AurumMod.ExampleWorld;
using System.Collections.Generic;
using System.IO;
using Terraria;
using Terraria.GameContent.Dyes;
using Terraria.GameContent.UI;
using Terraria.Graphics.Effects;
using Terraria.Graphics.Shaders;
using Terraria.ID;
using Terraria.Localization;
using Terraria.UI;
using static Terraria.ModLoader.ModContent;
using Terraria.ModLoader;
namespace AurumMod
{
public class StellarArmy
{
public static int[] invaders = {
NPCID.Zombie,
NPCID.BlueSlime,
};
//Setup for an Invasion
public static void StartStellarArmy()
{
//Set to no invasion if one is present
if (Main.invasionType != 0 && Main.invasionSize == 0)
{
Main.invasionType = 0;
}
//Once it is set to no invasion setup the invasion
if (Main.invasionType == 0)
{
//Checks amount of players for scaling
int numPlayers = 0;
for (int i = 0; i < 255; i++)
{
if (Main.player[i].active && Main.player[i].statLifeMax >= 200)
{
numPlayers++;
}
}
if (numPlayers > 0)
{
//Invasion setup
Main.invasionType = -1; //Not going to be using an invasion that is positive since those are vanilla invasions
ExampleWorld.StellarArmyUp = true;
Main.invasionSize = 100 * numPlayers;
Main.invasionSizeStart = Main.invasionSize;
Main.invasionProgress = 0;
Main.invasionProgressIcon = 0 + 3;
Main.invasionProgressWave = 0;
Main.invasionProgressMax = Main.invasionSizeStart;
Main.invasionWarn = 3600; //This doesn't really matter, as this does not work, I like to keep it here anyways
if (Main.rand.Next(2) == 0)
{
Main.invasionX = 0.0; //Starts invasion immediately rather than wait for it to spawn
return;
}
Main.invasionX = (double)Main.maxTilesX; //Set the initial starting location of the invasion to max tiles
}
}
}
public static void StellarArmyWarning()
{
String text = "";
if (Main.invasionX == (double)Main.spawnTileX)
{
text = "The Stellar Army desecends from the heaven!";
}
if (Main.invasionSize <= 0)
{
text = "The Stellar Army retreats.";
}
if (Main.netMode == 0)
{
Main.NewText(text, 175, 75, 255, false);
return;
}
if (Main.netMode == 2)
{
//Sync with net
NetMessage.SendData(25, -1, -1, NetworkText.FromLiteral(text), 255, 175f, 75f, 255f, 0, 0, 0);
}
}
//Updating the invasion
public static void UpdateStellarArmyWarning()
{
//If the custom invasion is up
if (ExampleWorld.StellarArmyUp)
{
//End invasion if size less or equal to 0
if (Main.invasionSize <= 0)
{
ExampleWorld.StellarArmyUp = false;
StellarArmyWarning();
Main.invasionType = 0;
Main.invasionDelay = 0;
}
//Do not do the rest if invasion already at spawn
if (Main.invasionX == (double)Main.spawnTileX)
{
return;
}
//Update when the invasion gets to Spawn
float moveRate = (float)Main.dayRate;
//If the invasion is greater than the spawn position
if (Main.invasionX > (double)Main.spawnTileX)
{
//Decrement invasion x as to "move them"
Main.invasionX -= (double)moveRate;
//If less than the spawn pos, set invasion pos to spawn pos and warn players that invaders are at spawn
if (Main.invasionX <= (double)Main.spawnTileX)
{
Main.invasionX = (double)Main.spawnTileX;
StellarArmyWarning();
}
else
{
Main.invasionWarn--;
}
}
else
{
//Same thing as the if statement above, just it is from the other side
if (Main.invasionX < (double)Main.spawnTileX)
{
Main.invasionX += (double)moveRate;
if (Main.invasionX >= (double)Main.spawnTileX)
{
Main.invasionX = (double)Main.spawnTileX;
StellarArmyWarning();
}
else
{
Main.invasionWarn--;
}
}
}
}
}
public static void CheckStellarArmyProgress()
{
//Not really sure what this is
if (Main.invasionProgressMode != 2)
{
Main.invasionProgressNearInvasion = false;
return;
}
//Checks if NPCs are in the spawn area to set the flag, which I do not know what it does
bool flag = false;
Player player = Main.player[Main.myPlayer];
Rectangle rectangle = new Rectangle((int)Main.screenPosition.X, (int)Main.screenPosition.Y, Main.screenWidth, Main.screenHeight);
int num = 5000;
int icon = 0;
for (int i = 0; i < 200; i++)
{
if (Main.npc[i].active)
{
icon = 0;
int type = Main.npc[i].type;
for (int n = 0; n < invaders.Length; n++)
{
if (type == invaders[n])
{
Rectangle value = new Rectangle((int)(Main.npc[i].position.X + (float)(Main.npc[i].width / 2)) - num, (int)(Main.npc[i].position.Y + (float)(Main.npc[i].height / 2)) - num, num * 2, num * 2);
if (rectangle.Intersects(value))
{
flag = true;
break;
}
}
}
}
}
Main.invasionProgressNearInvasion = flag;
int progressMax3 = 1;
//If the custom invasion is up, set the max progress as the initial invasion size
if (ExampleWorld.StellarArmyUp)
{
progressMax3 = Main.invasionSizeStart;
}
//If the custom invasion is up and the enemies are at the spawn pos
if (ExampleWorld.StellarArmyUp && (Main.invasionX == (double)Main.spawnTileX))
{
//Shows the UI for the invasion
Main.ReportInvasionProgress(Main.invasionSizeStart - Main.invasionSize, progressMax3, icon, 0);
}
//Syncing start of invasion
foreach (Player p in Main.player)
{
NetMessage.SendData(78, p.whoAmI, -1, null, Main.invasionSizeStart - Main.invasionSize, (float)Main.invasionSizeStart, (float)(Main.invasionType + 3), 0f, 0, 0, 0);
}
}
//Setting music to 1 which is “Night”
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ReLogic.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using Terraria;
using Terraria.GameContent.Dyes;
using Terraria.GameContent.UI;
using Terraria.Graphics.Effects;
using Terraria.Graphics.Shaders;
using Terraria.ID;
using Terraria.Localization;
using Terraria.UI;
using static Terraria.ModLoader.ModContent;
using Terraria.ModLoader;
namespace AurumMod
{
public class AurumMod : Mod
{
public AurumMod()
{
Properties = new ModProperties()
{
Autoload = true,
AutoloadGores = true,
AutoloadSounds = true
};
}
public override void UpdateMusic(ref int music)
{
//Checks if the invasion is in the correct spot, if it is, then change the music
if (ExampleWorld.StellarArmyUp && Main.invasionX == Main.spawnTileX)
{
music = 1;
}
}
public override void Load()
{
// Will show up in client.log under the ExampleMod name
// In older tModLoader versions we used: ErrorLogger.Log("blabla");
// Replace that with above
ModTranslation text = CreateTranslation("LivesLeft");
text = CreateTranslation("BossSpawnInfo.ExampleWormHead");
text.SetDefault("Use a [i:" + ModContent.ItemType<Items.ClingerWorm.StrangeBait>() + "] in the Corruption after Golem has been defeated");
AddTranslation(text);
// Volcano warning is for the random volcano tremor
}
public override void PostSetupContent()
{
// Showcases mod support with Boss Checklist without referencing the mod
Mod bossChecklist = ModLoader.GetMod("BossChecklist");
if (bossChecklist != null)
{
bossChecklist.Call(
"AddBoss",
10.5f,
new List<int> { ModContent.NPCType<NPCs.Bosses.Clinger_Worm.ExampleWormHead>()},
this, // Mod
"Clinger Worm",
(Func<bool>)(() => ExampleWorld.downedClingerWorm),
ModContent.ItemType<Items.ClingerWorm.StrangeBait>(),
"Use Strange Bait in the Corruption after Golem is defeated."
);
}
}
}
}
using static AurumMod.StellarArmy;
using AurumMod.NPCs.Bosses.Clinger_Worm;
using AurumMod.Items;
using AurumMod.NPCs;
using AurumMod;
using AurumMod.Tiles;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using System.IO;
using Terraria;
using Terraria.DataStructures;
using Terraria.GameContent.Generation;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.ModLoader.IO;
using Terraria.World.Generation;
using static Terraria.ModLoader.ModContent;
namespace AurumMod
{
public class ExampleWorld : ModWorld
{
public static bool downedClingerWorm;
public static bool StellarArmyUp = false;
public static bool downedStellarArmy = false;
public override void Initialize()
{
downedClingerWorm = false;
Main.invasionSize = 0;
StellarArmyUp = false;
downedStellarArmy = false;
}
public override TagCompound Save()
{
var downed = new List<string>();
if (downedStellarArmy) downed.Add("StellarArmy");
return new TagCompound {
{"downed", downed}
};
}
public override void Load(TagCompound tag)
{
var downed = tag.GetList<string>("downed");
downedClingerWorm = downed.Contains("ClingerWorm");
downedStellarArmy = downed.Contains("StellarArmy");
}
public override void NetSend(BinaryWriter writer)
{
var flags = new BitsByte();
flags[1] = downedClingerWorm;
flags[0] = downedStellarArmy;
writer.Write(flags);
}
// We use this hook to add 3 steps to world generation at various points.
public override void NetReceive(BinaryReader reader)
{
BitsByte flags = reader.ReadByte();
downedStellarArmy = flags[0];
}
//Allow to update invasion while game is running
public override void PostUpdate()
{
if (StellarArmyUp)
{
if (Main.invasionX == (double)Main.spawnTileX)
{
//Checks progress and reports progress only if invasion at spawn
StellarArmy.CheckStellarArmyProgress();
}
//Updates the custom invasion while it heads to spawn point and ends it
StellarArmy.UpdateStellarArmyWarning();
}
}
}
}
using System;
using System.Collections.Generic;
using AurumMod.Buffs;
using AurumMod.Dusts;
using AurumMod.Items;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using static Terraria.ModLoader.ModContent;
using AurumMod;
using static AurumMod.StellarArmy;
namespace AurumMod.NPCs
{
public class NPCsGLOBAL : GlobalNPC
{
public override bool InstancePerEntity => true;
public bool AetheralMalady = false;
public bool DivineInferno = false;
public override void ResetEffects(NPC npc)
{
AetheralMalady = false;
DivineInferno = false;
}
//Change the spawn pool
public override void EditSpawnPool(IDictionary<int, float> pool, NPCSpawnInfo spawnInfo)
{
//If the custom invasion is up and the invasion has reached the spawn pos
if (ExampleWorld.StellarArmyUp && (Main.invasionX == (double)Main.spawnTileX))
{
//Clear pool so that only the stuff you want spawns
pool.Clear();
//key = NPC ID | value = spawn weight
//pool.add(key, value)
//For every ID inside the invader array in our CustomInvasion file
foreach (int i in StellarArmy.invaders)
{
pool.Add(i, 1f); //Add it to the pool with the same weight of 1
}
}
}
//Changing the spawn rate
public override void EditSpawnRate(Player player, ref int spawnRate, ref int maxSpawns)
{
//Change spawn stuff if invasion up and invasion at spawn
if (ExampleWorld.StellarArmyUp && (Main.invasionX == (double)Main.spawnTileX))
{
spawnRate = 100; //Higher the number, the more spawns
maxSpawns = 10000; //Max spawns of NPCs depending on NPC value
}
}
//Adding to the AI of an NPC
public override void PostAI(NPC npc)
{
//Changes NPCs so they do not despawn when invasion up and invasion at spawn
if (ExampleWorld.StellarArmyUp && (Main.invasionX == (double)Main.spawnTileX))
{
npc.timeLeft = 1000;
}
}
public override void UpdateLifeRegen(NPC npc, ref int damage)// unrlated to th invasion
{
if (AetheralMalady)
{
if (npc.lifeRegen > 0)
{
npc.lifeRegen = 0;
}
npc.lifeRegen -= 160;
if (damage < 2)
{
damage = 4;
}
}
if (DivineInferno)
{
if (npc.lifeRegen > 0)
{
npc.lifeRegen = 0;
}
npc.lifeRegen -= 280;
if (damage < 2)
{
damage = 1;
}
}
}
public override void NPCLoot(NPC npc)
{
//The if (Main.rand.Next(x) == 0) determines how rare the drop is. To find the percent of a drop, divide 100 by your desired percent, minus the percent sign. Ex: A 2% chance would be 100% / 2%, or 50. This is what you put in place of x.
// only the stuff with the stellar army is related to the event
if (Main.rand.Next(50) == 0) //2% chance
{
if (npc.type == NPCID.ChaosElemental)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("DiscordianShard"));
}
if (npc.type == NPCID.SandElemental)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("ForbiddenTear"));
}
if (npc.type == NPCID.SandShark)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("ForbiddenTear"));
}
}
if (Main.rand.Next(2) == 0) //2% chance
{
if (npc.type == NPCID.NebulaHeadcrab)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("BrainsucklerTentacle"));
}
if (npc.type == NPCID.StardustCellBig)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("StardustCellCore"));
}
if (npc.type == NPCID.SolarCrawltipedeHead)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("CrawltipedeMandible"));
}
if (npc.type == NPCID.VortexHornet)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("AlienHornetStinger"));
}
}
if (Main.rand.Next(1) == 0) //2% chance
{
if (npc.type == NPCID.TruffleWorm)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("FungalSpray"));
}
if (npc.type == NPCID.TruffleWormDigger)
{
Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("FungalSpray"));
}
}
if (ExampleWorld.StellarArmyUp)
{
//Gets IDs of invaders from CustomInvasion file
foreach (int invader in StellarArmy.invaders)
{
//If npc type equal to invader's ID decrement size to progress invasion
if (npc.type == invader)
{
Main.invasionSize -= 1;
}
}
}
}
public override void DrawEffects(NPC npc, ref Color drawColor)//This is not related to the invasion
{
if (AetheralMalady)
{
if (Main.rand.Next(4) < 3)
{
int dust = Dust.NewDust(npc.position - new Vector2(2f, 2f), npc.width + 4, npc.height + 4, DustType<AetheralMaladust>(), npc.velocity.X * 0.4f, npc.velocity.Y * 0.4f, 100, default(Color), 3.5f);
Main.dust[dust].noGravity = true;
Main.dust[dust].velocity *= 1.8f;
Main.dust[dust].velocity.Y -= 0.5f;
if (Main.rand.NextBool(4))
{
Main.dust[dust].noGravity = false;
Main.dust[dust].scale *= 0.5f;
}
}
Lighting.AddLight(npc.position, 0.1f, 0.2f, 0.7f);
}
if (DivineInferno)
{
if (Main.rand.Next(4) < 3)
{
int dust = Dust.NewDust(npc.position - new Vector2(2f, 2f), npc.width + 4, npc.height + 4, DustType<DivineDust>(), npc.velocity.X * 0.4f, npc.velocity.Y * 0.4f, 100, default(Color), 3.5f);
Main.dust[dust].noGravity = true;
Main.dust[dust].velocity *= 1.8f;
Main.dust[dust].velocity.Y -= 0.5f;
if (Main.rand.NextBool(4))
{
Main.dust[dust].noGravity = false;
Main.dust[dust].scale *= 0.5f;
}
}
Lighting.AddLight(npc.position, 0.1f, 0.2f, 0.7f);
}
}
} }
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using static Terraria.ModLoader.ModContent;
namespace AurumMod.Items
{
public class StellarCrystal : ModItem
{
public override void SetStaticDefaults()
{
DisplayName.SetDefault("Stellar Crystal");
Tooltip.SetDefault("Awakens the Wyrms servants.");
}
public override void SetDefaults()
{
item.width = 32;
item.height = 32;
item.scale = 1;
item.maxStack = 25;
item.useTime = 30;
item.useAnimation = 30;
item.UseSound = SoundID.Item1;
item.useStyle = 1;
item.consumable = true;
item.value = Item.buyPrice(0, 1, 0, 0);
item.rare = 3;
}
public override bool UseItem(Player player)
{
if (!ExampleWorld.StellarArmyUp)
{
Main.NewText("The Stellar Army was angered.......", 175, 75, 255, false);
StellarArmy.StartStellarArmy();
return true;
}
else
{
return false;
}
}
public override void AddRecipes() {
ModRecipe recipe = new ModRecipe(mod);
recipe.AddIngredient(ItemType<Items.ManaCrystalSample>(), 25);
recipe.AddTile(TileID.DemonAltar);
recipe.SetResult(this);
recipe.AddRecipe();
}
}
}
amazing. will be useful for me at least (or I could just use Tremor source lol)Ok so there is quite some stuff that you need.
First of all you need an Invasion file.
This is what it should look like:
The next thing you'll need is the mod file.C#:using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using ReLogic.Graphics; using System; using AurumMod; using AurumMod.NPCs; using static AurumMod.StellarArmy; using static AurumMod.ExampleWorld; using System.Collections.Generic; using System.IO; using Terraria; using Terraria.GameContent.Dyes; using Terraria.GameContent.UI; using Terraria.Graphics.Effects; using Terraria.Graphics.Shaders; using Terraria.ID; using Terraria.Localization; using Terraria.UI; using static Terraria.ModLoader.ModContent; using Terraria.ModLoader; namespace AurumMod { public class StellarArmy { public static int[] invaders = { NPCID.Zombie, NPCID.BlueSlime, }; //Setup for an Invasion public static void StartStellarArmy() { //Set to no invasion if one is present if (Main.invasionType != 0 && Main.invasionSize == 0) { Main.invasionType = 0; } //Once it is set to no invasion setup the invasion if (Main.invasionType == 0) { //Checks amount of players for scaling int numPlayers = 0; for (int i = 0; i < 255; i++) { if (Main.player[i].active && Main.player[i].statLifeMax >= 200) { numPlayers++; } } if (numPlayers > 0) { //Invasion setup Main.invasionType = -1; //Not going to be using an invasion that is positive since those are vanilla invasions ExampleWorld.StellarArmyUp = true; Main.invasionSize = 100 * numPlayers; Main.invasionSizeStart = Main.invasionSize; Main.invasionProgress = 0; Main.invasionProgressIcon = 0 + 3; Main.invasionProgressWave = 0; Main.invasionProgressMax = Main.invasionSizeStart; Main.invasionWarn = 3600; //This doesn't really matter, as this does not work, I like to keep it here anyways if (Main.rand.Next(2) == 0) { Main.invasionX = 0.0; //Starts invasion immediately rather than wait for it to spawn return; } Main.invasionX = (double)Main.maxTilesX; //Set the initial starting location of the invasion to max tiles } } } public static void StellarArmyWarning() { String text = ""; if (Main.invasionX == (double)Main.spawnTileX) { text = "The Stellar Army desecends from the heaven!"; } if (Main.invasionSize <= 0) { text = "The Stellar Army retreats."; } if (Main.netMode == 0) { Main.NewText(text, 175, 75, 255, false); return; } if (Main.netMode == 2) { //Sync with net NetMessage.SendData(25, -1, -1, NetworkText.FromLiteral(text), 255, 175f, 75f, 255f, 0, 0, 0); } } //Updating the invasion public static void UpdateStellarArmyWarning() { //If the custom invasion is up if (ExampleWorld.StellarArmyUp) { //End invasion if size less or equal to 0 if (Main.invasionSize <= 0) { ExampleWorld.StellarArmyUp = false; StellarArmyWarning(); Main.invasionType = 0; Main.invasionDelay = 0; } //Do not do the rest if invasion already at spawn if (Main.invasionX == (double)Main.spawnTileX) { return; } //Update when the invasion gets to Spawn float moveRate = (float)Main.dayRate; //If the invasion is greater than the spawn position if (Main.invasionX > (double)Main.spawnTileX) { //Decrement invasion x as to "move them" Main.invasionX -= (double)moveRate; //If less than the spawn pos, set invasion pos to spawn pos and warn players that invaders are at spawn if (Main.invasionX <= (double)Main.spawnTileX) { Main.invasionX = (double)Main.spawnTileX; StellarArmyWarning(); } else { Main.invasionWarn--; } } else { //Same thing as the if statement above, just it is from the other side if (Main.invasionX < (double)Main.spawnTileX) { Main.invasionX += (double)moveRate; if (Main.invasionX >= (double)Main.spawnTileX) { Main.invasionX = (double)Main.spawnTileX; StellarArmyWarning(); } else { Main.invasionWarn--; } } } } } public static void CheckStellarArmyProgress() { //Not really sure what this is if (Main.invasionProgressMode != 2) { Main.invasionProgressNearInvasion = false; return; } //Checks if NPCs are in the spawn area to set the flag, which I do not know what it does bool flag = false; Player player = Main.player[Main.myPlayer]; Rectangle rectangle = new Rectangle((int)Main.screenPosition.X, (int)Main.screenPosition.Y, Main.screenWidth, Main.screenHeight); int num = 5000; int icon = 0; for (int i = 0; i < 200; i++) { if (Main.npc[i].active) { icon = 0; int type = Main.npc[i].type; for (int n = 0; n < invaders.Length; n++) { if (type == invaders[n]) { Rectangle value = new Rectangle((int)(Main.npc[i].position.X + (float)(Main.npc[i].width / 2)) - num, (int)(Main.npc[i].position.Y + (float)(Main.npc[i].height / 2)) - num, num * 2, num * 2); if (rectangle.Intersects(value)) { flag = true; break; } } } } } Main.invasionProgressNearInvasion = flag; int progressMax3 = 1; //If the custom invasion is up, set the max progress as the initial invasion size if (ExampleWorld.StellarArmyUp) { progressMax3 = Main.invasionSizeStart; } //If the custom invasion is up and the enemies are at the spawn pos if (ExampleWorld.StellarArmyUp && (Main.invasionX == (double)Main.spawnTileX)) { //Shows the UI for the invasion Main.ReportInvasionProgress(Main.invasionSizeStart - Main.invasionSize, progressMax3, icon, 0); } //Syncing start of invasion foreach (Player p in Main.player) { NetMessage.SendData(78, p.whoAmI, -1, null, Main.invasionSizeStart - Main.invasionSize, (float)Main.invasionSizeStart, (float)(Main.invasionType + 3), 0f, 0, 0, 0); } } //Setting music to 1 which is “Night” } }
This is what it should look like:
Next thing is the World file.Code:using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using ReLogic.Graphics; using System; using System.Collections.Generic; using System.IO; using Terraria; using Terraria.GameContent.Dyes; using Terraria.GameContent.UI; using Terraria.Graphics.Effects; using Terraria.Graphics.Shaders; using Terraria.ID; using Terraria.Localization; using Terraria.UI; using static Terraria.ModLoader.ModContent; using Terraria.ModLoader; namespace AurumMod { public class AurumMod : Mod { public AurumMod() { Properties = new ModProperties() { Autoload = true, AutoloadGores = true, AutoloadSounds = true }; } public override void UpdateMusic(ref int music) { //Checks if the invasion is in the correct spot, if it is, then change the music if (Main.invasionX == Main.spawnTileX) { music = 1; } } public override void Load() { // Will show up in client.log under the ExampleMod name // In older tModLoader versions we used: ErrorLogger.Log("blabla"); // Replace that with above ModTranslation text = CreateTranslation("LivesLeft"); text = CreateTranslation("BossSpawnInfo.ExampleWormHead"); text.SetDefault("Use a [i:" + ModContent.ItemType<Items.ClingerWorm.StrangeBait>() + "] in the Corruption after Golem has been defeated"); AddTranslation(text); // Volcano warning is for the random volcano tremor } public override void PostSetupContent() { // Showcases mod support with Boss Checklist without referencing the mod Mod bossChecklist = ModLoader.GetMod("BossChecklist"); if (bossChecklist != null) { bossChecklist.Call( "AddBoss", 10.5f, new List<int> { ModContent.NPCType<NPCs.Bosses.Clinger_Worm.ExampleWormHead>()}, this, // Mod "Clinger Worm", (Func<bool>)(() => ExampleWorld.downedClingerWorm), ModContent.ItemType<Items.ClingerWorm.StrangeBait>(), "Use Strange Bait in the Corruption after Golem is defeated." ); } } } }
What you need now is the Npc file for some stuff:Code:using static AurumMod.StellarArmy; using AurumMod.NPCs.Bosses.Clinger_Worm; using AurumMod.Items; using AurumMod.NPCs; using AurumMod; using AurumMod.Tiles; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.Collections.Generic; using System.IO; using Terraria; using Terraria.DataStructures; using Terraria.GameContent.Generation; using Terraria.ID; using Terraria.Localization; using Terraria.ModLoader; using Terraria.ModLoader.IO; using Terraria.World.Generation; using static Terraria.ModLoader.ModContent; namespace AurumMod { public class ExampleWorld : ModWorld { public static bool downedClingerWorm; public static bool StellarArmyUp = false; public static bool downedStellarArmy = false; public override void Initialize() { downedClingerWorm = false; Main.invasionSize = 0; StellarArmyUp = false; downedStellarArmy = false; } public override TagCompound Save() { var downed = new List<string>(); if (downedStellarArmy) downed.Add("StellarArmy"); return new TagCompound { {"downed", downed} }; } public override void Load(TagCompound tag) { var downed = tag.GetList<string>("downed"); downedClingerWorm = downed.Contains("ClingerWorm"); downedStellarArmy = downed.Contains("StellarArmy"); } public override void NetSend(BinaryWriter writer) { var flags = new BitsByte(); flags[1] = downedClingerWorm; flags[0] = downedStellarArmy; writer.Write(flags); } // We use this hook to add 3 steps to world generation at various points. public override void NetReceive(BinaryReader reader) { BitsByte flags = reader.ReadByte(); downedStellarArmy = flags[0]; } //Allow to update invasion while game is running public override void PostUpdate() { if (StellarArmyUp) { if (Main.invasionX == (double)Main.spawnTileX) { //Checks progress and reports progress only if invasion at spawn StellarArmy.CheckStellarArmyProgress(); } //Updates the custom invasion while it heads to spawn point and ends it StellarArmy.UpdateStellarArmyWarning(); } } } }
Now you need an item to summon the invasion.Code:using System; using System.Collections.Generic; using AurumMod.Buffs; using AurumMod.Dusts; using AurumMod.Items; using Microsoft.Xna.Framework; using Terraria; using Terraria.ID; using Terraria.ModLoader; using static Terraria.ModLoader.ModContent; using AurumMod; using static AurumMod.StellarArmy; namespace AurumMod.NPCs { public class NPCsGLOBAL : GlobalNPC { public override bool InstancePerEntity => true; public bool AetheralMalady = false; public bool DivineInferno = false; public override void ResetEffects(NPC npc) { AetheralMalady = false; DivineInferno = false; } //Change the spawn pool public override void EditSpawnPool(IDictionary<int, float> pool, NPCSpawnInfo spawnInfo) { //If the custom invasion is up and the invasion has reached the spawn pos if (ExampleWorld.StellarArmyUp && (Main.invasionX == (double)Main.spawnTileX)) { //Clear pool so that only the stuff you want spawns pool.Clear(); //key = NPC ID | value = spawn weight //pool.add(key, value) //For every ID inside the invader array in our CustomInvasion file foreach (int i in StellarArmy.invaders) { pool.Add(i, 1f); //Add it to the pool with the same weight of 1 } } } //Changing the spawn rate public override void EditSpawnRate(Player player, ref int spawnRate, ref int maxSpawns) { //Change spawn stuff if invasion up and invasion at spawn if (ExampleWorld.StellarArmyUp && (Main.invasionX == (double)Main.spawnTileX)) { spawnRate = 100; //Higher the number, the more spawns maxSpawns = 10000; //Max spawns of NPCs depending on NPC value } } //Adding to the AI of an NPC public override void PostAI(NPC npc) { //Changes NPCs so they do not despawn when invasion up and invasion at spawn if (ExampleWorld.StellarArmyUp && (Main.invasionX == (double)Main.spawnTileX)) { npc.timeLeft = 1000; } } public override void UpdateLifeRegen(NPC npc, ref int damage)// unrlated to th invasion { if (AetheralMalady) { if (npc.lifeRegen > 0) { npc.lifeRegen = 0; } npc.lifeRegen -= 160; if (damage < 2) { damage = 4; } } if (DivineInferno) { if (npc.lifeRegen > 0) { npc.lifeRegen = 0; } npc.lifeRegen -= 280; if (damage < 2) { damage = 1; } } } public override void NPCLoot(NPC npc) { //The if (Main.rand.Next(x) == 0) determines how rare the drop is. To find the percent of a drop, divide 100 by your desired percent, minus the percent sign. Ex: A 2% chance would be 100% / 2%, or 50. This is what you put in place of x. // only the stuff with the stellar army is related to the event if (Main.rand.Next(50) == 0) //2% chance { if (npc.type == NPCID.ChaosElemental) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("DiscordianShard")); } if (npc.type == NPCID.SandElemental) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("ForbiddenTear")); } if (npc.type == NPCID.SandShark) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("ForbiddenTear")); } } if (Main.rand.Next(2) == 0) //2% chance { if (npc.type == NPCID.NebulaHeadcrab) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("BrainsucklerTentacle")); } if (npc.type == NPCID.StardustCellBig) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("StardustCellCore")); } if (npc.type == NPCID.SolarCrawltipedeHead) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("CrawltipedeMandible")); } if (npc.type == NPCID.VortexHornet) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("AlienHornetStinger")); } } if (Main.rand.Next(1) == 0) //2% chance { if (npc.type == NPCID.TruffleWorm) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("FungalSpray")); } if (npc.type == NPCID.TruffleWormDigger) { Item.NewItem((int)npc.position.X, (int)npc.position.Y, npc.width, npc.height, mod.ItemType("FungalSpray")); } } if (ExampleWorld.StellarArmyUp) { //Gets IDs of invaders from CustomInvasion file foreach (int invader in StellarArmy.invaders) { //If npc type equal to invader's ID decrement size to progress invasion if (npc.type == invader) { Main.invasionSize -= 1; } } } } public override void DrawEffects(NPC npc, ref Color drawColor)//This is not related to the invasion { if (AetheralMalady) { if (Main.rand.Next(4) < 3) { int dust = Dust.NewDust(npc.position - new Vector2(2f, 2f), npc.width + 4, npc.height + 4, DustType<AetheralMaladust>(), npc.velocity.X * 0.4f, npc.velocity.Y * 0.4f, 100, default(Color), 3.5f); Main.dust[dust].noGravity = true; Main.dust[dust].velocity *= 1.8f; Main.dust[dust].velocity.Y -= 0.5f; if (Main.rand.NextBool(4)) { Main.dust[dust].noGravity = false; Main.dust[dust].scale *= 0.5f; } } Lighting.AddLight(npc.position, 0.1f, 0.2f, 0.7f); } if (DivineInferno) { if (Main.rand.Next(4) < 3) { int dust = Dust.NewDust(npc.position - new Vector2(2f, 2f), npc.width + 4, npc.height + 4, DustType<DivineDust>(), npc.velocity.X * 0.4f, npc.velocity.Y * 0.4f, 100, default(Color), 3.5f); Main.dust[dust].noGravity = true; Main.dust[dust].velocity *= 1.8f; Main.dust[dust].velocity.Y -= 0.5f; if (Main.rand.NextBool(4)) { Main.dust[dust].noGravity = false; Main.dust[dust].scale *= 0.5f; } } Lighting.AddLight(npc.position, 0.1f, 0.2f, 0.7f); } } } }
This item should look like this:
Note: Stuff like the clinger worm the aetheral malady and the divine inferno are unrelated to the invasion.Code:using Microsoft.Xna.Framework; using Terraria; using Terraria.ID; using Terraria.ModLoader; using static Terraria.ModLoader.ModContent; namespace AurumMod.Items { public class StellarCrystal : ModItem { public override void SetStaticDefaults() { DisplayName.SetDefault("Stellar Crystal"); Tooltip.SetDefault("Awakens the Wyrms servants."); } public override void SetDefaults() { item.width = 32; item.height = 32; item.scale = 1; item.maxStack = 25; item.useTime = 30; item.useAnimation = 30; item.UseSound = SoundID.Item1; item.useStyle = 1; item.consumable = true; item.value = Item.buyPrice(0, 1, 0, 0); item.rare = 3; } public override bool UseItem(Player player) { if (!ExampleWorld.StellarArmyUp) { Main.NewText("The Stellar Army was angered.......", 175, 75, 255, false); StellarArmy.StartStellarArmy(); return true; } else { return false; } } public override void AddRecipes() { ModRecipe recipe = new ModRecipe(mod); recipe.AddIngredient(ItemType<Items.ManaCrystalSample>(), 25); recipe.AddTile(TileID.DemonAltar); recipe.SetResult(this); recipe.AddRecipe(); } } }
This also applies to the manacrystal sample and most of the loot in the global npc file.
I really hope I was able to help
I can help you with the sprites if you me toamazing. will be useful for me at least (or I could just use Tremor source lol)