Trader Direct purchase updated and tested

This commit is contained in:
Mitch Freeman 2025-04-06 23:34:05 -03:00
parent 868815e658
commit 6ede52c004
19 changed files with 687 additions and 788 deletions

View File

@ -187,11 +187,11 @@ Bazaar::GetSearchResults(
);
}
else {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
search_criteria_trader.append(fmt::format(" AND trader.character_id = {}", search.trader_id));
}
}
else {
search_criteria_trader.append(fmt::format(" AND trader.char_id = {}", search.trader_id));
search_criteria_trader.append(fmt::format(" AND trader.character_id = {}", search.trader_id));
}
}
@ -297,8 +297,8 @@ Bazaar::GetSearchResults(
BazaarSearchResultsFromDB_Struct r{};
r.count = 1;
r.trader_id = t.trader.char_id;
r.serial_number = t.trader.item_sn;
r.trader_id = t.trader.character_id;
r.item_unique_id = t.trader.item_unique_id;
r.cost = t.trader.item_cost;
r.slot_id = t.trader.slot_id;
r.charges = t.trader.item_charges;
@ -307,7 +307,6 @@ Bazaar::GetSearchResults(
r.trader_zone_id = t.trader.char_zone_id;
r.trader_zone_instance_id = t.trader.char_zone_instance_id;
r.trader_entity_id = t.trader.char_entity_id;
r.serial_number_RoF = t.trader.item_sn;
r.item_name = fmt::format("{:.63}\0", item_results.at(t.trader.item_id).name);
r.trader_name = fmt::format("{:.63}\0", t.trader_name);
r.item_stat = item_results.at(t.trader.item_id).stats;

View File

@ -7189,7 +7189,7 @@ ALTER TABLE `character_parcels_containers`
ManifestEntry{
.version = 9329,
.description = "2025_03_27_implement_item_unique_unique_id.sql",
.check = "SHOW COLUMNS FROM `inventory` LIKE 'serial_number'",
.check = "SHOW COLUMNS FROM `inventory` LIKE 'item_unique_id'",
.condition = "empty",
.match = "",
.sql = R"(
@ -7220,6 +7220,23 @@ ALTER TABLE `inventory_snapshots`
DROP PRIMARY KEY,
ADD PRIMARY KEY (`time_index`, `character_id`, `slot_id`) USING BTREE;
ALTER TABLE `trader`
CHANGE COLUMN `char_id` `character_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`,
ADD COLUMN `item_unique_id` VARCHAR(16) NULL DEFAULT NULL AFTER `item_id`,
CHANGE COLUMN `aug_slot_1` `augment_one` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `item_unique_id`,
CHANGE COLUMN `aug_slot_2` `augment_two` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `augment_one`,
CHANGE COLUMN `aug_slot_3` `augment_three` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `augment_two`,
CHANGE COLUMN `aug_slot_4` `augment_four` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `augment_three`,
CHANGE COLUMN `aug_slot_5` `augment_five` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `augment_four`,
CHANGE COLUMN `aug_slot_6` `augment_six` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `augment_five`,
DROP COLUMN `item_sn`,
DROP INDEX `idx_trader_item_sn`,
DROP INDEX `charid_slotid`,
ADD INDEX `charid_slotid` (`character_id`, `slot_id`) USING BTREE,
DROP INDEX `idx_trader_char`,
ADD INDEX `idx_trader_char` (`character_id`, `char_zone_id`, `char_zone_instance_id`) USING BTREE,
ADD UNIQUE INDEX `idx_item_unique_id` (`item_unique_id`);
)",
.content_schema_update = false
},

View File

@ -3093,7 +3093,7 @@ struct BazaarSearchCriteria_Struct {
struct BazaarInspect_Struct {
uint32 action;
char player_name[64];
char serial_number[16];
char item_unique_id[17];
uint32 item_id;
uint32 trader_id;
};
@ -3730,7 +3730,7 @@ struct Trader_Struct {
};
struct TraderItems_Struct {
std::string serial_number;
std::string item_unique_id;
uint32 item_id;
uint64 item_cost;
@ -3738,7 +3738,7 @@ struct TraderItems_Struct {
void serialize(Archive &archive)
{
archive(
CEREAL_NVP(serial_number),
CEREAL_NVP(item_unique_id),
CEREAL_NVP(item_id),
CEREAL_NVP(item_cost)
);
@ -3850,7 +3850,7 @@ struct TraderBuy_Struct {
/*084*/ char seller_name[64];
/*148*/ char unknown_148[32];
/*180*/ char item_name[64];
/*244*/ char serial_number[17];
/*244*/ char item_unique_id[17];
/*261*/ char unknown_261[3];
/*264*/ uint32 item_id;
/*268*/ uint32 price;
@ -3869,12 +3869,12 @@ struct TraderItemUpdate_Struct{
};
struct TraderPriceUpdate_Struct {
/*000*/ uint32 Action;
/*004*/ uint32 SubAction;
/*008*/ char serial_number[16];
/*012*/ uint32 Unknown012;
/*016*/ uint32 NewPrice;
/*020*/ uint32 Unknown016;
/*000*/ uint32 action;
/*002*/ uint32 sub_action;
/*004*/ char item_unique_id[17];
/*021*/ char unknown_021[3];
/*024*/ uint32 unknown_024;
/*028*/ uint32 new_price;
};
struct MoneyUpdate_Struct{
@ -3889,6 +3889,7 @@ struct TraderDelItem_Struct{
uint32 trader_id;
uint32 item_id;
uint32 unknown_012;
char item_unique_id[17];
};
struct TraderClick_Struct{
@ -6494,7 +6495,7 @@ struct BazaarSearchResultsFromDB_Struct {
uint32 count;
uint32 trader_id;
uint32 item_id;
std::string serial_number;
std::string item_unique_id;
uint32 charges;
uint32 cost;
uint32 slot_id;
@ -6506,7 +6507,6 @@ struct BazaarSearchResultsFromDB_Struct {
uint32 item_stat;
bool stackable;
std::string item_name;
std::string serial_number_RoF;
std::string trader_name;
template<class Archive>
@ -6516,7 +6516,7 @@ struct BazaarSearchResultsFromDB_Struct {
CEREAL_NVP(count),
CEREAL_NVP(trader_id),
CEREAL_NVP(item_id),
CEREAL_NVP(serial_number),
CEREAL_NVP(item_unique_id),
CEREAL_NVP(charges),
CEREAL_NVP(cost),
CEREAL_NVP(slot_id),
@ -6528,7 +6528,6 @@ struct BazaarSearchResultsFromDB_Struct {
CEREAL_NVP(item_stat),
CEREAL_NVP(stackable),
CEREAL_NVP(item_name),
CEREAL_NVP(serial_number_RoF),
CEREAL_NVP(trader_name)
);
}

View File

@ -159,7 +159,7 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy)
m_timers = copy.m_timers;
if (copy.GetUniqueID().empty()) {
LogError("Creating Serial Number as part of Clone command");
LogError("Creating unique item ID as part of clone process for item id {}", copy.GetID());
copy.CreateUniqueID();
}
m_unique_id = copy.m_unique_id;

View File

@ -168,6 +168,14 @@ namespace EQ
int16 GetCharges() const { return m_charges; }
void SetCharges(int16 charges) { m_charges = charges; }
int16 GetQuantityFromCharges() const
{
if (GetCharges() > 0 || IsStackable() || GetItem()->MaxCharges > 0) {
return GetCharges();
}
return 1;
}
uint32 GetPrice() const { return m_price; }
void SetPrice(uint32 price) { m_price = price; }

View File

@ -480,7 +480,7 @@ namespace RoF2
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_STRING(bufptr, i.item_unique_id.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
@ -757,7 +757,7 @@ namespace RoF2
ar(bl);
//packet size
auto packet_size = bl.item_name.length() + 1 + 34;
uint32 packet_size = bl.item_name.length() + 1 + 34;
for (auto const &b: bl.trade_items) {
packet_size += b.item_name.length() + 1;
packet_size += 12;
@ -4130,17 +4130,19 @@ namespace RoF2
auto buffer = new char[4404]{}; // 4404 is the fixed size of the packet for 200 item limit of RoF2
auto pos = buffer;
auto pos_unique_id = buffer + 4;
auto pos_cost = buffer + 3604;
VARSTRUCT_ENCODE_TYPE(uint32, pos, structs::RoF2BazaarTraderBuyerActions::ListTraderItems);
for (auto const &t: tcm.items) {
strn0cpy(pos, t.serial_number.data(), t.serial_number.length() + 1);
pos += 3600;
VARSTRUCT_ENCODE_TYPE(uint32, pos, t.item_cost);
pos -= 3604 - 18;
strn0cpy(pos_unique_id, t.item_unique_id.data(), t.item_unique_id.length() + 1);
*(uint32 *) pos_cost = t.item_cost;
pos_unique_id += 18;
pos_cost += 4;
}
for (int i = tcm.items.size(); i < EQ::invtype::BAZAAR_SIZE; i++) {
strn0cpy(pos, "0000000000000000", 18);
pos += 18;
strn0cpy(pos_unique_id, "0000000000000000", 18);
pos_unique_id += 18;
}
safe_delete_array(in->pBuffer);
@ -4160,7 +4162,7 @@ namespace RoF2
}
case PriceUpdate: {
SETUP_DIRECT_ENCODE(TraderPriceUpdate_Struct, structs::TraderPriceUpdate_Struct);
switch (emu->SubAction) {
switch (emu->sub_action) {
case BazaarPriceChange_AddItem: {
auto outapp = std::make_unique<EQApplicationPacket>(
OP_Trader,
@ -4168,7 +4170,7 @@ namespace RoF2
);
auto data = (structs::TraderStatus_Struct *) outapp->pBuffer;
data->action = emu->Action;
data->action = emu->action;
data->sub_action = BazaarPriceChange_AddItem;
LogTrading(
"(RoF2) PriceUpdate action <green>[{}] AddItem subaction <yellow>[{}]",
@ -4186,7 +4188,7 @@ namespace RoF2
);
auto data = (structs::TraderStatus_Struct *) outapp->pBuffer;
data->action = emu->Action;
data->action = emu->action;
data->sub_action = BazaarPriceChange_RemoveItem;
LogTrading(
"(RoF2) PriceUpdate action <green>[{}] RemoveItem subaction <yellow>[{}]",
@ -4204,7 +4206,7 @@ namespace RoF2
);
auto data = (structs::TraderStatus_Struct *) outapp->pBuffer;
data->action = emu->Action;
data->action = emu->action;
data->sub_action = BazaarPriceChange_UpdatePrice;
LogTrading(
"(RoF2) PriceUpdate action <green>[{}] UpdatePrice subaction <yellow>[{}]",
@ -4229,7 +4231,7 @@ namespace RoF2
"(RoF2) BuyTraderItem action <green>[{}] item_id <green>[{}] item_sn <green>[{}] buyer <green>[{}]",
action,
eq->item_id,
eq->serial_number,
eq->item_unique_id,
eq->buyer_name
);
dest->FastQueuePacket(&in);
@ -4268,8 +4270,7 @@ namespace RoF2
OUT_str(buyer_name);
OUT_str(seller_name);
OUT_str(item_name);
OUT_str(serial_number);
//strn0cpy(eq->serial_number, emu->serial_number.c_str(), sizeof(eq->serial_number));
OUT_str(item_unique_id);
FINISH_ENCODE();
}
@ -4279,15 +4280,13 @@ namespace RoF2
ENCODE_LENGTH_EXACT(TraderDelItem_Struct);
SETUP_DIRECT_ENCODE(TraderDelItem_Struct, structs::TraderDelItem_Struct);
LogTrading(
"(RoF2) trader_id <green>[{}] item_id <green>[{}]",
"(RoF2) trader_id <green>[{}] item_unique_id <green>[{}]",
emu->trader_id,
emu->item_id
emu->item_unique_id
);
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);
eq->trader_id = emu->trader_id;
strn0cpy(eq->item_unique_id, emu->item_unique_id, sizeof(eq->item_unique_id));
FINISH_ENCODE();
}
@ -4334,8 +4333,7 @@ namespace RoF2
OUT_str(buyer_name);
OUT_str(seller_name);
OUT_str(item_name);
OUT_str(serial_number);
//strn0cpy(eq->serial_number, emu->serial_number.c_str(), sizeof(eq->serial_number));
OUT_str(item_unique_id);
FINISH_ENCODE();
break;
@ -6174,6 +6172,10 @@ namespace RoF2
ClickTraderNew_Struct out{};
out.action = TraderOn;
for (auto i = 0; i < RoF2::invtype::BAZAAR_SIZE; i++) {
if (eq->item_cost[i] == 0) {
continue;
}
BazaarTraderDetails btd{};
btd.unique_id = eq->item_unique_ids[i].item_unique_id;
btd.cost = eq->item_cost[i];
@ -6214,13 +6216,9 @@ namespace RoF2
SETUP_DIRECT_DECODE(TraderPriceUpdate_Struct, structs::TraderPriceUpdate_Struct);
LogTrading("(RoF2) PriceUpdate action <green>[{}]", action);
emu->Action = PriceUpdate;
strn0cpy(emu->serial_number, eq->serial_number, sizeof(emu->serial_number));
//FIXemu->serial_number = 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->action = PriceUpdate;
strn0cpy(emu->item_unique_id, eq->item_unique_id, sizeof(emu->item_unique_id));
emu->new_price = eq->new_price;
FINISH_DIRECT_DECODE();
break;
@ -6310,23 +6308,13 @@ namespace RoF2
IN(item_id);
IN(trader_id);
emu->action = BazaarInspect;
strn0cpy(emu->serial_number, eq->serial_number, sizeof(emu->serial_number));
//FIX 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;
// }
strn0cpy(emu->item_unique_id, eq->item_unique_id, sizeof(emu->item_unique_id));
// LogTrading("(RoF2) BazaarInspect action <green>[{}] item_id <green>[{}] serial_number <green>[{}]",
// action,
// eq->item_id,
// eq->serial_number
// );
LogTrading("(RoF2) BazaarInspect action <green>[{}] item_id <green>[{}] serial_number <green>[{}]",
action,
eq->item_id,
eq->item_unique_id
);
FINISH_DIRECT_DECODE();
break;
}
@ -6363,8 +6351,7 @@ namespace RoF2
IN_str(seller_name);
IN_str(item_name);
//IN_str(serial_number);
strn0cpy(emu->serial_number, eq->serial_number, sizeof(emu->serial_number));
//FIX emu->serial_number = eq->serial_number;
strn0cpy(emu->item_unique_id, eq->item_unique_id, sizeof(emu->item_unique_id));
FINISH_DIRECT_DECODE();
break;

View File

@ -3311,7 +3311,7 @@ struct BazaarInspect_Struct {
uint32 action;
uint32 unknown_004;
uint32 trader_id;
char serial_number[17];
char item_unique_id[17];
char unknown_029[3];
uint32 item_id;
uint32 unknown_036;
@ -3594,11 +3594,11 @@ struct BazaarWindowRemoveTrader_Struct {
};
struct TraderPriceUpdate_Struct {
uint32 action;
char serial_number[17];
char unknown_021[3];
uint32 unknown_024;
uint32 new_price;
/*000*/ uint32 action;
/*004*/ char item_unique_id[17];
/*021*/ char unknown_021[3];
/*024*/ uint32 unknown_024;
/*028*/ uint32 new_price;
};
struct Trader_ShowItems_Struct {
@ -3625,7 +3625,7 @@ struct TraderBuy_Struct {
/*084*/ char seller_name[64];
/*148*/ char unknown_148[32];
/*180*/ char item_name[64];
/*244*/ char serial_number[17];
/*244*/ char item_unique_id[17];
/*261*/ char unknown_261[3];
/*264*/ uint32 item_id;
/*268*/ uint32 price;
@ -3651,10 +3651,10 @@ struct MoneyUpdate_Struct{
};
struct TraderDelItem_Struct{
/*000*/ uint32 Unknown000;
/*004*/ uint32 TraderID;
/*008*/ char SerialNumber[17];
/*024*/ uint32 Unknown012;
/*000*/ uint32 unknown_000;
/*004*/ uint32 trader_id;
/*008*/ char item_unique_id[17];
/*025*/ uint32 unknown_025;
/*028*/
};

View File

@ -20,15 +20,15 @@ class BaseTraderRepository {
public:
struct Trader {
uint64_t id;
uint32_t char_id;
uint32_t character_id;
uint32_t item_id;
uint32_t aug_slot_1;
uint32_t aug_slot_2;
uint32_t aug_slot_3;
uint32_t aug_slot_4;
uint32_t aug_slot_5;
uint32_t aug_slot_6;
std::string item_sn;
std::string item_unique_id;
uint32_t augment_one;
uint32_t augment_two;
uint32_t augment_three;
uint32_t augment_four;
uint32_t augment_five;
uint32_t augment_six;
int32_t item_charges;
uint32_t item_cost;
uint8_t slot_id;
@ -48,15 +48,15 @@ public:
{
return {
"id",
"char_id",
"character_id",
"item_id",
"aug_slot_1",
"aug_slot_2",
"aug_slot_3",
"aug_slot_4",
"aug_slot_5",
"aug_slot_6",
"item_sn",
"item_unique_id",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"item_charges",
"item_cost",
"slot_id",
@ -72,15 +72,15 @@ public:
{
return {
"id",
"char_id",
"character_id",
"item_id",
"aug_slot_1",
"aug_slot_2",
"aug_slot_3",
"aug_slot_4",
"aug_slot_5",
"aug_slot_6",
"item_sn",
"item_unique_id",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"item_charges",
"item_cost",
"slot_id",
@ -130,15 +130,15 @@ public:
Trader e{};
e.id = 0;
e.char_id = 0;
e.character_id = 0;
e.item_id = 0;
e.aug_slot_1 = 0;
e.aug_slot_2 = 0;
e.aug_slot_3 = 0;
e.aug_slot_4 = 0;
e.aug_slot_5 = 0;
e.aug_slot_6 = 0;
e.item_sn = "";
e.item_unique_id = "";
e.augment_one = 0;
e.augment_two = 0;
e.augment_three = 0;
e.augment_four = 0;
e.augment_five = 0;
e.augment_six = 0;
e.item_charges = 0;
e.item_cost = 0;
e.slot_id = 0;
@ -184,15 +184,15 @@ public:
Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.character_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? row[9] : "";
e.item_unique_id = row[3] ? row[3] : "";
e.augment_one = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augment_two = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_three = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_four = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_five = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_six = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
@ -234,15 +234,15 @@ public:
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.char_id));
v.push_back(columns[1] + " = " + std::to_string(e.character_id));
v.push_back(columns[2] + " = " + std::to_string(e.item_id));
v.push_back(columns[3] + " = " + std::to_string(e.aug_slot_1));
v.push_back(columns[4] + " = " + std::to_string(e.aug_slot_2));
v.push_back(columns[5] + " = " + std::to_string(e.aug_slot_3));
v.push_back(columns[6] + " = " + std::to_string(e.aug_slot_4));
v.push_back(columns[7] + " = " + std::to_string(e.aug_slot_5));
v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_6));
v.push_back(columns[9] + " = '" + Strings::Escape(e.item_sn) + "'");
v.push_back(columns[3] + " = '" + Strings::Escape(e.item_unique_id) + "'");
v.push_back(columns[4] + " = " + std::to_string(e.augment_one));
v.push_back(columns[5] + " = " + std::to_string(e.augment_two));
v.push_back(columns[6] + " = " + std::to_string(e.augment_three));
v.push_back(columns[7] + " = " + std::to_string(e.augment_four));
v.push_back(columns[8] + " = " + std::to_string(e.augment_five));
v.push_back(columns[9] + " = " + std::to_string(e.augment_six));
v.push_back(columns[10] + " = " + std::to_string(e.item_charges));
v.push_back(columns[11] + " = " + std::to_string(e.item_cost));
v.push_back(columns[12] + " = " + std::to_string(e.slot_id));
@ -273,15 +273,15 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back("'" + Strings::Escape(e.item_sn) + "'");
v.push_back("'" + Strings::Escape(e.item_unique_id) + "'");
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.item_cost));
v.push_back(std::to_string(e.slot_id));
@ -320,15 +320,15 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back("'" + Strings::Escape(e.item_sn) + "'");
v.push_back("'" + Strings::Escape(e.item_unique_id) + "'");
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.item_cost));
v.push_back(std::to_string(e.slot_id));
@ -371,15 +371,15 @@ public:
Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.character_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? row[9] : "";
e.item_unique_id = row[3] ? row[3] : "";
e.augment_one = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augment_two = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_three = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_four = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_five = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_six = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
@ -413,15 +413,15 @@ public:
Trader e{};
e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.character_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.item_sn = row[9] ? row[9] : "";
e.item_unique_id = row[3] ? row[3] : "";
e.augment_one = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.augment_two = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_three = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_four = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_five = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_six = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
@ -505,15 +505,15 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back("'" + Strings::Escape(e.item_sn) + "'");
v.push_back("'" + Strings::Escape(e.item_unique_id) + "'");
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.item_cost));
v.push_back(std::to_string(e.slot_id));
@ -545,15 +545,15 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.aug_slot_1));
v.push_back(std::to_string(e.aug_slot_2));
v.push_back(std::to_string(e.aug_slot_3));
v.push_back(std::to_string(e.aug_slot_4));
v.push_back(std::to_string(e.aug_slot_5));
v.push_back(std::to_string(e.aug_slot_6));
v.push_back("'" + Strings::Escape(e.item_sn) + "'");
v.push_back("'" + Strings::Escape(e.item_unique_id) + "'");
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.item_cost));
v.push_back(std::to_string(e.slot_id));

View File

@ -58,9 +58,9 @@ public:
if (RuleB(Bazaar, UseAlternateBazaarSearch)) {
results = db.QueryDatabase(fmt::format(
"SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name "
"SELECT DISTINCT(t.character_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name "
"FROM trader AS t "
"JOIN character_data AS c ON t.char_id = c.id "
"JOIN character_data AS c ON t.character_id = c.id "
"WHERE t.char_zone_instance_id = {} "
"ORDER BY t.char_zone_instance_id ASC "
"LIMIT {}",
@ -69,13 +69,14 @@ public:
);
}
else {
results = db.QueryDatabase(fmt::format(
"SELECT DISTINCT(t.char_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name "
"FROM trader AS t "
"JOIN character_data AS c ON t.char_id = c.id "
"ORDER BY t.char_zone_instance_id ASC "
"LIMIT {}",
max_results)
results = db.QueryDatabase(
fmt::format(
"SELECT DISTINCT(t.character_id), t.char_zone_id, t.char_zone_instance_id, t.char_entity_id, c.name "
"FROM trader AS t "
"JOIN character_data AS c ON t.character_id = c.id "
"ORDER BY t.char_zone_instance_id ASC "
"LIMIT {}",
max_results)
);
}
@ -101,7 +102,7 @@ public:
{
WelcomeData_Struct e{};
auto results = db.QueryDatabase("SELECT COUNT(DISTINCT char_id), count(char_id) FROM trader;");
auto results = db.QueryDatabase("SELECT COUNT(DISTINCT character_id), count(character_id) FROM trader;");
if (!results.RowCount()) {
return e;
@ -113,15 +114,15 @@ public:
return e;
}
static int UpdateItem(Database &db, uint32 char_id, uint32 new_price, uint32 item_id, uint32 item_charges)
static int UpdateItem(Database &db, uint32 character_id, uint32 new_price, uint32 item_id, uint32 item_charges)
{
std::vector<BaseTraderRepository::Trader> items{};
if (item_charges == 0) {
items = GetWhere(
db,
fmt::format(
"char_id = '{}' AND item_id = '{}'",
char_id,
"character_id = '{}' AND item_id = '{}'",
character_id,
item_id
)
);
@ -130,8 +131,8 @@ public:
items = GetWhere(
db,
fmt::format(
"char_id = '{}' AND item_id = '{}' AND item_charges = '{}'",
char_id,
"character_id = '{}' AND item_id = '{}' AND item_charges = '{}'",
character_id,
item_id,
item_charges
)
@ -155,8 +156,8 @@ public:
Trader item{};
auto query = fmt::format(
"SELECT t.char_id, t.item_id, t.serialnumber, t.charges, t.item_cost, t.slot_id, t.entity_id FROM trader AS t "
"WHERE t.entity_id = {} AND t.item_id = {} AND t.item_cost = {} "
"SELECT t.character_id, t.item_id, t.item_unique.id, t.charges, t.item_cost, t.slot_id, t.entity_id FROM trader AS t "
"WHERE t.entity_id = '{}' AND t.item_id = '{}' AND t.item_cost = '{}' "
"LIMIT 1;",
trader_id,
item_id,
@ -168,41 +169,59 @@ public:
return item;
}
auto row = results.begin();
item.char_id = Strings::ToInt(row[0]);
item.item_id = Strings::ToInt(row[1]);
item.item_sn = Strings::ToInt(row[2]);
item.item_charges = Strings::ToInt(row[3]);
item.item_cost = Strings::ToInt(row[4]);
item.slot_id = Strings::ToInt(row[5]);
auto row = results.begin();
item.character_id = Strings::ToInt(row[0]);
item.item_id = Strings::ToInt(row[1]);
item.item_unique_id = row[2] ? row[2] : "";
item.item_charges = Strings::ToInt(row[3]);
item.item_cost = Strings::ToInt(row[4]);
item.slot_id = Strings::ToInt(row[5]);
return item;
}
static int UpdateQuantity(Database &db, uint32 char_id, const std::string &serial_number, int16 quantity)
static int UpdateQuantity(Database &db, const std::string &item_unique_id, int16 quantity)
{
const auto trader_item = GetWhere(
db,
fmt::format("char_id = '{}' AND item_sn = '{}' ", char_id, serial_number)
fmt::format("`item_unique_id` = '{}' ", item_unique_id)
);
if (trader_item.empty() || trader_item.size() > 1) {
return 0;
}
auto m = trader_item[0];
auto m = trader_item[0];
m.item_charges = quantity;
m.listing_date = time(nullptr);
return UpdateOne(db, m);
}
static Trader GetItemBySerialNumber(Database &db, std::string &serial_number, uint32 trader_id)
static int UpdatePrice(Database &db, const std::string &item_unique_id, uint32 price)
{
const auto trader_item = GetWhere(
db,
fmt::format("`item_unique_id` = '{}' ", item_unique_id)
);
if (trader_item.empty() || trader_item.size() > 1) {
return 0;
}
auto m = trader_item[0];
m.item_cost = price;
m.listing_date = time(nullptr);
return ReplaceOne(db, m);
}
static Trader GetItemBySerialNumber(Database &db, std::string &item_unique_id, uint32 trader_id)
{
Trader e{};
const auto trader_item = GetWhere(
db,
fmt::format("`char_id` = '{}' AND `item_sn` = '{}' LIMIT 1", trader_id, serial_number)
fmt::format("`character_id` = '{}' AND `item_unique_id` = '{}' LIMIT 1", trader_id, item_unique_id)
);
if (trader_item.empty()) {
@ -240,21 +259,16 @@ public:
return DeleteWhere(db, fmt::format("`id` IN({})", Strings::Implode(",", delete_ids)));
}
static DistinctTraders_Struct GetTraderByInstanceAndSerialnumber(
Database &db,
uint32 instance_id,
std::string &serial_number
)
static DistinctTraders_Struct GetTraderByItemUniqueNumber(Database &db, std::string &item_unique_id)
{
DistinctTraders_Struct trader{};
auto query = fmt::format(
"SELECT t.id, t.char_id, c.name "
"SELECT t.id, t.character_id, c.name "
"FROM trader AS t "
"JOIN character_data AS c ON c.id = t.char_id "
"WHERE t.char_zone_id = 151 AND t.char_zone_instance_id = {} AND t.item_sn = {} LIMIT 1",
instance_id,
serial_number
"JOIN character_data AS c ON c.id = t.character_id "
"WHERE t.item_unique_id = '{}' LIMIT 1",
item_unique_id
);
auto results = db.QueryDatabase(query);
@ -264,7 +278,6 @@ public:
}
auto row = results.begin();
std::string name = row[2];
trader.trader_id = Strings::ToUnsignedInt(row[1]);
trader.trader_name = row[2] ? row[2] : "";
@ -279,8 +292,12 @@ public:
std::vector<BazaarTraderSearch_Struct> all_entries{};
auto query = fmt::format(
"SELECT trader.*, c.`name` FROM `trader` INNER JOIN character_data AS c ON trader.char_id = c.id "
"WHERE {} ORDER BY trader.char_id ASC",
"SELECT trader.id, trader.character_id, trader.item_id, trader.item_unique_id, trader.augment_one, "
"trader.augment_two, trader.augment_three, trader.augment_four, trader.augment_five, trader.augment_six, "
"trader.item_charges, trader.item_cost, trader.slot_id, trader.char_entity_id, trader.char_zone_id, "
"trader.char_zone_instance_id, trader.active_transaction, c.`name` FROM `trader` "
"INNER JOIN character_data AS c ON trader.character_id = c.id "
"WHERE {} ORDER BY trader.character_id ASC",
search_criteria_trader
);
@ -295,15 +312,15 @@ public:
BazaarTraderSearch_Struct e{};
e.trader.id = row[0] ? strtoull(row[0], nullptr, 10) : 0;
e.trader.char_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.trader.character_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.trader.item_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.trader.aug_slot_1 = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.trader.aug_slot_2 = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.trader.aug_slot_3 = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.trader.aug_slot_4 = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.trader.aug_slot_5 = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.trader.aug_slot_6 = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.trader.item_sn = row[9] ? row[9] : std::string("");
e.trader.item_unique_id = row[3] ? row[3] : std::string("");
e.trader.augment_one = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
e.trader.augment_two = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.trader.augment_three = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.trader.augment_four = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.trader.augment_five = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.trader.augment_six = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.trader.item_charges = row[10] ? static_cast<int32_t>(atoi(row[10])) : 0;
e.trader.item_cost = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.trader.slot_id = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;

View File

@ -12702,7 +12702,7 @@ uint16 Client::GetSkill(EQ::skills::SkillType skill_id) const
return 0;
}
void Client::RemoveItemBySerialNumber(const std::string &item_unique_id, uint32 quantity)
bool Client::RemoveItemByItemUniqueId(const std::string &item_unique_id, uint32 quantity)
{
EQ::ItemInstance *item = nullptr;
uint32 removed_count = 0;
@ -12717,18 +12717,24 @@ void Client::RemoveItemBySerialNumber(const std::string &item_unique_id, uint32
if (item && item->GetUniqueID().compare(item_unique_id) == 0) {
uint32 charges = item->IsStackable() ? item->GetCharges() : 0;
uint32 stack_size = std::max(charges, static_cast<uint32>(1));
if ((removed_count + stack_size) <= quantity) {
if (removed_count + stack_size <= quantity) {
removed_count += stack_size;
DeleteItemInInventory(slot_id, charges, true);
if (DeleteItemInInventory(slot_id, charges, true)) {
return true;
}
} else {
uint32 amount_left = (quantity - removed_count);
uint32 amount_left = quantity - removed_count;
if (amount_left > 0 && stack_size >= amount_left) {
removed_count += amount_left;
DeleteItemInInventory(slot_id, amount_left, true);
if (DeleteItemInInventory(slot_id, amount_left, true)) {
return true;
}
}
}
}
}
return false;
}
void Client::SendTopLevelInventory()

View File

@ -314,7 +314,8 @@ public:
void Trader_CustomerBrowsing(Client *Customer);
void TraderEndTrader();
void TraderPriceUpdate(const EQApplicationPacket *app);
//void TraderPriceUpdate(const EQApplicationPacket *app);
void TraderUpdateItem(const EQApplicationPacket *app);
void SendBazaarDone(uint32 trader_id);
void SendBulkBazaarTraders();
void SendBulkBazaarBuyers();
@ -375,11 +376,12 @@ public:
uint32 FindTraderItemSerialNumber(int32 ItemID);
EQ::ItemInstance* FindTraderItemBySerialNumber(std::string &serial_number);
EQ::ItemInstance* FindTraderItemByUniqueID(std::string &unique_id);
void FindAndNukeTraderItem(std::string &serial_number, int16 quantity, Client* customer, uint16 trader_slot);
EQ::ItemInstance* FindTraderItemByUniqueID(const char* unique_id);
void FindAndNukeTraderItem(std::string &item_unique_id, int16 quantity, Client* customer, uint16 trader_slot);
void NukeTraderItem(uint16 slot, int16 charges, int16 quantity, Client* customer, uint16 trader_slot, const std::string &serial_number, int32 item_id = 0);
void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0);
void TradeRequestFailed(const EQApplicationPacket* app);
void BuyTraderItem(TraderBuy_Struct* tbs, Client* trader, const EQApplicationPacket* app);
void BuyTraderItem(const EQApplicationPacket* app);
void BuyTraderItemOutsideBazaar(TraderBuy_Struct* tbs, const EQApplicationPacket* app);
void FinishTrade(
Mob *with,
@ -416,9 +418,15 @@ public:
void SendBecomeTraderToWorld(Client *trader, BazaarTraderBarterActions action);
void SendBecomeTrader(BazaarTraderBarterActions action, uint32 trader_id);
bool IsThereACustomer() const { return customer_id ? true : false; }
bool IsThereACustomer() const { return customer_id ? true : false; }
uint32 GetCustomerID() { return customer_id; }
void SetCustomerID(uint32 id) { customer_id = id; }
void SetCustomerID(uint32 id) { customer_id = id; }
void ClearTraderMerchantList() { m_trader_merchant_list.clear(); }
void AddDataToMerchantList(int16 slot_id, int32 quantity, const std::string &item_unique_id);
std::tuple<int16, std::string> GetDataFromMerchantListByMerchantSlotId(int16 slot_id);
int16 GetSlotFromMerchantListByItemUniqueId(const std::string &unique_id);
std::pair<int16, std::tuple<uint32, std::string>> GetDataFromMerchantListByItemUniqueId(const std::string &unique_id);
std::map<int16, std::tuple<uint32, std::string>>* GetTraderMerchantList() { return &m_trader_merchant_list; }
void SetBuyerID(uint32 id) { m_buyer_id = id; }
uint32 GetBuyerID() { return m_buyer_id; }
@ -587,7 +595,7 @@ public:
void DisableAreaRegens();
void ServerFilter(SetServerFilter_Struct* filter);
void BulkSendTraderInventory(uint32 char_id);
void BulkSendTraderInventory(uint32 character_id);
void SendSingleTraderItem(uint32 char_id, const std::string &serial_number);
void BulkSendMerchantInventory(int merchant_id, int npcid);
@ -1145,13 +1153,13 @@ public:
bool FindNumberOfFreeInventorySlotsWithSizeCheck(std::vector<BuyerLineTradeItems_Struct> items);
bool PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update = false);
void SendCursorBuffer();
void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true);
bool DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true);
uint32 CountItem(uint32 item_id);
void ResetItemCooldown(uint32 item_id);
void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1);
uint32 GetItemCooldown(uint32 item_id);
void RemoveItem(uint32 item_id, uint32 quantity = 1);
void RemoveItemBySerialNumber(const std::string &item_unique_id, uint32 quantity = 1);
bool RemoveItemByItemUniqueId(const std::string &item_unique_id, uint32 quantity = 1);
bool SwapItem(MoveItem_Struct* move_in);
void SwapItemResync(MoveItem_Struct* move_slots);
void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, LootItem** bag_item_data = 0);
@ -2104,6 +2112,7 @@ private:
uint8 mercSlot; // selected merc slot
time_t m_trader_transaction_date;
uint32 m_trader_count{};
std::map<int16, std::tuple<uint32, std::string>> m_trader_merchant_list{};
uint32 m_buyer_id;
uint32 m_barter_time;
int32 m_parcel_platinum;

View File

@ -386,7 +386,7 @@ bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst)
PlayerEvent::EvolveItem e{};
RemoveItemBySerialNumber(inst.GetUniqueID());
RemoveItemByItemUniqueId(inst.GetUniqueID());
EvolvingItemsManager::Instance()->LoadPlayerEvent(inst, e);
e.status = "Evolved Item due to obtaining progression - Old Evolve Item removed from inventory.";
RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e);
@ -506,7 +506,7 @@ void Client::DoEvolveTransferXP(const EQApplicationPacket *app)
PlayerEvent::EvolveItem e{};
RemoveItemBySerialNumber(inst_from->GetUniqueID());
RemoveItemByItemUniqueId(inst_from->GetUniqueID());
EvolvingItemsManager::Instance()->LoadPlayerEvent(*inst_from, e);
e.status = "Transfer XP - Original FROM Evolve Item removed from inventory.";
RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e);
@ -516,7 +516,7 @@ void Client::DoEvolveTransferXP(const EQApplicationPacket *app)
e.status = "Transfer XP - Updated FROM item placed in inventory.";
RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e);
RemoveItemBySerialNumber(inst_to->GetUniqueID());
RemoveItemByItemUniqueId(inst_to->GetUniqueID());
EvolvingItemsManager::Instance()->LoadPlayerEvent(*inst_to, e);
e.status = "Transfer XP - Original TO Evolve Item removed from inventory.";
RecordPlayerEventLog(PlayerEvent::EVOLVE_ITEM, e);

View File

@ -15434,10 +15434,10 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
TraderStartTrader(app);
break;
}
case PriceUpdate:
case ItemMove: {
LogTrading("Trader Price Update");
TraderPriceUpdate(app);
case ItemMove:
case PriceUpdate:{
LogTrading("Trader item updated - removed, added or price change");
TraderUpdateItem(app);
break;
}
case EndTransaction: {
@ -15456,7 +15456,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
break;
}
default: {
LogError("Unknown size for OP_Trader: [{}]\n", app->size);
LogTrading("Unknown size for OP_Trader: [{}]\n", app->size);
}
}
}
@ -15467,29 +15467,12 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
//
// Client has elected to buy an item from a Trader
//
auto in = (TraderBuy_Struct *) app->pBuffer;
if (RuleB(Bazaar, UseAlternateBazaarSearch) && in->trader_id >= TraderRepository::TRADER_CONVERT_ID) {
auto sn = std::string(in->serial_number);
auto trader = TraderRepository::GetTraderByInstanceAndSerialnumber(
database,
in->trader_id - TraderRepository::TRADER_CONVERT_ID,
sn
);
if (!trader.trader_id) {
LogTrading("Unable to convert trader id for {} and serial number {}. Trader Buy aborted.",
in->trader_id - TraderRepository::TRADER_CONVERT_ID,
in->serial_number
);
return;
}
in->trader_id = trader.trader_id;
strn0cpy(in->seller_name, trader.trader_name.c_str(), sizeof(in->seller_name));
}
auto trader = entity_list.GetClientByID(in->trader_id);
auto in = (TraderBuy_Struct *) app->pBuffer;
auto item_unique_id = std::string(in->item_unique_id);
auto trader_details = TraderRepository::GetTraderByItemUniqueNumber(database, item_unique_id);
auto trader = entity_list.GetClientByID(in->trader_id);
strn0cpy(in->seller_name, trader_details.trader_name.c_str(), sizeof(in->seller_name));
switch (in->method) {
case BazaarByVendor: {
@ -15499,9 +15482,9 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
in->trader_id,
in->item_id,
in->quantity,
in->serial_number
in->item_unique_id
);
BuyTraderItem(in, trader, app);
BuyTraderItem(app);
}
break;
}
@ -15525,7 +15508,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
in->trader_id,
in->item_id,
in->quantity,
in->serial_number
in->item_unique_id
);
BuyTraderItemOutsideBazaar(in, app);
break;
@ -15550,7 +15533,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
in->trader_id,
in->item_id,
in->quantity,
in->serial_number
in->item_unique_id
);
Message(
Chat::Yellow,
@ -15561,6 +15544,9 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
TradeRequestFailed(app);
break;
}
default: {
}
}
}
@ -15651,17 +15637,18 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app)
switch (in->Code) {
case ClickTrader: {
LogTrading("Handle_OP_TraderShop case ClickTrader [{}]", in->Code);
auto outapp =
std::make_unique<EQApplicationPacket>(OP_TraderShop, static_cast<uint32>(sizeof(TraderClick_Struct))
auto outapp = std::make_unique<EQApplicationPacket>(
OP_TraderShop,
static_cast<uint32>(sizeof(TraderClick_Struct))
);
auto data = (TraderClick_Struct *) outapp->pBuffer;
auto trader_client = entity_list.GetClientByID(in->TraderID);
auto trader = entity_list.GetClientByID(in->TraderID);
if (trader_client) {
data->Approval = trader_client->WithCustomer(GetID());
if (trader) {
data->Approval = trader->WithCustomer(GetID());
LogTrading("Client::Handle_OP_TraderShop: Shop Request ([{}]) to ([{}]) with Approval: [{}]",
GetCleanName(),
trader_client->GetCleanName(),
trader->GetCleanName(),
data->Approval
);
}
@ -15669,6 +15656,9 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app)
LogTrading("Client::Handle_OP_TraderShop: entity_list.GetClientByID(tcs->traderid)"
" returned a nullptr pointer"
);
auto outapp = new EQApplicationPacket(OP_ShopEndConfirm);
QueuePacket(outapp);
safe_delete(outapp);
return;
}
@ -15678,8 +15668,9 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app)
QueuePacket(outapp.get());
if (data->Approval) {
BulkSendTraderInventory(trader_client->CharacterID());
trader_client->Trader_CustomerBrowsing(this);
ClearTraderMerchantList();
BulkSendTraderInventory(trader->CharacterID());
trader->Trader_CustomerBrowsing(this);
SetTraderID(in->TraderID);
LogTrading("Client::Handle_OP_TraderShop: Trader Inventory Sent to [{}] from [{}]",
GetID(),

View File

@ -958,7 +958,7 @@ void Client::SendCursorBuffer()
}
// Remove item from inventory
void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_update, bool update_db) {
bool Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_update, bool update_db) {
#if (EQDEBUG >= 5)
LogDebug("DeleteItemInInventory([{}], [{}], [{}])", slot_id, quantity, (client_update) ? "true":"false");
#endif
@ -977,7 +977,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_up
QueuePacket(outapp);
safe_delete(outapp);
}
return;
return false;
}
uint64 evolve_id = m_inv[slot_id]->GetEvolveUniqueID();
@ -1031,6 +1031,8 @@ void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_up
safe_delete(outapp);
}
}
return true;
}
bool Client::PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update)

