9
3

PlayerGroups.cpp 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "PlayerGroups.h"
  17. #include "../common/Log.h"
  18. #include "World.h"
  19. #include "Spells.h"
  20. #include "LuaInterface.h"
  21. #include "Bots/Bot.h"
  22. #include "SpellProcess.h"
  23. #include "Rules/Rules.h"
  24. #include "Web/PeerManager.h"
  25. #include "WorldDatabase.h"
  26. extern ConfigReader configReader;
  27. extern ZoneList zone_list;
  28. extern RuleManager rule_manager;
  29. extern PeerManager peer_manager;
  30. extern WorldDatabase database;
  31. /******************************************************** PlayerGroup ********************************************************/
  32. PlayerGroup::PlayerGroup(int32 id) {
  33. m_id = id;
  34. MGroupMembers.SetName("MGroupMembers");
  35. SetDefaultGroupOptions();
  36. }
  37. PlayerGroup::~PlayerGroup() {
  38. Disband();
  39. }
  40. bool PlayerGroup::AddMember(Entity* member, bool is_leader) {
  41. // Check to make sure the entity we are adding is valid
  42. if (!member) {
  43. LogWrite(GROUP__ERROR, 0, "Group", "New member is null");
  44. return false;
  45. }
  46. // Make sure entity we are adding isn't already in a group by checking if it has a GroupMemberInfo pointer
  47. if (member->GetGroupMemberInfo()) {
  48. LogWrite(GROUP__ERROR, 0, "Group", "New member (%s) already has a group", member->GetName());
  49. return false;
  50. }
  51. // Create a new GroupMemberInfo and assign it to the new member
  52. GroupMemberInfo* gmi = new GroupMemberInfo;
  53. gmi->group_id = m_id;
  54. gmi->member = member;
  55. gmi->leader = is_leader;
  56. if (member->IsPlayer()) {
  57. gmi->is_client = true;
  58. gmi->client = ((Player*)member)->GetClient();
  59. }
  60. else {
  61. gmi->is_client = false;
  62. gmi->client = 0;
  63. }
  64. gmi->mentor_target_char_id = 0;
  65. if (member->GetZone()) {
  66. gmi->zone_id = member->GetZone()->GetZoneID();
  67. gmi->instance_id = member->GetZone()->GetInstanceID();
  68. }
  69. gmi->client_peer_address = std::string(net.GetWorldAddress());
  70. gmi->client_peer_port = net.GetWorldPort();
  71. gmi->is_raid_looter = false;
  72. member->SetGroupMemberInfo(gmi);
  73. member->group_id = gmi->group_id;
  74. MGroupMembers.writelock();
  75. m_members.push_back(gmi);
  76. member->UpdateGroupMemberInfo(true, true);
  77. MGroupMembers.releasewritelock();
  78. SendGroupUpdate();
  79. return true;
  80. }
  81. bool PlayerGroup::AddMemberFromPeer(std::string name, bool isleader, bool isclient, int8 class_id, sint32 hp_cur, sint32 hp_max, int16 level_cur, int16 level_max,
  82. sint32 power_cur, sint32 power_max, int8 race_id, std::string zonename, int32 mentor_target_char_id, int32 zone_id, int32 instance_id,
  83. std::string peer_client_address, int16 peer_client_port, bool is_raid_looter) {
  84. // Create a new GroupMemberInfo and assign it to the new member
  85. GroupMemberInfo* gmi = new GroupMemberInfo;
  86. gmi->group_id = m_id;
  87. gmi->member = nullptr;
  88. gmi->leader = isleader;
  89. gmi->is_client = isclient;
  90. gmi->client = 0;
  91. gmi->mentor_target_char_id = 0;
  92. gmi->class_id = class_id;
  93. gmi->hp_max = hp_max;
  94. gmi->hp_current = hp_cur;
  95. gmi->level_max = level_max;
  96. gmi->level_current = level_cur;
  97. gmi->name = name;
  98. gmi->power_current = power_cur;
  99. gmi->power_max = power_max;
  100. gmi->race_id = race_id;
  101. gmi->zone = zonename;
  102. gmi->zone_id = zone_id;
  103. gmi->instance_id = instance_id;
  104. gmi->mentor_target_char_id = mentor_target_char_id;
  105. gmi->client_peer_address = peer_client_address;
  106. gmi->client_peer_port = peer_client_port;
  107. gmi->is_raid_looter = is_raid_looter;
  108. MGroupMembers.writelock();
  109. m_members.push_back(gmi);
  110. MGroupMembers.releasewritelock();
  111. SendGroupUpdate();
  112. return true;
  113. }
  114. bool PlayerGroup::RemoveMember(Entity* member) {
  115. GroupMemberInfo* gmi = member->GetGroupMemberInfo();
  116. if (!gmi) {
  117. return false;
  118. }
  119. bool ret = false;
  120. bool selfInRaid = IsInRaidGroup(gmi->group_id, false);
  121. MGroupMembers.writelock();
  122. member->SetGroupMemberInfo(0);
  123. deque<GroupMemberInfo*>::iterator erase_itr = m_members.end();
  124. deque<GroupMemberInfo*>::iterator itr;
  125. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  126. if (gmi == *itr)
  127. erase_itr = itr;
  128. if (member->IsPlayer() && (*itr)->mentor_target_char_id == ((Player*)member)->GetCharacterID() && (*itr)->client)
  129. {
  130. (*itr)->mentor_target_char_id = 0;
  131. (*itr)->client->GetPlayer()->EnableResetMentorship();
  132. }
  133. if ((*itr)->client) {
  134. (*itr)->client->GetPlayer()->SetCharSheetChanged(true);
  135. if (selfInRaid)
  136. (*itr)->client->GetPlayer()->SetRaidSheetChanged(true);
  137. }
  138. }
  139. if (erase_itr != m_members.end()) {
  140. ret = true;
  141. m_members.erase(erase_itr);
  142. }
  143. MGroupMembers.releasewritelock();
  144. member->SetGroupMemberInfo(nullptr);
  145. safe_delete(gmi);
  146. if (member->IsBot())
  147. ((Bot*)member)->Camp();
  148. return ret;
  149. }
  150. bool PlayerGroup::RemoveMember(std::string name, bool is_client, int32 charID) {
  151. bool ret = false;
  152. GroupMemberInfo* gmi = nullptr;
  153. bool selfInRaid = IsInRaidGroup(GetID(), false);
  154. deque<GroupMemberInfo*>::iterator erase_itr = m_members.end();
  155. deque<GroupMemberInfo*>::iterator itr;
  156. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  157. if ((*itr)->name == name && (*itr)->is_client == is_client) {
  158. gmi = (*itr);
  159. erase_itr = itr;
  160. }
  161. if (is_client && charID > 0 && (*itr)->mentor_target_char_id == charID && (*itr)->client)
  162. {
  163. (*itr)->mentor_target_char_id = 0;
  164. (*itr)->client->GetPlayer()->EnableResetMentorship();
  165. }
  166. if ((*itr)->client) {
  167. (*itr)->client->GetPlayer()->SetCharSheetChanged(true);
  168. if (selfInRaid)
  169. (*itr)->client->GetPlayer()->SetRaidSheetChanged(true);
  170. }
  171. }
  172. if (erase_itr != m_members.end()) {
  173. ret = true;
  174. m_members.erase(erase_itr);
  175. }
  176. MGroupMembers.releasewritelock();
  177. safe_delete(gmi);
  178. return ret;
  179. }
  180. void PlayerGroup::Disband() {
  181. m_raidgroups.clear();
  182. deque<GroupMemberInfo*>::iterator itr;
  183. MGroupMembers.writelock();
  184. bool selfInRaid = IsInRaidGroup(GetID(), false);
  185. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  186. if ((*itr)->member) {
  187. (*itr)->member->SetGroupMemberInfo(0);
  188. if ((*itr)->member->IsBot())
  189. ((Bot*)(*itr)->member)->Camp();
  190. }
  191. if ((*itr)->mentor_target_char_id && (*itr)->client)
  192. {
  193. (*itr)->mentor_target_char_id = 0;
  194. (*itr)->client->GetPlayer()->EnableResetMentorship();
  195. }
  196. if ((*itr)->client) {
  197. (*itr)->client->GetPlayer()->SetCharSheetChanged(true);
  198. if (selfInRaid)
  199. (*itr)->client->GetPlayer()->SetRaidSheetChanged(true);
  200. }
  201. safe_delete(*itr);
  202. }
  203. m_members.clear();
  204. MGroupMembers.releasewritelock();
  205. }
  206. void PlayerGroup::SendGroupUpdate(Client* exclude, bool forceRaidUpdate) {
  207. bool selfInRaid = IsInRaidGroup(GetID(), false);
  208. deque<GroupMemberInfo*>::iterator itr;
  209. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  210. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  211. GroupMemberInfo* gmi = *itr;
  212. if (gmi->client && gmi->client != exclude && !gmi->client->IsZoning()) {
  213. gmi->client->GetPlayer()->SetCharSheetChanged(true);
  214. if (selfInRaid || forceRaidUpdate)
  215. gmi->client->GetPlayer()->SetRaidSheetChanged(true);
  216. }
  217. }
  218. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  219. }
  220. void PlayerGroup::SimpleGroupMessage(const char* message) {
  221. deque<GroupMemberInfo*>::iterator itr;
  222. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  223. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  224. GroupMemberInfo* info = *itr;
  225. if (info->client)
  226. info->client->SimpleMessage(CHANNEL_GROUP_CHAT, message);
  227. }
  228. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  229. }
  230. void PlayerGroup::SendGroupMessage(int8 type, const char* message, ...) {
  231. va_list argptr;
  232. char buffer[4096];
  233. buffer[0] = 0;
  234. va_start(argptr, message);
  235. vsnprintf(buffer, sizeof(buffer), message, argptr);
  236. va_end(argptr);
  237. deque<GroupMemberInfo*>::iterator itr;
  238. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  239. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  240. GroupMemberInfo* info = *itr;
  241. if (info->client)
  242. info->client->SimpleMessage(type, buffer);
  243. }
  244. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  245. }
  246. void PlayerGroup::GroupChatMessage(Spawn* from, int32 language, const char* message, int16 channel) {
  247. deque<GroupMemberInfo*>::iterator itr;
  248. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  249. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  250. GroupMemberInfo* info = *itr;
  251. if (info && info->client && info->client->GetCurrentZone())
  252. info->client->GetCurrentZone()->HandleChatMessage(info->client, from, 0, channel, message, 0, 0, true, language);
  253. }
  254. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  255. }
  256. void PlayerGroup::GroupChatMessage(std::string fromName, int32 language, const char* message, int16 channel) {
  257. deque<GroupMemberInfo*>::iterator itr;
  258. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  259. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  260. GroupMemberInfo* info = *itr;
  261. if (info && info->client && info->client->GetCurrentZone())
  262. info->client->GetCurrentZone()->HandleChatMessage(info->client, fromName, "", channel, message, 0, 0, language);
  263. }
  264. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  265. }
  266. bool PlayerGroup::MakeLeader(Entity* new_leader) {
  267. if (!new_leader || new_leader->GetGroupMemberInfo())
  268. return false;
  269. bool selfInRaid = IsInRaidGroup(GetID(), false);
  270. deque<GroupMemberInfo*>::iterator itr;
  271. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  272. new_leader->GetGroupMemberInfo()->leader = true;
  273. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  274. GroupMemberInfo* info = *itr;
  275. if (info && info != new_leader->GetGroupMemberInfo() && info->leader) {
  276. info->leader = false;
  277. peer_manager.sendPeersGroupMember(GetID(), info, true);
  278. break;
  279. }
  280. if ((*itr)->client) {
  281. (*itr)->client->GetPlayer()->SetCharSheetChanged(true);
  282. if (selfInRaid)
  283. (*itr)->client->GetPlayer()->SetRaidSheetChanged(true);
  284. }
  285. }
  286. peer_manager.sendPeersGroupMember(GetID(), new_leader->GetGroupMemberInfo(), true);
  287. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  288. SendGroupUpdate();
  289. return true;
  290. }
  291. std::string PlayerGroup::GetLeaderName() {
  292. std::string name("");
  293. deque<GroupMemberInfo*>::iterator itr;
  294. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  295. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  296. GroupMemberInfo* info = *itr;
  297. if (info->leader && info->name.size() > 0) {
  298. name = info->name;
  299. break;
  300. }
  301. }
  302. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  303. return name;
  304. }
  305. bool PlayerGroup::ShareQuestWithGroup(Client* quest_sharer, Quest* quest) {
  306. if (!quest || !quest_sharer)
  307. return false;
  308. bool canShare = quest->CanShareQuestCriteria(quest_sharer);
  309. if (!canShare) {
  310. return false;
  311. }
  312. deque<GroupMemberInfo*>::iterator itr;
  313. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  314. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  315. GroupMemberInfo* info = *itr;
  316. if (info && info->client && info->client->GetCurrentZone()) {
  317. if (quest_sharer != info->client && info->client->GetPlayer()->HasAnyQuest(quest->GetQuestID()) == 0) {
  318. info->client->AddPendingQuest(new Quest(quest));
  319. info->client->Message(CHANNEL_COLOR_YELLOW, "%s has shared the quest %s with you.", quest_sharer->GetPlayer()->GetName(), quest->GetName());
  320. }
  321. }
  322. }
  323. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  324. return true;
  325. }
  326. /******************************************************** PlayerGroupManager ********************************************************/
  327. PlayerGroupManager::PlayerGroupManager() {
  328. m_nextGroupID = 1;
  329. MPendingInvites.SetName("PlayerGroupManager::m_pendingInvites");
  330. }
  331. PlayerGroupManager::~PlayerGroupManager() {
  332. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  333. m_pendingInvites.clear();
  334. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  335. std::unique_lock lock(MGroups);
  336. map<int32, PlayerGroup*>::iterator itr;
  337. for (itr = m_groups.begin(); itr != m_groups.end(); itr++)
  338. safe_delete(itr->second);
  339. m_groups.clear();
  340. }
  341. bool PlayerGroupManager::AddGroupMember(int32 group_id, Entity* member, bool is_leader) {
  342. std::shared_lock lock(MGroups);
  343. bool ret = false;
  344. if (m_groups.count(group_id) > 0) {
  345. PlayerGroup* group = m_groups[group_id];
  346. ret = group->AddMember(member, is_leader);
  347. peer_manager.sendPeersGroupMember(group_id, member->GetGroupMemberInfo());
  348. }
  349. return ret;
  350. }
  351. bool PlayerGroupManager::AddGroupMemberFromPeer(int32 group_id, GroupMemberInfo* info) {
  352. if (!info)
  353. return false;
  354. std::shared_lock lock(MGroups);
  355. bool ret = false;
  356. if (m_groups.count(group_id) > 0) {
  357. PlayerGroup* group = m_groups[group_id];
  358. ret = group->AddMemberFromPeer(info->name, info->leader, info->is_client, info->class_id, info->hp_current, info->hp_max, info->level_current, info->level_max,
  359. info->power_current, info->power_max, info->race_id, info->zone, info->mentor_target_char_id, info->zone_id, info->instance_id,
  360. info->client_peer_address, info->client_peer_port, info->is_raid_looter);
  361. }
  362. return ret;
  363. }
  364. bool PlayerGroupManager::RemoveGroupMember(int32 group_id, Entity* member) {
  365. if (!member)
  366. return false;
  367. bool ret = false;
  368. bool remove = false;
  369. Client* client = 0;
  370. if (member->GetGroupMemberInfo() && member->GetGroupMemberInfo()->mentor_target_char_id)
  371. {
  372. if (member->IsPlayer())
  373. {
  374. Player* tmpPlayer = (Player*)member;
  375. member->GetGroupMemberInfo()->mentor_target_char_id = 0;
  376. tmpPlayer->EnableResetMentorship();
  377. }
  378. }
  379. GroupLock(__FUNCTION__, __LINE__);
  380. if (m_groups.count(group_id) > 0) {
  381. PlayerGroup* group = m_groups[group_id];
  382. if (member->IsPlayer())
  383. client = member->GetGroupMemberInfo()->client;
  384. ret = group->RemoveMember(member);
  385. // If only 1 person left in the group set a flag to remove the group
  386. if (group->Size() == 1)
  387. remove = true;
  388. }
  389. ReleaseGroupLock(__FUNCTION__, __LINE__);
  390. if (client)
  391. RemoveGroupBuffs(group_id, client);
  392. peer_manager.sendPeersRemoveGroupMember(group_id, std::string(member->GetName()), (member->IsPlayer() ? ((Player*)member)->GetCharacterID() : 0), member->IsPlayer());
  393. // Call RemoveGroup outside the locks as it uses the same locks
  394. if (remove) {
  395. RemoveGroup(group_id);
  396. peer_manager.sendPeersDisbandGroup(group_id);
  397. }
  398. return ret;
  399. }
  400. bool PlayerGroupManager::RemoveGroupMember(int32 group_id, std::string name, bool is_client, int32 charID) {
  401. bool ret = false;
  402. bool remove = false;
  403. Client* client = 0;
  404. GroupLock(__FUNCTION__, __LINE__);
  405. if (m_groups.count(group_id) > 0) {
  406. PlayerGroup* group = m_groups[group_id];
  407. ret = group->RemoveMember(name, is_client, charID);
  408. // If only 1 person left in the group set a flag to remove the group
  409. if (group->Size() == 1)
  410. remove = true;
  411. }
  412. ReleaseGroupLock(__FUNCTION__, __LINE__);
  413. //if (client)
  414. // RemoveGroupBuffs(group_id, client);
  415. // Call RemoveGroup outside the locks as it uses the same locks
  416. if (remove)
  417. RemoveGroup(group_id);
  418. else {
  419. GroupMessage(group_id, "%s has left the group.", name.c_str());
  420. }
  421. return ret;
  422. }
  423. int32 PlayerGroupManager::NewGroup(Entity* leader, GroupOptions* goptions, int32 override_group_id) {
  424. std::unique_lock lock(MGroups);
  425. int32 groupID = 0;
  426. // Highly doubt this will ever be needed but putting it in any way, basically bump the id and ensure
  427. // no active group is currently using this id, if we hit the max for an int32 then reset the id to 1
  428. if (!override_group_id) {
  429. do {
  430. groupID = peer_manager.getUniqueGroupId();
  431. } while (m_groups.count(groupID) > 0);
  432. }
  433. else if (override_group_id) {
  434. groupID = override_group_id;
  435. if (m_groups.count(groupID))
  436. return 0; // group already exists
  437. }
  438. // last resort if the unique group id is not working out
  439. while (m_groups.count(groupID) > 0) {
  440. // If m_nextGroupID is at its max then reset it to 1, else increment it
  441. if (groupID == 4294967295)
  442. groupID = 1;
  443. else
  444. groupID++;
  445. }
  446. // Create a new group with the valid ID we got from above
  447. PlayerGroup* new_group = new PlayerGroup(groupID);
  448. new_group->SetDefaultGroupOptions(goptions);
  449. // Add the new group to the list (need to do this first, AddMember needs ref to the PlayerGroup ptr -> UpdateGroupMemberInfo)
  450. m_groups[groupID] = new_group;
  451. return groupID;
  452. }
  453. void PlayerGroupManager::RemoveGroup(int32 group_id) {
  454. std::unique_lock lock(MGroups);
  455. // Check to see if the id is in the list
  456. if (m_groups.count(group_id) > 0) {
  457. // Get a pointer to the group
  458. PlayerGroup* group = m_groups[group_id];
  459. std::vector<int32> raidGroups;
  460. m_groups[group_id]->GetRaidGroups(&raidGroups);
  461. if (raidGroups.size() > 0) {
  462. std::vector<int32>::iterator group_itr;
  463. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end(); group_itr++) {
  464. if (m_groups.count((*group_itr))) {
  465. m_groups[(*group_itr)]->ReplaceRaidGroups(&raidGroups);
  466. }
  467. }
  468. }
  469. m_groups[group_id]->ClearGroupRaid();
  470. // Erase the group from the list
  471. m_groups.erase(group_id);
  472. // Delete the group
  473. safe_delete(group);
  474. }
  475. }
  476. int8 PlayerGroupManager::Invite(Player* leader, Entity* member) {
  477. int8 ret = 255; // Should be changed, if it is not then we have an unknown error
  478. // Lock the pending invite list so we can work with it
  479. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  480. if (!member || (member->IsBot() && ((Bot*)member)->IsImmediateCamp()))
  481. ret = 6; // failure, not a valid target
  482. else if (member->IsNPC() && (!member->IsBot() /*|| !member->IsMec()*/))
  483. ret = 6;
  484. else if (leader == member)
  485. ret = 5; // failure, can't invite yourself
  486. else if (member->GetGroupMemberInfo())
  487. ret = 1; // failure, member already in a group
  488. // Check to see if the target of the invite already has a pending invite
  489. else if (m_pendingInvites.count(member->GetName()) > 0)
  490. ret = 2; // Target already has an invite
  491. // Check to see if the player that invited is already in a group
  492. else if (leader->GetGroupMemberInfo()) {
  493. // Read lock the group list so we can get the size of the inviters group
  494. GroupLock(__FUNCTION__, __LINE__);
  495. int32 group_size = m_groups[leader->GetGroupMemberInfo()->group_id]->Size();
  496. ReleaseGroupLock(__FUNCTION__, __LINE__);
  497. // Check to see if the group is full
  498. if (m_groups[leader->GetGroupMemberInfo()->group_id]->Size() >= 6)
  499. ret = 3; // Group full
  500. // Group isn't full so add the member to the pending invite list
  501. else {
  502. m_pendingInvites[member->GetName()] = leader->GetName();
  503. ret = 0; // Success
  504. }
  505. }
  506. // Inviter is not in a group
  507. else {
  508. // Check to see if the inviter has a pending invite himself
  509. if (m_pendingInvites.count(leader->GetName()) > 0)
  510. ret = 4; // inviter already has a pending group invite
  511. // No pending invites for the inviter add both the inviter and the target of the invite to the list
  512. else {
  513. m_pendingInvites[leader->GetName()] = leader->GetName();
  514. m_pendingInvites[member->GetName()] = leader->GetName();
  515. ret = 0; // success
  516. }
  517. }
  518. // Release the lock on pending invites
  519. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  520. bool group_existed = false;
  521. if (leader && leader->GetGroupMemberInfo()) {
  522. group_existed = true;
  523. }
  524. /* testing purposes only */
  525. if (ret == 0 && member->IsNPC()) {
  526. if (net.is_primary) {
  527. int32 group_id = 0;
  528. int8 result = AcceptInvite(member, &group_id, false);
  529. if (result == 0) {
  530. if (leader && leader->GetClient()) {
  531. if (group_existed) {
  532. group_id = leader->GetGroupMemberInfo()->group_id;
  533. GroupOptions options;
  534. leader->GetClient()->SetGroupOptionsReference(&options);
  535. peer_manager.sendPeersNewGroupRequest("", 0, group_id, std::string(leader->GetName()), std::string(member->GetName()), &options);
  536. }
  537. else {
  538. AddGroupMember(group_id, leader, true);
  539. }
  540. GroupMessage(group_id, "%s has joined the group.", member->GetName());
  541. AddGroupMember(group_id, member);
  542. }
  543. }
  544. }
  545. else {
  546. GroupOptions options;
  547. if (leader && leader->GetClient()) {
  548. GroupOptions options;
  549. leader->GetClient()->SetGroupOptionsReference(&options);
  550. peer_manager.sendPrimaryNewGroupRequest(std::string(leader->GetName()), std::string(member->GetName()), member->GetID(), &options);
  551. }
  552. }
  553. }
  554. return ret;
  555. }
  556. bool PlayerGroupManager::AddInvite(Player* leader, Entity* member) {
  557. bool ret = true;
  558. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  559. if (leader == member)
  560. ret = false; // failure, can't invite yourself
  561. else if (member->GetGroupMemberInfo())
  562. ret = false;
  563. // Check to see if the target of the invite already has a pending invite
  564. else if (m_pendingInvites.count(member->GetName()) > 0)
  565. ret = false; // Target already has an invite
  566. if (leader->GetGroupMemberInfo()) {
  567. m_pendingInvites[member->GetName()] = leader->GetName();
  568. }
  569. else {
  570. m_pendingInvites[leader->GetName()] = leader->GetName();
  571. m_pendingInvites[member->GetName()] = leader->GetName();
  572. }
  573. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  574. return ret;
  575. }
  576. int8 PlayerGroupManager::AcceptInvite(Entity* member, int32* group_override_id, bool auto_add_group) {
  577. int8 ret = 3; // default to unknown error
  578. int32 groupResultID = 0;
  579. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  580. if (m_pendingInvites.count(member->GetName()) > 0) {
  581. string leader = m_pendingInvites[member->GetName()];
  582. Client* client_leader = zone_list.GetClientByCharName(leader);
  583. if (client_leader) {
  584. if (m_pendingInvites.count(leader) > 0) {
  585. if (!client_leader->GetPlayer()->GetGroupMemberInfo()) {
  586. GroupOptions goptions;
  587. goptions.loot_method = client_leader->GetPlayer()->GetInfoStruct()->get_group_loot_method();
  588. goptions.loot_items_rarity = client_leader->GetPlayer()->GetInfoStruct()->get_group_loot_items_rarity();
  589. goptions.auto_split = client_leader->GetPlayer()->GetInfoStruct()->get_group_auto_split();
  590. goptions.default_yell = client_leader->GetPlayer()->GetInfoStruct()->get_group_default_yell();
  591. goptions.group_autolock = client_leader->GetPlayer()->GetInfoStruct()->get_group_autolock();
  592. goptions.group_lock_method = client_leader->GetPlayer()->GetInfoStruct()->get_group_lock_method();
  593. goptions.solo_autolock = client_leader->GetPlayer()->GetInfoStruct()->get_group_solo_autolock();
  594. goptions.auto_loot_method = client_leader->GetPlayer()->GetInfoStruct()->get_group_auto_loot_method();
  595. groupResultID = NewGroup(client_leader->GetPlayer(), &goptions, (group_override_id != nullptr) ? (*group_override_id) : 0);
  596. if (group_override_id != nullptr && *group_override_id == 0) {
  597. *group_override_id = groupResultID;
  598. }
  599. }
  600. else {
  601. if (group_override_id != nullptr && *group_override_id == 0) {
  602. if (client_leader->GetPlayer()->GetGroupMemberInfo())
  603. *group_override_id = client_leader->GetPlayer()->GetGroupMemberInfo()->group_id;
  604. }
  605. }
  606. m_pendingInvites.erase(leader);
  607. }
  608. // Remove from invite list and add to the group
  609. if (m_pendingInvites.count(member->GetName())) {
  610. m_pendingInvites.erase(member->GetName());
  611. }
  612. int32 result_group_id = 0;
  613. if (*group_override_id && *group_override_id > 0) {
  614. result_group_id = *group_override_id;
  615. }
  616. else
  617. result_group_id = groupResultID;
  618. if (auto_add_group && result_group_id) {
  619. AddGroupMember(result_group_id, client_leader->GetPlayer());
  620. GroupMessage(result_group_id, "%s has joined the group.", member->GetName());
  621. AddGroupMember(result_group_id, member);
  622. }
  623. ret = 0; // success
  624. }
  625. else {
  626. // Was unable to find the leader, remove from the invite list
  627. if (m_pendingInvites.count(member->GetName())) {
  628. m_pendingInvites.erase(member->GetName());
  629. }
  630. ret = 2; // failure, can't find leader
  631. }
  632. }
  633. else
  634. ret = 1; // failure, no pending invite
  635. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  636. return ret;
  637. }
  638. void PlayerGroupManager::DeclineInvite(Entity* member) {
  639. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  640. if (m_pendingInvites.count(member->GetName()) > 0) {
  641. string leader = m_pendingInvites[member->GetName()];
  642. // send decline to leader
  643. m_pendingInvites.erase(member->GetName());
  644. if (m_pendingInvites.count(leader) > 0)
  645. m_pendingInvites.erase(leader);
  646. }
  647. if (m_raidPendingInvites.count(member->GetName()) > 0) {
  648. string leader = m_raidPendingInvites[member->GetName()];
  649. // send decline to leader
  650. m_raidPendingInvites.erase(member->GetName());
  651. }
  652. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  653. }
  654. bool PlayerGroupManager::IsGroupIDValid(int32 group_id) {
  655. std::shared_lock lock(MGroups);
  656. bool ret = false;
  657. ret = m_groups.count(group_id) > 0;
  658. return ret;
  659. }
  660. void PlayerGroupManager::SendGroupUpdate(int32 group_id, Client* exclude, bool forceRaidUpdate) {
  661. std::shared_lock lock(MGroups);
  662. if (m_groups.count(group_id) > 0) {
  663. std::vector<int32> raidGroups;
  664. m_groups[group_id]->GetRaidGroups(&raidGroups);
  665. if (raidGroups.size() < 1)
  666. raidGroups.push_back(group_id);
  667. std::vector<int32>::iterator group_itr;
  668. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end(); group_itr++) {
  669. if (m_groups.count((*group_itr))) {
  670. m_groups[(*group_itr)]->SendGroupUpdate(exclude, forceRaidUpdate);
  671. }
  672. }
  673. }
  674. }
  675. PlayerGroup* PlayerGroupManager::GetGroup(int32 group_id) {
  676. if (m_groups.count(group_id) > 0)
  677. return m_groups[group_id];
  678. return 0;
  679. }
  680. void PlayerGroupManager::ClearPendingInvite(Entity* member) {
  681. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  682. if (m_pendingInvites.count(member->GetName()) > 0)
  683. m_pendingInvites.erase(member->GetName());
  684. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  685. }
  686. std::string PlayerGroupManager::HasPendingInvite(Entity* member) {
  687. std::string leader("");
  688. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  689. if (m_pendingInvites.count(member->GetName()) > 0) {
  690. leader = m_pendingInvites[member->GetName()];
  691. }
  692. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  693. return leader;
  694. }
  695. void PlayerGroupManager::RemoveGroupBuffs(int32 group_id, Client* client) {
  696. SpellEffects* se = 0;
  697. Spell* spell = 0;
  698. LuaSpell* luaspell = 0;
  699. EQ2Packet* packet = 0;
  700. Entity* pet = 0;
  701. Player* player = 0;
  702. Entity* charmed_pet = 0;
  703. PlayerGroup* group = 0;
  704. MGroups.lock_shared();
  705. if (m_groups.count(group_id) > 0)
  706. group = m_groups[group_id];
  707. if (group && client) {
  708. /* first remove all spell effects this group member has on them from other group members */
  709. player = client->GetPlayer();
  710. bool recoup_lock = true;
  711. for (int i = 0; i < NUM_SPELL_EFFECTS; i++) {
  712. if (recoup_lock) {
  713. player->GetSpellEffectMutex()->readlock(__FUNCTION__, __LINE__);
  714. recoup_lock = false;
  715. se = player->GetSpellEffects();
  716. }
  717. if (se && se[i].spell_id != 0xFFFFFFFF) {
  718. //If the client is the caster, don't remove the spell
  719. if (se[i].caster == player)
  720. continue;
  721. luaspell = se[i].spell;
  722. spell = luaspell->spell;
  723. /* is this a friendly group spell? */
  724. if (spell && spell->GetSpellData()->group_spell && spell->GetSpellData()->friendly_spell) {
  725. player->GetSpellEffectMutex()->releasereadlock(__FUNCTION__, __LINE__);
  726. recoup_lock = true;
  727. // we have to remove our spell effect mutex lock since RemoveSpellEffect needs a write lock to remove it
  728. //Remove all group buffs not cast by this player
  729. player->RemoveSpellEffect(luaspell);
  730. player->RemoveSpellBonus(luaspell);
  731. player->RemoveSkillBonus(spell->GetSpellID());
  732. //Also remove group buffs from pets
  733. pet = 0;
  734. charmed_pet = 0;
  735. if (player->HasPet()) {
  736. pet = player->GetPet();
  737. pet = player->GetCharmedPet();
  738. }
  739. if (pet) {
  740. pet->RemoveSpellEffect(luaspell);
  741. pet->RemoveSpellBonus(luaspell);
  742. }
  743. if (charmed_pet) {
  744. charmed_pet->RemoveSpellEffect(luaspell);
  745. charmed_pet->RemoveSpellBonus(luaspell);
  746. }
  747. }
  748. }
  749. }
  750. if (!recoup_lock) { // we previously set a readlock that we now release
  751. player->GetSpellEffectMutex()->releasereadlock(__FUNCTION__, __LINE__);
  752. }
  753. packet = client->GetPlayer()->GetSkills()->GetSkillPacket(client->GetVersion());
  754. if (packet)
  755. client->QueuePacket(packet);
  756. }
  757. MGroups.unlock_shared();
  758. }
  759. int32 PlayerGroupManager::GetGroupSize(int32 group_id) {
  760. std::shared_lock lock(MGroups);
  761. int32 ret = 0;
  762. if (m_groups.count(group_id) > 0)
  763. ret = m_groups[group_id]->Size();
  764. return ret;
  765. }
  766. void PlayerGroupManager::SendGroupQuests(int32 group_id, Client* client) {
  767. std::shared_lock lock(MGroups);
  768. GroupMemberInfo* info = 0;
  769. if (m_groups.count(group_id) > 0) {
  770. m_groups[group_id]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  771. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  772. deque<GroupMemberInfo*>::iterator itr;
  773. for (itr = members->begin(); itr != members->end(); itr++) {
  774. info = *itr;
  775. if (info->client) {
  776. LogWrite(PLAYER__DEBUG, 0, "Player", "Send Quest Journal...");
  777. info->client->SendQuestJournal(false, client);
  778. client->SendQuestJournal(false, info->client);
  779. }
  780. }
  781. m_groups[group_id]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  782. }
  783. }
  784. bool PlayerGroupManager::HasGroupCompletedQuest(int32 group_id, int32 quest_id) {
  785. std::shared_lock lock(MGroups);
  786. bool questComplete = true;
  787. GroupMemberInfo* info = 0;
  788. if (m_groups.count(group_id) > 0) {
  789. m_groups[group_id]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  790. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  791. deque<GroupMemberInfo*>::iterator itr;
  792. for (itr = members->begin(); itr != members->end(); itr++) {
  793. info = *itr;
  794. if (info->client) {
  795. bool isComplete = info->client->GetPlayer()->HasQuestBeenCompleted(quest_id);
  796. if (!isComplete)
  797. {
  798. questComplete = isComplete;
  799. break;
  800. }
  801. }
  802. }
  803. m_groups[group_id]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  804. }
  805. return questComplete;
  806. }
  807. void PlayerGroupManager::SimpleGroupMessage(int32 group_id, const char* message) {
  808. std::shared_lock lock(MGroups);
  809. if (m_groups.count(group_id) > 0)
  810. m_groups[group_id]->SimpleGroupMessage(message);
  811. }
  812. void PlayerGroupManager::SendGroupMessage(int32 group_id, int8 type, const char* message, ...) {
  813. std::shared_lock lock(MGroups);
  814. va_list argptr;
  815. char buffer[4096];
  816. buffer[0] = 0;
  817. va_start(argptr, message);
  818. vsnprintf(buffer, sizeof(buffer), message, argptr);
  819. va_end(argptr);
  820. if (m_groups.count(group_id) > 0)
  821. m_groups[group_id]->SendGroupMessage(type, buffer);
  822. }
  823. void PlayerGroupManager::GroupMessage(int32 group_id, const char* message, ...) {
  824. va_list argptr;
  825. char buffer[4096];
  826. buffer[0] = 0;
  827. va_start(argptr, message);
  828. vsnprintf(buffer, sizeof(buffer), message, argptr);
  829. va_end(argptr);
  830. SimpleGroupMessage(group_id, buffer);
  831. }
  832. void PlayerGroupManager::GroupChatMessage(int32 group_id, Spawn* from, int32 language, const char* message, int16 channel) {
  833. std::shared_lock lock(MGroups);
  834. if (m_groups.count(group_id) > 0) {
  835. std::vector<int32> raidGroups;
  836. if (channel == CHANNEL_RAID_SAY)
  837. m_groups[group_id]->GetRaidGroups(&raidGroups);
  838. if (raidGroups.size() < 1)
  839. raidGroups.push_back(group_id);
  840. std::vector<int32>::iterator group_itr;
  841. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end(); group_itr++) {
  842. if (m_groups.count((*group_itr))) {
  843. m_groups[(*group_itr)]->GroupChatMessage(from, language, message, channel);
  844. }
  845. }
  846. }
  847. }
  848. void PlayerGroupManager::GroupChatMessage(int32 group_id, std::string fromName, int32 language, const char* message, int16 channel) {
  849. std::shared_lock lock(MGroups);
  850. if (m_groups.count(group_id) > 0) {
  851. std::vector<int32> raidGroups;
  852. if (channel == CHANNEL_RAID_SAY)
  853. m_groups[group_id]->GetRaidGroups(&raidGroups);
  854. if (raidGroups.size() < 1)
  855. raidGroups.push_back(group_id);
  856. std::vector<int32>::iterator group_itr;
  857. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end(); group_itr++) {
  858. if (m_groups.count((*group_itr))) {
  859. m_groups[(*group_itr)]->GroupChatMessage(fromName, language, message, channel);
  860. }
  861. }
  862. }
  863. }
  864. void PlayerGroupManager::SendGroupChatMessage(int32 group_id, int16 channel, const char* message, ...) {
  865. std::shared_lock lock(MGroups);
  866. va_list argptr;
  867. char buffer[4096];
  868. buffer[0] = 0;
  869. va_start(argptr, message);
  870. vsnprintf(buffer, sizeof(buffer), message, argptr);
  871. va_end(argptr);
  872. if (m_groups.count(group_id) > 0) {
  873. std::vector<int32> raidGroups;
  874. if (channel == CHANNEL_RAID_SAY || channel == CHANNEL_LOOT_ROLLS)
  875. m_groups[group_id]->GetRaidGroups(&raidGroups);
  876. if (raidGroups.size() < 1)
  877. raidGroups.push_back(group_id);
  878. std::vector<int32>::iterator group_itr;
  879. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end(); group_itr++) {
  880. if (m_groups.count((*group_itr))) {
  881. m_groups[(*group_itr)]->SendGroupMessage(channel, buffer);
  882. }
  883. }
  884. }
  885. }
  886. bool PlayerGroupManager::MakeLeader(int32 group_id, Entity* new_leader) {
  887. std::shared_lock lock(MGroups);
  888. if (m_groups.count(group_id) > 0)
  889. return m_groups[group_id]->MakeLeader(new_leader);
  890. return false;
  891. }
  892. void PlayerGroupManager::UpdateGroupBuffs() {
  893. map<int32, PlayerGroup*>::iterator itr;
  894. deque<GroupMemberInfo*>::iterator member_itr;
  895. deque<GroupMemberInfo*>::iterator target_itr;
  896. map<int32, SkillBonusValue*>::iterator itr_skills;
  897. MaintainedEffects* me = nullptr;
  898. LuaSpell* luaspell = nullptr;
  899. Spell* spell = nullptr;
  900. Entity* group_member = nullptr;
  901. SkillBonus* sb = nullptr;
  902. EQ2Packet* packet = nullptr;
  903. int32 i = 0;
  904. PlayerGroup* group = nullptr;
  905. Player* caster = nullptr;
  906. vector<int32> new_target_list;
  907. vector<int32> char_list;
  908. Client* client = nullptr;
  909. bool has_effect = false;
  910. vector<BonusValues*>* sb_list = nullptr;
  911. BonusValues* bv = nullptr;
  912. Entity* pet = nullptr;
  913. Entity* charmed_pet = nullptr;
  914. for (itr = m_groups.begin(); itr != m_groups.end(); itr++) {
  915. group = itr->second;
  916. /* loop through the group members and see if any of them have any maintained spells that are group buffs and friendly.
  917. if so, update the list of targets and apply/remove effects as needed */
  918. vector<Player*> players;
  919. group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  920. for (member_itr = group->GetMembers()->begin(); member_itr != group->GetMembers()->end(); member_itr++) {
  921. if ((*member_itr)->client)
  922. caster = (*member_itr)->client->GetPlayer();
  923. else caster = 0;
  924. if (!caster)
  925. continue;
  926. if (!caster->GetMaintainedSpellBySlot(0))
  927. continue;
  928. players.push_back(caster);
  929. }
  930. group->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  931. vector<Player*>::iterator vitr;
  932. for (vitr = players.begin(); vitr != players.end(); vitr++) {
  933. caster = *vitr;
  934. caster->GetMaintainedMutex()->readlock(__FUNCTION__, __LINE__);
  935. // go through the player's maintained spells
  936. me = caster->GetMaintainedSpells();
  937. for (i = 0; i < NUM_MAINTAINED_EFFECTS; i++) {
  938. if (me[i].spell_id == 0xFFFFFFFF)
  939. continue;
  940. luaspell = me[i].spell;
  941. if (!luaspell)
  942. continue;
  943. if (!luaspell->caster)
  944. {
  945. LogWrite(PLAYER__ERROR, 0, "Player", "Bad luaspell, caster is NULL, spellid: %u", me[i].spell_id);
  946. continue;
  947. }
  948. spell = luaspell->spell;
  949. if (spell && spell->GetSpellData()->group_spell && spell->GetSpellData()->friendly_spell &&
  950. (spell->GetSpellData()->target_type == SPELL_TARGET_GROUP_AE || spell->GetSpellData()->target_type == SPELL_TARGET_RAID_AE)) {
  951. luaspell->MSpellTargets.writelock(__FUNCTION__, __LINE__);
  952. luaspell->char_id_targets.clear();
  953. for (target_itr = group->GetMembers()->begin(); target_itr != group->GetMembers()->end(); target_itr++) {
  954. group_member = (*target_itr)->member;
  955. if (!group_member)
  956. continue;
  957. if (group_member == caster)
  958. continue;
  959. client = (*target_itr)->client;
  960. has_effect = false;
  961. if (group_member->GetSpellEffect(spell->GetSpellID(), caster)) {
  962. has_effect = true;
  963. }
  964. if (!has_effect && (std::find(luaspell->removed_targets.begin(),
  965. luaspell->removed_targets.end(), group_member->GetID()) != luaspell->removed_targets.end())) {
  966. continue;
  967. }
  968. // Check if player is within range of the caster
  969. if (!rule_manager.GetGlobalRule(R_Spells, EnableCrossZoneGroupBuffs)->GetInt8() &&
  970. (group_member->GetZone() != caster->GetZone() || caster->GetDistance(group_member) > spell->GetSpellData()->radius)) {
  971. if (has_effect) {
  972. group_member->RemoveSpellEffect(luaspell);
  973. group_member->RemoveSpellBonus(luaspell);
  974. group_member->RemoveSkillBonus(spell->GetSpellID());
  975. if (client) {
  976. packet = ((Player*)group_member)->GetSkills()->GetSkillPacket(client->GetVersion());
  977. if (packet)
  978. client->QueuePacket(packet);
  979. }
  980. //Also remove group buffs from pet
  981. if (group_member->HasPet()) {
  982. pet = group_member->GetPet();
  983. charmed_pet = group_member->GetCharmedPet();
  984. if (pet) {
  985. pet->RemoveSpellEffect(luaspell);
  986. pet->RemoveSpellBonus(luaspell);
  987. }
  988. if (charmed_pet) {
  989. charmed_pet->RemoveSpellEffect(luaspell);
  990. charmed_pet->RemoveSpellBonus(luaspell);
  991. }
  992. }
  993. }
  994. continue;
  995. }
  996. if (group_member->GetZone() != caster->GetZone())
  997. {
  998. SpellProcess::AddSelfAndPetToCharTargets(luaspell, group_member);
  999. }
  1000. else
  1001. {
  1002. //this group member is a target of the spell
  1003. new_target_list.push_back(group_member->GetID());
  1004. }
  1005. if (has_effect)
  1006. continue;
  1007. pet = 0;
  1008. charmed_pet = 0;
  1009. if (group_member->HasPet()) {
  1010. pet = group_member->GetPet();
  1011. charmed_pet = group_member->GetCharmedPet();
  1012. }
  1013. group_member->AddSpellEffect(luaspell, luaspell->timer.GetRemainingTime() != 0 ? luaspell->timer.GetRemainingTime() : 0);
  1014. if (pet)
  1015. pet->AddSpellEffect(luaspell, luaspell->timer.GetRemainingTime() != 0 ? luaspell->timer.GetRemainingTime() : 0);
  1016. if (charmed_pet)
  1017. charmed_pet->AddSpellEffect(luaspell, luaspell->timer.GetRemainingTime() != 0 ? luaspell->timer.GetRemainingTime() : 0);
  1018. if (pet)
  1019. new_target_list.push_back(pet->GetID());
  1020. if (charmed_pet)
  1021. new_target_list.push_back(charmed_pet->GetID());
  1022. // look for a spell bonus on caster's spell
  1023. sb_list = caster->GetAllSpellBonuses(luaspell);
  1024. for (int32 x = 0; x < sb_list->size(); x++) {
  1025. bv = sb_list->at(x);
  1026. group_member->AddSpellBonus(luaspell, bv->type, bv->value, bv->class_req, bv->race_req, bv->faction_req);
  1027. if (pet)
  1028. pet->AddSpellBonus(luaspell, bv->type, bv->value, bv->class_req, bv->race_req, bv->faction_req);
  1029. if (charmed_pet)
  1030. charmed_pet->AddSpellBonus(luaspell, bv->type, bv->value, bv->class_req, bv->race_req, bv->faction_req);
  1031. }
  1032. sb_list->clear();
  1033. safe_delete(sb_list);
  1034. // look for a skill bonus on the caster's spell
  1035. sb = caster->GetSkillBonus(me[i].spell_id);
  1036. if (sb) {
  1037. for (itr_skills = sb->skills.begin(); itr_skills != sb->skills.end(); itr_skills++)
  1038. group_member->AddSkillBonus(sb->spell_id, (*itr_skills).second->skill_id, (*itr_skills).second->value);
  1039. }
  1040. if (client) {
  1041. packet = ((Player*)group_member)->GetSkills()->GetSkillPacket(client->GetVersion());
  1042. if (packet)
  1043. client->QueuePacket(packet);
  1044. }
  1045. }
  1046. luaspell->targets.swap(new_target_list);
  1047. SpellProcess::AddSelfAndPet(luaspell, caster);
  1048. luaspell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__);
  1049. new_target_list.clear();
  1050. }
  1051. }
  1052. caster->GetMaintainedMutex()->releasereadlock(__FUNCTION__, __LINE__);
  1053. }
  1054. }
  1055. }
  1056. bool PlayerGroupManager::IsInGroup(int32 group_id, Entity* member) {
  1057. std::shared_lock lock(MGroups);
  1058. bool ret = false;
  1059. if (m_groups.count(group_id) > 0) {
  1060. m_groups[group_id]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1061. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  1062. for (int8 i = 0; i < members->size(); i++) {
  1063. if (member == members->at(i)->member) {
  1064. ret = true;
  1065. break;
  1066. }
  1067. }
  1068. m_groups[group_id]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1069. }
  1070. return ret;
  1071. }
  1072. Entity* PlayerGroupManager::IsPlayerInGroup(int32 group_id, int32 character_id) {
  1073. std::shared_lock lock(MGroups);
  1074. Entity* ret = nullptr;
  1075. if (m_groups.count(group_id) > 0) {
  1076. m_groups[group_id]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1077. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  1078. for (int8 i = 0; i < members->size(); i++) {
  1079. if (members->at(i)->member && members->at(i)->member->IsPlayer() && character_id == ((Player*)members->at(i)->member)->GetCharacterID()) {
  1080. ret = members->at(i)->member;
  1081. break;
  1082. }
  1083. }
  1084. m_groups[group_id]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1085. }
  1086. return ret;
  1087. }
  1088. void PlayerGroupManager::SendPeerGroupData(std::string peerId) {
  1089. if (peerId.size() < 1) // must provide a peerId
  1090. return;
  1091. std::shared_lock lock(MGroups); // unique lock to avoid updates while we push to a new peer
  1092. map<int32, PlayerGroup*>::iterator itr;
  1093. for (itr = m_groups.begin(); itr != m_groups.end(); itr++) {
  1094. PlayerGroup* group = itr->second;
  1095. if (group) {
  1096. int32 groupID = group->GetID();
  1097. std::vector<int32> raidGroups;
  1098. group->GetRaidGroups(&raidGroups);
  1099. peer_manager.sendPeersNewGroupRequest("", 0, groupID, "", "", group->GetGroupOptions(), peerId, &raidGroups);
  1100. m_groups[groupID]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1101. deque<GroupMemberInfo*>* members = m_groups[groupID]->GetMembers();
  1102. for (int8 i = 0; i < members->size(); i++) {
  1103. GroupMemberInfo* info = members->at(i);
  1104. if (info)
  1105. peer_manager.sendPeersGroupMember(groupID, info, false, peerId);
  1106. }
  1107. m_groups[groupID]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1108. }
  1109. }
  1110. }
  1111. void PlayerGroup::RemoveClientReference(Client* remove) {
  1112. deque<GroupMemberInfo*>::iterator itr;
  1113. MGroupMembers.writelock();
  1114. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  1115. GroupMemberInfo* gmi = *itr;
  1116. if (gmi->client && gmi->client == remove)
  1117. {
  1118. gmi->client = 0;
  1119. gmi->member = 0;
  1120. break;
  1121. }
  1122. }
  1123. MGroupMembers.releasewritelock();
  1124. }
  1125. void PlayerGroup::UpdateGroupMemberInfo(Entity* ent, bool groupMembersLocked) {
  1126. Player* player = (Player*)ent;
  1127. if (!player || !player->GetGroupMemberInfo())
  1128. return;
  1129. if (!groupMembersLocked)
  1130. MGroupMembers.writelock();
  1131. GroupMemberInfo* group_member_info = player->GetGroupMemberInfo();
  1132. player->GetGroupMemberInfo()->class_id = player->GetAdventureClass();
  1133. group_member_info->hp_max = player->GetTotalHP();
  1134. group_member_info->hp_current = player->GetHP();
  1135. group_member_info->level_max = player->GetLevel();
  1136. group_member_info->level_current = player->GetLevel();
  1137. group_member_info->name = string(player->GetName());
  1138. group_member_info->power_current = player->GetPower();
  1139. group_member_info->power_max = player->GetTotalPower();
  1140. group_member_info->race_id = player->GetRace();
  1141. if (player->GetZone()) {
  1142. group_member_info->zone = player->GetZone()->GetZoneDescription();
  1143. group_member_info->zone_id = player->GetZone()->GetZoneID();
  1144. group_member_info->instance_id = player->GetZone()->GetInstanceID();
  1145. }
  1146. else {
  1147. group_member_info->zone = "Unknown";
  1148. group_member_info->zone_id = 0;
  1149. group_member_info->instance_id = 0;
  1150. }
  1151. peer_manager.sendPeersGroupMember(group_member_info->group_id, group_member_info, true);
  1152. if (!groupMembersLocked)
  1153. MGroupMembers.releasewritelock();
  1154. }
  1155. void PlayerGroup::GetRaidGroups(std::vector<int32>* groups) {
  1156. std::shared_lock lock(MRaidGroups);
  1157. if (groups)
  1158. groups->insert(groups->end(), m_raidgroups.begin(), m_raidgroups.end());
  1159. }
  1160. void PlayerGroup::ReplaceRaidGroups(std::vector<int32>* groups) {
  1161. std::unique_lock lock(MRaidGroups);
  1162. if (groups) {
  1163. m_raidgroups.clear();
  1164. m_raidgroups.insert(m_raidgroups.end(), groups->begin(), groups->end());
  1165. }
  1166. }
  1167. bool PlayerGroup::IsInRaidGroup(int32 groupID, bool isLeaderGroup) {
  1168. std::unique_lock lock(MRaidGroups);
  1169. if (isLeaderGroup) {
  1170. if (m_raidgroups.size() > 0) {
  1171. int32 group = m_raidgroups[0];
  1172. if (group == groupID)
  1173. return true;
  1174. }
  1175. }
  1176. else if (std::find(m_raidgroups.begin(), m_raidgroups.end(), groupID) != m_raidgroups.end()) {
  1177. return true;
  1178. }
  1179. return false;
  1180. }
  1181. void PlayerGroup::AddGroupToRaid(int32 groupID) {
  1182. std::unique_lock lock(MRaidGroups);
  1183. if (std::find(m_raidgroups.begin(), m_raidgroups.end(), groupID) == m_raidgroups.end()) {
  1184. m_raidgroups.push_back(groupID);
  1185. }
  1186. }
  1187. void PlayerGroup::RemoveGroupFromRaid(int32 groupID) {
  1188. std::unique_lock lock(MRaidGroups);
  1189. std::vector<int32>::iterator group_itr = std::find(m_raidgroups.begin(), m_raidgroups.end(), groupID);
  1190. if (group_itr != m_raidgroups.end()) {
  1191. m_raidgroups.erase(group_itr);
  1192. }
  1193. }
  1194. bool PlayerGroup::IsGroupRaid() {
  1195. std::unique_lock lock(MRaidGroups);
  1196. return (m_raidgroups.size() > 1);
  1197. }
  1198. void PlayerGroup::ClearGroupRaid() {
  1199. std::unique_lock lock(MRaidGroups);
  1200. m_raidgroups.clear();
  1201. }
  1202. void PlayerGroupManager::UpdateGroupMemberInfoFromPeer(int32 group_id, std::string name, bool is_client, GroupMemberInfo* updateinfo) {
  1203. std::shared_lock lock(MGroups);
  1204. if (m_groups.count(group_id) > 0) {
  1205. m_groups[group_id]->MGroupMembers.writelock(__FUNCTION__, __LINE__);
  1206. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  1207. for (int8 i = 0; i < members->size(); i++) {
  1208. GroupMemberInfo* curinfo = members->at(i);
  1209. if (curinfo && curinfo->name == name && curinfo->is_client == is_client) {
  1210. curinfo->class_id = updateinfo->class_id;
  1211. curinfo->hp_max = updateinfo->hp_max;
  1212. curinfo->hp_current = updateinfo->hp_current;
  1213. curinfo->level_max = updateinfo->level_max;
  1214. curinfo->level_current = updateinfo->level_current;
  1215. curinfo->name = updateinfo->name;
  1216. curinfo->power_current = updateinfo->power_current;
  1217. curinfo->power_max = updateinfo->power_max;
  1218. curinfo->race_id = updateinfo->race_id;
  1219. curinfo->zone = updateinfo->zone;
  1220. curinfo->mentor_target_char_id = updateinfo->mentor_target_char_id;
  1221. curinfo->is_client = updateinfo->is_client;
  1222. curinfo->leader = updateinfo->leader;
  1223. curinfo->client_peer_address = updateinfo->client_peer_address;
  1224. curinfo->client_peer_port = updateinfo->client_peer_port;
  1225. curinfo->is_raid_looter = updateinfo->is_raid_looter;
  1226. break;
  1227. }
  1228. }
  1229. m_groups[group_id]->MGroupMembers.releasewritelock(__FUNCTION__, __LINE__);
  1230. }
  1231. }
  1232. void PlayerGroupManager::ClearGroupRaid(int32 groupID) {
  1233. std::shared_lock lock(MGroups);
  1234. // Check to see if the id is in the list
  1235. if (m_groups.count(groupID) > 0) {
  1236. m_groups[groupID]->ClearGroupRaid();
  1237. }
  1238. SendGroupUpdate(groupID);
  1239. }
  1240. void PlayerGroupManager::RemoveGroupFromRaid(int32 groupID, int32 targetGroupID) {
  1241. std::shared_lock lock(MGroups);
  1242. // Check to see if the id is in the list
  1243. if (m_groups.count(groupID) > 0) {
  1244. // Get a pointer to the group
  1245. PlayerGroup* group = m_groups[groupID];
  1246. std::vector<int32> raidGroups;
  1247. m_groups[groupID]->GetRaidGroups(&raidGroups);
  1248. if (raidGroups.size() > 0) {
  1249. std::vector<int32>::iterator group_itr;
  1250. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end(); group_itr++) {
  1251. if (m_groups.count((*group_itr))) {
  1252. m_groups[(*group_itr)]->RemoveGroupFromRaid(targetGroupID);
  1253. }
  1254. }
  1255. }
  1256. }
  1257. }
  1258. bool PlayerGroupManager::IsInRaidGroup(int32 groupID, int32 targetGroupID, bool isLeaderGroup) {
  1259. std::shared_lock lock(MGroups);
  1260. if (m_groups.count(groupID))
  1261. return m_groups[groupID]->IsInRaidGroup(targetGroupID, isLeaderGroup);
  1262. return false;
  1263. }
  1264. bool PlayerGroupManager::GetDefaultGroupOptions(int32 groupID, GroupOptions* options) {
  1265. std::shared_lock lock(MGroups);
  1266. if (m_groups.count(groupID))
  1267. return m_groups[groupID]->GetDefaultGroupOptions(options);
  1268. return false;
  1269. }
  1270. void PlayerGroupManager::GetRaidGroups(int32 groupID, std::vector<int32>* newGroups) {
  1271. std::shared_lock lock(MGroups);
  1272. if (m_groups.count(groupID))
  1273. m_groups[groupID]->GetRaidGroups(newGroups);
  1274. }
  1275. void PlayerGroupManager::ReplaceRaidGroups(int32 groupID, std::vector<int32>* newGroups) {
  1276. std::shared_lock lock(MGroups);
  1277. if (m_groups.count(groupID))
  1278. m_groups[groupID]->ReplaceRaidGroups(newGroups);
  1279. SendGroupUpdate(groupID);
  1280. }
  1281. void PlayerGroupManager::SetGroupOptions(int32 groupID, GroupOptions* options) {
  1282. std::shared_lock lock(MGroups);
  1283. if (m_groups.count(groupID))
  1284. m_groups[groupID]->SetDefaultGroupOptions(options);
  1285. }
  1286. void PlayerGroupManager::SendWhoGroupMembers(Client* client, int32 groupID) {
  1287. std::shared_lock lock(MGroups);
  1288. if (m_groups.count(groupID) > 0) {
  1289. PacketStruct* packet = configReader.getStruct("WS_WhoQueryReply", client->GetVersion());
  1290. if (packet) {
  1291. packet->setDataByName("account_id", client->GetAccountID());
  1292. packet->setDataByName("unknown", 0xFFFFFFFF);
  1293. int8 num_characters = 0;
  1294. m_groups[groupID]->MGroupMembers.writelock(__FUNCTION__, __LINE__);
  1295. deque<GroupMemberInfo*>* members = m_groups[groupID]->GetMembers();
  1296. for (int8 i = 0; i < members->size(); i++) {
  1297. GroupMemberInfo* curinfo = members->at(i);
  1298. if (curinfo && curinfo->name.size() > 0) {
  1299. num_characters++;
  1300. }
  1301. }
  1302. packet->setDataByName("response", 2);
  1303. packet->setArrayLengthByName("num_characters", (int8)num_characters);
  1304. for (int8 i = 0; i < members->size(); i++) {
  1305. GroupMemberInfo* curinfo = members->at(i);
  1306. if (curinfo && curinfo->name.size() > 0) {
  1307. packet->setArrayDataByName("char_name", curinfo->name.c_str(), i);
  1308. packet->setArrayDataByName("level", curinfo->level_current, i);
  1309. packet->setArrayDataByName("class", curinfo->class_id, i);
  1310. packet->setArrayDataByName("unknown4", 0xFF, i); //probably tradeskill class
  1311. packet->setArrayDataByName("race", curinfo->race_id, i);
  1312. packet->setArrayDataByName("zone", curinfo->zone.c_str(), i);
  1313. }
  1314. }
  1315. client->QueuePacket(packet->serialize());
  1316. safe_delete(packet);
  1317. }
  1318. m_groups[groupID]->MGroupMembers.releasewritelock(__FUNCTION__, __LINE__);
  1319. }
  1320. }
  1321. void PlayerGroupManager::SendWhoRaidMembers(Client* client, int32 groupID) {
  1322. std::shared_lock lock(MGroups);
  1323. PlayerGroup* group = nullptr;
  1324. if (m_groups.count(groupID))
  1325. group = m_groups[groupID];
  1326. std::vector<int32> groups;
  1327. std::vector<int32>::iterator group_itr;
  1328. if (group)
  1329. group->GetRaidGroups(&groups);
  1330. if (groups.size() > 0) {
  1331. PacketStruct* packet = configReader.getStruct("WS_WhoQueryReply", client->GetVersion());
  1332. if (packet) {
  1333. packet->setDataByName("account_id", client->GetAccountID());
  1334. packet->setDataByName("unknown", 0xFFFFFFFF);
  1335. int8 num_characters = 0;
  1336. for (group_itr = groups.begin(); group_itr != groups.end(); group_itr++) {
  1337. if (m_groups.count((*group_itr))) {
  1338. // we will release this lock after we submit the data out below in the second group_itr
  1339. m_groups[(*group_itr)]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1340. deque<GroupMemberInfo*>* members = m_groups[(*group_itr)]->GetMembers();
  1341. for (int8 i = 0; i < members->size(); i++) {
  1342. GroupMemberInfo* curinfo = members->at(i);
  1343. if (curinfo && curinfo->name.size() > 0) {
  1344. num_characters++;
  1345. }
  1346. }
  1347. }
  1348. }
  1349. packet->setDataByName("response", 2);
  1350. packet->setArrayLengthByName("num_characters", (int8)num_characters);
  1351. int8 pos = 0;
  1352. for (group_itr = groups.begin(); group_itr != groups.end(); group_itr++) {
  1353. if (m_groups.count((*group_itr))) {
  1354. deque<GroupMemberInfo*>* members = m_groups[(*group_itr)]->GetMembers();
  1355. for (int8 i = 0; i < members->size(); i++) {
  1356. GroupMemberInfo* curinfo = members->at(i);
  1357. if (curinfo && curinfo->name.size() > 0) {
  1358. packet->setArrayDataByName("char_name", curinfo->name.c_str(), pos);
  1359. packet->setArrayDataByName("level", curinfo->level_current, pos);
  1360. packet->setArrayDataByName("class", curinfo->class_id, pos);
  1361. packet->setArrayDataByName("unknown4", 0xFF, pos); //probably tradeskill class
  1362. packet->setArrayDataByName("race", curinfo->race_id, pos);
  1363. packet->setArrayDataByName("zone", curinfo->zone.c_str(), pos);
  1364. pos++;
  1365. }
  1366. }
  1367. // release previously established lock during the count
  1368. m_groups[(*group_itr)]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1369. }
  1370. }
  1371. client->QueuePacket(packet->serialize());
  1372. safe_delete(packet);
  1373. }
  1374. }
  1375. else {
  1376. client->SimpleMessage(CHANNEL_COLOR_RED, "You are not currently in a raid.");
  1377. }
  1378. }
  1379. int8 PlayerGroupManager::AcceptRaidInvite(std::string acceptorName, int32 groupID) {
  1380. std::unique_lock lock(MGroups);
  1381. std::string raidLeaderName("");
  1382. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  1383. bool inviteAccept = true;
  1384. if (m_raidPendingInvites.count(acceptorName.c_str()) > 0) {
  1385. raidLeaderName = m_raidPendingInvites[acceptorName.c_str()];
  1386. m_raidPendingInvites.erase(acceptorName.c_str());
  1387. }
  1388. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  1389. if (raidLeaderName.size() < 1)
  1390. return 0;
  1391. Client* client_leader = zone_list.GetClientByCharName(raidLeaderName.c_str());
  1392. if (client_leader) {
  1393. if (client_leader->GetPlayer()->GetGroupMemberInfo() && m_groups.count(groupID) && m_groups.count(client_leader->GetPlayer()->GetGroupMemberInfo()->group_id)) {
  1394. Player* player = client_leader->GetPlayer();
  1395. PlayerGroup* spawn_group = m_groups[groupID];
  1396. PlayerGroup* player_group = m_groups[player->GetGroupMemberInfo()->group_id];
  1397. if (spawn_group && player_group) {
  1398. std::vector<int32> groups;
  1399. spawn_group->GetRaidGroups(&groups);
  1400. if (groups.size() > 0) {
  1401. return 0;
  1402. }
  1403. player_group->GetRaidGroups(&groups);
  1404. if (groups.size() > 3) {
  1405. return 0;
  1406. }
  1407. spawn_group->SetDefaultGroupOptions(player_group->GetGroupOptions());
  1408. if (groups.size() < 1) {
  1409. player_group->AddGroupToRaid(player_group->GetID());
  1410. player_group->AddGroupToRaid(spawn_group->GetID());
  1411. player_group->GetRaidGroups(&groups);
  1412. spawn_group->ReplaceRaidGroups(&groups);
  1413. return 1;
  1414. }
  1415. else {
  1416. groups.clear();
  1417. player_group->AddGroupToRaid(spawn_group->GetID());
  1418. player_group->GetRaidGroups(&groups);
  1419. std::vector<int32>::iterator group_itr;
  1420. for (group_itr = groups.begin(); group_itr != groups.end(); group_itr++) {
  1421. int32 cur_group_id = (*group_itr);
  1422. if (cur_group_id == player_group->GetID() || m_groups.count(cur_group_id) < 1) // we already set the player_group above, skip
  1423. continue;
  1424. PlayerGroup* temp_group = m_groups[cur_group_id];
  1425. temp_group->ReplaceRaidGroups(&groups);
  1426. }
  1427. return 1;
  1428. }
  1429. }
  1430. }
  1431. }
  1432. else {
  1433. // must be somewhere else in the world
  1434. }
  1435. return 0;
  1436. }
  1437. bool PlayerGroupManager::SendRaidInvite(Client* sender, Entity* target) {
  1438. std::shared_lock lock(MGroups);
  1439. if (!sender || !target)
  1440. return false;
  1441. if (!target->IsPlayer() || !((Player*)target)->GetClient() || !target->GetGroupMemberInfo() || !sender->GetPlayer()->GetGroupMemberInfo())
  1442. return false;
  1443. Player* player = sender->GetPlayer();
  1444. int32 spawn_group_id = target->GetGroupMemberInfo()->group_id;
  1445. if (m_groups.count(spawn_group_id) < 1)
  1446. return false;
  1447. PlayerGroup* spawn_group = m_groups[spawn_group_id];
  1448. int32 player_group_id = player->GetGroupMemberInfo() ? player->GetGroupMemberInfo()->group_id : 0;
  1449. PlayerGroup* player_group = nullptr;
  1450. if (m_groups.count(player_group_id))
  1451. player_group = m_groups[player_group_id];
  1452. // check if already invited
  1453. if (spawn_group && !player->IsGroupMember((Player*)target) && !spawn_group->IsGroupRaid() && player_group && player->GetGroupMemberInfo()->leader
  1454. && (!player_group->IsInRaidGroup(spawn_group_id) || player_group->IsInRaidGroup(player_group_id, true))) {
  1455. std::string leader = spawn_group->GetLeaderName();
  1456. std::vector<int32> groups;
  1457. player_group->GetRaidGroups(&groups);
  1458. if (groups.size() > 3) {
  1459. sender->SimpleMessage(CHANNEL_COLOR_RED, "You are currently in a full raid.");
  1460. return false;
  1461. }
  1462. if (leader.size() < 1) {
  1463. sender->SimpleMessage(CHANNEL_COLOR_RED, "Your target has no leader.");
  1464. return false;
  1465. }
  1466. MPendingInvites.readlock(__FUNCTION__, __LINE__);
  1467. bool inviteAccept = true;
  1468. if (m_raidPendingInvites.count(leader.c_str()) > 0) {
  1469. inviteAccept = false;
  1470. sender->SimpleMessage(CHANNEL_COLOR_RED, "Leader of the other group has a pending raid invite.");
  1471. }
  1472. MPendingInvites.releasereadlock(__FUNCTION__, __LINE__);
  1473. if (!inviteAccept)
  1474. return false;
  1475. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  1476. m_raidPendingInvites[leader] = player->GetGroupMemberInfo()->name.c_str();
  1477. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  1478. sender->SendReceiveOffer(((Player*)target)->GetClient(), 3, std::string(sender->GetPlayer()->GetName()), 1);
  1479. return true;
  1480. }
  1481. return false;
  1482. }
  1483. void PlayerGroupManager::SplitWithGroupOrRaid(Client* client, int32 coin_plat, int32 coin_gold, int32 coin_silver, int32 coin_copper) {
  1484. std::shared_lock lock(MGroups);
  1485. bool startWithLooter = true;
  1486. if (!client->GetPlayer()->GetGroupMemberInfo())
  1487. return;
  1488. if (!coin_plat && !coin_gold && !coin_silver && !coin_copper)
  1489. return;
  1490. if (client->GetPlayer()->GetInfoStruct()->get_coin_plat() < coin_plat &&
  1491. client->GetPlayer()->GetInfoStruct()->get_coin_gold() < coin_gold &&
  1492. client->GetPlayer()->GetInfoStruct()->get_coin_silver() < coin_silver &&
  1493. client->GetPlayer()->GetInfoStruct()->get_coin_copper() < coin_copper) {
  1494. // lacking coin
  1495. return;
  1496. }
  1497. int32 groupID = client->GetPlayer()->GetGroupMemberInfo()->group_id;
  1498. if (m_groups.count(groupID) < 1) {
  1499. return;
  1500. }
  1501. PlayerGroup* group = m_groups[groupID];
  1502. if (group)
  1503. {
  1504. bool isLeadGroup = group->IsInRaidGroup(group->GetID(), true);
  1505. bool isInRaid = group->IsInRaidGroup(group->GetID());
  1506. std::vector<int32> raidGroups;
  1507. group->GetRaidGroups(&raidGroups);
  1508. if (!isInRaid && raidGroups.size() < 1) {
  1509. raidGroups.push_back(group->GetID());
  1510. }
  1511. std::vector<int32>::iterator group_itr;
  1512. int32 split_coin_per_player = 0;
  1513. int32 actual_coins = coin_plat * 1000000 + coin_gold * 10000 + coin_silver * 100 + coin_copper;
  1514. int32 coins_remain_after_split = actual_coins;
  1515. int32 total_coins = actual_coins;
  1516. bool foundLooterResetRaidRun = false;
  1517. int8 members_in_zone = 0;
  1518. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end(); group_itr++) {
  1519. group = m_groups[(*group_itr)];
  1520. if (!group)
  1521. continue;
  1522. group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1523. deque<GroupMemberInfo*>* members = group->GetMembers();
  1524. for (int8 i = 0; i < members->size(); i++) {
  1525. Entity* member = members->at(i)->member;
  1526. if (!member || !member->IsPlayer())
  1527. continue;
  1528. if (member->GetZone() != client->GetPlayer()->GetZone())
  1529. continue;
  1530. members_in_zone++;
  1531. }
  1532. group->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1533. }
  1534. if (members_in_zone < 1) // this should not happen, but divide by zero checked
  1535. members_in_zone = 1;
  1536. split_coin_per_player = actual_coins / members_in_zone;
  1537. coins_remain_after_split = actual_coins - (split_coin_per_player * members_in_zone);
  1538. // try to individually take each tier of coin and not split the coin in inventory
  1539. client->GetPlayer()->GetInfoStruct()->set_coin_plat(client->GetPlayer()->GetInfoStruct()->get_coin_plat() - coin_plat);
  1540. client->GetPlayer()->GetInfoStruct()->set_coin_gold(client->GetPlayer()->GetInfoStruct()->get_coin_gold() - coin_gold);
  1541. client->GetPlayer()->GetInfoStruct()->set_coin_silver(client->GetPlayer()->GetInfoStruct()->get_coin_silver() - coin_silver);
  1542. client->GetPlayer()->GetInfoStruct()->set_coin_copper(client->GetPlayer()->GetInfoStruct()->get_coin_copper() - coin_copper);
  1543. int32 lootGroup = 0;
  1544. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end();) {
  1545. group = m_groups[(*group_itr)];
  1546. if (!group)
  1547. continue;
  1548. isLeadGroup = group->IsInRaidGroup((*group_itr), true);
  1549. group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1550. deque<GroupMemberInfo*>* members = group->GetMembers();
  1551. LogWrite(LOOT__INFO, 0, "Loot", "%s: Group SplitWithGroupOrRaid, split coin per player %u, remaining coin after split %u", client->GetPlayer()->GetName(), split_coin_per_player, coins_remain_after_split);
  1552. for (int8 i = 0; i < members->size(); i++) {
  1553. Entity* member = members->at(i)->member;
  1554. if (!member || !member->IsPlayer())
  1555. continue;
  1556. if (member->GetZone() != client->GetPlayer()->GetZone())
  1557. continue;
  1558. // this will make sure we properly send the loot window to the initial requester if there is no item rarity matches
  1559. if (startWithLooter && member != client->GetPlayer())
  1560. continue;
  1561. else if (!startWithLooter && member == client->GetPlayer())
  1562. continue;
  1563. int32 coin_recv = 0;
  1564. if (member == client->GetPlayer() && (split_coin_per_player + coins_remain_after_split) > 0) {
  1565. coin_recv = split_coin_per_player + coins_remain_after_split;
  1566. ((Player*)member)->AddCoins(split_coin_per_player + coins_remain_after_split);
  1567. if (coins_remain_after_split > 0) // overflow of coin division went to the first player
  1568. coins_remain_after_split = 0;
  1569. }
  1570. else if (split_coin_per_player > 0) {
  1571. coin_recv = split_coin_per_player;
  1572. ((Player*)member)->AddCoins(split_coin_per_player);
  1573. }
  1574. if (coin_recv && ((Player*)member)->GetClient()) {
  1575. ((Player*)member)->GetClient()->Message(CHANNEL_MONEY_SPLIT, "Your share of the %s split from %s is %s.", client->GetCoinMessage(total_coins).c_str(), client->GetPlayer()->GetName(), client->GetCoinMessage(coin_recv).c_str());
  1576. }
  1577. if (startWithLooter) {
  1578. startWithLooter = false;
  1579. foundLooterResetRaidRun = true; // we got it, shouldn't hit this again
  1580. break;
  1581. }
  1582. }
  1583. group->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1584. if (foundLooterResetRaidRun) {
  1585. group_itr = raidGroups.begin();
  1586. foundLooterResetRaidRun = false; // disable running it again
  1587. }
  1588. else
  1589. group_itr++;
  1590. } // end raid groups
  1591. } // end group
  1592. }
  1593. bool PlayerGroupManager::IdentifyMemberInGroupOrRaid(ZoneChangeDetails* details, Client* client, int32 zoneID, int32 instanceID) {
  1594. std::shared_lock lock(MGroups);
  1595. ZoneServer* ret = nullptr;
  1596. PlayerGroup* group = nullptr;
  1597. bool succeed = false;
  1598. if (client->GetPlayer()->GetGroupMemberInfo() && m_groups.count(client->GetPlayer()->GetGroupMemberInfo()->group_id))
  1599. group = m_groups[client->GetPlayer()->GetGroupMemberInfo()->group_id];
  1600. else
  1601. return false;
  1602. std::vector<int32> raidGroups;
  1603. std::vector<int32>::iterator group_itr;
  1604. if (group)
  1605. group->GetRaidGroups(&raidGroups);
  1606. group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1607. deque<GroupMemberInfo*>* members = group->GetMembers();
  1608. deque<GroupMemberInfo*>::iterator itr;
  1609. for (itr = members->begin(); itr != members->end(); itr++) {
  1610. // If a group member matches a target
  1611. if ((*itr)->is_client && (*itr)->member && (*itr)->member->GetZone() && (*itr)->zone_id == zoneID && (*itr)->instance_id == instanceID) {
  1612. // toggle the flag and break the loop
  1613. ret = (*itr)->member->GetZone();
  1614. break;
  1615. }
  1616. else if ((*itr)->is_client && (*itr)->zone_id == zoneID && (*itr)->instance_id == instanceID) {
  1617. // toggle the flag and break the loop
  1618. std::string id = peer_manager.isPeer((*itr)->client_peer_address, (*itr)->client_peer_port);
  1619. std::shared_ptr<Peer> peer = peer_manager.getPeerById(id);
  1620. if (peer) {
  1621. ZoneServer* tmp = new ZoneServer((*itr)->zone.c_str());
  1622. database.LoadZoneInfo(tmp);
  1623. peer_manager.setZonePeerData(details, peer->id, peer->worldAddr, peer->internalWorldAddr, peer->worldPort, peer->webAddr, peer->webPort, std::string(tmp->GetZoneFile()), std::string(tmp->GetZoneName()), tmp->GetZoneID(),
  1624. tmp->GetInstanceID(), tmp->GetSafeX(), tmp->GetSafeY(), tmp->GetSafeZ(), tmp->GetSafeHeading(),
  1625. tmp->GetZoneLockState(), tmp->GetMinimumStatus(), tmp->GetMinimumLevel(), tmp->GetMaximumLevel(),
  1626. tmp->GetMinimumVersion(), tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime(),
  1627. tmp->GetInstanceType(), tmp->NumPlayers());
  1628. safe_delete(tmp);
  1629. succeed = true;
  1630. break;
  1631. }
  1632. }
  1633. }
  1634. group->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1635. if (succeed) {
  1636. return true;
  1637. }
  1638. else if (ret) {
  1639. peer_manager.setZonePeerDataSelf(details, std::string(ret->GetZoneFile()), std::string(ret->GetZoneName()),
  1640. ret->GetZoneID(), ret->GetInstanceID(), ret->GetSafeX(), ret->GetSafeY(),
  1641. ret->GetSafeZ(), ret->GetSafeHeading(), ret->GetZoneLockState(),
  1642. ret->GetMinimumStatus(), ret->GetMinimumLevel(), ret->GetMaximumLevel(),
  1643. ret->GetMinimumVersion(), ret->GetDefaultLockoutTime(), ret->GetDefaultReenterTime(),
  1644. ret->GetInstanceType(), ret->NumPlayers(), ret);
  1645. return true;
  1646. }
  1647. for (group_itr = raidGroups.begin(); group_itr != raidGroups.end(); group_itr++) {
  1648. if (m_groups.count((*group_itr))) {
  1649. group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1650. deque<GroupMemberInfo*>* members = group->GetMembers();
  1651. deque<GroupMemberInfo*>::iterator itr;
  1652. for (itr = members->begin(); itr != members->end(); itr++) {
  1653. // If a group member matches a target
  1654. if ((*itr)->is_client && (*itr)->zone_id == zoneID && (*itr)->instance_id == instanceID) {
  1655. // toggle the flag and break the loop
  1656. std::string id = peer_manager.isPeer((*itr)->client_peer_address, (*itr)->client_peer_port);
  1657. std::shared_ptr<Peer> peer = peer_manager.getPeerById(id);
  1658. if (peer) {
  1659. ZoneServer* tmp = new ZoneServer((*itr)->zone.c_str());
  1660. database.LoadZoneInfo(tmp);
  1661. peer_manager.setZonePeerData(details, peer->id, peer->worldAddr, peer->internalWorldAddr, peer->worldPort, peer->webAddr, peer->webPort, std::string(tmp->GetZoneFile()), std::string(tmp->GetZoneName()), tmp->GetZoneID(),
  1662. tmp->GetInstanceID(), tmp->GetSafeX(), tmp->GetSafeY(), tmp->GetSafeZ(), tmp->GetSafeHeading(),
  1663. tmp->GetZoneLockState(), tmp->GetMinimumStatus(), tmp->GetMinimumLevel(), tmp->GetMaximumLevel(),
  1664. tmp->GetMinimumVersion(), tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime(),
  1665. tmp->GetInstanceType(), tmp->NumPlayers());
  1666. safe_delete(tmp);
  1667. succeed = true;
  1668. break;
  1669. }
  1670. }
  1671. }
  1672. group->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1673. if (succeed)
  1674. break;
  1675. }
  1676. }
  1677. return succeed;
  1678. }
  1679. void PlayerGroupManager::ClearGroupRaidLooterFlag(int32 groupID) {
  1680. std::shared_lock lock(MGroups);
  1681. if (m_groups.count(groupID) > 0) {
  1682. m_groups[groupID]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  1683. deque<GroupMemberInfo*>* members = m_groups[groupID]->GetMembers();
  1684. for (int8 i = 0; i < members->size(); i++) {
  1685. GroupMemberInfo* curinfo = members->at(i);
  1686. if (curinfo) {
  1687. curinfo->is_raid_looter = false;
  1688. }
  1689. }
  1690. m_groups[groupID]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  1691. }
  1692. }
  1693. Entity* PlayerGroup::GetGroupMemberByPosition(Entity* seeker, int32 mapped_position) {
  1694. Entity* ret = nullptr;
  1695. deque<GroupMemberInfo*>::iterator itr;
  1696. MGroupMembers.readlock();
  1697. int32 count = 1;
  1698. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  1699. if ((*itr)->member == seeker) {
  1700. continue;
  1701. }
  1702. count++;
  1703. if (count >= mapped_position) {
  1704. ret = (Entity*)(*itr)->member;
  1705. break;
  1706. }
  1707. }
  1708. MGroupMembers.releasereadlock();
  1709. return ret;
  1710. }
  1711. void PlayerGroup::SetDefaultGroupOptions(GroupOptions* options) {
  1712. MGroupMembers.writelock();
  1713. if (options != nullptr) {
  1714. group_options.loot_method = options->loot_method;
  1715. group_options.loot_items_rarity = options->loot_items_rarity;
  1716. group_options.auto_split = options->auto_split;
  1717. group_options.default_yell = options->default_yell;
  1718. group_options.group_lock_method = options->group_lock_method;
  1719. group_options.group_autolock = options->group_autolock;
  1720. group_options.solo_autolock = options->solo_autolock;
  1721. group_options.auto_loot_method = options->auto_loot_method;
  1722. }
  1723. else {
  1724. group_options.loot_method = 1;
  1725. group_options.loot_items_rarity = 0;
  1726. group_options.auto_split = 1;
  1727. group_options.default_yell = 1;
  1728. group_options.group_lock_method = 0;
  1729. group_options.group_autolock = 0;
  1730. group_options.solo_autolock = 0;
  1731. group_options.auto_loot_method = 0;
  1732. group_options.last_looted_index = 0;
  1733. }
  1734. MGroupMembers.releasewritelock();
  1735. }
  1736. bool PlayerGroup::GetDefaultGroupOptions(GroupOptions* options) {
  1737. bool setOptions = false;
  1738. MGroupMembers.readlock();
  1739. if (options != nullptr) {
  1740. options->loot_method = group_options.loot_method;
  1741. options->loot_items_rarity = group_options.loot_items_rarity;
  1742. options->auto_split = group_options.auto_split;
  1743. options->default_yell = group_options.default_yell;
  1744. options->group_lock_method = group_options.group_lock_method;
  1745. options->group_autolock = group_options.group_autolock;
  1746. options->solo_autolock = group_options.solo_autolock;
  1747. options->auto_loot_method = group_options.auto_loot_method;
  1748. setOptions = true;
  1749. }
  1750. MGroupMembers.releasereadlock();
  1751. return setOptions;
  1752. }