aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormegamage <none@none>2009-05-24 12:16:12 -0500
committermegamage <none@none>2009-05-24 12:16:12 -0500
commit09b386a78621d177b28df24ca9e13ee25e6d042b (patch)
treed7e68d961d693034b0dfd4ecb027194cdc824d61 /src
parentaa67033cc71c536f4d0f4c1cf6d6444d48103371 (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.h6
-rw-r--r--src/game/DBCfmt.h2
-rw-r--r--src/game/ObjectMgr.cpp84
-rw-r--r--src/game/ObjectMgr.h20
-rw-r--r--src/game/Pet.cpp170
-rw-r--r--src/game/Pet.h4
-rw-r--r--src/game/PetAI.cpp2
-rw-r--r--src/game/PetHandler.cpp3
-rw-r--r--src/game/SpellMgr.cpp123
-rw-r--r--src/game/SpellMgr.h20
-rw-r--r--src/game/World.cpp12
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();