Example #1
1
        void UpdateAI(const uint32 diff)
        {
            if (Event_Timer <= diff)
            {
                switch (Phase)
                {
                case 1:
                    if (someplayer)
                    {
                        Unit* u = Unit::GetUnit(*me, someplayer);
                        if (u && u->GetTypeId() == TYPEID_PLAYER) DoScriptText(EMOTE_START, me, u);
                    }
                    Event_Timer = 60000;
                    Wave = true;
                    ++Phase;
                    break;
                case 2:
                    DoScriptText(EMOTE_60, me);
                    Event_Timer = 30000;
                    ++Phase;
                    break;
                case 3:
                    DoScriptText(EMOTE_30, me);
                    Event_Timer = 20000;
                    DoFinalSpawnForCreature(me);
                    ++Phase;
                    break;
                case 4:
                    DoScriptText(EMOTE_10, me);
                    Event_Timer = 10000;
                    Wave = false;
                    ++Phase;
                    break;
                case 5:
                    DoScriptText(EMOTE_COMPLETE, me);
                    if (someplayer)
                    {
                        Unit* u = Unit::GetUnit(*me, someplayer);
                        if (u && u->GetTypeId() == TYPEID_PLAYER)
                            CAST_PLR(u)->KilledMonsterCredit(me->GetEntry(), me->GetGUID());
                        DoCast(me, SPELL_DISABLE_VISUAL);
                    }
                    if (goConsole)
                    {
                        if (GameObject* go = GameObject::GetGameObject(*me, goConsole))
                            go->RemoveFlag(GAMEOBJECT_FIELD_FLAGS, GO_FLAG_IN_USE);
                    }
                    ++Phase;
                    break;
                }
            } else Event_Timer -= diff;

            if (Wave)
            {
                if (Wave_Timer <= diff)
                {
                    DoWaveSpawnForCreature(me);
                } else Wave_Timer -= diff;
            }
        }
Example #2
1
void WorldSession::HandleMoveKnockBackAck( WorldPacket & recv_data )
{
    DEBUG_LOG("CMSG_MOVE_KNOCK_BACK_ACK");

    Unit *mover = _player->GetMover();
    Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;

    // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
    if(plMover && plMover->IsBeingTeleported())
    {
        recv_data.rpos(recv_data.wpos());                   // prevent warnings spam
        return;
    }

    ObjectGuid guid;
    MovementInfo movementInfo;

    recv_data >> guid.ReadAsPacked();
    recv_data >> Unused<uint32>();                          // knockback packets counter
    recv_data >> movementInfo;

    if (!VerifyMovementInfo(movementInfo, guid))
        return;

    HandleMoverRelocation(movementInfo);

    WorldPacket data(MSG_MOVE_KNOCK_BACK, recv_data.size() + 15);
    data << mover->GetPackGUID();
    data << movementInfo;
    data << movementInfo.GetJumpInfo().sinAngle;
    data << movementInfo.GetJumpInfo().cosAngle;
    data << movementInfo.GetJumpInfo().xyspeed;
    data << movementInfo.GetJumpInfo().velocity;
    mover->SendMessageToSetExcept(&data, _player);
}
Example #3
1
    void FlameWreathEffect()
    {
        std::vector<Unit*> targets;
        std::list<HostilReference *> t_list = m_creature->getThreatManager().getThreatList();

        if (!t_list.size())
            return;

        //store the threat list in a different container
        for(std::list<HostilReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
        {
            Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
            //only on alive players
            if (target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER)
                targets.push_back(target);
        }

        //cut down to size if we have more than 3 targets
        while(targets.size() > 3)
            targets.erase(targets.begin()+rand()%targets.size());

        uint32 i = 0;
        for(std::vector<Unit*>::iterator itr = targets.begin(); itr!= targets.end(); ++itr)
        {
            if (*itr)
            {
                FlameWreathTarget[i] = (*itr)->GetGUID();
                FWTargPosX[i] = (*itr)->GetPositionX();
                FWTargPosY[i] = (*itr)->GetPositionY();
                m_creature->CastSpell((*itr), SPELL_FLAME_WREATH, true);
                i++;
            }
        }
    }
Example #4
1
void Guardian::UpdateAttackPowerAndDamage(bool ranged)
{
    if (ranged)
        return;

    float val = 0.0f;
    float bonusAP = 0.0f;
    UnitMods unitMod = UNIT_MOD_ATTACK_POWER;

    if (GetEntry() == 416)                                   // imp's attack power
        val = GetStat(STAT_STRENGTH) - 10.0f;
    else
        val = 2 * GetStat(STAT_STRENGTH) - 20.0f;

    Unit* owner = GetOwner();
    if (owner && owner->GetTypeId() == TYPEID_PLAYER)
    {
        if (isHunterPet())                      //hunter pets benefit from owner's attack power
        {
            bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f;
            SetBonusDamage(int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.125f));
        }
        //demons benefit from warlocks shadow or fire damage
        else if (isPet() && owner->getClass() == CLASS_WARLOCK)
        {
            int32 fire  = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
            int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW);
            int32 maximum  = (fire > shadow) ? fire : shadow;
            if (maximum < 0)
                maximum = 0;
            SetBonusDamage(int32(maximum * 0.15f));
            bonusAP = maximum * 0.57f;
        }
        //water elementals benefit from mage's frost damage
        else if (GetEntry() == 510 && owner->getClass() == CLASS_MAGE)
        {
            int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST);
            if (frost < 0)
                frost = 0;
            SetBonusDamage(int32(frost * 0.4f));
        }
    }

    SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP);

    //in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
    float base_attPower  = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
    float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
    float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;

    //UNIT_FIELD_(RANGED)_ATTACK_POWER field
    SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower);
    //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
    SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)attPowerMod);
    //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
    SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier);

    //automatically update weapon damage after attack power modification
    UpdateDamagePhysical(BASE_ATTACK);
}
 void SpellHitTarget(Unit* target, const SpellEntry* spell)
 {
     if (spell->Id == SPELL_TRAMPLE && target->GetTypeId() == TYPEID_PLAYER)
     {
         if (!m_bTrampleCasted)
         {
             DoCast(me, SPELL_FROTHING_RAGE, true);
             m_bTrampleCasted = true;
         }
     }
 }
        void UpdateAI(const uint32 diff)
        {
            //Return since we have no target
            if (!UpdateVictim())
                return;

            if (uiBiteTimer <= diff)
            {
                DoCast(me->getVictim(), SPELL_ECK_BITE);
                uiBiteTimer = urand(8*IN_MILLISECONDS, 12*IN_MILLISECONDS);
            } else uiBiteTimer -= diff;

            if (uiSpitTimer <= diff)
            {
                DoCast(me->getVictim(), SPELL_ECK_SPIT);
                uiSpitTimer = urand(6*IN_MILLISECONDS, 14*IN_MILLISECONDS);
            } else uiSpitTimer -= diff;

            if (uiSpringTimer <= diff)
            {
                Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1);
                if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
                {
                    DoCast(pTarget, RAND(SPELL_ECK_SPRING_1, SPELL_ECK_SPRING_2));
                    uiSpringTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS);
                }
            } else uiSpringTimer -= diff;

            //Berserk on timer or 20% of health
            if (!bBerserk)
            {
                if (uiBerserkTimer <= diff)
                {
                    DoCast(me, SPELL_ECK_BERSERK);
                    bBerserk = true;
                }
                else
                {
                    uiBerserkTimer -= diff;
                    if (HealthBelowPct(20))
                    {
                        DoCast(me, SPELL_ECK_BERSERK);
                        bBerserk = true;
                    }
                }
            }

            DoMeleeAttackIfReady();
        }
Example #7
1
 void SonicBoomEffect()
 {
     ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList();
     for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
     {
         Unit* target = Unit::GetUnit(*me, (*itr)->getUnitGuid());
         if (target && target->GetTypeId() == TYPEID_PLAYER)
         {
             //Not do anything without aura, spell can be resisted!
             if (target->HasAura(SPELL_SONIC_BOOM_CAST) && me->IsWithinDistInMap(target, 34.0f))
             {
                 //This will be wrong calculation. Also, comments suggest it must deal damage
                 target->SetHealth(target->CountPctFromMaxHealth(20));
             }
         }
     }
 }
