Establish default order for merchantlist items.

Allow merchants to use 80th slot.
This commit is contained in:
JJ 2014-10-09 23:11:18 -04:00
parent c328829610
commit ea4c23efcf
2 changed files with 77 additions and 70 deletions

View File

@ -967,93 +967,96 @@ void Client::BulkSendInventoryItems()
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
const Item_Struct* handyitem = nullptr; const Item_Struct* handyitem = nullptr;
uint32 numItemSlots=80; //The max number of items passed in the transaction. uint32 numItemSlots = 80; //The max number of items passed in the transaction.
const Item_Struct *item; const Item_Struct *item;
std::list<MerchantList> merlist = zone->merchanttable[merchant_id]; std::list<MerchantList> merlist = zone->merchanttable[merchant_id];
std::list<MerchantList>::const_iterator itr; std::list<MerchantList>::const_iterator itr;
Mob* merch = entity_list.GetMobByNpcTypeID(npcid); Mob* merch = entity_list.GetMobByNpcTypeID(npcid);
if(merlist.size()==0){ //Attempt to load the data, it might have been missed if someone spawned the merchant after the zone was loaded 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]; merlist = zone->merchanttable[merchant_id];
if(merlist.size()==0) if (merlist.size() == 0)
return; return;
} }
std::list<TempMerchantList> tmp_merlist = zone->tmpmerchanttable[npcid]; std::list<TempMerchantList> tmp_merlist = zone->tmpmerchanttable[npcid];
std::list<TempMerchantList>::iterator tmp_itr; std::list<TempMerchantList>::iterator tmp_itr;
uint32 i=1; uint32 i = 1;
uint8 handychance = 0; uint8 handychance = 0;
for (itr = merlist.begin(); itr != merlist.end() && i < numItemSlots; ++itr) { for (itr = merlist.begin(); itr != merlist.end() && i <= numItemSlots; ++itr) {
MerchantList ml = *itr; MerchantList ml = *itr;
if (merch->CastToNPC()->GetMerchantProbability() > ml.probability) if (merch->CastToNPC()->GetMerchantProbability() > ml.probability)
continue; continue;
if(GetLevel() < ml.level_required) if (GetLevel() < ml.level_required)
continue; continue;
if (!(ml.classes_required & (1 << (GetClass() - 1)))) if (!(ml.classes_required & (1 << (GetClass() - 1))))
continue; continue;
int32 fac = merch ? merch->GetPrimaryFaction() : 0; int32 fac = merch ? merch->GetPrimaryFaction() : 0;
if(fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required) if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required)
continue; continue;
handychance = MakeRandomInt(0, merlist.size() + tmp_merlist.size() - 1 ); handychance = MakeRandomInt(0, merlist.size() + tmp_merlist.size() - 1);
item = database.GetItem(ml.item); item = database.GetItem(ml.item);
if(item) { if (item) {
if(handychance==0) if (handychance == 0)
handyitem=item; handyitem = item;
else else
handychance--; handychance--;
int charges=1; int charges = 1;
if(item->ItemClass==ItemClassCommon) if (item->ItemClass == ItemClassCommon)
charges=item->MaxCharges; charges = item->MaxCharges;
ItemInst* inst = database.CreateItem(item, charges); ItemInst* inst = database.CreateItem(item, charges);
if (inst) { if (inst) {
if (RuleB(Merchant, UsePriceMod)){ if (RuleB(Merchant, UsePriceMod)) {
inst->SetPrice((item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate*Client::CalcPriceMod(merch,false))); inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false)));
} }
else else
inst->SetPrice((item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate)); inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate));
inst->SetMerchantSlot(ml.slot); inst->SetMerchantSlot(ml.slot);
inst->SetMerchantCount(-1); //unlimited inst->SetMerchantCount(-1); //unlimited
if(charges > 0) if (charges > 0)
inst->SetCharges(charges); inst->SetCharges(charges);
else else
inst->SetCharges(1); 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 >= i) {
if (ml.slot > i)
LogFile->write(EQEMuLog::Debug, "(WARNING) Merchantlist contains gap at slot %d. Merchant: %d, NPC: %d", i, merchant_id, npcid);
i = ml.slot + 1; i = ml.slot + 1;
}
} }
std::list<TempMerchantList> origtmp_merlist = zone->tmpmerchanttable[npcid]; std::list<TempMerchantList> origtmp_merlist = zone->tmpmerchanttable[npcid];
tmp_merlist.clear(); tmp_merlist.clear();
for(tmp_itr = origtmp_merlist.begin();tmp_itr != origtmp_merlist.end() && i<numItemSlots;++tmp_itr){ for (tmp_itr = origtmp_merlist.begin(); tmp_itr != origtmp_merlist.end() && i <= numItemSlots; ++tmp_itr) {
TempMerchantList ml = *tmp_itr; TempMerchantList ml = *tmp_itr;
item=database.GetItem(ml.item); item = database.GetItem(ml.item);
ml.slot=i; ml.slot = i;
if (item) { if (item) {
if(handychance==0) if (handychance == 0)
handyitem=item; handyitem = item;
else else
handychance--; handychance--;
int charges=1; int charges = 1;
//if(item->ItemClass==ItemClassCommon && (int16)ml.charges <= item->MaxCharges) //if(item->ItemClass==ItemClassCommon && (int16)ml.charges <= item->MaxCharges)
// charges=ml.charges; // charges=ml.charges;
//else //else
charges = item->MaxCharges; charges = item->MaxCharges;
ItemInst* inst = database.CreateItem(item, charges); ItemInst* inst = database.CreateItem(item, charges);
if (inst) { if (inst) {
if (RuleB(Merchant, UsePriceMod)){ if (RuleB(Merchant, UsePriceMod)) {
inst->SetPrice((item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate*Client::CalcPriceMod(merch,false))); inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false)));
} }
else else
inst->SetPrice((item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate)); inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate));
inst->SetMerchantSlot(ml.slot); inst->SetMerchantSlot(ml.slot);
inst->SetMerchantCount(ml.charges); inst->SetMerchantCount(ml.charges);
if(charges > 0) if(charges > 0)
@ -1069,32 +1072,32 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
} }
//this resets the slot //this resets the slot
zone->tmpmerchanttable[npcid] = tmp_merlist; zone->tmpmerchanttable[npcid] = tmp_merlist;
if(merch != nullptr && handyitem){ if (merch != nullptr && handyitem) {
char handy_id[8]={0}; char handy_id[8] = { 0 };
int greeting=MakeRandomInt(0, 4); int greeting = MakeRandomInt(0, 4);
int greet_id=0; int greet_id = 0;
switch(greeting){ switch (greeting) {
case 1: case 1:
greet_id=MERCHANT_GREETING; greet_id = MERCHANT_GREETING;
break; break;
case 2: case 2:
greet_id=MERCHANT_HANDY_ITEM1; greet_id = MERCHANT_HANDY_ITEM1;
break; break;
case 3: case 3:
greet_id=MERCHANT_HANDY_ITEM2; greet_id = MERCHANT_HANDY_ITEM2;
break; break;
case 4: case 4:
greet_id=MERCHANT_HANDY_ITEM3; greet_id = MERCHANT_HANDY_ITEM3;
break; break;
default: default:
greet_id=MERCHANT_HANDY_ITEM4; greet_id = MERCHANT_HANDY_ITEM4;
} }
sprintf(handy_id,"%i",greet_id); sprintf(handy_id, "%i", greet_id);
if(greet_id!=MERCHANT_GREETING) if (greet_id != MERCHANT_GREETING)
Message_StringID(10,GENERIC_STRINGID_SAY,merch->GetCleanName(),handy_id,this->GetName(),handyitem->Name); Message_StringID(10, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName(), handyitem->Name);
else else
Message_StringID(10,GENERIC_STRINGID_SAY,merch->GetCleanName(),handy_id,this->GetName()); Message_StringID(10, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName());
merch->CastToNPC()->FaceTarget(this->CastToMob()); merch->CastToNPC()->FaceTarget(this->CastToMob());
} }

