Beispiel #1
0
        void HandlePushQuestToParty(PushQuestToParty packet)
        {
            if (!GetPlayer().CanShareQuest(packet.QuestID))
            {
                return;
            }

            Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);

            if (quest == null)
            {
                return;
            }

            Player sender = GetPlayer();

            Group group = sender.GetGroup();

            if (!group)
            {
                sender.SendPushToPartyResponse(sender, QuestPushReason.NotInParty);
                return;
            }

            for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next())
            {
                Player receiver = refe.GetSource();

                if (!receiver || receiver == sender)
                {
                    continue;
                }

                if (!receiver.SatisfyQuestStatus(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.OnQuest);
                    continue;
                }

                if (receiver.GetQuestStatus(packet.QuestID) == QuestStatus.Complete)
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.AlreadyDone);
                    continue;
                }

                if (!receiver.SatisfyQuestDay(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.DifferentServerDaily);
                    continue;
                }

                if (!receiver.CanTakeQuest(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Invalid);
                    continue;
                }

                if (!receiver.SatisfyQuestLog(false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.LogFull);
                    continue;
                }

                if (!receiver.GetPlayerSharingQuest().IsEmpty())
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Busy);
                    continue;
                }

                sender.SendPushToPartyResponse(receiver, QuestPushReason.Success);

                if (quest.IsAutoAccept() && receiver.CanAddQuest(quest, true) && receiver.CanTakeQuest(quest, true))
                {
                    receiver.AddQuestAndCheckCompletion(quest, sender);
                }

                if ((quest.IsAutoComplete() && quest.IsRepeatable() && !quest.IsDailyOrWeekly()) || quest.HasFlag(QuestFlags.AutoComplete))
                {
                    receiver.PlayerTalkClass.SendQuestGiverRequestItems(quest, sender.GetGUID(), receiver.CanCompleteRepeatableQuest(quest), true);
                }
                else
                {
                    receiver.SetQuestSharingInfo(sender.GetGUID(), quest.Id);
                    receiver.PlayerTalkClass.SendQuestGiverQuestDetails(quest, receiver.GetGUID(), true, false);
                }
            }
        }
