/// <summary>Processes the (re)spawning of entities in the zone. Iterates the spawns for this zone and then adds a corresponding /// NPC to the mob list if various spawn conditions are met.</summary> private void SpawnTimerCallback(object state) { NpcMob npcMob = null; using (EmuDataContext dbCtx = new EmuDataContext()) { dbCtx.ObjectTrackingEnabled = false; List<SkillCap> skillCaps = dbCtx.SkillCaps.OrderBy(sc => sc.SkillID).ThenBy(sc => sc.Class).ThenBy(sc => sc.Level).ToList(); foreach (Internals.Data.Spawn s in this.Zone.Spawns) { // TODO: Handle timeleft on spawn entity (may be able to wait until persistant zone state is in) // TODO: Process spawn conditions if (!s.ReadyForRespawn()) continue; try { Npc npc = s.SpawnGroup.PickNPC(); // Get an Npc if (npc != null) { npcMob = new NpcMob(GetNewEntityId(), npc, s.PathGrid, s.X, s.Y, s.Z, s.Heading); // Clean up the npc's name and make it unique (def. before we add to list) npcMob.Name = npcMob.Name.RemoveDigits(); npcMob.Name = GetUniqueMobName(npcMob.Name); var npcSkillCaps = skillCaps.Where(sc => sc.Class == npcMob.Class && sc.Level == npcMob.Level); foreach (SkillCap cap in npcSkillCaps) npcMob.SetSkillLevel((Skill)cap.SkillID, cap.Level); //_log.DebugFormat("Trying to add npc with entity id of {0}", npcMob.ID); AddNpc(npcMob, true, false); // TODO: add to npc limit list s.LastSpawned = DateTime.Now; // TODO: set roambox? npcMob.LoadGrid(this.Zone.ZoneID, dbCtx); } else { s.LastSpawned = DateTime.MaxValue; // better than tracking a separate list of deletes and delete routine? _log.DebugFormat("Spawn {0} removed due to lack of NPCs, spawn groups or cumulative spawn chance of zero.", s.SpawnID); } } catch (Exception ex) { _log.Error("Error in SpawnTimerCallback", ex); } } } }
private void NpcDeath(NpcMob npc, Mob lastAttacker, uint spellId, byte damageType, uint damage) { RemoveFromAllTargets(npc); // Remove NPC from any entity's target & hate lists // Send Death Packet Death d = new Death() { SpawnId = (uint)npc.ID, KillerId = lastAttacker == null ? 0u : (uint)lastAttacker.ID, BindToZoneId = 0u, SpellId = spellId == 0u ? 0xFFFFFFFF : spellId, AttackSkillId = damageType, Damage = damage }; EQApplicationPacket<Death> dPack = new EQApplicationPacket<Death>(AppOpCode.Death, d); _zoneSvr.QueuePacketToClients(lastAttacker, dPack, false); // TODO: this should be cool with a null lastAttacker, right? // TODO: something about respawn? Mob killer = npc.HateMgr.GetTopHated(); Mob xpMob = npc.HateMgr.GetTopDamager(); // Give xp out if (xpMob == null) xpMob = killer; if (xpMob == null) xpMob = lastAttacker; // TODO: if xpMob is pet, get the owner ZonePlayer xpClient = xpMob as ZonePlayer; if (xpClient != null) { // TODO: handle raid split, LDON adventure crap, etc. float groupBonus = 1.0f; if (xpClient.IsGrouped) { // TODO: handle group split // TODO: add group xp bonus } else { ConLevel conLvl = Mob.GetConsiderDificulty(xpClient.Level, npc.Level); if (conLvl != ConLevel.Green) { // TODO: figure high con bonus, if any int baseXp = (int)(npc.Level * npc.Level * groupBonus * _zoneSvr.Zone.XPMultiplier); xpClient.GiveXP((int)(npc.Level * npc.Level * 75 * _zoneSvr.Zone.XPMultiplier), conLvl); } } // TODO: raise death merit event? } // TODO: faction hits // Make a corpse and add to the manager if (npc.IsLootable) { // TODO: add additional checks for stuff like a guard killing the mob, etc. Corpse c = new Corpse(npc, npc.LootItems); AddCorpse(c); // TODO: if killer is a pet, get the owner if (xpClient != null) c.AllowLooter(killer as ZonePlayer); } // TODO: raise script event _log.DebugFormat("NPC {0} has died", npc.ID); }
private void AddNpc(NpcMob npcMob, bool sendSpawnPacket, bool dontQueue) { // TODO: try to see if we can get away with only one list for mobs & npcs... npcs are in the mob list, so hey, it might work //_npcMobs.Add(npcMob.NpcID, npcMob); // Added by id of the npc db entity AddMob(npcMob); if (sendSpawnPacket) { if (dontQueue) { EQApplicationPacket<Internals.Packets.Spawn> spawnPack = new EQApplicationPacket<Internals.Packets.Spawn>(AppOpCode.NewSpawn, npcMob.GetSpawn()); QueuePacketToClients(null, spawnPack, true); // TODO: raise spawn event } else if (_clients.Count > 0) // no clients, no send anything { lock (((ICollection)_spawnQueue).SyncRoot) { _spawnQueue.Enqueue(npcMob.GetSpawn()); } } // TODO: raise spawn event - nah, better place is where it actually spawns, yea? } }