コード例 #1
0
    void InitSentinelsNear(Unit* pTarget)
    {
        if (!m_lAssistList.empty())
        {
            for (GuidList::const_iterator itr = m_lAssistList.begin(); itr != m_lAssistList.end(); ++itr)
            {
                if (*itr == m_creature->GetObjectGuid())
                    continue;

                if (Creature* pBuddy = m_creature->GetMap()->GetCreature(*itr))
                {
                    if (pBuddy->isAlive())
                        pBuddy->AI()->AttackStart(pTarget);
                }
            }

            return;
        }

        std::list<Creature*> lAssistList;
        GetCreatureListWithEntryInGrid(lAssistList, m_creature, m_creature->GetEntry(), 80.0f);

        for (std::list<Creature*>::iterator iter = lAssistList.begin(); iter != lAssistList.end(); ++iter)
        {
            m_lAssistList.push_back((*iter)->GetObjectGuid());

            if ((*iter)->GetObjectGuid() == m_creature->GetObjectGuid())
                continue;

            (*iter)->AI()->AttackStart(pTarget);
        }

        if (m_lAssistList.size() != MAX_BUDDY)
            script_error_log("npc_anubisath_sentinel for %s found too few/too many buddies, expected %u.", m_creature->GetGuidStr().c_str(), MAX_BUDDY);
    }
コード例 #2
0
   Unit* SelectTargetWithinDist()
   {
        ThreatList const& m_threatlist = m_creature->getThreatManager().getThreatList();

        if (m_threatlist.empty())
            return NULL;

        GuidList distPositive;
        for (ThreatList::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr)
        {
            if (Unit* pTemp = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()))
            {
                //player within 80 yards
                if ((pTemp->GetTypeId() == TYPEID_PLAYER && !m_creature->IsWithinDist(pTemp, 10.0f) && m_creature->IsWithinDist(pTemp, 80.0f)))
                    distPositive.push_back(pTemp->GetObjectGuid());
            }
        }

        if (!distPositive.empty())
        {
            GuidList::iterator m_uiPlayerGUID = distPositive.begin();
            advance(m_uiPlayerGUID, (rand()%distPositive.size()));

            if (Player* pTemp = m_creature->GetMap()->GetPlayer(*m_uiPlayerGUID))
                return pTemp;
        }
        return NULL;
    }
コード例 #3
0
    void UpdateEscortAI(const uint32 uiDiff) override
    {
        DialogueUpdate(uiDiff);

        // Check if all Onyxia guards are dead
        if (m_uiGuardCheckTimer)
        {
            if (m_uiGuardCheckTimer <= uiDiff)
            {
                uint8 uiDeadGuardsCount = 0;
                for (GuidList::const_iterator itr = m_lRoyalGuardsGuidList.begin(); itr != m_lRoyalGuardsGuidList.end(); ++itr)
                {
                    if (Creature* pGuard = m_creature->GetMap()->GetCreature(*itr))
                    {
                        if (!pGuard->isAlive() && pGuard->GetEntry() == NPC_GUARD_ONYXIA)
                            ++uiDeadGuardsCount;
                    }
                }
                if (uiDeadGuardsCount == m_lRoyalGuardsGuidList.size())
                {
                    StartNextDialogueText(NPC_GUARD_ONYXIA);
                    m_uiGuardCheckTimer = 0;
                }
                else
                    m_uiGuardCheckTimer = 1000;
            }
            else
                m_uiGuardCheckTimer -= uiDiff;
        }
    }
コード例 #4
0
    // Activate a random Constellation
    void ActivateRandomConstellation()
    {
        // spawn a new set of constellations if empty
        if (m_lConstellationsGuids.empty())
        {
            DoSpawnConstellations();
            m_uiConstellationTimer = 5000;
            return;
        }

        GuidList::iterator iter = m_lConstellationsGuids.begin();
        advance(iter, urand(0, m_lConstellationsGuids.size() - 1));

        if (Creature* pConstellation = m_creature->GetMap()->GetCreature(*iter))
        {
            // follow second top aggro player
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, uint32(0), SELECT_FLAG_PLAYER))
            {
                pConstellation->GetMotionMaster()->MoveFollow(pTarget, CONTACT_DISTANCE, 0);
                SendAIEvent(AI_EVENT_CUSTOM_A, m_creature, pConstellation);
                ++m_uiActiveConstelations;
            }
        }

        m_lConstellationsGuids.remove(*iter);
    }
コード例 #5
0
 void GetAIInformation(ChatHandler& reader) override
 {
     if (m_lAssistList.empty())
         reader.PSendSysMessage("Anubisath Sentinel - group not assigned, will be assigned OnAggro");
     if (m_lAssistList.size() == MAX_BUDDY)
         reader.PSendSysMessage("Anubisath Sentinel - proper group found");
     else
         reader.PSendSysMessage("Anubisath Sentinel - not correct number of mobs for group found. Number found %u, should be %u", uint32(m_lAssistList.size()), MAX_BUDDY);
 }
コード例 #6
0
    void SummonedCreatureJustDied(Creature* pSummoned) override
    {
        if (pSummoned->GetEntry() == NPC_FLAMEWAKER_HEALER || pSummoned->GetEntry() == NPC_FLAMEWAKER_ELITE)
        {
            m_uiAddsKilled += 1;

            // Yell if only one Add alive
            if (m_uiAddsKilled == m_luiMajordomoAddsGUIDs.size() - 1)
                DoScriptText(SAY_LAST_ADD, m_creature);

            // All adds are killed, retreat
            else if (m_uiAddsKilled == m_luiMajordomoAddsGUIDs.size())
            {
                m_bHasEncounterFinished = true;
                m_creature->GetMotionMaster()->MoveTargetedHome();
            }
        }
    }
コード例 #7
0
ファイル: boss_thorim.cpp プロジェクト: jviljoen82/ScriptDev3
    // function to return a random arena upper Bunny
    Creature* SelectRandomUpperBunny()
    {
        if (m_lUpperBunniesGuids.empty())
            return NULL;

        GuidList::iterator iter = m_lUpperBunniesGuids.begin();
        advance(iter, urand(0, m_lUpperBunniesGuids.size() - 1));

        return m_creature->GetMap()->GetCreature(*iter);
    }
コード例 #8
0
ファイル: boss_thorim.cpp プロジェクト: jviljoen82/ScriptDev3
    // function to return a random arena bunny for Blizzard spell
    ObjectGuid SelectRandomBunnyGuid()
    {
        if (m_lBunniesGuids.empty())
            return ObjectGuid();

        GuidList::iterator iter = m_lBunniesGuids.begin();
        advance(iter, urand(0, m_lBunniesGuids.size() - 1));

        return *iter;
    }
コード例 #9
0
    ObjectGuid SelectRandomCrowdNpc()
    {
        if (m_lCrowdGuidList.empty())
            return ObjectGuid();

        GuidList::iterator iter = m_lCrowdGuidList.begin();
        advance(iter, urand(0, m_lCrowdGuidList.size() - 1));

        return *iter;
    }
コード例 #10
0
ファイル: boss_jedoga.cpp プロジェクト: jviljoen82/ScriptDev3
    ObjectGuid SelectRandomVolunteer()
    {
        if (m_lVolunteerGuidList.empty())
            return ObjectGuid();

        GuidList::iterator iter = m_lVolunteerGuidList.begin();
        advance(iter, urand(0, m_lVolunteerGuidList.size() - 1));

        return *iter;
    }
