mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-02 16:46:37 +00:00
[Feature] Add RoF2 Bazaar Support (#4315)
* Add RoF2 Bazaar Support Enable RoF2 bazaar features * Add augments to Trader Items * Cleanup Cleanup of formatting and unused functions * Update PlayerProfile for correct char_id in trader transactions. Further cleanup. * Add parcel delivery price functionality Add parcel delivery price functionality via rules and new delivery cost struct. * Add RoF support for bazaar window outside of bazaar with parcel delivery * Further Testing and ActiveTransaction added Further testing and a few fixes and messages added. Add active transaction check to ensure two clients cannot purchase from the bazaar window at the same time * Cleanup and Formatting updates Cleanup and Formatting updates * Update database manifest for the trader table against default peq trader table * Logs and formatting * Update bazaarsearch to be content_db aware * Fix crash * Simplify search * Search fixes * Push up more search logging * More search fixes * Formatting * Update trader_repository.h * Add Rule for Bazaar Parcel Delivery Add a rule Bazaar:EnableParcelDelivery to enable/disable bazaar parcel delivery. Default is True. * Fix crash * Update Bazaar Search Adds/Tested bazaar search with move to content_db - race, class, money, number of returned items, stats, name, slot, level, traders, local traders, specific trader. Outstanding - type, more stats to add (heroic, etc) * Formatting * Push * Update bazaarsearch to include all stats that are available in RoF2 * Update BazaarSearch Updates the bazaar search for item types. They should be working as per RoF2+ types. * Formatting * Final updates to BazaarSearch Add search by augmentation slots available on the item. This enables all but Prestige, which I believe are not implemented yet. * Add Titanium functionality correct ItemType Search Add Titanium /trader /bazaar functionality. Added itemtype=armor bazaar search. It was missed in the search work * Close off for loops --------- Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
+24
-26
@@ -3494,14 +3494,13 @@ namespace RoF
|
||||
ENCODE_LENGTH_EXACT(ClickTrader_Struct);
|
||||
SETUP_DIRECT_ENCODE(ClickTrader_Struct, structs::ClickTrader_Struct);
|
||||
|
||||
eq->Code = emu->Code;
|
||||
// Live actually has 200 items now, but 80 is the most our internal struct supports
|
||||
for (uint32 i = 0; i < 200; i++)
|
||||
eq->Code = emu->action;
|
||||
for (uint32 i = 0; i < RoF::invtype::BAZAAR_SIZE; i++)
|
||||
{
|
||||
strncpy(eq->items[i].SerialNumber, "0000000000000000", sizeof(eq->items[i].SerialNumber));
|
||||
eq->items[i].Unknown18 = 0;
|
||||
if (i < 80) {
|
||||
eq->ItemCost[i] = emu->ItemCost[i];
|
||||
eq->ItemCost[i] = emu->item_cost[i];
|
||||
}
|
||||
else {
|
||||
eq->ItemCost[i] = 0;
|
||||
@@ -3515,9 +3514,9 @@ namespace RoF
|
||||
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
|
||||
eq->Code = emu->Code;
|
||||
eq->Code = emu->action;
|
||||
strncpy(eq->SerialNumber, "0000000000000000", sizeof(eq->SerialNumber));
|
||||
eq->TraderID = emu->TraderID;
|
||||
eq->TraderID = emu->entity_id;
|
||||
eq->Stacksize = 0;
|
||||
eq->Price = 0;
|
||||
|
||||
@@ -3543,13 +3542,13 @@ namespace RoF
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
|
||||
OUT(Action);
|
||||
OUT(Price);
|
||||
OUT(TraderID);
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(ItemID);
|
||||
OUT(Quantity);
|
||||
OUT(AlreadySold);
|
||||
OUT(action);
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
|
||||
OUT(item_id);
|
||||
OUT(quantity);
|
||||
OUT(already_sold);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -5041,12 +5040,11 @@ namespace RoF
|
||||
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::ClickTrader_Struct);
|
||||
MEMSET_IN(ClickTrader_Struct);
|
||||
|
||||
emu->Code = eq->Code;
|
||||
// Live actually has 200 items now, but 80 is the most our internal struct supports
|
||||
for (uint32 i = 0; i < 80; i++)
|
||||
emu->action = eq->Code;
|
||||
for (uint32 i = 0; i < RoF::invtype::BAZAAR_SIZE; i++)
|
||||
{
|
||||
emu->SerialNumber[i] = 0; // eq->SerialNumber[i];
|
||||
emu->ItemCost[i] = eq->ItemCost[i];
|
||||
emu->serial_number[i] = 0; // eq->SerialNumber[i];
|
||||
emu->item_cost[i] = eq->ItemCost[i];
|
||||
}
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
@@ -5057,8 +5055,8 @@ namespace RoF
|
||||
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
MEMSET_IN(Trader_ShowItems_Struct);
|
||||
|
||||
emu->Code = eq->Code;
|
||||
emu->TraderID = eq->TraderID;
|
||||
emu->action = eq->Code;
|
||||
emu->entity_id = eq->TraderID;
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -5080,12 +5078,12 @@ namespace RoF
|
||||
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
MEMSET_IN(TraderBuy_Struct);
|
||||
|
||||
IN(Action);
|
||||
IN(Price);
|
||||
IN(TraderID);
|
||||
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
||||
IN(ItemID);
|
||||
IN(Quantity);
|
||||
IN(action);
|
||||
IN(price);
|
||||
IN(trader_id);
|
||||
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
|
||||
IN(item_id);
|
||||
IN(quantity);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
+558
-246
@@ -398,51 +398,182 @@ namespace RoF2
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
char *Buffer = (char *)in->pBuffer;
|
||||
uint32 action = *(uint32 *) in->pBuffer;
|
||||
|
||||
uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer);
|
||||
switch (action) {
|
||||
case BazaarSearch: {
|
||||
LogTrading("(RoF2) BazaarSearch action <green>[{}]", action);
|
||||
std::vector<BazaarSearchResultsFromDB_Struct> results{};
|
||||
auto bsms = (BazaarSearchMessaging_Struct *) in->pBuffer;
|
||||
EQ::Util::MemoryStreamReader ss(
|
||||
reinterpret_cast<char *>(bsms->payload),
|
||||
in->size - sizeof(BazaarSearchMessaging_Struct)
|
||||
);
|
||||
cereal::BinaryInputArchive ar(ss);
|
||||
ar(results);
|
||||
|
||||
if (SubAction != BazaarSearchResults)
|
||||
{
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
auto name_size = 0;
|
||||
for (auto const &i: results) {
|
||||
name_size += i.item_name.length() + 1;
|
||||
}
|
||||
|
||||
auto p_size = 41 * results.size() + name_size + 14;
|
||||
auto buffer = std::make_unique<char[]>(p_size);
|
||||
auto bufptr = buffer.get();
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint16, bufptr, results[0].trader_zone_id);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, results[0].trader_id);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, results.size());
|
||||
|
||||
for (auto i: results) {
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, i.trader_id); //trader ID
|
||||
VARSTRUCT_ENCODE_STRING(bufptr, i.serial_number_RoF.c_str()); //serial
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, i.cost); //cost
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, i.stackable ? i.charges : i.count); //quantity
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, i.item_id); //ID
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, i.icon_id); //icon
|
||||
VARSTRUCT_ENCODE_STRING(bufptr, i.item_name.c_str()); //name
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, i.item_stat); //itemstat
|
||||
}
|
||||
|
||||
safe_delete(in->pBuffer);
|
||||
in->size = p_size;
|
||||
in->pBuffer = (uchar *) buffer.get();
|
||||
dest->QueuePacket(in);
|
||||
|
||||
break;
|
||||
}
|
||||
case BazaarInspect: {
|
||||
LogTrading("(RoF2) BazaarInspect action <green>[{}]", action);
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
break;
|
||||
}
|
||||
case WelcomeMessage: {
|
||||
auto buffer = std::make_unique<char[]>(sizeof(structs::BazaarWelcome_Struct));
|
||||
auto emu = (BazaarWelcome_Struct *) in->pBuffer;
|
||||
auto eq = (structs::BazaarWelcome_Struct *) buffer.get();
|
||||
|
||||
eq->action = structs::RoF2BazaarTraderBuyerActions::WelcomeMessage;
|
||||
eq->num_of_traders = emu->traders;
|
||||
eq->num_of_items = emu->items;
|
||||
|
||||
safe_delete(in->pBuffer);
|
||||
in->SetOpcode(OP_TraderShop);
|
||||
in->size = sizeof(structs::BazaarWelcome_Struct);
|
||||
in->pBuffer = (uchar *) buffer.get();
|
||||
|
||||
LogTrading("(RoF2) WelcomeMessage action <green>[{}]", action);
|
||||
dest->QueuePacket(in);
|
||||
|
||||
break;
|
||||
}
|
||||
case DeliveryCostUpdate: {
|
||||
auto data = (BazaarDeliveryCost_Struct *) in->pBuffer;
|
||||
LogTrading("(RoF2) Delivery costs updated: vouchers <green>[{}] parcel percentage <green>[{}]",
|
||||
data->voucher_delivery_cost,
|
||||
data->parcel_deliver_cost
|
||||
);
|
||||
data->action = 0;
|
||||
dest->FastQueuePacket(&in);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("(RoF2) Unhandled action <red>[{}]", action);
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
ENCODE(OP_BecomeTrader)
|
||||
{
|
||||
EQApplicationPacket *inapp = *p;
|
||||
*p = nullptr;
|
||||
|
||||
BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer;
|
||||
unsigned char *__emu_buffer = inapp->pBuffer;
|
||||
auto in = (BecomeTrader_Struct *) __emu_buffer;
|
||||
|
||||
int EntryCount = in->size / sizeof(BazaarSearchResults_Struct);
|
||||
switch (in->action) {
|
||||
case TraderOff: {
|
||||
auto emu = (BecomeTrader_Struct *) __emu_buffer;
|
||||
|
||||
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
||||
{
|
||||
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
||||
delete in;
|
||||
return;
|
||||
auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(structs::BecomeTrader_Struct));
|
||||
auto eq = (structs::BecomeTrader_Struct *) outapp->pBuffer;
|
||||
|
||||
eq->action = TraderOff;
|
||||
eq->entity_id = emu->entity_id;
|
||||
|
||||
LogTrading(
|
||||
"(RoF2) TraderOff action <green>[{}] for entity_id <green>[{}]",
|
||||
eq->action,
|
||||
eq->entity_id
|
||||
);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case TraderOn: {
|
||||
auto emu = (BecomeTrader_Struct *) __emu_buffer;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(structs::BecomeTrader_Struct));
|
||||
auto eq = (structs::BecomeTrader_Struct *) outapp->pBuffer;
|
||||
|
||||
eq->action = TraderOn;
|
||||
eq->entity_id = emu->entity_id;
|
||||
|
||||
LogTrading(
|
||||
"(RoF2) TraderOn action <green>[{}] for entity_id <green>[{}]",
|
||||
eq->action,
|
||||
eq->entity_id
|
||||
);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case AddTraderToBazaarWindow: {
|
||||
auto emu = (BecomeTrader_Struct *) __emu_buffer;
|
||||
auto outapp = new EQApplicationPacket(OP_TraderShop, sizeof(BecomeTrader_Struct));
|
||||
auto eq = (BecomeTrader_Struct *) outapp->pBuffer;
|
||||
|
||||
eq->action = emu->action;
|
||||
eq->entity_id = emu->entity_id;
|
||||
eq->trader_id = emu->trader_id;
|
||||
eq->zone_id = emu->zone_id;
|
||||
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
|
||||
|
||||
LogTrading(
|
||||
"(RoF2) AddTraderToBazaarWindow action <green>[{}] trader_id <green>[{}] entity_id <green>[{}] zone_id <green>[{}]",
|
||||
eq->action,
|
||||
eq->entity_id,
|
||||
eq->trader_id,
|
||||
eq->zone_id
|
||||
);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
case RemoveTraderFromBazaarWindow: {
|
||||
auto emu = (BecomeTrader_Struct *) __emu_buffer;
|
||||
auto outapp = new EQApplicationPacket(OP_TraderShop, sizeof(structs::BazaarWindowRemoveTrader_Struct));
|
||||
auto eq = (structs::BazaarWindowRemoveTrader_Struct *) outapp->pBuffer;
|
||||
|
||||
eq->action = emu->action;
|
||||
eq->trader_id = emu->trader_id;
|
||||
|
||||
LogTrading(
|
||||
"(RoF2) RemoveTraderFromBazaarWindow action <green>[{}] for entity_id <green>[{}]",
|
||||
eq->action,
|
||||
eq->trader_id
|
||||
);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading(
|
||||
"(RoF2) Unhandled action <red>[{}]",
|
||||
in->action
|
||||
);
|
||||
dest->QueuePacket(inapp);
|
||||
}
|
||||
}
|
||||
|
||||
in->size = EntryCount * sizeof(structs::BazaarSearchResults_Struct);
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
memset(in->pBuffer, 0, in->size);
|
||||
|
||||
structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *)in->pBuffer;
|
||||
|
||||
for (int i = 0; i < EntryCount; ++i, ++emu, ++eq)
|
||||
{
|
||||
OUT(Beginning.Action);
|
||||
OUT(SellerID);
|
||||
memcpy(eq->SellerName, emu->SellerName, sizeof(eq->SellerName));
|
||||
OUT(NumItems);
|
||||
OUT(ItemID);
|
||||
OUT(SerialNumber);
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(Cost);
|
||||
OUT(ItemStat);
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
safe_delete(inapp);
|
||||
}
|
||||
|
||||
ENCODE(OP_BeginCast)
|
||||
@@ -2591,7 +2722,7 @@ namespace RoF2
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(emu->char_id); // character_id
|
||||
|
||||
outapp->WriteUInt8(emu->leadAAActive);
|
||||
|
||||
@@ -3586,54 +3717,146 @@ namespace RoF2
|
||||
|
||||
ENCODE(OP_Trader)
|
||||
{
|
||||
if ((*p)->size == sizeof(ClickTrader_Struct))
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(ClickTrader_Struct);
|
||||
SETUP_DIRECT_ENCODE(ClickTrader_Struct, structs::ClickTrader_Struct);
|
||||
uint32 action = *(uint32 *) (*p)->pBuffer;
|
||||
|
||||
eq->Code = emu->Code;
|
||||
// Live actually has 200 items now, but 80 is the most our internal struct supports
|
||||
for (uint32 i = 0; i < 200; i++)
|
||||
{
|
||||
eq->items[i].Unknown18 = 0;
|
||||
if (i < 80) {
|
||||
snprintf(eq->items[i].SerialNumber, sizeof(eq->items[i].SerialNumber), "%016" PRId64, emu->SerialNumber[i]);
|
||||
eq->ItemCost[i] = emu->ItemCost[i];
|
||||
}
|
||||
else {
|
||||
snprintf(eq->items[i].SerialNumber, sizeof(eq->items[i].SerialNumber), "%016d", 0);
|
||||
eq->ItemCost[i] = 0;
|
||||
}
|
||||
switch (action) {
|
||||
case TraderOn: {
|
||||
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
|
||||
eq->action = structs::RoF2BazaarTraderBuyerActions::BeginTraderMode;
|
||||
OUT(entity_id);
|
||||
|
||||
LogTrading("(RoF2) TraderOn action <green>[{}] entity_id <green>[{}]", action, eq->entity_id);
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case TraderOff: {
|
||||
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
else if ((*p)->size == sizeof(Trader_ShowItems_Struct))
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
eq->action = structs::RoF2BazaarTraderBuyerActions::EndTraderMode;
|
||||
OUT(entity_id);
|
||||
|
||||
eq->Code = emu->Code;
|
||||
//strncpy(eq->SerialNumber, "0000000000000000", sizeof(eq->SerialNumber));
|
||||
//snprintf(eq->SerialNumber, sizeof(eq->SerialNumber), "%016d", 0);
|
||||
eq->TraderID = emu->TraderID;
|
||||
//eq->Stacksize = 0;
|
||||
//eq->Price = 0;
|
||||
LogTrading("(RoF2) TraderOff action <green>[{}] entity_id <green>[{}]", action, eq->entity_id);
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case ListTraderItems: {
|
||||
ENCODE_LENGTH_EXACT(Trader_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_Struct, structs::ClickTrader_Struct);
|
||||
LogTrading("(RoF2) action <green>[{}]", action);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
else if ((*p)->size == sizeof(TraderStatus_Struct))
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TraderStatus_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderStatus_Struct, structs::TraderStatus_Struct);
|
||||
eq->action = structs::RoF2BazaarTraderBuyerActions::ListTraderItems;
|
||||
std::transform(
|
||||
std::begin(emu->items),
|
||||
std::end(emu->items),
|
||||
std::begin(eq->items),
|
||||
[&](const uint32 x) {
|
||||
return x;
|
||||
}
|
||||
);
|
||||
std::copy_n(
|
||||
std::begin(emu->item_cost),
|
||||
EQ::invtype::BAZAAR_SIZE,
|
||||
std::begin(eq->item_cost)
|
||||
);
|
||||
|
||||
eq->Code = emu->Code;
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case TraderAck2: {
|
||||
LogTrading("(RoF2) TraderAck2 action");
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
else if ((*p)->size == sizeof(TraderBuy_Struct))
|
||||
{
|
||||
ENCODE_FORWARD(OP_TraderBuy);
|
||||
dest->FastQueuePacket(&in);
|
||||
break;
|
||||
}
|
||||
case PriceUpdate: {
|
||||
SETUP_DIRECT_ENCODE(TraderPriceUpdate_Struct, structs::TraderPriceUpdate_Struct);
|
||||
switch (emu->SubAction) {
|
||||
case BazaarPriceChange_AddItem: {
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(
|
||||
OP_Trader,
|
||||
sizeof(structs::TraderStatus_Struct)
|
||||
);
|
||||
|
||||
auto data = (structs::TraderStatus_Struct *) outapp->pBuffer;
|
||||
data->action = emu->Action;
|
||||
data->sub_action = BazaarPriceChange_AddItem;
|
||||
LogTrading(
|
||||
"(RoF2) PriceUpdate action <green>[{}] AddItem subaction <yellow>[{}]",
|
||||
data->action,
|
||||
data->sub_action
|
||||
);
|
||||
|
||||
dest->QueuePacket(outapp.get());
|
||||
break;
|
||||
}
|
||||
case BazaarPriceChange_RemoveItem: {
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(
|
||||
OP_Trader,
|
||||
sizeof(structs::TraderStatus_Struct)
|
||||
);
|
||||
|
||||
auto data = (structs::TraderStatus_Struct *) outapp->pBuffer;
|
||||
data->action = emu->Action;
|
||||
data->sub_action = BazaarPriceChange_RemoveItem;
|
||||
LogTrading(
|
||||
"(RoF2) PriceUpdate action <green>[{}] RemoveItem subaction <yellow>[{}]",
|
||||
data->action,
|
||||
data->sub_action
|
||||
);
|
||||
|
||||
dest->QueuePacket(outapp.get());
|
||||
break;
|
||||
}
|
||||
case BazaarPriceChange_UpdatePrice: {
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(
|
||||
OP_Trader,
|
||||
sizeof(structs::TraderStatus_Struct)
|
||||
);
|
||||
|
||||
auto data = (structs::TraderStatus_Struct *) outapp->pBuffer;
|
||||
data->action = emu->Action;
|
||||
data->sub_action = BazaarPriceChange_UpdatePrice;
|
||||
LogTrading(
|
||||
"(RoF2) PriceUpdate action <green>[{}] UpdatePrice subaction <yellow>[{}]",
|
||||
data->action,
|
||||
data->sub_action
|
||||
);
|
||||
|
||||
dest->QueuePacket(outapp.get());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case BuyTraderItem: {
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
auto eq = (structs::TraderBuy_Struct *) in->pBuffer;
|
||||
LogTrading(
|
||||
"(RoF2) BuyTraderItem action <green>[{}] item_id <green>[{}] item_sn <green>[{}] buyer <green>[{}]",
|
||||
action,
|
||||
eq->item_id,
|
||||
eq->serial_number,
|
||||
eq->buyer_name
|
||||
);
|
||||
dest->FastQueuePacket(&in);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("(RoF2) action <red>[{}]", action);
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
dest->FastQueuePacket(&in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3641,14 +3864,26 @@ namespace RoF2
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
|
||||
OUT(Action);
|
||||
OUT(Price);
|
||||
OUT(TraderID);
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(ItemID);
|
||||
OUT(Quantity);
|
||||
OUT(AlreadySold);
|
||||
LogTrading(
|
||||
"(RoF2) item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
emu->item_id,
|
||||
emu->price,
|
||||
emu->quantity,
|
||||
emu->trader_id
|
||||
);
|
||||
__packet->SetOpcode(OP_TraderShop);
|
||||
OUT(action);
|
||||
OUT(method);
|
||||
OUT(sub_action);
|
||||
OUT(trader_id);
|
||||
OUT(item_id);
|
||||
OUT(price);
|
||||
OUT(already_sold);
|
||||
OUT(quantity);
|
||||
OUT_str(buyer_name);
|
||||
OUT_str(seller_name);
|
||||
OUT_str(item_name);
|
||||
OUT_str(serial_number);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -3657,71 +3892,74 @@ namespace RoF2
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TraderDelItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderDelItem_Struct, structs::TraderDelItem_Struct);
|
||||
LogTrading(
|
||||
"(RoF2) trader_id <green>[{}] item_id <green>[{}]",
|
||||
emu->trader_id,
|
||||
emu->item_id
|
||||
);
|
||||
|
||||
OUT(TraderID);
|
||||
snprintf(eq->SerialNumber, sizeof(eq->SerialNumber), "%016d", emu->ItemID);
|
||||
LogTrading("ENCODE(OP_TraderDelItem): TraderID [{}], SerialNumber: [{}]", emu->TraderID, emu->ItemID);
|
||||
eq->TraderID = emu->trader_id;
|
||||
auto serial = fmt::format("{:016}\n", emu->item_id);
|
||||
strn0cpy(eq->SerialNumber, serial.c_str(), sizeof(eq->SerialNumber));
|
||||
LogTrading("(RoF2) TraderID <green>[{}], SerialNumber: <green>[{}]", emu->trader_id, emu->item_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_TraderShop)
|
||||
{
|
||||
uint32 psize = (*p)->size;
|
||||
if (psize == sizeof(TraderClick_Struct))
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TraderClick_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderClick_Struct, structs::TraderClick_Struct);
|
||||
auto action = *(uint32 *) (*p)->pBuffer;
|
||||
|
||||
eq->Code = 28; // Seen on Live
|
||||
OUT(TraderID);
|
||||
OUT(Approval);
|
||||
switch (action) {
|
||||
case ClickTrader: {
|
||||
ENCODE_LENGTH_EXACT(TraderClick_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderClick_Struct, structs::TraderClick_Struct);
|
||||
LogTrading(
|
||||
"(RoF2) ClickTrader action <green>[{}] trader_id <green>[{}]",
|
||||
action,
|
||||
emu->TraderID
|
||||
);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
else if (psize == sizeof(BazaarWelcome_Struct))
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(BazaarWelcome_Struct);
|
||||
SETUP_DIRECT_ENCODE(BazaarWelcome_Struct, structs::BazaarWelcome_Struct);
|
||||
eq->action = structs::RoF2BazaarTraderBuyerActions::ClickTrader; // Seen on Live
|
||||
eq->trader_id = emu->TraderID;
|
||||
eq->unknown_008 = emu->Approval;
|
||||
|
||||
eq->Code = emu->Beginning.Action;
|
||||
eq->EntityID = emu->Unknown012;
|
||||
OUT(Traders);
|
||||
OUT(Items);
|
||||
eq->Traders2 = emu->Traders;
|
||||
eq->Items2 = emu->Items;
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case structs::RoF2BazaarTraderBuyerActions::BuyTraderItem: {
|
||||
ENCODE_LENGTH_EXACT(structs::TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"(RoF2) item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
eq->item_id,
|
||||
eq->price,
|
||||
eq->quantity,
|
||||
eq->trader_id
|
||||
);
|
||||
|
||||
LogTrading("ENCODE(OP_TraderShop): BazaarWelcome_Struct Code [{}], Traders [{}], Items [{}]",
|
||||
eq->Code, eq->Traders, eq->Items);
|
||||
OUT(action);
|
||||
OUT(method);
|
||||
OUT(trader_id);
|
||||
OUT(item_id);
|
||||
OUT(price);
|
||||
OUT(already_sold);
|
||||
OUT(quantity);
|
||||
OUT_str(buyer_name);
|
||||
OUT_str(seller_name);
|
||||
OUT_str(item_name);
|
||||
OUT_str(serial_number);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
else if (psize == sizeof(TraderBuy_Struct))
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("(RoF2) Unhandled action <red>[{}]", action);
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
OUT(Action);
|
||||
OUT(TraderID);
|
||||
|
||||
//memcpy(eq->BuyerName, emu->BuyerName, sizeof(eq->BuyerName));
|
||||
//memcpy(eq->SellerName, emu->SellerName, sizeof(eq->SellerName));
|
||||
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(ItemID);
|
||||
OUT(AlreadySold);
|
||||
OUT(Price);
|
||||
OUT(Quantity);
|
||||
snprintf(eq->SerialNumber, sizeof(eq->SerialNumber), "%016d", emu->ItemID);
|
||||
|
||||
LogTrading("ENCODE(OP_TraderShop): Buy Action [{}], Price [{}], Trader [{}], ItemID [{}], Quantity [{}], ItemName, [{}]",
|
||||
eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, emu->ItemName);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogTrading("ENCODE(OP_TraderShop): Encode Size Unknown ([{}])", psize);
|
||||
dest->FastQueuePacket(&in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4067,20 +4305,20 @@ namespace RoF2
|
||||
|
||||
structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer;
|
||||
|
||||
Bitfields->gender = emu->gender;
|
||||
Bitfields->ispet = emu->is_pet;
|
||||
Bitfields->afk = emu->afk;
|
||||
Bitfields->anon = emu->anon;
|
||||
Bitfields->gm = emu->gm;
|
||||
Bitfields->sneak = 0;
|
||||
Bitfields->lfg = emu->lfg;
|
||||
Bitfields->invis = emu->invis;
|
||||
Bitfields->linkdead = 0;
|
||||
Bitfields->showhelm = emu->showhelm;
|
||||
Bitfields->trader = 0;
|
||||
Bitfields->targetable = 1;
|
||||
Bitfields->gender = emu->gender;
|
||||
Bitfields->ispet = emu->is_pet;
|
||||
Bitfields->afk = emu->afk;
|
||||
Bitfields->anon = emu->anon;
|
||||
Bitfields->gm = emu->gm;
|
||||
Bitfields->sneak = 0;
|
||||
Bitfields->lfg = emu->lfg;
|
||||
Bitfields->invis = emu->invis;
|
||||
Bitfields->linkdead = 0;
|
||||
Bitfields->showhelm = emu->showhelm;
|
||||
Bitfields->trader = emu->trader ? 1 : 0;
|
||||
Bitfields->targetable = 1;
|
||||
Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0;
|
||||
Bitfields->showname = ShowName;
|
||||
Bitfields->showname = ShowName;
|
||||
|
||||
if (emu->DestructibleObject)
|
||||
{
|
||||
@@ -4431,6 +4669,7 @@ namespace RoF2
|
||||
char *Buffer = (char *)__packet->pBuffer;
|
||||
|
||||
uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer);
|
||||
LogTrading("(RoF2) action <green>[{}]", SubAction);
|
||||
|
||||
if ((SubAction != BazaarInspectItem) || (__packet->size != sizeof(structs::NewBazaarInspect_Struct)))
|
||||
return;
|
||||
@@ -4440,6 +4679,7 @@ namespace RoF2
|
||||
IN(Beginning.Action);
|
||||
memcpy(emu->Name, eq->Name, sizeof(emu->Name));
|
||||
IN(SerialNumber);
|
||||
LogTrading("(RoF2) action <green>[{}] serial_number <green>[{}]", eq->Beginning.Action, eq->SerialNumber);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@@ -5331,40 +5571,61 @@ namespace RoF2
|
||||
|
||||
DECODE(OP_Trader)
|
||||
{
|
||||
uint32 psize = __packet->size;
|
||||
if (psize == sizeof(structs::ClickTrader_Struct))
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::ClickTrader_Struct);
|
||||
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::ClickTrader_Struct);
|
||||
auto action = *(uint32 *)__packet->pBuffer;
|
||||
|
||||
emu->Code = eq->Code;
|
||||
// Live actually has 200 items now, but 80 is the most our internal struct supports
|
||||
for (uint32 i = 0; i < 80; i++)
|
||||
{
|
||||
emu->SerialNumber[i] = 0; // eq->SerialNumber[i];
|
||||
emu->ItemCost[i] = eq->ItemCost[i];
|
||||
switch (action) {
|
||||
case structs::RoF2BazaarTraderBuyerActions::BeginTraderMode: {
|
||||
DECODE_LENGTH_EXACT(structs::BeginTrader_Struct);
|
||||
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::BeginTrader_Struct);
|
||||
LogTrading("(RoF2) BeginTraderMode action <green>[{}]", action);
|
||||
|
||||
emu->action = TraderOn;
|
||||
std::copy_n(eq->item_cost, RoF2::invtype::BAZAAR_SIZE, emu->item_cost);
|
||||
std::transform(
|
||||
std::begin(eq->items),
|
||||
std::end(eq->items),
|
||||
std::begin(emu->serial_number),
|
||||
[&](const structs::TraderItemSerial_Struct x) {
|
||||
return Strings::ToUnsignedBigInt(x.serial_number,0);
|
||||
}
|
||||
);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::RoF2BazaarTraderBuyerActions::EndTraderMode: {
|
||||
DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
LogTrading("(RoF2) EndTraderMode action <green>[{}]", action);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
else if (psize == sizeof(structs::Trader_ShowItems_Struct))
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
emu->action = TraderOff;
|
||||
emu->entity_id = eq->entity_id;
|
||||
|
||||
emu->Code = eq->Code;
|
||||
emu->TraderID = eq->TraderID;
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::RoF2BazaarTraderBuyerActions::ListTraderItems: {
|
||||
LogTrading("(RoF2) ListTraderItems action <green>[{}]", action);
|
||||
break;
|
||||
}
|
||||
case structs::RoF2BazaarTraderBuyerActions::PriceUpdate: {
|
||||
DECODE_LENGTH_EXACT(structs::TraderPriceUpdate_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderPriceUpdate_Struct, structs::TraderPriceUpdate_Struct);
|
||||
LogTrading("(RoF2) PriceUpdate action <green>[{}]", action);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
else if (psize == sizeof(structs::TraderStatus_Struct))
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::TraderStatus_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderStatus_Struct, structs::TraderStatus_Struct);
|
||||
emu->Action = PriceUpdate;
|
||||
emu->SerialNumber = Strings::ToUnsignedBigInt(eq->serial_number, 0);
|
||||
if (emu->SerialNumber == 0) {
|
||||
LogTrading("(RoF2) Price change with invalid serial number <red>[{}]", eq->serial_number);
|
||||
}
|
||||
emu->NewPrice = eq->new_price;
|
||||
|
||||
emu->Code = eq->Code; // 11 = Start Trader, 2 = End Trader, 22 = ? - Guessing
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("(RoF2) Unhandled action <red>[{}]", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5372,73 +5633,136 @@ namespace RoF2
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"(RoF2) item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
eq->item_id,
|
||||
eq->price,
|
||||
eq->quantity,
|
||||
eq->trader_id
|
||||
);
|
||||
|
||||
IN(Action);
|
||||
IN(Price);
|
||||
IN(TraderID);
|
||||
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
||||
IN(ItemID);
|
||||
IN(Quantity);
|
||||
IN(action);
|
||||
IN(price);
|
||||
IN(trader_id);
|
||||
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
|
||||
IN(item_id);
|
||||
IN(quantity);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_TraderShop)
|
||||
{
|
||||
uint32 psize = __packet->size;
|
||||
if (psize == sizeof(structs::TraderClick_Struct))
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::TraderClick_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderClick_Struct, structs::TraderClick_Struct);
|
||||
uint32 action = *(uint32 *)__packet->pBuffer;
|
||||
|
||||
IN(Code);
|
||||
IN(TraderID);
|
||||
IN(Approval);
|
||||
LogTrading("DECODE(OP_TraderShop): TraderClick_Struct Code [{}], TraderID [{}], Approval [{}]",
|
||||
eq->Code, eq->TraderID, eq->Approval);
|
||||
switch (action) {
|
||||
case structs::RoF2BazaarTraderBuyerActions::BazaarSearch: {
|
||||
DECODE_LENGTH_EXACT(structs::BazaarSearch_Struct);
|
||||
SETUP_DIRECT_DECODE(BazaarSearchCriteria_Struct, structs::BazaarSearch_Struct);
|
||||
LogTrading(
|
||||
"(RoF2) BazaarSearch action <green>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
else if (psize == sizeof(structs::BazaarWelcome_Struct))
|
||||
{
|
||||
// Don't think this size gets used in RoF+ - Leaving for now...
|
||||
DECODE_LENGTH_EXACT(structs::BazaarWelcome_Struct);
|
||||
SETUP_DIRECT_DECODE(BazaarWelcome_Struct, structs::BazaarWelcome_Struct);
|
||||
__packet->SetOpcode(OP_BazaarSearch);
|
||||
emu->action = BazaarSearch;
|
||||
emu->type = eq->type == UINT32_MAX ? UINT8_MAX : eq->type;
|
||||
IN(item_stat);
|
||||
IN(max_cost);
|
||||
IN(min_cost);
|
||||
IN(max_level);
|
||||
IN(min_level);
|
||||
IN(race);
|
||||
IN(slot);
|
||||
IN(trader_id);
|
||||
IN(_class);
|
||||
IN(prestige);
|
||||
IN(search_scope);
|
||||
IN(max_results);
|
||||
IN(augment);
|
||||
IN_str(item_name);
|
||||
|
||||
emu->Beginning.Action = eq->Code;
|
||||
IN(Traders);
|
||||
IN(Items);
|
||||
LogTrading("DECODE(OP_TraderShop): BazaarWelcome_Struct Code [{}], Traders [{}], Items [{}]",
|
||||
eq->Code, eq->Traders, eq->Items);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::RoF2BazaarTraderBuyerActions::ClickTrader: {
|
||||
DECODE_LENGTH_EXACT(structs::TraderClick_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderClick_Struct, structs::TraderClick_Struct);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
else if (psize == sizeof(structs::TraderBuy_Struct))
|
||||
{
|
||||
emu->Code = ClickTrader;
|
||||
emu->TraderID = eq->trader_id;
|
||||
emu->Approval = eq->unknown_008;
|
||||
LogTrading("(RoF2) ClickTrader action <green>[{}], trader_id <green>[{}], approval <green>[{}]",
|
||||
eq->action,
|
||||
eq->trader_id,
|
||||
eq->unknown_008
|
||||
);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::RoF2BazaarTraderBuyerActions::BazaarInspect: {
|
||||
DECODE_LENGTH_EXACT(structs::BazaarInspect_Struct);
|
||||
SETUP_DIRECT_DECODE(BazaarInspect_Struct, structs::BazaarInspect_Struct);
|
||||
|
||||
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
__packet->SetOpcode(OP_BazaarSearch);
|
||||
IN(item_id);
|
||||
IN(trader_id);
|
||||
emu->action = BazaarInspect;
|
||||
emu->serial_number = Strings::ToUnsignedInt(eq->serial_number, 0);
|
||||
if (emu->serial_number == 0) {
|
||||
LogTrading(
|
||||
"(RoF2) trader_id = <green>[{}] requested a BazaarInspect with an invalid serial number of <red>[{}]",
|
||||
eq->trader_id,
|
||||
eq->serial_number
|
||||
);
|
||||
FINISH_DIRECT_DECODE();
|
||||
return;
|
||||
}
|
||||
|
||||
IN(Action);
|
||||
IN(Price);
|
||||
IN(TraderID);
|
||||
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
||||
IN(ItemID);
|
||||
IN(Quantity);
|
||||
LogTrading("DECODE(OP_TraderShop): TraderBuy_Struct (Unknowns) Unknown004 [{}], Unknown008 [{}], Unknown012 [{}], Unknown076 [{}], Unknown276 [{}]",
|
||||
eq->Unknown004, eq->Unknown008, eq->Unknown012, eq->Unknown076, eq->Unknown276);
|
||||
LogTrading("DECODE(OP_TraderShop): TraderBuy_Struct Buy Action [{}], Price [{}], Trader [{}], ItemID [{}], Quantity [{}], ItemName, [{}]",
|
||||
eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, eq->ItemName);
|
||||
LogTrading("(RoF2) BazaarInspect action <green>[{}] item_id <green>[{}] serial_number <green>[{}]",
|
||||
action,
|
||||
eq->item_id,
|
||||
eq->serial_number
|
||||
);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::RoF2BazaarTraderBuyerActions::WelcomeMessage: {
|
||||
__packet->SetOpcode(OP_BazaarSearch);
|
||||
LogTrading("(RoF2) WelcomeMessage action <green>[{}]", action);
|
||||
break;
|
||||
}
|
||||
case structs::RoF2BazaarTraderBuyerActions::BuyTraderItem: {
|
||||
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"(RoF2) item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
eq->item_id,
|
||||
eq->price,
|
||||
eq->quantity,
|
||||
eq->trader_id
|
||||
);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
else if (psize == 4)
|
||||
{
|
||||
LogTrading("DECODE(OP_TraderShop): Forwarding packet as-is with size 4");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogTrading("DECODE(OP_TraderShop): Decode Size Unknown ([{}])", psize);
|
||||
__packet->SetOpcode(OP_TraderBuy);
|
||||
IN(action);
|
||||
IN(method);
|
||||
IN(trader_id);
|
||||
IN(item_id);
|
||||
IN(price);
|
||||
IN(already_sold);
|
||||
IN(quantity);
|
||||
IN_str(buyer_name);
|
||||
IN_str(seller_name);
|
||||
IN_str(item_name);
|
||||
IN_str(serial_number);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("(RoF2) Unhandled action <red>[{}]", action);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5541,19 +5865,7 @@ namespace RoF2
|
||||
RoF2::structs::ItemSerializationHeader hdr;
|
||||
|
||||
//sprintf(hdr.unknown000, "06e0002Y1W00");
|
||||
|
||||
snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID);
|
||||
if (packet_type == ItemPacketParcel) {
|
||||
strn0cpy(
|
||||
hdr.unknown000,
|
||||
fmt::format(
|
||||
"{:03}PAR{:010}\0",
|
||||
inst->GetMerchantSlot(),
|
||||
item->ID
|
||||
).c_str(),
|
||||
sizeof(hdr.unknown000)
|
||||
);
|
||||
}
|
||||
strn0cpy(hdr.unknown000, fmt::format("{:016}\0", inst->GetSerialNumber()).c_str(),sizeof(hdr.unknown000));
|
||||
|
||||
hdr.stacksize =
|
||||
item->ID == PARCEL_MONEY_ITEM_ID ? inst->GetPrice() : (inst->IsStackable() ? ((inst->GetCharges() > 1000)
|
||||
|
||||
@@ -43,6 +43,7 @@ E(OP_ApplyPoison)
|
||||
E(OP_AugmentInfo)
|
||||
E(OP_Barter)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_BeginCast)
|
||||
E(OP_BlockedBuffs)
|
||||
E(OP_Buff)
|
||||
|
||||
+142
-112
@@ -3106,28 +3106,43 @@ struct EnvDamage2_Struct {
|
||||
};
|
||||
|
||||
//Bazaar Stuff
|
||||
enum RoF2BazaarTraderBuyerActions {
|
||||
Zero = 0,
|
||||
BeginTraderMode = 1,
|
||||
EndTraderMode = 2,
|
||||
PriceUpdate = 3,
|
||||
EndTransaction = 4,
|
||||
BazaarSearch = 7,
|
||||
WelcomeMessage = 9,
|
||||
BuyTraderItem = 10,
|
||||
ListTraderItems = 11,
|
||||
BazaarInspect = 18,
|
||||
ClickTrader = 28,
|
||||
ItemMove = 19,
|
||||
ReconcileItems = 20
|
||||
};
|
||||
|
||||
enum {
|
||||
BazaarTrader_StartTraderMode = 1,
|
||||
BazaarTrader_EndTraderMode = 2,
|
||||
BazaarTrader_UpdatePrice = 3,
|
||||
BazaarTrader_EndTransaction = 4,
|
||||
BazaarSearchResults = 7,
|
||||
BazaarWelcome = 9,
|
||||
BazaarBuyItem = 10,
|
||||
BazaarTrader_ShowItems = 11,
|
||||
BazaarSearchDone = 12,
|
||||
BazaarTrader_StartTraderMode = 1,
|
||||
BazaarTrader_EndTraderMode = 2,
|
||||
BazaarTrader_UpdatePrice = 3,
|
||||
BazaarTrader_EndTransaction = 4,
|
||||
BazaarSearchResults = 7,
|
||||
BazaarWelcome = 9,
|
||||
BazaarBuyItem = 10,
|
||||
BazaarTrader_ShowItems = 11,
|
||||
BazaarSearchDone = 12,
|
||||
BazaarTrader_CustomerBrowsing = 13,
|
||||
BazaarInspectItem = 18,
|
||||
BazaarSearchDone2 = 19,
|
||||
BazaarInspectItem = 18,
|
||||
BazaarSearchDone2 = 19,
|
||||
BazaarTrader_StartTraderMode2 = 22
|
||||
};
|
||||
|
||||
enum {
|
||||
BazaarPriceChange_Fail = 0,
|
||||
BazaarPriceChange_Fail = 0,
|
||||
BazaarPriceChange_UpdatePrice = 1,
|
||||
BazaarPriceChange_RemoveItem = 2,
|
||||
BazaarPriceChange_AddItem = 3
|
||||
BazaarPriceChange_RemoveItem = 2,
|
||||
BazaarPriceChange_AddItem = 3
|
||||
};
|
||||
|
||||
struct BazaarWindowStart_Struct {
|
||||
@@ -3136,34 +3151,51 @@ struct BazaarWindowStart_Struct {
|
||||
uint16 Unknown002;
|
||||
};
|
||||
|
||||
struct BazaarDeliveryCost_Struct {
|
||||
uint32 action;
|
||||
uint32 voucher_delivery_cost;
|
||||
float parcel_deliver_cost; //percentage of item cost
|
||||
uint32 unknown_010;
|
||||
};
|
||||
|
||||
struct BazaarWelcome_Struct {
|
||||
uint32 Code;
|
||||
uint32 EntityID;
|
||||
uint32 Traders;
|
||||
uint32 Items;
|
||||
uint32 Traders2;
|
||||
uint32 Items2;
|
||||
uint32 action;
|
||||
uint32 unknown_004;
|
||||
uint32 num_of_traders;
|
||||
uint32 num_of_items;
|
||||
};
|
||||
|
||||
struct BazaarSearch_Struct {
|
||||
BazaarWindowStart_Struct Beginning;
|
||||
uint32 TraderID;
|
||||
uint32 Class_;
|
||||
uint32 Race;
|
||||
uint32 ItemStat;
|
||||
uint32 Slot;
|
||||
uint32 Type;
|
||||
char Name[64];
|
||||
uint32 MinPrice;
|
||||
uint32 MaxPrice;
|
||||
uint32 Minlevel;
|
||||
uint32 MaxLlevel;
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint8 search_scope;//1 all traders 0 local traders
|
||||
/*005*/ uint8 unknown_005{0};
|
||||
/*006*/ uint16 unknown_006{0};
|
||||
/*008*/ uint32 unknown_008{0};
|
||||
/*012*/ uint32 unknown_012{0};
|
||||
/*016*/ uint32 trader_id;
|
||||
/*020*/ uint32 _class;
|
||||
/*024*/ uint32 race;
|
||||
/*028*/ uint32 item_stat;
|
||||
/*032*/ uint32 slot;
|
||||
/*036*/ uint32 type;
|
||||
/*040*/ char item_name[64];
|
||||
/*104*/ uint32 min_cost;
|
||||
/*108*/ uint32 max_cost;
|
||||
/*112*/ uint32 min_level;
|
||||
/*116*/ uint32 max_level;
|
||||
/*120*/ uint32 max_results;
|
||||
/*124*/ uint32 prestige;
|
||||
/*128*/ uint32 augment;
|
||||
};
|
||||
struct BazaarInspect_Struct{
|
||||
uint32 ItemID;
|
||||
uint32 Unknown004;
|
||||
char Name[64];
|
||||
|
||||
struct BazaarInspect_Struct {
|
||||
uint32 action;
|
||||
uint32 unknown_004;
|
||||
uint32 trader_id;
|
||||
char serial_number[17];
|
||||
char unknown_029[3];
|
||||
uint32 item_id;
|
||||
uint32 unknown_036;
|
||||
};
|
||||
|
||||
struct NewBazaarInspect_Struct {
|
||||
@@ -3184,18 +3216,23 @@ struct BazaarReturnDone_Struct{
|
||||
uint32 Unknown016;
|
||||
};
|
||||
|
||||
struct BazaarSearchResults_Struct {
|
||||
/*000*/ BazaarWindowStart_Struct Beginning;
|
||||
/*004*/ uint32 SellerID;
|
||||
/*008*/ char SellerName[64];
|
||||
/*072*/ uint32 NumItems;
|
||||
/*076*/ uint32 ItemID;
|
||||
/*080*/ uint32 SerialNumber;
|
||||
/*084*/ uint32 Unknown084;
|
||||
/*088*/ char ItemName[64];
|
||||
/*152*/ uint32 Cost;
|
||||
/*156*/ uint32 ItemStat;
|
||||
/*160*/
|
||||
struct BazaarSearchDetails_Struct { //24+name+17
|
||||
/*014*/ uint32 trader_id;
|
||||
/*018*/ char serial_num[17];
|
||||
/*022*/ uint32 cost;
|
||||
/*026*/ uint32 quanity;
|
||||
/*030*/ uint32 id;
|
||||
/*034*/ uint32 icon;
|
||||
/*038*/ char name[1];
|
||||
/*039*/ uint32 stat;
|
||||
};
|
||||
|
||||
struct BazaarSearchResults_Struct { //14
|
||||
/*000*/ uint32 unknown000;
|
||||
/*004*/ uint16 zone_id;
|
||||
/*006*/ uint32 entity_id;
|
||||
/*010*/ uint32 num_items;
|
||||
/*014*/ BazaarSearchDetails_Struct items[];
|
||||
};
|
||||
|
||||
struct ServerSideFilters_Struct {
|
||||
@@ -3398,21 +3435,26 @@ struct WhoAllPlayerPart4 {
|
||||
};
|
||||
|
||||
struct TraderItemSerial_Struct {
|
||||
char SerialNumber[17];
|
||||
uint8 Unknown18;
|
||||
char serial_number[17];
|
||||
uint8 unknown_018;
|
||||
|
||||
void operator=(uint32 a) {
|
||||
auto _tmp = fmt::format("{:016}", a);
|
||||
strn0cpy(this->serial_number, _tmp.c_str(), sizeof(this->serial_number));
|
||||
}
|
||||
};
|
||||
|
||||
struct Trader_Struct {
|
||||
/*0000*/ uint32 Code;
|
||||
/*0004*/ TraderItemSerial_Struct items[200];
|
||||
/*3604*/ uint32 ItemCost[200];
|
||||
struct BeginTrader_Struct {
|
||||
/*0000*/ uint32 action;
|
||||
/*0004*/ TraderItemSerial_Struct items[200];
|
||||
/*3604*/ uint32 item_cost[200];
|
||||
/*4404*/
|
||||
};
|
||||
|
||||
struct ClickTrader_Struct {
|
||||
/*0000*/ uint32 Code;
|
||||
/*0004*/ TraderItemSerial_Struct items[200];
|
||||
/*3604*/ uint32 ItemCost[200];
|
||||
/*0000*/ uint32 action;
|
||||
/*0004*/ TraderItemSerial_Struct items[200];
|
||||
/*3604*/ uint32 item_cost[200];
|
||||
/*4404*/
|
||||
};
|
||||
|
||||
@@ -3421,67 +3463,55 @@ struct GetItems_Struct {
|
||||
};
|
||||
|
||||
struct BecomeTrader_Struct {
|
||||
uint32 id;
|
||||
uint32 code;
|
||||
uint32 entity_id;
|
||||
uint32 action;
|
||||
};
|
||||
|
||||
struct BazaarWindowRemoveTrader_Struct {
|
||||
uint32 action;
|
||||
uint32 trader_id;
|
||||
};
|
||||
|
||||
struct TraderPriceUpdate_Struct {
|
||||
uint32 action;
|
||||
char serial_number[17];
|
||||
char unknown_021[3];
|
||||
uint32 unknown_024;
|
||||
uint32 new_price;
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct {
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint16 TraderID;
|
||||
/*008*/ uint32 Unknown08;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct_WIP {
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ char SerialNumber[17];
|
||||
/*021*/ uint8 Unknown21;
|
||||
/*022*/ uint16 TraderID;
|
||||
/*026*/ uint32 Stacksize;
|
||||
/*030*/ uint32 Price;
|
||||
/*032*/
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 entity_id;
|
||||
/*008*/ uint32 unknown_008;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
struct TraderStatus_Struct {
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint32 Uknown04;
|
||||
/*008*/ uint32 Uknown08;
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 sub_action;
|
||||
/*008*/ uint32 uknown_008;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Unknown008;
|
||||
/*012*/ uint32 Unknown012;
|
||||
/*016*/ uint32 TraderID;
|
||||
/*020*/ char BuyerName[64];
|
||||
/*084*/ char SellerName[64];
|
||||
/*148*/ char Unknown148[32];
|
||||
/*180*/ char ItemName[64];
|
||||
/*244*/ char SerialNumber[16];
|
||||
/*260*/ uint32 Unknown076;
|
||||
/*264*/ uint32 ItemID;
|
||||
/*268*/ uint32 Price;
|
||||
/*272*/ uint32 AlreadySold;
|
||||
/*276*/ uint32 Unknown276;
|
||||
/*280*/ uint32 Quantity;
|
||||
/*284*/
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct_OLD {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Price;
|
||||
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
|
||||
/*016*/ uint32 TraderID;
|
||||
/*020*/ char ItemName[64];
|
||||
/*084*/ uint32 Unknown076;
|
||||
/*088*/ uint32 ItemID;
|
||||
/*092*/ uint32 AlreadySold;
|
||||
/*096*/ uint32 Quantity;
|
||||
/*100*/ uint32 Unknown092;
|
||||
/*104*/
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 method;
|
||||
/*008*/ uint32 sub_action;
|
||||
/*012*/ uint32 unknown_012;
|
||||
/*016*/ uint32 trader_id;
|
||||
/*020*/ char buyer_name[64];
|
||||
/*084*/ char seller_name[64];
|
||||
/*148*/ char unknown_148[32];
|
||||
/*180*/ char item_name[64];
|
||||
/*244*/ char serial_number[17];
|
||||
/*261*/ char unknown_261[3];
|
||||
/*264*/ uint32 item_id;
|
||||
/*268*/ uint32 price;
|
||||
/*272*/ uint32 already_sold;
|
||||
/*276*/ uint32 unknown_276;
|
||||
/*280*/ uint32 quantity;
|
||||
/*284*/
|
||||
};
|
||||
|
||||
struct TraderItemUpdate_Struct{
|
||||
@@ -3502,15 +3532,15 @@ struct MoneyUpdate_Struct{
|
||||
struct TraderDelItem_Struct{
|
||||
/*000*/ uint32 Unknown000;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ char SerialNumber[16];
|
||||
/*008*/ char SerialNumber[17];
|
||||
/*024*/ uint32 Unknown012;
|
||||
/*028*/
|
||||
};
|
||||
|
||||
struct TraderClick_Struct{
|
||||
/*000*/ uint32 Code;
|
||||
/*004*/ uint32 TraderID;
|
||||
/*008*/ uint32 Approval;
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 trader_id;
|
||||
/*008*/ uint32 unknown_008;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
|
||||
@@ -3376,17 +3376,17 @@ struct TraderStatus_Struct {
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Price;
|
||||
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
|
||||
/*016*/ uint32 TraderID;
|
||||
/*020*/ char ItemName[64];
|
||||
/*084*/ uint32 Unknown076;
|
||||
/*088*/ uint32 ItemID;
|
||||
/*092*/ uint32 AlreadySold;
|
||||
/*096*/ uint32 Quantity;
|
||||
/*100*/ uint32 Unknown092;
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 unknown_004;
|
||||
/*008*/ uint32 price;
|
||||
/*012*/ uint32 unknown_008; // Probably high order bits of a 64 bit price.
|
||||
/*016*/ uint32 trader_id;
|
||||
/*020*/ char item_name[64];
|
||||
/*084*/ uint32 unknown_076;
|
||||
/*088*/ uint32 item_id;
|
||||
/*092*/ uint32 already_sold;
|
||||
/*096*/ uint32 quantity;
|
||||
/*100*/ uint32 unknown_092;
|
||||
/*104*/
|
||||
};
|
||||
|
||||
|
||||
+13
-13
@@ -2286,13 +2286,13 @@ namespace SoD
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
|
||||
OUT(Action);
|
||||
OUT(Price);
|
||||
OUT(TraderID);
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(ItemID);
|
||||
OUT(Quantity);
|
||||
OUT(AlreadySold);
|
||||
OUT(action);
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
|
||||
OUT(item_id);
|
||||
OUT(quantity);
|
||||
OUT(already_sold);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -3517,12 +3517,12 @@ namespace SoD
|
||||
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
MEMSET_IN(TraderBuy_Struct);
|
||||
|
||||
IN(Action);
|
||||
IN(Price);
|
||||
IN(TraderID);
|
||||
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
||||
IN(ItemID);
|
||||
IN(Quantity);
|
||||
IN(action);
|
||||
IN(price);
|
||||
IN(trader_id);
|
||||
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
|
||||
IN(item_id);
|
||||
IN(quantity);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
@@ -2879,20 +2879,21 @@ struct Trader_ShowItems_Struct{
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Price;
|
||||
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
|
||||
/*016*/ uint32 TraderID;
|
||||
/*020*/ char ItemName[64];
|
||||
/*084*/ uint32 Unknown076;
|
||||
/*088*/ uint32 ItemID;
|
||||
/*092*/ uint32 AlreadySold;
|
||||
/*096*/ uint32 Quantity;
|
||||
/*100*/ uint32 Unknown092;
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 unknown_004;
|
||||
/*008*/ uint32 price;
|
||||
/*012*/ uint32 unknown_008; // Probably high order bits of a 64 bit price.
|
||||
/*016*/ uint32 trader_id;
|
||||
/*020*/ char item_name[64];
|
||||
/*084*/ uint32 unknown_076;
|
||||
/*088*/ uint32 item_id;
|
||||
/*092*/ uint32 already_sold;
|
||||
/*096*/ uint32 quantity;
|
||||
/*100*/ uint32 unknown_092;
|
||||
/*104*/
|
||||
};
|
||||
|
||||
|
||||
struct TraderItemUpdate_Struct{
|
||||
uint32 unknown0;
|
||||
uint32 traderid;
|
||||
|
||||
+15
-15
@@ -270,8 +270,8 @@ namespace SoF
|
||||
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
|
||||
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
|
||||
|
||||
OUT(ID);
|
||||
OUT(Code);
|
||||
OUT(trader_id);
|
||||
OUT(action);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -1902,13 +1902,13 @@ namespace SoF
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
|
||||
OUT(Action);
|
||||
OUT(Price);
|
||||
OUT(TraderID);
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(ItemID);
|
||||
OUT(Quantity);
|
||||
OUT(AlreadySold);
|
||||
OUT(action);
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
memcpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
|
||||
OUT(item_id);
|
||||
OUT(quantity);
|
||||
OUT(already_sold);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@@ -2908,12 +2908,12 @@ namespace SoF
|
||||
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
MEMSET_IN(TraderBuy_Struct);
|
||||
|
||||
IN(Action);
|
||||
IN(Price);
|
||||
IN(TraderID);
|
||||
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
||||
IN(ItemID);
|
||||
IN(Quantity);
|
||||
IN(action);
|
||||
IN(price);
|
||||
IN(trader_id);
|
||||
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
|
||||
IN(item_id);
|
||||
IN(quantity);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
@@ -2771,8 +2771,8 @@ struct GetItems_Struct{
|
||||
};
|
||||
|
||||
struct BecomeTrader_Struct{
|
||||
uint32 ID;
|
||||
uint32 Code;
|
||||
uint32 trader_id;
|
||||
uint32 action;
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct{
|
||||
@@ -2782,15 +2782,15 @@ struct Trader_ShowItems_Struct{
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Price;
|
||||
/*008*/ uint32 TraderID;
|
||||
/*012*/ char ItemName[64];
|
||||
/*076*/ uint32 Unknown076;
|
||||
/*080*/ uint32 ItemID;
|
||||
/*084*/ uint32 AlreadySold;
|
||||
/*088*/ uint32 Quantity;
|
||||
/*092*/ uint32 Unknown092;
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 price;
|
||||
/*008*/ uint32 trader_id;
|
||||
/*012*/ char item_name[64];
|
||||
/*076*/ uint32 unknown_076;
|
||||
/*080*/ uint32 item_id;
|
||||
/*084*/ uint32 already_sold;
|
||||
/*088*/ uint32 quantity;
|
||||
/*092*/ uint32 unknown_092;
|
||||
};
|
||||
|
||||
struct TraderItemUpdate_Struct{
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
eq_struct *eq = (eq_struct *) __packet->pBuffer; \
|
||||
|
||||
#define ALLOC_LEN_ENCODE(len) \
|
||||
__packet->pBuffer = new unsigned char[len]; \
|
||||
__packet->pBuffer = new unsigned char[len] {}; \
|
||||
__packet->size = len; \
|
||||
memset(__packet->pBuffer, 0, len); \
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
#define SETUP_DIRECT_DECODE(emu_struct, eq_struct) \
|
||||
unsigned char *__eq_buffer = __packet->pBuffer; \
|
||||
__packet->size = sizeof(emu_struct); \
|
||||
__packet->pBuffer = new unsigned char[__packet->size]; \
|
||||
__packet->pBuffer = new unsigned char[__packet->size] {}; \
|
||||
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
|
||||
eq_struct *eq = (eq_struct *) __eq_buffer;
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
eq_struct* in = (eq_struct*)__packet->pBuffer; \
|
||||
auto size = strlen(in->var_field); \
|
||||
__packet->size = sizeof(emu_struct) + size + 1; \
|
||||
__packet->pBuffer = new unsigned char[__packet->size]; \
|
||||
__packet->pBuffer = new unsigned char[__packet->size] {}; \
|
||||
emu_struct *emu = (emu_struct *) __packet->pBuffer; \
|
||||
eq_struct *eq = (eq_struct *) __eq_buffer;
|
||||
|
||||
|
||||
+397
-68
@@ -32,6 +32,7 @@
|
||||
#include "../strings.h"
|
||||
#include "../item_instance.h"
|
||||
#include "titanium_structs.h"
|
||||
#include "../rulesys.h"
|
||||
#include "../path_manager.h"
|
||||
#include "../raid.h"
|
||||
#include "../guilds.h"
|
||||
@@ -197,64 +198,135 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_BazaarSearch)
|
||||
{
|
||||
if (((*p)->size == sizeof(BazaarReturnDone_Struct)) || ((*p)->size == sizeof(BazaarWelcome_Struct))) {
|
||||
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer;
|
||||
uint32 action = *(uint32 *)in->pBuffer;
|
||||
|
||||
//determine and verify length
|
||||
int entrycount = in->size / sizeof(BazaarSearchResults_Struct);
|
||||
if (entrycount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0) {
|
||||
Log(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
||||
delete in;
|
||||
return;
|
||||
switch (action) {
|
||||
case BazaarSearch: {
|
||||
LogTrading(
|
||||
"Encode OP_BazaarSearch(Ti) BazaarSearch action <green>[{}]",
|
||||
action
|
||||
);
|
||||
std::vector<BazaarSearchResultsFromDB_Struct> results {};
|
||||
auto bsms = (BazaarSearchMessaging_Struct *)in->pBuffer;
|
||||
EQ::Util::MemoryStreamReader ss(
|
||||
reinterpret_cast<char *>(bsms->payload),
|
||||
in->size - sizeof(BazaarSearchMessaging_Struct)
|
||||
);
|
||||
cereal::BinaryInputArchive ar(ss);
|
||||
ar(results);
|
||||
|
||||
auto size = results.size() * sizeof(structs::BazaarSearchResults_Struct);
|
||||
auto buffer = new uchar[size];
|
||||
uchar *bufptr = buffer;
|
||||
memset(buffer, 0, size);
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, structs::TiBazaarTraderBuyerActions::BazaarSearch);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->trader_entity_id);
|
||||
bufptr += 4;
|
||||
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->item_id);
|
||||
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number);
|
||||
bufptr += 4;
|
||||
if (row->stackable) {
|
||||
strn0cpy(
|
||||
reinterpret_cast<char *>(bufptr),
|
||||
fmt::format("{}({})", row->item_name.c_str(), row->charges).c_str(),
|
||||
64
|
||||
);
|
||||
}
|
||||
else {
|
||||
strn0cpy(
|
||||
reinterpret_cast<char *>(bufptr),
|
||||
fmt::format("{}({})", row->item_name.c_str(), row->count).c_str(),
|
||||
64
|
||||
);
|
||||
}
|
||||
bufptr += 64;
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->cost);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->item_stat);
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_BazaarSearch, size);
|
||||
memcpy(outapp->pBuffer, buffer, size);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
|
||||
safe_delete(outapp);
|
||||
safe_delete_array(buffer);
|
||||
safe_delete(in);
|
||||
break;
|
||||
}
|
||||
case BazaarInspect:
|
||||
case WelcomeMessage: {
|
||||
LogTrading(
|
||||
"Encode OP_BazaarSearch(Ti) BazaarInspect/WelcomeMessage action <green>[{}]",
|
||||
action
|
||||
);
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading(
|
||||
"Encode OP_BazaarSearch(Ti) unhandled action <red>[{}]",
|
||||
action
|
||||
);
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
}
|
||||
|
||||
//make the EQ struct.
|
||||
in->size = sizeof(structs::BazaarSearchResults_Struct)*entrycount;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *) in->pBuffer;
|
||||
|
||||
//zero out the packet. We could avoid this memset by setting all fields (including unknowns) in the loop.
|
||||
memset(in->pBuffer, 0, in->size);
|
||||
|
||||
for (int i = 0; i < entrycount; i++, eq++, emu++) {
|
||||
eq->Beginning.Action = emu->Beginning.Action;
|
||||
eq->Beginning.Unknown001 = emu->Beginning.Unknown001;
|
||||
eq->Beginning.Unknown002 = emu->Beginning.Unknown002;
|
||||
eq->NumItems = emu->NumItems;
|
||||
eq->SerialNumber = emu->SerialNumber;
|
||||
eq->SellerID = emu->SellerID;
|
||||
eq->Cost = emu->Cost;
|
||||
eq->ItemStat = emu->ItemStat;
|
||||
strcpy(eq->ItemName, emu->ItemName);
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_BecomeTrader)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
|
||||
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
|
||||
uint32 action = *(uint32 *)(*p)->pBuffer;
|
||||
|
||||
OUT(ID);
|
||||
OUT(Code);
|
||||
|
||||
FINISH_ENCODE();
|
||||
switch (action)
|
||||
{
|
||||
case TraderOff:
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
|
||||
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_BecomeTrader(Ti) TraderOff action <green>[{}] entity_id <green>[{}] trader_name "
|
||||
"<green>[{}]",
|
||||
emu->action,
|
||||
emu->entity_id,
|
||||
emu->trader_name
|
||||
);
|
||||
eq->action = structs::TiBazaarTraderBuyerActions::Zero;
|
||||
eq->entity_id = emu->entity_id;
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case TraderOn:
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
|
||||
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_BecomeTrader(Ti) TraderOn action <green>[{}] entity_id <green>[{}] trader_name "
|
||||
"<green>[{}]",
|
||||
emu->action,
|
||||
emu->entity_id,
|
||||
emu->trader_name
|
||||
);
|
||||
eq->action = structs::TiBazaarTraderBuyerActions::BeginTraderMode;
|
||||
eq->entity_id = emu->entity_id;
|
||||
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
LogTrading(
|
||||
"Encode OP_BecomeTrader(Ti) unhandled action <red>[{}] Sending packet as is.",
|
||||
action
|
||||
);
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ENCODE(OP_Buff)
|
||||
@@ -2010,32 +2082,170 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_Trader)
|
||||
{
|
||||
if ((*p)->size != sizeof(TraderBuy_Struct)) {
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
auto action = *(uint32 *) (*p)->pBuffer;
|
||||
|
||||
ENCODE_FORWARD(OP_TraderBuy);
|
||||
switch (action) {
|
||||
case TraderOn: {
|
||||
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_Trader BeginTraderMode action <green>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
eq->action = structs::TiBazaarTraderBuyerActions::BeginTraderMode;
|
||||
OUT(entity_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case TraderOff: {
|
||||
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_Trader EndTraderMode action <green>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
eq->action = structs::TiBazaarTraderBuyerActions::EndTraderMode;
|
||||
OUT(entity_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case ListTraderItems: {
|
||||
ENCODE_LENGTH_EXACT(Trader_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_Struct, structs::Trader_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_Trader ListTraderItems action <green>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
eq->action = structs::TiBazaarTraderBuyerActions::ListTraderItems;
|
||||
std::copy_n(emu->items, UF::invtype::BAZAAR_SIZE, eq->item_id);
|
||||
std::copy_n(emu->item_cost, UF::invtype::BAZAAR_SIZE, eq->item_cost);
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case BuyTraderItem: {
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_Trader item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
eq->item_id,
|
||||
eq->price,
|
||||
eq->quantity,
|
||||
eq->trader_id
|
||||
);
|
||||
|
||||
eq->action = structs::TiBazaarTraderBuyerActions::BuyTraderItem;
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
OUT(item_id);
|
||||
OUT(already_sold);
|
||||
OUT(quantity);
|
||||
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case ItemMove: {
|
||||
LogTrading(
|
||||
"Encode OP_Trader ItemMove action <green>[{}]",
|
||||
action
|
||||
);
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
LogError("Unknown Encode OP_Trader action <red>{} received. Unhandled.", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ENCODE(OP_TraderBuy)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_TraderBuy item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
emu->item_id,
|
||||
emu->price,
|
||||
emu->quantity,
|
||||
emu->trader_id
|
||||
);
|
||||
|
||||
OUT(Action);
|
||||
OUT(Price);
|
||||
OUT(TraderID);
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(ItemID);
|
||||
OUT(Quantity);
|
||||
OUT(AlreadySold);
|
||||
OUT(action);
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
OUT(item_id);
|
||||
OUT(already_sold);
|
||||
OUT(quantity);
|
||||
OUT_str(item_name);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_TraderShop)
|
||||
{
|
||||
auto action = *(uint32 *)(*p)->pBuffer;
|
||||
|
||||
switch (action) {
|
||||
case ClickTrader: {
|
||||
ENCODE_LENGTH_EXACT(TraderClick_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderClick_Struct, structs::TraderClick_Struct);
|
||||
LogTrading(
|
||||
"ClickTrader action <green>[{}] trader_id <green>[{}]",
|
||||
action,
|
||||
emu->TraderID
|
||||
);
|
||||
|
||||
eq->action = 0;
|
||||
eq->trader_id = emu->TraderID;
|
||||
eq->approval = emu->Approval;
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case BuyTraderItem: {
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_TraderShop item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
eq->item_id,
|
||||
eq->price,
|
||||
eq->quantity,
|
||||
eq->trader_id
|
||||
);
|
||||
|
||||
eq->action = structs::TiBazaarTraderBuyerActions::BuyTraderItem;
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
OUT(item_id);
|
||||
OUT(already_sold);
|
||||
OUT(quantity);
|
||||
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
LogError("Unknown Encode OP_TraderShop action <red>[{}] received. Unhandled.", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ENCODE(OP_TributeItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TributeItem_Struct);
|
||||
@@ -2286,6 +2496,53 @@ namespace Titanium
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_BazaarSearch)
|
||||
{
|
||||
uint32 action = *(uint32 *) __packet->pBuffer;
|
||||
|
||||
switch (action) {
|
||||
case structs::TiBazaarTraderBuyerActions::BazaarSearch: {
|
||||
DECODE_LENGTH_EXACT(structs::BazaarSearch_Struct);
|
||||
SETUP_DIRECT_DECODE(BazaarSearchCriteria_Struct, structs::BazaarSearch_Struct);
|
||||
|
||||
emu->action = eq->Beginning.Action;
|
||||
emu->item_stat = eq->ItemStat;
|
||||
emu->max_cost = eq->MaxPrice;
|
||||
emu->min_cost = eq->MinPrice;
|
||||
emu->max_level = eq->MaxLlevel;
|
||||
emu->min_level = eq->Minlevel;
|
||||
emu->race = eq->Race;
|
||||
emu->slot = eq->Slot;
|
||||
emu->type = eq->Type == UINT32_MAX ? UINT8_MAX : eq->Type;
|
||||
emu->trader_entity_id = eq->TraderID;
|
||||
emu->trader_id = 0;
|
||||
emu->_class = eq->Class_;
|
||||
emu->search_scope = eq->TraderID > 0 ? NonRoFBazaarSearchScope : Local_Scope;
|
||||
emu->max_results = RuleI(Bazaar, MaxSearchResults);
|
||||
strn0cpy(emu->item_name, eq->Name, sizeof(emu->item_name));
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::TiBazaarTraderBuyerActions::BazaarInspect: {
|
||||
SETUP_DIRECT_DECODE(BazaarInspect_Struct, structs::BazaarInspect_Struct);
|
||||
|
||||
IN(action);
|
||||
memcpy(emu->player_name, eq->player_name, sizeof(emu->player_name));
|
||||
IN(serial_number);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::TiBazaarTraderBuyerActions::WelcomeMessage: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("(Ti) Unhandled action <red>[{}]", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECODE(OP_Buff)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct);
|
||||
@@ -2925,18 +3182,90 @@ namespace Titanium
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Trader)
|
||||
{
|
||||
auto action = (uint32) __packet->pBuffer[0];
|
||||
|
||||
switch (action) {
|
||||
case structs::TiBazaarTraderBuyerActions::BeginTraderMode: {
|
||||
DECODE_LENGTH_EXACT(structs::BeginTrader_Struct);
|
||||
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::BeginTrader_Struct);
|
||||
LogTrading(
|
||||
"Decode OP_Trader BeginTraderMode action <red>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
emu->action = TraderOn;
|
||||
emu->unknown_004 = 0;
|
||||
std::copy_n(eq->serial_number, Titanium::invtype::BAZAAR_SIZE, emu->serial_number);
|
||||
std::copy_n(eq->cost, Titanium::invtype::BAZAAR_SIZE, emu->item_cost);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::TiBazaarTraderBuyerActions::EndTraderMode: {
|
||||
DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
LogTrading(
|
||||
"Decode OP_Trader(Ti) EndTraderMode action <red>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
emu->action = TraderOff;
|
||||
IN(entity_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::TiBazaarTraderBuyerActions::PriceUpdate:
|
||||
case structs::TiBazaarTraderBuyerActions::ItemMove:
|
||||
case structs::TiBazaarTraderBuyerActions::EndTransaction:
|
||||
case structs::TiBazaarTraderBuyerActions::ListTraderItems: {
|
||||
LogTrading(
|
||||
"Decode OP_Trader(Ti) Price/ItemMove/EndTransaction/ListTraderItems action <red>[{}]",
|
||||
action
|
||||
);
|
||||
break;
|
||||
}
|
||||
case structs::TiBazaarTraderBuyerActions::ReconcileItems: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogError("Unhandled(Ti) action <red>[{}] received.", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECODE(OP_TraderBuy)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
MEMSET_IN(TraderBuy_Struct);
|
||||
|
||||
IN(Action);
|
||||
IN(Price);
|
||||
IN(TraderID);
|
||||
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
||||
IN(ItemID);
|
||||
IN(Quantity);
|
||||
IN(action);
|
||||
IN(price);
|
||||
IN(trader_id);
|
||||
memcpy(emu->item_name, eq->item_name, sizeof(emu->item_name));
|
||||
IN(item_id);
|
||||
IN(quantity);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_TraderShop)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::TraderClick_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderClick_Struct, structs::TraderClick_Struct);
|
||||
LogTrading(
|
||||
"(Ti) action <green>[{}] trader_id <green>[{}] approval <green>[{}]",
|
||||
eq->action,
|
||||
eq->trader_id,
|
||||
eq->approval
|
||||
);
|
||||
|
||||
emu->Code = ClickTrader;
|
||||
emu->TraderID = eq->trader_id;
|
||||
emu->Approval = eq->approval;
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ E(OP_TaskDescription)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TraderShop)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
@@ -92,6 +93,7 @@ E(OP_ZoneSpawns)
|
||||
D(OP_AdventureMerchantSell)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_BazaarSearch)
|
||||
D(OP_Buff)
|
||||
D(OP_Bug)
|
||||
D(OP_CastSpell)
|
||||
@@ -123,7 +125,9 @@ D(OP_ReadBook)
|
||||
D(OP_SetServerFilter)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_ShopRequest)
|
||||
D(OP_Trader)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TraderShop)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_WearChange)
|
||||
|
||||
@@ -2273,24 +2273,29 @@ struct BazaarWelcome_Struct {
|
||||
};
|
||||
|
||||
struct BazaarSearch_Struct {
|
||||
BazaarWindowStart_Struct beginning;
|
||||
uint32 traderid;
|
||||
uint32 class_;
|
||||
uint32 race;
|
||||
uint32 stat;
|
||||
uint32 slot;
|
||||
uint32 type;
|
||||
char name[64];
|
||||
uint32 minprice;
|
||||
uint32 maxprice;
|
||||
uint32 minlevel;
|
||||
uint32 maxlevel;
|
||||
BazaarWindowStart_Struct Beginning;
|
||||
uint32 TraderID;
|
||||
uint32 Class_;
|
||||
uint32 Race;
|
||||
uint32 ItemStat;
|
||||
uint32 Slot;
|
||||
uint32 Type;
|
||||
char Name[64];
|
||||
uint32 MinPrice;
|
||||
uint32 MaxPrice;
|
||||
uint32 Minlevel;
|
||||
uint32 MaxLlevel;
|
||||
};
|
||||
struct BazaarInspect_Struct{
|
||||
|
||||
struct BazaarInspect_Struct {
|
||||
uint32 action;
|
||||
char player_name[64];
|
||||
uint32 unknown_068;
|
||||
uint32 serial_number;
|
||||
uint32 unknown_076;
|
||||
uint32 item_id;
|
||||
uint32 unknown;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct BazaarReturnDone_Struct{
|
||||
uint32 type;
|
||||
uint32 traderid;
|
||||
@@ -2298,16 +2303,17 @@ struct BazaarReturnDone_Struct{
|
||||
uint32 unknown12;
|
||||
uint32 unknown16;
|
||||
};
|
||||
|
||||
struct BazaarSearchResults_Struct {
|
||||
BazaarWindowStart_Struct Beginning;
|
||||
uint32 SellerID;
|
||||
uint32 NumItems; // Don't know. Don't know the significance of this field.
|
||||
uint32 SerialNumber;
|
||||
uint32 Unknown016;
|
||||
uint32 Unknown020; // Something to do with stats as well
|
||||
char ItemName[64];
|
||||
uint32 Cost;
|
||||
uint32 ItemStat;
|
||||
uint32 entity_id;
|
||||
uint32 unknown_008;
|
||||
uint32 item_id;
|
||||
uint32 serial_number;
|
||||
uint32 unknown_020;
|
||||
char item_name[64];
|
||||
uint32 item_cost;
|
||||
uint32 item_stat;
|
||||
};
|
||||
|
||||
struct ServerSideFilters_Struct {
|
||||
@@ -2454,11 +2460,18 @@ struct WhoAllReturnStruct {
|
||||
struct WhoAllPlayer player[0];
|
||||
};
|
||||
|
||||
struct BeginTrader_Struct {
|
||||
uint32 action;
|
||||
uint32 unknown04;
|
||||
uint64 serial_number[80];
|
||||
uint32 cost[80];
|
||||
};
|
||||
|
||||
struct Trader_Struct {
|
||||
uint32 code;
|
||||
uint32 itemid[160];
|
||||
uint32 unknown;
|
||||
uint32 itemcost[80];
|
||||
uint32 action;
|
||||
uint32 unknown004;
|
||||
uint64 item_id[80];
|
||||
uint32 item_cost[80];
|
||||
};
|
||||
|
||||
struct ClickTrader_Struct {
|
||||
@@ -2471,27 +2484,28 @@ struct GetItems_Struct{
|
||||
uint32 items[80];
|
||||
};
|
||||
|
||||
struct BecomeTrader_Struct{
|
||||
uint32 ID;
|
||||
uint32 Code;
|
||||
struct BecomeTrader_Struct {
|
||||
uint32 entity_id;
|
||||
uint32 action;
|
||||
char trader_name[64];
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct{
|
||||
uint32 code;
|
||||
uint32 traderid;
|
||||
uint32 action;
|
||||
uint32 entity_id;
|
||||
uint32 unknown08[3];
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Price;
|
||||
/*008*/ uint32 TraderID;
|
||||
/*012*/ char ItemName[64];
|
||||
/*076*/ uint32 Unknown076;
|
||||
/*080*/ uint32 ItemID;
|
||||
/*084*/ uint32 AlreadySold;
|
||||
/*088*/ uint32 Quantity;
|
||||
/*092*/ uint32 Unknown092;
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 price;
|
||||
/*008*/ uint32 trader_id;
|
||||
/*012*/ char item_name[64];
|
||||
/*076*/ uint32 unknown_076;
|
||||
/*080*/ uint32 item_id;
|
||||
/*084*/ uint32 already_sold;
|
||||
/*088*/ uint32 quantity;
|
||||
/*092*/ uint32 unknown_092;
|
||||
};
|
||||
|
||||
|
||||
@@ -2517,8 +2531,9 @@ struct TraderDelItem_Struct{
|
||||
};
|
||||
|
||||
struct TraderClick_Struct{
|
||||
uint32 traderid;
|
||||
uint32 unknown4[2];
|
||||
uint32 trader_id;
|
||||
uint32 action;
|
||||
uint32 unknown_004;
|
||||
uint32 approval;
|
||||
};
|
||||
|
||||
@@ -3744,6 +3759,21 @@ struct GuildMemberRank_Struct {
|
||||
/*076*/ uint32 alt_banker; //Banker/Alt bit 00 - none 10 - Alt 11 - Alt and Banker 01 - Banker. Banker not functional for RoF2+
|
||||
};
|
||||
|
||||
enum TiBazaarTraderBuyerActions {
|
||||
Zero = 0,
|
||||
BeginTraderMode = 1,
|
||||
EndTraderMode = 2,
|
||||
PriceUpdate = 3,
|
||||
EndTransaction = 4,
|
||||
BazaarSearch = 7,
|
||||
WelcomeMessage = 9,
|
||||
BuyTraderItem = 10,
|
||||
ListTraderItems = 11,
|
||||
BazaarInspect = 18,
|
||||
ItemMove = 19,
|
||||
ReconcileItems = 20
|
||||
};
|
||||
|
||||
}; /*structs*/
|
||||
|
||||
}; /*Titanium*/
|
||||
|
||||
+401
-69
@@ -37,6 +37,8 @@
|
||||
#include "../races.h"
|
||||
#include "../raid.h"
|
||||
#include "../guilds.h"
|
||||
//#include "../repositories/trader_repository.h"
|
||||
#include "../cereal/include/cereal/types/vector.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@@ -307,50 +309,134 @@ namespace UF
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
char *Buffer = (char *)in->pBuffer;
|
||||
uint32 action = *(uint32 *)in->pBuffer;
|
||||
|
||||
uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer);
|
||||
switch (action) {
|
||||
case BazaarSearch: {
|
||||
LogTrading(
|
||||
"Encode OP_BazaarSearch(UF) BazaarSearch action <green>[{}]",
|
||||
action
|
||||
);
|
||||
std::vector<BazaarSearchResultsFromDB_Struct> results {};
|
||||
auto bsms = (BazaarSearchMessaging_Struct *)in->pBuffer;
|
||||
EQ::Util::MemoryStreamReader ss(
|
||||
reinterpret_cast<char *>(bsms->payload),
|
||||
in->size - sizeof(BazaarSearchMessaging_Struct)
|
||||
);
|
||||
cereal::BinaryInputArchive ar(ss);
|
||||
ar(results);
|
||||
|
||||
if (SubAction != BazaarSearchResults)
|
||||
{
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
auto size = results.size() * sizeof(BazaarSearchResults_Struct);
|
||||
auto buffer = new uchar[size];
|
||||
uchar *bufptr = buffer;
|
||||
memset(buffer, 0, size);
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, structs::UFBazaarTraderBuyerActions::BazaarSearch);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->trader_entity_id);
|
||||
strn0cpy(reinterpret_cast<char *>(bufptr), row->trader_name.c_str(), 64);
|
||||
bufptr += 64;
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 1);
|
||||
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->item_id);
|
||||
VARSTRUCT_ENCODE_TYPE(int32, bufptr, row->serial_number);
|
||||
bufptr += 4;
|
||||
if (row->stackable) {
|
||||
strn0cpy(
|
||||
reinterpret_cast<char *>(bufptr),
|
||||
fmt::format("{}({})", row->item_name.c_str(), row->charges).c_str(),
|
||||
64
|
||||
);
|
||||
}
|
||||
else {
|
||||
strn0cpy(
|
||||
reinterpret_cast<char *>(bufptr),
|
||||
fmt::format("{}({})", row->item_name.c_str(), row->count).c_str(),
|
||||
64
|
||||
);
|
||||
}
|
||||
bufptr += 64;
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->cost);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, bufptr, row->item_stat);
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_BazaarSearch, size);
|
||||
memcpy(outapp->pBuffer, buffer, size);
|
||||
dest->FastQueuePacket(&outapp);
|
||||
|
||||
safe_delete(outapp);
|
||||
safe_delete_array(buffer);
|
||||
safe_delete(in);
|
||||
break;
|
||||
}
|
||||
case BazaarInspect:
|
||||
case WelcomeMessage: {
|
||||
LogTrading(
|
||||
"Encode OP_BazaarSearch(UF) BazaarInspect/WelcomeMessage action <green>[{}]",
|
||||
action
|
||||
);
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading(
|
||||
"Encode OP_BazaarSearch(UF) unhandled action <red>[{}]",
|
||||
action
|
||||
);
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
ENCODE(OP_BecomeTrader)
|
||||
{
|
||||
uint32 action = *(uint32 *)(*p)->pBuffer;
|
||||
|
||||
BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer;
|
||||
|
||||
int EntryCount = in->size / sizeof(BazaarSearchResults_Struct);
|
||||
|
||||
if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0)
|
||||
switch (action)
|
||||
{
|
||||
LogNetcode("[STRUCTS] Wrong size on outbound [{}]: Got [{}], expected multiple of [{}]", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct));
|
||||
delete in;
|
||||
return;
|
||||
case TraderOff:
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
|
||||
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_BecomeTrader(UF) TraderOff action <green>[{}] entity_id <green>[{}] trader_name "
|
||||
"<green>[{}]",
|
||||
emu->action,
|
||||
emu->entity_id,
|
||||
emu->trader_name
|
||||
);
|
||||
eq->action = structs::UFBazaarTraderBuyerActions::Zero;
|
||||
eq->entity_id = emu->entity_id;
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case TraderOn:
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(BecomeTrader_Struct);
|
||||
SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_BecomeTrader(UF) TraderOn action <green>[{}] entity_id <green>[{}] trader_name "
|
||||
"<green>[{}]",
|
||||
emu->action,
|
||||
emu->entity_id,
|
||||
emu->trader_name
|
||||
);
|
||||
eq->action = structs::UFBazaarTraderBuyerActions::BeginTraderMode;
|
||||
eq->entity_id = emu->entity_id;
|
||||
strn0cpy(eq->trader_name, emu->trader_name, sizeof(eq->trader_name));
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
LogTrading(
|
||||
"Encode OP_BecomeTrader(UF) unhandled action <red>[{}] Sending packet as is.",
|
||||
action
|
||||
);
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
}
|
||||
|
||||
in->size = EntryCount * sizeof(structs::BazaarSearchResults_Struct);
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
memset(in->pBuffer, 0, in->size);
|
||||
|
||||
structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *)in->pBuffer;
|
||||
|
||||
for (int i = 0; i < EntryCount; ++i, ++emu, ++eq)
|
||||
{
|
||||
OUT(Beginning.Action);
|
||||
OUT(SellerID);
|
||||
memcpy(eq->SellerName, emu->SellerName, sizeof(eq->SellerName));
|
||||
OUT(NumItems);
|
||||
OUT(ItemID);
|
||||
OUT(SerialNumber);
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(Cost);
|
||||
OUT(ItemStat);
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Buff)
|
||||
@@ -2743,32 +2829,170 @@ namespace UF
|
||||
|
||||
ENCODE(OP_Trader)
|
||||
{
|
||||
if ((*p)->size != sizeof(TraderBuy_Struct)) {
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
auto action = *(uint32 *) (*p)->pBuffer;
|
||||
|
||||
ENCODE_FORWARD(OP_TraderBuy);
|
||||
switch (action) {
|
||||
case TraderOn: {
|
||||
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_Trader BeginTraderMode action <green>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
eq->action = structs::UFBazaarTraderBuyerActions::BeginTraderMode;
|
||||
OUT(entity_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case TraderOff: {
|
||||
ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_Trader EndTraderMode action <green>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
eq->action = structs::UFBazaarTraderBuyerActions::EndTraderMode;
|
||||
OUT(entity_id);
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case ListTraderItems: {
|
||||
ENCODE_LENGTH_EXACT(Trader_Struct);
|
||||
SETUP_DIRECT_ENCODE(Trader_Struct, structs::Trader_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_Trader ListTraderItems action <green>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
eq->action = structs::UFBazaarTraderBuyerActions::ListTraderItems;
|
||||
std::copy_n(emu->items, UF::invtype::BAZAAR_SIZE, eq->item_id);
|
||||
std::copy_n(emu->item_cost, UF::invtype::BAZAAR_SIZE, eq->item_cost);
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case BuyTraderItem: {
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_Trader item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
eq->item_id,
|
||||
eq->price,
|
||||
eq->quantity,
|
||||
eq->trader_id
|
||||
);
|
||||
|
||||
eq->action = structs::UFBazaarTraderBuyerActions::BuyTraderItem;
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
OUT(item_id);
|
||||
OUT(already_sold);
|
||||
OUT(quantity);
|
||||
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case ItemMove: {
|
||||
LogTrading(
|
||||
"Encode OP_Trader ItemMove action <green>[{}]",
|
||||
action
|
||||
);
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
LogError("Unknown Encode OP_Trader action <red>{} received. Unhandled.", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ENCODE(OP_TraderBuy)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_TraderBuy item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
emu->item_id,
|
||||
emu->price,
|
||||
emu->quantity,
|
||||
emu->trader_id
|
||||
);
|
||||
|
||||
OUT(Action);
|
||||
OUT(Price);
|
||||
OUT(TraderID);
|
||||
memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName));
|
||||
OUT(ItemID);
|
||||
OUT(Quantity);
|
||||
OUT(AlreadySold);
|
||||
OUT(action);
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
OUT(item_id);
|
||||
OUT(already_sold);
|
||||
OUT(quantity);
|
||||
OUT_str(item_name);
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_TraderShop)
|
||||
{
|
||||
auto action = *(uint32 *)(*p)->pBuffer;
|
||||
|
||||
switch (action) {
|
||||
case ClickTrader: {
|
||||
ENCODE_LENGTH_EXACT(TraderClick_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderClick_Struct, structs::TraderClick_Struct);
|
||||
LogTrading(
|
||||
"ClickTrader action <green>[{}] trader_id <green>[{}]",
|
||||
action,
|
||||
emu->TraderID
|
||||
);
|
||||
|
||||
eq->action = 0;
|
||||
eq->trader_id = emu->TraderID;
|
||||
eq->approval = emu->Approval;
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
case BuyTraderItem: {
|
||||
ENCODE_LENGTH_EXACT(TraderBuy_Struct);
|
||||
SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"Encode OP_TraderShop item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
eq->item_id,
|
||||
eq->price,
|
||||
eq->quantity,
|
||||
eq->trader_id
|
||||
);
|
||||
|
||||
eq->action = structs::UFBazaarTraderBuyerActions::BuyTraderItem;
|
||||
OUT(price);
|
||||
OUT(trader_id);
|
||||
OUT(item_id);
|
||||
OUT(already_sold);
|
||||
OUT(quantity);
|
||||
strn0cpy(eq->item_name, emu->item_name, sizeof(eq->item_name));
|
||||
|
||||
FINISH_ENCODE();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
LogError("Unknown Encode OP_TraderShop action <red>[{}] received. Unhandled.", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ENCODE(OP_TributeItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(TributeItem_Struct);
|
||||
@@ -3040,7 +3264,7 @@ namespace UF
|
||||
Bitfields->targetable = 1;
|
||||
Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0;
|
||||
Bitfields->statue = 0;
|
||||
Bitfields->trader = 0;
|
||||
Bitfields->trader = emu->trader ? 1 : 0;
|
||||
Bitfields->buyer = 0;
|
||||
|
||||
Bitfields->showname = ShowName;
|
||||
@@ -3363,20 +3587,49 @@ namespace UF
|
||||
|
||||
DECODE(OP_BazaarSearch)
|
||||
{
|
||||
char *Buffer = (char *)__packet->pBuffer;
|
||||
uint32 action = *(uint32 *) __packet->pBuffer;
|
||||
|
||||
uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer);
|
||||
switch (action) {
|
||||
case structs::UFBazaarTraderBuyerActions::BazaarSearch: {
|
||||
DECODE_LENGTH_EXACT(structs::BazaarSearch_Struct);
|
||||
SETUP_DIRECT_DECODE(BazaarSearchCriteria_Struct, structs::BazaarSearch_Struct);
|
||||
|
||||
if ((SubAction != BazaarInspectItem) || (__packet->size != sizeof(structs::NewBazaarInspect_Struct)))
|
||||
return;
|
||||
emu->action = eq->Beginning.Action;
|
||||
emu->item_stat = eq->ItemStat;
|
||||
emu->max_cost = eq->MaxPrice;
|
||||
emu->min_cost = eq->MinPrice;
|
||||
emu->max_level = eq->MaxLlevel;
|
||||
emu->min_level = eq->Minlevel;
|
||||
emu->race = eq->Race;
|
||||
emu->slot = eq->Slot;
|
||||
emu->type = eq->Type == UINT32_MAX ? UINT8_MAX : eq->Type;
|
||||
emu->trader_entity_id = eq->TraderID;
|
||||
emu->trader_id = 0;
|
||||
emu->_class = eq->Class_;
|
||||
emu->search_scope = eq->TraderID > 0 ? NonRoFBazaarSearchScope : Local_Scope;
|
||||
emu->max_results = RuleI(Bazaar, MaxSearchResults);
|
||||
strn0cpy(emu->item_name, eq->Name, sizeof(emu->item_name));
|
||||
|
||||
SETUP_DIRECT_DECODE(NewBazaarInspect_Struct, structs::NewBazaarInspect_Struct);
|
||||
MEMSET_IN(structs::NewBazaarInspect_Struct);
|
||||
IN(Beginning.Action);
|
||||
memcpy(emu->Name, eq->Name, sizeof(emu->Name));
|
||||
IN(SerialNumber);
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::UFBazaarTraderBuyerActions::BazaarInspect: {
|
||||
SETUP_DIRECT_DECODE(BazaarInspect_Struct, structs::BazaarInspect_Struct);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
IN(action);
|
||||
memcpy(emu->player_name, eq->player_name, sizeof(emu->player_name));
|
||||
IN(serial_number);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::UFBazaarTraderBuyerActions::WelcomeMessage: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("(UF) Unhandled action <red>[{}]", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECODE(OP_BookButton)
|
||||
@@ -4059,18 +4312,97 @@ namespace UF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_Trader)
|
||||
{
|
||||
auto action = (uint32) __packet->pBuffer[0];
|
||||
|
||||
switch (action) {
|
||||
case structs::UFBazaarTraderBuyerActions::BeginTraderMode: {
|
||||
DECODE_LENGTH_EXACT(structs::BeginTrader_Struct);
|
||||
SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::BeginTrader_Struct);
|
||||
LogTrading(
|
||||
"Decode OP_Trader BeginTraderMode action <red>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
emu->action = TraderOn;
|
||||
emu->unknown_004 = 0;
|
||||
std::copy_n(eq->serial_number, UF::invtype::BAZAAR_SIZE, emu->serial_number);
|
||||
std::copy_n(eq->cost, UF::invtype::BAZAAR_SIZE, emu->item_cost);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::UFBazaarTraderBuyerActions::EndTraderMode: {
|
||||
DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct);
|
||||
SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct);
|
||||
LogTrading(
|
||||
"Decode OP_Trader(UF) EndTraderMode action <red>[{}]",
|
||||
action
|
||||
);
|
||||
|
||||
emu->action = TraderOff;
|
||||
IN(entity_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
break;
|
||||
}
|
||||
case structs::UFBazaarTraderBuyerActions::PriceUpdate:
|
||||
case structs::UFBazaarTraderBuyerActions::ItemMove:
|
||||
case structs::UFBazaarTraderBuyerActions::EndTransaction:
|
||||
case structs::UFBazaarTraderBuyerActions::ListTraderItems: {
|
||||
LogTrading(
|
||||
"Decode OP_Trader(UF) Price/ItemMove/EndTransaction/ListTraderItems action <red>[{}]",
|
||||
action
|
||||
);
|
||||
break;
|
||||
}
|
||||
case structs::UFBazaarTraderBuyerActions::ReconcileItems: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogError("Unhandled(UF) action <red>[{}] received.", action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECODE(OP_TraderBuy)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::TraderBuy_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct);
|
||||
MEMSET_IN(TraderBuy_Struct);
|
||||
LogTrading(
|
||||
"Decode OP_TraderBuy(UF) item_id <green>[{}] price <green>[{}] quantity <green>[{}] trader_id <green>[{}]",
|
||||
eq->item_id,
|
||||
eq->price,
|
||||
eq->quantity,
|
||||
eq->trader_id
|
||||
);
|
||||
|
||||
IN(Action);
|
||||
IN(Price);
|
||||
IN(TraderID);
|
||||
memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName));
|
||||
IN(ItemID);
|
||||
IN(Quantity);
|
||||
emu->action = BuyTraderItem;
|
||||
IN(price);
|
||||
IN(trader_id);
|
||||
IN(item_id);
|
||||
IN(quantity);
|
||||
IN(already_sold);
|
||||
strn0cpy(emu->item_name, eq->item_name, sizeof(eq->item_name));
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_TraderShop)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::TraderClick_Struct);
|
||||
SETUP_DIRECT_DECODE(TraderClick_Struct, structs::TraderClick_Struct);
|
||||
LogTrading(
|
||||
"(UF) action <green>[{}] trader_id <green>[{}] approval <green>[{}]",
|
||||
eq->action,
|
||||
eq->trader_id,
|
||||
eq->approval
|
||||
);
|
||||
|
||||
emu->Code = ClickTrader;
|
||||
emu->TraderID = eq->trader_id;
|
||||
emu->Approval = eq->approval;
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ E(OP_ApplyPoison)
|
||||
E(OP_AugmentInfo)
|
||||
E(OP_Barter)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_Buff)
|
||||
E(OP_BuffCreate)
|
||||
E(OP_CancelTrade)
|
||||
@@ -100,6 +101,7 @@ E(OP_TaskDescription)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
E(OP_TraderShop)
|
||||
E(OP_TributeItem)
|
||||
E(OP_VetRewardsAvaliable)
|
||||
E(OP_WearChange)
|
||||
@@ -160,7 +162,9 @@ D(OP_SetServerFilter)
|
||||
D(OP_ShopPlayerBuy)
|
||||
D(OP_ShopPlayerSell)
|
||||
D(OP_ShopRequest)
|
||||
D(OP_Trader)
|
||||
D(OP_TraderBuy)
|
||||
D(OP_TraderShop)
|
||||
D(OP_TradeSkillCombine)
|
||||
D(OP_TributeItem)
|
||||
D(OP_WearChange)
|
||||
|
||||
+75
-39
@@ -2640,23 +2640,23 @@ struct EnvDamage2_Struct {
|
||||
//Bazaar Stuff
|
||||
|
||||
enum {
|
||||
BazaarTrader_StartTraderMode = 1,
|
||||
BazaarTrader_EndTraderMode = 2,
|
||||
BazaarTrader_UpdatePrice = 3,
|
||||
BazaarTrader_EndTransaction = 4,
|
||||
BazaarSearchResults = 7,
|
||||
BazaarWelcome = 9,
|
||||
BazaarBuyItem = 10,
|
||||
BazaarTrader_ShowItems = 11,
|
||||
BazaarSearchDone = 12,
|
||||
BazaarTrader_StartTraderMode = 1,
|
||||
BazaarTrader_EndTraderMode = 2,
|
||||
BazaarTrader_UpdatePrice = 3,
|
||||
BazaarTrader_EndTransaction = 4,
|
||||
BazaarSearchResults = 7,
|
||||
BazaarWelcome = 9,
|
||||
BazaarBuyItem = 10,
|
||||
BazaarTrader_ShowItems = 11,
|
||||
BazaarSearchDone = 12,
|
||||
BazaarTrader_CustomerBrowsing = 13
|
||||
};
|
||||
|
||||
enum {
|
||||
BazaarPriceChange_Fail = 0,
|
||||
BazaarPriceChange_Fail = 0,
|
||||
BazaarPriceChange_UpdatePrice = 1,
|
||||
BazaarPriceChange_RemoveItem = 2,
|
||||
BazaarPriceChange_AddItem = 3
|
||||
BazaarPriceChange_RemoveItem = 2,
|
||||
BazaarPriceChange_AddItem = 3
|
||||
};
|
||||
|
||||
struct BazaarWindowStart_Struct {
|
||||
@@ -2687,10 +2687,14 @@ struct BazaarSearch_Struct {
|
||||
uint32 Minlevel;
|
||||
uint32 MaxLlevel;
|
||||
};
|
||||
struct BazaarInspect_Struct{
|
||||
uint32 ItemID;
|
||||
uint32 Unknown004;
|
||||
char Name[64];
|
||||
|
||||
struct BazaarInspect_Struct {
|
||||
uint32 action;
|
||||
char player_name[64];
|
||||
uint32 unknown_068;
|
||||
uint32 serial_number;
|
||||
uint32 unknown_076;
|
||||
uint32 item_id;
|
||||
};
|
||||
|
||||
struct NewBazaarInspect_Struct {
|
||||
@@ -2929,10 +2933,17 @@ struct WhoAllPlayerPart4 {
|
||||
};
|
||||
|
||||
struct Trader_Struct {
|
||||
uint32 code;
|
||||
uint32 itemid[160];
|
||||
uint32 unknown;
|
||||
uint32 itemcost[80];
|
||||
uint32 action;
|
||||
uint32 unknown004;
|
||||
uint64 item_id[80];
|
||||
uint32 item_cost[80];
|
||||
};
|
||||
|
||||
struct BeginTrader_Struct {
|
||||
uint32 action;
|
||||
uint32 unknown04;
|
||||
uint64 serial_number[80];
|
||||
uint32 cost[80];
|
||||
};
|
||||
|
||||
struct ClickTrader_Struct {
|
||||
@@ -2945,30 +2956,30 @@ struct GetItems_Struct{
|
||||
uint32 items[80];
|
||||
};
|
||||
|
||||
struct BecomeTrader_Struct{
|
||||
uint32 id;
|
||||
uint32 code;
|
||||
struct BecomeTrader_Struct {
|
||||
uint32 entity_id;
|
||||
uint32 action;
|
||||
char trader_name[64];
|
||||
};
|
||||
|
||||
struct Trader_ShowItems_Struct{
|
||||
uint32 code;
|
||||
uint32 traderid;
|
||||
uint32 action;
|
||||
uint32 entity_id;
|
||||
uint32 unknown08[3];
|
||||
};
|
||||
|
||||
struct TraderBuy_Struct {
|
||||
/*000*/ uint32 Action;
|
||||
/*004*/ uint32 Unknown004;
|
||||
/*008*/ uint32 Price;
|
||||
/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price.
|
||||
/*016*/ uint32 TraderID;
|
||||
/*020*/ char ItemName[64];
|
||||
/*084*/ uint32 Unknown076;
|
||||
/*088*/ uint32 ItemID;
|
||||
/*092*/ uint32 AlreadySold;
|
||||
/*096*/ uint32 Quantity;
|
||||
/*100*/ uint32 Unknown092;
|
||||
/*104*/
|
||||
uint32 action;
|
||||
uint32 unknown_004;
|
||||
uint32 price;
|
||||
uint32 unknown_008; // Probably high order bits of a 64 bit price.
|
||||
uint32 trader_id;
|
||||
char item_name[64];
|
||||
uint32 unknown_076;
|
||||
uint32 item_id;
|
||||
uint32 already_sold;
|
||||
uint32 quantity;
|
||||
uint32 unknown_092;
|
||||
};
|
||||
|
||||
struct TraderItemUpdate_Struct{
|
||||
@@ -3002,8 +3013,9 @@ struct TraderDelItem_Struct{
|
||||
};
|
||||
|
||||
struct TraderClick_Struct{
|
||||
uint32 traderid;
|
||||
uint32 unknown4[2];
|
||||
uint32 trader_id;
|
||||
uint32 action;
|
||||
uint32 unknown_004;
|
||||
uint32 approval;
|
||||
};
|
||||
|
||||
@@ -4674,6 +4686,30 @@ struct SayLinkBodyFrame_Struct {
|
||||
/*050*/
|
||||
};
|
||||
|
||||
struct TraderPriceUpdate_Struct {
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ uint32 sub_action;
|
||||
/*008*/ int32 serial_number;
|
||||
/*012*/ uint32 unknown_012;
|
||||
/*016*/ uint32 new_price;
|
||||
/*020*/ uint32 unknown_016;
|
||||
};
|
||||
|
||||
enum UFBazaarTraderBuyerActions {
|
||||
Zero = 0,
|
||||
BeginTraderMode = 1,
|
||||
EndTraderMode = 2,
|
||||
PriceUpdate = 3,
|
||||
EndTransaction = 4,
|
||||
BazaarSearch = 7,
|
||||
WelcomeMessage = 9,
|
||||
BuyTraderItem = 10,
|
||||
ListTraderItems = 11,
|
||||
BazaarInspect = 18,
|
||||
ItemMove = 19,
|
||||
ReconcileItems = 20
|
||||
};
|
||||
|
||||
}; /*structs*/
|
||||
|
||||
}; /*UF*/
|
||||
|
||||
Reference in New Issue
Block a user