View File

@ -458,7 +458,7 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in)
CharacterParcelsContainersRepository::InsertMany(database, all_entries);
}
RemoveItemBySerialNumber(inst->GetUniqueID(), parcel_out.quantity == 0 ? 1 : parcel_out.quantity);
RemoveItemByItemUniqueId(inst->GetUniqueID(), parcel_out.quantity == 0 ? 1 : parcel_out.quantity);
std::unique_ptr<EQApplicationPacket> outapp(new EQApplicationPacket(OP_ShopSendParcel));
QueuePacket(outapp.get());

View File

@ -309,6 +309,7 @@
#define PLAYER_CHARMED 1461 //You lose control of yourself!
#define TRADER_BUSY 1468 //That Trader is currently with a customer. Please wait until their transaction is finished.
#define SENSE_CORPSE_DIRECTION 1563 //You sense a corpse in this direction.
#define HOW_CAN_YOU_BUY_MORE 1571 //%1 tells you, 'Your inventory appears full! How can you buy more?'
#define DUPE_LORE_MERCHANT 1573 //%1 tells you, 'You already have the lore item, %2, on your person, on your shroud, in the bank, in a real estate, or as an augment in another item. You cannot have more than one of a particular lore item at a time.'
#define QUEUED_TELL 2458 //[queued]
#define QUEUE_TELL_FULL 2459 //[zoing and queue is full]
@ -466,6 +467,8 @@
#define LDON_NO_LOCKPICK 7564 //You must have a lock pick in your inventory to do this.
#define LDON_WAS_NOT_LOCKED 7565 //%1 was not locked.
#define LDON_WAS_NOT_TRAPPED 7566 //%1 was not trapped
#define DUPLICATE_LORE 7623 //Transaction failed: Duplicate Lore Item!
#define INSUFFICIENT_FUNDS 7632 //Transaction failed: Insufficient funds!
#define GAIN_SINGLE_AA_SINGLE_AA 8019 //You have gained an ability point! You now have %1 ability point.
#define GAIN_SINGLE_AA_MULTI_AA 8020 //You have gained an ability point! You now have %1 ability points.
#define GAIN_MULTI_AA_MULTI_AA 8021 //You have gained %1 ability point(s)! You now have %2 ability point(s).

