mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-21 01:37:37 +01:00
Backed out changeset: ad4f100c0a9d
--HG-- branch : trunk
This commit is contained in:
395
src/game/Pet.cpp
395
src/game/Pet.cpp
@@ -41,6 +41,27 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
|
||||
"'s Companion" // MINI_PET
|
||||
};
|
||||
|
||||
//numbers represent minutes * 100 while happy (you get 100 loyalty points per min while happy)
|
||||
uint32 const LevelUpLoyalty[6] =
|
||||
{
|
||||
5500,
|
||||
11500,
|
||||
17000,
|
||||
23500,
|
||||
31000,
|
||||
39500,
|
||||
};
|
||||
|
||||
uint32 const LevelStartLoyalty[6] =
|
||||
{
|
||||
2000,
|
||||
4500,
|
||||
7000,
|
||||
10000,
|
||||
13500,
|
||||
17500,
|
||||
};
|
||||
|
||||
Pet::Pet(PetType type) : Creature()
|
||||
{
|
||||
m_isPet = true;
|
||||
@@ -50,16 +71,17 @@ Pet::Pet(PetType type) : Creature()
|
||||
m_removed = false;
|
||||
m_regenTimer = 4000;
|
||||
m_happinessTimer = 7500;
|
||||
m_loyaltyTimer = 12000;
|
||||
m_duration = 0;
|
||||
m_bonusdamage = 0;
|
||||
|
||||
m_loyaltyPoints = 0;
|
||||
m_TrainingPoints = 0;
|
||||
m_resetTalentsCost = 0;
|
||||
m_resetTalentsTime = 0;
|
||||
|
||||
m_auraUpdateMask = 0;
|
||||
|
||||
m_loading = false;
|
||||
|
||||
// pets always have a charminfo, even if they are not actually charmed
|
||||
CharmInfo* charmInfo = InitCharmInfo(this);
|
||||
|
||||
@@ -106,26 +128,24 @@ void Pet::RemoveFromWorld()
|
||||
|
||||
bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool current )
|
||||
{
|
||||
m_loading = true;
|
||||
|
||||
uint32 ownerid = owner->GetGUIDLow();
|
||||
|
||||
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 FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, 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 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, 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 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 FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
|
||||
// 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 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
|
||||
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 FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
|
||||
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 FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
|
||||
|
||||
if(!result)
|
||||
return false;
|
||||
@@ -140,7 +160,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 summon_spell_id = fields[19].GetUInt32();
|
||||
uint32 summon_spell_id = fields[21].GetUInt32();
|
||||
SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id);
|
||||
|
||||
bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
|
||||
@@ -174,8 +194,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
||||
return false;
|
||||
}
|
||||
|
||||
setPetType(PetType(fields[20].GetUInt8()));
|
||||
SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction());
|
||||
setPetType(PetType(fields[22].GetUInt8()));
|
||||
SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
|
||||
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
|
||||
|
||||
CreatureInfo const *cinfo = GetCreatureInfo();
|
||||
@@ -186,67 +206,72 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
||||
delete result;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
|
||||
if(getPetType()==HUNTER_PET || (getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
|
||||
m_charmInfo->SetPetNumber(pet_number, true);
|
||||
else
|
||||
m_charmInfo->SetPetNumber(pet_number, false);
|
||||
|
||||
SetOwnerGUID(owner->GetGUID());
|
||||
SetUInt64Value(UNIT_FIELD_SUMMONEDBY, owner->GetGUID());
|
||||
SetDisplayId(fields[3].GetUInt32());
|
||||
SetNativeDisplayId(fields[3].GetUInt32());
|
||||
uint32 petlevel = fields[4].GetUInt32();
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, 0);
|
||||
SetName(fields[9].GetString());
|
||||
uint32 petlevel=fields[4].GetUInt32();
|
||||
SetUInt32Value(UNIT_NPC_FLAGS , 0);
|
||||
SetName(fields[11].GetString());
|
||||
|
||||
switch(getPetType())
|
||||
{
|
||||
|
||||
case SUMMON_PET:
|
||||
petlevel=owner->getLevel();
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
// this enables popup window (pet dismiss, cancel)
|
||||
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_1, 1, fields[8].GetUInt32());
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
|
||||
if(fields[12].GetBool())
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
|
||||
else
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, 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());
|
||||
SetTP(fields[9].GetInt32());
|
||||
SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
|
||||
SetPower( POWER_HAPPINESS,fields[15].GetUInt32());
|
||||
setPowerType(POWER_FOCUS);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType());
|
||||
sLog.outError("Pet have incorrect type (%u) for pet loading.",getPetType());
|
||||
}
|
||||
|
||||
InitStatsForLevel(petlevel);
|
||||
InitStatsForLevel( petlevel);
|
||||
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32());
|
||||
SetCreatorGUID(owner->GetGUID());
|
||||
SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID());
|
||||
|
||||
m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8()));
|
||||
m_charmInfo->SetReactState( ReactStates( fields[6].GetUInt8() ));
|
||||
m_loyaltyPoints = fields[7].GetInt32();
|
||||
|
||||
uint32 savedhealth = fields[11].GetUInt32();
|
||||
uint32 savedmana = fields[12].GetUInt32();
|
||||
uint32 savedhealth = fields[13].GetUInt32();
|
||||
uint32 savedmana = fields[14].GetUInt32();
|
||||
|
||||
// set current pet as current
|
||||
if(fields[8].GetUInt32() != 0)
|
||||
if(fields[10].GetUInt32() != 0)
|
||||
{
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'",ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'",ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.CommitTransaction();
|
||||
}
|
||||
|
||||
if(!is_temporary_summoned)
|
||||
{
|
||||
// permanent controlled pets store state in DB
|
||||
Tokens tokens = StrSplit(fields[14].GetString(), " ");
|
||||
Tokens tokens = StrSplit(fields[16].GetString(), " ");
|
||||
|
||||
if(tokens.size() != 20)
|
||||
{
|
||||
@@ -265,11 +290,11 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
||||
// patch for old data where some spells have ACT_DECIDE but should have ACT_CAST
|
||||
// so overwrite old state
|
||||
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_ENABLED;
|
||||
if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_CAST;
|
||||
}
|
||||
|
||||
//init teach spells
|
||||
tokens = StrSplit(fields[15].GetString(), " ");
|
||||
tokens = StrSplit(fields[17].GetString(), " ");
|
||||
for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index)
|
||||
{
|
||||
uint32 tmp = atol((*iter).c_str());
|
||||
@@ -284,10 +309,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
||||
}
|
||||
|
||||
// since last save (in seconds)
|
||||
uint32 timediff = (time(NULL) - fields[16].GetUInt32());
|
||||
|
||||
m_resetTalentsCost = fields[17].GetUInt32();
|
||||
m_resetTalentsTime = fields[18].GetUInt64();
|
||||
uint32 timediff = (time(NULL) - fields[18].GetUInt32());
|
||||
|
||||
delete result;
|
||||
|
||||
@@ -353,7 +375,6 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
||||
}
|
||||
}
|
||||
|
||||
m_loading = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -396,6 +417,10 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
||||
case PET_SAVE_IN_STABLE_SLOT_2:
|
||||
case PET_SAVE_NOT_IN_SLOT:
|
||||
{
|
||||
uint32 loyalty =1;
|
||||
if(getPetType()!=HUNTER_PET)
|
||||
loyalty = GetLoyaltyLevel();
|
||||
|
||||
uint32 owner = GUID_LOPART(GetOwnerGUID());
|
||||
std::string name = m_name;
|
||||
CharacterDatabase.escape_string(name);
|
||||
@@ -412,7 +437,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
||||
CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner );
|
||||
// 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, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata,TeachSpelldata,savetime,resettalents_cost,resettalents_time,CreatedBySpell,PetType) "
|
||||
<< "VALUES ("
|
||||
<< m_charmInfo->GetPetNumber() << ", "
|
||||
<< GetEntry() << ", "
|
||||
@@ -421,7 +446,9 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
||||
<< getLevel() << ", "
|
||||
<< GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", "
|
||||
<< uint32(m_charmInfo->GetReactState()) << ", "
|
||||
<< uint32(GetFreeTalentPoints()) << ", "
|
||||
<< m_loyaltyPoints << ", "
|
||||
<< GetLoyaltyLevel() << ", "
|
||||
<< m_TrainingPoints << ", "
|
||||
<< uint32(mode) << ", '"
|
||||
<< name.c_str() << "', "
|
||||
<< uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", "
|
||||
@@ -494,12 +521,12 @@ void Pet::setDeathState(DeathState s) // overwrite virtual
|
||||
if(!mapEntry || (mapEntry->map_type != MAP_ARENA && mapEntry->map_type != MAP_BATTLEGROUND))
|
||||
ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE);
|
||||
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
|
||||
}
|
||||
}
|
||||
else if(getDeathState()==ALIVE)
|
||||
{
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
|
||||
CastPetAuras(true);
|
||||
}
|
||||
}
|
||||
@@ -526,7 +553,6 @@ void Pet::Update(uint32 diff)
|
||||
// unsummon pet that lost owner
|
||||
Unit* owner = GetOwner();
|
||||
if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && !isPossessed()) || isControlled() && !owner->GetPetGUID())
|
||||
//if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && (owner->GetCharmGUID() && (owner->GetCharmGUID() != GetGUID()))) || (isControlled() && !owner->GetPetGUID()))
|
||||
{
|
||||
Remove(PET_SAVE_NOT_IN_SLOT, true);
|
||||
return;
|
||||
@@ -572,6 +598,14 @@ void Pet::Update(uint32 diff)
|
||||
else
|
||||
m_happinessTimer -= diff;
|
||||
|
||||
if(m_loyaltyTimer <= diff)
|
||||
{
|
||||
TickLoyaltyChange();
|
||||
m_loyaltyTimer = 12000;
|
||||
}
|
||||
else
|
||||
m_loyaltyTimer -= diff;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -603,12 +637,83 @@ void Pet::LooseHappiness()
|
||||
uint32 curValue = GetPower(POWER_HAPPINESS);
|
||||
if (curValue <= 0)
|
||||
return;
|
||||
int32 addvalue = 670; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
|
||||
int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
|
||||
if(isInCombat()) //we know in combat happiness fades faster, multiplier guess
|
||||
addvalue = int32(addvalue * 1.5);
|
||||
ModifyPower(POWER_HAPPINESS, -addvalue);
|
||||
}
|
||||
|
||||
void Pet::ModifyLoyalty(int32 addvalue)
|
||||
{
|
||||
uint32 loyaltylevel = GetLoyaltyLevel();
|
||||
|
||||
if(addvalue > 0) //only gain influenced, not loss
|
||||
addvalue = int32((float)addvalue * sWorld.getRate(RATE_LOYALTY));
|
||||
|
||||
if(loyaltylevel >= BEST_FRIEND && (addvalue + m_loyaltyPoints) > int32(GetMaxLoyaltyPoints(loyaltylevel)))
|
||||
return;
|
||||
|
||||
m_loyaltyPoints += addvalue;
|
||||
|
||||
if(m_loyaltyPoints < 0)
|
||||
{
|
||||
if(loyaltylevel > REBELLIOUS)
|
||||
{
|
||||
//level down
|
||||
--loyaltylevel;
|
||||
SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
|
||||
m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
|
||||
SetTP(m_TrainingPoints - int32(getLevel()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_loyaltyPoints = 0;
|
||||
Unit* owner = GetOwner();
|
||||
if(owner && owner->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_BROKEN, 0);
|
||||
((Player*)owner)->GetSession()->SendPacket(&data);
|
||||
|
||||
//run away
|
||||
((Player*)owner)->RemovePet(this,PET_SAVE_AS_DELETED);
|
||||
}
|
||||
}
|
||||
}
|
||||
//level up
|
||||
else if(m_loyaltyPoints > int32(GetMaxLoyaltyPoints(loyaltylevel)))
|
||||
{
|
||||
++loyaltylevel;
|
||||
SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
|
||||
m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
|
||||
SetTP(m_TrainingPoints + getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
void Pet::TickLoyaltyChange()
|
||||
{
|
||||
int32 addvalue;
|
||||
|
||||
switch(GetHappinessState())
|
||||
{
|
||||
case HAPPY: addvalue = 20; break;
|
||||
case CONTENT: addvalue = 10; break;
|
||||
case UNHAPPY: addvalue = -20; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
ModifyLoyalty(addvalue);
|
||||
}
|
||||
|
||||
void Pet::KillLoyaltyBonus(uint32 level)
|
||||
{
|
||||
if(level > 100)
|
||||
return;
|
||||
|
||||
//at lower levels gain is faster | the lower loyalty the more loyalty is gained
|
||||
uint32 bonus = uint32(((100 - level) / 10) + (6 - GetLoyaltyLevel()));
|
||||
ModifyLoyalty(bonus);
|
||||
}
|
||||
|
||||
HappinessState Pet::GetHappinessState()
|
||||
{
|
||||
if(GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE)
|
||||
@@ -619,6 +724,11 @@ HappinessState Pet::GetHappinessState()
|
||||
return CONTENT;
|
||||
}
|
||||
|
||||
void Pet::SetLoyaltyLevel(LoyaltyLevel level)
|
||||
{
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, 1, level);
|
||||
}
|
||||
|
||||
bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
|
||||
{
|
||||
uint8 activecount = 1;
|
||||
@@ -655,6 +765,82 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pet::HasTPForSpell(uint32 spellid)
|
||||
{
|
||||
int32 neededtrainp = GetTPForSpell(spellid);
|
||||
if((m_TrainingPoints - neededtrainp < 0 || neededtrainp < 0) && neededtrainp != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 Pet::GetTPForSpell(uint32 spellid)
|
||||
{
|
||||
uint32 basetrainp = 0;
|
||||
|
||||
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellid);
|
||||
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellid);
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
|
||||
{
|
||||
if(!_spell_idx->second->reqtrainpoints)
|
||||
return 0;
|
||||
|
||||
basetrainp = _spell_idx->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32 spenttrainp = 0;
|
||||
uint32 chainstart = spellmgr.GetFirstSpellInChain(spellid);
|
||||
|
||||
for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
|
||||
{
|
||||
if(itr->second->state == PETSPELL_REMOVED)
|
||||
continue;
|
||||
|
||||
if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart)
|
||||
{
|
||||
SkillLineAbilityMap::const_iterator _lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first);
|
||||
SkillLineAbilityMap::const_iterator _upper = spellmgr.GetEndSkillLineAbilityMap(itr->first);
|
||||
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx2 = _lower; _spell_idx2 != _upper; ++_spell_idx2)
|
||||
{
|
||||
if(_spell_idx2->second->reqtrainpoints > spenttrainp)
|
||||
{
|
||||
spenttrainp = _spell_idx2->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return int32(basetrainp) - int32(spenttrainp);
|
||||
}
|
||||
|
||||
uint32 Pet::GetMaxLoyaltyPoints(uint32 level)
|
||||
{
|
||||
return LevelUpLoyalty[level - 1];
|
||||
}
|
||||
|
||||
uint32 Pet::GetStartLoyaltyPoints(uint32 level)
|
||||
{
|
||||
return LevelStartLoyalty[level - 1];
|
||||
}
|
||||
|
||||
void Pet::SetTP(int32 TP)
|
||||
{
|
||||
m_TrainingPoints = TP;
|
||||
SetUInt32Value(UNIT_TRAINING_POINTS, (uint32)GetDispTP());
|
||||
}
|
||||
|
||||
int32 Pet::GetDispTP()
|
||||
{
|
||||
if(getPetType()!= HUNTER_PET)
|
||||
return(0);
|
||||
if(m_TrainingPoints < 0)
|
||||
return -m_TrainingPoints;
|
||||
else
|
||||
return -(m_TrainingPoints + 1);
|
||||
}
|
||||
|
||||
void Pet::Remove(PetSaveMode mode, bool returnreagent)
|
||||
{
|
||||
Unit* owner = GetOwner();
|
||||
@@ -717,6 +903,9 @@ void Pet::GivePetXP(uint32 xp)
|
||||
}
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP);
|
||||
|
||||
if(getPetType() == HUNTER_PET)
|
||||
KillLoyaltyBonus(level);
|
||||
}
|
||||
|
||||
void Pet::GivePetLevel(uint32 level)
|
||||
@@ -724,7 +913,9 @@ void Pet::GivePetLevel(uint32 level)
|
||||
if(!level)
|
||||
return;
|
||||
|
||||
InitStatsForLevel(level);
|
||||
InitStatsForLevel( level);
|
||||
|
||||
SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1));
|
||||
}
|
||||
|
||||
bool Pet::CreateBaseAtCreature(Creature* creature)
|
||||
@@ -782,12 +973,16 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
|
||||
else
|
||||
SetName(creature->GetName());
|
||||
|
||||
m_loyaltyPoints = 1000;
|
||||
if(cinfo->type == CREATURE_TYPE_BEAST)
|
||||
{
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
|
||||
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED));
|
||||
|
||||
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED) );
|
||||
SetLoyaltyLevel(REBELLIOUS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -917,7 +1112,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
|
||||
case HUNTER_PET:
|
||||
{
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::XP::xp_to_level(petlevel))/4));
|
||||
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
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) );
|
||||
@@ -1128,6 +1323,10 @@ void Pet::_LoadAuras(uint32 timediff)
|
||||
for (int i = 0; i < TOTAL_AURAS; i++)
|
||||
m_modAuras[i].clear();
|
||||
|
||||
// all aura related fields
|
||||
for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i)
|
||||
SetUInt32Value(i, 0);
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
|
||||
|
||||
if(result)
|
||||
@@ -1268,7 +1467,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
|
||||
|
||||
// same spells don't have autocast option
|
||||
if (spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET)
|
||||
active = ACT_ENABLED;
|
||||
active = ACT_CAST;
|
||||
|
||||
PetSpellMap::iterator itr = m_spells.find(spell_id);
|
||||
if (itr != m_spells.end())
|
||||
@@ -1320,12 +1519,11 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
|
||||
ToggleAutocast(itr->first, false);
|
||||
|
||||
oldspell_id = itr->first;
|
||||
unlearnSpell(itr->first);
|
||||
break;
|
||||
removeSpell(itr->first);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 tmpslot = slot_id;
|
||||
uint16 tmpslot=slot_id;
|
||||
|
||||
if (tmpslot == 0xffff)
|
||||
{
|
||||
@@ -1359,65 +1557,20 @@ bool Pet::learnSpell(uint16 spell_id)
|
||||
if (!addSpell(spell_id))
|
||||
return false;
|
||||
|
||||
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if(!m_loading)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_LEARNED_SPELL, 2);
|
||||
data << uint16(spell_id);
|
||||
((Player*)GetOwner())->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
Unit* owner = GetOwner();
|
||||
if(owner->GetTypeId() == TYPEID_PLAYER)
|
||||
if(owner->GetTypeId()==TYPEID_PLAYER)
|
||||
((Player*)owner)->PetSpellInitialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Pet::learnLevelupSpells()
|
||||
{
|
||||
PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family);
|
||||
if(!levelupSpells)
|
||||
return;
|
||||
|
||||
uint32 level = getLevel();
|
||||
|
||||
for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr)
|
||||
{
|
||||
if(itr->first <= level)
|
||||
learnSpell(itr->second);
|
||||
else
|
||||
unlearnSpell(itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool Pet::unlearnSpell(uint16 spell_id)
|
||||
{
|
||||
if(removeSpell(spell_id))
|
||||
{
|
||||
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if(!m_loading)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_REMOVED_SPELL, 2);
|
||||
data << uint16(spell_id);
|
||||
((Player*)GetOwner())->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Pet::removeSpell(uint16 spell_id)
|
||||
void Pet::removeSpell(uint16 spell_id)
|
||||
{
|
||||
PetSpellMap::iterator itr = m_spells.find(spell_id);
|
||||
if (itr == m_spells.end())
|
||||
return false;
|
||||
return;
|
||||
|
||||
if(itr->second->state == PETSPELL_REMOVED)
|
||||
return false;
|
||||
return;
|
||||
|
||||
if(itr->second->state == PETSPELL_NEW)
|
||||
{
|
||||
@@ -1428,8 +1581,6 @@ bool Pet::removeSpell(uint16 spell_id)
|
||||
itr->second->state = PETSPELL_REMOVED;
|
||||
|
||||
RemoveAurasDueToSpell(spell_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pet::_removeSpell(uint16 spell_id)
|
||||
@@ -1449,7 +1600,7 @@ void Pet::InitPetCreateSpells()
|
||||
m_charmInfo->InitPetActionBar();
|
||||
|
||||
m_spells.clear();
|
||||
int32 petspellid;
|
||||
int32 usedtrainpoints = 0, petspellid;
|
||||
PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry());
|
||||
if(CreateSpells)
|
||||
{
|
||||
@@ -1478,12 +1629,23 @@ void Pet::InitPetCreateSpells()
|
||||
petspellid = learn_spellproto->Id;
|
||||
|
||||
addSpell(petspellid);
|
||||
|
||||
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
|
||||
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
|
||||
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
|
||||
{
|
||||
usedtrainpoints += _spell_idx->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LearnPetPassives();
|
||||
|
||||
CastPetAuras(false);
|
||||
|
||||
SetTP(-usedtrainpoints);
|
||||
}
|
||||
|
||||
void Pet::CheckLearning(uint32 spellid)
|
||||
@@ -1542,9 +1704,7 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
|
||||
|
||||
if(apply)
|
||||
{
|
||||
for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++)
|
||||
; // just search
|
||||
|
||||
for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++);
|
||||
if (i == m_autospells.size())
|
||||
{
|
||||
m_autospells.push_back(spellid);
|
||||
@@ -1555,9 +1715,7 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
|
||||
else
|
||||
{
|
||||
AutoSpellList::iterator itr2 = m_autospells.begin();
|
||||
for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++)
|
||||
; // just search
|
||||
|
||||
for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++);
|
||||
if (i < m_autospells.size())
|
||||
{
|
||||
m_autospells.erase(itr2);
|
||||
@@ -1580,7 +1738,8 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
|
||||
if(!InitEntry(Entry))
|
||||
return false;
|
||||
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
|
||||
if(getPetType() == MINI_PET) // always non-attackable
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
Reference in New Issue
Block a user