mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-19 20:41:33 +00:00
[Merchants] Add Merchant Data Bucket capability. (#2160)
* [Merchants] Add Merchant Data Bucket capability.
- Allows server operators to limit merchant items based on data bucket values and comparisons.
- Adds 3 columns, bucket_name, bucket_value, and bucket_comparison to merchantlist table.
- Bucket is checked based on GetBucketKey()-bucket_name.
- Buckets are mass loaded when using the merchant so it's not a database call per item, just a grouping of all their buckets from the start.
- This is a nearly year old pull request redone for master.
- bucket_comparison Values are as follows:
- bucket_comparison 0: bucket_name == bucket_value
- bucket_comparison 1: bucket_name != bucket_value
- bucket_comparison 2: bucket_name >= bucket_value
- bucket_comparison 3: bucket_name <= bucket_value
- bucket_comparison 4: bucket_name > bucket_value
- bucket_comparison 5: bucket_name < bucket_value
- bucket_comparison 6: bucket_name is any of pipe(|)-separated bucket_value
- bucket_comparison 7: bucket_name is not any of pipe(|)-separated bucket_value
- bucket_comparison 8: bucket_name is between first and second value of pipe(|)-separated bucket_value
- bucket_comparison 9: bucket_name is not between first and second value of pipe(|)-separated bucket_value
* Revert query change.
This commit is contained in:
parent
6e0d101457
commit
763fc82379
@ -431,4 +431,17 @@ enum ReloadWorld : uint8 {
|
|||||||
ForceRepop
|
ForceRepop
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MerchantBucketComparison : uint8 {
|
||||||
|
BucketEqualTo = 0,
|
||||||
|
BucketNotEqualTo,
|
||||||
|
BucketGreaterThanOrEqualTo,
|
||||||
|
BucketLesserThanOrEqualTo,
|
||||||
|
BucketGreaterThan,
|
||||||
|
BucketLesserThan,
|
||||||
|
BucketIsAny,
|
||||||
|
BucketIsNotAny,
|
||||||
|
BucketIsBetween,
|
||||||
|
BucketIsNotBetween
|
||||||
|
};
|
||||||
|
|
||||||
#endif /*COMMON_EMU_CONSTANTS_H*/
|
#endif /*COMMON_EMU_CONSTANTS_H*/
|
||||||
|
|||||||
@ -3621,14 +3621,17 @@ struct LevelAppearance_Struct { //Sends a little graphic on level up
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MerchantList {
|
struct MerchantList {
|
||||||
uint32 id;
|
uint32 id;
|
||||||
uint32 slot;
|
uint32 slot;
|
||||||
uint32 item;
|
uint32 item;
|
||||||
int16 faction_required;
|
int16 faction_required;
|
||||||
int8 level_required;
|
int8 level_required;
|
||||||
uint16 alt_currency_cost;
|
uint16 alt_currency_cost;
|
||||||
uint32 classes_required;
|
uint32 classes_required;
|
||||||
uint8 probability;
|
uint8 probability;
|
||||||
|
std::string bucket_name;
|
||||||
|
std::string bucket_value;
|
||||||
|
uint8 bucket_comparison;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TempMerchantList {
|
struct TempMerchantList {
|
||||||
|
|||||||
@ -34,7 +34,7 @@
|
|||||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9182
|
#define CURRENT_BINARY_DATABASE_VERSION 9183
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9028
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9028
|
||||||
|
|||||||
@ -436,6 +436,7 @@
|
|||||||
9180|2022_05_01_character_peqzone_flags.sql|SHOW TABLES LIKE 'character_peqzone_flags'|empty|
|
9180|2022_05_01_character_peqzone_flags.sql|SHOW TABLES LIKE 'character_peqzone_flags'|empty|
|
||||||
9181|2022_05_03_task_activity_goal_match_list.sql|SHOW COLUMNS FROM `task_activities` LIKE 'goal_match_list'|empty|
|
9181|2022_05_03_task_activity_goal_match_list.sql|SHOW COLUMNS FROM `task_activities` LIKE 'goal_match_list'|empty|
|
||||||
9182|2022_05_02_npc_types_int64.sql|SHOW COLUMNS FROM `npc_types` LIKE 'hp'|missing|bigint
|
9182|2022_05_02_npc_types_int64.sql|SHOW COLUMNS FROM `npc_types` LIKE 'hp'|missing|bigint
|
||||||
|
9183|2022_05_07_merchant_data_buckets.sql|SHOW COLUMNS FROM `merchantlist` LIKE 'bucket_comparison'|empty
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE `merchantlist`
|
||||||
|
ADD COLUMN `bucket_name` varchar(100) NOT NULL DEFAULT '' AFTER `probability`,
|
||||||
|
ADD COLUMN `bucket_value` varchar(100) NOT NULL DEFAULT '' AFTER `bucket_name`,
|
||||||
|
ADD COLUMN `bucket_comparison` tinyint UNSIGNED NULL DEFAULT 0 AFTER `bucket_value`;
|
||||||
164
zone/client.cpp
164
zone/client.cpp
@ -11048,3 +11048,167 @@ void Client::ReconnectUCS()
|
|||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Client::CheckMerchantDataBucket(uint8 bucket_comparison, std::string bucket_value, std::string player_value)
|
||||||
|
{
|
||||||
|
std::vector<std::string> bucket_checks;
|
||||||
|
bool found = false;
|
||||||
|
bool passes = false;
|
||||||
|
|
||||||
|
switch (bucket_comparison) {
|
||||||
|
case MerchantBucketComparison::BucketEqualTo:
|
||||||
|
{
|
||||||
|
if (player_value != bucket_value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketNotEqualTo:
|
||||||
|
{
|
||||||
|
if (player_value == bucket_value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketGreaterThanOrEqualTo:
|
||||||
|
{
|
||||||
|
if (player_value < bucket_value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketLesserThanOrEqualTo:
|
||||||
|
{
|
||||||
|
if (player_value > bucket_value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketGreaterThan:
|
||||||
|
{
|
||||||
|
if (player_value <= bucket_value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketLesserThan:
|
||||||
|
{
|
||||||
|
if (player_value >= bucket_value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketIsAny:
|
||||||
|
{
|
||||||
|
bucket_checks = split_string(bucket_value, "|");
|
||||||
|
if (bucket_checks.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &bucket : bucket_checks) {
|
||||||
|
if (player_value == bucket) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketIsNotAny:
|
||||||
|
{
|
||||||
|
bucket_checks = split_string(bucket_value, "|");
|
||||||
|
if (bucket_checks.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &bucket : bucket_checks) {
|
||||||
|
if (player_value == bucket) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketIsBetween:
|
||||||
|
{
|
||||||
|
bucket_checks = split_string(bucket_value, "|");
|
||||||
|
if (bucket_checks.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
std::stoll(player_value) < std::stoll(bucket_checks[0]) ||
|
||||||
|
std::stoll(player_value) > std::stoll(bucket_checks[1])
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MerchantBucketComparison::BucketIsNotBetween:
|
||||||
|
{
|
||||||
|
bucket_checks = split_string(bucket_value, "|");
|
||||||
|
if (bucket_checks.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
std::stoll(player_value) >= std::stoll(bucket_checks[0]) &&
|
||||||
|
std::stoll(player_value) <= std::stoll(bucket_checks[1])
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return passes;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string,std::string> Client::GetMerchantDataBuckets()
|
||||||
|
{
|
||||||
|
std::map<std::string,std::string> merchant_data_buckets;
|
||||||
|
|
||||||
|
auto query = fmt::format(
|
||||||
|
"SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'",
|
||||||
|
EscapeString(GetBucketKey())
|
||||||
|
);
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
|
||||||
|
if (!results.Success() || !results.RowCount()) {
|
||||||
|
return merchant_data_buckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto row : results) {
|
||||||
|
merchant_data_buckets.insert(std::pair<std::string,std::string>(row[0], row[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return merchant_data_buckets;
|
||||||
|
}
|
||||||
|
|||||||
@ -1652,6 +1652,9 @@ public:
|
|||||||
// rate limit
|
// rate limit
|
||||||
Timer m_list_task_timers_rate_limit = {};
|
Timer m_list_task_timers_rate_limit = {};
|
||||||
|
|
||||||
|
std::map<std::string,std::string> GetMerchantDataBuckets();
|
||||||
|
bool CheckMerchantDataBucket(uint8 bucket_comparison, std::string bucket_value, std::string player_value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Mob;
|
friend class Mob;
|
||||||
void CalcItemBonuses(StatBonuses* newbon);
|
void CalcItemBonuses(StatBonuses* newbon);
|
||||||
|
|||||||
@ -813,152 +813,168 @@ void Client::BulkSendInventoryItems()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
|
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
|
||||||
const EQ::ItemData* handyitem = nullptr;
|
const EQ::ItemData* handy_item = nullptr;
|
||||||
uint32 numItemSlots = 80; //The max number of items passed in the transaction.
|
|
||||||
|
uint32 merchant_slots = 80; //The max number of items passed in the transaction.
|
||||||
if (m_ClientVersionBit & EQ::versions::maskRoFAndLater) { // RoF+ can send 200 items
|
if (m_ClientVersionBit & EQ::versions::maskRoFAndLater) { // RoF+ can send 200 items
|
||||||
numItemSlots = 200;
|
merchant_slots = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EQ::ItemData *item = nullptr;
|
const EQ::ItemData *item = nullptr;
|
||||||
std::list<MerchantList> merlist = zone->merchanttable[merchant_id];
|
auto merchant_list = zone->merchanttable[merchant_id];
|
||||||
std::list<MerchantList>::const_iterator itr;
|
auto npc = entity_list.GetMobByNpcTypeID(npcid);
|
||||||
Mob* merch = entity_list.GetMobByNpcTypeID(npcid);
|
if (!merchant_list.size() == 0) {
|
||||||
if (merlist.size() == 0) { //Attempt to load the data, it might have been missed if someone spawned the merchant after the zone was loaded
|
|
||||||
zone->LoadNewMerchantData(merchant_id);
|
zone->LoadNewMerchantData(merchant_id);
|
||||||
merlist = zone->merchanttable[merchant_id];
|
merchant_list = zone->merchanttable[merchant_id];
|
||||||
if (merlist.size() == 0)
|
if (!merchant_list.size()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::list<TempMerchantList> tmp_merlist = zone->tmpmerchanttable[npcid];
|
|
||||||
std::list<TempMerchantList>::iterator tmp_itr;
|
|
||||||
|
|
||||||
uint32 i = 1;
|
auto client_data_buckets = GetMerchantDataBuckets();
|
||||||
uint8 handychance = 0;
|
|
||||||
for (itr = merlist.begin(); itr != merlist.end() && i <= numItemSlots; ++itr) {
|
|
||||||
MerchantList ml = *itr;
|
|
||||||
if (ml.probability != 100 && zone->random.Int(1, 100) > ml.probability)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (GetLevel() < ml.level_required)
|
auto temporary_merchant_list = zone->tmpmerchanttable[npcid];
|
||||||
continue;
|
uint32 slot_id = 1;
|
||||||
|
uint8 handy_chance = 0;
|
||||||
if (!(ml.classes_required & (1 << (GetClass() - 1))))
|
for (auto ml : merchant_list) {
|
||||||
continue;
|
if (slot_id > merchant_slots) {
|
||||||
|
break;
|
||||||
int32 fac = merch ? merch->GetPrimaryFaction() : 0;
|
|
||||||
int32 cur_fac_level;
|
|
||||||
if (fac == 0 || sneaking) {
|
|
||||||
cur_fac_level = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cur_fac_level = GetModCharacterFactionLevel(fac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_fac_level < ml.faction_required)
|
auto bucket_name = ml.bucket_name;
|
||||||
continue;
|
auto bucket_value = ml.bucket_value;
|
||||||
|
if (!bucket_name.empty() && !bucket_value.empty()) {
|
||||||
|
auto full_name = fmt::format(
|
||||||
|
"{}-{}",
|
||||||
|
GetBucketKey(),
|
||||||
|
bucket_name
|
||||||
|
);
|
||||||
|
|
||||||
handychance = zone->random.Int(0, merlist.size() + tmp_merlist.size() - 1);
|
auto player_value = client_data_buckets[full_name];
|
||||||
|
if (player_value.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CheckMerchantDataBucket(ml.bucket_comparison, bucket_value, player_value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ml.probability != 100 && zone->random.Int(1, 100) > ml.probability) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetLevel() < ml.level_required) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ml.classes_required & (1 << (GetClass() - 1)))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32 faction_id = npc ? npc->GetPrimaryFaction() : 0;
|
||||||
|
int32 faction_level = (
|
||||||
|
(!faction_id || sneaking) ?
|
||||||
|
0 :
|
||||||
|
GetModCharacterFactionLevel(faction_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (faction_level < ml.faction_required) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
handy_chance = zone->random.Int(0, merchant_list.size() + temporary_merchant_list.size() - 1);
|
||||||
|
|
||||||
item = database.GetItem(ml.item);
|
item = database.GetItem(ml.item);
|
||||||
if (item) {
|
if (item) {
|
||||||
if (handychance == 0)
|
if (!handy_chance) {
|
||||||
handyitem = item;
|
handy_item = item;
|
||||||
else
|
} else {
|
||||||
handychance--;
|
handy_chance--;
|
||||||
int charges = 1;
|
}
|
||||||
if (item->IsClassCommon())
|
|
||||||
charges = item->MaxCharges;
|
int16 charges = item->IsClassCommon() ? item->MaxCharges : 1;
|
||||||
EQ::ItemInstance* inst = database.CreateItem(item, charges);
|
|
||||||
|
auto inst = database.CreateItem(item, charges);
|
||||||
if (inst) {
|
if (inst) {
|
||||||
|
auto item_price = static_cast<uint32>(item->Price * RuleR(Merchant, SellCostMod) * item->SellRate);
|
||||||
|
auto item_charges = charges ? charges : 1;
|
||||||
|
|
||||||
if (RuleB(Merchant, UsePriceMod)) {
|
if (RuleB(Merchant, UsePriceMod)) {
|
||||||
inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false)));
|
item_price *= Client::CalcPriceMod(npc);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate));
|
inst->SetCharges(item_charges);
|
||||||
|
inst->SetMerchantCount(-1);
|
||||||
inst->SetMerchantSlot(ml.slot);
|
inst->SetMerchantSlot(ml.slot);
|
||||||
inst->SetMerchantCount(-1); //unlimited
|
inst->SetPrice(item_price);
|
||||||
if (charges > 0)
|
|
||||||
inst->SetCharges(charges);
|
|
||||||
else
|
|
||||||
inst->SetCharges(1);
|
|
||||||
|
|
||||||
SendItemPacket(ml.slot - 1, inst, ItemPacketMerchant);
|
SendItemPacket(ml.slot - 1, inst, ItemPacketMerchant);
|
||||||
safe_delete(inst);
|
safe_delete(inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account for merchant lists with gaps.
|
// Account for merchant lists with gaps.
|
||||||
if (ml.slot >= i) {
|
if (ml.slot >= slot_id) {
|
||||||
if (ml.slot > i)
|
if (ml.slot > slot_id) {
|
||||||
LogDebug("(WARNING) Merchantlist contains gap at slot [{}]. Merchant: [{}], NPC: [{}]", i, merchant_id, npcid);
|
LogDebug("(WARNING) Merchantlist contains gap at slot [{}]. Merchant: [{}], NPC: [{}]", slot_id, merchant_id, npcid);
|
||||||
i = ml.slot + 1;
|
}
|
||||||
|
|
||||||
|
slot_id = ml.slot + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::list<TempMerchantList> origtmp_merlist = zone->tmpmerchanttable[npcid];
|
|
||||||
tmp_merlist.clear();
|
auto temporary_merchant_list_two = zone->tmpmerchanttable[npcid];
|
||||||
for (tmp_itr = origtmp_merlist.begin(); tmp_itr != origtmp_merlist.end() && i <= numItemSlots; ++tmp_itr) {
|
temporary_merchant_list.clear();
|
||||||
TempMerchantList ml = *tmp_itr;
|
for (auto ml : temporary_merchant_list_two) {
|
||||||
|
if (slot_id > merchant_slots) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
item = database.GetItem(ml.item);
|
item = database.GetItem(ml.item);
|
||||||
ml.slot = i;
|
ml.slot = slot_id;
|
||||||
if (item) {
|
if (item) {
|
||||||
if (handychance == 0)
|
if (!handy_chance) {
|
||||||
handyitem = item;
|
handy_item = item;
|
||||||
else
|
} else {
|
||||||
handychance--;
|
handy_chance--;
|
||||||
int charges = 1;
|
}
|
||||||
//if(item->ItemClass==ItemClassCommon && (int16)ml.charges <= item->MaxCharges)
|
|
||||||
// charges=ml.charges;
|
auto charges = item->MaxCharges;
|
||||||
//else
|
auto inst = database.CreateItem(item, charges);
|
||||||
charges = item->MaxCharges;
|
|
||||||
EQ::ItemInstance* inst = database.CreateItem(item, charges);
|
|
||||||
if (inst) {
|
if (inst) {
|
||||||
|
auto item_price = static_cast<uint32>(item->Price * RuleR(Merchant, SellCostMod) * item->SellRate);
|
||||||
|
auto item_charges = charges ? charges : 1;
|
||||||
|
|
||||||
if (RuleB(Merchant, UsePriceMod)) {
|
if (RuleB(Merchant, UsePriceMod)) {
|
||||||
inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false)));
|
item_price *= Client::CalcPriceMod(npc);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate));
|
inst->SetCharges(item_charges);
|
||||||
inst->SetMerchantSlot(ml.slot);
|
|
||||||
inst->SetMerchantCount(ml.charges);
|
inst->SetMerchantCount(ml.charges);
|
||||||
if(charges > 0)
|
inst->SetMerchantSlot(ml.slot);
|
||||||
inst->SetCharges(item->MaxCharges);//inst->SetCharges(charges);
|
inst->SetPrice(item_price);
|
||||||
else
|
|
||||||
inst->SetCharges(1);
|
SendItemPacket(ml.slot - 1, inst, ItemPacketMerchant);
|
||||||
SendItemPacket(ml.slot-1, inst, ItemPacketMerchant);
|
|
||||||
safe_delete(inst);
|
safe_delete(inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmp_merlist.push_back(ml);
|
temporary_merchant_list.push_back(ml);
|
||||||
i++;
|
slot_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//this resets the slot
|
//this resets the slot
|
||||||
zone->tmpmerchanttable[npcid] = tmp_merlist;
|
zone->tmpmerchanttable[npcid] = temporary_merchant_list;
|
||||||
if (merch != nullptr && handyitem) {
|
if (npc && handy_item) {
|
||||||
char handy_id[8] = { 0 };
|
int greet_id = zone->random.Int(MERCHANT_GREETING, MERCHANT_HANDY_ITEM4);
|
||||||
int greeting = zone->random.Int(0, 4);
|
auto handy_id = std::to_string(greet_id);
|
||||||
int greet_id = 0;
|
if (greet_id != MERCHANT_GREETING) {
|
||||||
switch (greeting) {
|
MessageString(Chat::NPCQuestSay, GENERIC_STRINGID_SAY, npc->GetCleanName(), handy_id.c_str(), GetName(), handy_item->Name);
|
||||||
case 1:
|
} else {
|
||||||
greet_id = MERCHANT_GREETING;
|
MessageString(Chat::NPCQuestSay, GENERIC_STRINGID_SAY, npc->GetCleanName(), handy_id.c_str(), GetName());
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
greet_id = MERCHANT_HANDY_ITEM1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
greet_id = MERCHANT_HANDY_ITEM2;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
greet_id = MERCHANT_HANDY_ITEM3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
greet_id = MERCHANT_HANDY_ITEM4;
|
|
||||||
}
|
}
|
||||||
sprintf(handy_id, "%i", greet_id);
|
|
||||||
|
|
||||||
if (greet_id != MERCHANT_GREETING)
|
|
||||||
MessageString(Chat::NPCQuestSay, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, GetName(), handyitem->Name);
|
|
||||||
else
|
|
||||||
MessageString(Chat::NPCQuestSay, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, GetName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// safe_delete_array(cpi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 Client::WithCustomer(uint16 NewCustomer){
|
uint8 Client::WithCustomer(uint16 NewCustomer){
|
||||||
|
|||||||
112
zone/zone.cpp
112
zone/zone.cpp
@ -605,26 +605,25 @@ void Zone::LoadTempMerchantData()
|
|||||||
|
|
||||||
void Zone::LoadNewMerchantData(uint32 merchantid) {
|
void Zone::LoadNewMerchantData(uint32 merchantid) {
|
||||||
|
|
||||||
std::list<MerchantList> merlist;
|
std::list<MerchantList> merchant_list;
|
||||||
|
|
||||||
std::string query = fmt::format(
|
auto query = fmt::format(
|
||||||
SQL(
|
SQL(
|
||||||
SELECT
|
SELECT
|
||||||
item,
|
item,
|
||||||
slot,
|
slot,
|
||||||
faction_required,
|
faction_required,
|
||||||
level_required,
|
level_required,
|
||||||
alt_currency_cost,
|
alt_currency_cost,
|
||||||
classes_required,
|
classes_required,
|
||||||
probability
|
probability,
|
||||||
FROM
|
bucket_name,
|
||||||
merchantlist
|
bucket_value,
|
||||||
WHERE
|
bucket_comparison
|
||||||
merchantid = {}
|
FROM merchantlist
|
||||||
{}
|
WHERE merchantid = {} {}
|
||||||
ORDER BY
|
ORDER BY slot
|
||||||
slot
|
),
|
||||||
),
|
|
||||||
merchantid,
|
merchantid,
|
||||||
ContentFilterCriteria::apply()
|
ContentFilterCriteria::apply()
|
||||||
);
|
);
|
||||||
@ -634,25 +633,28 @@ void Zone::LoadNewMerchantData(uint32 merchantid) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row : results) {
|
||||||
MerchantList ml;
|
MerchantList ml;
|
||||||
ml.id = merchantid;
|
ml.id = merchantid;
|
||||||
ml.item = atoul(row[0]);
|
ml.item = std::stoul(row[0]);
|
||||||
ml.slot = atoul(row[1]);
|
ml.slot = std::stoul(row[1]);
|
||||||
ml.faction_required = atoul(row[2]);
|
ml.faction_required = static_cast<int16>(std::stoi(row[2]));
|
||||||
ml.level_required = atoul(row[3]);
|
ml.level_required = static_cast<uint8>(std::stoul(row[3]));
|
||||||
ml.alt_currency_cost = atoul(row[4]);
|
ml.alt_currency_cost = static_cast<uint16>(std::stoul(row[4]));
|
||||||
ml.classes_required = atoul(row[5]);
|
ml.classes_required = std::stoul(row[5]);
|
||||||
ml.probability = atoul(row[6]);
|
ml.probability = static_cast<uint8>(std::stoul(row[6]));
|
||||||
merlist.push_back(ml);
|
ml.bucket_name = row[7];
|
||||||
|
ml.bucket_value = row[8];
|
||||||
|
ml.bucket_comparison = static_cast<uint8>(std::stoul(row[9]));
|
||||||
|
merchant_list.push_back(ml);
|
||||||
}
|
}
|
||||||
|
|
||||||
merchanttable[merchantid] = merlist;
|
merchanttable[merchantid] = merchant_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::GetMerchantDataForZoneLoad() {
|
void Zone::GetMerchantDataForZoneLoad() {
|
||||||
LogInfo("Loading Merchant Lists");
|
LogInfo("Loading Merchant Lists");
|
||||||
std::string query = fmt::format(
|
auto query = fmt::format(
|
||||||
SQL (
|
SQL (
|
||||||
SELECT
|
SELECT
|
||||||
DISTINCT merchantlist.merchantid,
|
DISTINCT merchantlist.merchantid,
|
||||||
@ -662,7 +664,10 @@ void Zone::GetMerchantDataForZoneLoad() {
|
|||||||
merchantlist.level_required,
|
merchantlist.level_required,
|
||||||
merchantlist.alt_currency_cost,
|
merchantlist.alt_currency_cost,
|
||||||
merchantlist.classes_required,
|
merchantlist.classes_required,
|
||||||
merchantlist.probability
|
merchantlist.probability,
|
||||||
|
merchantlist.bucket_name,
|
||||||
|
merchantlist.bucket_value,
|
||||||
|
merchantlist.bucket_comparison
|
||||||
FROM
|
FROM
|
||||||
merchantlist,
|
merchantlist,
|
||||||
npc_types,
|
npc_types,
|
||||||
@ -688,49 +693,50 @@ void Zone::GetMerchantDataForZoneLoad() {
|
|||||||
std::map<uint32, std::list<MerchantList> >::iterator merchant_list;
|
std::map<uint32, std::list<MerchantList> >::iterator merchant_list;
|
||||||
|
|
||||||
uint32 npc_id = 0;
|
uint32 npc_id = 0;
|
||||||
if (results.RowCount() == 0) {
|
if (!results.Success() || !results.RowCount()) {
|
||||||
LogDebug("No Merchant Data found for [{}]", GetShortName());
|
LogDebug("No Merchant Data found for [{}]", GetShortName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
|
||||||
MerchantList merchant_list_entry{};
|
for (auto row : results) {
|
||||||
merchant_list_entry.id = atoul(row[0]);
|
MerchantList mle{};
|
||||||
if (npc_id != merchant_list_entry.id) {
|
mle.id = atoul(row[0]);
|
||||||
merchant_list = merchanttable.find(merchant_list_entry.id);
|
if (npc_id != mle.id) {
|
||||||
|
merchant_list = merchanttable.find(mle.id);
|
||||||
if (merchant_list == merchanttable.end()) {
|
if (merchant_list == merchanttable.end()) {
|
||||||
std::list<MerchantList> empty;
|
std::list<MerchantList> empty;
|
||||||
merchanttable[merchant_list_entry.id] = empty;
|
merchanttable[mle.id] = empty;
|
||||||
merchant_list = merchanttable.find(merchant_list_entry.id);
|
merchant_list = merchanttable.find(mle.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
npc_id = merchant_list_entry.id;
|
npc_id = mle.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto iter = merchant_list->second.begin();
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
while (iter != merchant_list->second.end()) {
|
for (const auto &m : merchant_list->second) {
|
||||||
if ((*iter).item == merchant_list_entry.id) {
|
if (m.item == mle.id) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mle.slot = std::stoul(row[0]);
|
||||||
|
mle.item = std::stoul(row[1]);
|
||||||
|
mle.faction_required = static_cast<int16>(std::stoi(row[2]));
|
||||||
|
mle.level_required = static_cast<uint8>(std::stoul(row[3]));
|
||||||
|
mle.alt_currency_cost = static_cast<uint16>(std::stoul(row[4]));
|
||||||
|
mle.classes_required = std::stoul(row[5]);
|
||||||
|
mle.probability = static_cast<uint8>(std::stoul(row[6]));
|
||||||
|
mle.bucket_name = row[7];
|
||||||
|
mle.bucket_value = row[8];
|
||||||
|
mle.bucket_comparison = static_cast<uint8>(std::stoul(row[9]));
|
||||||
|
|
||||||
merchant_list_entry.slot = atoul(row[1]);
|
merchant_list->second.push_back(mle);
|
||||||
merchant_list_entry.item = atoul(row[2]);
|
|
||||||
merchant_list_entry.faction_required = atoul(row[3]);
|
|
||||||
merchant_list_entry.level_required = atoul(row[4]);
|
|
||||||
merchant_list_entry.alt_currency_cost = atoul(row[5]);
|
|
||||||
merchant_list_entry.classes_required = atoul(row[6]);
|
|
||||||
merchant_list_entry.probability = atoul(row[7]);
|
|
||||||
|
|
||||||
merchant_list->second.push_back(merchant_list_entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::LoadMercTemplates(){
|
void Zone::LoadMercTemplates(){
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user