void AssistanceMovementGenerator::Finalize(Unit &unit)
{
    ((Creature*)&unit)->SetNoCallAssistance(false);
    ((Creature*)&unit)->CallAssistance();
    if (unit.isAlive())
        unit.GetMotionMaster()->MoveSeekAssistanceDistract(sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY));
}
        void UpdateAI(uint32 diff) override
        {
            if (!UpdateVictim())
                return;

            if (BerserkTimer <= diff)
            {
                Talk(SAY_BERSERK);
                DoCast(me, SPELL_BERSERK, true);
                BerserkTimer = 60000;
            } else BerserkTimer -= diff;

            if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE)
            {
                if (SaberlashTimer <= diff)
                {
                    // A tank with more than 490 defense skills should receive no critical hit
                    //DoCast(me, 41296, true);
                    DoCastVictim(SPELL_SABER_LASH, true);
                    //me->RemoveAurasDueToSpell(41296);
                    SaberlashTimer = 30000;
                } else SaberlashTimer -= diff;

                if (FrenzyTimer <= diff)
                {
                    DoCast(me, SPELL_FRENZY);
                    FrenzyTimer = urand(10000, 15000);
                } else FrenzyTimer -= diff;

                if (Phase == PHASE_LYNX)
                {
                    if (CheckTimer <= diff)
                    {
                        if (HealthBelowPct(25 * (3 - TransformCount)))
                            EnterPhase(PHASE_SPLIT);
                        CheckTimer = 1000;
                    } else CheckTimer -= diff;
                }
            }

            if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE)
            {
                if (TotemTimer <= diff)
                {
                    DoCast(me, SPELL_SUMMON_TOTEM);
                    TotemTimer = 20000;
                } else TotemTimer -= diff;

                if (ShockTimer <= diff)
                {
                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                    {
                        if (target->IsNonMeleeSpellCast(false))
                            DoCast(target, SPELL_EARTHSHOCK);
                        else
                            DoCast(target, SPELL_FLAMESHOCK);
                        ShockTimer = urand(10000, 15000);
                    }
                } else ShockTimer -= diff;

                if (Phase == PHASE_HUMAN)
                {
                    if (CheckTimer <= diff)
                    {
                        if (!HealthAbovePct(20) /*HealthBelowPct(10)*/)
                            EnterPhase(PHASE_MERGE);
                        else
                        {
                            Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
                            if (Lynx && !Lynx->HealthAbovePct(20) /*Lynx->HealthBelowPct(10)*/)
                                EnterPhase(PHASE_MERGE);
                        }
                        CheckTimer = 1000;
                    } else CheckTimer -= diff;
                }
            }

            if (Phase == PHASE_MERGE)
            {
                if (CheckTimer <= diff)
                {
                    Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
                    if (Lynx)
                    {
                        Lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
                        me->GetMotionMaster()->MoveFollow(Lynx, 0, 0);
                        if (me->IsWithinDistInMap(Lynx, 6.0f))
                        {
                            if (TransformCount < 3)
                                EnterPhase(PHASE_LYNX);
                            else
                                EnterPhase(PHASE_ENRAGE);
                        }
                    }
                    CheckTimer = 1000;
                } else CheckTimer -= diff;
            }

            DoMeleeAttackIfReady();
        }
