diff options
Diffstat (limited to 'src/game/Pet.cpp')
-rw-r--r-- | src/game/Pet.cpp | 302 |
1 files changed, 1 insertions, 301 deletions
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 47d406f6453..29d9ffc34c8 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -17,7 +17,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include "Common.h" #include "Database/DatabaseEnv.h" #include "Log.h" @@ -30,7 +29,6 @@ #include "CreatureAI.h" #include "Unit.h" #include "Util.h" - char const* petTypeSuffix[MAX_PET_TYPE] = { "'s Minion", // SUMMON_PET @@ -38,9 +36,7 @@ char const* petTypeSuffix[MAX_PET_TYPE] = "'s Guardian", // GUARDIAN_PET "'s Companion" // MINI_PET }; - #define PET_XP_FACTOR 0.1f - Pet::Pet(Player *owner, PetType type) : Guardian(NULL, owner), m_petType(type), m_removed(false), m_happinessTimer(7500), m_duration(0), m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraRaidUpdateMask(0), m_loading(false), @@ -49,24 +45,19 @@ m_declinedname(NULL), m_owner(owner) m_unitTypeMask |= UNIT_MASK_PET; if(type == HUNTER_PET) m_unitTypeMask |= UNIT_MASK_HUNTER_PET; - if (!(m_unitTypeMask & UNIT_MASK_CONTROLABLE_GUARDIAN)) { m_unitTypeMask |= UNIT_MASK_CONTROLABLE_GUARDIAN; InitCharmInfo(); } - m_name = "Pet"; m_regenTimer = 4000; - m_isWorldObject = true; } - Pet::~Pet() { delete m_declinedname; } - void Pet::AddToWorld() { ///- Register the pet for guid lookup @@ -77,7 +68,6 @@ void Pet::AddToWorld() Unit::AddToWorld(); AIM_Initialize(); } - // Prevent stuck pets when zoning. Pets default to "follow" when added to world // so we'll reset flags and let the AI handle things if (this->GetCharmInfo() && this->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) @@ -87,9 +77,7 @@ void Pet::AddToWorld() this->GetCharmInfo()->SetIsFollowing(false); this->GetCharmInfo()->SetIsReturning(false); } - } - void Pet::RemoveFromWorld() { ///- Remove the pet from the accessor @@ -100,15 +88,11 @@ void Pet::RemoveFromWorld() ObjectAccessor::Instance().RemoveObject(this); } } - bool Pet::LoadPetFromDB( Player* 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 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 " @@ -131,12 +115,9 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool 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); - if(!result) return false; - Field *fields = result->Fetch(); - // update for case of current pet "slot = 0" petentry = fields[1].GetUInt32(); if (!petentry) @@ -144,19 +125,15 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool delete result; return false; } - uint32 summon_spell_id = fields[17].GetUInt32(); SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id); - bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0; - // check temporary summoned pets like mage water elemental if (current && is_temporary_summoned) { delete result; return false; } - PetType pet_type = PetType(fields[18].GetUInt8()); if(pet_type==HUNTER_PET) { @@ -167,16 +144,13 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return false; } } - uint32 pet_number = fields[0].GetUInt32(); - if (current && owner->IsPetNeedBeTemporaryUnsummoned()) { owner->SetTemporaryUnsummonedPetNumber(pet_number); delete result; return false; } - Map *map = owner->GetMap(); uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_PET); if (!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number)) @@ -184,11 +158,9 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool delete result; return false; } - float px, py, pz; owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle()); Relocate(px, py, pz, owner->GetOrientation()); - if (!IsPositionValid()) { sLog.outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", @@ -196,11 +168,9 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool delete result; return false; } - setPetType(pet_type); setFaction(owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); - CreatureInfo const *cinfo = GetCreatureInfo(); if (cinfo->type == CREATURE_TYPE_CRITTER) { @@ -208,20 +178,16 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool delete result; return true; } - m_charmInfo->SetPetNumber(pet_number, IsPermanentPetFor(owner)); - SetDisplayId(fields[3].GetUInt32()); SetNativeDisplayId(fields[3].GetUInt32()); uint32 petlevel = fields[4].GetUInt32(); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); SetName(fields[8].GetString()); - switch (getPetType()) { case SUMMON_PET: petlevel=owner->getLevel(); - SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); //class=mage SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) @@ -230,7 +196,6 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); //class=warrior,gender=none,power=focus SetSheath(SHEATH_STATE_MELEE); 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)); @@ -242,16 +207,12 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType()); break; } - SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); SetCreatorGUID(owner->GetGUID()); - SetReactState( ReactStates( fields[6].GetUInt8() )); - SetCanModifyStats(true); InitStatsForLevel(petlevel); - if(getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current { SetHealth(GetMaxHealth()); @@ -264,7 +225,6 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana); } - // set current pet as current // 0=current // 1..MAX_PET_STABLES in stable slot @@ -278,7 +238,6 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool PET_SAVE_AS_CURRENT, ownerid, m_charmInfo->GetPetNumber()); CharacterDatabase.CommitTransaction(); } - // Send fake summon spell cast - this is needed for correct cooldown application for spells // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside // TODO: pets should be summoned from real cast instead of just faking it? @@ -293,50 +252,37 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool data << uint32(0); SendMessageToSet(&data, true); } - owner->SetMinion(this, true); map->Add((Creature*)this); - m_resetTalentsCost = fields[15].GetUInt32(); m_resetTalentsTime = fields[16].GetUInt64(); InitTalentForLevel(); // set original talents points before spell loading - uint32 timediff = (time(NULL) - fields[14].GetUInt32()); _LoadAuras(timediff); - // load action bar, if data broken will fill later by default spells. if (!is_temporary_summoned) { m_charmInfo->LoadPetActionBar(fields[13].GetCppString()); - _LoadSpells(); _LoadSpellCooldowns(); LearnPetPassives(); InitLevelupSpellsForLevel(); CastPetAuras(current); } - CleanupActionBar(); // remove unknown spells from action bar after load - delete result; sLog.outDebug("New Pet has guid %u", GetGUIDLow()); - owner->PetSpellInitialize(); - if(owner->GetGroup()) owner->SetGroupUpdateFlag(GROUP_UPDATE_PET); - owner->SendTalentsInfoData(true); - if(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()); - if(result) { if(m_declinedname) delete m_declinedname; - m_declinedname = new DeclinedName; Field *fields2 = result->Fetch(); for(uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) @@ -345,34 +291,26 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool } } } - //set last used pet number (for use in BG's) if(owner->GetTypeId() == TYPEID_PLAYER && isControlled() && !isTemporarySummoned() && (getPetType() == SUMMON_PET || getPetType() == HUNTER_PET)) ((Player*)owner)->SetLastPetNumber(pet_number); - m_loading = false; - SynchronizeLevelWithOwner(); return true; } - void Pet::SavePetToDB(PetSaveMode mode) { if (!GetEntry()) return; - // save only fully controlled creature if (!isControlled()) return; - // not save not player pets if(!IS_PLAYER_GUID(GetOwnerGUID())) return; - Player* pOwner = (Player*)GetOwner(); if (!pOwner) return; - // not save pet as current if another pet temporary unsummoned if (mode == PET_SAVE_AS_CURRENT && pOwner->GetTemporaryUnsummonedPetNumber() && pOwner->GetTemporaryUnsummonedPetNumber() != m_charmInfo->GetPetNumber()) @@ -380,24 +318,19 @@ void Pet::SavePetToDB(PetSaveMode mode) // pet will lost anyway at restore temporary unsummoned if(getPetType()==HUNTER_PET) return; - // for warlock case mode = PET_SAVE_NOT_IN_SLOT; } - uint32 curhealth = GetHealth(); uint32 curmana = GetPower(POWER_MANA); - // stable and not in slot saves if(mode > PET_SAVE_AS_CURRENT) { RemoveAllAuras(); } - _SaveSpells(); _SaveSpellCooldowns(); _SaveAuras(); - // current/stable/not_in_slot if(mode >= PET_SAVE_AS_CURRENT) { @@ -407,12 +340,10 @@ void Pet::SavePetToDB(PetSaveMode mode) CharacterDatabase.BeginTransaction(); // remove current data CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND id = '%u'", owner,m_charmInfo->GetPetNumber() ); - // prevent duplicate using slot (except PET_SAVE_NOT_IN_SLOT) if(mode <= PET_SAVE_LAST_STABLE_SLOT) CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u'", PET_SAVE_NOT_IN_SLOT, owner, uint32(mode) ); - // prevent existence another hunter pet in PET_SAVE_AS_CURRENT and PET_SAVE_NOT_IN_SLOT if(getPetType()==HUNTER_PET && (mode==PET_SAVE_AS_CURRENT||mode > PET_SAVE_LAST_STABLE_SLOT)) CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u')", @@ -434,21 +365,18 @@ void Pet::SavePetToDB(PetSaveMode mode) << (curhealth<1?1:curhealth) << ", " << curmana << ", " << GetPower(POWER_HAPPINESS) << ", '"; - // save only spell slots from action bar for(uint32 i = ACTION_BAR_INDEX_PET_SPELL_START; i < ACTION_BAR_INDEX_PET_SPELL_END; ++i) { ss << uint32(m_charmInfo->GetActionBarEntry(i)->GetType()) << " " << uint32(m_charmInfo->GetActionBarEntry(i)->GetAction()) << " "; }; - ss << "', " << time(NULL) << ", " << uint32(m_resetTalentsCost) << ", " << uint64(m_resetTalentsTime) << ", " << GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", " << uint32(getPetType()) << ")"; - CharacterDatabase.Execute( ss.str().c_str() ); CharacterDatabase.CommitTransaction(); } @@ -459,7 +387,6 @@ void Pet::SavePetToDB(PetSaveMode mode) DeleteFromDB(m_charmInfo->GetPetNumber()); } } - void Pet::DeleteFromDB(uint32 guidlow) { CharacterDatabase.PExecute("DELETE FROM character_pet WHERE id = '%u'", guidlow); @@ -468,7 +395,6 @@ void Pet::DeleteFromDB(uint32 guidlow) CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u'", guidlow); CharacterDatabase.PExecute("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", guidlow); } - void Pet::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState { Creature::setDeathState(s); @@ -479,12 +405,10 @@ void Pet::setDeathState(DeathState s) // overwrite virtual // pet corpse non lootable and non skinnable SetUInt32Value( UNIT_DYNAMIC_FLAGS, 0x00 ); RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); - //lose happiness when died and not in BG/Arena MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId()); 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); } } @@ -494,12 +418,10 @@ void Pet::setDeathState(DeathState s) // overwrite virtual CastPetAuras(true); } } - void Pet::Update(uint32 diff) { if(m_removed) // pet already removed, just wait in remove queue, no updates return; - switch( m_deathState ) { case CORPSE: @@ -521,7 +443,6 @@ void Pet::Update(uint32 diff) Remove(PET_SAVE_NOT_IN_SLOT, true); return; } - if(isControlled()) { if( owner->GetPetGUID() != GetGUID() ) @@ -531,7 +452,6 @@ void Pet::Update(uint32 diff) return; } } - if(m_duration > 0) { if(m_duration > diff) @@ -542,7 +462,6 @@ void Pet::Update(uint32 diff) return; } } - //regenerate focus for hunter pets or energy for deathknight's ghoul if(m_regenTimer) { @@ -567,12 +486,10 @@ void Pet::Update(uint32 diff) m_regenTimer = 0; break; } - } + } } - if(getPetType() != HUNTER_PET) break; - if(m_happinessTimer <= diff) { LooseHappiness(); @@ -580,7 +497,6 @@ void Pet::Update(uint32 diff) } else m_happinessTimer -= diff; - break; } default: @@ -588,17 +504,13 @@ void Pet::Update(uint32 diff) } Creature::Update(diff); } - void Creature::Regenerate(Powers power) { uint32 curValue = GetPower(power); uint32 maxValue = GetMaxPower(power); - if (curValue >= maxValue) return; - float addvalue = 0.0f; - switch (power) { case POWER_FOCUS: @@ -616,16 +528,13 @@ void Creature::Regenerate(Powers power) default: return; } - // Apply modifiers (if any). AuraEffectList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); for(AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) if ((*i)->GetMiscValue() == power) addvalue *= ((*i)->GetAmount() + 100) / 100.0f; - ModifyPower(power, (int32)addvalue); } - void Pet::LooseHappiness() { uint32 curValue = GetPower(POWER_HAPPINESS); @@ -636,7 +545,6 @@ void Pet::LooseHappiness() addvalue = int32(addvalue * 1.5); ModifyPower(POWER_HAPPINESS, -addvalue); } - HappinessState Pet::GetHappinessState() { if(GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE) @@ -646,35 +554,26 @@ HappinessState Pet::GetHappinessState() else return CONTENT; } - bool Pet::CanTakeMoreActiveSpells(uint32 spellid) { uint8 activecount = 1; uint32 chainstartstore[ACTIVE_SPELLS_MAX]; - if(IsPassiveSpell(spellid)) return true; - chainstartstore[0] = spellmgr.GetFirstSpellInChain(spellid); - for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) { if(itr->second.state == PETSPELL_REMOVED) continue; - if(IsPassiveSpell(itr->first)) continue; - uint32 chainstart = spellmgr.GetFirstSpellInChain(itr->first); - uint8 x; - for(x = 0; x < activecount; x++) { if(chainstart == chainstartstore[x]) break; } - if(x == activecount) //spellchain not yet saved -> add active count { ++activecount; @@ -685,63 +584,48 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid) } return true; } - void Pet::Remove(PetSaveMode mode, bool returnreagent) { m_owner->RemovePet(this,mode,returnreagent); } - void Pet::GivePetXP(uint32 xp) { if(getPetType() != HUNTER_PET) return; - if ( xp < 1 ) return; - if(!isAlive()) return; - uint32 level = getLevel(); - // XP to money conversion processed in Player::RewardQuest if(level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) return; - uint32 curXP = GetUInt32Value(UNIT_FIELD_PETEXPERIENCE); uint32 nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); uint32 newXP = curXP + xp; - if(newXP >= nextLvlXP && level+1 > GetOwner()->getLevel()) { SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, nextLvlXP-1); return; } - while( newXP >= nextLvlXP && level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) { newXP -= nextLvlXP; - GivePetLevel(level+1); SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(level+1)*PET_XP_FACTOR); - level = getLevel(); nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); } - SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP); } - void Pet::GivePetLevel(uint32 level) { if(!level) return; - InitStatsForLevel(level); InitLevelupSpellsForLevel(); InitTalentForLevel(); } - bool Pet::CreateBaseAtCreature(Creature* creature) { if(!creature) @@ -750,28 +634,23 @@ bool Pet::CreateBaseAtCreature(Creature* creature) return false; } uint32 guid=objmgr.GenerateLowGuid(HIGHGUID_PET); - sLog.outDebug("Create pet"); uint32 pet_number = objmgr.GeneratePetNumber(); if(!Create(guid, creature->GetMap(), creature->GetPhaseMask(), creature->GetEntry(), pet_number)) return false; - Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); - if(!IsPositionValid()) { sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); return false; } - CreatureInfo const *cinfo = GetCreatureInfo(); if(!cinfo) { sLog.outError("CreateBaseAtCreature() failed, creatureInfo is missing!"); return false; } - SetDisplayId(creature->GetDisplayId()); SetNativeDisplayId(creature->GetNativeDisplayId()); SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); @@ -781,12 +660,10 @@ bool Pet::CreateBaseAtCreature(Creature* creature) SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(creature->getLevel())*PET_XP_FACTOR); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); - if(CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family)) SetName(cFamily->Name[sWorld.GetDefaultDbcLocale()]); else SetName(creature->GetNameForLocaleIdx(objmgr.GetDBCLocaleIndex())); - if(cinfo->type == CREATURE_TYPE_BEAST) { SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); @@ -796,15 +673,12 @@ bool Pet::CreateBaseAtCreature(Creature* creature) } return true; } - // TODO: Move stat mods code to pet passive auras bool Guardian::InitStatsForLevel(uint32 petlevel) { CreatureInfo const *cinfo = GetCreatureInfo(); assert(cinfo); - SetLevel(petlevel); - //Determine pet type PetType petType = MAX_PET_TYPE; if(isPet() && m_owner->GetTypeId() == TYPEID_PLAYER) @@ -819,19 +693,13 @@ bool Guardian::InitStatsForLevel(uint32 petlevel) else sLog.outError("Unknown type pet %u is summoned by player class %u", GetEntry(), m_owner->getClass()); } - uint32 creature_ID = (petType == HUNTER_PET) ? 1 : cinfo->Entry; - SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); - SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50)); - SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME); SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME); SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME); - SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0); - //scale CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family); if(cFamily && cFamily->minScale > 0.0f && petType==HUNTER_PET) @@ -843,10 +711,8 @@ bool Guardian::InitStatsForLevel(uint32 petlevel) scale = cFamily->minScale; else scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale); - SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } - //resistance int32 createResistance[MAX_SPELL_SCHOOL] = {0,0,0,0,0,0,0}; if(cinfo && petType != HUNTER_PET) @@ -860,7 +726,6 @@ bool Guardian::InitStatsForLevel(uint32 petlevel) } for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i])); - //health, mana, armor and resistance PetLevelInfo const* pInfo = objmgr.GetPetLevelInfo(creature_ID, petlevel); if(pInfo) // exist in DB @@ -868,10 +733,8 @@ bool Guardian::InitStatsForLevel(uint32 petlevel) SetCreateHealth(pInfo->health); if(petType != HUNTER_PET) //hunter pet use focus SetCreateMana(pInfo->mana); - if(pInfo->armor > 0) SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); - for(uint8 stat = 0; stat < MAX_STATS; ++stat) SetCreateStat(Stats(stat), float(pInfo->stats[stat])); } @@ -880,14 +743,12 @@ bool Guardian::InitStatsForLevel(uint32 petlevel) // remove elite bonuses included in DB values //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); } - m_bonusdamage = 0; switch(petType) { @@ -899,10 +760,8 @@ bool Guardian::InitStatsForLevel(uint32 petlevel) uint32 val = (fire > shadow) ? fire : shadow; SetBonusDamage(int32 (val * 0.15f)); //bonusAP += val * 0.57; - SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) ); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)) ); - //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower)); break; } @@ -996,32 +855,25 @@ bool Guardian::InitStatsForLevel(uint32 petlevel) break; } } - UpdateAllStats(); - SetHealth(GetMaxHealth()); SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); return true; } - bool Pet::HaveInDiet(ItemPrototype const* item) const { if (!item->FoodType) return false; - CreatureInfo const* cInfo = GetCreatureInfo(); if(!cInfo) return false; - CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family); if(!cFamily) return false; - uint32 diet = cFamily->petFoodMask; uint32 FoodMask = 1 << (item->FoodType-1); return diet & FoodMask; } - uint32 Pet::GetCurrentFoodBenefitLevel(uint32 itemlevel) { // -5 or greater food level @@ -1037,63 +889,47 @@ uint32 Pet::GetCurrentFoodBenefitLevel(uint32 itemlevel) else return 0; //food too low level } - void Pet::_LoadSpellCooldowns() { m_CreatureSpellCooldowns.clear(); m_CreatureCategoryCooldowns.clear(); - QueryResult *result = CharacterDatabase.PQuery("SELECT spell,time FROM pet_spell_cooldown WHERE guid = '%u'",m_charmInfo->GetPetNumber()); - if(result) { time_t curTime = time(NULL); - WorldPacket data(SMSG_SPELL_COOLDOWN, (8+1+result->GetRowCount()*8)); data << GetGUID(); data << uint8(0x0); // flags (0x1, 0x2) - do { Field *fields = result->Fetch(); - uint32 spell_id = fields[0].GetUInt32(); time_t db_time = (time_t)fields[1].GetUInt64(); - if(!sSpellStore.LookupEntry(spell_id)) { sLog.outError("Pet %u have unknown spell %u in `pet_spell_cooldown`, skipping.",m_charmInfo->GetPetNumber(),spell_id); continue; } - // skip outdated cooldown if(db_time <= curTime) continue; - data << uint32(spell_id); data << uint32(uint32(db_time-curTime)*IN_MILISECONDS); - _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)); } while( result->NextRow() ); - delete result; - if(!m_CreatureSpellCooldowns.empty() && GetOwner()) { ((Player*)GetOwner())->GetSession()->SendPacket(&data); } } } - void Pet::_SaveSpellCooldowns() { CharacterDatabase.PExecute("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", m_charmInfo->GetPetNumber()); - time_t curTime = time(NULL); - // remove oudated and save active for(CreatureSpellCooldowns::iterator itr = m_CreatureSpellCooldowns.begin();itr != m_CreatureSpellCooldowns.end();) { @@ -1106,35 +942,28 @@ void Pet::_SaveSpellCooldowns() } } } - void Pet::_LoadSpells() { QueryResult *result = CharacterDatabase.PQuery("SELECT spell,active FROM pet_spell WHERE guid = '%u'",m_charmInfo->GetPetNumber()); - if(result) { do { Field *fields = result->Fetch(); - addSpell(fields[0].GetUInt32(), ActiveStates(fields[1].GetUInt8()), PETSPELL_UNCHANGED); } while( result->NextRow() ); - delete result; } } - void Pet::_SaveSpells() { for (PetSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next) { ++next; - // prevent saving family passives to DB if (itr->second.type == PETSPELL_FAMILY) continue; - switch(itr->second.state) { case PETSPELL_REMOVED: @@ -1151,17 +980,13 @@ void Pet::_SaveSpells() case PETSPELL_UNCHANGED: continue; } - itr->second.state = PETSPELL_UNCHANGED; } } - void Pet::_LoadAuras(uint32 timediff) { sLog.outDebug("Loading auras for pet %u",GetGUIDLow()); - QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_mask,stackcount,amount0, amount1, amount2 ,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber()); - if(result) { do @@ -1178,23 +1003,19 @@ void Pet::_LoadAuras(uint32 timediff) int32 maxduration = (int32)fields[7].GetUInt32(); int32 remaintime = (int32)fields[8].GetUInt32(); int32 remaincharges = (int32)fields[9].GetUInt32(); - SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid); if(!spellproto) { sLog.outError("Unknown aura (spellid %u), ignore.",spellid); continue; } - // negative effects should continue counting down after logout if (remaintime != -1 && !IsPositiveSpell(spellid)) { if(remaintime <= int32(timediff)) continue; - remaintime -= timediff; } - // prevent wrong values of remaincharges if(spellproto->procCharges) { @@ -1203,7 +1024,6 @@ void Pet::_LoadAuras(uint32 timediff) } else remaincharges = 0; - Aura* aura = new Aura(spellproto, effmask, this, this, this); aura->SetLoadedState(caster_guid,maxduration,remaintime,remaincharges, stackcount, &damage[0]); if(!aura->CanBeSaved()) @@ -1215,21 +1035,17 @@ void Pet::_LoadAuras(uint32 timediff) sLog.outDetail("Added aura spellid %u, effectmask %u", spellproto->Id, effmask); } while( result->NextRow() ); - delete result; } } - void Pet::_SaveAuras() { 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) { if(!itr->second->CanBeSaved()) continue; - int32 amounts[MAX_SPELL_EFFECTS]; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { @@ -1238,7 +1054,6 @@ void Pet::_SaveAuras() else amounts[i] = 0; } - CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_mask,stackcount,amount0, amount1, amount2,maxduration,remaintime,remaincharges) " "VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%u')", m_charmInfo->GetPetNumber(), itr->second->GetCasterGUID(), itr->second->GetId(), (uint32)itr->second->GetEffectMask(), @@ -1246,7 +1061,6 @@ void Pet::_SaveAuras() ,itr->second->GetAuraMaxDuration(), itr->second->GetAuraDuration(), (uint32)itr->second->GetAuraCharges()); } } - bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); @@ -1260,10 +1074,8 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel } else sLog.outError("Pet::addSpell: Non-existed in SpellStore spell #%u request.",spell_id); - return false; } - PetSpellMap::iterator itr = m_spells.find(spell_id); if (itr != m_spells.end()) { @@ -1276,24 +1088,19 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel { // can be in case spell loading but learned at some previous spell loading itr->second.state = PETSPELL_UNCHANGED; - if(active == ACT_ENABLED) ToggleAutocast(spell_id, true); else if(active == ACT_DISABLED) ToggleAutocast(spell_id, false); - return false; } else return false; } - uint32 oldspell_id = 0; - PetSpell newspell; newspell.state = state; newspell.type = type; - if(active == ACT_DECIDE) //active was not used before, so we save it's autocast/passive state here { if(IsAutocastableSpell(spell_id)) @@ -1303,7 +1110,6 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel } else newspell.active = active; - // talent: unlearn all other talent ranks (high and low) if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id)) { @@ -1315,7 +1121,6 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel uint32 rankSpellId = talentInfo->RankID[i]; if(!rankSpellId || rankSpellId==spell_id) continue; - // skip unknown ranks if(!HasSpell(rankSpellId)) continue; @@ -1328,17 +1133,14 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel for (PetSpellMap::const_iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2) { if(itr2->second.state == PETSPELL_REMOVED) continue; - if( spellmgr.IsRankSpellDueToSpell(spellInfo,itr2->first) ) { // replace by new high rank if(spellmgr.IsHighRankOfSpell(spell_id,itr2->first)) { newspell.active = itr2->second.active; - if(newspell.active == ACT_ENABLED) ToggleAutocast(itr2->first, false); - oldspell_id = itr2->first; unlearnSpell(itr2->first,false,false); break; @@ -1349,17 +1151,13 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel } } } - m_spells[spell_id] = newspell; - if (IsPassiveSpell(spell_id)) CastSpell(this, spell_id, true); else m_charmInfo->AddSpellToActionBar(spell_id); - if(newspell.active == ACT_ENABLED) ToggleAutocast(spell_id, true); - uint32 talentCost = GetTalentSpellCost(spell_id); if (talentCost) { @@ -1371,13 +1169,11 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel } return true; } - bool Pet::learnSpell(uint32 spell_id) { // prevent duplicated entires in spell book if (!addSpell(spell_id)) return false; - if(!m_loading) { WorldPacket data(SMSG_PET_LEARNED_SPELL, 4); @@ -1387,11 +1183,9 @@ bool Pet::learnSpell(uint32 spell_id) } return true; } - void Pet::InitLevelupSpellsForLevel() { uint32 level = getLevel(); - if(PetLevelupSpellSet const *levelupSpells = GetCreatureInfo()->family ? spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family) : NULL) { // PetLevelupSpellSet ordered by levels, process in reversed order @@ -1405,9 +1199,7 @@ void Pet::InitLevelupSpellsForLevel() learnSpell(itr->second); // will unlearn prev rank if any } } - int32 petSpellsId = GetCreatureInfo()->PetSpellDataId ? -(int32)GetCreatureInfo()->PetSpellDataId : GetEntry(); - // default spells (can be not learned if pet level (as owner level decrease result for example) less first possible in normal game) if(PetDefaultSpellsEntry const *defSpells = spellmgr.GetPetDefaultSpellsEntry(petSpellsId)) { @@ -1416,7 +1208,6 @@ void Pet::InitLevelupSpellsForLevel() SpellEntry const* spellEntry = sSpellStore.LookupEntry(defSpells->spellid[i]); if(!spellEntry) continue; - // will called first if level down if(spellEntry->spellLevel > level) unlearnSpell(spellEntry->Id,true); @@ -1426,7 +1217,6 @@ void Pet::InitLevelupSpellsForLevel() } } } - bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab) { if(removeSpell(spell_id,learn_prev,clear_ab)) @@ -1441,23 +1231,18 @@ bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab) } return false; } - 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()) return false; - if(itr->second.state == PETSPELL_REMOVED) return false; - if(itr->second.state == PETSPELL_NEW) m_spells.erase(itr); else itr->second.state = PETSPELL_REMOVED; - RemoveAurasDueToSpell(spell_id); - uint32 talentCost = GetTalentSpellCost(spell_id); if (talentCost > 0) { @@ -1469,7 +1254,6 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab) int32 free_points = GetMaxTalentPointsForLevel(getLevel()) - m_usedTalentCount; SetFreeTalentPoints(free_points > 0 ? free_points : 0); } - if (learn_prev) { if (uint32 prev_id = spellmgr.GetPrevSpellInChain (spell_id)) @@ -1477,7 +1261,6 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab) else learn_prev = false; } - // if remove last rank or non-ranked then update action bar at server and client if need if (clear_ab && !learn_prev && m_charmInfo->RemoveSpellFromActionBar(spell_id)) { @@ -1489,11 +1272,9 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab) ((Player*)owner)->PetSpellInitialize(); } } - return true; } - void Pet::CleanupActionBar() { for(uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) @@ -1506,28 +1287,22 @@ void Pet::CleanupActionBar() ToggleAutocast(ab->GetAction(), true); } } - void Pet::InitPetCreateSpells() { m_charmInfo->InitPetActionBar(); m_spells.clear(); - LearnPetPassives(); InitLevelupSpellsForLevel(); - CastPetAuras(false); } - bool Pet::resetTalents(bool no_cost) { Unit *owner = GetOwner(); if (!owner || owner->GetTypeId()!=TYPEID_PLAYER) return false; - // not need after this call if(((Player*)owner)->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) ((Player*)owner)->RemoveAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS,true); - CreatureInfo const * ci = GetCreatureInfo(); if(!ci) return false; @@ -1535,46 +1310,34 @@ bool Pet::resetTalents(bool no_cost) CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); if(!pet_family || pet_family->petTalentType < 0) return false; - Player *player = (Player *)owner; - uint32 level = getLevel(); uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); - if (m_usedTalentCount == 0) { SetFreeTalentPoints(talentPointsForLevel); return false; } - uint32 cost = 0; - if(!no_cost) { cost = resetTalentsCost(); - if (player->GetMoney() < cost) { player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); return false; } } - for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); - if (!talentInfo) continue; - TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); - if(!talentTabInfo) continue; - // unlearn only talents for pets family talent type if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) continue; - for (int j = 0; j < MAX_TALENT_RANK; j++) { for(PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end();) @@ -1586,7 +1349,6 @@ bool Pet::resetTalents(bool no_cost) } // remove learned spells (all ranks) uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first); - // unlearn if first rank is talent or learned by talent if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId)) { @@ -1599,13 +1361,10 @@ bool Pet::resetTalents(bool no_cost) } } } - SetFreeTalentPoints(talentPointsForLevel); - if(!no_cost) { player->ModifyMoney(-(int32)cost); - m_resetTalentsCost = cost; m_resetTalentsTime = time(NULL); } @@ -1613,91 +1372,65 @@ bool Pet::resetTalents(bool no_cost) player->PetSpellInitialize(); return true; } - void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* online_pet /*= NULL*/) { // not need after this call if(((Player*)owner)->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) ((Player*)owner)->RemoveAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS,true); - // reset for online if(online_pet) online_pet->resetTalents(true); - // now need only reset for offline pets (all pets except online case) uint32 except_petnumber = online_pet ? online_pet->GetCharmInfo()->GetPetNumber() : 0; - QueryResult *resultPets = CharacterDatabase.PQuery( "SELECT id FROM character_pet WHERE owner = '%u' AND id <> '%u'", owner->GetGUIDLow(),except_petnumber); - // no offline pets if(!resultPets) return; - QueryResult *result = CharacterDatabase.PQuery( "SELECT DISTINCT pet_spell.spell FROM pet_spell, character_pet " "WHERE character_pet.owner = '%u' AND character_pet.id = pet_spell.guid AND character_pet.id <> %u", owner->GetGUIDLow(),except_petnumber); - if(!result) { delete resultPets; return; } - bool need_comma = false; std::ostringstream ss; ss << "DELETE FROM pet_spell WHERE guid IN ("; - do { Field *fields = resultPets->Fetch(); - uint32 id = fields[0].GetUInt32(); - if(need_comma) ss << ","; - ss << id; - need_comma = true; } while( resultPets->NextRow() ); - delete resultPets; - ss << ") AND spell IN ("; - bool need_execute = false; do { Field *fields = result->Fetch(); - uint32 spell = fields[0].GetUInt32(); - if(!GetTalentSpellCost(spell)) continue; - if(need_execute) ss << ","; - ss << spell; - need_execute = true; } while( result->NextRow() ); - delete result; - if(!need_execute) return; - ss << ")"; - CharacterDatabase.Execute(ss.str().c_str()); } - void Pet::InitTalentForLevel() { uint32 level = getLevel(); @@ -1709,19 +1442,15 @@ void Pet::InitTalentForLevel() resetTalents(true); } SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); - Unit *owner = GetOwner(); if (!owner || owner->GetTypeId() != TYPEID_PLAYER) return; - if(!m_loading) ((Player*)owner)->SendTalentsInfoData(true); } - uint32 Pet::resetTalentsCost() const { uint32 days = (sWorld.GetGameTime() - m_resetTalentsTime)/DAY; - // The first time reset costs 10 silver; after 1 day cost is reset to 10 silver if(m_resetTalentsCost < 10*SILVER || days > 0) return 10*SILVER; @@ -1735,7 +1464,6 @@ uint32 Pet::resetTalentsCost() const else return (m_resetTalentsCost + 1*GOLD > 10*GOLD ? 10*GOLD : m_resetTalentsCost + 1*GOLD); } - uint8 Pet::GetMaxTalentPointsForLevel(uint32 level) { uint8 points = (level >= 20) ? ((level - 16) / 4) : 0; @@ -1744,27 +1472,21 @@ uint8 Pet::GetMaxTalentPointsForLevel(uint32 level) points+=owner->GetTotalAuraModifier(SPELL_AURA_MOD_PET_TALENT_POINTS); return points; } - void Pet::ToggleAutocast(uint32 spellid, bool apply) { if(!IsAutocastableSpell(spellid)) return; - PetSpellMap::iterator itr = m_spells.find(spellid); if(itr == m_spells.end()) return; - uint32 i; - if(apply) { for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; ++i) ; // just search - if (i == m_autospells.size()) { m_autospells.push_back(spellid); - if(itr->second.active != ACT_ENABLED) { itr->second.active = ACT_ENABLED; @@ -1778,7 +1500,6 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) AutoSpellList::iterator itr2 = m_autospells.begin(); for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; ++i, itr2++) ; // just search - if (i < m_autospells.size()) { m_autospells.erase(itr2); @@ -1791,7 +1512,6 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) } } } - bool Pet::IsPermanentPetFor(Player* owner) { switch(getPetType()) @@ -1812,43 +1532,33 @@ bool Pet::IsPermanentPetFor(Player* owner) return false; } } - bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number) { assert(map); SetMap(map); - SetPhaseMask(phaseMask,false); Object::_Create(guidlow, pet_number, HIGHGUID_PET); - m_DBTableGuid = guidlow; m_originalEntry = Entry; - if(!InitEntry(Entry)) return false; - SetSheath(SHEATH_STATE_MELEE); - return true; } - bool Pet::HasSpell(uint32 spell) const { PetSpellMap::const_iterator itr = m_spells.find(spell); return (itr != m_spells.end() && itr->second.state != PETSPELL_REMOVED ); } - // Get all passive spells in our skill line void Pet::LearnPetPassives() { CreatureInfo const* cInfo = GetCreatureInfo(); if(!cInfo) return; - CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family); if(!cFamily) return; - PetFamilySpellsStore::const_iterator petStore = sPetFamilySpellsStore.find(cFamily->ID); if(petStore != sPetFamilySpellsStore.end()) { @@ -1859,34 +1569,28 @@ void Pet::LearnPetPassives() addSpell(*petSet, ACT_DECIDE, PETSPELL_NEW, PETSPELL_FAMILY); } } - void Pet::CastPetAuras(bool current) { Unit* owner = GetOwner(); if(!owner || owner->GetTypeId()!=TYPEID_PLAYER) return; - if(!IsPermanentPetFor((Player*)owner)) return; - for(PetAuraSet::const_iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();) { PetAura const* pa = *itr; ++itr; - if(!current && pa->IsRemovedOnChangePet()) owner->RemovePetAura(pa); else CastPetAura(pa); } } - void Pet::CastPetAura(PetAura const* aura) { uint32 auraId = aura->GetAura(GetEntry()); if(!auraId) return; - if(auraId == 35696) // Demonic Knowledge { int32 basePoints = int32(aura->GetDamage() * (GetStat(STAT_STAMINA) + GetStat(STAT_INTELLECT)) / 100); @@ -1895,21 +1599,17 @@ void Pet::CastPetAura(PetAura const* aura) else CastSpell(this, auraId, true); } - void Pet::learnSpellHighRank(uint32 spellid) { learnSpell(spellid); - if(uint32 next = spellmgr.GetNextSpellInChain(spellid)) learnSpellHighRank(next); } - void Pet::SynchronizeLevelWithOwner() { Unit* owner = GetOwner(); if (!owner || owner->GetTypeId() != TYPEID_PLAYER) return; - switch(getPetType()) { // always same level |