void UpdateAI(const uint32 diff)
 {
     if (!Vorpil)
     {
         me->DealDamage(me, me->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
         return;
     }
     if (move <= diff)
     {
         if (sacrificed)
         {
             SpellEntry *spell = (SpellEntry *)GetSpellStore()->LookupEntry(HeroicMode?H_SPELL_EMPOWERING_SHADOWS:SPELL_EMPOWERING_SHADOWS);
             if (spell)
                 Vorpil->AddAura(new EmpoweringShadowsAura(spell, 0, NULL, Vorpil, me));
             Vorpil->SetHealth(Vorpil->GetHealth()+Vorpil->GetMaxHealth()/25);
             DoCast(me, SPELL_SHADOW_NOVA, true);
             me->DealDamage(me, me->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
             return;
         }
         me->GetMotionMaster()->MoveFollow(Vorpil,0,0);
         if (me->GetDistance(Vorpil) < 3)
         {
             DoCast(me, SPELL_SACRIFICE, false);
             sacrificed = true;
             move = 500;
             return;
         }
         if (!Vorpil->isInCombat() || Vorpil->isDead())
         {
             me->DealDamage(me, me->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
             return;
         }
         move = 1000;
     } else move -= diff;
 }
            SpellCastResult CheckCast()
            {
                Unit* caster = GetCaster();
                if (caster->GetTypeId() == TYPEID_PLAYER && !caster->isInCombat())
                    return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;

                return SPELL_CAST_OK;
            }
Example #3
0
 void EnterCombat(Unit* /*who*/)
 {
     DoCast(me, SPELL_STRENGHT_OF_THE_PACK, true);
     if (me->ToTempSummon())
     {
         Unit* auriaya = me->ToTempSummon()->GetSummoner();
         if (auriaya && auriaya->ToCreature() && !auriaya->isInCombat())
             auriaya->ToCreature()->SetInCombatWithZone();
     }
 }
Example #4
0
void ScriptedPetAI::UpdateAI(const uint32 diff)
{
    if (!m_creature->isAlive())                             // should not be needed, isAlive is checked in mangos before calling UpdateAI
        return;

    // UpdateAllies() is done in the generic PetAI in Mangos, but we can't do this from script side.
    // Unclear what side effects this has, but is something to be resolved from Mangos.

    if (m_creature->getVictim())                            // in combat
    {
        if (!m_creature->CanAttack(m_creature->getVictim()))
        {
            // target no longer valid for pet, so either attack stops or new target are selected
            // doesn't normally reach this, because of how petAi is designed in Mangos. CombatStop
            // are called before this update diff, and then pet will already have no victim.
            ResetPetCombat();
            return;
        }

        // update when in combat
        UpdatePetAI(diff);
    }
    else if (m_creature->GetCharmInfo())
    {
        if (m_creature->isInCombat())
            m_creature->CombatStop(true, true);

        Unit* owner = m_creature->GetMaster();

        if (!owner)
            return;

        if (owner->isInCombat() && !HasReactState(REACT_PASSIVE))
        {
            // Not correct in all cases.
            // When mob initiate attack by spell, pet should not start attack before spell landed.
            AttackStart(owner->getAttackerForHelper());
        }
        else if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
        {
            // not following, so start follow
            if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW))
                m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);

            // update when not in combat
            UpdatePetOOCAI(diff);
        }
    }
}
 void WaypointReached(uint32 uiPointId)
 {
     switch (uiPointId)
     {
         case 0:
             DoScriptText(EMOTE_WOLF_LIFT_HEAD, me);
             break;
         case 2:
             DoScriptText(EMOTE_WOLF_HOWL, me);
             break;
         case 50:
             if (pRyga && pRyga->isAlive() && !pRyga->isInCombat())
                 DoScriptText(SAY_WOLF_WELCOME, pRyga);
             break;
     }
 }
