Beispiel #1
0
bool PassengerEjectEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
    if (!m_vehicle.GetVehicleInfo())
        return true;

    VehicleKit* pVehicle = m_vehicle.GetVehicleKit();

    if (!pVehicle)
        return true;

    Unit* passenger = pVehicle->GetPassenger(m_seatId);

    if (passenger && passenger->IsInWorld() && passenger->hasUnitState(UNIT_STAT_ON_VEHICLE))
    {
        uint32 controlSpell = 0;
        Unit::AuraList const& controlAuras = m_vehicle.GetAurasByType(SPELL_AURA_CONTROL_VEHICLE);
        for(Unit::AuraList::const_iterator i = controlAuras.begin(); i != controlAuras.end(); ++i)
        {
            if ((*i)->GetCasterGuid() == passenger->GetObjectGuid())
            {
                controlSpell = (*i)->GetId();
                break;
            }
        }

        if (controlSpell)
        {
            m_vehicle.RemoveAurasByCasterSpell(controlSpell, passenger->GetObjectGuid());
        }
        else
            passenger->ExitVehicle();
    }
    return true;
}
Beispiel #2
0
void WorldSession::HandleSpellClick( WorldPacket & recv_data )
{
    ObjectGuid guid;
    recv_data >> guid;

    Creature* unit = _player->GetMap()->GetAnyTypeCreature(guid);
    if (!unit)
        return;

    if (_player->isInCombat() && !unit->IsVehicle())                              // client prevent click and set different icon at combat state
        return;

    SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry());
    for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
    {
        if (itr->second.IsFitToRequirements(_player, unit))
        {
            if (sScriptMgr.OnNpcSpellClick(_player, unit, itr->second.spellId))
                return;

            Unit* caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit;
            Unit* target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit;

            if (itr->second.spellId)
                caster->CastSpell(target, itr->second.spellId, true, NULL, NULL,caster->GetObjectGuid());
            else
                sLog.outError("WorldSession::HandleSpellClick: npc_spell_click with entry %u has 0 in spell_id. Not handled custom case?", unit->GetEntry());
        }
    }
}
Beispiel #3
0
void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket &recv_data)
{
    DEBUG_LOG("WORLD: Recvd CMSG_REQUEST_VEHICLE_SWITCH_SEAT");
    recv_data.hexlike();

    ObjectGuid guid;
    recv_data >> guid.ReadAsPacked();

    int8 seatId;
    recv_data >> seatId;

    Unit *pVehicleBase = GetPlayer()->GetVehicleBase();

    if(!pVehicleBase)
        return;

    if (pVehicleBase->GetObjectGuid() == guid)
        GetPlayer()->ChangeSeat(seatId);
    else if (Unit *vehUnit = ObjectAccessor::GetUnit(*GetPlayer(), guid))
    {
        if (VehicleKit *vehicle = vehUnit->GetVehicleKit())
        {
            if (vehicle->HasEmptySeat(seatId))
                GetPlayer()->EnterVehicle(vehicle, seatId);
        }
    }
}
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 : nullptr;

    // 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;
    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->GetObjectGuid();
    data << movementInfo;
    data << movementInfo.GetJumpInfo().sinAngle;
    data << movementInfo.GetJumpInfo().cosAngle;
    data << movementInfo.GetJumpInfo().xyspeed;
    data << movementInfo.GetJumpInfo().velocity;
    mover->SendMessageToSetExcept(data, _player);
}
Beispiel #5
0
bool PetAI::_needToStop() const
{
    Unit* pVictim = m_creature->getVictim();
    if (!pVictim)
        return true;

    // This is needed for charmed creatures, as once their target was reset other effects can trigger threat
    if (m_creature->isCharmed() && m_creature->GetCharmer() == pVictim)
        return true;

    Unit* owner = m_creature->GetCharmerOrOwner();

    if (owner == pVictim)
        return true;

    if (!pVictim->isVisibleForOrDetect(m_creature, m_creature, false))
        return true;

    if (owner && !pVictim->isVisibleForOrDetect(owner, owner, true))
        return true;

    if (m_primaryTargetGuid && m_primaryTargetGuid != pVictim->GetObjectGuid())
        return true;

    return !pVictim->isTargetableForAttack();
}
Beispiel #6
0
    // Custom threat management
    bool SelectHostileTarget()
    {
        Unit* pTarget = nullptr;
        Unit* pOldTarget = m_creature->getVictim();

        if (!m_creature->getThreatManager().isThreatListEmpty())
            pTarget = m_creature->getThreatManager().getHostileTarget();

        if (pTarget)
        {
            if (pOldTarget != pTarget)
                AttackStart(pTarget);

            // Set victim to old target
            if (pOldTarget && pOldTarget->isAlive())
            {
                m_creature->SetTargetGuid(pOldTarget->GetObjectGuid());
                m_creature->SetInFront(pOldTarget);
            }

            return true;
        }

        // Will call EnterEvadeMode if fit
        return m_creature->SelectHostileTarget();
    }
    void UpdateAI(const uint32 diff)
    {
        if (!init)
        {
            init = true;
            Unit* owner = m_creature->GetCreator();
            if (!owner)
                return;

            summonedBySpell = m_creature->GetUInt32Value(UNIT_CREATED_BY_SPELL);

            m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);

            if (summonedBySpell == SPELL_GUARDIAN_PROT)
            {
                m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
                m_creature->StopMoving();
                m_creature->SetTargetGuid(owner->GetObjectGuid());
                m_creature->CastSpell(owner, SPELL_ANCIENT_GUARDIAN, true);
            }
            else if (summonedBySpell == SPELL_GUARDIAN_RETRO)
            {
                owner->CastSpell(owner, SPELL_ANCIENT_CRUSADER_PLAYER, true);
                m_creature->CastSpell(m_creature, SPELL_ANCIENT_CRUSADER_PET, true);
            }
            else if (summonedBySpell == SPELL_GUARDIAN_HOLY)
                owner->CastSpell(owner, SPELL_ANCIENT_HEALER, true);
        }
        else
        {
            if (summonedBySpell == SPELL_GUARDIAN_RETRO)
            {
                Unit* owner = m_creature->GetOwner();
                Unit* ownerVictim = owner ? owner->getVictim() : NULL;

                if (m_creature->getVictim())
                {
                    if (m_creature->getVictim()->hasUnitState(UNIT_STAT_NO_FREE_MOVE))
                    {
                        m_creature->AttackStop();
                        return;
                    }
                    else if (ownerVictim && m_creature->getVictim() != ownerVictim && !ownerVictim->hasUnitState(UNIT_STAT_NO_FREE_MOVE))
                        AttackStart(ownerVictim);
                }
                else if (ownerVictim && !ownerVictim->hasUnitState(UNIT_STAT_NO_FREE_MOVE))
                    AttackStart(ownerVictim);
            }
        }

        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (!m_creature->IsNonMeleeSpellCasted(false))
            return;

        if (summonedBySpell == SPELL_GUARDIAN_RETRO)
            DoMeleeAttackIfReady();
    }
