diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 915976c9a..3618f0975 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -801,34 +801,35 @@ int16 EQ::InventoryProfile::HasItemByLoreGroup(uint32 loregroup, uint8 where) // Returns slot_id when there's one available, else SLOT_INVALID int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow) { - // Check basic inventory - for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) { - if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0) - continue; + const int16 last_bag_slot = RuleI(World, ExpansionSettings) & EQ::expansions::bitHoT ? EQ::invslot::slotGeneral10 : EQ::invslot::slotGeneral8; - if (!GetItem(i)) - // Found available slot in personal inventory - return i; + for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { // Check basic inventory + if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) { + continue; + } + + if (!GetItem(i)) { + return i; // Found available slot in personal inventory + } } if (!for_bag) { - for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) { - if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0) + for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { + if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) { continue; + } - const ItemInstance* inst = GetItem(i); - if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) - { - if (inst->GetItem()->BagType == item::BagTypeQuiver && inst->GetItem()->ItemType != item::ItemTypeArrow) - { + const auto *inst = GetItem(i); + if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) { + if (inst->GetItem()->BagType == item::BagTypeQuiver && + inst->GetItem()->ItemType != item::ItemTypeArrow) { continue; } - int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN); + const int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN); - uint8 slots = inst->GetItem()->BagSlots; - uint8 j; - for (j = invbag::SLOT_BEGIN; jGetItem()->BagSlots; + for (uint8 j = invbag::SLOT_BEGIN; j < slots; j++) { if (!GetItem(base_slot_id + j)) { // Found available slot within bag return (base_slot_id + j); diff --git a/zone/client.h b/zone/client.h index 3ee7e75bc..d2553e97e 100644 --- a/zone/client.h +++ b/zone/client.h @@ -982,6 +982,7 @@ public: void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, ServerLootItem_Struct** bag_item_data = 0); bool AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQ::invslot::slotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); + void SummonItemIntoInventory(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool is_attuned = false); void SummonBaggedItems(uint32 bag_item_id, const std::vector& bag_items); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 027d88f53..95ed20c85 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -4739,3 +4739,53 @@ bool Client::IsAugmentRestricted(uint8 item_type, uint32 augment_restriction) return false; } + +void Client::SummonItemIntoInventory( + uint32 item_id, + int16 charges, + uint32 aug1, + uint32 aug2, + uint32 aug3, + uint32 aug4, + uint32 aug5, + uint32 aug6, + bool is_attuned +) +{ + auto *inst = database.CreateItem( + item_id, + charges, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6, + is_attuned + ); + + if (!inst) { + return; + } + + const bool is_arrow = inst->GetItem()->ItemType == EQ::item::ItemTypeArrow; + const int16 slot_id = m_inv.FindFreeSlot( + inst->IsClassBag(), + true, + inst->GetItem()->Size, + is_arrow + ); + + SummonItem( + item_id, + charges, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6, + is_attuned, + slot_id + ); +} diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 69b6138d4..eb9442247 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -3217,6 +3217,35 @@ void Lua_Client::RemoveRadiantCrystals(uint32 amount) self->RemoveRadiantCrystals(amount); } +void Lua_Client::SummonItemIntoInventory(luabind::object item_table) { + Lua_Safe_Call_Void(); + if (luabind::type(item_table) != LUA_TTABLE) { + return; + } + + const uint32 item_id = luabind::object_cast(item_table["item_id"]); + const int16 charges = luabind::object_cast(item_table["charges"]); + const uint32 augment_one = luabind::type(item_table["augment_one"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_one"]) : 0; + const uint32 augment_two = luabind::type(item_table["augment_two"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_two"]) : 0; + const uint32 augment_three = luabind::type(item_table["augment_three"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_three"]) : 0; + const uint32 augment_four = luabind::type(item_table["augment_four"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_four"]) : 0; + const uint32 augment_five = luabind::type(item_table["augment_five"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_five"]) : 0; + const uint32 augment_six = luabind::type(item_table["augment_six"]) != LUA_TNIL ? luabind::object_cast(item_table["augment_six"]) : 0; + const bool attuned = luabind::type(item_table["attuned"]) != LUA_TNIL ? luabind::object_cast(item_table["attuned"]) : false; + + self->SummonItemIntoInventory( + item_id, + charges, + augment_one, + augment_two, + augment_three, + augment_four, + augment_five, + augment_six, + attuned + ); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -3723,6 +3752,7 @@ luabind::scope lua_register_client() { .def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32))&Lua_Client::SummonItem) .def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32,bool))&Lua_Client::SummonItem) .def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32,bool,int))&Lua_Client::SummonItem) + .def("SummonItemIntoInventory", (void(Lua_Client::*)(luabind::adl::object))&Lua_Client::SummonItemIntoInventory) .def("TGB", (bool(Lua_Client::*)(void))&Lua_Client::TGB) .def("TakeMoneyFromPP", (bool(Lua_Client::*)(uint64))&Lua_Client::TakeMoneyFromPP) .def("TakeMoneyFromPP", (bool(Lua_Client::*)(uint64,bool))&Lua_Client::TakeMoneyFromPP) diff --git a/zone/lua_client.h b/zone/lua_client.h index f298bacc0..b34e6f4e9 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -486,6 +486,7 @@ public: void AddRadiantCrystals(uint32 amount); void RemoveEbonCrystals(uint32 amount); void RemoveRadiantCrystals(uint32 amount); + void SummonItemIntoInventory(luabind::object item_table); void ApplySpell(int spell_id); void ApplySpell(int spell_id, int duration); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index a2495bedc..b6c7a8d15 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3028,6 +3028,36 @@ void Perl_Client_RemoveRadiantCrystals(Client* self, uint32 amount) self->RemoveRadiantCrystals(amount); } +void Perl_Client_SummonItemIntoInventory(Client* self, perl::reference table_ref) +{ + perl::hash table = table_ref; + if (!table.exists("item_id") || !table.exists("charges")) { + return; + } + + const uint32 item_id = table["item_id"]; + const int16 charges = table["charges"]; + const uint32 augment_one = table.exists("augment_one") ? table["augment_one"] : 0; + const uint32 augment_two = table.exists("augment_two") ? table["augment_two"] : 0; + const uint32 augment_three = table.exists("augment_three") ? table["augment_three"] : 0; + const uint32 augment_four = table.exists("augment_four") ? table["augment_four"] : 0; + const uint32 augment_five = table.exists("augment_five") ? table["augment_five"] : 0; + const uint32 augment_six = table.exists("augment_six") ? table["augment_six"] : 0; + const bool attuned = table.exists("attuned") ? table["attuned"] : false; + + self->SummonItemIntoInventory( + item_id, + charges, + augment_one, + augment_two, + augment_three, + augment_four, + augment_five, + augment_six, + attuned + ); +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3535,6 +3565,7 @@ void perl_register_client() package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32))&Perl_Client_SummonItem); package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32, uint32))&Perl_Client_SummonItem); package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32, uint32, uint16))&Perl_Client_SummonItem); + package.add("SummonItemIntoInventory", &Perl_Client_SummonItemIntoInventory); package.add("TGB", &Perl_Client_TGB); package.add("TakeMoneyFromPP", (bool(*)(Client*, uint64_t))&Perl_Client_TakeMoneyFromPP); package.add("TakeMoneyFromPP", (bool(*)(Client*, uint64_t, bool))&Perl_Client_TakeMoneyFromPP);