void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        switch(stage)
        {
            case 0: {
                timedCast(SPELL_POUND, uiDiff);
                timedCast(SPELL_COLD, uiDiff);
                if (timedQuery(SUMMON_BORROWER, uiDiff)) {
                        doCast(SUMMON_BORROWER);
                        DoScriptText(-1713556,m_creature);
                        };
                if (timedQuery(SPELL_SUBMERGE_0, uiDiff)) stage = 1;

                    break;}
            case 1: {
                    doCast(SPELL_SUBMERGE_0);
                    m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    stage = 2;
                    DoScriptText(-1713557,m_creature);
                    break;}
            case 2: {
                    if (timedQuery(SPELL_SPIKE_CALL, uiDiff)) {
                         pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
//                         doCast(SPELL_SPIKE_CALL);
//                         This summon not supported in database. Temporary override.
                         Unit* spike = doSummon(NPC_SPIKE,TEMPSUMMON_TIMED_DESPAWN,60000);
                         if (spike) { spike->AddThreat(pTarget, 1000.0f);
                                      DoScriptText(-1713558,m_creature,pTarget);
                                      doCast(SPELL_MARK,pTarget);
                                      spike->GetMotionMaster()->MoveChase(pTarget);
                                     }
                         };
                    if (timedQuery(SPELL_SUMMON_BEATLES, uiDiff)) {
                            doCast(SPELL_SUMMON_BEATLES);
                            doCast(SUMMON_SCARAB);
                            DoScriptText(-1713560,m_creature);
                         };
                    if (timedQuery(SPELL_SUBMERGE_0, uiDiff)) stage = 3;
                    break;}
            case 3: {
                    stage = 0;
                    DoScriptText(-1713559,m_creature);
                    m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    doRemove(SPELL_SUBMERGE_0,m_creature);
                    break;}
            case 4: {
                            doCast(SPELL_LEECHING_SWARM);
                            DoScriptText(-1713561,m_creature);
                    stage = 5;
                    break;}
            case 5: {
                        timedCast(SPELL_POUND, uiDiff);
                        timedCast(SPELL_COLD, uiDiff);
                        break;}

        }
        timedCast(SUMMON_FROSTSPHERE, uiDiff);

        timedCast(SPELL_BERSERK, uiDiff);

        if (m_creature->GetHealthPercent() < 30.0f && stage == 0) stage = 4;

        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, urand(10, 15) * IN_MILLISECONDS);
                            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 = NULL;
                            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, 10 * IN_MILLISECONDS);
                            }
                            else
                                _events.ScheduleEvent(EVENT_HEALING_SURGE, 2 * IN_MILLISECONDS);
                            break;
                        }
                        default:
                            break;
                    }
                }

                DoMeleeAttackIfReady();
            }

            if (HasEscortState(STATE_ESCORT_NONE))
                return;

            npc_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], G3D::Quat(), 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], G3D::Quat(), 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->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
                                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;

                                target->AddThreat(sironas, 0.001f);
                                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;
            }
        }
