//perception and AI void ADA2UE4Creature::OnSeePlayer(APawn* Pawn) { ADA2UE4CreatureController* AIController = Cast<ADA2UE4CreatureController>(GetController()); ADA2UE4Creature* SensedPawn = Cast<ADA2UE4Creature>(Pawn); if (AIController)// && SensedPawn->IsAlive()) { //have I seen this pawn before? //if yes, did the hostility changed? Cast<ADA2UE4Creature>(SensedPawn)->LastSensedTime = GetWorld()->GetTimeSeconds(); //TODO handle bStealth, and event integer 1 = ability int32 bStealth = TRUE_; if (!SensedPawns.Contains(SensedPawn)) { #ifdef DEBUG LogWarning(GetName() + " | OnSee " + SensedPawn->GetName() + " by " + GetName()); #endif // DEBUG int32 bHostile = IsObjectHostile(this, Cast<ADA2UE4Creature>(SensedPawn)); if (bHostile) AddThreat(SensedPawn, 10.f); //default threat SensedPawns.Add(SensedPawn); } else if (bHostilityChanged) { #ifdef DEBUG LogWarning(GetName() + " | OnSee Hostility changed " + SensedPawn->GetName() + " by " + GetName()); #endif // DEBUG bHostilityChanged = FALSE_; int32 bHostile = IsObjectHostile(this, Cast<ADA2UE4Creature>(SensedPawn)); if (bHostile) AddThreat(SensedPawn, 10.f); //default threat } } }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; DoMeleeAttackIfReady(); if (ChaseTimer <= diff) { if (!IsChasing) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { Talk(SAY_WOLF_HOOD); DoCast(target, SPELL_LITTLE_RED_RIDING_HOOD, true); TempThreat = GetThreat(target); if (TempThreat) ModifyThreatByPercent(target, -100); HoodGUID = target->GetGUID(); AddThreat(target, 1000000.0f); ChaseTimer = 20000; IsChasing = true; } } else { IsChasing = false; if (Unit* target = ObjectAccessor::GetUnit(*me, HoodGUID)) { HoodGUID.Clear(); if (GetThreat(target)) ModifyThreatByPercent(target, -100); AddThreat(target, TempThreat); TempThreat = 0; } ChaseTimer = 40000; } } else ChaseTimer -= diff; if (IsChasing) return; if (FearTimer <= diff) { DoCastVictim(SPELL_TERRIFYING_HOWL); FearTimer = urand(25000, 35000); } else FearTimer -= diff; if (SwipeTimer <= diff) { DoCastVictim(SPELL_WIDE_SWIPE); SwipeTimer = urand(25000, 30000); } else SwipeTimer -= diff; }
void IsSummonedBy(Unit* summoner) override { targetGUID = summoner->GetGUID(); summoner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); summoner->SetControlled(true, UNIT_STATE_ROOT); me->SetInCombatWith(summoner); AddThreat(summoner, 250.0f); AddThreat(me, 250.0f, summoner); if (Creature* target = ObjectAccessor::GetCreature(*me, targetGUID)) { DoCast(target, SPELL_FLASH_FREEZE_HELPER, true); // Prevents to have Ice Block on other place than target is me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation()); } }
void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override { if (waypointId == 7 && instance) { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) AddThreat(target, 0.0f); } }
void StartChase(Unit* who) { DoCast(who, SPELL_MARK); me->SetSpeedRate(MOVE_RUN, 0.5f); // make sure the Spine will really follow the one he should me->GetThreatManager().ResetAllThreat(); DoZoneInCombat(); AddThreat(who, 1000000.0f); me->GetMotionMaster()->Clear(true); me->GetMotionMaster()->MoveChase(who); }
void AttackStart(Unit* who) override { if (me->Attack(who, true)) { AddThreat(who, 0.0f); me->SetInCombatWith(who); who->SetInCombatWith(me); if (!m_bIsFrozen) me->GetMotionMaster()->MoveChase(who); } }
void IsSummonedBy(Unit* summoner) override { if (summoner->GetTypeId() != TYPEID_PLAYER || !summoner->GetVehicle()) return; _tigerGuid = summoner->GetVehicle()->GetBase()->GetGUID(); if (Unit* tiger = ObjectAccessor::GetUnit(*me, _tigerGuid)) { AddThreat(tiger, 500000.0f); DoCast(me, SPELL_FURIOUS_BITE); } }
void IsSummonedBy(WorldObject* summonerWO) override { Player* summoner = summonerWO->ToPlayer(); if (!summoner || !summoner->GetVehicle()) return; _tigerGuid = summoner->GetVehicle()->GetBase()->GetGUID(); if (Unit* tiger = ObjectAccessor::GetUnit(*me, _tigerGuid)) { AddThreat(tiger, 500000.0f); DoCast(me, SPELL_FURIOUS_BITE); } }
void JustEngagedWith(Unit* /*who*/) override { Talk(SAY_ROMULO_AGGRO); if (JulianneGUID) { Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID)); if (Julianne && Julianne->GetVictim()) { AddThreat(Julianne->GetVictim(), 1.0f); AttackStart(Julianne->GetVictim()); } } }
void IsSummonedBy(Unit* summoner) override { targetGUID = summoner->GetGUID(); me->SetInCombatWith(summoner); AddThreat(summoner, 250.0f); if (Unit* target = ObjectAccessor::GetUnit(*me, targetGUID)) { DoCast(target, SPELL_BLOCK_OF_ICE, true); // Prevents to have Ice Block on other place than target is me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation()); if (target->GetTypeId() == TYPEID_PLAYER) if (Creature* hodir = instance->GetCreature(BOSS_HODIR)) hodir->AI()->DoAction(ACTION_CHEESE_THE_FREEZE); } }
void SetThreatList(Creature* summonedUnit) { if (!summonedUnit) return; ThreatContainer::StorageType const& threatlist = me->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); if (unit && unit->IsAlive()) { float threat = me->GetThreatManager().getThreat(unit); AddThreat(unit, threat, summonedUnit); } } }
bool TryActivateAfterTTelep(uint32 diff) { if (AfterTeleport) { if (!tspellcast) { me->ClearUnitState(UNIT_STATE_STUNNED); DoCast(me, SPELL_TWIN_TELEPORT); me->AddUnitState(UNIT_STATE_STUNNED); } tspellcast = true; if (AfterTeleportTimer <= diff) { AfterTeleport = false; me->ClearUnitState(UNIT_STATE_STUNNED); if (Unit* nearu = me->SelectNearestTarget(100)) { //DoYell(nearu->GetName(), LANG_UNIVERSAL, 0); AttackStart(nearu); AddThreat(nearu, 10000); } return true; } else { AfterTeleportTimer -= diff; // update important timers which would otherwise get skipped if (EnrageTimer > diff) EnrageTimer -= diff; else EnrageTimer = 0; if (Teleport_Timer > diff) Teleport_Timer -= diff; else Teleport_Timer = 0; return false; } } else { return true; } }
void SummonCreatureWithRandomTarget(uint32 creatureId, int position) { if (Creature* summoned = me->SummonCreature(creatureId, PyrewoodSpawnPoints[position][0], PyrewoodSpawnPoints[position][1], PyrewoodSpawnPoints[position][2], PyrewoodSpawnPoints[position][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000)) { Unit* target = nullptr; if (PlayerGUID) if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) if (player->IsAlive() && RAND(0, 1)) target = player; if (!target) target = me; summoned->SetFaction(FACTION_ENEMY); AddThreat(target, 32.0f, summoned); summoned->AI()->AttackStart(target); } }
void SelectNewTarget() { if (Creature* teron = _instance->GetCreature(DATA_TERON_GOREFIEND)) { Unit* target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_SPIRITUAL_VENGEANCE); // He should target Vengeful Spirits only if has no other player available if (!target) target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0); if (target) { ResetThreatList(); AttackStart(target); AddThreat(target, 1000000.0f); targetGUID = target->GetGUID(); } } }
void MovementInform(uint32 type, uint32 pointId) override { if (!instance || type != POINT_MOTION_TYPE) return; // debug_log("dummy_dragonAI: %s reached point %u", me->GetName(), uiPointId); // if healers messed up the raid and we was already initialized if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) { EnterEvadeMode(); return; } // this is end, if we reach this, don't do much if (pointId == POINT_ID_LAND) { me->GetMotionMaster()->Clear(); DoZoneInCombat(); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) { AddThreat(target, 1.0f); me->Attack(target, true); me->GetMotionMaster()->MoveChase(target); } _canMoveFree = false; return; } // increase waypointId = pointId + 1; // if we have reached a point bigger or equal to count, it mean we must reset to point 0 if (waypointId >= MAX_WAYPOINT) { if (!_canMoveFree) _canMoveFree = true; waypointId = 0; } events.ScheduleEvent(EVENT_FREE_MOVEMENT, 500); }
void DoSummonAtRift(uint32 creature_entry) { if (!creature_entry) return; if (instance->GetData(TYPE_MEDIVH) != IN_PROGRESS) { me->InterruptNonMeleeSpells(true); me->RemoveAllAuras(); return; } Position pos = me->GetRandomNearPosition(10.0f); //normalize Z-level if we can, if rift is not at ground level. pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); if (Unit* Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) if (Unit* temp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MEDIVH))) AddThreat(temp, 0.0f, Summon); }
void JustSummoned(Creature* summon) override { switch (summon->GetEntry()) { case NPC_SPIRIT_FOUNT: summon->CastSpell(summon, SPELL_SPIRIT_FOUNT, true); summon->SetDisplayId(11686); SpiritFountGUID = summon->GetGUID(); break; case NPC_AVENGING_SPIRIT: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { AddThreat(target, 0.0f, summon); summon->AI()->AttackStart(target); } break; default: break; } summons.Summon(summon); }
void UpdateAI(uint32 diff) override { if (DespawnTimer <= diff) me->KillSelf(); else DespawnTimer -= diff; //Return since we have no target if (!UpdateVictim()) return; if (ChangeTargetTimer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { AddThreat(target, 1.0f); me->TauntApply(target); AttackStart(target); } ChangeTargetTimer = urand(5000, 15000); } else ChangeTargetTimer -= diff; }
void DoAction(int32 actionId) override { if (actionId == ACTION_STORE_OLD_TARGET) { if (Unit* victim = me->GetVictim()) { _oldTargetGUID = victim->GetGUID(); _tempThreat = GetThreat(victim); } } else if (actionId == ACTION_RESET_THREAT) { if (Unit* oldTarget = ObjectAccessor::GetUnit(*me, _oldTargetGUID)) { if (Unit* current = me->GetVictim()) ModifyThreatByPercent(current, -100); AddThreat(oldTarget, _tempThreat); AttackStart(oldTarget); _oldTargetGUID.Clear(); _tempThreat = 0.0f; } } }
void UpdateAI(uint32 diff) override { //Return since we have no target if (!UpdateVictim()) return; if (!WhirlWind && WhirlWind_Timer <= diff) { DoCast(me, SPELL_WHIRLWINDADD); WhirlWind = true; WhirlWind_Timer = urand(25000, 40000); WhirlWindEnd_Timer = 15000; } else WhirlWind_Timer -= diff; if (WhirlWind) { if (WhirlWindRandom_Timer <= diff) { //Attack random Gamers if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { AddThreat(target, 1.0f); AttackStart(target); } WhirlWindRandom_Timer = urand(3000, 7000); } else WhirlWindRandom_Timer -= diff; if (WhirlWindEnd_Timer <= diff) { WhirlWind = false; } else WhirlWindEnd_Timer -= diff; } if (!WhirlWind) { if (AggroReset_Timer <= diff) { //Attack random Gamers if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { AddThreat(target, 1.0f); AttackStart(target); } AggroReset = true; AggroReset_Timer = urand(2000, 5000); } else AggroReset_Timer -= diff; if (KnockBack_Timer <= diff) { DoCast(me, SPELL_WHIRLWINDADD); KnockBack_Timer = urand(10000, 20000); } else KnockBack_Timer -= diff; } if (AggroReset) { if (AggroResetEnd_Timer <= diff) { AggroReset = false; AggroResetEnd_Timer = 5000; AggroReset_Timer = urand(30000, 40000); } else AggroResetEnd_Timer -= diff; } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { //Return since we have no target if (!UpdateVictim()) return; if (WhirlWind) { if (WhirlWindRandom_Timer <= diff) { //Attack random Gamers if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { AddThreat(target, 1.0f); AttackStart(target); } WhirlWindRandom_Timer = urand(3000, 7000); } else WhirlWindRandom_Timer -= diff; if (WhirlWindEnd_Timer <= diff) { WhirlWind = false; WhirlWind_Timer = urand(25000, 40000); } else WhirlWindEnd_Timer -= diff; } if (!WhirlWind) { if (WhirlWind_Timer <= diff) { DoCast(me, SPELL_WHIRLWIND); WhirlWind = true; WhirlWindEnd_Timer = 15000; } else WhirlWind_Timer -= diff; if (AggroReset_Timer <= diff) { //Attack random Gamers if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { AddThreat(target, 1.0f); AttackStart(target); } AggroReset = true; AggroReset_Timer = urand(2000, 5000); } else AggroReset_Timer -= diff; if (AggroReset) { if (AggroResetEnd_Timer <= diff) { AggroReset = false; AggroResetEnd_Timer = 5000; AggroReset_Timer = urand(35000, 45000); } else AggroResetEnd_Timer -= diff; } //If she is 20% enrage if (!Enraged) { if (!HealthAbovePct(20) && !me->IsNonMeleeSpellCast(false)) { DoCast(me, SPELL_ENRAGE); Enraged = true; } } //After 10 minutes hard enrage if (!EnragedHard) { if (EnrageHard_Timer <= diff) { DoCast(me, SPELL_ENRAGEHARD); EnragedHard = true; } else EnrageHard_Timer -= diff; } DoMeleeAttackIfReady(); } }
void JustEngagedWith(Unit* who) override { AddThreat(who, 0.1f); }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; events.Update(diff); while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_STATIC_DISRUPTION: { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); if (!target) target = me->GetVictim(); if (target) { TargetGUID = target->GetGUID(); DoCast(target, SPELL_STATIC_DISRUPTION, false); } /*if (float dist = me->IsWithinDist3d(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 5.0f) dist = 5.0f; SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/ events.ScheduleEvent(EVENT_STATIC_DISRUPTION, 10s, 18s); break; } case EVENT_GUST_OF_WIND: { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); if (!target) target = me->GetVictim(); if (target) DoCast(target, SPELL_GUST_OF_WIND); events.ScheduleEvent(EVENT_GUST_OF_WIND, 20s, 30s); break; } case EVENT_CALL_LIGHTNING: DoCastVictim(SPELL_CALL_LIGHTNING); events.ScheduleEvent(EVENT_CALL_LIGHTNING, 12s, 17s); // totaly random timer. can't find any info on this break; case EVENT_ELECTRICAL_STORM: { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); if (!target) { EnterEvadeMode(); return; } target->CastSpell(target, 44007, true); // cloud visual DoCast(target, SPELL_ELECTRICAL_STORM, false); // storm cyclon + visual float x, y, z; target->GetPosition(x, y, z); /// @todo: fix it in correct way, that causes player to can fly until logout /* if (target) { target->SetDisableGravity(true); target->MonsterMoveWithSpeed(x, y, me->GetPositionZ()+15, 0); } */ Unit* Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000); if (Cloud) { CloudGUID = Cloud->GetGUID(); Cloud->SetDisableGravity(true); Cloud->StopMoving(); Cloud->SetObjectScale(1.0f); Cloud->SetFaction(FACTION_FRIENDLY); Cloud->SetMaxHealth(9999999); Cloud->SetHealth(9999999); Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } StormCount = 1; events.ScheduleEvent(EVENT_ELECTRICAL_STORM, 1min); // 60 seconds(bosskillers) events.ScheduleEvent(EVENT_RAIN, 47s, 52s); break; } case EVENT_RAIN: if (!isRaining) { SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f); isRaining = true; } else events.ScheduleEvent(EVENT_RAIN, 1s); break; case EVENT_STORM_SEQUENCE: { Unit* target = ObjectAccessor::GetUnit(*me, CloudGUID); if (!target || !target->IsAlive()) { EnterEvadeMode(); return; } else if (Unit* Cyclone = ObjectAccessor::GetUnit(*me, CycloneGUID)) Cyclone->CastSpell(target, SPELL_SAND_STORM, true); // keep casting or... HandleStormSequence(target); break; } case EVENT_SUMMON_EAGLES: Talk(SAY_SUMMON); float x, y, z; me->GetPosition(x, y, z); for (uint8 i = 0; i < 8; ++i) { Unit* bird = ObjectAccessor::GetUnit(*me, BirdGUIDs[i]); if (!bird) //they despawned on die { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { x = target->GetPositionX() + irand(-10, 10); y = target->GetPositionY() + irand(-10, 10); z = target->GetPositionZ() + urand(16, 20); if (z > 95) z = 95.0f - urand(0, 5); } Creature* creature = me->SummonCreature(NPC_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); if (creature) { AddThreat(me->GetVictim(), 1.0f, creature); creature->AI()->AttackStart(me->GetVictim()); BirdGUIDs[i] = creature->GetGUID(); } } } break; case EVENT_ENRAGE: Talk(SAY_ENRAGE); DoCast(me, SPELL_BERSERK, true); events.ScheduleEvent(EVENT_ENRAGE, 10min); break; default: break; } } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { _events.Update(diff); if (UpdateVictim()) { while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_FROST_SHOCK: DoCastVictim(SPELL_FROST_SHOCK); _events.DelayEvents(1 * IN_MILLISECONDS); _events.ScheduleEvent(EVENT_FROST_SHOCK, 10s, 15s); break; case EVENT_SEARING_TOTEM: DoCast(me, SPELL_SEARING_TOTEM); _events.DelayEvents(1 * IN_MILLISECONDS); _events.ScheduleEvent(EVENT_SEARING_TOTEM, urand(110, 130) * IN_MILLISECONDS); break; case EVENT_STRENGTH_OF_EARTH_TOTEM: DoCast(me, SPELL_STRENGTH_OF_EARTH_TOTEM); _events.DelayEvents(1 * IN_MILLISECONDS); _events.ScheduleEvent(EVENT_STRENGTH_OF_EARTH_TOTEM, urand(110, 130) * IN_MILLISECONDS); break; case EVENT_HEALING_SURGE: { Unit* target = nullptr; if (me->GetHealthPct() < 85) target = me; else if (Player* player = GetPlayerForEscort()) if (player->GetHealthPct() < 85) target = player; if (target) { DoCast(target, SPELL_HEALING_SURGE); _events.ScheduleEvent(EVENT_HEALING_SURGE, 10s); } else _events.ScheduleEvent(EVENT_HEALING_SURGE, 2s); break; } default: break; } } DoMeleeAttackIfReady(); } if (HasEscortState(STATE_ESCORT_NONE)) return; EscortAI::UpdateAI(diff); if (_phase) { if (_moveTimer <= diff) { switch (_phase) { case PHASE_WP_26: //debug skip path to point 26, buggy path calculation me->GetMotionMaster()->MovePoint(WP_DEBUG_2, -2021.77f, -10648.8f, 129.903f, false); _moveTimer = 2 * IN_MILLISECONDS; _phase = PHASE_CONTINUE; break; case PHASE_CONTINUE: // continue escort SetEscortPaused(false); _moveTimer = 0 * IN_MILLISECONDS; _phase = PHASE_NONE; break; case PHASE_WP_22: //debug skip path to point 22, buggy path calculation me->GetMotionMaster()->MovePoint(WP_EXPLOSIVES_FIRST_PLANT, -1958.026f, -10660.465f, 111.547f, false); Talk(SAY_LEGOSO_3); _moveTimer = 2 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_KNEEL; break; case PHASE_PLANT_FIRST_KNEEL: // plant first explosives stage 1 kneel me->SetStandState(UNIT_STAND_STATE_KNEEL); _moveTimer = 10 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_STAND; break; case PHASE_PLANT_FIRST_STAND: // plant first explosives stage 1 stand me->SetStandState(UNIT_STAND_STATE_STAND); _moveTimer = 0.5* IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_WORK; break; case PHASE_PLANT_FIRST_WORK: // plant first explosives stage 2 work Talk(SAY_LEGOSO_4); _moveTimer = 17.5 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_FINISH; break; case PHASE_PLANT_FIRST_FINISH: // plant first explosives finish _explosivesGuids.clear(); for (uint8 i = 0; i != MAX_EXPLOSIVES; ++i) { if (GameObject* explosive = me->SummonGameObject(GO_DRAENEI_EXPLOSIVES_1, ExplosivesPos[0][i], QuaternionData(), 0)) _explosivesGuids.push_back(explosive->GetGUID()); } me->HandleEmoteCommand(EMOTE_ONESHOT_NONE); // reset anim state // force runoff movement so he will not screw up next waypoint me->GetMotionMaster()->MovePoint(WP_EXPLOSIVES_FIRST_RUNOFF, -1955.6f, -10669.8f, 110.65f, false); Talk(SAY_LEGOSO_5); _moveTimer = 1.5 * IN_MILLISECONDS; _phase = PHASE_CONTINUE; break; case PHASE_PLANT_FIRST_TIMER_1: // first explosives detonate timer 1 Talk(SAY_LEGOSO_6); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_TIMER_2; break; case PHASE_PLANT_FIRST_TIMER_2: // first explosives detonate timer 2 Talk(SAY_LEGOSO_7); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_TIMER_3; break; case PHASE_PLANT_FIRST_TIMER_3: // first explosives detonate timer 3 Talk(SAY_LEGOSO_8); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_DETONATE; break; case PHASE_PLANT_FIRST_DETONATE: // first explosives detonate finish for (GuidList::iterator itr = _explosivesGuids.begin(); itr != _explosivesGuids.end(); ++itr) { if (GameObject* explosive = ObjectAccessor::GetGameObject(*me, *itr)) me->RemoveGameObject(explosive, true); } _explosivesGuids.clear(); me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); _moveTimer = 2 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_SPEECH; break; case PHASE_PLANT_FIRST_SPEECH: // after detonation 1 speech Talk(SAY_LEGOSO_9); _moveTimer = 4 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_ROTATE; break; case PHASE_PLANT_FIRST_ROTATE: // after detonation 1 rotate to next point me->SetFacingTo(2.272f); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_FIRST_POINT; break; case PHASE_PLANT_FIRST_POINT: // after detonation 1 send point anim and go on to next point me->HandleEmoteCommand(EMOTE_ONESHOT_POINT); _moveTimer = 2 * IN_MILLISECONDS; _phase = PHASE_CONTINUE; break; case PHASE_FEEL_SIRONAS_1: // legoso exclamation before sironas 1.1 Talk(SAY_LEGOSO_10); _moveTimer = 4 * IN_MILLISECONDS; _phase = PHASE_FEEL_SIRONAS_2; break; case PHASE_FEEL_SIRONAS_2: // legoso exclamation before sironas 1.2 Talk(SAY_LEGOSO_11); _moveTimer = 4 * IN_MILLISECONDS; _phase = PHASE_CONTINUE; break; case PHASE_MEET_SIRONAS_ROAR: // legoso exclamation before sironas 2.1 Talk(SAY_LEGOSO_12); _moveTimer = 4 * IN_MILLISECONDS; _phase = PHASE_MEET_SIRONAS_TURN; break; case PHASE_MEET_SIRONAS_TURN: // legoso exclamation before sironas 2.2 if (Player* player = GetPlayerForEscort()) me->SetFacingToObject(player); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_MEET_SIRONAS_SPEECH; break; case PHASE_MEET_SIRONAS_SPEECH: // legoso exclamation before sironas 2.3 Talk(SAY_LEGOSO_13); _moveTimer = 7 * IN_MILLISECONDS; _phase = PHASE_CONTINUE; break; case PHASE_PLANT_SECOND_KNEEL: // plant second explosives stage 1 kneel me->SetStandState(UNIT_STAND_STATE_KNEEL); _moveTimer = 11 * IN_MILLISECONDS; _phase = PHASE_PLANT_SECOND_SPEECH; break; case PHASE_PLANT_SECOND_SPEECH: // plant second explosives stage 2 kneel Talk(SAY_LEGOSO_14); _moveTimer = 13 * IN_MILLISECONDS; _phase = PHASE_PLANT_SECOND_STAND; break; case PHASE_PLANT_SECOND_STAND: // plant second explosives finish me->SetStandState(UNIT_STAND_STATE_STAND); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_SECOND_FINISH; break; case PHASE_PLANT_SECOND_FINISH: // plant second explosives finish - create explosives _explosivesGuids.clear(); for (uint8 i = 0; i != MAX_EXPLOSIVES; ++i) { if (GameObject* explosive = me->SummonGameObject(GO_DRAENEI_EXPLOSIVES_2, ExplosivesPos[1][i], QuaternionData(), 0)) _explosivesGuids.push_back(explosive->GetGUID()); } Talk(SAY_LEGOSO_15); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_SECOND_WAIT; break; case PHASE_PLANT_SECOND_WAIT: // plant second explosives finish - proceed to next point _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_CONTINUE; break; case PHASE_PLANT_SECOND_TIMER_1: // second explosives detonate timer 1 Talk(SAY_LEGOSO_16); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_SECOND_TIMER_2; break; case PHASE_PLANT_SECOND_TIMER_2: // second explosives detonate timer 2 Talk(SAY_LEGOSO_17); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_SECOND_TIMER_3; break; case PHASE_PLANT_SECOND_TIMER_3: // second explosives detonate timer 3 Talk(SAY_LEGOSO_18); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_PLANT_SECOND_DETONATE; break; case PHASE_PLANT_SECOND_DETONATE: // second explosives detonate finish for (GuidList::iterator itr = _explosivesGuids.begin(); itr != _explosivesGuids.end(); ++itr) { if (GameObject* explosive = ObjectAccessor::GetGameObject(*me, *itr)) me->RemoveGameObject(explosive, true); } _explosivesGuids.clear(); if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS)) { sironas->SetImmuneToAll(false); me->SetFacingToObject(sironas); } _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_FIGHT_SIRONAS_STOP; break; case PHASE_FIGHT_SIRONAS_STOP: // sironas channel stop if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS)) sironas->AI()->DoAction(ACTION_SIRONAS_CHANNEL_STOP); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_FIGHT_SIRONAS_SPEECH_1; break; case PHASE_FIGHT_SIRONAS_SPEECH_1: // sironas exclamation before aggro if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS)) sironas->AI()->Talk(SAY_SIRONAS_1); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_FIGHT_SIRONAS_SPEECH_2; break; case PHASE_FIGHT_SIRONAS_SPEECH_2: // legoso exclamation before aggro if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS)) sironas->SetObjectScale(3.0f); Talk(SAY_LEGOSO_19); _moveTimer = 1 * IN_MILLISECONDS; _phase = PHASE_FIGHT_SIRONAS_START; break; case PHASE_FIGHT_SIRONAS_START: // legoso exclamation at aggro if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS)) { Unit* target = GetPlayerForEscort(); if (!target) target = me; AddThreat(sironas, 0.001f, target); sironas->Attack(target, true); sironas->GetMotionMaster()->MoveChase(target); } _moveTimer = 10 * IN_MILLISECONDS; _phase = PHASE_CONTINUE; break; case PHASE_SIRONAS_SLAIN_SPEECH_1: // legoso exclamation after battle - stage 1.1 Talk(SAY_LEGOSO_20); _moveTimer = 2 * IN_MILLISECONDS; _phase = PHASE_SIRONAS_SLAIN_EMOTE_1; break; case PHASE_SIRONAS_SLAIN_EMOTE_1: // legoso exclamation after battle - stage 1.2 me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); _moveTimer = 2 * IN_MILLISECONDS; _phase = PHASE_SIRONAS_SLAIN_EMOTE_2; break; case PHASE_SIRONAS_SLAIN_EMOTE_2: // legoso exclamation after battle - stage 1.3 if (Player* player = GetPlayerForEscort()) player->GroupEventHappens(QUEST_ENDING_THEIR_WORLD, me); me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); _moveTimer = 5 * IN_MILLISECONDS; _phase = PHASE_SIRONAS_SLAIN_SPEECH_2; break; case PHASE_SIRONAS_SLAIN_SPEECH_2: // legoso exclamation after battle - stage 2 Talk(SAY_LEGOSO_21); _moveTimer = 30 * IN_MILLISECONDS; _phase = PHASE_CONTINUE; break; default: break; } } else if (!me->IsInCombat()) _moveTimer -= diff; } }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; events.Update(diff); while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_HATEFUL: { // Hateful Strike targets the highest non-MT threat in melee range on 10man // and the higher HP target out of the two highest non-MT threats in melee range on 25man ThreatReference* secondThreat = nullptr; ThreatReference* thirdThreat = nullptr; ThreatManager const& mgr = me->GetThreatManager(); Unit* currentVictim = mgr.GetCurrentVictim(); auto list = mgr.GetModifiableThreatList(); auto it = list.begin(), end = list.end(); if (it == end) { EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return; } if ((*it)->GetVictim() != currentVictim) secondThreat = *it; if ((!secondThreat || Is25ManRaid()) && (++it != end && (*it)->IsAvailable())) { if ((*it)->GetVictim() != currentVictim) (secondThreat ? thirdThreat : secondThreat) = *it; if (!thirdThreat && Is25ManRaid() && (++it != end && (*it)->IsAvailable())) thirdThreat = *it; } Unit* pHatefulTarget = nullptr; if (!secondThreat) pHatefulTarget = currentVictim; else if (!thirdThreat) pHatefulTarget = secondThreat->GetVictim(); else pHatefulTarget = (secondThreat->GetVictim()->GetHealth() < thirdThreat->GetVictim()->GetHealth()) ? thirdThreat->GetVictim() : secondThreat->GetVictim(); // add threat to highest threat targets AddThreat(currentVictim, HATEFUL_THREAT_AMT); if (secondThreat) secondThreat->AddThreat(HATEFUL_THREAT_AMT); if (thirdThreat) thirdThreat->AddThreat(HATEFUL_THREAT_AMT); DoCast(pHatefulTarget, SPELL_HATEFUL_STRIKE, true); events.Repeat(Seconds(1)); break; } case EVENT_BERSERK: DoCast(me, SPELL_BERSERK, true); Talk(EMOTE_BERSERK); events.ScheduleEvent(EVENT_SLIME, Seconds(2)); break; case EVENT_SLIME: DoCastAOE(SPELL_SLIME_BOLT, true); events.Repeat(Seconds(2)); break; } } if (!Enraged && HealthBelowPct(5)) { DoCast(me, SPELL_FRENZY, true); Talk(EMOTE_FRENZY); Enraged = true; } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { //Return since we have no target if (!UpdateVictim()) return; switch (Phase) { case 0: { // *Heroic mode only: if (IsHeroic()) { if (PyroblastTimer <= diff) { me->InterruptSpell(CURRENT_CHANNELED_SPELL); me->InterruptSpell(CURRENT_GENERIC_SPELL); DoCast(me, SPELL_SHOCK_BARRIER, true); DoCastVictim(SPELL_PYROBLAST); PyroblastTimer = 60000; } else PyroblastTimer -= diff; } if (FireballTimer <= diff) { DoCastVictim(SPELL_FIREBALL_NORMAL); FireballTimer = urand(2000, 6000); } else FireballTimer -= diff; if (PhoenixTimer <= diff) { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); uint8 random = urand(1, 2); float x = KaelLocations[random][0]; float y = KaelLocations[random][1]; Creature* Phoenix = me->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); if (Phoenix) { Phoenix->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); SetThreatList(Phoenix); Phoenix->AI()->AttackStart(target); } Talk(SAY_PHOENIX); PhoenixTimer = 60000; } else PhoenixTimer -= diff; if (FlameStrikeTimer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { me->InterruptSpell(CURRENT_CHANNELED_SPELL); me->InterruptSpell(CURRENT_GENERIC_SPELL); DoCast(target, SPELL_FLAMESTRIKE3, true); Talk(SAY_FLAMESTRIKE); } FlameStrikeTimer = urand(15000, 25000); } else FlameStrikeTimer -= diff; // Below 50% if (HealthBelowPct(50)) { me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); me->StopMoving(); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); GravityLapseTimer = 0; GravityLapsePhase = 0; Phase = 1; } DoMeleeAttackIfReady(); } break; case 1: { if (GravityLapseTimer <= diff) { switch (GravityLapsePhase) { case 0: if (FirstGravityLapse) // Different yells at 50%, and at every following Gravity Lapse { Talk(SAY_GRAVITY_LAPSE); FirstGravityLapse = false; instance->SetData(DATA_KAELTHAS_STATUES, 1); } else Talk(SAY_RECAST_GRAVITY); DoCast(me, SPELL_GRAVITY_LAPSE_INITIAL); GravityLapseTimer = 2000 + diff;// Don't interrupt the visual spell GravityLapsePhase = 1; break; case 1: TeleportPlayersToSelf(); GravityLapseTimer = 1000; GravityLapsePhase = 2; break; case 2: CastGravityLapseKnockUp(); GravityLapseTimer = 1000; GravityLapsePhase = 3; break; case 3: CastGravityLapseFly(); GravityLapseTimer = 30000; GravityLapsePhase = 4; for (uint8 i = 0; i < 3; ++i) { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); if (Orb && target) { Orb->SetSpeedRate(MOVE_RUN, 0.5f); AddThreat(target, 1000000.0f, Orb); Orb->AI()->AttackStart(target); } } DoCast(me, SPELL_GRAVITY_LAPSE_CHANNEL); break; case 4: me->InterruptNonMeleeSpells(false); Talk(SAY_TIRED); DoCast(me, SPELL_POWER_FEEDBACK); RemoveGravityLapse(); GravityLapseTimer = 10000; GravityLapsePhase = 0; break; } } else GravityLapseTimer -= diff; } break; } }