コード例 #11
0
    void SummonedCreatureJustDied(Creature* pSummoned) override
    {
        if (pSummoned->GetEntry() == NPC_FLAMEWAKER_HEALER || pSummoned->GetEntry() == NPC_FLAMEWAKER_ELITE)
        {
            m_uiAddsKilled += 1;

            // If 4 adds (half of them) are dead, make all remaining healers immune to polymorph via aura
            if (m_uiAddsKilled >= MAX_MAJORDOMO_ADDS / 2)
                DoCastSpellIfCan(m_creature, SPELL_IMMUNE_POLY);

            // Yell if only one Add alive
            if (m_uiAddsKilled == m_luiMajordomoAddsGUIDs.size() - 1)
                DoScriptText(SAY_LAST_ADD, m_creature);

            // All adds are killed, retreat
            else if (m_uiAddsKilled == m_luiMajordomoAddsGUIDs.size())
            {
                m_bHasEncounterFinished = true;
                m_creature->GetMotionMaster()->MoveTargetedHome();
            }
        }
    }
コード例 #12
0
    void UpdateEscortAI(const uint32 uiDiff) override
    {
        DialogueUpdate(uiDiff);

        // Check if all Onyxia guards are dead
        if (m_uiGuardCheckTimer)
        {
            if (m_uiGuardCheckTimer <= uiDiff)
            {
                uint8 uiDeadGuardsCount = 0;
                for (GuidList::const_iterator itr = m_lRoyalGuardsGuidList.begin(); itr != m_lRoyalGuardsGuidList.end(); ++itr)
                {
                    if (Creature* pGuard = m_creature->GetMap()->GetCreature(*itr))
                    {
                        if (!pGuard->isAlive() && pGuard->GetEntry() == NPC_GUARD_ONYXIA)
                            ++uiDeadGuardsCount;
                    }
                }
                if (uiDeadGuardsCount == m_lRoyalGuardsGuidList.size())
                {
                    StartNextDialogueText(NPC_GUARD_ONYXIA);
                    m_uiGuardCheckTimer = 0;
                }
                else
                    m_uiGuardCheckTimer = 1000;
            }
            else
                m_uiGuardCheckTimer -= uiDiff;
        }

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

        if (m_uiHammerTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAMMER_OF_JUSTICE) == CAST_OK)
                m_uiHammerTimer = 60000;
        }
        else
            m_uiHammerTimer -= uiDiff;

        if (m_uiCleaveTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_STRONG_CLEAVE) == CAST_OK)
                m_uiCleaveTimer = urand(1000, 5000);
        }
        else
            m_uiCleaveTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
コード例 #13
0
    void DoSetupAdds()
    {
        m_uiSetupAddsTimer = 0;

        if (!m_pInstance)
            return;

        GuidList lAddGuids;
        m_pInstance->GetKelidanAddList(lAddGuids);

        // Sort Adds to vector if not already done
        if (!lAddGuids.empty())
        {
            m_vAddGuids.reserve(lAddGuids.size());
            std::list<Creature*> lAdds;
            for (GuidList::const_iterator itr = lAddGuids.begin(); itr != lAddGuids.end(); ++itr)
            {
                if (Creature* pAdd = m_pInstance->instance->GetCreature(*itr))
                    lAdds.push_back(pAdd);
            }
            // Sort them by angle
            lAdds.sort(SortByAngle(m_creature));
            for (std::list<Creature*>::const_iterator itr = lAdds.begin(); itr != lAdds.end(); ++itr)
                m_vAddGuids.push_back((*itr)->GetObjectGuid());
        }

        // Respawn killed adds and reset counter
        m_uiKilledAdds = 0;
        for (GuidVector::const_iterator itr = m_vAddGuids.begin(); itr != m_vAddGuids.end(); ++itr)
        {
            Creature* pAdd = m_pInstance->instance->GetCreature(*itr);
            if (pAdd && !pAdd->isAlive())
                pAdd->Respawn();
        }

        // Cast pentagram
        uint8 s = m_vAddGuids.size();
        for (uint8 i = 0; i < s; ++i)
        {
            Creature* pCaster = m_pInstance->instance->GetCreature(m_vAddGuids[i]);
            Creature* pTarget = m_pInstance->instance->GetCreature(m_vAddGuids[(i + 2) % s]);
            if (pCaster && pTarget)
                pCaster->CastSpell(pTarget, SPELL_CHANNELING, TRIGGERED_NONE);
        }

        m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
        m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
    }
