/// <summary> /// Broadcasts the player death animation, updates vitae, and sends network messages for player death /// Queues the action to call TeleportOnDeath and enter portal space soon /// </summary> protected override void Die(WorldObject lastDamager, WorldObject topDamager) { UpdateVital(Health, 0); NumDeaths++; DeathLevel = Level; // for calculating vitae XP VitaeCpPool = 0; // reset vitae XP earned // killer = top damager for looting rights if (topDamager != null) { Killer = topDamager.Guid.Full; } // broadcast death animation var deathAnim = new Motion(MotionStance.NonCombat, MotionCommand.Dead); EnqueueBroadcastMotion(deathAnim); // killer death message = last damager var killerMsg = lastDamager != null ? " to " + lastDamager.Name : ""; var currentDeathMessage = $"died{killerMsg}."; // create network messages for player death var msgHealthUpdate = new GameMessagePrivateUpdateAttribute2ndLevel(this, Vital.Health, 0); // TODO: death sounds? seems to play automatically in client // var msgDeathSound = new GameMessageSound(Guid, Sound.Death1, 1.0f); 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 GameEventMagicPurgeEnchantments(Session); // update vitae var vitae = EnchantmentManager.UpdateVitae(); var spellID = (uint)SpellId.Vitae; var spell = new Spell(spellID); var vitaeEnchantment = new Enchantment(this, Guid, spellID, spell.Duration, 0, (EnchantmentMask)spell.StatModType, vitae); var msgVitaeEnchantment = new GameEventMagicUpdateEnchantment(Session, vitaeEnchantment); // send network messages for player death Session.Network.EnqueueSend(msgHealthUpdate, msgNumDeaths, msgDeathLevel, msgVitaeCpPool, msgPurgeEnchantments, msgVitaeEnchantment); // wait for the death animation to finish var dieChain = new ActionChain(); var animLength = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId).GetAnimationLength(MotionCommand.Dead); dieChain.AddDelaySeconds(animLength + 1.0f); // enter portal space dieChain.AddAction(this, CreateCorpse); dieChain.AddAction(this, TeleportOnDeath); dieChain.EnqueueChain(); }
/// <summary> /// Inflicts vitae /// </summary> public void InflictVitaePenalty(int amount = 5) { DeathLevel = Level; // for calculating vitae XP VitaeCpPool = 0; // reset vitae XP earned var msgDeathLevel = new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.DeathLevel, DeathLevel ?? 0); var msgVitaeCpPool = new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.VitaeCpPool, VitaeCpPool.Value); Session.Network.EnqueueSend(msgDeathLevel, msgVitaeCpPool); var vitae = EnchantmentManager.UpdateVitae(); var spellID = (uint)SpellId.Vitae; var spell = new Spell(spellID); var vitaeEnchantment = new Enchantment(this, Guid.Full, spellID, 0, (EnchantmentMask)spell.StatModType, vitae); Session.Network.EnqueueSend(new GameEventMagicUpdateEnchantment(Session, vitaeEnchantment)); }
/// <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); }
/// <summary> /// Broadcasts the player death animation, updates vitae, and sends network messages for player death /// Queues the action to call TeleportOnDeath and enter portal space soon /// </summary> protected override void Die(WorldObject lastDamager, WorldObject topDamager) { UpdateVital(Health, 0); NumDeaths++; DeathLevel = Level; // for calculating vitae XP VitaeCpPool = 0; // reset vitae XP earned // killer = top damager for looting rights if (topDamager != null) { Killer = topDamager.Guid.Full; } // broadcast death animation var deathAnim = new UniversalMotion(MotionStance.NonCombat, new MotionItem(MotionCommand.Dead)); EnqueueBroadcastMotion(deathAnim); // killer death message = last damager var killerMsg = lastDamager != null ? " to " + lastDamager.Name : ""; var currentDeathMessage = $"died{killerMsg}."; // create network messages for player death var msgHealthUpdate = new GameMessagePrivateUpdateAttribute2ndLevel(this, Vital.Health, 0); // TODO: death sounds? seems to play automatically in client // var msgDeathSound = new GameMessageSound(Guid, Sound.Death1, 1.0f); 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); // update 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, Guid, spellID, (double)spell.Duration, 0, spell.StatModType, vitae); var msgVitaeEnchantment = new GameEventMagicUpdateEnchantment(Session, vitaeEnchantment); // send network messages for player death Session.Network.EnqueueSend(msgHealthUpdate, msgYourDeath, msgNumDeaths, msgDeathLevel, msgVitaeCpPool, msgPurgeEnchantments, msgVitaeEnchantment); // wait for the death animation to finish var dieChain = new ActionChain(); var animLength = DatManager.PortalDat.ReadFromDat <MotionTable>(MotionTableId).GetAnimationLength(MotionCommand.Dead); dieChain.AddDelaySeconds(animLength + 1.0f); // enter portal space dieChain.AddAction(this, CreateCorpse); dieChain.AddAction(this, TeleportOnDeath); dieChain.EnqueueChain(); // if the player's lifestone is in a different landblock, also broadcast their demise to that landblock if (Sanctuary != null && Location.Landblock != Sanctuary.Landblock) { var killerGuid = lastDamager != null ? lastDamager.Guid : Guid; ActionBroadcastKill($"{Name} has {currentDeathMessage}", Guid, killerGuid); } DamageHistory.Reset(); }