示例#1
0
        /// <summary>
        /// Customize NPC to Customized NPC specifications
        /// </summary>
        /// <param name="index"></param>
        /// <param name="obj"></param>
        /// <param name="netDef">If false, this method doesn't set netDefaults on the npc in question.</param>
        public void ConvertNPCToCustom(int index, CustomNPCDefinition obj, bool netDef = true)
        {
            NPC npc = Main.npc[index];

            if (netDef)
            {
                npc.SetDefaults(obj.customBase.netID);
            }

            npc._givenName    = obj.customName;
            npc.lifeMax       = obj.customHealth;
            npc.life          = obj.customHealth + 1;
            npc.aiStyle       = obj.customAI;
            npc.lavaImmune    = obj.lavaImmune;
            npc.noGravity     = obj.noGravity;
            npc.noTileCollide = obj.noTileCollide;

            npc.defense    = obj.customDefense;
            npc.defDefense = obj.customDefense;

            npc.boss = obj.isBoss;

            if (!string.IsNullOrEmpty(obj.customSpawnMessage))
            {
                TSPlayer.All.SendMessage(obj.customSpawnMessage, obj.customSpawnMessageColor);
            }
        }
示例#2
0
        private static int SpawnCustomNPC(int x, int y, CustomNPCDefinition definition)
        {
            //DEBUG
            TShock.Log.ConsoleInfo("DEBUG Spawning Custom NPC at {0}, {1} with customID {2}", x, y, definition.customID);
            //DEBUG

            int npcid = NPC.NewNPC(x, y, definition.customBase.type);

            if (npcid == 200)
            {
                //DEBUG
                TShock.Log.ConsoleInfo("DEBUG Spawning FAILED (mobcap) at {0}, {1} for customID {2}", x, y, definition.customID);
                //DEBUG
                return(-1);
            }

            Data.ConvertNPCToCustom(npcid, definition);
            DateTime[] dt = null;
            if (definition.customProjectiles != null)
            {
                dt = Enumerable.Repeat(DateTime.Now, definition.customProjectiles.Count).ToArray();
            }
            NPCs[npcid] = new CustomNPCVars(definition, dt, Main.npc[npcid]);

            TSPlayer.All.SendData(PacketTypes.NpcUpdate, "", npcid);
            return(npcid);
        }
示例#3
0
        public void Add(CustomNPCDefinition definition)
        {
            if (definition == null)
            {
                throw new ArgumentNullException("definition");
            }

            Definitions.Add(definition.customID, definition);
        }
示例#4
0
        /// <summary>
        /// List custom npcs using /csmlist &lt;page&gt; [onlyalive]
        /// </summary>
        /// <param name="args"></param>
        private void CommandListNPCS(CommandArgs args)
        {
            //Error if too many or too few params specified
            if (args.Parameters.Count == 0 || args.Parameters.Count > 2)
            {
                args.Player.SendInfoMessage("Usage: /csmlist <page> [onlyalive]");
                return;
            }

            int page;

            if (!int.TryParse(args.Parameters[0], out page))
            {
                args.Player.SendErrorMessage("Error: Invalid page defined! Please give a number.");
                return;
            }

            bool onlyalive = false;

            if (args.Parameters.Count == 2 && !bool.TryParse(args.Parameters[1], out onlyalive))
            {
                args.Player.SendErrorMessage("Error: Invalid onlyalive flag! onlyalive can be true or false.");
                return;
            }

            //Check if page is valid
            if (page < 1)
            {
                args.Player.SendErrorMessage("Error: Invalid page defined! Page has to be 1 or bigger.");
                return;
            }

            var vals = NPCManager.Data.CustomNPCs.Values.Where(cd => cd != null && (!onlyalive || cd.currSpawnsVar > 0));

            int start      = (page - 1) * 6;
            int end        = start + 6;
            int total      = vals.Count();
            int totalpages = (total + 5) / 6;

            if (start > total)
            {
                args.Player.SendErrorMessage("Error: Page too large! The last page is \"{0}\".", totalpages);
                return;
            }

            args.Player.SendInfoMessage("Page {0} / {1}. Only Alive = {2}", page, totalpages, onlyalive);

            for (int i = start; i < end && i < total; i++)
            {
                CustomNPCDefinition obj = vals.ElementAt(i);

                args.Player.SendInfoMessage("[{0}]: {1}. Spawned: {2}", obj.customID, obj.customName, obj.currSpawnsVar);
            }
        }
