/// <summary> /// /// </summary> /// <param name="info"></param> /// <param name="amount">SpawnInfo.Amount used if 0. Needed for respawning.</param> /// <param name="effect"></param> /// <returns>Amount of creatures spawned</returns> public int Spawn(SpawnInfo info, uint amount = 0, bool effect = false) { var result = 0; var rand = RandomProvider.Get(); var raceInfo = MabiData.RaceDb.Find(info.RaceId); if (raceInfo == null) { Logger.Warning("Race not found: " + info.RaceId.ToString()); return 0; } string aiFilePath = null; if (!string.IsNullOrEmpty(raceInfo.AI)) { aiFilePath = Path.Combine(WorldConf.ScriptPath, "ai", raceInfo.AI + ".cs"); if (!File.Exists(aiFilePath)) { Logger.Warning("AI script '" + raceInfo.AI + ".cs' couldn't be found."); aiFilePath = null; } } if (amount == 0) amount = info.Amount; for (int i = 0; i < amount; ++i) { var monster = new MabiNPC(); monster.SpawnId = info.Id; monster.Name = raceInfo.Name; var loc = info.GetRandomSpawnPoint(rand); monster.SetLocation(info.Region, loc.X, loc.Y); monster.AnchorPoint = new MabiVertex(loc.X, loc.Y); monster.Color1 = raceInfo.ColorA; monster.Color2 = raceInfo.ColorB; monster.Color3 = raceInfo.ColorC; monster.Height = raceInfo.Size; monster.LifeMaxBase = raceInfo.Life; monster.Life = raceInfo.Life; monster.Race = raceInfo.Id; monster.BattleExp = raceInfo.Exp; monster.Direction = (byte)rand.Next(256); monster.State &= ~CreatureStates.GoodNpc; // Use race default? monster.GoldMin = raceInfo.GoldMin; monster.GoldMax = raceInfo.GoldMax; monster.Drops = raceInfo.Drops; foreach (var skill in raceInfo.Skills) { monster.Skills.Add(new MabiSkill(skill.SkillId, skill.Rank, monster.Race)); } monster.LoadDefault(); // Missing stat data? if (monster.Life < 1) monster.Life = monster.LifeMaxBase = 10; try { if (aiFilePath != null) { var aiscriptAsm = this.GetScript(aiFilePath); if (aiscriptAsm != null) { var types = aiscriptAsm.GetTypes().Where(t => t.IsSubclassOf(typeof(AIScript))); monster.AIScript = Activator.CreateInstance(types.First()) as AIScript; monster.AIScript.Creature = monster; monster.AIScript.OnLoad(); monster.AIScript.Activate(0); // AI is intially active } else { raceInfo.AI = null; // Suppress future attempts to load this AI } } } catch (Exception ex) { Logger.Exception(ex); } monster.AncientEligible = true; monster.AncientTime = DateTime.Now.AddMinutes(WorldConf.TimeBeforeAncient); WorldManager.Instance.AddCreature(monster); if (effect) WorldManager.Instance.Broadcast(PacketCreator.SpawnEffect(monster, SpawnEffect.Monster), SendTargets.Range, monster); result++; } return result; }