diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b14a09c79..8bbfce4e9 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2359,7 +2359,6 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { return false; } DBnpcspells_Struct* parentlist = database.GetNPCSpells(spell_list->parent_list); - uint32 i; #if MobAI_DEBUG_Spells >= 10 std::string debug_msg = StringFormat("Loading NPCSpells onto %s: dbspellsid=%u", this->GetName(), iDBSpellsID); if (spell_list) { @@ -2414,14 +2413,11 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { _idle_no_sp_recast_min = parentlist->idle_no_sp_recast_min; _idle_no_sp_recast_max = parentlist->idle_no_sp_recast_max; _idle_beneficial_chance = parentlist->idle_beneficial_chance; - for (i=0; inumentries; i++) { - if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spellid > 0) { - if (!IsSpellInList(spell_list, parentlist->entries[i].spellid)) + for (auto &e : parentlist->entries) { + if (GetLevel() >= e.minlevel && GetLevel() <= e.maxlevel && e.spellid > 0) { + if (!IsSpellInList(spell_list, e.spellid)) { - AddSpellToNPCList(parentlist->entries[i].priority, - parentlist->entries[i].spellid, parentlist->entries[i].type, - parentlist->entries[i].manacost, parentlist->entries[i].recast_delay, - parentlist->entries[i].resist_adjust); + AddSpellToNPCList(e.priority, e.spellid, e.type, e.manacost, e.recast_delay, e.resist_adjust); } } } @@ -2460,14 +2456,12 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { _idle_beneficial_chance = spell_list->idle_beneficial_chance; } - for (i=0; inumentries; i++) { - if (GetLevel() >= spell_list->entries[i].minlevel && GetLevel() <= spell_list->entries[i].maxlevel && spell_list->entries[i].spellid > 0) { - AddSpellToNPCList(spell_list->entries[i].priority, - spell_list->entries[i].spellid, spell_list->entries[i].type, - spell_list->entries[i].manacost, spell_list->entries[i].recast_delay, - spell_list->entries[i].resist_adjust); + for (auto &e : spell_list->entries) { + if (GetLevel() >= e.minlevel && GetLevel() <= e.maxlevel && e.spellid > 0) { + AddSpellToNPCList(e.priority, e.spellid, e.type, e.manacost, e.recast_delay, e.resist_adjust); } } + std::sort(AIspells.begin(), AIspells.end(), [](const AISpells_Struct& a, const AISpells_Struct& b) { return a.priority > b.priority; }); @@ -2605,11 +2599,9 @@ bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSp } bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) { - for (uint32 i=0; i < spell_list->numentries; i++) { - if (spell_list->entries[i].spellid == iSpellID) - return true; - } - return false; + auto it = std::find_if(spell_list->entries.begin(), spell_list->entries.end(), + [iSpellID](const DBnpcspells_entries_Struct &a) { return a.spellid == iSpellID; }); + return it != spell_list->entries.end(); } // adds a spell to the list, taking into account priority and resorting list as needed. @@ -2664,125 +2656,102 @@ void NPC::AISpellsList(Client *c) return; } -DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { +DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) +{ if (iDBSpellsID == 0) return nullptr; - if (!npc_spells_cache) { - npc_spells_maxid = GetMaxNPCSpellsID() + 50; // TODO: make this better, shitfix to allow dev work - npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1]; - npc_spells_loadtried = new bool[npc_spells_maxid+1]; - for (uint32 i=0; i<=npc_spells_maxid; i++) { - npc_spells_cache[i] = nullptr; - npc_spells_loadtried[i] = false; - } + auto it = npc_spells_cache.find(iDBSpellsID); + + if (it != npc_spells_cache.end()) { // it's in the cache, easy =) + return &it->second; } - if (iDBSpellsID > npc_spells_maxid) - return nullptr; - if (npc_spells_cache[iDBSpellsID]) { // it's in the cache, easy =) - return npc_spells_cache[iDBSpellsID]; - } - - else if (!npc_spells_loadtried[iDBSpellsID]) { // no reason to ask the DB again if we have failed once already - npc_spells_loadtried[iDBSpellsID] = true; + if (!npc_spells_loadtried.count(iDBSpellsID)) { // no reason to ask the DB again if we have failed once already + npc_spells_loadtried.insert(iDBSpellsID); std::string query = StringFormat("SELECT id, parent_list, attack_proc, proc_chance, " - "range_proc, rproc_chance, defensive_proc, dproc_chance, " - "fail_recast, engaged_no_sp_recast_min, engaged_no_sp_recast_max, " - "engaged_b_self_chance, engaged_b_other_chance, engaged_d_chance, " - "pursue_no_sp_recast_min, pursue_no_sp_recast_max, " - "pursue_d_chance, idle_no_sp_recast_min, idle_no_sp_recast_max, " - "idle_b_chance FROM npc_spells WHERE id=%d", iDBSpellsID); - auto results = QueryDatabase(query); - if (!results.Success()) { + "range_proc, rproc_chance, defensive_proc, dproc_chance, " + "fail_recast, engaged_no_sp_recast_min, engaged_no_sp_recast_max, " + "engaged_b_self_chance, engaged_b_other_chance, engaged_d_chance, " + "pursue_no_sp_recast_min, pursue_no_sp_recast_max, " + "pursue_d_chance, idle_no_sp_recast_min, idle_no_sp_recast_max, " + "idle_b_chance FROM npc_spells WHERE id=%d", + iDBSpellsID); + auto results = QueryDatabase(query); + if (!results.Success()) { return nullptr; - } + } - if (results.RowCount() != 1) - return nullptr; + if (results.RowCount() != 1) + return nullptr; - auto row = results.begin(); - uint32 tmpparent_list = atoi(row[1]); - uint16 tmpattack_proc = atoi(row[2]); - uint8 tmpproc_chance = atoi(row[3]); - uint16 tmprange_proc = atoi(row[4]); - int16 tmprproc_chance = atoi(row[5]); - uint16 tmpdefensive_proc = atoi(row[6]); - int16 tmpdproc_chance = atoi(row[7]); - uint32 tmppfail_recast = atoi(row[8]); - uint32 tmpengaged_no_sp_recast_min = atoi(row[9]); - uint32 tmpengaged_no_sp_recast_max = atoi(row[10]); - uint8 tmpengaged_b_self_chance = atoi(row[11]); - uint8 tmpengaged_b_other_chance = atoi(row[12]); - uint8 tmpengaged_d_chance = atoi(row[13]); - uint32 tmppursue_no_sp_recast_min = atoi(row[14]); - uint32 tmppursue_no_sp_recast_max = atoi(row[15]); - uint8 tmppursue_d_chance = atoi(row[16]); - uint32 tmpidle_no_sp_recast_min = atoi(row[17]); - uint32 tmpidle_no_sp_recast_max = atoi(row[18]); - uint8 tmpidle_b_chance = atoi(row[19]); + auto row = results.begin(); + DBnpcspells_Struct spell_set; + + spell_set.parent_list = atoi(row[1]); + spell_set.attack_proc = atoi(row[2]); + spell_set.proc_chance = atoi(row[3]); + spell_set.range_proc = atoi(row[4]); + spell_set.rproc_chance = atoi(row[5]); + spell_set.defensive_proc = atoi(row[6]); + spell_set.dproc_chance = atoi(row[7]); + spell_set.fail_recast = atoi(row[8]); + spell_set.engaged_no_sp_recast_min = atoi(row[9]); + spell_set.engaged_no_sp_recast_max = atoi(row[10]); + spell_set.engaged_beneficial_self_chance = atoi(row[11]); + spell_set.engaged_beneficial_other_chance = atoi(row[12]); + spell_set.engaged_detrimental_chance = atoi(row[13]); + spell_set.pursue_no_sp_recast_min = atoi(row[14]); + spell_set.pursue_no_sp_recast_max = atoi(row[15]); + spell_set.pursue_detrimental_chance = atoi(row[16]); + spell_set.idle_no_sp_recast_min = atoi(row[17]); + spell_set.idle_no_sp_recast_max = atoi(row[18]); + spell_set.idle_beneficial_chance = atoi(row[19]); // pulling fixed values from an auto-increment field is dangerous... - query = StringFormat("SELECT spellid, type, minlevel, maxlevel, " - "manacost, recast_delay, priority, resist_adjust " + query = StringFormat( + "SELECT spellid, type, minlevel, maxlevel, " + "manacost, recast_delay, priority, resist_adjust " #ifdef BOTS - "FROM %s " - "WHERE npc_spells_id=%d ORDER BY minlevel", (iDBSpellsID >= 3001 && iDBSpellsID <= 3016 ? "bot_spells_entries" : "npc_spells_entries"), iDBSpellsID); + "FROM %s " + "WHERE npc_spells_id=%d ORDER BY minlevel", + (iDBSpellsID >= 3001 && iDBSpellsID <= 3016 ? "bot_spells_entries" : "npc_spells_entries"), + iDBSpellsID); #else - "FROM npc_spells_entries " - "WHERE npc_spells_id=%d ORDER BY minlevel", iDBSpellsID); + "FROM npc_spells_entries " + "WHERE npc_spells_id=%d ORDER BY minlevel", + iDBSpellsID); #endif - results = QueryDatabase(query); + results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { return nullptr; - } + } - uint32 tmpSize = sizeof(DBnpcspells_Struct) + (sizeof(DBnpcspells_entries_Struct) * results.RowCount()); - npc_spells_cache[iDBSpellsID] = (DBnpcspells_Struct*) new uchar[tmpSize]; - memset(npc_spells_cache[iDBSpellsID], 0, tmpSize); - npc_spells_cache[iDBSpellsID]->parent_list = tmpparent_list; - npc_spells_cache[iDBSpellsID]->attack_proc = tmpattack_proc; - npc_spells_cache[iDBSpellsID]->proc_chance = tmpproc_chance; - npc_spells_cache[iDBSpellsID]->range_proc = tmprange_proc; - npc_spells_cache[iDBSpellsID]->rproc_chance = tmprproc_chance; - npc_spells_cache[iDBSpellsID]->defensive_proc = tmpdefensive_proc; - npc_spells_cache[iDBSpellsID]->dproc_chance = tmpdproc_chance; - npc_spells_cache[iDBSpellsID]->fail_recast = tmppfail_recast; - npc_spells_cache[iDBSpellsID]->engaged_no_sp_recast_min = tmpengaged_no_sp_recast_min; - npc_spells_cache[iDBSpellsID]->engaged_no_sp_recast_max = tmpengaged_no_sp_recast_max; - npc_spells_cache[iDBSpellsID]->engaged_beneficial_self_chance = tmpengaged_b_self_chance; - npc_spells_cache[iDBSpellsID]->engaged_beneficial_other_chance = tmpengaged_b_other_chance; - npc_spells_cache[iDBSpellsID]->engaged_detrimental_chance = tmpengaged_d_chance; - npc_spells_cache[iDBSpellsID]->pursue_no_sp_recast_min = tmppursue_no_sp_recast_min; - npc_spells_cache[iDBSpellsID]->pursue_no_sp_recast_max = tmppursue_no_sp_recast_max; - npc_spells_cache[iDBSpellsID]->pursue_detrimental_chance = tmppursue_d_chance; - npc_spells_cache[iDBSpellsID]->idle_no_sp_recast_min = tmpidle_no_sp_recast_min; - npc_spells_cache[iDBSpellsID]->idle_no_sp_recast_max = tmpidle_no_sp_recast_max; - npc_spells_cache[iDBSpellsID]->idle_beneficial_chance = tmpidle_b_chance; - npc_spells_cache[iDBSpellsID]->numentries = results.RowCount(); + int entryIndex = 0; + for (row = results.begin(); row != results.end(); ++row, ++entryIndex) { + DBnpcspells_entries_Struct entry; + int spell_id = atoi(row[0]); + entry.spellid = spell_id; + entry.type = atoul(row[1]); + entry.minlevel = atoi(row[2]); + entry.maxlevel = atoi(row[3]); + entry.manacost = atoi(row[4]); + entry.recast_delay = atoi(row[5]); + entry.priority = atoi(row[6]); - int entryIndex = 0; - for (row = results.begin(); row != results.end(); ++row, ++entryIndex) - { - int spell_id = atoi(row[0]); - npc_spells_cache[iDBSpellsID]->entries[entryIndex].spellid = spell_id; - npc_spells_cache[iDBSpellsID]->entries[entryIndex].type = atoul(row[1]); - npc_spells_cache[iDBSpellsID]->entries[entryIndex].minlevel = atoi(row[2]); - npc_spells_cache[iDBSpellsID]->entries[entryIndex].maxlevel = atoi(row[3]); - npc_spells_cache[iDBSpellsID]->entries[entryIndex].manacost = atoi(row[4]); - npc_spells_cache[iDBSpellsID]->entries[entryIndex].recast_delay = atoi(row[5]); - npc_spells_cache[iDBSpellsID]->entries[entryIndex].priority = atoi(row[6]); + if (row[7]) + entry.resist_adjust = atoi(row[7]); + else if (IsValidSpell(spell_id)) + entry.resist_adjust = spells[spell_id].ResistDiff; - if(row[7]) - npc_spells_cache[iDBSpellsID]->entries[entryIndex].resist_adjust = atoi(row[7]); - else if(IsValidSpell(spell_id)) - npc_spells_cache[iDBSpellsID]->entries[entryIndex].resist_adjust = spells[spell_id].ResistDiff; - } + spell_set.entries.push_back(entry); + } - return npc_spells_cache[iDBSpellsID]; + npc_spells_cache.insert(std::make_pair(iDBSpellsID, spell_set)); + + return &npc_spells_cache[iDBSpellsID]; } return nullptr; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e23d534c5..1de044973 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -34,28 +34,15 @@ ZoneDatabase::ZoneDatabase(const char* host, const char* user, const char* passw void ZoneDatabase::ZDBInitVars() { memset(door_isopen_array, 0, sizeof(door_isopen_array)); - npc_spells_maxid = 0; - npc_spellseffects_maxid = 0; - npc_spells_cache = 0; npc_spellseffects_cache = 0; - npc_spells_loadtried = 0; npc_spellseffects_loadtried = 0; max_faction = 0; faction_array = nullptr; } ZoneDatabase::~ZoneDatabase() { - unsigned int x; - if (npc_spells_cache) { - for (x = 0; x <= npc_spells_maxid; x++) { - safe_delete_array(npc_spells_cache[x]); - } - safe_delete_array(npc_spells_cache); - } - safe_delete_array(npc_spells_loadtried); - if (npc_spellseffects_cache) { - for (x = 0; x <= npc_spellseffects_maxid; x++) { + for (int x = 0; x <= npc_spellseffects_maxid; x++) { safe_delete_array(npc_spellseffects_cache[x]); } safe_delete_array(npc_spellseffects_cache); @@ -63,7 +50,7 @@ ZoneDatabase::~ZoneDatabase() { safe_delete_array(npc_spellseffects_loadtried); if (faction_array != nullptr) { - for (x = 0; x <= max_faction; x++) { + for (int x = 0; x <= max_faction; x++) { if (faction_array[x] != 0) safe_delete(faction_array[x]); } diff --git a/zone/zonedb.h b/zone/zonedb.h index c134dade3..96604ce28 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -1,6 +1,8 @@ #ifndef ZONEDB_H_ #define ZONEDB_H_ +#include + #include "../common/shareddb.h" #include "../common/eq_packet_structs.h" #include "position.h" @@ -75,7 +77,6 @@ struct DBnpcspells_Struct { int16 rproc_chance; uint16 defensive_proc; int16 dproc_chance; - uint32 numentries; uint32 fail_recast; uint32 engaged_no_sp_recast_min; uint32 engaged_no_sp_recast_max; @@ -88,7 +89,7 @@ struct DBnpcspells_Struct { uint32 idle_no_sp_recast_min; uint32 idle_no_sp_recast_max; uint8 idle_beneficial_chance; - DBnpcspells_entries_Struct entries[0]; + std::vector entries; }; struct DBnpcspellseffects_Struct { @@ -524,10 +525,9 @@ protected: uint32 max_faction; Faction** faction_array; - uint32 npc_spells_maxid; uint32 npc_spellseffects_maxid; - DBnpcspells_Struct** npc_spells_cache; - bool* npc_spells_loadtried; + std::unordered_map npc_spells_cache; + std::unordered_set npc_spells_loadtried; DBnpcspellseffects_Struct** npc_spellseffects_cache; bool* npc_spellseffects_loadtried; uint8 door_isopen_array[255];