*Fix CAST_INTURRUPT_PREVIOUS flag for eventai action cast

*Rewrite .reload all pet_spells command to make it reset actionbars correctly.

--HG--
branch : trunk
This commit is contained in:
QAston
2009-04-26 02:48:20 +02:00
parent 6909b20f2c
commit 2d1521dea9
7 changed files with 89 additions and 100 deletions
@@ -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;
+1 -1
View File
@@ -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 //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 cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
if(param3 & CAST_AURA_NOT_PRESENT) if(param3 & CAST_AURA_NOT_PRESENT)
+6 -1
View File
@@ -5392,8 +5392,13 @@ bool ChatHandler::HandleResetAllCommand(const char * args)
} }
else if(casename=="pet_spells") 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); sWorld.SendWorldText(LANG_RESETALL_PET_SPELLS);
return true;
} }
else else
{ {
+70 -51
View File
@@ -50,6 +50,8 @@ m_declinedname(NULL), m_owner(owner)
m_name = "Pet"; m_name = "Pet";
m_regenTimer = 4000; m_regenTimer = 4000;
owner->SetPetAtLoginFlag(0);
if(type == POSSESSED_PET) // always passive if(type == POSSESSED_PET) // always passive
SetReactState(REACT_PASSIVE); SetReactState(REACT_PASSIVE);
} }
@@ -100,25 +102,25 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
QueryResult *result; QueryResult *result;
if (petnumber) 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 // 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 " 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'", "FROM character_pet WHERE owner = '%u' AND id = '%u'",
ownerid, petnumber); ownerid, petnumber);
else if (current) 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 // 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 " 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'", "FROM character_pet WHERE owner = '%u' AND slot = '%u'",
ownerid, PET_SAVE_AS_CURRENT ); ownerid, PET_SAVE_AS_CURRENT );
else if (petentry) else if (petentry)
// known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets) // 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 // 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 " 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') ", "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); ownerid, petentry,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
else else
// any current or other non-stabled pet (for hunter "call pet") // 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 // 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 " 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') ", "FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ",
ownerid,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT); 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_resetTalentsCost = fields[17].GetUInt32();
m_resetTalentsTime = fields[18].GetUInt64(); m_resetTalentsTime = fields[18].GetUInt64();
learnLevelupSpells(); uint8 loadFlags = fields[21].GetUInt8();
LearnPetPassives(); if (loadFlags & AT_LOAD_RESET_SPELLS)
_LoadSpells();
_LoadSpellCooldowns();
if (!is_temporary_summoned)
{ {
// permanent controlled pets store state in DB CharacterDatabase.PExecute("UPDATE character_pet SET load_flags = load_flags & ~ %u WHERE guid = '%d'",uint32(AT_LOAD_RESET_SPELLS),pet_number);
Tokens tokens = StrSplit(fields[14].GetString(), " "); loadFlags &= ~uint8(AT_LOAD_RESET_SPELLS);
CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%d'",pet_number);
InitPetCreateSpells();
resetTalents(true);
learnLevelupSpells();
}
else
{
learnLevelupSpells();
LearnPetPassives();
_LoadSpells();
_LoadSpellCooldowns();
if (tokens.size() != 20) // Load action bar data
if (!is_temporary_summoned)
{ {
delete result; // permanent controlled pets store state in DB
return false; Tokens tokens = StrSplit(fields[14].GetString(), " ");
}
int index; if (tokens.size() != 20)
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());
// 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) delete result;
m_charmInfo->GetActionBarEntry(index)->Type = ACT_DISABLED; return false;
}
if(m_charmInfo->GetActionBarEntry(index)->Type == ACT_ENABLED) int index;
ToggleAutocast(spellInfo->Id, true); 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());
// 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);
}
}
//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;
} }
} }
//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;
}
} }
owner->SetPetAtLoginFlag(loadFlags);
//load spells/cooldowns/auras //load spells/cooldowns/auras
// Spells should be loaded after pet is added to map, because in CheckCast is check on it // 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); owner,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
// save pet // save pet
std::ostringstream ss; 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 (" << "VALUES ("
<< m_charmInfo->GetPetNumber() << ", " << m_charmInfo->GetPetNumber() << ", "
<< GetEntry() << ", " << GetEntry() << ", "
@@ -450,7 +467,8 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< uint32(m_resetTalentsCost) << ", " << uint32(m_resetTalentsCost) << ", "
<< uint64(m_resetTalentsTime) << ", " << uint64(m_resetTalentsTime) << ", "
<< GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", " << GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", "
<< uint32(getPetType()) << ")"; << uint32(getPetType()) << ", "
<< (pOwner->GetAtLoginFlag()>>AT_LOAD_PET_FLAGS) << ")";
CharacterDatabase.Execute( ss.str().c_str() ); CharacterDatabase.Execute( ss.str().c_str() );
CharacterDatabase.CommitTransaction(); CharacterDatabase.CommitTransaction();
@@ -461,6 +479,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
RemoveAllAuras(); RemoveAllAuras();
DeleteFromDB(m_charmInfo->GetPetNumber()); DeleteFromDB(m_charmInfo->GetPetNumber());
} }
pOwner->SetPetAtLoginFlag(0);
} }
void Pet::DeleteFromDB(uint32 guidlow) void Pet::DeleteFromDB(uint32 guidlow)
+6
View File
@@ -90,6 +90,12 @@ enum PetTalk
PET_TALK_ATTACK = 1 PET_TALK_ATTACK = 1
}; };
enum AtLoadFlags
{
AT_LOAD_NONE = 0,
AT_LOAD_RESET_SPELLS = 1,
};
enum PetNameInvalidReason enum PetNameInvalidReason
{ {
PET_NAME_INVALID = 1, PET_NAME_INVALID = 1,
+1 -45
View File
@@ -14524,12 +14524,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
InitTalentForLevel(); InitTalentForLevel();
learnDefaultSpells(); 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)); _LoadTutorials(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTUTORIALS));
// must be before inventory (some items required reputation check) // 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 << uint32(m_stableSlots); // to prevent save uint8 as char
ss << ", "; ss << ", ";
ss << uint32(m_atLoginFlags); ss << uint32(m_atLoginFlags & ((1<<AT_LOAD_PET_FLAGS) -1));
ss << ", "; ss << ", ";
ss << GetZoneId(); ss << GetZoneId();
@@ -18591,44 +18585,6 @@ void Player::resetSpells()
learnQuestRewardedSpells(); 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() void Player::learnDefaultSpells()
{ {
// learn default race/class spells // learn default race/class spells
+3 -2
View File
@@ -57,6 +57,7 @@ typedef std::deque<Mail*> PlayerMails;
#define PLAYER_MAX_SKILLS 127 #define PLAYER_MAX_SKILLS 127
#define PLAYER_MAX_DAILY_QUESTS 25 #define PLAYER_MAX_DAILY_QUESTS 25
#define AT_LOAD_PET_FLAGS 16
// Note: SPELLMOD_* values is aura types in fact // Note: SPELLMOD_* values is aura types in fact
enum SpellModType enum SpellModType
@@ -498,7 +499,6 @@ enum AtLoginFlags
AT_LOGIN_RESET_SPELLS = 2, AT_LOGIN_RESET_SPELLS = 2,
AT_LOGIN_RESET_TALENTS = 4, AT_LOGIN_RESET_TALENTS = 4,
AT_LOGIN_CUSTOMIZE = 8, AT_LOGIN_CUSTOMIZE = 8,
AT_LOGIN_RESET_PET_SPELLS = 16
}; };
typedef std::map<uint32, QuestStatusData> QuestStatusMap; 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 learnSpell(uint32 spell_id, bool dependent);
void removeSpell(uint32 spell_id, bool disabled = false, bool update_action_bar_for_low_rank = false); void removeSpell(uint32 spell_id, bool disabled = false, bool update_action_bar_for_low_rank = false);
void resetSpells(); void resetSpells();
void _resetAllPetSpells();
void learnDefaultSpells(); void learnDefaultSpells();
void learnQuestRewardedSpells(); void learnQuestRewardedSpells();
void learnQuestRewardedSpells(Quest const* quest); 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; } bool HasAtLoginFlag(AtLoginFlags f) const { return m_atLoginFlags & f; }
void SetAtLoginFlag(AtLoginFlags f) { 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; LookingForGroup m_lookingForGroup;