mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-13 11:42:23 +00:00
feat(Scripting): Created two perl/lua scripting hooks for merchants (#5083)
This commit is contained in:
parent
ef6dfe0469
commit
ca704c7f88
@ -14378,9 +14378,8 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app)
|
||||
sizeof(Merchant_Purchase_Struct), app->size);
|
||||
return;
|
||||
}
|
||||
RDTSC_Timer t1(true);
|
||||
|
||||
Merchant_Purchase_Struct* mp = (Merchant_Purchase_Struct*)app->pBuffer;
|
||||
|
||||
Mob* vendor = entity_list.GetMob(mp->npcid);
|
||||
|
||||
if (vendor == 0 || !vendor->IsNPC() || vendor->GetClass() != Class::Merchant)
|
||||
@ -14390,35 +14389,51 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app)
|
||||
if (DistanceSquared(m_Position, vendor->GetPosition()) > USE_NPC_RANGE2)
|
||||
return;
|
||||
|
||||
uint32 price = 0;
|
||||
uint32 itemid = GetItemIDAt(mp->itemslot);
|
||||
if (itemid == 0)
|
||||
return;
|
||||
|
||||
const EQ::ItemData* item = database.GetItem(itemid);
|
||||
EQ::ItemInstance* inst = GetInv().GetItem(mp->itemslot);
|
||||
if (!item || !inst) {
|
||||
Message(Chat::Red, "You seemed to have misplaced that item..");
|
||||
Message(Chat::Red, "You seem to have misplaced that item..");
|
||||
return;
|
||||
}
|
||||
if (mp->quantity > 1)
|
||||
{
|
||||
|
||||
if (!item->NoDrop) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mp->quantity > 1) {
|
||||
if ((inst->GetCharges() < 0) || (mp->quantity > (uint32)inst->GetCharges()))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item->NoDrop) {
|
||||
//Message(Chat::Red,"%s tells you, 'LOL NOPE'", vendor->GetName());
|
||||
return;
|
||||
// Check for veto from script
|
||||
if (parse->PlayerHasQuestSub(EVENT_MERCHANT_PRESELL)) {
|
||||
std::string export_string = fmt::format("{} {} {}", mp->itemslot, itemid, inst->GetItemType());
|
||||
std::vector<std::any> extra_pointers = { vendor, inst };
|
||||
|
||||
int result = parse->EventPlayer(EVENT_MERCHANT_PRESELL, this, export_string, 0, &extra_pointers);
|
||||
// CANCEL: If a script returns -1 for this event, the sale wil be cancelled. Sends a dummy packet sent to satisfy the client
|
||||
if (result == -1) {
|
||||
auto outapp = new EQApplicationPacket(OP_ShopPlayerSell, sizeof(Merchant_Purchase_Struct));
|
||||
Merchant_Purchase_Struct* mco = (Merchant_Purchase_Struct*)outapp->pBuffer;
|
||||
mco->npcid = vendor->GetID();
|
||||
mco->itemslot = -1; // Critical or the client will remove the item visually
|
||||
mco->quantity = 0;
|
||||
mco->price = 0;
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 cost_quantity = mp->quantity;
|
||||
if (inst->IsCharged())
|
||||
uint32 cost_quantity = 1;
|
||||
|
||||
uint32 i;
|
||||
uint32 cost_quantity = inst->IsCharged() ? 1 : mp->quantity;
|
||||
uint32 price = 0;
|
||||
|
||||
if (RuleB(Merchant, UsePriceMod)) {
|
||||
for (i = 1; i <= cost_quantity; i++) {
|
||||
for (uint32 i = 1; i <= cost_quantity; i++) {
|
||||
price = (uint32)(item->Price * i) * Client::CalcPriceMod(vendor, true);
|
||||
|
||||
// Don't use SellCostMod if using UseClassicPriceMod
|
||||
@ -14436,7 +14451,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 1; i <= cost_quantity; i++) {
|
||||
for (uint32 i = 1; i <= cost_quantity; i++) {
|
||||
price = (uint32)((item->Price * i)*(RuleR(Merchant, BuyCostMod)) + 0.5); // need to round up, because client does it automatically when displaying price
|
||||
if (price > 4000000000) {
|
||||
cost_quantity = i;
|
||||
@ -14448,6 +14463,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app)
|
||||
|
||||
AddMoneyToPP(price);
|
||||
|
||||
// Update merchant stock and refresh client
|
||||
if (inst->IsStackable() || inst->IsCharged())
|
||||
{
|
||||
unsigned int i_quan = inst->GetCharges();
|
||||
@ -14561,6 +14577,8 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app)
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
SendMoneyUpdate();
|
||||
|
||||
RDTSC_Timer t1(true);
|
||||
t1.start();
|
||||
Save(1);
|
||||
t1.stop();
|
||||
@ -14679,6 +14697,11 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app)
|
||||
if ((tabs_to_display & Parcel) == Parcel) {
|
||||
SendBulkParcels();
|
||||
}
|
||||
|
||||
if (parse->PlayerHasQuestSub(EVENT_MERCHANT_OPEN)) {
|
||||
std::vector<std::any> extra_pointers = { tmp };
|
||||
parse->EventPlayer(EVENT_MERCHANT_OPEN, this, "", 0, &extra_pointers);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@ -163,8 +163,10 @@ const char* QuestEventSubroutines[_LargestEventID] = {
|
||||
"EVENT_LANGUAGE_SKILL_UP",
|
||||
"EVENT_ALT_CURRENCY_MERCHANT_BUY",
|
||||
"EVENT_ALT_CURRENCY_MERCHANT_SELL",
|
||||
"EVENT_MERCHANT_OPEN",
|
||||
"EVENT_MERCHANT_BUY",
|
||||
"EVENT_MERCHANT_SELL",
|
||||
"EVENT_MERCHANT_PRESELL",
|
||||
"EVENT_INSPECT",
|
||||
"EVENT_TASK_BEFORE_UPDATE",
|
||||
"EVENT_AA_BUY",
|
||||
@ -2289,6 +2291,33 @@ void PerlembParser::ExportEventVariables(
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_MERCHANT_OPEN: {
|
||||
if (!extra_pointers || extra_pointers->size() < 1) break;
|
||||
|
||||
auto mob_ptr = std::any_cast<Mob*>(extra_pointers->at(0));
|
||||
if (!mob_ptr) break;
|
||||
|
||||
ExportVar(package_name.c_str(), "other", "Mob", mob_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_MERCHANT_PRESELL: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "slot_id", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "item_id", sep.arg[1]);
|
||||
ExportVar(package_name.c_str(), "item_type", sep.arg[2]);
|
||||
|
||||
if (!extra_pointers || extra_pointers->size() < 2) break;
|
||||
|
||||
auto mob_ptr = std::any_cast<Mob*>(extra_pointers->at(0));
|
||||
auto inst_ptr = std::any_cast<EQ::ItemInstance*>(extra_pointers->at(1));
|
||||
if (!mob_ptr || !inst_ptr) break;
|
||||
|
||||
ExportVar(package_name.c_str(), "other", "Mob", mob_ptr);
|
||||
ExportVar(package_name.c_str(), "item", "ItemInstance", inst_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_AA_BUY: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "aa_cost", sep.arg[0]);
|
||||
|
||||
@ -116,8 +116,10 @@ enum QuestEventID {
|
||||
EVENT_LANGUAGE_SKILL_UP,
|
||||
EVENT_ALT_CURRENCY_MERCHANT_BUY,
|
||||
EVENT_ALT_CURRENCY_MERCHANT_SELL,
|
||||
EVENT_MERCHANT_OPEN,
|
||||
EVENT_MERCHANT_BUY,
|
||||
EVENT_MERCHANT_SELL,
|
||||
EVENT_MERCHANT_PRESELL,
|
||||
EVENT_INSPECT,
|
||||
EVENT_TASK_BEFORE_UPDATE,
|
||||
EVENT_AA_BUY,
|
||||
|
||||
@ -6968,8 +6968,10 @@ luabind::scope lua_register_events() {
|
||||
luabind::value("language_skill_up", static_cast<int>(EVENT_LANGUAGE_SKILL_UP)),
|
||||
luabind::value("alt_currency_merchant_buy", static_cast<int>(EVENT_ALT_CURRENCY_MERCHANT_BUY)),
|
||||
luabind::value("alt_currency_merchant_sell", static_cast<int>(EVENT_ALT_CURRENCY_MERCHANT_SELL)),
|
||||
luabind::value("merchant_open", static_cast<int>(EVENT_MERCHANT_OPEN)),
|
||||
luabind::value("merchant_buy", static_cast<int>(EVENT_MERCHANT_BUY)),
|
||||
luabind::value("merchant_sell", static_cast<int>(EVENT_MERCHANT_SELL)),
|
||||
luabind::value("merchant_presell", static_cast<int>(EVENT_MERCHANT_PRESELL)),
|
||||
luabind::value("inspect", static_cast<int>(EVENT_INSPECT)),
|
||||
luabind::value("task_before_update", static_cast<int>(EVENT_TASK_BEFORE_UPDATE)),
|
||||
luabind::value("aa_buy", static_cast<int>(EVENT_AA_BUY)),
|
||||
|
||||
@ -158,6 +158,11 @@ uint32 Lua_ItemInst::GetItemScriptID() {
|
||||
return self->GetItemScriptID();
|
||||
}
|
||||
|
||||
uint8 Lua_ItemInst::GetItemType() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetItemType();
|
||||
}
|
||||
|
||||
int Lua_ItemInst::GetCharges() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetCharges();
|
||||
@ -497,6 +502,7 @@ luabind::scope lua_register_iteminst() {
|
||||
.def("GetItemID", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetItemID)
|
||||
.def("GetItemLink", (std::string(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItemLink)
|
||||
.def("GetItemScriptID", (uint32(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItemScriptID)
|
||||
.def("GetItemType", (uint8(Lua_ItemInst::*)(void)) & Lua_ItemInst::GetItemType)
|
||||
.def("GetMaxEvolveLvl", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetMaxEvolveLvl)
|
||||
.def("GetName", (std::string(Lua_ItemInst::*)(void))&Lua_ItemInst::GetName)
|
||||
.def("GetSerialNumber", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetSerialNumber)
|
||||
|
||||
@ -71,6 +71,7 @@ public:
|
||||
bool IsAmmo();
|
||||
uint32 GetID();
|
||||
uint32 GetItemScriptID();
|
||||
uint8 GetItemType();
|
||||
int GetCharges();
|
||||
void SetCharges(int charges);
|
||||
uint32 GetPrice();
|
||||
|
||||
@ -160,8 +160,10 @@ const char *LuaEvents[_LargestEventID] = {
|
||||
"event_language_skill_up",
|
||||
"event_alt_currency_merchant_buy",
|
||||
"event_alt_currency_merchant_sell",
|
||||
"event_merchant_open",
|
||||
"event_merchant_buy",
|
||||
"event_merchant_sell",
|
||||
"event_merchant_presell",
|
||||
"event_inspect",
|
||||
"event_task_before_update",
|
||||
"event_aa_buy",
|
||||
@ -335,8 +337,10 @@ LuaParser::LuaParser() {
|
||||
PlayerArgumentDispatch[EVENT_LANGUAGE_SKILL_UP] = handle_player_language_skill_up;
|
||||
PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_BUY] = handle_player_alt_currency_merchant;
|
||||
PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_SELL] = handle_player_alt_currency_merchant;
|
||||
PlayerArgumentDispatch[EVENT_MERCHANT_OPEN] = handle_player_merchant_open;
|
||||
PlayerArgumentDispatch[EVENT_MERCHANT_BUY] = handle_player_merchant;
|
||||
PlayerArgumentDispatch[EVENT_MERCHANT_SELL] = handle_player_merchant;
|
||||
PlayerArgumentDispatch[EVENT_MERCHANT_PRESELL] = handle_player_merchant_presell;
|
||||
PlayerArgumentDispatch[EVENT_INSPECT] = handle_player_inspect;
|
||||
PlayerArgumentDispatch[EVENT_AA_BUY] = handle_player_aa_buy;
|
||||
PlayerArgumentDispatch[EVENT_AA_GAIN] = handle_player_aa_gain;
|
||||
|
||||
@ -2340,6 +2340,53 @@ void handle_player_merchant(
|
||||
lua_setfield(L, -2, "item_cost");
|
||||
}
|
||||
|
||||
void handle_player_merchant_open(
|
||||
QuestInterface* parse,
|
||||
lua_State* L,
|
||||
Client* client,
|
||||
std::string data,
|
||||
uint32 extra_data,
|
||||
std::vector<std::any>* extra_pointers
|
||||
) {
|
||||
if (!extra_pointers || extra_pointers->size() < 1) return;
|
||||
|
||||
auto mob_ptr = std::any_cast<Mob*>(extra_pointers->at(0));
|
||||
if (!mob_ptr) return;
|
||||
|
||||
Lua_Mob l_mob(mob_ptr);
|
||||
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
|
||||
l_mob_o.push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
}
|
||||
|
||||
void handle_player_merchant_presell(
|
||||
QuestInterface* parse,
|
||||
lua_State* L,
|
||||
Client* client,
|
||||
std::string data,
|
||||
uint32 extra_data,
|
||||
std::vector<std::any>* extra_pointers
|
||||
) {
|
||||
Seperator sep(data.c_str());
|
||||
lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "slot_id");
|
||||
lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "item_id");
|
||||
lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "item_type");
|
||||
|
||||
if (!extra_pointers || extra_pointers->size() < 2) return;
|
||||
|
||||
auto mob_ptr = std::any_cast<Mob*>(extra_pointers->at(0));
|
||||
auto inst_ptr = std::any_cast<EQ::ItemInstance*>(extra_pointers->at(1));
|
||||
if (!mob_ptr || !inst_ptr) return;
|
||||
|
||||
Lua_Mob l_mob(mob_ptr);
|
||||
luabind::adl::object(L, l_mob).push(L);
|
||||
lua_setfield(L, -2, "other");
|
||||
|
||||
Lua_ItemInst l_iteminst(inst_ptr);
|
||||
luabind::adl::object(L, l_iteminst).push(L);
|
||||
lua_setfield(L, -2, "item");
|
||||
}
|
||||
|
||||
void handle_player_augment_insert(
|
||||
QuestInterface *parse,
|
||||
lua_State* L,
|
||||
|
||||
@ -671,6 +671,24 @@ void handle_player_merchant(
|
||||
std::vector<std::any> *extra_pointers
|
||||
);
|
||||
|
||||
void handle_player_merchant_open(
|
||||
QuestInterface* parse,
|
||||
lua_State* L,
|
||||
Client* client,
|
||||
std::string data,
|
||||
uint32 extra_data,
|
||||
std::vector<std::any>* extra_pointers
|
||||
);
|
||||
|
||||
void handle_player_merchant_presell(
|
||||
QuestInterface* parse,
|
||||
lua_State* L,
|
||||
Client* client,
|
||||
std::string data,
|
||||
uint32 extra_data,
|
||||
std::vector<std::any>* extra_pointers
|
||||
);
|
||||
|
||||
void handle_player_inspect(
|
||||
QuestInterface *parse,
|
||||
lua_State* L,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user