Example #8
1
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
    uint32 opcode = recv_data.GetOpcode();
    DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
    recv_data.hexlike();

    Unit *mover = _player->GetMover();
    Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;

    // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
    if(plMover && plMover->IsBeingTeleported())
    {
        recv_data.rpos(recv_data.wpos());                   // prevent warnings spam
        return;
    }

    /* extract packet */
    ObjectGuid guid;
    MovementInfo movementInfo;

    recv_data >> guid.ReadAsPacked();
    recv_data >> movementInfo;
    /*----------------*/

    if (!VerifyMovementInfo(movementInfo, guid))
        return;

    // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
    if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->IsTaxiFlying())
        plMover->HandleFall(movementInfo);

    /* process position-change */
    HandleMoverRelocation(movementInfo);

    if (plMover)
        plMover->UpdateFallInformationIfNeed(movementInfo, opcode);

    // after move info set
    if (opcode == MSG_MOVE_SET_WALK_MODE || opcode == MSG_MOVE_SET_RUN_MODE)
        mover->UpdateWalkMode(mover, false);

    WorldPacket data(opcode, recv_data.size());
    data << mover->GetPackGUID();             // write guid
    movementInfo.Write(data);                               // write data
    mover->SendMessageToSetExcept(&data, _player);
}
Example #9
1
void PetAI::UpdateAllies()
{
    Unit* owner = m_creature->GetCharmerOrOwner();
    Group* pGroup = NULL;

    m_updateAlliesTimer = 10 * IN_MILLISECONDS;             // update friendly targets every 10 seconds, lesser checks increase performance

    if (!owner)
        return;
    else if (owner->GetTypeId() == TYPEID_PLAYER)
        pGroup = ((Player*)owner)->GetGroup();

    // only pet and owner/not in group->ok
    if (m_AllySet.size() == 2 && !pGroup)
        return;
    // owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
    if (pGroup && !pGroup->isRaidGroup() && m_AllySet.size() == (pGroup->GetMembersCount() + 2))
        return;

    m_AllySet.clear();
    m_AllySet.insert(m_creature->GetObjectGuid());
    if (pGroup)                                             // add group
    {
        for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
        {
            Player* target = itr->getSource();
            if (!target || !pGroup->SameSubGroup((Player*)owner, target))
                continue;

            if (target->GetObjectGuid() == owner->GetObjectGuid())
                continue;

            m_AllySet.insert(target->GetObjectGuid());
        }
    }
    else                                                    // remove group
        m_AllySet.insert(owner->GetObjectGuid());
}
Example #10
1
/// %Log the player out
void WorldSession::LogoutPlayer(bool Save)
{
    // finish pending transfers before starting the logout
    while(_player && _player->IsBeingTeleportedFar())
        HandleMoveWorldportAckOpcode();

    m_playerLogout = true;
    m_playerSave = Save;

    if (_player)
    {
        // Playerbot mod: log out all player bots owned by this toon
        if (GetPlayer()->GetPlayerbotMgr())
            GetPlayer()->GetPlayerbotMgr()->LogoutAllBots();

        sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (guid: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() ,_player->GetGUIDLow());

        if (ObjectGuid lootGuid = GetPlayer()->GetLootGuid())
            DoLootRelease(lootGuid);

        ///- If the player just died before logging out, make him appear as a ghost
        //FIXME: logout must be delayed in case lost connection with client in time of combat
        if (GetPlayer()->GetDeathTimer())
        {
            GetPlayer()->getHostileRefManager().deleteReferences();
            GetPlayer()->BuildPlayerRepop();
            GetPlayer()->RepopAtGraveyard();
        }
        else if (GetPlayer()->IsInCombat() && GetPlayer()->GetMap())
        {
            GetPlayer()->CombatStop();
            GetPlayer()->getHostileRefManager().setOnlineOfflineState(false);
            GetPlayer()->RemoveAllAurasOnDeath();

            // build set of player who attack _player or who have pet attacking of _player
            std::set<Player*> aset;
            GuidSet& attackers = GetPlayer()->GetMap()->GetAttackersFor(GetPlayer()->GetObjectGuid());

            for (GuidSet::const_iterator itr = attackers.begin(); itr != attackers.end();)
            {
                Unit* attacker = GetPlayer()->GetMap()->GetUnit(*itr++);
                if (!attacker)
                    continue;

                Unit* owner = attacker->GetOwner();           // including player controlled case
                if(owner)
                {
                    if(owner->GetTypeId() == TYPEID_PLAYER)
                        aset.insert((Player*)owner);
                }
                else if(attacker->GetTypeId() == TYPEID_PLAYER)
                    aset.insert((Player*)(attacker));
            }

            GetPlayer()->SetPvPDeath(!aset.empty());
            GetPlayer()->KillPlayer();
            GetPlayer()->BuildPlayerRepop();
            GetPlayer()->RepopAtGraveyard();

            // give honor to all attackers from set like group case
            for(std::set<Player*>::const_iterator itr = aset.begin(); itr != aset.end(); ++itr)
                (*itr)->RewardHonor(GetPlayer(),aset.size());

            // give bg rewards and update counters like kill by first from attackers
            // this can't be called for all attackers.
            if(!aset.empty())
                if(BattleGround *bg = GetPlayer()->GetBattleGround())
                    bg->HandleKillPlayer(GetPlayer(),*aset.begin());
        }
        else if(GetPlayer()->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
        {
            // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION
            GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
            //GetPlayer()->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time
            GetPlayer()->KillPlayer();
            GetPlayer()->BuildPlayerRepop();
            GetPlayer()->RepopAtGraveyard();
        }
        else if (GetPlayer()->HasPendingBind())
        {
            GetPlayer()->RepopAtGraveyard();
            GetPlayer()->SetPendingBind(NULL, 0);
        }

        //drop a flag if player is carrying it
        if(BattleGround *bg = GetPlayer()->GetBattleGround())
            bg->EventPlayerLoggedOut(GetPlayer());

        ///- Teleport to home if the player is in an invalid instance
        if(!GetPlayer()->m_InstanceValid && !GetPlayer()->isGameMaster())
        {
            GetPlayer()->TeleportToHomebind();
            //this is a bad place to call for far teleport because we need player to be in world for successful logout
            //maybe we should implement delayed far teleport logout?
        }

        // FG: finish pending transfers after starting the logout
        // this should fix players beeing able to logout and login back with full hp at death position
        while(GetPlayer()->IsBeingTeleportedFar())
            HandleMoveWorldportAckOpcode();

        for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
        {
            if(BattleGroundQueueTypeId bgQueueTypeId = GetPlayer()->GetBattleGroundQueueTypeId(i))
            {
                GetPlayer()->RemoveBattleGroundQueueId(bgQueueTypeId);
                sBattleGroundMgr.m_BattleGroundQueues[ bgQueueTypeId ].RemovePlayer(GetPlayer()->GetObjectGuid(), true);
            }
        }

        ///- Reset the online field in the account table
        // no point resetting online in character table here as Player::SaveToDB() will set it to 1 since player has not been removed from world at this stage
        // No SQL injection as AccountID is uint32
        if (!GetPlayer()->GetPlayerbotAI())
        {
            static SqlStatementID id;

            SqlStatement stmt = LoginDatabase.CreateStatement(id, "UPDATE account SET active_realm_id = ? WHERE id = ?");
            stmt.PExecute(uint32(0), GetAccountId());
        }

        ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
        Guild* guild = sGuildMgr.GetGuildById(GetPlayer()->GetGuildId());
        if (guild)
        {
            if (MemberSlot* slot = guild->GetMemberSlot(GetPlayer()->GetObjectGuid()))
            {
                slot->SetMemberStats(GetPlayer());
                slot->UpdateLogoutTime();
            }

            guild->BroadcastEvent(GE_SIGNED_OFF, GetPlayer()->GetObjectGuid(), GetPlayer()->GetName());
        }

        ///- Remove pet
        GetPlayer()->RemovePet(PET_SAVE_AS_CURRENT);

        GetPlayer()->InterruptNonMeleeSpells(true);

        if (VehicleKitPtr vehicle = GetPlayer()->GetVehicle())
            GetPlayer()->ExitVehicle();

        ///- empty buyback items and save the player in the database
        // some save parts only correctly work in case player present in map/player_lists (pets, etc)
        if(Save)
            GetPlayer()->SaveToDB();

        ///- Leave all channels before player delete...
        GetPlayer()->CleanupChannels();

        // LFG cleanup
        sLFGMgr.Leave(GetPlayer());

        ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group.
        GetPlayer()->UninviteFromGroup();

        // remove player from the group if he is:
        // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
        if(GetPlayer()->GetGroup() && !GetPlayer()->GetGroup()->isRaidGroup() && m_Socket)
            GetPlayer()->RemoveFromGroup();

        ///- Send update to group
        if(GetPlayer()->GetGroup())
            GetPlayer()->GetGroup()->SendUpdate();

        ///- Broadcast a logout message to the player's friends
        sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_OFFLINE, GetPlayer()->GetObjectGuid(), true);
        sSocialMgr.RemovePlayerSocial (GetPlayer()->GetGUIDLow ());

        // Playerbot - remember player GUID for update SQL below
        uint32 guid = GetPlayer()->GetGUIDLow();

        ///- Remove the player from the world
        // the player may not be in the world when logging out
        // e.g if he got disconnected during a transfer to another map
        // calls to GetMap in this case may cause crashes
        if (GetPlayer()->IsInWorld())
        {
            Map* _map = GetPlayer()->GetMap();
            _map->Remove(GetPlayer(), true);
        }
        else
        {
            GetPlayer()->CleanupsBeforeDelete();
            if (GetPlayer()->GetMap())
                GetPlayer()->GetMap()->DeleteFromWorld(GetPlayer());
            else
            {
                sObjectAccessor.RemoveObject(GetPlayer());
                delete GetPlayer();
            }
        }

        SetPlayer(NULL);                                    // deleted in Remove/DeleteFromWorld call

        ///- Send the 'logout complete' packet to the client
        WorldPacket data( SMSG_LOGOUT_COMPLETE, 0 );
        SendPacket( &data );

        static SqlStatementID updChars;

        // Playerbot mod: commented out above and do this one instead
        SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 0 WHERE guid = ?");
        stmt.PExecute(guid);

        DEBUG_LOG( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" );
    }

    m_playerLogout = false;
    m_playerSave = false;
    m_playerRecentlyLogout = true;
    LogoutRequest(0);
}
Example #11
1
/// %Log the player out
void WorldSession::LogoutPlayer(bool Save)
{
    // finish pending transfers before starting the logout
    while (_player && _player->IsBeingTeleportedFar())
        HandleMoveWorldportAckOpcode();

    m_playerLogout = true;
    m_playerSave = Save;

    if (_player)
    {
        if (uint64 lguid = GetPlayer()->GetLootGUID())
            DoLootRelease(lguid);

        ///- If the player just died before logging out, make him appear as a ghost
        //FIXME: logout must be delayed in case lost connection with client in time of combat
        if (_player->GetDeathTimer())
        {
            _player->getHostileRefManager().deleteReferences();
            _player->BuildPlayerRepop();
            _player->RepopAtGraveyard();
        }
        else if (!_player->getAttackers().empty())
        {
            _player->getHostileRefManager().setOnlineOfflineState(false);
            _player->RemoveAllAurasOnDeath();

            // build set of player who attack _player or who have pet attacking of _player
            std::set<Player *> aset;
            for (Unit::AttackerSet::const_iterator itr = _player->getAttackers().begin(); itr != _player->getAttackers().end(); ++itr)
            {
                Unit *owner = (*itr)->GetOwner();           // including player controlled case
                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    aset.insert(owner->ToPlayer());
                else if ((*itr)->GetTypeId() == TYPEID_PLAYER)
                    aset.insert((Player*)(*itr));
            }

            _player->SetPvPDeath(!aset.empty());
            _player->KillPlayer();
            _player->BuildPlayerRepop();
            _player->RepopAtGraveyard();

            // give honor to all attackers from set like group case
            for (std::set<Player *>::const_iterator itr = aset.begin(); itr != aset.end(); ++itr)
                (*itr)->RewardHonor(_player, aset.size());

            // give bg rewards and update counters like kill by first from attackers
            // this can't be called for all attackers.
            if (!aset.empty())
                if (Battleground *bg = _player->GetBattleground())
                    bg->HandleKillPlayer(_player, *aset.begin());
        }
        else if (_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
        {
            // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION
            _player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
            _player->KillPlayer();
            _player->BuildPlayerRepop();
            _player->RepopAtGraveyard();
        }
        else if (_player->HasPendingBind())
        {
            _player->RepopAtGraveyard();
            _player->SetPendingBind(NULL, 0);
        }

        //drop a flag if player is carrying it
        if (Battleground *bg = _player->GetBattleground())
            bg->EventPlayerLoggedOut(_player);

        ///- Teleport to home if the player is in an invalid instance
        if (!_player->m_InstanceValid && !_player->isGameMaster())
            _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation());

        sOutdoorPvPMgr->HandlePlayerLeaveZone(_player, _player->GetZoneId());

        for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
        {
            if (BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i))
            {
                _player->RemoveBattlegroundQueueId(bgQueueTypeId);
                sBattlegroundMgr->m_BattlegroundQueues[ bgQueueTypeId ].RemovePlayer(_player->GetGUID(), true);
            }
        }

        // Repop at GraveYard or other player far teleport will prevent saving player because of not present map
        // Teleport player immediately for correct player save
        while (_player->IsBeingTeleportedFar())
            HandleMoveWorldportAckOpcode();

        ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
        if (Guild *pGuild = sGuildMgr->GetGuildById(_player->GetGuildId()))
            pGuild->HandleMemberLogout(this);

        ///- Remove pet
        _player->RemovePet(NULL, PET_SAVE_AS_CURRENT, true);

        ///- empty buyback items and save the player in the database
        // some save parts only correctly work in case player present in map/player_lists (pets, etc)
        if (Save)
        {
            uint32 eslot;
            for (int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; ++j)
            {
                eslot = j - BUYBACK_SLOT_START;
                _player->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (eslot * 2), 0);
                _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0);
                _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, 0);
            }
            _player->SaveToDB();
        }

        ///- Leave all channels before player delete...
        _player->CleanupChannels();

        ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group.
        _player->UninviteFromGroup();

        // remove player from the group if he is:
        // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
        if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket)
            _player->RemoveFromGroup();

        ///- Send update to group and reset stored max enchanting level
        if (_player->GetGroup())
        {
            _player->GetGroup()->SendUpdate();
            _player->GetGroup()->ResetMaxEnchantingLevel();
        }

        ///- Broadcast a logout message to the player's friends
        sSocialMgr->SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true);
        sSocialMgr->RemovePlayerSocial (_player->GetGUIDLow ());

        // Call script hook before deletion
        sScriptMgr->OnPlayerLogout(GetPlayer());

        ///- Remove the player from the world
        // the player may not be in the world when logging out
        // e.g if he got disconnected during a transfer to another map
        // calls to GetMap in this case may cause crashes
        _player->CleanupsBeforeDelete();
        sLogMgr->WriteLn(CHAR_LOG, "Account: %d (IP: %s) Logout Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() , _player->GetGUIDLow());
        Map *_map = _player->GetMap();
        _map->Remove(_player, true);
        SetPlayer(NULL);                                    // deleted in Remove call

        ///- Send the 'logout complete' packet to the client
        WorldPacket data(SMSG_LOGOUT_COMPLETE, 0);
        SendPacket(&data);

        ///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline
        //No SQL injection as AccountId is uint32
        CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = '%u'", GetAccountId());
        sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION: Sent SMSG_LOGOUT_COMPLETE Message");
    }

    m_playerLogout = false;
    m_playerSave = false;
    m_playerRecentlyLogout = true;
    LogoutRequest(0);
}
Example #12
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);
    }
}
Example #13
1
void PetAI::UpdateAI(const uint32 diff)
{
    if (!me->isAlive())
        return;

    Unit* owner = me->GetCharmerOrOwner();

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

    // me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc.
    if (me->getVictim())
    {
        // is only necessary to stop casting, the pet must not exit combat
        if (me->getVictim()->HasBreakableByDamageCrowdControlAura(me))
        {
            me->InterruptNonMeleeSpells(false);
            return;
        }

        if (_needToStop())
        {
            sLog->outStaticDebug("Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
            _stopAttack();
            return;
        }

        DoMeleeAttackIfReady();
    }
    else if (owner && me->GetCharmInfo()) //no victim
    {
        Unit* nextTarget = SelectNextTarget();

        if (me->HasReactState(REACT_PASSIVE))
            _stopAttack();
        else if (nextTarget)
            AttackStart(nextTarget);
        else
            HandleReturnMovement();
    }
    else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
        me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());

    if (!me->GetCharmInfo())
        return;

    // Autocast (casted only in combat or persistent spells in any state)
    if (!me->HasUnitState(UNIT_STATE_CASTING))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;

        for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
        {
            uint32 spellID = me->GetPetAutoSpellOnPos(i);
            if (!spellID)
                continue;

            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
            if (!spellInfo)
                continue;

            // Check global cooldown
            if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                continue;

            // Check spell cooldown
            if (me->HasSpellCooldown(spellInfo->Id))
                continue;

            // Check if pet is in combat and if spell can be cast
            if (me->isInCombat() && !spellInfo->CanBeUsedInCombat())
                continue;

            // Prevent spells like Furious Howl from constantly casting out of
            //  combat when the cooldown is up
            if (!me->isInCombat() && !spellInfo->NeedsToBeTriggeredByCaster())
                continue;

            // We have a spell we can cast, let's pick a target
            if (spellInfo->IsPositive())
            {
                // These would be buff spells like Furious Howl, Consume Shadows, etc.
                Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);

                bool spellUsed = false;
                for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                {
                    Unit* target = ObjectAccessor::GetUnit(*me, *tar);

                    if (!target)
                        continue;

                    if (spell->CanAutoCast(target))
                    {
                        targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(target, spell));
                        spellUsed = true;
                        break;
                    }
                }
                if (!spellUsed)
                    delete spell;
            }
            else if (me->getVictim() && CanAttack(me->getVictim()))
            {
                // These would be offensive spells like Claw, Bite, Torment, Fireball, etc.
                Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
                if (spell->CanAutoCast(me->getVictim()))
                    targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(me->getVictim(), spell));
                else
                    delete spell;
            }
        }

        //found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.SetUnitTarget(target);

            if (!me->HasInArc(M_PI, target))
            {
                me->SetInFront(target);
                if (target && target->GetTypeId() == TYPEID_PLAYER)
                    me->SendUpdateToPlayer(target->ToPlayer());

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    me->SendUpdateToPlayer(owner->ToPlayer());
            }

            me->AddCreatureSpellCooldown(spell->m_spellInfo->Id);

            spell->prepare(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }
}
Example #14
1
void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 eventId, Unit* actionInvoker)
{
    switch (action.type)
    {
    case ACTION_T_TEXT:
    {
        if (!action.text.TextId1)
            return;

        int32 temp = action.text.TextId1;

        if (action.text.TextId2 && action.text.TextId3)
            temp = RAND(action.text.TextId1, action.text.TextId2, action.text.TextId3);
        else if (action.text.TextId2 && urand(0, 1))
            temp = action.text.TextId2;

        if (temp)
        {
            Unit* target = NULL;

            if (actionInvoker)
            {
                if (actionInvoker->GetTypeId() == TYPEID_PLAYER)
                    target = actionInvoker;
                else if (Unit* owner = actionInvoker->GetOwner())
                {
                    if (owner->GetTypeId() == TYPEID_PLAYER)
                        target = owner;
                }
            }
            else
            {
                target = me->getVictim();
                if (target && target->GetTypeId() != TYPEID_PLAYER)
                    if (Unit* owner = target->GetOwner())
                        if (owner->GetTypeId() == TYPEID_PLAYER)
                            target = owner;
            }

            DoScriptText(temp, me, target);
        }
        break;
    }
    case ACTION_T_SET_FACTION:
    {
        if (action.set_faction.factionId)
            me->setFaction(action.set_faction.factionId);
        else
        {
            if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(me->GetEntry()))
            {
                //if no id provided, assume reset and then use default
                if (me->getFaction() != ci->faction_A)
                    me->setFaction(ci->faction_A);
            }
        }
        break;
    }
    case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
    {
        if (action.morph.creatureId || action.morph.modelId)
        {
            //set model based on entry from creature_template
            if (action.morph.creatureId)
            {
                if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(action.morph.creatureId))
                {
                    uint32 display_id = sObjectMgr->ChooseDisplayId(0, ci);
                    me->SetDisplayId(display_id);
                }
            }
            //if no param1, then use value from param2 (modelId)
            else
                me->SetDisplayId(action.morph.modelId);
        }
        else
            me->DeMorph();
        break;
    }
    case ACTION_T_SOUND:
        me->PlayDirectSound(action.sound.soundId);
        break;
    case ACTION_T_EMOTE:
        me->HandleEmoteCommand(action.emote.emoteId);
        break;
    case ACTION_T_RANDOM_SOUND:
    {
        int32 temp = GetRandActionParam(rnd, action.random_sound.soundId1, action.random_sound.soundId2, action.random_sound.soundId3);
        if (temp >= 0)
            me->PlayDirectSound(temp);
        break;
    }
    case ACTION_T_RANDOM_EMOTE:
    {
        int32 temp = GetRandActionParam(rnd, action.random_emote.emoteId1, action.random_emote.emoteId2, action.random_emote.emoteId3);
        if (temp >= 0)
            me->HandleEmoteCommand(temp);
        break;
    }
    case ACTION_T_CAST:
    {
        Unit* target = GetTargetByType(action.cast.target, actionInvoker);
        Unit* caster = me;

        if (!target)
            return;

        if (action.cast.castFlags & CAST_FORCE_TARGET_SELF)
            caster = target;

        //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
        bool canCast = !caster->IsNonMeleeSpellCasted(false) || (action.cast.castFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS));

        // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
        if (action.cast.castFlags & CAST_AURA_NOT_PRESENT)
        {
            if (target->HasAura(action.cast.spellId))
                return;
        }

        if (canCast)
        {
            const SpellInfo* tSpell = sSpellMgr->GetSpellInfo(action.cast.spellId);

            //Verify that spell exists
            if (tSpell)
            {
                //Check if cannot cast spell
                if (!(action.cast.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
                        !CanCast(target, tSpell, (action.cast.castFlags & CAST_TRIGGERED)))
                {
                    //Melee current victim if flag not set
                    switch(me->GetMotionMaster()->GetCurrentMovementGeneratorType())
                    {
                    case CHASE_MOTION_TYPE:
                    case FOLLOW_MOTION_TYPE:
                        m_AttackDistance = 0.0f;
                        m_AttackAngle = 0.0f;

                        me->GetMotionMaster()->Clear(false);
                        break;
                    }
                }
                else
                {
                    //Interrupt any previous spell
                    if (caster->IsNonMeleeSpellCasted(false) && action.cast.castFlags & CAST_INTERRUPT_PREVIOUS)
                        caster->InterruptNonMeleeSpells(false);

                    caster->CastSpell(target, action.cast.spellId, (action.cast.castFlags & CAST_TRIGGERED));
                }
            }
            else
                sLog->outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", eventId, me->GetEntry(), action.cast.spellId);
        }
        break;
    }
    case ACTION_T_SUMMON:
    {
        Unit* target = GetTargetByType(action.summon.target, actionInvoker);

        Creature* creature = NULL;

        if (action.summon.duration)
            creature = me->SummonCreature(action.summon.creatureId, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, action.summon.duration);
        else
            creature = me->SummonCreature(action.summon.creatureId, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);

        if (!creature)
            sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", action.summon.creatureId, eventId, me->GetEntry());
        else if (action.summon.target != TARGET_T_SELF && target)
            creature->AI()->AttackStart(target);
        break;
    }
    case ACTION_T_THREAT_SINGLE_PCT:
        if (Unit* target = GetTargetByType(action.threat_single_pct.target, actionInvoker))
            me->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent);
        break;
    case ACTION_T_THREAT_ALL_PCT:
    {
        std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList();
        for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i)
            if (Unit* Temp = Unit::GetUnit(*me, (*i)->getUnitGuid()))
                me->getThreatManager().modifyThreatPercent(Temp, action.threat_all_pct.percent);
        break;
    }
    case ACTION_T_QUEST_EVENT:
        if (Unit* target = GetTargetByType(action.quest_event.target, actionInvoker))
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ToPlayer()->AreaExploredOrEventHappens(action.quest_event.questId);
        break;
    case ACTION_T_CAST_EVENT:
        if (Unit* target = GetTargetByType(action.cast_event.target, actionInvoker))
            if (target->GetTypeId() == TYPEID_PLAYER)
                target->ToPlayer()->CastedCreatureOrGO(action.cast_event.creatureId, me->GetGUID(), action.cast_event.spellId);
        break;
    case ACTION_T_SET_UNIT_FIELD:
    {
        Unit* target = GetTargetByType(action.set_unit_field.target, actionInvoker);

        // not allow modify important for integrity object fields
        if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
            return;

        if (target)
            target->SetUInt32Value(action.set_unit_field.field, action.set_unit_field.value);

        break;
    }
    case ACTION_T_SET_UNIT_FLAG:
        if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker))
            target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
        break;
    case ACTION_T_REMOVE_UNIT_FLAG:
        if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker))
            target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
        break;
    case ACTION_T_AUTO_ATTACK:
        m_MeleeEnabled = action.auto_attack.state != 0;
        break;
    case ACTION_T_COMBAT_MOVEMENT:
        // ignore no affect case
        if (m_CombatMovementEnabled == (action.combat_movement.state != 0))
            return;

        m_CombatMovementEnabled = action.combat_movement.state != 0;

        //Allow movement (create new targeted movement gen only if idle)
        if (m_CombatMovementEnabled)
        {
            Unit* victim = me->getVictim();
            if (me->isInCombat() && victim)
            {
                if (action.combat_movement.melee)
                {
                    me->AddUnitState(UNIT_STATE_MELEE_ATTACKING);
                    me->SendMeleeAttackStart(victim);
                }
                if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE)
                    me->GetMotionMaster()->MoveChase(victim, m_AttackDistance, m_AttackAngle); // Targeted movement generator will start melee automatically, no need to send it explicitly
            }
        }
        else
        {
            if (me->isInCombat())
            {
                Unit* victim = me->getVictim();
                if (action.combat_movement.melee && victim)
                {
                    me->ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
                    me->SendMeleeAttackStop(victim);
                }
                if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
                    me->GetMotionMaster()->MoveIdle();
            }
        }
        break;
    case ACTION_T_SET_PHASE:
        m_Phase = action.set_phase.phase;
        break;
    case ACTION_T_INC_PHASE:
    {
        int32 new_phase = int32(m_Phase)+action.set_inc_phase.step;
        if (new_phase < 0)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d decrease m_Phase under 0. CreatureEntry = %d", eventId, me->GetEntry());
            m_Phase = 0;
        }
        else if (new_phase >= MAX_PHASE)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d incremented m_Phase above %u. m_Phase mask cannot be used with phases past %u. CreatureEntry = %d", eventId, MAX_PHASE-1, MAX_PHASE-1, me->GetEntry());
            m_Phase = MAX_PHASE-1;
        }
        else
            m_Phase = new_phase;

        break;
    }
    case ACTION_T_EVADE:
        EnterEvadeMode();
        break;
    case ACTION_T_FLEE_FOR_ASSIST:
        me->DoFleeToGetAssistance();
        break;
    case ACTION_T_QUEST_EVENT_ALL:
        if (actionInvoker && actionInvoker->GetTypeId() == TYPEID_PLAYER)
        {
            if (Unit* Temp = Unit::GetUnit(*me, actionInvoker->GetGUID()))
                if (Temp->GetTypeId() == TYPEID_PLAYER)
                    Temp->ToPlayer()->GroupEventHappens(action.quest_event_all.questId, me);
        }
        break;
    case ACTION_T_CAST_EVENT_ALL:
    {
        std::list<HostileReference*>& threatList = me->getThreatManager().getThreatList();
        for (std::list<HostileReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i)
            if (Unit* Temp = Unit::GetUnit(*me, (*i)->getUnitGuid()))
                if (Temp->GetTypeId() == TYPEID_PLAYER)
                    Temp->ToPlayer()->CastedCreatureOrGO(action.cast_event_all.creatureId, me->GetGUID(), action.cast_event_all.spellId);
        break;
    }
    case ACTION_T_REMOVEAURASFROMSPELL:
        if (Unit* target = GetTargetByType(action.remove_aura.target, actionInvoker))
            target->RemoveAurasDueToSpell(action.remove_aura.spellId);
        break;
    case ACTION_T_RANGED_MOVEMENT:
        m_AttackDistance = (float)action.ranged_movement.distance;
        m_AttackAngle = action.ranged_movement.angle/180.0f*M_PI;

        if (m_CombatMovementEnabled)
        {
            me->GetMotionMaster()->MoveChase(me->getVictim(), m_AttackDistance, m_AttackAngle);
        }
        break;
    case ACTION_T_RANDOM_PHASE:
        m_Phase = GetRandActionParam(rnd, action.random_phase.phase1, action.random_phase.phase2, action.random_phase.phase3);
        break;
    case ACTION_T_RANDOM_PHASE_RANGE:
        if (action.random_phase_range.phaseMin <= action.random_phase_range.phaseMax)
            m_Phase = urand(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax);
        else
            sLog->outErrorDb("CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 < Param1. Event = %d. CreatureEntry = %d", eventId, me->GetEntry());
        break;
    case ACTION_T_SUMMON_ID:
    {
        Unit* target = GetTargetByType(action.summon_id.target, actionInvoker);

        CreatureEventAI_Summon_Map::const_iterator i = sEventAIMgr->GetCreatureEventAISummonMap().find(action.summon_id.spawnId);
        if (i == sEventAIMgr->GetCreatureEventAISummonMap().end())
        {
            sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", action.summon_id.creatureId, action.summon_id.spawnId, eventId, me->GetEntry());
            return;
        }

        Creature* creature = NULL;
        if ((*i).second.SpawnTimeSecs)
            creature = me->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
        else
            creature = me->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);

        if (!creature)
            sLog->outErrorDb("CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", action.summon_id.creatureId, eventId, me->GetEntry());
        else if (action.summon_id.target != TARGET_T_SELF && target)
            creature->AI()->AttackStart(target);

        break;
    }
    case ACTION_T_KILLED_MONSTER:
        //first attempt player who tapped creature
        if (Player* player = me->GetLootRecipient())
            player->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player);    // player as param is a hacky solution not to use GUID
        else
        {
            //if not available, use actionInvoker
            if (Unit* target = GetTargetByType(action.killed_monster.target, actionInvoker))
                if (Player* player2 = target->GetCharmerOrOwnerPlayerOrPlayerItself())
                    player2->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player2);
        }
        break;
    case ACTION_T_SET_INST_DATA:
    {
        InstanceScript* instance = (InstanceScript*)me->GetInstanceScript();
        if (!instance)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", eventId, me->GetEntry());
            return;
        }

        instance->SetData(action.set_inst_data.field, action.set_inst_data.value);
        break;
    }
    case ACTION_T_SET_INST_DATA64:
    {
        Unit* target = GetTargetByType(action.set_inst_data64.target, actionInvoker);
        if (!target)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", eventId, me->GetEntry());
            return;
        }

        InstanceScript* instance = (InstanceScript*)me->GetInstanceScript();
        if (!instance)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", eventId, me->GetEntry());
            return;
        }

        instance->SetData64(action.set_inst_data64.field, target->GetGUID());
        break;
    }
    case ACTION_T_UPDATE_TEMPLATE:
        if (me->GetEntry() == action.update_template.creatureId)
        {
            sLog->outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", eventId, me->GetEntry());
            return;
        }

        me->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE);
        break;
    case ACTION_T_DIE:
        if (me->isDead())
        {
            sLog->outErrorDb("CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", eventId, me->GetEntry());
            return;
        }
        me->Kill(me);
        break;
    case ACTION_T_ZONE_COMBAT_PULSE:
    {
        me->SetInCombatWithZone();
        break;
    }
    case ACTION_T_CALL_FOR_HELP:
    {
        me->CallForHelp((float)action.call_for_help.radius);
        break;
    }
    break;

    case ACTION_T_MOVE_RANDOM_POINT: //dosen't work in combat
    {
        float x, y, z;
        me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float)action.raw.param1);
        me->GetMotionMaster()->MovePoint(0, x, y, z);
        break;
    }
    case ACTION_T_SET_STAND_STATE:
        me->SetStandState(UnitStandStateType(action.raw.param1));
        break;
    case ACTION_T_SET_PHASE_MASK:
        me->SetPhaseMask(action.raw.param1, true);
        break;
    case ACTION_T_SET_VISIBILITY:
        me->SetVisible(bool(action.raw.param1));
        break;
    case ACTION_T_SET_ACTIVE:
        me->setActive(action.raw.param1 ? true : false);
        break;
    case ACTION_T_SET_AGGRESSIVE:
        me->SetReactState(ReactStates(action.raw.param1));
        break;
    case ACTION_T_ATTACK_START_PULSE:
        AttackStart(me->SelectNearestTarget((float)action.raw.param1));
        break;
    case ACTION_T_SUMMON_GO:
    {
        GameObject* object = NULL;

        float x, y, z;
        me->GetPosition(x, y, z);
        object = me->SummonGameObject(action.raw.param1, x, y, z, 0, 0, 0, 0, 0, action.raw.param2);
        if (!object)
        {
            sLog->outErrorDb("TSCR: EventAI failed to spawn object %u. Spawn event %d is on creature %d", action.raw.param1, eventId, me->GetEntry());
        }
        break;
    }

    case ACTION_T_SET_SHEATH:
    {
        me->SetSheath(SheathState(action.set_sheath.sheath));
        break;
    }
    case ACTION_T_FORCE_DESPAWN:
    {
        me->DespawnOrUnsummon(action.forced_despawn.msDelay);
        break;
    }
    case ACTION_T_SET_INVINCIBILITY_HP_LEVEL:
    {
        if (action.invincibility_hp_level.is_percent)
            m_InvinceabilityHpLevel = me->CountPctFromMaxHealth(action.invincibility_hp_level.hp_level);
        else
            m_InvinceabilityHpLevel = action.invincibility_hp_level.hp_level;
        break;
    }
    case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL:
    {
        if (action.mount.creatureId || action.mount.modelId)
        {
            // set model based on entry from creature_template
            if (action.mount.creatureId)
            {
                if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(action.mount.creatureId))
                {
                    uint32 display_id = sObjectMgr->ChooseDisplayId(0, cInfo);
                    me->Mount(display_id);
                }
            }
            //if no param1, then use value from param2 (modelId)
            else
                me->Mount(action.mount.modelId);
        }
        else
            me->Dismount();

        break;
    }
    }
}
Example #15
1
void PetAI::UpdateAI(const uint32 diff)
{
    if (!me->isAlive())
        return;

    Unit* owner = me->GetCharmerOrOwner();

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

    // me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc.
    if (me->getVictim())
    {
        if (_needToStop())
        {
            sLog->outStaticDebug("Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
            _stopAttack();
            return;
        }
        targetHasCC = _CheckTargetCC(me->getVictim());

        DoMeleeAttackIfReady();
    }
    else if (owner && me->GetCharmInfo()) //no victim
    {
        Unit* nextTarget = SelectNextTarget();

        if (me->HasReactState(REACT_PASSIVE))
            _stopAttack();
        else if (nextTarget)
            AttackStart(nextTarget);
        else
            HandleReturnMovement();
    }
    else if (owner && !me->HasUnitState(UNIT_STAT_FOLLOW)) // no charm info and no victim
        me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());

    if (!me->GetCharmInfo())
        return;

    // Autocast (casted only in combat or persistent spells in any state)
    if (!me->HasUnitState(UNIT_STAT_CASTING))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;

        for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
        {
            uint32 spellID = me->GetPetAutoSpellOnPos(i);
            if (!spellID)
                continue;

            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
            if (!spellInfo)
                continue;

            if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                continue;

            if (spellInfo->IsPositive())
            {
                // non combat spells allowed
                // only pet spells have IsNonCombatSpell and not fit this reqs:
                // Consume Shadows, Lesser Invisibility, so ignore checks for its
                if (spellInfo->CanBeUsedInCombat())
                {
                    // allow only spell without spell cost or with spell cost but not duration limit
                    int32 duration = spellInfo->GetDuration();
                    if ((spellInfo->ManaCost || spellInfo->ManaCostPercentage || spellInfo->ManaPerSecond) && duration > 0)
                        continue;

                    // allow only spell without cooldown > duration
                    int32 cooldown = spellInfo->GetRecoveryTime();
                    if (cooldown >= 0 && duration >= 0 && cooldown > duration)
                        continue;
                }

                Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);

                bool spellUsed = false;
                for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                {
                    Unit* target = ObjectAccessor::GetUnit(*me, *tar);

                    //only buff targets that are in combat, unless the spell can only be cast while out of combat
                    if (!target)
                        continue;

                    if (spell->CanAutoCast(target))
                    {
                        targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(target, spell));
                        spellUsed = true;
                        break;
                    }
                }
                if (!spellUsed)
                    delete spell;
            }
            else if (me->getVictim() && CanAttack(me->getVictim()) && spellInfo->CanBeUsedInCombat())
            {
                Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
                if (spell->CanAutoCast(me->getVictim()))
                    targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(me->getVictim(), spell));
                else
                    delete spell;
            }
        }

        //found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.SetUnitTarget(target);

            if (!me->HasInArc(M_PI, target))
            {
                me->SetInFront(target);
                if (target && target->GetTypeId() == TYPEID_PLAYER)
                    me->SendUpdateToPlayer(target->ToPlayer());

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    me->SendUpdateToPlayer(owner->ToPlayer());
            }

            me->AddCreatureSpellCooldown(spell->m_spellInfo->Id);

            spell->prepare(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            delete itr->second;
    }
}
Example #16
0
void WorldSession::HandleMoveTeleportAckOpcode(WorldPacket& recv_data)
{
    DEBUG_LOG("MSG_MOVE_TELEPORT_ACK");

    ObjectGuid guid;

    recv_data >> guid.ReadAsPacked();

    uint32 flags, time;
    recv_data >> flags >> time;
    DEBUG_LOG("Guid: %s", guid.GetString().c_str());
    DEBUG_LOG("Flags %u, time %u", flags, time/IN_MILLISECONDS);

    Unit *mover = _player->GetMover();
    Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;

    if(!plMover || !plMover->IsBeingTeleportedNear())
        return;

    if(guid != plMover->GetObjectGuid())
        return;

    plMover->SetSemaphoreTeleportNear(false);

    uint32 old_zone = plMover->GetZoneId();

    WorldLocation const& dest = plMover->GetTeleportDest();

    plMover->SetPosition(dest.coord_x, dest.coord_y, dest.coord_z, dest.orientation, true);

    uint32 newzone, newarea;
    plMover->GetZoneAndAreaId(newzone, newarea);
    plMover->UpdateZone(newzone, newarea);

    // new zone
    if(old_zone != newzone)
    {
        // honorless target
        if(plMover->pvpInfo.inHostileArea)
            plMover->CastSpell(plMover, 2479, true);
    }

    // resummon pet
    GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();

    //lets process all delayed operations on successful teleport
    GetPlayer()->ProcessDelayedOperations();
}
Example #17
0
    void JustDied(Unit* killer)
    {
        if (!m_creature || m_creature->GetTypeId() != TYPEID_UNIT)
            return;

        if (!ownerGUID)
            ownerGUID = m_creature->GetCreatorGUID();

        Unit* owner = m_creature->GetMap()->GetUnit(ownerGUID);

        if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
            return;

        owner->RemoveAurasDueToSpell(seatSpell);
        owner->RemoveAurasDueToSpell(53797);
        m_creature->SetCreatorGUID(0);
    }
