diff options
author | megamage <none@none> | 2009-05-24 12:16:12 -0500 |
---|---|---|
committer | megamage <none@none> | 2009-05-24 12:16:12 -0500 |
commit | 09b386a78621d177b28df24ca9e13ee25e6d042b (patch) | |
tree | d7e68d961d693034b0dfd4ecb027194cdc824d61 /src | |
parent | aa67033cc71c536f4d0f4c1cf6d6444d48103371 (diff) |
[7886] Drop use table `petcreateinfo_spell`
This is first commit in chain for remove oudated and not used pet functionality.
* Use instead dropped table CreatureSpellData.dbc if creature_template.PetSpellDataId set (mostly hunter pets)
* Use creature_template.spellN if not set creature_template.PetSpellDataId (mostly different summon creatures)
* Fixed bug with not removing from action bar spell icon for not ranked unlearned spells.
Note: summoned controllable creatures without PetSpellDataId must have expected spells in spellN feilds for creature_template.
[7887] Drop pet spell teaching code, including field in character_pet.
Author: VladimirMangos
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/game/DBCStructure.h | 6 | ||||
-rw-r--r-- | src/game/DBCfmt.h | 2 | ||||
-rw-r--r-- | src/game/ObjectMgr.cpp | 84 | ||||
-rw-r--r-- | src/game/ObjectMgr.h | 20 | ||||
-rw-r--r-- | src/game/Pet.cpp | 170 | ||||
-rw-r--r-- | src/game/Pet.h | 4 | ||||
-rw-r--r-- | src/game/PetAI.cpp | 2 | ||||
-rw-r--r-- | src/game/PetHandler.cpp | 3 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 123 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 20 | ||||
-rw-r--r-- | src/game/World.cpp | 12 |
11 files changed, 209 insertions, 237 deletions
diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index a7433574162..50a543859cd 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -725,11 +725,13 @@ struct CreatureFamilyEntry // 27 m_iconFile }; +#define MAX_CREATURE_SPELL_DATA_SLOT 4 + struct CreatureSpellDataEntry { uint32 ID; // 0 m_ID - //uint32 spellId[4]; // 1-4 m_spells[4] - //uint32 availability[4]; // 4-7 m_availability[4] + uint32 spellId[MAX_CREATURE_SPELL_DATA_SLOT]; // 1-4 m_spells[4] + //uint32 availability[MAX_CREATURE_SPELL_DATA_SLOT]; // 4-7 m_availability[4] }; struct CreatureTypeEntry diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index 77f01edb5a2..9187cc85e3d 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -40,7 +40,7 @@ const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxx const char CinematicSequencesEntryfmt[]="nxxxxxxxxx"; const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx"; const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; -const char CreatureSpellDatafmt[]="nxxxxxxxx"; +const char CreatureSpellDatafmt[]="niiiixxxx"; const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx"; const char CurrencyTypesfmt[]="xnxi"; const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 87e7d10bdcb..d7337fadd77 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3747,90 +3747,6 @@ void ObjectMgr::LoadQuestLocales() sLog.outString( ">> Loaded %lu Quest locale strings", (unsigned long)mQuestLocaleMap.size() ); } -void ObjectMgr::LoadPetCreateSpells() -{ - QueryResult *result = WorldDatabase.Query("SELECT entry, Spell1, Spell2, Spell3, Spell4 FROM petcreateinfo_spell"); - if(!result) - { - barGoLink bar( 1 ); - bar.step(); - - sLog.outString(); - sLog.outString( ">> Loaded 0 pet create spells" ); - sLog.outErrorDb("`petcreateinfo_spell` table is empty!"); - return; - } - - uint32 count = 0; - - barGoLink bar( result->GetRowCount() ); - - mPetCreateSpell.clear(); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 creature_id = fields[0].GetUInt32(); - - if(!creature_id) - { - sLog.outErrorDb("Creature id %u listed in `petcreateinfo_spell` not exist.",creature_id); - continue; - } - - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(creature_id); - if(!cInfo) - { - sLog.outErrorDb("Creature id %u listed in `petcreateinfo_spell` not exist.",creature_id); - continue; - } - - PetCreateSpellEntry PetCreateSpell; - - bool have_spell = false; - bool have_spell_db = false; - for(int i = 0; i < 4; i++) - { - PetCreateSpell.spellid[i] = fields[i + 1].GetUInt32(); - - if(!PetCreateSpell.spellid[i]) - continue; - - have_spell_db = true; - - SpellEntry const* i_spell = sSpellStore.LookupEntry(PetCreateSpell.spellid[i]); - if(!i_spell) - { - sLog.outErrorDb("Spell %u listed in `petcreateinfo_spell` does not exist",PetCreateSpell.spellid[i]); - PetCreateSpell.spellid[i] = 0; - continue; - } - - have_spell = true; - } - - if(!have_spell_db) - { - sLog.outErrorDb("Creature %u listed in `petcreateinfo_spell` have only 0 spell data, why it listed?",creature_id); - continue; - } - - if(!have_spell) - continue; - - mPetCreateSpell[creature_id] = PetCreateSpell; - ++count; - } - while (result->NextRow()); - - delete result; - - sLog.outString(); - sLog.outString( ">> Loaded %u pet create spells", count ); -} - void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) { if(sWorld.IsScriptScheduled()) // function don't must be called in time scripts use. diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 000e95623f4..ca4093f875a 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -195,11 +195,6 @@ struct PointOfInterest std::string icon_name; }; -struct PetCreateSpellEntry -{ - uint32 spellid[4]; -}; - #define WEATHER_SEASONS 4 struct WeatherSeasonChances { @@ -339,8 +334,6 @@ class ObjectMgr typedef UNORDERED_MAP<uint32, WeatherZoneChances> WeatherZoneMap; - typedef UNORDERED_MAP<uint32, PetCreateSpellEntry> PetCreateSpellMap; - typedef std::vector<std::string> ScriptNameMap; UNORDERED_MAP<uint32, uint32> TransportEventMap; @@ -494,14 +487,6 @@ class ObjectMgr return NULL; } - PetCreateSpellEntry const* GetPetCreateSpellEntry(uint32 id) const - { - PetCreateSpellMap::const_iterator itr = mPetCreateSpell.find(id); - if(itr != mPetCreateSpell.end()) - return &itr->second; - return NULL; - } - void LoadGuilds(); void LoadArenaTeams(); void LoadGroups(); @@ -534,8 +519,7 @@ class ObjectMgr bool LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value); bool LoadTrinityStrings() { return LoadTrinityStrings(WorldDatabase,"trinity_string",MIN_TRINITY_STRING_ID,MAX_TRINITY_STRING_ID); } - void LoadDbScriptStrings(); - void LoadPetCreateSpells(); + void LoadDbScriptStrings(); void LoadCreatureLocales(); void LoadCreatureTemplates(); void LoadCreatures(); @@ -867,8 +851,6 @@ class ObjectMgr WeatherZoneMap mWeatherZoneMap; - PetCreateSpellMap mPetCreateSpell; - //character reserved names typedef std::set<std::wstring> ReservedNamesMap; ReservedNamesMap m_ReservedNames; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 24d71ca631f..300106eb2c3 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -93,25 +93,25 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool QueryResult *result; if (petnumber) - // known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType , load_flags " + // known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType, load_flags " "FROM character_pet WHERE owner = '%u' AND id = '%u'", ownerid, petnumber); else if (current) - // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType , load_flags " + // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType, load_flags " "FROM character_pet WHERE owner = '%u' AND slot = '%u'", ownerid, PET_SAVE_AS_CURRENT ); else if (petentry) // known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets) - // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType , load_flags " + // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType, load_flags " "FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '%u' OR slot > '%u') ", ownerid, petentry,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT); else // any current or other non-stabled pet (for hunter "call pet") - // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType , load_flags " + // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType, load_flags " "FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ", ownerid,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT); @@ -128,7 +128,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return false; } - uint32 summon_spell_id = fields[19].GetUInt32(); + uint32 summon_spell_id = fields[18].GetUInt32(); SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id); bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0; @@ -169,7 +169,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return false; } - setPetType(PetType(fields[20].GetUInt8())); + setPetType(PetType(fields[19].GetUInt8())); SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); @@ -253,14 +253,14 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool owner->SetMinion(this, true); map->Add((Creature*)this); - m_resetTalentsCost = fields[17].GetUInt32(); - m_resetTalentsTime = fields[18].GetUInt64(); + m_resetTalentsCost = fields[16].GetUInt32(); + m_resetTalentsTime = fields[17].GetUInt64(); InitTalentForLevel(); - uint32 timediff = (time(NULL) - fields[16].GetUInt32()); + uint32 timediff = (time(NULL) - fields[15].GetUInt32()); _LoadAuras(timediff); - uint8 loadFlags = fields[21].GetUInt8(); + uint8 loadFlags = fields[20].GetUInt8(); owner->SetPetAtLoginFlag(loadFlags); if (loadFlags & AT_LOAD_RESET_SPELLS) { @@ -295,20 +295,6 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool m_charmInfo->GetActionBarEntry(index)->Type = ACT_PASSIVE; } - //init teach spells - tokens = StrSplit(fields[15].GetString(), " "); - for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index) - { - uint32 tmp = atol((*iter).c_str()); - - ++iter; - - if(tmp) - AddTeachSpell(tmp, atol((*iter).c_str())); - else - break; - } - _LoadSpells(); _LoadSpellCooldowns(); LearnPetPassives(); @@ -414,7 +400,7 @@ void Pet::SavePetToDB(PetSaveMode mode) owner,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT); // save pet std::ostringstream ss; - ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType, load_flags) " + ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType, load_flags) " << "VALUES (" << m_charmInfo->GetPetNumber() << ", " << GetEntry() << ", " @@ -433,17 +419,6 @@ void Pet::SavePetToDB(PetSaveMode mode) for(uint32 i = 0; i < 10; ++i) ss << uint32(m_charmInfo->GetActionBarEntry(i)->Type) << " " << uint32(m_charmInfo->GetActionBarEntry(i)->SpellOrAction) << " "; - ss << "', '"; - - //save spells the pet can teach to it's Master - { - int i = 0; - for(TeachSpellMap::const_iterator itr = m_teachspells.begin(); i < 4 && itr != m_teachspells.end(); ++i, ++itr) - ss << itr->first << " " << itr->second << " "; - for(; i < 4; ++i) - ss << uint32(0) << " " << uint32(0) << " "; - } - ss << "', " << time(NULL) << ", " << uint32(m_resetTalentsCost) << ", " @@ -1366,25 +1341,40 @@ bool Pet::learnSpell(uint32 spell_id) void Pet::InitLevelupSpellsForLevel() { - uint32 family = GetCreatureInfo()->family; - if(!family) - return; + uint32 level = getLevel(); - PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(family); - if(!levelupSpells) - return; + if(PetLevelupSpellSet const *levelupSpells = GetCreatureInfo()->family ? spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family) : NULL) + { + // PetLevelupSpellSet ordered by levels, process in reversed order + for(PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr) + { + // will called first if level down + if(itr->first > level) + unlearnSpell(itr->second,true); // will learn prev rank if any + // will called if level up + else + learnSpell(itr->second); // will unlearn prev rank if any + } + } - uint32 level = getLevel(); + int32 petSpellsId = GetCreatureInfo()->PetSpellDataId ? -(int32)GetCreatureInfo()->PetSpellDataId : GetEntry(); - // PetLevelupSpellSet ordered by levels, process in reversed order - for(PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr) + // default spells (can be not learned if pet level (as owner level decrease result for example) less first possible in normal game) + if(PetDefaultSpellsEntry const *defSpells = spellmgr.GetPetDefaultSpellsEntry(petSpellsId)) { - // will called first if level down - if(itr->first > level) - unlearnSpell(itr->second,true); // will learn prev rank if any - // will called if level up - else - learnSpell(itr->second); // will unlearn prev rank if any + for(int i = 0; i < MAX_CREATURE_SPELL_DATA_SLOT; ++i) + { + SpellEntry const* spellEntry = sSpellStore.LookupEntry(defSpells->spellid[i]); + if(!spellEntry) + continue; + + // will called first if level down + if(spellEntry->spellLevel > level) + unlearnSpell(spellEntry->Id,false); + // will called if level up + else + learnSpell(spellEntry->Id); + } } } @@ -1442,14 +1432,16 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev) learnSpell(prev_id); } else - { - m_charmInfo->AddSpellToAB(spell_id, 0); + learn_prev = false; + } - // need update action bar for last removed rank - if (Unit* owner = GetOwner()) - if (owner->GetTypeId() == TYPEID_PLAYER) - ((Player*)owner)->PetSpellInitialize(); - } + // if remove last rank or non-ranked then update action bar at server and client if need + if(!learn_prev && m_charmInfo->AddSpellToAB(spell_id, 0)) + { + // need update action bar for last removed rank + if (Unit* owner = GetOwner()) + if (owner->GetTypeId() == TYPEID_PLAYER) + ((Player*)owner)->PetSpellInitialize(); } return true; @@ -1460,66 +1452,12 @@ void Pet::InitPetCreateSpells() m_charmInfo->InitPetActionBar(); m_spells.clear(); - uint32 petspellid; - PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry()); - if(CreateSpells) - { - for(uint8 i = 0; i < 4; ++i) - { - if(!CreateSpells->spellid[i]) - break; - - SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(CreateSpells->spellid[i]); - if(!learn_spellproto) - continue; - - if(learn_spellproto->Effect[0] == SPELL_EFFECT_LEARN_SPELL || learn_spellproto->Effect[0] == SPELL_EFFECT_LEARN_PET_SPELL) - { - petspellid = learn_spellproto->EffectTriggerSpell[0]; - Unit* owner = GetOwner(); - if(owner->GetTypeId() == TYPEID_PLAYER && !((Player*)owner)->HasSpell(learn_spellproto->Id)) - { - if(IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right - ((Player*)owner)->learnSpell(learn_spellproto->Id,false); - else - AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id); - } - } - else - petspellid = learn_spellproto->Id; - - addSpell(petspellid); - } - } - LearnPetPassives(); InitLevelupSpellsForLevel(); CastPetAuras(false); } -void Pet::CheckLearning(uint32 spellid) -{ - //charmed case -> prevent crash - if(GetTypeId() == TYPEID_PLAYER || getPetType() != HUNTER_PET) - return; - - Unit* owner = GetOwner(); - - if(m_teachspells.empty() || !owner || owner->GetTypeId() != TYPEID_PLAYER) - return; - - TeachSpellMap::iterator itr = m_teachspells.find(spellid); - if(itr == m_teachspells.end()) - return; - - if(urand(0, 100) < 10) - { - ((Player*)owner)->learnSpell(itr->second,false); - m_teachspells.erase(itr); - } -} - bool Pet::resetTalents(bool no_cost) { Unit *owner = GetOwner(); diff --git a/src/game/Pet.h b/src/game/Pet.h index a92d53cecdb..d66e13edf0c 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -113,7 +113,6 @@ enum PetNameInvalidReason }; typedef UNORDERED_MAP<uint32, PetSpell> PetSpellMap; -typedef std::map<uint32,uint32> TeachSpellMap; typedef std::vector<uint32> AutoSpellList; #define HAPPINESS_LEVEL_SIZE 333000 @@ -185,7 +184,6 @@ class Pet : public Guardian void ToggleAutocast(uint32 spellid, bool apply); bool HasSpell(uint32 spell) const; - void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; } void LearnPetPassives(); void CastPetAuras(bool current); @@ -206,11 +204,9 @@ class Pet : public Guardian bool removeSpell(uint32 spell_id, bool learn_prev); PetSpellMap m_spells; - TeachSpellMap m_teachspells; AutoSpellList m_autospells; void InitPetCreateSpells(); - void CheckLearning(uint32 spellid); bool resetTalents(bool no_cost = false); uint32 resetTalentsCost() const; diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index a5a3f28c92a..7851ee6773f 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -199,8 +199,6 @@ void PetAI::UpdateAI(const uint32 diff) } m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id); - if(m_creature->isPet()) - ((Pet*)m_creature)->CheckLearning(spell->m_spellInfo->Id); spell->prepare(&targets); } diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index bfbe8ca7df4..459055383cf 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -250,8 +250,6 @@ void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid if(result == SPELL_CAST_OK) { ((Creature*)pet)->AddCreatureSpellCooldown(spellid); - if (((Creature*)pet)->isPet()) - ((Pet*)pet)->CheckLearning(spellid); unit_target = spell->m_targets.getUnitTarget(); @@ -657,7 +655,6 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) if(pet->isPet()) { Pet* p = (Pet*)pet; - p->CheckLearning(spellid); // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if(p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index a859a672c9e..bad3c94a034 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2005,6 +2005,129 @@ void SpellMgr::LoadPetLevelupSpellMap() sLog.outString( ">> Loaded %u pet levelup and default spells for %u families", count, family_count ); } +bool LoadPetDefaultSpells_helper(CreatureInfo const* cInfo, PetDefaultSpellsEntry& petDefSpells) +{ + // skip empty list; + bool have_spell = false; + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + { + if(petDefSpells.spellid[j]) + { + have_spell = true; + break; + } + } + if(!have_spell) + return false; + + // remove duplicates with levelupSpells if any + if(PetLevelupSpellSet const *levelupSpells = cInfo->family ? spellmgr.GetPetLevelupSpellList(cInfo->family) : NULL) + { + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + { + if(!petDefSpells.spellid[j]) + continue; + + for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) + { + if (itr->second == petDefSpells.spellid[j]) + { + petDefSpells.spellid[j] = 0; + break; + } + } + } + } + + // skip empty list; + have_spell = false; + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + { + if(petDefSpells.spellid[j]) + { + have_spell = true; + break; + } + } + + return have_spell; +} + +void SpellMgr::LoadPetDefaultSpells() +{ + mPetDefaultSpellsMap.clear(); + + uint32 countCreature = 0; + uint32 countData = 0; + + for(uint32 i = 0; i < sCreatureStorage.MaxEntry; ++i ) + { + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i); + if(!cInfo) + continue; + + if(!cInfo->PetSpellDataId) + continue; + + // for creature with PetSpellDataId get default pet spells from dbc + CreatureSpellDataEntry const* spellDataEntry = sCreatureSpellDataStore.LookupEntry(cInfo->PetSpellDataId); + if(!spellDataEntry) + continue; + + int32 petSpellsId = -(int32)cInfo->PetSpellDataId; + PetDefaultSpellsEntry petDefSpells; + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + petDefSpells.spellid[j] = spellDataEntry->spellId[j]; + + if(LoadPetDefaultSpells_helper(cInfo, petDefSpells)) + { + mPetDefaultSpellsMap[petSpellsId] = petDefSpells; + ++countData; + } + } + + // different summon spells + for(uint32 i = 0; i < sSpellStore.GetNumRows(); ++i ) + { + SpellEntry const* spellEntry = sSpellStore.LookupEntry(i); + if(!spellEntry) + continue; + + for(int k = 0; k < 3; ++k) + { + if(spellEntry->Effect[k]==SPELL_EFFECT_SUMMON || spellEntry->Effect[k]==SPELL_EFFECT_SUMMON_PET) + { + uint32 creature_id = spellEntry->EffectMiscValue[k]; + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(creature_id); + if(!cInfo) + continue; + + // already loaded + if(cInfo->PetSpellDataId) + continue; + + // for creature without PetSpellDataId get default pet spells from creature_template + int32 petSpellsId = cInfo->Entry; + if(mPetDefaultSpellsMap.find(cInfo->Entry) != mPetDefaultSpellsMap.end()) + continue; + + PetDefaultSpellsEntry petDefSpells; + for(int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j) + petDefSpells.spellid[j] = cInfo->spells[j]; + + if(LoadPetDefaultSpells_helper(cInfo, petDefSpells)) + { + mPetDefaultSpellsMap[petSpellsId] = petDefSpells; + ++countCreature; + } + } + } + } + + sLog.outString(); + sLog.outString( ">> Loaded addition spells for %u pet spell data entries and %u summonable creature templates", countData, countCreature ); +} + /// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) { diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 0fde7578860..6bcba4cd95c 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -681,6 +681,15 @@ typedef std::multimap<uint32, SkillLineAbilityEntry const*> SkillLineAbilityMap; typedef std::multimap<uint32, uint32> PetLevelupSpellSet; typedef std::map<uint32, PetLevelupSpellSet> PetLevelupSpellMap; +struct PetDefaultSpellsEntry +{ + uint32 spellid[MAX_CREATURE_SPELL_DATA_SLOT]; +}; + +// < 0 for petspelldata id, > 0 for creature_id +typedef std::map<int32, PetDefaultSpellsEntry> PetDefaultSpellsMap; + + inline bool IsPrimaryProfessionSkill(uint32 skill) { SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill); @@ -1004,6 +1013,15 @@ class SpellMgr SpellEffectTargetTypes EffectTargetType[TOTAL_SPELL_EFFECTS]; SpellSelectTargetTypes SpellTargetType[TOTAL_SPELL_TARGETS]; + // < 0 for petspelldata id, > 0 for creature_id + PetDefaultSpellsEntry const* GetPetDefaultSpellsEntry(int32 id) const + { + PetDefaultSpellsMap::const_iterator itr = mPetDefaultSpellsMap.find(id); + if(itr != mPetDefaultSpellsMap.end()) + return &itr->second; + return NULL; + } + SpellCastResult GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL); SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const @@ -1056,6 +1074,7 @@ class SpellMgr void LoadSpellEnchantProcData(); void LoadSpellLinked(); void LoadPetLevelupSpellMap(); + void LoadPetDefaultSpells(); void LoadSpellAreas(); private: @@ -1076,6 +1095,7 @@ class SpellMgr SpellLinkedMap mSpellLinkedMap; SpellEnchantProcEventMap mSpellEnchantProcEventMap; PetLevelupSpellMap mPetLevelupSpellMap; + PetDefaultSpellsMap mPetDefaultSpellsMap; // only spells not listed in related mPetLevelupSpellMap entry SpellAreaMap mSpellAreaMap; SpellAreaForQuestMap mSpellAreaForQuestMap; SpellAreaForQuestMap mSpellAreaForActiveQuestMap; diff --git a/src/game/World.cpp b/src/game/World.cpp index b6cda4ee067..2a08f03c23f 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1255,15 +1255,18 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Points Of Interest Data..." ); objmgr.LoadPointsOfInterest(); - sLog.outString( "Loading Pet Create Spells..." ); - objmgr.LoadPetCreateSpells(); - sLog.outString( "Loading Creature Data..." ); objmgr.LoadCreatures(); sLog.outString( "Loading Creature Linked Respawn..." ); objmgr.LoadCreatureLinkedRespawn(); // must be after LoadCreatures() + sLog.outString( "Loading pet levelup spells..." ); + spellmgr.LoadPetLevelupSpellMap(); + + sLog.outString( "Loading pet default spell additional to levelup spells..." ); + spellmgr.LoadPetDefaultSpells(); + sLog.outString( "Loading Creature Addon Data..." ); sLog.outString(); objmgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures() @@ -1333,9 +1336,6 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading spell pet auras..." ); spellmgr.LoadSpellPetAuras(); - sLog.outString( "Loading pet levelup spells..." ); - spellmgr.LoadPetLevelupSpellMap(); - sLog.outString( "Loading spell extra attributes...(TODO)" ); spellmgr.LoadSpellCustomAttr(); |