Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app)
- {
- if (app->size != sizeof(Merchant_Sell_Struct)) {
- LogFile->write(EQEMuLog::Error, "Invalid size on OP_ShopPlayerBuy: Expected %i, Got %i",
- sizeof(Merchant_Sell_Struct), app->size);
- return;
- }
- RDTSC_Timer t1;
- t1.start();
- Merchant_Sell_Struct* mp = (Merchant_Sell_Struct*)app->pBuffer;
- #if EQDEBUG >= 5
- LogFile->write(EQEMuLog::Debug, "%s, purchase item..", GetName());
- DumpPacket(app);
- #endif
- int merchantid;
- bool tmpmer_used = false;
- Mob* tmp = entity_list.GetMob(mp->npcid);
- if (tmp == 0 || !tmp->IsNPC() || tmp->GetClass() != MERCHANT)
- return;
- if (mp->quantity < 1) return;
- //you have to be somewhat close to them to be properly using them
- if (DistNoRoot(*tmp) > USE_NPC_RANGE2)
- return;
- merchantid = tmp->CastToNPC()->MerchantType;
- uint32 item_id = 0;
- std::list<MerchantList> merlist = zone->merchanttable[merchantid];
- std::list<MerchantList>::const_iterator itr;
- for (itr = merlist.begin(); itr != merlist.end(); ++itr){
- MerchantList ml = *itr;
- if (GetLevel() < ml.level_required) {
- continue;
- }
- int32 fac = tmp->GetPrimaryFaction();
- if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required) {
- continue;
- }
- if (mp->itemslot == ml.slot){
- item_id = ml.item;
- break;
- }
- }
- const Item_Struct* item = nullptr;
- uint32 prevcharges = 0;
- if (item_id == 0) { //check to see if its on the temporary table
- std::list<TempMerchantList> tmp_merlist = zone->tmpmerchanttable[tmp->GetNPCTypeID()];
- std::list<TempMerchantList>::const_iterator tmp_itr;
- TempMerchantList ml;
- for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr){
- ml = *tmp_itr;
- if (mp->itemslot == ml.slot){
- item_id = ml.item;
- tmpmer_used = true;
- prevcharges = ml.charges;
- break;
- }
- }
- }
- item = database.GetItem(item_id);
- if (!item){
- //error finding item, client didnt get the update packet for whatever reason, roleplay a tad
- Message(15, "%s tells you 'Sorry, that item is for display purposes only.' as they take the item off the shelf.", tmp->GetCleanName());
- EQApplicationPacket* delitempacket = new EQApplicationPacket(OP_ShopDelItem, sizeof(Merchant_DelItem_Struct));
- Merchant_DelItem_Struct* delitem = (Merchant_DelItem_Struct*)delitempacket->pBuffer;
- delitem->itemslot = mp->itemslot;
- delitem->npcid = mp->npcid;
- delitem->playerid = mp->playerid;
- delitempacket->priority = 6;
- entity_list.QueueCloseClients(tmp, delitempacket); //que for anyone that could be using the merchant so they see the update
- safe_delete(delitempacket);
- return;
- }
- if (CheckLoreConflict(item))
- {
- Message(15, "You can only have one of a lore item.");
- return;
- }
- if (tmpmer_used && (mp->quantity > prevcharges || item->MaxCharges > 1))
- {
- if (prevcharges > item->MaxCharges && item->MaxCharges > 1)
- mp->quantity = item->MaxCharges;
- else
- mp->quantity = prevcharges;
- }
- EQApplicationPacket* outapp = new EQApplicationPacket(OP_ShopPlayerBuy, sizeof(Merchant_Sell_Struct));
- Merchant_Sell_Struct* mpo = (Merchant_Sell_Struct*)outapp->pBuffer;
- mpo->quantity = mp->quantity;
- mpo->playerid = mp->playerid;
- mpo->npcid = mp->npcid;
- mpo->itemslot = mp->itemslot;
- int16 freeslotid = INVALID_INDEX;
- int16 charges = 0;
- if (item->Stackable || item->MaxCharges > 1)
- charges = mp->quantity;
- else
- charges = item->MaxCharges;
- ItemInst* inst = database.CreateItem(item, charges);
- int SinglePrice = 0;
- if (RuleB(Merchant, UsePriceMod))
- SinglePrice = (item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(tmp, false));
- else
- SinglePrice = (item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate);
- if (item->MaxCharges > 1)
- mpo->price = SinglePrice;
- else
- mpo->price = SinglePrice * mp->quantity;
- if (mpo->price < 0)
- {
- safe_delete(outapp);
- safe_delete(inst);
- return;
- }
- // this area needs some work..two inventory insertion check failure points
- // below do not return player's money..is this the intended behavior?
- if (!TakeMoneyFromPP(mpo->price))
- {
- char *hacker_str = nullptr;
- MakeAnyLenString(&hacker_str, "Vendor Cheat: attempted to buy %i of %i: %s that cost %d cp but only has %d pp %d gp %d sp %d cp\n",
- mpo->quantity, item->ID, item->Name,
- mpo->price, m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper);
- database.SetMQDetectionFlag(AccountName(), GetName(), hacker_str, zone->GetShortName());
- safe_delete_array(hacker_str);
- safe_delete(outapp);
- safe_delete(inst);
- return;
- }
- bool stacked = TryStacking(inst);
- if (!stacked)
- freeslotid = m_inv.FindFreeSlot(false, true, item->Size);
- // shouldn't we be reimbursing if these two fail?
- //make sure we are not completely full...
- if (freeslotid == MainCursor) {
- if (m_inv.GetItem(MainCursor) != nullptr) {
- Message(13, "You do not have room for any more items.");
- safe_delete(outapp);
- safe_delete(inst);
- return;
- }
- }
- if (!stacked && freeslotid == INVALID_INDEX)
- {
- Message(13, "You do not have room for any more items.");
- safe_delete(outapp);
- safe_delete(inst);
- return;
- }
- std::string packet;
- if (!stacked && inst) {
- PutItemInInventory(freeslotid, *inst);
- SendItemPacket(freeslotid, inst, ItemPacketTrade);
- }
- else if (!stacked){
- LogFile->write(EQEMuLog::Error, "OP_ShopPlayerBuy: item->ItemClass Unknown! Type: %i", item->ItemClass);
- }
- QueuePacket(outapp);
- if (inst && tmpmer_used){
- int32 new_charges = prevcharges - mp->quantity;
- zone->SaveTempItem(merchantid, tmp->GetNPCTypeID(), item_id, new_charges);
- if (new_charges <= 0){
- EQApplicationPacket* delitempacket = new EQApplicationPacket(OP_ShopDelItem, sizeof(Merchant_DelItem_Struct));
- Merchant_DelItem_Struct* delitem = (Merchant_DelItem_Struct*)delitempacket->pBuffer;
- delitem->itemslot = mp->itemslot;
- delitem->npcid = mp->npcid;
- delitem->playerid = mp->playerid;
- delitempacket->priority = 6;
- entity_list.QueueClients(tmp, delitempacket); //que for anyone that could be using the merchant so they see the update
- safe_delete(delitempacket);
- }
- else {
- // Update the charges/quantity in the merchant window
- inst->SetCharges(new_charges);
- inst->SetPrice(SinglePrice);
- inst->SetMerchantSlot(mp->itemslot);
- inst->SetMerchantCount(new_charges);
- SendItemPacket(mp->itemslot, inst, ItemPacketMerchant);
- }
- }
- safe_delete(inst);
- safe_delete(outapp);
- // start QS code
- // stacking purchases not supported at this time - entire process will need some work to catch them properly
- if (RuleB(QueryServ, PlayerLogMerchantTransactions)) {
- ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, sizeof(QSMerchantLogTransaction_Struct)+sizeof(QSTransactionItems_Struct));
- QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer;
- qsaudit->zone_id = zone->GetZoneID();
- qsaudit->merchant_id = tmp->CastToNPC()->MerchantType;
- qsaudit->merchant_money.platinum = 0;
- qsaudit->merchant_money.gold = 0;
- qsaudit->merchant_money.silver = 0;
- qsaudit->merchant_money.copper = 0;
- qsaudit->merchant_count = 1;
- qsaudit->char_id = character_id;
- qsaudit->char_money.platinum = (mpo->price / 1000);
- qsaudit->char_money.gold = (mpo->price / 100) % 10;
- qsaudit->char_money.silver = (mpo->price / 10) % 10;
- qsaudit->char_money.copper = mpo->price % 10;
- qsaudit->char_count = 0;
- qsaudit->items[0].char_slot = freeslotid == INVALID_INDEX ? 0 : freeslotid;
- qsaudit->items[0].item_id = item->ID;
- qsaudit->items[0].charges = mpo->quantity;
- if(freeslotid == INVALID_INDEX) {
- qsaudit->items[0].aug_1 = 0;
- qsaudit->items[0].aug_2 = 0;
- qsaudit->items[0].aug_3 = 0;
- qsaudit->items[0].aug_4 = 0;
- qsaudit->items[0].aug_5 = 0;
- } else {
- qsaudit->items[0].aug_1 = m_inv[freeslotid]->GetAugmentItemID(0);
- qsaudit->items[0].aug_2 = m_inv[freeslotid]->GetAugmentItemID(1);
- qsaudit->items[0].aug_3 = m_inv[freeslotid]->GetAugmentItemID(2);
- qsaudit->items[0].aug_4 = m_inv[freeslotid]->GetAugmentItemID(3);
- qsaudit->items[0].aug_5 = m_inv[freeslotid]->GetAugmentItemID(4);
- }
- qspack->Deflate();
- if (worldserver.Connected()) { worldserver.SendPacket(qspack); }
- safe_delete(qspack);
- }
- // end QS code
- if (RuleB(EventLog, RecordBuyFromMerchant))
- LogMerchant(this, tmp, mpo->quantity, mpo->price, item, true);
- if ((RuleB(Character, EnableDiscoveredItems)))
- {
- if (!GetGM() && !IsDiscovered(item_id))
- DiscoverItem(item_id);
- }
- t1.stop();
- std::cout << "At 1: " << t1.getDuration() << std::endl;
- return;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement