This commit is contained in:
Mitch Freeman 2025-04-17 22:37:22 -03:00
parent 125457afe6
commit 93c38f5e24
6 changed files with 271 additions and 191 deletions

View File

@ -48,6 +48,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
ClientUnknown::constants::EXPANSIONS_MASK,
ClientUnknown::INULL,
ClientUnknown::INULL,
ClientUnknown::INULL,
ClientUnknown::INULL
),
/*[ClientVersion::Client62] =*/
@ -57,6 +58,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
Client62::constants::EXPANSIONS_MASK,
Client62::INULL,
Client62::INULL,
Client62::INULL,
Client62::INULL
),
/*[ClientVersion::Titanium] =*/
@ -66,6 +68,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
Titanium::constants::EXPANSIONS_MASK,
Titanium::constants::CHARACTER_CREATION_LIMIT,
Titanium::constants::SAY_LINK_BODY_SIZE,
Titanium::INULL,
Titanium::INULL
),
/*[ClientVersion::SoF] =*/
@ -75,6 +78,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
SoF::constants::EXPANSIONS_MASK,
SoF::constants::CHARACTER_CREATION_LIMIT,
SoF::constants::SAY_LINK_BODY_SIZE,
SoF::INULL,
SoF::INULL
),
/*[ClientVersion::SoD] =*/
@ -84,6 +88,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
SoD::constants::EXPANSIONS_MASK,
SoD::constants::CHARACTER_CREATION_LIMIT,
SoD::constants::SAY_LINK_BODY_SIZE,
SoD::INULL,
SoD::INULL
),
/*[ClientVersion::UF] =*/
@ -93,6 +98,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
UF::constants::EXPANSIONS_MASK,
UF::constants::CHARACTER_CREATION_LIMIT,
UF::constants::SAY_LINK_BODY_SIZE,
UF::INULL,
UF::INULL
),
/*[ClientVersion::RoF] =*/
@ -102,6 +108,7 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
RoF::constants::EXPANSIONS_MASK,
RoF::constants::CHARACTER_CREATION_LIMIT,
RoF::constants::SAY_LINK_BODY_SIZE,
RoF::INULL,
RoF::INULL
),
/*[ClientVersion::RoF2] =*/
@ -111,7 +118,8 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
RoF2::constants::EXPANSIONS_MASK,
RoF2::constants::CHARACTER_CREATION_LIMIT,
RoF2::constants::SAY_LINK_BODY_SIZE,
RoF2::constants::MAX_BAZAAR_TRADERS
RoF2::constants::MAX_BAZAAR_TRADERS,
RoF2::constants::MAX_BAZAAR_TRANSACTION
)
};

View File

@ -43,6 +43,7 @@ namespace EQ
int16 CharacterCreationLimit;
size_t SayLinkBodySize;
uint32 BazaarTraderLimit;
uint32 BazaarMaxTransaction;
LookupEntry(const LookupEntry *lookup_entry) { }
LookupEntry(
@ -51,14 +52,16 @@ namespace EQ
uint32 ExpansionsMask,
int16 CharacterCreationLimit,
size_t SayLinkBodySize,
uint32 BazaarTraderLimit
uint32 BazaarTraderLimit,
uint32 BazaarMaxTransaction
) :
Expansion(Expansion),
ExpansionBit(ExpansionBit),
ExpansionsMask(ExpansionsMask),
CharacterCreationLimit(CharacterCreationLimit),
SayLinkBodySize(SayLinkBodySize),
BazaarTraderLimit(BazaarTraderLimit)
BazaarTraderLimit(BazaarTraderLimit),
BazaarMaxTransaction(BazaarMaxTransaction)
{ }
};

View File

