TrinityCore
LFGScripts.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Interaction between core and LFGScripts
20 */
21
22#include "LFGScripts.h"
23#include "Common.h"
24#include "Group.h"
25#include "LFGMgr.h"
26#include "Log.h"
27#include "Map.h"
28#include "ObjectAccessor.h"
29#include "Player.h"
30#include "QueryPackets.h"
31#include "ScriptMgr.h"
32#include "SharedDefines.h"
33#include "WorldSession.h"
34
35namespace lfg
36{
37
39
41{
43 return;
44
45 if (!player->GetGroup())
46 sLFGMgr->LeaveLfg(player->GetGUID());
47 else if (player->GetSession()->PlayerDisconnected())
48 sLFGMgr->LeaveLfg(player->GetGUID(), true);
49}
50
51void LFGPlayerScript::OnLogin(Player* player, bool /*loginFirst*/)
52{
54 return;
55
56 // Temporal: Trying to determine when group data and LFG data gets desynched
57 ObjectGuid guid = player->GetGUID();
58 ObjectGuid gguid = sLFGMgr->GetGroup(guid);
59
60 if (Group const* group = player->GetGroup())
61 {
62 ObjectGuid gguid2 = group->GetGUID();
63 if (gguid != gguid2)
64 {
65 TC_LOG_ERROR("lfg", "{} on group {} but LFG has group {} saved... Fixing.",
66 player->GetSession()->GetPlayerInfo(), gguid2.ToString(), gguid.ToString());
67 sLFGMgr->SetupGroupMember(guid, group->GetGUID());
68 }
69 }
70
71 sLFGMgr->SetTeam(player->GetGUID(), player->GetTeam());
73}
74
76{
77 Map const* map = player->GetMap();
78
79 if (sLFGMgr->inLfgDungeonMap(player->GetGUID(), map->GetId(), map->GetDifficultyID()))
80 {
81 Group* group = player->GetGroup();
82 // This function is also called when players log in
83 // if for some reason the LFG system recognises the player as being in a LFG dungeon,
84 // but the player was loaded without a valid group, we'll teleport to homebind to prevent
85 // crashes or other undefined behaviour
86 if (!group)
87 {
88 sLFGMgr->LeaveLfg(player->GetGUID());
90 player->TeleportTo(player->m_homebind);
91 TC_LOG_ERROR("lfg", "LFGPlayerScript::OnMapChanged, Player {} {} is in LFG dungeon map but does not have a valid group! "
92 "Teleporting to homebind.", player->GetName(), player->GetGUID().ToString());
93 return;
94 }
95
97 for (Group::MemberSlot const& memberSlot : group->GetMemberSlots())
98 player->GetSession()->BuildNameQueryData(memberSlot.guid, response.Players.emplace_back());
99
100 player->SendDirectMessage(response.Write());
101
102 if (sLFGMgr->selectedRandomLfgDungeon(player->GetGUID()))
103 player->CastSpell(player, LFG_SPELL_LUCK_OF_THE_DRAW, true);
104 }
105 else
106 {
107 Group* group = player->GetGroup();
108 if (group && group->GetMembersCount() == 1)
109 {
110 sLFGMgr->LeaveLfg(group->GetGUID());
111 group->Disband();
112 TC_LOG_DEBUG("lfg", "LFGPlayerScript::OnMapChanged, Player {}({}) is last in the lfggroup so we disband the group.",
113 player->GetName(), player->GetGUID().ToString());
114 }
116 }
117}
118
120
122{
124 return;
125
126 ObjectGuid gguid = group->GetGUID();
127 ObjectGuid leader = group->GetLeaderGUID();
128
129 if (leader == guid)
130 {
131 TC_LOG_DEBUG("lfg", "LFGScripts::OnAddMember [{}]: added [{}] leader [{}]", gguid.ToString(), guid.ToString(), leader.ToString());
132 sLFGMgr->SetLeader(gguid, guid);
133 }
134 else
135 {
136 LfgState gstate = sLFGMgr->GetState(gguid);
137 LfgState state = sLFGMgr->GetState(guid);
138 TC_LOG_DEBUG("lfg", "LFGScripts::OnAddMember [{}]: added [{}] leader [{}] gstate: {}, state: {}", gguid.ToString(), guid.ToString(), leader.ToString(), gstate, state);
139
140 if (state == LFG_STATE_QUEUED)
141 sLFGMgr->LeaveLfg(guid);
142
143 if (gstate == LFG_STATE_QUEUED)
144 sLFGMgr->LeaveLfg(gguid);
145 }
146
147 sLFGMgr->SetGroup(guid, gguid);
148 sLFGMgr->AddPlayerToGroup(gguid, guid);
149}
150
151void LFGGroupScript::OnRemoveMember(Group* group, ObjectGuid guid, RemoveMethod method, ObjectGuid kicker, char const* reason)
152{
154 return;
155
156 ObjectGuid gguid = group->GetGUID();
157 TC_LOG_DEBUG("lfg", "LFGScripts::OnRemoveMember [{}]: remove [{}] Method: {} Kicker: [{}] Reason: {}",
158 gguid.ToString(), guid.ToString(), method, kicker.ToString(), (reason ? reason : ""));
159
160 bool isLFG = group->isLFGGroup();
161
162 if (isLFG && method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked
163 {
165 std::string str_reason = "";
166 if (reason)
167 str_reason = std::string(reason);
168 sLFGMgr->InitBoot(gguid, kicker, guid, str_reason);
169 return;
170 }
171
172 LfgState state = sLFGMgr->GetState(gguid);
173
174 // If group is being formed after proposal success do nothing more
175 if (state == LFG_STATE_PROPOSAL && method == GROUP_REMOVEMETHOD_DEFAULT)
176 {
177 // LfgData: Remove player from group
178 sLFGMgr->SetGroup(guid, ObjectGuid::Empty);
179 sLFGMgr->RemovePlayerFromGroup(gguid, guid);
180 return;
181 }
182
183 sLFGMgr->LeaveLfg(guid);
184 sLFGMgr->SetGroup(guid, ObjectGuid::Empty);
185 uint8 players = sLFGMgr->RemovePlayerFromGroup(gguid, guid);
186
187 if (Player* player = ObjectAccessor::FindPlayer(guid))
188 {
189 if (method == GROUP_REMOVEMETHOD_LEAVE && state == LFG_STATE_DUNGEON &&
191 player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, true);
192 else if (method == GROUP_REMOVEMETHOD_KICK_LFG)
193 player->RemoveAurasDueToSpell(LFG_SPELL_DUNGEON_COOLDOWN);
194 //else if (state == LFG_STATE_BOOT)
195 // Update internal kick cooldown of kicked
196
197 player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1), true);
198 if (isLFG && player->GetMap()->IsDungeon()) // Teleport player out the dungeon
199 sLFGMgr->TeleportPlayer(player, true);
200 }
201
202 if (isLFG && state != LFG_STATE_FINISHED_DUNGEON) // Need more players to finish the dungeon
203 if (Player* leader = ObjectAccessor::FindConnectedPlayer(sLFGMgr->GetLeader(gguid)))
204 leader->GetSession()->SendLfgOfferContinue(sLFGMgr->GetDungeon(gguid, false));
205}
206
208{
210 return;
211
212 ObjectGuid gguid = group->GetGUID();
213 TC_LOG_DEBUG("lfg", "LFGScripts::OnDisband [{}]", gguid.ToString());
214
215 sLFGMgr->RemoveGroupData(gguid);
216}
217
218void LFGGroupScript::OnChangeLeader(Group* group, ObjectGuid newLeaderGuid, ObjectGuid oldLeaderGuid)
219{
221 return;
222
223 ObjectGuid gguid = group->GetGUID();
224
225 TC_LOG_DEBUG("lfg", "LFGScripts::OnChangeLeader [{}]: old [{}] new [{}]",
226 gguid.ToString(), newLeaderGuid.ToString(), oldLeaderGuid.ToString());
227
228 sLFGMgr->SetLeader(gguid, newLeaderGuid);
229}
230
232{
234 return;
235
236 ObjectGuid gguid = group->GetGUID();
237 ObjectGuid leader = group->GetLeaderGUID();
238 TC_LOG_DEBUG("lfg", "LFGScripts::OnInviteMember [{}]: invite [{}] leader [{}]",
239 gguid.ToString(), guid.ToString(), leader.ToString());
240
241 // No gguid == new group being formed
242 // No leader == after group creation first invite is new leader
243 // leader and no gguid == first invite after leader is added to new group (this is the real invite)
244 if (!leader.IsEmpty() && gguid.IsEmpty())
245 sLFGMgr->LeaveLfg(leader);
246}
247
249{
250 new LFGPlayerScript();
251 new LFGGroupScript();
252}
253
254} // namespace lfg
uint8_t uint8
Definition: Define.h:144
#define sLFGMgr
Definition: LFGMgr.h:507
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
RemoveMethod
@ GROUP_REMOVEMETHOD_KICK_LFG
@ GROUP_REMOVEMETHOD_DEFAULT
@ GROUP_REMOVEMETHOD_KICK
@ GROUP_REMOVEMETHOD_LEAVE
Definition: Group.h:197
MemberSlotList const & GetMemberSlots() const
Definition: Group.h:324
bool isLFGGroup() const
Definition: Group.cpp:1633
void Disband(bool hideDestroy=false)
Definition: Group.cpp:733
ObjectGuid GetGUID() const
Definition: Group.cpp:1663
uint32 GetMembersCount() const
Definition: Group.h:327
ObjectGuid GetLeaderGUID() const
Definition: Group.cpp:1658
Definition: Map.h:189
Difficulty GetDifficultyID() const
Definition: Map.h:324
uint32 GetId() const
Definition: Map.cpp:3228
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:319
std::string ToString() const
Definition: ObjectGuid.cpp:554
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, TeleportToOptions options=TELE_TO_NONE, Optional< uint32 > instanceId={})
Definition: Player.cpp:1250
WorldLocation m_homebind
Definition: Player.h:2503
WorldSession * GetSession() const
Definition: Player.h:2101
Group * GetGroup(Optional< uint8 > partyIndex)
Definition: Player.h:2606
Team GetTeam() const
Definition: Player.h:2235
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
Map * GetMap() const
Definition: Object.h:624
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
std::string const & GetName() const
Definition: Object.h:555
std::vector< NameCacheLookupResult > Players
Definition: QueryPackets.h:159
WorldPacket const * Write() override
bool PlayerDisconnected() const
std::string GetPlayerInfo() const
void BuildNameQueryData(ObjectGuid guid, WorldPackets::Query::NameCacheLookupResult &lookupData)
void OnRemoveMember(Group *group, ObjectGuid guid, RemoveMethod method, ObjectGuid kicker, char const *reason) override
Definition: LFGScripts.cpp:151
void OnInviteMember(Group *group, ObjectGuid guid) override
Definition: LFGScripts.cpp:231
void OnChangeLeader(Group *group, ObjectGuid newLeaderGuid, ObjectGuid oldLeaderGuid) override
Definition: LFGScripts.cpp:218
void OnAddMember(Group *group, ObjectGuid guid) override
Definition: LFGScripts.cpp:121
void OnDisband(Group *group) override
Definition: LFGScripts.cpp:207
void OnLogout(Player *player) override
Definition: LFGScripts.cpp:40
void OnMapChanged(Player *player) override
Definition: LFGScripts.cpp:75
void OnLogin(Player *player, bool loginFirst) override
Definition: LFGScripts.cpp:51
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
Definition: LFG.cpp:24
@ LFG_OPTION_ENABLE_DUNGEON_FINDER
Definition: LFGMgr.h:49
@ LFG_OPTION_ENABLE_RAID_BROWSER
Definition: LFGMgr.h:50
@ LFG_UPDATETYPE_LEADER_UNK1
Definition: LFG.h:50
@ LFG_SPELL_DUNGEON_COOLDOWN
Definition: LFGMgr.h:59
@ LFG_GROUP_KICK_VOTES_NEEDED
Definition: LFGMgr.h:62
@ LFG_SPELL_LUCK_OF_THE_DRAW
Definition: LFGMgr.h:61
@ LFG_SPELL_DUNGEON_DESERTER
Definition: LFGMgr.h:60
void AddSC_LFGScripts()
Definition: LFGScripts.cpp:248
LfgState
Definition: LFG.h:74
@ LFG_STATE_FINISHED_DUNGEON
Definition: LFG.h:81
@ LFG_STATE_DUNGEON
Definition: LFG.h:80
@ LFG_STATE_PROPOSAL
Definition: LFG.h:78
@ LFG_STATE_QUEUED
Definition: LFG.h:77