Beispiel #8
0
    // Custom threat management
    bool SelectHostileTarget()
    {
        Unit* pTarget = NULL;
        Unit* pOldTarget = m_creature->getVictim();

        if (!m_creature->getThreatManager().isThreatListEmpty())
            pTarget = m_creature->getThreatManager().getHostileTarget();

        if (pTarget)
        {
            if (pOldTarget != pTarget && m_Phase == PHASE_EYE_NORMAL)
                AttackStart(pTarget);

            // Set victim to old target (if not while Dark Glare)
            if (pOldTarget && pOldTarget->isAlive() && m_Phase == PHASE_EYE_NORMAL)
            {
                m_creature->SetTargetGuid(pOldTarget->GetObjectGuid());
                m_creature->SetInFront(pOldTarget);
            }

            return true;
        }

        // Will call EnterEvadeMode if fit
        return m_creature->SelectHostileTarget();
    }
Beispiel #9
0
void VehicleKit::Dismount(Unit* passenger, VehicleSeatEntry const* seatInfo)
{
    if (!passenger)
        return;

    float ox, oy, oz, oo;

    Unit* base = m_pBase->GetVehicle() ? m_pBase->GetVehicle()->GetBase() : m_pBase;
    base->GetPosition(ox, oy, oz);
    oo = base->GetOrientation();
    passenger->SetPosition(ox,oy,oz,oo,false);

    if (b_dstSet)
    {
        // parabolic traectory (catapults, explode, other effects). mostly set destination in DummyEffect.
        // destination Z not checked in this case! only limited on 8.0 delta. requred full correct set in spelleffects. 
        float speed = ((m_dst_speed > M_NULL_F) ? m_dst_speed : ((seatInfo && seatInfo->m_exitSpeed > M_NULL_F) ? seatInfo->m_exitSpeed : BASE_CHARGE_SPEED));
        float verticalSpeed = speed * sin(m_dst_elevation);
        float horisontalSpeed = speed * cos(m_dst_elevation);
        float moveTimeHalf =  verticalSpeed / ((seatInfo && seatInfo->m_exitGravity > 0.0f) ? seatInfo->m_exitGravity : Movement::gravity);
        float max_height = - Movement::computeFallElevation(moveTimeHalf,false,-verticalSpeed);

        passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x,m_dst_y,m_dst_z,passenger->GetOrientation(), horisontalSpeed, max_height, true);
    }
    else if (seatInfo)
    {
        // half-parabolic traectory (unmount)
        float horisontalSpeed = seatInfo->m_exitSpeed;

        if (horisontalSpeed < M_NULL_F)
            horisontalSpeed = BASE_CHARGE_SPEED;

        // may be under water
        base->GetClosePoint(m_dst_x, m_dst_y, m_dst_z, base->GetObjectBoundingRadius(), frand(2.0f, 3.0f), frand(M_PI_F/2.0f,3.0f*M_PI_F/2.0f), passenger);
        if (m_dst_z < oz)
            m_dst_z = oz;

        passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x, m_dst_y, m_dst_z + 0.1f, passenger->GetOrientation(), horisontalSpeed, 0.0f);
    }
    else
    {
        // jump from vehicle without seatInfo (? error case)
        base->GetClosePoint(m_dst_x, m_dst_y, m_dst_z, base->GetObjectBoundingRadius(), 2.0f, M_PI_F, passenger);
        passenger->UpdateAllowedPositionZ(m_dst_x, m_dst_y, m_dst_z);
        if (m_dst_z < oz)
            m_dst_z = oz;

        passenger->GetMotionMaster()->MoveSkyDiving(m_dst_x, m_dst_y, m_dst_z + 0.1f, passenger->GetOrientation(), BASE_CHARGE_SPEED, 0.0f);
    }

    DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS,"VehicleKit::Dismount %s from %s (%f %f %f), destination point is %f %f %f",
        passenger->GetObjectGuid().GetString().c_str(),
        base->GetObjectGuid().GetString().c_str(),
        ox,oy,oz,
        m_dst_x,m_dst_y,m_dst_z);
    SetDestination();
}
Beispiel #10
0
void AggressorAI::UpdateAI(const uint32 /*diff*/)
{
    // update i_victimGuid if m_creature->getVictim() != 0 and changed
    Unit* pVictim = SelectVictim();
    if (!pVictim)
        return;

    i_victimGuid = pVictim->GetObjectGuid();

    DoMeleeAttackIfReady();
}
Beispiel #11
0
void PetAI::UpdateAllies()
{
    Unit* owner = m_creature->GetCharmerOrOwner();
    Group *group = 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)
        group = ((Player*)owner)->GetGroup();

    //only pet and owner/not in group->ok
    if (m_AllySet.size() == 2 && !group)
        return;

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

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

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

            m_AllySet.insert(target->GetObjectGuid());
        }
    }
    else                                                    //remove group
        m_AllySet.insert(owner->GetObjectGuid());
}
Beispiel #12
0
void PetAI::UpdateAllies()
{
    Unit* owner = m_creature->GetCharmerOrOwner();
    if (!owner)
        return;

    Group* pGroup = NULL;

    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());
}
void
TotemAI::UpdateAI(const uint32 /*diff*/)
{
    if (getTotem().GetTotemType() != TOTEM_ACTIVE)
        return;

    if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false))
        return;

    // Search spell
    SpellEntry const *spellInfo = sSpellStore.LookupEntry(getTotem().GetSpell());
    if (!spellInfo)
        return;

    SpellMiscEntry const* spellMisc = sSpellMiscStore.LookupEntry(spellInfo->Id);

    // Get spell rangy
    SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellMisc->rangeIndex);
    float max_range = GetSpellMaxRange(srange);

    // SPELLMOD_RANGE not applied in this place just because nonexistent range mods for attacking totems

    // pointer to appropriate target if found any
    Unit* victim = m_creature->GetMap()->GetUnit(i_victimGuid);

    // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end)
    if( !victim ||
            !victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) ||
            m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,m_creature,false) )
    {
        victim = NULL;

        Strawberry::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range);
        Strawberry::UnitLastSearcher<Strawberry::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check);
        Cell::VisitAllObjects(m_creature, checker, max_range);
    }

    // If have target
    if (victim)
    {
        // remember
        i_victimGuid = victim->GetObjectGuid();

        // attack
        m_creature->SetInFront(victim);                      // client change orientation by self
        m_creature->CastSpell(victim, getTotem().GetSpell(), false);
    }
    else
        i_victimGuid.Clear();
}
Beispiel #14
0
// Vehicle events
bool PassengerEjectEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
    if (!m_vehicle.IsVehicle())
        return true;

    VehicleKitPtr pVehicle = m_vehicle.GetVehicleKit();

    Unit* passenger = pVehicle->GetPassenger(m_seatId);

    if (passenger && passenger->IsInWorld())
    {
        if (!m_vehicle.RemoveSpellsCausingAuraByCaster(SPELL_AURA_CONTROL_VEHICLE, passenger->GetObjectGuid()))
            passenger->ExitVehicle();
    }
    return true;
}
Beispiel #15
0
void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
{
    //movementInfo.UpdateTime(WorldTimer::getMSTime());

    Unit *mover = _player->GetMover();

    if (Player *plMover = mover->ToPlayer())
    {
        if (sWorld.getConfig(CONFIG_ENABLE_PASSIVE_ANTICHEAT) && !plMover->hasUnitState(UNIT_STAT_LOST_CONTROL | UNIT_STAT_NOT_MOVE) && !plMover->GetSession()->HasPermissions(PERM_GMT) && plMover->m_AC_timer == 0)
            sWorld.m_ac.execute(new ACRequest(plMover, plMover->m_movementInfo, movementInfo));

        if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT))
        {
            if (!plMover->GetTransport())
            {
                // 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->GetTransport())               // if we were on a transport, leave
        {
            plMover->GetTransport()->RemovePassenger(plMover);
            plMover->SetTransport(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()->IsInWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z));
        }
    }

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

    if (mover->GetObjectGuid().IsPlayer())
        mover->ToPlayer()->HandleFallUnderMap(movementInfo.GetPos()->z);
}
Beispiel #16
0
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
        {
            return;
        }

        if (m_bCanTeleport)
        {
            if (m_uiExile_Timer < uiDiff)
            {
                if (Player* pTarget = m_creature->GetMap()->GetPlayer(m_playerGuid))
                {
                    pTarget->CastSpell(pTarget, SPELL_EXILE, true);
                    pTarget->CastSpell(pTarget, SPELL_BANISH_TELEPORT, true);
                }

                m_playerGuid.Clear();
                m_uiExile_Timer = 8500;
                m_bCanTeleport = false;
            }
            else
            {
                m_uiExile_Timer -= uiDiff;
            }
        }
        else if (m_uiBanish_Timer < uiDiff)
        {
            Unit* pVictim = m_creature->getVictim();

            if (pVictim && pVictim->GetTypeId() == TYPEID_PLAYER)
            {
                DoCastSpellIfCan(pVictim, m_uiAuraBanished);
                m_uiBanish_Timer = 9000;
                m_playerGuid = pVictim->GetObjectGuid();
                m_bCanTeleport = true;
            }
        }
        else
        {
            m_uiBanish_Timer -= uiDiff;
        }

        DoMeleeAttackIfReady();
    }
