diff --git a/common/features.h b/common/features.h index 0e157a652..3c5301992 100644 --- a/common/features.h +++ b/common/features.h @@ -82,6 +82,10 @@ Zone extensions and features #define QUEST_GLOBAL_DIRECTORY "global" #endif +// Number of quest items a Quest NPC can hold +#define MAX_NPC_QUEST_INVENTORY 24 + + //the min ratio at which a mob's speed is reduced #define FLEE_HP_MINSPEED 22 //number of tics to try to run straight away before looking again @@ -111,6 +115,7 @@ Zone extensions and features #define SKILL_MAX_LEVEL 75 + /* Zone Numerical configuration diff --git a/common/loot.h b/common/loot.h index ba36c364f..61ceb8594 100644 --- a/common/loot.h +++ b/common/loot.h @@ -25,6 +25,8 @@ struct LootItem { uint16 trivial_max_level; uint16 npc_min_level; uint16 npc_max_level; + uint8 quest; + uint8 pet; }; typedef std::list LootItems; diff --git a/zone/loot.cpp b/zone/loot.cpp index a81284c2f..f7c53fc07 100644 --- a/zone/loot.cpp +++ b/zone/loot.cpp @@ -285,6 +285,8 @@ void NPC::AddLootDrop( const EQ::ItemData *item2, LootdropEntriesRepository::LootdropEntries loot_drop, bool wear_change, + bool quest, + bool pet, uint32 augment_one, uint32 augment_two, uint32 augment_three, @@ -297,6 +299,10 @@ void NPC::AddLootDrop( return; } + if (CountQuestItems() >= MAX_NPC_QUEST_INVENTORY) { + return; + } + auto item = new LootItem; if (LogSys.log_settings[Logs::Loot].is_category_enabled == 1) { @@ -318,6 +324,10 @@ void NPC::AddLootDrop( ); } + if (quest || pet) { + LogLoot("Adding {} to npc: {}. Wearchange: {} Multiquest: {} Pet: {}", item2->Name, GetName(), wear_change, quest, pet); + } + EQApplicationPacket *outapp = nullptr; WearChange_Struct *p_wear_change_struct = nullptr; if (wear_change) { @@ -339,6 +349,8 @@ void NPC::AddLootDrop( item->trivial_min_level = loot_drop.trivial_min_level; item->trivial_max_level = loot_drop.trivial_max_level; item->equip_slot = EQ::invslot::SLOT_INVALID; + item->quest = quest; + item->pet = pet; // unsure if required to equip, YOLO for now if (item2->ItemType == EQ::item::ItemTypeBow) { @@ -349,6 +361,11 @@ void NPC::AddLootDrop( SetArrowEquipped(true); } + if (pet && quest) { + LogLoot("Error: Item {} is being added to {} as both a pet and a quest.", item2->Name, GetName()); + item->pet = 0; + } + bool found = false; // track if we found an empty slot we fit into int found_slot = INVALID_INDEX; // for multi-slot items @@ -541,20 +558,21 @@ void NPC::AddLootDrop( safe_delete(inst); } -void NPC::AddItem(const EQ::ItemData *item, uint16 charges, bool equip_item) +void NPC::AddItem(const EQ::ItemData *item, uint16 charges, bool equip_item, bool quest) { auto l = LootdropEntriesRepository::NewNpcEntity(); l.equip_item = static_cast(equip_item ? 1 : 0); l.item_charges = charges; - AddLootDrop(item, l, true); + AddLootDrop(item, l, equip_item, quest); } void NPC::AddItem( uint32 item_id, uint16 charges, bool equip_item, + bool quest, uint32 augment_one, uint32 augment_two, uint32 augment_three, @@ -576,7 +594,8 @@ void NPC::AddItem( AddLootDrop( item, l, - true, + equip_item, + quest, augment_one, augment_two, augment_three, @@ -695,6 +714,50 @@ LootItem *NPC::GetItem(int slot_id) return (nullptr); } +LootItem *NPC::GetItemByItemID(int16 item_id) +{ + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + for (; cur != end; ++cur) { + LootItem *item = *cur; + if (item->item_id == item_id) { + return item; + } + } + return(nullptr); +} + +void NPC::RemoveItem(LootItem *item_data, uint8 quantity) { + if (!item_data) { + return; + } + + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + for (; cur != end; ++cur) { + LootItem *item = *cur; + if (item != item_data) { continue; } + + if (!item) { + return; + } + + if (item->charges <= quantity) { + m_loot_items.erase(cur); + UpdateEquipmentLight(); + if (UpdateActiveLight()) { SendAppearancePacket(AppearanceType::Light, GetActiveLightType()); } + } + else { + item->charges -= quantity; + } + return; + + } + +} + void NPC::RemoveItem(uint32 item_id, uint16 quantity, uint16 slot) { LootItems::iterator cur, end; @@ -941,3 +1004,315 @@ void NPC::RemoveLootCash() m_loot_gold = 0; m_loot_platinum = 0; } + +bool NPC::HasQuestLootItem(int16 itemid) +{ + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + for (; cur != end; ++cur) { + LootItem *quest_item = *cur; + if (quest_item && quest_item->quest == 1 && quest_item->item_id == itemid) { + return true; + } + } + + return false; +} + +bool NPC::HasQuestLoot() +{ + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + for (; cur != end; ++cur) { + LootItem *quest_loot = *cur; + if (quest_loot && quest_loot->quest == 1) { + return true; + } + } + + return false; +} + +bool NPC::RemoveQuestLootItems(int16 itemid) +{ + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + for (; cur != end; ++cur) { + LootItem *quest_item = *cur; + if (quest_item && quest_item->quest == 1) { + if (itemid == 0 || itemid == quest_item->item_id) { + RemoveItem(quest_item); + return true; + } + } + } + + return false; +} + +bool NPC::HasRequiredQuestLoot(int16 itemid1, int16 itemid2, int16 itemid3, int16 itemid4) +{ + if (itemid2 == 0 && itemid3 == 0 && itemid4 == 0) { + return true; + } + + uint8 item2count = 0, item3count = 0, item4count = 0, item1npc = 0, item2npc = 0, item3npc = 0, item4npc = 0; + uint8 item1count = 1; + if (itemid2 > 0) { + item2count = 1; + } + if (itemid3 > 0) { + item3count = 1; + } + if (itemid4 > 0) { + item4count = 1; + } + + if (itemid1 == itemid2 && itemid2 > 0) { + item2count = item1count; + ++item1count; + ++item2count; + } + if (itemid1 == itemid3 && itemid3 > 0) { + item3count = item1count; + ++item1count; + ++item3count; + } + if (itemid1 == itemid4 && itemid4 > 0) { + item4count = item1count; + ++item1count; + ++item4count; + } + if (itemid2 == itemid3 && itemid2 > 0 && itemid3 > 0) { + item3count = item2count; + ++item2count; + ++item3count; + } + if (itemid2 == itemid4 && itemid2 > 0 && itemid4 > 0) { + item4count = item2count; + ++item2count; + ++item4count; + } + if (itemid3 == itemid4 && itemid3 > 0 && itemid4 > 0) { + item4count = item3count; + ++item3count; + ++item4count; + } + + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + for (; cur != end; ++cur) { + LootItem *sitem = *cur; + if (sitem && sitem->quest == 1) { + if (sitem->item_id == itemid1) { + ++item1npc; + } + + if (sitem->item_id == itemid2 && itemid2 > 0) { + ++item2npc; + } + + if (sitem->item_id == itemid3 && itemid3 > 0) { + ++item3npc; + } + + if (sitem->item_id == itemid4 && itemid4 > 0) { + ++item4npc; + } + } + } + + if (item1npc < item1count) { + return false; + } + + if (itemid2 > 0 && item2npc < item2count) { + return false; + } + + if (itemid3 > 0 && item3npc < item3count) { + return false; + } + + if (itemid4 > 0 && item4npc < item4count) { + return false; + } + + return true; +} + +void NPC::CleanQuestLootItems() +{ + //Removes nodrop or multiple quest loot items from a NPC before sending the corpse items to the client. + + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + uint8 count = 0; + for (; cur != end; ++cur) { + LootItem *quest_item = *cur; + if (quest_item && (quest_item->quest == 1 || quest_item->pet == 1)) { + uint8 count = CountQuestItem(quest_item->item_id); + if (count > 1 && quest_item->pet != 1) { + RemoveItem(quest_item); + return; + } + else { + const EQ::ItemData *item = database.GetItem(quest_item->item_id); + if (item && item->NoDrop == 0) { + RemoveItem(quest_item); + return; + } + } + } + } +} + +uint8 NPC::CountQuestItem(uint16 itemid) +{ + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + uint8 count = 0; + for (; cur != end; ++cur) { + LootItem *quest_item = *cur; + if (quest_item && quest_item->item_id == itemid) { + ++count; + } + } + + return count; +} + +uint8 NPC::CountQuestItems() +{ + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + uint8 count = 0; + for (; cur != end; ++cur) { + LootItem *quest_item = *cur; + if (quest_item && quest_item->quest == 1) { + ++count; + } + } + + return count; +} + +bool NPC::AddQuestLoot(int16 itemid, int8 charges) { + auto l = LootdropEntriesRepository::NewNpcEntity(); + + const EQ::ItemData *item = database.GetItem(itemid); + if (item) { + l.item_charges = charges; + l.equip_item = 0; + AddLootDrop(item, l, false, false, true); + LogLoot("Adding item {} to the NPC's loot marked as quest.", itemid); + if (itemid > 0 && HasPetLootItem(itemid)) { + LogLoot("Deleting quest item {} from NPC's pet loot.", itemid); + RemovePetLootItems(itemid); + } + } + else + return false; + + return true; +} + +void NPC::DeleteQuestLoot(int16 itemid1, int16 itemid2, int16 itemid3, int16 itemid4) +{ + int16 items = m_loot_items.size(); + for (int i = 0; i < items; ++i) { + if (itemid1 == 0) { + if (!RemoveQuestLootItems(itemid1)) + break; + } + else { + if (itemid1 != 0) { + RemoveQuestLootItems(itemid1); + } + if (itemid2 != 0) { + RemoveQuestLootItems(itemid2); + } + if (itemid3 != 0) { + RemoveQuestLootItems(itemid3); + } + if (itemid4 != 0) { + RemoveQuestLootItems(itemid4); + } + } + } +} + +void NPC::DeleteInvalidQuestLoot() +{ + int16 items = m_loot_items.size(); + for (int i = 0; i < items; ++i) { + CleanQuestLootItems(); + } +} + +bool NPC::AddPetLoot(int16 itemid, int8 charges, bool fromquest) { + auto l = LootdropEntriesRepository::NewNpcEntity(); + + const EQ::ItemData *item = database.GetItem(itemid); + bool IsCharmedPet = IsPet() && IsCharmed(); + + if (!item) { + return false; + } + + bool valid = (item->NoDrop != 0 && ( !IsCharmedPet || (IsCharmedPet && CountQuestItem(item->ID) == 0))); + if (!fromquest || valid) { + if (item) { + l.item_charges = charges; + AddLootDrop(item, l, true, true, false, true); + LogLoot("Adding item {} to the NPC's loot marked as pet.", itemid); + return true; + } + } + else { + LogLoot("Item {} is a duplicate or no drop. Deleting...", itemid); + return false; + } + + return false; +} + +bool NPC::HasPetLootItem(int16 itemid) +{ + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + for (; cur != end; ++cur) { + LootItem *quest_item = *cur; + if (quest_item && quest_item->pet == 1 && quest_item->item_id == itemid) { + return true; + } + } + + return false; +} + +bool NPC::RemovePetLootItems(int16 itemid) +{ + LootItems::iterator cur, end; + cur = m_loot_items.begin(); + end = m_loot_items.end(); + for (; cur != end; ++cur) { + LootItem *quest_item = *cur; + if (quest_item && quest_item->pet == 1) { + if (itemid == 0 || itemid == quest_item->item_id) { + RemoveItem(quest_item); + return true; + } + } + } + + return false; +} diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index 76520340f..d3772674c 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -32,34 +32,39 @@ void Lua_NPC::AddItem(int item_id, int charges, bool equip) { self->AddItem(item_id, charges, equip); } -void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1) { +void Lua_NPC::AddItem(int item_id, int charges, bool equip, bool quest) { Lua_Safe_Call_Void(); - self->AddItem(item_id, charges, equip, aug1); + self->AddItem(item_id, charges, equip, quest); } -void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2) { +void Lua_NPC::AddItem(int item_id, int charges, bool equip, bool quest, int aug1) { Lua_Safe_Call_Void(); - self->AddItem(item_id, charges, equip, aug1, aug2); + self->AddItem(item_id, charges, equip, quest, aug1); } -void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3) { +void Lua_NPC::AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2) { Lua_Safe_Call_Void(); - self->AddItem(item_id, charges, equip, aug1, aug2, aug3); + self->AddItem(item_id, charges, equip, quest, aug1, aug2); } -void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4) { +void Lua_NPC::AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2, int aug3) { Lua_Safe_Call_Void(); - self->AddItem(item_id, charges, equip, aug1, aug2, aug3, aug4); + self->AddItem(item_id, charges, equip, quest, aug1, aug2, aug3); } -void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4, int aug5) { +void Lua_NPC::AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2, int aug3, int aug4) { Lua_Safe_Call_Void(); - self->AddItem(item_id, charges, equip, aug1, aug2, aug3, aug4, aug5); + self->AddItem(item_id, charges, equip, quest, aug1, aug2, aug3, aug4); } -void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6) { +void Lua_NPC::AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2, int aug3, int aug4, int aug5) { Lua_Safe_Call_Void(); - self->AddItem(item_id, charges, equip, aug1, aug2, aug3, aug4, aug5, aug6); + self->AddItem(item_id, charges, equip, quest, aug1, aug2, aug3, aug4, aug5); +} + +void Lua_NPC::AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6) { + Lua_Safe_Call_Void(); + self->AddItem(item_id, charges, equip, quest, aug1, aug2, aug3, aug4, aug5, aug6); } void Lua_NPC::AddLootTable() { @@ -831,6 +836,90 @@ uint32 Lua_NPC::GetNPCSpellsEffectsID() return self->GetNPCSpellsEffectsID(); } +void Lua_NPC::AddQuestLoot(int itemid) +{ + Lua_Safe_Call_Void(); + self->AddQuestLoot(itemid); +} + +void Lua_NPC::AddQuestLoot(int itemid, int charges) +{ + Lua_Safe_Call_Void(); + self->AddQuestLoot(itemid, charges); +} + +bool Lua_NPC::GetQuestLoot(int itemid) +{ + Lua_Safe_Call_Bool(); + return self->HasQuestLootItem(itemid); +} + +bool Lua_NPC::HasQuestLoot() +{ + Lua_Safe_Call_Bool(); + return self->HasQuestLoot(); +} + +void Lua_NPC::AddPetLoot(int itemid) +{ + Lua_Safe_Call_Void(); + self->AddPetLoot(itemid, 1, true); +} + +void Lua_NPC::AddPetLoot(int itemid, int charges) +{ + Lua_Safe_Call_Void(); + self->AddPetLoot(itemid, charges, true); +} + +bool Lua_NPC::GetPetLoot(int itemid) +{ + Lua_Safe_Call_Bool(); + return self->HasPetLootItem(itemid); +} + +void Lua_NPC::DeleteQuestLoot() +{ + Lua_Safe_Call_Void(); + self->DeleteQuestLoot(0); +} + +void Lua_NPC::DeleteQuestLoot(int itemid1) +{ + Lua_Safe_Call_Void(); + self->DeleteQuestLoot(itemid1); +} + +void Lua_NPC::DeleteQuestLoot(int itemid1, int itemid2) +{ + Lua_Safe_Call_Void(); + self->DeleteQuestLoot(itemid1, itemid2); +} + +void Lua_NPC::DeleteQuestLoot(int itemid1, int itemid2, int itemid3) +{ + Lua_Safe_Call_Void(); + self->DeleteQuestLoot(itemid1, itemid2, itemid3); +} + +void Lua_NPC::DeleteQuestLoot(int itemid1, int itemid2, int itemid3, int itemid4) +{ + Lua_Safe_Call_Void(); + self->DeleteQuestLoot(itemid1, itemid2, itemid3, itemid4); +} + +bool Lua_NPC::HasRequiredQuestLoot(int itemid1, int itemid2, int itemid3, int itemid4) +{ + Lua_Safe_Call_Bool(); + return self->HasRequiredQuestLoot(itemid1, itemid2, itemid3, itemid4); +} + +int Lua_NPC::QuestLootCount(int itemid) +{ + Lua_Safe_Call_Int(); + return self->CountQuestItem(itemid); +} + luabind::scope lua_register_npc() { return luabind::class_("NPC") .def(luabind::constructor<>()) @@ -842,14 +931,19 @@ luabind::scope lua_register_npc() { .def("AddCash", (void(Lua_NPC::*)(uint32,uint32,uint32,uint32))&Lua_NPC::AddLootCash) .def("AddItem", (void(Lua_NPC::*)(int,int))&Lua_NPC::AddItem) .def("AddItem", (void(Lua_NPC::*)(int,int,bool))&Lua_NPC::AddItem) - .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int))&Lua_NPC::AddItem) - .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int))&Lua_NPC::AddItem) - .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int,int))&Lua_NPC::AddItem) - .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int,int,int))&Lua_NPC::AddItem) - .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int,int,int,int))&Lua_NPC::AddItem) - .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int,int,int,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,bool)) & Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,bool,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,bool,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,bool,int,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,bool,int,int,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,bool,int,int,int,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,bool,int,int,int,int,int,int))&Lua_NPC::AddItem) .def("AddLootTable", (void(Lua_NPC::*)(int))&Lua_NPC::AddLootTable) .def("AddLootTable", (void(Lua_NPC::*)(void))&Lua_NPC::AddLootTable) + .def("AddQuestLoot", (void(Lua_NPC::*)(int)) & Lua_NPC::AddQuestLoot) + .def("AddQuestLoot", (void(Lua_NPC::*)(int,int)) & Lua_NPC::AddQuestLoot) + .def("AddPetLoot", (void(Lua_NPC:: *)(int)) & Lua_NPC::AddPetLoot) + .def("AddPetLoot", (void(Lua_NPC:: *)(int, int)) & Lua_NPC::AddPetLoot) .def("AssignWaypoints", (void(Lua_NPC::*)(int))&Lua_NPC::AssignWaypoints) .def("CalculateNewWaypoint", (void(Lua_NPC::*)(void))&Lua_NPC::CalculateNewWaypoint) .def("ChangeLastName", (void(Lua_NPC::*)(std::string))&Lua_NPC::ChangeLastName) @@ -859,6 +953,11 @@ luabind::scope lua_register_npc() { .def("CountItem", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::CountItem) .def("CountLoot", (int(Lua_NPC::*)(void))&Lua_NPC::CountLoot) .def("DeleteBucket", (void(Lua_NPC::*)(std::string))&Lua_NPC::DeleteBucket) + .def("DeleteQuestLoot", (void(Lua_NPC:: *)(void)) & Lua_NPC::DeleteQuestLoot) + .def("DeleteQuestLoot", (void(Lua_NPC:: *)(int)) & Lua_NPC::DeleteQuestLoot) + .def("DeleteQuestLoot", (void(Lua_NPC:: *)(int, int)) & Lua_NPC::DeleteQuestLoot) + .def("DeleteQuestLoot", (void(Lua_NPC:: *)(int, int, int)) & Lua_NPC::DeleteQuestLoot) + .def("DeleteQuestLoot", (void(Lua_NPC:: *)(int, int, int, int)) & Lua_NPC::DeleteQuestLoot) .def("DisplayWaypointInfo", (void(Lua_NPC::*)(Lua_Client))&Lua_NPC::DisplayWaypointInfo) .def("DoClassAttacks", (void(Lua_NPC::*)(Lua_Mob))&Lua_NPC::DoClassAttacks) .def("GetAccuracyRating", (int(Lua_NPC::*)(void))&Lua_NPC::GetAccuracyRating) @@ -896,10 +995,12 @@ luabind::scope lua_register_npc() { .def("GetNPCSpellsEffectsID", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsEffectsID) .def("GetNPCSpellsID", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID) .def("GetNPCStat", (float(Lua_NPC::*)(std::string))&Lua_NPC::GetNPCStat) + .def("GetPetLoot", (bool(Lua_NPC:: *)(int)) & Lua_NPC::GetPetLoot) .def("GetPetSpellID", (int(Lua_NPC::*)(void))&Lua_NPC::GetPetSpellID) .def("GetPlatinum", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetPlatinum) .def("GetPrimSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetPrimSkill) .def("GetPrimaryFaction", (int(Lua_NPC::*)(void))&Lua_NPC::GetPrimaryFaction) + .def("GetQuestLoot", (bool(Lua_NPC:: *)(int)) & Lua_NPC::GetQuestLoot) .def("GetRawAC", (int(Lua_NPC::*)(void))&Lua_NPC::GetRawAC) .def("GetScore", (int(Lua_NPC::*)(void))&Lua_NPC::GetScore) .def("GetSecSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetSecSkill) @@ -920,6 +1021,8 @@ luabind::scope lua_register_npc() { .def("GetWaypointMax", (int(Lua_NPC::*)(void))&Lua_NPC::GetWaypointMax) .def("HasAISpellEffect", (bool(Lua_NPC::*)(int))&Lua_NPC::HasAISpellEffect) .def("HasItem", (bool(Lua_NPC::*)(uint32))&Lua_NPC::HasItem) + .def("HasQuestLoot", (bool(Lua_NPC::*)(void)) & Lua_NPC::HasQuestLoot) + .def("HasRequiredQuestLoot", (bool(Lua_NPC::*)(int,int,int,int)) &Lua_NPC::HasRequiredQuestLoot) .def("IsAnimal", (bool(Lua_NPC::*)(void))&Lua_NPC::IsAnimal) .def("IsGuarding", (bool(Lua_NPC::*)(void))&Lua_NPC::IsGuarding) .def("IsLDoNLocked", (bool(Lua_NPC::*)(void))&Lua_NPC::IsLDoNLocked) @@ -937,6 +1040,7 @@ luabind::scope lua_register_npc() { .def("NextGuardPosition", (void(Lua_NPC::*)(void))&Lua_NPC::NextGuardPosition) .def("PauseWandering", (void(Lua_NPC::*)(int))&Lua_NPC::PauseWandering) .def("PickPocket", (void(Lua_NPC::*)(Lua_Client))&Lua_NPC::PickPocket) + .def("QuestLootCount", (int(Lua_NPC::*)(int)) &Lua_NPC::QuestLootCount) .def("RecalculateSkills", (void(Lua_NPC::*)(void))&Lua_NPC::RecalculateSkills) .def("ReloadSpells", (void(Lua_NPC::*)(void))&Lua_NPC::ReloadSpells) .def("RemoveAISpell", (void(Lua_NPC::*)(int))&Lua_NPC::RemoveAISpell) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index 9ecdb589f..563b8f072 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -33,12 +33,13 @@ public: int CheckNPCFactionAlly(int faction); void AddItem(int item_id, int charges); void AddItem(int item_id, int charges, bool equip); - void AddItem(int item_id, int charges, bool equip, int aug1); - void AddItem(int item_id, int charges, bool equip, int aug1, int aug2); - void AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3); - void AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4); - void AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4, int aug5); - void AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6); + void AddItem(int item_id, int charges, bool equip, bool quest); + void AddItem(int item_id, int charges, bool equip, bool quest, int aug1); + void AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2); + void AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2, int aug3); + void AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2, int aug3, int aug4); + void AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2, int aug3, int aug4, int aug5); + void AddItem(int item_id, int charges, bool equip, bool quest, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6); void AddLootTable(); void AddLootTable(int id); void RemoveItem(int item_id); @@ -185,6 +186,20 @@ public: bool GetNPCAggro(); void SetNPCAggro(bool in_npc_aggro); uint32 GetNPCSpellsEffectsID(); + void AddQuestLoot(int itemid); // + void AddQuestLoot(int itemid, int charges); // + void AddPetLoot(int itemid); // + void AddPetLoot(int itemid, int charges); // + bool GetQuestLoot(int itemid); // + bool GetPetLoot(int itemid); // + bool HasQuestLoot(); // + void DeleteQuestLoot(); + void DeleteQuestLoot(int itemid1); + void DeleteQuestLoot(int itemid1, int itemid2); + void DeleteQuestLoot(int itemid1, int itemid2, int itemid3); + void DeleteQuestLoot(int itemid1, int itemid2, int itemid3, int itemid4); + bool HasRequiredQuestLoot(int itemid1, int itemid2, int itemid3, int itemid4); + int QuestLootCount(int itemid); }; #endif diff --git a/zone/npc.h b/zone/npc.h index c9f074a1b..5a26d8e3d 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -197,11 +197,12 @@ public: virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); // loot - void AddItem(const EQ::ItemData *item, uint16 charges, bool equip_item = true); + void AddItem(const EQ::ItemData *item, uint16 charges, bool equip_item = true, bool quest = false); void AddItem( uint32 item_id, uint16 charges, bool equip_item = true, + bool quest = false, uint32 augment_one = 0, uint32 augment_two = 0, uint32 augment_three = 0, @@ -214,10 +215,12 @@ public: void AddLootDropTable(uint32 lootdrop_id, uint8 drop_limit, uint8 min_drop); void CheckGlobalLootTables(); void RemoveItem(uint32 item_id, uint16 quantity = 0, uint16 slot = 0); + void RemoveItem(LootItem *item_data, uint8 quantity = 0); void CheckTrivialMinMaxLevelDrop(Mob *killer); void ClearLootItems(); inline const LootItems &GetLootItems() { return m_loot_items; } LootItem *GetItem(int slot_id); + LootItem *GetItemByItemID(int16 itemid); void AddLootCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum); void RemoveLootCash(); void QueryLoot(Client *to, bool is_pet_query = false); @@ -238,6 +241,22 @@ public: inline void SetGold(uint32 amt) { m_loot_gold = amt; } inline void SetPlatinum(uint32 amt) { m_loot_platinum = amt; } + // MultiQuest + bool HasQuestLootItem(int16 itemid); + bool HasQuestLoot(); + bool RemoveQuestLootItems(int16 itemid); + bool HasRequiredQuestLoot(int16 itemid1, int16 itemid2, int16 itemid3, int16 itemid4); + void CleanQuestLootItems(); + uint8 CountQuestItem(uint16 itemid); + uint8 CountQuestItems(); + bool AddQuestLoot(int16 itemid, int8 charges = 1); + void DeleteQuestLoot(int16 itemid1, int16 itemid2 = 0, int16 itemid3 = 0, int16 itemid4 = 0); + void DeleteInvalidQuestLoot(); + + bool AddPetLoot(int16 itemid, int8 charges = 1, bool fromquest = false); + bool HasPetLootItem(int16 itemid); + bool RemovePetLootItems(int16 itemid); + void DescribeAggro(Client *to_who, Mob *mob, bool verbose); virtual void UpdateEquipmentLight(); virtual int64 CalcMaxMana(); @@ -326,6 +345,8 @@ public: const EQ::ItemData *item2, LootdropEntriesRepository::LootdropEntries loot_drop, bool wear_change = false, + bool quest = false, + bool pet = false, uint32 augment_one = 0, uint32 augment_two = 0, uint32 augment_three = 0,