File diff suppressed because it is too large Load Diff

View File

@ -3791,8 +3791,8 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
}
auto sn = std::string(in->trader_buy_struct.item_unique_id);
auto outapp = std::make_unique<EQApplicationPacket>(OP_Trader, static_cast<uint32>(sizeof(TraderBuy_Struct)));
auto sn = std::string(in->trader_buy_struct.serial_number);
auto data = (TraderBuy_Struct *) outapp->pBuffer;
memcpy(data, &in->trader_buy_struct, sizeof(TraderBuy_Struct));
@ -3826,7 +3826,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e);
}
trader_pc->RemoveItemBySerialNumber(sn, in->trader_buy_struct.quantity);
trader_pc->RemoveItemByItemUniqueId(sn, in->trader_buy_struct.quantity);
trader_pc->AddMoneyToPP(in->trader_buy_struct.price * in->trader_buy_struct.quantity, true);
trader_pc->QueuePacket(outapp.get());

View File

@ -343,12 +343,12 @@ std::unique_ptr<EQ::ItemInstance> ZoneDatabase::LoadSingleTraderItem(uint32 char
database.CreateItem(
item_id,
charges,
results.at(0).aug_slot_1,
results.at(0).aug_slot_2,
results.at(0).aug_slot_3,
results.at(0).aug_slot_4,
results.at(0).aug_slot_5,
results.at(0).aug_slot_6
results.at(0).augment_one,
results.at(0).augment_two,
results.at(0).augment_three,
results.at(0).augment_four,
results.at(0).augment_five,
results.at(0).augment_six
)
);
if (!inst) {