@ -369,12 +369,13 @@ enum {
};
enum {
BazaarPurchaseFailed = 0,
BazaarPurchaseSuccess = 1,
BazaarPurchaseSellerFailed = 2,
BazaarPurchaseSellerSuccess = 3,
BazaarPurchaseBuyerFailed = 4,
BazaarPurchaseBuyerSuccess = 5
BazaarPurchaseFailed = 0,
BazaarPurchaseSuccess = 1,
BazaarPurchaseBuyerCompleteSendToSeller = 2,
BazaarPurchaseSellerCompleteSendToBuyer = 3,
BazaarPurchaseBuyerFailed = 4,
BazaarPurchaseBuyerSuccess = 5,
BazaarPurchaseTraderFailed = 6
};
/************ PACKET RELATED STRUCT ************/
class ServerPacket
@ -1783,10 +1784,13 @@ struct BazaarPurchaseMessaging_Struct {
uint32 item_aug_5;
uint32 item_aug_6;
uint32 buyer_id;
uint32 item_charges;
uint32 item_quantity;
int16 item_charges;
uint32 id;
uint32 trader_zone_id;
uint32 trader_zone_instance_id;
uint32 buyer_zone_id;
uint32 buyer_zone_instance_id;
uint32 transaction_status;
};

View File

