tModLoader How to make an invasion?

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?
 
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:
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”
      


    }
}
The next thing you'll need is the mod file.
This is what it should look like:
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 (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."
                );

            }
        }


    } 
  


}
Next thing is the World file.
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();
            }
        }




    }

      
}
What you need now is the Npc file for some stuff:
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);
            }
        }
}    }
Now you need an item to summon the invasion.
This item should look like this:
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();
        }

      
    }
}
Note: Stuff like the clinger worm the aetheral malady and the divine inferno are unrelated to the invasion.
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 :)
Edit:Fixed an mistake in the script.
 
Last edited:
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:
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”
       


    }
}
The next thing you'll need is the mod file.
This is what it should look like:
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."
                );

            }
        }


    }  
   


}
Next thing is the World file.
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();
            }
        }




    }

       
}
What you need now is the Npc file for some stuff:
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);
            }
        }
}    }
Now you need an item to summon the invasion.
This item should look like this:
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();
        }

       
    }
}
Note: Stuff like the clinger worm the aetheral malady and the divine inferno are unrelated to the invasion.
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 :)
amazing. will be useful for me at least (or I could just use Tremor source lol)
 
Back
Top Bottom