mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
[Quest API] Adds new methods to NPCs and Corpses (#1510)
- Add $npc->HasItem(item_id) to Perl. - Add $npc->CountItem(item_id) to Perl. - Add $npc->GetItemIDBySlot(loot_slot) to Perl. - Add $npc->GetFirstSlotByItemID(item_id) to Perl. - Add $corpse->HasItem(item_id) to Perl. - Add $corpse->CountItem(item_id) to Perl. - Add $corpse->GetItemIDBySlot(loot_slot) to Perl. - Add $corpse->GetFirstSlotByItemID(item_id) to Perl. - Add npc:HasItem(item_id) to Lua. - Add npc:CountItem(item_id) to Lua. - Add npc:GetItemIDBySlot(loot_slot) to Lua. - Add npc:GetFirstSlotByItemID(item_id) to Lua. - Add corpse:HasItem(item_id) to Lua. - Add corpse:CountItem(item_id) to Lua. - Add corpse:GetItemIDBySlot(loot_slot) to Lua. - Add corpse:GetFirstSlotByItemID(item_id) to Lua. These methods will allow server operators to view the loot a current has in a slot, the first slot found by item ID, count the item by ID, and see if the NPC has the item. With that functionality you could build a custom loot system and modify loot more dynamically.
This commit is contained in:
parent
642cbfcadc
commit
26299354b6
@ -1454,6 +1454,75 @@ void Corpse::QueryLoot(Client* to) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Corpse::HasItem(uint32 item_id) {
|
||||
if (!database.GetItem(item_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
||||
LogError("NPC::CountItem() - Database error, invalid item");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (loot_item->item_id == item_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 Corpse::CountItem(uint32 item_id) {
|
||||
uint16 item_count = 0;
|
||||
if (!database.GetItem(item_id)) {
|
||||
return item_count;
|
||||
}
|
||||
|
||||
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");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
||||
LogError("NPC::CountItem() - Database error, invalid item");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (loot_item->item_id == item_id) {
|
||||
item_count += loot_item->charges;
|
||||
}
|
||||
}
|
||||
return item_count;
|
||||
}
|
||||
|
||||
uint32 Corpse::GetItemIDBySlot(uint16 loot_slot) {
|
||||
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||
ServerLootItem_Struct* loot_item = *current_item;
|
||||
if (loot_item->lootslot == loot_slot) {
|
||||
return loot_item->item_id;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 Corpse::GetFirstSlotByItemID(uint32 item_id) {
|
||||
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||
ServerLootItem_Struct* loot_item = *current_item;
|
||||
if (loot_item->item_id == item_id) {
|
||||
return loot_item->lootslot;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) {
|
||||
uint32 dist2 = 10000; // pow(100, 2);
|
||||
if (!spell) {
|
||||
|
||||
@ -113,6 +113,10 @@ class Corpse : public Mob {
|
||||
|
||||
/* Corpse: Loot */
|
||||
void QueryLoot(Client* to);
|
||||
bool HasItem(uint32 item_id);
|
||||
uint16 CountItem(uint32 item_id);
|
||||
uint32 GetItemIDBySlot(uint16 loot_slot);
|
||||
uint16 GetFirstSlotByItemID(uint32 item_id);
|
||||
void LootItem(Client* client, const EQApplicationPacket* app);
|
||||
void EndLoot(Client* client, const EQApplicationPacket* app);
|
||||
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
|
||||
|
||||
@ -152,6 +152,26 @@ void Lua_Corpse::AddLooter(Lua_Mob who) {
|
||||
self->AddLooter(who);
|
||||
}
|
||||
|
||||
bool Lua_Corpse::HasItem(uint32 item_id) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasItem(item_id);
|
||||
}
|
||||
|
||||
uint16 Lua_Corpse::CountItem(uint32 item_id) {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->CountItem(item_id);
|
||||
}
|
||||
|
||||
uint32 Lua_Corpse::GetItemIDBySlot(uint16 loot_slot) {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetItemIDBySlot(loot_slot);
|
||||
}
|
||||
|
||||
uint16 Lua_Corpse::GetFirstSlotByItemID(uint32 item_id) {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetFirstSlotByItemID(item_id);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_corpse() {
|
||||
return luabind::class_<Lua_Corpse, Lua_Mob>("Corpse")
|
||||
.def(luabind::constructor<>())
|
||||
@ -185,7 +205,11 @@ luabind::scope lua_register_corpse() {
|
||||
.def("GetSilver", (uint32(Lua_Corpse::*)(void))&Lua_Corpse::GetSilver)
|
||||
.def("GetGold", (uint32(Lua_Corpse::*)(void))&Lua_Corpse::GetGold)
|
||||
.def("GetPlatinum", (uint32(Lua_Corpse::*)(void))&Lua_Corpse::GetPlatinum)
|
||||
.def("AddLooter", (void(Lua_Corpse::*)(Lua_Mob))&Lua_Corpse::AddLooter);
|
||||
.def("AddLooter", (void(Lua_Corpse::*)(Lua_Mob))&Lua_Corpse::AddLooter)
|
||||
.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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -54,6 +54,10 @@ public:
|
||||
uint32 GetGold();
|
||||
uint32 GetPlatinum();
|
||||
void AddLooter(Lua_Mob who);
|
||||
bool HasItem(uint32 item_id);
|
||||
uint16 CountItem(uint32 item_id);
|
||||
uint32 GetItemIDBySlot(uint16 loot_slot);
|
||||
uint16 GetFirstSlotByItemID(uint32 item_id);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -582,6 +582,30 @@ void Lua_NPC::ClearLastName()
|
||||
self->ClearLastName();
|
||||
}
|
||||
|
||||
bool Lua_NPC::HasItem(uint32 item_id)
|
||||
{
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasItem(item_id);
|
||||
}
|
||||
|
||||
uint16 Lua_NPC::CountItem(uint32 item_id)
|
||||
{
|
||||
Lua_Safe_Call_Int();
|
||||
return self->CountItem(item_id);
|
||||
}
|
||||
|
||||
uint32 Lua_NPC::GetItemIDBySlot(uint16 loot_slot)
|
||||
{
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetItemIDBySlot(loot_slot);
|
||||
}
|
||||
|
||||
uint16 Lua_NPC::GetFirstSlotByItemID(uint32 item_id)
|
||||
{
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetFirstSlotByItemID(item_id);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_npc() {
|
||||
return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
|
||||
.def(luabind::constructor<>())
|
||||
@ -698,7 +722,11 @@ luabind::scope lua_register_npc() {
|
||||
.def("ScaleNPC", (void(Lua_NPC::*)(uint8))&Lua_NPC::ScaleNPC)
|
||||
.def("IsRaidTarget", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRaidTarget)
|
||||
.def("ChangeLastName", (void(Lua_NPC::*)(const char*))&Lua_NPC::ChangeLastName)
|
||||
.def("ClearLastName", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLastName);
|
||||
.def("ClearLastName", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLastName)
|
||||
.def("HasItem", (bool(Lua_NPC::*)(uint32))&Lua_NPC::HasItem)
|
||||
.def("CountItem", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::CountItem)
|
||||
.def("GetItemIDBySlot", (uint32(Lua_NPC::*)(uint16))&Lua_NPC::GetItemIDBySlot)
|
||||
.def("GetFirstSlotByItemID", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::GetFirstSlotByItemID);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -140,6 +140,10 @@ public:
|
||||
bool IsRaidTarget();
|
||||
void ChangeLastName(const char *lastname);
|
||||
void ClearLastName();
|
||||
bool HasItem(uint32 item_id);
|
||||
uint16 CountItem(uint32 item_id);
|
||||
uint32 GetItemIDBySlot(uint16 slot_id);
|
||||
uint16 GetFirstSlotByItemID(uint32 item_id);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
69
zone/npc.cpp
69
zone/npc.cpp
@ -674,6 +674,75 @@ void NPC::QueryLoot(Client* to)
|
||||
to->Message(Chat::White, "| %i Platinum %i Gold %i Silver %i Copper", platinum, gold, silver, copper);
|
||||
}
|
||||
|
||||
bool NPC::HasItem(uint32 item_id) {
|
||||
if (!database.GetItem(item_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
||||
LogError("NPC::CountItem() - Database error, invalid item");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (loot_item->item_id == item_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 NPC::CountItem(uint32 item_id) {
|
||||
uint16 item_count = 0;
|
||||
if (!database.GetItem(item_id)) {
|
||||
return item_count;
|
||||
}
|
||||
|
||||
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");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!loot_item->item_id || !database.GetItem(loot_item->item_id)) {
|
||||
LogError("NPC::CountItem() - Database error, invalid item");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (loot_item->item_id == item_id) {
|
||||
item_count += loot_item->charges;
|
||||
}
|
||||
}
|
||||
return item_count;
|
||||
}
|
||||
|
||||
uint32 NPC::GetItemIDBySlot(uint16 loot_slot) {
|
||||
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||
ServerLootItem_Struct* loot_item = *current_item;
|
||||
if (loot_item->lootslot == loot_slot) {
|
||||
return loot_item->item_id;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 NPC::GetFirstSlotByItemID(uint32 item_id) {
|
||||
for (auto current_item = itemlist.begin(); current_item != itemlist.end(); ++current_item) {
|
||||
ServerLootItem_Struct* loot_item = *current_item;
|
||||
if (loot_item->item_id == item_id) {
|
||||
return loot_item->lootslot;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum) {
|
||||
if(in_copper >= 0)
|
||||
copper = in_copper;
|
||||
|
||||
@ -204,6 +204,10 @@ public:
|
||||
void AddCash();
|
||||
void RemoveCash();
|
||||
void QueryLoot(Client* to);
|
||||
bool HasItem(uint32 item_id);
|
||||
uint16 CountItem(uint32 item_id);
|
||||
uint32 GetItemIDBySlot(uint16 loot_slot);
|
||||
uint16 GetFirstSlotByItemID(uint32 item_id);
|
||||
uint32 CountLoot();
|
||||
inline uint32 GetLoottableID() const { return loottable_id; }
|
||||
virtual void UpdateEquipmentLight();
|
||||
|
||||
@ -1741,6 +1741,77 @@ XS(XS_NPC_IsRaidTarget) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_HasItem); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_HasItem) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: NPC::HasItem(THIS, uint32 item_id)"); // @categories Script Utility
|
||||
{
|
||||
NPC *THIS;
|
||||
bool has_item = false;
|
||||
uint32 item_id = (uint32) SvUV(ST(1));
|
||||
VALIDATE_THIS_IS_NPC;
|
||||
has_item = THIS->HasItem(item_id);
|
||||
ST(0) = boolSV(has_item);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_CountItem);
|
||||
XS(XS_NPC_CountItem) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: NPC::CountItem(THIS, uint32 item_id)"); // @categories Script Utility
|
||||
{
|
||||
NPC *THIS;
|
||||
uint16 item_count = 0;
|
||||
uint32 item_id = (uint32) SvUV(ST(1));
|
||||
dXSTARG;
|
||||
VALIDATE_THIS_IS_NPC;
|
||||
item_count = THIS->CountItem(item_id);
|
||||
XSprePUSH;
|
||||
PUSHu((UV) item_count);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetItemIDBySlot);
|
||||
XS(XS_NPC_GetItemIDBySlot) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: NPC::GetItemIDBySlot(THIS, uint16 loot_slot)"); // @categories Script Utility
|
||||
{
|
||||
NPC *THIS;
|
||||
uint32 item_id = 0;
|
||||
uint16 loot_slot = (uint16) SvUV(ST(1));
|
||||
dXSTARG;
|
||||
VALIDATE_THIS_IS_NPC;
|
||||
item_id = THIS->GetItemIDBySlot(loot_slot);
|
||||
XSprePUSH;
|
||||
PUSHu((UV) item_id);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetFirstSlotByItemID);
|
||||
XS(XS_NPC_GetFirstSlotByItemID) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: NPC::GetFirstSlotByItemID(THIS, uint32 item_id)"); // @categories Script Utility
|
||||
{
|
||||
NPC *THIS;
|
||||
uint16 loot_slot = 0;
|
||||
uint32 item_id = (uint32) SvUV(ST(1));
|
||||
dXSTARG;
|
||||
VALIDATE_THIS_IS_NPC;
|
||||
loot_slot = THIS->GetFirstSlotByItemID(item_id);
|
||||
XSprePUSH;
|
||||
PUSHu((UV) loot_slot);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
@ -1859,6 +1930,10 @@ XS(boot_NPC) {
|
||||
newXSproto(strcpy(buf, "RecalculateSkills"), XS_NPC_RecalculateSkills, file, "$");
|
||||
newXSproto(strcpy(buf, "ScaleNPC"), XS_NPC_ScaleNPC, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsRaidTarget"), XS_NPC_IsRaidTarget, file, "$");
|
||||
newXSproto(strcpy(buf, "HasItem"), XS_NPC_HasItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "CountItem"), XS_NPC_CountItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetItemIDBySlot"), XS_NPC_GetItemIDBySlot, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_NPC_GetFirstSlotByItemID, file, "$$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
@ -528,6 +528,77 @@ XS(XS_Corpse_IsRezzed) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_HasItem); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Corpse_HasItem) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::HasItem(THIS, uint32 item_id)"); // @categories Script Utility
|
||||
{
|
||||
Corpse *THIS;
|
||||
bool has_item = false;
|
||||
uint32 item_id = (uint32) SvUV(ST(1));
|
||||
VALIDATE_THIS_IS_CORPSE;
|
||||
has_item = THIS->HasItem(item_id);
|
||||
ST(0) = boolSV(has_item);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_CountItem);
|
||||
XS(XS_Corpse_CountItem) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::CountItem(THIS, uint32 item_id)"); // @categories Script Utility
|
||||
{
|
||||
Corpse *THIS;
|
||||
uint16 item_count = 0;
|
||||
uint32 item_id = (uint32) SvUV(ST(1));
|
||||
dXSTARG;
|
||||
VALIDATE_THIS_IS_CORPSE;
|
||||
item_count = THIS->CountItem(item_id);
|
||||
XSprePUSH;
|
||||
PUSHu((UV) item_count);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetItemIDBySlot);
|
||||
XS(XS_Corpse_GetItemIDBySlot) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetItemIDBySlot(THIS, uint16 loot_slot)"); // @categories Script Utility
|
||||
{
|
||||
Corpse *THIS;
|
||||
uint32 item_id = 0;
|
||||
uint16 loot_slot = (uint16) SvUV(ST(1));
|
||||
dXSTARG;
|
||||
VALIDATE_THIS_IS_CORPSE;
|
||||
item_id = THIS->GetItemIDBySlot(loot_slot);
|
||||
XSprePUSH;
|
||||
PUSHu((UV) item_id);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Corpse_GetFirstSlotByItemID);
|
||||
XS(XS_Corpse_GetFirstSlotByItemID) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Corpse::GetFirstSlotByItemID(THIS, uint32 item_id)"); // @categories Script Utility
|
||||
{
|
||||
Corpse *THIS;
|
||||
uint16 loot_slot = 0;
|
||||
uint32 item_id = (uint32) SvUV(ST(1));
|
||||
dXSTARG;
|
||||
VALIDATE_THIS_IS_CORPSE;
|
||||
loot_slot = THIS->GetFirstSlotByItemID(item_id);
|
||||
XSprePUSH;
|
||||
PUSHu((UV) loot_slot);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
@ -574,6 +645,10 @@ XS(boot_Corpse) {
|
||||
newXSproto(strcpy(buf, "AllowMobLoot"), XS_Corpse_AllowMobLoot, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AddLooter"), XS_Corpse_AddLooter, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsRezzed"), XS_Corpse_IsRezzed, file, "$");
|
||||
newXSproto(strcpy(buf, "HasItem"), XS_Corpse_HasItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "CountItem"), XS_Corpse_CountItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetItemIDBySlot"), XS_Corpse_GetItemIDBySlot, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetFirstSlotByItemID"), XS_Corpse_GetFirstSlotByItemID, file, "$$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user