Example #18
0
        void JustDied(Unit* /*killer*/)
        {
            DoScriptText(EMOTE_ABORT, me);

            if (someplayer)
            {
                Unit* p = Unit::GetUnit(*me, someplayer);
                if (p && p->GetTypeId() == TYPEID_PLAYER)
                {
                    switch (me->GetEntry())
                    {
                    case ENTRY_BNAAR_C_CONSOLE:
                        CAST_PLR(p)->FailQuest(10299);
                        CAST_PLR(p)->FailQuest(10329);
                        break;
                    case ENTRY_CORUU_C_CONSOLE:
                        CAST_PLR(p)->FailQuest(10321);
                        CAST_PLR(p)->FailQuest(10330);
                        break;
                    case ENTRY_DURO_C_CONSOLE:
                        CAST_PLR(p)->FailQuest(10322);
                        CAST_PLR(p)->FailQuest(10338);
                        break;
                    case ENTRY_ARA_C_CONSOLE:
                        CAST_PLR(p)->FailQuest(10323);
                        CAST_PLR(p)->FailQuest(10365);
                        break;
                    }
                }
            }

            if (goConsole)
            {
                if (GameObject* go = GameObject::GetGameObject(*me, goConsole))
                    go->RemoveFlag(GAMEOBJECT_FIELD_FLAGS, GO_FLAG_IN_USE);
            }
        }