void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket& recvPacket)
{
    DEBUG_LOG("WORLD: Received CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
    recvPacket.hexlike();

    ObjectGuid srcVehicleGuid;
    MovementInfo movementInfo;
    ObjectGuid destVehicleGuid;
    uint8 seat;

    recvPacket >> srcVehicleGuid.ReadAsPacked();
    recvPacket >> movementInfo;                             // Not used at the moment
    recvPacket >> destVehicleGuid.ReadAsPacked();
    recvPacket >> seat;

    TransportInfo* transportInfo = _player->GetTransportInfo();
    if (!transportInfo || !transportInfo->IsOnVehicle())
        return;

    Unit* srcVehicle = (Unit*)transportInfo->GetTransport();

    // Something went wrong
    if (srcVehicleGuid != srcVehicle->GetObjectGuid())
        return;

    if (srcVehicleGuid != destVehicleGuid)
    {
        Unit* destVehicle = _player->GetMap()->GetUnit(destVehicleGuid);

        if (!destVehicle || !destVehicle->IsVehicle())
            return;

        // Change vehicle is not possible
        if (destVehicle->GetVehicleInfo()->GetVehicleEntry()->m_flags & VEHICLE_FLAG_DISABLE_SWITCH)
            return;

        SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(destVehicle->GetEntry());
        for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
            if (itr->second.IsFitToRequirements(_player))
                _player->CastSpell(destVehicle, itr->second.spellId, true);
    }
    else
        srcVehicle->GetVehicleInfo()->SwitchSeat(_player, seat);
}
Beispiel #18
0
void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket &recv_data)
{
    DEBUG_LOG("WORLD: Recvd CMSG_REQUEST_VEHICLE_SWITCH_SEAT");
    recv_data.hexlike();

    ObjectGuid guid;
    recv_data >> guid.ReadAsPacked();

    int8 seatId;
    recv_data >> seatId;

    Unit *pVehicleBase = GetPlayer()->GetVehicleBase();

    if (!pVehicleBase)
        return;

    if (pVehicleBase->GetObjectGuid() == guid)
        GetPlayer()->ChangeSeat(seatId);
}
    void EnfeebleHealthEffect()
    {
        const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT);
        if (!info)
            return;

        ThreatList const& tList = m_creature->getThreatManager().getThreatList();
        std::vector<Unit *> targets;

        if (tList.empty())
            return;

        //begin + 1 , so we don't target the one with the highest threat
        ThreatList::const_iterator itr = tList.begin();
        std::advance(itr, 1);
        for(; itr!= tList.end(); ++itr)                    //store the threat list in a different container
        {
            Unit *target = m_creature->GetMap()->GetUnit((*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 5 targets
        while(targets.size() > 5)
            targets.erase(targets.begin()+rand()%targets.size());

        int i = 0;
        for(std::vector<Unit *>::iterator iter = targets.begin(); iter!= targets.end(); ++iter, ++i)
        {
            Unit *target = *iter;
            if (target)
            {
                m_aEnfeebleTargetGuid[i] = target->GetObjectGuid();
                m_auiEnfeebleHealth[i] = target->GetHealth();

                target->CastSpell(target, SPELL_ENFEEBLE, true, 0, 0, m_creature->GetObjectGuid());
                target->SetHealth(1);
            }
        }

    }
Beispiel #20
0
void WorldSession::HandleSpellClick( WorldPacket & recv_data )
{
    ObjectGuid guid;
    recv_data >> guid;

    Creature *unit = _player->GetMap()->GetAnyTypeCreature(guid);
    if (!unit)
        return;

    if (_player->isInCombat() && !guid.IsVehicle())                              // client prevent click and set different icon at combat state
        return;

    if(guid.IsVehicle() && _player->GetVehicleKit())
        _player->RemoveVehicleKit();

    SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry());
    for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
    {
        if (itr->second.IsFitToRequirements(_player))
        {
            Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit;
            Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit;

            if(itr->second.castFlags & 0x4)
            {
                unit->SetDeathState(JUST_DIED);
                unit->RemoveCorpse();
                unit->SetHealth(0);
            }

            caster->CastSpell(target, itr->second.spellId, true, NULL, NULL,caster->GetObjectGuid());
        }
    }

    if (unit->GetObjectGuid().IsVehicle())
    {
        _player->EnterVehicle(unit->GetVehicleKit());
    }
}
Beispiel #21
0
void WorldSession::HandleEjectPassenger(WorldPacket &recv_data)
{
    recv_data.hexlike();

    ObjectGuid guid;
    recv_data >> guid;

    DEBUG_LOG("WORLD: Received CMSG_EJECT_PASSENGER %s",guid.GetString().c_str());

    Unit* passenger = ObjectAccessor::GetUnit(*GetPlayer(), guid);

    if (!passenger)
        return;

    VehicleKit* pVehicle = passenger->GetVehicle();

    if (!pVehicle ||
       ((pVehicle != GetPlayer()->GetVehicleKit()) &&
        !(pVehicle->GetBase()->GetVehicleInfo()->GetEntry()->m_flags & (VEHICLE_FLAG_ACCESSORY))))
    {
        sLog.outError("WorldSession::HandleEjectPassenger %s try eject %s, but not may do this!",GetPlayer()->GetObjectGuid().GetString().c_str(),guid.GetString().c_str());
        return;
    }

    passenger->ExitVehicle();

    // eject and remove creatures of player mounts
    if (passenger->GetTypeId() == TYPEID_UNIT)
    {
        if (((Creature*)passenger)->IsTemporarySummon())
        {
            // Fixme: delay must be calculated not from this, but from creature template parameters (off traders ...?).
            uint32 delay = passenger->GetObjectGuid().IsVehicle() ? 1000: 60000;
            ((TemporarySummon*)passenger)->UnSummon(delay);
        }
        else
            passenger->AddObjectToRemoveList();
    }
}
void instance_onyxias_lair::OnCreatureCreate(Creature* pCreature)
{
    switch(pCreature->GetEntry())
    {
        case NPC_ONYXIA:
            m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid();
            break;
        case NPC_ONYXIA_WARDER:
            m_uiOnyxiaWarderGUID.push_back(pCreature->GetObjectGuid());
            break;
		case NPC_ONYXIA_WHELP:
		case NPC_ONYXIA_WHELP_WEST:
			{
				TemporarySummon * summonedWhelp = dynamic_cast<TemporarySummon*>(pCreature);

				if (summonedWhelp != NULL)
				{
					m_onyxianWhelps.push_back(summonedWhelp);

					Unit* pOnyxia = GetSingleCreatureFromStorage(NPC_ONYXIA);

					if (pOnyxia && summonedWhelp->GetSummonerGuid() == pOnyxia->GetObjectGuid())
					{
						//Hard-summoned whelps- start them pathing & set them up to aggro on LOS
						summonedWhelp->GetMotionMaster()->MoveWaypoint();
					} else
					{
						//Egg-summoned whelps- aggro them now
						summonedWhelp->SetInCombatWithZone();
					}
				}
				
				break;
			}
		case NPC_ONYXIA_TRIGGER:
			this->m_mNpcEntryGuidStore[NPC_ONYXIA_TRIGGER] = pCreature->GetObjectGuid();
			break;
    }
}
Beispiel #23
0
void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
{
    DEBUG_LOG("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
    recv_data.hexlike();

    ObjectGuid guid;
    recv_data >> guid.ReadAsPacked();

    MovementInfo mi;
    recv_data >> mi;

    ObjectGuid accessory;
    recv_data >> accessory.ReadAsPacked();

    int8 seatId;
    recv_data >> seatId;

    Unit *pVehicleBase = GetPlayer()->GetVehicleBase();

    if(!pVehicleBase)
        return;

    GetPlayer()->m_movementInfo = mi;

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

    if (accessory.IsEmpty())
        GetPlayer()->ChangeSeat(-1, seatId > 0); // prev/next
    else if (Unit *vehUnit = ObjectAccessor::GetUnit(*_player, accessory))
    {
        if (VehicleKit *vehicle = vehUnit->GetVehicleKit())
        {
            if (vehicle->HasEmptySeat(seatId))
                GetPlayer()->EnterVehicle(vehicle, seatId);
        }
    }
}
void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket& recvPacket)
{
    DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_SWITCH_SEAT");
    recvPacket.hexlike();

    ObjectGuid vehicleGuid;
    uint8 seat;

    recvPacket >> vehicleGuid.ReadAsPacked();
    recvPacket >> seat;

    TransportInfo* transportInfo = _player->GetTransportInfo();
    if (!transportInfo || !transportInfo->IsOnVehicle())
        return;

    Unit* vehicle = (Unit*)transportInfo->GetTransport();

    // Something went wrong
    if (vehicleGuid != vehicle->GetObjectGuid())
        return;

    vehicle->GetVehicleInfo()->SwitchSeat(_player, seat);
}
void WorldSession::HandleDismissControlledVehicle(WorldPacket& recvPacket)
{
    DEBUG_LOG("WORLD: Received CMSG_DISMISS_CONTROLLED_VEHICLE");
    recvPacket.hexlike();

    ObjectGuid vehicleGuid;
    MovementInfo movementInfo;                              // Not used at the moment

    recvPacket >> vehicleGuid.ReadAsPacked();
    recvPacket >> movementInfo;

    TransportInfo* transportInfo = _player->GetTransportInfo();
    if (!transportInfo || !transportInfo->IsOnVehicle())
        return;

    Unit* vehicle = (Unit*)transportInfo->GetTransport();

    // Something went wrong
    if (vehicleGuid != vehicle->GetObjectGuid())
        return;

    // Remove Vehicle Control Aura
    vehicle->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, _player->GetObjectGuid());
}
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (m_uiSummonTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_FIENDISH_HOUND) == CAST_OK)
                m_uiSummonTimer = urand(24100, 26900);
        }
        else
            m_uiSummonTimer -= uiDiff;

        if (m_bCanPullBack)
        {
            if (m_uiShadowWhipTimer < uiDiff)
            {
                if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid))
                {
                    // if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted)
                    if (pPlayer->HasMovementFlag(MOVEFLAG_FALLING))
                        DoCastSpellIfCan(pPlayer, SPELL_SHADOW_WHIP, CAST_INTERRUPT_PREVIOUS);
                }
                m_playerGuid.Clear();
                m_uiShadowWhipTimer = 2000;
                m_bCanPullBack = false;
            }
            else
                m_uiShadowWhipTimer -= uiDiff;
        }
        else if (m_uiOrbitalStrikeTimer < uiDiff)
        {
            Unit* pTemp = NULL;
            if (m_creature->CanReachWithMeleeAttack(m_creature->getVictim()))
                pTemp = m_creature->getVictim();
            else
                pTemp = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);

            if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER)
            {
                if (DoCastSpellIfCan(pTemp, SPELL_ORBITAL_STRIKE) == CAST_OK)
                {
                    m_uiOrbitalStrikeTimer = urand(14000, 16000);
                    m_playerGuid = pTemp->GetObjectGuid();

                    m_bCanPullBack = true;
                }
            }
        }
        else
            m_uiOrbitalStrikeTimer -= uiDiff;

        if (m_creature->GetHealthPercent() < 20.0f)
        {
            if (m_uiDemonicShieldTimer < uiDiff)
            {
                if (DoCastSpellIfCan(m_creature, SPELL_DEMONIC_SHIELD) == CAST_OK)
                    m_uiDemonicShieldTimer = 15000;
            }
            else
                m_uiDemonicShieldTimer -= uiDiff;
        }

        if (m_uiAuraTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_TREACHEROUS_AURA : SPELL_BANE_OF_TREACHERY_H) == CAST_OK)
                {
                    m_uiAuraTimer = urand(8000, 16000);
                    DoScriptText(SAY_CURSE, m_creature);
                }
            }
        }
        else
            m_uiAuraTimer -= uiDiff;

        if (m_uiShadowboltTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
            {
                if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOW_BOLT : SPELL_SHADOW_BOLT_H) == CAST_OK)
                    m_uiShadowboltTimer = urand(4200, 7300);
            }
            else
                m_uiShadowboltTimer = 2000;
        }
        else
            m_uiShadowboltTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
