/// <summary> /// Called when a player dies, in conjunction with Die() /// </summary> /// <param name="lastDamager">The last damager that landed the death blow</param> /// <param name="damageType">The damage type for the death message</param> public override DeathMessage OnDeath(WorldObject lastDamager, DamageType damageType, bool criticalHit = false) { var deathMessage = base.OnDeath(lastDamager, damageType, criticalHit); lastDamager.EmoteManager.OnKill(this); var playerMsg = string.Format(deathMessage.Victim, Name, lastDamager.Name); var msgYourDeath = new GameEventYourDeath(Session, playerMsg); Session.Network.EnqueueSend(msgYourDeath); // broadcast to nearby players var nearbyMsg = string.Format(deathMessage.Broadcast, Name, lastDamager.Name); var broadcastMsg = new GameMessageSystemChat(nearbyMsg, ChatMessageType.Broadcast); var excludePlayers = new List <Player>(); if (lastDamager is Player lastDamagerPlayer) { excludePlayers.Add(lastDamagerPlayer); } var nearbyPlayers = EnqueueBroadcast(excludePlayers, false, broadcastMsg); excludePlayers.AddRange(nearbyPlayers); excludePlayers.Add(this); // exclude self if (Fellowship != null) { Fellowship.OnDeath(this); } // if the player's lifestone is in a different landblock, also broadcast their demise to that landblock if (Sanctuary != null && Location.Landblock != Sanctuary.Landblock) { // ActionBroadcastKill might not work if other players around lifestone aren't aware of this player yet... // this existing broadcast method is also based on the current visible objects to the player, // and the player hasn't entered portal space or teleported back to the lifestone yet, so this doesn't work //ActionBroadcastKill(nearbyMsg, Guid, lastDamager.Guid); // instead, we get all of the players in the lifestone landblock + adjacent landblocks, // and possibly limit that to some radius around the landblock? var lifestoneBlock = LandblockManager.GetLandblock(new LandblockId(Sanctuary.Landblock << 16 | 0xFFFF), true); lifestoneBlock.EnqueueBroadcast(excludePlayers, true, broadcastMsg); } return(deathMessage); }
/// <summary> /// Player Death/Kill, use this to kill a session's player /// </summary> /// <remarks> /// TODO: /// 1. Find the best vitae formula and add vitae /// 2. Generate the correct death message, or have it passed in as a parameter. /// 3. Find the correct player death noise based on the player model and play on death. /// 4. Determine if we need to Send Queued Action for Lifestone Materialize, after Action Location. /// 5. Find the health after death formula and Set the correct health /// </remarks> private void OnKill(Session killerSession) { ObjectGuid killerId = killerSession.Player.Guid; IsAlive = false; Health.Current = 0; // Set the health to zero NumDeaths++; // Increase the NumDeaths counter DeathLevel = Level; // For calculating vitae XP VitaeCpPool = 0; // Set vitae XP // TODO: Generate a death message based on the damage type to pass in to each death message: string currentDeathMessage = $"died to {killerSession.Player.Name}."; // Send Vicitim Notification, or "Your Death" event to the client: // create and send the client death event, GameEventYourDeath var msgYourDeath = new GameEventYourDeath(Session, $"You have {currentDeathMessage}"); var msgNumDeaths = new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.NumDeaths, NumDeaths ?? 0); var msgDeathLevel = new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.DeathLevel, DeathLevel ?? 0); var msgVitaeCpPool = new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.VitaeCpPool, VitaeCpPool.Value); var msgPurgeEnchantments = new GameEventPurgeAllEnchantments(Session); // var msgDeathSound = new GameMessageSound(Guid, Sound.Death1, 1.0f); // handle vitae var vitae = EnchantmentManager.UpdateVitae(); var spellID = (uint)Network.Enum.Spell.Vitae; var spellBase = DatManager.PortalDat.SpellTable.Spells[spellID]; var spell = DatabaseManager.World.GetCachedSpell(spellID); var vitaeEnchantment = new Enchantment(this, spellID, (double)spell.Duration, 0, spell.StatModType, vitae); var msgVitaeEnchantment = new GameEventMagicUpdateEnchantment(Session, vitaeEnchantment); var msgHealthUpdate = new GameMessagePrivateUpdateAttribute2ndLevel(this, Vital.Health, 0); // Send first death message group Session.Network.EnqueueSend(msgHealthUpdate, msgYourDeath, msgNumDeaths, msgDeathLevel, msgVitaeCpPool, msgPurgeEnchantments, msgVitaeEnchantment); // Broadcast the 019E: Player Killed GameMessage ActionBroadcastKill($"{Name} has {currentDeathMessage}", Guid, killerId); }