[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
This commit is contained in:
Alex King 2024-01-29 00:03:34 -05:00 committed by GitHub
parent 1cb72642ac
commit a1f2a21c99
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 298 additions and 190 deletions

View File

@ -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<int>(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<int>(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<std::any> 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<std::any> 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;

View File

@ -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();

View File

@ -438,7 +438,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
qGlobals = nullptr;
SetEmoteID(static_cast<uint32>(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<NPC_Emote_Struct*> 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;
}