Creature* instance_zulgurub::SelectRandomPantherTrigger(bool bIsLeft)
{
    GuidList* plTempList = bIsLeft ? &m_lLeftPantherTriggerGUIDList : &m_lRightPantherTriggerGUIDList;
    std::vector<Creature*> vTriggers;
    vTriggers.reserve(plTempList->size());

    for (GuidList::const_iterator itr = plTempList->begin(); itr != plTempList->end(); ++itr)
    {
        if (Creature* pTemp = instance->GetCreature(*itr))
            vTriggers.push_back(pTemp);
    }

    if (vTriggers.empty())
        return NULL;

    return vTriggers[urand(0, vTriggers.size()-1)];
}
コード例 #15
0
    Player* SelectRandomPlayerForMark()
    {
        Player* pResult = NULL;
        GuidList lPlayers;
        ThreatList const& threatlist = m_creature->getThreatManager().getThreatList();

        if (!threatlist.empty())
        {
            for (ThreatList::const_iterator itr = threatlist.begin();itr != threatlist.end(); ++itr)
            {
                ObjectGuid const& guid = (*itr)->getUnitGuid();
                if (guid.IsPlayer() && guid != m_creature->getVictim()->GetObjectGuid()) // exclude current target
                {
                    // check if player already has the mark
                    if (Player* pPlayer = m_creature->GetMap()->GetPlayer(guid))
                    {
                        if (!pPlayer->HasAura(SPELL_MARK_OF_FALLEN_CHAMPION_DEBUFF))
                            lPlayers.push_back(guid);
                    }
                }
            }
        }

        if (!lPlayers.empty())
        {
            GuidList::iterator i = lPlayers.begin();
            uint32 max = uint32(lPlayers.size() - 1);

            if (max > 0)
                std::advance(i, urand(0, max));

            pResult = m_creature->GetMap()->GetPlayer(*i);
        }

        // last option - current target
        if (!pResult)
        {
            Unit* pVictim = m_creature->getVictim();
            if (pVictim && pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->HasAura(SPELL_MARK_OF_FALLEN_CHAMPION_DEBUFF))
                pResult = (Player*)pVictim;
        }

        return pResult;
    }
コード例 #16
0
    void UpdateAI(const uint32 uiDiff) override
    {
        switch (m_uiPhase)
        {
            case PHASE_CHANNEL:

                if (m_uiSummonDefenderTimer < uiDiff)
                {
                    DoSummonAshtongue(SPELL_SUMMON_DEFENDER);
                    m_uiSummonDefenderTimer = 15000;
                }
                else
                    m_uiSummonDefenderTimer -= uiDiff;

                if (m_lSorcerersGUIDList.size() <= m_uiChannelersDead)
                {
                    if (m_uiSummonSorcererTimer < uiDiff)
                    {
                        DoSummonAshtongue(SPELL_SUMMON_SORCERER);
                        m_uiSummonSorcererTimer = urand(20000, 30000);
                    }
                    else
                        m_uiSummonSorcererTimer -= uiDiff;
                }

                if (m_uiSummonPackTimer < uiDiff)
                {
                    DoSummonAshtongue();
                    m_uiSummonPackTimer = 35000;
                }
                else
                    m_uiSummonPackTimer -= uiDiff;

                break;
            case PHASE_COMBAT:

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

                if (!m_bHasYelledOnce && m_creature->GetHealthPercent() < 15.0f)
                {
                    DoScriptText(SAY_LOW_HEALTH, m_creature);
                    m_bHasYelledOnce = true;
                }

                if (m_uiDestructivePoisonTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_DESTRUCTIVE_POISON) == CAST_OK)
                        m_uiDestructivePoisonTimer = 15000;
                }
                else
                    m_uiDestructivePoisonTimer -= uiDiff;

                if (m_uiLightningBoltTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CHAIN_LIGHTNING) == CAST_OK)
                        m_uiLightningBoltTimer = 10000;
                }
                else
                    m_uiLightningBoltTimer -= uiDiff;

                DoMeleeAttackIfReady();

                break;
            case PHASE_EPILOGUE:
                DialogueUpdate(uiDiff);
                break;
        }
    }
