rendered paste bodydiff --git a/sql/updates/ek/mangos_pet_levelspells.sql b/sql/updates/ek/mangos_pet_levelspells.sqlnew file mode 100644index 0000000..3d69228--- /dev/null+++ b/sql/updates/ek/mangos_pet_levelspells.sql@@ -0,0 +1,112 @@+DROP TABLE IF EXISTS `pet_levelspells`;+CREATE TABLE `pet_levelspells` (+ `entry` int(11) unsigned NOT NULL default '0',+ `spell` int(11) unsigned NOT NULL default '0',+ PRIMARY KEY (`entry`,`spell`)+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System';++INSERT INTO `pet_levelspells` VALUES ('15', '19244');+INSERT INTO `pet_levelspells` VALUES ('15', '19505');+INSERT INTO `pet_levelspells` VALUES ('15', '19647');+INSERT INTO `pet_levelspells` VALUES ('15', '19731');+INSERT INTO `pet_levelspells` VALUES ('15', '19734');+INSERT INTO `pet_levelspells` VALUES ('15', '19736');+INSERT INTO `pet_levelspells` VALUES ('15', '27276');+INSERT INTO `pet_levelspells` VALUES ('15', '27277');+INSERT INTO `pet_levelspells` VALUES ('15', '48011');+INSERT INTO `pet_levelspells` VALUES ('15', '54049');+INSERT INTO `pet_levelspells` VALUES ('15', '54050');+INSERT INTO `pet_levelspells` VALUES ('15', '54051');+INSERT INTO `pet_levelspells` VALUES ('15', '54052');+INSERT INTO `pet_levelspells` VALUES ('15', '54053');+INSERT INTO `pet_levelspells` VALUES ('15', '54424');+INSERT INTO `pet_levelspells` VALUES ('15', '57564');+INSERT INTO `pet_levelspells` VALUES ('15', '57565');+INSERT INTO `pet_levelspells` VALUES ('15', '57566');+INSERT INTO `pet_levelspells` VALUES ('15', '57567');+INSERT INTO `pet_levelspells` VALUES ('16', '3716');+INSERT INTO `pet_levelspells` VALUES ('16', '7809');+INSERT INTO `pet_levelspells` VALUES ('16', '7810');+INSERT INTO `pet_levelspells` VALUES ('16', '7811');+INSERT INTO `pet_levelspells` VALUES ('16', '7812');+INSERT INTO `pet_levelspells` VALUES ('16', '11774');+INSERT INTO `pet_levelspells` VALUES ('16', '11775');+INSERT INTO `pet_levelspells` VALUES ('16', '17735');+INSERT INTO `pet_levelspells` VALUES ('16', '17750');+INSERT INTO `pet_levelspells` VALUES ('16', '17751');+INSERT INTO `pet_levelspells` VALUES ('16', '17752');+INSERT INTO `pet_levelspells` VALUES ('16', '17767');+INSERT INTO `pet_levelspells` VALUES ('16', '17850');+INSERT INTO `pet_levelspells` VALUES ('16', '17851');+INSERT INTO `pet_levelspells` VALUES ('16', '17852');+INSERT INTO `pet_levelspells` VALUES ('16', '17853');+INSERT INTO `pet_levelspells` VALUES ('16', '17854');+INSERT INTO `pet_levelspells` VALUES ('16', '19438');+INSERT INTO `pet_levelspells` VALUES ('16', '19440');+INSERT INTO `pet_levelspells` VALUES ('16', '19441');+INSERT INTO `pet_levelspells` VALUES ('16', '19442');+INSERT INTO `pet_levelspells` VALUES ('16', '19443');+INSERT INTO `pet_levelspells` VALUES ('16', '27270');+INSERT INTO `pet_levelspells` VALUES ('16', '27271');+INSERT INTO `pet_levelspells` VALUES ('16', '27272');+INSERT INTO `pet_levelspells` VALUES ('16', '27273');+INSERT INTO `pet_levelspells` VALUES ('16', '33701');+INSERT INTO `pet_levelspells` VALUES ('16', '47984');+INSERT INTO `pet_levelspells` VALUES ('16', '47985');+INSERT INTO `pet_levelspells` VALUES ('16', '47986');+INSERT INTO `pet_levelspells` VALUES ('16', '47987');+INSERT INTO `pet_levelspells` VALUES ('16', '47988');+INSERT INTO `pet_levelspells` VALUES ('16', '47989');+INSERT INTO `pet_levelspells` VALUES ('16', '47990');+INSERT INTO `pet_levelspells` VALUES ('17', '6358');+INSERT INTO `pet_levelspells` VALUES ('17', '6360');+INSERT INTO `pet_levelspells` VALUES ('17', '7813');+INSERT INTO `pet_levelspells` VALUES ('17', '7814');+INSERT INTO `pet_levelspells` VALUES ('17', '7815');+INSERT INTO `pet_levelspells` VALUES ('17', '7816');+INSERT INTO `pet_levelspells` VALUES ('17', '7870');+INSERT INTO `pet_levelspells` VALUES ('17', '11778');+INSERT INTO `pet_levelspells` VALUES ('17', '11779');+INSERT INTO `pet_levelspells` VALUES ('17', '11780');+INSERT INTO `pet_levelspells` VALUES ('17', '11784');+INSERT INTO `pet_levelspells` VALUES ('17', '11785');+INSERT INTO `pet_levelspells` VALUES ('17', '27274');+INSERT INTO `pet_levelspells` VALUES ('17', '27275');+INSERT INTO `pet_levelspells` VALUES ('17', '47991');+INSERT INTO `pet_levelspells` VALUES ('17', '47992');+INSERT INTO `pet_levelspells` VALUES ('23', '2947');+INSERT INTO `pet_levelspells` VALUES ('23', '3110');+INSERT INTO `pet_levelspells` VALUES ('23', '4511');+INSERT INTO `pet_levelspells` VALUES ('23', '6307');+INSERT INTO `pet_levelspells` VALUES ('23', '7799');+INSERT INTO `pet_levelspells` VALUES ('23', '7800');+INSERT INTO `pet_levelspells` VALUES ('23', '7801');+INSERT INTO `pet_levelspells` VALUES ('23', '7802');+INSERT INTO `pet_levelspells` VALUES ('23', '7804');+INSERT INTO `pet_levelspells` VALUES ('23', '7805');+INSERT INTO `pet_levelspells` VALUES ('23', '8316');+INSERT INTO `pet_levelspells` VALUES ('23', '8317');+INSERT INTO `pet_levelspells` VALUES ('23', '11762');+INSERT INTO `pet_levelspells` VALUES ('23', '11763');+INSERT INTO `pet_levelspells` VALUES ('23', '11766');+INSERT INTO `pet_levelspells` VALUES ('23', '11767');+INSERT INTO `pet_levelspells` VALUES ('23', '11770');+INSERT INTO `pet_levelspells` VALUES ('23', '11771');+INSERT INTO `pet_levelspells` VALUES ('23', '27267');+INSERT INTO `pet_levelspells` VALUES ('23', '27268');+INSERT INTO `pet_levelspells` VALUES ('23', '27269');+INSERT INTO `pet_levelspells` VALUES ('23', '47964');+INSERT INTO `pet_levelspells` VALUES ('23', '47982');+INSERT INTO `pet_levelspells` VALUES ('23', '47983');+INSERT INTO `pet_levelspells` VALUES ('29', '30151');+INSERT INTO `pet_levelspells` VALUES ('29', '30194');+INSERT INTO `pet_levelspells` VALUES ('29', '30198');+INSERT INTO `pet_levelspells` VALUES ('29', '30213');+INSERT INTO `pet_levelspells` VALUES ('29', '30219');+INSERT INTO `pet_levelspells` VALUES ('29', '30223');+INSERT INTO `pet_levelspells` VALUES ('29', '33698');+INSERT INTO `pet_levelspells` VALUES ('29', '33699');+INSERT INTO `pet_levelspells` VALUES ('29', '33700');+INSERT INTO `pet_levelspells` VALUES ('29', '47993');+INSERT INTO `pet_levelspells` VALUES ('29', '47994');+INSERT INTO `pet_levelspells` VALUES ('29', '47996');\ No newline at end of filediff --git a/src/game/Pet.cpp b/src/game/Pet.cppindex 3442611..f475cb9 100644--- a/src/game/Pet.cpp+++ b/src/game/Pet.cpp@@ -177,6 +177,25 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool SetUInt32Value(UNIT_NPC_FLAGS, 0); SetName(fields[9].GetString()); + bool petlevelchange = false;+ switch(owner->getClass())+ {+ case CLASS_WARLOCK:+ {+ // if player level up without pet, when player summon a pet, pet auto level up. (only warlock)+ _LoadSpells();+ _LoadSpellCooldowns();++ if(owner->getLevel() > petlevel)+ {+ petlevelchange = true;+ }+ break;+ }+ default:+ break;+ }+ switch(getPetType()) { case SUMMON_PET:@@ -202,6 +221,18 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType()); } + switch(owner->getClass())+ {+ case CLASS_WARLOCK:+ {+ _LoadSpells();+ _LoadSpellCooldowns();+ break;+ }+ default:+ break;+ }+ InitStatsForLevel(petlevel); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32());@@ -295,8 +326,25 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool map->Add((Creature*)this); // Spells should be loaded after pet is added to map, because in CheckCast is check on it- _LoadSpells();- _LoadSpellCooldowns();+ switch(owner->getClass())+ {+ case CLASS_WARLOCK:+ {+ //if player level up to high level without pet, when player summon a pet, pet auto level up. (only warlock)+ if(petlevelchange == true) + {+ InitPetCreateSpells();+ InitStatsForLevel(petlevel);+ }+ break;+ }+ default:+ {+ _LoadSpells();+ _LoadSpellCooldowns();+ break;+ }+ } owner->SetPet(this); // in DB stored only full controlled creature sLog.outDebug("New Pet has guid %u", GetGUIDLow());@@ -745,7 +793,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature) setPowerType(POWER_FOCUS); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);- SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(creature->getLevel())/4);+ SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(creature->getLevel())/10); SetUInt32Value(UNIT_NPC_FLAGS, 0); if(CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))@@ -831,6 +879,9 @@ bool Pet::InitStatsForLevel(uint32 petlevel) uint32 fire = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE); uint32 shadow = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW); uint32 val = (fire > shadow) ? fire : shadow;+ + // WARLOCK+ learnLevelupSpellsWarlock(); SetBonusDamage(int32 (val * 0.15f)); //bonusAP += val * 0.57;@@ -887,7 +938,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel) } case HUNTER_PET: {- SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(petlevel)/4);+ SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(petlevel)/10); learnLevelupSpells(); //these formula may not be correct; however, it is designed to be close to what it should be //this makes dps 0.5 of pets level@@ -1051,7 +1102,7 @@ void Pet::_SaveSpellCooldowns() m_CreatureSpellCooldowns.erase(itr++); else {- CharacterDatabase.PExecute("INSERT INTO pet_spell_cooldown (guid,spell,time) VALUES ('%u', '%u', '" I64FMTD "')", m_charmInfo->GetPetNumber(), itr->first, uint64(itr->second));+ CharacterDatabase.PExecute("INSERT IGNORE INTO pet_spell_cooldown (guid,spell,time) VALUES ('%u', '%u', '" I64FMTD "')", m_charmInfo->GetPetNumber(), itr->first, uint64(itr->second)); ++itr; } }@@ -1083,9 +1134,8 @@ void Pet::_SaveSpells() if (itr->second->type == PETSPELL_FAMILY) continue; // prevent saving family passives to DB if (itr->second->state == PETSPELL_REMOVED || itr->second->state == PETSPELL_CHANGED) CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first);- if (itr->second->state == PETSPELL_NEW || itr->second->state == PETSPELL_CHANGED)- CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second->active);-+ if (itr->second->state == PETSPELL_NEW || itr->second->state == PETSPELL_CHANGED) + CharacterDatabase.PExecute("INSERT IGNORE INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second->active); if (itr->second->state == PETSPELL_REMOVED) _removeSpell(itr->first); else@@ -1370,6 +1420,113 @@ void Pet::learnLevelupSpells() } } +void Pet::learnLevelupSpellsWarlock()+{+ PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family);+ if(!levelupSpells)+ return;++ uint32 level = getLevel();+ uint32 levelspelladd = 0;+ uint32 levelspelldel = 0;++ for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr)+ {+ if((itr->first & 0xffff) <= level) + {+ if (existAddSpell(itr->second) == true) + {+ // add spell+ if(existLowRankOfSpell(itr->second) == false)+ {+ levelspelladd++;+ }+ }+ }+ else + {+ if(existDeleteSpell(itr->second) == true)+ {+ // delete spell+ levelspelldel++;+ }+ }+ }+ if(levelspelladd == 0 && levelspelldel == 0)+ {+ return;+ }+ for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr)+ {+ if((itr->first & 0xffff) <= level) + {+ if(existLowRankOfSpell(itr->second) == false)+ {+ learnSpell(itr->second);+ }+ }+ else + {+ unlearnSpell(itr->second);+ }+ }+}++bool Pet::existLowRankOfSpell(uint32 spell_id)+{+ uint32 levelspelllow = 0;+ for (PetSpellMap::const_iterator sitr = m_spells.begin(), next = m_spells.begin(); sitr != m_spells.end(); sitr = next) {+ ++next;+ if(sitr->first == spell_id) {+ levelspelllow = 1;+ break;+ }+ else if(spellmgr.IsHighRankOfSpell(sitr->first,spell_id)) + {+ levelspelllow = 1;+ break;+ }+ }+ if(levelspelllow)+ {+ return(true);+ }+ return(false);+}++bool Pet::existAddSpell(uint32 spell_id)+{+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);+ if (!spellInfo)+ {+ sLog.outError("Pet::existAddSpell: Non-existed in SpellStore spell #%u request.",spell_id);+ return false;+ }+ PetSpellMap::iterator itr = m_spells.find(spell_id);+ if (itr != m_spells.end())+ {+ if (itr->second->state == PETSPELL_REMOVED)+ {+ }+ else+ return false;+ }+ return true;+}++bool Pet::existDeleteSpell(uint32 spell_id)+{+ PetSpellMap::iterator itr = m_spells.find(spell_id);+ if (itr == m_spells.end())+ return false;++ if(itr->second->state == PETSPELL_REMOVED)+ return false;++ return true;+}++ bool Pet::unlearnSpell(uint32 spell_id) { if(removeSpell(spell_id))diff --git a/src/game/Pet.h b/src/game/Pet.hindex 7f43b06..133f233 100644--- a/src/game/Pet.h+++ b/src/game/Pet.h@@ -192,6 +192,10 @@ class Pet : public Creature bool learnSpell(uint32 spell_id); void learnSpellHighRank(uint32 spellid); void learnLevelupSpells();+ void learnLevelupSpellsWarlock();+ bool existLowRankOfSpell(uint32 spell_id);+ bool existAddSpell(uint32 spell_id);+ bool existDeleteSpell(uint32 spell_id); bool unlearnSpell(uint32 spell_id); bool removeSpell(uint32 spell_id); bool _removeSpell(uint32 spell_id);diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cppindex 7ef35a5..b1796fb 100644--- a/src/game/SpellMgr.cpp+++ b/src/game/SpellMgr.cpp@@ -2114,6 +2114,44 @@ void SpellMgr::LoadPetLevelupSpellMap() SpellEntry const *spell; uint32 count = 0; + #define MAX_PET_SPELL_COUNT 1024+ uint32 pet_spell_db_no = 0;+ uint32 pet_spell_is;+ uint32 pet_spell_count;+ uint32 pet_spell_data[MAX_PET_SPELL_COUNT][2];+ QueryResult *result = WorldDatabase.PQuery("SELECT entry, spell FROM pet_levelspells");+ if(!result)+ {+ sLog.outErrorDb(">> Loaded 0 pet dblevel spells. DB table `pet_levelspells` is empty.");+ pet_spell_db_no = 1;+ }+ else+ {+ pet_spell_count = 0;+ do + {+ Field *fields = result->Fetch();+ + pet_spell_data[pet_spell_count][0] = fields[0].GetUInt32();+ pet_spell_data[pet_spell_count][1] = fields[1].GetUInt32();+ + pet_spell_count++;+ + if(pet_spell_count >= MAX_PET_SPELL_COUNT)+ {+ // Overflow Detect+ sLog.outErrorDb(">> Loaded %u over pet dblevel spells. DB table `pet_levelspells`.",pet_spell_count);+ break;+ }+ }+ while ( result->NextRow() );++ delete result;++ sLog.outString();+ sLog.outString( ">> Loaded %u spell pet dblevel spells", pet_spell_count );+ }+ for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i) { creatureFamily = sCreatureFamilyStore.LookupEntry(i);@@ -2121,8 +2159,33 @@ void SpellMgr::LoadPetLevelupSpellMap() if(!creatureFamily) // not exist continue; - if(creatureFamily->petTalentType < 0) // not hunter pet family- continue;+ if(pet_spell_db_no == 0)+ {+ //WARLOCK+ switch(creatureFamily->ID)+ {+ case CREATURE_FAMILY_IMP:+ case CREATURE_FAMILY_VOIDWALKER:+ case CREATURE_FAMILY_SUCCUBUS:+ case CREATURE_FAMILY_FELHUNTER:+ case CREATURE_FAMILY_FELGUARD:+ pet_spell_is = 1;+ break;+ default:+ pet_spell_is = 0;+ break;+ }+ }+ else+ {+ pet_spell_is = 0;+ }++ if(pet_spell_is == 0)+ {+ if(creatureFamily->petTalentType < 0) // not hunter pet family+ continue;+ } for(uint32 j = 0; j < sSpellStore.GetNumRows(); ++j) {@@ -2131,6 +2194,21 @@ void SpellMgr::LoadPetLevelupSpellMap() // not exist if(!spell) continue;+ + //WARLOCK+ if(pet_spell_is)+ {+ for(uint32 k = 0; k < pet_spell_count; k++)+ {+ if(creatureFamily->ID == pet_spell_data[k][0] && spell->Id == pet_spell_data[k][1])+ {+ mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel + (k*0x10000)] = spell->Id;+ count++;+ break;+ }+ }+ continue;+ } // not hunter spell if(spell->SpellFamilyName != SPELLFAMILY_HUNTER)