Example #19
0
void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData)
{
    if (!GetPlayer()->IsAlive())
        return;

    if (!GetPlayer()->CanSpeak())
    {
        std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
        SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str());
        return;
    }

    uint32 text_emote, emoteNum;
    uint64 guid;

    recvData >> text_emote;
    recvData >> emoteNum;
    recvData >> guid;

    sScriptMgr->OnPlayerTextEmote(GetPlayer(), text_emote, emoteNum, guid);

    EmotesTextEntry const* em = sEmotesTextStore.LookupEntry(text_emote);
    if (!em)
        return;

    uint32 emote_anim = em->textid;

    switch (emote_anim)
    {
    case EMOTE_STATE_SLEEP:
    case EMOTE_STATE_SIT:
    case EMOTE_STATE_KNEEL:
    case EMOTE_ONESHOT_NONE:
        break;
    default:
        // Only allow text-emotes for "dead" entities (feign death included)
        if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
            break;
        GetPlayer()->HandleEmoteCommand(emote_anim);
        break;
    }

    Unit* unit = ObjectAccessor::GetUnit(*_player, guid);

    CellCoord p = Trinity::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());

    Cell cell(p);
    cell.SetNoCreate();

    Trinity::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit);
    Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > emote_do(emote_builder);
    Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), emote_do);
    TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder> >, WorldTypeMapContainer> message(emote_worker);
    cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));

    GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);

    //Send scripted event call
    if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI())
        ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote);
}
    void UpdateAI(const uint32 diff)
    {
        //Return since we have no target
        if (!UpdateVictim())
            return;

        //MortalWound_Timer
        if (MortalWound_Timer <= diff)
        {
            DoCast(me->getVictim(),SPELL_MORTAL_WOUND);
            MortalWound_Timer = 10000 + rand()%10000;
        } else MortalWound_Timer -= diff;

        //Summon 1-3 Spawns of Fankriss at random time.
        if (SpawnSpawns_Timer <= diff)
        {
            switch (rand()%3)
            {
            case 0:
                SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM, 0));
                break;
            case 1:
                SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM, 0));
                SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM, 0));
                break;
            case 2:
                SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM, 0));
                SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM, 0));
                SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM, 0));
                break;
            }
            SpawnSpawns_Timer = 30000 + rand()%30000;
        } else SpawnSpawns_Timer -= diff;

        // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer.
        //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot.
        if (me->GetHealth()*100 / me->GetMaxHealth() > 3)
        {
            if (SpawnHatchlings_Timer <= diff)
            {
                Unit *pTarget = NULL;
                pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
                if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
                {
                    DoCast(pTarget, SPELL_ROOT);

                    if (DoGetThreat(pTarget))
                        DoModifyThreatPercent(pTarget, -100);

                    switch (rand()%3)
                    {
                    case 0:
                        DoTeleportPlayer(pTarget, -8106.0142f, 1289.2900f,-74.419533f, 5.112f);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        break;
                    case 1:
                        DoTeleportPlayer(pTarget, -7990.135354f, 1155.1907f,-78.849319f, 2.608f);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        break;
                    case 2:
                        DoTeleportPlayer(pTarget,-8159.7753f, 1127.9064f,-76.868660f, 0.675f);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
                        if (Hatchling)
                            ((CreatureAI*)Hatchling->AI())->AttackStart(pTarget);
                        break;
                    }
                }
                SpawnHatchlings_Timer = 45000 + rand()%15000;
            } else SpawnHatchlings_Timer -= diff;
        }

        DoMeleeAttackIfReady();
    }