コード例 #17
0
ファイル: boss_fankriss.cpp プロジェクト: Maduse/server
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        //
        // Mortal Wound
        if (m_uiMortalWoundTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_WOUND) == CAST_OK)
                m_uiMortalWoundTimer = urand(4000, 8000);
        }
        else
            m_uiMortalWoundTimer -= uiDiff;

        //
        // Summon Worm (1-3)
        if (m_uiSummonWorm1Timer < uiDiff)
        {
            // randomize order of Summon Worm pattern
            std::random_shuffle(vIndex.begin(), vIndex.end());
            m_creature->SummonCreature(NPC_SPAWN_FANKRISS, aSummonWormLocs[vIndex[0]].m_fX, aSummonWormLocs[vIndex[0]].m_fY, aSummonWormLocs[vIndex[0]].m_fZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 50000);
            m_uiSummonWorm1Timer = urand(50000, 70000);
            m_uiSummonWorm2Timer = urand(1000, 30000);
            m_uiSummonWorm3Timer = urand(2000, 30000);
        }
        else
            m_uiSummonWorm1Timer -= uiDiff;

        if (m_uiSummonWorm2Timer)
        {
            if (m_uiSummonWorm2Timer <= uiDiff)
            {
                m_creature->SummonCreature(NPC_SPAWN_FANKRISS, aSummonWormLocs[vIndex[1]].m_fX, aSummonWormLocs[vIndex[1]].m_fY, aSummonWormLocs[vIndex[1]].m_fZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 50000);
                m_uiSummonWorm2Timer = 0;
            }
            else
                m_uiSummonWorm2Timer -= uiDiff;
        }

        if (m_uiSummonWorm3Timer)
        {
            if (m_uiSummonWorm3Timer <= uiDiff)
            {
                m_creature->SummonCreature(NPC_SPAWN_FANKRISS, aSummonWormLocs[vIndex[2]].m_fX, aSummonWormLocs[vIndex[2]].m_fY, aSummonWormLocs[vIndex[2]].m_fZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 50000);
                m_uiSummonWorm3Timer = 0;
            }
            else
                m_uiSummonWorm3Timer -= uiDiff;
        }

        //
        // Entangle (1-3)
        if (m_uiEntangle1Timer < uiDiff)
        {
            // randomize order of Entangle pattern
            std::random_shuffle(vEntangleSpells.begin(), vEntangleSpells.end());
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER))
            {
                if (DoCastSpellIfCan(pTarget, vEntangleSpells[0]) == CAST_OK)
                {
                    m_uiEntangle1Timer      = urand(35000, 45000);
                    m_uiEntangle2Timer      = urand(2000, 20000);
                    m_uiEntangle3Timer      = urand(2000, 20000);
                    m_EntangleTargetGUID    = pTarget->GetObjectGuid();
                    m_uiEntangleSummonTimer = 1000;
                }
            }
        }
        else
            m_uiEntangle1Timer -= uiDiff;

        if (m_uiEntangle2Timer && !m_uiEntangleSummonTimer)
        {
            if (m_uiEntangle2Timer < uiDiff)
            {
                if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER))
                {
                    if (DoCastSpellIfCan(pTarget, vEntangleSpells[1]) == CAST_OK)
                    {
                        m_uiEntangle2Timer = 0;
                        m_EntangleTargetGUID = pTarget->GetObjectGuid();
                        m_uiEntangleSummonTimer = 1000;
                    }
                }
            }
            else
                m_uiEntangle2Timer -= uiDiff;
        }

        if (m_uiEntangle3Timer && !m_uiEntangleSummonTimer)
        {
            if (m_uiEntangle3Timer < uiDiff)
            {
                if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER))
                {
                    if (DoCastSpellIfCan(pTarget, vEntangleSpells[2]) == CAST_OK)
                    {
                        m_uiEntangle3Timer = 0;
                        m_EntangleTargetGUID = pTarget->GetObjectGuid();
                        m_uiEntangleSummonTimer = 1000;
                    }
                }
            }
            else
                m_uiEntangle3Timer -= uiDiff;
        }

        //
        // Spawn 4 Hatchlings on top of players who have been entangled
        if (m_uiEntangleSummonTimer)
        {
			if (m_uiEntangleSummonTimer < uiDiff)
			{
                if (m_lHatchlingsGUIDs.size() < (MAX_HATCHLINGS + 4))                               // If there are already more than MAX_HATCHLINGS - 4 up, prevent spawn
                {
                    if (Player* pTarget = m_creature->GetMap()->GetPlayer(m_EntangleTargetGUID))
                    {
                        float fX, fY, fZ;
                        for (uint8 i = 0; i < 4; ++i)
                        {
                            m_creature->GetRandomPoint(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 3.0f, fX, fY, fZ);
                            m_creature->SummonCreature(NPC_VEKNISS_HATCHLING, fX, fY, fZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 65000);
                        }
                    }
                }
				m_uiEntangleAttackTimer = 1500;
                m_uiEntangleSummonTimer = 0;
            }
            else
                m_uiEntangleSummonTimer -= uiDiff;
        }

		// Summoned Hatchlings should be set in combat with Zone after meleeing the person they've spawned next to once (if not picked up by a tank)
		if (m_uiEntangleAttackTimer)
		{
			if (m_uiEntangleAttackTimer < uiDiff)
			{
				for (GuidList::const_iterator itr = m_lHatchlingsGUIDs.begin(); itr != m_lHatchlingsGUIDs.end(); itr++)
				{
					if (Creature* pSummoned = m_creature->GetMap()->GetCreature(*itr))
						pSummoned->SetInCombatWithZone();
				}
			}
			else
				m_uiEntangleAttackTimer -= uiDiff;
		}

        DoMeleeAttackIfReady();

		// Evade in case Fankriss starts running after someone at zone in
		if (m_uiEvadeCheckTimer < uiDiff)
		{
			m_uiEvadeCheckTimer = 2500;
			if (m_creature->GetPositionY() > 1400)
				EnterEvadeMode();
		}
		else
			m_uiEvadeCheckTimer -= uiDiff;
    }
