Unit* ScriptedAI::SelectCastTarget(uint32 spellId, castTargetMode targetMode) { switch (targetMode) { case CAST_TANK: return me->getVictim(); case CAST_NULL: return NULL; case CAST_RANDOM: case CAST_RANDOM_WITHOUT_TANK: { SpellEntry const* pSpell = GetSpellStore()->LookupEntry(spellId); return SelectUnit(SELECT_TARGET_RANDOM, 0, GetSpellMaxRange(spellId), pSpell->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY, targetMode == CAST_RANDOM_WITHOUT_TANK ? me->getVictimGUID() : 0); } case CAST_SELF: return me; case CAST_LOWEST_HP_FRIENDLY: { SpellEntry const* pSpell = GetSpellStore()->LookupEntry(spellId); return SelectLowestHpFriendly(GetSpellMaxRange(spellId)); } case CAST_THREAT_SECOND: { SpellEntry const* pSpell = GetSpellStore()->LookupEntry(spellId); return SelectUnit(SELECT_TARGET_TOPAGGRO, 1, GetSpellMaxRange(spellId), pSpell->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY); } default: return NULL; }; }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (i_totem.GetTotemType() != TOTEM_ACTIVE) return; if (!i_totem.isAlive() || i_totem.IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_totem.GetSpell()); if (!spellInfo) return; // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); float max_range = GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // pointer to appropriate target if found any Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(i_totem, i_victimGuid) : NULL; // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || !victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) || i_totem.IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(&i_totem,false)) { CellPair p(BlizzLike::ComputeCellPair(i_totem.GetPositionX(),i_totem.GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; victim = NULL; BlizzLike::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range); BlizzLike::UnitLastSearcher<BlizzLike::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); TypeContainerVisitor<BlizzLike::UnitLastSearcher<BlizzLike::NearestAttackableUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); TypeContainerVisitor<BlizzLike::UnitLastSearcher<BlizzLike::NearestAttackableUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); //TODO: Backport BLizzLike Add to CreatureAI field pointing to creature itself //cell.Visit(p, grid_object_checker, *m_creature.GetMap(), *m_creature, max_range); //cell.Visit(p, world_object_checker, *m_creature.GetMap(), *m_creature, max_range); cell.Visit(p, grid_object_checker, *i_totem.GetMap()); cell.Visit(p, world_object_checker, *i_totem.GetMap()); } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack i_totem.SetInFront(victim); // client change orientation by self i_totem.CastSpell(victim, i_totem.GetSpell(), false); } else i_victimGuid = 0; }
TurretAI::TurretAI(Creature *c) : CreatureAI(c) { ASSERT(me->m_spells[0]); m_minRange = GetSpellMinRange(me->m_spells[0], false); me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false); me->m_SightDistance = me->m_CombatDistance; }
void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target) { GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(trapEntry); if(!trapInfo || trapInfo->type!=GAMEOBJECT_TYPE_TRAP) return; SpellEntry const* trapSpell = sSpellStore.LookupEntry(trapInfo->trap.spellId); if(!trapSpell) // checked at load already return; float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(trapSpell->rangeIndex)); // search nearest linked GO GameObject* trapGO = NULL; { // using original GO distance CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*target,trapEntry,range); MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> checker(trapGO,go_check); TypeContainerVisitor<MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, object_checker, *GetMap()); } // found correct GO // FIXME: when GO casting will be implemented trap must cast spell to target if(trapGO) target->CastSpell(target,trapSpell,true); }
ArchorAI::ArchorAI(Creature *c) : CreatureAI(c) { ASSERT(me->m_spells[0]); m_minRange = GetSpellMinRange(me->m_spells[0], false); if (!m_minRange) m_minRange = MELEE_RANGE; me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false); me->m_SightDistance = me->m_CombatDistance; }
TurretAI::TurretAI(Creature *c) : CreatureAI(c) { if (!me->m_spells[0]) sLog.outError("TurretAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry()); m_minRange = GetSpellMinRange(me->m_spells[0], false); me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false); me->m_SightDistance = me->m_CombatDistance; }
ArchorAI::ArchorAI(Creature *c) : CreatureAI(c) { if (!me->m_spells[0]) sLog->outError("ArchorAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry()); m_minRange = GetSpellMinRange(me->m_spells[0], false); if (!m_minRange) m_minRange = MELEE_RANGE; me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false); me->m_SightDistance = me->m_CombatDistance; }
ArcherAI::ArcherAI(Creature* c) : CreatureAI(c) { SpellEntry const* spellInfo = sSpellStore.LookupEntry(me->m_spells[0]); m_minRange = spellInfo ? GetSpellMinRange(spellInfo) : 0; if (!m_minRange) m_minRange = MELEE_RANGE; me->SetCombatDistance(spellInfo ? GetSpellMaxRange(spellInfo) : 0); me->m_SightDistance = me->GetCombatDistance(); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; //IceArmor_Timer if (IceArmor_Timer < diff) { DoCast(m_creature, SPELL_ICEARMOR); IceArmor_Timer = 180000; }else IceArmor_Timer -= diff; //Frostbolt_Timer if (Frostbolt_Timer < diff) { Unit* target = NULL; target = SelectUnit(SELECT_TARGET_RANDOM,0, GetSpellMaxRange(SPELL_FROSTBOLT), true); if (target) DoCast(target,SPELL_FROSTBOLT); Frostbolt_Timer = 8000; }else Frostbolt_Timer -= diff; //Freeze_Timer if (Freeze_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_FREEZE); Freeze_Timer = 24000; }else Freeze_Timer -= diff; //Fear_Timer if (Fear_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_FEAR); Fear_Timer = 30000; }else Fear_Timer -= diff; //ChillNova_Timer if (ChillNova_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_CHILLNOVA); ChillNova_Timer = 14000; }else ChillNova_Timer -= diff; //FrostVolley_Timer if (FrostVolley_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_FROSTVOLLEY); FrostVolley_Timer = 15000; }else FrostVolley_Timer -= diff; DoMeleeAttackIfReady(); }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (getTotem().GetTotemType() != TOTEM_ACTIVE) return; if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(getTotem().GetSpell()); if (!spellInfo) return; SpellMiscEntry const* spellMisc = sSpellMiscStore.LookupEntry(spellInfo->Id); // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellMisc->rangeIndex); float max_range = GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because nonexistent range mods for attacking totems // pointer to appropriate target if found any Unit* victim = m_creature->GetMap()->GetUnit(i_victimGuid); // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if( !victim || !victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) || m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,m_creature,false) ) { victim = NULL; Strawberry::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range); Strawberry::UnitLastSearcher<Strawberry::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); Cell::VisitAllObjects(m_creature, checker, max_range); } // If have target if (victim) { // remember i_victimGuid = victim->GetObjectGuid(); // attack m_creature->SetInFront(victim); // client change orientation by self m_creature->CastSpell(victim, getTotem().GetSpell(), false); } else i_victimGuid.Clear(); }
void UpdateAI(const uint32 diff) { if(!UpdateVictim()) return; if( BerserkerCharge_Timer < diff ) { Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,GetSpellMaxRange(SPELL_BERSERKER_CHARGE), true); if( target ) DoCast(target,SPELL_BERSERKER_CHARGE); BerserkerCharge_Timer = 25000; }else BerserkerCharge_Timer -= diff; if( Uppercut_Timer < diff ) { DoCast(m_creature->getVictim(),SPELL_UPPERCUT); Uppercut_Timer = 20000; }else Uppercut_Timer -= diff; if( Thunderclap_Timer < diff ) { DoCast(m_creature->getVictim(),SPELL_THUNDERCLAP); Thunderclap_Timer = 15000; }else Thunderclap_Timer -= diff; if( MortalStrike_Timer < diff ) { DoCast(m_creature->getVictim(),SPELL_MORTAL_STRIKE); MortalStrike_Timer = 15000; }else MortalStrike_Timer -= diff; if( Cleave_Timer < diff ) { DoCast(m_creature->getVictim(),SPELL_CLEAVE); Cleave_Timer = 7000; }else Cleave_Timer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI (const uint32 diff) { if (!UpdateVictim()) return; //Bomb_Timer if (Bomb_Timer < diff) { if (Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0, GetSpellMaxRange(SPELL_BOMB), true)) { DoCast(target, SPELL_BOMB); Bomb_Timer = 5000; } } else Bomb_Timer -= diff; //Check_Timer if (Check_Timer < diff) { if (pInstance) { if (pInstance->GetData(DATA_JEKLIKEVENT) == DONE) { m_creature->setDeathState(JUST_DIED); m_creature->RemoveCorpse(); } } Check_Timer = 1000; } else Check_Timer -= diff; DoMeleeAttackIfReady(); }
void PetAI::Reset() { m_primaryTargetGuid.Clear(); m_savedTargetGuid.Clear(); m_attackDistanceRecheckTimer.SetInterval(TIME_INTERVAL_LOOK); m_attackDistanceRecheckTimer.Reset(); m_updateAlliesTimer.SetInterval(ALLIES_UPDATE_TIME); m_updateAlliesTimer.Reset(); UpdateAllies(); for (uint8 i = PET_SPELL_PASSIVE; i < PET_SPELL_MAX; ++i) m_spellType[i].clear(); m_AIType = PET_AI_PASSIVE; m_attackDistance = 0.0f; float f_range = 0.0f; if (!m_creature->GetCharmInfo()) return; uint32 spellsSize = m_creature->IsPet() ? ((Pet*)m_creature)->GetPetAutoSpellSize() : m_creature->GetPetAutoSpellSize(); uint8 rangedDamageSpells = 0; uint8 meleeDamageSpells = 0; // classification for pet spells for (uint32 i = 0; i < spellsSize; ++i) { uint32 spellID = m_creature->IsPet() ? ((Pet*)m_creature)->GetPetAutoSpellOnPos(i) : m_creature->GetPetAutoSpellOnPos(i); if (!spellID) continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID); if (!spellInfo) continue; if (IsPassiveSpell(spellInfo)) { m_spellType[PET_SPELL_PASSIVE].insert(spellID); continue; } if (IsNonCombatSpell(spellInfo)) { // Voidwalker Consume Shadows if (IsChanneledSpell(spellInfo)) m_spellType[PET_SPELL_HEAL].insert(spellID); else m_spellType[PET_SPELL_NONCOMBAT].insert(spellID); continue; } // need more correct define this type if (IsSpellReduceThreat(spellInfo) || IsChanneledSpell(spellInfo)) { m_spellType[PET_SPELL_DEFENCE].insert(spellID); continue; } // Voracious Appetite && Cannibalize && Carrion Feeder if (spellInfo->HasAttribute(SPELL_ATTR_ABILITY) && spellInfo->HasAttribute(SPELL_ATTR_EX2_ALLOW_DEAD_TARGET)) { m_spellType[PET_SPELL_HEAL].insert(spellID); continue; } if (IsPositiveSpell(spellInfo) && IsSpellAppliesAura(spellInfo)) { m_spellType[PET_SPELL_BUFF].insert(spellID); continue; } if (spellInfo->HasAttribute(SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)) { m_spellType[PET_SPELL_FREEACTION].insert(spellID); continue; } // don't have SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY ! if (spellInfo->HasAttribute(SPELL_ATTR_EX_CANT_REFLECTED) || spellInfo->HasAttribute(SPELL_ATTR_EX7_HAS_CHARGE_EFFECT)) { m_spellType[PET_SPELL_ATTACKSTART].insert(spellID); continue; } if (IsSpellIncreaseThreat(spellInfo)) { m_spellType[PET_SPELL_THREAT].insert(spellID); continue; } // all non-combat spells classified. switch (spellInfo->rangeIndex) { case SPELL_RANGE_IDX_COMBAT: { if (IsSpellCauseDamage(spellInfo)) { m_spellType[PET_SPELL_MELEE].insert(spellID); ++meleeDamageSpells; } else { m_spellType[PET_SPELL_SPECIAL].insert(spellID); } break; } // possible debuffs or auras? case SPELL_RANGE_IDX_SELF_ONLY: case SPELL_RANGE_IDX_ANYWHERE: { m_spellType[PET_SPELL_SPECIAL].insert(spellID); break; } default: { float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellInfo->rangeIndex), false); if (f_range < M_NULL_F || (range > M_NULL_F && range < f_range)) f_range = range; if (IsSpellCauseDamage(spellInfo)) { m_spellType[PET_SPELL_RANGED].insert(spellID); ++rangedDamageSpells; } else { m_spellType[PET_SPELL_SPECIAL].insert(spellID); } break; } } } // define initial AI type if (m_creature->IsVehicle()) m_AIType = PET_AI_PASSIVE; if (m_spellType[PET_SPELL_RANGED].size() > 0 && (m_spellType[PET_SPELL_MELEE].size() < m_spellType[PET_SPELL_RANGED].size())) { m_AIType = PET_AI_RANGED; m_attackDistance = f_range - m_creature->GetObjectBoundingRadius() - 2.0f; if (m_attackDistance < 20.0f) m_attackDistance = 18.0f; } else { m_AIType = PET_AI_MELEE; m_attackDistance = 0.0f; } m_savedAIType = m_AIType; m_creature->GetMotionMaster()->MoveTargetedHome(); DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS,"PetAI::Reset %s, AI %u dist %f, spells: "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD" "SIZEFMTD , m_creature->GetObjectGuid().GetString().c_str(), m_AIType, m_attackDistance, m_spellType[PET_SPELL_PASSIVE].size(), m_spellType[PET_SPELL_NONCOMBAT].size(), m_spellType[PET_SPELL_BUFF].size(), m_spellType[PET_SPELL_DEBUFF].size(), m_spellType[PET_SPELL_FREEACTION].size(), m_spellType[PET_SPELL_ATTACKSTART].size(), m_spellType[PET_SPELL_THREAT].size(), m_spellType[PET_SPELL_MELEE].size(), m_spellType[PET_SPELL_RANGED].size(), m_spellType[PET_SPELL_DEFENCE].size(), m_spellType[PET_SPELL_SPECIAL].size(), m_spellType[PET_SPELL_HEAL].size() ); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim() ) return; if(CheckTimer < diff) { if(!m_creature->IsWithinDistInMap(&wLoc, 30.0f)) EnterEvadeMode(); else DoZoneInCombat(); CheckTimer = 3000; } else CheckTimer -= diff; if(Enrage_Timer < diff && !Enraged) { DoCast(m_creature, SPELL_BERSERK,true); Enraged = true; } else Enrage_Timer -=diff; if(Holyground_Timer < diff) { DoCast(m_creature, SPELL_HOLYGROUND, true); //Triggered so it doesn't interrupt her at all Holyground_Timer = 3000; } else Holyground_Timer -= diff; if (Repentance_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_REPENTANCE); DoScriptText(RAND(SAY_REPENTANCE1, SAY_REPENTANCE2), m_creature); Repentance_Timer = 30000 + rand()%15000; //A little randomness on that spell Holyfire_Timer += 6000; } else Repentance_Timer -= diff; if(Holyfire_Timer < diff) { if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,GetSpellMaxRange(SPELL_HOLYFIRE), true)) DoCast(target,SPELL_HOLYFIRE); Holyfire_Timer = 8000 + rand()%17000; //Anywhere from 8 to 25 seconds, good luck having several of those in a row! } else Holyfire_Timer -= diff; if(Holywrath_Timer < diff) { if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,GetSpellMaxRange(SPELL_HOLYWRATH), true)) DoCast(target,SPELL_HOLYWRATH); Holywrath_Timer = 20000+(rand()%10000); //20-30 secs sounds nice } else Holywrath_Timer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; //BrainWashTotem_Timer if (BrainWashTotem_Timer < diff) { DoCast(m_creature, SPELL_BRAINWASHTOTEM); BrainWashTotem_Timer = 18000 + rand()%8000; } else BrainWashTotem_Timer -= diff; //HealingWard_Timer if (HealingWard_Timer < diff) { DoCast(m_creature, SPELL_POWERFULLHEALINGWARD); HealingWard_Timer = 14000 + rand()%6000; } else HealingWard_Timer -= diff; //Hex_Timer if (Hex_Timer < diff) { DoCast(m_creature->getVictim(), SPELL_HEX); if(DoGetThreat(m_creature->getVictim())) DoModifyThreatPercent(m_creature->getVictim(),-80); Hex_Timer = 12000 + rand()%8000; } else Hex_Timer -= diff; //Casting the delusion curse with a shade. So shade will attack the same target with the curse. if(Delusions_Timer < diff) { if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0, GetSpellMaxRange(SPELL_DELUSIONSOFJINDO), true)) { DoCast(target, SPELL_DELUSIONSOFJINDO); Shade = m_creature->SummonCreature(14986, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Shade) Shade->AI()->AttackStart(target); } Delusions_Timer = 4000 + rand()%8000; } else Delusions_Timer -= diff; //Teleporting a random gamer and spawning 9 skeletons that will attack this gamer if(Teleport_Timer < diff) { if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0, 200, true)) { DoTeleportPlayer(target, -11583.7783,-1249.4278,77.5471,4.745); if(DoGetThreat(m_creature->getVictim())) DoModifyThreatPercent(target,-100); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()-2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()-4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()+2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()-2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()+4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()-4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+3, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Skeletons) Skeletons->AI()->AttackStart(target); } Teleport_Timer = 15000 + rand()%8000; } else Teleport_Timer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if(!UpdateVictim()) return; if (checkTimer2 < diff) { if (!m_creature->IsWithinDistInMap(&wLoc, 50)) EnterEvadeMode(); else DoZoneInCombat(); checkTimer2 = 3000; } else checkTimer2 -= diff; if(BerserkTimer < diff) { AddSpellToCastWithScriptText(m_creature, SPELL_BERSERK, YELL_BERSERK); BerserkTimer = 60000; }else BerserkTimer -= diff; if(Phase == PHASE_LYNX || Phase == PHASE_ENRAGE) { if(SaberlashTimer < diff) { AddSpellToCastWithScriptText(m_creature->getVictim(), SPELL_SABER_LASH, RAND(YELL_SABER_ONE, YELL_SABER_TWO)); SaberlashTimer = 5000 + rand() % 10000; }else SaberlashTimer -= diff; if(FrenzyTimer < diff) { AddSpellToCast(m_creature, SPELL_FRENZY); FrenzyTimer = (10+rand()%5)*1000; }else FrenzyTimer -= diff; if(Phase == PHASE_LYNX) if(CheckTimer < diff) { if(m_creature->GetHealth() * 4 < m_creature->GetMaxHealth() * (3 - TransformCount)) EnterPhase(PHASE_SPLIT); CheckTimer = 1000; }else CheckTimer -= diff; } if(Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE) { if(TotemTimer < diff) { AddSpellToCast(m_creature, SPELL_SUMMON_TOTEM); TotemTimer = 20000; }else TotemTimer -= diff; if(ShockTimer < diff) { if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,GetSpellMaxRange(SPELL_EARTHSHOCK), true)) { if(target->IsNonMeleeSpellCasted(false)) AddSpellToCast(target,SPELL_EARTHSHOCK); else AddSpellToCast(target,SPELL_FLAMESHOCK); ShockTimer = 10000 + rand()%5000; } }else ShockTimer -= diff; if(Phase == PHASE_HUMAN) if(CheckTimer < diff) { if( ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() <= 20)/*m_creature->GetHealth() * 10 < m_creature->GetMaxHealth()*/) EnterPhase(PHASE_MERGE); else { Unit *Lynx = Unit::GetUnit(*m_creature, LynxGUID); if(Lynx && ((Lynx->GetHealth()*100) / Lynx->GetMaxHealth() <= 20)/*Lynx->GetHealth() * 10 < Lynx->GetMaxHealth()*/) EnterPhase(PHASE_MERGE); } CheckTimer = 1000; }else CheckTimer -= diff; } if(Phase == PHASE_MERGE) { if(CheckTimer < diff) { Unit *Lynx = Unit::GetUnit(*m_creature, LynxGUID); if(Lynx) { Lynx->GetMotionMaster()->MoveFollow(m_creature, 0, 0); m_creature->GetMotionMaster()->MoveFollow(Lynx, 0, 0); if(m_creature->IsWithinDistInMap(Lynx, 6.0f)) { if(TransformCount < 3) EnterPhase(PHASE_LYNX); else EnterPhase(PHASE_ENRAGE); } } CheckTimer = 1000; }else CheckTimer -= diff; } CastNextSpellIfAnyAndReady(); DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if(!UpdateVictim()) return; if(m_creature->getVictim() && m_creature->isAlive()) { if(PoisonVolley_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_POISONVOLLEY); PoisonVolley_Timer = 10000 + rand()%10000; } else PoisonVolley_Timer -= diff; if(!PhaseTwo && Aspect_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_ASPECT_OF_MARLI); Aspect_Timer = 13000 + rand()%5000; } else Aspect_Timer -= diff; if(!Spawned && SpawnStartSpiders_Timer < diff) { DoScriptText(SAY_SPIDER_SPAWN, m_creature); Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0); if(!target) return; Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Spider) Spider->AI()->AttackStart(target); Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Spider) Spider->AI()->AttackStart(target); Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Spider) Spider->AI()->AttackStart(target); Spider = m_creature->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 = SelectUnit(SELECT_TARGET_RANDOM,0); if(!target) return; Spider = m_creature->SummonCreature(15041,target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if(Spider) Spider->AI()->AttackStart(target); SpawnSpider_Timer = 12000 + rand()%5000; } else SpawnSpider_Timer -= diff; if(!PhaseTwo && Transform_Timer < diff) { DoScriptText(SAY_TRANSFORM, m_creature); DoCast(m_creature,SPELL_SPIDER_FORM); const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); m_creature->UpdateDamagePhysical(BASE_ATTACK); DoCast(m_creature->getVictim(),SPELL_ENVOLWINGWEB); if(DoGetThreat(m_creature->getVictim())) DoModifyThreatPercent(m_creature->getVictim(),-100); PhaseTwo = true; Transform_Timer = 35000 + rand()%25000; } 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; //not aggro leader target = SelectUnit(SELECT_TARGET_RANDOM,1, GetSpellMaxRange(SPELL_CHARGE), true, m_creature->getVictimGUID()); if(target) if (target->getPowerType() == POWER_MANA) i=3; } if(target) { DoCast(target, SPELL_CHARGE); //m_creature->Relocate(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0); //m_creature->SendMonsterMove(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, true,1); AttackStart(target); } Charge_Timer = 8000; } else Charge_Timer -= diff; if(TransformBack_Timer < diff) { m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15220); const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1))); m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1))); m_creature->UpdateDamagePhysical(BASE_ATTACK); PhaseTwo = false; TransformBack_Timer = 25000 + rand()%15000; } else TransformBack_Timer -= diff; } DoMeleeAttackIfReady(); } }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if(Check_Timer < diff) { if(!m_creature->IsWithinDistInMap(&wLoc, 80.0f)) EnterEvadeMode(); Check_Timer = 2000; }else Check_Timer -= diff; //Spell Enrage, when hp <= 20% gain enrage if (((m_creature->GetHealth()*100)/ m_creature->GetMaxHealth()) <= 20) { if(Enrage_Timer < diff) { m_creature->RemoveAurasDueToSpell(SPELL_ENRAGE); DoCast(m_creature,SPELL_ENRAGE); Enrage_Timer = 600000; InEnrage = true; }else Enrage_Timer -= diff; } //Spell Overrun if (Overrun_Timer < diff) { DoScriptText(RAND(SAY_OVERRUN_1, SAY_OVERRUN_2), m_creature); DoCast(m_creature->getVictim(),SPELL_OVERRUN); DoResetThreat(); Overrun_Timer = 25000 + rand()%15000; }else Overrun_Timer -= diff; //Spell Earthquake if (Quake_Timer < diff) { if (rand()%2) return; DoScriptText(RAND(SAY_EARTHQUAKE_1, SAY_EARTHQUAKE_2), m_creature); //remove enrage before casting earthquake because enrage + earthquake = 16000dmg over 8sec and all dead if (InEnrage) m_creature->RemoveAura(SPELL_ENRAGE, 0); DoCast(m_creature,SPELL_EARTHQUAKE); Enrage_Timer = 8000; Quake_Timer = 30000 + rand()%25000; }else Quake_Timer -= diff; //Spell Chain Lightning if (Chain_Timer < diff) { Unit* target = NULL; target = SelectUnit(SELECT_TARGET_RANDOM,1, GetSpellMaxRange(SPELL_CHAIN_LIGHTNING), true, m_creature->getVictimGUID()); if (!target) target = m_creature->getVictim(); if (target) DoCast(target,SPELL_CHAIN_LIGHTNING); Chain_Timer = 10000 + rand()%25000; }else Chain_Timer -= diff; //Spell Sunder Armor if (Armor_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_SUNDER_ARMOR); Armor_Timer = 10000 + rand()%15000; }else Armor_Timer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if(isFlameBreathing) { if(!m_creature->IsNonMeleeSpellCasted(false)) { isFlameBreathing = false; }else { if(EnrageTimer > diff) EnrageTimer -= diff; else EnrageTimer = 0; if(HatcherTimer > diff) HatcherTimer -= diff; else HatcherTimer = 0; return; } } if(isBombing) { if(BombSequenceTimer < diff) { HandleBombSequence(); }else BombSequenceTimer -= diff; if(EnrageTimer > diff) EnrageTimer -= diff; else EnrageTimer = 0; if(HatcherTimer > diff) HatcherTimer -= diff; else HatcherTimer = 0; return; } if(!UpdateVictim()) return; if (checkTimer < diff) { if (!m_creature->IsWithinDistInMap(&wLoc, 25)) EnterEvadeMode(); else DoZoneInCombat(); checkTimer = 3000; } else checkTimer -= diff; //enrage if under 25% hp before 5 min. if(!enraged && m_creature->GetHealth() * 4 < m_creature->GetMaxHealth()) EnrageTimer = 0; if(EnrageTimer < diff) { if(!enraged) { m_creature->CastSpell(m_creature, SPELL_ENRAGE, true); enraged = true; EnrageTimer = 300000; } else { DoScriptText(SAY_BERSERK, m_creature); m_creature->CastSpell(m_creature, SPELL_BERSERK, true); EnrageTimer = 300000; } }else EnrageTimer -= diff; if(BombTimer < diff) { DoScriptText(SAY_FIRE_BOMBS, m_creature); m_creature->AttackStop(); m_creature->GetMotionMaster()->Clear(); DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); m_creature->StopMoving(); m_creature->CastSpell(m_creature, SPELL_FIRE_BOMB_CHANNEL, false); //DoTeleportPlayer(m_creature, JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2], 0); //m_creature->CastSpell(m_creature, SPELL_TELE_TO_CENTER, true); FireWall(); SpawnBombs(); isBombing = true; BombSequenceTimer = 100; //Teleport every Player into the middle Map *map = m_creature->GetMap(); if(!map->IsDungeon()) return; Map::PlayerList const &PlayerList = map->GetPlayers(); for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { if (Player* i_pl = i->getSource()) if(i_pl->isAlive()) DoTeleportPlayer(i_pl, JanalainPos[0][0]-5+rand()%10, JanalainPos[0][1]-5+rand()%10, JanalainPos[0][2], 0); } //m_creature->CastSpell(Temp, SPELL_SUMMON_PLAYERS, true); // core bug, spell does not work if too far return; }else BombTimer -= diff; if(!noeggs) { if(100 * m_creature->GetHealth() < 35 * m_creature->GetMaxHealth()) { DoScriptText(SAY_ALL_EGGS, m_creature); m_creature->AttackStop(); m_creature->GetMotionMaster()->Clear(); DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); m_creature->StopMoving(); m_creature->CastSpell(m_creature, SPELL_HATCH_ALL, false); HatchAllEggs(2); noeggs = true; } else if(HatcherTimer < diff) { if(HatchAllEggs(0)) { DoScriptText(SAY_SUMMON_HATCHER, m_creature); m_creature->SummonCreature(MOB_AMANI_HATCHER,hatcherway[0][0][0],hatcherway[0][0][1],hatcherway[0][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); m_creature->SummonCreature(MOB_AMANI_HATCHER,hatcherway[1][0][0],hatcherway[1][0][1],hatcherway[1][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); HatcherTimer = 90000; } else noeggs = true; }else HatcherTimer -= diff; } if(ResetTimer < diff) { float x, y, z, o; m_creature->GetHomePosition(x, y, z, o); if(m_creature->GetPositionZ() <= z-7) { EnterEvadeMode(); return; } ResetTimer = 5000; }else ResetTimer -= diff; DoMeleeAttackIfReady(); if(FireBreathTimer < diff) { if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0, GetSpellMaxRange(SPELL_FLAME_BREATH), true)) { me->SetSelection(target->GetGUID()); me->SetInFront(target); m_creature->CastSpell(target, SPELL_FLAME_BREATH, false); isFlameBreathing = true; } FireBreathTimer = 8000; }else FireBreathTimer -= diff; }
void TotemAI::UpdateAI(const uint32 diff) { // Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events if (m_EventUpdateTime < diff) { m_EventDiff += diff; // Check for time based events for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i) { // Decrement Timers if (i->Time) { // Do not decrement timers if event cannot trigger in this phase if (!(i->Event.event_inverse_phase_mask & (1 << m_Phase))) { if (i->Time > m_EventDiff) i->Time -= m_EventDiff; else i->Time = 0; } } // Skip processing of events that have time remaining or are disabled if (!(i->Enabled) || i->Time) continue; if (IsTimerBasedEvent(i->Event.event_type)) ProcessEvent(*i); } m_EventDiff = 0; m_EventUpdateTime = EVENT_UPDATE_TIME; } else { m_EventDiff += diff; m_EventUpdateTime -= diff; } if (getTotem().GetTotemType() != TOTEM_ACTIVE) return; if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(getTotem().GetSpell()); if (!spellInfo) return; // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); float maxRange = GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because nonexistent range mods for attacking totems // pointer to appropriate target if found any Unit* victim = m_creature->GetMap()->GetUnit(i_victimGuid); // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || !m_creature->CanAttack(victim) || !m_creature->IsWithinDistInMap(victim, maxRange) || m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature, m_creature, false)) { victim = nullptr; MaNGOS::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, maxRange); MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); Cell::VisitAllObjects(m_creature, checker, maxRange); } // If have target if (victim) { // remember i_victimGuid = victim->GetObjectGuid(); // attack m_creature->SetInFront(victim); // client change orientation by self m_creature->CastSpell(victim, getTotem().GetSpell(), TRIGGERED_NONE); } else i_victimGuid.Clear(); }
void UpdateAI(const uint32 diff) { if(waitTimer) { if(inMove) if(waitTimer < diff) { (*m_creature).GetMotionMaster()->MovementExpired(); (*m_creature).GetMotionMaster()->MovePoint(MovePhase,NalorakkWay[MovePhase][0],NalorakkWay[MovePhase][1],NalorakkWay[MovePhase][2]); waitTimer = 0; }else waitTimer -= diff; } if(!UpdateVictim()) return; if (checkTimer < diff) { if (!m_creature->IsWithinDistInMap(&wLoc, 75) && !MoveEvent) EnterEvadeMode(); else DoZoneInCombat(); m_creature->SetSpeed(MOVE_RUN,2); checkTimer = 3000; } else checkTimer -= diff; if(Berserk_Timer < diff) { AddSpellToCastWithScriptText(m_creature, SPELL_BERSERK, YELL_BERSERK, true); Berserk_Timer = 600000; }else Berserk_Timer -= diff; if(!inBearForm) { if(BrutalSwipe_Timer < diff) { AddSpellToCast(m_creature->getVictim(), SPELL_BRUTALSWIPE); BrutalSwipe_Timer = 7000 + rand()%5000; }else BrutalSwipe_Timer -= diff; if(Mangle_Timer < diff) { if(m_creature->getVictim() && !m_creature->getVictim()->HasAura(SPELL_MANGLEEFFECT, 0)) { AddSpellToCast(m_creature->getVictim(), SPELL_MANGLE); Mangle_Timer = 1000; } else Mangle_Timer = 10000 + rand()%5000; }else Mangle_Timer -= diff; if(Surge_Timer < diff) { if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 1, GetSpellMaxRange(SPELL_SURGE), true, m_creature->getVictimGUID())) AddSpellToCastWithScriptText(target, SPELL_SURGE, YELL_SURGE); Surge_Timer = 15000 + rand()%5000; }else Surge_Timer -= diff; if(ShapeShift_Timer) { if(ShapeShift_Timer <= diff) { AddSpellToCastWithScriptText(m_creature, SPELL_BEARFORM, YELL_SHIFTEDTOBEAR, true); ShapeShift_Timer = 0; }else ShapeShift_Timer -= diff; } } else { if(LaceratingSlash_Timer < diff) { AddSpellToCast(m_creature->getVictim(), SPELL_LACERATINGSLASH); LaceratingSlash_Timer = 18000 + rand()%5000; }else LaceratingSlash_Timer -= diff; if(RendFlesh_Timer < diff) { AddSpellToCast(m_creature->getVictim(), SPELL_RENDFLESH); RendFlesh_Timer = 5000 + rand()%5000; }else RendFlesh_Timer -= diff; if(DeafeningRoar_Timer < diff) { AddSpellToCast(m_creature->getVictim(), SPELL_DEAFENINGROAR); DeafeningRoar_Timer = 15000 + rand()%5000; }else DeafeningRoar_Timer -= diff; } CastNextSpellIfAnyAndReady(); DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if(!UpdateVictim() ) return; if(pInstance && !pInstance->GetData(DATA_MOROES_EVENT)) { EnterEvadeMode(); return; } if(!Enrage && m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30) { DoCast(m_creature, SPELL_FRENZY); Enrage = true; } if (CheckAdds_Timer < diff) { for (uint8 i = 0; i < 4; ++i) { Creature* Temp = NULL; if (AddGUID[i]) { Temp = Unit::GetCreature((*m_creature),AddGUID[i]); if (Temp && Temp->isAlive()) if (!Temp->getVictim() ) Temp->AI()->AttackStart(m_creature->getVictim()); } } CheckAdds_Timer = 5000; } else CheckAdds_Timer -= diff; if (!Enrage) { //Cast Vanish, then Garrote random victim if (Vanish_Timer < diff) { DoCast(m_creature, SPELL_VANISH); InVanish = true; m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); NonAttackable = true; NonAttackable_Timer = 12100; Vanish_Timer = 30000; Wait_Timer = 5000; } else Vanish_Timer -= diff; if(Gouge_Timer < diff) { DoCast(m_creature->getVictim(), SPELL_GOUGE); Gouge_Timer = 40000; } else Gouge_Timer -= diff; if(Blind_Timer < diff) { if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, GetSpellMaxRange(SPELL_BLIND), true)) DoCast(target, SPELL_BLIND); Blind_Timer = 40000; } else Blind_Timer -= diff; } if(InVanish) { if(Wait_Timer < diff) { DoScriptText(RAND(SAY_SPECIAL_1, SAY_SPECIAL_2), m_creature); if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 50, true)) target->CastSpell(target, SPELL_GARROTE,true); InVanish = false; } else Wait_Timer -= diff; } if(!InVanish) DoMeleeAttackIfReady(); if(NonAttackable) { if(NonAttackable_Timer < diff) { m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); NonAttackable = false; } else NonAttackable_Timer -= diff; } }
void UpdateAI(const uint32 diff) { if (!UpdateVictim()) return; if (m_creature->getVictim() && m_creature->isAlive()) { if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth() > 50)) { if (Charge_Timer < diff) { if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, GetSpellMaxRange(SPELL_CHARGE), true)) { DoCast(target,SPELL_CHARGE); AttackStart(target); } Charge_Timer = 15000 + rand()%15000; } else Charge_Timer -= diff; if (SonicBurst_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_SONICBURST); SonicBurst_Timer = 8000 + rand()%5000; } else SonicBurst_Timer -= diff; if (Screech_Timer < diff) { DoCast(m_creature->getVictim(),SPELL_SCREECH); Screech_Timer = 18000 + rand()%8000; } else Screech_Timer -= diff; if (SpawnBats_Timer < diff) { Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0); if (target) { Creature* Bat = NULL; for (uint8 i = 0 ; i < BAT_COUNT; ++i) { Bat = m_creature->SummonCreature(BAT_ID, batLocations[i][0], batLocations[i][1], batLocations[i][2], 5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); if (Bat) Bat->AI()->AttackStart(target); } } SpawnBats_Timer = 60000; } else SpawnBats_Timer -= diff; } else { if (PhaseTwo) { if (PhaseTwo && ShadowWordPain_Timer < diff) { if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,GetSpellMaxRange(SPELL_SHADOW_WORD_PAIN), true)) { DoCast(target, SPELL_SHADOW_WORD_PAIN); ShadowWordPain_Timer = 12000 + rand()%6000; } } else ShadowWordPain_Timer -=diff; if (MindFlay_Timer < diff) { DoCast(m_creature->getVictim(), SPELL_MIND_FLAY); MindFlay_Timer = 16000; } else MindFlay_Timer -= diff; if (ChainMindFlay_Timer < diff) { m_creature->InterruptNonMeleeSpells(false); DoCast(m_creature->getVictim(), SPELL_CHAIN_MIND_FLAY); ChainMindFlay_Timer = 15000 + rand()%15000; } else ChainMindFlay_Timer -= diff; if (GreaterHeal_Timer < diff) { m_creature->InterruptNonMeleeSpells(false); DoCast(m_creature,SPELL_GREATERHEAL); GreaterHeal_Timer = 25000 + rand()%10000; } else GreaterHeal_Timer -= diff; if (SpawnFlyingBats_Timer < diff) { Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0); if (!target) return; Creature* FlyingBat = m_creature->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 = 10000 + rand()%5000; } else SpawnFlyingBats_Timer -=diff; } else { m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 15219); DoResetThreat(); PhaseTwo = true; } } DoMeleeAttackIfReady(); } }
void UpdateAI(const uint32 diff) { if(!UpdateVictim()) return; DoSpecialThings(diff, DO_EVERYTHING, 125.0f, 1.5f); // Void Zone if(VoidZoneTimer < diff) { if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM,1,GetSpellMaxRange(SPELL_VOIDZONE),true, m_creature->getVictimGUID())) AddSpellToCast(target,SPELL_VOIDZONE,true); VoidZoneTimer = 15000; } else VoidZoneTimer -= diff; // NetherInfusion Berserk if(!Berserk && NetherInfusionTimer < diff) { m_creature->AddAura(SPELL_NETHER_INFUSION, m_creature); ForceSpellCast(m_creature, SPELL_NETHERSPITE_ROAR, INTERRUPT_AND_CAST_INSTANTLY); Berserk = true; } else NetherInfusionTimer -= diff; if(PortalPhase) // PORTAL PHASE { // Distribute beams and buffs if(PortalTimer < diff) { UpdatePortals(); PortalTimer = 1000; } else PortalTimer -= diff; // Empowerment & Nether Burn if(EmpowermentTimer < diff) { ForceSpellCast(m_creature, SPELL_EMPOWERMENT); m_creature->AddAura(SPELL_NETHERBURN_AURA, m_creature); EmpowermentTimer = 90000; } else EmpowermentTimer -= diff; if(PhaseTimer < diff) { if(!m_creature->IsNonMeleeSpellCast(false)) { SwitchToBanishPhase(); return; } } else PhaseTimer -= diff; DoMeleeAttackIfReady(); } else // BANISH PHASE { if(m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE) { m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->MoveIdle(); } // Netherbreath if(NetherbreathTimer < diff) { if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0,GetSpellMaxRange(SPELL_NETHERBREATH),true)) AddSpellToCast(target,SPELL_NETHERBREATH); NetherbreathTimer = 5000+rand()%2000; } else NetherbreathTimer -= diff; if(PhaseTimer < diff) { if(!m_creature->IsNonMeleeSpellCast(false)) { SwitchToPortalPhase(); return; } } else PhaseTimer -= diff; } CastNextSpellIfAnyAndReady(); }
void ScriptedAI::CastNextSpellIfAnyAndReady(uint32 diff) { // clear spell list if caster isn't alive if (!m_creature->isAlive()) { spellList.clear(); autocast = false; return; } bool casted = false; if (m_creature->hasUnitState(UNIT_STAT_CASTING) || me->IsNonMeleeSpellCasted(true)) casted = true; if (!spellList.empty() && !casted) { SpellToCast temp(spellList.front()); spellList.pop_front(); // creature can't cast if lost control - moved here to drop spells if controlled instead not adding them to queue if (m_creature->isCrowdControlled() || m_creature->IsPolymorphed()) return; if (!temp.spellId) return; if (temp.isDestCast) { m_creature->CastSpell(temp.castDest[0], temp.castDest[1], temp.castDest[2], temp.spellId, temp.triggered); casted = true; return; } if (temp.scriptTextEntry) { if (temp.targetGUID && temp.setAsTarget) { if (Unit* target = m_creature->GetUnit(temp.targetGUID)) DoScriptText(temp.scriptTextEntry, m_creature, target); } else DoScriptText(temp.scriptTextEntry, m_creature, m_creature->getVictim()); } if (temp.targetGUID) { Unit * tempU = m_creature->GetUnit(*m_creature, temp.targetGUID); if (tempU && tempU->IsInWorld() && tempU->isAlive() && tempU->IsInMap(m_creature)) if (temp.spellId) { if(temp.setAsTarget && !m_creature->hasIgnoreVictimSelection()) m_creature->SetSelection(temp.targetGUID); if(temp.hasCustomValues) m_creature->CastCustomSpell(tempU, temp.spellId, &temp.damage[0], &temp.damage[1], &temp.damage[2], temp.triggered); else m_creature->CastSpell(tempU, temp.spellId, temp.triggered); } } else { if(temp.hasCustomValues) m_creature->CastCustomSpell((Unit*)NULL, temp.spellId, &temp.damage[0], &temp.damage[1], &temp.damage[2], temp.triggered); else m_creature->CastSpell((Unit*)NULL, temp.spellId, temp.triggered); } casted = true; } if (autocast) { if (autocastTimer < diff) { if (!casted) { Unit * victim = NULL; switch (autocastMode) { case CAST_TANK: { victim = m_creature->getVictim(); // prevent from LoS exploiting, probably some general check should be implemented for this uint8 i = 0; SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(autocastId); // while (!victim or not in los) and i < threatlist size while ((!victim || (!SpellMgr::SpellIgnoreLOS(spellInfo, 0) && !m_creature->IsWithinLOSInMap(victim))) && i < m_creature->getThreatManager().getThreatList().size()) { ++i; victim = SelectUnit(SELECT_TARGET_TOPAGGRO, i, GetSpellMaxRange(autocastId), true); } break; } case CAST_NULL: m_creature->CastSpell((Unit*)NULL, autocastId, false); break; case CAST_RANDOM: victim = SelectUnit(SELECT_TARGET_RANDOM, 0, autocastTargetRange, autocastTargetPlayer); break; case CAST_RANDOM_WITHOUT_TANK: victim = SelectUnit(SELECT_TARGET_RANDOM, 1, autocastTargetRange, autocastTargetPlayer, m_creature->getVictimGUID()); break; case CAST_SELF: victim = m_creature; break; case CAST_THREAT_SECOND: victim = SelectUnit(SELECT_TARGET_TOPAGGRO, 1, autocastTargetRange, autocastTargetPlayer); break; default: //unsupported autocast, stop { autocast = false; return; } } if (victim && !m_creature->hasIgnoreVictimSelection()) { m_creature->SetSelection(victim->GetGUID()); // for autocast always target actual victim m_creature->CastSpell(victim, autocastId, false); } autocastTimer = autocastTimerDef; } } else autocastTimer -= diff; } }
void UpdateAI(const uint32 diff) { if (Intro) { if (IntroTimer < diff) { if (attackers.empty()) NextWave(); Map* tmpMap = me->GetMap(); if (!tmpMap) return; if (!attackers.empty()) { bool alive = false; for (std::list<uint64>::iterator itr = attackers.begin(); itr != attackers.end(); ++itr) { if (Creature* attacker = tmpMap->GetCreature((*itr))) { if (attacker->isAlive()) { alive = true; break; } } } if (!alive) { NextWave(); NextTimer = 5000; } } if (Creature* Thrall = tmpMap->GetCreature(ThrallGUID)) { if (!Thrall->isAlive()) me->ForcedDespawn(); } IntroTimer = 5000; } else IntroTimer -= diff; if (Next) { if (NextTimer <= diff) { NextWave(); } else NextTimer -= diff; } } //Return since we have no target if (!UpdateVictim() ) return; //Sand Breath if (SandBreath_Timer < diff) { if (me->IsNonMeleeSpellCast(false)) me->InterruptNonMeleeSpells(false); DoCast(me->getVictim(),SPELL_SAND_BREATH); DoScriptText(RAND(SAY_BREATH1, SAY_BREATH2), me); SandBreath_Timer = 25000+rand()%5000; } else SandBreath_Timer -= diff; if(ImpendingDeath_Timer < diff) { if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0 , GetSpellMaxRange(SPELL_IMPENDING_DEATH), true)) DoCast(target,SPELL_IMPENDING_DEATH); ImpendingDeath_Timer = 30000+rand()%5000; } else ImpendingDeath_Timer -= diff; if(WingBuffet_Timer < diff) { DoCast(me,SPELL_WING_BUFFET); WingBuffet_Timer = 25000+rand()%10000; } else WingBuffet_Timer -= diff; if(Mda_Timer < diff) { DoCast(me,SPELL_MAGIC_DISRUPTION_AURA); Mda_Timer = 15000; } else Mda_Timer -= diff; DoMeleeAttackIfReady(); }