Updated objects stuff

This commit is contained in:
tomrus88 2008-10-26 10:20:52 +03:00
parent 579fc917bb
commit 9c8864f134
12 changed files with 896 additions and 500 deletions

View file

@ -39,27 +39,6 @@ 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;
@ -69,12 +48,9 @@ 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;
@ -130,19 +106,19 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
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 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);
// 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);
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 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 );
// 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 );
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 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 );
// 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 );
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 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);
// 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);
if(!result)
return false;
@ -157,7 +133,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
return false;
}
uint32 summon_spell_id = fields[21].GetUInt32();
uint32 summon_spell_id = fields[19].GetUInt32();
SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id);
bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
@ -170,7 +146,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
}
Map *map = owner->GetMap();
uint32 guid=objmgr.GenerateLowGuid(HIGHGUID_PET);
uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_PET);
uint32 pet_number = fields[0].GetUInt32();
if(!Create(guid, map, petentry, pet_number))
{
@ -179,7 +155,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
}
float px, py, pz;
owner->GetClosePoint(px, py, pz,GetObjectSize(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
Relocate(px, py, pz, owner->GetOrientation());
@ -190,8 +166,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
return false;
}
setPetType(PetType(fields[22].GetUInt8()));
SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
setPetType(PetType(fields[20].GetUInt8()));
SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction());
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
CreatureInfo const *cinfo = GetCreatureInfo();
@ -202,72 +178,67 @@ 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);
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[11].GetString());
uint32 petlevel = fields[4].GetUInt32();
SetUInt32Value(UNIT_NPC_FLAGS, 0);
SetName(fields[9].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[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);
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);
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// this enables popup window (pet abandon, cancel)
SetTP(fields[9].GetInt32());
SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
SetPower( POWER_HAPPINESS,fields[15].GetUInt32());
SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
SetPower(POWER_HAPPINESS, fields[13].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());
SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID());
m_charmInfo->SetReactState( ReactStates( fields[6].GetUInt8() ));
m_loyaltyPoints = fields[7].GetInt32();
m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8()));
uint32 savedhealth = fields[13].GetUInt32();
uint32 savedmana = fields[14].GetUInt32();
uint32 savedhealth = fields[11].GetUInt32();
uint32 savedmana = fields[12].GetUInt32();
// set current pet as current
if(fields[10].GetUInt32() != 0)
if(fields[8].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[16].GetString(), " ");
Tokens tokens = StrSplit(fields[14].GetString(), " ");
if(tokens.size() != 20)
{
@ -285,7 +256,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
}
//init teach spells
tokens = StrSplit(fields[17].GetString(), " ");
tokens = StrSplit(fields[15].GetString(), " ");
for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index)
{
uint32 tmp = atol((*iter).c_str());
@ -300,7 +271,10 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
}
// since last save (in seconds)
uint32 timediff = (time(NULL) - fields[18].GetUInt32());
uint32 timediff = (time(NULL) - fields[16].GetUInt32());
m_resetTalentsCost = fields[17].GetUInt32();
m_resetTalentsTime = fields[18].GetUInt64();
delete result;
@ -350,7 +324,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
if(owner->GetTypeId() == TYPEID_PLAYER && getPetType() == HUNTER_PET)
{
result = CharacterDatabase.PQuery("SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'",owner->GetGUIDLow(),GetCharmInfo()->GetPetNumber());
result = CharacterDatabase.PQuery("SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", owner->GetGUIDLow(), GetCharmInfo()->GetPetNumber());
if(result)
{
@ -408,10 +382,6 @@ 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);
@ -428,7 +398,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, loyaltypoints, loyalty, trainpoint, 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) "
<< "VALUES ("
<< m_charmInfo->GetPetNumber() << ", "
<< GetEntry() << ", "
@ -437,9 +407,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< getLevel() << ", "
<< GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", "
<< uint32(m_charmInfo->GetReactState()) << ", "
<< m_loyaltyPoints << ", "
<< GetLoyaltyLevel() << ", "
<< m_TrainingPoints << ", "
<< uint32(GetFreeTalentPoints()) << ", "
<< uint32(mode) << ", '"
<< name.c_str() << "', "
<< uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", "
@ -590,14 +558,6 @@ void Pet::Update(uint32 diff)
else
m_happinessTimer -= diff;
if(m_loyaltyTimer <= diff)
{
TickLoyaltyChange();
m_loyaltyTimer = 12000;
}
else
m_loyaltyTimer -= diff;
break;
}
default:
@ -629,83 +589,12 @@ void Pet::LooseHappiness()
uint32 curValue = GetPower(POWER_HAPPINESS);
if (curValue <= 0)
return;
int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
int32 addvalue = 670; //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)
@ -716,11 +605,6 @@ 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;
@ -757,82 +641,6 @@ 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();
@ -895,9 +703,6 @@ void Pet::GivePetXP(uint32 xp)
}
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP);
if(getPetType() == HUNTER_PET)
KillLoyaltyBonus(level);
}
void Pet::GivePetLevel(uint32 level)
@ -905,9 +710,7 @@ void Pet::GivePetLevel(uint32 level)
if(!level)
return;
InitStatsForLevel( level);
SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1));
InitStatsForLevel(level);
}
bool Pet::CreateBaseAtCreature(Creature* creature)
@ -949,14 +752,14 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
}
SetDisplayId(creature->GetDisplayId());
SetNativeDisplayId(creature->GetNativeDisplayId());
SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
SetPower( POWER_HAPPINESS,166500);
SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
SetPower(POWER_HAPPINESS, 166500);
setPowerType(POWER_FOCUS);
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(creature->getLevel()))/4));
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
SetUInt32Value(UNIT_NPC_FLAGS , 0);
SetUInt32Value(UNIT_NPC_FLAGS, 0);
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family);
if( char* familyname = cFamily->Name[sWorld.GetDefaultDbcLocale()] )
@ -964,16 +767,12 @@ 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) );
SetLoyaltyLevel(REBELLIOUS);
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED));
}
return true;
}
@ -992,7 +791,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
uint32 creature_ID = (getPetType() == HUNTER_PET) ? 1 : cinfo->Entry;
SetLevel( petlevel);
SetLevel(petlevel);
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
@ -1081,7 +880,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
for(int stat = 0; stat < MAX_STATS; ++stat)
{
SetCreateStat(Stats(stat),float(pInfo->stats[stat]));
SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
}
}
else // not exist in DB, use some default fake data
@ -1092,11 +891,11 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
SetCreateMana( uint32(((float(cinfo->maxmana) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
SetCreateStat(STAT_STRENGTH,22);
SetCreateStat(STAT_AGILITY,22);
SetCreateStat(STAT_STAMINA,25);
SetCreateStat(STAT_INTELLECT,28);
SetCreateStat(STAT_SPIRIT,27);
SetCreateStat(STAT_STRENGTH, 22);
SetCreateStat(STAT_AGILITY, 22);
SetCreateStat(STAT_STAMINA, 25);
SetCreateStat(STAT_INTELLECT, 28);
SetCreateStat(STAT_SPIRIT, 27);
}
break;
}
@ -1131,34 +930,35 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
// remove elite bonuses included in DB values
SetCreateHealth( uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
SetCreateStat(STAT_STRENGTH,22);
SetCreateStat(STAT_AGILITY,22);
SetCreateStat(STAT_STAMINA,25);
SetCreateStat(STAT_INTELLECT,28);
SetCreateStat(STAT_SPIRIT,27);
SetCreateStat(STAT_STRENGTH, 22);
SetCreateStat(STAT_AGILITY, 22);
SetCreateStat(STAT_STAMINA, 25);
SetCreateStat(STAT_INTELLECT, 28);
SetCreateStat(STAT_SPIRIT, 27);
}
break;
}
case GUARDIAN_PET:
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
SetCreateMana( 28 + 10*petlevel );
SetCreateHealth( 28 + 30*petlevel );
SetCreateMana(28 + 10*petlevel);
SetCreateHealth(28 + 30*petlevel);
// FIXME: this is wrong formula, possible each guardian pet have own damage formula
//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)) );
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
//damage range is then petlevel / 2
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)) );
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
break;
default:
sLog.outError("Pet have incorrect type (%u) for levelup.",getPetType()); break;
sLog.outError("Pet have incorrect type (%u) for levelup.", getPetType());
break;
}
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]) );
SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]));
UpdateAllStats();
@ -1189,7 +989,7 @@ bool Pet::HaveInDiet(ItemPrototype const* item) const
uint32 Pet::GetCurrentFoodBenefitLevel(uint32 itemlevel)
{
// -5 or greater food level
if(getLevel() <= itemlevel +5) //possible to feed level 60 pet with level 55 level food for full effect
if(getLevel() <= itemlevel + 5) //possible to feed level 60 pet with level 55 level food for full effect
return 35000;
// -10..-6
else if(getLevel() <= itemlevel + 10) //pure guess, but sounds good
@ -1239,7 +1039,7 @@ void Pet::_LoadSpellCooldowns()
_AddCreatureSpellCooldown(spell_id,db_time);
sLog.outDebug("Pet (Number: %u) spell %u cooldown loaded (%u secs).",m_charmInfo->GetPetNumber(),spell_id,uint32(db_time-curTime));
sLog.outDebug("Pet (Number: %u) spell %u cooldown loaded (%u secs).", m_charmInfo->GetPetNumber(), spell_id, uint32(db_time-curTime));
}
while( result->NextRow() );
@ -1313,10 +1113,6 @@ 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,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
if(result)
@ -1382,7 +1178,7 @@ void Pet::_LoadAuras(uint32 timediff)
void Pet::_SaveAuras()
{
CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber());
AuraMap const& auras = GetAuras();
for(AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
@ -1483,7 +1279,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
}
}
uint16 tmpslot=slot_id;
uint16 tmpslot = slot_id;
if (tmpslot == 0xffff)
{
@ -1500,6 +1296,16 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
newspell->slotId = tmpslot;
m_spells[spell_id] = newspell;
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
{
if(!IsPassiveSpell(spell_id))
{
WorldPacket data(SMSG_PET_LEARNED_SPELL, 2);
data << uint16(spell_id);
((Player*)GetOwner())->GetSession()->SendPacket(&data);
}
}
if (IsPassiveSpell(spell_id))
CastSpell(this, spell_id, true);
else if(state == PETSPELL_NEW)
@ -1518,7 +1324,7 @@ bool Pet::learnSpell(uint16 spell_id)
return false;
Unit* owner = GetOwner();
if(owner->GetTypeId()==TYPEID_PLAYER)
if(owner->GetTypeId() == TYPEID_PLAYER)
((Player*)owner)->PetSpellInitialize();
return true;
}
@ -1541,6 +1347,16 @@ void Pet::removeSpell(uint16 spell_id)
itr->second->state = PETSPELL_REMOVED;
RemoveAurasDueToSpell(spell_id);
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
{
if(!IsPassiveSpell(spell_id))
{
WorldPacket data(SMSG_PET_UNLEARNED_SPELL, 2);
data << uint16(spell_id);
((Player*)GetOwner())->GetSession()->SendPacket(&data);
}
}
}
bool Pet::_removeSpell(uint16 spell_id)
@ -1560,7 +1376,7 @@ void Pet::InitPetCreateSpells()
m_charmInfo->InitPetActionBar();
m_spells.clear();
int32 usedtrainpoints = 0, petspellid;
int32 petspellid;
PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry());
if(CreateSpells)
{
@ -1589,23 +1405,12 @@ 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)
@ -1693,8 +1498,7 @@ 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, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
if(getPetType() == MINI_PET) // always non-attackable
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
@ -1735,7 +1539,7 @@ void Pet::CastPetAuras(bool current)
if(getPetType() != HUNTER_PET && (getPetType() != SUMMON_PET || owner->getClass() != CLASS_WARLOCK))
return;
for(PetAuraSet::iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end(); )
for(PetAuraSet::iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();)
{
PetAura const* pa = *itr;
++itr;
@ -1756,7 +1560,7 @@ void Pet::CastPetAura(PetAura const* aura)
if(auraId == 35696) // Demonic Knowledge
{
int32 basePoints = int32(aura->GetDamage() * (GetStat(STAT_STAMINA) + GetStat(STAT_INTELLECT)) / 100);
CastCustomSpell(this,auraId,&basePoints, NULL, NULL, true );
CastCustomSpell(this, auraId, &basePoints, NULL, NULL, true);
}
else
CastSpell(this, auraId, true);