From 091c8ea5f14ec826b6c7f97c8bd60dd264f5ec67 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 19:33:20 -0700 Subject: [PATCH 01/24] BazaarAuditTrail converted to QueryDatabase --- zone/trading.cpp | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index c89af4010..1b431cd2a 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -133,7 +133,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { client->Kick(); return; } - + SendItemData(inst, trade_slot_id); _log(TRADING__HOLDER, "%s added item '%s' to trade slot %i", owner->GetName(), inst->GetItem()->Name, trade_slot_id); @@ -451,13 +451,13 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st mlog(TRADING__CLIENT, "Finishing trade with client %s", other->GetName()); this->AddMoneyToPP(other->trade->cp, other->trade->sp, other->trade->gp, other->trade->pp, true); - + // step 0: pre-processing // QS code if (RuleB(QueryServ, PlayerLogTrades) && event_entry && event_details) { qs_audit = (QSPlayerLogTrade_Struct*)event_entry; qs_log = true; - + if (finalizer) { qs_audit->char2_id = this->character_id; @@ -506,7 +506,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st detail->aug_5 = inst->GetAugmentItemID(5); event_details->push_back(detail); - + if (finalizer) qs_audit->char2_count += detail->charges; else @@ -886,7 +886,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (baginst) { const Item_Struct* bagitem = baginst->GetItem(); if (bagitem && (GetGM() || (bagitem->NoDrop != 0 && baginst->IsInstNoDrop() == false))) { - tradingWith->CastToNPC()->AddLootDrop(bagitem, &tradingWith->CastToNPC()->itemlist, + tradingWith->CastToNPC()->AddLootDrop(bagitem, &tradingWith->CastToNPC()->itemlist, baginst->GetCharges(), 1, 127, true, true); } else if (RuleB(NPC, ReturnNonQuestNoDropItems)) { @@ -895,8 +895,8 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } } } - - tradingWith->CastToNPC()->AddLootDrop(item, &tradingWith->CastToNPC()->itemlist, + + tradingWith->CastToNPC()->AddLootDrop(item, &tradingWith->CastToNPC()->itemlist, inst->GetCharges(), 1, 127, true, true); } // Return NO DROP and Attuned items being handed into a non-quest NPC if the rule is true @@ -943,7 +943,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if(tradingWith->GetAppearance() != eaDead) { tradingWith->FaceTarget(this); } - + ItemInst *insts[4] = { 0 }; for(int i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_NPC_END; ++i) { insts[i - EmuConstants::TRADE_BEGIN] = m_inv.PopItem(i); @@ -1475,18 +1475,16 @@ void Client::TradeRequestFailed(const EQApplicationPacket* app) { } -static void BazaarAuditTrail(const char *Seller, const char *Buyer, const char *ItemName, int Quantity, int TotalCost, int TranType) { +static void BazaarAuditTrail(const char *seller, const char *buyer, const char *itemName, int quantity, int totalCost, int tranType) { - const char *AuditQuery="INSERT INTO `trader_audit` (`time`, `seller`, `buyer`, `itemname`, `quantity`, `totalcost`, `trantype`) " - "VALUES (NOW(), '%s', '%s', '%s', %i, %i, %i)"; + std::string query = StringFormat("INSERT INTO `trader_audit` " + "(`time`, `seller`, `buyer`, `itemname`, `quantity`, `totalcost`, `trantype`) " + "VALUES (NOW(), '%s', '%s', '%s', %i, %i, %i)", + seller, buyer, itemName, quantity, totalCost, tranType); + auto results = database.QueryDatabase(query); + if(!results.Success()) + _log(TRADING__CLIENT, "Audit write error: %s : %s", query.c_str(), results.ErrorMessage().c_str()); - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - - if(!database.RunQuery(query, MakeAnyLenString(&query, AuditQuery, Seller, Buyer, ItemName, Quantity, TotalCost, TranType), errbuf)) - _log(TRADING__CLIENT, "Audit write error: %s : %s", query, errbuf); - - safe_delete_array(query); } From 6eba6720132aa8dab5758b855cff97e55aeb1ed0 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 19:39:50 -0700 Subject: [PATCH 02/24] SendBazaarWelcome converted to QueryDatabase --- zone/trading.cpp | 55 ++++++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index 1b431cd2a..67fbd004d 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1624,50 +1624,35 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs,Client* Trader,const EQApplicat void Client::SendBazaarWelcome(){ - char errbuf[MYSQL_ERRMSG_SIZE]; + const std::string query = "SELECT COUNT(DISTINCT char_id), count(char_id) FROM trader"; + auto results = database.QueryDatabase(query); + if (results.Success() && results.RowCount() == 1){ + auto row = results.begin(); - char* query = 0; + EQApplicationPacket* outapp = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarWelcome_Struct)); - MYSQL_RES *result; + memset(outapp->pBuffer,0,outapp->size); - MYSQL_ROW row; + BazaarWelcome_Struct* bws = (BazaarWelcome_Struct*)outapp->pBuffer; - if (database.RunQuery(query,MakeAnyLenString(&query, "select count(distinct char_id),count(char_id) from trader"),errbuf,&result)){ - if(mysql_num_rows(result)==1){ + bws->Beginning.Action = BazaarWelcome; - row = mysql_fetch_row(result); + bws->Traders = atoi(row[0]); + bws->Items = atoi(row[1]); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarWelcome_Struct)); + QueuePacket(outapp); - memset(outapp->pBuffer,0,outapp->size); + safe_delete(outapp); + } - BazaarWelcome_Struct* bws = (BazaarWelcome_Struct*)outapp->pBuffer; + const std::string buyerCountQuery = "SELECT COUNT(DISTINCT charid) FROM buyer"; + results = database.QueryDatabase(query); + if (!results.Success() || results.RowCount() != 1) + return; - bws->Beginning.Action = BazaarWelcome; - - bws->Items = atoi(row[1]); - - bws->Traders = atoi(row[0]); - - QueuePacket(outapp); - - safe_delete(outapp); - } - mysql_free_result(result); - } - safe_delete_array(query); - - if (database.RunQuery(query,MakeAnyLenString(&query, "select count(distinct charid) from buyer"),errbuf,&result)){ - if(mysql_num_rows(result)==1) { - - row = mysql_fetch_row(result); - - Message(10, "There are %i Buyers waiting to purchase your loot. Type /barter to search for them," - " or use /buyer to set up your own Buy Lines.", atoi(row[0])); - } - mysql_free_result(result); - } - safe_delete_array(query); + auto row = results.begin(); + Message(10, "There are %i Buyers waiting to purchase your loot. Type /barter to search for them, " + "or use /buyer to set up your own Buy Lines.", atoi(row[0])); } void Client::SendBazaarResults(uint32 TraderID, uint32 Class_, uint32 Race, uint32 ItemStat, uint32 Slot, uint32 Type, From 36c1d88eac8a041e9d66f8f78de7c1df1110a24c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 20:18:07 -0700 Subject: [PATCH 03/24] SendBazaarResults converted to QueryDatabase --- zone/trading.cpp | 398 ++++++++++++++++++++++------------------------- 1 file changed, 187 insertions(+), 211 deletions(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index 67fbd004d..2df409b22 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1658,314 +1658,290 @@ void Client::SendBazaarWelcome(){ void Client::SendBazaarResults(uint32 TraderID, uint32 Class_, uint32 Race, uint32 ItemStat, uint32 Slot, uint32 Type, char Name[64], uint32 MinPrice, uint32 MaxPrice) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* Query = 0; - std::string Search, Values; - MYSQL_RES *Result; - MYSQL_ROW Row; - char Tmp[100] = {0}; + std::string searchValues = " COUNT(item_id), trader.*, items.name "; + std::string searchCriteria = " WHERE trader.item_id = items.id "; - Values.append("count(item_id),trader.*,items.name"); + if(TraderID > 0) { + Client* trader = entity_list.GetClientByID(TraderID); - Search.append("where trader.item_id=items.id"); + if(trader) + searchCriteria.append(StringFormat(" AND trader.char_id = %i", trader->CharacterID())); + } - if(TraderID > 0){ - Client* Trader = entity_list.GetClientByID(TraderID); + if(MinPrice != 0) + searchCriteria.append(StringFormat(" AND trader.item_cost >= %i", MinPrice)); - if(Trader){ - sprintf(Tmp," and trader.char_id=%i",Trader->CharacterID()); - Search.append(Tmp); - } + if(MaxPrice != 0) + searchCriteria.append(StringFormat(" AND trader.item_cost <= %i", MaxPrice)); + if(strlen(Name) > 0) { + char *safeName = RemoveApostrophes(Name); + searchCriteria.append(StringFormat(" AND items.name LIKE '%%%s%%'", safeName)); + safe_delete_array(safeName); } - std::string SearchrResults; - if(MinPrice != 0){ - sprintf(Tmp, " and trader.item_cost>=%i", MinPrice); - Search.append(Tmp); - } - if(MaxPrice != 0){ - sprintf(Tmp, " and trader.item_cost<=%i", MaxPrice); - Search.append(Tmp); - } - if(strlen(Name) > 0){ - char *SafeName = RemoveApostrophes(Name); - sprintf(Tmp, " and items.name like '%%%s%%'", SafeName); - safe_delete_array(SafeName); - Search.append(Tmp); - } - if(Class_ != 0xFFFFFFFF){ - sprintf(Tmp, " and mid(reverse(bin(items.classes)),%i,1)=1", Class_); - Search.append(Tmp); - } - if(Race!=0xFFFFFFFF){ - sprintf(Tmp, " and mid(reverse(bin(items.races)),%i,1)=1", Race); - Search.append(Tmp); - } - if(Slot!=0xFFFFFFFF){ - sprintf(Tmp, " and mid(reverse(bin(items.slots)),%i,1)=1", Slot + 1); - Search.append(Tmp); - } - if(Type!=0xFFFFFFFF){ + if(Class_ != 0xFFFFFFFF) + searchCriteria.append(StringFormat(" AND MID(REVERSE(BIN(items.classes)), %i, 1) = 1", Class_)); - switch(Type){ + if(Race != 0xFFFFFFFF) + searchCriteria.append(StringFormat(" AND MID(REVERSE(BIN(items.races)), %i, 1) = 1", Race)); - case 0: - // 1H Slashing - Search.append(" and items.itemtype=0 and damage>0"); - break; - case 31: - Search.append(" and items.itemclass=2"); - break; - case 46: - Search.append(" and items.spellid>0 and items.spellid<65000"); - break; - case 47: - Search.append(" and items.spellid=998"); - break; - case 48: - Search.append(" and items.spellid>=1298 and items.spellid<=1307"); - break; - case 49: - Search.append(" and items.focuseffect>0"); - break; - default: - sprintf(Tmp, " and items.itemtype=%i", Type); - Search.append(Tmp); - } - } + if(Slot != 0xFFFFFFFF) + searchCriteria.append(StringFormat(" AND MID(REVERSE(BIN(items.slots)), %i, 1) = 1", Slot + 1)); + + switch(Type){ + case 0xFFFFFFFF: + break; + case 0: + // 1H Slashing + searchCriteria.append(" AND items.itemtype = 0 AND damage > 0"); + break; + case 31: + searchCriteria.append(" AND items.itemclass = 2"); + break; + case 46: + searchCriteria.append(" AND items.spellid > 0 AND items.spellid < 65000"); + break; + case 47: + searchCriteria.append(" AND items.spellid = 998"); + break; + case 48: + searchCriteria.append(" AND items.spellid >= 1298 AND items.spellid <= 1307"); + break; + case 49: + searchCriteria.append(" AND items.focuseffect > 0"); + break; + + default: + searchCriteria.append(StringFormat(" AND items.itemtype = %i", Type)); + } switch(ItemStat) { case STAT_AC: - Search.append(" and items.ac>0"); - Values.append(",items.ac"); + searchCriteria.append(" AND items.ac > 0"); + searchValues.append(", items.ac"); break; case STAT_AGI: - Search.append(" and items.aagi>0"); - Values.append(",items.aagi"); + searchCriteria.append(" AND items.aagi > 0"); + searchValues.append(", items.aagi"); break; case STAT_CHA: - Search.append(" and items.acha>0"); - Values.append(",items.acha"); + searchCriteria.append(" AND items.acha > 0"); + searchValues.append(", items.acha"); break; case STAT_DEX: - Search.append(" and items.adex>0"); - Values.append(",items.adex"); + searchCriteria.append(" AND items.adex > 0"); + searchValues.append(", items.adex"); break; case STAT_INT: - Search.append(" and items.aint>0"); - Values.append(",items.aint"); + searchCriteria.append(" AND items.aint > 0"); + searchValues.append(", items.aint"); break; case STAT_STA: - Search.append(" and items.asta>0"); - Values.append(",items.asta"); + searchCriteria.append(" AND items.asta > 0"); + searchValues.append(", items.asta"); break; case STAT_STR: - Search.append(" and items.astr>0"); - Values.append(",items.astr"); + searchCriteria.append(" AND items.astr > 0"); + searchValues.append(", items.astr"); break; case STAT_WIS: - Search.append(" and items.awis>0"); - Values.append(",items.awis"); + searchCriteria.append(" AND items.awis > 0"); + searchValues.append(", items.awis"); break; case STAT_COLD: - Search.append(" and items.cr>0"); - Values.append(",items.cr"); + searchCriteria.append(" AND items.cr > 0"); + searchValues.append(", items.cr"); break; case STAT_DISEASE: - Search.append(" and items.dr>0"); - Values.append(",items.dr"); + searchCriteria.append(" AND items.dr > 0"); + searchValues.append(", items.dr"); break; case STAT_FIRE: - Search.append(" and items.fr>0"); - Values.append(",items.fr"); + searchCriteria.append(" AND items.fr > 0"); + searchValues.append(", items.fr"); break; case STAT_MAGIC: - Values.append(",items.mr"); - Search.append(" and items.mr>0"); + searchCriteria.append(" AND items.mr > 0"); + searchValues.append(", items.mr"); break; case STAT_POISON: - Search.append(" and items.pr>0"); - Values.append(",items.pr"); + searchCriteria.append(" AND items.pr > 0"); + searchValues.append(", items.pr"); break; case STAT_HP: - Search.append(" and items.hp>0"); - Values.append(",items.hp"); + searchCriteria.append(" AND items.hp > 0"); + searchValues.append(", items.hp"); break; case STAT_MANA: - Search.append(" and items.mana>0"); - Values.append(",items.mana"); + searchCriteria.append(" AND items.mana > 0"); + searchValues.append(", items.mana"); break; case STAT_ENDURANCE: - Search.append(" and items.endur>0"); - Values.append(",items.endur"); + searchCriteria.append(" AND items.endur > 0"); + searchValues.append(", items.endur"); break; case STAT_ATTACK: - Search.append(" and items.attack>0"); - Values.append(",items.attack"); + searchCriteria.append(" AND items.attack > 0"); + searchValues.append(", items.attack"); break; case STAT_HP_REGEN: - Search.append(" and items.regen>0"); - Values.append(",items.regen"); + searchCriteria.append(" AND items.regen > 0"); + searchValues.append(", items.regen"); break; case STAT_MANA_REGEN: - Search.append(" and items.manaregen>0"); - Values.append(",items.manaregen"); + searchCriteria.append(" AND items.manaregen > 0"); + searchValues.append(", items.manaregen"); break; case STAT_HASTE: - Search.append(" and items.haste>0"); - Values.append(",items.haste"); + searchCriteria.append(" AND items.haste > 0"); + searchValues.append(", items.haste"); break; case STAT_DAMAGE_SHIELD: - Search.append(" and items.damageshield>00"); - Values.append(",items.damageshield"); + searchCriteria.append(" AND items.damageshield > 0"); + searchValues.append(", items.damageshield"); break; default: - Values.append(",0"); + searchValues.append(", 0"); break; } - Values.append(",sum(charges), items.stackable "); + std::string query = StringFormat("SELECT %s, SUM(charges), items.stackable " + "FROM trader, items %s GROUP BY items.id, charges, char_id LIMIT %i", + searchValues.c_str(), searchCriteria.c_str(), RuleI(Bazaar, MaxSearchResults)); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + _log(TRADING__CLIENT, "Failed to retrieve Bazaar Search!! %s %s\n", query.c_str(), results.ErrorMessage().c_str()); + return; + } - if (database.RunQuery(Query,MakeAnyLenString(&Query, "select %s from trader,items %s group by items.id,charges,char_id limit %i", - Values.c_str(),Search.c_str(), RuleI(Bazaar, MaxSearchResults)),errbuf,&Result)){ + _log(TRADING__CLIENT, "SRCH: %s", query.c_str()); - _log(TRADING__CLIENT, "SRCH: %s", Query); - safe_delete_array(Query); + int Size = 0; + uint32 ID = 0; - int Size = 0; - uint32 ID = 0; - - if(mysql_num_rows(Result) == static_cast(RuleI(Bazaar, MaxSearchResults))) + if (results.RowCount() == static_cast(RuleI(Bazaar, MaxSearchResults))) Message(15, "Your search reached the limit of %i results. Please narrow your search down by selecting more options.", RuleI(Bazaar, MaxSearchResults)); - if(mysql_num_rows(Result) == 0){ - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct)); - BazaarReturnDone_Struct* brds = (BazaarReturnDone_Struct*)outapp2->pBuffer; - brds->TraderID = ID; - brds->Type = BazaarSearchDone; - brds->Unknown008 = 0xFFFFFFFF; - brds->Unknown012 = 0xFFFFFFFF; - brds->Unknown016 = 0xFFFFFFFF; - this->QueuePacket(outapp2); - _pkt(TRADING__PACKETS,outapp2); - safe_delete(outapp2); - mysql_free_result(Result); - return; - } - Size = mysql_num_rows(Result) * sizeof(BazaarSearchResults_Struct); - uchar *buffer = new uchar[Size]; - uchar *bufptr = buffer; - memset(buffer, 0, Size); - - int Action = BazaarSearchResults; - uint32 Cost = 0; - int32 SerialNumber = 0; - char Name[64] = {0}; - int Count = 0; - uint32 StatValue=0; - - while ((Row = mysql_fetch_row(Result))) { - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Action); - Count = atoi(Row[0]); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Count); - SerialNumber = atoi(Row[3]); - VARSTRUCT_ENCODE_TYPE(int32, bufptr, SerialNumber); - Client* Trader2=entity_list.GetClientByCharID(atoi(Row[1])); - if(Trader2){ - ID = Trader2->GetID(); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, ID); - } - else{ - _log(TRADING__CLIENT, "Unable to find trader: %i\n",atoi(Row[1])); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 0); - } - Cost = atoi(Row[5]); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Cost); - StatValue = atoi(Row[8]); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, StatValue); - bool Stackable = atoi(Row[10]); - if(Stackable) { - int Charges = atoi(Row[9]); - sprintf(Name, "%s(%i)", Row[7], Charges); - } - else - sprintf(Name,"%s(%i)",Row[7], Count); - - memcpy(bufptr,&Name, strlen(Name)); - - bufptr += 64; - - // Extra fields for SoD+ - // - if(Trader2) - sprintf(Name, "%s", Trader2->GetName()); - else - sprintf(Name, "Unknown"); - - memcpy(bufptr,&Name, strlen(Name)); - - bufptr += 64; - - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, atoi(Row[1])); // ItemID - } - mysql_free_result(Result); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_BazaarSearch, Size); - - memcpy(outapp->pBuffer, buffer, Size); - - this->QueuePacket(outapp); - - _pkt(TRADING__PACKETS,outapp); - - safe_delete(outapp); - safe_delete_array(buffer); - + if(results.RowCount() == 0) { EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct)); BazaarReturnDone_Struct* brds = (BazaarReturnDone_Struct*)outapp2->pBuffer; - brds->TraderID = ID; brds->Type = BazaarSearchDone; - brds->Unknown008 = 0xFFFFFFFF; brds->Unknown012 = 0xFFFFFFFF; brds->Unknown016 = 0xFFFFFFFF; - this->QueuePacket(outapp2); - _pkt(TRADING__PACKETS,outapp2); safe_delete(outapp2); - - } - else{ - _log(TRADING__CLIENT, "Failed to retrieve Bazaar Search!! %s %s\n", Query, errbuf); - safe_delete_array(Query); return; } + + Size = results.RowCount() * sizeof(BazaarSearchResults_Struct); + uchar *buffer = new uchar[Size]; + uchar *bufptr = buffer; + memset(buffer, 0, Size); + + int Action = BazaarSearchResults; + uint32 Cost = 0; + int32 SerialNumber = 0; + char Name[64] = {0}; + int Count = 0; + uint32 StatValue=0; + + for (auto row = results.begin(); row != results.end(); ++row) { + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Action); + Count = atoi(row[0]); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Count); + SerialNumber = atoi(row[3]); + VARSTRUCT_ENCODE_TYPE(int32, bufptr, SerialNumber); + Client* Trader2=entity_list.GetClientByCharID(atoi(row[1])); + if(Trader2){ + ID = Trader2->GetID(); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, ID); + } + else{ + _log(TRADING__CLIENT, "Unable to find trader: %i\n",atoi(row[1])); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 0); + } + Cost = atoi(row[5]); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Cost); + StatValue = atoi(row[8]); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, StatValue); + bool Stackable = atoi(row[10]); + if(Stackable) { + int Charges = atoi(row[9]); + sprintf(Name, "%s(%i)", row[7], Charges); + } + else + sprintf(Name,"%s(%i)",row[7], Count); + + memcpy(bufptr,&Name, strlen(Name)); + + bufptr += 64; + + // Extra fields for SoD+ + // + if(Trader2) + sprintf(Name, "%s", Trader2->GetName()); + else + sprintf(Name, "Unknown"); + + memcpy(bufptr,&Name, strlen(Name)); + + bufptr += 64; + + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, atoi(row[1])); // ItemID + } + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_BazaarSearch, Size); + + memcpy(outapp->pBuffer, buffer, Size); + + this->QueuePacket(outapp); + + _pkt(TRADING__PACKETS,outapp); + + safe_delete(outapp); + safe_delete_array(buffer); + + EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct)); + BazaarReturnDone_Struct* brds = (BazaarReturnDone_Struct*)outapp2->pBuffer; + + brds->TraderID = ID; + brds->Type = BazaarSearchDone; + + brds->Unknown008 = 0xFFFFFFFF; + brds->Unknown012 = 0xFFFFFFFF; + brds->Unknown016 = 0xFFFFFFFF; + + this->QueuePacket(outapp2); + + _pkt(TRADING__PACKETS,outapp2); + safe_delete(outapp2); } static void UpdateTraderCustomerItemsAdded(uint32 CustomerID, TraderCharges_Struct* gis, uint32 ItemID) { From a8b8f7109294bb0e5fa8a24b55d9ae332e39a288 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 20:24:30 -0700 Subject: [PATCH 04/24] ShowBuyLines converted to QueryDatabase --- zone/trading.cpp | 78 +++++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 47 deletions(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index 2df409b22..10cf33e69 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -2402,60 +2402,44 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { safe_delete(outapp); - char errbuf[MYSQL_ERRMSG_SIZE]; - char* Query = 0; - char ItemName[64]; - std::string Search, Values; - MYSQL_RES *Result; - MYSQL_ROW Row; + std::string query = StringFormat("SELECT * FROM buyer WHERE charid = %i", Buyer->CharacterID()); + auto results = database.QueryDatabase(query); + if (!results.Success() || results.RowCount() == 0) + return; - if (database.RunQuery(Query,MakeAnyLenString(&Query, "select * from buyer where charid = %i", - Buyer->CharacterID()),errbuf,&Result)){ + for (auto row = results.begin(); row != results.end(); ++row) { + char ItemName[64]; + uint32 BuySlot = atoi(row[1]); + uint32 ItemID = atoi(row[2]); + strcpy(ItemName, row[3]); + uint32 Quantity = atoi(row[4]); + uint32 Price = atoi(row[5]); - if(mysql_num_rows(Result) == 0) { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 936); - safe_delete_array(Query); + char *Buf = (char *)outapp->pBuffer; - mysql_free_result(Result); + const Item_Struct* item = database.GetItem(ItemID); - return; - } + if(!item) + continue; - while ((Row = mysql_fetch_row(Result))) { + VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow); + VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); + VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Flag + VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID); + VARSTRUCT_ENCODE_STRING(Buf, ItemName); + VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); + VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); + VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Flag + VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); + VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID()); + VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); + VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); - uint32 BuySlot = atoi(Row[1]); - uint32 ItemID = atoi(Row[2]); - strcpy(ItemName, Row[3]); - uint32 Quantity = atoi(Row[4]); - uint32 Price = atoi(Row[5]); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 936); - - char *Buf = (char *)outapp->pBuffer; - - const Item_Struct* item = database.GetItem(ItemID); - - if(!item) continue; - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Flag - VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID); - VARSTRUCT_ENCODE_STRING(Buf, ItemName); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Flag - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID()); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); - VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); - - _pkt(TRADING__BARTER, outapp); - QueuePacket(outapp); - } - mysql_free_result(Result); - } - safe_delete_array(Query); + _pkt(TRADING__BARTER, outapp); + QueuePacket(outapp); + } } void Client::SellToBuyer(const EQApplicationPacket *app) { From 081905dbc31627ef6d94bf37423fd30ba1f04d56 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 20:34:07 -0700 Subject: [PATCH 05/24] SendBuyerResults converted to QueryDatabase --- zone/trading.cpp | 155 ++++++++++++++++++++++------------------------- 1 file changed, 72 insertions(+), 83 deletions(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index 10cf33e69..98b3c8a5a 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -2263,103 +2263,92 @@ void Client::HandleTraderPriceUpdate(const EQApplicationPacket *app) { } -void Client::SendBuyerResults(char* SearchString, uint32 SearchID) { +void Client::SendBuyerResults(char* searchString, uint32 searchID) { // This method is called when a potential seller in the /barter window searches for matching buyers // - _log(TRADING__BARTER, "Client::SendBuyerResults %s\n", SearchString); + _log(TRADING__BARTER, "Client::SendBuyerResults %s\n", searchString); - char errbuf[MYSQL_ERRMSG_SIZE]; - char* Query = 0; - char ItemName[64]; - std::string Search, Values; - MYSQL_RES *Result; - MYSQL_ROW Row; + char* escSearchString = new char[strlen(searchString) * 2 + 1]; + database.DoEscapeString(escSearchString, searchString, strlen(searchString)); - char*EscSearchString = new char[strlen(SearchString) * 2 + 1]; - database.DoEscapeString(EscSearchString, SearchString, strlen(SearchString)); + std::string query = StringFormat("SELECT * FROM buyer WHERE itemname LIKE '%%%s%%' ORDER BY charid LIMIT %i", + escSearchString, RuleI(Bazaar, MaxBarterSearchResults)); + safe_delete_array(escSearchString); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + _log(TRADING__CLIENT, "Failed to retrieve Barter Search!! %s %s\n", query.c_str(), results.ErrorMessage().c_str()); + return; + } - if (database.RunQuery(Query,MakeAnyLenString(&Query, "select * from buyer where itemname like '%%%s%%' order by charid limit %i", - EscSearchString, RuleI(Bazaar, MaxBarterSearchResults)), errbuf, &Result)) { + int numberOfRows = results.RowCount(); - int NumberOfRows = mysql_num_rows(Result); + if(numberOfRows == RuleI(Bazaar, MaxBarterSearchResults)) + Message(15, "Your search found too many results; some are not displayed."); + else if(strlen(searchString) == 0) + Message(10, "There are %i Buy Lines.", numberOfRows); + else + Message(10, "There are %i Buy Lines that match the search string '%s'.", numberOfRows, searchString); - if(NumberOfRows == RuleI(Bazaar, MaxBarterSearchResults)) - Message(15, "Your search found too many results; some are not displayed."); - else { - if(strlen(SearchString) == 0) - Message(10, "There are %i Buy Lines.", NumberOfRows); - else - Message(10, "There are %i Buy Lines that match the search string '%s'.", - NumberOfRows, SearchString); + if(numberOfRows == 0) + return; + + uint32 lastCharID = 0; + Client *buyer = nullptr; + + for (auto row = results.begin(); row != results.end(); ++row) { + char itemName[64]; + + uint32 charID = atoi(row[0]); + uint32 buySlot = atoi(row[1]); + uint32 itemID = atoi(row[2]); + strcpy(itemName, row[3]); + uint32 quantity = atoi(row[4]); + uint32 price = atoi(row[5]); + + // Each item in the search results is sent as a single fixed length packet, although the position of + // the fields varies due to the use of variable length strings. The reason the packet is so big, is + // to allow item compensation, e.g. a buyer could offer to buy a Blade Of Carnage for 10000pp plus + // other items in exchange. Item compensation is not currently supported in EQEmu. + // + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 940); + + char *buf = (char *)outapp->pBuffer; + + const Item_Struct* item = database.GetItem(itemID); + + if(!item) + continue; + + // Save having to scan the client list when dealing with multiple buylines for the same Character. + if(charID != lastCharID) { + buyer = entity_list.GetClientByCharID(charID); + lastCharID = charID; } - if(NumberOfRows == 0) { - mysql_free_result(Result); - safe_delete_array(Query); - return; - } + if(!buyer) + continue; - uint32 LastCharID = 0; - Client *Buyer = nullptr; + VARSTRUCT_ENCODE_TYPE(uint32, buf, Barter_BuyerSearchResults); // Command + VARSTRUCT_ENCODE_TYPE(uint32, buf, searchID); // Match up results with the request + VARSTRUCT_ENCODE_TYPE(uint32, buf, buySlot); // Slot in this Buyer's list + VARSTRUCT_ENCODE_TYPE(uint8, buf, 0x01); // Unknown - probably a flag field + VARSTRUCT_ENCODE_TYPE(uint32, buf, itemID); // ItemID + VARSTRUCT_ENCODE_STRING(buf, itemName); // Itemname + VARSTRUCT_ENCODE_TYPE(uint32, buf, item->Icon); // Icon + VARSTRUCT_ENCODE_TYPE(uint32, buf, quantity); // Quantity + VARSTRUCT_ENCODE_TYPE(uint8, buf, 0x01); // Unknown - probably a flag field + VARSTRUCT_ENCODE_TYPE(uint32, buf, price); // Price + VARSTRUCT_ENCODE_TYPE(uint32, buf, buyer->GetID()); // Entity ID + VARSTRUCT_ENCODE_TYPE(uint32, buf, 0); // Flag for + Items , probably ItemCount + VARSTRUCT_ENCODE_STRING(buf, buyer->GetName()); // Seller Name - while ((Row = mysql_fetch_row(Result))) { + _pkt(TRADING__BARTER, outapp); - uint32 CharID = atoi(Row[0]); - uint32 BuySlot = atoi(Row[1]); - uint32 ItemID = atoi(Row[2]); - strcpy(ItemName, Row[3]); - uint32 Quantity = atoi(Row[4]); - uint32 Price = atoi(Row[5]); + QueuePacket(outapp); + safe_delete(outapp); + } - // Each item in the search results is sent as a single fixed length packet, although the position of - // the fields varies due to the use of variable length strings. The reason the packet is so big, is - // to allow item compensation, e.g. a buyer could offer to buy a Blade Of Carnage for 10000pp plus - // other items in exchange. Item compensation is not currently supported in EQEmu. - // - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 940); - - char *Buf = (char *)outapp->pBuffer; - - const Item_Struct* item = database.GetItem(ItemID); - - if(!item) continue; - - // Save having to scan the client list when dealing with multiple buylines for the same Character. - if(CharID != LastCharID) { - Buyer = entity_list.GetClientByCharID(CharID); - LastCharID = CharID; - } - - if(!Buyer) continue; - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerSearchResults); // Command - VARSTRUCT_ENCODE_TYPE(uint32, Buf, SearchID); // Match up results with the request - VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); // Slot in this Buyer's list - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01); // Unknown - probably a flag field - VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID); // ItemID - VARSTRUCT_ENCODE_STRING(Buf, ItemName); // Itemname - VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); // Icon - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); // Quantity - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01); // Unknown - probably a flag field - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); // Price - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID()); // Entity ID - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Flag for + Items , probably ItemCount - VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); // Seller Name - - _pkt(TRADING__BARTER, outapp); - - QueuePacket(outapp); - safe_delete(outapp); - } - - mysql_free_result(Result); - } - else{ - _log(TRADING__CLIENT, "Failed to retrieve Barter Search!! %s %s\n", Query, errbuf); - } - safe_delete_array(Query); - safe_delete_array(EscSearchString); } void Client::ShowBuyLines(const EQApplicationPacket *app) { From 58343480ff7da00c2ea18f8da023d14827ec9320 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 23:07:28 -0700 Subject: [PATCH 06/24] InsertQuestGlobal converted to QueryDatabase --- zone/questmgr.cpp | 128 +++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 70 deletions(-) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fc31178ae..2ace6c0dd 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -172,7 +172,7 @@ void QuestManager::EndQuest() { cur = QTimerList.erase(cur); else ++cur; - } + } run.owner->Depop(); } quests_running_.pop(); @@ -447,7 +447,7 @@ void QuestManager::settimer(const char *timer_name, int seconds) { end = QTimerList.end(); while (cur != end) { - if(cur->mob && cur->mob == owner && cur->name == timer_name) + if(cur->mob && cur->mob == owner && cur->name == timer_name) { cur->Timer_.Enable(); cur->Timer_.Start(seconds * 1000, false); @@ -471,7 +471,7 @@ void QuestManager::settimerMS(const char *timer_name, int milliseconds) { end = QTimerList.end(); while (cur != end) { - if(cur->mob && cur->mob == owner && cur->name == timer_name) + if(cur->mob && cur->mob == owner && cur->name == timer_name) { cur->Timer_.Enable(); cur->Timer_.Start(milliseconds, false); @@ -1308,7 +1308,7 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti if (initiator && initiator->IsClient()){ // some events like waypoint and spawn don't have a player involved qgCharid=initiator->CharacterID(); - } + } else { qgCharid=-qgNpcid; // make char id negative npc id as a fudge } @@ -1335,81 +1335,69 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti /* Inserts global variable into quest_globals table */ int QuestManager::InsertQuestGlobal(int charid, int npcid, int zoneid, const char *varname, const char *varvalue, int duration) { - char *query = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; // Make duration string either "unix_timestamp(now()) + xxx" or "NULL" - std::stringstream duration_ss; - if (duration == INT_MAX) { - duration_ss << "NULL"; - } - else { - duration_ss << "unix_timestamp(now()) + " << duration; - } + std::string durationText = (duration == INT_MAX)? "NULL": StringFormat("unix_timestamp(now()) + %i", duration); /* NOTE: this should be escaping the contents of arglist npcwise a malicious script can arbitrarily alter the DB */ - uint32 last_id = 0; - if (!database.RunQuery(query, MakeAnyLenString(&query, - "REPLACE INTO quest_globals (charid, npcid, zoneid, name, value, expdate)" - "VALUES (%i, %i, %i, '%s', '%s', %s)", - charid, npcid, zoneid, varname, varvalue, duration_ss.str().c_str() - ), errbuf, nullptr, nullptr, &last_id)) - { - std::cerr << "setglobal error inserting " << varname << " : " << errbuf << std::endl; - } - safe_delete_array(query); - if(zone) { - /* Delete existing qglobal data and update zone processes */ - ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); - ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer; - qgd->npc_id = npcid; - qgd->char_id = charid; - qgd->zone_id = zoneid; - qgd->from_zone_id = zone->GetZoneID(); - qgd->from_instance_id = zone->GetInstanceID(); - strcpy(qgd->name, varname); + std::string query = StringFormat("REPLACE INTO quest_globals " + "(charid, npcid, zoneid, name, value, expdate)" + "VALUES (%i, %i, %i, '%s', '%s', %s)", + charid, npcid, zoneid, varname, varvalue, durationText.c_str()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + std::cerr << "setglobal error inserting " << varname << " : " << results.ErrorMessage() << std::endl; - entity_list.DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); - zone->DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); + if(!zone) + return 0; - worldserver.SendPacket(pack); - safe_delete(pack); + /* Delete existing qglobal data and update zone processes */ + ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); + ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer; + qgd->npc_id = npcid; + qgd->char_id = charid; + qgd->zone_id = zoneid; + qgd->from_zone_id = zone->GetZoneID(); + qgd->from_instance_id = zone->GetInstanceID(); + strcpy(qgd->name, varname); - /* Create new qglobal data and update zone processes */ - pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct)); - ServerQGlobalUpdate_Struct *qgu = (ServerQGlobalUpdate_Struct*)pack->pBuffer; - qgu->npc_id = npcid; - qgu->char_id = charid; - qgu->zone_id = zoneid; - if(duration == INT_MAX) { - qgu->expdate = 0xFFFFFFFF; - } - else { - qgu->expdate = Timer::GetTimeSeconds() + duration; - } - strcpy((char*)qgu->name, varname); - strn0cpy((char*)qgu->value, varvalue, 128); - qgu->id = last_id; - qgu->from_zone_id = zone->GetZoneID(); - qgu->from_instance_id = zone->GetInstanceID(); + entity_list.DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); + zone->DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); - QGlobal temp; - temp.npc_id = npcid; - temp.char_id = charid; - temp.zone_id = zoneid; - temp.expdate = qgu->expdate; - temp.name.assign(qgu->name); - temp.value.assign(qgu->value); - entity_list.UpdateQGlobal(qgu->id, temp); - zone->UpdateQGlobal(qgu->id, temp); + worldserver.SendPacket(pack); + safe_delete(pack); - worldserver.SendPacket(pack); - safe_delete(pack); - } + /* Create new qglobal data and update zone processes */ + pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct)); + ServerQGlobalUpdate_Struct *qgu = (ServerQGlobalUpdate_Struct*)pack->pBuffer; + qgu->npc_id = npcid; + qgu->char_id = charid; + qgu->zone_id = zoneid; + + qgu->expdate = (duration == INT_MAX)? 0xFFFFFFFF: Timer::GetTimeSeconds() + duration; + + strcpy((char*)qgu->name, varname); + strn0cpy((char*)qgu->value, varvalue, 128); + qgu->id = results.LastInsertedID(); + qgu->from_zone_id = zone->GetZoneID(); + qgu->from_instance_id = zone->GetInstanceID(); + + QGlobal temp; + temp.npc_id = npcid; + temp.char_id = charid; + temp.zone_id = zoneid; + temp.expdate = qgu->expdate; + temp.name.assign(qgu->name); + temp.value.assign(qgu->value); + entity_list.UpdateQGlobal(qgu->id, temp); + zone->UpdateQGlobal(qgu->id, temp); + + worldserver.SendPacket(pack); + safe_delete(pack); return 0; } @@ -1425,9 +1413,9 @@ void QuestManager::delglobal(const char *varname) { int qgZoneid=zone->GetZoneID(); int qgCharid=0; int qgNpcid=owner->GetNPCTypeID(); - - - + + + if (initiator && initiator->IsClient()) // some events like waypoint and spawn don't have a player involved { qgCharid=initiator->CharacterID(); @@ -1709,7 +1697,7 @@ void QuestManager::showgrid(int grid) { pt.z = atof(row[2]); pts.push_back(pt); } - mysql_free_result(result); + mysql_free_result(result); initiator->SendPathPacket(pts); } else // DB query error! From 1bb5c4e0d8a4c0cda834924842d84254caed5767 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 23:10:42 -0700 Subject: [PATCH 07/24] delglobal converted to QueryDatabase --- zone/questmgr.cpp | 53 ++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 2ace6c0dd..e951f0fee 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1408,22 +1408,14 @@ void QuestManager::targlobal(const char *varname, const char *value, const char void QuestManager::delglobal(const char *varname) { QuestManagerCurrentQuestVars(); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; int qgZoneid=zone->GetZoneID(); int qgCharid=0; int qgNpcid=owner->GetNPCTypeID(); - - if (initiator && initiator->IsClient()) // some events like waypoint and spawn don't have a player involved - { qgCharid=initiator->CharacterID(); - } - - else { + else qgCharid=-qgNpcid; // make char id negative npc id as a fudge - } /* QS: PlayerLogQGlobalUpdate */ if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){ @@ -1431,31 +1423,32 @@ void QuestManager::delglobal(const char *varname) { QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); } - if (!database.RunQuery(query, - MakeAnyLenString(&query, - "DELETE FROM quest_globals WHERE name='%s'" - " && (npcid=0 || npcid=%i) && (charid=0 || charid=%i) && (zoneid=%i || zoneid=0)", - varname,qgNpcid,qgCharid,qgZoneid),errbuf)) - { - std::cerr << "delglobal error deleting " << varname << " : " << errbuf << std::endl; - } - safe_delete_array(query); + std::string query = StringFormat("DELETE FROM quest_globals " + "WHERE name = '%s' " + "&& (npcid=0 || npcid=%i) " + "&& (charid=0 || charid=%i) " + "&& (zoneid=%i || zoneid=0)", + varname, qgNpcid, qgCharid, qgZoneid); + auto results = database.QueryDatabase(query); + if (!results.Success()) + std::cerr << "delglobal error deleting " << varname << " : " << results.ErrorMessage() << std::endl; - if(zone) { - ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); - ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer; + if(!zone) + return; - qgu->npc_id = qgNpcid; - qgu->char_id = qgCharid; - qgu->zone_id = qgZoneid; - strcpy(qgu->name, varname); + ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); + ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer; - entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); - zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); + qgu->npc_id = qgNpcid; + qgu->char_id = qgCharid; + qgu->zone_id = qgZoneid; + strcpy(qgu->name, varname); - worldserver.SendPacket(pack); - safe_delete(pack); - } + entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); + zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); + + worldserver.SendPacket(pack); + safe_delete(pack); } // Converts duration string to duration value (in seconds) From 882521836129c261e94564cf3a5a4d5e2cd9cedc Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 23:14:16 -0700 Subject: [PATCH 08/24] showgrid converted to QueryDatabase --- zone/questmgr.cpp | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index e951f0fee..333aaf7be 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1669,11 +1669,6 @@ void QuestManager::showgrid(int grid) { if(initiator == nullptr) return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - FindPerson_Point pt; std::vector pts; @@ -1683,22 +1678,25 @@ void QuestManager::showgrid(int grid) { pts.push_back(pt); // Retrieve all waypoints for this grid - if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `x`,`y`,`z` FROM grid_entries WHERE `gridid`=%i AND `zoneid`=%i ORDER BY `number`",grid,zone->GetZoneID()),errbuf,&result)) { - while((row = mysql_fetch_row(result))) { - pt.x = atof(row[0]); - pt.y = atof(row[1]); - pt.z = atof(row[2]); - pts.push_back(pt); - } - mysql_free_result(result); - initiator->SendPathPacket(pts); - } - else // DB query error! - { - LogFile->write(EQEMuLog::Quest, "Error loading grid %d for showgrid(): %s", grid, errbuf); + std::string query = StringFormat("SELECT `x`,`y`,`z` FROM grid_entries " + "WHERE `gridid` = %i AND `zoneid` = %i " + "ORDER BY `number`", grid, zone->GetZoneID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Quest, "Error loading grid %d for showgrid(): %s", grid, results.ErrorMessage().c_str()); return; - } - safe_delete_array(query); + } + + for(auto row = results.begin(); row != results.end(); ++row) { + pt.x = atof(row[0]); + pt.y = atof(row[1]); + pt.z = atof(row[2]); + + pts.push_back(pt); + } + + initiator->SendPathPacket(pts); + } //change the value of a spawn condition From b710c41c345254ab382c7dd78becb8604878e820 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 23:17:20 -0700 Subject: [PATCH 09/24] clearspawntimers converted to QueryDatabase --- zone/questmgr.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 333aaf7be..db7d53e47 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2272,19 +2272,19 @@ bool QuestManager::istaskappropriate(int task) { } void QuestManager::clearspawntimers() { - if(zone) { - //TODO: Dec 19, 2008, replace with code updated for current spawn timers. - LinkedListIterator iterator(zone->spawn2_list); - iterator.Reset(); - while (iterator.MoreElements()) - { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - database.RunQuery(query, MakeAnyLenString(&query, "DELETE FROM respawn_times WHERE id=%lu AND " - "instance_id=%lu",(unsigned long)iterator.GetData()->GetID(), (unsigned long)zone->GetInstanceID()), errbuf); - safe_delete_array(query); - iterator.Advance(); - } + if(!zone) + return; + + //TODO: Dec 19, 2008, replace with code updated for current spawn timers. + LinkedListIterator iterator(zone->spawn2_list); + iterator.Reset(); + while (iterator.MoreElements()) { + std::string query = StringFormat("DELETE FROM respawn_times " + "WHERE id = %lu AND instance_id = %lu", + (unsigned long)iterator.GetData()->GetID(), + (unsigned long)zone->GetInstanceID()); + auto results = database.QueryDatabase(query); + iterator.Advance(); } } From 221c667a232cd2131a18e51750bdcb89bd0dc4ac Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 23:26:09 -0700 Subject: [PATCH 10/24] saylink converted to QueryDatabase --- zone/questmgr.cpp | 59 +++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 43 deletions(-) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index db7d53e47..51e2e568d 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2661,11 +2661,6 @@ void QuestManager::FlagInstanceByRaidLeader(uint32 zone, int16 version) const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkName) { QuestManagerCurrentQuestVars(); - const char *ERR_MYSQLERROR = "Error in saylink phrase queries"; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; int sayid = 0; int sz = strlen(Phrase); @@ -2673,42 +2668,26 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam database.DoEscapeString(escaped_string, Phrase, sz); // Query for an existing phrase and id in the saylink table - if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `id` FROM `saylink` WHERE `phrase` = '%s'", escaped_string),errbuf,&result)) + std::string query = StringFormat("SELECT `id` FROM `saylink` WHERE `phrase` = '%s'", escaped_string); + auto results = database.QueryDatabase(query); + if(results.Success()) { - if (mysql_num_rows(result) >= 1) - { - while((row = mysql_fetch_row(result))) - { + if (results.RowCount() >= 1) + for (auto row = results.begin();row != results.end(); ++row) sayid = atoi(row[0]); - } - mysql_free_result(result); - } else // Add a new saylink entry to the database and query it again for the new sayid number { - safe_delete_array(query); + query = StringFormat("INSERT INTO `saylink` (`phrase`) VALUES ('%s')", escaped_string); + results = database.QueryDatabase(query); - database.RunQuery(query,MakeAnyLenString(&query,"INSERT INTO `saylink` (`phrase`) VALUES ('%s')", escaped_string),errbuf); - safe_delete_array(query); - - if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `id` FROM saylink WHERE `phrase` = '%s'", escaped_string),errbuf,&result)) - { - if (mysql_num_rows(result) >= 1) - { - while((row = mysql_fetch_row(result))) - { + if(!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str()); + else if (results.RowCount() >= 1) + for(auto row = results.begin(); row != results.end(); ++row) sayid = atoi(row[0]); - } - mysql_free_result(result); - } - } - else - { - LogFile->write(EQEMuLog::Error, ERR_MYSQLERROR, errbuf); - } - safe_delete_array(query); + } } - safe_delete_array(query); safe_delete_array(escaped_string); if(silent) @@ -2716,27 +2695,21 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam else sayid = sayid + 500000; - //Create the say link as an item link hash - char linktext[250]; + //Create the say link as an item link hash + char linktext[250]; if(initiator) { if (initiator->GetClientVersion() >= EQClientRoF) - { sprintf(linktext,"%c%06X%s%s%c",0x12,sayid,"0000000000000000000000000000000000000000000000000",LinkName,0x12); - } else if (initiator->GetClientVersion() >= EQClientSoF) - { sprintf(linktext,"%c%06X%s%s%c",0x12,sayid,"00000000000000000000000000000000000000000000",LinkName,0x12); - } else - { sprintf(linktext,"%c%06X%s%s%c",0x12,sayid,"000000000000000000000000000000000000000",LinkName,0x12); - } } - else { // If no initiator, create an RoF saylink, since older clients handle RoF ones better than RoF handles older ones. + else // If no initiator, create an RoF saylink, since older clients handle RoF ones better than RoF handles older ones. sprintf(linktext,"%c%06X%s%s%c",0x12,sayid,"0000000000000000000000000000000000000000000000000",LinkName,0x12); - } + strcpy(Phrase,linktext); return Phrase; From 15fa2b371ca4a1f52b394dfb1ce1b4da10c4372c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 5 Sep 2014 10:45:36 -0700 Subject: [PATCH 11/24] LearnMembers converted to QueryDatabase --- zone/groups.cpp | 57 +++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 5c34cf359..83c997836 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -195,7 +195,7 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu if (members[i] != nullptr && members[i]->IsClient()) { // If Group Member is Client Client *c = members[i]->CastToClient(); //I could not get MoneyOnCorpse to work, so we use this - c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); + c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); c->Message(2, msg.c_str()); } } @@ -957,31 +957,28 @@ void Group::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float } bool Group::LearnMembers() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT name FROM group_id WHERE groupid=%lu", (unsigned long)GetID()), - errbuf,&result)){ - safe_delete_array(query); - if(mysql_num_rows(result) < 1) { //could prolly be 2 - mysql_free_result(result); - LogFile->write(EQEMuLog::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), errbuf); - return(false); - } - int i = 0; - while((row = mysql_fetch_row(result))) { - if(!row[0]) - continue; - members[i] = nullptr; - strn0cpy(membername[i], row[0], 64); + std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %lu", (unsigned long)GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return false; - i++; - } - mysql_free_result(result); + if (results.RowCount() == 0) { + LogFile->write(EQEMuLog::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str()); + return false; + } + + int memberIndex = 0; + for(auto row = results.begin(); row != results.end(); ++row) { + if(!row[0]) + continue; + + members[memberIndex] = nullptr; + strn0cpy(membername[memberIndex], row[0], 64); + + memberIndex++; } - return(true); + return true; } void Group::VerifyGroup() { @@ -1065,7 +1062,7 @@ void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range) if (!range) range = 200; - + float distance; float range2 = range*range; @@ -1102,10 +1099,10 @@ void Group::BalanceHP(int32 penalty, int32 range, Mob* caster, int32 limit) return; if (!range) - range = 200; - + range = 200; + int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0; - + float distance; float range2 = range*range; @@ -1152,16 +1149,16 @@ void Group::BalanceMana(int32 penalty, int32 range, Mob* caster, int32 limit) return; if (!range) - range = 200; + range = 200; float distance; float range2 = range*range; - + int manataken = 0, numMem = 0, manataken_tmp = 0; unsigned int gi = 0; for(; gi < MAX_GROUP_MEMBERS; gi++) { - if(members[gi] && (members[gi]->GetMaxMana() > 0)){ + if(members[gi] && (members[gi]->GetMaxMana() > 0)){ distance = caster->DistNoRoot(*members[gi]); if(distance <= range2){ From b5ec35e672b0bb098ef14c7d18f0e60dbfc6aafa Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 5 Sep 2014 15:27:12 -0700 Subject: [PATCH 12/24] DelegateMainTank converted to QueryDatabase --- zone/groups.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 83c997836..9dc417aa1 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1326,15 +1326,12 @@ void Group::DelegateMainTank(const char *NewMainTankName, uint8 toggle) } if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - char *Query = nullptr; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='%s' WHERE gid=%i LIMIT 1", - MainTankName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main tank: %s\n", errbuff); - - safe_delete_array(Query); + std::string query = StringFormat("UPDATE group_leaders SET maintank = '%s' WHERE gid = %i LIMIT 1", + MainTankName.c_str(), GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Unable to set group main tank: %s\n", results.ErrorMessage().c_str()); } } From 99fe610f72a4811f566062521cee2044a7545fb7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 5 Sep 2014 15:46:06 -0700 Subject: [PATCH 13/24] DelegatePuller converted to QueryDatabase --- zone/groups.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 9dc417aa1..5033d344c 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1372,15 +1372,13 @@ void Group::DelegateMainAssist(const char *NewMainAssistName, uint8 toggle) } if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - char *Query = nullptr; + std::string query = StringFormat("UPDATE group_leaders SET assist = '%s' WHERE gid = %i LIMIT 1", + MainAssistName.c_str(), GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Unable to set group main assist: %s\n", results.ErrorMessage().c_str()); - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='%s' WHERE gid=%i LIMIT 1", - MainAssistName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main assist: %s\n", errbuff); - - safe_delete_array(Query); } } @@ -1421,15 +1419,13 @@ void Group::DelegatePuller(const char *NewPullerName, uint8 toggle) } if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - char *Query = nullptr; + std::string query = StringFormat("UPDATE group_leaders SET puller = '%s' WHERE gid = %i LIMIT 1", + PullerName.c_str(), GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Unable to set group main puller: %s\n", results.ErrorMessage().c_str()); - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='%s' WHERE gid=%i LIMIT 1", - PullerName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main puller: %s\n", errbuff); - - safe_delete_array(Query); } } From b525a32b6e78b1d70369e8be90c72b045b96e603 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 5 Sep 2014 15:54:07 -0700 Subject: [PATCH 14/24] UndelegateMainTank converted to QueryDatabase --- zone/groups.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 5033d344c..4ed4fc41f 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1571,15 +1571,11 @@ void Group::UnDelegateMainTank(const char *OldMainTankName, uint8 toggle) // informing them of the change and update the group_leaders table. // if(OldMainTankName == MainTankName) { - char errbuff[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main tank: %s\n", errbuff); - - safe_delete_array(Query); + std::string query = StringFormat("UPDATE group_leaders SET maintank = '' WHERE gid = %i LIMIT 1", GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Unable to clear group main tank: %s\n", results.ErrorMessage().c_str()); if(!toggle) { for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { From 5b7aaff1503e90a6a13026eeee24275bdb0e05d1 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 5 Sep 2014 15:58:21 -0700 Subject: [PATCH 15/24] UnDelegateMainAssist converted to QueryDatabase --- zone/groups.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 4ed4fc41f..63dc63822 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1621,15 +1621,10 @@ void Group::UnDelegateMainAssist(const char *OldMainAssistName, uint8 toggle) safe_delete(outapp); - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main assist: %s\n", errbuff); - - safe_delete_array(Query); + std::string query = StringFormat("UPDATE group_leaders SET assist = '' WHERE gid = %i LIMIT 1", GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Unable to clear group main assist: %s\n", results.ErrorMessage().c_str()); if(!toggle) { From 31177b7dc7feae0c96d89800316b4913ce30a081 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 5 Sep 2014 16:04:34 -0700 Subject: [PATCH 16/24] UnDelegatePuller converted to QueryDatabase --- zone/groups.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 63dc63822..6628d67d5 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1648,15 +1648,11 @@ void Group::UnDelegatePuller(const char *OldPullerName, uint8 toggle) // informing them of the change and update the group_leaders table. // if(OldPullerName == PullerName) { - char errbuff[MYSQL_ERRMSG_SIZE]; - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main puller: %s\n", errbuff); - - safe_delete_array(Query); + std::string query = StringFormat("UPDATE group_leaders SET puller = '' WHERE gid = %i LIMIT 1", GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Unable to clear group main puller: %s\n", results.ErrorMessage().c_str()); if(!toggle) { for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { From ef1f1562f004e0d223fa5767dc3e26f900d78c9b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 5 Sep 2014 16:13:50 -0700 Subject: [PATCH 17/24] DelegateMarkNPC converted to QueryDatabase --- zone/groups.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 6628d67d5..2e3d8ecb0 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1787,16 +1787,11 @@ void Group::DelegateMarkNPC(const char *NewNPCMarkerName) if(members[i] && members[i]->IsClient()) NotifyMarkNPC(members[i]->CastToClient()); - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='%s' WHERE gid=%i LIMIT 1", - NewNPCMarkerName, GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group mark npc: %s\n", errbuff); - - safe_delete_array(Query); - + std::string query = StringFormat("UPDATE group_leaders SET marknpc = '%s' WHERE gid = %i LIMIT 1", + NewNPCMarkerName, GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Unable to set group mark npc: %s\n", results.ErrorMessage().c_str()); } void Group::NotifyMarkNPC(Client *c) From 59618e0038ca2582a678e32c0422222367ed8227 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Fri, 5 Sep 2014 16:14:28 -0700 Subject: [PATCH 18/24] UnDelegateMarkNPC converted to QueryDatabase --- zone/groups.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 2e3d8ecb0..6c0200250 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1868,15 +1868,12 @@ void Group::UnDelegateMarkNPC(const char *OldNPCMarkerName) NPCMarkerName.clear(); - char errbuff[MYSQL_ERRMSG_SIZE]; - char *Query = 0; + std::string query = StringFormat("UPDATE group_leaders SET marknpc = '' WHERE gid = %i LIMIT 1", GetID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Unable to clear group marknpc: %s\n", results.ErrorMessage().c_str()); - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group marknpc: %s\n", errbuff); - - safe_delete_array(Query); } void Group::SaveGroupLeaderAA() From c57292a9dd33f79980def3f50402b1bdfcf60e08 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 25 Sep 2014 14:54:40 -0700 Subject: [PATCH 19/24] Tired of this GLM warning (and we dont even use glm rotate grr) also reworked how I approached that peq entity process crash after thinking about it a bit --- CMakeLists.txt | 1 + zone/entity.cpp | 52 ++++++++++++++++++++++++++++--------------------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d0b6a632..8f9c5429b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,6 +289,7 @@ ADD_DEFINITIONS(-DLOG_LEVEL_DEBUG=${EQEMU_LOG_LEVEL_DEBUG}) ADD_DEFINITIONS(-DLOG_LEVEL_QUEST=${EQEMU_LOG_LEVEL_QUEST}) ADD_DEFINITIONS(-DLOG_LEVEL_COMMANDS=${EQEMU_LOG_LEVEL_COMMANDS}) ADD_DEFINITIONS(-DLOG_LEVEL_CRASH=${EQEMU_LOG_LEVEL_CRASH}) +ADD_DEFINITIONS(-DGLM_FORCE_RADIANS) IF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=true) diff --git a/zone/entity.cpp b/zone/entity.cpp index 243bf99f5..fd031d618 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -490,22 +490,36 @@ void EntityList::MobProcess() #endif auto it = mob_list.begin(); while (it != mob_list.end()) { - if (!it->second) { + uint16 id = it->first; + Mob *mob = it->second; + + size_t sz = mob_list.size(); + bool p_val = mob->Process(); + size_t a_sz = mob_list.size(); + + if(a_sz > sz) { + //increased size can potentially screw with iterators so reset it to current value + //if buckets are re-orderered we may skip a process here and there but since + //process happens so often it shouldn't matter much + it = mob_list.find(id); + ++it; + } else { ++it; - continue; } - if (!it->second->Process()) { - Mob *mob = it->second; - uint16 tempid = it->first; - if (mob->IsNPC()) { - entity_list.RemoveNPC(mob->CastToNPC()->GetID()); - } else if (mob->IsMerc()) { - entity_list.RemoveMerc(mob->CastToMerc()->GetID()); + + if(!p_val) { + if(mob->IsNPC()) { + entity_list.RemoveNPC(id); + } + else if(mob->IsMerc()) { + entity_list.RemoveMerc(id); #ifdef BOTS - } else if (mob->IsBot()) { - entity_list.RemoveBot(mob->CastToBot()->GetID()); + } + else if(mob->IsBot()) { + entity_list.RemoveBot(id); #endif - } else { + } + else { #ifdef _WINDOWS struct in_addr in; in.s_addr = mob->CastToClient()->GetIP(); @@ -513,25 +527,19 @@ void EntityList::MobProcess() #endif zone->StartShutdownTimer(); Group *g = GetGroupByMob(mob); - if (g) { + if(g) { LogFile->write(EQEMuLog::Error, "About to delete a client still in a group."); g->DelMember(mob); } Raid *r = entity_list.GetRaidByClient(mob->CastToClient()); - if (r) { + if(r) { LogFile->write(EQEMuLog::Error, "About to delete a client still in a raid."); r->MemberZoned(mob->CastToClient()); } - entity_list.RemoveClient(mob->GetID()); + entity_list.RemoveClient(id); } - if(entity_list.RemoveMob(tempid)) { - it = mob_list.begin(); - } else { - ++it; - } - } else { - ++it; + entity_list.RemoveMob(id); } } } From 039e321ddeedb74872fc0a0599daa1f47e9cf638 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 25 Sep 2014 18:48:58 -0400 Subject: [PATCH 20/24] More re-enumeration prep work --- common/misc_functions.cpp | 23 +++ common/misc_functions.h | 2 + common/patches/client62.cpp | 16 -- common/patches/client62_ops.h | 53 +++---- common/patches/rof_ops.h | 282 ++++++++++++++++----------------- common/patches/sod_ops.h | 198 ++++++++++++----------- common/patches/sof_ops.h | 164 ++++++++++--------- common/patches/titanium.cpp | 16 -- common/patches/titanium_ops.h | 79 +++++---- common/patches/underfoot_ops.h | 216 +++++++++++++------------ 10 files changed, 516 insertions(+), 533 deletions(-) diff --git a/common/misc_functions.cpp b/common/misc_functions.cpp index e7b581733..882cc61c7 100644 --- a/common/misc_functions.cpp +++ b/common/misc_functions.cpp @@ -387,3 +387,26 @@ float EQHtoFloat(int d) { return(360.0f - float((d * 360) >> 11)); } + +// returns a swapped-bit value for use in client translator and inventory functions +uint32 SwapBits21and22(uint32 mask) +{ + static const uint32 BIT21 = 1 << 21; + static const uint32 BIT22 = 1 << 22; + static const uint32 SWAPBITS = (BIT21 | BIT22); + + if ((bool)(mask & BIT21) != (bool)(mask & BIT22)) + mask ^= SWAPBITS; + + return mask; +} + +// returns an unset bit 22 value for use in client translators +uint32 Catch22(uint32 mask) +{ + static const uint32 KEEPBITS = ~(1 << 22); + + mask &= KEEPBITS; + + return mask; +} diff --git a/common/misc_functions.h b/common/misc_functions.h index c057af8d8..abc9747b5 100644 --- a/common/misc_functions.h +++ b/common/misc_functions.h @@ -102,6 +102,8 @@ int FloatToEQ13(float d); int NewFloatToEQ13(float d); int FloatToEQ19(float d); int FloatToEQH(float d); +uint32 SwapBits21and22(uint32 mask); +uint32 Catch22(uint32 mask); // macro to catch fp errors (provided by noudness) #define FCMP(a,b) (fabs(a-b) < FLT_EPSILON) diff --git a/common/patches/client62.cpp b/common/patches/client62.cpp index 10cc331ec..494049876 100644 --- a/common/patches/client62.cpp +++ b/common/patches/client62.cpp @@ -131,22 +131,6 @@ static inline uint32 Client62ToServerCorpseSlot(uint32 Client62Corpse) { // reserved } */ -/* -static inline uint32 RemovePowerSourceBit(uint32 slots) { // shouldn't need to add one..just grab the actual server reference, if so... - static const uint32 BIT21 = 1 << 21; - static const uint32 BIT22 = 1 << 22; - static const uint32 KEEPBITS = ~(BIT21 | BIT22); - - bool wearammo = slots & BIT22; - - slots &= KEEPBITS; - - if (wearammo) - slots |= BIT21; - - return slots; -} -*/ EAT_ENCODE(OP_ZoneServerReady) diff --git a/common/patches/client62_ops.h b/common/patches/client62_ops.h index 5f1a1b4a0..8f544ccfc 100644 --- a/common/patches/client62_ops.h +++ b/common/patches/client62_ops.h @@ -1,36 +1,35 @@ - -//list of packets we need to encode on the way out: +// out-going packets that require an ENCODE translation: +E(OP_Action) +E(OP_BazaarSearch) +E(OP_BecomeTrader) +E(OP_CharInventory) +E(OP_DeleteSpawn) +E(OP_GuildMemberLevelUpdate) +E(OP_GuildMemberList) +E(OP_Illusion) +E(OP_ItemLinkResponse) +E(OP_ItemPacket) +E(OP_LeadershipExpUpdate) +E(OP_NewSpawn) +E(OP_OnLevelMessage) +E(OP_PetBuffWindow) +E(OP_PlayerProfile) +E(OP_ReadBook) +E(OP_RespondAA) E(OP_SendAATable) E(OP_SendCharInfo) -E(OP_LeadershipExpUpdate) -E(OP_PlayerProfile) -E(OP_NewSpawn) -E(OP_ZoneSpawns) -E(OP_ZoneEntry) -E(OP_ItemPacket) -E(OP_ItemLinkResponse) -E(OP_CharInventory) -E(OP_GuildMemberList) -E(OP_ZoneServerReady) -E(OP_GuildMemberLevelUpdate) -E(OP_ReadBook) -E(OP_Illusion) E(OP_Track) -E(OP_BazaarSearch) -E(OP_RespondAA) -E(OP_DeleteSpawn) E(OP_WearChange) -E(OP_Action) -E(OP_BecomeTrader) -E(OP_PetBuffWindow) -E(OP_OnLevelMessage) -//list of packets we need to decode on the way in: -D(OP_SetServerFilter) +E(OP_ZoneEntry) +E(OP_ZoneServerReady) +E(OP_ZoneSpawns) +// incoming packets that require a DECODE translation: D(OP_CharacterCreate) -D(OP_ItemLinkClick) -D(OP_WhoAllRequest) -D(OP_ReadBook) D(OP_FaceChange) +D(OP_ItemLinkClick) +D(OP_ReadBook) +D(OP_SetServerFilter) D(OP_WearChange) +D(OP_WhoAllRequest) #undef E #undef D diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 9e3a91c7e..030c331d6 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -1,162 +1,160 @@ - -//list of packets we need to encode on the way out: - -E(OP_SendCharInfo) -E(OP_ZoneServerInfo) -E(OP_SendAATable) -E(OP_PlayerProfile) -E(OP_ZoneEntry) -E(OP_CharInventory) -E(OP_NewZone) -E(OP_SpawnDoor) -E(OP_GroundSpawn) -E(OP_SendZonepoints) -E(OP_NewSpawn) -E(OP_ZoneSpawns) -E(OP_ItemLinkResponse) -E(OP_ItemPacket) -E(OP_GuildMemberList) -E(OP_Illusion) -E(OP_ManaChange) -E(OP_ClientUpdate) -E(OP_LeadershipExpUpdate) -E(OP_ExpansionInfo) -E(OP_LogServer) -E(OP_Damage) -E(OP_Buff) +// out-going packets that require an ENCODE translation: E(OP_Action) -E(OP_Consider) -E(OP_CancelTrade) -E(OP_ShopPlayerSell) -E(OP_DeleteItem) -E(OP_ItemVerifyReply) -E(OP_DeleteCharge) -E(OP_MoveItem) -//E(OP_OpenNewTasksWindow) -E(OP_BazaarSearch) -E(OP_Trader) -E(OP_TraderBuy) -E(OP_LootItem) -E(OP_TributeItem) -E(OP_SomeItemPacketMaybe) -E(OP_ReadBook) -E(OP_Stun) -E(OP_ZonePlayerToBind) E(OP_AdventureMerchantSell) -E(OP_RaidUpdate) -E(OP_RaidJoin) -E(OP_VetRewardsAvaliable) -E(OP_InspectRequest) -E(OP_GroupInvite) -E(OP_GroupFollow) -E(OP_GroupFollow2) -E(OP_GroupUpdate) -E(OP_GroupCancelInvite) -E(OP_WhoAllResponse) -E(OP_Track) -E(OP_ShopPlayerBuy) -E(OP_PetBuffWindow) -E(OP_OnLevelMessage) -E(OP_Barter) +E(OP_AltCurrency) +E(OP_AltCurrencySell) +E(OP_Animation) E(OP_ApplyPoison) +E(OP_Barter) +E(OP_BazaarSearch) +E(OP_BeginCast) +E(OP_BlockedBuffs) +E(OP_Buff) +E(OP_BuffCreate) +E(OP_CancelTrade) +E(OP_CastSpell) E(OP_ChannelMessage) -E(OP_GuildsList) +E(OP_CharInventory) +E(OP_ClickObjectAction) +E(OP_ClientUpdate) +E(OP_Consider) +E(OP_Damage) +E(OP_DeleteCharge) +E(OP_DeleteItem) +E(OP_DeleteSpawn) +E(OP_DisciplineUpdate) +E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzCompass) -E(OP_DzMemberList) E(OP_DzExpeditionList) -E(OP_DzLeaderStatus) E(OP_DzJoinExpeditionConfirm) -E(OP_TargetBuffs) -E(OP_BuffCreate) -E(OP_SpawnAppearance) -E(OP_RespondAA) -E(OP_DisciplineUpdate) -E(OP_AltCurrencySell) -E(OP_AltCurrency) -E(OP_RequestClientZoneChange) -E(OP_ZoneChange) -E(OP_WearChange) -E(OP_ShopRequest) -E(OP_CastSpell) -E(OP_InterruptCast) -E(OP_SendMembership) -E(OP_Animation) -E(OP_HPUpdate) -E(OP_BlockedBuffs) -E(OP_RemoveBlockedBuffs) -E(OP_DeleteSpawn) -E(OP_ClickObjectAction) -E(OP_RecipeAutoCombine) -E(OP_GMTrainSkillConfirm) -E(OP_SkillUpdate) -E(OP_TributeInfo) -E(OP_TaskHistoryReply) -E(OP_TaskDescription) -E(OP_SetGuildRank) -E(OP_MercenaryDataUpdate) -E(OP_MercenaryDataResponse) -E(OP_GuildMemberUpdate) +E(OP_DzLeaderStatus) +E(OP_DzMemberList) +E(OP_ExpansionInfo) E(OP_GMLastName) -E(OP_BeginCast) +E(OP_GMTrainSkillConfirm) +E(OP_GroundSpawn) +E(OP_GroupCancelInvite) +E(OP_GroupFollow) +E(OP_GroupFollow2) +E(OP_GroupInvite) +E(OP_GroupUpdate) +E(OP_GuildMemberList) +E(OP_GuildMemberUpdate) +E(OP_GuildsList) +E(OP_HPUpdate) +E(OP_Illusion) +E(OP_InspectRequest) +E(OP_InterruptCast) +E(OP_ItemLinkResponse) +E(OP_ItemPacket) +E(OP_ItemVerifyReply) +E(OP_LeadershipExpUpdate) +E(OP_LogServer) +E(OP_LootItem) +E(OP_ManaChange) +E(OP_MercenaryDataResponse) +E(OP_MercenaryDataUpdate) +E(OP_MoveItem) +E(OP_NewSpawn) +E(OP_NewZone) +E(OP_OnLevelMessage) +//E(OP_OpenNewTasksWindow) +E(OP_PetBuffWindow) +E(OP_PlayerProfile) +E(OP_RaidJoin) +E(OP_RaidUpdate) +E(OP_ReadBook) +E(OP_RecipeAutoCombine) +E(OP_RemoveBlockedBuffs) +E(OP_RequestClientZoneChange) +E(OP_RespondAA) E(OP_RezzRequest) -//list of packets we need to decode on the way in: -D(OP_SetServerFilter) -D(OP_CharacterCreate) -D(OP_ItemLinkClick) -D(OP_ConsiderCorpse) -D(OP_Consider) -D(OP_ClientUpdate) -D(OP_MoveItem) -D(OP_WhoAllRequest) +E(OP_SendAATable) +E(OP_SendCharInfo) +E(OP_SendMembership) +E(OP_SendZonepoints) +E(OP_SetGuildRank) +E(OP_ShopPlayerBuy) +E(OP_ShopPlayerSell) +E(OP_ShopRequest) +E(OP_SkillUpdate) +E(OP_SomeItemPacketMaybe) +E(OP_SpawnAppearance) +E(OP_SpawnDoor) +E(OP_Stun) +E(OP_TargetBuffs) +E(OP_TaskDescription) +E(OP_TaskHistoryReply) +E(OP_Track) +E(OP_Trader) +E(OP_TraderBuy) +E(OP_TributeInfo) +E(OP_TributeItem) +E(OP_VetRewardsAvaliable) +E(OP_WearChange) +E(OP_WhoAllResponse) +E(OP_ZoneChange) +E(OP_ZoneEntry) +E(OP_ZonePlayerToBind) +E(OP_ZoneServerInfo) +E(OP_ZoneSpawns) +// incoming packets that require a DECODE translation: +D(OP_AdventureMerchantSell) +D(OP_AltCurrencySell) +D(OP_AltCurrencySellSelection) +D(OP_ApplyPoison) +D(OP_AugmentInfo) +D(OP_AugmentItem) +D(OP_BazaarSearch) +D(OP_BlockedBuffs) D(OP_Buff) -D(OP_ShopPlayerSell) -D(OP_Consume) +D(OP_BuffRemoveRequest) D(OP_CastSpell) -D(OP_Save) -D(OP_ItemVerifyRequest) -D(OP_GroupInvite) -D(OP_GroupInvite2) +D(OP_ChannelMessage) +D(OP_CharacterCreate) +D(OP_ClientUpdate) +D(OP_Consider) +D(OP_ConsiderCorpse) +D(OP_Consume) +D(OP_Damage) +D(OP_DeleteItem) +D(OP_EnvDamage) +D(OP_FaceChange) +D(OP_FindPersonRequest) +D(OP_GMLastName) +D(OP_GroupCancelInvite) +D(OP_GroupDisband) D(OP_GroupFollow) D(OP_GroupFollow2) -D(OP_GroupDisband) -D(OP_GroupCancelInvite) -D(OP_FindPersonRequest) -D(OP_TraderBuy) -D(OP_LootItem) -D(OP_TributeItem) -D(OP_ReadBook) -D(OP_AugmentInfo) -D(OP_FaceChange) -D(OP_AdventureMerchantSell) -D(OP_TradeSkillCombine) -D(OP_RaidInvite) -D(OP_InspectRequest) -D(OP_ShopPlayerBuy) -D(OP_BazaarSearch) -D(OP_LoadSpellSet) -D(OP_ApplyPoison) -D(OP_Damage) -D(OP_EnvDamage) -D(OP_ChannelMessage) -D(OP_DeleteItem) -D(OP_AugmentItem) -D(OP_PetCommands) -D(OP_BuffRemoveRequest) -D(OP_AltCurrencySellSelection) -D(OP_AltCurrencySell) -D(OP_ZoneChange) -D(OP_ZoneEntry) -D(OP_ShopRequest) -D(OP_BlockedBuffs) -D(OP_RemoveBlockedBuffs) -D(OP_RecipeAutoCombine) +D(OP_GroupInvite) +D(OP_GroupInvite2) D(OP_GuildDemote) D(OP_GuildRemove) D(OP_GuildStatus) -D(OP_Trader) -D(OP_GMLastName) +D(OP_InspectRequest) +D(OP_ItemLinkClick) +D(OP_ItemVerifyRequest) +D(OP_LoadSpellSet) +D(OP_LootItem) +D(OP_MoveItem) +D(OP_PetCommands) +D(OP_RaidInvite) +D(OP_ReadBook) +D(OP_RecipeAutoCombine) +D(OP_RemoveBlockedBuffs) D(OP_RezzAnswer) +D(OP_Save) +D(OP_SetServerFilter) +D(OP_ShopPlayerBuy) +D(OP_ShopPlayerSell) +D(OP_ShopRequest) +D(OP_Trader) +D(OP_TraderBuy) +D(OP_TradeSkillCombine) +D(OP_TributeItem) +D(OP_WhoAllRequest) +D(OP_ZoneChange) +D(OP_ZoneEntry) #undef E #undef D diff --git a/common/patches/sod_ops.h b/common/patches/sod_ops.h index d7b87d514..792c9e5d3 100644 --- a/common/patches/sod_ops.h +++ b/common/patches/sod_ops.h @@ -1,117 +1,115 @@ - -//list of packets we need to encode on the way out: - -E(OP_SendCharInfo) -E(OP_ZoneServerInfo) -E(OP_SendAATable) -E(OP_PlayerProfile) -E(OP_ZoneEntry) -E(OP_CharInventory) -E(OP_NewZone) -E(OP_SpawnDoor) -E(OP_GroundSpawn) -E(OP_SendZonepoints) -E(OP_NewSpawn) -E(OP_ZoneSpawns) -E(OP_ItemLinkResponse) -E(OP_ItemPacket) -E(OP_GuildMemberList) -E(OP_Illusion) -E(OP_ManaChange) -E(OP_ClientUpdate) -E(OP_LeadershipExpUpdate) -E(OP_ExpansionInfo) -E(OP_LogServer) -E(OP_Damage) -E(OP_Buff) +// out-going packets that require an ENCODE translation: E(OP_Action) -E(OP_Consider) -E(OP_CancelTrade) -E(OP_ShopPlayerSell) -E(OP_DeleteItem) -E(OP_ItemVerifyReply) -E(OP_DeleteCharge) -E(OP_MoveItem) -E(OP_OpenNewTasksWindow) -E(OP_BazaarSearch) -E(OP_Trader) -E(OP_TraderBuy) -E(OP_LootItem) -E(OP_TributeItem) -E(OP_SomeItemPacketMaybe) -E(OP_ReadBook) -E(OP_Stun) -E(OP_ZonePlayerToBind) E(OP_AdventureMerchantSell) -E(OP_RaidUpdate) -E(OP_RaidJoin) -E(OP_VetRewardsAvaliable) -E(OP_InspectRequest) -E(OP_GroupInvite) -E(OP_GroupFollow) -E(OP_GroupFollow2) -E(OP_GroupUpdate) -E(OP_GroupCancelInvite) -E(OP_WhoAllResponse) -E(OP_Track) -E(OP_ShopPlayerBuy) -E(OP_PetBuffWindow) -E(OP_OnLevelMessage) -E(OP_Barter) +E(OP_AltCurrencySell) E(OP_ApplyPoison) +E(OP_Barter) +E(OP_BazaarSearch) +E(OP_Buff) +E(OP_CancelTrade) +E(OP_CharInventory) +E(OP_ClientUpdate) +E(OP_Consider) +E(OP_Damage) +E(OP_DeleteCharge) +E(OP_DeleteItem) +E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzCompass) -E(OP_DzMemberList) E(OP_DzExpeditionList) -E(OP_DzLeaderStatus) E(OP_DzJoinExpeditionConfirm) -E(OP_TargetBuffs) -E(OP_AltCurrencySell) -E(OP_WearChange) +E(OP_DzLeaderStatus) +E(OP_DzMemberList) +E(OP_ExpansionInfo) +E(OP_GroundSpawn) +E(OP_GroupCancelInvite) +E(OP_GroupFollow) +E(OP_GroupFollow2) +E(OP_GroupInvite) +E(OP_GroupUpdate) +E(OP_GuildMemberList) +E(OP_Illusion) +E(OP_InspectRequest) +E(OP_ItemLinkResponse) +E(OP_ItemPacket) +E(OP_ItemVerifyReply) +E(OP_LeadershipExpUpdate) +E(OP_LogServer) +E(OP_LootItem) +E(OP_ManaChange) E(OP_MercenaryDataResponse) E(OP_MercenaryDataUpdate) -//list of packets we need to decode on the way in: -D(OP_SetServerFilter) -D(OP_CharacterCreate) -D(OP_ItemLinkClick) -D(OP_ConsiderCorpse) -D(OP_Consider) -D(OP_ClientUpdate) -D(OP_MoveItem) -D(OP_WhoAllRequest) +E(OP_MoveItem) +E(OP_NewSpawn) +E(OP_NewZone) +E(OP_OnLevelMessage) +E(OP_OpenNewTasksWindow) +E(OP_PetBuffWindow) +E(OP_PlayerProfile) +E(OP_RaidJoin) +E(OP_RaidUpdate) +E(OP_ReadBook) +E(OP_SendAATable) +E(OP_SendCharInfo) +E(OP_SendZonepoints) +E(OP_ShopPlayerBuy) +E(OP_ShopPlayerSell) +E(OP_SomeItemPacketMaybe) +E(OP_SpawnDoor) +E(OP_Stun) +E(OP_TargetBuffs) +E(OP_Track) +E(OP_Trader) +E(OP_TraderBuy) +E(OP_TributeItem) +E(OP_VetRewardsAvaliable) +E(OP_WearChange) +E(OP_WhoAllResponse) +E(OP_ZoneEntry) +E(OP_ZonePlayerToBind) +E(OP_ZoneServerInfo) +E(OP_ZoneSpawns) +// incoming packets that require a DECODE translation: +D(OP_AdventureMerchantSell) +D(OP_AltCurrencySell) +D(OP_AltCurrencySellSelection) +D(OP_ApplyPoison) +D(OP_AugmentInfo) +D(OP_AugmentItem) +D(OP_BazaarSearch) D(OP_Buff) -D(OP_ShopPlayerSell) -D(OP_Consume) +D(OP_Bug) D(OP_CastSpell) -D(OP_Save) -D(OP_ItemVerifyRequest) -D(OP_GroupInvite) -D(OP_GroupInvite2) +D(OP_CharacterCreate) +D(OP_ClientUpdate) +D(OP_Consider) +D(OP_ConsiderCorpse) +D(OP_Consume) +D(OP_DeleteItem) +D(OP_FaceChange) +D(OP_FindPersonRequest) +D(OP_GroupCancelInvite) +D(OP_GroupDisband) D(OP_GroupFollow) D(OP_GroupFollow2) -D(OP_GroupDisband) -D(OP_GroupCancelInvite) -D(OP_FindPersonRequest) -D(OP_TraderBuy) -D(OP_LootItem) -D(OP_TributeItem) -D(OP_ReadBook) -D(OP_AugmentInfo) -D(OP_FaceChange) -D(OP_AdventureMerchantSell) -D(OP_TradeSkillCombine) -D(OP_RaidInvite) +D(OP_GroupInvite) +D(OP_GroupInvite2) D(OP_InspectRequest) -D(OP_WearChange) -D(OP_ShopPlayerBuy) -D(OP_BazaarSearch) +D(OP_ItemLinkClick) +D(OP_ItemVerifyRequest) D(OP_LoadSpellSet) -D(OP_ApplyPoison) -D(OP_DeleteItem) -D(OP_AugmentItem) -D(OP_Bug) -D(OP_AltCurrencySellSelection) -D(OP_AltCurrencySell) +D(OP_LootItem) +D(OP_MoveItem) +D(OP_RaidInvite) +D(OP_ReadBook) +D(OP_Save) +D(OP_SetServerFilter) +D(OP_ShopPlayerBuy) +D(OP_ShopPlayerSell) +D(OP_TraderBuy) +D(OP_TradeSkillCombine) +D(OP_TributeItem) +D(OP_WearChange) +D(OP_WhoAllRequest) #undef E #undef D diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index ac8dd2008..f039c2189 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -1,100 +1,98 @@ - -//list of packets we need to encode on the way out: - -E(OP_SendCharInfo) -E(OP_ZoneServerInfo) -E(OP_SendAATable) -E(OP_PlayerProfile) -E(OP_ZoneEntry) -E(OP_CharInventory) -E(OP_NewZone) -E(OP_SpawnDoor) -E(OP_GroundSpawn) -E(OP_SendZonepoints) -E(OP_NewSpawn) -E(OP_ZoneSpawns) -E(OP_ItemLinkResponse) -E(OP_ItemPacket) -E(OP_GuildMemberList) -E(OP_Illusion) -E(OP_ManaChange) -E(OP_ClientUpdate) -E(OP_LeadershipExpUpdate) -E(OP_ExpansionInfo) -E(OP_LogServer) -E(OP_Damage) -E(OP_Buff) +// out-going packets that require an ENCODE translation: E(OP_Action) -E(OP_Consider) -E(OP_CancelTrade) -E(OP_ShopPlayerSell) -E(OP_DeleteItem) -E(OP_ItemVerifyReply) -E(OP_DeleteCharge) -E(OP_MoveItem) -E(OP_OpenNewTasksWindow) -E(OP_BazaarSearch) -E(OP_Trader) -E(OP_TraderBuy) -E(OP_LootItem) -E(OP_TributeItem) -E(OP_SomeItemPacketMaybe) -E(OP_ReadBook) -E(OP_Stun) -E(OP_ZonePlayerToBind) E(OP_AdventureMerchantSell) -E(OP_RaidUpdate) -E(OP_RaidJoin) -E(OP_VetRewardsAvaliable) -E(OP_InspectRequest) -E(OP_Track) -E(OP_DeleteSpawn) +E(OP_AltCurrencySell) E(OP_ApplyPoison) +E(OP_BazaarSearch) +E(OP_BecomeTrader) +E(OP_Buff) +E(OP_CancelTrade) +E(OP_CharInventory) +E(OP_ClientUpdate) +E(OP_Consider) +E(OP_Damage) +E(OP_DeleteCharge) +E(OP_DeleteItem) +E(OP_DeleteSpawn) +E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzCompass) -E(OP_DzMemberList) E(OP_DzExpeditionList) -E(OP_DzLeaderStatus) E(OP_DzJoinExpeditionConfirm) -E(OP_BecomeTrader) -E(OP_PetBuffWindow) +E(OP_DzLeaderStatus) +E(OP_DzMemberList) +E(OP_ExpansionInfo) +E(OP_GroundSpawn) +E(OP_GuildMemberList) +E(OP_Illusion) +E(OP_InspectRequest) +E(OP_ItemLinkResponse) +E(OP_ItemPacket) +E(OP_ItemVerifyReply) +E(OP_LeadershipExpUpdate) +E(OP_LogServer) +E(OP_LootItem) +E(OP_ManaChange) +E(OP_MoveItem) +E(OP_NewSpawn) +E(OP_NewZone) E(OP_OnLevelMessage) -E(OP_AltCurrencySell) +E(OP_OpenNewTasksWindow) +E(OP_PetBuffWindow) +E(OP_PlayerProfile) +E(OP_RaidJoin) +E(OP_RaidUpdate) +E(OP_ReadBook) +E(OP_SendAATable) +E(OP_SendCharInfo) +E(OP_SendZonepoints) +E(OP_ShopPlayerSell) +E(OP_SomeItemPacketMaybe) +E(OP_SpawnDoor) +E(OP_Stun) +E(OP_Track) +E(OP_Trader) +E(OP_TraderBuy) +E(OP_TributeItem) +E(OP_VetRewardsAvaliable) E(OP_WearChange) -//list of packets we need to decode on the way in: -D(OP_SetServerFilter) -D(OP_CharacterCreate) -D(OP_ItemLinkClick) -D(OP_ConsiderCorpse) -D(OP_Consider) -D(OP_ClientUpdate) -D(OP_MoveItem) -D(OP_WhoAllRequest) +E(OP_ZoneEntry) +E(OP_ZonePlayerToBind) +E(OP_ZoneServerInfo) +E(OP_ZoneSpawns) +// incoming packets that require a DECODE translation: +D(OP_AdventureMerchantSell) +D(OP_AltCurrencySell) +D(OP_AltCurrencySellSelection) +D(OP_ApplyPoison) +D(OP_AugmentInfo) +D(OP_AugmentItem) D(OP_Buff) -D(OP_ShopPlayerSell) -D(OP_Consume) D(OP_CastSpell) -D(OP_Save) -D(OP_ItemVerifyRequest) +D(OP_CharacterCreate) +D(OP_ClientUpdate) +D(OP_Consider) +D(OP_ConsiderCorpse) +D(OP_Consume) +D(OP_DeleteItem) +D(OP_FaceChange) +D(OP_FindPersonRequest) D(OP_GroupFollow) D(OP_GroupFollow2) -D(OP_FindPersonRequest) -D(OP_TraderBuy) -D(OP_LootItem) -D(OP_TributeItem) -D(OP_ReadBook) -D(OP_AugmentInfo) -D(OP_FaceChange) -D(OP_AdventureMerchantSell) -D(OP_TradeSkillCombine) -D(OP_RaidInvite) D(OP_InspectRequest) +D(OP_ItemLinkClick) +D(OP_ItemVerifyRequest) +D(OP_LootItem) +D(OP_MoveItem) +D(OP_RaidInvite) +D(OP_ReadBook) +D(OP_Save) +D(OP_SetServerFilter) +D(OP_ShopPlayerSell) +D(OP_TraderBuy) +D(OP_TradeSkillCombine) +D(OP_TributeItem) D(OP_WearChange) -D(OP_ApplyPoison) -D(OP_DeleteItem) -D(OP_AugmentItem) -D(OP_AltCurrencySellSelection) -D(OP_AltCurrencySell) +D(OP_WhoAllRequest) #undef E #undef D diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index c79fa5d4f..77d87cb7d 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -133,22 +133,6 @@ static inline uint32 TitaniumToServerCorpseSlot(uint32 TitaniumCorpse) { // reserved } */ -/* -static inline uint32 RemovePowerSourceBit(uint32 slots) { // shouldn't need to add one..just grab the actual server reference, if so... - static const uint32 BIT21 = 1 << 21; - static const uint32 BIT22 = 1 << 22; - static const uint32 KEEPBITS = ~(BIT21 | BIT22); - - bool wearammo = slots & BIT22; - - slots &= KEEPBITS; - - if (wearammo) - slots |= BIT21; - - return slots; -} -*/ EAT_ENCODE(OP_ZoneServerReady) diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index ead6bcecc..40651a652 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -1,53 +1,52 @@ - -//list of packets we need to encode on the way out: -E(OP_SendCharInfo) -E(OP_SendAATable) -E(OP_LeadershipExpUpdate) -E(OP_PlayerProfile) -E(OP_NewSpawn) -E(OP_ZoneSpawns) -E(OP_ZoneEntry) -E(OP_CharInventory) -E(OP_ItemLinkResponse) -E(OP_ItemPacket) +// out-going packets that require an ENCODE translation: +E(OP_Action) E(OP_BazaarSearch) -E(OP_GuildMemberList) -E(OP_ZoneServerReady) -E(OP_GuildMemberLevelUpdate) -E(OP_Trader) -E(OP_TraderBuy) -E(OP_ReadBook) -E(OP_Illusion) -E(OP_VetRewardsAvaliable) -E(OP_InspectRequest) -E(OP_InspectAnswer) -E(OP_Track) -E(OP_RespondAA) +E(OP_BecomeTrader) +E(OP_CharInventory) E(OP_DeleteSpawn) -E(OP_WearChange) +E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzCompass) -E(OP_DzMemberList) E(OP_DzExpeditionList) -E(OP_DzLeaderStatus) E(OP_DzJoinExpeditionConfirm) -E(OP_Action) -E(OP_BecomeTrader) -E(OP_PetBuffWindow) -E(OP_OnLevelMessage) +E(OP_DzLeaderStatus) +E(OP_DzMemberList) +E(OP_GuildMemberLevelUpdate) +E(OP_GuildMemberList) +E(OP_Illusion) +E(OP_InspectAnswer) +E(OP_InspectRequest) +E(OP_ItemLinkResponse) +E(OP_ItemPacket) +E(OP_LeadershipExpUpdate) E(OP_LFGuild) -//list of packets we need to decode on the way in: -D(OP_SetServerFilter) +E(OP_OnLevelMessage) +E(OP_PetBuffWindow) +E(OP_PlayerProfile) +E(OP_NewSpawn) +E(OP_ReadBook) +E(OP_RespondAA) +E(OP_SendCharInfo) +E(OP_SendAATable) +E(OP_Track) +E(OP_Trader) +E(OP_TraderBuy) +E(OP_VetRewardsAvaliable) +E(OP_WearChange) +E(OP_ZoneEntry) +E(OP_ZoneServerReady) +E(OP_ZoneSpawns) +// incoming packets that require a DECODE translation: D(OP_CharacterCreate) -D(OP_ItemLinkClick) -D(OP_TraderBuy) -D(OP_WhoAllRequest) -D(OP_ReadBook) D(OP_FaceChange) -D(OP_InspectRequest) D(OP_InspectAnswer) -D(OP_WearChange) +D(OP_InspectRequest) +D(OP_ItemLinkClick) D(OP_LFGuild) +D(OP_ReadBook) +D(OP_SetServerFilter) +D(OP_TraderBuy) +D(OP_WearChange) +D(OP_WhoAllRequest) #undef E #undef D diff --git a/common/patches/underfoot_ops.h b/common/patches/underfoot_ops.h index 7aa9caf50..28864301d 100644 --- a/common/patches/underfoot_ops.h +++ b/common/patches/underfoot_ops.h @@ -1,128 +1,126 @@ - -//list of packets we need to encode on the way out: - -E(OP_SendCharInfo) -E(OP_ZoneServerInfo) -E(OP_SendAATable) -E(OP_PlayerProfile) -E(OP_ZoneEntry) -E(OP_CharInventory) -E(OP_NewZone) -E(OP_SpawnDoor) -E(OP_GroundSpawn) -E(OP_SendZonepoints) -E(OP_NewSpawn) -E(OP_ZoneSpawns) -E(OP_ItemLinkResponse) -E(OP_ItemPacket) -E(OP_GuildMemberList) -E(OP_Illusion) -E(OP_ManaChange) -E(OP_ClientUpdate) -E(OP_LeadershipExpUpdate) -E(OP_ExpansionInfo) -E(OP_LogServer) -E(OP_Damage) -E(OP_Buff) +// out-going packets that require an ENCODE translation: E(OP_Action) -E(OP_Consider) -E(OP_CancelTrade) -E(OP_ShopPlayerSell) -E(OP_DeleteItem) -E(OP_ItemVerifyReply) -E(OP_DeleteCharge) -E(OP_MoveItem) -E(OP_OpenNewTasksWindow) -E(OP_BazaarSearch) -E(OP_Trader) -E(OP_TraderBuy) -E(OP_LootItem) -E(OP_TributeItem) -E(OP_SomeItemPacketMaybe) -E(OP_ReadBook) -E(OP_Stun) -E(OP_ZonePlayerToBind) E(OP_AdventureMerchantSell) -E(OP_RaidUpdate) -E(OP_RaidJoin) -E(OP_VetRewardsAvaliable) -E(OP_InspectRequest) -E(OP_GroupInvite) -E(OP_GroupFollow) -E(OP_GroupFollow2) -E(OP_GroupUpdate) -E(OP_GroupCancelInvite) -E(OP_WhoAllResponse) -E(OP_Track) -E(OP_ShopPlayerBuy) -E(OP_PetBuffWindow) -E(OP_OnLevelMessage) -E(OP_Barter) +E(OP_AltCurrency) +E(OP_AltCurrencySell) E(OP_ApplyPoison) +E(OP_Barter) +E(OP_BazaarSearch) +E(OP_Buff) +E(OP_BuffCreate) +E(OP_CancelTrade) E(OP_ChannelMessage) -E(OP_GuildsList) +E(OP_CharInventory) +E(OP_ClientUpdate) +E(OP_Consider) +E(OP_Damage) +E(OP_DeleteCharge) +E(OP_DeleteItem) +E(OP_DisciplineUpdate) +E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzCompass) -E(OP_DzMemberList) E(OP_DzExpeditionList) -E(OP_DzLeaderStatus) E(OP_DzJoinExpeditionConfirm) -E(OP_TargetBuffs) -E(OP_BuffCreate) -E(OP_SpawnAppearance) -E(OP_RespondAA) -E(OP_DisciplineUpdate) -E(OP_AltCurrencySell) -E(OP_AltCurrency) -E(OP_WearChange) +E(OP_DzLeaderStatus) +E(OP_DzMemberList) +E(OP_ExpansionInfo) +E(OP_GroundSpawn) +E(OP_GroupCancelInvite) +E(OP_GroupFollow) +E(OP_GroupFollow2) +E(OP_GroupInvite) +E(OP_GroupUpdate) +E(OP_GuildMemberList) +E(OP_GuildsList) +E(OP_Illusion) +E(OP_InspectRequest) +E(OP_ItemLinkResponse) +E(OP_ItemPacket) +E(OP_ItemVerifyReply) +E(OP_LeadershipExpUpdate) +E(OP_LogServer) +E(OP_LootItem) +E(OP_ManaChange) E(OP_MercenaryDataResponse) E(OP_MercenaryDataUpdate) -//list of packets we need to decode on the way in: -D(OP_SetServerFilter) -D(OP_CharacterCreate) -D(OP_ItemLinkClick) -D(OP_ConsiderCorpse) -D(OP_Consider) -D(OP_ClientUpdate) -D(OP_MoveItem) -D(OP_WhoAllRequest) +E(OP_MoveItem) +E(OP_NewSpawn) +E(OP_NewZone) +E(OP_OnLevelMessage) +E(OP_OpenNewTasksWindow) +E(OP_PetBuffWindow) +E(OP_PlayerProfile) +E(OP_RaidJoin) +E(OP_RaidUpdate) +E(OP_ReadBook) +E(OP_RespondAA) +E(OP_SendAATable) +E(OP_SendCharInfo) +E(OP_SendZonepoints) +E(OP_ShopPlayerBuy) +E(OP_ShopPlayerSell) +E(OP_SomeItemPacketMaybe) +E(OP_SpawnAppearance) +E(OP_SpawnDoor) +E(OP_Stun) +E(OP_TargetBuffs) +E(OP_Track) +E(OP_Trader) +E(OP_TraderBuy) +E(OP_TributeItem) +E(OP_VetRewardsAvaliable) +E(OP_WearChange) +E(OP_WhoAllResponse) +E(OP_ZoneEntry) +E(OP_ZonePlayerToBind) +E(OP_ZoneServerInfo) +E(OP_ZoneSpawns) +// incoming packets that require a DECODE translation: +D(OP_AdventureMerchantSell) +D(OP_AltCurrencySell) +D(OP_AltCurrencySellSelection) +D(OP_ApplyPoison) +D(OP_AugmentInfo) +D(OP_AugmentItem) +D(OP_BazaarSearch) D(OP_Buff) -D(OP_ShopPlayerSell) -D(OP_Consume) +D(OP_BuffRemoveRequest) D(OP_CastSpell) -D(OP_Save) -D(OP_ItemVerifyRequest) -D(OP_GroupInvite) -D(OP_GroupInvite2) +D(OP_ChannelMessage) +D(OP_CharacterCreate) +D(OP_ClientUpdate) +D(OP_Consider) +D(OP_ConsiderCorpse) +D(OP_Consume) +D(OP_Damage) +D(OP_DeleteItem) +D(OP_EnvDamage) +D(OP_FaceChange) +D(OP_FindPersonRequest) +D(OP_GroupCancelInvite) +D(OP_GroupDisband) D(OP_GroupFollow) D(OP_GroupFollow2) -D(OP_GroupDisband) -D(OP_GroupCancelInvite) -D(OP_FindPersonRequest) -D(OP_TraderBuy) -D(OP_LootItem) -D(OP_TributeItem) -D(OP_ReadBook) -D(OP_AugmentInfo) -D(OP_FaceChange) -D(OP_AdventureMerchantSell) -D(OP_TradeSkillCombine) -D(OP_RaidInvite) +D(OP_GroupInvite) +D(OP_GroupInvite2) D(OP_InspectRequest) -D(OP_WearChange) -D(OP_ShopPlayerBuy) -D(OP_BazaarSearch) +D(OP_ItemLinkClick) +D(OP_ItemVerifyRequest) D(OP_LoadSpellSet) -D(OP_ApplyPoison) -D(OP_Damage) -D(OP_EnvDamage) -D(OP_ChannelMessage) -D(OP_DeleteItem) -D(OP_AugmentItem) +D(OP_LootItem) +D(OP_MoveItem) D(OP_PetCommands) -D(OP_BuffRemoveRequest) -D(OP_AltCurrencySellSelection) -D(OP_AltCurrencySell) +D(OP_RaidInvite) +D(OP_ReadBook) +D(OP_Save) +D(OP_SetServerFilter) +D(OP_ShopPlayerBuy) +D(OP_ShopPlayerSell) +D(OP_TraderBuy) +D(OP_TradeSkillCombine) +D(OP_TributeItem) +D(OP_WearChange) +D(OP_WhoAllRequest) #undef E #undef D From 723e5d536ab3edb59cfda7c1c24a234eb171e1ad Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 25 Sep 2014 21:20:59 -0400 Subject: [PATCH 21/24] EQEmu::IsTradeskill uint32 to SkillUseTypes --- common/skills.cpp | 2 +- common/skills.h | 2 +- world/client.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/skills.cpp b/common/skills.cpp index 96b87c4a9..2eefd49c8 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -18,7 +18,7 @@ #include "types.h" #include "skills.h" -bool EQEmu::IsTradeskill(uint32 skill) +bool EQEmu::IsTradeskill(SkillUseTypes skill) { switch (skill) { case SkillFishing: diff --git a/common/skills.h b/common/skills.h index 15876cedc..939223e56 100644 --- a/common/skills.h +++ b/common/skills.h @@ -262,7 +262,7 @@ typedef enum { // for skill related helper functions namespace EQEmu { - bool IsTradeskill(uint32 skill); + bool IsTradeskill(SkillUseTypes skill); } #endif diff --git a/world/client.cpp b/world/client.cpp index 9120ce70b..ad82f11fe 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1797,7 +1797,7 @@ void Client::SetClassStartingSkills(PlayerProfile_Struct *pp) if (i >= SkillSpecializeAbjure && i <= SkillSpecializeEvocation) continue; - if (EQEmu::IsTradeskill(i) || i == SkillBegging) + if (EQEmu::IsTradeskill((SkillUseTypes)i) || i == SkillBegging) continue; pp->skills[i] = database.GetSkillCap(pp->class_, (SkillUseTypes)i, 1); From 61b784e96e14b82a499eb5774bf71008bc7178ea Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 25 Sep 2014 21:35:17 -0400 Subject: [PATCH 22/24] Add tests for skills utilities --- tests/CMakeLists.txt | 1 + tests/main.cpp | 2 ++ tests/skills_util_test.h | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 tests/skills_util_test.h diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 428e8b5b1..1c13ae26c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,7 @@ SET(tests_headers ipc_mutex_test.h memory_mapped_file_test.h string_util_test.h + skills_util_test.h ) ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers}) diff --git a/tests/main.cpp b/tests/main.cpp index 9d9b658f9..d64dfead4 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -28,6 +28,7 @@ #include "hextoi_32_64_test.h" #include "string_util_test.h" #include "data_verification_test.h" +#include "skills_util_test.h" int main() { try { @@ -42,6 +43,7 @@ int main() { tests.add(new hextoi_32_64_Test()); tests.add(new StringUtilTest()); tests.add(new DataVerificationTest()); + tests.add(new SkillsUtilsTest()); tests.run(*output, true); } catch(...) { return -1; diff --git a/tests/skills_util_test.h b/tests/skills_util_test.h new file mode 100644 index 000000000..63b5cde5a --- /dev/null +++ b/tests/skills_util_test.h @@ -0,0 +1,42 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_TESTS_SKILLS_UTILS_H +#define __EQEMU_TESTS_SKILLS_UTILS_H + +#include "cppunit/cpptest.h" +#include "../common/skills.h" + +class SkillsUtilsTest: public Test::Suite { + typedef void(SkillsUtilsTest::*TestFunction)(void); +public: + SkillsUtilsTest() { + TEST_ADD(SkillsUtilsTest::IsTradeskill); + } + + ~SkillsUtilsTest() { + } + + private: + void IsTradeskill() { + TEST_ASSERT(EQEmu::IsTradeskill(SkillPottery)); + TEST_ASSERT(!EQEmu::IsTradeskill(SkillParry)); + } +}; + +#endif From 0f12a740747be849961007013fde47786f4639bb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 25 Sep 2014 21:40:31 -0400 Subject: [PATCH 23/24] Add bool EQEmu::IsSpecializedSkill(SkillUseTypes skill) --- common/skills.cpp | 16 ++++++++++++++++ common/skills.h | 1 + tests/skills_util_test.h | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/common/skills.cpp b/common/skills.cpp index 2eefd49c8..24a32196e 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -38,3 +38,19 @@ bool EQEmu::IsTradeskill(SkillUseTypes skill) return false; } } + +bool EQEmu::IsSpecializedSkill(SkillUseTypes skill) +{ + // this could be a simple if, but if this is more portable if any IDs change (probably won't) + // or any other specialized are added (also unlikely) + switch (skill) { + case SkillSpecializeAbjure: + case SkillSpecializeAlteration: + case SkillSpecializeConjuration: + case SkillSpecializeDivination: + case SkillSpecializeEvocation: + return true; + default: + return false; + } +} diff --git a/common/skills.h b/common/skills.h index 939223e56..b4064ab3f 100644 --- a/common/skills.h +++ b/common/skills.h @@ -263,6 +263,7 @@ typedef enum { // for skill related helper functions namespace EQEmu { bool IsTradeskill(SkillUseTypes skill); + bool IsSpecializedSkill(SkillUseTypes skill); } #endif diff --git a/tests/skills_util_test.h b/tests/skills_util_test.h index 63b5cde5a..96507256e 100644 --- a/tests/skills_util_test.h +++ b/tests/skills_util_test.h @@ -27,6 +27,7 @@ class SkillsUtilsTest: public Test::Suite { public: SkillsUtilsTest() { TEST_ADD(SkillsUtilsTest::IsTradeskill); + TEST_ADD(SkillsUtilsTest::IsSpecializedSkill); } ~SkillsUtilsTest() { @@ -37,6 +38,11 @@ public: TEST_ASSERT(EQEmu::IsTradeskill(SkillPottery)); TEST_ASSERT(!EQEmu::IsTradeskill(SkillParry)); } + + void IsSpecializedSkill() { + TEST_ASSERT(EQEmu::IsSpecializedSkill(SkillSpecializeConjuration)); + TEST_ASSERT(!EQEmu::IsSpecializedSkill(SkillConjuration)) + } }; #endif From 179400c7778d18570aa13da642187eca7bfe670d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 26 Sep 2014 00:44:51 -0400 Subject: [PATCH 24/24] Client::SetClassStartingSkills should now match live --- world/client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index ad82f11fe..a373004e1 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1794,10 +1794,10 @@ void Client::SetClassStartingSkills(PlayerProfile_Struct *pp) { for (uint32 i = 0; i <= HIGHEST_SKILL; ++i) { if (pp->skills[i] == 0) { - if (i >= SkillSpecializeAbjure && i <= SkillSpecializeEvocation) - continue; - - if (EQEmu::IsTradeskill((SkillUseTypes)i) || i == SkillBegging) + // Skip specialized, tradeskills (fishing excluded), Alcohol Tolerance, and Bind Wound + if (EQEmu::IsSpecializedSkill((SkillUseTypes)i) || + (EQEmu::IsTradeskill((SkillUseTypes)i) && i != SkillFishing) || + i == SkillAlcoholTolerance || i == SkillBindWound) continue; pp->skills[i] = database.GetSkillCap(pp->class_, (SkillUseTypes)i, 1);