コード例 #18
0
ファイル: LFGQueue.cpp プロジェクト: samaelsacred/4.3.4
/**
   Check compatibilities between groups. If group is Matched proposal will be created

   @param[in]     check List of guids to check compatibilities
   @return LfgCompatibility type of compatibility
*/
LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
{
    std::string strGuids = ConcatenateGuids(check);
    LfgProposal proposal;
    LfgDungeonSet proposalDungeons;
    LfgGroupsMap proposalGroups;
    LfgRolesMap proposalRoles;

    // Check for correct size
    if (check.size() > MAXGROUPSIZE || check.empty())
    {
        TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s): Size wrong - Not compatibles", strGuids.c_str());
        return LFG_INCOMPATIBLES_WRONG_GROUP_SIZE;
    }

    // Check all-but-new compatiblitity
    if (check.size() > 2)
    {
        ObjectGuid frontGuid = check.front();
        check.pop_front();

        // Check all-but-new compatibilities (New, A, B, C, D) --> check(A, B, C, D)
        LfgCompatibility child_compatibles = CheckCompatibility(check);
        if (child_compatibles < LFG_COMPATIBLES_WITH_LESS_PLAYERS) // Group not compatible
        {
            TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) child %s not compatibles", strGuids.c_str(), ConcatenateGuids(check).c_str());
            SetCompatibles(strGuids, child_compatibles);
            return child_compatibles;
        }
        check.push_front(frontGuid);
    }

    // Check if more than one LFG group and number of players joining
    uint8 numPlayers = 0;
    uint8 numLfgGroups = 0;
    for (GuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it)
    {
        ObjectGuid guid = *it;
        LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
        if (itQueue == QueueDataStore.end())
        {
            TC_LOG_ERROR("lfg.queue.match.compatibility.check", "Guid: [%s] is not queued but listed as queued!", guid.ToString().c_str());
            RemoveFromQueue(guid);
            return LFG_COMPATIBILITY_PENDING;
        }

        // Store group so we don't need to call Mgr to get it later (if it's player group will be 0 otherwise would have joined as group)
        for (LfgRolesMap::const_iterator it2 = itQueue->second.roles.begin(); it2 != itQueue->second.roles.end(); ++it2)
            proposalGroups[it2->first] = itQueue->first.IsGroup() ? itQueue->first : ObjectGuid::Empty;

        numPlayers += itQueue->second.roles.size();

        if (sLFGMgr->IsLfgGroup(guid))
        {
            if (!numLfgGroups)
                proposal.group = guid;
            ++numLfgGroups;
        }
    }

    // Group with less that MAXGROUPSIZE members always compatible
    if (check.size() == 1 && numPlayers != MAXGROUPSIZE)
    {
        TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) sigle group. Compatibles", strGuids.c_str());
        LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());

        LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS);
        data.roles = itQueue->second.roles;
        LFGMgr::CheckGroupRoles(data.roles);

        UpdateBestCompatibleInQueue(itQueue, strGuids, data.roles);
        SetCompatibilityData(strGuids, data);
        return LFG_COMPATIBLES_WITH_LESS_PLAYERS;
    }

    if (numLfgGroups > 1)
    {
        TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) More than one Lfggroup (%u)", strGuids.c_str(), numLfgGroups);
        SetCompatibles(strGuids, LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS);
        return LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS;
    }

    if (numPlayers > MAXGROUPSIZE)
    {
        TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Too much players (%u)", strGuids.c_str(), numPlayers);
        SetCompatibles(strGuids, LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS);
        return LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS;
    }

    // If it's single group no need to check for duplicate players, ignores, bad roles or bad dungeons as it's been checked before joining
    if (check.size() > 1)
    {
        for (GuidList::const_iterator it = check.begin(); it != check.end(); ++it)
        {
            LfgRolesMap const& roles = QueueDataStore[(*it)].roles;
            for (LfgRolesMap::const_iterator itRoles = roles.begin(); itRoles != roles.end(); ++itRoles)
            {
                LfgRolesMap::const_iterator itPlayer;
                for (itPlayer = proposalRoles.begin(); itPlayer != proposalRoles.end(); ++itPlayer)
                {
                    if (itRoles->first == itPlayer->first)
                        TC_LOG_ERROR("lfg.queue.match.compatibility.check", "Guids: ERROR! Player multiple times in queue! [%s]", itRoles->first.ToString().c_str());
                    else if (sLFGMgr->HasIgnore(itRoles->first, itPlayer->first))
                        break;
                }
                if (itPlayer == proposalRoles.end())
                    proposalRoles[itRoles->first] = itRoles->second;
            }
        }

        if (uint8 playersize = numPlayers - proposalRoles.size())
        {
            TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) not compatible, %u players are ignoring each other", strGuids.c_str(), playersize);
            SetCompatibles(strGuids, LFG_INCOMPATIBLES_HAS_IGNORES);
            return LFG_INCOMPATIBLES_HAS_IGNORES;
        }

        LfgRolesMap debugRoles = proposalRoles;
        if (!LFGMgr::CheckGroupRoles(proposalRoles))
        {
            std::ostringstream o;
            for (LfgRolesMap::const_iterator it = debugRoles.begin(); it != debugRoles.end(); ++it)
                o << ", " << it->first.GetRawValue() << ": " << GetRolesString(it->second);

            TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Roles not compatible%s", strGuids.c_str(), o.str().c_str());
            SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_ROLES);
            return LFG_INCOMPATIBLES_NO_ROLES;
        }

        GuidList::iterator itguid = check.begin();
        proposalDungeons = QueueDataStore[*itguid].dungeons;
        std::ostringstream o;
        o << ", " << itguid->GetRawValue() << ": (" << ConcatenateDungeons(proposalDungeons) << ")";
        for (++itguid; itguid != check.end(); ++itguid)
        {
            LfgDungeonSet temporal;
            LfgDungeonSet& dungeons = QueueDataStore[*itguid].dungeons;
            o << ", " << itguid->GetRawValue() << ": (" << ConcatenateDungeons(dungeons) << ")";
            std::set_intersection(proposalDungeons.begin(), proposalDungeons.end(), dungeons.begin(), dungeons.end(), std::inserter(temporal, temporal.begin()));
            proposalDungeons = temporal;
        }

        if (proposalDungeons.empty())
        {
            TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) No compatible dungeons%s", strGuids.c_str(), o.str().c_str());
            SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_DUNGEONS);
            return LFG_INCOMPATIBLES_NO_DUNGEONS;
        }
    }
    else
    {
        ObjectGuid gguid = *check.begin();
        const LfgQueueData &queue = QueueDataStore[gguid];
        proposalDungeons = queue.dungeons;
        proposalRoles = queue.roles;
        LFGMgr::CheckGroupRoles(proposalRoles);          // assing new roles
    }

    // Enough players?
    if (numPlayers != MAXGROUPSIZE)
    {
        TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Compatibles but not enough players(%u)", strGuids.c_str(), numPlayers);
        LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS);
        data.roles = proposalRoles;

        for (GuidList::const_iterator itr = check.begin(); itr != check.end(); ++itr)
            UpdateBestCompatibleInQueue(QueueDataStore.find(*itr), strGuids, data.roles);

        SetCompatibilityData(strGuids, data);
        return LFG_COMPATIBLES_WITH_LESS_PLAYERS;
    }

    ObjectGuid gguid = *check.begin();
    proposal.queues = check;
    proposal.isNew = numLfgGroups != 1 || sLFGMgr->GetOldState(gguid) != LFG_STATE_DUNGEON;

    if (!sLFGMgr->AllQueued(check))
    {
        TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Group MATCH but can't create proposal!", strGuids.c_str());
        SetCompatibles(strGuids, LFG_COMPATIBLES_BAD_STATES);
        return LFG_COMPATIBLES_BAD_STATES;
    }

    // Create a new proposal
    proposal.cancelTime = time(NULL) + LFG_TIME_PROPOSAL;
    proposal.state = LFG_PROPOSAL_INITIATING;
    proposal.leader.Clear();
    proposal.dungeonId = Trinity::Containers::SelectRandomContainerElement(proposalDungeons);

    bool leader = false;
    for (LfgRolesMap::const_iterator itRoles = proposalRoles.begin(); itRoles != proposalRoles.end(); ++itRoles)
    {
        // Assing new leader
        if (itRoles->second & PLAYER_ROLE_LEADER)
        {
            if (!leader || !proposal.leader || urand(0, 1))
                proposal.leader = itRoles->first;
            leader = true;
        }
        else if (!leader && (!proposal.leader || urand(0, 1)))
            proposal.leader = itRoles->first;

        // Assing player data and roles
        LfgProposalPlayer &data = proposal.players[itRoles->first];
        data.role = itRoles->second;
        data.group = proposalGroups.find(itRoles->first)->second;
        if (!proposal.isNew && data.group && data.group == proposal.group) // Player from existing group, autoaccept
            data.accept = LFG_ANSWER_AGREE;
    }

    // Mark proposal members as not queued (but not remove queue data)
    for (GuidList::const_iterator itQueue = proposal.queues.begin(); itQueue != proposal.queues.end(); ++itQueue)
    {
        ObjectGuid guid = (*itQueue);
        RemoveFromNewQueue(guid);
        RemoveFromCurrentQueue(guid);
    }

    sLFGMgr->AddProposal(proposal);

    TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) MATCH! Group formed", strGuids.c_str());
    SetCompatibles(strGuids, LFG_COMPATIBLES_MATCH);
    return LFG_COMPATIBLES_MATCH;
}