diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 498780e1f..1e655a6bc 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1462,12 +1462,12 @@ bool Corpse::HasItem(uint32 item_id) { for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) { ServerLootItem_Struct* loot_item = *current_item; if (!loot_item) { - LogError("NPC::CountItem() - ItemList error, null item"); + LogError("Corpse::HasItem() - ItemList error, null item"); continue; } if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) { - LogError("NPC::CountItem() - Database error, invalid item"); + LogError("Corpse::HasItem() - Database error, invalid item"); continue; } @@ -1487,12 +1487,12 @@ uint16 Corpse::CountItem(uint32 item_id) { for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) { ServerLootItem_Struct* loot_item = *current_item; if (!loot_item) { - LogError("NPC::CountItem() - ItemList error, null item"); + LogError("Corpse::CountItem() - ItemList error, null item"); continue; } if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) { - LogError("NPC::CountItem() - Database error, invalid item"); + LogError("Corpse::CountItem() - Database error, invalid item"); continue; } @@ -1747,3 +1747,21 @@ bool Corpse::MovePlayerCorpseToNonInstance() return false; } + +std::vector Corpse::GetLootList() { + std::vector corpse_items; + for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) { + ServerLootItem_Struct* loot_item = *current_item; + if (!loot_item) { + LogError("Corpse::GetLootList() - ItemList error, null item"); + continue; + } + + if (std::find(corpse_items.begin(), corpse_items.end(), loot_item->item_id) != corpse_items.end()) { + continue; + } + + corpse_items.push_back(loot_item->item_id); + } + return corpse_items; +} diff --git a/zone/corpse.h b/zone/corpse.h index 80d3b4e8f..acbd63ac5 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -117,6 +117,7 @@ class Corpse : public Mob { uint16 CountItem(uint32 item_id); uint32 GetItemIDBySlot(uint16 loot_slot); uint16 GetFirstSlotByItemID(uint32 item_id); + std::vector GetLootList(); void LootItem(Client* client, const EQApplicationPacket* app); void EndLoot(Client* client, const EQApplicationPacket* app); void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app); diff --git a/zone/lua_corpse.cpp b/zone/lua_corpse.cpp index 85e4150f7..200e13ce3 100644 --- a/zone/lua_corpse.cpp +++ b/zone/lua_corpse.cpp @@ -2,11 +2,16 @@ #include "lua.hpp" #include +#include #include "corpse.h" #include "lua_corpse.h" #include "lua_client.h" +struct Lua_Corpse_Loot_List { + std::vector entries; +}; + uint32 Lua_Corpse::GetCharID() { Lua_Safe_Call_Int(); return self->GetCharID(); @@ -172,6 +177,18 @@ uint16 Lua_Corpse::GetFirstSlotByItemID(uint32 item_id) { return self->GetFirstSlotByItemID(item_id); } +Lua_Corpse_Loot_List Lua_Corpse::GetLootList(lua_State* L) { + Lua_Safe_Call_Class(Lua_Corpse_Loot_List); + Lua_Corpse_Loot_List ret; + auto loot_list = self->GetLootList(); + + for (auto item_id : loot_list) { + ret.entries.push_back(item_id); + } + + return ret; +} + luabind::scope lua_register_corpse() { return luabind::class_("Corpse") .def(luabind::constructor<>()) @@ -209,7 +226,13 @@ luabind::scope lua_register_corpse() { .def("HasItem", (bool(Lua_Corpse::*)(uint32))&Lua_Corpse::HasItem) .def("CountItem", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem) .def("GetItemIDBySlot", (uint32(Lua_Corpse::*)(uint16))&Lua_Corpse::GetItemIDBySlot) - .def("GetFirstSlotByItemID", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::GetFirstSlotByItemID); + .def("GetFirstSlotByItemID", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::GetFirstSlotByItemID) + .def("GetLootList", (Lua_Corpse_Loot_List(Lua_Corpse::*)(lua_State* L))&Lua_Corpse::GetLootList); +} + +luabind::scope lua_register_corpse_loot_list() { + return luabind::class_("CorpseLootList") + .def_readwrite("entries", &Lua_Corpse_Loot_List::entries, luabind::return_stl_iterator); } #endif diff --git a/zone/lua_corpse.h b/zone/lua_corpse.h index 679fe4948..c8c9bf470 100644 --- a/zone/lua_corpse.h +++ b/zone/lua_corpse.h @@ -6,12 +6,14 @@ class Corpse; class Lua_Client; +struct Lua_Corpse_Loot_List; namespace luabind { struct scope; } luabind::scope lua_register_corpse(); +luabind::scope lua_register_corpse_loot_list(); class Lua_Corpse : public Lua_Mob { @@ -58,6 +60,7 @@ public: uint16 CountItem(uint32 item_id); uint32 GetItemIDBySlot(uint16 loot_slot); uint16 GetFirstSlotByItemID(uint32 item_id); + Lua_Corpse_Loot_List GetLootList(lua_State* L); }; #endif diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index c8bc012c9..8d9fe87ed 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -2,11 +2,16 @@ #include "lua.hpp" #include +#include #include "npc.h" #include "lua_npc.h" #include "lua_client.h" +struct Lua_NPC_Loot_List { + std::vector entries; +}; + void Lua_NPC::Signal(int id) { Lua_Safe_Call_Void(); self->SignalNPC(id); @@ -618,6 +623,18 @@ float Lua_NPC::GetSpellScale() return self->GetSpellScale(); } +Lua_NPC_Loot_List Lua_NPC::GetLootList(lua_State* L) { + Lua_Safe_Call_Class(Lua_NPC_Loot_List); + Lua_NPC_Loot_List ret; + auto loot_list = self->GetLootList(); + + for (auto item_id : loot_list) { + ret.entries.push_back(item_id); + } + + return ret; +} + luabind::scope lua_register_npc() { return luabind::class_("NPC") .def(luabind::constructor<>()) @@ -740,7 +757,13 @@ luabind::scope lua_register_npc() { .def("GetItemIDBySlot", (uint32(Lua_NPC::*)(uint16))&Lua_NPC::GetItemIDBySlot) .def("GetFirstSlotByItemID", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::GetFirstSlotByItemID) .def("GetHealScale", (float(Lua_NPC::*)(void))&Lua_NPC::GetHealScale) - .def("GetSpellScale", (float(Lua_NPC::*)(void))&Lua_NPC::GetSpellScale); + .def("GetSpellScale", (float(Lua_NPC::*)(void))&Lua_NPC::GetSpellScale) + .def("GetLootList", (Lua_NPC_Loot_List(Lua_NPC::*)(lua_State* L))&Lua_NPC::GetLootList); +} + +luabind::scope lua_register_npc_loot_list() { + return luabind::class_("NPCLootList") + .def_readwrite("entries", &Lua_NPC_Loot_List::entries, luabind::return_stl_iterator); } #endif diff --git a/zone/lua_npc.h b/zone/lua_npc.h index 1577a1e20..6c329907b 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -8,12 +8,14 @@ class NPC; class Lua_Mob; class Lua_NPC; class Lua_Client; +struct Lua_NPC_Loot_List; namespace luabind { struct scope; } luabind::scope lua_register_npc(); +luabind::scope lua_register_npc_loot_list(); class Lua_NPC : public Lua_Mob { @@ -146,6 +148,7 @@ public: uint16 GetFirstSlotByItemID(uint32 item_id); float GetHealScale(); float GetSpellScale(); + Lua_NPC_Loot_List GetLootList(lua_State* L); }; #endif diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 5a0601658..11106a254 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -1121,6 +1121,8 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_object_list(), lua_register_door_list(), lua_register_spawn_list(), + lua_register_corpse_loot_list(), + lua_register_npc_loot_list(), lua_register_group(), lua_register_raid(), lua_register_corpse(), diff --git a/zone/npc.cpp b/zone/npc.cpp index 85a843ca0..e402c89ab 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -682,12 +682,12 @@ bool NPC::HasItem(uint32 item_id) { for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) { ServerLootItem_Struct* loot_item = *current_item; if (!loot_item) { - LogError("NPC::CountItem() - ItemList error, null item"); + LogError("NPC::HasItem() - ItemList error, null item"); continue; } if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) { - LogError("NPC::CountItem() - Database error, invalid item"); + LogError("NPC::HasItem() - Database error, invalid item"); continue; } @@ -3474,3 +3474,21 @@ bool NPC::IsGuard() } return false; } + +std::vector NPC::GetLootList() { + std::vector npc_items; + for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) { + ServerLootItem_Struct* loot_item = *current_item; + if (!loot_item) { + LogError("NPC::GetLootList() - ItemList error, null item"); + continue; + } + + if (std::find(npc_items.begin(), npc_items.end(), loot_item->item_id) != npc_items.end()) { + continue; + } + + npc_items.push_back(loot_item->item_id); + } + return npc_items; +} diff --git a/zone/npc.h b/zone/npc.h index c758ee19f..af07b396c 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -208,6 +208,7 @@ public: uint16 CountItem(uint32 item_id); uint32 GetItemIDBySlot(uint16 loot_slot); uint16 GetFirstSlotByItemID(uint32 item_id); + std::vector GetLootList(); uint32 CountLoot(); inline uint32 GetLoottableID() const { return loottable_id; } virtual void UpdateEquipmentLight(); diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 6496e5863..d22962fbb 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -1846,6 +1846,29 @@ XS(XS_NPC_GetSpellScale) { XSRETURN(1); } +XS(XS_NPC_GetLootList); +XS(XS_NPC_GetLootList) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetLootList(THIS)"); // @categories Script Utility + { + NPC *THIS; + VALIDATE_THIS_IS_NPC; + auto npc_items = THIS->GetLootList(); + auto item_count = npc_items.size(); + if (item_count > 0) { + EXTEND(sp, item_count); + for (int index = 0; index < item_count; ++index) { + ST(index) = sv_2mortal(newSVuv(npc_items[index])); + } + XSRETURN(item_count); + } + SV* return_value = &PL_sv_undef; + ST(0) = return_value; + XSRETURN(1); + } +} + #ifdef __cplusplus extern "C" #endif @@ -1970,6 +1993,7 @@ XS(boot_NPC) { newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_NPC_GetFirstSlotByItemID, file, "$$"); newXSproto(strcpy(buf, "GetHealScale"), XS_NPC_GetHealScale, file, "$"); newXSproto(strcpy(buf, "GetSpellScale"), XS_NPC_GetSpellScale, file, "$"); + newXSproto(strcpy(buf, "GetLootList"), XS_NPC_GetLootList, file, "$"); XSRETURN_YES; } diff --git a/zone/perl_player_corpse.cpp b/zone/perl_player_corpse.cpp index dc6aaeb8b..dd01acda4 100644 --- a/zone/perl_player_corpse.cpp +++ b/zone/perl_player_corpse.cpp @@ -599,6 +599,29 @@ XS(XS_Corpse_GetFirstSlotByItemID) { XSRETURN(1); } +XS(XS_Corpse_GetLootList); +XS(XS_Corpse_GetLootList) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Corpse::GetLootList(THIS)"); // @categories Script Utility + { + Corpse *THIS; + VALIDATE_THIS_IS_CORPSE; + auto corpse_items = THIS->GetLootList(); + auto item_count = corpse_items.size(); + if (item_count > 0) { + EXTEND(sp, item_count); + for (int index = 0; index < item_count; ++index) { + ST(index) = sv_2mortal(newSVuv(corpse_items[index])); + } + XSRETURN(item_count); + } + SV* return_value = &PL_sv_undef; + ST(0) = return_value; + XSRETURN(1); + } +} + #ifdef __cplusplus extern "C" #endif @@ -649,6 +672,7 @@ XS(boot_Corpse) { newXSproto(strcpy(buf, "CountItem"), XS_Corpse_CountItem, file, "$$"); newXSproto(strcpy(buf, "GetItemIDBySlot"), XS_Corpse_GetItemIDBySlot, file, "$$"); newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_Corpse_GetFirstSlotByItemID, file, "$$"); + newXSproto(strcpy(buf, "GetLootList"), XS_Corpse_GetLootList, file, "$"); XSRETURN_YES; }