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; } }
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); }