Beispiel #27
0
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
    Opcodes opcode = recv_data.GetOpcodeEnum();
    DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);

    recv_data.hexlike();

    Unit *mover = _player->m_mover;

    STRAWBERRY_ASSERT(mover != NULL);                                  // there must always be a mover

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

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

    /* extract packet */
    MovementInfo movementInfo;
    ReadMovementInfo(recv_data, &movementInfo);

    recv_data.rfinish();                  // prevent warnings spam

    // prevent tampered movement data
    if (movementInfo.guid != mover->GetObjectGuid())
        return;

    /* handle special cases */
    if (movementInfo.moveFlags & MOVEFLAG_ONTRANSPORT)
    {
        // transports size limited
        // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
        if (movementInfo.t_pos.x > 50 || movementInfo.t_pos.y > 50 || movementInfo.t_pos.z > 50)
        {
            recv_data.rfinish();                   // prevent warnings spam
            return;
        }

        if (!Strawberry::IsValidMapCoord(movementInfo.pos.x + movementInfo.t_pos.x, movementInfo.pos.y + movementInfo.t_pos.y),
            movementInfo.pos.z + movementInfo.t_pos.z, movementInfo.pos.o + movementInfo.t_pos.o)
        {
            recv_data.rfinish();                   // prevent warnings spam
            return;
        }

        // if we boarded a transport, add us to it
        if (plMover && !plMover->GetTransport())
        {
            // elevators also cause the client to send MOVEMENTFLAG_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.t_guid)
                {
                    plMover->m_transport = (*iter);
                    (*iter)->AddPassenger(plMover);
                    break;
                }
            }
        }

        if (!mover->GetTransport() && !mover->GetVehicle())
        {
            GameObject *go = mover->GetMap()->GetGameObject(movementInfo.t_guid);
            if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
                movementInfo.moveFlags &= ~MOVEFLAG_ONTRANSPORT;
        }
    }
    else if (plMover && plMover->GetTransport())                // if we were on a transport, leave
    {
        plMover->m_transport->RemovePassenger(plMover);
        plMover->m_transport = NULL;
        movementInfo.t_time = 0;
        movementInfo.t_seat = -1;
    }

    // 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->HandleFall(movementInfo);

    if (plMover && ((movementInfo.moveFlags & MOVEFLAG_SWIMMING) != 0) != plMover->IsInWater())
    {
        // now client not include swimming flag in case jumping under water
        plMover->SetInWater(!plMover->IsInWater());// || plMover->GetMap()->IsUnderWater(movementInfo.pos.x, movementInfo.pos.y, movementInfo.pos.y));
    }

    /*----------------------*/

    /* process position-change */
    WorldPacket data(Opcodes(opcode), recv_data.size());
    movementInfo.time = WorldTimer::getMSTime();
    movementInfo.guid = mover->GetObjectGuid();
    WriteMovementInfo(&data, &movementInfo);
    mover->SendMessageToSet(&data, _player);

    mover->m_movementInfo = movementInfo;

    // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
    if (mover->GetVehicle())
    {
        mover->SetOrientation(movementInfo.pos.o);
        return;
    }

    mover->SetPosition(movementInfo.pos.x, movementInfo.pos.y, movementInfo.pos.z, movementInfo.pos.o, false);

    if (plMover)                                            // nothing is charmed, or player charmed
    {
        plMover->UpdateFallInformationIfNeed(movementInfo, opcode);

        if (movementInfo.pos.z < -500.0f)
        {
            //if (!(plMover->InBattleground()
            //    && plMover->GetBattleground()
            //    && plMover->GetBattleground()->HandlePlayerUnderMap(_player)))
            {
                // 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, GetPlayer()->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();
            }
        }
    }
}
Beispiel #28
0
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
{
    DEBUG_LOG("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS");
    uint64 Guid;
    recv_data >> Guid;

    Player *player = sObjectMgr.GetPlayer(Guid);
    if(!player)
    {
        WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2);
        data << uint8(0);                                   // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
        data.appendPackGUID(Guid);
        data << uint32(GROUP_UPDATE_FLAG_STATUS);
        data << uint16(MEMBER_STATUS_OFFLINE);
        SendPacket(&data);
        return;
    }

    Unit *pet = player->GetCharmOrPet();

    WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8);
    data << uint8(0);                                       // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
    data << player->GetPackGUID();

    uint32 mask1 = 0x00040BFF;                              // common mask, real flags used 0x000040BFF
    if(pet)
        mask1 = 0xFFFFFFFF;                                 // for hunters and other classes with pets

    Powers powerType = player->getPowerType();
    data << uint32(mask1);                                  // group update mask
    data << uint16(MEMBER_STATUS_ONLINE);                   // member's online status
    data << uint32(player->GetHealth());                    // GROUP_UPDATE_FLAG_CUR_HP
    data << uint32(player->GetMaxHealth());                 // GROUP_UPDATE_FLAG_MAX_HP
    data << uint8(powerType);                               // GROUP_UPDATE_FLAG_POWER_TYPE
    data << uint16(player->GetPower(powerType));            // GROUP_UPDATE_FLAG_CUR_POWER
    data << uint16(player->GetMaxPower(powerType));         // GROUP_UPDATE_FLAG_MAX_POWER
    data << uint16(player->getLevel());                     // GROUP_UPDATE_FLAG_LEVEL
    data << uint16(player->GetZoneId());                    // GROUP_UPDATE_FLAG_ZONE
    data << uint16(player->GetPositionX());                 // GROUP_UPDATE_FLAG_POSITION
    data << uint16(player->GetPositionY());                 // GROUP_UPDATE_FLAG_POSITION

    uint64 auramask = 0;
    size_t maskPos = data.wpos();
    data << uint64(auramask);                               // placeholder
    for(uint8 i = 0; i < MAX_AURAS; ++i)
    {
        if(uint32 aura = player->GetVisibleAura(i))
        {
            auramask |= (uint64(1) << i);
            data << uint32(aura);
            data << uint8(1);
        }
    }
    data.put<uint64>(maskPos, auramask);                    // GROUP_UPDATE_FLAG_AURAS

    if(pet)
    {
        Powers petpowertype = pet->getPowerType();
        data << pet->GetObjectGuid();                       // GROUP_UPDATE_FLAG_PET_GUID
        data << pet->GetName();                             // GROUP_UPDATE_FLAG_PET_NAME
        data << uint16(pet->GetDisplayId());                // GROUP_UPDATE_FLAG_PET_MODEL_ID
        data << uint32(pet->GetHealth());                   // GROUP_UPDATE_FLAG_PET_CUR_HP
        data << uint32(pet->GetMaxHealth());                // GROUP_UPDATE_FLAG_PET_MAX_HP
        data << uint8(petpowertype);                        // GROUP_UPDATE_FLAG_PET_POWER_TYPE
        data << uint16(pet->GetPower(petpowertype));        // GROUP_UPDATE_FLAG_PET_CUR_POWER
        data << uint16(pet->GetMaxPower(petpowertype));     // GROUP_UPDATE_FLAG_PET_MAX_POWER

        uint64 petauramask = 0;
        size_t petMaskPos = data.wpos();
        data << uint64(petauramask);                        // placeholder
        for(uint8 i = 0; i < MAX_AURAS; ++i)
        {
            if(uint32 petaura = pet->GetVisibleAura(i))
            {
                petauramask |= (uint64(1) << i);
                data << uint32(petaura);
                data << uint8(1);
            }
        }
        data.put<uint64>(petMaskPos, petauramask);          // GROUP_UPDATE_FLAG_PET_AURAS
        data << (uint32) player->m_movementInfo.GetTransportDBCSeat();
    }
    else
    {
        data << uint8(0);                                   // GROUP_UPDATE_FLAG_PET_NAME
        data << uint64(0);                                  // GROUP_UPDATE_FLAG_PET_AURAS
    }

    SendPacket(&data);
}
Beispiel #29
0
void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data)
{
    uint32 mask = player->GetGroupUpdateFlag();

    if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)                // if update power type, update current/max power also
        mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER);

    if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)            // same for pets
        mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);

    uint32 byteCount = 0;
    for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i)
        if (mask & (1 << i))
            byteCount += GroupUpdateLength[i];

    data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount);
    *data << player->GetPackGUID();
    *data << uint32(mask);

    if (mask & GROUP_UPDATE_FLAG_STATUS)
    {
        if (player)
        {
            if (player->IsPvP())
                *data << uint16(MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP);
            else
                *data << uint16(MEMBER_STATUS_ONLINE);
        }
        else
            *data << uint16(MEMBER_STATUS_OFFLINE);
    }

    if (mask & GROUP_UPDATE_FLAG_CUR_HP)
        *data << uint32(player->GetHealth());

    if (mask & GROUP_UPDATE_FLAG_MAX_HP)
        *data << uint32(player->GetMaxHealth());

    Powers powerType = player->getPowerType();
    if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
        *data << uint8(powerType);

    if (mask & GROUP_UPDATE_FLAG_CUR_POWER)
        *data << uint16(player->GetPower(powerType));

    if (mask & GROUP_UPDATE_FLAG_MAX_POWER)
        *data << uint16(player->GetMaxPower(powerType));

    if (mask & GROUP_UPDATE_FLAG_LEVEL)
        *data << uint16(player->getLevel());

    if (mask & GROUP_UPDATE_FLAG_ZONE)
        *data << uint16(player->GetZoneId());

    if (mask & GROUP_UPDATE_FLAG_POSITION)
        *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY());

    if (mask & GROUP_UPDATE_FLAG_AURAS)
    {
        const uint64& auramask = player->GetAuraUpdateMask();
        *data << uint64(auramask);
        for(uint32 i = 0; i < MAX_AURAS; ++i)
        {
            if(auramask & (uint64(1) << i))
            {
                *data << uint32(player->GetVisibleAura(i));
                *data << uint8(1);
            }
        }
    }

    Unit *pet = player->GetCharmOrPet();
    if (mask & GROUP_UPDATE_FLAG_PET_GUID)
        *data << (pet ? pet->GetObjectGuid() : ObjectGuid());

    if (mask & GROUP_UPDATE_FLAG_PET_NAME)
    {
        if(pet)
            *data << pet->GetName();
        else
            *data << uint8(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID)
    {
        if(pet)
            *data << uint16(pet->GetDisplayId());
        else
            *data << uint16(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
    {
        if(pet)
            *data << uint32(pet->GetHealth());
        else
            *data << uint32(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
    {
        if(pet)
            *data << uint32(pet->GetMaxHealth());
        else
            *data << uint32(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
    {
        if(pet)
            *data << uint8(pet->getPowerType());
        else
            *data << uint8(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER)
    {
        if(pet)
            *data << uint16(pet->GetPower(pet->getPowerType()));
        else
            *data << uint16(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER)
    {
        if(pet)
            *data << uint16(pet->GetMaxPower(pet->getPowerType()));
        else
            *data << uint16(0);
    }

    if (mask & GROUP_UPDATE_FLAG_PET_AURAS)
    {
        if(pet)
        {
            const uint64& auramask = pet->GetAuraUpdateMask();
            *data << uint64(auramask);
            for(uint32 i = 0; i < MAX_AURAS; ++i)
            {
                if(auramask & (uint64(1) << i))
                {
                    *data << uint32(pet->GetVisibleAura(i));
                    *data << uint8(1);
                }
            }
        }
        else
            *data << uint64(0);
    }

    if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
    {
        *data << (uint32) player->m_movementInfo.GetTransportDBCSeat();
    }
}
bool TargetedMovementGeneratorMedium<T, D>::update(T& owner, const uint32& time_diff)
{
    if (!m_target.isValid() || !m_target->IsInWorld())
        return false;

    if (!owner.isAlive())
        return true;

    if (owner.hasUnitState(UNIT_STAT_NOT_MOVE) || (owner.IsInUnitState(UNIT_ACTION_CHASE) && owner.hasUnitState(UNIT_STAT_NO_COMBAT_MOVEMENT)))
    {
        D::_clearUnitStateMove(owner);
        return true;
    }

    // prevent movement while casting spells with cast time or channel time
    if (!IsAbleMoveWhenCast(owner.GetEntry()) && owner.IsNonMeleeSpellCasted(false, false, true))
    {
        owner.StopMoving();
        return true;
    }

    // prevent crash after creature killed pet
    if (static_cast<D*>(this)->_lostTarget(owner))
    {
        D::_clearUnitStateMove(owner);
        if (m_waitTargetTimer >= TARGET_NOT_ACCESSIBLE_MAX_TIMER)
            return false;
        else
        {
            m_waitTargetTimer += 5 * time_diff;
            return true;
        }
    }

    if (!m_target->isInAccessablePlaceFor(&owner))
        return true;

    bool moveToTarget = false;

    m_recheckDistanceTimer.Update(time_diff);
    if (m_recheckDistanceTimer.Passed())
    {
        m_recheckDistanceTimer.Reset(this->GetMovementGeneratorType() == FOLLOW_MOTION_TYPE
                                     ? RECHECK_DISTANCE_TIMER_FOLLOW
                                     : RECHECK_DISTANCE_TIMER);

        G3D::Vector3 dest = owner.movespline->FinalDestination();
        moveToTarget = dest == Vector3() ? true : RequiresNewPosition(owner, dest.x, dest.y, dest.z);

        if (owner.GetTypeId() == TYPEID_UNIT && !((Creature*)&owner)->IsPet())
        {
            Unit* pVictim = owner.getVictim();
            if (pVictim && pVictim->GetObjectGuid() == m_target->GetObjectGuid())
            {
                if (!pVictim->isAlive() && owner.movespline->Finalized())
                    return false;

                if (!m_offset && owner.movespline->Finalized() && !owner.CanReachWithMeleeAttack(pVictim) &&
                        !m_target->m_movementInfo.HasMovementFlag(MOVEFLAG_PENDINGSTOP))
                {
                    if (m_waitTargetTimer < TARGET_NOT_ACCESSIBLE_MAX_TIMER)
                        m_waitTargetTimer += m_recheckDistanceTimer.GetExpiry();
                    else
                        return false;
                }
                else
                    m_waitTargetTimer = 0;
            }
        }
    }

    if (m_speedChanged || moveToTarget)
        _setTargetLocation(owner, moveToTarget);

    if (owner.movespline->Finalized())
    {
        if (fabs(m_angle) < M_NULL_F && !owner.HasInArc(0.01f, m_target.getTarget()))
            owner.SetInFront(m_target.getTarget());

        if (!m_targetReached)
        {
            m_targetReached = true;
            static_cast<D*>(this)->_reachTarget(owner);
        }
    }
    return true;
}