fix(Core/DungeonFinder): misc improvements (#7488)

- Players should be able to enter the same dungeon if just completed it
- Properly define if the proposal is new
- Set teleport point to the nearest graveyard if teleported to dungeon from other instance
- Display completed encounters when joining LFG in progress (excluding random)
- Closes #5914
- Closes #7388
This commit is contained in:
UltraNix
2021-09-01 10:44:29 +02:00
committed by GitHub
parent a69be39fcb
commit 498faf380b
8 changed files with 131 additions and 33 deletions
+42 -22
View File
@@ -662,6 +662,14 @@ namespace lfg
if (isRaid && grp && (grp->isLFGGroup() || guid != grp->GetLeaderGUID()))
return;
// Do not allow to change dungeon in the middle of a current dungeon
if (!isRaid && isContinue && grp->GetMembersCount() == 5)
{
dungeons.clear();
dungeons.insert(GetDungeon(gguid));
joinData.result = LFG_JOIN_PARTY_NOT_MEET_REQS;
}
// Can't join. Send result
if (joinData.result != LFG_JOIN_OK)
{
@@ -1603,6 +1611,18 @@ namespace lfg
_SaveToDB(gguid);
// Select a player inside to be teleported to
WorldLocation const* teleportLocation = nullptr;
for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next())
{
Player* plr = itr->GetSource();
if (plr && plr->GetMapId() == uint32(dungeon->map) && !proposal.isNew)
{
teleportLocation = plr;
break;
}
}
bool randomDungeon = false;
// Teleport Player
for (LfgGuidList::const_iterator it = playersToTeleport.begin(); it != playersToTeleport.end(); ++it)
@@ -1610,6 +1630,16 @@ namespace lfg
{
if (player->GetGroup() != grp) // pussywizard: could not add because group was full (some shitness happened)
continue;
if (player->GetMapId() == uint32(dungeon->map))
{
// Remove bind to that map
if (!sInstanceSaveMgr->PlayerIsPermBoundToInstance(player->GetGUID(), dungeon->map, player->GetDungeonDifficulty()))
{
sInstanceSaveMgr->PlayerUnbindInstance(player->GetGUID(), dungeon->map, player->GetDungeonDifficulty(), true);
}
}
// Add the cooldown spell if queued for a random dungeon
// xinef: add aura
if ((randomDungeon || selectedRandomLfgDungeon(player->GetGUID())) && !player->HasAura(LFG_SPELL_DUNGEON_COOLDOWN))
@@ -1617,7 +1647,8 @@ namespace lfg
randomDungeon = true;
player->AddAura(LFG_SPELL_DUNGEON_COOLDOWN, player);
}
TeleportPlayer(player, false);
TeleportPlayer(player, false, teleportLocation);
}
if (randomDungeon)
@@ -1952,7 +1983,7 @@ namespace lfg
@param[in] out Teleport out (true) or in (false)
@param[in] fromOpcode Function called from opcode handlers? (Default false)
*/
void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false*/)
void LFGMgr::TeleportPlayer(Player* player, bool out, WorldLocation const* teleportLocation /*= nullptr*/)
{
LFGDungeonData const* dungeon = nullptr;
Group* group = player->GetGroup();
@@ -1986,7 +2017,7 @@ namespace lfg
error = LFG_TELEPORTERROR_IN_VEHICLE;
else if (player->GetCharmGUID())
error = LFG_TELEPORTERROR_CHARMING;
else if (player->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance
else
{
uint32 mapid = dungeon->map;
float x = dungeon->x;
@@ -1994,32 +2025,21 @@ namespace lfg
float z = dungeon->z;
float orientation = dungeon->o;
if (!fromOpcode)
if (teleportLocation)
{
// Select a player inside to be teleported to
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
Player* plrg = itr->GetSource();
if (plrg && plrg != player && plrg->GetMapId() == uint32(dungeon->map))
{
mapid = plrg->GetMapId();
x = plrg->GetPositionX();
y = plrg->GetPositionY();
z = plrg->GetPositionZ();
orientation = plrg->GetOrientation();
break;
}
}
teleportLocation->GetWorldLocation(mapid, x, y, z, orientation);
}
if (!player->GetMap()->IsDungeon())
if (!player->GetMap()->IsDungeon() || player->GetEntryPoint().GetMapId() == MAPID_INVALID)
{
player->SetEntryPoint();
}
if (!player->TeleportTo(mapid, x, y, z, orientation))
if (!player->TeleportTo(mapid, x, y, z, orientation, 0, nullptr, mapid == player->GetMapId()))
{
error = LFG_TELEPORTERROR_INVALID_LOCATION;
}
}
else
error = LFG_TELEPORTERROR_INVALID_LOCATION;
if (error != LFG_TELEPORTERROR_OK)
player->GetSession()->SendLfgTeleportError(uint8(error));
+2 -1
View File
@@ -18,6 +18,7 @@
class Group;
class Player;
class Quest;
class WorldLocation;
namespace lfg
{
@@ -500,7 +501,7 @@ namespace lfg
/// Returns all random and seasonal dungeons for given level and expansion
LfgDungeonSet GetRandomAndSeasonalDungeons(uint8 level, uint8 expansion);
/// Teleport a player to/from selected dungeon
void TeleportPlayer(Player* player, bool out, bool fromOpcode = false);
void TeleportPlayer(Player* player, bool out, WorldLocation const* teleportLocation = nullptr);
/// Inits new proposal to boot a player
void InitBoot(ObjectGuid gguid, ObjectGuid kicker, ObjectGuid victim, std::string const& reason);
/// Updates player boot proposal with new player answer
+24 -2
View File
@@ -15,12 +15,15 @@
*/
#include "Containers.h"
#include "DBCStores.h"
#include "Group.h"
#include "InstanceScript.h"
#include "LFGMgr.h"
#include "LFGQueue.h"
#include "Log.h"
#include "ObjectDefines.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "World.h"
namespace lfg
@@ -397,9 +400,8 @@ namespace lfg
return LFG_COMPATIBLES_WITH_LESS_PLAYERS;
}
ObjectGuid gguid = check.front();
proposal.queues = strGuids;
proposal.isNew = numLfgGroups != 1 || sLFGMgr->GetOldState(gguid) != LFG_STATE_DUNGEON;
proposal.isNew = numLfgGroups != 1 || sLFGMgr->GetOldState(proposal.group) != LFG_STATE_DUNGEON;
if (!sLFGMgr->AllQueued(check)) // can't create proposal
return LFG_COMPATIBILITY_PENDING;
@@ -410,6 +412,7 @@ namespace lfg
proposal.leader.Clear();
proposal.dungeonId = Acore::Containers::SelectRandomContainerElement(proposalDungeons);
uint32 completedEncounters = 0;
bool leader = false;
for (LfgRolesMap::const_iterator itRoles = proposalRoles.begin(); itRoles != proposalRoles.end(); ++itRoles)
{
@@ -429,8 +432,27 @@ namespace lfg
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;
if (!completedEncounters && !proposal.isNew)
{
if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(proposal.dungeonId))
{
if (Player* player = ObjectAccessor::FindConnectedPlayer(itRoles->first))
{
if (player->GetMapId() == static_cast<uint32>(dungeon->map))
{
if (InstanceScript* instance = player->GetInstanceScript())
{
completedEncounters = instance->GetCompletedEncounterMask();
}
}
}
}
}
}
proposal.encounters = completedEncounters;
for (uint8 i = 0; i < 5 && proposal.queues.guids[i]; ++i)
RemoveFromQueue(proposal.queues.guids[i], true);