diff --git a/sql/characters.sql b/sql/characters.sql index c20530a05..fc717c1ef 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_7887_01_characters_character_pet` bit(1) default NULL + `required_7903_01_characters_character_pet` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -472,7 +472,6 @@ CREATE TABLE `character_pet` ( `level` int(11) unsigned NOT NULL default '1', `exp` int(11) unsigned NOT NULL default '0', `Reactstate` tinyint(1) unsigned NOT NULL default '0', - `talentpoints` int(11) unsigned NOT NULL default '0', `name` varchar(100) default 'Pet', `renamed` tinyint(1) unsigned NOT NULL default '0', `slot` int(11) unsigned NOT NULL default '0', diff --git a/sql/updates/7903_01_characters_character_pet.sql b/sql/updates/7903_01_characters_character_pet.sql new file mode 100644 index 000000000..834aac200 --- /dev/null +++ b/sql/updates/7903_01_characters_character_pet.sql @@ -0,0 +1,4 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7887_01_characters_character_pet required_7903_01_characters_character_pet bit; + +ALTER TABLE `character_pet` + DROP `talentpoints`; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index d090aa5af..6e18e6493 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -203,6 +203,7 @@ pkgdata_DATA = \ 7896_01_mangos_creature_template.sql \ 7902_01_mangos_pool_creature.sql \ 7902_02_mangos_pool_gameobject.sql \ + 7903_01_characters_character_pet.sql \ README ## Additional files to include when running 'make dist' @@ -386,4 +387,5 @@ EXTRA_DIST = \ 7896_01_mangos_creature_template.sql \ 7902_01_mangos_pool_creature.sql \ 7902_02_mangos_pool_gameobject.sql \ + 7903_01_characters_character_pet.sql \ README diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 9244736c2..60b7c06b4 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -87,25 +87,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 - 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 " + // known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType " "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 - 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 " + // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType " "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 - 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 " + // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType " "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 - 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 " + // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ", ownerid,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT); @@ -122,7 +122,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return false; } - uint32 summon_spell_id = fields[18].GetUInt32(); + uint32 summon_spell_id = fields[17].GetUInt32(); SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id); bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0; @@ -164,7 +164,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return false; } - setPetType(PetType(fields[19].GetUInt8())); + setPetType(PetType(fields[18].GetUInt8())); SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); @@ -184,7 +184,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool SetNativeDisplayId(fields[3].GetUInt32()); uint32 petlevel = fields[4].GetUInt32(); SetUInt32Value(UNIT_NPC_FLAGS, 0); - SetName(fields[9].GetString()); + SetName(fields[8].GetString()); switch (getPetType()) { @@ -197,14 +197,13 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool break; case HUNTER_PET: SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); - SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[7].GetUInt32()); SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - SetByteValue(UNIT_FIELD_BYTES_2, 2, fields[10].GetBool() ? UNIT_RENAME_NOT_ALLOWED : UNIT_RENAME_ALLOWED); + SetByteValue(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_RENAME_NOT_ALLOWED : UNIT_RENAME_ALLOWED); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet abandon, cancel) SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); - SetPower(POWER_HAPPINESS, fields[13].GetUInt32()); + SetPower(POWER_HAPPINESS, fields[12].GetUInt32()); setPowerType(POWER_FOCUS); break; default: @@ -215,20 +214,22 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool SetPvP(true); InitStatsForLevel(petlevel); + InitTalentForLevel(); // set original talents points before spell loading + SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); SetCreatorGUID(owner->GetGUID()); m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8())); - uint32 savedhealth = fields[11].GetUInt32(); - uint32 savedmana = fields[12].GetUInt32(); + uint32 savedhealth = fields[10].GetUInt32(); + uint32 savedmana = fields[11].GetUInt32(); // set current pet as current // 0=current // 1..MAX_PET_STABLES in stable slot // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning)) - if (fields[8].GetUInt32() != 0) + if (fields[7].GetUInt32() != 0) { CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u' AND id <> '%u'", @@ -240,7 +241,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool if (!is_temporary_summoned) { - if(!m_charmInfo->LoadActionBar(fields[14].GetCppString())) + if(!m_charmInfo->LoadActionBar(fields[13].GetCppString())) { delete result; return false; @@ -248,10 +249,10 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool } // since last save (in seconds) - uint32 timediff = (time(NULL) - fields[15].GetUInt32()); + uint32 timediff = (time(NULL) - fields[14].GetUInt32()); - m_resetTalentsCost = fields[16].GetUInt32(); - m_resetTalentsTime = fields[17].GetUInt64(); + m_resetTalentsCost = fields[15].GetUInt32(); + m_resetTalentsTime = fields[16].GetUInt64(); delete result; @@ -394,7 +395,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, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) " + ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) " << "VALUES (" << m_charmInfo->GetPetNumber() << ", " << GetEntry() << ", " @@ -403,7 +404,6 @@ void Pet::SavePetToDB(PetSaveMode mode) << getLevel() << ", " << GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", " << uint32(m_charmInfo->GetReactState()) << ", " - << uint32(GetFreeTalentPoints()) << ", " << uint32(mode) << ", '" << name.c_str() << "', " << uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", " @@ -1093,7 +1093,17 @@ void Pet::_LoadSpells() { Field *fields = result->Fetch(); - addSpell(fields[0].GetUInt32(), ActiveStates(fields[1].GetUInt16()), PETSPELL_UNCHANGED); + uint32 spell_id = fields[0].GetUInt32(); + + // load only pet talents, other spell types auto-learned + if(GetTalentSpellCost(spell_id)==0) + { + CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE spell = '%u'",spell_id); + sLog.outError("Table `pet_spell` have non-talent spell %u , spell removed from table for all pets.",spell_id); + continue; + } + + addSpell(spell_id, ActiveStates(fields[1].GetUInt16()), PETSPELL_UNCHANGED,PETSPELL_TALENT); } while( result->NextRow() ); @@ -1107,8 +1117,8 @@ void Pet::_SaveSpells() { ++next; - // prevent saving family passives to DB - if (itr->second.type == PETSPELL_FAMILY) + // save only talent spells for pets, other spells auto-applied + if (itr->second.type != PETSPELL_TALENT) continue; switch(itr->second.state) @@ -1319,6 +1329,9 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel // talent: unlearn all other talent ranks (high and low) if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id)) { + // propertly mark spell for allow save + newspell.type = PETSPELL_TALENT; + if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id )) { for(int i=0; i < MAX_TALENT_RANK; ++i) diff --git a/src/game/Pet.h b/src/game/Pet.h index 510738731..223675a88 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -65,6 +65,7 @@ enum PetSpellType { PETSPELL_NORMAL = 0, PETSPELL_FAMILY = 1, + PETSPELL_TALENT = 2, }; struct PetSpell diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 2728cb06c..de1b34343 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7902" + #define REVISION_NR "7903" #endif // __REVISION_NR_H__