mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-19 13:28:25 +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:
+2
-2
@@ -4157,7 +4157,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) {
|
||||
continue;
|
||||
|
||||
// TEST CODE: test for bazaar trader crashing with charm items
|
||||
if (Trader)
|
||||
if (IsTrader())
|
||||
if (i >= EQ::invbag::GENERAL_BAGS_BEGIN && i <= EQ::invbag::GENERAL_BAGS_END) {
|
||||
EQ::ItemInstance* parent_item = m_inv.GetItem(EQ::InventoryProfile::CalcSlotId(i));
|
||||
if (parent_item && parent_item->GetItem()->BagType == EQ::item::BagTypeTradersSatchel)
|
||||
@@ -4249,7 +4249,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) {
|
||||
continue;
|
||||
|
||||
// TEST CODE: test for bazaar trader crashing with charm items
|
||||
if (Trader)
|
||||
if (IsTrader())
|
||||
if (i >= EQ::invbag::GENERAL_BAGS_BEGIN && i <= EQ::invbag::GENERAL_BAGS_END) {
|
||||
EQ::ItemInstance* parent_item = m_inv.GetItem(EQ::InventoryProfile::CalcSlotId(i));
|
||||
if (parent_item && parent_item->GetItem()->BagType == EQ::item::BagTypeTradersSatchel)
|
||||
|
||||
+8
-6
@@ -202,11 +202,11 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
|
||||
ip = eqs->GetRemoteIP();
|
||||
port = ntohs(eqs->GetRemotePort());
|
||||
client_state = CLIENT_CONNECTING;
|
||||
Trader=false;
|
||||
SetTrader(false);
|
||||
Buyer = false;
|
||||
Haste = 0;
|
||||
CustomerID = 0;
|
||||
TraderID = 0;
|
||||
SetCustomerID(0);
|
||||
SetTraderID(0);
|
||||
TrackingID = 0;
|
||||
WID = 0;
|
||||
account_id = 0;
|
||||
@@ -421,8 +421,9 @@ Client::~Client() {
|
||||
if (merc)
|
||||
merc->Depop();
|
||||
|
||||
if(Trader)
|
||||
database.DeleteTraderItem(CharacterID());
|
||||
if(IsTrader()) {
|
||||
TraderEndTrader();
|
||||
}
|
||||
|
||||
if(Buyer)
|
||||
ToggleBuyerMode(false);
|
||||
@@ -2163,6 +2164,7 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
|
||||
ns->spawn.anon = m_pp.anon;
|
||||
ns->spawn.gm = GetGM() ? 1 : 0;
|
||||
ns->spawn.guildID = GuildID();
|
||||
ns->spawn.trader = IsTrader();
|
||||
// ns->spawn.linkdead = IsLD() ? 1 : 0;
|
||||
// ns->spawn.pvp = GetPVP(false) ? 1 : 0;
|
||||
ns->spawn.show_name = true;
|
||||
@@ -11969,7 +11971,7 @@ void Client::SendPath(Mob* target)
|
||||
RuleB(Bazaar, EnableWarpToTrader) &&
|
||||
target->IsClient() &&
|
||||
(
|
||||
target->CastToClient()->Trader ||
|
||||
target->CastToClient()->IsTrader() ||
|
||||
target->CastToClient()->Buyer
|
||||
)
|
||||
) {
|
||||
|
||||
+37
-15
@@ -69,6 +69,7 @@ namespace EQ
|
||||
#include "../common/events/player_events.h"
|
||||
#include "../common/data_verification.h"
|
||||
#include "../common/repositories/character_parcels_repository.h"
|
||||
#include "../common/repositories/trader_repository.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
// since windows defines these within windef.h (which windows.h include)
|
||||
@@ -280,10 +281,20 @@ public:
|
||||
void AI_Stop();
|
||||
void AI_Process();
|
||||
void AI_SpellCast();
|
||||
void Trader_ShowItems();
|
||||
void TraderShowItems();
|
||||
void Trader_CustomerBrowsing(Client *Customer);
|
||||
void Trader_EndTrader();
|
||||
void Trader_StartTrader();
|
||||
|
||||
void TraderEndTrader();
|
||||
void TraderPriceUpdate(const EQApplicationPacket *app);
|
||||
void SendBazaarDone(uint32 trader_id);
|
||||
void SendBulkBazaarTraders();
|
||||
void DoBazaarInspect(const BazaarInspect_Struct &in);
|
||||
void SendBazaarDeliveryCosts();
|
||||
static std::string DetermineMoneyString(uint64 copper);
|
||||
|
||||
void SendTraderMode(BazaarTraderBarterActions status);
|
||||
void TraderStartTrader(const EQApplicationPacket *app);
|
||||
// void TraderPriceUpdate(const EQApplicationPacket *app);
|
||||
uint8 WithCustomer(uint16 NewCustomer);
|
||||
void KeyRingLoad();
|
||||
void KeyRingAdd(uint32 item_id);
|
||||
@@ -315,15 +326,17 @@ public:
|
||||
void Tell_StringID(uint32 string_id, const char *who, const char *message);
|
||||
void SendColoredText(uint32 color, std::string message);
|
||||
void SendBazaarResults(uint32 trader_id, uint32 in_class, uint32 in_race, uint32 item_stat, uint32 item_slot, uint32 item_type, char item_name[64], uint32 min_price, uint32 max_price);
|
||||
void SendTraderItem(uint32 item_id,uint16 quantity);
|
||||
void SendTraderItem(uint32 item_id,uint16 quantity, TraderRepository::Trader &trader);
|
||||
void DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria);
|
||||
uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity);
|
||||
uint32 FindTraderItemSerialNumber(int32 ItemID);
|
||||
EQ::ItemInstance* FindTraderItemBySerialNumber(int32 SerialNumber);
|
||||
void FindAndNukeTraderItem(int32 item_id,int16 quantity,Client* customer,uint16 traderslot);
|
||||
void NukeTraderItem(uint16 slot, int16 charges, int16 quantity, Client* customer, uint16 traderslot, int32 uniqueid, int32 itemid = 0);
|
||||
void FindAndNukeTraderItem(int32 serial_number, int16 quantity, Client* customer, uint16 trader_slot);
|
||||
void NukeTraderItem(uint16 slot, int16 charges, int16 quantity, Client* customer, uint16 trader_slot, int32 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(TraderBuy_Struct* tbs, Client* trader, const EQApplicationPacket* app);
|
||||
void BuyTraderItemOutsideBazaar(TraderBuy_Struct* tbs, const EQApplicationPacket* app);
|
||||
void FinishTrade(
|
||||
Mob *with,
|
||||
bool finalizer = false,
|
||||
@@ -335,7 +348,7 @@ public:
|
||||
void DoParcelCancel();
|
||||
void DoParcelSend(const Parcel_Struct *parcel_in);
|
||||
void DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in);
|
||||
void SendParcel(const Parcel_Struct &parcel);
|
||||
void SendParcel(Parcel_Struct &parcel);
|
||||
void SendParcelStatus();
|
||||
void SendParcelAck();
|
||||
void SendParcelRetrieveAck();
|
||||
@@ -355,6 +368,13 @@ public:
|
||||
int32 FindNextFreeParcelSlot(uint32 char_id);
|
||||
void SendParcelIconStatus();
|
||||
|
||||
void SendBecomeTraderToWorld(Client *trader, BazaarTraderBarterActions action);
|
||||
void SendBecomeTrader(BazaarTraderBarterActions action, uint32 trader_id);
|
||||
|
||||
bool IsThereACustomer() const { return customer_id ? true : false; }
|
||||
uint32 GetCustomerID() { return customer_id; }
|
||||
void SetCustomerID(uint32 id) { customer_id = id; }
|
||||
|
||||
void SendBuyerResults(char *SearchQuery, uint32 SearchID);
|
||||
void ShowBuyLines(const EQApplicationPacket *app);
|
||||
void SellToBuyer(const EQApplicationPacket *app);
|
||||
@@ -485,7 +505,7 @@ public:
|
||||
|
||||
void ServerFilter(SetServerFilter_Struct* filter);
|
||||
void BulkSendTraderInventory(uint32 char_id);
|
||||
void SendSingleTraderItem(uint32 char_id, int uniqueid);
|
||||
void SendSingleTraderItem(uint32 char_id, int serial_number);
|
||||
void BulkSendMerchantInventory(int merchant_id, int npcid);
|
||||
|
||||
inline uint8 GetLanguageSkill(uint8 language_id) const { return m_pp.languages[language_id]; }
|
||||
@@ -1067,7 +1087,11 @@ public:
|
||||
bool IsValidSlot(uint32 slot);
|
||||
bool IsBankSlot(uint32 slot);
|
||||
|
||||
inline bool IsTrader() const { return(Trader); }
|
||||
bool IsTrader() const { return trader; }
|
||||
void SetTrader(bool status) { trader = status; }
|
||||
uint16 GetTraderID() { return trader_id; }
|
||||
void SetTraderID(uint16 id) { trader_id = id; }
|
||||
|
||||
inline bool IsBuyer() const { return(Buyer); }
|
||||
eqFilterMode GetFilter(eqFilterType filter_id) const { return ClientFilters[filter_id]; }
|
||||
void SetFilter(eqFilterType filter_id, eqFilterMode filter_mode) { ClientFilters[filter_id] = filter_mode; }
|
||||
@@ -1800,8 +1824,6 @@ private:
|
||||
void RemoveBandolier(const EQApplicationPacket *app);
|
||||
void SetBandolier(const EQApplicationPacket *app);
|
||||
|
||||
void HandleTraderPriceUpdate(const EQApplicationPacket *app);
|
||||
|
||||
int32 CalcItemATKCap() final;
|
||||
int32 CalcHaste();
|
||||
|
||||
@@ -1880,13 +1902,13 @@ private:
|
||||
uint16 controlling_boat_id;
|
||||
uint16 controlled_mob_id;
|
||||
uint16 TrackingID;
|
||||
uint16 CustomerID;
|
||||
uint16 TraderID;
|
||||
bool trader;
|
||||
uint16 trader_id;
|
||||
uint16 customer_id;
|
||||
uint32 account_creation;
|
||||
uint8 firstlogon;
|
||||
uint32 mercid; // current merc
|
||||
uint8 mercSlot; // selected merc slot
|
||||
bool Trader;
|
||||
bool Buyer;
|
||||
std::string BuyerWelcomeMessage;
|
||||
int32 m_parcel_platinum;
|
||||
|
||||
+195
-304
@@ -918,6 +918,10 @@ void Client::CompleteConnect()
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
|
||||
SendBulkBazaarTraders();
|
||||
}
|
||||
|
||||
// TODO: load these states
|
||||
// We at least will set them to the correct state for now
|
||||
if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) {
|
||||
@@ -1074,9 +1078,6 @@ void Client::Handle_Connect_OP_ReqClientSpawn(const EQApplicationPacket *app)
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
if (strncasecmp(zone->GetShortName(), "bazaar", 6) == 0)
|
||||
SendBazaarWelcome();
|
||||
|
||||
conn_state = ZoneContentsSent;
|
||||
|
||||
return;
|
||||
@@ -3787,7 +3788,7 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app)
|
||||
|
||||
case Barter_BuyerModeOn:
|
||||
{
|
||||
if (!Trader) {
|
||||
if (!IsTrader()) {
|
||||
ToggleBuyerMode(true);
|
||||
}
|
||||
else {
|
||||
@@ -3864,7 +3865,7 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app)
|
||||
|
||||
case Barter_Welcome:
|
||||
{
|
||||
SendBazaarWelcome();
|
||||
//SendBazaarWelcome();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3918,7 +3919,7 @@ void Client::Handle_OP_BazaarInspect(const EQApplicationPacket *app)
|
||||
|
||||
BazaarInspect_Struct* bis = (BazaarInspect_Struct*)app->pBuffer;
|
||||
|
||||
const EQ::ItemData* item = database.GetItem(bis->ItemID);
|
||||
const EQ::ItemData* item = database.GetItem(bis->item_id);
|
||||
|
||||
if (!item) {
|
||||
Message(Chat::Red, "Error: This item does not exist!");
|
||||
@@ -3937,39 +3938,47 @@ void Client::Handle_OP_BazaarInspect(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_BazaarSearch(const EQApplicationPacket *app)
|
||||
{
|
||||
uint32 action = *(uint32 *) app->pBuffer;
|
||||
|
||||
if (app->size == sizeof(BazaarSearch_Struct)) {
|
||||
switch (action) {
|
||||
case BazaarSearch: {
|
||||
BazaarSearchCriteria_Struct *bss = (BazaarSearchCriteria_Struct *) app->pBuffer;
|
||||
BazaarSearchCriteria_Struct search_details{};
|
||||
|
||||
BazaarSearch_Struct* bss = (BazaarSearch_Struct*)app->pBuffer;
|
||||
search_details.action = BazaarSearchResults;
|
||||
search_details.augment = bss->augment;
|
||||
search_details._class = bss->_class;
|
||||
search_details.item_stat = bss->item_stat;
|
||||
search_details.min_cost = bss->min_cost;
|
||||
search_details.max_cost = bss->max_cost;
|
||||
search_details.min_level = bss->min_level;
|
||||
search_details.max_level = bss->max_level;
|
||||
search_details.max_results = bss->max_results;
|
||||
search_details.prestige = bss->prestige;
|
||||
search_details.race = bss->race;
|
||||
search_details.search_scope = bss->search_scope;
|
||||
search_details.slot = bss->slot;
|
||||
search_details.trader_entity_id = bss->trader_entity_id;
|
||||
search_details.trader_id = bss->trader_id;
|
||||
search_details.type = bss->type;
|
||||
strn0cpy(search_details.item_name, bss->item_name, sizeof(search_details.item_name));
|
||||
|
||||
SendBazaarResults(bss->TraderID, bss->Class_, bss->Race, bss->ItemStat, bss->Slot, bss->Type,
|
||||
bss->Name, bss->MinPrice * 1000, bss->MaxPrice * 1000);
|
||||
}
|
||||
else if (app->size == sizeof(BazaarWelcome_Struct)) {
|
||||
|
||||
BazaarWelcome_Struct* bws = (BazaarWelcome_Struct*)app->pBuffer;
|
||||
|
||||
if (bws->Beginning.Action == BazaarWelcome)
|
||||
SendBazaarWelcome();
|
||||
}
|
||||
else if (app->size == sizeof(NewBazaarInspect_Struct)) {
|
||||
|
||||
NewBazaarInspect_Struct *nbis = (NewBazaarInspect_Struct*)app->pBuffer;
|
||||
|
||||
Client *c = entity_list.GetClientByName(nbis->Name);
|
||||
if (c) {
|
||||
EQ::ItemInstance* inst = c->FindTraderItemBySerialNumber(nbis->SerialNumber);
|
||||
if (inst)
|
||||
SendItemPacket(0, inst, ItemPacketViewLink);
|
||||
DoBazaarSearch(search_details);
|
||||
break;
|
||||
}
|
||||
case BazaarInspect: {
|
||||
auto in = (BazaarInspect_Struct *) app->pBuffer;
|
||||
DoBazaarInspect(*in);
|
||||
break;
|
||||
}
|
||||
case WelcomeMessage: {
|
||||
SendBazaarWelcome();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogError("Malformed BazaarSearch_Struct packet received, ignoring\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
LogTrading("Malformed BazaarSearch_Struct packet received, ignoring");
|
||||
LogError("Malformed BazaarSearch_Struct packet received, ignoring\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_Begging(const EQApplicationPacket *app)
|
||||
@@ -4973,8 +4982,8 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
|
||||
if (cy != m_Position.y || cx != m_Position.x) {
|
||||
// End trader mode if we move
|
||||
if (Trader) {
|
||||
Trader_EndTrader();
|
||||
if (IsTrader()) {
|
||||
TraderEndTrader();
|
||||
}
|
||||
|
||||
/* Break Hide if moving without sneaking and set rewind timer if moved */
|
||||
@@ -15494,174 +15503,49 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
|
||||
//
|
||||
// SoF sends 1 or more unhandled OP_Trader packets of size 96 when a trade has completed.
|
||||
// I don't know what they are for (yet), but it doesn't seem to matter that we ignore them.
|
||||
auto action = *(uint32 *)app->pBuffer;
|
||||
|
||||
|
||||
uint32 max_items = 80;
|
||||
|
||||
/*
|
||||
if (GetClientVersion() >= EQClientRoF)
|
||||
max_items = 200;
|
||||
*/
|
||||
|
||||
//Show Items
|
||||
if (app->size == sizeof(Trader_ShowItems_Struct))
|
||||
{
|
||||
Trader_ShowItems_Struct* sis = (Trader_ShowItems_Struct*)app->pBuffer;
|
||||
|
||||
switch (sis->Code)
|
||||
{
|
||||
case BazaarTrader_EndTraderMode: {
|
||||
Trader_EndTrader();
|
||||
switch (action) {
|
||||
case TraderOff: {
|
||||
TraderEndTrader();
|
||||
LogTrading("End Trader Session");
|
||||
break;
|
||||
}
|
||||
case BazaarTrader_EndTransaction: {
|
||||
|
||||
Client* c = entity_list.GetClientByID(sis->TraderID);
|
||||
if (c)
|
||||
{
|
||||
c->WithCustomer(0);
|
||||
LogTrading("End Transaction");
|
||||
}
|
||||
else
|
||||
LogTrading("Null Client Pointer");
|
||||
|
||||
break;
|
||||
}
|
||||
case BazaarTrader_ShowItems: {
|
||||
Trader_ShowItems();
|
||||
LogTrading("Show Trader Items");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("Unhandled action code in OP_Trader ShowItems_Struct");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (app->size == sizeof(ClickTrader_Struct))
|
||||
{
|
||||
if (Buyer) {
|
||||
Trader_EndTrader();
|
||||
Message(Chat::Red, "You cannot be a Trader and Buyer at the same time.");
|
||||
return;
|
||||
}
|
||||
|
||||
ClickTrader_Struct* ints = (ClickTrader_Struct*)app->pBuffer;
|
||||
|
||||
if (ints->Code == BazaarTrader_StartTraderMode)
|
||||
{
|
||||
GetItems_Struct* gis = GetTraderItems();
|
||||
|
||||
LogTrading("Start Trader Mode");
|
||||
// Verify there are no NODROP or items with a zero price
|
||||
bool TradeItemsValid = true;
|
||||
|
||||
for (uint32 i = 0; i < max_items; i++) {
|
||||
|
||||
if (gis->Items[i] == 0) break;
|
||||
|
||||
if (ints->ItemCost[i] == 0) {
|
||||
Message(Chat::Red, "Item in Trader Satchel with no price. Unable to start trader mode");
|
||||
TradeItemsValid = false;
|
||||
break;
|
||||
}
|
||||
const EQ::ItemData *Item = database.GetItem(gis->Items[i]);
|
||||
|
||||
if (!Item) {
|
||||
Message(Chat::Red, "Unexpected error. Unable to start trader mode");
|
||||
TradeItemsValid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Item->NoDrop == 0) {
|
||||
Message(Chat::Red, "NODROP Item in Trader Satchel. Unable to start trader mode");
|
||||
TradeItemsValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!TradeItemsValid) {
|
||||
Trader_EndTrader();
|
||||
safe_delete(gis);
|
||||
case TraderOn: {
|
||||
if (Buyer) {
|
||||
TraderEndTrader();
|
||||
Message(Chat::Red, "You cannot be a Trader and Buyer at the same time.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < max_items; i++) {
|
||||
if (database.GetItem(gis->Items[i])) {
|
||||
database.SaveTraderItem(CharacterID(), gis->Items[i], gis->SerialNumber[i],
|
||||
gis->Charges[i], ints->ItemCost[i], i);
|
||||
|
||||
auto inst = FindTraderItemBySerialNumber(gis->SerialNumber[i]);
|
||||
if (inst)
|
||||
inst->SetPrice(ints->ItemCost[i]);
|
||||
}
|
||||
else {
|
||||
//return; //sony doesnt memset so assume done on first bad item
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
safe_delete(gis);
|
||||
|
||||
Trader_StartTrader();
|
||||
|
||||
// This refreshes the Trader window to display the End Trader button
|
||||
if (ClientVersion() >= EQ::versions::ClientVersion::RoF)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderStatus_Struct));
|
||||
TraderStatus_Struct* tss = (TraderStatus_Struct*)outapp->pBuffer;
|
||||
tss->Code = BazaarTrader_StartTraderMode2;
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogTrading("Unknown TraderStruct code of: [{}]\n",
|
||||
ints->Code);
|
||||
|
||||
LogError("Unknown TraderStruct code of: [{}]\n", ints->Code);
|
||||
}
|
||||
}
|
||||
else if (app->size == sizeof(TraderStatus_Struct))
|
||||
{
|
||||
TraderStatus_Struct* tss = (TraderStatus_Struct*)app->pBuffer;
|
||||
|
||||
LogTrading("Trader Status Code: [{}]", tss->Code);
|
||||
|
||||
switch (tss->Code)
|
||||
{
|
||||
case BazaarTrader_EndTraderMode: {
|
||||
Trader_EndTrader();
|
||||
LogTrading("End Trader Session");
|
||||
TraderStartTrader(app);
|
||||
break;
|
||||
}
|
||||
case BazaarTrader_ShowItems: {
|
||||
Trader_ShowItems();
|
||||
case PriceUpdate:
|
||||
case ItemMove: {
|
||||
LogTrading("Trader Price Update");
|
||||
TraderPriceUpdate(app);
|
||||
break;
|
||||
}
|
||||
case EndTransaction: {
|
||||
auto sis = (Trader_ShowItems_Struct *) app->pBuffer;
|
||||
Client *c = entity_list.GetClientByID(sis->entity_id);
|
||||
if (c) {
|
||||
c->WithCustomer(0);
|
||||
LogTrading("End Transaction");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ListTraderItems: {
|
||||
TraderShowItems();
|
||||
LogTrading("Show Trader Items");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogTrading("Unhandled action code in OP_Trader ShowItems_Struct");
|
||||
break;
|
||||
LogError("Unknown size for OP_Trader: [{}]\n", app->size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (app->size == sizeof(TraderPriceUpdate_Struct))
|
||||
{
|
||||
LogTrading("Trader Price Update");
|
||||
HandleTraderPriceUpdate(app);
|
||||
}
|
||||
else {
|
||||
LogTrading("Unknown size for OP_Trader: [{}]\n", app->size);
|
||||
LogError("Unknown size for OP_Trader: [{}]\n", app->size);
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
|
||||
@@ -15670,23 +15554,80 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
|
||||
//
|
||||
// Client has elected to buy an item from a Trader
|
||||
//
|
||||
if (app->size != sizeof(TraderBuy_Struct)) {
|
||||
LogError("Wrong size: OP_TraderBuy, size=[{}], expected [{}]", app->size, sizeof(TraderBuy_Struct));
|
||||
return;
|
||||
auto in = (TraderBuy_Struct *) app->pBuffer;
|
||||
auto trader = entity_list.GetClientByID(in->trader_id);
|
||||
|
||||
switch (in->method) {
|
||||
case ByVendor: {
|
||||
if (trader) {
|
||||
LogTrading("Buy item directly from vendor id <green>[{}] item_id <green>[{}] quantity <green>[{}] "
|
||||
"serial_number <green>[{}]",
|
||||
in->trader_id,
|
||||
in->item_id,
|
||||
in->quantity,
|
||||
in->serial_number
|
||||
);
|
||||
BuyTraderItem(in, trader, app);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ByParcel: {
|
||||
if (!RuleB(Parcel, EnableParcelMerchants) || !RuleB(Bazaar, EnableParcelDelivery)) {
|
||||
LogTrading(
|
||||
"Bazaar purchase attempt by parcel delivery though 'Parcel:EnableParcelMerchants' or "
|
||||
"'Bazaar::EnableParcelDelivery' not enabled."
|
||||
);
|
||||
Message(
|
||||
Chat::Yellow,
|
||||
"The bazaar parcel delivey system is not enabled on this server. Please visit the vendor directly in the Bazaar."
|
||||
);
|
||||
in->method = ByParcel;
|
||||
in->sub_action = Failed;
|
||||
TradeRequestFailed(app);
|
||||
return;
|
||||
}
|
||||
LogTrading("Buy item by parcel delivery <green>[{}] item_id <green>[{}] quantity <green>[{}] "
|
||||
"serial_number <green>[{}]",
|
||||
in->trader_id,
|
||||
in->item_id,
|
||||
in->quantity,
|
||||
in->serial_number
|
||||
);
|
||||
BuyTraderItemOutsideBazaar(in, app);
|
||||
break;
|
||||
}
|
||||
case ByDirectToInventory: {
|
||||
if (!RuleB(Parcel, EnableDirectToInventoryDelivery)) {
|
||||
LogTrading("Bazaar purchase attempt by direct inventory delivery though "
|
||||
"'Parcel:EnableDirectToInventoryDelivery' not enabled."
|
||||
);
|
||||
Message(
|
||||
Chat::Yellow,
|
||||
"Direct inventory delivey is not enabled on this server. Please visit the vendor directly."
|
||||
);
|
||||
in->method = ByDirectToInventory;
|
||||
in->sub_action = Failed;
|
||||
TradeRequestFailed(app);
|
||||
return;
|
||||
}
|
||||
trader = entity_list.GetClientByCharID(in->trader_id);
|
||||
LogTrading("Buy item by direct inventory delivery <green>[{}] item_id <green>[{}] quantity <green>[{}] "
|
||||
"serial_number <green>[{}]",
|
||||
in->trader_id,
|
||||
in->item_id,
|
||||
in->quantity,
|
||||
in->serial_number
|
||||
);
|
||||
Message(
|
||||
Chat::Yellow,
|
||||
"Direct inventory delivey is not yet implemented. Please visit the vendor directly or purchase via parcel delivery."
|
||||
);
|
||||
in->method = ByDirectToInventory;
|
||||
in->sub_action = Failed;
|
||||
TradeRequestFailed(app);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TraderBuy_Struct* tbs = (TraderBuy_Struct*)app->pBuffer;
|
||||
|
||||
if (Client* Trader = entity_list.GetClientByID(tbs->TraderID)) {
|
||||
BuyTraderItem(tbs, Trader, app);
|
||||
LogTrading("Client::Handle_OP_TraderBuy: Buy Trader Item ");
|
||||
}
|
||||
else {
|
||||
LogTrading("Client::Handle_OP_TraderBuy: Null Client Pointer");
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_TradeRequest(const EQApplicationPacket *app)
|
||||
@@ -15749,126 +15690,76 @@ void Client::Handle_OP_TradeRequestAck(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_TraderShop(const EQApplicationPacket *app)
|
||||
{
|
||||
// Bazaar Trader:
|
||||
auto in = (TraderClick_Struct *) app->pBuffer;
|
||||
LogTrading("Handle_OP_TraderShop: TraderClick_Struct TraderID [{}], Code [{}], Unknown008 [{}], Approval [{}]",
|
||||
in->TraderID,
|
||||
in->Code,
|
||||
in->Unknown008,
|
||||
in->Approval
|
||||
);
|
||||
|
||||
if (app->size == sizeof(TraderClick_Struct))
|
||||
{
|
||||
switch (in->Code) {
|
||||
case ClickTrader: {
|
||||
LogTrading("Handle_OP_TraderShop case ClickTrader [{}]", in->Code);
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(OP_TraderShop, sizeof(TraderClick_Struct));
|
||||
auto data = (TraderClick_Struct *) outapp->pBuffer;
|
||||
auto trader_client = entity_list.GetClientByID(in->TraderID);
|
||||
|
||||
TraderClick_Struct* tcs = (TraderClick_Struct*)app->pBuffer;
|
||||
|
||||
LogTrading("Handle_OP_TraderShop: TraderClick_Struct TraderID [{}], Code [{}], Unknown008 [{}], Approval [{}]",
|
||||
tcs->TraderID, tcs->Code, tcs->Unknown008, tcs->Approval);
|
||||
|
||||
if (tcs->Code == BazaarWelcome)
|
||||
{
|
||||
LogTrading("Client::Handle_OP_TraderShop: Sent Bazaar Welcome Info");
|
||||
SendBazaarWelcome();
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is when a potential purchaser right clicks on this client who is in Trader mode to
|
||||
// browse their goods.
|
||||
auto outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderClick_Struct));
|
||||
|
||||
TraderClick_Struct* outtcs = (TraderClick_Struct*)outapp->pBuffer;
|
||||
|
||||
Client* Trader = entity_list.GetClientByID(tcs->TraderID);
|
||||
|
||||
if (Trader)
|
||||
{
|
||||
outtcs->Approval = Trader->WithCustomer(GetID());
|
||||
LogTrading("Client::Handle_OP_TraderShop: Shop Request ([{}]) to ([{}]) with Approval: [{}]", GetCleanName(), Trader->GetCleanName(), outtcs->Approval);
|
||||
if (trader_client) {
|
||||
data->Approval = trader_client->WithCustomer(GetID());
|
||||
LogTrading("Client::Handle_OP_TraderShop: Shop Request ([{}]) to ([{}]) with Approval: [{}]",
|
||||
GetCleanName(),
|
||||
trader_client->GetCleanName(),
|
||||
data->Approval
|
||||
);
|
||||
}
|
||||
else {
|
||||
LogTrading("Client::Handle_OP_TraderShop: entity_list.GetClientByID(tcs->traderid)"
|
||||
" returned a nullptr pointer");
|
||||
safe_delete(outapp);
|
||||
" returned a nullptr pointer"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
outtcs->TraderID = tcs->TraderID;
|
||||
data->Code = ClickTrader;
|
||||
data->TraderID = in->TraderID;
|
||||
data->Unknown008 = 0x3f800000;
|
||||
QueuePacket(outapp.get());
|
||||
|
||||
outtcs->Unknown008 = 0x3f800000;
|
||||
|
||||
QueuePacket(outapp);
|
||||
|
||||
|
||||
if (outtcs->Approval) {
|
||||
BulkSendTraderInventory(Trader->CharacterID());
|
||||
Trader->Trader_CustomerBrowsing(this);
|
||||
TraderID = tcs->TraderID;
|
||||
LogTrading("Client::Handle_OP_TraderShop: Trader Inventory Sent");
|
||||
if (data->Approval) {
|
||||
BulkSendTraderInventory(trader_client->CharacterID());
|
||||
trader_client->Trader_CustomerBrowsing(this);
|
||||
SetTraderID(in->TraderID);
|
||||
LogTrading("Client::Handle_OP_TraderShop: Trader Inventory Sent to [{}] from [{}]",
|
||||
GetID(),
|
||||
in->TraderID
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
MessageString(Chat::Yellow, TRADER_BUSY);
|
||||
LogTrading("Client::Handle_OP_TraderShop: Trader Busy");
|
||||
}
|
||||
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else if (app->size == sizeof(BazaarWelcome_Struct))
|
||||
{
|
||||
// RoF+
|
||||
// Client requested Bazaar Welcome Info (Trader and Item Total Counts)
|
||||
SendBazaarWelcome();
|
||||
LogTrading("Client::Handle_OP_TraderShop: Sent Bazaar Welcome Info");
|
||||
}
|
||||
else if (app->size == sizeof(TraderBuy_Struct))
|
||||
{
|
||||
// RoF+
|
||||
// Customer has purchased an item from the Trader
|
||||
|
||||
TraderBuy_Struct* tbs = (TraderBuy_Struct*)app->pBuffer;
|
||||
|
||||
if (Client* Trader = entity_list.GetClientByID(tbs->TraderID))
|
||||
{
|
||||
BuyTraderItem(tbs, Trader, app);
|
||||
LogTrading("Handle_OP_TraderShop: Buy Action [{}], Price [{}], Trader [{}], ItemID [{}], Quantity [{}], ItemName, [{}]",
|
||||
tbs->Action, tbs->Price, tbs->TraderID, tbs->ItemID, tbs->Quantity, tbs->ItemName);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogTrading("OP_TraderShop: Null Client Pointer");
|
||||
}
|
||||
}
|
||||
else if (app->size == 4)
|
||||
{
|
||||
// RoF+
|
||||
// Customer has closed the trade window
|
||||
uint32 Command = *((uint32 *)app->pBuffer);
|
||||
|
||||
if (Command == 4)
|
||||
{
|
||||
Client* c = entity_list.GetClientByID(TraderID);
|
||||
TraderID = 0;
|
||||
if (c)
|
||||
{
|
||||
case EndTransaction: {
|
||||
Client *c = entity_list.GetClientByID(GetTraderID());
|
||||
SetTraderID(0);
|
||||
if (c) {
|
||||
c->WithCustomer(0);
|
||||
LogTrading("End Transaction - Code [{}]", Command);
|
||||
LogTrading("End Transaction - Code [{}]", in->Code);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogTrading("Null Client Pointer for Trader - Code [{}]", Command);
|
||||
else {
|
||||
LogTrading("Null Client Pointer for Trader - Code [{}]", in->Code);
|
||||
}
|
||||
EQApplicationPacket empty(OP_ShopEndConfirm);
|
||||
QueuePacket(&empty);
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_ShopEndConfirm);
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogTrading("Unhandled Code [{}]", Command);
|
||||
default: {
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogTrading("Unknown size for OP_TraderShop: [{}]\n", app->size);
|
||||
LogError("Unknown size for OP_TraderShop: [{}]\n", app->size);
|
||||
DumpPacket(app);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Client::Handle_OP_TradeSkillCombine(const EQApplicationPacket *app)
|
||||
|
||||
@@ -994,22 +994,22 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
|
||||
uint8 Client::WithCustomer(uint16 NewCustomer){
|
||||
|
||||
if(NewCustomer == 0) {
|
||||
CustomerID = 0;
|
||||
SetCustomerID(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(CustomerID == 0) {
|
||||
CustomerID = NewCustomer;
|
||||
if(GetCustomerID() == 0) {
|
||||
SetCustomerID(NewCustomer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check that the player browsing our wares hasn't gone away.
|
||||
|
||||
Client* c = entity_list.GetClientByID(CustomerID);
|
||||
Client* c = entity_list.GetClientByID(GetCustomerID());
|
||||
|
||||
if(!c) {
|
||||
LogTrading("Previous customer has gone away");
|
||||
CustomerID = NewCustomer;
|
||||
SetCustomerID(NewCustomer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ void command_parcels(Client *c, const Seperator *sep)
|
||||
return;
|
||||
}
|
||||
|
||||
auto results = CharacterParcelsRepository::GetWhere(
|
||||
auto results = CharacterParcelsRepository::GetWhere(
|
||||
database,
|
||||
fmt::format("char_id = '{}' ORDER BY slot_id ASC", player_id.at(0).char_id)
|
||||
);
|
||||
@@ -120,8 +120,8 @@ void command_parcels(Client *c, const Seperator *sep)
|
||||
auto note = std::string(sep->argplus[5]);
|
||||
|
||||
auto send_to_client = CharacterParcelsRepository::GetParcelCountAndCharacterName(
|
||||
database,
|
||||
to_name
|
||||
database,
|
||||
to_name
|
||||
);
|
||||
if (send_to_client.at(0).character_name.empty()) {
|
||||
c->MessageString(Chat::Yellow, CANT_FIND_PLAYER, to_name.c_str());
|
||||
@@ -164,14 +164,14 @@ void command_parcels(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
CharacterParcelsRepository::CharacterParcels parcel_out;
|
||||
parcel_out.from_name = c->GetName();
|
||||
parcel_out.note = note;
|
||||
parcel_out.sent_date = time(nullptr);
|
||||
parcel_out.quantity = quantity == 0 ? 1 : quantity;
|
||||
parcel_out.item_id = PARCEL_MONEY_ITEM_ID;
|
||||
parcel_out.char_id = send_to_client.at(0).char_id;
|
||||
parcel_out.slot_id = next_slot;
|
||||
parcel_out.id = 0;
|
||||
parcel_out.from_name = c->GetName();
|
||||
parcel_out.note = note;
|
||||
parcel_out.sent_date = time(nullptr);
|
||||
parcel_out.quantity = quantity == 0 ? 1 : quantity;
|
||||
parcel_out.item_id = PARCEL_MONEY_ITEM_ID;
|
||||
parcel_out.char_id = send_to_client.at(0).char_id;
|
||||
parcel_out.slot_id = next_slot;
|
||||
parcel_out.id = 0;
|
||||
|
||||
auto result = CharacterParcelsRepository::InsertOne(database, parcel_out);
|
||||
if (!result.id) {
|
||||
@@ -205,7 +205,7 @@ void command_parcels(Client *c, const Seperator *sep)
|
||||
e.quantity = parcel_out.quantity;
|
||||
e.sent_date = parcel_out.sent_date;
|
||||
|
||||
RecordPlayerEventLogWithClient(c, PlayerEvent::PARCEL_SEND, e);
|
||||
RecordPlayerEventLogWithClient (c, PlayerEvent::PARCEL_SEND, e);
|
||||
}
|
||||
|
||||
Parcel_Struct ps{};
|
||||
@@ -242,14 +242,14 @@ void command_parcels(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
CharacterParcelsRepository::CharacterParcels parcel_out;
|
||||
parcel_out.from_name = c->GetName();
|
||||
parcel_out.note = note.empty() ? "" : note;
|
||||
parcel_out.sent_date = time(nullptr);
|
||||
parcel_out.quantity = quantity;
|
||||
parcel_out.item_id = item_id;
|
||||
parcel_out.char_id = send_to_client.at(0).char_id;
|
||||
parcel_out.slot_id = next_slot;
|
||||
parcel_out.id = 0;
|
||||
parcel_out.from_name = c->GetName();
|
||||
parcel_out.note = note.empty() ? "" : note;
|
||||
parcel_out.sent_date = time(nullptr);
|
||||
parcel_out.quantity = quantity;
|
||||
parcel_out.item_id = item_id;
|
||||
parcel_out.char_id = send_to_client.at(0).char_id;
|
||||
parcel_out.slot_id = next_slot;
|
||||
parcel_out.id = 0;
|
||||
|
||||
auto result = CharacterParcelsRepository::InsertOne(database, parcel_out);
|
||||
if (!result.id) {
|
||||
@@ -283,7 +283,7 @@ void command_parcels(Client *c, const Seperator *sep)
|
||||
e.quantity = parcel_out.quantity;
|
||||
e.sent_date = parcel_out.sent_date;
|
||||
|
||||
RecordPlayerEventLogWithClient(c, PlayerEvent::PARCEL_SEND, e);
|
||||
RecordPlayerEventLogWithClient (c, PlayerEvent::PARCEL_SEND, e);
|
||||
}
|
||||
|
||||
Parcel_Struct ps{};
|
||||
@@ -300,8 +300,8 @@ void SendParcelsSubCommands(Client *c)
|
||||
c->Message(Chat::White, "#parcels listdb [Character Name]");
|
||||
c->Message(Chat::White, "#parcels listmemory [Character Name] (Must be in the same zone)");
|
||||
c->Message(
|
||||
Chat::White,
|
||||
"#parcels add [Character Name] [item id] [quantity] [note]. To send money use item id of 99990. Quantity is valid for stackable items, charges on an item, or amount of copper."
|
||||
Chat::White,
|
||||
"#parcels add [Character Name] [item id] [quantity] [note]. To send money use item id of 99990. Quantity is valid for stackable items, charges on an item, or amount of copper."
|
||||
);
|
||||
c->Message(Chat::White, "#parcels details [Character Name]");
|
||||
}
|
||||
|
||||
@@ -164,10 +164,11 @@ void ShowInventory(Client *c, const Seperator *sep)
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Slot {} | {} ({}){}",
|
||||
"Slot {} | {} ({}/{}){}",
|
||||
((scope_bit & peekWorld) ? (EQ::invslot::WORLD_BEGIN + index_main) : index_main),
|
||||
linker.GenerateLink(),
|
||||
item_data->ID,
|
||||
c->GetInv().GetItem(((scope_bit &peekWorld) ? (EQ::invslot::WORLD_BEGIN + index_main) : index_main))->GetSerialNumber(),
|
||||
(
|
||||
inst_main->IsStackable() && inst_main->GetCharges() > 0 ?
|
||||
fmt::format(
|
||||
@@ -228,7 +229,7 @@ void ShowInventory(Client *c, const Seperator *sep)
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Slot {} Bag Slot {} | {} ({}){}",
|
||||
"Slot {} Bag Slot {}/{} | {} ({}/{}){}",
|
||||
(
|
||||
(scope_bit & peekWorld) ?
|
||||
INVALID_INDEX :
|
||||
@@ -238,6 +239,7 @@ void ShowInventory(Client *c, const Seperator *sep)
|
||||
sub_index,
|
||||
linker.GenerateLink(),
|
||||
item_data->ID,
|
||||
c->GetInv().GetItem(EQ::InventoryProfile::CalcSlotId(index_main, sub_index))->GetSerialNumber(),
|
||||
(
|
||||
inst_sub->IsStackable() && inst_sub->GetCharges() > 0 ?
|
||||
fmt::format(
|
||||
|
||||
+25
-4
@@ -1864,19 +1864,19 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
LogInventory("Dest slot [{}] has item [{}] ([{}]) with [{}] charges in it", dst_slot_id, dst_inst->GetItem()->Name, dst_inst->GetItem()->ID, dst_inst->GetCharges());
|
||||
dstitemid = dst_inst->GetItem()->ID;
|
||||
}
|
||||
if (Trader && srcitemid>0){
|
||||
if (IsTrader() && srcitemid>0){
|
||||
EQ::ItemInstance* srcbag;
|
||||
EQ::ItemInstance* dstbag;
|
||||
uint32 srcbagid =0;
|
||||
uint32 dstbagid = 0;
|
||||
|
||||
if (src_slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN && src_slot_id <= EQ::invbag::GENERAL_BAGS_END) {
|
||||
srcbag = m_inv.GetItem(((int)(src_slot_id / 10)) - 3);
|
||||
srcbag = m_inv.GetItem(EQ::InventoryProfile::CalcSlotId(src_slot_id));
|
||||
if (srcbag)
|
||||
srcbagid = srcbag->GetItem()->ID;
|
||||
}
|
||||
if (dst_slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN && dst_slot_id <= EQ::invbag::GENERAL_BAGS_END) {
|
||||
dstbag = m_inv.GetItem(((int)(dst_slot_id / 10)) - 3);
|
||||
dstbag = m_inv.GetItem(EQ::InventoryProfile::CalcSlotId(dst_slot_id));
|
||||
if (dstbag)
|
||||
dstbagid = dstbag->GetItem()->ID;
|
||||
}
|
||||
@@ -1884,7 +1884,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
(dstbagid && dstbag->GetItem()->BagType == EQ::item::BagTypeTradersSatchel) ||
|
||||
(srcitemid && src_inst && src_inst->GetItem()->BagType == EQ::item::BagTypeTradersSatchel) ||
|
||||
(dstitemid && dst_inst && dst_inst->GetItem()->BagType == EQ::item::BagTypeTradersSatchel)) {
|
||||
Trader_EndTrader();
|
||||
TraderEndTrader();
|
||||
Message(Chat::Red,"You cannot move your Trader Satchels, or items inside them, while Trading.");
|
||||
}
|
||||
}
|
||||
@@ -2180,6 +2180,27 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
}
|
||||
|
||||
LogInventory("Moving entire item from slot [{}] to slot [{}]", src_slot_id, dst_slot_id);
|
||||
if (src_inst->IsStackable() &&
|
||||
dst_slot_id >= EQ::invbag::GENERAL_BAGS_BEGIN &&
|
||||
dst_slot_id <= EQ::invbag::GENERAL_BAGS_END
|
||||
) {
|
||||
EQ::ItemInstance *bag = nullptr;
|
||||
bag = m_inv.GetItem(EQ::InventoryProfile::CalcSlotId(dst_slot_id));
|
||||
if (bag) {
|
||||
if (bag->GetItem()->BagType == EQ::item::BagTypeTradersSatchel) {
|
||||
PutItemInInventory(dst_slot_id, *src_inst, true);
|
||||
//This resets the UF client to recognize the new serial item of the placed item
|
||||
//if it came from a stack without having to close the trader window and re-open.
|
||||
//It is not required for the RoF2 client.
|
||||
if (ClientVersion() < EQ::versions::ClientVersion::RoF2) {
|
||||
auto outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderBuy_Struct));
|
||||
auto data = (TraderBuy_Struct *) outapp->pBuffer;
|
||||
data->action = BazaarBuyItem;
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (src_slot_id <= EQ::invslot::EQUIPMENT_END) {
|
||||
if(src_inst) {
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ void Client::SendBulkParcels()
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SendParcel(const Parcel_Struct &parcel_in)
|
||||
void Client::SendParcel(Parcel_Struct &parcel_in)
|
||||
{
|
||||
auto results = CharacterParcelsRepository::GetWhere(
|
||||
database,
|
||||
|
||||
@@ -195,6 +195,7 @@
|
||||
#define PARCEL_DELAY 734 //%1 tells you, 'You must give me a chance to send the last parcel before I can send another!'
|
||||
#define PARCEL_DUPLICATE_DELETE 737 //Duplicate lore items are not allowed! Your duplicate %1 has been deleted!
|
||||
#define PARCEL_DELIVER_3 741 //%1 told you, 'I will deliver the stack of %2 %3 to %4 as soon as possible!'
|
||||
#define TRADER_MODE_FAILED_ROF2 785 //Your attempt to become a trader has failed.
|
||||
#define PARCEL_INV_FULL 790 //%1 tells you, 'Your inventory appears full! Unable to retrieve parceled item.'
|
||||
#define AA_CAP 1000 //You have reached the AA point cap, and cannot gain any further experience until some of your stored AA point pool is used.
|
||||
#define GM_GAINXP 1002 //[GM] You have gained %1 AXP and %2 EXP (%3).
|
||||
@@ -427,6 +428,9 @@
|
||||
#define GENERIC_STRING 6688 //%1 (used to any basic message)
|
||||
#define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel.
|
||||
#define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel.
|
||||
#define TRADER_MODE_OFF 6741 //Bazaar Trader Mode *OFF*
|
||||
#define TRADER_MODE_ON 6742 //Bazaar Trader Mode *ON*
|
||||
#define TRADER_SET_PRICE 6754 //To become a merchant you must assign a price to an item in your list. Do this by selecting an item, then selecting a money amount, and then clicking set price.
|
||||
#define IDENTIFY_SPELL 6765 //Item Lore: %1.
|
||||
#define PET_NOW_HOLDING 6834 //Now holding, Master. I will not start attacks until ordered.
|
||||
#define PET_ON_GHOLD 6843 //Pet greater hold has been set to on.
|
||||
|
||||
+1254
-774
File diff suppressed because it is too large
Load Diff
+92
-4
@@ -3915,10 +3915,98 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogInfo("Unknown ZS Opcode [{}] size [{}]", (int)pack->opcode, pack->size);
|
||||
break;
|
||||
}
|
||||
case ServerOP_TraderMessaging: {
|
||||
auto in = (TraderMessaging_Struct *) pack->pBuffer;
|
||||
for (auto const &c: entity_list.GetClientList()) {
|
||||
if (c.second->ClientVersion() >= EQ::versions::ClientVersion::RoF2) {
|
||||
auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct));
|
||||
auto out = (BecomeTrader_Struct *) outapp->pBuffer;
|
||||
switch (in->action) {
|
||||
case TraderOn: {
|
||||
out->action = AddTraderToBazaarWindow;
|
||||
break;
|
||||
}
|
||||
case TraderOff: {
|
||||
out->action = RemoveTraderFromBazaarWindow;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
out->action = 0;
|
||||
}
|
||||
}
|
||||
out->entity_id = in->entity_id;
|
||||
out->zone_id = in->zone_id;
|
||||
out->trader_id = in->trader_id;
|
||||
strn0cpy(out->trader_name, in->trader_name, sizeof(out->trader_name));
|
||||
|
||||
c.second->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
if (zone && zone->GetZoneID() == Zones::BAZAAR) {
|
||||
if (in->action == TraderOn) {
|
||||
c.second->SendBecomeTrader(TraderOn, in->entity_id);
|
||||
}
|
||||
else {
|
||||
c.second->SendBecomeTrader(TraderOff, in->entity_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_BazaarPurchase: {
|
||||
auto in = (BazaarPurchaseMessaging_Struct *) pack->pBuffer;
|
||||
auto trader_pc = entity_list.GetClientByCharID(in->trader_buy_struct.trader_id);
|
||||
if (!trader_pc) {
|
||||
LogTrading("Request trader_id <red>[{}] could not be found in zone_id <red>[{}]",
|
||||
in->trader_buy_struct.trader_id,
|
||||
zone->GetZoneID()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
auto item_sn = Strings::ToUnsignedBigInt(in->trader_buy_struct.serial_number);
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(OP_Trader, sizeof(TraderBuy_Struct));
|
||||
auto data = (TraderBuy_Struct *) outapp->pBuffer;
|
||||
|
||||
memcpy(data, &in->trader_buy_struct, sizeof(TraderBuy_Struct));
|
||||
|
||||
if (trader_pc->ClientVersion() < EQ::versions::ClientVersion::RoF) {
|
||||
data->price = in->trader_buy_struct.price * in->trader_buy_struct.quantity;
|
||||
}
|
||||
|
||||
TraderRepository::UpdateQuantity(
|
||||
database,
|
||||
trader_pc->CharacterID(),
|
||||
item_sn,
|
||||
in->item_quantity_available - in->trader_buy_struct.quantity
|
||||
);
|
||||
TraderRepository::UpdateActiveTransaction(database, in->id, false);
|
||||
|
||||
trader_pc->RemoveItemBySerialNumber(item_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());
|
||||
|
||||
if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_SELL)) {
|
||||
auto e = PlayerEvent::TraderSellEvent{
|
||||
.item_id = in->trader_buy_struct.item_id,
|
||||
.item_name = in->trader_buy_struct.item_name,
|
||||
.buyer_id = in->buyer_id,
|
||||
.buyer_name = in->trader_buy_struct.buyer_name,
|
||||
.price = in->trader_buy_struct.price,
|
||||
.charges = in->trader_buy_struct.quantity,
|
||||
.total_cost = (in->trader_buy_struct.price * in->trader_buy_struct.quantity),
|
||||
.player_money_balance = trader_pc->GetCarriedMoney(),
|
||||
};
|
||||
|
||||
RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LogInfo("Unknown ZS Opcode [{}] size [{}]", (int) pack->opcode, pack->size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -68,6 +68,7 @@
|
||||
#include "../common/repositories/merc_stance_entries_repository.h"
|
||||
#include "../common/repositories/alternate_currency_repository.h"
|
||||
#include "../common/repositories/graveyard_repository.h"
|
||||
#include "../common/repositories/trader_repository.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -1197,7 +1198,7 @@ bool Zone::Init(bool is_static) {
|
||||
|
||||
//clear trader items if we are loading the bazaar
|
||||
if (strncasecmp(short_name, "bazaar", 6) == 0) {
|
||||
database.DeleteTraderItem(0);
|
||||
TraderRepository::Truncate(database);
|
||||
database.DeleteBuyLines(0);
|
||||
}
|
||||
|
||||
|
||||
+108
-165
@@ -51,6 +51,9 @@
|
||||
#include "../common/repositories/character_corpse_items_repository.h"
|
||||
#include "../common/repositories/zone_repository.h"
|
||||
|
||||
#include "../common/repositories/trader_repository.h"
|
||||
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <fmt/format.h>
|
||||
@@ -302,187 +305,114 @@ void ZoneDatabase::DeleteWorldContainer(uint32 parent_id, uint32 zone_id)
|
||||
);
|
||||
}
|
||||
|
||||
Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id)
|
||||
std::unique_ptr<EQ::ItemInstance> ZoneDatabase::LoadSingleTraderItem(uint32 char_id, int serial_number)
|
||||
{
|
||||
auto loadti = new Trader_Struct;
|
||||
memset(loadti,0,sizeof(Trader_Struct));
|
||||
auto results = TraderRepository::GetWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`char_id` = '{}' AND `item_sn` = '{}' ORDER BY slot_id",
|
||||
char_id,
|
||||
serial_number
|
||||
)
|
||||
);
|
||||
|
||||
std::string query = StringFormat("SELECT * FROM trader WHERE char_id = %i ORDER BY slot_id LIMIT 80", char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogTrading("Failed to load trader information!\n");
|
||||
return loadti;
|
||||
if (results.empty()) {
|
||||
LogTrading("Could not find item serial number {} for character id {}", serial_number, char_id);
|
||||
}
|
||||
|
||||
loadti->Code = BazaarTrader_ShowItems;
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
if (Strings::ToInt(row[5]) >= 80 || Strings::ToInt(row[4]) < 0) {
|
||||
LogTrading("Bad Slot number when trying to load trader information!\n");
|
||||
continue;
|
||||
}
|
||||
int item_id = results.at(0).item_id;
|
||||
int charges = results.at(0).item_charges;
|
||||
int cost = results.at(0).item_cost;
|
||||
|
||||
loadti->Items[Strings::ToInt(row[5])] = Strings::ToInt(row[1]);
|
||||
loadti->ItemCost[Strings::ToInt(row[5])] = Strings::ToInt(row[4]);
|
||||
const EQ::ItemData *item = database.GetItem(item_id);
|
||||
if (!item) {
|
||||
LogTrading("Unable to create item.");
|
||||
return nullptr;
|
||||
}
|
||||
return loadti;
|
||||
|
||||
if (item->NoDrop == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<EQ::ItemInstance> inst(
|
||||
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
|
||||
)
|
||||
);
|
||||
if (!inst) {
|
||||
LogTrading("Unable to create item instance.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inst->SetCharges(charges);
|
||||
inst->SetSerialNumber(serial_number);
|
||||
inst->SetMerchantSlot(serial_number);
|
||||
inst->SetPrice(cost);
|
||||
|
||||
if (inst->IsStackable()) {
|
||||
inst->SetMerchantCount(charges);
|
||||
}
|
||||
|
||||
return std::move(inst);
|
||||
}
|
||||
|
||||
TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id)
|
||||
{
|
||||
auto loadti = new TraderCharges_Struct;
|
||||
memset(loadti,0,sizeof(TraderCharges_Struct));
|
||||
void ZoneDatabase::UpdateTraderItemPrice(int char_id, uint32 item_id, uint32 charges, uint32 new_price) {
|
||||
|
||||
std::string query = StringFormat("SELECT * FROM trader WHERE char_id=%i ORDER BY slot_id LIMIT 80", char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogTrading("Failed to load trader information!\n");
|
||||
return loadti;
|
||||
}
|
||||
|
||||
for (auto& row = results.begin(); row != results.end(); ++row) {
|
||||
if (Strings::ToInt(row[5]) >= 80 || Strings::ToInt(row[5]) < 0) {
|
||||
LogTrading("Bad Slot number when trying to load trader information!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
loadti->ItemID[Strings::ToInt(row[5])] = Strings::ToInt(row[1]);
|
||||
loadti->SerialNumber[Strings::ToInt(row[5])] = Strings::ToInt(row[2]);
|
||||
loadti->Charges[Strings::ToInt(row[5])] = Strings::ToInt(row[3]);
|
||||
loadti->ItemCost[Strings::ToInt(row[5])] = Strings::ToInt(row[4]);
|
||||
}
|
||||
return loadti;
|
||||
}
|
||||
|
||||
EQ::ItemInstance* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) {
|
||||
std::string query = StringFormat("SELECT * FROM trader WHERE char_id = %i AND serialnumber = %i "
|
||||
"ORDER BY slot_id LIMIT 80", CharID, SerialNumber);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return nullptr;
|
||||
|
||||
if (results.RowCount() == 0) {
|
||||
LogTrading("Bad result from query\n"); fflush(stdout);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto& row = results.begin();
|
||||
|
||||
int ItemID = Strings::ToInt(row[1]);
|
||||
int Charges = Strings::ToInt(row[3]);
|
||||
int Cost = Strings::ToInt(row[4]);
|
||||
|
||||
const EQ::ItemData *item = database.GetItem(ItemID);
|
||||
LogTrading("ZoneDatabase::UpdateTraderPrice([{}], [{}], [{}], [{}])", char_id, item_id, charges, new_price);
|
||||
const EQ::ItemData *item = database.GetItem(item_id);
|
||||
|
||||
if(!item) {
|
||||
LogTrading("Unable to create item\n");
|
||||
fflush(stdout);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (item->NoDrop == 0)
|
||||
return nullptr;
|
||||
|
||||
EQ::ItemInstance* inst = database.CreateItem(item);
|
||||
if(!inst) {
|
||||
LogTrading("Unable to create item instance\n");
|
||||
fflush(stdout);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inst->SetCharges(Charges);
|
||||
inst->SetSerialNumber(SerialNumber);
|
||||
inst->SetMerchantSlot(SerialNumber);
|
||||
inst->SetPrice(Cost);
|
||||
|
||||
if(inst->IsStackable())
|
||||
inst->SetMerchantCount(Charges);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
void ZoneDatabase::SaveTraderItem(uint32 CharID, uint32 ItemID, uint32 SerialNumber, int32 Charges, uint32 ItemCost, uint8 Slot){
|
||||
|
||||
std::string query = StringFormat("REPLACE INTO trader VALUES(%i, %i, %i, %i, %i, %i)",
|
||||
CharID, ItemID, SerialNumber, Charges, ItemCost, Slot);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to save trader item: [{}] for char_id: [{}], the error was: [{}]\n", ItemID, CharID, results.ErrorMessage().c_str());
|
||||
|
||||
}
|
||||
|
||||
void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) {
|
||||
LogTrading("ZoneDatabase::UpdateTraderItemCharges([{}], [{}], [{}])", CharID, SerialNumber, Charges);
|
||||
|
||||
std::string query = StringFormat("UPDATE trader SET charges = %i WHERE char_id = %i AND serialnumber = %i",
|
||||
Charges, CharID, SerialNumber);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to update charges for trader item: [{}] for char_id: [{}], the error was: [{}]\n", SerialNumber, CharID, results.ErrorMessage().c_str());
|
||||
|
||||
}
|
||||
|
||||
void ZoneDatabase::UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice) {
|
||||
|
||||
LogTrading("ZoneDatabase::UpdateTraderPrice([{}], [{}], [{}], [{}])", CharID, ItemID, Charges, NewPrice);
|
||||
|
||||
const EQ::ItemData *item = database.GetItem(ItemID);
|
||||
|
||||
if(!item)
|
||||
return;
|
||||
}
|
||||
|
||||
if(NewPrice == 0) {
|
||||
LogTrading("Removing Trader items from the DB for CharID [{}], ItemID [{}]", CharID, ItemID);
|
||||
if (new_price == 0) {
|
||||
LogTrading("Removing Trader items from the DB for char_id [{}], item_id [{}]", char_id, item_id);
|
||||
|
||||
std::string query = StringFormat("DELETE FROM trader WHERE char_id = %i AND item_id = %i",CharID, ItemID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to remove trader item(s): [{}] for char_id: [{}], the error was: [{}]\n", ItemID, CharID, results.ErrorMessage().c_str());
|
||||
auto results = TraderRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`char_id` = '{}' AND `item_id` = {}",
|
||||
char_id,
|
||||
item_id
|
||||
)
|
||||
);
|
||||
if (!results) {
|
||||
LogDebug("[CLIENT] Failed to remove trader item(s): [{}] for char_id: [{}]",
|
||||
item_id,
|
||||
char_id
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!item->Stackable) {
|
||||
std::string query = StringFormat("UPDATE trader SET item_cost = %i "
|
||||
"WHERE char_id = %i AND item_id = %i AND charges=%i",
|
||||
NewPrice, CharID, ItemID, Charges);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to update price for trader item: [{}] for char_id: [{}], the error was: [{}]\n", ItemID, CharID, results.ErrorMessage().c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string query = StringFormat("UPDATE trader SET item_cost = %i "
|
||||
"WHERE char_id = %i AND item_id = %i",
|
||||
NewPrice, CharID, ItemID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to update price for trader item: [{}] for char_id: [{}], the error was: [{}]\n", ItemID, CharID, results.ErrorMessage().c_str());
|
||||
}
|
||||
|
||||
void ZoneDatabase::DeleteTraderItem(uint32 char_id){
|
||||
|
||||
if(char_id==0) {
|
||||
const std::string query = "DELETE FROM trader";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to delete all trader items data, the error was: [{}]\n", results.ErrorMessage().c_str());
|
||||
|
||||
return;
|
||||
if (!item->Stackable) {
|
||||
auto results = TraderRepository::UpdateItem(database, char_id, new_price, item_id, charges);
|
||||
if (!results) {
|
||||
LogTrading(
|
||||
"Failed to update price for trader item [{}] for char_id: [{}]",
|
||||
item_id,
|
||||
char_id
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::string query = StringFormat("DELETE FROM trader WHERE char_id = %i", char_id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to delete trader item data for char_id: [{}], the error was: [{}]\n", char_id, results.ErrorMessage().c_str());
|
||||
|
||||
}
|
||||
void ZoneDatabase::DeleteTraderItem(uint32 CharID,uint16 SlotID) {
|
||||
|
||||
std::string query = StringFormat("DELETE FROM trader WHERE char_id = %i And slot_id = %i", CharID, SlotID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to delete trader item data for char_id: [{}], the error was: [{}]\n",CharID, results.ErrorMessage().c_str());
|
||||
auto results = TraderRepository::UpdateItem(database, char_id, new_price, item_id, 0);
|
||||
if (!results) {
|
||||
LogTrading(
|
||||
"Failed to update price for trader item [{}] for char_id: [{}]",
|
||||
item_id,
|
||||
char_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void ZoneDatabase::DeleteBuyLines(uint32 CharID) {
|
||||
@@ -526,10 +456,22 @@ void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity)
|
||||
return;
|
||||
}
|
||||
|
||||
std::string query = StringFormat("UPDATE buyer SET quantity = %i WHERE charid = %i AND buyslot = %i", Quantity, CharID, BuySlot);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
LogDebug("[CLIENT] Failed to update quantity in buyslot [{}] for charid: [{}], the error was: [{}]\n", BuySlot, CharID, results.ErrorMessage().c_str());
|
||||
std::string query = StringFormat(
|
||||
"UPDATE buyer SET quantity = %i WHERE charid = %i AND buyslot = %i",
|
||||
Quantity,
|
||||
CharID,
|
||||
BuySlot
|
||||
);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogTrading(
|
||||
"Failed to update quantity in buyslot [{}] for charid [{}], the error was [{}]\n",
|
||||
BuySlot,
|
||||
CharID,
|
||||
results.ErrorMessage().c_str()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -630,6 +572,7 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct*
|
||||
pp->raidAutoconsent = e.raid_auto_consent;
|
||||
pp->guildAutoconsent = e.guild_auto_consent;
|
||||
pp->RestTimer = e.RestTimer;
|
||||
pp->char_id = e.id;
|
||||
m_epp->aa_effects = e.e_aa_effects;
|
||||
m_epp->perAA = e.e_percent_to_aa;
|
||||
m_epp->expended_aa = e.e_expended_aa_spent;
|
||||
|
||||
+2
-2
@@ -389,11 +389,11 @@ public:
|
||||
/* Traders */
|
||||
void SaveTraderItem(uint32 char_id,uint32 itemid,uint32 uniqueid, int32 charges,uint32 itemcost,uint8 slot);
|
||||
void UpdateTraderItemCharges(int char_id, uint32 ItemInstID, int32 charges);
|
||||
void UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice);
|
||||
void UpdateTraderItemPrice(int char_id, uint32 item_id, uint32 charges, uint32 new_price);
|
||||
void DeleteTraderItem(uint32 char_id);
|
||||
void DeleteTraderItem(uint32 char_id,uint16 slot_id);
|
||||
|
||||
EQ::ItemInstance* LoadSingleTraderItem(uint32 char_id, int uniqueid);
|
||||
std::unique_ptr<EQ::ItemInstance> LoadSingleTraderItem(uint32 char_id, int serial_number);
|
||||
Trader_Struct* LoadTraderItem(uint32 char_id);
|
||||
TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user