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); } } }
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)); } } }
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); } } }