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

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

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

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

View File

@@ -666,11 +666,49 @@ public:
Relocate(x, y, z, o);
}
void SetMapId(uint32 mapId)
{
m_mapId = mapId;
}
[[nodiscard]] uint32 GetMapId() const
{
return m_mapId;
}
void GetWorldLocation(uint32& mapId, float& x, float& y) const
{
mapId = m_mapId;
x = m_positionX;
y = m_positionY;
}
void GetWorldLocation(uint32& mapId, float& x, float& y, float& z) const
{
mapId = m_mapId;
x = m_positionX;
y = m_positionY;
z = m_positionZ;
}
void GetWorldLocation(uint32& mapId, float& x, float& y, float& z, float& o) const
{
mapId = m_mapId;
x = m_positionX;
y = m_positionY;
z = m_positionZ;
o = m_orientation;
}
void GetWorldLocation(WorldLocation* location) const
{
if (location)
{
location->Relocate(m_positionX, m_positionY, m_positionZ, m_orientation);
location->SetMapId(m_mapId);
}
}
[[nodiscard]] WorldLocation GetWorldLocation() const
{
return *this;

View File

@@ -1277,7 +1277,7 @@ void Player::SendTeleportAckPacket()
GetSession()->SendPacket(&data);
}
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options /*= 0*/, Unit* target /*= nullptr*/)
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options /*= 0*/, Unit* target /*= nullptr*/, bool newInstance /*= false*/)
{
// for except kick by antispeedhack
sScriptMgr->AnticheatSetSkipOnePacketForASH(this, true);
@@ -1378,7 +1378,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!sScriptMgr->OnBeforePlayerTeleport(this, mapid, x, y, z, orientation, options, target))
return false;
if (GetMapId() == mapid)
if (GetMapId() == mapid && !newInstance)
{
//lets reset far teleport flag if it wasn't reset during chained teleports
SetSemaphoreTeleportFar(0);
@@ -1547,9 +1547,15 @@ bool Player::TeleportToEntryPoint()
ScheduleDelayedOperation(DELAYED_BG_TAXI_RESTORE);
ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE);
if (m_entryPointData.joinPos.m_mapId == MAPID_INVALID)
WorldLocation loc = m_entryPointData.joinPos;
m_entryPointData.joinPos.m_mapId = MAPID_INVALID;
if (loc.m_mapId == MAPID_INVALID)
{
return TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation());
return TeleportTo(m_entryPointData.joinPos);
}
return TeleportTo(loc);
}
void Player::ProcessDelayedOperations()

View File

@@ -992,7 +992,7 @@ public:
return GetSession()->GetSessionDbLocaleIndex() == LOCALE_esES || GetSession()->GetSessionDbLocaleIndex() == LOCALE_esMX;
}
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0, Unit* target = nullptr);
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0, Unit* target = nullptr, bool newInstance = false);
bool TeleportTo(WorldLocation const& loc, uint32 options = 0, Unit* target = nullptr)
{
return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options, target);

View File

@@ -119,8 +119,19 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
}
Group* group = GetPlayer()->GetGroup();
if (group && (group->isBGGroup() || group->isBFGroup()))
group = GetPlayer()->GetOriginalGroup();
if (group)
{
if (group->isLFGGroup() && group->IsLfgRandomInstance())
{
SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S);
return;
}
if (group->isBGGroup() || group->isBFGroup())
{
group = GetPlayer()->GetOriginalGroup();
}
}
Group* group2 = player->GetGroup();
if (group2 && (group2->isBGGroup() || group2->isBFGroup()))

View File

@@ -151,7 +151,7 @@ void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recvData)
recvData >> out;
LOG_DEBUG("network", "CMSG_LFG_TELEPORT [%s] out: %u", GetPlayer()->GetGUID().ToString().c_str(), out ? 1 : 0);
sLFGMgr->TeleportPlayer(GetPlayer(), out, true);
sLFGMgr->TeleportPlayer(GetPlayer(), out);
}
void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recvData*/)