Enabling solo-dungeon queue and implementing first dungeonhelper prototyp
This commit is contained in:
1 parent
fcedaf23b9
commit
f35c3c4ae9
5 files changed
+168
-3
No files matched your search
@@ -23,6 +23,7 @@
|
||||
#include "Group.h"
|
||||
#include "LFGQueue.h"
|
||||
#include "LFGMgr.h"
|
||||
#include "World.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace lfg
|
||||
@@ -331,6 +332,105 @@ uint8 LFGQueue::FindGroups()
|
||||
else
|
||||
AddToCurrentQueue(frontguid); // Lfg group not found, add this group to the queue.
|
||||
}
|
||||
|
||||
// Keep normal TrinityCore matchmaking authoritative. Only after normal
|
||||
// matching has failed do we permit an underfilled low-population group.
|
||||
if (sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_LOW_POPULATION_ENABLE))
|
||||
proposals += FindLowPopulationGroups();
|
||||
|
||||
return proposals;
|
||||
}
|
||||
|
||||
GuidList LFGQueue::GetQueueGuidsFromKey(std::string const& key) const
|
||||
{
|
||||
GuidList result;
|
||||
|
||||
for (GuidList::const_iterator itr = currentQueueStore.begin(); itr != currentQueueStore.end(); ++itr)
|
||||
{
|
||||
std::ostringstream o;
|
||||
o << itr->GetRawValue();
|
||||
std::string token = o.str();
|
||||
|
||||
size_t pos = key.find(token);
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
size_t end = pos + token.length();
|
||||
bool leftBoundary = pos == 0 || key[pos - 1] == '|';
|
||||
bool rightBoundary = end == key.length() || key[end] == '|';
|
||||
|
||||
if (leftBoundary && rightBoundary)
|
||||
{
|
||||
result.push_back(*itr);
|
||||
break;
|
||||
}
|
||||
|
||||
pos = key.find(token, pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8 LFGQueue::FindLowPopulationGroups()
|
||||
{
|
||||
uint8 proposals = 0;
|
||||
uint32 const fallbackDelay =
|
||||
sWorld->getIntConfig(CONFIG_DUNGEON_FINDER_LOW_POPULATION_FALLBACK_DELAY);
|
||||
uint32 const minPlayers =
|
||||
sWorld->getIntConfig(CONFIG_DUNGEON_FINDER_LOW_POPULATION_MIN_PLAYERS);
|
||||
time_t const now = GameTime::GetGameTime();
|
||||
|
||||
bool createdProposal = true;
|
||||
while (createdProposal)
|
||||
{
|
||||
createdProposal = false;
|
||||
GuidList queueSnapshot = currentQueueStore;
|
||||
|
||||
for (GuidList::const_iterator itrGuid = queueSnapshot.begin(); itrGuid != queueSnapshot.end(); ++itrGuid)
|
||||
{
|
||||
LfgQueueDataContainer::iterator itrQueue = QueueDataStore.find(*itrGuid);
|
||||
if (itrQueue == QueueDataStore.end())
|
||||
continue;
|
||||
|
||||
LfgQueueData& queueData = itrQueue->second;
|
||||
|
||||
if (now < queueData.joinTime || uint32(now - queueData.joinTime) < fallbackDelay)
|
||||
continue;
|
||||
|
||||
if (queueData.bestCompatible.empty())
|
||||
FindBestCompatibleInQueue(itrQueue);
|
||||
|
||||
if (queueData.bestCompatible.empty())
|
||||
continue;
|
||||
|
||||
GuidList check = GetQueueGuidsFromKey(queueData.bestCompatible);
|
||||
if (check.empty())
|
||||
continue;
|
||||
|
||||
uint32 playerCount = 0;
|
||||
for (GuidList::const_iterator itrCheck = check.begin(); itrCheck != check.end(); ++itrCheck)
|
||||
{
|
||||
LfgQueueDataContainer::const_iterator itrData = QueueDataStore.find(*itrCheck);
|
||||
if (itrData != QueueDataStore.end())
|
||||
playerCount += uint32(itrData->second.roles.size());
|
||||
}
|
||||
|
||||
if (playerCount < minPlayers)
|
||||
continue;
|
||||
|
||||
TC_LOG_DEBUG("lfg.queue.lowpopulation",
|
||||
"Low population fallback after %u seconds: trying partial group (%s) with %u player(s)",
|
||||
fallbackDelay, ConcatenateGuids(check).c_str(), playerCount);
|
||||
|
||||
if (CheckCompatibility(check, true) == LFG_COMPATIBLES_MATCH)
|
||||
{
|
||||
++proposals;
|
||||
createdProposal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return proposals;
|
||||
}
|
||||
|
||||
@@ -379,7 +479,7 @@ LfgCompatibility LFGQueue::FindNewGroups(GuidList& check, GuidList& all)
|
||||
@param[in] check List of guids to check compatibilities
|
||||
@return LfgCompatibility type of compatibility
|
||||
*/
|
||||
LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
|
||||
LfgCompatibility LFGQueue::CheckCompatibility(GuidList check, bool allowIncomplete)
|
||||
{
|
||||
std::string strGuids = ConcatenateGuids(check);
|
||||
LfgProposal proposal;
|
||||
@@ -544,7 +644,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
|
||||
}
|
||||
|
||||
// Enough players?
|
||||
if (numPlayers != dungeon->GetMaxGroupSize())
|
||||
if (numPlayers != dungeon->GetMaxGroupSize() && !allowIncomplete)
|
||||
{
|
||||
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Compatibles but not enough players(%u)", GetDetailedMatchRoles(check).c_str(), numPlayers);
|
||||
LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS);
|
||||
|
||||
@@ -138,9 +138,11 @@ class TC_GAME_API LFGQueue
|
||||
LfgCompatibilityData* GetCompatibilityData(std::string const& key);
|
||||
void FindBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue);
|
||||
void UpdateBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue, std::string const& key, LfgRolesMap const& roles);
|
||||
uint8 FindLowPopulationGroups();
|
||||
GuidList GetQueueGuidsFromKey(std::string const& key) const;
|
||||
|
||||
LfgCompatibility FindNewGroups(GuidList& check, GuidList& all);
|
||||
LfgCompatibility CheckCompatibility(GuidList check);
|
||||
LfgCompatibility CheckCompatibility(GuidList check, bool allowIncomplete = false);
|
||||
|
||||
// Queue
|
||||
LfgQueueDataContainer QueueDataStore; ///< Queued groups
|
||||
|
||||
@@ -1521,6 +1521,20 @@ void World::LoadConfigSettings(bool reload)
|
||||
|
||||
// Dungeon finder
|
||||
m_int_configs[CONFIG_LFG_OPTIONSMASK] = sConfigMgr->GetIntDefault("DungeonFinder.OptionsMask", 1);
|
||||
m_bool_configs[CONFIG_DUNGEON_FINDER_LOW_POPULATION_ENABLE] =
|
||||
sConfigMgr->GetBoolDefault("DungeonFinder.LowPopulation.Enable", false);
|
||||
m_int_configs[CONFIG_DUNGEON_FINDER_LOW_POPULATION_FALLBACK_DELAY] =
|
||||
sConfigMgr->GetIntDefault("DungeonFinder.LowPopulation.FallbackDelay", 60);
|
||||
m_int_configs[CONFIG_DUNGEON_FINDER_LOW_POPULATION_MIN_PLAYERS] =
|
||||
sConfigMgr->GetIntDefault("DungeonFinder.LowPopulation.MinPlayers", 1);
|
||||
|
||||
if (m_int_configs[CONFIG_DUNGEON_FINDER_LOW_POPULATION_MIN_PLAYERS] < 1)
|
||||
{
|
||||
TC_LOG_ERROR("server.loading",
|
||||
"DungeonFinder.LowPopulation.MinPlayers (%u) must be at least 1. Using 1 instead.",
|
||||
m_int_configs[CONFIG_DUNGEON_FINDER_LOW_POPULATION_MIN_PLAYERS]);
|
||||
m_int_configs[CONFIG_DUNGEON_FINDER_LOW_POPULATION_MIN_PLAYERS] = 1;
|
||||
}
|
||||
|
||||
// DBC_ItemAttributes
|
||||
m_bool_configs[CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES] = sConfigMgr->GetBoolDefault("DBC.EnforceItemAttributes", true);
|
||||
|
||||
@@ -122,6 +122,7 @@ enum WorldBoolConfigs : uint8
|
||||
CONFIG_CHAT_PARTY_RAID_WARNINGS,
|
||||
CONFIG_DETECT_POS_COLLISION,
|
||||
CONFIG_RESTRICTED_LFG_CHANNEL,
|
||||
CONFIG_DUNGEON_FINDER_LOW_POPULATION_ENABLE,
|
||||
CONFIG_CHAT_FAKE_MESSAGE_PREVENTING,
|
||||
CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP,
|
||||
CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE,
|
||||
@@ -364,6 +365,8 @@ enum WorldIntConfigs : uint8
|
||||
CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION,
|
||||
CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS,
|
||||
CONFIG_LFG_OPTIONSMASK,
|
||||
CONFIG_DUNGEON_FINDER_LOW_POPULATION_FALLBACK_DELAY,
|
||||
CONFIG_DUNGEON_FINDER_LOW_POPULATION_MIN_PLAYERS,
|
||||
CONFIG_MAX_INSTANCES_PER_HOUR,
|
||||
CONFIG_WARDEN_CLIENT_RESPONSE_DELAY,
|
||||
CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF,
|
||||
|
||||
@@ -37,6 +37,7 @@ EndContentData */
|
||||
#include "Spell.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace ItemScripts
|
||||
{
|
||||
@@ -412,6 +413,50 @@ class item_generic_limit_chance_above_60 : public ItemScript
|
||||
return true;
|
||||
}
|
||||
};
|
||||
/*#####
|
||||
# item_horde_adventurer_horn
|
||||
#####*/
|
||||
|
||||
enum HordeAdventurerHorn
|
||||
{
|
||||
NPC_ORGRIMMAR_GRUNT = 3296
|
||||
};
|
||||
|
||||
class item_horde_adventurer_horn : public ItemScript
|
||||
{
|
||||
public:
|
||||
item_horde_adventurer_horn() : ItemScript("item_horde_adventurer_horn") { }
|
||||
|
||||
bool OnUse(Player* player, Item* item, SpellCastTargets const& /*targets*/) override
|
||||
{
|
||||
TC_LOG_INFO("scripts", "Horde adventureer horn OnUse triggered by player %s (item %u)", player->GetName().c_str(), item->GetEntry());
|
||||
// The horn may not be used during combat.
|
||||
if (player->IsInCombat())
|
||||
{
|
||||
player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The horn may only be used inside a dungeon instance.
|
||||
if (!player->GetMap()->IsDungeon())
|
||||
{
|
||||
player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
player->SummonCreature(
|
||||
NPC_ORGRIMMAR_GRUNT,
|
||||
player->GetPositionX() + 2.0f,
|
||||
player->GetPositionY(),
|
||||
player->GetPositionZ(),
|
||||
player->GetOrientation(),
|
||||
TEMPSUMMON_MANUAL_DESPAWN,
|
||||
0
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void AddSC_item_scripts()
|
||||
@@ -428,4 +473,5 @@ void AddSC_item_scripts()
|
||||
new item_dehta_trap_smasher();
|
||||
new item_captured_frog();
|
||||
new item_generic_limit_chance_above_60();
|
||||
new item_horde_adventurer_horn();
|
||||
}
|
||||
Reference in new issue
Block a user