Example #3
1
void WorldSession::HandlePetAction(WorldPacket& recv_data)
{
    ObjectGuid petGuid;
    uint32 data;
    ObjectGuid targetGuid;
    recv_data >> petGuid;
    recv_data >> data;
    recv_data >> targetGuid;

    uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data);
    uint8 flag = UNIT_ACTION_BUTTON_TYPE(data);             // delete = 0x07 CastSpell = C1

    DETAIL_LOG("HandlePetAction: %s flag is %u, spellid is %u, target %s.", petGuid.GetString().c_str(), uint32(flag), spellid, targetGuid.GetString().c_str());

    // used also for charmed creature/player
    Unit* pet = _player->GetMap()->GetUnit(petGuid);
    if (!pet)
    {
        sLog.outError("HandlePetAction: %s not exist.", petGuid.GetString().c_str());
        return;
    }

    if (GetPlayer()->GetObjectGuid() != pet->GetCharmerOrOwnerGuid())
    {
        sLog.outError("HandlePetAction: %s isn't controlled by %s.", petGuid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str());
        return;
    }

    if (!pet->isAlive())
        return;

    if (pet->GetTypeId() == TYPEID_PLAYER)
    {
        // controller player can only do melee attack
        if (!(flag == ACT_COMMAND && spellid == COMMAND_ATTACK))
            return;
    }
    else if (((Creature*)pet)->IsPet())
    {
        // pet can have action bar disabled
        if (((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
            return;
    }

    CharmInfo* charmInfo = pet->GetCharmInfo();
    if (!charmInfo)
    {
        sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
        return;
    }

    switch (flag)
    {
    case ACT_COMMAND:                                   // 0x07
        switch (spellid)
        {
        case COMMAND_STAY:                          // flat=1792  // STAY
            pet->StopMoving();
            pet->GetMotionMaster()->Clear(false);
            pet->GetMotionMaster()->MoveIdle();
            charmInfo->SetCommandState(COMMAND_STAY);
            break;
        case COMMAND_FOLLOW:                        // spellid=1792  // FOLLOW
            pet->AttackStop();
            pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
            charmInfo->SetCommandState(COMMAND_FOLLOW);
            break;
        case COMMAND_ATTACK:                        // spellid=1792  // ATTACK
        {
            Unit* TargetUnit = _player->GetMap()->GetUnit(targetGuid);
            if (!TargetUnit)
                return;

            // not let attack friendly units.
            if (GetPlayer()->IsFriendlyTo(TargetUnit))
                return;
            // Not let attack through obstructions
            if (!pet->IsWithinLOSInMap(TargetUnit))
                return;

            // This is true if pet has no target or has target but targets differs.
            if (pet->getVictim() != TargetUnit)
            {
                if (pet->getVictim())
                    pet->AttackStop();

                if (pet->hasUnitState(UNIT_STAT_CONTROLLED))
                {
                    pet->Attack(TargetUnit, true);
                    pet->SendPetAIReaction();
                }
                else
                {
                    pet->GetMotionMaster()->Clear();

                    if (((Creature*)pet)->AI())
                        ((Creature*)pet)->AI()->AttackStart(TargetUnit);

                    // 10% chance to play special pet attack talk, else growl
                    if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10))
                        pet->SendPetTalk((uint32)PET_TALK_ATTACK);
                    else
                    {
                        // 90% chance for pet and 100% chance for charmed creature
                        pet->SendPetAIReaction();
                    }
                }
            }
            break;
        }
        case COMMAND_ABANDON:                       // abandon (hunter pet) or dismiss (summoned pet)
            if (((Creature*)pet)->IsPet())
            {
                Pet* p = (Pet*)pet;
                if (p->getPetType() == HUNTER_PET)
                    p->Unsummon(PET_SAVE_AS_DELETED, _player);
                else
                    // dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
                    p->SetDeathState(CORPSE);
            }
            else                                    // charmed
                _player->Uncharm();
            break;
        default:
            sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
        }
        break;
    case ACT_REACTION:                                  // 0x6
        switch (spellid)
        {
        case REACT_PASSIVE:                         // passive
        case REACT_DEFENSIVE:                       // recovery
        case REACT_AGGRESSIVE:                      // activete
            charmInfo->SetReactState(ReactStates(spellid));
            break;
        }
        break;
    case ACT_DISABLED:                                  // 0x81    spell (disabled), ignore
    case ACT_PASSIVE:                                   // 0x01
    case ACT_ENABLED:                                   // 0xC1    spell
    {
        Unit* unit_target = NULL;
        if (targetGuid)
            unit_target = _player->GetMap()->GetUnit(targetGuid);

        // do not cast unknown spells
        SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid);
        if (!spellInfo)
        {
            sLog.outError("WORLD: unknown PET spell id %i", spellid);
            return;
        }

        if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
            return;

        for (int i = 0; i < MAX_EFFECT_INDEX; ++i)
        {
            if (spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
                return;
        }

        // do not cast not learned spells
        if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo))
            return;

        pet->clearUnitState(UNIT_STAT_MOVING);

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

        SpellCastResult result = spell->CheckPetCast(unit_target);

        // auto turn to target unless possessed
        if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
        {
            if (unit_target)
            {
                pet->SetInFront(unit_target);
                if (unit_target->GetTypeId() == TYPEID_PLAYER)
                    pet->SendCreateUpdateToPlayer((Player*)unit_target);
            }
            else if (Unit* unit_target2 = spell->m_targets.getUnitTarget())
            {
                pet->SetInFront(unit_target2);
                if (unit_target2->GetTypeId() == TYPEID_PLAYER)
                    pet->SendCreateUpdateToPlayer((Player*)unit_target2);
            }
            if (Unit* powner = pet->GetCharmerOrOwner())
                if (powner->GetTypeId() == TYPEID_PLAYER)
                    pet->SendCreateUpdateToPlayer((Player*)powner);
            result = SPELL_CAST_OK;
        }

        if (result == SPELL_CAST_OK)
        {
            ((Creature*)pet)->AddCreatureSpellCooldown(spellid);
            if (((Creature*)pet)->IsPet())
                ((Pet*)pet)->CheckLearning(spellid);

            unit_target = spell->m_targets.getUnitTarget();

            // 10% chance to play special pet attack talk, else growl
            // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
            if (((Creature*)pet)->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10))
                pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
            else
            {
                pet->SendPetAIReaction();
            }

            if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
            {
                // This is true if pet has no target or has target but targets differs.
                if (pet->getVictim() != unit_target)
                {
                    if (pet->getVictim())
                        pet->AttackStop();
                    pet->GetMotionMaster()->Clear();
                    if (((Creature*)pet)->AI())
                        ((Creature*)pet)->AI()->AttackStart(unit_target);
                }
            }

            spell->prepare(&(spell->m_targets));
        }
        else
        {
            if (pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
                Spell::SendCastResult(GetPlayer(), spellInfo, 0, result);
            else
            {
                Unit* owner = pet->GetCharmerOrOwner();
                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    Spell::SendCastResult((Player*)owner, spellInfo, 0, result, true);
            }

            if (!((Creature*)pet)->HasSpellCooldown(spellid))
                GetPlayer()->SendClearCooldown(spellid, pet);

            spell->finish(false);
            delete spell;
        }
        break;
    }
    default:
        sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
    }
}
        uint32 NextStep(uint32 Step)
        {
            Unit* arca = Unit::GetUnit((*me),ArcanagosGUID);
            Map* pMap = me->GetMap();
            switch(Step)
            {
            case 0:
                return 9999999;
            case 1:
                me->MonsterYell(SAY_DIALOG_MEDIVH_1,LANG_UNIVERSAL,NULL);
                return 10000;
            case 2:
                if (arca)
                    CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_2,LANG_UNIVERSAL,NULL);
                return 20000;
            case 3:
                me->MonsterYell(SAY_DIALOG_MEDIVH_3,LANG_UNIVERSAL,NULL);
                return 10000;
            case 4:
                if (arca)
                    CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, NULL);
                return 20000;
            case 5:
                me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, NULL);
                return 20000;
            case 6:
                if (arca)
                    CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, NULL);
                return 10000;
            case 7:
                FireArcanagosTimer = 500;
                return 5000;
            case 8:
                FireMedivhTimer = 500;
                DoCast(me, SPELL_MANA_SHIELD);
                return 10000;
            case 9:
                me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false);
                return 10000;
            case 10:
                if (arca)
                    DoCast(arca, SPELL_CONFLAGRATION_BLAST, false);
                return 1000;
            case 11:
                if (arca)
                    CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL);
                return 5000;
            case 12:
                arca->GetMotionMaster()->MovePoint(0, -11010.82f,-1761.18f, 156.47f);
                arca->setActive(true);
                arca->InterruptNonMeleeSpells(true);
                arca->SetSpeed(MOVE_FLIGHT, 2.0f);
                return 10000;
            case 13:
                me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL);
                return 10000;
            case 14:
                me->SetVisible(false);
                me->ClearInCombat();

                if (pMap->IsDungeon())
                {
                    InstanceMap::PlayerList const &PlayerList = pMap->GetPlayers();
                    for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                    {
                        if (i->getSource()->isAlive())
                        {
                            if (i->getSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE)
                                i->getSource()->CompleteQuest(9645);
                        }
                    }
                }
                return 50000;
            case 15:
                arca->DealDamage(arca,arca->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
                return 5000;
            default :
                return 9999999;
            }

        }