Exemple #1
0
// Helper function, to process a slave list
void CreatureLinkingHolder::ProcessSlaveGuidList(CreatureLinkingEvent eventType, Creature* pSource, uint32 flag, uint16 searchRange, GuidList& slaveGuidList, Unit* pEnemy)
{
    if (!flag)
        return;

    for (GuidList::iterator slave_itr = slaveGuidList.begin(); slave_itr != slaveGuidList.end();)
    {
        Creature* pSlave = pSource->GetMap()->GetCreature(*slave_itr);
        if (!pSlave)
        {
            // Remove old guid first
            slaveGuidList.erase(slave_itr++);
            continue;
        }

        ++slave_itr;

        // Ignore Pets
        if (pSlave->IsPet())
            continue;

        // Handle single slave
        if (IsSlaveInRangeOfBoss(pSlave, pSource, searchRange))
            ProcessSlave(eventType, pSource, flag, pSlave, pEnemy);
    }
}
Exemple #2
0
// This function lets a slave refollow his master
bool CreatureLinkingHolder::TryFollowMaster(Creature* pCreature)
{
    CreatureLinkingInfo const*  pInfo = sCreatureLinkingMgr.GetLinkedTriggerInformation(pCreature);
    if (!pInfo || !(pInfo->linkingFlag & FLAG_FOLLOW))
        return false;

    Creature* pMaster = NULL;
    if (pInfo->mapId != INVALID_MAP_ID)                     // entry case
    {
        BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
        for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr)
        {
            pMaster = pCreature->GetMap()->GetCreature(itr->second);
            if (pMaster && IsSlaveInRangeOfBoss(pCreature, pMaster, pInfo->searchRange))
                break;
        }
    }
    else                                                    // guid case
    {
        CreatureData const* masterData = sObjectMgr.GetCreatureData(pInfo->masterDBGuid);
        CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(masterData->id);
        pMaster = pCreature->GetMap()->GetCreature(ObjectGuid(cInfo->GetHighGuid(), cInfo->Entry, pInfo->masterDBGuid));
    }

    if (pMaster && pMaster->isAlive())
    {
        SetFollowing(pCreature, pMaster);
        return true;
    }

    return false;
}
/** Worker function to check if a spawning condition is met
 *
 *  This function is used directly from above function, and for recursive use
 *   in case of recursive use it is used only on _map with information of lowGuid.
 *
 *  @param lowGuid (only relevant in case of recursive uses) -- db-guid of the npc that is checked
 *  @param _map Map on which things are checked
 *  @param pInfo (only shipped in case of initial use) -- used as marker of first use, also in first use filled directly
 *  @param sx, sy (spawn position of the checked npc with initial use)
 */
