This commit is contained in:
Mitch Freeman 2025-04-15 21:39:35 -03:00
parent 885b472340
commit 125457afe6
4 changed files with 135 additions and 28 deletions

View File

@ -245,6 +245,21 @@ public:
return trader_item.at(0);
}
static Trader GetItemByItemUniqueNumber(Database &db, const char* item_unique_id)
{
Trader e{};
const auto trader_item = GetWhere(
db,
fmt::format("`item_unique_id` = '{}' LIMIT 1", item_unique_id)
);
if (trader_item.empty()) {
return e;
}
return trader_item.at(0);
}
static int UpdateActiveTransaction(Database &db, uint32 id, bool status)
{
auto e = FindOne(db, id);
@ -338,7 +353,6 @@ public:
"trader.char_zone_instance_id, trader.active_transaction, c.`name` FROM `trader` "
"INNER JOIN character_data AS c ON trader.character_id = c.id "
"WHERE {} "
"GROUP BY trader.item_id "
"ORDER BY trader.character_id ASC",
search_criteria_trader
);

View File

@ -368,6 +368,14 @@ enum {
UserToWorldStatusAlreadyOnline = -4
};
enum {
BazaarPurchaseFailed = 0,
BazaarPurchaseSuccess = 1,
BazaarPurchaseSellerFailed = 2,
BazaarPurchaseSellerSuccess = 3,
BazaarPurchaseBuyerFailed = 4,
BazaarPurchaseBuyerSuccess = 5
};
/************ PACKET RELATED STRUCT ************/
class ServerPacket
{
@ -1775,8 +1783,11 @@ struct BazaarPurchaseMessaging_Struct {
uint32 item_aug_5;
uint32 item_aug_6;
uint32 buyer_id;
uint32 item_quantity_available;
uint32 item_charges;
uint32 id;
uint32 trader_zone_id;
uint32 trader_zone_instance_id;
uint32 transaction_status;
};

View File

@ -1677,7 +1677,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
auto in = (BazaarPurchaseMessaging_Struct *)pack->pBuffer;
if (in->trader_buy_struct.trader_id <= 0) {
LogTrading(
"World Message <red>[{}] received with invalid trader_id <red>[{}]",
"World Message [{}] received with invalid trader_id [{}]",
"ServerOP_BazaarPurchase",
in->trader_buy_struct.trader_id
);
@ -1686,7 +1686,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
auto trader = ClientList::Instance()->FindCLEByCharacterID(in->trader_buy_struct.trader_id);
if (trader) {
ZSList::Instance()->SendPacket(trader->zone(), trader->instance(), pack);
ZSList::Instance()->SendPacket(in->trader_zone_id, in->trader_zone_instance_id, pack);
}
break;

View File

@ -2773,8 +2773,7 @@ std::string Client::DetermineMoneyString(uint64 cp)
void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
{
auto in = reinterpret_cast<TraderBuy_Struct *>(app->pBuffer);
auto item_unique_id = std::string(in->item_unique_id);
auto trader_item = TraderRepository::GetItemByItemUniqueNumber(database, item_unique_id);
auto trader_item = TraderRepository::GetItemByItemUniqueNumber(database, in->item_unique_id);
LogTradingDetail(
"Packet details: \n"
@ -2836,13 +2835,11 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
return;
}
TraderRepository::UpdateActiveTransaction(database, trader_item.id, true);
auto next_slot = FindNextFreeParcelSlot(CharacterID());
if (next_slot == INVALID_INDEX) {
LogTrading(
"{} attempted to purchase {} from the bazaar with parcel delivery. Unfortunately their parcel limit was reached. "
"Purchase unsuccessful.",
"{} attempted to purchase {} from the bazaar with parcel delivery. Unfortunately their parcel limit was "
"reached. Purchase unsuccessful.",
GetCleanName(),
in->item_name
);
@ -2853,11 +2850,24 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
return;
}
LogTrading(
"Name: [{}] Requested Quantity: [{}] Charges on Item [{}]",
in->item_name,
in->quantity,
trader_item.item_charges
TraderRepository::UpdateActiveTransaction(database, trader_item.id, true);
uint32 quantity = in->quantity;
int16 charges = 1;
auto item = database.GetItem(trader_item.item_id);
if (trader_item.item_charges > 0 || item->Stackable || item->MaxCharges > 0) {
charges = trader_item.item_charges;
}
LogTrading("Name: [{}] Requested Quantity: [{}] Charges: [{}]", in->item_name, quantity, charges);
LogTradingDetail(
"Step 1:Bazaar Purchase. Buyer [{}] Seller [{}] Quantity [{}] Charges [{}] Item_Unique_ID [{}]",
CharacterID(),
in->trader_id,
quantity,
charges,
in->item_unique_id
);
uint64 total_cost = static_cast<uint64>(in->price) * static_cast<uint64>(in->quantity);
@ -2872,7 +2882,7 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
return;
}
uint64 fee = std::round(total_cost * RuleR(Bazaar, ParcelDeliveryCostMod));
uint64 fee = std::round(total_cost * RuleR(Bazaar, ParcelDeliveryCostMod));
if (!TakeMoneyFromPP(total_cost + fee, false)) {
in->method = BazaarByParcel;
in->sub_action = InsufficientFunds;
@ -2882,7 +2892,8 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
}
Message(Chat::Red, fmt::format("You paid {} for the parcel delivery.", DetermineMoneyString(fee)).c_str());
LogTrading("Customer <green>[{}] Paid: <green>[{}] in Copper", CharacterID(), total_cost);
LogTrading("Customer [{}] Paid: [{}] to trader [{}]", CharacterID(), DetermineMoneyString(total_cost), trader_item.character_id);
LogTradingDetail("Step 2:Bazaar Purchase. Took [{}] from Buyer [{}] ", DetermineMoneyString(total_cost), CharacterID());
if (buy_item && PlayerEventLogs::Instance()->IsEventEnabled(PlayerEvent::TRADER_PURCHASE)) {
auto e = PlayerEvent::TraderPurchaseEvent{
@ -2910,7 +2921,7 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
parcel_out.from_name = in->seller_name;
parcel_out.note = "Delivered from a Bazaar Purchase";
parcel_out.sent_date = time(nullptr);
parcel_out.quantity = in->quantity;
parcel_out.quantity = charges;
parcel_out.item_id = trader_item.item_id;
parcel_out.aug_slot_1 = trader_item.augment_one;
parcel_out.aug_slot_2 = trader_item.augment_two;
@ -2934,6 +2945,7 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
in->method = BazaarByParcel;
in->sub_action = Failed;
TraderRepository::UpdateActiveTransaction(database, trader_item.id, false);
AddMoneyToPP(total_cost + fee);
TradeRequestFailed(app);
return;
}
@ -2960,20 +2972,41 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
Parcel_Struct ps{};
ps.item_slot = parcel_out.slot_id;
strn0cpy(ps.send_to, GetCleanName(), sizeof(ps.send_to));
if (trader_item.item_charges <= static_cast<int32>(in->quantity) || !trader_item.item_charges <= 0) {
TraderRepository::DeleteOne(database, trader_item.id);
}
SendParcelDeliveryToWorld(ps);
auto out_server = std::make_unique<ServerPacket>(ServerOP_BazaarPurchase, static_cast<uint32>(sizeof(BazaarPurchaseMessaging_Struct)));
LogTradingDetail("Step 3:Bazaar Purchase. Sent parcel to Buyer [{}] Item ID [{}] Quantity [{}] Charges [{}]",
CharacterID(),
trader_item.item_id,
quantity,
charges
);
if (item->Stackable && quantity != charges) {
TraderRepository::UpdateQuantity(database, in->item_unique_id, trader_item.item_charges - quantity);
LogTradingDetail(
"Step 4a:Bazaar Purchase. Decreased database id {} from [{}] to [{}] charges",
trader_item.item_id,
trader_item.item_charges,
charges
);
}
else {
TraderRepository::DeleteOne(database, trader_item.id);
LogTradingDetail(
"Step 4b:Bazaar Purchase. Deleted database id [{}] because database quantity [{}] equals [{}] purchased quantity",
trader_item.id,
trader_item.item_charges,
charges
);
}
auto out_server = std::make_unique<ServerPacket>(ServerOP_BazaarPurchase, sizeof(BazaarPurchaseMessaging_Struct));
auto out_data = (BazaarPurchaseMessaging_Struct *) out_server->pBuffer;
out_data->trader_buy_struct.action = in->action;
out_data->trader_buy_struct.method = in->method;
out_data->trader_buy_struct.already_sold = in->already_sold;
out_data->trader_buy_struct.item_id = in->item_id;
out_data->trader_buy_struct.item_id = item->ID;
out_data->trader_buy_struct.price = in->price;
out_data->trader_buy_struct.quantity = in->quantity;
out_data->trader_buy_struct.sub_action = in->sub_action;
@ -2985,12 +3018,13 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
out_data->item_aug_4 = trader_item.augment_four;
out_data->item_aug_5 = trader_item.augment_five;
out_data->item_aug_6 = trader_item.augment_six;
out_data->item_quantity_available = trader_item.item_charges;
out_data->item_charges = trader_item.item_charges;
out_data->id = trader_item.id;
out_data->trader_zone_id = trader_item.char_zone_id;
out_data->trader_zone_instance_id = trader_item.char_zone_instance_id;
strn0cpy(out_data->trader_buy_struct.buyer_name, GetCleanName(), sizeof(out_data->trader_buy_struct.buyer_name));
strn0cpy(out_data->trader_buy_struct.buyer_name, in->buyer_name, sizeof(out_data->trader_buy_struct.buyer_name));
strn0cpy(out_data->trader_buy_struct.item_name, in->item_name, sizeof(out_data->trader_buy_struct.item_name));
strn0cpy(out_data->trader_buy_struct.seller_name, in->seller_name, sizeof(out_data->trader_buy_struct.seller_name));
strn0cpy(out_data->trader_buy_struct.item_name, in->item_name, sizeof(out_data->trader_buy_struct.item_name));
strn0cpy(
out_data->trader_buy_struct.item_unique_id,
in->item_unique_id,
@ -2998,8 +3032,56 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
);
worldserver.SendPacket(out_server.get());
LogTradingDetail("Step 5:Bazaar Purchase. Send bazaar messaging data to world.\n"
"Action: {} \n"
"Sub Action: {} \n"
"Method: {} \n"
"Item ID: {} \n"
"Item Unique ID: {} \n"
"Item Name: {} \n"
"Price: {} \n"
"Quantity: {} \n"
"Charges: {} \n"
"Augment One: {} \n"
"Augment Two: {} \n"
"Augment Three: {} \n"
"Augment Four: {} \n"
"Augment Five: {} \n"
"Augment Six: {} \n"
"Already Sold: {} \n"
"DB ID: {} \n"
"Trader ID: {} \n"
"Trader: {} \n"
"Trader Zone ID {} \n"
"Trader Zone Instance ID {} \n"
"Buyer ID: {} \n"
"Buyer: {} \n",
out_data->trader_buy_struct.action,
out_data->trader_buy_struct.sub_action,
out_data->trader_buy_struct.method,
out_data->trader_buy_struct.item_id,
out_data->trader_buy_struct.item_unique_id,
out_data->trader_buy_struct.item_name,
out_data->trader_buy_struct.price,
out_data->trader_buy_struct.quantity,
out_data->item_charges,
out_data->item_aug_1,
out_data->item_aug_2,
out_data->item_aug_3,
out_data->item_aug_4,
out_data->item_aug_5,
out_data->item_aug_6,
out_data->trader_buy_struct.already_sold,
out_data->id,
out_data->trader_buy_struct.trader_id,
out_data->trader_buy_struct.seller_name,
out_data->trader_zone_id,
out_data->trader_zone_instance_id,
out_data->buyer_id,
out_data->trader_buy_struct.buyer_name);
SendMoneyUpdate();
LogTradingDetail("Step 6:Bazaar Purchase. Send money update to client {}. Buyer Actions complete.", CharacterID());
}
void Client::SetBuyerWelcomeMessage(const char *welcome_message)