// The pHatingUnit is not used yet float ThreatCalcHelper::CalcThreat(Unit* pHatedUnit, Unit* /*pHatingUnit*/, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) { // all flat mods applied early if (fabs(threat) < M_NULL_F) return 0.0f; if (pThreatSpell) { if (pThreatSpell->AttributesEx & SPELL_ATTR_EX_NO_THREAT && !IsSpellReduceThreat(pThreatSpell)) return 0.0f; if (Player* modOwner = pHatedUnit->GetSpellModOwner()) modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, threat); if (crit) threat *= pHatedUnit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRITICAL_THREAT, schoolMask); } threat = pHatedUnit->ApplyTotalThreatModifier(threat, schoolMask); return threat; }
void PetAI::Reset() { m_primaryTargetGuid.Clear(); m_savedTargetGuid.Clear(); m_attackDistanceRecheckTimer.SetInterval(TIME_INTERVAL_LOOK); m_attackDistanceRecheckTimer.Reset(); m_updateAlliesTimer.SetInterval(ALLIES_UPDATE_TIME); m_updateAlliesTimer.Reset(); UpdateAllies(); for (uint8 i = PET_SPELL_PASSIVE; i < PET_SPELL_MAX; ++i) m_spellType[i].clear(); m_AIType = PET_AI_PASSIVE; m_attackDistance = 0.0f; float f_range = 0.0f; if (!m_creature->GetCharmInfo()) return; uint32 spellsSize = m_creature->IsPet() ? ((Pet*)m_creature)->GetPetAutoSpellSize() : m_creature->GetPetAutoSpellSize(); uint8 rangedDamageSpells = 0; uint8 meleeDamageSpells = 0; // classification for pet spells for (uint32 i = 0; i < spellsSize; ++i) { uint32 spellID = m_creature->IsPet() ? ((Pet*)m_creature)->GetPetAutoSpellOnPos(i) : m_creature->GetPetAutoSpellOnPos(i); if (!spellID) continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID); if (!spellInfo) continue; if (IsPassiveSpell(spellInfo)) { m_spellType[PET_SPELL_PASSIVE].insert(spellID); continue; } if (IsNonCombatSpell(spellInfo)) { // Voidwalker Consume Shadows if (IsChanneledSpell(spellInfo)) m_spellType[PET_SPELL_HEAL].insert(spellID); else m_spellType[PET_SPELL_NONCOMBAT].insert(spellID); continue; } // need more correct define this type if (IsSpellReduceThreat(spellInfo) || IsChanneledSpell(spellInfo)) { m_spellType[PET_SPELL_DEFENCE].insert(spellID); continue; } // Voracious Appetite && Cannibalize && Carrion Feeder if (spellInfo->HasAttribute(SPELL_ATTR_ABILITY) && spellInfo->HasAttribute(SPELL_ATTR_EX2_ALLOW_DEAD_TARGET)) { m_spellType[PET_SPELL_HEAL].insert(spellID); continue; } if (IsPositiveSpell(spellInfo) && IsSpellAppliesAura(spellInfo)) { m_spellType[PET_SPELL_BUFF].insert(spellID); continue; } if (spellInfo->HasAttribute(SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)) { m_spellType[PET_SPELL_FREEACTION].insert(spellID); continue; } // don't have SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY ! if (spellInfo->HasAttribute(SPELL_ATTR_EX_CANT_REFLECTED) || spellInfo->HasAttribute(SPELL_ATTR_EX7_HAS_CHARGE_EFFECT)) { m_spellType[PET_SPELL_ATTACKSTART].insert(spellID); continue; } if (IsSpellIncreaseThreat(spellInfo)) { m_spellType[PET_SPELL_THREAT].insert(spellID); continue; } // all non-combat spells classified. switch (spellInfo->rangeIndex) { case SPELL_RANGE_IDX_COMBAT: { if (IsSpellCauseDamage(spellInfo)) { m_spellType[PET_SPELL_MELEE].insert(spellID); ++meleeDamageSpells; } else { m_spellType[PET_SPELL_SPECIAL].insert(spellID); } break; } // possible debuffs or auras? case SPELL_RANGE_IDX_SELF_ONLY: case SPELL_RANGE_IDX_ANYWHERE: { m_spellType[PET_SPELL_SPECIAL].insert(spellID); break; } default: { float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellInfo->rangeIndex), false); if (f_range < M_NULL_F || (range > M_NULL_F && range < f_range)) f_range = range; if (IsSpellCauseDamage(spellInfo)) { m_spellType[PET_SPELL_RANGED].insert(spellID); ++rangedDamageSpells; } else { m_spellType[PET_SPELL_SPECIAL].insert(spellID); } break; } } } // define initial AI type if (m_creature->IsVehicle()) m_AIType = PET_AI_PASSIVE; if (m_spellType[PET_SPELL_RANGED].size() > 0 && (m_spellType[PET_SPELL_MELEE].size() < m_spellType[PET_SPELL_RANGED].size())) { m_AIType = PET_AI_RANGED; m_attackDistance = f_range - m_creature->GetObjectBoundingRadius() - 2.0f; if (m_attackDistance < 20.0f) m_attackDistance = 18.0f; } else { m_AIType = PET_AI_MELEE; m_attackDistance = 0.0f; } m_savedAIType = m_AIType; m_creature->GetMotionMaster()->MoveTargetedHome(); DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS,"PetAI::Reset %s, AI %u dist %f, spells: "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD , m_creature->GetObjectGuid().GetString().c_str(), m_AIType, m_attackDistance, m_spellType[PET_SPELL_PASSIVE].size(), m_spellType[PET_SPELL_NONCOMBAT].size(), m_spellType[PET_SPELL_BUFF].size(), m_spellType[PET_SPELL_DEBUFF].size(), m_spellType[PET_SPELL_FREEACTION].size(), m_spellType[PET_SPELL_ATTACKSTART].size(), m_spellType[PET_SPELL_THREAT].size(), m_spellType[PET_SPELL_MELEE].size(), m_spellType[PET_SPELL_RANGED].size(), m_spellType[PET_SPELL_DEFENCE].size(), m_spellType[PET_SPELL_SPECIAL].size(), m_spellType[PET_SPELL_HEAL].size() ); }