void ImpAI::UpdateAI(const uint32 diff) { if (!me->isAlive()) return; m_owner = me->GetCharmerOrOwner(); updateAlliesTimer.Update(diff); if (updateAlliesTimer.Passed()) UpdateAllies(); if (m_forceTimer) { if (m_forceTimer < diff) m_forceTimer = 0; else m_forceTimer -= diff; } // me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc. if (Unit *target = me->getVictim()) { if (_needToStop()) { DEBUG_LOG("Pet AI stoped attacking [guid=%u]", me->GetGUIDLow()); _stopAttack(); return; } float dist = me->GetDistance2d(target); if (dist < 30 && m_chasing) { me->clearUnitState(UNIT_STAT_FOLLOW); me->GetMotionMaster()->MoveIdle(); m_chasing = false; } if (dist > 30 && !m_chasing) { me->GetMotionMaster()->MoveChase(target); m_chasing = true; } } else { if (me->isInCombat()) { if (!m_owner|| !m_owner->GetObjectGuid().IsPlayer()) _stopAttack(); } else if (m_owner && me->GetCharmInfo()) //no victim { if (m_owner->isInCombat() && !(me->HasReactState(REACT_PASSIVE) || me->GetCharmInfo()->HasCommandState(COMMAND_STAY))) AttackStart(m_owner->getAttackerForHelper()); else if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !me->hasUnitState(UNIT_STAT_FOLLOW)) me->GetMotionMaster()->MoveFollow(m_owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); } } if (!me->GetCharmInfo()) return; if (!me->hasUnitState(UNIT_STAT_CASTING)) { //Autocast for (uint8 i = 0; i < me->GetPetAutoSpellSize(); i++) PrepareSpellForAutocast(me->GetPetAutoSpellOnPos(i)); AutocastPreparedSpells(); } }
void PetAI::UpdateAI(const uint32 diff) { if (!m_creature->IsAlive()) { return; } Unit* owner = m_creature->GetCharmerOrOwner(); 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; } bool meleeReach = m_creature->CanReachWithMeleeAttack(m_creature->getVictim()); if (m_creature->IsStopped() || meleeReach) { // 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 (DoMeleeAttackIfReady()) { 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, PET_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; } // not allow instant kill autocasts as full health cost if (IsSpellHaveEffect(spellInfo, SPELL_EFFECT_INSTAKILL)) { continue; } } } else { // just ignore non-combat spells if (IsNonCombatSpell(spellInfo)) { continue; } } Spell* spell = new Spell(m_creature, spellInfo, false); if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim())) { targetSpellStore.push_back(TargetSpellList::value_type(m_creature->getVictim(), spell)); continue; } else { bool spellUsed = false; for (GuidSet::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) { Unit* Target = m_creature->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_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); if (m_creature->IsPet()) { ((Pet*)m_creature)->CheckLearning(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; } } }
void UpdateAI(const uint32 diff) { if (questPhase == 1) { if (timer <= diff) { me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); me->setFaction(FACTION_HOSTILE); questPhase = 0; if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { me->AddThreat(pTarget, 5000000.0f); AttackStart(pTarget); } } else timer -= diff; } if (!UpdateVictim()) return; // healer if (spellFlashLight && HealthBelowPct(70)) { if (timerFlashLight <= diff) { DoCast(me, SPELL_FLASH_OF_LIGHT); timerFlashLight = 3225 + rand()%3225; } else timerFlashLight -= diff; } if (spellJustice) { if (timerJustice <= diff) { DoCast(me, SPELL_SEAL_OF_JUSTICE); timerJustice = 10000 + rand()%10000; } else timerJustice -= diff; } if (spellJudLight) { if (timerJudLight <= diff) { DoCast(me, SPELL_JUDGEMENT_OF_LIGHT); timerJudLight = 10000 + rand()%10000; } else timerJudLight -= diff; } if (spellCommand) { if (timerCommand <= diff) { DoCast(me, SPELL_SEAL_OF_COMMAND); timerCommand = 20000 + rand()%20000; } else timerCommand -= diff; } DoMeleeAttackIfReady(); }
void HandleFlightSequence() { switch (uiFlightCount) { case 0: //me->AttackStop(); me->GetMotionMaster()->Clear(false); me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); me->StopMoving(); DoScriptText(YELL_TAKEOFF, me); events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 2000); break; case 1: me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+1, me->GetPositionY(), me->GetPositionZ()+10); break; case 2: { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); if (!target) target = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_PLAYER_GUID) : 0); if (!target) { EnterEvadeMode(); return; } Creature* Vapor = me->SummonCreature(MOB_VAPOR, target->GetPositionX()-5+rand()%10, target->GetPositionY()-5+rand()%10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); if (Vapor) { Vapor->AI()->AttackStart(target); me->InterruptNonMeleeSpells(false); DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true); } events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); break; } case 3: { DespawnSummons(MOB_VAPOR_TRAIL); //DoCast(me, SPELL_VAPOR_SELECT); need core support Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); if (!target) target = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_PLAYER_GUID) : 0); if (!target) { EnterEvadeMode(); return; } //target->CastSpell(target, SPELL_VAPOR_SUMMON, true); need core support Creature* pVapor = me->SummonCreature(MOB_VAPOR, target->GetPositionX()-5+rand()%10, target->GetPositionY()-5+rand()%10, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); if (pVapor) { if (pVapor->AI()) pVapor->AI()->AttackStart(target); me->InterruptNonMeleeSpells(false); DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true); } events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); break; } case 4: DespawnSummons(MOB_VAPOR_TRAIL); events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); break; case 5: { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); if (!target) target = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_PLAYER_GUID) : 0); if (!target) { EnterEvadeMode(); return; } breathX = target->GetPositionX(); breathY = target->GetPositionY(); float x, y, z; target->GetContactPoint(me, x, y, z, 70); me->GetMotionMaster()->MovePoint(0, x, y, z+10); break; } case 6: me->SetOrientation(me->GetAngle(breathX, breathY)); me->StopMoving(); //DoTextEmote("takes a deep breath.", NULL); events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); break; case 7: { DoCast(me, SPELL_FOG_BREATH, true); float x, y, z; me->GetPosition(x, y, z); x = 2 * breathX - x; y = 2 * breathY - y; me->GetMotionMaster()->MovePoint(0, x, y, z); events.ScheduleEvent(EVENT_SUMMON_FOG, 1); break; } case 8: me->CastStop(SPELL_FOG_BREATH); me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); ++uiBreathCount; events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); if (uiBreathCount < 3) uiFlightCount = 4; break; case 9: if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO)) DoStartMovement(target); else { EnterEvadeMode(); return; } break; case 10: me->SetDisableGravity(false); me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); EnterPhase(PHASE_GROUND); AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO)); break; } ++uiFlightCount; }
void MoveInLineOfSight(Unit* who) { if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsValidAttackTarget(who)) AttackStart(who); }
void UpdateAI(const uint32 diff) { if (SayTimer <= diff) { if (Event) SayTimer = NextStep(++Step); } else SayTimer -= diff; if (Attack) { Player* pPlayer = Unit::GetPlayer(*me, PlayerGUID); me->setFaction(14); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); if (pPlayer) { Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); if (Creepjack) { Creepjack->Attack(pPlayer, true); Creepjack->setFaction(14); Creepjack->GetMotionMaster()->MoveChase(pPlayer); Creepjack->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); if (Malone) { Malone->Attack(pPlayer, true); Malone->setFaction(14); Malone->GetMotionMaster()->MoveChase(pPlayer); Malone->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } DoStartMovement(pPlayer); AttackStart(pPlayer); } Attack = false; } if (HealthBelowPct(5) && !Done) { me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->RemoveAllAuras(); Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); if (Creepjack) { CAST_CRE(Creepjack)->AI()->EnterEvadeMode(); Creepjack->setFaction(1194); Creepjack->GetMotionMaster()->MoveTargetedHome(); Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); if (Malone) { CAST_CRE(Malone)->AI()->EnterEvadeMode(); Malone->setFaction(1194); Malone->GetMotionMaster()->MoveTargetedHome(); Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } me->setFaction(1194); Done = true; DoScriptText(SAY_GIVEUP, me, NULL); me->DeleteThreatList(); me->CombatStop(); me->GetMotionMaster()->MoveTargetedHome(); Player* pPlayer = Unit::GetPlayer(*me, PlayerGUID); if (pPlayer) CAST_PLR(pPlayer)->GroupEventHappens(QUEST_WBI, me); } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { npc_escortAI::UpdateAI(diff); if (!PlayerGUID) { me->setDeathState(JUST_DIED); return; } if (!me->isInCombat() && !Event_onWait) { if (checkPlayer_Timer <= diff) { Player* player = Unit::GetPlayer(*me, PlayerGUID); if (player && player->isInCombat() && player->getAttackerForHelper()) AttackStart(player->getAttackerForHelper()); checkPlayer_Timer = 1000; } else checkPlayer_Timer -= diff; } if (Event_onWait && Event_Timer <= diff) { Player* player = Unit::GetPlayer(*me, PlayerGUID); if (!player || (player && player->GetQuestStatus(10965) == QUEST_STATUS_NONE)) { me->setDeathState(JUST_DIED); return; } switch (CurrWP) { case 0: switch (Step) { case 0: me->Say(CLINTAR_SPIRIT_SAY_START, 0, PlayerGUID); Event_Timer = 8000; Step = 1; break; case 1: Event_onWait = false; break; } break; case 6: switch (Step) { case 0: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); Event_Timer = 5000; Step = 1; break; case 1: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); DoScriptText(CLINTAR_SPIRIT_SAY_GET_ONE, me, player); Event_onWait = false; break; } break; case 15: switch (Step) { case 0: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); Event_Timer = 5000; Step = 1; break; case 1: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); Event_onWait = false; break; } break; case 16: switch (Step) { case 0: DoScriptText(CLINTAR_SPIRIT_SAY_GET_TWO, me, player); Event_Timer = 15000; Step = 1; break; case 1: Event_onWait = false; break; } break; case 20: switch (Step) { case 0: { Creature* mob = me->SummonCreature(ASPECT_RAVEN, ASPECT_RAVEN_SUMMON_X, ASPECT_RAVEN_SUMMON_Y, ASPECT_RAVEN_SUMMON_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); if (mob) { mob->AddThreat(me, 10000.0f); mob->AI()->AttackStart(me); } Event_Timer = 2000; Step = 1; break; } case 1: Event_onWait = false; break; } break; case 24: switch (Step) { case 0: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); Event_Timer = 5000; Step = 1; break; case 1: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); Event_onWait = false; break; } break; case 25: switch (Step) { case 0: DoScriptText(CLINTAR_SPIRIT_SAY_GET_THREE, me, player); Event_Timer = 4000; Step = 1; break; case 1: Event_onWait = false; break; } break; case 40: switch (Step) { case 0: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 2); DoScriptText(CLINTAR_SPIRIT_SAY_GET_FINAL, me, player); player->CompleteQuest(10965); Event_Timer = 1500; Step = 1; break; case 1: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); Event_Timer = 3000; Step = 2; break; case 2: player->TalkedToCreature(me->GetEntry(), me->GetGUID()); PlayerGUID = 0; Reset(); me->setDeathState(JUST_DIED); break; } break; default: Event_onWait = false; break; } } else if (Event_onWait) Event_Timer -= diff; }
void MoveInLineOfSight(Unit *who) { if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) AttackStart(who); }
void UpdateAI(const uint32 diff) { if (Intro && !Done) { if (AggroTimer <= diff) { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); DoScriptText(SAY_AGGRO, me); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); Done = true; if (AggroTargetGUID) { Unit* pUnit = Unit::GetUnit((*me), AggroTargetGUID); if (pUnit) AttackStart(pUnit); DoZoneInCombat(); } else { EnterEvadeMode(); return; } } else AggroTimer -= diff; } if (!UpdateVictim() || !Done) return; if (SummonShadowsTimer <= diff) { //MindControlGhost(); for (uint8 i = 0; i < 2; ++i) { Creature* Shadow = NULL; float X = CalculateRandomLocation(me->GetPositionX(), 10); Shadow = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 0); if (Shadow) { Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); if (!pTarget) pTarget = me->getVictim(); if (pTarget) Shadow->AI()->AttackStart(pTarget); } } SummonShadowsTimer = 60000; } else SummonShadowsTimer -= diff; if (SummonDoomBlossomTimer <= diff) { if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) { float X = CalculateRandomLocation(pTarget->GetPositionX(), 20); float Y = CalculateRandomLocation(pTarget->GetPositionY(), 20); float Z = pTarget->GetPositionZ(); Z = me->GetMap()->GetVmapHeight(X, Y, Z); Creature* DoomBlossom = me->SummonCreature(CREATURE_DOOM_BLOSSOM, X, Y, Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); if (DoomBlossom) { DoomBlossom->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); DoomBlossom->setFaction(me->getFaction()); DoomBlossom->AddThreat(pTarget, 1.0f); CAST_AI(mob_doom_blossomAI, DoomBlossom->AI())->SetTeronGUID(me->GetGUID()); pTarget->CombatStart(DoomBlossom); SetThreatList(DoomBlossom); SummonDoomBlossomTimer = 35000; } } } else SummonDoomBlossomTimer -= diff; if (IncinerateTimer <= diff) { Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); if (!pTarget) pTarget = me->getVictim(); if (pTarget) { DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); DoCast(pTarget, SPELL_INCINERATE); IncinerateTimer = 20000 + rand()%31 * 1000; } } else IncinerateTimer -= diff; if (CrushingShadowsTimer <= diff) { Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); if (pTarget && pTarget->isAlive()) DoCast(pTarget, SPELL_CRUSHING_SHADOWS); CrushingShadowsTimer = 10000 + rand()%16 * 1000; } else CrushingShadowsTimer -= diff; /*** NOTE FOR FUTURE DEV: UNCOMMENT BELOW ONLY IF MIND CONTROL IS FULLY IMPLEMENTED **/ /*if (ShadowOfDeathTimer <= diff) { Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); if (!pTarget) pTarget = me->getVictim(); if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) { DoCast(pTarget, SPELL_SHADOW_OF_DEATH); GhostGUID = pTarget->GetGUID(); ShadowOfDeathTimer = 30000; SummonShadowsTimer = 53000; // Make it VERY close but slightly less so that we can check if the aura is still on the player } } else ShadowOfDeathTimer -= diff;*/ if (RandomYellTimer <= diff) { DoScriptText(RAND(SAY_SPELL1,SAY_SPELL2), me); RandomYellTimer = 50000 + rand()%51 * 1000; } else RandomYellTimer -= diff; if (!me->HasAura(SPELL_BERSERK)) { if (EnrageTimer <= diff) { DoCast(me, SPELL_BERSERK); DoScriptText(SAY_ENRAGE, me); } else EnrageTimer -= diff; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { //Speech if (DoingSpeech) { if (SpeechTimer <= diff) { switch (SpeechNum) { case 0: //16 seconds till next line DoScriptText(SAY_LINE2, me); SpeechTimer = 16000; ++SpeechNum; break; case 1: //This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!" DoScriptText(SAY_LINE3, me); SpeechTimer = 10000; ++SpeechNum; break; case 2: me->setFaction(103); if (PlayerGUID && Unit::GetUnit(*me, PlayerGUID)) { AttackStart(Unit::GetUnit(*me, PlayerGUID)); DoCast(me, SPELL_ESSENCEOFTHERED); } SpeechTimer = 0; DoingSpeech = false; break; } } else SpeechTimer -= diff; } //Return since we have no target if (!UpdateVictim()) return; // Yell if hp lower than 15% if (HealthBelowPct(15) && !HasYelled) { DoScriptText(SAY_HALFLIFE, me); HasYelled = true; } //Cleave_Timer if (Cleave_Timer <= diff) { DoCast(me->getVictim(), SPELL_CLEAVE); Cleave_Timer = 15000; } else Cleave_Timer -= diff; //FlameBreath_Timer if (FlameBreath_Timer <= diff) { DoCast(me->getVictim(), SPELL_FLAMEBREATH); FlameBreath_Timer = urand(4000, 8000); } else FlameBreath_Timer -= diff; //BurningAdrenalineCaster_Timer if (BurningAdrenalineCaster_Timer <= diff) { Unit* target = NULL; uint8 i = 0; while (i < 3) // max 3 tries to get a random target with power_mana { ++i; target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); //not aggro leader if (target && target->getPowerType() == POWER_MANA) i = 3; } if (target) // cast on self (see below) target->CastSpell(target, SPELL_BURNINGADRENALINE, 1); BurningAdrenalineCaster_Timer = 15000; } else BurningAdrenalineCaster_Timer -= diff; //BurningAdrenalineTank_Timer if (BurningAdrenalineTank_Timer <= diff) { // have the victim cast the spell on himself otherwise the third effect aura will be applied // to Vael instead of the player me->getVictim()->CastSpell(me->getVictim(), SPELL_BURNINGADRENALINE, 1); BurningAdrenalineTank_Timer = 45000; } else BurningAdrenalineTank_Timer -= diff; //FireNova_Timer if (FireNova_Timer <= diff) { DoCast(me->getVictim(), SPELL_FIRENOVA); FireNova_Timer = 5000; } else FireNova_Timer -= diff; //TailSwipe_Timer if (TailSwipe_Timer <= diff) { //Only cast if we are behind /*if (!me->HasInArc(M_PI, me->getVictim())) { DoCast(me->getVictim(), SPELL_TAILSWIPE); }*/ TailSwipe_Timer = 20000; } else TailSwipe_Timer -= diff; DoMeleeAttackIfReady(); }
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()) { if (_needToStop()) { sLog->outStaticDebug("Pet AI stopped attacking [guid=%u]", me->GetGUIDLow()); _stopAttack(); return; } targetHasCC = _CheckTargetCC(me->getVictim()); DoMeleeAttackIfReady(); } else if (owner && me->GetCharmInfo()) //no victim { Unit *nextTarget = SelectNextTarget(); if (me->HasReactState(REACT_PASSIVE)) _stopAttack(); else if (nextTarget) AttackStart(nextTarget); else HandleReturnMovement(); } else if (owner && !me->HasUnitState(UNIT_STAT_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->GetGlobalCooldown() == 0 && !me->HasUnitState(UNIT_STAT_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; SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); if (!spellInfo) continue; // ignore some combinations of combat state and combat/noncombat spells if (!me->getVictim()) { // 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(me, spellInfo, false, 0); // Fix to allow pets on STAY to autocast if (me->getVictim() && _CanAttack(me->getVictim()) && spell->CanAutoCast(me->getVictim())) { targetSpellStore.push_back( std::make_pair<Unit*, Spell*>(me->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(*me, *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 (!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; } }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) { return; } // Summon panters every 5 seconds if (m_uiSummonTimer < uiDiff) { if (m_pInstance) { if (Creature* pTrigger = m_pInstance->instance->GetCreature(ObjectGuid(m_pInstance->GetData64(TYPE_SIGNAL_2)))) { m_creature->SummonCreature(NPC_ZULIAN_PROWLER, pTrigger->GetPositionX(), pTrigger->GetPositionY(), pTrigger->GetPositionZ(), 0, TEMPSUMMON_TIMED_OOC_DESPAWN, 30000); } if (Creature* pTrigger = m_pInstance->instance->GetCreature(ObjectGuid(m_pInstance->GetData64(TYPE_SIGNAL_3)))) { m_creature->SummonCreature(NPC_ZULIAN_PROWLER, pTrigger->GetPositionX(), pTrigger->GetPositionY(), pTrigger->GetPositionZ(), 0, TEMPSUMMON_TIMED_OOC_DESPAWN, 30000); } } m_uiSummonTimer = 5000; } else { m_uiSummonTimer -= uiDiff; } if (m_uiVisibleTimer) { if (m_uiVisibleTimer <= uiDiff) { // Restore visibility m_creature->SetVisibility(VISIBILITY_ON); if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { AttackStart(pTarget); } m_uiVisibleTimer = 0; } else { m_uiVisibleTimer -= uiDiff; } // Do nothing while vanished return; } // Troll phase if (!m_bIsPhaseTwo) { if (m_uiShadowWordPainTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_SHADOW_WORD_PAIN) == CAST_OK) { m_uiShadowWordPainTimer = 15000; } } } else { m_uiShadowWordPainTimer -= uiDiff; } if (m_uiMarkTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_MARK_ARLOKK, SELECT_FLAG_PLAYER)) { if (DoCastSpellIfCan(pTarget, SPELL_MARK_ARLOKK) == CAST_OK) { DoScriptText(SAY_FEAST_PANTHER, m_creature, pTarget); m_uiMarkTimer = 30000; } } } else { m_uiMarkTimer -= uiDiff; } if (m_uiGougeTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_GOUGE) == CAST_OK) { if (m_creature->GetThreatManager().getThreat(m_creature->getVictim())) { m_creature->GetThreatManager().modifyThreatPercent(m_creature->getVictim(), -80); } m_uiGougeTimer = urand(17000, 27000); } } else { m_uiGougeTimer -= uiDiff; } // Transform to Panther if (m_uiTransformTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_PANTHER_TRANSFORM) == CAST_OK) { m_uiTransformTimer = 80000; m_bIsPhaseTwo = true; } } else { m_uiTransformTimer -= uiDiff; } } // Panther phase else { if (m_uiRavageTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_RAVAGE) == CAST_OK) { m_uiRavageTimer = urand(10000, 15000); } } else { m_uiRavageTimer -= uiDiff; } if (m_uiTrashTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_TRASH) == CAST_OK) { m_uiTrashTimer = urand(13000, 15000); } } else { m_uiTrashTimer -= uiDiff; } if (m_uiWhirlwindTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_WHIRLWIND) == CAST_OK) { m_uiWhirlwindTimer = 15000; } } else { m_uiWhirlwindTimer -= uiDiff; } if (m_uiVanishTimer < uiDiff) { // Note: this is a workaround because we do not know the real vanish spell m_creature->SetVisibility(VISIBILITY_OFF); DoResetThreat(); m_uiVanishTimer = 85000; m_uiVisibleTimer = 45000; } else { m_uiVanishTimer -= uiDiff; } // Transform back if (m_uiTransformTimer < uiDiff) { m_creature->RemoveAurasDueToSpell(SPELL_PANTHER_TRANSFORM); m_uiTransformTimer = 30000; m_bIsPhaseTwo = false; } else { m_uiTransformTimer -= uiDiff; } } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) { if (!UpdateVictim()) return; events.Update(diff); if( me->HasUnitState(UNIT_STATE_CASTING) ) return; switch( events.GetEvent() ) { case 0: break; case EVENT_YELL_DEAD_1: Talk(YELL_DEAD_1); events.PopEvent(); break; case EVENT_START_RESURRECTION: me->CastSpell(me, SPELL_SUMMON_VALKYR, true); events.PopEvent(); events.RescheduleEvent(EVENT_VALKYR_BEAM, 7000); events.RescheduleEvent(EVENT_VALKYR_MOVE, 1); events.RescheduleEvent(EVENT_ANNHYLDE_YELL, 3000); break; case EVENT_VALKYR_MOVE: if( Creature* s = ObjectAccessor::GetCreature(*me, ValkyrGUID) ) s->GetMotionMaster()->MovePoint(1, s->GetPositionX(), s->GetPositionY(), s->GetPositionZ()-15.0f); events.PopEvent(); break; case EVENT_ANNHYLDE_YELL: if( Creature* s = ObjectAccessor::GetCreature(*me, ValkyrGUID) ) s->AI()->Talk(YELL_ANHYLDE_2); events.PopEvent(); break; case EVENT_VALKYR_BEAM: me->RemoveAura(SPELL_SUMMON_VALKYR); if( Creature* c = ObjectAccessor::GetCreature(*me, ValkyrGUID) ) c->CastSpell(me, SPELL_RESURRECTION_BEAM, false); events.PopEvent(); events.RescheduleEvent(EVENT_RESURRECTION_BALL, 4000); break; case EVENT_RESURRECTION_BALL: me->CastSpell(me, SPELL_RESURRECTION_BALL, true); events.PopEvent(); events.RescheduleEvent(EVENT_RESURRECTION_HEAL, 4000); break; case EVENT_RESURRECTION_HEAL: me->RemoveAura(SPELL_RESURRECTION_BALL); me->CastSpell(me, SPELL_RESURRECTION_HEAL, true); FeignDeath(false); events.PopEvent(); events.RescheduleEvent(EVENT_MORPH_TO_UNDEAD, 3000); break; case EVENT_MORPH_TO_UNDEAD: me->CastSpell(me, SPELL_INGVAR_TRANSFORM, true); events.PopEvent(); events.RescheduleEvent(EVENT_START_PHASE_2, 1000); break; case EVENT_START_PHASE_2: if( Creature* c = ObjectAccessor::GetCreature(*me, ValkyrGUID) ) { c->DespawnOrUnsummon(); summons.DespawnAll(); } events.PopEvent(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); AttackStart(me->GetVictim()); me->GetMotionMaster()->MoveChase(me->GetVictim()); Talk(YELL_AGGRO_2); // schedule Phase 2 abilities events.RescheduleEvent(EVENT_SPELL_ROAR, 15000); events.RescheduleEvent(EVENT_SPELL_CLEAVE_OR_WOE_STRIKE, 2000); events.RescheduleEvent(EVENT_SPELL_SMASH, 5000); events.RescheduleEvent(EVENT_SPELL_ENRAGE_OR_SHADOW_AXE, 10000); break; // ABILITIES HERE: case EVENT_UNROOT: me->SetControlled(false, UNIT_STATE_ROOT); me->DisableRotate(false); events.PopEvent(); break; case EVENT_SPELL_ROAR: Talk(EMOTE_ROAR); me->_AddCreatureSpellCooldown(SPELL_STAGGERING_ROAR, 0); me->_AddCreatureSpellCooldown(SPELL_DREADFUL_ROAR, 0); if (me->GetDisplayId() == DISPLAYID_DEFAULT) me->CastSpell((Unit*)NULL, SPELL_STAGGERING_ROAR, false); else me->CastSpell((Unit*)NULL, SPELL_DREADFUL_ROAR, false); events.RepeatEvent(urand(15000,20000)); break; case EVENT_SPELL_CLEAVE_OR_WOE_STRIKE: if( me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) == 0 ) { events.RepeatEvent(3000); break; } if (me->GetDisplayId() == DISPLAYID_DEFAULT) me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false); else me->CastSpell(me->GetVictim(), SPELL_WOE_STRIKE, false); events.RepeatEvent(urand(0,4000)+3000); break; case EVENT_SPELL_SMASH: if( me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) == 0 ) { events.RepeatEvent(3000); break; } me->SetControlled(true, UNIT_STATE_ROOT); me->DisableRotate(true); me->SendMovementFlagUpdate(); if (me->GetDisplayId() == DISPLAYID_DEFAULT) me->CastSpell((Unit*)NULL, SPELL_SMASH, false); else me->CastSpell((Unit*)NULL, SPELL_DARK_SMASH, false); events.RepeatEvent(urand(9000,11000)); events.RescheduleEvent(EVENT_UNROOT, 3750); break; case EVENT_SPELL_ENRAGE_OR_SHADOW_AXE: if (me->GetDisplayId() == DISPLAYID_DEFAULT) { me->CastSpell(me, SPELL_ENRAGE, false); events.RepeatEvent(10000); } else { me->CastSpell((Unit*)NULL, SPELL_SHADOW_AXE, true); SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); events.RepeatEvent(35000); events.RescheduleEvent(EVENT_AXE_RETURN, 10000); } break; case EVENT_AXE_RETURN: if (Creature* c = ObjectAccessor::GetCreature(*me, ThrowGUID)) c->GetMotionMaster()->MoveCharge(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+0.5f); events.PopEvent(); events.RescheduleEvent(EVENT_AXE_PICKUP, 1500); break; case EVENT_AXE_PICKUP: if (Creature* c = ObjectAccessor::GetCreature(*me, ThrowGUID)) { c->DestroyForNearbyPlayers(); c->DespawnOrUnsummon(); summons.DespawnAll(); } ThrowGUID = 0; SetEquipmentSlots(true); events.PopEvent(); break; } if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (instance) { if (!leotherasGUID) leotherasGUID = instance->GetData64(DATA_LEOTHERAS); if (!me->isInCombat() && instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) { Unit* victim = NULL; victim = Unit::GetUnit(*me, instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); if (victim) AttackStart(victim); } } if (!UpdateVictim()) { CastChanneling(); return; } if (instance && !instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) { EnterEvadeMode(); return; } if (Mindblast_Timer <= diff) { Unit* target = NULL; target = SelectTarget(SELECT_TARGET_RANDOM, 0); if (target)DoCast(target, SPELL_MINDBLAST); Mindblast_Timer = urand(10000, 15000); } else Mindblast_Timer -= diff; if (Earthshock_Timer <= diff) { Map* map = me->GetMap(); Map::PlayerList const &PlayerList = map->GetPlayers(); for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) { if (Player* i_pl = itr->getSource()) { bool isCasting = false; for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) if (i_pl->GetCurrentSpell(i)) isCasting = true; if (isCasting) { DoCast(i_pl, SPELL_EARTHSHOCK); break; } } } Earthshock_Timer = urand(8000, 15000); } else Earthshock_Timer -= diff; DoMeleeAttackIfReady(); }
void PetAI::UpdateAI(const uint32 diff) { if (!m_creature->isAlive()) return; m_updateAlliesTimer.Update(diff); if (m_updateAlliesTimer.Passed()) { UpdateAllies(); m_updateAlliesTimer.Reset(); } Unit* owner = m_creature->GetCharmerOrOwner(); if (owner && !m_creature->IsWithinDistInMap(owner, m_fMaxRadiusToOwner) && !m_creature->IsInUnitState(UNIT_ACTION_HOME)) { if (owner->GetTypeId() == TYPEID_PLAYER && (m_creature->IsPet() || m_creature->isCharmed())) { owner->CallForAllControlledUnits(DoPetActionWithHelper((Player*)owner, ACT_REACTION, REACT_PASSIVE, m_creature->GetObjectGuid(), ObjectGuid()), CONTROLLED_PET | CONTROLLED_GUARDIANS | CONTROLLED_CHARM); owner->CallForAllControlledUnits(DoPetActionWithHelper((Player*)owner, ACT_COMMAND, COMMAND_FOLLOW, m_creature->GetObjectGuid(), ObjectGuid()), CONTROLLED_PET | CONTROLLED_GUARDIANS | CONTROLLED_CHARM); return; } } if (!inCombat && m_savedTargetGuid) { if (Unit* savedTarget = m_creature->GetMap()->GetUnit(m_savedTargetGuid)) { if (!savedTarget->isAlive()) m_savedTargetGuid.Clear(); else if (!savedTarget->IsCrowdControlled()) AttackStart(savedTarget); } else m_savedTargetGuid.Clear(); } Unit* pVictim = m_creature->getVictim(); if (inCombat && (!pVictim || !pVictim->isAlive() || (m_creature->IsPet() && m_creature->GetCharmInfo()->HasState(CHARM_STATE_ACTION, ACTIONS_DISABLE)))) _stopAttack(); if (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT) || m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) { UpdateAIType(); return; } // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. if (pVictim) { bool meleeReach = m_creature->CanReachWithMeleeAttack(pVictim); if (_needToStop()) { DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_creature->GetGUIDLow()); _stopAttack(); return; } else if (!pVictim->isAlive()) // Stop attack if target dead { m_creature->InterruptNonMeleeSpells(false); _stopAttack(); return; } // Stop attack if target under CC effect else if (sWorld.getConfig(CONFIG_BOOL_PET_ADVANCED_AI) && IsInCombat() && pVictim->IsCrowdControlled() && !m_creature->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) { m_savedTargetGuid = pVictim->GetObjectGuid(); m_creature->InterruptSpell(CURRENT_GENERIC_SPELL, true); if (!m_creature->IsNonMeleeSpellCasted(false, false, true)) _stopAttack(); return; } else if (m_creature->IsStopped() || meleeReach) { // 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 (DoMeleeAttackIfReady()) { pVictim = m_creature->getVictim(); if (!pVictim) return; // if pet misses its target, it will also be the first in threat list pVictim->AddThreat(m_creature); if (_needToStop()) _stopAttack(); } } if (!m_creature->IsNonMeleeSpellCasted(true)) { m_attackDistanceRecheckTimer.Update(diff); if (m_attackDistanceRecheckTimer.Passed()) { m_attackDistanceRecheckTimer.Reset(); if (sWorld.getConfig(CONFIG_BOOL_PET_ADVANCED_AI) && m_AIType == PET_AI_RANGED && pVictim) { float dist = m_creature->GetDistance(pVictim); if ((m_creature->CanReachWithMeleeAttack(pVictim) && m_creature->IsWithinDist(owner, m_creature->GetMap()->GetVisibilityDistance() / 2.0f)) || dist > (m_attackDistance + 2.0f)) { MoveToVictim(pVictim); return; } } if (sWorld.getConfig(CONFIG_BOOL_PET_ADVANCED_AI)) { // FIXME: AOE check } } } } else if (Unit* target = GetPrimaryTarget()) { AttackStart(target); } else if (owner) { switch (m_creature->GetCharmState(CHARM_STATE_REACT)) { case REACT_DEFENSIVE: { if (!m_primaryTargetGuid) { Unit* ownerVictim = owner->getVictim(); if (ownerVictim && ownerVictim->isAlive()) AttackStart(ownerVictim); } break; } case REACT_AGGRESSIVE: { if (Unit* pTarget = owner->getAttackerForHelper()) AttackStart(pTarget); break; } // case REACT_PASSIVE: default: break; } } UpdateAIType(); if (m_creature->IsNonMeleeSpellCasted(true)) return; // Autocast (casted only in combat or persistent spells in any state) if (!sWorld.getConfig(CONFIG_BOOL_PET_ADVANCED_AI) && m_AIType != PET_AI_PASSIVE) { typedef std::vector<std::pair<ObjectGuid, uint32> > 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; if (m_creature->HasSpellCooldown(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; } Unit* autoCastTarget = NULL; if (inCombat) { Unit* pVictim = m_creature->getVictim(); if (pVictim && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) { SpellCastResult result = CanAutoCast(pVictim, spellInfo); if (result == SPELL_CAST_OK || result == SPELL_FAILED_UNIT_NOT_INFRONT) autoCastTarget = pVictim; } } if (!autoCastTarget) { for (GuidSet::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) { Unit* target = m_creature->GetMap()->GetUnit(*tar); // Only buff targets that are in combat, unless the spell can only be cast while out of combat if (!target) continue; SpellCastResult result = CanAutoCast(target, spellInfo); if (result == SPELL_CAST_OK || result == SPELL_FAILED_UNIT_NOT_INFRONT) { autoCastTarget = target; break; } } } if (autoCastTarget) targetSpellStore.push_back(TargetSpellList::value_type(autoCastTarget->GetObjectGuid(), spellInfo->Id)); } // found units to cast on to if (!targetSpellStore.empty()) { uint32 index = urand(0, targetSpellStore.size() - 1); if (Unit* target = m_creature->GetMap()->GetUnit(targetSpellStore[index].first)) m_creature->DoPetCastSpell(target, targetSpellStore[index].second); } } else { AutoSpellList currentSpells; switch (m_AIType) { case PET_AI_PASSIVE: { currentSpells.push_back(GetSpellType(PET_SPELL_BUFF)); break; } case PET_AI_SLACKER: { if (!IsInCombat()) break; if (m_creature->IsCrowdControlled() || (owner && owner->IsCrowdControlled())) currentSpells.push_back(GetSpellType(PET_SPELL_FREEACTION)); currentSpells.push_back(GetSpellType(PET_SPELL_DEFENCE)); currentSpells.push_back(GetSpellType(PET_SPELL_BUFF)); currentSpells.push_back(GetSpellType(PET_SPELL_DEBUFF)); currentSpells.push_back(GetSpellType(PET_SPELL_RANGED)); break; } case PET_AI_HEALER: { if (!IsInCombat()) break; if (m_creature->IsCrowdControlled() || (owner && owner->IsCrowdControlled())) currentSpells.push_back(GetSpellType(PET_SPELL_FREEACTION)); if (m_creature->GetHealth() < m_creature->GetMaxHealth() || (owner && (owner->GetHealth() < owner->GetMaxHealth()))) currentSpells.push_back(GetSpellType(PET_SPELL_HEAL)); currentSpells.push_back(GetSpellType(PET_SPELL_BUFF)); currentSpells.push_back(GetSpellType(PET_SPELL_RANGED)); break; } case PET_AI_RANGED: { if (!IsInCombat()) break; if (m_creature->IsCrowdControlled() || (owner && owner->IsCrowdControlled())) currentSpells.push_back(GetSpellType(PET_SPELL_FREEACTION)); currentSpells.push_back(GetSpellType(PET_SPELL_RANGED)); currentSpells.push_back(GetSpellType(PET_SPELL_DEBUFF)); currentSpells.push_back(GetSpellType(PET_SPELL_BUFF)); break; } case PET_AI_MELEE: case PET_AI_RANGED_NOAMMO: { if (!IsInCombat()) break; if (Unit* victim = m_creature->getVictim()) { Unit* victimVictim = victim->getVictim(); if (!victimVictim || (victimVictim->GetObjectGuid() != m_creature->GetObjectGuid())) { currentSpells.push_back(GetSpellType(PET_SPELL_ATTACKSTART)); currentSpells.push_back(GetSpellType(PET_SPELL_THREAT)); } } if (m_creature->IsCrowdControlled() || (owner && owner->IsCrowdControlled())) currentSpells.push_back(GetSpellType(PET_SPELL_FREEACTION)); } /* no break here!*/ default: { if (!IsInCombat()) break; currentSpells.push_back(GetSpellType(PET_SPELL_MELEE)); currentSpells.push_back(GetSpellType(PET_SPELL_DEBUFF)); currentSpells.push_back(GetSpellType(PET_SPELL_RANGED)); currentSpells.push_back(GetSpellType(PET_SPELL_BUFF)); break; } } if (!IsInCombat()) { currentSpells.push_back(GetSpellType(PET_SPELL_NONCOMBAT)); if (m_creature->GetHealthPercent() < 95.0f) currentSpells.push_back(GetSpellType(PET_SPELL_HEAL)); } else currentSpells.push_back(GetSpellType(PET_SPELL_SPECIAL)); for (AutoSpellList::const_iterator itr = currentSpells.begin(); itr != currentSpells.end(); ++itr) { uint32 spellID = *itr; if (!spellID) continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID); if (!spellInfo) continue; if (m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) continue; Unit* pTarget = m_creature->IsPet() ? ((Pet*)m_creature)->SelectPreferredTargetForSpell(spellInfo) : ((Creature*)m_creature)->SelectPreferredTargetForSpell(spellInfo); bool b_castOk = false; if (pTarget) { SpellCastResult result = CanAutoCast(pTarget, spellInfo); DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS,"PetAI::Update %s, AI %u try cast %u Target %s", m_creature->GetGuidStr().c_str(), m_AIType, spellID, pTarget ? pTarget->GetGuidStr().c_str() : "<none>"); switch (result) { case SPELL_FAILED_TOO_CLOSE: case SPELL_FAILED_OUT_OF_RANGE: break; // ignore case SPELL_FAILED_UNIT_NOT_INFRONT: { if (DoCastSpellIfCan(pTarget, spellID) == CAST_OK) { b_castOk = true; m_creature->SetInFront(pTarget); if (pTarget->GetTypeId() == TYPEID_PLAYER) m_creature->SendCreateUpdateToPlayer((Player*)pTarget); } break; } case SPELL_CAST_OK: { if (DoCastSpellIfCan(pTarget, spellID) == CAST_OK) b_castOk = true; break; } default: { Player* owner = (Player*)m_creature->GetOwner(); if (owner) Spell::SendCastResult(owner, spellInfo, 0, result, true); DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI::Update cast %s, AI %u Target %s spell %u result %u", m_creature->GetGuidStr().c_str(), m_AIType, pTarget ? pTarget->GetGuidStr().c_str() : "<none>", spellID, result); break; } } } else continue; if (b_castOk) { if (m_creature->IsPet()) { if (((Pet*)m_creature)->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) m_creature->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else m_creature->SendPetAIReaction(); } break; } } } }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if (me->getVictim() && me->isAlive()) { if (HealthAbovePct(50)) { if (Charge_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { DoCast(target, SPELL_CHARGE); AttackStart(target); } Charge_Timer = urand(15000, 30000); } else Charge_Timer -= diff; if (SonicBurst_Timer <= diff) { DoCast(me->getVictim(), SPELL_SONICBURST); SonicBurst_Timer = urand(8000, 13000); } else SonicBurst_Timer -= diff; if (Screech_Timer <= diff) { DoCast(me->getVictim(), SPELL_SCREECH); Screech_Timer = urand(18000, 26000); } else Screech_Timer -= diff; if (SpawnBats_Timer <= diff) { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); Creature* Bat = NULL; Bat = me->SummonCreature(11368, -12291.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (target && Bat) Bat ->AI()->AttackStart(target); Bat = me->SummonCreature(11368, -12289.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (target && Bat) Bat ->AI()->AttackStart(target); Bat = me->SummonCreature(11368, -12293.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (target && Bat) Bat ->AI()->AttackStart(target); Bat = me->SummonCreature(11368, -12291.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (target && Bat) Bat ->AI()->AttackStart(target); Bat = me->SummonCreature(11368, -12289.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (target && Bat) Bat ->AI()->AttackStart(target); Bat = me->SummonCreature(11368, -12293.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (target && Bat) Bat ->AI()->AttackStart(target); SpawnBats_Timer = 60000; } else SpawnBats_Timer -= diff; } else { if (PhaseTwo) { if (PhaseTwo && ShadowWordPain_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { DoCast(target, SPELL_SHADOW_WORD_PAIN); ShadowWordPain_Timer = urand(12000, 18000); } } ShadowWordPain_Timer -=diff; if (MindFlay_Timer <= diff) { DoCast(me->getVictim(), SPELL_MIND_FLAY); MindFlay_Timer = 16000; } MindFlay_Timer -=diff; if (ChainMindFlay_Timer <= diff) { me->InterruptNonMeleeSpells(false); DoCast(me->getVictim(), SPELL_CHAIN_MIND_FLAY); ChainMindFlay_Timer = urand(15000, 30000); } ChainMindFlay_Timer -=diff; if (GreaterHeal_Timer <= diff) { me->InterruptNonMeleeSpells(false); DoCast(me, SPELL_GREATERHEAL); GreaterHeal_Timer = urand(25000, 35000); } GreaterHeal_Timer -=diff; if (SpawnFlyingBats_Timer <= diff) { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); if (!target) return; Creature* FlyingBat = me->SummonCreature(14965, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (FlyingBat) FlyingBat->AI()->AttackStart(target); SpawnFlyingBats_Timer = urand(10000, 15000); } else SpawnFlyingBats_Timer -=diff; } else { me->SetDisplayId(15219); DoResetThreat(); PhaseTwo = true; } } DoMeleeAttackIfReady(); } }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM,0); if (!pTarget) return; if(me->GetPositionY() > -60 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. { me->RemoveAllAuras(); me->DeleteThreatList(); me->CombatStop(false); me->GetMotionMaster()->MoveTargetedHome(); } if (me->getVictim() && !me->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) me->Kill(me->getVictim()); if ((me->GetHealth()*100 / me->GetMaxHealth()) < 90 && Phase == 0) { Phase = 1; bFly = true; } if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50 && Phase == 1) { me->RemoveAllAuras(); Phase = 2; InitialSpawn = false; if (IsFlying) { me->SetFlying(false); me->GetMotionMaster()->MoveTargetedHome(); IsFlying = false; me->SetReactState(REACT_AGGRESSIVE); me->SendMovementFlagUpdate(); } DoScriptText(SAY_PHASE_2_TRANS, me); } if ((me->GetHealth()*100 / me->GetMaxHealth()) < 33 && Phase == 2) { Phase = 3; DoScriptText(SAY_PHASE_3_TRANS, me); } if (Phase >= 2) { if (FuseArmorTimer <= diff) { DoCastVictim(SPELL_FUSEARMOR); FuseArmorTimer = 10000; } else FuseArmorTimer -= diff; if (WingBuffetTimer <= diff) { DoCast(SPELL_WINGBUFFET); WingBuffetTimer = urand(27000,34000); } else WingBuffetTimer -= diff; if (FireballTimer <= diff) { if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) { me->SetInFront(pTarget); DoCast(pTarget, SPELL_FIREBALL); } FireballTimer = 18000; } else FireballTimer -= diff; if (Phase == 3) { if (FlameBuffetTimer <= diff) { DoScriptText(EMOTE_BREATH, me); std::list<Unit*> pTargets; SelectTargetList(pTargets, RAID_MODE(3,9), SELECT_TARGET_RANDOM, 100, true); uint8 i = 0; for (std::list<Unit*>::const_iterator itr = pTargets.begin(); itr != pTargets.end();) { if (me->HasInArc(M_PI, *itr)) { DoCast(*itr, SPELL_FLAMEBUFFET, true); ++i; } if (++itr == pTargets.end() || i == RAID_MODE(3,9)) { AttackStart(*--itr); break; } if (!i) return; } FlameBuffetTimer = 25000; } else FlameBuffetTimer -= diff; if (FlameBreathTimer <= diff) { DoScriptText(EMOTE_BREATH, me); DoCastVictim(SPELL_FLAMEBREATH); FlameBreathTimer = 15000; } else FlameBreathTimer -= diff; } DoMeleeAttackIfReady(); } else if (Phase == 1) { if (bFly) { FlyPhase(Phase, diff); SummonAddsTimer = 8000; bFly = false; } Creature* pSpellHitt; pSpellHitt = NULL; if (pSpellHitt = me->FindNearestCreature(NPC_VISUAL_HITT, 5.0f, true)) { me->GetMotionMaster()->MoveTargetedHome(); me->SetFlying(false); me->SendMovementFlagUpdate(); IsFlying = false; bFlyPhase1 = true; bFlyPhaseTimer = 35000; bFly = false; InitialSpawn = false; me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); StunTimer = 2000; } if (!bFly && bFlyPhase1 && !IsFlying && StunTimer <= diff) { DoCast(me,SPELL_STUN); StunTimer = 2000; } else StunTimer -= diff; if (bFlyPhase1 && bFlyPhaseTimer <= diff) { me->RemoveAllAuras(); me->SetReactState(REACT_AGGRESSIVE); me->SendMovementFlagUpdate(); DoScriptText(EMOTE_BREATH, me); DoCastVictim(SPELL_FLAMEBREATH); DoCast(SPELL_WINGBUFFET); bFlyPhaseTimer = 40000; SpawnHarpoonTimer = 60000; bFly = true; bFlyPhase1 = false; } else bFlyPhaseTimer -= diff; if (FireballTimer <= diff) { if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) { me->SetInFront(pTarget); DoCast(pTarget, SPELL_FIREBALL); } FireballTimer = 12000; } else FireballTimer -= diff; if (DevouringFlameTimer <= diff) { if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) { me->SetInFront(pTarget); DoCast(pTarget, DEVOURING_FLAME_VISUAL); } DevouringFlameTimer = 6000; } else DevouringFlameTimer -= diff; if (InitialSpawn) { if (SummonAddsTimer <= diff) { SummonAdds(); InitialSpawn = true; } else SummonAddsTimer -= diff; } if (InitialSpawn && SpawnHarpoonTimer <= diff) { if (pInstance) pInstance->SetData(DATA_HARPOON, pInstance->GetData(DATA_HARPOON)+1); //if(!GetClosestGameObjectWithEntry(me, GO_BROKEN_HARPOON, 200.0f)) //if (GameObject* pGo = me->SummonGameObject(GO_BROKEN_HARPOON, 607.613, -134.207, 391.297, 4.10138, 0, 0, 0, 0,0)) SpawnHarpoonTimer = 60000; } else SpawnHarpoonTimer -= diff; //EnterEvadeIfOutOfCombatArea(diff); } }
void UpdateAI(uint32 diff) override { //Only if not incombat check if the event is started if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) { if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) { AttackStart(target); GetAdvisors(); } } //Return since we have no target if (!UpdateVictim()) return; //someone evaded! if (!instance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; } //CataclysmicBolt_Timer if (CataclysmicBolt_Timer <= diff) { //select a random unit other than the main tank Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); //if there aren't other units, cast on the tank if (!target) target = me->GetVictim(); if (target) DoCast(target, SPELL_CATACLYSMIC_BOLT); CataclysmicBolt_Timer = 10000; } else CataclysmicBolt_Timer -= diff; //SearNova_Timer if (SearNova_Timer <= diff) { DoCastVictim(SPELL_SEAR_NOVA); SearNova_Timer = 20000 + rand32() % 40000; } else SearNova_Timer -= diff; //Enrage_Timer if (Enrage_Timer <= diff) { DoCast(me, SPELL_ENRAGE); Enrage_Timer = 90000; } else Enrage_Timer -= diff; //Blessing of Tides Trigger if (!HealthAbovePct(75) && !BlessingOfTides) { BlessingOfTides = true; bool continueTriggering = false; for (uint8 i = 0; i < MAX_ADVISORS; ++i) { if (!Advisors[i].IsEmpty()) { Creature* advisor = ObjectAccessor::GetCreature(*me, Advisors[i]); if (advisor && advisor->IsAlive()) { continueTriggering = true; break; } } } if (continueTriggering) { DoCast(me, SPELL_BLESSING_OF_THE_TIDES); me->Yell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL); DoPlaySoundToSet(me, SOUND_GAIN_BLESSING_OF_TIDES); } } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) { if (!isActive) { IntroTimer += diff; if (IntroTimer > 5000 && IntroTimer < 10000) { if (SelectTargetFromPlayerList(60)) { Talk(SAY_INTRO_1); IntroTimer = 10000; } else IntroTimer = 0; } if (IntroTimer >= 30000 && IntroTimer < 40000) { Talk(SAY_INTRO_2); IntroTimer = 40000; } if (IntroTimer >= 60000) { isActive = true; if (m_pInstance) m_pInstance->SetData(TYPE_LOKEN_INTRO, 1); me->SetControlled(false, UNIT_STATE_STUNNED); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); if (Player* target = SelectTargetFromPlayerList(80)) AttackStart(target); } return; } //Return since we have no target if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; switch (events.GetEvent()) { case EVENT_CHECK_HEALTH: if (HealthBelowPct(HealthCheck)) { LokenSpeach(true); HealthCheck -= 25; } events.RepeatEvent(1000); break; case EVENT_LIGHTNING_NOVA: events.RepeatEvent(15000); me->CastSpell(me, SPELL_LIGHTNING_NOVA_VISUAL, true); me->CastSpell(me, SPELL_LIGHTNING_NOVA_THUNDERS, true); events.DelayEvents(5001); events.ScheduleEvent(EVENT_AURA_REMOVE, me->GetMap()->IsHeroic() ? 4000 : 5000); me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_LIGHTNING_NOVA_H : SPELL_LIGHTNING_NOVA_N, false); break; case EVENT_SHOCKWAVE: me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_PULSING_SHOCKWAVE_H : SPELL_PULSING_SHOCKWAVE_N, false); events.PopEvent(); break; case EVENT_ARC_LIGHTNING: if (Unit* target = SelectTargetFromPlayerList(100, SPELL_ARC_LIGHTNING)) me->CastSpell(target, SPELL_ARC_LIGHTNING, false); events.RepeatEvent(12000); break; case EVENT_AURA_REMOVE: me->RemoveAura(SPELL_LIGHTNING_NOVA_THUNDERS); events.PopEvent(); break; } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { //Only if not incombat check if the event is started if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) { if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) AttackStart(target); } //Return since we have no target if (!UpdateVictim()) return; //someone evaded! if (!instance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; } //LeechingThrow_Timer if (LeechingThrow_Timer <= diff) { DoCastVictim(SPELL_LEECHING_THROW); LeechingThrow_Timer = 20000; } else LeechingThrow_Timer -= diff; //Multishot_Timer if (Multishot_Timer <= diff) { DoCastVictim(SPELL_MULTISHOT); Multishot_Timer = 20000; } else Multishot_Timer -= diff; //TheBeastWithin_Timer if (TheBeastWithin_Timer <= diff) { DoCast(me, SPELL_THE_BEAST_WITHIN); Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); if (Pet && Pet->IsAlive()) Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); TheBeastWithin_Timer = 30000; } else TheBeastWithin_Timer -= diff; //Pet_Timer if (Pet_Timer < diff && pet == false) { pet = true; //uint32 spell_id; uint32 pet_id; if (!urand(0, 1)) { //spell_id = SPELL_SUMMON_FATHOM_LURKER; pet_id = CREATURE_FATHOM_LURKER; } else { //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; pet_id = CREATURE_FATHOM_SPOREBAT; } //DoCast(me, spell_id, true); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { if (Creature* Pet = DoSpawnCreature(pet_id, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000)) { Pet->AI()->AttackStart(target); SummonedPet = Pet->GetGUID(); } } } else Pet_Timer -= diff; DoMeleeAttackIfReady(); }
void WorldBossAI::_EnterCombat() { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true); if (target) AttackStart(target); }
void UpdateAI(uint32 diff) override { //Only if not incombat check if the event is started if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) { if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) AttackStart(target); } //Return since we have no target if (!UpdateVictim()) return; //someone evaded! if (!instance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; } if (!me->HasAura(SPELL_WINDFURY_WEAPON)) { DoCast(me, SPELL_WINDFURY_WEAPON); } //FrostShock_Timer if (FrostShock_Timer <= diff) { DoCastVictim(SPELL_FROST_SHOCK); FrostShock_Timer = 25000 + rand32() % 5000; } else FrostShock_Timer -= diff; //Spitfire_Timer if (Spitfire_Timer <= diff) { DoCast(me, SPELL_SPITFIRE_TOTEM); if (Unit* SpitfireTotem = me->FindNearestCreature(CREATURE_SPITFIRE_TOTEM, 100.0f)) SpitfireTotem->ToCreature()->AI()->AttackStart(me->GetVictim()); Spitfire_Timer = 60000; } else Spitfire_Timer -= diff; //PoisonCleansing_Timer if (PoisonCleansing_Timer <= diff) { DoCast(me, SPELL_POISON_CLEANSING_TOTEM); PoisonCleansing_Timer = 30000; } else PoisonCleansing_Timer -= diff; //Earthbind_Timer if (Earthbind_Timer <= diff) { DoCast(me, SPELL_EARTHBIND_TOTEM); Earthbind_Timer = 45000; } else Earthbind_Timer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 /*diff*/) { if (!me->getVictim()) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) AttackStart(target); }
void UpdateAI(uint32 diff) override { //Only if not incombat check if the event is started if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) { if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) AttackStart(target); } //Return since we have no target if (!UpdateVictim()) return; //someone evaded! if (!instance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; } //WaterBoltVolley_Timer if (WaterBoltVolley_Timer <= diff) { DoCastVictim(SPELL_WATER_BOLT_VOLLEY); WaterBoltVolley_Timer = 30000; } else WaterBoltVolley_Timer -= diff; //TidalSurge_Timer if (TidalSurge_Timer <= diff) { DoCastVictim(SPELL_TIDAL_SURGE); // Hacky way to do it - won't trigger elseways if (me->GetVictim()) me->EnsureVictim()->CastSpell(me->GetVictim(), SPELL_TIDAL_SURGE_FREEZE, true); TidalSurge_Timer = 15000 + rand32() % 5000; } else TidalSurge_Timer -= diff; //Cyclone_Timer if (Cyclone_Timer <= diff) { //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work Cyclone_Timer = 30000 + rand32() % 10000; if (Creature* Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand32() % 5), TEMPSUMMON_TIMED_DESPAWN, 15000)) { Cyclone->SetObjectScale(3.0f); Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Cyclone->setFaction(me->getFaction()); Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) Cyclone->AI()->AttackStart(target); } } else Cyclone_Timer -= diff; //Heal_Timer if (Heal_Timer <= diff) { // It can be cast on any of the mobs Unit* unit = NULL; while (unit == NULL || !unit->IsAlive()) unit = selectAdvisorUnit(); if (unit && unit->IsAlive()) DoCast(unit, SPELL_HEAL); Heal_Timer = 60000; } else Heal_Timer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; switch (m_uiPhase) { case PHASE_FAKE_DEATH: if (m_uiResurrectTimer < uiDiff) { // resurrect him in any case DoCastSpellIfCan(m_creature, SPELL_RESURRECT); m_uiPhase = PHASE_WAITING; if (m_pInstance) { CanPreventAddsResurrect(); m_pInstance->SetData(TYPE_THEKAL, IN_PROGRESS); } } else m_uiResurrectTimer -= uiDiff; // No break needed here case PHASE_WAITING: return; case PHASE_NORMAL: if (m_uiMortalCleaveTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_CLEAVE) == CAST_OK) m_uiMortalCleaveTimer = urand(15000, 20000); } else m_uiMortalCleaveTimer -= uiDiff; if (m_uiSilenceTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_SILENCE) == CAST_OK) m_uiSilenceTimer = urand(20000, 25000); } } else m_uiSilenceTimer -= uiDiff; break; case PHASE_TIGER: if (m_uiChargeTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_CHARGE) == CAST_OK) { DoResetThreat(); AttackStart(pTarget); m_uiChargeTimer = urand(15000, 22000); } } } else m_uiChargeTimer -= uiDiff; if (m_uiFrenzyTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK) m_uiFrenzyTimer = 30000; } else m_uiFrenzyTimer -= uiDiff; if (m_uiForcePunchTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_FORCE_PUNCH) == CAST_OK) m_uiForcePunchTimer = urand(16000, 21000); } else m_uiForcePunchTimer -= uiDiff; if (m_uiSummonTigersTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_TIGERS) == CAST_OK) m_uiSummonTigersTimer = 50000; } else m_uiSummonTigersTimer -= uiDiff; if (!m_bEnraged && m_creature->GetHealthPercent() < 11.0f) { if (DoCastSpellIfCan(m_creature, SPELL_ENRAGE) == CAST_OK) m_bEnraged = true; } break; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { //Only if not incombat check if the event is started if (!me->isInCombat() && instance && instance->GetData(DATA_MAULGAREVENT)) { Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_MAULGAREVENT_TANK)); if (target) { AttackStart(target); GetCouncil(); } } //Return since we have no target if (!UpdateVictim()) return; //someone evaded! if (instance && !instance->GetData(DATA_MAULGAREVENT)) { EnterEvadeMode(); return; } //ArcingSmash_Timer if (ArcingSmash_Timer <= diff) { DoCast(me->getVictim(), SPELL_ARCING_SMASH); ArcingSmash_Timer = 10000; } else ArcingSmash_Timer -= diff; //Whirlwind_Timer if (Whirlwind_Timer <= diff) { DoCast(me->getVictim(), SPELL_WHIRLWIND); Whirlwind_Timer = 55000; } else Whirlwind_Timer -= diff; //MightyBlow_Timer if (MightyBlow_Timer <= diff) { DoCast(me->getVictim(), SPELL_MIGHTY_BLOW); MightyBlow_Timer = 30000+rand()%10000; } else MightyBlow_Timer -= diff; //Entering Phase 2 if (!Phase2 && HealthBelowPct(50)) { Phase2 = true; Talk(SAY_ENRAGE); DoCast(me, SPELL_DUAL_WIELD, true); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); } if (Phase2) { //Charging_Timer if (Charging_Timer <= diff) { Unit* target = NULL; target = SelectTarget(SELECT_TARGET_RANDOM, 0); if (target) { AttackStart(target); DoCast(target, SPELL_BERSERKER_C); } Charging_Timer = 20000; } else Charging_Timer -= diff; //Intimidating Roar if (Roar_Timer <= diff) { DoCast(me, SPELL_ROAR); Roar_Timer = 40000+(rand()%10000); } else Roar_Timer -= diff; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if (me->getVictim() && me->isAlive()) { if (PoisonVolley_Timer <= diff) { DoCast(me->getVictim(), SPELL_POISONVOLLEY); PoisonVolley_Timer = urand(10000, 20000); } else PoisonVolley_Timer -= diff; if (!PhaseTwo && Aspect_Timer <= diff) { DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); Aspect_Timer = urand(13000, 18000); } else Aspect_Timer -= diff; if (!Spawned && SpawnStartSpiders_Timer <= diff) { Talk(SAY_SPIDER_SPAWN); Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); if (!target) return; Creature* Spider = NULL; Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (Spider) Spider->AI()->AttackStart(target); Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (Spider) Spider->AI()->AttackStart(target); Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (Spider) Spider->AI()->AttackStart(target); Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (Spider) Spider->AI()->AttackStart(target); Spawned = true; } else SpawnStartSpiders_Timer -= diff; if (SpawnSpider_Timer <= diff) { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); if (!target) return; Creature* Spider = me->SummonCreature(15041, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (Spider) Spider->AI()->AttackStart(target); SpawnSpider_Timer = urand(12000, 17000); } else SpawnSpider_Timer -= diff; if (!PhaseTwo && Transform_Timer <= diff) { Talk(SAY_TRANSFORM); DoCast(me, SPELL_SPIDER_FORM); const CreatureTemplate* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); me->UpdateDamagePhysical(BASE_ATTACK); DoCast(me->getVictim(), SPELL_ENVOLWINGWEB); if (DoGetThreat(me->getVictim())) DoModifyThreatPercent(me->getVictim(), -100); PhaseTwo = true; Transform_Timer = urand(35000, 60000); } else Transform_Timer -= diff; if (PhaseTwo) { if (Charge_Timer <= diff) { Unit* target = NULL; int i = 0; while (i < 3) // max 3 tries to get a random target with power_mana { ++i; target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); // not aggro leader if (target && target->getPowerType() == POWER_MANA) i = 3; } if (target) { DoCast(target, SPELL_CHARGE); //me->SetPosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); //me->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true, 1); AttackStart(target); } Charge_Timer = 8000; } else Charge_Timer -= diff; if (TransformBack_Timer <= diff) { me->SetDisplayId(15220); const CreatureTemplate* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1))); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1))); me->UpdateDamagePhysical(BASE_ATTACK); PhaseTwo = false; TransformBack_Timer = urand(25000, 40000); } else TransformBack_Timer -= diff; } DoMeleeAttackIfReady(); } }
void UpdateAI(const uint32 diff) { //Only if not incombat check if the event is started if (!me->isInCombat() && instance && instance->GetData(DATA_MAULGAREVENT)) { Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_MAULGAREVENT_TANK)); if (target) { AttackStart(target); } } //Return since we have no target if (!UpdateVictim()) return; //someone evaded! if (instance && !instance->GetData(DATA_MAULGAREVENT)) { EnterEvadeMode(); return; } //GreaterFireball_Timer if (GreaterFireball_Timer < diff || me->IsWithinDist(me->getVictim(), 30)) { DoCast(me->getVictim(), SPELL_GREATER_FIREBALL); GreaterFireball_Timer = 2000; } else GreaterFireball_Timer -= diff; //SpellShield_Timer if (SpellShield_Timer <= diff) { me->InterruptNonMeleeSpells(false); DoCast(me->getVictim(), SPELL_SPELLSHIELD); SpellShield_Timer = 30000; } else SpellShield_Timer -= diff; //BlastWave_Timer if (BlastWave_Timer <= diff) { Unit* target = NULL; std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); std::vector<Unit*> target_list; for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { target = Unit::GetUnit(*me, (*itr)->getUnitGuid()); //15 yard radius minimum if (target && target->IsWithinDist(me, 15, false)) target_list.push_back(target); target = NULL; } if (!target_list.empty()) target = *(target_list.begin()+rand()%target_list.size()); me->InterruptNonMeleeSpells(false); DoCast(target, SPELL_BLAST_WAVE); BlastWave_Timer = 60000; } else BlastWave_Timer -= diff; }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; //Invisible_Timer if (Invisible_Timer <= diff) { me->InterruptSpell(CURRENT_GENERIC_SPELL); SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); me->SetDisplayId(11686); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Invisible = true; Invisible_Timer = 15000 + rand()%15000; } else Invisible_Timer -= diff; if (Invisible) { if (Ambush_Timer <= diff) { Unit *pTarget = NULL; pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); if (pTarget) { DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); DoCast(pTarget, SPELL_AMBUSH); } Ambushed = true; Ambush_Timer = 3000; } else Ambush_Timer -= diff; } if (Ambushed) { if (Visible_Timer <= diff) { me->InterruptSpell(CURRENT_GENERIC_SPELL); me->SetDisplayId(15268); SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Invisible = false; Visible_Timer = 4000; } else Visible_Timer -= diff; } //Resetting some aggro so he attacks other gamers if (!Invisible) if (Aggro_Timer <= diff) { Unit *pTarget = NULL; pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); if (DoGetThreat(me->getVictim())) DoModifyThreatPercent(me->getVictim(),-50); if (pTarget) AttackStart(pTarget); Aggro_Timer = 7000 + rand()%13000; } else Aggro_Timer -= diff; if (!Invisible) if (ThousandBlades_Timer <= diff) { DoCast(me->getVictim(), SPELL_THOUSANDBLADES); ThousandBlades_Timer = 7000 + rand()%5000; } else ThousandBlades_Timer -= diff; DoMeleeAttackIfReady(); }
void PetAI::UpdateAI(const uint32 diff) { m_owner = me->GetCharmerOrOwner(); // quest support - Razorthorn Ravager, switch to CreatureAI when charmed and not in combat if (me->GetEntry() == 24922 && me->isCharmed() && !me->isInCombat()) me->NeedChangeAI = true; updateAlliesTimer.Update(diff); if (updateAlliesTimer.Passed()) UpdateAllies(); if (m_forceTimer) { if (m_forceTimer < diff) m_forceTimer = 0; else m_forceTimer -= diff; } if (me->getVictim()) { if (_needToStop()) { _stopAttack(); return; } DoMeleeAttackIfReady(); } else { if (me->isInCombat()) { if (!me->GetOwner() || !me->GetOwner()->GetObjectGuid().IsPlayer()) _stopAttack(); } else if (Unit* owner = me->GetOwner()) { if (!me->HasReactState(REACT_PASSIVE) && !me->GetCharmInfo()->HasCommandState(COMMAND_STAY)) { Unit* target = NULL; if (owner->isInCombat()) target = owner->getAttackerForHelper(); else target = me->getAttackerForHelper(); if (target) AttackStart(target); } // we still do NOT have target, if follow command were appliend and we are NOT followin, reapply movegen :P if (!me->getVictim() && me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) && !me->hasUnitState(UNIT_STAT_FOLLOW)) me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); } } if (!me->GetCharmInfo()) return; if (!me->hasUnitState(UNIT_STAT_CASTING)) { //Autocast for (uint8 i = 0; i < me->GetPetAutoSpellSize(); i++) PrepareSpellForAutocast(me->GetPetAutoSpellOnPos(i)); AutocastPreparedSpells(); } }