/// <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; } }
private void InvasionTimer_Elapsed(object sender, ElapsedEventArgs e) { if (TShock.Utils.ActivePlayers() == 0) { return; } int spawnFails = 0; int spawnsThisWave = 0; int spawnX = Main.spawnTileX - 150; int spawnY = Main.spawnTileY - 150; Rectangle SpawnRegion = new Rectangle(spawnX, spawnY, 300, 300); foreach (SpawnMinion minions in CurrentWave.SpawnGroup.SpawnMinions) { var npcdef = NPCManager.Data.GetNPCbyID(minions.MobID); if (npcdef == null) { TShock.Log.ConsoleError("[CustomNPC]: Error! The custom mob id \"{0}\" does not exist!", minions.MobID); continue; } // Check spawn conditions if (minions.SpawnConditions != SpawnConditions.None) { if (NPCManager.CheckSpawnConditions(minions.SpawnConditions)) { continue; } } foreach (TSPlayer player in TShock.Players) { //Skip spawning more NPCs when we have likely hit the server's mob limit. if (spawnFails > 40 && spawnsThisWave >= 150) { continue; } if (player == null || player.Dead || !player.Active || !NPCManager.Chance(minions.Chance)) { continue; } 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; } if (minions.BiomeConditions != BiomeTypes.None) { BiomeTypes biomes = player.GetCurrentBiomes(); if ((minions.BiomeConditions & biomes) == 0) { continue; } } // Prevent multiple bosses from spawning during invasions if (minions.isBoss && NPCManager.AliveCount(minions.MobID) > 0) { continue; } int mobid = -1; //Try max 3 times. Since every try checks 50 positions around the player to spawn the mob, //3 tries means a maximum of 150 spawn attempts. for (int i = 0; mobid == -1 && i < 3; i++) { mobid = NPCManager.SpawnMobAroundPlayer(player, npcdef); } if (mobid == -1) { spawnFails++; continue; } NPCManager.GetCustomNPCByIndex(mobid).isInvasion = true; spawnsThisWave++; } } if (spawnFails > 0) { TShock.Log.ConsoleInfo("[CustomNPC]: Failed to spawn {0} npcs this wave!", spawnFails); } }