示例#5
0
        public CustomNPCVars(CustomNPCDefinition customnpc, DateTime[] lastattemptedprojectile, NPC mainnpc, bool isclone = false)
        {
            lastAttemptedProjectile = lastattemptedprojectile;
            isDead      = false;
            isUncounted = false;
            isClone     = isclone;
            customNPC   = customnpc;
            mainNPC     = mainnpc;
            droppedLoot = false;

            //Update if this mob is using custom ai.
            updateCustomAI();
        }
示例#6
0
        /// <summary>
        /// Transforms a NPC to another Custom NPC
        /// </summary>
        /// <param name="id">CustomNPC that will be replacing it</param>
        /// <param name="addhealth">Increase monsters Health</param>
        /// <param name="additionalhealth">Amount to Increase by, if 0 - get new monsters health and add that to NPC</param>
        /// <param name="fullTransform">When false, only the skin of the NPC changes. When true, also applies some of the given NPC's stats</param>
        public bool Transform(string id, bool addhealth = false, int additionalhealth = 0)
        {
            CustomNPCDefinition search = NPCManager.Data.GetNPCbyID(id);

            //If not found, return false
            if (search == null)
            {
                return(false);
            }

            Transform(search, addhealth, additionalhealth);
            return(true);
        }
示例#7
0
        public static int SpawnNPCAroundNPC(int npcindex, ShotTile shottile, CustomNPCDefinition customnpc)
        {
            NPC npc = Main.npc[npcindex];

            if (npc == null)
            {
                return(-1);
            }

            int x = (int)(npc.position.X + shottile.X);
            int y = (int)(npc.position.Y + shottile.Y);

            return(SpawnCustomNPC(x, y, customnpc));
        }
示例#8
0
        /// <summary>
        /// (Attempts to) Spawn monsters randomly around the current x y position.
        /// </summary>
        /// <param name="npcvar">The Custom NPC to use to spawn children</param>
        /// <param name="amount">The amount to spawn</param>
        /// <param name="sethealth"></param>
        /// <param name="health"></param>
        public void Multiply(CustomNPCDefinition type, int amount, bool sethealth = false, int health = 0)
        {
            //DEBUG
            TShock.Log.ConsoleInfo("DEBUG [Multiply] entry. amount={0}, sethealth={1}, health={2}", amount, sethealth, health);
            //DEBUG

            // MainNPC is gone.
            if (mainNPC == null)
            {
                return;
            }

            if (type == null)
            {
                return;
            }

            for (int i = 0; i < amount; i++)
            {
                int x = (int)mainNPC.position.X + rand.Next(-8, 9);
                int y = (int)mainNPC.position.Y + rand.Next(-8, 9);

                int npc = NPCManager.SpawnNPCAtLocation(x, y, type);
                if (npc == -1)
                {
                    //DEBUG
                    TShock.Log.ConsoleInfo("DEBUG [Multiply] spawn failed. location={0}, {1}", x, y);
                    //DEBUG
                    continue;
                }

                var spawned = NPCManager.GetCustomNPCByIndex(npc);
                if (spawned == null)
                {
                    continue;
                }

                if (sethealth)
                {
                    spawned.mainNPC.life = health;
                }

                spawned.isClone = true;
            }
        }
示例#9
0
        /// <summary>
        /// Returns a list of all Custom NPC that are spawned of the given type.
        /// </summary>
        /// <param name="customnpc">The type to look for</param>
        /// <returns></returns>
        public static List <CustomNPCVars> GetAllOfType(CustomNPCDefinition customnpc)
        {
            List <CustomNPCVars> tbr = new List <CustomNPCVars>();

            foreach (CustomNPCVars v in NPCs)
            {
                if (v == null)
                {
                    continue;
                }

                if (v.customNPC == customnpc)
                {
                    tbr.Add(v);
                }
            }

            return(tbr);
        }
