Merge branch 'master' into 310

Conflicts:
	src/game/Player.cpp
This commit is contained in:
tomrus88 2009-05-28 10:16:02 +04:00
commit f6e2b55e2c
25 changed files with 382 additions and 240 deletions

View file

@ -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,30 +241,18 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
if (!is_temporary_summoned)
{
// permanent controlled pets store state in DB
Tokens tokens = StrSplit(fields[14].GetString(), " ");
if (tokens.size() != 20)
if(!m_charmInfo->LoadActionBar(fields[13].GetCppString()))
{
delete result;
return false;
}
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());
}
}
// 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;
@ -299,6 +288,10 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
// Spells should be loaded after pet is added to map, because in CheckCast is check on it
_LoadSpells();
InitLevelupSpellsForLevel();
CleanupActionBar(); // remove unknown spells from action bar after load
_LoadSpellCooldowns();
owner->SetPet(this); // in DB stored only full controlled creature
@ -329,8 +322,6 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
}
}
InitLevelupSpellsForLevel();
m_loading = false;
SynchronizeLevelWithOwner();
@ -404,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() << ", "
@ -413,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) << ", "
@ -421,8 +411,12 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< curmana << ", "
<< GetPower(POWER_HAPPINESS) << ", '";
for(uint32 i = 0; i < 10; ++i)
ss << uint32(m_charmInfo->GetActionBarEntry(i)->Type) << " " << uint32(m_charmInfo->GetActionBarEntry(i)->SpellOrAction) << " ";
for(uint32 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
{
ss << uint32(m_charmInfo->GetActionBarEntry(i)->Type) << " "
<< uint32(m_charmInfo->GetActionBarEntry(i)->SpellOrAction) << " ";
};
ss << "', "
<< time(NULL) << ", "
<< uint32(m_resetTalentsCost) << ", "
@ -1099,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() );
@ -1113,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)
@ -1325,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)
@ -1337,7 +1344,7 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel
// skip unknown ranks
if(!HasSpell(rankSpellId))
continue;
removeSpell(rankSpellId,false);
removeSpell(rankSpellId,false,false);
}
}
}
@ -1358,7 +1365,7 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel
ToggleAutocast(itr2->first, false);
oldspell_id = itr2->first;
unlearnSpell(itr2->first,false);
unlearnSpell(itr2->first,false,false);
break;
}
// ignore new lesser rank
@ -1373,7 +1380,7 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel
if (IsPassiveSpell(spell_id))
CastSpell(this, spell_id, true);
else
m_charmInfo->AddSpellToAB(oldspell_id, spell_id);
m_charmInfo->AddSpellToActionBar(spell_id);
if(newspell.active == ACT_ENABLED)
ToggleAutocast(spell_id, true);
@ -1396,16 +1403,17 @@ bool Pet::learnSpell(uint32 spell_id)
if (!addSpell(spell_id))
return false;
Unit* owner = GetOwner();
if(owner && owner->GetTypeId() == TYPEID_PLAYER)
if(!m_loading)
{
if(!m_loading)
Unit* owner = GetOwner();
if(owner && owner->GetTypeId() == TYPEID_PLAYER)
{
WorldPacket data(SMSG_PET_LEARNED_SPELL, 2);
data << uint16(spell_id);
((Player*)owner)->GetSession()->SendPacket(&data);
((Player*)owner)->PetSpellInitialize();
}
((Player*)owner)->PetSpellInitialize();
}
return true;
}
@ -1441,7 +1449,7 @@ void Pet::InitLevelupSpellsForLevel()
// will called first if level down
if(spellEntry->spellLevel > level)
unlearnSpell(spellEntry->Id,false);
unlearnSpell(spellEntry->Id,true);
// will called if level up
else
learnSpell(spellEntry->Id);
@ -1449,9 +1457,9 @@ void Pet::InitLevelupSpellsForLevel()
}
}
bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev)
bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
{
if(removeSpell(spell_id,learn_prev))
if(removeSpell(spell_id,learn_prev,clear_ab))
{
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
{
@ -1467,7 +1475,7 @@ bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev)
return false;
}
bool Pet::removeSpell(uint32 spell_id, bool learn_prev)
bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
{
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr == m_spells.end())
@ -1498,29 +1506,35 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev)
if (learn_prev)
{
if (uint32 prev_id = spellmgr.GetPrevSpellInChain (spell_id))
{
// replace to next spell
if(!talentCost && !IsPassiveSpell(prev_id))
m_charmInfo->AddSpellToAB(spell_id, prev_id);
learnSpell(prev_id);
}
else
learn_prev = false;
}
// 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))
if (clear_ab && !learn_prev && m_charmInfo->RemoveSpellFromActionBar(spell_id))
{
// need update action bar for last removed rank
if (Unit* owner = GetOwner())
if (owner->GetTypeId() == TYPEID_PLAYER)
((Player*)owner)->PetSpellInitialize();
if(!m_loading)
{
// need update action bar for last removed rank
if (Unit* owner = GetOwner())
if (owner->GetTypeId() == TYPEID_PLAYER)
((Player*)owner)->PetSpellInitialize();
}
}
return true;
}
void Pet::CleanupActionBar()
{
for(int i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
if(UnitActionBarEntry const* ab = m_charmInfo->GetActionBarEntry(i))
if(ab->SpellOrAction && ab->IsActionBarForSpell() && !HasSpell(ab->SpellOrAction))
m_charmInfo->SetActionBar(i,0,ACT_DISABLED);
}
void Pet::InitPetCreateSpells()
{
m_charmInfo->InitPetActionBar();