Example #6
0
void PetAI::UpdateAI(const uint32 diff)
{
    if (!m_creature->isAlive())
        return;

    Unit* owner = m_creature->GetCharmerOrOwner();

    // chained, use original owner instead
    if (owner && owner->GetTypeId() == TYPEID_UNIT && ((Creature*)owner)->GetEntry() == m_creature->GetEntry())
        if (Unit *creator = m_creature->GetCreator())
            owner = creator;

    if (m_updateAlliesTimer <= diff)
        // UpdateAllies self set update timer
        UpdateAllies();
    else
        m_updateAlliesTimer -= diff;

    if (inCombat && (!m_creature->getVictim() || m_creature->isPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS))
        _stopAttack();

    // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
    if (m_creature->getVictim())
    {
        if (_needToStop())
        {
            DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_creature->GetGUIDLow());
            _stopAttack();
            return;
        }
        else if (m_creature->IsStopped() || m_creature->IsTargetWithinAttackRange())
        {
            // required to be stopped cases
            if (m_creature->IsStopped() && m_creature->IsNonMeleeSpellCasted(false))
            {
                if (m_creature->hasUnitState(UNIT_STAT_FOLLOW_MOVE))
                    m_creature->InterruptNonMeleeSpells(false);
                else
                    return;
            }
            // not required to be stopped case
            else if (m_creature->isAttackReady() && m_creature->canReachWithAttack(m_creature->getVictim()))
            {
                m_creature->AttackerStateUpdate(m_creature->getVictim());

                m_creature->resetAttackTimer();

                if (!m_creature->getVictim())
                    return;

                //if pet misses its target, it will also be the first in threat list
                m_creature->getVictim()->AddThreat(m_creature);

                if ( _needToStop() )
                    _stopAttack();
            }
        }
    }
    else if (owner && m_creature->GetCharmInfo())
    {
        if (owner->isInCombat() && !(m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY)))
        {
            AttackStart(owner->getAttackerForHelper());
        }
        else if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
        {
            if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW) )
            {
                m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST, m_creature->isPet() ? ((Pet*)m_creature)->GetPetFollowAngle() : PET_DEFAULT_FOLLOW_ANGLE);
            }
        }
    }

    // Autocast (casted only in combat or persistent spells in any state)
    if (!m_creature->IsNonMeleeSpellCasted(false))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;

        for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i)
        {
            uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
            if (!spellID)
                continue;

            SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
            if (!spellInfo)
                continue;

            if (m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                continue;

            // ignore some combinations of combat state and combat/noncombat spells
            if (!inCombat)
            {
                // ignore attacking spells, and allow only self/around spells
                if (!IsPositiveSpell(spellInfo->Id))
                    continue;

                // non combat spells allowed
                // only pet spells have IsNonCombatSpell and not fit this reqs:
                // Consume Shadows, Lesser Invisibility, so ignore checks for its
                if (!IsNonCombatSpell(spellInfo))
                {
                    // allow only spell without spell cost or with spell cost but not duration limit
                    int32 duration = GetSpellDuration(spellInfo);
                    if ((spellInfo->manaCost || spellInfo->ManaCostPercentage || spellInfo->manaPerSecond) && duration > 0)
                        continue;

                    // allow only spell without cooldown > duration
                    int32 cooldown = GetSpellRecoveryTime(spellInfo);
                    if (cooldown >= 0 && duration >= 0 && cooldown > duration)
                        continue;
                }
            }
            else
            {
                // just ignore non-combat spells
                if (IsNonCombatSpell(spellInfo))
                    continue;
            }

            Spell *spell = new Spell(m_creature, spellInfo, false, 0);

            if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim()))
            {
                targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(m_creature->getVictim(), spell));
                continue;
            }
            else
            {
                bool spellUsed = false;
                for(std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                {
                    Unit* Target = ObjectAccessor::GetUnit(*m_creature,*tar);

                    //only buff targets that are in combat, unless the spell can only be cast while out of combat
                    if (!Target)
                        continue;

                    if (spell->CanAutoCast(Target))
                    {
                        targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(Target, spell));
                        spellUsed = true;
                        break;
                    }
                }
                if (!spellUsed)
                    delete spell;
            }
        }

        //found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.setUnitTarget( target );

            if (!m_creature->HasInArc(M_PI_F, target))
            {
                m_creature->SetInFront(target);
                if (target->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer((Player*)target);

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer( (Player*)owner );
            }

            m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id);

            spell->prepare(&targets);
        }

        // deleted cached Spell objects
        for(TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }
}
Example #7
0
void PetAI::UpdateAI(const uint32 diff)
{
    if (!m_unit->isAlive())
        return;
    Creature* creature = (m_unit->GetTypeId() == TYPEID_UNIT) ? static_cast<Creature*>(m_unit) : nullptr;
    Pet* pet = (creature && creature->IsPet()) ? static_cast<Pet*>(m_unit) : nullptr;
    
    Unit* owner = m_unit->GetMaster();
    if (!owner)
        return;

    Unit* victim = (pet && pet->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) ? nullptr : m_unit->getVictim();

    if (m_updateAlliesTimer <= diff)
        // UpdateAllies self set update timer
        UpdateAllies();
    else
        m_updateAlliesTimer -= diff;

    if (inCombat && !victim)
    {
        m_unit->AttackStop(true, true);
        inCombat = false;
    }

    CharmInfo* charminfo = m_unit->GetCharmInfo();
    MANGOS_ASSERT(charminfo);

    if (charminfo->GetIsRetreating())
    {
        if (!owner->IsWithinDistInMap(m_unit, (PET_FOLLOW_DIST * 2)))
        {
            if (!m_unit->hasUnitState(UNIT_STAT_FOLLOW))
                m_unit->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);

            return;
        }
        else
            charminfo->SetIsRetreating();
    }
    else if (charminfo->GetSpellOpener() != 0) // have opener stored
    {
        uint32 minRange = charminfo->GetSpellOpenerMinRange();

        if (!(victim = m_unit->getVictim())
            || (minRange != 0 && m_unit->IsWithinDistInMap(victim, minRange)))
            charminfo->SetSpellOpener();
        else if (m_unit->IsWithinDistInMap(victim, charminfo->GetSpellOpenerMaxRange())
                && m_unit->IsWithinLOSInMap(victim))
        {
            // stop moving
            m_unit->clearUnitState(UNIT_STAT_MOVING);

            // auto turn to target
            m_unit->SetInFront(victim);

            if (victim->GetTypeId() == TYPEID_PLAYER)
                m_unit->SendCreateUpdateToPlayer((Player*)victim);

            if (owner->GetTypeId() == TYPEID_PLAYER)
                m_unit->SendCreateUpdateToPlayer((Player*)owner);

            uint32 spell_id = charminfo->GetSpellOpener();
            SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(spell_id);

            Spell* spell = new Spell(m_unit, spellInfo, false);

            SpellCastResult result = spell->CheckPetCast(victim);

            if (result == SPELL_CAST_OK)
                spell->SpellStart(&(spell->m_targets));
            else
                delete spell;

            charminfo->SetSpellOpener();
        }
        else
            return;
    }
    // Auto cast (casted only in combat or persistent spells in any state)
    else if (!m_unit->IsNonMeleeSpellCasted(false))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;
        if (pet)
        {
            for (uint8 i = 0; i < pet->GetPetAutoSpellSize(); ++i)
            {
                uint32 spellID = pet->GetPetAutoSpellOnPos(i);
                if (!spellID)
                    continue;

                SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(spellID);
                if (!spellInfo)
                    continue;

                if (!m_unit->IsSpellReady(*spellInfo))
                    continue;

                // ignore some combinations of combat state and combat/non combat spells
                if (!inCombat)
                {
                    // ignore attacking spells, and allow only self/around spells
                    if (!IsPositiveSpell(spellInfo->Id))
                        continue;

                    // non combat spells allowed
                    // only pet spells have IsNonCombatSpell and not fit this requirements:
                    // Consume Shadows, Lesser Invisibility, so ignore checks for its
                    if (!IsNonCombatSpell(spellInfo))
                    {
                        int32 duration = GetSpellDuration(spellInfo);
                        int32 cooldown = GetSpellRecoveryTime(spellInfo);

                        // allow only spell not on cooldown
                        if (cooldown != 0 && duration < cooldown)
                            continue;

                        // not allow instant kill auto casts as full health cost
                        if (IsSpellHaveEffect(spellInfo, SPELL_EFFECT_INSTAKILL))
                            continue;
                    }
                }
                // just ignore non-combat spells
                else if (IsNonCombatSpell(spellInfo))
                    continue;

                Spell* spell = new Spell(m_unit, spellInfo, false);

                if (inCombat && !m_unit->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(victim))
                {
                    targetSpellStore.push_back(TargetSpellList::value_type(victim, spell));
                    continue;
                }
                else
                {
                    bool spellUsed = false;
                    for (GuidSet::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                    {
                        Unit* Target = m_unit->GetMap()->GetUnit(*tar);

                        // only buff targets that are in combat, unless the spell can only be cast while out of combat
                        if (!Target)
                            continue;

                        if (spell->CanAutoCast(Target))
                        {
                            targetSpellStore.push_back(TargetSpellList::value_type(Target, spell));
                            spellUsed = true;
                            break;
                        }
                    }
                    if (!spellUsed)
                        delete spell;
                }
            }
        }

        // found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.setUnitTarget(target);

            if (!m_unit->HasInArc(M_PI_F, target))
            {
                m_unit->SetInFront(target);
                if (target->GetTypeId() == TYPEID_PLAYER)
                    m_unit->SendCreateUpdateToPlayer((Player*)target);

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    m_unit->SendCreateUpdateToPlayer((Player*)owner);
            }

            spell->SpellStart(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }

    // Stop here if casting spell (No melee and no movement)
    if (m_unit->IsNonMeleeSpellCasted(false))
        return;

    // we may get our actions disabled during spell casting, so do entire recheck for victim
    victim = (pet && pet->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) ? nullptr : m_unit->getVictim();

    if (victim)
    {
        // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
        // This is needed for charmed creatures, as once their target was reset other effects can trigger threat
        if (!victim->isTargetableForAttack())
        {
            DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_unit->GetGUIDLow());
            m_unit->CombatStop();
            inCombat = false;
            
            return;
        }

        // if pet misses its target, it will also be the first in threat list
        if ((!creature || !(creature->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_MELEE))
            && m_unit->CanReachWithMeleeAttack(victim))
        {
            if (!m_unit->HasInArc(2 * M_PI_F / 3, victim))
            {
                m_unit->SetInFront(victim);
                if (victim->GetTypeId() == TYPEID_PLAYER)
                    m_unit->SendCreateUpdateToPlayer((Player*)victim);

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    m_unit->SendCreateUpdateToPlayer((Player*)owner);
            }

            DoMeleeAttackIfReady();
        }
        else if (!m_unit->hasUnitState(UNIT_STAT_MOVING))
            AttackStart(victim);
    }
    else if (owner)
    {
        CharmInfo* charmInfo = m_unit->GetCharmInfo();

        if (owner->isInCombat() && !(charmInfo && charmInfo->HasReactState(REACT_PASSIVE)))
            AttackStart(owner->getAttackerForHelper());
        else
        {
            if (charmInfo && charmInfo->HasCommandState(COMMAND_STAY))
            {
                //if stay command is set but we don't have stay pos set then we need to establish current pos as stay position
                if (!charminfo->IsStayPosSet())
                    charminfo->SetStayPosition(true);

                float stayPosX = charminfo->GetStayPosX();
                float stayPosY = charminfo->GetStayPosY();
                float stayPosZ = charminfo->GetStayPosZ();

                if (m_unit->GetPositionX() == stayPosX
                    && m_unit->GetPositionY() == stayPosY
                    && m_unit->GetPositionZ() == stayPosZ)
                {
                    float StayPosO = charminfo->GetStayPosO();

                    if (m_unit->hasUnitState(UNIT_STAT_MOVING))
                    {
                        m_unit->GetMotionMaster()->Clear(false);
                        m_unit->GetMotionMaster()->MoveIdle();
                    }
                    else if (m_unit->GetOrientation() != StayPosO)
                        m_unit->SetOrientation(StayPosO);
                }
                else
                    m_unit->GetMotionMaster()->MovePoint(0, stayPosX, stayPosY, stayPosZ, false);
            }
            else if (m_unit->hasUnitState(UNIT_STAT_FOLLOW))
            {
                if (owner->IsWithinDistInMap(m_unit, PET_FOLLOW_DIST))
                {
                    m_unit->GetMotionMaster()->Clear(false);
                    m_unit->GetMotionMaster()->MoveIdle();
                }
            }
            else if (charmInfo && charmInfo->HasCommandState(COMMAND_FOLLOW)
                && !owner->IsWithinDistInMap(m_unit, (PET_FOLLOW_DIST * 2)))
                m_unit->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
        }
    }
}
Example #8
0
void PetAI::UpdateAI(const uint32 diff)
{
    if (!me->isAlive())
        return;

    Unit* owner = me->GetCharmerOrOwner();

    if (m_updateAlliesTimer <= diff)
        // UpdateAllies self set update timer
        UpdateAllies();
    else
        m_updateAlliesTimer -= diff;

    // me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc.
    if (me->getVictim())
    {
        // is only necessary to stop casting, the pet must not exit combat
        if (me->getVictim()->HasCrowdControlAura(me))
        {
            me->InterruptNonMeleeSpellsExcept(false, 90337);    // hack for Bad Manner
            return;
        }

        if (_needToStop())
        {
            sLog->outDebug(LOG_FILTER_GENERAL, "Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
            _stopAttack();
            return;
        }

        if (owner && !owner->isInCombat())
            owner->SetInCombatWith(me->getVictim());

        DoMeleeAttackIfReady();
    }
    else if (owner && me->GetCharmInfo()) //no victim
    {
        // Only aggressive pets do target search every update.
        // Defensive pets do target search only in these cases:
        //  * Owner attacks something - handled by OwnerAttacked()
        //  * Owner receives damage - handled by OwnerDamagedBy()
        //  * Pet is in combat and current target dies - handled by KilledUnit()
        if (me->HasReactState(REACT_AGGRESSIVE))
        {
            Unit* nextTarget = SelectNextTarget();

            if (nextTarget)
                AttackStart(nextTarget);
            else
                HandleReturnMovement();
        }
        else
            HandleReturnMovement();
    }
    else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
        me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());

    if (!me->GetCharmInfo())
        return;

    // Autocast (casted only in combat or persistent spells in any state)

    if (!me->HasAura(130201)) // stampede cannot auto cast spells
    if (!me->HasUnitState(UNIT_STATE_CASTING))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;

        for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
        {
            uint32 spellID = me->GetPetAutoSpellOnPos(i);
            if (!spellID)
                continue;

            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
            if (!spellInfo)
                continue;

            if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                continue;

            if (spellInfo->IsPositive())
            {
                if (spellInfo->CanBeUsedInCombat())
                {
                    // check spell cooldown
                    if (me->HasSpellCooldown(spellInfo->Id))
                        continue;

                    // Check if we're in combat or commanded to attack
                    if (!me->isInCombat() && !me->GetCharmInfo()->IsCommandAttack())
                        continue;
                }

                Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
                bool spellUsed = false;

                // Some spells can target enemy or friendly (DK Ghoul's Leap)
                // Check for enemy first (pet then owner)
                Unit* target = me->getAttackerForHelper();
                if (!target && owner)
                    target = owner->getAttackerForHelper();

                if (target)
                {
                    if (CanAttack(target) && spell->CanAutoCast(target))
                    {
                        targetSpellStore.push_back(std::make_pair(target, spell));
                        spellUsed = true;
                    }
                }

                // No enemy, check friendly
                if (!spellUsed)
                {
                    for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                    {
                        Unit* ally = ObjectAccessor::GetUnit(*me, *tar);

                        //only buff targets that are in combat, unless the spell can only be cast while out of combat
                        if (!ally)
                            continue;

                        if (spell->CanAutoCast(ally))
                        {
                            targetSpellStore.push_back(std::make_pair(ally, spell));
                            spellUsed = true;
                            break;
                        }
                    }
                }

                // No valid targets at all
                if (!spellUsed)
                    delete spell;
            }
            else if (me->getVictim() && CanAttack(me->getVictim()) && spellInfo->CanBeUsedInCombat())
            {
                Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
                if (spell->CanAutoCast(me->getVictim()))
                    targetSpellStore.push_back(std::make_pair(me->getVictim(), spell));
                else
                    delete spell;
            }
        }

        //found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.SetUnitTarget(target);

            if (!me->HasInArc(M_PI, target))
            {
                me->SetInFront(target);
                if (target && target->GetTypeId() == TYPEID_PLAYER)
                    me->SendUpdateToPlayer(target->ToPlayer());

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    me->SendUpdateToPlayer(owner->ToPlayer());
            }

            me->AddCreatureSpellCooldown(spell->m_spellInfo->Id);

            spell->prepare(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }

    // Update speed as needed to prevent dropping too far behind and despawning
    // This not need to call every update.
    //me->UpdateSpeed(MOVE_RUN, true);
    //me->UpdateSpeed(MOVE_WALK, true);
    //me->UpdateSpeed(MOVE_FLIGHT, true);
}
Example #9
0
    void UpdateAI(const uint32 diff)
    {
         if (!UpdateVictim())
            return;

        if (me->getVictim() && me->isAlive())
        {
            //Check for Frost Bolt
            if (FrostBolt_Timer <= diff)
            {
                DoCast(me->getVictim(),SPELL_FROST_BOLT);
                //Cast again on time
                FrostBolt_Timer = (rand()%60)*1000;
            } else FrostBolt_Timer -= diff;

            //Check for Frost Bolt Nova
            if (FrostBoltNova_Timer <= diff)
            {
                DoCast(me->getVictim(),SPELL_FROST_BOLT_NOVA);
                FrostBoltNova_Timer = 15000;
            } else FrostBoltNova_Timer -= diff;

            //Check for Chains Of Kelthuzad
            if (ChainsOfKelthuzad_Timer <= diff)
            {
                //DoCast(me->getVictim(),SPELL_CHAINS_OF_KELTHUZAD);

                //if (rand()%2 == 0)
                   //DoScriptText(SAY_CHAIN1, me);
                //else
                    //DoScriptText(SAY_CHAIN2, me);
                ChainsOfKelthuzad_Timer = (rand()%30+30)*1000;
            } else ChainsOfKelthuzad_Timer -= diff;

            //Check for Mana Detonation
            if (ManaDetonation_Timer <= diff)
            {
                //time to cast
                DoCast(me->getVictim(),SPELL_MANA_DETONATION);

                 if (rand()%2)
                     DoScriptText(SAY_SPECIAL1_MANA_DET, me);
                ManaDetonation_Timer = 20000;
            } else ManaDetonation_Timer -= diff;

            //Check for Shadow Fissure
            if (ShadowFisure_Timer <= diff)
            {
                DoCast(me->getVictim(),SPELL_SHADOW_FISURE);

               if (rand()%2)
                   DoScriptText(SAY_SPECIAL3_MANA_DET, me);
                ShadowFisure_Timer = 25000;
            } else ShadowFisure_Timer -= diff;

            //Check for Frost Blast
            if (FrostBlast_Timer <= diff)
            {
                //time to cast
                DoCast(me->getVictim(),SPELL_FROST_BLAST);

                if (rand()%2 == 0)
                    DoScriptText(SAY_FROST_BLAST, me);
                FrostBlast_Timer = (rand()%30+30)*1000;
            } else FrostBlast_Timer -= diff;

            //start phase 3 when we are 40% health
            if (!Phase3 && (me->GetHealth()*100 / me->GetMaxHealth()) < 40)
            {
                Phase3 = true;
                    DoScriptText(SAY_REQUEST_AID, me);
                //here Lich King should respond to KelThuzad but I don't know which creature to make talk
                //so for now just make Kelthuzad says it.
                DoScriptText(SAY_ANSWER_REQUEST, me);
            }

            if (Phase3 && (GuardiansOfIcecrown_Count < 5))
            {
                if (GuardiansOfIcecrown_Timer <= diff)
                {
                    //Summon a Guardian of Icecrown in a random alcove (Creature # 16441)
                    //uint32 TimeToWalk;
                    Unit* pUnit = NULL;
                    float Walk_Pos_X;
                    float Walk_Pos_Y;
                    float Walk_Pos_Z;
                    switch (rand()%6)
                    {
                        case 0:
                            pUnit = me->SummonCreature(16441,ADDX_LEFT_FAR,ADDY_LEFT_FAR,ADDZ_LEFT_FAR,ADDO_LEFT_FAR,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000);
                            //Setting walk position
                            Walk_Pos_X = WALKX_LEFT_FAR;
                            Walk_Pos_Y = WALKY_LEFT_FAR;
                            Walk_Pos_Z = WALKZ_LEFT_FAR;
                            break;
                        case 1:
                            pUnit = me->SummonCreature(16441,ADDX_LEFT_MIDDLE,ADDY_LEFT_MIDDLE,ADDZ_LEFT_MIDDLE,ADDO_LEFT_MIDDLE,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000);
                            //Start moving guardian towards the center of the room
                            Walk_Pos_X = WALKX_LEFT_MIDDLE;
                            Walk_Pos_Y = WALKY_LEFT_MIDDLE;
                            Walk_Pos_Z = WALKZ_LEFT_MIDDLE;
                            break;
                        case 2:
                            pUnit = me->SummonCreature(16441,ADDX_LEFT_NEAR,ADDY_LEFT_NEAR,ADDZ_LEFT_NEAR,ADDO_LEFT_NEAR,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000);
                            //Start moving guardian towards the center of the room
                            Walk_Pos_X = WALKX_LEFT_NEAR;
                            Walk_Pos_Y = WALKY_LEFT_NEAR;
                            Walk_Pos_Z = WALKZ_LEFT_NEAR;
                            break;
                        case 3:

                            pUnit = me->SummonCreature(16441,ADDX_RIGHT_FAR,ADDY_RIGHT_FAR,ADDZ_RIGHT_FAR,ADDO_RIGHT_FAR,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000);
                            //Start moving guardian towards the center of the room
                            Walk_Pos_X = WALKX_RIGHT_FAR;
                            Walk_Pos_Y = WALKY_RIGHT_FAR;
                            Walk_Pos_Z = WALKZ_RIGHT_FAR;
                            break;
                        case 4:
                            pUnit = me->SummonCreature(16441,ADDX_RIGHT_MIDDLE,ADDY_RIGHT_MIDDLE,ADDZ_RIGHT_MIDDLE,ADDO_RIGHT_MIDDLE,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000);
                            //Start moving guardian towards the center of the room
                            Walk_Pos_X = WALKX_RIGHT_MIDDLE;
                            Walk_Pos_Y = WALKY_RIGHT_MIDDLE;
                            Walk_Pos_Z = WALKZ_RIGHT_MIDDLE;
                            break;
                        case 5:
                            pUnit = me->SummonCreature(16441,ADDX_RIGHT_NEAR,ADDY_RIGHT_NEAR,ADDZ_RIGHT_NEAR,ADDO_RIGHT_NEAR,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,1000);
                            //Start moving guardian towards the center of the room
                            Walk_Pos_X = WALKX_RIGHT_NEAR;
                            Walk_Pos_Y = WALKY_RIGHT_NEAR;
                            Walk_Pos_Z = WALKZ_RIGHT_NEAR;
                            break;
                    }

                    if (pUnit)
                    {
                        //if we find no one to figth walk to the center
                        if (!pUnit->isInCombat())
                            pUnit->SendMonsterMoveWithSpeed(Walk_Pos_X,Walk_Pos_Y,Walk_Pos_Z,MOVEFLAG_WALK_MODE);

                        //Safe storing of creatures
                        GuardiansOfIcecrown[GuardiansOfIcecrown_Count] = pUnit->GetGUID();

                        //Update guardian count
                        GuardiansOfIcecrown_Count++;

                    }
                    //5 seconds until summoning next guardian
                    GuardiansOfIcecrown_Timer = 5000;
                }
                else GuardiansOfIcecrown_Timer -= diff;
            }

            DoMeleeAttackIfReady();
        }
    }