示例#10
0
        /// <summary>
        /// Transforms a NPC to another Custom NPC
        /// </summary>
        /// <param name="npcdef">CustomNPC that will be replacing it</param>
        /// <param name="addhealth">Increase monsters Health</param>
        /// <param name="additionalhealth">Amount to Increase by, if 0 - get new monsters health and add that to NPC</param>
        public void Transform(CustomNPCDefinition npcdef, bool addhealth = false, int additionalhealth = 0)
        {
            //DEBUG
            TShock.Log.ConsoleInfo("DEBUG [TransformToCustom] addHealth={0} additionalHealth={1}", addhealth, additionalhealth);
            //DEBUG

            customNPC = npcdef;

            CustomTransform();

            //mainNPC.type = npcdef.customBase.type;

            if (addhealth)
            {
                if (additionalhealth == 0)
                {
                    mainNPC.life += npcdef.customHealth;
                }
                else
                {
                    mainNPC.life += additionalhealth;
                }
            }

            postTransform();

            //#Issue Number 7: Github issue
            //Improve this!
            //Temp Fix for projectiles not attaching to transformations, some one else should redo this in a better way..
            DateTime[] dt = null;
            if (npcdef.customProjectiles != null)
            {
                dt = Enumerable.Repeat(DateTime.Now, npcdef.customProjectiles.Count).ToArray();
            }

            NPC spawned = Main.npc[mainNPC.whoAmI];

            NPCManager.NPCs[mainNPC.whoAmI] = new CustomNPCVars(npcdef, dt, spawned);
            NPCManager.Data.ConvertNPCToCustom(mainNPC.whoAmI, npcdef);
        }
示例#11
0
        /// <summary>
        /// This is called once the CustomNPCDefinitions have been loaded into the DefinitionManager.
        /// </summary>
        /// <param name="definitions"></param>
        internal void LoadFrom(DefinitionManager definitions)
        {
            foreach (var pair in definitions.Definitions)
            {
                string id = pair.Key;
                CustomNPCDefinition definition = pair.Value;

                CustomNPCs.Add(id, definition);
                foreach (var spawning in definition.customNPCSpawning)
                {
                    if (spawning.spawnBiome != BiomeTypes.None)
                    {
                        AddCustomNPCToBiome(spawning.spawnBiome, id, spawning);
                    }

                    if (!string.IsNullOrEmpty(spawning.spawnRegion))
                    {
                        AddCustomNPCToRegion(spawning.spawnRegion, id, spawning);
                    }
                }
            }
        }
示例#12
0
 public bool TryGetDefinition(string id, out CustomNPCDefinition definition)
 {
     return(Definitions.TryGetValue(id, out definition));
 }
示例#13
0
            /// <summary>
            /// Attempts to spawn the given minion for every player online, where applicable.
            /// </summary>
            /// <param name="spawnRegion"></param>
            /// <param name="minion"></param>
            /// <param name="npcdef"></param>
            /// <param name="attempts"></param>
            private static void SpawnMinion(Rectangle spawnRegion, SpawnMinion minion, CustomNPCDefinition npcdef, int attempts)
            {
                //Loop through players
                foreach (TSPlayer player in TShock.Players)
                {
                    if (player == null || player.Dead || !player.Active || !NPCManager.Chance(minion.Chance))
                    {
                        continue;
                    }

                    //Check if the minions can spawn anywhere, or if we need to check if players see them.
                    if (!CurrentWave.SpawnAnywhere)
                    {
                        Rectangle playerFrame = new Rectangle((int)player.TPlayer.position.X, (int)player.TPlayer.position.Y, player.TPlayer.width, player.TPlayer.height);
                        if (!playerFrame.Intersects(spawnRegion))
                        {
                            continue;
                        }
                    }

                    //Check biomes
                    if (minion.BiomeConditions != BiomeTypes.None)
                    {
                        BiomeTypes biomes = player.GetCurrentBiomes();

                        if ((minion.BiomeConditions & biomes) == 0)
                        {
                            continue;
                        }
                    }

                    int mobid = -1;

                    //Try max attempts times. This gives attempts*50 spawn attempts at random positions.
                    for (int i = 0; mobid == -1 && i < attempts; i++)
                    {
                        mobid = NPCManager.SpawnMobAroundPlayer(player, npcdef);
                    }

                    //Spawning failed :(
                    if (mobid == -1)
                    {
                        continue;
                    }

                    NPCManager.GetCustomNPCByIndex(mobid).isInvasion = true;
                }
            }
