[Feature] Add Barter/Buyer Features (#4405)

* Add Barter/Buyer Features

Adds barter and buyer features, for ROF2 only at this time including item compensation

* Remove FKs from buyer tables

Remove FKs from buyer tables

* Bug fix for Find Buyer and mutli item selling

Update for quantity purchases not correctly providing multi items.
Update for Find Buyer functionality based on zone instancing.
Update buyer messaging
Update buyer LORE duplicate check

* Revert zone instance comment

* Revert zone_id packet size field

* Add zone instancing to barter/buyer

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
Mitch Freeman
2024-07-30 17:23:37 -03:00
committed by GitHub
parent fc3c691588
commit e49ab924cc
40 changed files with 4715 additions and 946 deletions
+89 -93
View File
@@ -65,6 +65,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/repositories/account_repository.h"
#include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/guild_tributes_repository.h"
#include "../common/repositories/buyer_buy_lines_repository.h"
#include "../common/events/player_event_logs.h"
#include "../common/repositories/character_stats_record_repository.h"
@@ -758,8 +759,6 @@ void Client::CompleteConnect()
entity_list.SendIllusionWearChange(this);
entity_list.SendTraders(this);
SendWearChangeAndLighting(EQ::textures::LastTexture);
Mob* pet = GetPet();
if (pet) {
@@ -3759,116 +3758,104 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app)
}
char* Buf = (char *)app->pBuffer;
auto in = (BuyerGeneric_Struct *)app->pBuffer;
// The first 4 bytes of the packet determine the action. A lot of Barter packets require the
// packet the client sent, sent back to it as an acknowledgement.
//
uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buf);
//uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buf);
switch (Action)
{
switch (in->action) {
case Barter_BuyerSearch:
{
BuyerItemSearch(app);
break;
}
case Barter_SellerSearch:
{
BarterSearchRequest_Struct *bsr = (BarterSearchRequest_Struct*)app->pBuffer;
SendBuyerResults(bsr->SearchString, bsr->SearchID);
break;
}
case Barter_BuyerModeOn:
{
if (!IsTrader()) {
ToggleBuyerMode(true);
case Barter_BuyerSearch: {
BuyerItemSearch(app);
break;
}
else {
Buf = (char *)app->pBuffer;
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerModeOff);
Message(Chat::Red, "You cannot be a Trader and Buyer at the same time.");
case Barter_SellerSearch: {
auto bsr = (BarterSearchRequest_Struct *) app->pBuffer;
SendBuyerResults(*bsr);
break;
}
QueuePacket(app);
break;
}
case Barter_BuyerModeOff:
{
QueuePacket(app);
ToggleBuyerMode(false);
break;
}
case Barter_BuyerModeOn: {
if (!IsTrader()) {
ToggleBuyerMode(true);
}
else {
ToggleBuyerMode(false);
Message(Chat::Red, "You cannot be a Trader and Buyer at the same time.");
}
break;
}
case Barter_BuyerItemUpdate:
{
UpdateBuyLine(app);
break;
}
case Barter_BuyerModeOff: {
ToggleBuyerMode(false);
break;
}
case Barter_BuyerItemRemove:
{
BuyerRemoveItem_Struct* bris = (BuyerRemoveItem_Struct*)app->pBuffer;
database.RemoveBuyLine(CharacterID(), bris->BuySlot);
QueuePacket(app);
break;
}
case Barter_BuyerItemUpdate: {
ModifyBuyLine(app);
break;
}
case Barter_SellItem:
{
SellToBuyer(app);
break;
}
case Barter_BuyerItemStart: {
CreateStartingBuyLines(app);
break;
}
case Barter_BuyerInspectBegin:
{
ShowBuyLines(app);
break;
}
case Barter_BuyerItemRemove: {
auto bris = (BuyerRemoveItem_Struct *) app->pBuffer;
BuyerBuyLinesRepository::DeleteBuyLine(database, CharacterID(), bris->buy_slot_id);
QueuePacket(app);
break;
}
case Barter_BuyerInspectEnd:
{
BuyerInspectRequest_Struct* bir = (BuyerInspectRequest_Struct*)app->pBuffer;
Client *Buyer = entity_list.GetClientByID(bir->BuyerID);
if (Buyer)
Buyer->WithCustomer(0);
case Barter_SellItem: {
SellToBuyer(app);
break;
}
break;
}
case Barter_BuyerInspectBegin: {
ShowBuyLines(app);
break;
}
case Barter_BarterItemInspect:
{
BarterItemSearchLinkRequest_Struct* bislr = (BarterItemSearchLinkRequest_Struct*)app->pBuffer;
case Barter_BuyerInspectEnd: {
auto bir = (BuyerInspectRequest_Struct *) app->pBuffer;
auto buyer = entity_list.GetClientByID(bir->buyer_id);
if (buyer) {
buyer->WithCustomer(0);
}
const EQ::ItemData* item = database.GetItem(bislr->ItemID);
break;
}
case Barter_BarterItemInspect: {
auto bislr = (BarterItemSearchLinkRequest_Struct *) app->pBuffer;
const EQ::ItemData *item = database.GetItem(bislr->item_id);
if (!item)
Message(Chat::Red, "Error: This item does not exist!");
else
{
EQ::ItemInstance* inst = database.CreateItem(item);
if (inst)
{
if (!item) {
Message(Chat::Red, "Error: This item does not exist!");
return;
}
EQ::ItemInstance *inst = database.CreateItem(item);
if (inst) {
SendItemPacket(0, inst, ItemPacketViewLink);
safe_delete(inst);
}
}
break;
}
case Barter_Welcome:
{
//SendBazaarWelcome();
SendBarterWelcome();
break;
}
case Barter_WelcomeMessageUpdate:
{
BuyerWelcomeMessageUpdate_Struct* bwmu = (BuyerWelcomeMessageUpdate_Struct*)app->pBuffer;
SetBuyerWelcomeMessage(bwmu->WelcomeMessage);
case Barter_WelcomeMessageUpdate: {
auto bwmu = (BuyerWelcomeMessageUpdate_Struct *) app->pBuffer;
SetBuyerWelcomeMessage(bwmu->welcome_message);
break;
}
@@ -3892,15 +3879,20 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app)
break;
}
case Barter_Unknown23:
case Barter_Greeting:
{
// Sent by SoD client for no discernible reason.
auto data = (BuyerGreeting_Struct *)app->pBuffer;
SendBuyerGreeting(data->buyer_id);
}
case Barter_OpenBarterWindow:
{
SendBulkBazaarBuyers();
break;
}
default:
Message(Chat::Red, "Unrecognised Barter action.");
LogTrading("Unrecognised Barter Action [{}]", Action);
LogTrading("Unrecognised Barter Action [{}]", in->action);
}
}
@@ -4982,6 +4974,10 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
TraderEndTrader();
}
if (IsBuyer()) {
ToggleBuyerMode(false);
}
/* Break Hide if moving without sneaking and set rewind timer if moved */
if ((hidden || improved_hidden) && !sneaking) {
hidden = false;
@@ -15640,7 +15636,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
break;
}
case TraderOn: {
if (Buyer) {
if (IsBuyer()) {
TraderEndTrader();
Message(Chat::Red, "You cannot be a Trader and Buyer at the same time.");
return;
@@ -15686,7 +15682,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
auto trader = entity_list.GetClientByID(in->trader_id);
switch (in->method) {
case ByVendor: {
case BazaarByVendor: {
if (trader) {
LogTrading("Buy item directly from vendor id <green>[{}] item_id <green>[{}] quantity <green>[{}] "
"serial_number <green>[{}]",
@@ -15699,7 +15695,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
}
break;
}
case ByParcel: {
case BazaarByParcel: {
if (!RuleB(Parcel, EnableParcelMerchants) || !RuleB(Bazaar, EnableParcelDelivery)) {
LogTrading(
"Bazaar purchase attempt by parcel delivery though 'Parcel:EnableParcelMerchants' or "
@@ -15709,7 +15705,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
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->method = BazaarByParcel;
in->sub_action = Failed;
TradeRequestFailed(app);
return;
@@ -15724,7 +15720,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
BuyTraderItemOutsideBazaar(in, app);
break;
}
case ByDirectToInventory: {
case BazaarByDirectToInventory: {
if (!RuleB(Parcel, EnableDirectToInventoryDelivery)) {
LogTrading("Bazaar purchase attempt by direct inventory delivery though "
"'Parcel:EnableDirectToInventoryDelivery' not enabled."
@@ -15733,7 +15729,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
Chat::Yellow,
"Direct inventory delivey is not enabled on this server. Please visit the vendor directly."
);
in->method = ByDirectToInventory;
in->method = BazaarByDirectToInventory;
in->sub_action = Failed;
TradeRequestFailed(app);
return;
@@ -15750,7 +15746,7 @@ void Client::Handle_OP_TraderBuy(const EQApplicationPacket *app)
Chat::Yellow,
"Direct inventory delivey is not yet implemented. Please visit the vendor directly or purchase via parcel delivery."
);
in->method = ByDirectToInventory;
in->method = BazaarByDirectToInventory;
in->sub_action = Failed;
TradeRequestFailed(app);
break;