示例#3
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // Corrupted Mind
        if (m_uiCorruptedMindTimer < uiDiff)
        {
            DoCastSpellIfCan(m_creature->getVictim(), SPELL_CORRUPTED_MIND);
            m_uiCorruptedMindTimer = 62000;
        }
        else
            m_uiCorruptedMindTimer -= uiDiff;

        // Poison Aura
        if (m_uiPoisonAuraTimer < uiDiff)
        {
            DoCastSpellIfCan(m_creature->getVictim(), SPELL_POISON_AURA);
            m_uiPoisonAuraTimer = 60000;
        }
        else
            m_uiPoisonAuraTimer -= uiDiff;

        // Inevitable Doom
        if (m_uiInevitableDoomTimer < uiDiff)
        {
            DoCastSpellIfCan(m_creature->getVictim(), SPELL_INEVITABLE_DOOM);
            m_uiInevitableDoomTimer = 120000;
        }
        else
            m_uiInevitableDoomTimer -= uiDiff;

        // Inevitable Doom 5mins
        if (m_uiInevitableDoom5minsTimer < uiDiff)
        {
            DoCastSpellIfCan(m_creature->getVictim(), SPELL_INEVITABLE_DOOM);
            m_uiInevitableDoom5minsTimer = 15000;
        }
        else
            m_uiInevitableDoom5minsTimer -= uiDiff;

        // Remove Curse
        if (m_uiRemoveCurseTimer < uiDiff)
        {
            DoCastSpellIfCan(m_creature, SPELL_REMOVE_CURSE);
            m_uiRemoveCurseTimer = 30000;
        }
        else
            m_uiRemoveCurseTimer -= uiDiff;

        // Summon
        if (m_uiSummonTimer < uiDiff)
        {
            Unit* pSummonedSpores = NULL;

            pSummonedSpores = m_creature->SummonCreature(16286, ADD_1X, ADD_1Y, ADD_1Z, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            pSummonedSpores = m_creature->SummonCreature(16286, ADD_2X, ADD_2Y, ADD_2Z, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            pSummonedSpores = m_creature->SummonCreature(16286, ADD_3X, ADD_3Y, ADD_3Z, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            if (pSummonedSpores)
            {
                if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
                    pSummonedSpores->AddThreat(pTarget);
            }

            m_uiSummonTimer = 28000;
        }
        else
            m_uiSummonTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
示例#4
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        //MortalWound_Timer
        if (MortalWound_Timer <= diff)
        {
            DoCast(me->getVictim(),SPELL_MORTALWOUND);
            MortalWound_Timer = 10000;
        } else MortalWound_Timer -= diff;

        //Decimate_Timer
        if (Decimate_Timer <= diff)
        {
            DoCast(me->getVictim(),SPELL_DECIMATE);
            Decimate_Timer = 100000;
        } else Decimate_Timer -= diff;

        //TerrifyingRoar_Timer
        if (TerrifyingRoar_Timer <= diff)
        {
            DoCast(me->getVictim(),SPELL_TERRIFYINGROAR);
            TerrifyingRoar_Timer = 20000;
        } else TerrifyingRoar_Timer -= diff;

        //Frenzy_Timer
        if (Frenzy_Timer <= diff)
        {
            DoCast(me,SPELL_FRENZY);
            Frenzy_Timer = 10500;
        } else Frenzy_Timer -= diff;

        //Enrage_Timer
        if (Enrage_Timer <= diff)
        {
            DoCast(me,SPELL_ENRAGE);
            Enrage_Timer = 61000;
        } else Enrage_Timer -= diff;

        //Summon_Timer
        if (Summon_Timer <= diff)
        {
            Unit* pTarget = NULL;
            Unit* SummonedZombies = NULL;

            SummonedZombies = me->SummonCreature(16360,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedZombies = me->SummonCreature(16360,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedZombies = me->SummonCreature(16360,ADD_3X,ADD_3Y,ADD_3Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedZombies = me->SummonCreature(16360,ADD_4X,ADD_4Y,ADD_4Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedZombies = me->SummonCreature(16360,ADD_5X,ADD_5Y,ADD_5Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedZombies = me->SummonCreature(16360,ADD_6X,ADD_6Y,ADD_6Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedZombies = me->SummonCreature(16360,ADD_7X,ADD_7Y,ADD_7Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedZombies = me->SummonCreature(16360,ADD_8X,ADD_8Y,ADD_8Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedZombies = me->SummonCreature(16360,ADD_9X,ADD_9Y,ADD_9Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);

            if (SummonedZombies)
            {
                pTarget = SelectUnit(SELECT_TARGET_RANDOM,0);
                if (pTarget)
                    SummonedZombies->AddThreat(pTarget,1.0f);
            }

            Summon_Timer = 28000;
        } else Summon_Timer -= diff;

        DoMeleeAttackIfReady();
    }
示例#5
0
void PetAI::UpdateAI(const uint32 diff)
{
    if (!m_creature->isAlive())
        return;

    m_updateAlliesTimer.Update(diff);
    if (m_updateAlliesTimer.Passed())
    {
        UpdateAllies();
        m_updateAlliesTimer.Reset();
    }

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

    Unit* owner = m_creature->GetCharmerOrOwner();

    // 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);
                    SpellPowerEntry const* spellPower = spellInfo->GetSpellPower();
                    if (spellPower && (spellPower->manaCost || spellPower->ManaCostPercentage || spellPower->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;
            }
        }
    }
}
示例#6
0
void PetAI::UpdateAI(const uint32 diff)
{
    if (!m_creature->IsAlive())
        return;

    Unit* owner = m_creature->GetCharmerOrOwner();
    Unit* victim = NULL;

    if (!((Pet*)m_creature)->isControlled())
        m_creature->SelectHostileTarget();

    // Creature pets and guardians will always look in threat list for victim
    if (!(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)
        || (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)))
        victim = m_creature->getVictim();

    if (m_updateAlliesTimer <= diff)
        // UpdateAllies self set update timer
        UpdateAllies();
    else
        m_updateAlliesTimer -= diff;

    if (inCombat && !victim)
    {
        m_creature->AttackStop(true);
        inCombat = false;
    }

    if (((Pet*)m_creature)->GetIsRetreating())
    {
        if (!owner->IsWithinDistInMap(m_creature, (PET_FOLLOW_DIST * 2)))
        {
            if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW))
                m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);

            return;
        }
        else
           ((Pet*)m_creature)->SetIsRetreating();
    }
    else if (((Pet*)m_creature)->GetSpellOpener() != 0) // have opener stored
    {
        uint32 minRange = ((Pet*)m_creature)->GetSpellOpenerMinRange();

        if (!(victim = m_creature->getVictim())
            || (minRange != 0 && m_creature->IsWithinDistInMap(victim, minRange)))
            ((Pet*)m_creature)->SetSpellOpener();
        else if (m_creature->IsWithinDistInMap(victim, ((Pet*)m_creature)->GetSpellOpenerMaxRange())
                && m_creature->IsWithinLOSInMap(victim))
        {
            // stop moving
            m_creature->clearUnitState(UNIT_STAT_MOVING);

            // auto turn to target
            m_creature->SetInFront(victim);

            if (victim->GetTypeId() == TYPEID_PLAYER)
                m_creature->SendCreateUpdateToPlayer((Player*)victim);

            if (owner->GetTypeId() == TYPEID_PLAYER)
                m_creature->SendCreateUpdateToPlayer((Player*)owner);

            uint32 spell_id = ((Pet*)m_creature)->GetSpellOpener();
            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);

            Spell* spell = new Spell(m_creature, spellInfo, false);

            SpellCastResult result = spell->CheckPetCast(victim);

            if (result == SPELL_CAST_OK)
            {
                m_creature->AddCreatureSpellCooldown(spell_id);
                spell->SpellStart(&(spell->m_targets));
            }
            else
                delete spell;

            ((Pet*)m_creature)->SetSpellOpener();
        }
        else
            return;
    }
    // Autocast (casted only in combat or persistent spells in any state)
    else 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))
                {
                    int32 duration = GetSpellDuration(spellInfo);
                    SpellPowerEntry const* spellPower = spellInfo->GetSpellPower();
                    if (spellPower && (spellPower->manaCost || spellPower->ManaCostPercentage || spellPower->manaPerSecond) && duration > 0)
                        continue;

                    // allow only spell without cooldown > duration
                    int32 cooldown = GetSpellRecoveryTime(spellInfo);

                    // allow only spell not on cooldown
                    if (cooldown != 0 && duration < cooldown)
                        continue;
                }
            }
            // just ignore non-combat spells
            else if (IsNonCombatSpell(spellInfo))
                continue;

            Spell* spell = new Spell(m_creature, spellInfo, false);

            if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(victim))
            {
                targetSpellStore.push_back(TargetSpellList::value_type(victim, 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);

            spell->SpellStart(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }

    // Guardians will always look in threat list for victim
    if (!((Pet*)m_creature)->isControlled())
        m_creature->SelectHostileTarget();

    if (!(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)
        || (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)))
        victim = m_creature->getVictim();

    // Stop here if casting spell (No melee and no movement)
    if (m_creature->IsNonMeleeSpellCasted(false))
        return;

    if (victim)
    {
        // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
        // This is needed for charmed creatures, as once their target was reset other effects can trigger threat
        if ((m_creature->IsCharmed() && victim == m_creature->GetCharmer()) || !victim->IsTargetableForAttack())
        {
            DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_creature->GetGUIDLow());
            m_creature->CombatStop();
            inCombat = false;
            
            return;
        }

        // if pet misses its target, it will also be the first in threat list
        if (!(m_creature->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_MELEE)
            && m_creature->CanReachWithMeleeAttack(victim))
        {
            if (!m_creature->HasInArc(2 * M_PI_F / 3, victim))
            {
                m_creature->SetInFront(victim);
                if (victim->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer((Player*)victim);

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer((Player*)owner);
            }

            if (DoMeleeAttackIfReady())
                victim->AddThreat(m_creature);
        }
        else if (!(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)
            || m_creature->hasUnitState(UNIT_STAT_MOVING)))
            AttackStart(victim);
    }
    else if (owner)
    {
        CharmInfo* charmInfo = m_creature->GetCharmInfo();

        if (owner->IsInCombat() && !(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE)
            || (charmInfo && charmInfo->HasReactState(REACT_PASSIVE))))
            AttackStart(owner->getAttackerForHelper());
        else if (!m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
        {
            if (charmInfo && charmInfo->HasCommandState(COMMAND_STAY))
            {
                if (Pet* pet = (Pet*)m_creature)
                {
                    //if stay command is set but we dont have stay pos set then we need to establish current pos as stay position
                    if (!pet->IsStayPosSet())
                        pet->SetStayPosition(true);

                    float stayPosX = pet->GetStayPosX();
                    float stayPosY = pet->GetStayPosY();
                    float stayPosZ = pet->GetStayPosZ();

                    if (m_creature->GetPositionX() == stayPosX
                        && m_creature->GetPositionY() == stayPosY
                        && m_creature->GetPositionZ() == stayPosZ)
                    {
                        float StayPosO = pet->GetStayPosO();

                        if (m_creature->hasUnitState(UNIT_STAT_MOVING))
                        {
                            m_creature->GetMotionMaster()->Clear(false);
                            m_creature->GetMotionMaster()->MoveIdle();
                        }
                        else if (m_creature->GetOrientation() != StayPosO)
                            m_creature->SetOrientation(StayPosO);
                    }
                    else
                        pet->GetMotionMaster()->MovePoint(0, stayPosX, stayPosY, stayPosZ, false);
                }
            }
            else if (m_creature->hasUnitState(UNIT_STAT_FOLLOW))
            {
                if (owner->IsWithinDistInMap(m_creature, PET_FOLLOW_DIST))
                {
                    m_creature->GetMotionMaster()->Clear(false);
                    m_creature->GetMotionMaster()->MoveIdle();
                }
            }
            else if (charmInfo && charmInfo->HasCommandState(COMMAND_FOLLOW)
                && !owner->IsWithinDistInMap(m_creature, (PET_FOLLOW_DIST * 2)))
                m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
        }
    }
}
示例#7
0
文件: PetAI.cpp 项目: Ccaz/mangos-tbc
void PetAI::UpdateAI(const uint32 diff)
{
    if (!m_creature->isAlive())
        return;

    Unit* owner = m_creature->GetCharmerOrOwner();
    Unit* victim = m_creature->getVictim();

    if (m_updateAlliesTimer <= diff)
        // UpdateAllies self set update timer
        UpdateAllies();
    else
        m_updateAlliesTimer -= diff;

    if (inCombat && (!victim || (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)))
        _stopAttack();

    if (((Pet*)m_creature)->GetIsRetreating())
    {
        if (!owner->_IsWithinDist(m_creature, (PET_FOLLOW_DIST * 2), true))
        {
            if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW))
                m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);

            return;
        }
        else
           ((Pet*)m_creature)->SetIsRetreating();
    }
    else if (((Pet*)m_creature)->GetSpellOpener() != 0) // have opener stored
    {
        uint32 minRange = ((Pet*)m_creature)->GetSpellOpenerMinRange();

        if (!(victim = m_creature->getVictim())
            || (minRange != 0 && m_creature->IsWithinDistInMap(victim, minRange)))
            ((Pet*)m_creature)->SetSpellOpener();
        else if (m_creature->IsWithinDistInMap(victim, ((Pet*)m_creature)->GetSpellOpenerMaxRange()) && m_creature->IsWithinLOSInMap(victim))
        {
            // stop moving
            m_creature->clearUnitState(UNIT_STAT_MOVING);

            // auto turn to target
            m_creature->SetInFront(victim);

            if (victim->GetTypeId() == TYPEID_PLAYER)
                m_creature->SendCreateUpdateToPlayer((Player*)victim);

            if (owner->GetTypeId() == TYPEID_PLAYER)
                m_creature->SendCreateUpdateToPlayer((Player*)owner);

            uint32 spell_id = ((Pet*)m_creature)->GetSpellOpener();
            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);

            Spell* spell = new Spell(m_creature, spellInfo, false);

            SpellCastResult result = spell->CheckPetCast(victim);

            if (result == SPELL_CAST_OK)
            {
                m_creature->AddCreatureSpellCooldown(spell_id);

                spell->SpellStart(&(spell->m_targets));
            }
            else
                delete spell;

            ((Pet*)m_creature)->SetSpellOpener();
        }

        else
            return;
    }
    // Autocast (casted only in combat or persistent spells in any state)
    else 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))
                {
                    int32 duration = GetSpellDuration(spellInfo);
                    int32 cooldown = GetSpellRecoveryTime(spellInfo);

                    // allow only spell not on cooldown
                    if (cooldown != 0 && duration < cooldown)
                        continue;

                    // not allow instant kill autocasts as full health cost
                    if (IsSpellHaveEffect(spellInfo, SPELL_EFFECT_INSTAKILL))
                        continue;
                }
            }
            // just ignore non-combat spells
            else 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->SpellStart(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }
    else if (m_creature->hasUnitState(UNIT_STAT_FOLLOW_MOVE))
        m_creature->InterruptNonMeleeSpells(false);

    if (victim = m_creature->getVictim())
    {
        // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
        if (_needToStop())
        {
            DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_creature->GetGUIDLow());
            _stopAttack();
            return;
        }

        // 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 if (m_creature->CanReachWithMeleeAttack(victim))
        {
            if (DoMeleeAttackIfReady())
                // if pet misses its target, it will also be the first in threat list
                victim->AddThreat(m_creature);
            else
                AttackStart(victim);
        }
    }
    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))
        {
            // The distance is to prevent the pet from running around to reach the owners back when  walking towards it
            //  and the reason for increasing it more than the follow distance is to prevent the same thing
            // from happening when the owner turns and twists (as this increases the distance between them)
            if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW) && !owner->IsWithinDistInMap(m_creature, (PET_FOLLOW_DIST * 2)))
                m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
            // This is to stop the pet from following you when you're close to each other, to support the above condition.
            else if (m_creature->hasUnitState(UNIT_STAT_FOLLOW))
            {
                m_creature->GetMotionMaster()->Clear(false);
                m_creature->GetMotionMaster()->MoveIdle();
            }
        }
    }
}
示例#8
0
    void createClassMirrors() 
    {
		for (int i = 0; i <= 5; i++)
		{
            Map* pMap = m_creature->GetMap();
            Map::PlayerList const &players = pMap->GetPlayers();
		    for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) 
			{ 
                if(Unit* target = m_creature->GetMap()->GetUnit(itr->getSource()->GetGUID())) 
				{ 
			        Unit* pClone = m_creature->SummonCreature(m_bIsRegularMode ? CLONE : CLONE_H, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                    if (pClone) 
                    {
                        pClone->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PASSIVE);
                        pClone->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NOT_SELECTABLE);
                        pClone->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE);
                        pClone->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_UNK_6);
					    pClone->SetDisplayId(target->GetNativeDisplayId());
					    pClone->SetName(target->GetName());
                        pClone->setFaction(FAC_HOSTILE);

					    switch (target->getClass()) 
					    { 
						    case CLASS_PRIEST: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_PRIEST : CLONE_HEALTH_PRIEST_H); break;
                            case CLASS_PALADIN: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_PALA : CLONE_HEALTH_PALA_H); break;
    					    case CLASS_WARLOCK: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_WARLOCK : CLONE_HEALTH_WARLOCK_H); break;
    					    case CLASS_MAGE: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_MAGE : CLONE_HEALTH_MAGE_H); break;
						    case CLASS_ROGUE: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_ROGUE : CLONE_HEALTH_ROGUE_H); break;
					        case CLASS_WARRIOR: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_WARRIOR : CLONE_HEALTH_WARRIOR_H); break;
						    case CLASS_DRUID: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_DRUID : CLONE_HEALTH_DRUID_H); break;
						    case CLASS_SHAMAN: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_SHAMAN : CLONE_HEALTH_SHAMAN_H); break;
						    case CLASS_HUNTER: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_HUNT : CLONE_HEALTH_HUNT_H); break;
						    case CLASS_DEATH_KNIGHT: pClone->SetMaxHealth(m_bIsRegularMode ? CLONE_HEALTH_DK : CLONE_HEALTH_DK_H); break;
                            default: break;
                        }

                        pClone->SetHealth(pClone->GetMaxHealth()); 
					    pClone->Attack(target, true); 
					    pClone->AddThreat(target, 10.0f);
					    cloneGUIDList.push_back(pClone->GetGUID()); 
				    } 

				    switch(i)
				    {
					    case 1:
						    pClone->SetPhaseMask(16, true);
						    clone16GUIDList.push_back(pClone->GetGUID());
						    break;
					    case 2:
						    pClone->SetPhaseMask(32, true);
						    clone32GUIDList.push_back(pClone->GetGUID());
						    break;
					    case 3:
						    pClone->SetPhaseMask(64, true);
						    clone64GUIDList.push_back(pClone->GetGUID());
						    break;
					    case 4:
						    pClone->SetPhaseMask(128, true);
						    clone128GUIDList.push_back(pClone->GetGUID());
						    break;
					    case 5:
						    pClone->SetPhaseMask(256, true);
						    clone256GUIDList.push_back(pClone->GetGUID());
						    break;
					    default:
						    break;
					} 
				} 
			} 
		}
    } 
