Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
LFGScripts.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/*
7 * Interaction between core and LFGScripts
8 */
9
10#include "Common.h"
11#include "Group.h"
12#include "LFGMgr.h"
13#include "LFGScripts.h"
14#include "ObjectAccessor.h"
15#include "Player.h"
16#include "ScriptMgr.h"
17#include "SharedDefines.h"
18#include "WorldSession.h"
19
20namespace lfg
21{
22 namespace
23 {
24 bool IsLfgDungeonState(LfgState state)
25 {
26 return state == LFG_STATE_DUNGEON || state == LFG_STATE_FINISHED_DUNGEON;
27 }
28
29 bool ClearStrayPlayerState(Player* player, char const* reason)
30 {
31 if (!player)
32 return false;
33
34 Group* group = player->GetGroup();
35 if (group && group->isLFGGroup())
36 return false;
37
38 uint64 const guid = player->GetGUID();
39 LfgState const state = sLFGMgr->GetState(guid);
40 uint64 const savedGroup = sLFGMgr->GetGroup(guid);
41 if (!savedGroup && !IsLfgDungeonState(state) && state != LFG_STATE_BOOT)
42 return false;
43
44 if (savedGroup)
45 sLFGMgr->SetGroup(guid, 0);
46
47 sLFGMgr->LeaveSoloLfg(guid, sLFGMgr->GetQueueId(guid));
48 player->GetSession()->SendLfgClearStatus();
49 SF_LOG_DEBUG("lfg", "%s, Player %s(%u) cleared stray LFG state %u savedGroup %u.",
50 reason ? reason : "LFG stray state cleanup", player->GetName().c_str(), GUID_LOPART(guid),
51 uint32(state), GUID_LOPART(savedGroup));
52 return true;
53 }
54 }
55
57
59 {
61 return;
62
63 if (!player->GetGroup())
64 {
65 sLFGMgr->LeaveLfg(player->GetGUID());
66 }
67 else if (player->GetSession()->PlayerDisconnected())
68 sLFGMgr->LeaveLfg(player->GetGUID(), true);
69 }
70
71 void LFGPlayerScript::OnLogin(Player* player, bool /*loginFirst*/)
72 {
74 return;
75
76 // Temporal: Trying to determine when group data and LFG data gets desynched
77 uint64 guid = player->GetGUID();
78 uint64 gguid = sLFGMgr->GetGroup(guid);
79
80 if (Group const* group = player->GetGroup())
81 {
82 uint64 gguid2 = group->GetGUID();
83 if (gguid != gguid2)
84 {
85 SF_LOG_ERROR("lfg", "%s on group %u but LFG has group %u saved... Fixing.",
86 player->GetSession()->GetPlayerInfo().c_str(), GUID_LOPART(gguid2), GUID_LOPART(gguid));
87 sLFGMgr->SetupGroupMember(guid, group->GetGUID());
88 }
89 }
90 sLFGMgr->SetTeam(player->GetGUID(), player->GetTeam());
91
92 if (ClearStrayPlayerState(player, "LFGPlayerScript::OnLogin"))
93 return;
94
95 if (sLFGMgr->RestoreActiveQueue(guid))
96 {
97 LfgUpdateData updateData = sLFGMgr->GetLfgStatus(guid);
98 player->GetSession()->SendLfgUpdateStatus(updateData, player->GetGroup() != NULL);
99 if (updateData.state == LFG_STATE_PROPOSAL)
100 sLFGMgr->SendActiveProposal(guid);
101 }
102 }
103
105 {
106 Map const* map = player->GetMap();
107
108 if (sLFGMgr->inLfgDungeonMap(player->GetGUID(), map->GetId(), map->GetDifficulty()))
109 {
110 Group* group = player->GetGroup();
111 // This function is also called when players log in
112 // if for some reason the LFG system recognises the player as being in a LFG dungeon,
113 // but the player was loaded without a valid group, we'll teleport to homebind to prevent
114 // crashes or other undefined behaviour
115 if (!group)
116 {
117 sLFGMgr->LeaveLfg(player->GetGUID());
119 player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, 0.0f);
120 SF_LOG_ERROR("lfg", "LFGPlayerScript::OnMapChanged, Player %s (%u) is in LFG dungeon map but does not have a valid group! "
121 "Teleporting to homebind.", player->GetName().c_str(), player->GetGUIDLow());
122 return;
123 }
124
125 for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
126 if (Player* member = itr->GetSource())
127 player->GetSession()->SendNameQueryOpcode(member->GetGUID());
128
129 if (sLFGMgr->selectedRandomLfgDungeon(player->GetGUID()))
130 player->CastSpell(player, LFG_SPELL_LUCK_OF_THE_DRAW, true);
131 }
132 else
133 {
134 if (ClearStrayPlayerState(player, "LFGPlayerScript::OnMapChanged"))
135 {
137 return;
138 }
139
140 Group* group = player->GetGroup();
141 if (group && group->isLFGGroup())
142 {
143 uint64 const groupGuid = group->GetGUID();
144 uint64 const playerGuid = player->GetGUID();
145 LfgState const groupState = sLFGMgr->GetState(groupGuid);
146
147 if (!IsLfgDungeonState(groupState) && groupState != LFG_STATE_NONE)
148 {
150 return;
151 }
152
153 group->Disband();
154
155 SF_LOG_DEBUG("lfg", "LFGPlayerScript::OnMapChanged, Player %s(%u) left LFG dungeon flow; disbanded LFG group %u with state %u.",
156 player->GetName().c_str(), GUID_LOPART(playerGuid), GUID_LOPART(groupGuid), uint32(groupState));
157 }
159 }
160 }
161
163
165 {
167 return;
168
169 uint64 gguid = group->GetGUID();
170 uint64 leader = group->GetLeaderGUID();
171
172 if (leader == guid)
173 {
174 SF_LOG_DEBUG("lfg", "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "] leader " UI64FMTD "]", gguid, guid, leader);
175 sLFGMgr->SetLeader(gguid, guid);
176 }
177 else
178 {
179 LfgState gstate = sLFGMgr->GetState(gguid);
180 LfgState state = sLFGMgr->GetState(guid);
181 SF_LOG_DEBUG("lfg", "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "] leader " UI64FMTD "] gstate: %u, state: %u", gguid, guid, leader, gstate, state);
182
183 if (state == LFG_STATE_QUEUED)
184 sLFGMgr->LeaveLfg(guid);
185
186 if (gstate == LFG_STATE_QUEUED)
187 sLFGMgr->LeaveLfg(gguid);
188 }
189
190 sLFGMgr->SetGroup(guid, gguid);
191 sLFGMgr->AddPlayerToGroup(gguid, guid);
192 }
193
194 void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod method, uint64 kicker, char const* reason)
195 {
197 return;
198
199 uint64 gguid = group->GetGUID();
200 SF_LOG_DEBUG("lfg", "LFGScripts::OnRemoveMember [" UI64FMTD "]: remove [" UI64FMTD "] Method: %d Kicker: [" UI64FMTD "] Reason: %s", gguid, guid, method, kicker, (reason ? reason : ""));
201
202 bool isLFG = group->isLFGGroup();
203 LfgState state = sLFGMgr->GetState(gguid);
204
205 if (isLFG && method == GROUP_REMOVEMETHOD_KICK && IsLfgDungeonState(state)) // Player have been kicked
206 {
208 std::string str_reason = "";
209 if (reason)
210 str_reason = std::string(reason);
211 sLFGMgr->InitBoot(gguid, kicker, guid, str_reason);
212 return;
213 }
214
215 // If group is being formed after proposal success do nothing more
216 if (state == LFG_STATE_PROPOSAL && method == GROUP_REMOVEMETHOD_DEFAULT)
217 {
218 // LfgData: Remove player from group
219 sLFGMgr->SetGroup(guid, 0);
220 sLFGMgr->RemovePlayerFromGroup(gguid, guid);
221 return;
222 }
223
224 sLFGMgr->LeaveLfg(guid);
225 sLFGMgr->SetGroup(guid, 0);
226 uint8 players = sLFGMgr->RemovePlayerFromGroup(gguid, guid);
227
228 if (Player* player = ObjectAccessor::FindPlayer(guid))
229 {
230 if (method == GROUP_REMOVEMETHOD_LEAVE && state == LFG_STATE_DUNGEON &&
232 player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, true);
233 //else if (state == LFG_STATE_BOOT)
234 // Update internal kick cooldown of kicked
235
237 if (isLFG && player->GetMap()->IsInstance()) // Teleport player out the dungeon
238 sLFGMgr->TeleportPlayer(player, true);
239 }
240
241 if (isLFG && state != LFG_STATE_FINISHED_DUNGEON) // Need more players to finish the dungeon
242 {
243 uint64 leaderGuid = sLFGMgr->GetLeader(gguid);
244 Player* leader = ObjectAccessor::FindPlayer(leaderGuid);
245 if (!leader)
246 {
247 leaderGuid = group->GetLeaderGUID();
248 leader = ObjectAccessor::FindPlayer(leaderGuid);
249 }
250
251 if (leader)
252 leader->GetSession()->SendLfgOfferContinue(sLFGMgr->GetDungeon(gguid, false));
253 }
254 }
255
257 {
259 return;
260
261 uint64 gguid = group->GetGUID();
262 SF_LOG_DEBUG("lfg", "LFGScripts::OnDisband [" UI64FMTD "]", gguid);
263
264 if (group->isLFGGroup())
265 {
266 sLFGMgr->TeleportDungeonGroupOut(group);
267 sLFGMgr->ClearDungeonGroupState(gguid, group->GetDbStoreId(), "LFG group disband", true);
268 }
269
270 sLFGMgr->RemoveGroupData(gguid);
271 }
272
273 void LFGGroupScript::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
274 {
276 return;
277
278 uint64 gguid = group->GetGUID();
279
280 SF_LOG_DEBUG("lfg", "LFGScripts::OnChangeLeader [" UI64FMTD "]: old [" UI64FMTD "] new [" UI64FMTD "]", gguid, newLeaderGuid, oldLeaderGuid);
281 sLFGMgr->SetLeader(gguid, newLeaderGuid);
282 }
283
285 {
287 return;
288
289 uint64 gguid = group->GetGUID();
290 uint64 leader = group->GetLeaderGUID();
291 SF_LOG_DEBUG("lfg", "LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, leader);
292 // No gguid == new group being formed
293 // No leader == after group creation first invite is new leader
294 // leader and no gguid == first invite after leader is added to new group (this is the real invite)
295 if (leader && !gguid)
296 sLFGMgr->LeaveLfg(leader);
297 }
298
299} // namespace lfg
#define UI64FMTD
Definition Define.h:64
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
#define sLFGMgr
Definition LFGMgr.h:518
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
uint32 GUID_LOPART(uint64 x)
RemoveMethod
@ GROUP_REMOVEMETHOD_DEFAULT
@ GROUP_REMOVEMETHOD_KICK
@ GROUP_REMOVEMETHOD_LEAVE
static Summons Group[]
Definition boss_urom.cpp:65
Definition Group.h:147
bool isLFGGroup() const
Definition Group.cpp:2543
void Disband(bool hideDestroy=false)
Definition Group.cpp:700
uint64 GetGUID() const
Definition Group.cpp:2573
GroupReference * GetFirstMember()
Definition Group.h:225
uint32 GetDbStoreId() const
Definition Group.h:206
uint64 GetLeaderGUID() const
Definition Group.cpp:2568
GroupReference * next()
GroupScript(const char *name)
Definition Map.h:238
DifficultyID GetDifficulty() const
Definition Map.h:363
uint32 GetId(void) const
Definition Map.h:300
bool IsInstance() const
Definition Map.h:368
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
uint32 GetGUIDLow() const
Definition Object.h:120
uint32 GetTeam() const
Definition Player.h:2527
float m_homebindZ
Definition Player.h:2851
uint32 m_homebindMapId
Definition Player.h:2847
WorldSession * GetSession() const
Definition Player.h:2417
float m_homebindY
Definition Player.h:2850
Group * GetGroup()
Definition Player.h:2972
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:2090
float m_homebindX
Definition Player.h:2849
PlayerScript(const char *name)
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Map * GetMap() const
Definition Object.h:740
std::string const & GetName() const
Definition Object.h:664
void SendLfgClearStatus(uint64 lfgGroupGuid=0, uint8 queueIdOverride=0, bool groupLeave=false)
bool PlayerDisconnected() const
void SendNameQueryOpcode(ObjectGuid guid)
std::string GetPlayerInfo() const
void SendLfgUpdateStatus(lfg::LfgUpdateData const &updateData, bool party, uint64 queueGuidOverride=0, uint8 queueIdOverride=0)
void SendLfgOfferContinue(uint32 dungeonEntry)
void OnChangeLeader(Group *group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
void OnInviteMember(Group *group, uint64 guid)
void OnDisband(Group *group)
void OnRemoveMember(Group *group, uint64 guid, RemoveMethod method, uint64 kicker, char const *reason)
void OnAddMember(Group *group, uint64 guid)
void OnLogout(Player *player)
void OnLogin(Player *player, bool loginFirst)
void OnMapChanged(Player *player)
Definition LFG.cpp:11
@ LFG_OPTION_ENABLE_DUNGEON_FINDER
Definition LFGMgr.h:26
@ LFG_OPTION_ENABLE_RAID_BROWSER
Definition LFGMgr.h:27
LfgState
Definition LFG.h:61
@ LFG_STATE_FINISHED_DUNGEON
Definition LFG.h:68
@ LFG_STATE_DUNGEON
Definition LFG.h:67
@ LFG_STATE_PROPOSAL
Definition LFG.h:65
@ LFG_STATE_BOOT
Definition LFG.h:66
@ LFG_STATE_NONE
Definition LFG.h:62
@ LFG_STATE_QUEUED
Definition LFG.h:64
@ LFG_UPDATETYPE_LEADER_UNK1
Definition LFG.h:41
@ LFG_GROUP_KICK_VOTES_NEEDED
Definition LFGMgr.h:39
@ LFG_SPELL_LUCK_OF_THE_DRAW
Definition LFGMgr.h:38
@ LFG_SPELL_DUNGEON_DESERTER
Definition LFGMgr.h:37
LfgState state
Definition LFGMgr.h:168