diff options
author | QAston <none@none> | 2008-12-14 23:01:02 +0100 |
---|---|---|
committer | QAston <none@none> | 2008-12-14 23:01:02 +0100 |
commit | 42d52c1e1782b9f9bbccf37541fe32865c34cfe5 (patch) | |
tree | 2ba45b5a2783b6f86a90abb283ba0d44857cb365 | |
parent | 9948e98703d8d9044a3b8ad6dbd70a16e6181dc0 (diff) |
*Use prev_spell data calculated on startup instead of sql column.
*Changed map structure of req spell.
*Added precalculated data for next spell in rank and last one.
*Removed duplicated rank entries for some spells and used req_spell column instead.
*Allow required spell to have required spell.
--HG--
branch : trunk
-rw-r--r-- | sql/updates/506_world.sql | 83 | ||||
-rw-r--r-- | src/game/Level3.cpp | 12 | ||||
-rw-r--r-- | src/game/Player.cpp | 25 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 153 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 16 |
5 files changed, 204 insertions, 85 deletions
diff --git a/sql/updates/506_world.sql b/sql/updates/506_world.sql new file mode 100644 index 00000000000..5e4b12d7a16 --- /dev/null +++ b/sql/updates/506_world.sql @@ -0,0 +1,83 @@ +-- added missing entry for 3rd rank of gift of the wild + +DELETE FROM spell_chain WHERE spell_id = 21849; +DELETE FROM spell_chain WHERE spell_id = 21850; +DELETE FROM spell_chain WHERE spell_id = 26991; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (21849,0,21849,1,0); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (21850,21849,21849,2,0); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (26991,21850,21849,3,0); + +-- weaponsmith and armorsmith as blacksmith req spells + +DELETE FROM spell_chain WHERE spell_id = 9787; +DELETE FROM spell_chain WHERE spell_id = 9788; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (9787,0,9787,1,9785); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (9788,0,9788,1,9785); + +-- axe/sword/hammer smith req weaponsmith + +DELETE FROM spell_chain WHERE spell_id = 17039; +DELETE FROM spell_chain WHERE spell_id = 17040; +DELETE FROM spell_chain WHERE spell_id = 17041; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (17039,0,17039,1,9787); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (17040,0,17040,1,9787); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (17041,0,17041,1,9787); + +-- letherworking specs req spells + +DELETE FROM spell_chain WHERE spell_id = 10660; +DELETE FROM spell_chain WHERE spell_id = 10658; +DELETE FROM spell_chain WHERE spell_id = 10656; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (10660,0,10660,1,10662); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (10658,0,10658,1,10662); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (10656,0,10656,1,10662); + +-- alchemy specs req spells + +DELETE FROM spell_chain WHERE spell_id = 28672; +DELETE FROM spell_chain WHERE spell_id = 28675; +DELETE FROM spell_chain WHERE spell_id = 28677; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (28672,0,28672,1,28596); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (28675,0,28675,1,28596); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (28677,0,28677,1,28596); + +-- tailoring specs req spells + +DELETE FROM spell_chain WHERE spell_id = 26801; +DELETE FROM spell_chain WHERE spell_id = 26798; +DELETE FROM spell_chain WHERE spell_id = 26797; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (26801,0,26801,1,26790); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (26798,0,26798,1,26790); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (26797,0,26797,1,26790); + +-- engineering specs req spells + +DELETE FROM spell_chain WHERE spell_id = 20222; +DELETE FROM spell_chain WHERE spell_id = 20219; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (20222,0,20222,1,12656); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (20219,0,20219,1,12656); + +-- divine spirit req spells + +DELETE FROM spell_chain WHERE spell_id = 27681; +DELETE FROM spell_chain WHERE spell_id = 32999; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (27681,0,27681,1,14752); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (32999,27681,27681,2,0); + +-- judgement of justice req seal of justice(dunno what is this for) + +DELETE FROM spell_chain WHERE spell_id = 20184; +DELETE FROM spell_chain WHERE spell_id = 31896; + +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (20184,0,20184,1,20164); +INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (31896,20184,20184,2,0); + +ALTER TABLE spell_chain DROP COLUMN prev_spell;
\ No newline at end of file diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index f66cab42c66..15d9f8f02d2 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1769,12 +1769,16 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) static void learnAllHighRanks(Player* player, uint32 spellid) { - SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); - for(SpellChainMapNext::const_iterator itr = nextMap.lower_bound(spellid); itr != nextMap.upper_bound(spellid); ++itr) + SpellChainNode const* node; + do { - player->learnSpell(itr->second); - learnAllHighRanks(player,itr->second); + node = spellmgr.GetSpellChainNode(spellid); + player->learnSpell(spellid); + if (!node) + break; + spellid=node->next; } + while (node->next); } bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 1b1344473de..1be902f72e4 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2911,12 +2911,12 @@ void Player::learnSpell(uint32 spell_id) bool learning = addSpell(spell_id,active); // learn all disabled higher ranks (recursive) - SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); - for(SpellChainMapNext::const_iterator i = nextMap.lower_bound(spell_id); i != nextMap.upper_bound(spell_id); ++i) + SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id); + if (node) { - PlayerSpellMap::iterator iter = m_spells.find(i->second); - if (disabled && iter != m_spells.end() && iter->second->disabled) - learnSpell(i->second); + PlayerSpellMap::iterator iter = m_spells.find(node->next); + if (disabled && iter != m_spells.end() && iter->second->disabled ) + learnSpell(node->next); } // prevent duplicated entires in spell book @@ -2938,10 +2938,17 @@ void Player::removeSpell(uint32 spell_id, bool disabled) return; // unlearn non talent higher ranks (recursive) - SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); - for(SpellChainMapNext::const_iterator itr2 = nextMap.lower_bound(spell_id); itr2 != nextMap.upper_bound(spell_id); ++itr2) - if(HasSpell(itr2->second) && !GetTalentSpellPos(itr2->second)) - removeSpell(itr2->second,disabled); + SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id); + if (node) + { + if(HasSpell(node->next) && !GetTalentSpellPos(node->next)) + removeSpell(node->next,disabled); + } + //unlearn spells dependent from recently removed spells + SpellRequiredMap const& reqMap = spellmgr.GetSpellRequiredMap(); + SpellRequiredMap::const_iterator itr2 = reqMap.find(spell_id); + for (uint32 i=reqMap.count(spell_id);i>0;i--,itr2++) + removeSpell(itr2->second,disabled); // removing WorldPacket data(SMSG_REMOVED_SPELL, 4); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 4db9eff8c72..07db96ad71e 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1156,11 +1156,6 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool { //if(spellId_1 == spellId_2) // auras due to the same spell // return false; - - //use data of highest rank spell(needed for spells which ranks have different effects) - //spellId_1=GetLastSpellInChain(spellId_1); - //spellId_2=GetLastSpellInChain(spellId_2); - SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1); SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2); @@ -1217,14 +1212,19 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool } } - if(spellInfo_1->SpellFamilyName && IsRankSpellDueToSpell(spellInfo_1, spellId_2)) - return true; +// not needed now because we compare effects last rank of spells +// if(spellInfo_1->SpellFamilyName && IsRankSpellDueToSpell(spellInfo_1, spellId_2)) +// return true; + + //use data of highest rank spell(needed for spells which ranks have different effects) + SpellEntry const *spellInfo1=sSpellStore.LookupEntry(GetLastSpellInChain(spellId_1)); + SpellEntry const *spellInfo2=sSpellStore.LookupEntry(GetLastSpellInChain(spellId_2)); //if spells have exactly the same effect they cannot stack for(uint32 i = 0; i < 3; ++i) - if(spellInfo_1->Effect[i] != spellInfo_2->Effect[i] - || spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i] - || spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i]) // paladin resist aura + if(spellInfo1->Effect[i] != spellInfo2->Effect[i] + || spellInfo1->EffectApplyAuraName[i] != spellInfo2->EffectApplyAuraName[i] + || spellInfo1->EffectMiscValue[i] != spellInfo2->EffectMiscValue[i]) // paladin resist aura return false; // need itemtype check? need an example to add that check return true; @@ -1305,9 +1305,18 @@ SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spell void SpellMgr::LoadSpellChains() { mSpellChains.clear(); // need for reload case - mSpellChainsNext.clear(); // need for reload case + mSpellReq.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query("SELECT spell_id, first_spell, rank, req_spell from spell_chain ORDER BY first_spell, rank"); + + struct SpellChainEntry + { + uint32 spell; + uint32 first; + uint32 req; + uint8 rank; + }; - QueryResult *result = WorldDatabase.Query("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain"); if(result == NULL) { barGoLink bar( 1 ); @@ -1318,8 +1327,9 @@ void SpellMgr::LoadSpellChains() sLog.outErrorDb("`spell_chains` table is empty!"); return; } + uint32 rows = 0; - uint32 count = 0; + SpellChainEntry *SpellChainTable = new SpellChainEntry [result->GetRowCount()]; barGoLink bar( result->GetRowCount() ); do @@ -1327,48 +1337,83 @@ void SpellMgr::LoadSpellChains() bar.step(); Field *fields = result->Fetch(); - uint32 spell_id = fields[0].GetUInt32(); + SpellChainTable[rows].spell = fields[0].GetUInt32(); + SpellChainTable[rows].first = fields[1].GetUInt32(); + SpellChainTable[rows].rank = fields[2].GetUInt32(); + SpellChainTable[rows].req = fields[3].GetUInt32(); + + if (SpellChainTable[rows].req) + mSpellReq.insert (std::pair<uint32, uint32>(SpellChainTable[rows].req, SpellChainTable[rows].spell)); + ++rows; + } while( result->NextRow() ); + delete result; + uint32 cur_row=0; + do + { + uint32 spell_id=SpellChainTable[cur_row].spell; SpellChainNode node; - node.prev = fields[1].GetUInt32(); - node.first = fields[2].GetUInt32(); - node.rank = fields[3].GetUInt8(); - node.req = fields[4].GetUInt32(); + node.first = SpellChainTable[cur_row].first; + node.rank = SpellChainTable[cur_row].rank; + node.req = SpellChainTable[cur_row].req; - if(!sSpellStore.LookupEntry(spell_id)) + //get field "prev" + if (spell_id == node.first || cur_row==0) { - sLog.outErrorDb("Spell %u listed in `spell_chain` does not exist",spell_id); - continue; + if (node.rank!=1) + sLog.outErrorDb("Incorrect rank for entry: %u",spell_id); + node.prev = 0; + } + else if (SpellChainTable[cur_row-1].rank!=node.rank-1) + { + sLog.outErrorDb("Spells %u and %u (first: %u, rank: %d, req: %u) listed in `spell_chain` have not compatible rank data." + ,spell_id,SpellChainTable[cur_row-1].spell,node.first,node.rank,node.req); + node.prev = 0; } + else + node.prev=SpellChainTable[cur_row-1].spell; - if(node.prev!=0 && !sSpellStore.LookupEntry(node.prev)) + //get field "next" + if (cur_row==rows-1 || SpellChainTable[cur_row+1].first!= node.first ) { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existed previous rank spell.", - spell_id,node.prev,node.first,node.rank,node.req); - continue; + //get field "last" + for (uint32 last_row=1;SpellChainTable[cur_row-last_row].first == node.first;last_row++) + mSpellChains[SpellChainTable[cur_row-last_row].spell].last = spell_id; + node.last = spell_id; + node.next = 0; + } + else if (SpellChainTable[cur_row+1].rank!=node.rank+1) + { + sLog.outErrorDb("Spells %u and %u (first: %u, rank: %d, req: %u) listed in `spell_chain` have not compatible rank data." + ,spell_id,SpellChainTable[cur_row+1].spell,node.first,node.rank,node.req); + node.next = 0; + } + else + { + node.next=SpellChainTable[cur_row+1].spell; + node.last=0; } - if(!sSpellStore.LookupEntry(node.first)) + + cur_row++; + + if(!sSpellStore.LookupEntry(spell_id)) { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing first rank spell.", - spell_id,node.prev,node.first,node.rank,node.req); + sLog.outErrorDb("Spell %u listed in `spell_chain` does not exist",spell_id); continue; } - // check basic spell chain data integrity (note: rank can be equal 0 or 1 for first/single spell) - if( (spell_id == node.first) != (node.rank <= 1) || - (spell_id == node.first) != (node.prev == 0) || - (node.rank <= 1) != (node.prev == 0) ) + if(!sSpellStore.LookupEntry(node.first)) { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not compatible chain data.", - spell_id,node.prev,node.first,node.rank,node.req); + sLog.outErrorDb("Spell %u (first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing first rank spell.", + spell_id,node.first,node.rank,node.req); continue; } if(node.req!=0 && !sSpellStore.LookupEntry(node.req)) { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing required spell.", - spell_id,node.prev,node.first,node.rank,node.req); + sLog.outErrorDb("Spell %u (first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing required spell.", + spell_id,node.first,node.rank,node.req); continue; } @@ -1377,8 +1422,8 @@ void SpellMgr::LoadSpellChains() { if(node.rank!=pos->rank+1) { - sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong rank.", - spell_id,node.prev,node.first,node.rank,node.req); + sLog.outErrorDb("Talent %u (first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong rank.", + spell_id,node.first,node.rank,node.req); continue; } @@ -1386,8 +1431,8 @@ void SpellMgr::LoadSpellChains() { if(node.first!=talentEntry->RankID[0]) { - sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong first rank spell.", - spell_id,node.prev,node.first,node.rank,node.req); + sLog.outErrorDb("Talent %u (first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong first rank spell.", + spell_id,node.first,node.rank,node.req); continue; } @@ -1397,26 +1442,14 @@ void SpellMgr::LoadSpellChains() spell_id,node.prev,node.first,node.rank,node.req); continue; } - - if(node.req!=talentEntry->DependsOnSpell) - { - sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong required spell.", - spell_id,node.prev,node.first,node.rank,node.req); - continue; - } } } mSpellChains[spell_id] = node; + } + while( cur_row<rows ); - if(node.prev) - mSpellChainsNext.insert(SpellChainMapNext::value_type(node.prev,spell_id)); - - if(node.req) - mSpellChainsNext.insert(SpellChainMapNext::value_type(node.req,spell_id)); - - ++count; - } while( result->NextRow() ); + delete[] SpellChainTable; // additional integrity checks for(SpellChainMap::iterator i = mSpellChains.begin(); i != mSpellChains.end(); ++i) @@ -1457,19 +1490,11 @@ void SpellMgr::LoadSpellChains() i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, i_req->second.prev,i_req->second.first,i_req->second.rank,i_req->second.req); } - else if( i_req->second.req ) - { - sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has required rank spell with required spell (prev: %u, first: %u, rank: %d, req: %u).", - i->first,i->second.prev,i->second.first,i->second.rank,i->second.req, - i_req->second.prev,i_req->second.first,i_req->second.rank,i_req->second.req); - } } } - delete result; - sLog.outString(); - sLog.outString( ">> Loaded %u spell chain records", count ); + sLog.outString( ">> Loaded %u spell chain records", rows ); } void SpellMgr::LoadSpellLearnSkills() diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 638f93d534b..9a1fe691723 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -634,13 +634,15 @@ typedef std::map<uint16, PetAura> SpellPetAuraMap; struct SpellChainNode { uint32 prev; + uint32 next; uint32 first; + uint32 last; uint32 req; uint8 rank; }; typedef UNORDERED_MAP<uint32, SpellChainNode> SpellChainMap; -typedef std::multimap<uint32, uint32> SpellChainMapNext; +typedef std::multimap<uint32, uint32> SpellRequiredMap; // Spell learning properties (accessed using SpellMgr functions) struct SpellLearnSkillNode @@ -781,7 +783,7 @@ class SpellMgr return 0; } - SpellChainMapNext const& GetSpellChainNext() const { return mSpellChainsNext; } + SpellRequiredMap const& GetSpellRequiredMap() const { return mSpellReq; } // Note: not use rank for compare to spell ranks: spell chains isn't linear order // Use IsHighRankOfSpell instead @@ -795,11 +797,9 @@ class SpellMgr uint32 GetLastSpellInChain(uint32 spell_id) const { - if (!GetSpellChainNode(spell_id)) - return spell_id; - SpellChainMapNext const& nextMap = GetSpellChainNext(); - for(SpellChainMapNext::const_iterator itr = nextMap.lower_bound(spell_id); itr != nextMap.upper_bound(spell_id); ++itr) - spell_id=itr->second; + if(SpellChainNode const* node = GetSpellChainNode(spell_id)) + return node->last; + return spell_id; } @@ -940,7 +940,7 @@ class SpellMgr private: SpellScriptTarget mSpellScriptTarget; SpellChainMap mSpellChains; - SpellChainMapNext mSpellChainsNext; + SpellRequiredMap mSpellReq; SpellLearnSkillMap mSpellLearnSkills; SpellLearnSpellMap mSpellLearnSpells; SpellTargetPositionMap mSpellTargetPositions; |