bool PetAI::_needToStop() const { Unit* pVictim = m_creature->getVictim(); if (!pVictim) return true; // This is needed for charmed creatures, as once their target was reset other effects can trigger threat if (m_creature->isCharmed() && m_creature->GetCharmer() == pVictim) return true; Unit* owner = m_creature->GetCharmerOrOwner(); if (owner == pVictim) return true; if (!pVictim->isVisibleForOrDetect(m_creature, m_creature, false)) return true; if (owner && !pVictim->isVisibleForOrDetect(owner, owner, true)) return true; if (m_primaryTargetGuid && m_primaryTargetGuid != pVictim->GetObjectGuid()) return true; return !pVictim->isTargetableForAttack(); }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (i_totem.GetTotemType() != TOTEM_ACTIVE) return; if (!i_totem.isAlive() || i_totem.IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_totem.GetSpell()); if (!spellInfo) return; // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); float max_range = GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // pointer to appropriate target if found any Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(i_totem, i_victimGuid) : NULL; // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || !victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) || i_totem.IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(&i_totem,false)) { CellPair p(BlizzLike::ComputeCellPair(i_totem.GetPositionX(),i_totem.GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; victim = NULL; BlizzLike::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range); BlizzLike::UnitLastSearcher<BlizzLike::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); TypeContainerVisitor<BlizzLike::UnitLastSearcher<BlizzLike::NearestAttackableUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); TypeContainerVisitor<BlizzLike::UnitLastSearcher<BlizzLike::NearestAttackableUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); //TODO: Backport BLizzLike Add to CreatureAI field pointing to creature itself //cell.Visit(p, grid_object_checker, *m_creature.GetMap(), *m_creature, max_range); //cell.Visit(p, world_object_checker, *m_creature.GetMap(), *m_creature, max_range); cell.Visit(p, grid_object_checker, *i_totem.GetMap()); cell.Visit(p, world_object_checker, *i_totem.GetMap()); } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack i_totem.SetInFront(victim); // client change orientation by self i_totem.CastSpell(victim, i_totem.GetSpell(), false); } else i_victimGuid = 0; }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (i_totem.GetTotemType() != TOTEM_ACTIVE) return; i_totem.SetSelection(0); if (!i_totem.isAlive() || i_totem.IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_totem.GetSpell()); if (!spellInfo) return; // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); float max_range = SpellMgr::GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // pointer to appropriate target if found any Unit* victim = i_victimGuid ? i_totem.GetMap()->GetUnit(i_victimGuid) : NULL; if (!max_range) victim = &i_totem; // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || (!SpellMgr::SpellIgnoreLOS(spellInfo, 0) && !i_totem.IsWithinLOSInMap(victim)) || !victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) || (i_totem.IsFriendlyTo(victim) && victim != &i_totem) || !victim->isVisibleForOrDetect(&i_totem, &i_totem, false)) { victim = NULL; Looking4group::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range); Looking4group::UnitLastSearcher<Looking4group::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); Cell::VisitAllObjects(m_creature, checker, max_range); } // If have target if (victim) { //this should prevent target-type totems from attacking from unattackable zones and attacking while being unattackable if ((i_totem.isInSanctuary() || victim->isInSanctuary()) && victim->GetCharmerOrOwnerPlayerOrPlayerItself()) return; // remember i_victimGuid = victim->GetGUID(); // attack i_totem.CastSpell(victim, i_totem.GetSpell(), false, NULL, NULL, i_totem.GetOwner()->GetGUID()); } else i_victimGuid = 0; //i_totem.SetFacingToObject(&i_totem); }
void TotemAI::UpdateAI(const uint32 diff) { if (i_totem.GetTotemType() != TOTEM_ACTIVE) return; if (!i_totem.isAlive() || i_totem.IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_totem.GetSpell()); if (!spellInfo) return; // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); float max_range = GetMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems Unit* victim = NULL; // pointer to appropriate target if found any // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if( !i_victimGuid || !(victim = ObjectAccessor::GetUnit(i_totem, i_victimGuid)) || !victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) || i_totem.IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(&i_totem,false) ) { CellPair p(MaNGOS::ComputeCellPair(i_totem.GetPositionX(),i_totem.GetPositionY())); Cell cell = RedZone::GetZone(p); cell.data.Part.reserved = ALL_DISTRICT; victim = NULL; MaNGOS::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range); MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(i_totem.GetMapId(), &i_totem)); cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(i_totem.GetMapId(), &i_totem)); } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack i_totem.SetInFront(victim); // client change orientation by self i_totem.CastSpell(victim, i_totem.GetSpell(), false); } else i_victimGuid = 0; }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (getTotem().GetTotemType() != TOTEM_ACTIVE) return; if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(getTotem().GetSpell()); if (!spellInfo) return; SpellMiscEntry const* spellMisc = sSpellMiscStore.LookupEntry(spellInfo->Id); // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellMisc->rangeIndex); float max_range = GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because nonexistent range mods for attacking totems // pointer to appropriate target if found any Unit* victim = m_creature->GetMap()->GetUnit(i_victimGuid); // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if( !victim || !victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) || m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,m_creature,false) ) { victim = NULL; Strawberry::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range); Strawberry::UnitLastSearcher<Strawberry::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); Cell::VisitAllObjects(m_creature, checker, max_range); } // If have target if (victim) { // remember i_victimGuid = victim->GetObjectGuid(); // attack m_creature->SetInFront(victim); // client change orientation by self m_creature->CastSpell(victim, getTotem().GetSpell(), false); } else i_victimGuid.Clear(); }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (((Totem*)m_creature)->GetTotemType() != TOTEM_ACTIVE) return; if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(((Totem*)m_creature)->GetSpell()); if (!spellInfo) return; // Get spell range SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); float max_range = GetSpellMaxRangeForHostile(srange); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // pointer to appropriate target if found any Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*m_creature, i_victimGuid) : NULL; // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if( !victim || !victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) || m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,false) ) { victim = NULL; Quad::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range); Quad::UnitLastSearcher<Quad::NearestAttackableUnitInObjectRangeCheck> checker(m_creature, victim, u_check); m_creature->VisitNearbyObject(max_range, checker); } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack m_creature->SetInFront(victim); // client change orientation by self m_creature->CastSpell(victim, ((Totem*)m_creature)->GetSpell(), false); } else i_victimGuid = 0; }
void TotemAI::UpdateAI(const uint32 diff) { // Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events if (m_EventUpdateTime < diff) { m_EventDiff += diff; // Check for time based events for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) { // Decrement Timers if (i->Time) { // Do not decrement timers if event cannot trigger in this phase if (!(i->Event.event_inverse_phase_mask & (1 << m_Phase))) { if (i->Time > m_EventDiff) i->Time -= m_EventDiff; else i->Time = 0; } } // Skip processing of events that have time remaining or are disabled if (!(i->Enabled) || i->Time) continue; if (IsTimerBasedEvent(i->Event.event_type)) ProcessEvent(*i); } m_EventDiff = 0; m_EventUpdateTime = EVENT_UPDATE_TIME; } else { m_EventDiff += diff; m_EventUpdateTime -= diff; } if (getTotem().GetTotemType() != TOTEM_ACTIVE) return; if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(getTotem().GetSpell()); if (!spellInfo) return; // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); float maxRange = GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because nonexistent range mods for attacking totems // pointer to appropriate target if found any Unit* victim = m_creature->GetMap()->GetUnit(i_victimGuid); // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || !m_creature->CanAttack(victim) || !m_creature->IsWithinDistInMap(victim, maxRange) || m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature, m_creature, false)) { victim = nullptr; MaNGOS::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, maxRange); MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); Cell::VisitAllObjects(m_creature, checker, maxRange); } // If have target if (victim) { // remember i_victimGuid = victim->GetObjectGuid(); // attack m_creature->SetInFront(victim); // client change orientation by self m_creature->CastSpell(victim, getTotem().GetSpell(), TRIGGERED_NONE); } else i_victimGuid.Clear(); }