From a1f2a21c99596e3b2439b6b7110a6eb96eb9358d Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 29 Jan 2024 00:03:34 -0500 Subject: [PATCH] [Bug Fix] Fix NPC After Death Emotes (#4021) * [Bug Fix] Fix NPC After Death Emotes - `DoNPCEmote` was being called on the corpse, not the NPC, so it wasn't working for some reason despite it working for years. - Cleaned up some other logic and variable names in `NPC::Death` while I was in there. * Update attack.cpp * Update npc.cpp * Update attack.cpp * Update attack.cpp --- zone/attack.cpp | 468 ++++++++++++++++++++++++++++++------------------ zone/mob_ai.cpp | 5 +- zone/npc.cpp | 15 +- 3 files changed, 298 insertions(+), 190 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 108851fd1..5472710fd 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1818,9 +1818,8 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); } - const uint32 emote_id = killerMob->GetEmoteID(); - if (emote_id) { - killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emote_id, this); + if (emoteid) { + killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid, this); } killerMob->TrySpellOnKill(killed_level, spell); @@ -2376,10 +2375,15 @@ void NPC::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::SkillTyp bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillType attack_skill) { - LogCombat("Fatal blow dealt by [{}] with [{}] damage, spell [{}], skill [{}]", - ((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill); + LogCombat( + "Fatal blow dealt by [{}] with [{}] damage, spell [{}], skill [{}]", + (killer_mob ? killer_mob->GetName() : "[nullptr]"), + damage, + spell, + attack_skill + ); - Mob *oos = killer_mob ? killer_mob->GetOwnerOrSelf() : nullptr; + Mob* owner_or_self = killer_mob ? killer_mob->GetOwnerOrSelf() : nullptr; if (IsNPC()) { if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH)) { @@ -2391,7 +2395,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy static_cast(attack_skill) ); - if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) { + if (parse->EventNPC(EVENT_DEATH, this, owner_or_self, export_string, 0) != 0) { if (GetHP() < 0) { SetHP(0); } @@ -2408,7 +2412,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy spell, static_cast(attack_skill) ); - if (parse->EventBot(EVENT_DEATH, CastToBot(), oos, export_string, 0) != 0) { + if (parse->EventBot(EVENT_DEATH, CastToBot(), owner_or_self, export_string, 0) != 0) { if (GetHP() < 0) { SetHP(0); } @@ -2435,7 +2439,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy if (IsEngaged()) { zone->DelAggroMob(); - Log(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount()); + LogAttackDetail("{} Mob{} currently aggroed.", zone->MobsAggroCount(), zone->MobsAggroCount() != 1 ? "s" : ""); } ShieldAbilityClearVariables(); @@ -2444,45 +2448,52 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy SetPet(0); if (GetSwarmOwner()) { - auto* owner = entity_list.GetMobID(GetSwarmOwner()); + Mob* owner = entity_list.GetMobID(GetSwarmOwner()); if (owner) { owner->SetTempPetCount(owner->GetTempPetCount() - 1); } } - auto* killer = GetHateDamageTop(this); - entity_list.RemoveFromTargets(this, p_depop); if (p_depop) { return false; } - const auto illusion_spell_id = spellbonuses.Illusion; + const int illusion_spell_id = spellbonuses.Illusion; HasAISpellEffects = false; + BuffFadeAll(); - const auto killed_level = GetLevel(); + + const uint8 killed_level = GetLevel(); if (GetClass() == Class::LDoNTreasure) { // open chest auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); - Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; - anim->spawnid = GetID(); - anim->action = 0x0F; - anim->speed = 10; + + auto a = (Animation_Struct*) outapp->pBuffer; + + a->spawnid = GetID(); + a->action = 0x0F; + a->speed = 10; + entity_list.QueueCloseClients(this, outapp); safe_delete(outapp); } auto app = new EQApplicationPacket(OP_Death, sizeof(Death_Struct)); - auto* d = (Death_Struct*) app->pBuffer; - d->spawn_id = GetID(); - d->killer_id = killer_mob ? killer_mob->GetID() : 0; - d->bindzoneid = 0; - d->spell_id = 0xffffffff; // Sending spell was causing extra DoT land msg + + auto d = (Death_Struct*) app->pBuffer; + + d->spawn_id = GetID(); + d->killer_id = killer_mob ? killer_mob->GetID() : 0; + d->bindzoneid = 0; + d->spell_id = UINT32_MAX; d->attack_skill = SkillDamageTypes[attack_skill]; - d->damage = damage; + d->damage = damage; + app->priority = 6; + entity_list.QueueClients(killer_mob, app, false); safe_delete(app); @@ -2495,24 +2506,37 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy hate_list.AddEntToHateList(killer_mob, damage); } - Mob *give_exp = hate_list.GetDamageTopOnHateList(this); + Mob* give_exp = hate_list.GetDamageTopOnHateList(this); if (give_exp) { - give_exp = killer; + give_exp = killer_mob; } if (give_exp && give_exp->HasOwner()) { - bool ownerInGroup = false; - if ((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner())) - || (give_exp->IsPet() && (give_exp->GetOwner()->IsClient() - || (give_exp->GetOwner()->HasGroup() && give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner())))) - ) { - ownerInGroup = true; + bool owner_in_group = false; + + if ( + ( + give_exp->HasGroup() && + give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner()) + ) || + ( + give_exp->IsPet() && + ( + give_exp->GetOwner()->IsClient() || + ( + give_exp->GetOwner()->HasGroup() && + give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner()) + ) + ) + ) + ) { + owner_in_group = true; } give_exp = give_exp->GetUltimateOwner(); - if (!RuleB(Bots, BotGroupXP) && !ownerInGroup) { + if (!RuleB(Bots, BotGroupXP) && !owner_in_group) { give_exp = nullptr; } } @@ -2526,9 +2550,9 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } } - int PlayerCount = 0; // QueryServ Player Counting + int player_count = 0; // QueryServ Player Counting - Client *give_exp_client = nullptr; + Client* give_exp_client = nullptr; if (give_exp && give_exp->IsClient()) { give_exp_client = give_exp->CastToClient(); } @@ -2538,13 +2562,13 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy hate_list.DoFactionHits(GetNPCFactionID(), GetPrimaryFaction(), GetFactionAmount()); } - bool IsLdonTreasure = (GetClass() == Class::LDoNTreasure); + const bool is_ldon_treasure = GetClass() == Class::LDoNTreasure; if (give_exp_client && !IsCorpse()) { - Group *kg = entity_list.GetGroupByClient(give_exp_client); - Raid *kr = entity_list.GetRaidByClient(give_exp_client); + Group* killer_group = entity_list.GetGroupByClient(give_exp_client); + Raid* killer_raid = entity_list.GetRaidByClient(give_exp_client); - int64 finalxp = give_exp_client->GetExperienceForKill(this); + int64 final_exp = give_exp_client->GetExperienceForKill(this); // handle task credit on behalf of the killer if (RuleB(TaskSystem, EnableTaskSystem)) { @@ -2556,75 +2580,98 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy task_manager->HandleUpdateTasksOnKill(give_exp_client, this); } - if (kr) { - if (!IsLdonTreasure && MerchantType == 0) { - kr->SplitExp((finalxp), this); - if (killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName()))) + if (killer_raid) { + if (!is_ldon_treasure && MerchantType == 0) { + killer_raid->SplitExp(final_exp, this); + + if ( + killer_mob && + ( + killer_raid->IsRaidMember(killer_mob->GetName()) || + killer_raid->IsRaidMember(killer_mob->GetUltimateOwner()->GetName()) + ) + ) { killer_mob->TrySpellOnKill(killed_level, spell); + } } /* Send the EVENT_KILLED_MERIT event for all raid members */ - for (const auto& m : kr->members) { + for (const auto& m : killer_raid->members) { if (m.is_bot) { continue; } - if (m.member && m.member->IsClient()) { // If Group Member is Client - Client *c = m.member; + if (m.member) { + m.member->RecordKilledNPCEvent(this); - c->RecordKilledNPCEvent(this); if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) { - parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); + parse->EventNPC(EVENT_KILLED_MERIT, this, m.member, "killed", 0); } if (RuleB(NPC, EnableMeritBasedFaction)) { - c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); + m.member->SetFactionLevel( + m.member->CharacterID(), + GetNPCFactionID(), + m.member->GetBaseClass(), + m.member->GetBaseRace(), + m.member->GetDeity() + ); } - PlayerCount++; + player_count++; } } // QueryServ Logging - Raid Kills if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = - new ServerPacket(ServerOP_QSPlayerLogNPCKills, - sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); - PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; - QS->s1.NPCID = GetNPCTypeID(); + auto pack = new ServerPacket( + ServerOP_QSPlayerLogNPCKills, + sizeof(QSPlayerLogNPCKill_Struct) + + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * player_count) + ); + + player_count = 0; + + auto QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; + + QS->s1.NPCID = GetNPCTypeID(); QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 2; // Raid Fight - for (const auto& m : kr->members) { + QS->s1.Type = 2; // Raid Fight + + for (const auto& m : killer_raid->members) { if (m.is_bot) { continue; } - if (m.member && m.member->IsClient()) { // If Group Member is Client - Client *c = m.member; - QS->Chars[PlayerCount].char_id = c->CharacterID(); - PlayerCount++; + if (m.member && m.member->IsClient()) { + QS->Chars[player_count].char_id = m.member->CastToClient()->CharacterID(); + player_count++; } } - worldserver.SendPacket(pack); // Send Packet to World + + worldserver.SendPacket(pack); safe_delete(pack); } - // End QueryServ Logging + } else if (give_exp_client->IsGrouped() && killer_group) { + if (!is_ldon_treasure && MerchantType == 0) { + killer_group->SplitExp(final_exp, this); - } - else if (give_exp_client->IsGrouped() && kg != nullptr) { - if (!IsLdonTreasure && MerchantType == 0) { - kg->SplitExp((finalxp), this); - if (killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName()))) + if ( + killer_mob && + ( + killer_group->IsGroupMember(killer_mob->GetName()) || + killer_group->IsGroupMember(killer_mob->GetUltimateOwner()->GetName()) + ) + ) { killer_mob->TrySpellOnKill(killed_level, spell); + } } /* Send the EVENT_KILLED_MERIT event and update kill tasks * for all group members */ - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client - Client *c = kg->members[i]->CastToClient(); + for (const auto& m : killer_group->members) { + if (m && m->IsClient()) { + Client* c = m->CastToClient(); c->RecordKilledNPCEvent(this); @@ -2632,70 +2679,101 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); } - if (RuleB(NPC, EnableMeritBasedFaction)) - c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); + if (RuleB(NPC, EnableMeritBasedFaction)) { + c->SetFactionLevel( + c->CharacterID(), + GetNPCFactionID(), + c->GetBaseClass(), + c->GetBaseRace(), + c->GetDeity() + ); + } - PlayerCount++; + player_count++; } } // QueryServ Logging - Group Kills if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = - new ServerPacket(ServerOP_QSPlayerLogNPCKills, - sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); - PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; - QS->s1.NPCID = GetNPCTypeID(); + auto pack = new ServerPacket( + ServerOP_QSPlayerLogNPCKills, + sizeof(QSPlayerLogNPCKill_Struct) + + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * player_count) + ); + + player_count = 0; + + auto QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; + + QS->s1.NPCID = GetNPCTypeID(); QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 1; // Group Fight - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client - Client *c = kg->members[i]->CastToClient(); - QS->Chars[PlayerCount].char_id = c->CharacterID(); - PlayerCount++; + QS->s1.Type = 1; // Group Fight + + for (const auto& m : killer_group->members) { + if (m && m->IsClient()) { + QS->Chars[player_count].char_id = m->CastToClient()->CharacterID(); + player_count++; } } - worldserver.SendPacket(pack); // Send Packet to World + + worldserver.SendPacket(pack); safe_delete(pack); } - // End QueryServ Logging - } - else { - if (!IsLdonTreasure && MerchantType == 0) { - int conlevel = give_exp->GetLevelCon(GetLevel()); - if (conlevel != CON_GRAY) { + } else { + if (!is_ldon_treasure && !MerchantType) { + const uint32 con_level = give_exp->GetLevelCon(GetLevel()); + + if (con_level != CON_GRAY) { if (!GetOwner() || (GetOwner() && !GetOwner()->IsClient())) { - give_exp_client->AddEXP((finalxp), conlevel); - if (killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) + give_exp_client->AddEXP(final_exp, con_level); + + if ( + killer_mob && + ( + killer_mob->GetID() == give_exp_client->GetID() || + killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID() + ) + ) { killer_mob->TrySpellOnKill(killed_level, spell); + } } } } /* Send the EVENT_KILLED_MERIT event */ give_exp_client->RecordKilledNPCEvent(this); + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) { parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); } - if (RuleB(NPC, EnableMeritBasedFaction)) - give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(), - give_exp_client->GetBaseRace(), give_exp_client->GetDeity()); + if (RuleB(NPC, EnableMeritBasedFaction)) { + give_exp_client->SetFactionLevel( + give_exp_client->CharacterID(), + GetNPCFactionID(), + give_exp_client->GetBaseClass(), + give_exp_client->GetBaseRace(), + give_exp_client->GetDeity() + ); + } // QueryServ Logging - Solo if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, + auto pack = new ServerPacket( + ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; - QS->s1.NPCID = GetNPCTypeID(); - QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 0; // Solo Fight - Client *c = give_exp_client; - QS->Chars[0].char_id = c->CharacterID(); - PlayerCount++; + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1) + ); + + auto QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; + + QS->s1.NPCID = GetNPCTypeID(); + QS->s1.ZoneID = GetZoneID(); + QS->s1.Type = 0; // Solo Fight + QS->Chars[0].char_id = give_exp_client->CharacterID(); + + player_count++; + worldserver.SendPacket(pack); // Send Packet to World safe_delete(pack); } @@ -2703,32 +2781,68 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } } - bool allow_merchant_corpse = RuleB(Merchant, AllowCorpse); - bool is_merchant = (class_ == Class::Merchant || class_ == Class::AdventureMerchant || MerchantType != 0); + const bool allow_merchant_corpse = RuleB(Merchant, AllowCorpse); + const bool is_merchant = (class_ == Class::Merchant || class_ == Class::AdventureMerchant || MerchantType != 0); Corpse* corpse = nullptr; const uint16 entity_id = GetID(); - if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) && - ((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || - (killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient()))) - || (killer_mob && IsLdonTreasure))) - { - if (killer != 0) { - if (killer->GetOwner() != 0 && killer->GetOwner()->IsClient()) - killer = killer->GetOwner(); + if ( + !HasOwner() && + !IsMerc() && + !GetSwarmInfo() && + (!is_merchant || allow_merchant_corpse) && + ( + ( + killer_mob && + ( + killer_mob->IsClient() || + ( + killer_mob->HasOwner() && + killer_mob->GetUltimateOwner()->IsClient() + ) || + ( + killer_mob->IsNPC() && + killer_mob->CastToNPC()->GetSwarmInfo() && + killer_mob->CastToNPC()->GetSwarmInfo()->GetOwner() && + killer_mob->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient() + ) + ) + ) || + ( + killer_mob && is_ldon_treasure + ) + ) + ) { + if (killer_mob) { + if (killer_mob->GetOwner() != 0 && killer_mob->GetOwner()->IsClient()) { + killer_mob = killer_mob->GetOwner(); + } - if (killer->IsClient() && !killer->CastToClient()->GetGM()) - CheckTrivialMinMaxLevelDrop(killer); + if (killer_mob->IsClient() && !killer_mob->CastToClient()->GetGM()) { + CheckTrivialMinMaxLevelDrop(killer_mob); + } } entity_list.RemoveFromAutoXTargets(this); - const uint32 emote_id = GetEmoteID(); - corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata, - level > 54 ? RuleI(NPC, MajorNPCCorpseDecayTimeMS) - : RuleI(NPC, MinorNPCCorpseDecayTimeMS)); + corpse = new Corpse( + this, + &itemlist, + GetNPCTypeID(), + &NPCTypedata, + ( + level > 54 ? + RuleI(NPC, MajorNPCCorpseDecayTimeMS) : + RuleI(NPC, MinorNPCCorpseDecayTimeMS) + ) + ); + + if (killer_mob && emoteid) { + DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid, killer_mob); + } + entity_list.LimitRemoveNPC(this); entity_list.AddCorpse(corpse, GetID()); @@ -2740,25 +2854,27 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy SetID(0); ApplyIllusionToCorpse(illusion_spell_id, corpse); - if (killer != 0 && emote_id) - corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emote_id, killer); - if (killer != 0 && killer->IsClient()) { - corpse->AllowPlayerLoot(killer, 0); - if (killer->IsGrouped()) { - Group* group = entity_list.GetGroupByClient(killer->CastToClient()); - if (group != 0) { - for (int i = 0; i<6; i++) { // Doesnt work right, needs work - if (group->members[i] != nullptr) { - corpse->AllowPlayerLoot(group->members[i], i); + if (killer_mob && killer_mob->IsClient()) { + corpse->AllowPlayerLoot(killer_mob, 0); + if (killer_mob->IsGrouped()) { + Group* g = entity_list.GetGroupByClient(killer_mob->CastToClient()); + if (g) { + uint8 slot_id = 0; + + for (const auto &m : g->members) { + if (m) { + corpse->AllowPlayerLoot(m, slot_id); } + + slot_id++; } } - } - else if (killer->IsRaidGrouped()) { - Raid* r = entity_list.GetRaidByClient(killer->CastToClient()); + } else if (killer_mob->IsRaidGrouped()) { + Raid* r = entity_list.GetRaidByClient(killer_mob->CastToClient()); if (r) { - int i = 0; - for (const auto& m : r->members) { + uint8 slot_id = 0; + + for (const auto &m : r->members) { if (m.is_bot) { continue; } @@ -2766,77 +2882,71 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy switch (r->GetLootType()) { case RaidLootType::LeaderOnly: if (m.member && m.is_raid_leader) { - corpse->AllowPlayerLoot(m.member, i); - i++; + corpse->AllowPlayerLoot(m.member, slot_id); + slot_id++; } break; case RaidLootType::LeaderAndGroupLeadersOnly: if (m.member && (m.is_raid_leader || m.is_group_leader)) { - corpse->AllowPlayerLoot(m.member, i); - i++; + corpse->AllowPlayerLoot(m.member, slot_id); + slot_id++; } break; case RaidLootType::LeaderSelected: if (m.member && m.is_looter) { - corpse->AllowPlayerLoot(m.member, i); - i++; + corpse->AllowPlayerLoot(m.member, slot_id); + slot_id++; } break; case RaidLootType::EntireRaid: default: if (m.member) { - corpse->AllowPlayerLoot(m.member, i); - i++; + corpse->AllowPlayerLoot(m.member, slot_id); + slot_id++; } break; } } } } - } - else if (killer_mob && IsLdonTreasure) { - auto u_owner = killer_mob->GetUltimateOwner(); - if (u_owner->IsClient()) - corpse->AllowPlayerLoot(u_owner, 0); + } else if (killer_mob && is_ldon_treasure) { + Mob* ultimate_owner = killer_mob->GetUltimateOwner(); + if (ultimate_owner->IsClient()) { + corpse->AllowPlayerLoot(ultimate_owner, 0); + } } if (zone && zone->adv_data) { - ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; + auto sr = (ServerZoneAdventureDataReply_Struct *) zone->adv_data; if (sr->type == Adventure_Kill) { zone->DoAdventureCountIncrease(); - } - else if (sr->type == Adventure_Assassinate) { + } else if (sr->type == Adventure_Assassinate) { if (sr->data_id == GetNPCTypeID()) { zone->DoAdventureCountIncrease(); - } - else { + } else { zone->DoAdventureAssassinationCountIncrease(); } } } - } - else { + } else { entity_list.RemoveFromXTargets(this); } - - // Parse quests even if we're killed by an NPC - if (oos) { - if (IsNPC()) { - const uint32 emote_id = GetEmoteID(); - if (emote_id) { - DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emote_id, killer_mob); - } + if (IsNPC()) { + if (emoteid) { + DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid, killer_mob); } + } - if (oos->IsNPC()) { - if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) { - parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); + if (owner_or_self) { + if (owner_or_self->IsNPC()) { + if (parse->HasQuestSub(owner_or_self->GetNPCTypeID(), EVENT_NPC_SLAY)) { + parse->EventNPC(EVENT_NPC_SLAY, owner_or_self->CastToNPC(), this, "", 0); } - const uint32 emote_id = oos->GetEmoteID(); + const uint32 emote_id = owner_or_self->GetEmoteID(); if (emote_id) { - oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id, this); + owner_or_self->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id, this); } if (killer_mob) { @@ -2854,10 +2964,12 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } WipeHateList(); + p_depop = true; - if (killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted - killer_mob->SetTarget(nullptr); //via AE effects and such.. + if (killer_mob && killer_mob->GetTarget() == this) { // We can kill things without having them targeted + killer_mob->SetTarget(nullptr); + } entity_list.UpdateFindableNPCState(this, true); @@ -2875,7 +2987,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy std::vector args = { corpse }; - parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args); + parse->EventNPC(EVENT_DEATH_COMPLETE, this, owner_or_self, export_string, 0, &args); } // Zone controller process EVENT_DEATH_ZONE (Death events) @@ -2891,7 +3003,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy std::vector args = { corpse, this }; - DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args); + DispatchZoneControllerEvent(EVENT_DEATH_ZONE, owner_or_self, export_string, 0, &args); } return true; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index af7d48768..30c97d3d0 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1800,9 +1800,8 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help) parse->EventNPC(EVENT_COMBAT, CastToNPC(), attacker, "1", 0); } - const uint32 emote_id = GetEmoteID(); - if (emote_id) { - CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::EnterCombat, emote_id, attacker); + if (emoteid) { + CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::EnterCombat, emoteid, attacker); } std::string mob_name = GetCleanName(); diff --git a/zone/npc.cpp b/zone/npc.cpp index abfdbceea..36716d9f5 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -438,7 +438,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi qGlobals = nullptr; - SetEmoteID(static_cast(npc_type_data->emoteid)); + SetEmoteID(npc_type_data->emoteid); InitializeBuffSlots(); CalcBonuses(); @@ -1113,9 +1113,8 @@ void NPC::UpdateEquipmentLight() } void NPC::Depop(bool start_spawn_timer) { - const uint32 emote_id = GetEmoteID(); - if (emote_id) { - DoNPCEmote(EQ::constants::EmoteEventTypes::OnDespawn, emote_id); + if (emoteid) { + DoNPCEmote(EQ::constants::EmoteEventTypes::OnDespawn, emoteid); } if (IsNPC()) { @@ -3073,10 +3072,8 @@ void NPC::SendPayload(int payload_id, std::string payload_value) NPC_Emote_Struct* NPC::GetNPCEmote(uint32 emote_id, uint8 event_) { std::vector emotes; - for (const auto &e : zone->npc_emote_list) { - auto nes = e; - - if (nes->emoteid == emote_id && nes->event_ == event_) { + for (auto& e : zone->npc_emote_list) { + if (e->emoteid == emote_id && e->event_ == event_) { emotes.emplace_back(e); } } @@ -3098,7 +3095,7 @@ void NPC::DoNPCEmote(uint8 event_, uint32 emote_id, Mob* t) return; } - auto e = GetNPCEmote(emote_id, event_); + const auto& e = GetNPCEmote(emote_id, event_); if (!e) { return; }