Example #10
0
        void UpdateAI(const uint32 diff)
        {
            if(!UpdateVictim())
                return;

            if(me->getVictim() && me->isAlive())
            {
                if(!CombatStart)
                {
                    //At combat Start Mandokir is mounted so we must unmount it first
                    me->Unmount();

                    //And summon his raptor
                    me->SummonCreature(14988, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
                    CombatStart = true;
                }

                if(Watch_Timer <= diff)                         //Every 20 Sec Mandokir will check this
                {
                    if(WatchTarget)                             //If someone is watched and If the Position of the watched target is different from the one stored, or are attacking, mandokir will charge him
                    {
                        Unit* pUnit = Unit::GetUnit(*me, WatchTarget);

                        if(pUnit && (
                                    targetX != pUnit->GetPositionX() ||
                                    targetY != pUnit->GetPositionY() ||
                                    targetZ != pUnit->GetPositionZ() ||
                                    pUnit->isInCombat()))
                        {
                            if(me->IsWithinMeleeRange(pUnit))
                            {
                                DoCast(pUnit, 24316);
                            }
                            else
                            {
                                DoCast(pUnit, SPELL_CHARGE);
                                //me->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true, 1);
                                AttackStart(pUnit);
                            }
                        }
                    }
                    someWatched = false;
                    Watch_Timer = 20000;
                } else Watch_Timer -= diff;

                if((Watch_Timer < 8000) && !someWatched)       //8 sec(cast time + expire time) before the check for the watch effect mandokir will cast watch debuff on a random target
                {
                    if(Unit* p = SelectTarget(SELECT_TARGET_RANDOM, 0))
                    {
                        DoScriptText(SAY_WATCH, me, p);
                        DoCast(p, SPELL_WATCH);
                        WatchTarget = p->GetGUID();
                        someWatched = true;
                        endWatch = true;
                    }
                }

                if((Watch_Timer < 1000) && endWatch)           //1 sec before the debuf expire, store the target position
                {
                    Unit* pUnit = Unit::GetUnit(*me, WatchTarget);
                    if(pUnit)
                    {
                        targetX = pUnit->GetPositionX();
                        targetY = pUnit->GetPositionY();
                        targetZ = pUnit->GetPositionZ();
                    }
                    endWatch = false;
                }

                if(!someWatched)
                {
                    //Cleave
                    if(Cleave_Timer <= diff)
                    {
                        DoCast(me->getVictim(), SPELL_CLEAVE);
                        Cleave_Timer = 7000;
                    } else Cleave_Timer -= diff;

                    //Whirlwind
                    if(Whirlwind_Timer <= diff)
                    {
                        DoCast(me, SPELL_WHIRLWIND);
                        Whirlwind_Timer = 18000;
                    } else Whirlwind_Timer -= diff;

                    //If more then 3 targets in melee range mandokir will cast fear
                    if(Fear_Timer <= diff)
                    {
                        TargetInRange = 0;

                        std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
                        for(; i != me->getThreatManager().getThreatList().end(); ++i)
                        {
                            Unit* pUnit = Unit::GetUnit(*me, (*i)->getUnitGuid());
                            if(pUnit && me->IsWithinMeleeRange(pUnit))
                                ++TargetInRange;
                        }

                        if(TargetInRange > 3)
                            DoCast(me->getVictim(), SPELL_FEAR);

                        Fear_Timer = 4000;
                    } else Fear_Timer -=diff;

                    //Mortal Strike if target below 50% hp
                    if(me->getVictim() && me->getVictim()->HealthBelowPct(50))
                    {
                        if(MortalStrike_Timer <= diff)
                        {
                            DoCast(me->getVictim(), SPELL_MORTAL_STRIKE);
                            MortalStrike_Timer = 15000;
                        } else MortalStrike_Timer -= diff;
                    }
                }
                //Checking if Ohgan is dead. If yes Mandokir will enrage.
                if(Check_Timer <= diff)
                {
                    if(pInstance)
                    {
                        if(pInstance->GetData(DATA_OHGAN) == DONE)
                        {
                            if(!RaptorDead)
                            {
                                DoCast(me, SPELL_ENRAGE);
                                RaptorDead = true;
                            }
                        }
                    }

                    Check_Timer = 1000;
                } else Check_Timer -= diff;

                DoMeleeAttackIfReady();
            }
        }
Example #11
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        if (me->getVictim() && me->isAlive())
        {
            if (!CombatStart)
            {
                // At combat Start Mandokir is mounted so we must unmount it first
                me->Unmount();

                // And summon his raptor
                me->SummonCreature(OHGAN, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
                CombatStart = true;
            }

            if (Gaze_Timer <= diff)                         // Every 20 seconds Mandokir will check this
            {
                if (GazeTarget)
                {
                    Unit* pUnit = Unit::GetUnit(*me, GazeTarget);

                    if (pUnit && (
                        targetX != pUnit->GetPositionX() ||
                        targetY != pUnit->GetPositionY() ||
                        targetZ != pUnit->GetPositionZ() ||
                        pUnit->isInCombat()))
                    {
                        if (me->IsWithinMeleeRange(pUnit))
                        {
                            DoCast(pUnit, 24316);
                        }
                        else
                        {
                            DoCast(pUnit, SPELL_CHARGE);
                            //me->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true,1);
                            AttackStart(pUnit);
                        }
                    }
                }
                someGazed = false;
                Gaze_Timer = 20000;
            }
            else
                Gaze_Timer -= diff;

            if (Gaze_Timer < 8000 && !someGazed)            // 8 second(cast time + expire time) before the check for the gaze effect Mandokir will cast gaze debuff on a random target
            {
                if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
                {
                    DoScriptText(SAY_GAZE, me, pTarget);
                    DoCast(pTarget, SPELL_GAZE);
                    me->MonsterWhisper(SAY_GAZE_WHISPER, pTarget->GetGUID());
                    GazeTarget = pTarget->GetGUID();
                    someGazed = true;
                    endGaze = true;
                }
            }

            if (Gaze_Timer < 1000 && endGaze)               // 1 second before the debuff expires, check whether the GazeTarget is in LoS
            {
                Unit* pUnit = Unit::GetUnit(*me, GazeTarget);
                if (pUnit)
                {
                    targetX = pUnit->GetPositionX();
                    targetY = pUnit->GetPositionY();
                    targetZ = pUnit->GetPositionZ();
                }
                endGaze = false;
            }

            if (!someGazed)
            {
                // Cleave
                if (Cleave_Timer <= diff)
                {
                    DoCast(me->getVictim(), SPELL_CLEAVE);
                    Cleave_Timer = 7000;
                }
                else
                    Cleave_Timer -= diff;

                // Whirlwind
                if (Whirlwind_Timer <= diff)
                {
                    DoCast(me, SPELL_WHIRLWIND);
                    Whirlwind_Timer = 18000;
                }
                else
                    Whirlwind_Timer -= diff;

                // If more than 3 targets in melee range Mandokir will cast fear
                if (Fear_Timer <= diff)
                {
                    TargetInRange = 0;

                    std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
                    for (; i != me->getThreatManager().getThreatList().end(); ++i)
                    {
                        Unit* pUnit = Unit::GetUnit(*me, (*i)->getUnitGuid());
                        if (pUnit && me->IsWithinMeleeRange(pUnit))
                            ++TargetInRange;
                    }

                    if (TargetInRange > 3)
                        DoCast(me->getVictim(), SPELL_FEAR);

                    Fear_Timer = 4000;
                }
                else
                    Fear_Timer -=diff;

                // Mortal Strike if target is below 50% hp
                if (me->getVictim() && me->getVictim()->GetHealth() < me->getVictim()->GetMaxHealth() * 0.5f)
                {
                    if (MortalStrike_Timer <= diff)
                    {
                        DoCast(me->getVictim(), SPELL_MORTAL_STRIKE);
                        MortalStrike_Timer = 15000;
                    }
                    else
                        MortalStrike_Timer -= diff;
                }
            }

            // Checking if Ohgan is dead. If yes Mandokir will enrage.
            if (Check_Timer <= diff)
            {
                if (pInstance)
                {
                    if (pInstance->GetData(TYPE_OHGAN) == DONE)
                    {
                        if (!RaptorDead)
                        {
                            DoCast(me, SPELL_ENRAGE);
                            RaptorDead = true;
                        }
                    }
                }

                Check_Timer = 1000;
            }
            else
                Check_Timer -= diff;

            DoMeleeAttackIfReady();
        }
    }
Example #12
0
File: bot_ai.cpp Project: Rhyuk/Dev
void bot_ai::ResetOrGetNextTarget()
{
    if (master->GetBotMustDie()) return;
    uint64 targetGUID = 0;

    // check if anyone has raid target
    //targetGUID = getTargetWithIcon();
    Group *group = master->GetGroup();
    targetGUID = group->GetTargetWithIconByGroup (m_creature->GetGUID());


    if (targetGUID && targetGUID!=master->GetGUID())
    {

        Unit * target = m_creature->GetCreature(*master, targetGUID);
        if (target && target->isAlive() && target->IsHostileTo(master) && target->isInCombat() /*&& m_creature->IsWithinDist(target, 30)*/)
        {
            BotAttackStart(target);
            return;
        }
    }

    AttackerSet m_attackers = master->getAttackers();

    //check if anyone is attacking master
    if(gettingAttacked(m_attackers)) return;

    //check if anyone is attacking me
    m_attackers = m_creature->getAttackers();
    if(gettingAttacked(m_attackers)) return;

    //check if master has a victim
    if(master->getVictim() && master->getVictim()->IsHostileTo(master))
    {
        if(m_creature->IsWithinDist(m_creature->getVictim(), 50))
        {
            BotAttackStart(master->getVictim());
            return;
        }
    }

    //lastly check a random victim, including bots, pets, etc
    Unit *target = DoSelectLowestHpFriendly(30);
    if(target != NULL && target->isAlive() && !target->IsHostileToPlayers())
    {
        m_attackers = target->getAttackers();
        if(gettingAttacked(m_attackers)) {
            return;
        }

    }

    //if there is no one to attack, make sure we are following master
    if(m_creature->getVictim() == NULL &&
        m_creature->GetCharmInfo()->GetCommandState() != COMMAND_STAY &&
        master->GetDistance(m_creature) > 20 &&
        !master->IsBeingTeleported())
    {
        if (!master->isAlive())
            master->SetBotCommandState(COMMAND_STAY);
        else if (master->GetBotCommandState()==COMMAND_ATTACK)
            master->SetBotCommandState(prevCommandState);


        return;
    }
}
Example #13
0
        void UpdateAI(uint32 const diff)
        {
            if (!_entered)
            {
                if (_enterTimer <= diff)
                {
                    uint32 spellId = 0;
                    _entered = true;

                    switch (me->GetEntry())
                    {
                    case NPC_EMERALD_DRAKE:
                        spellId = 49346;
                        break;
                    case NPC_AMBER_DRAKE:
                        spellId = 49460;
                        break;
                    case NPC_RUBY_DRAKE:
                        spellId = 49464;
                        break;
                    }

                    if (!me->ToTempSummon())
                        return;

                    Unit* summoner = me->ToTempSummon()->GetSummoner();

                    if (summoner && summoner->isAlive() && summoner->GetDistance(me) < 30.0f && !summoner->isInCombat())
                    {
                        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                        summoner->CastSpell(me, spellId, true);
                    }
                    else
                        me->DespawnOrUnsummon();
                }
                else
                    _enterTimer -= diff;
            }
        }