示例#14
0
        public static int SpawnMobAroundPlayer(TSPlayer player, CustomNPCDefinition definition)
        {
            const int SpawnSpaceX = 3;
            const int SpawnSpaceY = 3;

            //Search for a location
            int screenTilesX = (int)(NPC.sWidth / 16f);
            int screenTilesY = (int)(NPC.sHeight / 16f);
            int spawnRangeX  = (int)(screenTilesX * 0.7);
            int spawnRangeY  = (int)(screenTilesY * 0.7);
            int safeRangeX   = (int)(screenTilesX * 0.52);
            int safeRangeY   = (int)(screenTilesY * 0.52);

            Vector2 position    = player.TPlayer.position;
            int     playerTileX = (int)(position.X / 16f);
            int     playerTileY = (int)(position.Y / 16f);

            int spawnRangeMinX = Math.Max(0, Math.Min(Main.maxTilesX, playerTileX - spawnRangeX));
            int spawnRangeMaxX = Math.Max(0, Math.Min(Main.maxTilesX, playerTileX + spawnRangeX));
            int spawnRangeMinY = Math.Max(0, Math.Min(Main.maxTilesY, playerTileY - spawnRangeY));
            int spawnRangeMaxY = Math.Max(0, Math.Min(Main.maxTilesY, playerTileY + spawnRangeY));

            int safeRangeMinX = Math.Max(0, Math.Min(Main.maxTilesX, playerTileX - safeRangeX));
            int safeRangeMaxX = Math.Max(0, Math.Min(Main.maxTilesX, playerTileX + safeRangeX));
            int safeRangeMinY = Math.Max(0, Math.Min(Main.maxTilesY, playerTileY - safeRangeY));
            int safeRangeMaxY = Math.Max(0, Math.Min(Main.maxTilesY, playerTileY + safeRangeY));

            int spawnX = 0;
            int spawnY = 0;

            bool found    = false;
            int  attempts = 0;

            while (attempts < 50)
            {
                int testX = rand.Next(spawnRangeMinX, spawnRangeMaxX);
                int testY = rand.Next(spawnRangeMinY, spawnRangeMaxY);

                OTAPI.Tile.ITile testTile = Main.tile[testX, testY];
                if (testTile.nactive() && Main.tileSolid[testTile.type])
                {
                    attempts++;
                    continue;
                }

                if (!Main.wallHouse[testTile.wall])
                {
                    for (int y = testY; y < Main.maxTilesY; y++)
                    {
                        OTAPI.Tile.ITile test = Main.tile[testX, y];
                        if (test.nactive() && Main.tileSolid[test.type])
                        {
                            if (testX < safeRangeMinX || testX > safeRangeMaxX || y < safeRangeMinY || y > safeRangeMaxY)
                            {
                                spawnX = testX;
                                spawnY = y;
                                found  = true;
                                break;
                            }
                        }
                    }

                    if (!found)
                    {
                        attempts++;
                    }

                    int spaceMinX = spawnX - (SpawnSpaceX / 2);
                    int spaceMaxX = spawnX + (SpawnSpaceX / 2);
                    int spaceMinY = spawnY - SpawnSpaceY;
                    int spaceMaxY = spawnY;
                    if (spaceMinX < 0 || spaceMaxX > Main.maxTilesX)
                    {
                        attempts++;
                        continue;
                    }

                    if (spaceMinY < 0 || spaceMaxY > Main.maxTilesY)
                    {
                        attempts++;
                        continue;
                    }

                    if (found)
                    {
                        for (int x = spaceMinX; x < spaceMaxX; x++)
                        {
                            for (int y = spaceMinY; y < spaceMaxY; y++)
                            {
                                if (Main.tile[x, y].nactive() && Main.tileSolid[Main.tile[x, y].type])
                                {
                                    found = false;
                                    break;
                                }

                                if (Main.tile[x, y].lava())
                                {
                                    found = false;
                                    break;
                                }
                            }
                        }

                        if (!found)
                        {
                            attempts++;
                            continue;
                        }
                    }

                    if (spawnX >= safeRangeMinX && spawnX <= safeRangeMaxX)
                    {
                        if (!found)
                        {
                            attempts++;
                            continue;
                        }
                    }
                }
            }

            if (found)
            {
                return(SpawnCustomNPC((spawnX * 16) + 8, spawnY * 16, definition));
            }

            return(-1);
        }