bool CreatureLinkingHolder::CanSpawn(uint32 lowGuid, Map* _map, CreatureLinkingInfo const*  pInfo, float sx, float sy) const
{
    if (!pInfo)                                             // Prepare data for recursive use
    {
        CreatureData const* data = sObjectMgr.GetCreatureData(lowGuid);
        if (!data)
            return true;
        pInfo = sCreatureLinkingMgr.GetLinkedTriggerInformation(data->id, lowGuid, data->mapid);
        if (!pInfo)
            return true;
        // Has lowGuid npc actually spawning linked?
        if (!sCreatureLinkingMgr.IsSpawnedByLinkedMob(pInfo))
            return true;

        sx = data->posX;                                    // Fill position data
        sy = data->posY;
    }

    if (pInfo->searchRange == 0)                            // Map wide case
    {
        if (!pInfo->masterDBGuid)
            return false;                                   // This should never happen

        if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_DEAD)
            return IsRespawnReady(pInfo->masterDBGuid, _map);
        else if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_ALIVE)
            return !IsRespawnReady(pInfo->masterDBGuid, _map);
        else
            return true;
    }

    // Search for nearby master
    BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
    for (BossGuidMap::const_iterator itr = finds.first; itr != finds.second; ++itr)
    {
        Creature* pMaster = _map->GetCreature(itr->second);
        if (pMaster && IsSlaveInRangeOfBoss(pMaster, sx, sy, pInfo->searchRange))
        {
            if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_DEAD)
                return pMaster->IsAlive();
            else if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_ALIVE)
                return !pMaster->IsAlive();
            else
                return true;
        }
    }

    return true;                                            // local boss does not exist - spawn
}
Exemple #4
0
// This function lets a slave refollow his master
bool CreatureLinkingHolder::TryFollowMaster(Creature* pCreature)
{
    CreatureLinkingInfo const*  pInfo = sCreatureLinkingMgr.GetLinkedTriggerInformation(pCreature);
    if (!pInfo || !(pInfo->linkingFlag & FLAG_FOLLOW))
        return false;

    BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
    for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr)
    {
        Creature* pMaster = pCreature->GetMap()->GetCreature(itr->second);
        if (pMaster && pMaster->isAlive() && IsSlaveInRangeOfBoss(pCreature, pMaster, pInfo->searchRange))
        {
            SetFollowing(pCreature, pMaster);
            return true;
        }
    }

    return false;
}
Exemple #5
0
// Function to check if a passive spawning condition is met
bool CreatureLinkingHolder::CanSpawn(Creature* pCreature)
{
    CreatureLinkingInfo const*  pInfo = sCreatureLinkingMgr.GetLinkedTriggerInformation(pCreature);
    if (!pInfo)
        return true;

    if (pInfo->searchRange == 0)                            // Map wide case
    {
        if (!pInfo->masterDBGuid)
            return false;                                   // This should never happen

        if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_DEAD)
            return pCreature->GetMap()->GetPersistentState()->GetCreatureRespawnTime(pInfo->masterDBGuid) == 0;
        else if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_ALIVE)
            return pCreature->GetMap()->GetPersistentState()->GetCreatureRespawnTime(pInfo->masterDBGuid) > 0;
        else
            return true;
    }

    // Search for nearby master
    BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
    for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr)
    {
        Creature* pMaster = pCreature->GetMap()->GetCreature(itr->second);
        if (pMaster && IsSlaveInRangeOfBoss(pCreature, pMaster, pInfo->searchRange))
        {
            if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_DEAD)
                return pMaster->isAlive();
            else if (pInfo->linkingFlag & FLAG_CANT_SPAWN_IF_BOSS_ALIVE)
                return !pMaster->isAlive();
            else
                return true;
        }
    }

    return true;                                            // local boss does not exist - spawn
}
Exemple #6
0
// Function to process actions for linked NPCs
void CreatureLinkingHolder::DoCreatureLinkingEvent(CreatureLinkingEvent eventType, Creature* pSource, Unit* pEnemy /* = NULL*/)
{
    // This check will be needed in reload case
    if (!sCreatureLinkingMgr.IsLinkedEventTrigger(pSource))
        return;

    // Ignore atypic behaviour
    if (pSource->IsControlledByPlayer())
        return;

    if (eventType == LINKING_EVENT_AGGRO && !pEnemy)
        return;

    uint32 eventFlagFilter = 0;
    uint32 reverseEventFlagFilter = 0;

    switch (eventType)
    {
        case LINKING_EVENT_AGGRO:   eventFlagFilter = EVENT_MASK_ON_AGGRO;   reverseEventFlagFilter = FLAG_TO_AGGRO_ON_AGGRO;   break;
        case LINKING_EVENT_EVADE:   eventFlagFilter = EVENT_MASK_ON_EVADE;   reverseEventFlagFilter = FLAG_TO_RESPAWN_ON_EVADE; break;
        case LINKING_EVENT_DIE:     eventFlagFilter = EVENT_MASK_ON_DIE;     reverseEventFlagFilter = 0;                        break;
        case LINKING_EVENT_RESPAWN: eventFlagFilter = EVENT_MASK_ON_RESPAWN; reverseEventFlagFilter = FLAG_FOLLOW;              break;
    }

    // Process Slaves (by entry)
    HolderMapBounds bounds = m_holderMap.equal_range(pSource->GetEntry());
    for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
        ProcessSlaveGuidList(eventType, pSource, itr->second.linkingFlag & eventFlagFilter, itr->second.searchRange, itr->second.linkedGuids, pEnemy);

    // Process Slaves (by guid)
    bounds = m_holderGuidMap.equal_range(pSource->GetGUIDLow());
    for (HolderMap::iterator itr = bounds.first; itr != bounds.second; ++itr)
        ProcessSlaveGuidList(eventType, pSource, itr->second.linkingFlag & eventFlagFilter, itr->second.searchRange, itr->second.linkedGuids, pEnemy);

    // Process Master
    if (CreatureLinkingInfo const* pInfo = sCreatureLinkingMgr.GetLinkedTriggerInformation(pSource))
    {
        if (pInfo->linkingFlag & reverseEventFlagFilter)
        {
            Creature* pMaster = NULL;
            if (pInfo->mapId != INVALID_MAP_ID)             // entry case
            {
                BossGuidMapBounds finds = m_masterGuid.equal_range(pInfo->masterId);
                for (BossGuidMap::iterator itr = finds.first; itr != finds.second; ++itr)
                {
                    pMaster = pSource->GetMap()->GetCreature(itr->second);
                    if (pMaster && IsSlaveInRangeOfBoss(pSource, pMaster, pInfo->searchRange))
                        break;
                }
            }
            else                                            // guid case
            {
                CreatureData const* masterData = sObjectMgr.GetCreatureData(pInfo->masterDBGuid);
                CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(masterData->id);
                pMaster = pSource->GetMap()->GetCreature(ObjectGuid(cInfo->GetHighGuid(), cInfo->Entry, pInfo->masterDBGuid));
            }

            if (pMaster)
            {
                switch (eventType)
                {
                    case LINKING_EVENT_AGGRO:
                        if (pMaster->IsControlledByPlayer())
                            return;

                        if (pMaster->isInCombat())
                            pMaster->SetInCombatWith(pEnemy);
                        else
                            pMaster->AI()->AttackStart(pEnemy);
                        break;
                    case LINKING_EVENT_EVADE:
                        if (!pMaster->isAlive())
                            pMaster->Respawn();
                        break;
                    case LINKING_EVENT_RESPAWN:
                        if (pMaster->isAlive())
                            SetFollowing(pSource, pMaster);
                }
            }
        }
    }
}
// Function to check if a slave belongs to a boss by range-issue
bool CreatureLinkingHolder::IsSlaveInRangeOfBoss(Creature const* pSlave, Creature const* pBoss, uint16 searchRange) const
{
    float sX, sY, sZ;
    pSlave->GetRespawnCoord(sX, sY, sZ);
    return IsSlaveInRangeOfBoss(pBoss, sX, sY, searchRange);
}