Trader Direct purchase updated and tested

This commit is contained in:
Mitch Freeman
2025-04-06 23:34:05 -03:00
parent 868815e658
commit 6ede52c004
19 changed files with 687 additions and 788 deletions
+11 -5
View File
@@ -12702,7 +12702,7 @@ uint16 Client::GetSkill(EQ::skills::SkillType skill_id) const
return 0;
}
void Client::RemoveItemBySerialNumber(const std::string &item_unique_id, uint32 quantity)
bool Client::RemoveItemByItemUniqueId(const std::string &item_unique_id, uint32 quantity)
{
EQ::ItemInstance *item = nullptr;
uint32 removed_count = 0;
@@ -12717,18 +12717,24 @@ void Client::RemoveItemBySerialNumber(const std::string &item_unique_id, uint32
if (item && item->GetUniqueID().compare(item_unique_id) == 0) {
uint32 charges = item->IsStackable() ? item->GetCharges() : 0;
uint32 stack_size = std::max(charges, static_cast<uint32>(1));
if ((removed_count + stack_size) <= quantity) {
if (removed_count + stack_size <= quantity) {
removed_count += stack_size;
DeleteItemInInventory(slot_id, charges, true);
if (DeleteItemInInventory(slot_id, charges, true)) {
return true;
}
} else {
uint32 amount_left = (quantity - removed_count);
uint32 amount_left = quantity - removed_count;
if (amount_left > 0 && stack_size >= amount_left) {
removed_count += amount_left;
DeleteItemInInventory(slot_id, amount_left, true);
if (DeleteItemInInventory(slot_id, amount_left, true)) {
return true;
}
}
}
}
}
return false;
}
void Client::SendTopLevelInventory()
+17 -8
View File
@@ -314,7 +314,8 @@ public:
void Trader_CustomerBrowsing(Client *Customer);
void TraderEndTrader();
void TraderPriceUpdate(const EQApplicationPacket *app);
//void TraderPriceUpdate(const EQApplicationPacket *app);
void TraderUpdateItem(const EQApplicationPacket *app);
void SendBazaarDone(uint32 trader_id);
void SendBulkBazaarTraders();
void SendBulkBazaarBuyers();
@@ -375,11 +376,12 @@ public:
uint32 FindTraderItemSerialNumber(int32 ItemID);
EQ::ItemInstance* FindTraderItemBySerialNumber(std::string &serial_number);
EQ::ItemInstance* FindTraderItemByUniqueID(std::string &unique_id);
void FindAndNukeTraderItem(std::string &serial_number, int16 quantity, Client* customer, uint16 trader_slot);
EQ::ItemInstance* FindTraderItemByUniqueID(const char* unique_id);
void FindAndNukeTraderItem(std::string &item_unique_id, int16 quantity, Client* customer, uint16 trader_slot);
void NukeTraderItem(uint16 slot, int16 charges, int16 quantity, Client* customer, uint16 trader_slot, const std::string &serial_number, int32 item_id = 0);
void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0);
void TradeRequestFailed(const EQApplicationPacket* app);
void BuyTraderItem(TraderBuy_Struct* tbs, Client* trader, const EQApplicationPacket* app);
void BuyTraderItem(const EQApplicationPacket* app);
void BuyTraderItemOutsideBazaar(TraderBuy_Struct* tbs, const EQApplicationPacket* app);
void FinishTrade(
Mob *with,
@@ -416,9 +418,15 @@ public:
void SendBecomeTraderToWorld(Client *trader, BazaarTraderBarterActions action);
void SendBecomeTrader(BazaarTraderBarterActions action, uint32 trader_id);
bool IsThereACustomer() const { return customer_id ? true : false; }
bool IsThereACustomer() const { return customer_id ? true : false; }
uint32 GetCustomerID() { return customer_id; }
void SetCustomerID(uint32 id) { customer_id = id; }
void SetCustomerID(uint32 id) { customer_id = id; }
void ClearTraderMerchantList() { m_trader_merchant_list.clear(); }
void AddDataToMerchantList(int16 slot_id, int32 quantity, const std::string &item_unique_id);
std::tuple<int16, std::string> GetDataFromMerchantListByMerchantSlotId(int16 slot_id);
int16 GetSlotFromMerchantListByItemUniqueId(const std::string &unique_id);
std::pair<int16, std::tuple<uint32, std::string>> GetDataFromMerchantListByItemUniqueId(const std::string &unique_id);
std::map<int16, std::tuple<uint32, std::string>>* GetTraderMerchantList() { return &m_trader_merchant_list; }
void SetBuyerID(uint32 id) { m_buyer_id = id; }
uint32 GetBuyerID() { return m_buyer_id; }
@@ -587,7 +595,7 @@ public:
void DisableAreaRegens();
void ServerFilter(SetServerFilter_Struct* filter);
void BulkSendTraderInventory(uint32 char_id);
void BulkSendTraderInventory(uint32 character_id);
void SendSingleTraderItem(uint32 char_id, const std::string &serial_number);
void BulkSendMerchantInventory(int merchant_id, int npcid);
@@ -1145,13 +1153,13 @@ public:
bool FindNumberOfFreeInventorySlotsWithSizeCheck(std::vector<BuyerLineTradeItems_Struct> items);
bool PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update = false);
void SendCursorBuffer();
void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true);
bool DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true);
uint32 CountItem(uint32 item_id);
void ResetItemCooldown(uint32 item_id);
void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1);
uint32 GetItemCooldown(uint32 item_id);
void RemoveItem(uint32 item_id, uint32 quantity = 1);
void RemoveItemBySerialNumber(const std::string &item_unique_id, uint32 quantity = 1);
bool RemoveItemByItemUniqueId(const std::string &item_unique_id, uint32 quantity = 1);
bool SwapItem(MoveItem_Struct* move_in);
void SwapItemResync(MoveItem_Struct* move_slots);
void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, LootItem** bag_item_data = 0);
@@ -2104,6 +2112,7 @@ private:
uint8 mercSlot; // selected merc slot
time_t m_trader_transaction_date;
uint32 m_trader_count{};
std::map<int16, std::tuple<uint32, std::string>> m_trader_merchant_list{};
uint32 m_buyer_id;
uint32 m_barter_time;
int32 m_parcel_platinum;
+3 -3
View File
@@ -386,7 +386,7 @@ bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst)
PlayerEvent::EvolveItem e{};
RemoveItemBySerialNumber(inst.GetUniqueID());
RemoveItemByItemUniqueId(inst.GetUniqueID());
EvolvingItemsManager::Instance()->LoadPlayerEvent(inst, e);
e.status = "Evolved Item due to obtaining progression - Old Evolve Item removed from inventory.";
RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e);
@@ -506,7 +506,7 @@ void Client::DoEvolveTransferXP(const EQApplicationPacket *app)
PlayerEvent::EvolveItem e{};
RemoveItemBySerialNumber(inst_from->GetUniqueID());
RemoveItemByItemUniqueId(inst_from->GetUniqueID());
EvolvingItemsManager::Instance()->LoadPlayerEvent(*inst_from, e);
e.status = "Transfer XP - Original FROM Evolve Item removed from inventory.";
RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e);
@@ -516,7 +516,7 @@ void Client::DoEvolveTransferXP(const EQApplicationPacket *app)
e.status = "Transfer XP - Updated FROM item placed in inventory.";
RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e);
RemoveItemBySerialNumber(inst_to->GetUniqueID());
RemoveItemByItemUniqueId(inst_to->GetUniqueID());
EvolvingItemsManager::Instance()->LoadPlayerEvent(*inst_to, e);
e.status = "Transfer XP - Original TO Evolve Item removed from inventory.";
RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e);
+30 -39
View File
@@ -15434,10 +15434,10 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
TraderStartTrader(app);
break;
}
case PriceUpdate:
case ItemMove: {
LogTrading("Trader Price Update");
TraderPriceUpdate(app);
case ItemMove:
case PriceUpdate:{
LogTrading("Trader item updated - removed, added or price change");
TraderUpdateItem(app);
break;
}
case EndTransaction: {
@@ -15456,7 +15456,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
break;
}
default: {
LogError("Unknown size for OP_Trader: [{}]\n", app->size);
LogTrading("Unknown size for OP_Trader: [{}]\n", app->size);
}
}
}
@@ -15467,29 +15467,12 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
//
// Client has elected to buy an item from a Trader
//
auto in = (TraderBuy_Struct *) app->pBuffer;
if (RuleB(Bazaar, UseAlternateBazaarSearch) && in->trader_id >= TraderRepository::TRADER_CONVERT_ID) {
auto sn = std::string(in->serial_number);
auto trader = TraderRepository::GetTraderByInstanceAndSerialnumber(
database,
in->trader_id - TraderRepository::TRADER_CONVERT_ID,
sn
);
if (!trader.trader_id) {
LogTrading("Unable to convert trader id for {} and serial number {}. Trader Buy aborted.",
in->trader_id - TraderRepository::TRADER_CONVERT_ID,
in->serial_number
);
return;
}
in->trader_id = trader.trader_id;
strn0cpy(in->seller_name, trader.trader_name.c_str(), sizeof(in->seller_name));
}
auto trader = entity_list.GetClientByID(in->trader_id);
auto in = (TraderBuy_Struct *) app->pBuffer;
auto item_unique_id = std::string(in->item_unique_id);
auto trader_details = TraderRepository::GetTraderByItemUniqueNumber(database, item_unique_id);
auto trader = entity_list.GetClientByID(in->trader_id);
strn0cpy(in->seller_name, trader_details.trader_name.c_str(), sizeof(in->seller_name));
switch (in->method) {
case BazaarByVendor: {
@@ -15499,9 +15482,9 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
in->trader_id,
in->item_id,
in->quantity,
in->serial_number
in->item_unique_id
);
BuyTraderItem(in, trader, app);
BuyTraderItem(app);
}
break;
}
@@ -15525,7 +15508,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
in->trader_id,
in->item_id,
in->quantity,
in->serial_number
in->item_unique_id
);
BuyTraderItemOutsideBazaar(in, app);
break;
@@ -15550,7 +15533,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
in->trader_id,
in->item_id,
in->quantity,
in->serial_number
in->item_unique_id
);
Message(
Chat::Yellow,
@@ -15561,6 +15544,9 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
TradeRequestFailed(app);
break;
}
default: {
}
}
}
@@ -15651,17 +15637,18 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app)
switch (in->Code) {
case ClickTrader: {
LogTrading("Handle_OP_TraderShop case ClickTrader [{}]", in->Code);
auto outapp =
std::make_unique<EQApplicationPacket>(OP_TraderShop, static_cast<uint32>(sizeof(TraderClick_Struct))
auto outapp = std::make_unique<EQApplicationPacket>(
OP_TraderShop,
static_cast<uint32>(sizeof(TraderClick_Struct))
);
auto data = (TraderClick_Struct *) outapp->pBuffer;
auto trader_client = entity_list.GetClientByID(in->TraderID);
auto trader = entity_list.GetClientByID(in->TraderID);
if (trader_client) {
data->Approval = trader_client->WithCustomer(GetID());
if (trader) {
data->Approval = trader->WithCustomer(GetID());
LogTrading("Client::Handle_OP_TraderShop: Shop Request ([{}]) to ([{}]) with Approval: [{}]",
GetCleanName(),
trader_client->GetCleanName(),
trader->GetCleanName(),
data->Approval
);
}
@@ -15669,6 +15656,9 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app)
LogTrading("Client::Handle_OP_TraderShop: entity_list.GetClientByID(tcs->traderid)"
" returned a nullptr pointer"
);
auto outapp = new EQApplicationPacket(OP_ShopEndConfirm);
QueuePacket(outapp);
safe_delete(outapp);
return;
}
@@ -15678,8 +15668,9 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app)
QueuePacket(outapp.get());
if (data->Approval) {
BulkSendTraderInventory(trader_client->CharacterID());
trader_client->Trader_CustomerBrowsing(this);
ClearTraderMerchantList();
BulkSendTraderInventory(trader->CharacterID());
trader->Trader_CustomerBrowsing(this);
SetTraderID(in->TraderID);
LogTrading("Client::Handle_OP_TraderShop: Trader Inventory Sent to [{}] from [{}]",
GetID(),
+4 -2
View File
@@ -958,7 +958,7 @@ void Client::SendCursorBuffer()
}
// Remove item from inventory
void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_update, bool update_db) {
bool Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_update, bool update_db) {
#if (EQDEBUG >= 5)
LogDebug("DeleteItemInInventory([{}], [{}], [{}])", slot_id, quantity, (client_update) ? "true":"false");
#endif
@@ -977,7 +977,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_up
QueuePacket(outapp);
safe_delete(outapp);
}
return;
return false;
}
uint64 evolve_id = m_inv[slot_id]->GetEvolveUniqueID();
@@ -1031,6 +1031,8 @@ void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_up
safe_delete(outapp);
}
}
return true;
}
bool Client::PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update)
+1 -1
View File
@@ -458,7 +458,7 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in)
CharacterParcelsContainersRepository::InsertMany(database, all_entries);
}
RemoveItemBySerialNumber(inst->GetUniqueID(), parcel_out.quantity == 0 ? 1 : parcel_out.quantity);
RemoveItemByItemUniqueId(inst->GetUniqueID(), parcel_out.quantity == 0 ? 1 : parcel_out.quantity);
std::unique_ptr<EQApplicationPacket> outapp(new EQApplicationPacket(OP_ShopSendParcel));
QueuePacket(outapp.get());
+3
View File
@@ -309,6 +309,7 @@
#define PLAYER_CHARMED 1461 //You lose control of yourself!
#define TRADER_BUSY 1468 //That Trader is currently with a customer. Please wait until their transaction is finished.
#define SENSE_CORPSE_DIRECTION 1563 //You sense a corpse in this direction.
#define HOW_CAN_YOU_BUY_MORE 1571 //%1 tells you, 'Your inventory appears full! How can you buy more?'
#define DUPE_LORE_MERCHANT 1573 //%1 tells you, 'You already have the lore item, %2, on your person, on your shroud, in the bank, in a real estate, or as an augment in another item. You cannot have more than one of a particular lore item at a time.'
#define QUEUED_TELL 2458 //[queued]
#define QUEUE_TELL_FULL 2459 //[zoing and queue is full]
@@ -466,6 +467,8 @@
#define LDON_NO_LOCKPICK 7564 //You must have a lock pick in your inventory to do this.
#define LDON_WAS_NOT_LOCKED 7565 //%1 was not locked.
#define LDON_WAS_NOT_TRAPPED 7566 //%1 was not trapped
#define DUPLICATE_LORE 7623 //Transaction failed: Duplicate Lore Item!
#define INSUFFICIENT_FUNDS 7632 //Transaction failed: Insufficient funds!
#define GAIN_SINGLE_AA_SINGLE_AA 8019 //You have gained an ability point! You now have %1 ability point.
#define GAIN_SINGLE_AA_MULTI_AA 8020 //You have gained an ability point! You now have %1 ability points.
#define GAIN_MULTI_AA_MULTI_AA 8021 //You have gained %1 ability point(s)! You now have %2 ability point(s).
+357 -496
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -3791,8 +3791,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
}
auto sn = std::string(in->trader_buy_struct.item_unique_id);
auto outapp = std::make_unique<EQApplicationPacket>(OP_Trader, static_cast<uint32>(sizeof(TraderBuy_Struct)));
auto sn = std::string(in->trader_buy_struct.serial_number);
auto data = (TraderBuy_Struct *) outapp->pBuffer;
memcpy(data, &in->trader_buy_struct, sizeof(TraderBuy_Struct));
@@ -3826,7 +3826,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e);
}
trader_pc->RemoveItemBySerialNumber(sn, in->trader_buy_struct.quantity);
trader_pc->RemoveItemByItemUniqueId(sn, in->trader_buy_struct.quantity);
trader_pc->AddMoneyToPP(in->trader_buy_struct.price * in->trader_buy_struct.quantity, true);
trader_pc->QueuePacket(outapp.get());
+6 -6
View File
@@ -343,12 +343,12 @@ std::unique_ptr<EQ::ItemInstance> ZoneDatabase::LoadSingleTraderItem(uint32 char
database.CreateItem(
item_id,
charges,
results.at(0).aug_slot_1,
results.at(0).aug_slot_2,
results.at(0).aug_slot_3,
results.at(0).aug_slot_4,
results.at(0).aug_slot_5,
results.at(0).aug_slot_6
results.at(0).augment_one,
results.at(0).augment_two,
results.at(0).augment_three,
results.at(0).augment_four,
results.at(0).augment_five,
results.at(0).augment_six
)
);
if (!inst) {