Beispiel #2
0
        public void LoadFromDB()
        {
            // Pool templates
            {
                uint oldMSTime = Time.GetMSTime();

                SQLResult result = DB.World.Query("SELECT entry, max_limit FROM pool_template");
                if (result.IsEmpty())
                {
                    mPoolTemplate.Clear();
                    Log.outInfo(LogFilter.ServerLoading, "Loaded 0 object pools. DB table `pool_template` is empty.");
                    return;
                }

                uint count = 0;
                do
                {
                    uint pool_id = result.Read <uint>(0);

                    PoolTemplateData pPoolTemplate = new PoolTemplateData();
                    pPoolTemplate.MaxLimit = result.Read <uint>(1);
                    mPoolTemplate[pool_id] = pPoolTemplate;
                    ++count;
                }while (result.NextRow());

                Log.outInfo(LogFilter.ServerLoading, "Loaded {0} objects pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
            }

            // Creatures

            Log.outInfo(LogFilter.ServerLoading, "Loading Creatures Pooling Data...");
            {
                uint oldMSTime = Time.GetMSTime();

                //                                                 1       2         3
                SQLResult result = DB.World.Query("SELECT guid, pool_entry, chance FROM pool_creature");

                if (result.IsEmpty())
                {
                    Log.outInfo(LogFilter.ServerLoading, "Loaded 0 creatures in  pools. DB table `pool_creature` is empty.");
                }
                else
                {
                    uint count = 0;
                    do
                    {
                        ulong guid    = result.Read <ulong>(0);
                        uint  pool_id = result.Read <uint>(1);
                        float chance  = result.Read <float>(2);

                        CreatureData data = Global.ObjectMgr.GetCreatureData(guid);
                        if (data == null)
                        {
                            Log.outError(LogFilter.Sql, "`pool_creature` has a non existing creature spawn (GUID: {0}) defined for pool id ({1}), skipped.", guid, pool_id);
                            continue;
                        }
                        if (!mPoolTemplate.ContainsKey(pool_id))
                        {
                            Log.outError(LogFilter.Sql, "`pool_creature` pool id ({0}) is out of range compared to max pool id in `pool_template`, skipped.", pool_id);
                            continue;
                        }
                        if (chance < 0 || chance > 100)
                        {
                            Log.outError(LogFilter.Sql, "`pool_creature` has an invalid chance ({0}) for creature guid ({1}) in pool id ({2}), skipped.", chance, guid, pool_id);
                            continue;
                        }
                        PoolTemplateData pPoolTemplate = mPoolTemplate[pool_id];
                        PoolObject       plObject      = new PoolObject(guid, chance);

                        if (!mPoolCreatureGroups.ContainsKey(pool_id))
                        {
                            mPoolCreatureGroups[pool_id] = new PoolGroup <Creature>();
                        }

                        PoolGroup <Creature> cregroup = mPoolCreatureGroups[pool_id];
                        cregroup.SetPoolId(pool_id);
                        cregroup.AddEntry(plObject, pPoolTemplate.MaxLimit);

                        mCreatureSearchMap.Add(guid, pool_id);
                        ++count;
                    }while (result.NextRow());

                    Log.outInfo(LogFilter.ServerLoading, "Loaded {0} creatures in pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
                }
            }

            // Gameobjects

            Log.outInfo(LogFilter.ServerLoading, "Loading Gameobject Pooling Data...");
            {
                uint oldMSTime = Time.GetMSTime();

                //                                                 1        2         3
                SQLResult result = DB.World.Query("SELECT guid, pool_entry, chance FROM pool_gameobject");

                if (result.IsEmpty())
                {
                    Log.outInfo(LogFilter.ServerLoading, "Loaded 0 gameobjects in  pools. DB table `pool_gameobject` is empty.");
                }
                else
                {
                    uint count = 0;
                    do
                    {
                        ulong guid    = result.Read <ulong>(0);
                        uint  pool_id = result.Read <uint>(1);
                        float chance  = result.Read <float>(2);

                        GameObjectData data = Global.ObjectMgr.GetGOData(guid);
                        if (data == null)
                        {
                            Log.outError(LogFilter.Sql, "`pool_gameobject` has a non existing gameobject spawn (GUID: {0}) defined for pool id ({1}), skipped.", guid, pool_id);
                            continue;
                        }

                        GameObjectTemplate goinfo = Global.ObjectMgr.GetGameObjectTemplate(data.id);
                        if (goinfo.type != GameObjectTypes.Chest &&
                            goinfo.type != GameObjectTypes.FishingHole &&
                            goinfo.type != GameObjectTypes.GatheringNode &&
                            goinfo.type != GameObjectTypes.Goober)
                        {
                            Log.outError(LogFilter.Sql, "`pool_gameobject` has a not lootable gameobject spawn (GUID: {0}, type: {1}) defined for pool id ({2}), skipped.", guid, goinfo.type, pool_id);
                            continue;
                        }

                        if (!mPoolTemplate.ContainsKey(pool_id))
                        {
                            Log.outError(LogFilter.Sql, "`pool_gameobject` pool id ({0}) is out of range compared to max pool id in `pool_template`, skipped.", pool_id);
                            continue;
                        }

                        if (chance < 0 || chance > 100)
                        {
                            Log.outError(LogFilter.Sql, "`pool_gameobject` has an invalid chance ({0}) for gameobject guid ({1}) in pool id ({2}), skipped.", chance, guid, pool_id);
                            continue;
                        }

                        PoolTemplateData pPoolTemplate = mPoolTemplate[pool_id];
                        PoolObject       plObject      = new PoolObject(guid, chance);

                        if (!mPoolGameobjectGroups.ContainsKey(pool_id))
                        {
                            mPoolGameobjectGroups[pool_id] = new PoolGroup <GameObject>();
                        }

                        PoolGroup <GameObject> gogroup = mPoolGameobjectGroups[pool_id];
                        gogroup.SetPoolId(pool_id);
                        gogroup.AddEntry(plObject, pPoolTemplate.MaxLimit);

                        mGameobjectSearchMap.Add(guid, pool_id);
                        ++count;
                    }while (result.NextRow());

                    Log.outInfo(LogFilter.ServerLoading, "Loaded {0} gameobject in pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
                }
            }

            // Pool of pools

            Log.outInfo(LogFilter.ServerLoading, "Loading Mother Pooling Data...");
            {
                uint oldMSTime = Time.GetMSTime();

                //                                                  1        2            3
                SQLResult result = DB.World.Query("SELECT pool_id, mother_pool, chance FROM pool_pool");

                if (result.IsEmpty())
                {
                    Log.outInfo(LogFilter.ServerLoading, "Loaded 0 pools in pools");
                }
                else
                {
                    uint count = 0;
                    do
                    {
                        uint  child_pool_id  = result.Read <uint>(0);
                        uint  mother_pool_id = result.Read <uint>(1);
                        float chance         = result.Read <float>(2);

                        if (!mPoolTemplate.ContainsKey(mother_pool_id))
                        {
                            Log.outError(LogFilter.Sql, "`pool_pool` mother_pool id ({0}) is out of range compared to max pool id in `pool_template`, skipped.", mother_pool_id);
                            continue;
                        }
                        if (!mPoolTemplate.ContainsKey(child_pool_id))
                        {
                            Log.outError(LogFilter.Sql, "`pool_pool` included pool_id ({0}) is out of range compared to max pool id in `pool_template`, skipped.", child_pool_id);
                            continue;
                        }
                        if (mother_pool_id == child_pool_id)
                        {
                            Log.outError(LogFilter.Sql, "`pool_pool` pool_id ({0}) includes itself, dead-lock detected, skipped.", child_pool_id);
                            continue;
                        }
                        if (chance < 0 || chance > 100)
                        {
                            Log.outError(LogFilter.Sql, "`pool_pool` has an invalid chance ({0}) for pool id ({1}) in mother pool id ({2}), skipped.", chance, child_pool_id, mother_pool_id);
                            continue;
                        }
                        PoolTemplateData pPoolTemplateMother = mPoolTemplate[mother_pool_id];
                        PoolObject       plObject            = new PoolObject(child_pool_id, chance);

                        if (!mPoolPoolGroups.ContainsKey(mother_pool_id))
                        {
                            mPoolPoolGroups[mother_pool_id] = new PoolGroup <Pool>();
                        }

                        PoolGroup <Pool> plgroup = mPoolPoolGroups[mother_pool_id];
                        plgroup.SetPoolId(mother_pool_id);
                        plgroup.AddEntry(plObject, pPoolTemplateMother.MaxLimit);

                        mPoolSearchMap.Add(child_pool_id, mother_pool_id);
                        ++count;
                    }while (result.NextRow());

                    Log.outInfo(LogFilter.ServerLoading, "Loaded {0} pools in mother pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
                }
            }

            Log.outInfo(LogFilter.ServerLoading, "Loading Quest Pooling Data...");
            {
                uint oldMSTime = Time.GetMSTime();

                PreparedStatement stmt   = DB.World.GetPreparedStatement(WorldStatements.SEL_QUEST_POOLS);
                SQLResult         result = DB.World.Query(stmt);

                if (result.IsEmpty())
                {
                    Log.outInfo(LogFilter.ServerLoading, "Loaded 0 quests in pools");
                }
                else
                {
                    List <uint> creBounds;
                    List <uint> goBounds;

                    Dictionary <uint, eQuestTypes> poolTypeMap = new Dictionary <uint, eQuestTypes>();
                    uint count = 0;
                    do
                    {
                        uint entry   = result.Read <uint>(0);
                        uint pool_id = result.Read <uint>(1);

                        if (!poolTypeMap.ContainsKey(pool_id))
                        {
                            poolTypeMap[pool_id] = 0;
                        }

                        Quest quest = Global.ObjectMgr.GetQuestTemplate(entry);
                        if (quest == null)
                        {
                            Log.outError(LogFilter.Sql, "`pool_quest` has a non existing quest template (Entry: {0}) defined for pool id ({1}), skipped.", entry, pool_id);
                            continue;
                        }

                        if (!mPoolTemplate.ContainsKey(pool_id))
                        {
                            Log.outError(LogFilter.Sql, "`pool_quest` pool id ({0}) is out of range compared to max pool id in `pool_template`, skipped.", pool_id);
                            continue;
                        }

                        if (!quest.IsDailyOrWeekly())
                        {
                            Log.outError(LogFilter.Sql, "`pool_quest` has an quest ({0}) which is not daily or weekly in pool id ({1}), use ExclusiveGroup instead, skipped.", entry, pool_id);
                            continue;
                        }

                        if (poolTypeMap[pool_id] == eQuestTypes.None)
                        {
                            poolTypeMap[pool_id] = quest.IsDaily() ? eQuestTypes.Daily : eQuestTypes.Weekly;
                        }

                        eQuestTypes currType = quest.IsDaily() ? eQuestTypes.Daily : eQuestTypes.Weekly;

                        if (poolTypeMap[pool_id] != currType)
                        {
                            Log.outError(LogFilter.Sql, "`pool_quest` quest {0} is {1} but pool ({2}) is specified for {3}, mixing not allowed, skipped.",
                                         entry, currType, pool_id, poolTypeMap[pool_id]);
                            continue;
                        }

                        creBounds = mQuestCreatureRelation.LookupByKey(entry);
                        goBounds  = mQuestGORelation.LookupByKey(entry);

                        if (creBounds.Empty() && goBounds.Empty())
                        {
                            Log.outError(LogFilter.Sql, "`pool_quest` lists entry ({0}) as member of pool ({1}) but is not started anywhere, skipped.", entry, pool_id);
                            continue;
                        }

                        PoolTemplateData pPoolTemplate = mPoolTemplate[pool_id];
                        PoolObject       plObject      = new PoolObject(entry, 0.0f);

                        if (!mPoolQuestGroups.ContainsKey(pool_id))
                        {
                            mPoolQuestGroups[pool_id] = new PoolGroup <Quest>();
                        }

                        PoolGroup <Quest> questgroup = mPoolQuestGroups[pool_id];
                        questgroup.SetPoolId(pool_id);
                        questgroup.AddEntry(plObject, pPoolTemplate.MaxLimit);

                        mQuestSearchMap.Add(entry, pool_id);
                        ++count;
                    }while (result.NextRow());

                    Log.outInfo(LogFilter.ServerLoading, "Loaded {0} quests in pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
                }
            }

            // The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks
            Log.outInfo(LogFilter.ServerLoading, "Starting objects pooling system...");
            {
                uint oldMSTime = Time.GetMSTime();

                SQLResult result = DB.World.Query("SELECT DISTINCT pool_template.entry, pool_pool.pool_id, pool_pool.mother_pool FROM pool_template" +
                                                  " LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry" +
                                                  " LEFT JOIN pool_pool ON pool_template.entry=pool_pool.pool_id WHERE game_event_pool.pool_entry IS NULL");

                if (result.IsEmpty())
                {
                    Log.outInfo(LogFilter.ServerLoading, "Pool handling system initialized, 0 pools spawned.");
                }
                else
                {
                    uint count = 0;
                    do
                    {
                        uint pool_entry   = result.Read <uint>(0);
                        uint pool_pool_id = result.Read <uint>(1);

                        if (!CheckPool(pool_entry))
                        {
                            if (pool_pool_id != 0)
                            {
                                // The pool is a child pool in pool_pool table. Ideally we should remove it from the pool handler to ensure it never gets spawned,
                                // however that could recursively invalidate entire chain of mother pools. It can be done in the future but for now we'll do nothing.
                                Log.outError(LogFilter.Sql, "Pool Id {0} has no equal chance pooled entites defined and explicit chance sum is not 100. This broken pool is a child pool of Id {1} and cannot be safely removed.", pool_entry, result.Read <uint>(2));
                            }
                            else
                            {
                                Log.outError(LogFilter.Sql, "Pool Id {0} has no equal chance pooled entites defined and explicit chance sum is not 100. The pool will not be spawned.", pool_entry);
                            }
                            continue;
                        }

                        // Don't spawn child pools, they are spawned recursively by their parent pools
                        if (pool_pool_id == 0)
                        {
                            SpawnPool(pool_entry);
                            count++;
                        }
                    }while (result.NextRow());

                    Log.outDebug(LogFilter.Pool, "Pool handling system initialized, {0} pools spawned in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
                }
            }
        }
Beispiel #3
0
        void HandlePushQuestToParty(PushQuestToParty packet)
        {
            Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);

            if (quest == null)
            {
                return;
            }

            Player sender = GetPlayer();

            if (!_player.CanShareQuest(packet.QuestID))
            {
                sender.SendPushToPartyResponse(sender, QuestPushReason.NotAllowed);
                return;
            }

            // in pool and not currently available (wintergrasp weekly, dalaran weekly) - can't share
            if (Global.QuestPoolMgr.IsQuestActive(packet.QuestID))
            {
                sender.SendPushToPartyResponse(sender, QuestPushReason.NotDaily);
                return;
            }

            Group group = sender.GetGroup();

            if (!group)
            {
                sender.SendPushToPartyResponse(sender, QuestPushReason.NotInParty);
                return;
            }

            for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next())
            {
                Player receiver = refe.GetSource();

                if (!receiver || receiver == sender)
                {
                    continue;
                }

                if (!receiver.GetPlayerSharingQuest().IsEmpty())
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Busy);
                    continue;
                }

                if (!receiver.IsAlive())
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Dead);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.DeadToRecipient, quest);
                    continue;
                }

                switch (receiver.GetQuestStatus(packet.QuestID))
                {
                case QuestStatus.Rewarded:
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.AlreadyDone);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.AlreadyDoneToRecipient, quest);
                    continue;
                }

                case QuestStatus.Incomplete:
                case QuestStatus.Complete:
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.OnQuest);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.OnQuestToRecipient, quest);
                    continue;
                }

                default:
                    break;
                }

                if (!receiver.SatisfyQuestLog(false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.LogFull);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.LogFullToRecipient, quest);
                    continue;
                }

                if (!receiver.SatisfyQuestDay(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.AlreadyDone);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.AlreadyDoneToRecipient, quest);
                    continue;
                }

                if (!receiver.SatisfyQuestMinLevel(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.LowLevel);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.LowLevelToRecipient, quest);
                    continue;
                }

                if (!receiver.SatisfyQuestMaxLevel(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.HighLevel);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.HighLevelToRecipient, quest);
                    continue;
                }

                if (!receiver.SatisfyQuestClass(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Class);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.ClassToRecipient, quest);
                    continue;
                }

                if (!receiver.SatisfyQuestRace(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Race);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.RaceToRecipient, quest);
                    continue;
                }

                if (!receiver.SatisfyQuestReputation(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.LowFaction);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.LowFactionToRecipient, quest);
                    continue;
                }

                if (!receiver.SatisfyQuestDependentQuests(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Prerequisite);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.PrerequisiteToRecipient, quest);
                    continue;
                }

                if (!receiver.SatisfyQuestExpansion(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Expansion);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.ExpansionToRecipient, quest);
                    continue;
                }

                if (!receiver.CanTakeQuest(quest, false))
                {
                    sender.SendPushToPartyResponse(receiver, QuestPushReason.Invalid);
                    receiver.SendPushToPartyResponse(sender, QuestPushReason.InvalidToRecipient, quest);
                    continue;
                }

                sender.SendPushToPartyResponse(receiver, QuestPushReason.Success);

                if (quest.IsAutoAccept() && receiver.CanAddQuest(quest, true) && receiver.CanTakeQuest(quest, true))
                {
                    receiver.AddQuestAndCheckCompletion(quest, sender);
                }

                if ((quest.IsAutoComplete() && quest.IsRepeatable() && !quest.IsDailyOrWeekly()) || quest.HasFlag(QuestFlags.AutoComplete))
                {
                    receiver.PlayerTalkClass.SendQuestGiverRequestItems(quest, sender.GetGUID(), receiver.CanCompleteRepeatableQuest(quest), true);
                }
                else
                {
                    receiver.SetQuestSharingInfo(sender.GetGUID(), quest.Id);
                    receiver.PlayerTalkClass.SendQuestGiverQuestDetails(quest, receiver.GetGUID(), true, false);
                }
            }
        }