Example #21
0
void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
{
    movementInfo.UpdateTime(getMSTime());

    Unit *mover = _player->GetMover();

    if (Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL)
    {
        if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT))
        {
            if (!plMover->m_transport)
            {
                // elevators also cause the client to send MOVEFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
                for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
                {
                    if ((*iter)->GetObjectGuid() == movementInfo.GetTransportGuid())
                    {
                        plMover->m_transport = (*iter);
                        (*iter)->AddPassenger(plMover);
                        break;
                    }
                }
            }
        }
        else if (plMover->m_transport)               // if we were on a transport, leave
        {
            plMover->m_transport->RemovePassenger(plMover);
            plMover->m_transport = NULL;
            movementInfo.ClearTransportData();
        }

        if (movementInfo.HasMovementFlag(MOVEFLAG_SWIMMING) != plMover->IsInWater())
        {
            // now client not include swimming flag in case jumping under water
            plMover->SetInWater( !plMover->IsInWater() || plMover->GetTerrain()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z) );
        }

        plMover->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o);
        plMover->m_movementInfo = movementInfo;

        if(movementInfo.GetPos()->z < -500.0f)
        {
            if(plMover->InBattleGround()
                    && plMover->GetBattleGround()
                    && plMover->GetBattleGround()->HandlePlayerUnderMap(_player))
            {
                // do nothing, the handle already did if returned true
            }
            else
            {
                // NOTE: this is actually called many times while falling
                // even after the player has been teleported away
                // TODO: discard movement packets after the player is rooted
                if(plMover->isAlive())
                {
                    plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, plMover->GetMaxHealth());
                    // pl can be alive if GM/etc
                    if(!plMover->isAlive())
                    {
                        // change the death state to CORPSE to prevent the death timer from
                        // starting in the next player update
                        plMover->KillPlayer();
                        plMover->BuildPlayerRepop();
                    }
                }

                // cancel the death timer here if started
                plMover->RepopAtGraveyard();
            }
        }
    }
    else                                                    // creature charmed
    {
        if (mover->IsInWorld())
            mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o);
    }
}
Example #22
0
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
{
    DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL");

    ObjectGuid guid;
    uint32 spellid;

    recvPacket >> guid >> spellid;

    DEBUG_LOG("WORLD: CMSG_PET_CAST_SPELL, %s, spellid %u", guid.GetString().c_str(), spellid);

    Creature* pet = _player->GetMap()->GetAnyTypeCreature(guid);

    if (!pet || (guid != _player->GetPetGuid() && guid != _player->GetCharmGuid()))
    {
        sLog.outError("HandlePetCastSpellOpcode: %s isn't pet of %s .", guid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str());
        return;
    }

    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;


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

    SpellCastTargets targets;

    recvPacket >> targets.ReadForCaster(pet);

    pet->clearUnitState(UNIT_STAT_MOVING);

    Spell* spell = new Spell(pet, spellInfo, false);
    spell->m_targets = targets;

    SpellCastResult result = spell->CheckPetCast(NULL);
    if (result == SPELL_CAST_OK)
    {
        pet->AddCreatureSpellCooldown(spellid);
        if (pet->IsPet())
        {
            ((Pet*)pet)->CheckLearning(spellid);

            // 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 (((Pet*)pet)->getPetType() == SUMMON_PET && (urand(0, 100) < 10))
                pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
            else
                pet->SendPetAIReaction();
        }

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

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

        spell->finish(false);
        delete spell;
    }
}
Example #23
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if(m_uiIntroTimer < uiDiff)
        {
            if(m_bIsIntroNow)
            {
                m_creature->StopMoving();
                m_creature->GetMotionMaster()->Clear();
                m_creature->GetMotionMaster()->MoveIdle();

                switch(m_uiIntroCount)
                {
                case 0:
                    DoPlaySoundToSet(m_creature, SOUND_MADR_ICE_BARRIER);
                    m_uiIntroTimer = 6000;
                    break;
                case 1:
                    DoPlaySoundToSet(m_creature, SOUND_MADR_INTRO);
                    m_uiIntroTimer = 5000;
                    break;
                case 2:
                    DoPlaySoundToSet(m_creature, SOUND_INTRO);
                    m_uiIntroTimer = 6000;
                    break;
                case 3:
                    DoPlaySoundToSet(m_creature, SOUND_MADR_ICE_BLOCK);
                    m_uiIntroTimer = 4000;
                    break;
                case 4:
                    DoPlaySoundToSet(m_creature, SOUND_INTRO_BREAK_ICE);
                    m_uiIntroTimer = 5000;
                    break;
                case 5:
                    DoPlaySoundToSet(m_creature, SOUND_MADR_TRAP);
                    m_uiIntroTimer = 5000;
                    break;
                case 6:
                    DoPlaySoundToSet(m_creature, SOUND_INTRO_CHARGE);
                    m_uiIntroTimer = 5000;
                    break;
                case 7:
                    DoPlaySoundToSet(m_creature, SOUND_MADR_DEATH);
                    m_uiIntroTimer = 5000;
                    break;
                case 8:
                    DoPlaySoundToSet(m_creature, SOUND_INTRO_KILL_MADRIGOSA);
                    m_uiIntroTimer = 6000;
                    break;
                case 9:
                    DoPlaySoundToSet(m_creature, SOUND_INTRO_TAUNT);
                    m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
                    m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    m_uiBerserkTimer = 360000;
                    m_bIsIntroNow = false;
                    break;
                }
                ++m_uiIntroCount;
            }
        } else m_uiIntroTimer -= uiDiff;

        if(m_bIsIntroNow)
            return;

        if (m_uiBurnCheckTimer < uiDiff)
        {
            std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
            for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
            {
                Unit *BurnedPlayer = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
                if (BurnedPlayer && BurnedPlayer->GetTypeId() == TYPEID_PLAYER && BurnedPlayer->HasAura(SPELL_BURN_AURA))
                {
                    std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList();
                    for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                    {
                        Unit *TargetedPlayer = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
                        if (TargetedPlayer && TargetedPlayer->GetTypeId() == TYPEID_PLAYER && TargetedPlayer->IsWithinDistInMap(BurnedPlayer, 6) && !TargetedPlayer->HasAura(SPELL_BURN_AURA))
                            TargetedPlayer->CastSpell(TargetedPlayer,SPELL_BURN_AURA,true);
                    }
                }
            }
            m_uiBurnCheckTimer = 1000;
        } else m_uiBurnCheckTimer -= uiDiff;

        if (m_uiLoveTimer < uiDiff)
        {
            switch(urand(0, 2))
            {
            case 0:
                DoScriptText(YELL_LOVE1, m_creature);
                break;
            case 1:
                DoScriptText(YELL_LOVE2, m_creature);
                break;
            case 2:
                DoScriptText(YELL_LOVE3, m_creature);
                break;
            }
            m_uiLoveTimer = urand(15000, 23000);
        }
        else
            m_uiLoveTimer -= uiDiff;

        if (m_uiSlashTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->getVictim())
                DoCast(pTarget,SPELL_METEOR_SLASH);
            m_uiSlashTimer = 11000;
        } else m_uiSlashTimer -= uiDiff;

        if (m_uiStompTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->getVictim())
            {
                DoCast(pTarget,SPELL_STOMP);

                if (pTarget->HasAura(SPELL_BURN_AURA))
                    pTarget->RemoveAurasDueToSpell(SPELL_BURN_AURA);
            }
            m_uiStompTimer = 30000;
        }
        else
            m_uiStompTimer -= uiDiff;

        if (m_uiBurnTimer < uiDiff)
        {
            if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
            {
                DoCast(target,SPELL_BURN);
                target->CastSpell(target,SPELL_BURN_AURA, true);
            }
            m_uiBurnTimer = 60000;
        }
        else m_uiBurnTimer -= uiDiff;

        if (m_uiBerserkTimer < uiDiff)
        {
            DoScriptText(YELL_BERSERK, m_creature);
            DoCast(m_creature,SPELL_BERSERK);
            m_uiBerserkTimer = 20000;
        }
        else
            m_uiBerserkTimer -= uiDiff;

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

    Unit* owner = m_creature->GetCharmerOrOwner();

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

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

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

        bool meleeReach = m_creature->CanReachWithMeleeAttack(m_creature->getVictim());

        if (m_creature->IsStopped() || meleeReach)
        {
            // required to be stopped cases
            if (m_creature->IsStopped() && m_creature->IsNonMeleeSpellCasted(false))
            {
                if (m_creature->hasUnitState(UNIT_STAT_FOLLOW_MOVE))
                    m_creature->InterruptNonMeleeSpells(false);
                else
                    return;
            }
            // not required to be stopped case
            else if (DoMeleeAttackIfReady())
            {
                if (!m_creature->getVictim())
                    return;

                // if pet misses its target, it will also be the first in threat list
                m_creature->getVictim()->AddThreat(m_creature);

                if (_needToStop())
                    _stopAttack();
            }
        }
    }
    else if (owner && m_creature->GetCharmInfo())
    {
        if (owner->isInCombat() && !(m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY)))
        {
            AttackStart(owner->getAttackerForHelper());
        }
        else if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
        {
            if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW))
            {
                m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
            }
        }
    }

    // Autocast (casted only in combat or persistent spells in any state)
    if (!m_creature->IsNonMeleeSpellCasted(false))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;

        for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i)
        {
            uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
            if (!spellID)
                continue;

            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID);
            if (!spellInfo)
                continue;

            if (m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                continue;

            // ignore some combinations of combat state and combat/noncombat spells
            if (!inCombat)
            {
                // ignore attacking spells, and allow only self/around spells
                if (!IsPositiveSpell(spellInfo->Id))
                    continue;

                // non combat spells allowed
                // only pet spells have IsNonCombatSpell and not fit this reqs:
                // Consume Shadows, Lesser Invisibility, so ignore checks for its
                if (!IsNonCombatSpell(spellInfo))
                {
                    // allow only spell without spell cost or with spell cost but not duration limit
                    int32 duration = GetSpellDuration(spellInfo);
                    if ((spellInfo->manaCost || spellInfo->ManaCostPercentage || spellInfo->manaPerSecond) && duration > 0)
                        continue;

                    // allow only spell without cooldown > duration
                    int32 cooldown = GetSpellRecoveryTime(spellInfo);
                    if (cooldown >= 0 && duration >= 0 && cooldown > duration)
                        continue;
                }
            }
            else
            {
                // just ignore non-combat spells
                if (IsNonCombatSpell(spellInfo))
                    continue;
            }

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

            if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim()))
            {
                targetSpellStore.push_back(TargetSpellList::value_type(m_creature->getVictim(), spell));
                continue;
            }
            else
            {
                bool spellUsed = false;
                for (GuidSet::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                {
                    Unit* Target = m_creature->GetMap()->GetUnit(*tar);

                    // only buff targets that are in combat, unless the spell can only be cast while out of combat
                    if (!Target)
                        continue;

                    if (spell->CanAutoCast(Target))
                    {
                        targetSpellStore.push_back(TargetSpellList::value_type(Target, spell));
                        spellUsed = true;
                        break;
                    }
                }
                if (!spellUsed)
                    delete spell;
            }
        }

        // found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.setUnitTarget(target);

            if (!m_creature->HasInArc(M_PI_F, target))
            {
                m_creature->SetInFront(target);
                if (target->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer((Player*)target);

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

            m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id);

            spell->prepare(&targets);
        }

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