View File

@ -307,41 +307,40 @@ bool Zone::LoadGroundSpawns() {
return(true); return(true);
} }
int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold){ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold) {
int freeslot = 0; int freeslot = 0;
std::list<MerchantList> merlist = merchanttable[merchantid]; std::list<MerchantList> merlist = merchanttable[merchantid];
std::list<MerchantList>::const_iterator itr; std::list<MerchantList>::const_iterator itr;
uint32 i = 1; uint32 i = 1;
for (itr = merlist.begin(); itr != merlist.end(); ++itr) { for (itr = merlist.begin(); itr != merlist.end(); ++itr) {
MerchantList ml = *itr; MerchantList ml = *itr;
if(ml.item == item) if (ml.item == item)
return 0; return 0;
// Account for merchant lists with gaps in them. // Account for merchant lists with gaps in them.
if(ml.slot >= i) if (ml.slot >= i)
i = ml.slot + 1; i = ml.slot + 1;
} }
std::list<TempMerchantList> tmp_merlist = tmpmerchanttable[npcid]; std::list<TempMerchantList> tmp_merlist = tmpmerchanttable[npcid];
std::list<TempMerchantList>::const_iterator tmp_itr; std::list<TempMerchantList>::const_iterator tmp_itr;
bool update_charges = false; bool update_charges = false;
TempMerchantList ml; TempMerchantList ml;
while(freeslot == 0 && !update_charges){ while (freeslot == 0 && !update_charges) {
freeslot = i; freeslot = i;
for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) { for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) {
ml = *tmp_itr; ml = *tmp_itr;
if(ml.item == item){ if (ml.item == item) {
update_charges = true; update_charges = true;
freeslot = 0; freeslot = 0;
break; break;
} }
if((ml.slot == i) || (ml.origslot==i)) { if ((ml.slot == i) || (ml.origslot == i)) {
freeslot=0; freeslot = 0;
} }
} }
i++; i++;
} }
if(update_charges){ if (update_charges) {
tmp_merlist.clear(); tmp_merlist.clear();
std::list<TempMerchantList> oldtmp_merlist = tmpmerchanttable[npcid]; std::list<TempMerchantList> oldtmp_merlist = tmpmerchanttable[npcid];
for (tmp_itr = oldtmp_merlist.begin(); tmp_itr != oldtmp_merlist.end(); ++tmp_itr) { for (tmp_itr = oldtmp_merlist.begin(); tmp_itr != oldtmp_merlist.end(); ++tmp_itr) {
@ -349,27 +348,27 @@ int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charg
if(ml2.item != item) if(ml2.item != item)
tmp_merlist.push_back(ml2); tmp_merlist.push_back(ml2);
} }
if(sold) if (sold)
ml.charges = ml.charges + charges; ml.charges = ml.charges + charges;
else else
ml.charges = charges; ml.charges = charges;
if(!ml.origslot) if (!ml.origslot)
ml.origslot = ml.slot; ml.origslot = ml.slot;
if(charges>0){ if (charges > 0) {
database.SaveMerchantTemp(npcid, ml.origslot, item, ml.charges); database.SaveMerchantTemp(npcid, ml.origslot, item, ml.charges);
tmp_merlist.push_back(ml); tmp_merlist.push_back(ml);
} }
else{ else {
database.DeleteMerchantTemp(npcid,ml.origslot); database.DeleteMerchantTemp(npcid, ml.origslot);
} }
tmpmerchanttable[npcid] = tmp_merlist; tmpmerchanttable[npcid] = tmp_merlist;
if(sold) if (sold)
return ml.slot; return ml.slot;
} }
if(freeslot){ if (freeslot) {
if(charges<0) //sanity check only, shouldnt happen if (charges < 0) //sanity check only, shouldnt happen
charges = 0x7FFF; charges = 0x7FFF;
database.SaveMerchantTemp(npcid, freeslot, item, charges); database.SaveMerchantTemp(npcid, freeslot, item, charges);
tmp_merlist = tmpmerchanttable[npcid]; tmp_merlist = tmpmerchanttable[npcid];
@ -391,13 +390,13 @@ uint32 Zone::GetTempMerchantQuantity(uint32 NPCID, uint32 Slot) {
std::list<TempMerchantList>::const_iterator Iterator; std::list<TempMerchantList>::const_iterator Iterator;
for (Iterator = TmpMerchantList.begin(); Iterator != TmpMerchantList.end(); ++Iterator) for (Iterator = TmpMerchantList.begin(); Iterator != TmpMerchantList.end(); ++Iterator)
if((*Iterator).slot == Slot) if ((*Iterator).slot == Slot)
return (*Iterator).charges; return (*Iterator).charges;
return 0; return 0;
} }
void Zone::LoadTempMerchantData(){ void Zone::LoadTempMerchantData() {
LogFile->write(EQEMuLog::Status, "Loading Temporary Merchant Lists..."); LogFile->write(EQEMuLog::Status, "Loading Temporary Merchant Lists...");
std::string query = StringFormat( std::string query = StringFormat(
"SELECT " "SELECT "
@ -412,7 +411,8 @@ void Zone::LoadTempMerchantData(){
"WHERE " "WHERE "
"ml.npcid = se.npcid " "ml.npcid = se.npcid "
"AND se.spawngroupid = s2.spawngroupid " "AND se.spawngroupid = s2.spawngroupid "
"AND s2.zone = '%s' AND s2.version = %i", GetShortName(), GetInstanceVersion()); "AND s2.zone = '%s' AND s2.version = %i"
"ORDER BY ml.slot ", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadTempMerchantData query '%s' %s", query.c_str(), results.ErrorMessage().c_str()); LogFile->write(EQEMuLog::Error, "Error in LoadTempMerchantData query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
@ -441,11 +441,11 @@ void Zone::LoadTempMerchantData(){
pQueuedMerchantsWorkID = 0; pQueuedMerchantsWorkID = 0;
} }
void Zone::LoadNewMerchantData(uint32 merchantid){ void Zone::LoadNewMerchantData(uint32 merchantid) {
std::list<MerchantList> merlist; std::list<MerchantList> merlist;
std::string query = StringFormat("SELECT item, slot, faction_required, level_required, alt_currency_cost, " std::string query = StringFormat("SELECT item, slot, faction_required, level_required, alt_currency_cost, "
"classes_required FROM merchantlist WHERE merchantid=%d", merchantid); "classes_required FROM merchantlist WHERE merchantid=%d ORDER BY slot", merchantid);
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadNewMerchantData query '%s' %s", query.c_str(), results.ErrorMessage().c_str()); LogFile->write(EQEMuLog::Error, "Error in LoadNewMerchantData query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
@ -467,7 +467,7 @@ void Zone::LoadNewMerchantData(uint32 merchantid){
merchanttable[merchantid] = merlist; merchanttable[merchantid] = merlist;
} }
void Zone::GetMerchantDataForZoneLoad(){ void Zone::GetMerchantDataForZoneLoad() {
LogFile->write(EQEMuLog::Status, "Loading Merchant Lists..."); LogFile->write(EQEMuLog::Status, "Loading Merchant Lists...");
std::string query = StringFormat( std::string query = StringFormat(
"SELECT " "SELECT "
@ -485,15 +485,19 @@ void Zone::GetMerchantDataForZoneLoad(){
"spawnentry AS se, " "spawnentry AS se, "
"spawn2 AS s2 " "spawn2 AS s2 "
"WHERE nt.merchant_id = ml.merchantid AND nt.id = se.npcid " "WHERE nt.merchant_id = ml.merchantid AND nt.id = se.npcid "
"AND se.spawngroupid = s2.spawngroupid AND s2.zone = '%s' AND s2.version = %i ", GetShortName(), GetInstanceVersion()); "AND se.spawngroupid = s2.spawngroupid AND s2.zone = '%s' AND s2.version = %i "
"ORDER BY ml.slot ", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
std::map<uint32, std::list<MerchantList> >::iterator cur; std::map<uint32, std::list<MerchantList> >::iterator cur;
uint32 npcid = 0; uint32 npcid = 0;
if (results.RowCount() == 0){ LogFile->write(EQEMuLog::Error, "Error in loading Merchant Data for zone"); return; } if (results.RowCount() == 0) {
LogFile->write(EQEMuLog::Error, "Error in loading Merchant Data for zone");
return;
}
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
MerchantList ml; MerchantList ml;
ml.id = atoul(row[0]); ml.id = atoul(row[0]);
if (npcid != ml.id){ if (npcid != ml.id) {
cur = merchanttable.find(ml.id); cur = merchanttable.find(ml.id);
if (cur == merchanttable.end()) { if (cur == merchanttable.end()) {
std::list<MerchantList> empty; std::list<MerchantList> empty;