mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 14:41:28 +00:00
[Quest API] Add client->SummonBaggedItems(bag_item_id, bag_items_ref) to Perl/Lua.
Alternative apis using arrays of hash items for EQEmu/Server#1575 Perl usage: ```pl # create as an array, pass as reference my @bag_items = ( { item_id => 1001, charges => 1 }, { item_id => 1002, charges => 1 }, { item_id => 10037, charges => 10 }, ); $client->SummonBaggedItems(17403, \@bag_items); # create directly as an array reference my $bag_items = [ { item_id => 1001, charges => 1 }, { item_id => 1002, charges => 1 }, { item_id => 10037, charges => 10 }, ]; $client->SummonBaggedItems(17403, $bag_items); ``` Lua Usage: ```lua local bag_items = { { item_id = 1001, charges = 1 }, { item_id = 1002, charges = 1 }, { item_id = 10037, charges = 10 } } e.other:SummonBaggedItems(17403, bag_items);
This commit is contained in:
parent
9a413cf553
commit
5560b198ca
@ -10567,3 +10567,65 @@ std::vector<Client *> Client::GetPartyMembers()
|
||||
|
||||
return clients_to_update;
|
||||
}
|
||||
|
||||
void Client::SummonBaggedItems(uint32 bag_item_id, const std::vector<ServerLootItem_Struct>& bag_items)
|
||||
{
|
||||
if (bag_items.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// todo: maybe some common functions for SE_SummonItem and SE_SummonItemIntoBag
|
||||
|
||||
const EQ::ItemData* bag_item = database.GetItem(bag_item_id);
|
||||
if (!bag_item)
|
||||
{
|
||||
Message(Chat::Red, fmt::format("Unable to summon item [{}]. Item not found.", bag_item_id).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckLoreConflict(bag_item))
|
||||
{
|
||||
DuplicateLoreMessage(bag_item_id);
|
||||
return;
|
||||
}
|
||||
|
||||
int bag_item_charges = 1; // just summoning a single bag
|
||||
EQ::ItemInstance* summoned_bag = database.CreateItem(bag_item_id, bag_item_charges);
|
||||
if (!summoned_bag || !summoned_bag->IsClassBag())
|
||||
{
|
||||
Message(Chat::Red, fmt::format("Failed to summon bag item [{}]", bag_item_id).c_str());
|
||||
safe_delete(summoned_bag);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& item : bag_items)
|
||||
{
|
||||
uint8 open_slot = summoned_bag->FirstOpenSlot();
|
||||
if (open_slot == 0xff)
|
||||
{
|
||||
Message(Chat::Red, "Attempting to summon item in to bag, but there is no room in the summoned bag!");
|
||||
break;
|
||||
}
|
||||
|
||||
const EQ::ItemData* current_item = database.GetItem(item.item_id);
|
||||
|
||||
if (CheckLoreConflict(current_item))
|
||||
{
|
||||
DuplicateLoreMessage(item.item_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
EQ::ItemInstance* summoned_bag_item = database.CreateItem(item.item_id, item.charges);
|
||||
if (summoned_bag_item)
|
||||
{
|
||||
summoned_bag->PutItem(open_slot, *summoned_bag_item);
|
||||
safe_delete(summoned_bag_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PushItemOnCursor(*summoned_bag);
|
||||
SendItemPacket(EQ::invslot::slotCursor, summoned_bag, ItemPacketLimbo);
|
||||
safe_delete(summoned_bag);
|
||||
}
|
||||
|
||||
@ -913,6 +913,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 SummonBaggedItems(uint32 bag_item_id, const std::vector<ServerLootItem_Struct>& bag_items);
|
||||
void SetStats(uint8 type,int16 set_val);
|
||||
void IncStats(uint8 type,int16 increase_val);
|
||||
void DropItem(int16 slot_id, bool recurse = true);
|
||||
|
||||
@ -2229,6 +2229,31 @@ void Lua_Client::UntrainDiscBySpellID(uint16 spell_id, bool update_client) {
|
||||
self->UntrainDiscBySpellID(spell_id, update_client);
|
||||
}
|
||||
|
||||
void Lua_Client::SummonBaggedItems(uint32 bag_item_id, luabind::adl::object bag_items_table) {
|
||||
Lua_Safe_Call_Void();
|
||||
if (luabind::type(bag_items_table) != LUA_TTABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<ServerLootItem_Struct> bagged_items;
|
||||
|
||||
luabind::raw_iterator end; // raw_iterator uses lua_rawget
|
||||
for (luabind::raw_iterator it(bag_items_table); it != end; ++it)
|
||||
{
|
||||
// verify array element is a table for item details
|
||||
if (luabind::type(*it) == LUA_TTABLE)
|
||||
{
|
||||
// no need to try/catch, quest lua parser already catches exceptions
|
||||
ServerLootItem_Struct item{};
|
||||
item.item_id = luabind::object_cast<uint32>((*it)["item_id"]);
|
||||
item.charges = luabind::object_cast<int16>((*it)["charges"]);
|
||||
bagged_items.emplace_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
self->SummonBaggedItems(bag_item_id, bagged_items);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_client() {
|
||||
return luabind::class_<Lua_Client, Lua_Mob>("Client")
|
||||
.def(luabind::constructor<>())
|
||||
@ -2604,7 +2629,8 @@ luabind::scope lua_register_client() {
|
||||
.def("RemoveItem", (void(Lua_Client::*)(uint32,uint32))&Lua_Client::RemoveItem)
|
||||
.def("SetGMStatus", (void(Lua_Client::*)(int32))&Lua_Client::SetGMStatus)
|
||||
.def("UntrainDiscBySpellID", (void(Lua_Client::*)(uint16))&Lua_Client::UntrainDiscBySpellID)
|
||||
.def("UntrainDiscBySpellID", (void(Lua_Client::*)(uint16,bool))&Lua_Client::UntrainDiscBySpellID);
|
||||
.def("UntrainDiscBySpellID", (void(Lua_Client::*)(uint16,bool))&Lua_Client::UntrainDiscBySpellID)
|
||||
.def("SummonBaggedItems", (void(Lua_Client::*)(uint32,luabind::adl::object))&Lua_Client::SummonBaggedItems);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_inventory_where() {
|
||||
|
||||
@ -215,6 +215,7 @@ public:
|
||||
bool attuned);
|
||||
void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
|
||||
bool attuned, int to_slot);
|
||||
void SummonBaggedItems(uint32 bag_item_id, luabind::adl::object bag_items_table);
|
||||
void SetStats(int type, int value);
|
||||
void IncStats(int type, int value);
|
||||
void DropItem(int slot_id);
|
||||
|
||||
@ -5712,6 +5712,57 @@ XS(XS_Client_UntrainDiscBySpellID) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Client_SummonBaggedItems); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_SummonBaggedItems) {
|
||||
dXSARGS;
|
||||
if (items != 3) {
|
||||
Perl_croak(aTHX_ "Usage: Client::SummonBaggedItems(THIS, uint32 bag_item_id, ARRAYREF bag_items_array)"); // @categories Inventory and Items, Script Utility
|
||||
}
|
||||
|
||||
Client* THIS;
|
||||
VALIDATE_THIS_IS_CLIENT;
|
||||
|
||||
uint32 bag_item_id = (uint32) SvUV(ST(1));
|
||||
|
||||
// verify we're receiving a reference to an array type
|
||||
SV* bag_items_avref = ST(2);
|
||||
if (!bag_items_avref || !SvROK(bag_items_avref) || SvTYPE(SvRV(bag_items_avref)) != SVt_PVAV)
|
||||
{
|
||||
Perl_croak(aTHX_ "Client::SummonBaggedItems second argument is not a reference to an array");
|
||||
}
|
||||
|
||||
// dereference into the array
|
||||
AV* bag_items_av = (AV*)SvRV(bag_items_avref);
|
||||
|
||||
std::vector<ServerLootItem_Struct> bagged_items;
|
||||
|
||||
auto count = av_len(bag_items_av) + 1;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
SV** element = av_fetch(bag_items_av, i, 0);
|
||||
|
||||
// verify array element is a hash reference containing item details
|
||||
if (element && SvROK(*element) && SvTYPE(SvRV(*element)) == SVt_PVHV)
|
||||
{
|
||||
HV* hash = (HV*)SvRV(*element); // dereference
|
||||
|
||||
SV** item_id_ptr = hv_fetchs(hash, "item_id", false);
|
||||
SV** item_charges_ptr = hv_fetchs(hash, "charges", false);
|
||||
if (item_id_ptr && item_charges_ptr)
|
||||
{
|
||||
ServerLootItem_Struct item{};
|
||||
item.item_id = static_cast<uint32>(SvUV(*item_id_ptr));
|
||||
item.charges = static_cast<int16>(SvIV(*item_charges_ptr));
|
||||
bagged_items.emplace_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
THIS->SummonBaggedItems(bag_item_id, bagged_items);
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
@ -6001,6 +6052,7 @@ XS(boot_Client) {
|
||||
newXSproto(strcpy(buf, "Sit"), XS_Client_Sit, file, "$");
|
||||
newXSproto(strcpy(buf, "SlotConvert2"), XS_Client_SlotConvert2, file, "$$");
|
||||
newXSproto(strcpy(buf, "Stand"), XS_Client_Stand, file, "$");
|
||||
newXSproto(strcpy(buf, "SummonBaggedItems"), XS_Client_SummonBaggedItems, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SummonItem"), XS_Client_SummonItem, file, "$$;$$$$$$$$");
|
||||
newXSproto(strcpy(buf, "TakeMoneyFromPP"), XS_Client_TakeMoneyFromPP, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "TGB"), XS_Client_TGB, file, "$");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user