// @todo Move stat mods code to pet passive auras public bool InitStatsForLevel(uint petlevel) { CreatureTemplate cinfo = GetCreatureTemplate(); Cypher.Assert(cinfo != null); SetLevel(petlevel); //Determine pet type PetType petType = PetType.Max; if (IsPet() && GetOwner().IsTypeId(TypeId.Player)) { if (GetOwner().GetClass() == Class.Warlock || GetOwner().GetClass() == Class.Shaman || // Fire Elemental GetOwner().GetClass() == Class.Deathknight) // Risen Ghoul { petType = PetType.Summon; } else if (GetOwner().GetClass() == Class.Hunter) { petType = PetType.Hunter; UnitTypeMask |= UnitTypeMask.HunterPet; } else { Log.outError(LogFilter.Unit, "Unknown type pet {0} is summoned by player class {1}", GetEntry(), GetOwner().GetClass()); } } uint creature_ID = (petType == PetType.Hunter) ? 1 : cinfo.Entry; SetMeleeDamageSchool((SpellSchools)cinfo.DmgSchool); SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, (float)petlevel * 50); SetBaseAttackTime(WeaponAttackType.BaseAttack, SharedConst.BaseAttackTime); SetBaseAttackTime(WeaponAttackType.OffAttack, SharedConst.BaseAttackTime); SetBaseAttackTime(WeaponAttackType.RangedAttack, SharedConst.BaseAttackTime); //scale var cFamily = CliDB.CreatureFamilyStorage.LookupByKey(cinfo.Family); if (cFamily != null && cFamily.MinScale > 0.0f && petType == PetType.Hunter) { float scale; if (GetLevel() >= cFamily.MaxScaleLevel) { scale = cFamily.MaxScale; } else if (GetLevel() <= cFamily.MinScaleLevel) { scale = cFamily.MinScale; } else { scale = cFamily.MinScale + (float)(GetLevel() - cFamily.MinScaleLevel) / cFamily.MaxScaleLevel * (cFamily.MaxScale - cFamily.MinScale); } SetObjectScale(scale); } // Resistance // Hunters pet should not inherit resistances from creature_template, they have separate auras for that if (!IsHunterPet()) { for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i) { SetStatFlatModifier(UnitMods.ResistanceStart + i, UnitModifierFlatType.Base, cinfo.Resistance[i]); } } // Health, Mana or Power, Armor PetLevelInfo pInfo = Global.ObjectMgr.GetPetLevelInfo(creature_ID, petlevel); if (pInfo != null) // exist in DB { SetCreateHealth(pInfo.health); SetCreateMana(pInfo.mana); if (pInfo.armor > 0) { SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, pInfo.armor); } for (byte stat = 0; stat < (int)Stats.Max; ++stat) { SetCreateStat((Stats)stat, pInfo.stats[stat]); } } else // not exist in DB, use some default fake data { // remove elite bonuses included in DB values CreatureBaseStats stats = Global.ObjectMgr.GetCreatureBaseStats(petlevel, cinfo.UnitClass); CreatureLevelScaling scaling = cinfo.GetLevelScaling(GetMap().GetDifficultyID()); SetCreateHealth((uint)(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, petlevel, cinfo.GetHealthScalingExpansion(), scaling.ContentTuningID, (Class)cinfo.UnitClass) * cinfo.ModHealth * cinfo.ModHealthExtra)); SetCreateMana(stats.BaseMana); SetCreateStat(Stats.Strength, 22); SetCreateStat(Stats.Agility, 22); SetCreateStat(Stats.Stamina, 25); SetCreateStat(Stats.Intellect, 28); } // Power if (petType == PetType.Hunter) // Hunter pets have focus { SetPowerType(PowerType.Focus); } else if (IsPetGhoul() || IsPetAbomination()) // DK pets have energy { SetPowerType(PowerType.Energy); } else if (IsPetImp() || IsPetFelhunter() || IsPetVoidwalker() || IsPetSuccubus() || IsPetDoomguard() || IsPetFelguard()) // Warlock pets have energy (since 5.x) { SetPowerType(PowerType.Energy); } else { SetPowerType(PowerType.Mana); } // Damage SetBonusDamage(0); switch (petType) { case PetType.Summon: { // the damage bonus used for pets is either fire or shadow damage, whatever is higher int fire = GetOwner().ToPlayer().m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Fire]; int shadow = GetOwner().ToPlayer().m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Shadow]; int val = (fire > shadow) ? fire : shadow; if (val < 0) { val = 0; } SetBonusDamage((int)(val * 0.15f)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel + (petlevel / 4)); break; } case PetType.Hunter: { ToPet().SetPetNextLevelExperience((uint)(Global.ObjectMgr.GetXPForLevel(petlevel) * 0.05f)); //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(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4)); //damage range is then petlevel / 2 SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel + (petlevel / 4)); //damage is increased afterwards as strength and pet scaling modify attack power break; } default: { switch (GetEntry()) { case 510: // mage Water Elemental { SetBonusDamage((int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Frost) * 0.33f)); break; } case 1964: //force of nature { if (pInfo == null) { SetCreateHealth(30 + 30 * petlevel); } float bonusDmg = GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Nature) * 0.15f; SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel * 2.5f - ((float)petlevel / 2) + bonusDmg); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel * 2.5f + ((float)petlevel / 2) + bonusDmg); break; } case 15352: //earth elemental 36213 { if (pInfo == null) { SetCreateHealth(100 + 120 * petlevel); } SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel + (petlevel / 4)); break; } case 15438: //fire elemental { if (pInfo == null) { SetCreateHealth(40 * petlevel); SetCreateMana(28 + 10 * petlevel); } SetBonusDamage((int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Fire) * 0.5f)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel * 4 - petlevel); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel * 4 + petlevel); break; } case 19668: // Shadowfiend { if (pInfo == null) { SetCreateMana(28 + 10 * petlevel); SetCreateHealth(28 + 30 * petlevel); } int bonus_dmg = (int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Shadow) * 0.3f); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, (petlevel * 4 - petlevel) + bonus_dmg); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, (petlevel * 4 + petlevel) + bonus_dmg); break; } case 19833: //Snake Trap - Venomous Snake { SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, (petlevel / 2) - 25); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, (petlevel / 2) - 18); break; } case 19921: //Snake Trap - Viper { SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel / 2 - 10); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel / 2); break; } case 29264: // Feral Spirit { if (pInfo == null) { SetCreateHealth(30 * petlevel); } // wolf attack speed is 1.5s SetBaseAttackTime(WeaponAttackType.BaseAttack, cinfo.BaseAttackTime); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, (petlevel * 4 - petlevel)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, (petlevel * 4 + petlevel)); SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, GetOwner().GetArmor() * 0.35f); // Bonus Armor (35% of player armor) SetStatFlatModifier(UnitMods.StatStamina, UnitModifierFlatType.Base, GetOwner().GetStat(Stats.Stamina) * 0.3f); // Bonus Stamina (30% of player stamina) if (!HasAura(58877)) //prevent apply twice for the 2 wolves { AddAura(58877, this); //Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done. } break; } case 31216: // Mirror Image { SetBonusDamage((int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Frost) * 0.33f)); SetDisplayId(GetOwner().GetDisplayId()); if (pInfo == null) { SetCreateMana(28 + 30 * petlevel); SetCreateHealth(28 + 10 * petlevel); } break; } case 27829: // Ebon Gargoyle { if (pInfo == null) { SetCreateMana(28 + 10 * petlevel); SetCreateHealth(28 + 30 * petlevel); } SetBonusDamage((int)(GetOwner().GetTotalAttackPowerValue(WeaponAttackType.BaseAttack) * 0.5f)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel + (petlevel / 4)); break; } case 28017: // Bloodworms { SetCreateHealth(4 * petlevel); SetBonusDamage((int)(GetOwner().GetTotalAttackPowerValue(WeaponAttackType.BaseAttack) * 0.006f)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - 30 - (petlevel / 4)); SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel - 30 + (petlevel / 4)); } break; } break; } } UpdateAllStats(); SetFullHealth(); SetFullPower(PowerType.Mana); return(true); }