示例#9
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (!m_bFirstPlanar && !m_bIsRegularMode && m_creature->GetHealthPercent() < 50.0f)
        {
            m_bFirstPlanar = true;
            Events.ScheduleEvent(EVENT_PLANAR_SHIFT, 0);
        }

        if (!m_bSecondPlanar && !m_bIsRegularMode &&  m_creature->GetHealthPercent() < 25.0f)
        {
            m_bSecondPlanar = true;
            Events.ScheduleEvent(EVENT_PLANAR_SHIFT, 0);
        }

        if (m_creature->GetDistance2d(m_creature->getVictim()) > 35.0f && !m_bIsMove)
        {
           m_bIsMove = true;
           SetCombatMovement(m_bIsMove);
           if (Unit* pTarget = m_creature->getVictim())
              m_creature->GetMotionMaster()->MoveChase(pTarget);
        }

        if (m_creature->GetDistance2d(m_creature->getVictim()) < 20.0f && m_bIsMove)
        {
           m_bIsMove = false;
           SetCombatMovement(m_bIsMove);
           m_creature->GetMotionMaster()->Clear(false);
           m_creature->GetMotionMaster()->MoveIdle();
           m_creature->StopMoving();
        }

        Events.Update(uiDiff);
        while (uint32 uiEventId = Events.ExecuteEvent())
            switch (uiEventId)
            {
                case EVENT_DRAKE_COLOR_CHECK:
                    CheckDrakeColors();
                    break;
                case EVENT_ARCANE_BARRAGE:
                    DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ARCANE_BARRAGE_N : SPELL_ARCANE_BARRAGE_H);
                    break;
                case EVENT_ARCANE_VOLLEY:
                    DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ARCANE_VOLLEY_N : SPELL_ARCANE_VOLLEY_H);
                    break;
                case EVENT_PLANAR_SHIFT:
                    m_creature->MonsterTextEmote(EMOTE_PLANAR_SHIFT, m_creature, true);
                    Events.DelayEvents(18*IN_MILLISECONDS);
                    m_creature->InterruptNonMeleeSpells(false);
                    DoCast(m_creature, SPELL_PLANAR_SHIFT, false);
                    Events.ScheduleEvent(EVENT_ENRAGED_ASSAULT, 19*IN_MILLISECONDS);
                    Events.ScheduleEvent(EVENT_PLANAR_ANOMALITIES, 2*IN_MILLISECONDS);
                    break;
                case EVENT_ENRAGED_ASSAULT:
                    DoCast(m_creature, SPELL_ENRAGED_ASSAULT, true);
                    break;
                case EVENT_PLANAR_ANOMALITIES:
                    DoCast(m_creature, SPELL_PLANAR_ANOMALIES, true);
                    break;
                case EVENT_SUMMON_DRAKES:
                    if (SummonMgr.GetSummonCount(NPC_DRAGON) > MAX_DRAGON_COUNT)
                        break;
                    for (int i = 0 ; i < 3 ; i++)
                    {
                        //DoCast(m_creature, SPELL_SUMMON_DRAKE, true); // summoned @ ground position
                        Unit* pSumm =  SummonMgr.SummonCreature(NPC_DRAGON, m_creature->GetPositionX() - 5 + urand(0, 10), m_creature->GetPositionY() - 5 + urand(0, 10),
                            m_creature->GetPositionZ() - 5 + urand(0, 10), 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
                        if (Unit* pPlayer = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM_PLAYER, 0))
                        {
                            if (pPlayer->GetVehicle())
                                if (Unit* pDrake = pPlayer->GetVehicle()->GetBase())
                                {
                                    pSumm->AddThreat(pDrake, 10000.0f);
                                    pSumm->GetMotionMaster()->MoveIdle();
                                    pSumm->StopMoving();
                                    pSumm->GetMotionMaster()->MoveChase(pDrake, 20.0f);
                                }
                        }
                    }
                    break;
                default:
                    break;
            }

        DoMeleeAttackIfReady();
    }
    void UpdateAI(const uint32 diff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (EnfeebleResetTimer)
        {
            if (EnfeebleResetTimer <= diff)                  //Let's not forget to reset that
            {
                EnfeebleResetHealth();
                EnfeebleResetTimer=0;
            } else EnfeebleResetTimer -= diff;
        }

        if (m_creature->hasUnitState(UNIT_STAT_STUNNED))    //While shifting to phase 2 malchezaar stuns himself
            return;

        if (m_creature->GetUInt64Value(UNIT_FIELD_TARGET)!=m_creature->getVictim()->GetGUID())
            m_creature->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->getVictim()->GetGUID());

        if (phase == 1)
        {
            if (m_creature->GetHealthPercent() < 60.0f)
            {
                m_creature->InterruptNonMeleeSpells(false);

                phase = 2;

                //animation
                DoCastSpellIfCan(m_creature, SPELL_EQUIP_AXES);

                //text
                DoScriptText(SAY_AXE_TOSS1, m_creature);

                //passive thrash aura
                m_creature->CastSpell(m_creature, SPELL_THRASH_AURA, true);

                //models
                SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE);

                //damage
                const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
                m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg);
                m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg);
                m_creature->UpdateDamagePhysical(BASE_ATTACK);

                m_creature->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg);
                m_creature->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg);
                //Sigh, updating only works on main attack , do it manually ....
                m_creature->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg);
                m_creature->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg);

                m_creature->SetAttackTime(OFF_ATTACK, (m_creature->GetAttackTime(BASE_ATTACK)*150)/100);
            }
        }
        else if (phase == 2)
        {
            if (m_creature->GetHealthPercent() < 30.0f)
            {
                InfernalTimer = 15000;

                phase = 3;

                ClearWeapons();

                //remove thrash
                m_creature->RemoveAurasDueToSpell(SPELL_THRASH_AURA);

                DoScriptText(SAY_AXE_TOSS2, m_creature);

                Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                for(uint32 i=0; i<2; ++i)
                {
                    Creature *axe = m_creature->SummonCreature(MALCHEZARS_AXE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000);
                    if (axe)
                    {
                        axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                        axe->setFaction(m_creature->getFaction());

                        axes[i] = axe->GetGUID();
                        if (target)
                        {
                            axe->AI()->AttackStart(target);
                            // axe->getThreatManager().tauntApply(target); //Taunt Apply and fade out does not work properly
                                                            // So we'll use a hack to add a lot of threat to our target
                            axe->AddThreat(target, 10000000.0f);
                        }
                    }
                }

                if (ShadowNovaTimer > 35000)
                    ShadowNovaTimer = EnfeebleTimer + 5000;

                return;
            }

            if (SunderArmorTimer < diff)
            {
                DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUNDER_ARMOR);
                SunderArmorTimer = urand(10000, 18000);

            }else SunderArmorTimer -= diff;

            if (Cleave_Timer < diff)
            {
                DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
                Cleave_Timer = urand(6000, 12000);

            }else Cleave_Timer -= diff;
        }
        else
        {
            if (AxesTargetSwitchTimer < diff)
            {
                AxesTargetSwitchTimer = urand(7500, 20000);

                Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                if (target)
                {
                    for(int i = 0; i < 2; ++i)
                    {
                        Unit *axe = Unit::GetUnit(*m_creature, axes[i]);
                        if (axe)
                        {
                            float threat = 1000000.0f;
                            if (axe->getVictim() && m_creature->getThreatManager().getThreat(axe->getVictim()))
                            {
                                threat = axe->getThreatManager().getThreat(axe->getVictim());
                                axe->getThreatManager().modifyThreatPercent(axe->getVictim(), -100);
                            }
                            if (target)
                                axe->AddThreat(target, threat);
                            //axe->getThreatManager().tauntFadeOut(axe->getVictim());
                            //axe->getThreatManager().tauntApply(target);
                        }
                    }
                }
            } else AxesTargetSwitchTimer -= diff;

            if (AmplifyDamageTimer < diff)
            {
                if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
                    DoCastSpellIfCan(pTarget, SPELL_AMPLIFY_DAMAGE);

                AmplifyDamageTimer = urand(20000, 30000);
            }else AmplifyDamageTimer -= diff;
        }

        //Time for global and double timers
        if (InfernalTimer < diff)
        {
            SummonInfernal(diff);
            InfernalTimer =  phase == 3 ? 14500 : 44500;    //15 secs in phase 3, 45 otherwise
        }else InfernalTimer -= diff;

        if (ShadowNovaTimer < diff)
        {
            DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOWNOVA);
            ShadowNovaTimer = phase == 3 ? 31000 : -1;
        } else ShadowNovaTimer -= diff;

        if (phase != 2)
        {
            if (SWPainTimer < diff)
            {
                Unit* target = NULL;
                if (phase == 1)
                    target = m_creature->getVictim();       // the tank
                else                                        //anyone but the tank
                    target = SelectUnit(SELECT_TARGET_RANDOM, 1);

                if (target)
                    DoCastSpellIfCan(target, SPELL_SW_PAIN);

                SWPainTimer = 20000;
            }else SWPainTimer -= diff;
        }

        if (phase != 3)
        {
            if (EnfeebleTimer < diff)
            {
                EnfeebleHealthEffect();
                EnfeebleTimer = 30000;
                ShadowNovaTimer = 5000;
                EnfeebleResetTimer = 9000;
            }else EnfeebleTimer -= diff;
        }

        if (phase==2)
            DoMeleeAttacksIfReady();
        else
            DoMeleeAttackIfReady();
    }
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // Necrotic Aura
        if ( NecroticAuraTimer < uiDiff)
        {
            DoCast(m_creature->getVictim(),SPELL_NECROTIC_AURA);
            NecroticAuraTimer = 20000;
        }else NecroticAuraTimer -= uiDiff;

        // Necrotic Aura fade warning
        if ( NecroticAuraFadeWarning < uiDiff)
        {
            DoScriptText(SAY_NECROTIC_AURA_FADE, m_creature);
            NecroticAuraFadeWarning = 20000;
        }else NecroticAuraFadeWarning -= uiDiff;

        // Deathbloom
        if ( DeathbloomTimer < uiDiff)
        {
            DoCast(m_creature, m_bIsRegularMode ? SPELL_DEATHBLOOM: H_SPELL_DEATHBLOOM);
            DeathbloomTimer = 30000;
        }else DeathbloomTimer -= uiDiff;

        // Inevitable Doom
        if ( InevitableDoomTimer < uiDiff)
        {
            DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_INEVITABLE_DOOM : H_SPELL_INEVITABLE_DOOM);
            InevitableDoomTimer = 120000 - ( IDoomCount* IDoomTimeShortage);
            IDoomCount ++;
        }else InevitableDoomTimer -= uiDiff;

        // Inevitable Doom 7mins
        if ( IDoom7minsTimer < uiDiff)
        {
            DoCast(m_creature->getVictim(), SPELL_INEVITABLE_DOOM);
            IDoom7minsTimer = 15000;
        }else IDoom7minsTimer -= uiDiff;

        // Summon
        if ( SummonTimer < uiDiff)
        {
            Unit* pSummonedSpores = NULL;

            pSummonedSpores = m_creature->SummonCreature(16286,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            pSummonedSpores = m_creature->SummonCreature(16286,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            pSummonedSpores = m_creature->SummonCreature(16286,ADD_3X,ADD_3Y,ADD_3Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            if (pSummonedSpores)
            {
                if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
                    pSummonedSpores->AddThreat(pTarget);
            }

             SummonTimer = 28000;
        }
        else
             SummonTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
示例#12
0
    void UpdateAI(const uint32 diff)
    {
        //Return since we have no target
        if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
            return;

        //MortalWound_Timer
        if (MortalWound_Timer < diff)
        {
            //Cast
            DoCast(m_creature->getVictim(),SPELL_MORTALWOUND);

            //10 seconds
            MortalWound_Timer = 10000;
        }else MortalWound_Timer -= diff;

        //Decimate_Timer
        if (Decimate_Timer < diff)
        {
            //Cast
            DoCast(m_creature,SPELL_DECIMATE);

            Unit* Temp = NULL;
            std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
            for (; i != m_creature->getThreatManager().getThreatList().end(); ++i)
            {
                Temp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid());
                if (Temp )
                    Temp->SetHealth(Temp->GetMaxHealth()* 0.05);
            }
            //105 seconds until we should cast this agian
            Decimate_Timer = 105000;
        }else Decimate_Timer -= diff;

        //TerrifyingRoar_Timer
        if (TerrifyingRoar_Timer < diff)
        {
            //Cast
            DoCast(m_creature->getVictim(),SPELL_TERRIFYINGROAR);

            //20 seconds until we should cast this agian
            TerrifyingRoar_Timer = 20000;
        }else TerrifyingRoar_Timer -= diff;

        //Frenzy_Timer
        if (Frenzy_Timer < diff)
        {
            //Cast
            DoCast(m_creature,SPELL_FRENZY);

            //10.5 seconds until we should cast this agian
            Frenzy_Timer = 10500;
        }else Frenzy_Timer -= diff;

        if (Enrage_Timer < diff)
        {
            //Cast
            DoCast(m_creature,SPELL_ENRAGE);

            //61 seconds until we should cast this agian
            Enrage_Timer = 61000;
        }else Enrage_Timer -= diff;

        //Summon_Timer
        if (Summon_Timer < diff)
        {

            Unit* target = NULL;
            Unit* SummonedZombies = NULL;

            for (int i = 0; i < 6; i++);
            {
                switch (rand()%9)
                {
                case 0:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                    break;
                case 1:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                case 2:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_3X,ADD_3Y,ADD_3Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                    break;
                case 3:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_4X,ADD_4Y,ADD_4Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                    break;
                case 4:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_5X,ADD_5Y,ADD_5Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                    break;
                case 5:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_6X,ADD_6Y,ADD_6Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                    break;
                case 6:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_7X,ADD_7Y,ADD_7Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                    break;
                case 7:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_8X,ADD_8Y,ADD_8Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000); 
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                    break;
                case 8:
                    SummonedZombies = m_creature->SummonCreature(16360,ADD_9X,ADD_9Y,ADD_9Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
                    if (SummonedZombies)
                    {
                        target = SelectUnit(SELECT_TARGET_RANDOM,0);
                        if (target)
                            SummonedZombies->AddThreat(target,0.0f);
                    }
                    break;
                }
            }

            //24 seconds until we should cast this agian
            Summon_Timer = 120000;
        } else Summon_Timer -= diff;

        DoMeleeAttackIfReady();
    }
示例#13
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        //CorruptedMind_Timer
        if (CorruptedMind_Timer < diff)
        {
            DoCast(m_creature->getVictim(),SPELL_CORRUPTED_MIND);
            CorruptedMind_Timer = 62000;
        }else CorruptedMind_Timer -= diff;

        //PoisonAura_Timer
        if (PoisonAura_Timer < diff)
        {
            DoCast(m_creature->getVictim(),SPELL_POISON_AURA);
            PoisonAura_Timer = 60000;
        }else PoisonAura_Timer -= diff;

        //InevitableDoom_Timer
        if (InevitableDoom_Timer < diff)
        {
            DoCast(m_creature->getVictim(),SPELL_INEVITABLE_DOOM);
            InevitableDoom_Timer = 120000;
        }else InevitableDoom_Timer -= diff;

        //InevitableDoom5mins_Timer
        if (InevitableDoom5mins_Timer < diff)
        {
            DoCast(m_creature->getVictim(),SPELL_INEVITABLE_DOOM);
            InevitableDoom5mins_Timer = 15000;
        }else InevitableDoom5mins_Timer -= diff;

        //RemoveCurse_Timer
        if (RemoveCurse_Timer < diff)
        {
            DoCast(m_creature,SPELL_REMOVE_CURSE);
            RemoveCurse_Timer = 30000;
        }else RemoveCurse_Timer -= diff;

        //Summon_Timer
        if (Summon_Timer < diff)
        {
            Unit* target = NULL;
            Unit* SummonedSpores = NULL;

            SummonedSpores = m_creature->SummonCreature(16286,ADD_1X,ADD_1Y,ADD_1Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedSpores = m_creature->SummonCreature(16286,ADD_2X,ADD_2Y,ADD_2Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            SummonedSpores = m_creature->SummonCreature(16286,ADD_3X,ADD_3Y,ADD_3Z,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,80000);
            if (SummonedSpores)
            {
                target = SelectUnit(SELECT_TARGET_RANDOM,0);
                if (target)
                    SummonedSpores->AddThreat(target,1.0f);
            }

            Summon_Timer = 28000;
        } else Summon_Timer -= diff;

        DoMeleeAttackIfReady();
    }
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        switch(stage)
        {
            case 0: {
                bsw->timedCast(SPELL_POUND, uiDiff);
                bsw->timedCast(SPELL_COLD, uiDiff);
                if (bsw->timedQuery(SUMMON_BORROWER, uiDiff)) {
                        bsw->doCast(SUMMON_BORROWER);
                        DoScriptText(-1713556,m_creature);
                        };
                if (bsw->timedQuery(SPELL_SUBMERGE_0, uiDiff)) stage = 1;

                    break;}
            case 1: {
                    bsw->doCast(SPELL_SUBMERGE_0);
                    m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    stage = 2;
                    DoScriptText(-1713557,m_creature);
                    break;}
            case 2: {
                    if (bsw->timedQuery(SPELL_SPIKE_CALL, uiDiff)) {
                         pTarget = bsw->SelectUnit();
//                         bsw->doCast(SPELL_SPIKE_CALL);
                         Unit* spike = bsw->doSummon(NPC_SPIKE,TEMPSUMMON_TIMED_DESPAWN,60000);
//                         Creature* spike = GetClosestCreatureWithEntry(m_creature, NPC_SPIKE, 50.0f);
                         if (spike) { spike->AddThreat(pTarget, 1000.0f);
                                      DoScriptText(-1713558,m_creature,pTarget);
                                      bsw->doCast(SPELL_MARK,pTarget);
                                      spike->GetMotionMaster()->MoveChase(pTarget);
                                     }
                         };
                    if (bsw->timedQuery(SPELL_SUMMON_BEATLES, uiDiff)) {
                            bsw->doCast(SPELL_SUMMON_BEATLES);
                            bsw->doCast(SUMMON_SCARAB);
                            DoScriptText(-1713560,m_creature);
                         };
                    if (bsw->timedQuery(SPELL_SUBMERGE_0, uiDiff)) stage = 3;
                    break;}
            case 3: {
                    stage = 0;
                    DoScriptText(-1713559,m_creature);
                    m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    bsw->doRemove(SPELL_SUBMERGE_0,m_creature);
                    break;}
            case 4: {
                            bsw->doCast(SPELL_LEECHING_SWARM);
                            DoScriptText(-1713561,m_creature);
                    stage = 5;
                    break;}
            case 5: {
                        bsw->timedCast(SPELL_POUND, uiDiff);
                        bsw->timedCast(SPELL_COLD, uiDiff);
                        break;}

        }
        bsw->timedCast(SUMMON_FROSTSPHERE, uiDiff);

        bsw->timedCast(SPELL_BERSERK, uiDiff);

        if (m_creature->GetHealthPercent() < 30.0f && stage == 0) stage = 4;

        DoMeleeAttackIfReady();
    }
示例#15
0
    void UpdateAI(const uint32 diff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        int i;

        //PHASE 1
        if(phase==1)
        {
            if(Phase_Timer < diff)
            {
                phase = 2;
                Phase_Timer = 60000; //phase 2 lasts 60 seconds
            }
            else Phase_Timer -= diff;

            //summon trainees
            if(Trainee_Timer < diff)
            {
                for(i=0; i<trainees; i++)
                {
                    Unit *mob = m_creature->SummonCreature(CR_UN_TRAINEE, LiveX[i], LiveY[i], LiveZ[i], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
                    Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                    if(mob && target) mob->AddThreat(target, 1.0f);
                }
                Trainee_Timer = 15000;
            }
            else Trainee_Timer -= diff;

            //summon death knights
            if(DeathKnight_Timer < diff)
            {
                i = irand(0,2);
                Unit *mob = m_creature->SummonCreature(CR_UN_DEATHKNIGHT, LiveX[i], LiveY[i], LiveZ[i], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
                Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                if(mob && target) mob->AddThreat(target, 1.0f);
                DeathKnight_Timer = 30000;
            }
            else DeathKnight_Timer -= diff;

            //summon rider
            if(Rider_Timer < diff)
            {
                i = irand(0,2);
                Unit *mob = m_creature->SummonCreature(CR_UN_RIDER, LiveX[i], LiveY[i], LiveZ[i], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
                Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                if(mob && target) mob->AddThreat(target, 1.0f);
                Rider_Timer = 45000;
            }
            else Rider_Timer -= diff;
        }

        //PHASE 2
        if(phase==2)
        {
            if(Phase_Timer < diff)
            {
                //teleport gothik down
                m_creature->NearTeleportTo(UNDEAD_X, UNDEAD_Y, UNDEAD_Z, 0);
                Phase_Timer = 15000;
                phase = 3;

                SetCombatMovement(true);
                m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
            }
            else Phase_Timer -= diff;
        }

        //PHASE 3,4
        if(phase==3 || phase==4)
        {
            if(Phase_Timer < diff)
            {
                //cast Harvest Soul (-10% stats to the raid)
                Unit* target = NULL;
                ThreatList const& tList = m_creature->getThreatManager().getThreatList();
                for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
                {
                    if (Unit* target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid()))
                        if(target->isAlive())
                            DoCast(target, SP_HARVEST_SOUL, true);
                }
                //teleport gothik to the other side
                if(phase==3)
                    m_creature->NearTeleportTo(LIVE_X, LIVE_Y, LIVE_Z, 0);
                else
                    m_creature->NearTeleportTo(UNDEAD_X, UNDEAD_Y, UNDEAD_Z, 0);

                Phase_Timer = 15000;
                phase = (phase==3) ? 4 : 3;
            }
            else Phase_Timer -= diff;

            //cast shadowbolts
            if(Shadowbolt_Timer < diff)
            {
                DoCast(m_creature->getVictim(), Regular ? SP_SHADOWBOLT : H_SP_SHADOWBOLT);
                Shadowbolt_Timer = 1200;
            }
            else Shadowbolt_Timer -= diff;

            //if 30% left, stop teleporting
            if ((m_creature->GetHealth()*100) / m_creature->GetMaxHealth() <= 30)
            {
                phase=5;
                if(pInstance) pInstance->SetData(TYPE_GOTHIK, SPECIAL);
            }
        }

        //PHASE 5
        if(phase==5)
        {
            if(Shadowbolt_Timer < diff)
            {
                DoCast(m_creature->getVictim(), Regular ? SP_SHADOWBOLT : H_SP_SHADOWBOLT);
                Shadowbolt_Timer = 1200;
            }
            else Shadowbolt_Timer -= diff;
        }
    }