aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/2928_characters_character_pet.sql2
-rw-r--r--src/game/CreatureEventAI.cpp2
-rw-r--r--src/game/Level3.cpp7
-rw-r--r--src/game/Pet.cpp113
-rw-r--r--src/game/Pet.h6
-rw-r--r--src/game/Player.cpp46
-rw-r--r--src/game/Player.h5
7 files changed, 85 insertions, 96 deletions
diff --git a/sql/updates/2928_characters_character_pet.sql b/sql/updates/2928_characters_character_pet.sql
new file mode 100644
index 00000000000..95a34404413
--- /dev/null
+++ b/sql/updates/2928_characters_character_pet.sql
@@ -0,0 +1,2 @@
+ALTER TABLE character_pet ADD load_flags INT(3) DEFAULT '0' NOT NULL AFTER teachspelldata;
+UPDATE characters SET at_login = at_login & ~16 WHERE at_login & 16;
diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
index c50243b0fb3..704dad6ad34 100644
--- a/src/game/CreatureEventAI.cpp
+++ b/src/game/CreatureEventAI.cpp
@@ -625,7 +625,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
}
//Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
- bool canCast = !(caster->IsNonMeleeSpellCasted(false) && (param3 & CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS));
+ bool canCast = !(caster->IsNonMeleeSpellCasted(false) && !(param3 & CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS));
// If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
if(param3 & CAST_AURA_NOT_PRESENT)
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index 4b7fce652f5..ae1b0933bbf 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -5392,8 +5392,13 @@ bool ChatHandler::HandleResetAllCommand(const char * args)
}
else if(casename=="pet_spells")
{
- atLogin = AT_LOGIN_RESET_PET_SPELLS;
+ CharacterDatabase.PExecute("UPDATE character_pet SET load_flags = load_flags | '%u' WHERE (load_flags & '%u') = '0'",uint32(AT_LOAD_RESET_SPELLS),uint32(AT_LOAD_RESET_SPELLS));
+ HashMapHolder<Player>::MapType const& plist = ObjectAccessor::Instance().GetPlayers();
+ for(HashMapHolder<Player>::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr)
+ if (itr->second->GetPet())
+ itr->second->SetPetAtLoginFlag(AT_LOAD_RESET_SPELLS);
sWorld.SendWorldText(LANG_RESETALL_PET_SPELLS);
+ return true;
}
else
{
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index 9c8835b8ded..ccd2e02be87 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -50,6 +50,8 @@ m_declinedname(NULL), m_owner(owner)
m_name = "Pet";
m_regenTimer = 4000;
+ owner->SetPetAtLoginFlag(0);
+
if(type == POSSESSED_PET) // always passive
SetReactState(REACT_PASSIVE);
}
@@ -100,25 +102,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
- 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 "
+ // 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 "
"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
- 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 "
+ // 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 "
"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
- 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 "
+ // 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 "
"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
- 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 "
+ // 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 "
"FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ",
ownerid,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
@@ -264,56 +266,71 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
m_resetTalentsCost = fields[17].GetUInt32();
m_resetTalentsTime = fields[18].GetUInt64();
- learnLevelupSpells();
- LearnPetPassives();
- _LoadSpells();
- _LoadSpellCooldowns();
-
- if (!is_temporary_summoned)
+ uint8 loadFlags = fields[21].GetUInt8();
+ if (loadFlags & AT_LOAD_RESET_SPELLS)
+ {
+ CharacterDatabase.PExecute("UPDATE character_pet SET load_flags = load_flags & ~ %u WHERE guid = '%d'",uint32(AT_LOAD_RESET_SPELLS),pet_number);
+ loadFlags &= ~uint8(AT_LOAD_RESET_SPELLS);
+ CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%d'",pet_number);
+ InitPetCreateSpells();
+ resetTalents(true);
+ learnLevelupSpells();
+ }
+ else
{
- // permanent controlled pets store state in DB
- Tokens tokens = StrSplit(fields[14].GetString(), " ");
+ learnLevelupSpells();
+ LearnPetPassives();
+ _LoadSpells();
+ _LoadSpellCooldowns();
- if (tokens.size() != 20)
+ // Load action bar data
+ if (!is_temporary_summoned)
{
- delete result;
- return false;
- }
+ // permanent controlled pets store state in DB
+ Tokens tokens = StrSplit(fields[14].GetString(), " ");
- int index;
- Tokens::iterator iter;
- for(iter = tokens.begin(), index = 0; index < 10; ++iter, ++index )
- {
- m_charmInfo->GetActionBarEntry(index)->Type = atol((*iter).c_str());
- ++iter;
- m_charmInfo->GetActionBarEntry(index)->SpellOrAction = atol((*iter).c_str());
+ if (tokens.size() != 20)
+ {
+ delete result;
+ return false;
+ }
- // patch for old data where some spells have ACT_DECIDE but should have ACT_CAST
- // so overwrite old state
- if(SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_charmInfo->GetActionBarEntry(index)->SpellOrAction))
+ int index;
+ Tokens::iterator iter;
+ for(iter = tokens.begin(), index = 0; index < 10; ++iter, ++index )
{
- if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET)
- m_charmInfo->GetActionBarEntry(index)->Type = ACT_DISABLED;
+ m_charmInfo->GetActionBarEntry(index)->Type = atol((*iter).c_str());
+ ++iter;
+ m_charmInfo->GetActionBarEntry(index)->SpellOrAction = atol((*iter).c_str());
+
+ // patch for old data where some spells have ACT_DECIDE but should have ACT_CAST
+ // so overwrite old state
+ if(SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_charmInfo->GetActionBarEntry(index)->SpellOrAction))
+ {
+ if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET)
+ m_charmInfo->GetActionBarEntry(index)->Type = ACT_DISABLED;
- if(m_charmInfo->GetActionBarEntry(index)->Type == ACT_ENABLED)
- ToggleAutocast(spellInfo->Id, true);
+ if(m_charmInfo->GetActionBarEntry(index)->Type == ACT_ENABLED)
+ ToggleAutocast(spellInfo->Id, true);
+ }
}
- }
- //init teach spells
- tokens = StrSplit(fields[15].GetString(), " ");
- for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index)
- {
- uint32 tmp = atol((*iter).c_str());
+ //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;
+ ++iter;
- if(tmp)
- AddTeachSpell(tmp, atol((*iter).c_str()));
- else
- break;
+ if(tmp)
+ AddTeachSpell(tmp, atol((*iter).c_str()));
+ else
+ break;
+ }
}
}
+ owner->SetPetAtLoginFlag(loadFlags);
//load spells/cooldowns/auras
// Spells should be loaded after pet is added to map, because in CheckCast is check on it
@@ -415,7 +432,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) "
+ 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) "
<< "VALUES ("
<< m_charmInfo->GetPetNumber() << ", "
<< GetEntry() << ", "
@@ -450,7 +467,8 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< uint32(m_resetTalentsCost) << ", "
<< uint64(m_resetTalentsTime) << ", "
<< GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", "
- << uint32(getPetType()) << ")";
+ << uint32(getPetType()) << ", "
+ << (pOwner->GetAtLoginFlag()>>AT_LOAD_PET_FLAGS) << ")";
CharacterDatabase.Execute( ss.str().c_str() );
CharacterDatabase.CommitTransaction();
@@ -461,6 +479,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
RemoveAllAuras();
DeleteFromDB(m_charmInfo->GetPetNumber());
}
+ pOwner->SetPetAtLoginFlag(0);
}
void Pet::DeleteFromDB(uint32 guidlow)
diff --git a/src/game/Pet.h b/src/game/Pet.h
index aaa4c786d10..9d7a42e57a0 100644
--- a/src/game/Pet.h
+++ b/src/game/Pet.h
@@ -90,6 +90,12 @@ enum PetTalk
PET_TALK_ATTACK = 1
};
+enum AtLoadFlags
+{
+ AT_LOAD_NONE = 0,
+ AT_LOAD_RESET_SPELLS = 1,
+};
+
enum PetNameInvalidReason
{
PET_NAME_INVALID = 1,
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index a400909a43e..d1bbaebd0d6 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -14524,12 +14524,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
InitTalentForLevel();
learnDefaultSpells();
- // must be done after aura loading for correct pet talent amount calculation
- if(HasAtLoginFlag(AT_LOGIN_RESET_PET_SPELLS))
- {
- _resetAllPetSpells();
- }
-
_LoadTutorials(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTUTORIALS));
// must be before inventory (some items required reputation check)
@@ -15775,7 +15769,7 @@ void Player::SaveToDB()
ss << uint32(m_stableSlots); // to prevent save uint8 as char
ss << ", ";
- ss << uint32(m_atLoginFlags);
+ ss << uint32(m_atLoginFlags & ((1<<AT_LOAD_PET_FLAGS) -1));
ss << ", ";
ss << GetZoneId();
@@ -18591,44 +18585,6 @@ void Player::resetSpells()
learnQuestRewardedSpells();
}
-void Player::_resetAllPetSpells()
-{
- if(HasAtLoginFlag(AT_LOGIN_RESET_PET_SPELLS))
- {
- m_atLoginFlags = m_atLoginFlags & ~AT_LOGIN_RESET_PET_SPELLS;
- CharacterDatabase.PExecute("UPDATE characters set at_login = at_login & ~ %u WHERE guid ='%u'", uint32(AT_LOGIN_RESET_PET_SPELLS), GetGUIDLow());
- }
-
- if (QueryResult * result = CharacterDatabase.PQuery("SELECT id, level, entry FROM character_pet WHERE owner = '%u'", GetGUIDLow()))
- {
- // Mod points from owner SPELL_AURA_MOD_PET_TALENT_POINTS
- uint32 pointMod = GetTotalAuraModifier(SPELL_AURA_MOD_PET_TALENT_POINTS);
- do
- {
- Field *fields = result->Fetch();
- uint32 petId = fields[0].GetUInt32();
- uint32 level = fields[1].GetUInt32();
- uint32 entry = fields[2].GetUInt32();
- CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry);
- if (!ci)
- sLog.outError("Unknown pet (id %d) type saved in character_pet!", petId);
- CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
- if (!pet_family)
- sLog.outError("Unknown pet (id %d) type saved in character_pet!", petId);
- if(pet_family && pet_family->petTalentType >= 0)
- {
- uint32 points = (level >= 20) ? ((level - 16) / 4) : 0;
- CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u'", petId);
- std::ostringstream ss;
- ss << "UPDATE character_pet SET talentpoints = '"<<points + pointMod<<"' WHERE id = '"<<petId<<"'";
- sLog.outDebug(ss.str().c_str());
- CharacterDatabase.Execute(ss.str().c_str());
- }
- }
- while( result->NextRow() );
- }
-}
-
void Player::learnDefaultSpells()
{
// learn default race/class spells
diff --git a/src/game/Player.h b/src/game/Player.h
index e5c3a80fc71..73e714fe41d 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -57,6 +57,7 @@ typedef std::deque<Mail*> PlayerMails;
#define PLAYER_MAX_SKILLS 127
#define PLAYER_MAX_DAILY_QUESTS 25
+#define AT_LOAD_PET_FLAGS 16
// Note: SPELLMOD_* values is aura types in fact
enum SpellModType
@@ -498,7 +499,6 @@ enum AtLoginFlags
AT_LOGIN_RESET_SPELLS = 2,
AT_LOGIN_RESET_TALENTS = 4,
AT_LOGIN_CUSTOMIZE = 8,
- AT_LOGIN_RESET_PET_SPELLS = 16
};
typedef std::map<uint32, QuestStatusData> QuestStatusMap;
@@ -1343,7 +1343,6 @@ class TRINITY_DLL_SPEC Player : public Unit
void learnSpell(uint32 spell_id, bool dependent);
void removeSpell(uint32 spell_id, bool disabled = false, bool update_action_bar_for_low_rank = false);
void resetSpells();
- void _resetAllPetSpells();
void learnDefaultSpells();
void learnQuestRewardedSpells();
void learnQuestRewardedSpells(Quest const* quest);
@@ -1953,6 +1952,8 @@ class TRINITY_DLL_SPEC Player : public Unit
bool HasAtLoginFlag(AtLoginFlags f) const { return m_atLoginFlags & f; }
void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; }
+ uint32 GetAtLoginFlag() { return m_atLoginFlags; }
+ void SetPetAtLoginFlag(uint8 f) { m_atLoginFlags |= uint32(f<<AT_LOAD_PET_FLAGS); }
LookingForGroup m_lookingForGroup;