@ -1674,21 +1674,23 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
break;
}
case ServerOP_BazaarPurchase: {
auto in = (BazaarPurchaseMessaging_Struct *)pack->pBuffer;
if (in->trader_buy_struct.trader_id <= 0) {
LogTrading(
"World Message [{}] received with invalid trader_id [{}]",
"ServerOP_BazaarPurchase",
in->trader_buy_struct.trader_id
);
return;
auto in = reinterpret_cast<BazaarPurchaseMessaging_Struct *>(pack->pBuffer);
switch (in->transaction_status) {
case BazaarPurchaseBuyerCompleteSendToSeller: {
zoneserver_list.SendPacket(in->trader_zone_id, in->trader_zone_instance_id, pack);
break;
}
case BazaarPurchaseTraderFailed:
case BazaarPurchaseSuccess: {
zoneserver_list.SendPacket(in->buyer_zone_id, in->buyer_zone_instance_id, pack);
break;
}
default: {
LogError(
"ServerOP_BazaarPurchase received with no corresponding action for [{}]",
in->transaction_status);
}
}
auto trader = ClientList::Instance()->FindCLEByCharacterID(in->trader_buy_struct.trader_id);
if (trader) {
ZSList::Instance()->SendPacket(in->trader_zone_id, in->trader_zone_instance_id, pack);
}
break;
}
case ServerOP_BuyerMessaging: {

View File

@ -1462,11 +1462,11 @@ void Client::BuyTraderItem(const EQApplicationPacket *app)
}
uint64 total_transaction_value = static_cast<uint64>(in->price) * static_cast<uint64>(quantity);
if (total_transaction_value > RoF2::constants::MAX_BAZAAR_TRANSACTION) {
if (total_transaction_value > EQ::constants::StaticLookup(ClientVersion())->BazaarMaxTransaction) {
Message(
Chat::Red,
"That would exceed the single transaction limit of %u platinum.",
RoF2::constants::MAX_BAZAAR_TRANSACTION / 1000
EQ::constants::StaticLookup(ClientVersion())->BazaarMaxTransaction / 1000
);
TradeRequestFailed(app);
return;
@ -2853,9 +2853,9 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
TraderRepository::UpdateActiveTransaction(database, trader_item.id, true);
uint32 quantity = in->quantity;
int16 charges = 1;
auto item = database.GetItem(trader_item.item_id);
auto item = database.GetItem(trader_item.item_id);
int16 charges = 1;
if (trader_item.item_charges > 0 || item->Stackable || item->MaxCharges > 0) {
charges = trader_item.item_charges;
}
@ -2870,12 +2870,12 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
in->item_unique_id
);
uint64 total_cost = static_cast<uint64>(in->price) * static_cast<uint64>(in->quantity);
if (total_cost > RoF2::constants::MAX_BAZAAR_TRANSACTION) {
uint64 total_cost = static_cast<uint64>(in->price) * static_cast<uint64>(quantity);
if (total_cost > EQ::constants::StaticLookup(ClientVersion())->BazaarMaxTransaction) {
Message(
Chat::Red,
"That would exceed the single transaction limit of %u platinum.",
RoF2::constants::MAX_BAZAAR_TRANSACTION / 1000
EQ::constants::StaticLookup(ClientVersion())->BazaarMaxTransaction / 1000
);
TraderRepository::UpdateActiveTransaction(database, trader_item.id, false);
TradeRequestFailed(app);
@ -2895,114 +2895,10 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
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{
.item_id = trader_item.item_id,
.augment_1_id = trader_item.augment_one,
.augment_2_id = trader_item.augment_two,
.augment_3_id = trader_item.augment_three,
.augment_4_id = trader_item.augment_four,
.augment_5_id = trader_item.augment_five,
.augment_6_id = trader_item.augment_six,
.item_name = in->item_name,
.trader_id = in->trader_id,
.trader_name = in->seller_name,
.price = in->price,
.quantity = in->quantity,
.charges = trader_item.item_charges,
.total_cost = total_cost,
.player_money_balance = GetCarriedMoney(),
};
RecordPlayerEventLog(PlayerEvent::TRADER_PURCHASE, e);
}
CharacterParcelsRepository::CharacterParcels parcel_out{};
parcel_out.from_name = in->seller_name;
parcel_out.note = "Delivered from a Bazaar Purchase";
parcel_out.sent_date = time(nullptr);
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;
parcel_out.aug_slot_3 = trader_item.augment_three;
parcel_out.aug_slot_4 = trader_item.augment_four;
parcel_out.aug_slot_5 = trader_item.augment_five;
parcel_out.aug_slot_6 = trader_item.augment_six;
parcel_out.char_id = CharacterID();
parcel_out.slot_id = next_slot;
parcel_out.id = 0;
auto result = CharacterParcelsRepository::InsertOne(database, parcel_out);
if (!result.id) {
LogError("Failed to add parcel to database. From {} to {} item {} quantity {}",
parcel_out.from_name,
GetCleanName(),
parcel_out.item_id,
parcel_out.quantity
);
Message(Chat::Yellow, "Unable to save parcel to the database. Please contact an administrator.");
in->method = BazaarByParcel;
in->sub_action = Failed;
TraderRepository::UpdateActiveTransaction(database, trader_item.id, false);
AddMoneyToPP(total_cost + fee);
TradeRequestFailed(app);
return;
}
ReturnTraderReq(app, in->quantity, trader_item.item_id);
if (PlayerEventLogs::Instance()->IsEventEnabled(PlayerEvent::PARCEL_SEND)) {
PlayerEvent::ParcelSend e{};
e.from_player_name = parcel_out.from_name;
e.to_player_name = GetCleanName();
e.item_id = parcel_out.item_id;
e.augment_1_id = parcel_out.aug_slot_1;
e.augment_2_id = parcel_out.aug_slot_2;
e.augment_3_id = parcel_out.aug_slot_3;
e.augment_4_id = parcel_out.aug_slot_4;
e.augment_5_id = parcel_out.aug_slot_5;
e.augment_6_id = parcel_out.aug_slot_6;
e.quantity = in->quantity;
e.charges = trader_item.item_charges;
e.sent_date = parcel_out.sent_date;
RecordPlayerEventLog(PlayerEvent::PARCEL_SEND, e);
}
Parcel_Struct ps{};
ps.item_slot = parcel_out.slot_id;
strn0cpy(ps.send_to, GetCleanName(), sizeof(ps.send_to));
SendParcelDeliveryToWorld(ps);
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;
auto out_data = reinterpret_cast<BazaarPurchaseMessaging_Struct *>(out_server->pBuffer);
out_data->transaction_status = BazaarPurchaseBuyerCompleteSendToSeller;
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;
@ -3010,7 +2906,7 @@ void Client::BuyTraderItemFromBazaarWindow(const EQApplicationPacket *app)
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;
out_data->trader_buy_struct.trader_id = in->trader_id;
out_data->trader_buy_struct.trader_id = trader_item.character_id;
out_data->buyer_id = CharacterID();
out_data->item_aug_1 = trader_item.augment_one;
out_data->item_aug_2 = trader_item.augment_two;
@ -3018,10 +2914,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_charges = trader_item.item_charges;
out_data->item_quantity = quantity;
out_data->item_charges = 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;
out_data->buyer_zone_id = GetZoneID();
out_data->buyer_zone_instance_id = GetInstanceID();
strn0cpy(out_data->trader_buy_struct.buyer_name, GetCleanName(), sizeof(out_data->trader_buy_struct.buyer_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));

View File

@ -3774,62 +3774,226 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
break;
}
case ServerOP_BazaarPurchase: {
auto in = (BazaarPurchaseMessaging_Struct *) pack->pBuffer;
auto trader_pc = entity_list.GetClientByCharID(in->trader_buy_struct.trader_id);
if (!trader_pc) {
LogTrading("Request trader_id <red>[{}] could not be found in zone_id <red>[{}]",
in->trader_buy_struct.trader_id,
zone->GetZoneID()
);
return;
}
auto in = reinterpret_cast<BazaarPurchaseMessaging_Struct *>(pack->pBuffer);
switch (in->transaction_status) {
case BazaarPurchaseBuyerCompleteSendToSeller: {
auto trader_pc = entity_list.GetClientByCharID(in->trader_buy_struct.trader_id);
if (!trader_pc) {
LogTrading(
"Request trader_id <red>[{}] could not be found in zone_id <red>[{}]",
in->trader_buy_struct.trader_id,
zone->GetZoneID());
return;
}
if (trader_pc->IsThereACustomer()) {
auto customer = entity_list.GetClientByID(trader_pc->GetCustomerID());
if (customer) {
customer->CancelTraderTradeWindow();
auto item = trader_pc->FindTraderItemByUniqueID(in->trader_buy_struct.item_unique_id);
if (!item) {
in->transaction_status = BazaarPurchaseTraderFailed;
TraderRepository::UpdateActiveTransaction(database, in->id, false);
worldserver.SendPacket(pack);
break;
}
//if there is a customer currently browsing, close to ensure no conflict of purchase
if (trader_pc->IsThereACustomer()) {
auto customer = entity_list.GetClientByID(trader_pc->GetCustomerID());
if (customer) {
customer->CancelTraderTradeWindow();
}
}
//Update the trader's db entries
if (item->IsStackable() && in->item_quantity != in->item_charges) {
TraderRepository::UpdateQuantity(database, in->trader_buy_struct.item_unique_id, item->GetCharges() - in->item_quantity);
LogTradingDetail(
"Step 4a:Bazaar Purchase. Decreased database id {} from [{}] to [{}] charges",
in->trader_buy_struct.item_id,
in->item_charges,
in->item_charges
);
}
else {
TraderRepository::DeleteOne(database, in->trader_buy_struct.item_id);
LogTradingDetail(
"Step 4b:Bazaar Purchase. Deleted database id [{}] because database quantity [{}] equals [{}] purchased quantity",
in->trader_buy_struct.item_id,
in->item_charges,
in->item_charges
);
}
//at this time, buyer checks ok, seller checks ok.
//perform actions to trader
uint64 total_cost = static_cast<uint64>(in->trader_buy_struct.price) * static_cast<uint64>(in->item_quantity);
if (!trader_pc->RemoveItemByItemUniqueId(in->trader_buy_struct.item_unique_id, in->item_quantity)) {
in->transaction_status = BazaarPurchaseTraderFailed;
TraderRepository::UpdateActiveTransaction(database, in->id, false);
worldserver.SendPacket(pack);
break;
}
trader_pc->AddMoneyToPP(total_cost, true);
//Update the trader to indicate the sale has completed
EQApplicationPacket outapp(OP_Trader, sizeof(TraderBuy_Struct));
auto data = reinterpret_cast<TraderBuy_Struct *>(outapp.pBuffer);
memcpy(data, &in->trader_buy_struct, sizeof(TraderBuy_Struct));
trader_pc->QueuePacket(&outapp);
if (item && PlayerEventLogs::Instance()->IsEventEnabled(PlayerEvent::TRADER_SELL)) {
auto e = PlayerEvent::TraderSellEvent{
.item_id = item->GetID(),
.augment_1_id = item->GetAugmentItemID(0),
.augment_2_id = item->GetAugmentItemID(1),
.augment_3_id = item->GetAugmentItemID(2),
.augment_4_id = item->GetAugmentItemID(3),
.augment_5_id = item->GetAugmentItemID(4),
.augment_6_id = item->GetAugmentItemID(5),
.item_name = in->trader_buy_struct.item_name,
.buyer_id = in->buyer_id,
.buyer_name = in->trader_buy_struct.buyer_name,
.price = in->trader_buy_struct.price,
.quantity = in->item_quantity,
.charges = in->item_charges,
.total_cost = total_cost,
.player_money_balance = trader_pc->GetCarriedMoney(),
};
RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e);
}
in->transaction_status = BazaarPurchaseSuccess;
TraderRepository::UpdateActiveTransaction(database, in->id, false);
worldserver.SendPacket(pack);
break;
}
case BazaarPurchaseTraderFailed: {
auto buyer = entity_list.GetClientByCharID(in->buyer_id);
if (!buyer) {
LogTrading(
"Requested buyer_id [{}] could not be found in zone_id [{}] instance_id [{}]",
in->trader_buy_struct.trader_id,
zone->GetZoneID(),
zone->GetInstanceID()
);
return;
}
// return buyer's money including the fee
uint64 total_cost =
static_cast<uint64>(in->trader_buy_struct.price) * static_cast<uint64>(in->item_quantity);
uint64 fee = std::round(total_cost * RuleR(Bazaar, ParcelDeliveryCostMod));
buyer->AddMoneyToPP(total_cost + fee, false);
buyer->SendMoneyUpdate();
break;
}
case BazaarPurchaseSuccess: {
auto buyer = entity_list.GetClientByCharID(in->buyer_id);
if (!buyer) {
LogTrading(
"Requested buyer_id [{}] could not be found in zone_id [{}] instance_id [{}]",
in->trader_buy_struct.trader_id,
zone->GetZoneID(),
zone->GetInstanceID()
);
return;
}
uint64 total_cost =
static_cast<uint64>(in->trader_buy_struct.price) * static_cast<uint64>(in->item_quantity);
if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_PURCHASE)) {
auto e = PlayerEvent::TraderPurchaseEvent{
.item_id = in->trader_buy_struct.item_id,
.augment_1_id = in->item_aug_1,
.augment_2_id = in->item_aug_2,
.augment_3_id = in->item_aug_3,
.augment_4_id = in->item_aug_4,
.augment_5_id = in->item_aug_5,
.augment_6_id = in->item_aug_6,
.item_name = in->trader_buy_struct.item_name,
.trader_id = in->trader_buy_struct.trader_id,
.trader_name = in->trader_buy_struct.seller_name,
.price = in->trader_buy_struct.price,
.quantity = in->item_quantity,
.charges = in->item_charges,
.total_cost = total_cost,
.player_money_balance = buyer->GetCarriedMoney(),
};
RecordPlayerEventLogWithClient(buyer, PlayerEvent::TRADER_PURCHASE, e);
}
auto item = database.GetItem(in->trader_buy_struct.item_id);
auto quantity = in->item_quantity;
if (item->MaxCharges > 0) {
quantity = in->item_charges;
}
//Send the item via parcel
CharacterParcelsRepository::CharacterParcels parcel_out{};
parcel_out.from_name = in->trader_buy_struct.seller_name;
parcel_out.note = "Delivered from a Bazaar Purchase";
parcel_out.sent_date = time(nullptr);
parcel_out.quantity = quantity;
parcel_out.item_id = in->trader_buy_struct.item_id;
parcel_out.aug_slot_1 = in->item_aug_1;
parcel_out.aug_slot_2 = in->item_aug_2;
parcel_out.aug_slot_3 = in->item_aug_3;
parcel_out.aug_slot_4 = in->item_aug_4;
parcel_out.aug_slot_5 = in->item_aug_5;
parcel_out.aug_slot_6 = in->item_aug_6;
parcel_out.char_id = buyer->CharacterID();
parcel_out.slot_id = buyer->FindNextFreeParcelSlot(buyer->CharacterID());
parcel_out.id = 0;
CharacterParcelsRepository::InsertOne(database, parcel_out);
if (player_event_logs.IsEventEnabled(PlayerEvent::PARCEL_SEND)) {
PlayerEvent::ParcelSend e{};
e.from_player_name = parcel_out.from_name;
e.to_player_name = buyer->GetCleanName();
e.item_id = parcel_out.item_id;
e.augment_1_id = parcel_out.aug_slot_1;
e.augment_2_id = parcel_out.aug_slot_2;
e.augment_3_id = parcel_out.aug_slot_3;
e.augment_4_id = parcel_out.aug_slot_4;
e.augment_5_id = parcel_out.aug_slot_5;
e.augment_6_id = parcel_out.aug_slot_6;
e.quantity = in->item_quantity;
e.charges = in->item_charges;
e.sent_date = parcel_out.sent_date;
RecordPlayerEventLogWithClient(buyer, PlayerEvent::PARCEL_SEND, e);
}
Parcel_Struct ps{};
ps.item_slot = parcel_out.slot_id;
strn0cpy(ps.send_to, buyer->GetCleanName(), sizeof(ps.send_to));
buyer->SendParcelDeliveryToWorld(ps);
LogTradingDetail(
"Step 3:Bazaar Purchase. Sent parcel to Buyer [{}] Item ID [{}] Quantity [{}] Charges [{}]",
buyer->CharacterID(),
in->trader_buy_struct.item_id,
in->item_quantity,
in->item_charges
);
//Update the buyer to indicate the sale has completed
EQApplicationPacket outapp(OP_Trader, sizeof(TraderBuy_Struct));
auto data = reinterpret_cast<TraderBuy_Struct *>(outapp.pBuffer);
memcpy(data, &in->trader_buy_struct, sizeof(TraderBuy_Struct));
buyer->ReturnTraderReq(&outapp, in->item_quantity, in->trader_buy_struct.item_id);
break;
}
default: {
}
}
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 data = (TraderBuy_Struct *) outapp->pBuffer;
memcpy(data, &in->trader_buy_struct, sizeof(TraderBuy_Struct));
if (trader_pc->ClientVersion() < EQ::versions::ClientVersion::RoF) {
data->price = in->trader_buy_struct.price * in->trader_buy_struct.quantity;
}
TraderRepository::UpdateActiveTransaction(database, in->id, false);
auto item = trader_pc->FindTraderItemBySerialNumber(sn);
if (item && PlayerEventLogs::Instance()->IsEventEnabled(PlayerEvent::TRADER_SELL)) {
auto e = PlayerEvent::TraderSellEvent{
.item_id = item ? item->GetID() : 0,
.augment_1_id = item->GetAugmentItemID(0),
.augment_2_id = item->GetAugmentItemID(1),
.augment_3_id = item->GetAugmentItemID(2),
.augment_4_id = item->GetAugmentItemID(3),
.augment_5_id = item->GetAugmentItemID(4),
.augment_6_id = item->GetAugmentItemID(5),
.item_name = in->trader_buy_struct.item_name,
.buyer_id = in->buyer_id,
.buyer_name = in->trader_buy_struct.buyer_name,
.price = in->trader_buy_struct.price,
.quantity = in->trader_buy_struct.quantity,
.charges = item ? item->IsStackable() ? 1 : item->GetCharges() : 0,
.total_cost = (in->trader_buy_struct.price * in->trader_buy_struct.quantity),
.player_money_balance = trader_pc->GetCarriedMoney(),
};
RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e);
}
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());
break;
}
case ServerOP_BuyerMessaging: {