void DamageTaken(Unit* pDealer, uint32& uiDamage, DamageEffectType /*damagetype*/) override
    {
        uint32 uiStep = m_uiThrowAIEventStep != 100 ? m_uiThrowAIEventStep : 0;
        if (uiStep < CRUSADER_HEALTH_STEPS)
        {
            // Throw at 90%, 50% and 10% health
            float fHealthSteps[CRUSADER_HEALTH_STEPS] = { 90.0f, 50.0f, 10.0f };
            float fNewHealthPercent = (m_creature->GetHealth() - uiDamage) * 100.0f / m_creature->GetMaxHealth();
            AIEventType sendEvent[CRUSADER_HEALTH_STEPS] = { AI_EVENT_LOST_SOME_HEALTH, AI_EVENT_LOST_HEALTH, AI_EVENT_CRITICAL_HEALTH };

            if (fNewHealthPercent > fHealthSteps[uiStep])
                return;                                         // Not reached the next mark

            // search for highest reached mark (with actual event attached)
            for (uint32 i = CRUSADER_HEALTH_STEPS - 1; i > uiStep; --i)
            {
                if (fNewHealthPercent < fHealthSteps[i])
                {
                    uiStep = i;
                    break;
                }
            }

            // send event around and to self
            SendAIEventAround(sendEvent[uiStep], pDealer, 0, CRUSADER_AIEVENT_THROW_RADIUS);
            SendAIEvent(sendEvent[uiStep], pDealer, m_creature);
            m_uiThrowAIEventStep = uiStep + 1;
        }
    }
Ejemplo n.º 2
0
 void ReceiveAIEvent(AIEventType eventType, Creature* /*pSender*/, Unit* pInvoker, uint32 uiMiscValue) override
 {
     if (eventType == AI_EVENT_START_ESCORT && pInvoker->GetTypeId() == TYPEID_PLAYER)
     {
         Start(false, (Player*)pInvoker, GetQuestTemplateStore(uiMiscValue));
         SendAIEventAround(AI_EVENT_CUSTOM_A, pInvoker, 0, 12.0f);
     }
 }
    void HealedBy(Unit* pHealer, uint32& uiHealedAmount) override
    {
        if (m_uiThrowAIEventStep == 100)
            return;

        if (m_creature->GetHealth() + uiHealedAmount >= m_creature->GetMaxHealth())
        {
            SendAIEventAround(AI_EVENT_GOT_FULL_HEALTH, pHealer, 0, CRUSADER_AIEVENT_THROW_RADIUS);
            m_uiThrowAIEventStep = 100;
        }
    }
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // Call specific virtual function
        if (!UpdateCrusaderAI(uiDiff))
            return;

        if (m_uiAbilityTimer < uiDiff)
        {
            uint8 uiIndex = urand(0, m_uiMaxAbilities - 1);
            uint32 uiMinHealth = m_pAbilityArray[uiIndex].m_uiMinHealth;
            uint8 uiTargetType = m_pAbilityArray[uiIndex].m_uiTargetType;

            SelectFlags spellSelectFlag = m_pAbilityArray[uiIndex].m_selectFlag;

            // check timers and health condition
            // only cast spells that have timers expired
            // also check for health percentage for self cast spells
            if (m_uiSpellTimer[uiIndex] || (uiTargetType == TARGET_TYPE_SELF && uiMinHealth && m_creature->GetHealthPercent() > uiMinHealth))
            {
                 m_uiAbilityTimer = 2000;
                 return;
            }
            else
            {
                uint32 uiSpellId = m_pAbilityArray[uiIndex].m_uiSpellId;

                // special case for heroism / bloodlust
                if (uiSpellId == SPELL_HEROISM && m_pInstance && m_pInstance->GetPlayerTeam() == ALLIANCE)
                    uiSpellId = SPELL_BLOODLUST;

                if (CanUseSpecialAbility(uiSpellId, uiTargetType, spellSelectFlag, uiMinHealth))
                {
                    m_uiSpellTimer[uiIndex] = m_pAbilityArray[uiIndex].m_uiCooldown;
                    m_uiAbilityTimer = urand(2000, 6000);
                }
                else
                    m_uiAbilityTimer = 2000;
            }
        }
        else
            m_uiAbilityTimer -= uiDiff;

        // spell cooldown
        for (uint8 i = 0; i < m_uiMaxAbilities; ++i)
        {
            if (m_uiSpellTimer[i])
            {
                if (m_uiSpellTimer[i] <= uiDiff)
                    m_uiSpellTimer[i] = 0;
                else
                    m_uiSpellTimer[i] -= uiDiff;
            }
        }

        // Change target
        if (m_uiResetThreatTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
            {
                DoResetThreat();
                AttackStart(pTarget);
                m_uiResetThreatTimer = urand(5000, 15000);
            }
        }
        else
            m_uiResetThreatTimer -= uiDiff;

        // CC check for PVP trinket
        if (m_uiIsCCTimer < uiDiff)
        {
            if (m_creature->isFrozen() || m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT))
            {
                // Pvp trinket only in heroic mode
                if (m_pInstance && m_pInstance->IsHeroicDifficulty() && !m_uiTrinketCooldownTimer)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_PVP_TRINKET, CAST_TRIGGERED) == CAST_OK)
                        m_uiTrinketCooldownTimer = 120000;
                }

                SendAIEventAround(AI_EVENT_GOT_CCED, NULL, 0, CRUSADER_AIEVENT_THROW_RADIUS);
                SendAIEvent(AI_EVENT_GOT_CCED, NULL, m_creature);
                m_uiIsCCTimer = 5000;
            }
            else
                m_uiIsCCTimer = 2000;
        }
        else
            m_uiIsCCTimer -= uiDiff;

        // trinket cooldown
        if (m_uiTrinketCooldownTimer)
        {
            if (m_uiTrinketCooldownTimer <= uiDiff)
                m_uiTrinketCooldownTimer = 0;
            else
                m_uiTrinketCooldownTimer -= uiDiff;
        }

        DoMeleeAttackIfReady();
    }
 void JustDied(Unit* pKiller) override
 {
     SendAIEventAround(AI_EVENT_JUST_DIED, pKiller, 0, CRUSADER_AIEVENT_THROW_RADIUS);
 }