bool Minion::IsGuardianPet() const { return isPet() || (m_Properties && m_Properties->Category == SUMMON_CATEGORY_PET); }
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; }
bool Guardian::UpdateStats(Stats stat) { if (stat >= MAX_STATS) return false; // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); ApplyStatBuffMod(stat, m_statFromOwner[stat], false); float ownersBonus = 0.0f; Unit *owner = GetOwner(); // Handle Death Knight Glyphs and Talents float mod = 0.75f; if (IsPetGhoul() && (stat == STAT_STAMINA || stat == STAT_STRENGTH)) { switch (stat) { case STAT_STAMINA: mod = 0.3f; break; // Default Owner's Stamina scale case STAT_STRENGTH: mod = 0.7f; break; // Default Owner's Strength scale default: break; } // Ravenous Dead AuraEffect const *aurEff = NULL; // Check just if owner has Ravenous Dead since it's effect is not an aura aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0); if (aurEff) { SpellEntry const* sProto = aurEff->GetSpellProto(); // Then get the SpellProto and add the dummy effect value AddPctN(mod, SpellMgr::CalculateSpellEffectAmount(sProto, 1)); // Ravenous Dead edits the original scale } // Glyph of the Ghoul aurEff = owner->GetAuraEffect(58686, 0); if (aurEff) mod += CalculatePctN(1.0f, aurEff->GetAmount()); // Glyph of the Ghoul adds a flat value to the scale mod ownersBonus = float(owner->GetStat(stat)) * mod; value += ownersBonus; } else if (stat == STAT_STAMINA) { if (owner->getClass() == CLASS_WARLOCK && isPet()) { ownersBonus = CalculatePctN(owner->GetStat(STAT_STAMINA), 75); value += ownersBonus; } else { mod = 0.45f; if (isPet()) { PetSpellMap::const_iterator itr = (ToPet()->m_spells.find(62758)); // Wild Hunt rank 1 if (itr == ToPet()->m_spells.end()) itr = ToPet()->m_spells.find(62762); // Wild Hunt rank 2 if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellEntry const* sProto = sSpellStore.LookupEntry(itr->first); // Then get the SpellProto and add the dummy effect value AddPctN(mod, SpellMgr::CalculateSpellEffectAmount(sProto, 0)); } } ownersBonus = float(owner->GetStat(stat)) * mod; value += ownersBonus; } } //warlock's and mage's pets gain 30% of owner's intellect else if (stat == STAT_INTELLECT) { if (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) { ownersBonus = CalculatePctN(owner->GetStat(stat), 30); value += ownersBonus; } } /* else if (stat == STAT_STRENGTH) { if (IsPetGhoul()) value += float(owner->GetStat(stat)) * 0.3f; } */ SetStat(stat, int32(value)); m_statFromOwner[stat] = ownersBonus; ApplyStatBuffMod(stat, m_statFromOwner[stat], true); switch (stat) { case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; case STAT_AGILITY: UpdateArmor(); break; case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); break; case STAT_SPIRIT: default: break; } return true; }
bool Guardian::UpdateStats(Stats stat) { if (stat >= MAX_STATS) return false; // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); ApplyStatBuffMod(stat, m_statFromOwner[stat], false); float ownersBonus = 0.0f; Unit* owner = GetOwner(); float mod = 0.75f; switch (stat) { case STAT_STRENGTH: { if (IsPetGhoul()) { mod = 0.7f; // Glyph of the Ghoul if (AuraEffect const* aurEff = owner->GetAuraEffect(58686, 0)) mod += CalculatePct(1.0f, aurEff->GetAmount()); ownersBonus = owner->GetStat(stat) * mod; value += ownersBonus; } break; } case STAT_STAMINA: { mod = 0.0f; if (IsPetGhoul() || IsPetGargoyle()) { // Glyph of the Ghoul if (AuraEffect const* aurEff = owner->GetAuraEffect(58686, 0)) mod += CalculatePct(1.0f, aurEff->GetAmount()); } ownersBonus = owner->GetStat(stat) * mod; ownersBonus *= GetModifierValue(UNIT_MOD_STAT_STAMINA, TOTAL_PCT); value += ownersBonus; break; } case STAT_INTELLECT: { if (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) { mod = 0.3f; ownersBonus = owner->GetStat(stat) * mod; } else if (owner->getClass() == CLASS_DEATH_KNIGHT && GetEntry() == 31216) { mod = 0.3f; if (owner->getSimulacrumTarget()) ownersBonus = owner->getSimulacrumTarget()->GetStat(stat) * mod; else ownersBonus = owner->GetStat(stat) * mod; } value += ownersBonus; break; } } SetStat(stat, int32(value)); m_statFromOwner[stat] = ownersBonus; ApplyStatBuffMod(stat, m_statFromOwner[stat], true); switch (stat) { case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; case STAT_AGILITY: UpdateArmor(); break; case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); if (isPet() && (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE)) UpdateAttackPowerAndDamage(); break; case STAT_SPIRIT: default: break; } return true; }
void Guardian::UpdateAttackPowerAndDamage(bool ranged) { if (ranged) return; float val = 0.0f; float bonusAP = 0.0f; UnitMods unitMod = UNIT_MOD_ATTACK_POWER; if (GetEntry() == ENTRY_IMP) // imp's attack power val = GetStat(STAT_STRENGTH) - 10.0f; else val = 2 * GetStat(STAT_STRENGTH) - 20.0f; Unit* owner = GetOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER) { if (isHunterPet()) //hunter pets benefit from owner's attack power { float mod = 1.0f; //Hunter contribution modifier if (isPet()) { PetSpellMap::const_iterator itr = ToPet()->m_spells.find(62758); //Wild Hunt rank 1 if (itr == ToPet()->m_spells.end()) itr = ToPet()->m_spells.find(62762); //Wild Hunt rank 2 if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellEntry const* sProto = sSpellStore.LookupEntry(itr->first); // Then get the SpellProto and add the dummy effect value mod += CalculatePctN(1.0f, SpellMgr::CalculateSpellEffectAmount(sProto, 1)); } } bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod; SetBonusDamage(int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod)); } else if (IsPetGhoul()) //ghouls benefit from deathknight's attack power (may be summon pet or not) { bonusAP = owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.22f; SetBonusDamage(int32(owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.1287f)); } //demons benefit from warlocks shadow or fire damage else if (isPet()) { int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE); int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW); int32 maximum = (fire > shadow) ? fire : shadow; if (maximum < 0) maximum = 0; SetBonusDamage(int32(maximum * 0.15f)); bonusAP = maximum * 0.57f; } //water elementals benefit from mage's frost damage else if (GetEntry() == ENTRY_WATER_ELEMENTAL) { int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST); if (frost < 0) frost = 0; SetBonusDamage(int32(frost * 0.4f)); } } SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP); //in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier); //automatically update weapon damage after attack power modification UpdateDamagePhysical(BASE_ATTACK); }
bool Guardian::UpdateStats(Stats stat) { if (stat >= MAX_STATS) return false; float value = GetTotalStatValue(stat); ApplyStatBuffMod(stat, m_statFromOwner[stat], false); float ownersBonus = 0.0f; Unit* owner = GetOwner(); // Handle Death Knight Glyphs and Talents float mod = 0.75f; switch (stat) { case STAT_STAMINA: { mod = 0.3f; if (IsPetGhoul() || IsPetGargoyle()) mod = 0.45f; else if (owner->getClass() == CLASS_WARLOCK && isPet()) mod = 0.75f; else if (owner->getClass() == CLASS_MAGE && isPet()) mod = 0.75f; else mod = 0.7f; ownersBonus = float(owner->GetStat(stat)) * mod; ownersBonus *= GetModifierValue(UNIT_MOD_STAT_STAMINA, TOTAL_PCT); value += ownersBonus; break; } case STAT_STRENGTH: { mod = 0.7f; ownersBonus = owner->GetStat(stat) * mod; value += ownersBonus; break; } case STAT_INTELLECT: { if (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) { mod = 0.3f; ownersBonus = owner->GetStat(stat) * mod; } else if (owner->getClass() == CLASS_DEATH_KNIGHT && GetEntry() == 31216) { mod = 0.3f; if (owner->GetSimulacrumTarget()) ownersBonus = owner->GetSimulacrumTarget()->GetStat(stat) * mod; else ownersBonus = owner->GetStat(stat) * mod; } value += ownersBonus; break; } default: break; } SetStat(stat, int32(value)); m_statFromOwner[stat] = ownersBonus; ApplyStatBuffMod(stat, m_statFromOwner[stat], true); switch (stat) { case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; case STAT_AGILITY: UpdateArmor(); break; case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); if (owner->getClass() == CLASS_MAGE) UpdateAttackPowerAndDamage(); break; case STAT_SPIRIT: default: break; } return true; }
bool Guardian::UpdateStats(Stats stat) { if (stat >= MAX_STATS) return false; // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); Unit *owner = GetOwner(); // Handle Death Knight Glyphs and Talents float mod = 0.75f; if (IsPetGhoul() && (stat == STAT_STAMINA || stat == STAT_STRENGTH)) { switch (stat) { case STAT_STAMINA: mod = 0.3f; break; // Default Owner's Stamina scale case STAT_STRENGTH: mod = 0.7f; break; // Default Owner's Strength scale default: break; } // Ravenous Dead AuraEffect const *aurEff; // Check just if owner has Ravenous Dead since it's effect is not an aura if (aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0)) { SpellEntry const* sProto = aurEff->GetSpellProto(); // Then get the SpellProto and add the dummy effect value mod += mod * (sProto->EffectBasePoints[1] / 100.0f); // Ravenous Dead edits the original scale } // Glyph of the Ghoul if (aurEff = owner->GetAuraEffect(58686, 0)) mod += (aurEff->GetAmount() / 100.0f); // Glyph of the Ghoul adds a flat value to the scale mod value += float(owner->GetStat(stat)) * mod; } else if (stat == STAT_STAMINA) { if (owner->getClass() == CLASS_WARLOCK && isPet()) value += float(owner->GetStat(STAT_STAMINA)) * 0.75f; else { mod = 0.3f; if (((Creature*)this)->isPet()) { PetSpellMap::const_iterator itr = (((Pet*)this)->m_spells.find(62758)); // Wild Hunt rank 1 if (itr == ((Pet*)this)->m_spells.end()) { itr = ((Pet*)this)->m_spells.find(62762); // Wild Hunt rank 2 } if (itr != ((Pet*)this)->m_spells.end()) // If pet has Wild Hunt { SpellEntry const* sProto = sSpellStore.LookupEntry(itr->first); // Then get the SpellProto and add the dummy effect value mod += mod * (sProto->EffectBasePoints[0] / 100.0f); } } value += float(owner->GetStat(stat)) * mod; } } //warlock's and mage's pets gain 30% of owner's intellect else if (stat == STAT_INTELLECT) { if (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) value += float(owner->GetStat(stat)) * 0.3f; } /* else if (stat == STAT_STRENGTH) { if (IsPetGhoul()) value += float(owner->GetStat(stat)) * 0.3f; } */ SetStat(stat, int32(value)); switch (stat) { case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; case STAT_AGILITY: UpdateArmor(); break; case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); break; case STAT_SPIRIT: default: break; } return true; }
void CreatureImplementation::fillAttributeList(AttributeListMessage* alm, CreatureObject* player) { AiAgentImplementation::fillAttributeList(alm, player); int creaKnowledge = player->getSkillMod("creature_knowledge"); if (getHideType().isEmpty() && getBoneType().isEmpty() && getMeatType().isEmpty()) { if(!isPet()) // we do want to show this for pets return; } if (creaKnowledge >= 5) { if (isAggressiveTo(player)) alm->insertAttribute("aggro", "yes"); else alm->insertAttribute("aggro", "no"); if (isStalker()) alm->insertAttribute("stalking", "yes"); else alm->insertAttribute("stalking", "no"); } if (creaKnowledge >= 10) { if (getTame() > 0.0f) alm->insertAttribute("tamable", "yes"); else alm->insertAttribute("tamable", "no"); } if (creaKnowledge >= 20 && !isPet()) { if (!getHideType().isEmpty()) { StringBuffer hideName; hideName << "@obj_attr_n:" << getHideType(); alm->insertAttribute("res_hide", hideName.toString()); } else alm->insertAttribute("res_hide", "---"); if (!getBoneType().isEmpty()) { StringBuffer boneName; boneName << "@obj_attr_n:" << getBoneType(); alm->insertAttribute("res_bone", boneName.toString()); } else alm->insertAttribute("res_bone", "---"); if (!getMeatType().isEmpty()) { StringBuffer meatName; meatName << "@obj_attr_n:" << getMeatType(); alm->insertAttribute("res_meat", meatName.toString()); } else alm->insertAttribute("res_meat", "---"); } if (creaKnowledge >= 30) { if (isKiller()) alm->insertAttribute("killer", "yes"); else alm->insertAttribute("killer", "no"); } if (creaKnowledge >= 40) { alm->insertAttribute("ferocity", (int) getFerocity()); } if (creaKnowledge >= 50) alm->insertAttribute("challenge_level", getAdultLevel()); //int skillNum = skillCommands.size(); CreatureAttackMap* attackMap = getAttackMap(); int skillNum = 0; if (attackMap != NULL) skillNum = attackMap->size(); if (creaKnowledge >= 70) { String skillname = ""; if (skillNum >= 1) skillname = attackMap->getCommand(0); if (skillname == "creatureareaattack") skillname = "unknown_attack"; else if (skillname.isEmpty()) skillname = "none"; StringBuffer skillMsg; skillMsg << "@combat_effects:" << skillname; alm->insertAttribute("pet_command_18", skillMsg.toString()); } if (creaKnowledge >= 80) { String skillname = ""; if (skillNum >= 2) skillname = attackMap->getCommand(1); if (skillname == "creatureareaattack") skillname = "unknown_attack"; else if (skillname.isEmpty()) skillname = "none"; StringBuffer skillMsg; skillMsg << "@combat_effects:" << skillname; alm->insertAttribute("pet_command_19", skillMsg.toString()); } if (creaKnowledge >= 90) alm->insertAttribute("basetohit", getChanceHit()); if (creaKnowledge >= 100) { StringBuffer damageMsg; damageMsg << getDamageMin() << "-" << getDamageMax(); alm->insertAttribute("cat_wpn_damage", damageMsg.toString()); } }
bool CreatureImplementation::canMilkMe(CreatureObject* player) { if (!hasMilk() || milkState != CreatureManager::NOTMILKED || _this.get()->isInCombat() || _this.get()->isDead() || isPet()) return false; if(!player->isInRange(_this.get(), 5.0f) || player->isInCombat() || player->isDead() || player->isIncapacitated() || !(player->hasState(CreatureState::MASKSCENT))) return false; return true; }