示例#15
0
 public static int SpawnNPCAtLocation(int x, int y, CustomNPCDefinition customnpc)
 {
     return(SpawnCustomNPC(x, y, customnpc));
 }
示例#16
0
        internal static void SpawnMobsInBiomeAndRegion()
        {
            //loop through all players
            foreach (TSPlayer player in TShock.Players)
            {
                //Check if player exist and is connected
                if (player == null || !player.ConnectionAlive)
                {
                    continue;
                }

                //Log.ConsoleInfo("{0} - Checking spawn for player", player.Name);

                //Check all biome spawns
                BiomeTypes biomes = player.GetCurrentBiomes();
                foreach (BiomeTypes biome in availableBiomes.Where(x => biomes.HasFlag(x)))
                {
                    //Log.ConsoleInfo("{0} - Checking biome for player", biome.ToString());

                    //Get list of mobs that can be spawned in that biome
                    List <Tuple <string, CustomNPCSpawning> > biomeSpawns;
                    if (!Data.BiomeSpawns.TryGetValue(biome, out biomeSpawns))
                    {
                        continue;
                    }

                    foreach (Tuple <string, CustomNPCSpawning> obj in biomeSpawns)
                    {
                        //Log.ConsoleInfo("{0} - Checking mob spawn", obj.Item1);
                        //Check spawn conditions
                        if (!CheckSpawnConditions(obj.Item2.spawnConditions))
                        {
                            //Log.ConsoleInfo("False Conditions");
                            continue;
                        }

                        CustomNPCDefinition customnpc = Data.GetNPCbyID(obj.Item1);

                        if (customnpc.maxSpawns <= -1)
                        {
                            customnpc.currSpawnsVar++;
                        }

                        //Make sure not spawning more then maxSpawns
                        if (customnpc.maxSpawns != -1 && customnpc.currSpawnsVar >= customnpc.maxSpawns)
                        {
                            continue;
                        }


                        //Get the last spawn attempt
                        DateTime lastSpawnAttempt;
                        if (!Data.LastSpawnAttempt.TryGetValue(customnpc.customID, out lastSpawnAttempt))
                        {
                            lastSpawnAttempt = default(DateTime);
                            Data.LastSpawnAttempt[customnpc.customID] = lastSpawnAttempt;
                        }

                        //If not enough time has passed, we skip and go to the next NPC.
                        if ((DateTime.Now - lastSpawnAttempt).TotalSeconds < obj.Item2.spawnRate)
                        {
                            continue;
                        }

                        //Check spawn chance
                        if (!NPCManager.Chance(obj.Item2.spawnChance))
                        {
                            continue;
                        }

                        // Check Player Depth

                        if (player.TileY > obj.Item2.minDepth && player.TileY < obj.Item2.maxDepth || obj.Item2.minDepth == -1 || obj.Item2.maxDepth == -1)
                        {
                            //Check spawn method
                            if (obj.Item2.useTerrariaSpawn)
                            {
                                //All checks completed --> spawn mob
                                int npcid = SpawnMobAroundPlayer(player, customnpc);
                                if (npcid != -1)
                                {
                                    Main.npc[npcid].target = player.Index;
                                    Data.LastSpawnAttempt[customnpc.customID] = DateTime.Now;
                                    customnpc.currSpawnsVar++;
                                }
                            }
                            else
                            {
                                //All checks completed --> spawn mob
                                int spawnX;
                                int spawnY;

                                TShock.Utils.GetRandomClearTileWithInRange(player.TileX, player.TileY, 50, 50, out spawnX, out spawnY);

                                int npcid = SpawnNPCAtLocation((spawnX * 16) + 8, spawnY * 16, customnpc);
                                if (npcid == -1)
                                {
                                    continue;
                                }

                                Data.LastSpawnAttempt[customnpc.customID] = DateTime.Now;
                                Main.npc[npcid].target = player.Index;
                                customnpc.currSpawnsVar++;
                            }
                        }
                    }
                }

                //Then check regions as well
                Rectangle playerRectangle = new Rectangle(player.TileX, player.TileY, player.TPlayer.width, player.TPlayer.height);
                foreach (Region obj in Data.RegionSpawns.Keys.Select(name => TShock.Regions.GetRegionByName(name)).Where(region => region != null && region.InArea(playerRectangle)))
                {
                    List <Tuple <string, CustomNPCSpawning> > regionSpawns;
                    if (!Data.RegionSpawns.TryGetValue(obj.Name, out regionSpawns))
                    {
                        continue;
                    }

                    foreach (Tuple <string, CustomNPCSpawning> obj2 in regionSpawns)
                    {
                        //Invalid spawn conditions
                        if (!CheckSpawnConditions(obj2.Item2.spawnConditions))
                        {
                            continue;
                        }

                        CustomNPCDefinition customnpc = Data.GetNPCbyID(obj2.Item1);

                        //Make sure not spawning more then maxSpawns
                        if (customnpc.maxSpawns != -1 && customnpc.currSpawnsVar >= customnpc.maxSpawns)
                        {
                            continue;
                        }

                        //Get the last spawn attempt
                        DateTime lastSpawnAttempt;
                        if (!Data.LastSpawnAttempt.TryGetValue(customnpc.customID, out lastSpawnAttempt))
                        {
                            lastSpawnAttempt = default(DateTime);
                            Data.LastSpawnAttempt[customnpc.customID] = lastSpawnAttempt;
                        }

                        //If not enough time passed, we skip and go to the next NPC.
                        if ((DateTime.Now - lastSpawnAttempt).TotalSeconds < obj2.Item2.spawnRate)
                        {
                            continue;
                        }

                        Data.LastSpawnAttempt[customnpc.customID] = DateTime.Now;

                        if (!NPCManager.Chance(obj2.Item2.spawnChance))
                        {
                            continue;
                        }

                        // Check Player Depth

                        if (player.TileY > obj2.Item2.minDepth && player.TileY < obj2.Item2.maxDepth || obj2.Item2.minDepth == -1 || obj2.Item2.maxDepth == -1)
                        {
                            var region = TShock.Regions.GetRegionByName(obj2.Item2.spawnRegion);
                            ActiveArenas.Add(region);
                            ActiveArenas.Count();

                            var arenaX = region.Area.X + (region.Area.Width / 2);
                            var arenaY = region.Area.Y + (region.Area.Height / 2);
                            var rangeX = region.Area.Width / 2;
                            var rangeY = region.Area.Height / 2;

                            int spawnX;
                            int spawnY;

                            TShock.Utils.GetRandomClearTileWithInRange(arenaX, arenaY, rangeX, rangeY, out spawnX, out spawnY);

                            int npcid = SpawnNPCAtLocation((spawnX * 16) + 8, spawnY * 16, customnpc);
                            if (npcid == -1)
                            {
                                continue;
                            }


                            Main.npc[npcid].target = player.Index;
                            customnpc.currSpawnsVar++;
                            ActiveArenas.Remove(region);
                            continue;
                        }
                    }
                }
            }
        }