// TODO: Move stat mods code to pet passive auras bool Guardian::InitStatsForLevel(uint8 petlevel) { CreatureTemplate const* cinfo = GetCreatureInfo(); ASSERT(cinfo); SetLevel(petlevel); //Determine pet type PetType petType = MAX_PET_TYPE; if (isPet() && m_owner->GetTypeId() == TYPEID_PLAYER) { if ((m_owner->getClass() == CLASS_WARLOCK) || (m_owner->getClass() == CLASS_SHAMAN) // Fire Elemental || (m_owner->getClass() == CLASS_DEATH_KNIGHT)) // Risen Ghoul petType = SUMMON_PET; else if (m_owner->getClass() == CLASS_HUNTER) { petType = HUNTER_PET; m_unitTypeMask |= UNIT_MASK_HUNTER_PET; } 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.0f); //scale CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family); if (cFamily && cFamily->minScale > 0.0f && petType == HUNTER_PET) { 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); SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } // Resistance for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i])); //health, mana, armor and resistance PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel); if (pInfo) // exist in DB { 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])); } else // not exist in DB, use some default fake data { // remove elite bonuses included in DB values CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(petlevel, cinfo->unit_class); SetCreateHealth(stats->BaseHealth[cinfo->expansion]); SetCreateMana(stats->BaseMana); SetCreateStat(STAT_STRENGTH, 22); SetCreateStat(STAT_AGILITY, 22); SetCreateStat(STAT_STAMINA, 25); SetCreateStat(STAT_INTELLECT, 28); SetCreateStat(STAT_SPIRIT, 27); } SetBonusDamage(0); switch (petType) { case SUMMON_PET: { //the damage bonus used for pets is either fire or shadow damage, whatever is higher uint32 fire = m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE); uint32 shadow = m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW); 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; } case HUNTER_PET: { SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32(sObjectMgr->GetXPForLevel(petlevel)*PET_XP_FACTOR)); //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))); //damage range is then petlevel / 2 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(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(int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FROST) * 0.33f)); break; } case 1964: //force of nature { if (!pInfo) SetCreateHealth(30 + 30*petlevel); float bonusDmg = m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_NATURE) * 0.15f; SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 2.5f - (petlevel / 2) + bonusDmg)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 2.5f + (petlevel / 2) + bonusDmg)); break; } case 15352: //earth elemental 36213 { if (!pInfo) SetCreateHealth(100 + 120*petlevel); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); break; } case 15438: //fire elemental { if (!pInfo) { SetCreateHealth(40*petlevel); SetCreateMana(28 + 10*petlevel); } SetBonusDamage(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FIRE) * 0.5f); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel)); break; } case 19668: // Shadowfiend { if (!pInfo) { SetCreateMana(28 + 10*petlevel); SetCreateHealth(28 + 30*petlevel); } int32 bonus_dmg = (int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_SHADOW)* 0.3f)); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + bonus_dmg)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + bonus_dmg)); break; } case 19833: //Snake Trap - Venomous Snake { SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel / 2) - 25)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel / 2) - 18)); break; } case 19921: //Snake Trap - Viper { SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel / 2 - 10)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel / 2)); break; } case 29264: // Feral Spirit { if (!pInfo) SetCreateHealth(30*petlevel); float dmg_multiplier = 0.3f; if (m_owner->GetAuraEffect(63271, 0)) // Glyph of Feral Spirit dmg_multiplier = 0.6f; SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier)); // 14AP == 1dps, wolf's strike speed == 2s so dmg = basedmg + AP / 14 * 2 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + (m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier * 2 / 14))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + (m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier * 2 / 14))); SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(m_owner->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor) SetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(m_owner->GetStat(STAT_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(int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FROST) * 0.33f)); SetDisplayId(m_owner->GetDisplayId()); if (!pInfo) { SetCreateMana(28 + 30*petlevel); SetCreateHealth(28 + 10*petlevel); } break; } case 27829: // Ebon Gargoyle { if (!pInfo) { SetCreateMana(28 + 10*petlevel); SetCreateHealth(28 + 30*petlevel); } SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f)); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); break; } } break; } } UpdateAllStats(); SetFullHealth(); SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); return true; }
bool Creature::CreateFromProto(uint32 guidlow,uint32 Entry) { Object::_Create(guidlow, HIGHGUID_UNIT); m_DBTableGuid = guidlow; SetUInt32Value(OBJECT_FIELD_ENTRY,Entry); CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(Entry); if(!cinfo) { sLog.outError("Error: creature entry %u does not exist.",Entry); return false; } uint32 rank = isPet()? 0 : cinfo->rank; float damagemod = _GetDamageMod(rank);; uint32 display_id = cinfo->randomDisplayID(); SetUInt32Value(UNIT_FIELD_DISPLAYID,display_id ); SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID,display_id ); SetUInt32Value(UNIT_FIELD_BYTES_2,1); // let creature used equiped weapon in fight SetName(GetCreatureInfo()->Name); SelectLevel(cinfo); SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction); SetUInt32Value(UNIT_NPC_FLAGS,cinfo->npcflag); SetFloatValue(UNIT_FIELD_MINDAMAGE,cinfo->mindmg * damagemod); SetFloatValue(UNIT_FIELD_MAXDAMAGE,cinfo->maxdmg * damagemod); SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,cinfo->minrangedmg * damagemod); SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,cinfo->maxrangedmg * damagemod); SetAttackTime(BASE_ATTACK, cinfo->baseattacktime); SetAttackTime(RANGED_ATTACK,cinfo->rangeattacktime); SetUInt32Value(UNIT_FIELD_FLAGS,cinfo->Flags); SetUInt32Value(UNIT_DYNAMIC_FLAGS,cinfo->dynamicflags); SetArmor(cinfo->armor); SetResistance(SPELL_SCHOOL_HOLY,cinfo->resistance1); SetResistance(SPELL_SCHOOL_FIRE,cinfo->resistance2); SetResistance(SPELL_SCHOOL_NATURE,cinfo->resistance3); SetResistance(SPELL_SCHOOL_FROST,cinfo->resistance4); SetResistance(SPELL_SCHOOL_SHADOW,cinfo->resistance5); SetResistance(SPELL_SCHOOL_ARCANE,cinfo->resistance6); //this is probably wrong SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, cinfo->equipmodel[0]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , cinfo->equipinfo[0]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, cinfo->equipslot[0]); SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, cinfo->equipmodel[1]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 2, cinfo->equipinfo[1]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 2 + 1, cinfo->equipslot[1]); SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+2, cinfo->equipmodel[2]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 4, cinfo->equipinfo[2]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 4 + 1, cinfo->equipslot[2]); SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->size); SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,cinfo->bounding_radius); SetFloatValue(UNIT_FIELD_COMBATREACH,cinfo->combat_reach ); FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cinfo->faction); if (factionTemplate) { FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction); if (factionEntry) if (cinfo->civilian != 1 && (factionEntry->team == ALLIANCE || factionEntry->team == HORDE)) SetPvP(true); } else sLog.outErrorDb("Error: invalid faction (%u) for creature (GUIDLow: %u Entry: %u)", cinfo->faction, GetGUIDLow(),Entry); if (cinfo->mount != 0) Mount(cinfo->mount); m_spells[0] = cinfo->spell1; m_spells[1] = cinfo->spell2; m_spells[2] = cinfo->spell3; m_spells[3] = cinfo->spell4; SetSpeed(MOVE_WALK, cinfo->speed ); SetSpeed(MOVE_RUN, cinfo->speed ); SetSpeed(MOVE_WALKBACK, cinfo->speed ); SetSpeed(MOVE_SWIM, cinfo->speed); SetSpeed(MOVE_SWIMBACK, cinfo->speed); if(cinfo->MovementType < MAX_DB_MOTION_TYPE) m_defaultMovementType = MovementGeneratorType(cinfo->MovementType); else { m_defaultMovementType = IDLE_MOTION_TYPE; sLog.outErrorDb("Creature template %u have wrong movement generator type value %u, ignore and set to IDLE.",Entry,cinfo->MovementType); } return true; }