diff --git a/zone/attack.cpp b/zone/attack.cpp index e4a72de78..a29f56c01 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2618,12 +2618,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } if (m.member) { - m.member->RecordKilledNPCEvent(this); - - if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) { - parse->EventNPC(EVENT_KILLED_MERIT, this, m.member, "killed", 0); - } - if (RuleB(NPC, EnableMeritBasedFaction)) { m.member->SetFactionLevel( m.member->CharacterID(), @@ -2683,18 +2677,11 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } } - /* Send the EVENT_KILLED_MERIT event and update kill tasks - * for all group members */ + /* Update kill tasks for all group members */ for (const auto& m : killer_group->members) { if (m && m->IsClient()) { Client* c = m->CastToClient(); - c->RecordKilledNPCEvent(this); - - if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) { - parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); - } - if (RuleB(NPC, EnableMeritBasedFaction)) { c->SetFactionLevel( c->CharacterID(), @@ -2756,13 +2743,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy } } - /* 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(), @@ -2991,6 +2971,17 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy m_combat_record.Stop(); + if (give_exp_client && !IsCorpse()) { + const auto& v = give_exp_client->GetRaidOrGroupOrSelf(true); + for (const auto& m : v) { + m->CastToClient()->RecordKilledNPCEvent(this); + + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_KILLED_MERIT)) { + parse->EventNPC(EVENT_KILLED_MERIT, this, m, "killed", 0); + } + } + } + if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) { const auto& export_string = fmt::format( "{} {} {} {} {} {} {} {} {}", diff --git a/zone/client.cpp b/zone/client.cpp index e0ec723bd..b2254d661 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -12320,3 +12320,34 @@ int Client::GetEXPPercentage() return static_cast(std::round(scaled * 100.0 / 330.0)); // unscaled pct } + +std::vector Client::GetRaidOrGroupOrSelf(bool clients_only) +{ + std::vector v; + + if (IsRaidGrouped()) { + Raid* r = GetRaid(); + + if (r) { + for (const auto& m : r->members) { + if (m.member && (!m.is_bot || !clients_only)) { + v.emplace_back(m.member); + } + } + } + } else if (IsGrouped()) { + Group* g = GetGroup(); + + if (g) { + for (const auto& m : g->members) { + if (m && (m->IsClient() || !clients_only)) { + v.emplace_back(m); + } + } + } + } else { + v.emplace_back(this); + } + + return v; +} diff --git a/zone/client.h b/zone/client.h index af0bf64ff..f86a3a167 100644 --- a/zone/client.h +++ b/zone/client.h @@ -272,6 +272,8 @@ public: int GetQuiverHaste(int delay); void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false); + std::vector GetRaidOrGroupOrSelf(bool clients_only = false); + void AI_Init(); void AI_Start(uint32 iMoveDelay = 0); void AI_Stop(); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 6886a48fb..bdba5a29b 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -3308,6 +3308,38 @@ bool Lua_Client::RemoveAlternateCurrencyValue(uint32 currency_id, uint32 amount) return self->RemoveAlternateCurrencyValue(currency_id, amount); } +luabind::object Lua_Client::GetRaidOrGroupOrSelf(lua_State* L) +{ + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = self->GetRaidOrGroupOrSelf(); + int i = 1; + for (const auto& e : l) { + t[i] = Lua_Mob(e); + i++; + } + } + + return t; +} + +luabind::object Lua_Client::GetRaidOrGroupOrSelf(lua_State* L, bool clients_only) +{ + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = self->GetRaidOrGroupOrSelf(clients_only); + int i = 1; + for (const auto& e : l) { + t[i] = Lua_Mob(e); + i++; + } + } + + return t; +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -3542,6 +3574,8 @@ luabind::scope lua_register_client() { .def("GetRaceBitmask", (int(Lua_Client::*)(void))&Lua_Client::GetRaceBitmask) .def("GetRadiantCrystals", (uint32(Lua_Client::*)(void))&Lua_Client::GetRadiantCrystals) .def("GetRaid", (Lua_Raid(Lua_Client::*)(void))&Lua_Client::GetRaid) + .def("GetRaidOrGroupOrSelf", (luabind::object(Lua_Client::*)(lua_State*))&Lua_Client::GetRaidOrGroupOrSelf) + .def("GetRaidOrGroupOrSelf", (luabind::object(Lua_Client::*)(lua_State*,bool))&Lua_Client::GetRaidOrGroupOrSelf) .def("GetRaidPoints", (uint32(Lua_Client::*)(void))&Lua_Client::GetRaidPoints) .def("GetRaceAbbreviation", (std::string(Lua_Client::*)(void))&Lua_Client::GetRaceAbbreviation) .def("GetRawItemAC", (int(Lua_Client::*)(void))&Lua_Client::GetRawItemAC) diff --git a/zone/lua_client.h b/zone/lua_client.h index 6a249924e..2c916a128 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -496,6 +496,8 @@ public: int GetAAEXPPercentage(); int GetEXPPercentage(); bool IsInAGuild(); + luabind::object GetRaidOrGroupOrSelf(lua_State* L); + luabind::object GetRaidOrGroupOrSelf(lua_State* L, bool clients_only); void ApplySpell(int spell_id); void ApplySpell(int spell_id, int duration); diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 512849b23..1b2490624 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -3311,7 +3311,7 @@ luabind::object Lua_Mob::GetBuffs(lua_State* L) { auto l = self->GetBuffs(); int i = 1; for (int slot_id = 0; slot_id < self->GetMaxBuffSlots(); slot_id++) { - t[i] = l[slot_id]; + t[i] = Lua_Buff(&l[slot_id]); i++; } } diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 708d89a03..607946dce 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3113,6 +3113,36 @@ bool Perl_Client_RemoveAlternateCurrencyValue(Client* self, uint32 currency_id, return self->RemoveAlternateCurrencyValue(currency_id, amount); } +perl::array Perl_Client_GetRaidOrGroupOrSelf(Client* self) +{ + perl::array result; + + const auto& l = self->GetRaidOrGroupOrSelf(); + + result.reserve(l.size()); + + for (const auto& e : l) { + result.push_back(e); + } + + return result; +} + +perl::array Perl_Client_GetRaidOrGroupOrSelf(Client* self, bool clients_only) +{ + perl::array result; + + const auto& l = self->GetRaidOrGroupOrSelf(clients_only); + + result.reserve(l.size()); + + for (const auto& e : l) { + result.push_back(e); + } + + return result; +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3346,6 +3376,8 @@ void perl_register_client() package.add("GetRaceBitmask", &Perl_Client_GetRaceBitmask); package.add("GetRadiantCrystals", &Perl_Client_GetRadiantCrystals); package.add("GetRaid", &Perl_Client_GetRaid); + package.add("GetRaidOrGroupOrSelf", (perl::array(*)(Client*))&Perl_Client_GetRaidOrGroupOrSelf); + package.add("GetRaidOrGroupOrSelf", (perl::array(*)(Client*, bool))&Perl_Client_GetRaidOrGroupOrSelf); package.add("GetRaidPoints", &Perl_Client_GetRaidPoints); package.add("GetRawItemAC", &Perl_Client_GetRawItemAC); package.add("GetRawSkill", &Perl_Client_GetRawSkill);