PlayerGroups.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  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. extern ZoneList zone_list;
  25. extern RuleManager rule_manager;
  26. /******************************************************** PlayerGroup ********************************************************/
  27. PlayerGroup::PlayerGroup(int32 id) {
  28. m_id = id;
  29. MGroupMembers.SetName("MGroupMembers");
  30. SetDefaultGroupOptions();
  31. }
  32. PlayerGroup::~PlayerGroup() {
  33. Disband();
  34. }
  35. bool PlayerGroup::AddMember(Entity* member) {
  36. // Check to make sure the entity we are adding is valid
  37. if (!member) {
  38. LogWrite(GROUP__ERROR, 0, "Group", "New member is null");
  39. return false;
  40. }
  41. // Make sure entity we are adding isn't already in a group by checking if it has a GroupMemberInfo pointer
  42. if (member->GetGroupMemberInfo()) {
  43. LogWrite(GROUP__ERROR, 0, "Group", "New member (%s) already has a group", member->GetName());
  44. return false;
  45. }
  46. // Create a new GroupMemberInfo and assign it to the new member
  47. GroupMemberInfo* gmi = new GroupMemberInfo;
  48. gmi->group_id = m_id;
  49. gmi->member = member;
  50. gmi->leader = false;
  51. if (member->IsPlayer())
  52. gmi->client = ((Player*)member)->GetClient();
  53. else
  54. gmi->client = 0;
  55. gmi->mentor_target_char_id = 0;
  56. member->SetGroupMemberInfo(gmi);
  57. member->group_id = gmi->group_id;
  58. MGroupMembers.writelock();
  59. m_members.push_back(gmi);
  60. member->UpdateGroupMemberInfo(true, true);
  61. MGroupMembers.releasewritelock();
  62. SendGroupUpdate();
  63. return true;
  64. }
  65. bool PlayerGroup::RemoveMember(Entity* member) {
  66. GroupMemberInfo* gmi = member->GetGroupMemberInfo();
  67. if (!gmi) {
  68. return false;
  69. }
  70. bool ret = false;
  71. MGroupMembers.writelock();
  72. member->SetGroupMemberInfo(0);
  73. deque<GroupMemberInfo*>::iterator erase_itr = m_members.end();
  74. deque<GroupMemberInfo*>::iterator itr;
  75. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  76. if (gmi == *itr)
  77. erase_itr = itr;
  78. if(member->IsPlayer() && (*itr)->mentor_target_char_id == ((Player*)member)->GetCharacterID() && (*itr)->client)
  79. {
  80. (*itr)->mentor_target_char_id = 0;
  81. (*itr)->client->GetPlayer()->EnableResetMentorship();
  82. }
  83. if ((*itr)->client)
  84. (*itr)->client->GetPlayer()->SetCharSheetChanged(true);
  85. }
  86. if (erase_itr != m_members.end()) {
  87. ret = true;
  88. m_members.erase(erase_itr);
  89. }
  90. MGroupMembers.releasewritelock();
  91. member->SetGroupMemberInfo(nullptr);
  92. safe_delete(gmi);
  93. if (member->IsBot())
  94. ((Bot*)member)->Camp();
  95. return ret;
  96. }
  97. void PlayerGroup::Disband() {
  98. deque<GroupMemberInfo*>::iterator itr;
  99. MGroupMembers.writelock();
  100. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  101. if ((*itr)->member) {
  102. (*itr)->member->SetGroupMemberInfo(0);
  103. if ((*itr)->member->IsBot())
  104. ((Bot*)(*itr)->member)->Camp();
  105. }
  106. if((*itr)->mentor_target_char_id && (*itr)->client)
  107. {
  108. (*itr)->mentor_target_char_id = 0;
  109. (*itr)->client->GetPlayer()->EnableResetMentorship();
  110. }
  111. if ((*itr)->client)
  112. (*itr)->client->GetPlayer()->SetCharSheetChanged(true);
  113. safe_delete(*itr);
  114. }
  115. m_members.clear();
  116. MGroupMembers.releasewritelock();
  117. }
  118. void PlayerGroup::SendGroupUpdate(Client* exclude) {
  119. deque<GroupMemberInfo*>::iterator itr;
  120. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  121. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  122. GroupMemberInfo* gmi = *itr;
  123. if (gmi->client && gmi->client != exclude && !gmi->client->IsZoning())
  124. gmi->client->GetPlayer()->SetCharSheetChanged(true);
  125. }
  126. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  127. }
  128. void PlayerGroup::SimpleGroupMessage(const char* message) {
  129. deque<GroupMemberInfo*>::iterator itr;
  130. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  131. for(itr = m_members.begin(); itr != m_members.end(); itr++) {
  132. GroupMemberInfo* info = *itr;
  133. if(info->client)
  134. info->client->SimpleMessage(CHANNEL_GROUP_CHAT, message);
  135. }
  136. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  137. }
  138. void PlayerGroup::SendGroupMessage(int8 type, const char* message, ...) {
  139. va_list argptr;
  140. char buffer[4096];
  141. buffer[0] = 0;
  142. va_start(argptr, message);
  143. vsnprintf(buffer, sizeof(buffer), message, argptr);
  144. va_end(argptr);
  145. deque<GroupMemberInfo*>::iterator itr;
  146. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  147. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  148. GroupMemberInfo* info = *itr;
  149. if (info->client)
  150. info->client->SimpleMessage(type, buffer);
  151. }
  152. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  153. }
  154. void PlayerGroup::GroupChatMessage(Spawn* from, int32 language, const char* message) {
  155. deque<GroupMemberInfo*>::iterator itr;
  156. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  157. for(itr = m_members.begin(); itr != m_members.end(); itr++) {
  158. GroupMemberInfo* info = *itr;
  159. if(info && info->client && info->client->GetCurrentZone())
  160. info->client->GetCurrentZone()->HandleChatMessage(info->client, from, 0, CHANNEL_GROUP_SAY, message, 0, 0, true, language);
  161. }
  162. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  163. }
  164. bool PlayerGroup::MakeLeader(Entity* new_leader) {
  165. deque<GroupMemberInfo*>::iterator itr;
  166. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  167. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  168. GroupMemberInfo* info = *itr;
  169. if (info->leader) {
  170. info->leader = false;
  171. break;
  172. }
  173. }
  174. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  175. new_leader->GetGroupMemberInfo()->leader = true;
  176. SendGroupUpdate();
  177. return true;
  178. }
  179. bool PlayerGroup::ShareQuestWithGroup(Client* quest_sharer, Quest* quest) {
  180. if(!quest || !quest_sharer)
  181. return false;
  182. bool canShare = quest->CanShareQuestCriteria(quest_sharer);
  183. if(!canShare) {
  184. return false;
  185. }
  186. deque<GroupMemberInfo*>::iterator itr;
  187. MGroupMembers.readlock(__FUNCTION__, __LINE__);
  188. for(itr = m_members.begin(); itr != m_members.end(); itr++) {
  189. GroupMemberInfo* info = *itr;
  190. if(info && info->client && info->client->GetCurrentZone()) {
  191. if( quest_sharer != info->client && info->client->GetPlayer()->HasAnyQuest(quest->GetQuestID()) == 0 ) {
  192. info->client->AddPendingQuest(new Quest(quest));
  193. info->client->Message(CHANNEL_COLOR_YELLOW, "%s has shared the quest %s with you.", quest_sharer->GetPlayer()->GetName(), quest->GetName());
  194. }
  195. }
  196. }
  197. MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  198. return true;
  199. }
  200. /******************************************************** PlayerGroupManager ********************************************************/
  201. PlayerGroupManager::PlayerGroupManager() {
  202. m_nextGroupID = 1;
  203. MPendingInvites.SetName("PlayerGroupManager::m_pendingInvites");
  204. }
  205. PlayerGroupManager::~PlayerGroupManager() {
  206. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  207. m_pendingInvites.clear();
  208. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  209. std::unique_lock lock(MGroups);
  210. map<int32, PlayerGroup*>::iterator itr;
  211. for (itr = m_groups.begin(); itr != m_groups.end(); itr++)
  212. safe_delete(itr->second);
  213. m_groups.clear();
  214. }
  215. bool PlayerGroupManager::AddGroupMember(int32 group_id, Entity* member) {
  216. std::shared_lock lock(MGroups);
  217. bool ret = false;
  218. if (m_groups.count(group_id) > 0) {
  219. PlayerGroup* group = m_groups[group_id];
  220. ret = group->AddMember(member);
  221. }
  222. return ret;
  223. }
  224. bool PlayerGroupManager::RemoveGroupMember(int32 group_id, Entity* member) {
  225. bool ret = false;
  226. bool remove = false;
  227. Client* client = 0;
  228. if(member->GetGroupMemberInfo()->mentor_target_char_id)
  229. {
  230. if(member->IsPlayer())
  231. {
  232. Player* tmpPlayer = (Player*)member;
  233. member->GetGroupMemberInfo()->mentor_target_char_id = 0;
  234. tmpPlayer->EnableResetMentorship();
  235. }
  236. }
  237. GroupLock(__FUNCTION__, __LINE__);
  238. if (m_groups.count(group_id) > 0) {
  239. PlayerGroup* group = m_groups[group_id];
  240. if (member->IsPlayer())
  241. client = member->GetGroupMemberInfo()->client;
  242. ret = group->RemoveMember(member);
  243. // If only 1 person left in the group set a flag to remove the group
  244. if (group->Size() == 1)
  245. remove = true;
  246. }
  247. ReleaseGroupLock(__FUNCTION__, __LINE__);
  248. if (client)
  249. RemoveGroupBuffs(group_id, client);
  250. // Call RemoveGroup outside the locks as it uses the same locks
  251. if (remove)
  252. RemoveGroup(group_id);
  253. return ret;
  254. }
  255. void PlayerGroupManager::NewGroup(Entity* leader) {
  256. std::unique_lock lock(MGroups);
  257. // Highly doubt this will ever be needed but putting it in any way, basically bump the id and ensure
  258. // no active group is currently using this id, if we hit the max for an int32 then reset the id to 1
  259. while (m_groups.count(m_nextGroupID) > 0) {
  260. // If m_nextGroupID is at its max then reset it to 1, else increment it
  261. if (m_nextGroupID == 4294967295)
  262. m_nextGroupID = 1;
  263. else
  264. m_nextGroupID++;
  265. }
  266. // Create a new group with the valid ID we got from above
  267. PlayerGroup* new_group = new PlayerGroup(m_nextGroupID);
  268. GroupOptions goptions;
  269. goptions.loot_method = leader->GetInfoStruct()->get_group_loot_method();
  270. goptions.loot_items_rarity = leader->GetInfoStruct()->get_group_loot_items_rarity();
  271. goptions.auto_split = leader->GetInfoStruct()->get_group_auto_split();
  272. goptions.default_yell = leader->GetInfoStruct()->get_group_default_yell();
  273. goptions.group_autolock = leader->GetInfoStruct()->get_group_autolock();
  274. goptions.group_lock_method = leader->GetInfoStruct()->get_group_lock_method();
  275. goptions.solo_autolock = leader->GetInfoStruct()->get_group_solo_autolock();
  276. goptions.auto_loot_method = leader->GetInfoStruct()->get_group_auto_loot_method();
  277. new_group->SetDefaultGroupOptions(&goptions);
  278. // Add the new group to the list (need to do this first, AddMember needs ref to the PlayerGroup ptr -> UpdateGroupMemberInfo)
  279. m_groups[m_nextGroupID] = new_group;
  280. // Add the leader to the group
  281. new_group->AddMember(leader);
  282. leader->GetGroupMemberInfo()->leader = true;
  283. }
  284. void PlayerGroupManager::RemoveGroup(int32 group_id) {
  285. std::unique_lock lock(MGroups);
  286. // Check to see if the id is in the list
  287. if (m_groups.count(group_id) > 0) {
  288. // Get a pointer to the group
  289. PlayerGroup* group = m_groups[group_id];
  290. // Erase the group from the list
  291. m_groups.erase(group_id);
  292. // Delete the group
  293. safe_delete(group);
  294. }
  295. }
  296. int8 PlayerGroupManager::Invite(Player* leader, Entity* member) {
  297. int8 ret = 255; // Should be changed, if it is not then we have an unknown error
  298. // Lock the pending invite list so we can work with it
  299. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  300. if (!member || (member->IsBot() && ((Bot*)member)->IsImmediateCamp()))
  301. ret = 6; // failure, not a valid target
  302. else if (member->IsNPC() && (!member->IsBot() /*|| !member->IsMec()*/))
  303. ret = 6;
  304. else if (leader == member)
  305. ret = 5; // failure, can't invite yourself
  306. else if (member->GetGroupMemberInfo())
  307. ret = 1; // failure, member already in a group
  308. // Check to see if the target of the invite already has a pending invite
  309. else if (m_pendingInvites.count(member->GetName()) > 0)
  310. ret = 2; // Target already has an invite
  311. // Check to see if the player that invited is already in a group
  312. else if (leader->GetGroupMemberInfo()) {
  313. // Read lock the group list so we can get the size of the inviters group
  314. GroupLock(__FUNCTION__, __LINE__);
  315. int32 group_size = m_groups[leader->GetGroupMemberInfo()->group_id]->Size();
  316. ReleaseGroupLock(__FUNCTION__, __LINE__);
  317. // Check to see if the group is full
  318. if (m_groups[leader->GetGroupMemberInfo()->group_id]->Size() >= 6)
  319. ret = 3; // Group full
  320. // Group isn't full so add the member to the pending invite list
  321. else {
  322. m_pendingInvites[member->GetName()] = leader->GetName();
  323. ret = 0; // Success
  324. }
  325. }
  326. // Inviter is not in a group
  327. else {
  328. // Check to see if the inviter has a pending invite himself
  329. if (m_pendingInvites.count(leader->GetName()) > 0)
  330. ret = 4; // inviter already has a pending group invite
  331. // No pending invites for the inviter add both the inviter and the target of the invite to the list
  332. else {
  333. m_pendingInvites[leader->GetName()] = leader->GetName();
  334. m_pendingInvites[member->GetName()] = leader->GetName();
  335. ret = 0; // success
  336. }
  337. }
  338. // Release the lock on pending invites
  339. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  340. /* testing purposes only */
  341. if (ret == 0 && member->IsNPC())
  342. AcceptInvite(member);
  343. return ret;
  344. }
  345. int8 PlayerGroupManager::AcceptInvite(Entity* member) {
  346. int8 ret = 3; // default to unknown error
  347. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  348. if (m_pendingInvites.count(member->GetName()) > 0) {
  349. string leader = m_pendingInvites[member->GetName()];
  350. Client* client_leader = zone_list.GetClientByCharName(leader);
  351. if (client_leader) {
  352. if (m_pendingInvites.count(leader) > 0) {
  353. NewGroup(client_leader->GetPlayer());
  354. m_pendingInvites.erase(leader);
  355. }
  356. // Remove from invite list and add to the group
  357. m_pendingInvites.erase(member->GetName());
  358. GroupMessage(client_leader->GetPlayer()->GetGroupMemberInfo()->group_id, "%s has joined the group.", member->GetName());
  359. AddGroupMember(client_leader->GetPlayer()->GetGroupMemberInfo()->group_id, member);
  360. ret = 0; // success
  361. }
  362. else {
  363. // Was unable to find the leader, remove from the invite list
  364. m_pendingInvites.erase(member->GetName());
  365. ret = 2; // failure, can't find leader
  366. }
  367. }
  368. else
  369. ret = 1; // failure, no pending invite
  370. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  371. return ret;
  372. }
  373. void PlayerGroupManager::DeclineInvite(Entity* member) {
  374. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  375. if (m_pendingInvites.count(member->GetName()) > 0) {
  376. string leader = m_pendingInvites[member->GetName()];
  377. m_pendingInvites.erase(member->GetName());
  378. if (m_pendingInvites.count(leader) > 0)
  379. m_pendingInvites.erase(leader);
  380. }
  381. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  382. }
  383. bool PlayerGroupManager::IsGroupIDValid(int32 group_id) {
  384. std::shared_lock lock(MGroups);
  385. bool ret = false;
  386. ret = m_groups.count(group_id) > 0;
  387. return ret;
  388. }
  389. void PlayerGroupManager::SendGroupUpdate(int32 group_id, Client* exclude) {
  390. std::shared_lock lock(MGroups);
  391. if (m_groups.count(group_id) > 0) {
  392. m_groups[group_id]->SendGroupUpdate(exclude);
  393. }
  394. }
  395. PlayerGroup* PlayerGroupManager::GetGroup(int32 group_id) {
  396. if (m_groups.count(group_id) > 0)
  397. return m_groups[group_id];
  398. return 0;
  399. }
  400. void PlayerGroupManager::ClearPendingInvite(Entity* member) {
  401. MPendingInvites.writelock(__FUNCTION__, __LINE__);
  402. if (m_pendingInvites.count(member->GetName()) > 0)
  403. m_pendingInvites.erase(member->GetName());
  404. MPendingInvites.releasewritelock(__FUNCTION__, __LINE__);
  405. }
  406. void PlayerGroupManager::RemoveGroupBuffs(int32 group_id, Client* client) {
  407. SpellEffects* se = 0;
  408. Spell* spell = 0;
  409. LuaSpell* luaspell = 0;
  410. EQ2Packet* packet = 0;
  411. Entity* pet = 0;
  412. Player* player = 0;
  413. Entity* charmed_pet = 0;
  414. PlayerGroup* group = 0;
  415. MGroups.lock_shared();
  416. if (m_groups.count(group_id) > 0)
  417. group = m_groups[group_id];
  418. if (group && client) {
  419. /* first remove all spell effects this group member has on them from other group members */
  420. player = client->GetPlayer();
  421. bool recoup_lock = true;
  422. for (int i = 0; i < NUM_SPELL_EFFECTS; i++) {
  423. if(recoup_lock) {
  424. player->GetSpellEffectMutex()->readlock(__FUNCTION__, __LINE__);
  425. recoup_lock = false;
  426. se = player->GetSpellEffects();
  427. }
  428. if (se && se[i].spell_id != 0xFFFFFFFF) {
  429. //If the client is the caster, don't remove the spell
  430. if (se[i].caster == player)
  431. continue;
  432. luaspell = se[i].spell;
  433. spell = luaspell->spell;
  434. /* is this a friendly group spell? */
  435. if (spell && spell->GetSpellData()->group_spell && spell->GetSpellData()->friendly_spell) {
  436. player->GetSpellEffectMutex()->releasereadlock(__FUNCTION__, __LINE__);
  437. recoup_lock = true;
  438. // we have to remove our spell effect mutex lock since RemoveSpellEffect needs a write lock to remove it
  439. //Remove all group buffs not cast by this player
  440. player->RemoveSpellEffect(luaspell);
  441. player->RemoveSpellBonus(luaspell);
  442. player->RemoveSkillBonus(spell->GetSpellID());
  443. //Also remove group buffs from pets
  444. pet = 0;
  445. charmed_pet = 0;
  446. if (player->HasPet()){
  447. pet = player->GetPet();
  448. pet = player->GetCharmedPet();
  449. }
  450. if (pet){
  451. pet->RemoveSpellEffect(luaspell);
  452. pet->RemoveSpellBonus(luaspell);
  453. }
  454. if (charmed_pet){
  455. charmed_pet->RemoveSpellEffect(luaspell);
  456. charmed_pet->RemoveSpellBonus(luaspell);
  457. }
  458. }
  459. }
  460. }
  461. if(!recoup_lock) { // we previously set a readlock that we now release
  462. player->GetSpellEffectMutex()->releasereadlock(__FUNCTION__, __LINE__);
  463. }
  464. packet = client->GetPlayer()->GetSkills()->GetSkillPacket(client->GetVersion());
  465. if (packet)
  466. client->QueuePacket(packet);
  467. }
  468. MGroups.unlock_shared();
  469. }
  470. int32 PlayerGroupManager::GetGroupSize(int32 group_id) {
  471. std::shared_lock lock(MGroups);
  472. int32 ret = 0;
  473. if (m_groups.count(group_id) > 0)
  474. ret = m_groups[group_id]->Size();
  475. return ret;
  476. }
  477. void PlayerGroupManager::SendGroupQuests(int32 group_id, Client* client) {
  478. std::shared_lock lock(MGroups);
  479. GroupMemberInfo* info = 0;
  480. if (m_groups.count(group_id) > 0) {
  481. m_groups[group_id]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  482. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  483. deque<GroupMemberInfo*>::iterator itr;
  484. for (itr = members->begin(); itr != members->end(); itr++) {
  485. info = *itr;
  486. if (info->client) {
  487. LogWrite(PLAYER__DEBUG, 0, "Player", "Send Quest Journal...");
  488. info->client->SendQuestJournal(false, client);
  489. client->SendQuestJournal(false, info->client);
  490. }
  491. }
  492. m_groups[group_id]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  493. }
  494. }
  495. bool PlayerGroupManager::HasGroupCompletedQuest(int32 group_id, int32 quest_id) {
  496. std::shared_lock lock(MGroups);
  497. bool questComplete = true;
  498. GroupMemberInfo* info = 0;
  499. if (m_groups.count(group_id) > 0) {
  500. m_groups[group_id]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  501. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  502. deque<GroupMemberInfo*>::iterator itr;
  503. for (itr = members->begin(); itr != members->end(); itr++) {
  504. info = *itr;
  505. if (info->client) {
  506. bool isComplete = info->client->GetPlayer()->HasQuestBeenCompleted(quest_id);
  507. if(!isComplete)
  508. {
  509. questComplete = isComplete;
  510. break;
  511. }
  512. }
  513. }
  514. m_groups[group_id]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  515. }
  516. return questComplete;
  517. }
  518. void PlayerGroupManager::SimpleGroupMessage(int32 group_id, const char* message) {
  519. std::shared_lock lock(MGroups);
  520. if (m_groups.count(group_id) > 0)
  521. m_groups[group_id]->SimpleGroupMessage(message);
  522. }
  523. void PlayerGroupManager::SendGroupMessage(int32 group_id, int8 type, const char* message, ...) {
  524. std::shared_lock lock(MGroups);
  525. va_list argptr;
  526. char buffer[4096];
  527. buffer[0] = 0;
  528. va_start(argptr, message);
  529. vsnprintf(buffer, sizeof(buffer), message, argptr);
  530. va_end(argptr);
  531. if (m_groups.count(group_id) > 0)
  532. m_groups[group_id]->SendGroupMessage(type, buffer);
  533. }
  534. void PlayerGroupManager::GroupMessage(int32 group_id, const char* message, ...) {
  535. va_list argptr;
  536. char buffer[4096];
  537. buffer[0] = 0;
  538. va_start(argptr, message);
  539. vsnprintf(buffer, sizeof(buffer), message, argptr);
  540. va_end(argptr);
  541. SimpleGroupMessage(group_id, buffer);
  542. }
  543. void PlayerGroupManager::GroupChatMessage(int32 group_id, Spawn* from, int32 language, const char* message) {
  544. std::shared_lock lock(MGroups);
  545. if (m_groups.count(group_id) > 0)
  546. m_groups[group_id]->GroupChatMessage(from, language, message);
  547. }
  548. bool PlayerGroupManager::MakeLeader(int32 group_id, Entity* new_leader) {
  549. std::shared_lock lock(MGroups);
  550. if (m_groups.count(group_id) > 0)
  551. return m_groups[group_id]->MakeLeader(new_leader);
  552. return false;
  553. }
  554. void PlayerGroupManager::UpdateGroupBuffs() {
  555. map<int32, PlayerGroup*>::iterator itr;
  556. deque<GroupMemberInfo*>::iterator member_itr;
  557. deque<GroupMemberInfo*>::iterator target_itr;
  558. map<int32, SkillBonusValue*>::iterator itr_skills;
  559. MaintainedEffects* me = nullptr;
  560. LuaSpell* luaspell = nullptr;
  561. Spell* spell = nullptr;
  562. Entity* group_member = nullptr;
  563. SkillBonus* sb = nullptr;
  564. EQ2Packet* packet = nullptr;
  565. int32 i = 0;
  566. PlayerGroup* group = nullptr;
  567. Player* caster = nullptr;
  568. vector<int32> new_target_list;
  569. vector<int32> char_list;
  570. Client* client = nullptr;
  571. bool has_effect = false;
  572. vector<BonusValues*>* sb_list = nullptr;
  573. BonusValues* bv = nullptr;
  574. Entity* pet = nullptr;
  575. Entity* charmed_pet = nullptr;
  576. for (itr = m_groups.begin(); itr != m_groups.end(); itr++) {
  577. group = itr->second;
  578. /* loop through the group members and see if any of them have any maintained spells that are group buffs and friendly.
  579. if so, update the list of targets and apply/remove effects as needed */
  580. vector<Player*> players;
  581. group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  582. for (member_itr = group->GetMembers()->begin(); member_itr != group->GetMembers()->end(); member_itr++) {
  583. if ((*member_itr)->client)
  584. caster = (*member_itr)->client->GetPlayer();
  585. else caster = 0;
  586. if (!caster)
  587. continue;
  588. if (!caster->GetMaintainedSpellBySlot(0))
  589. continue;
  590. players.push_back(caster);
  591. }
  592. group->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  593. vector<Player*>::iterator vitr;
  594. for (vitr = players.begin(); vitr != players.end(); vitr++) {
  595. caster = *vitr;
  596. caster->GetMaintainedMutex()->readlock(__FUNCTION__, __LINE__);
  597. // go through the player's maintained spells
  598. me = caster->GetMaintainedSpells();
  599. for (i = 0; i < NUM_MAINTAINED_EFFECTS; i++) {
  600. if (me[i].spell_id == 0xFFFFFFFF)
  601. continue;
  602. luaspell = me[i].spell;
  603. if (!luaspell)
  604. continue;
  605. if (!luaspell->caster)
  606. {
  607. LogWrite(PLAYER__ERROR, 0, "Player", "Bad luaspell, caster is NULL, spellid: %u", me[i].spell_id);
  608. continue;
  609. }
  610. spell = luaspell->spell;
  611. if (spell && spell->GetSpellData()->group_spell && spell->GetSpellData()->friendly_spell &&
  612. (spell->GetSpellData()->target_type == SPELL_TARGET_GROUP_AE || spell->GetSpellData()->target_type == SPELL_TARGET_RAID_AE)) {
  613. luaspell->MSpellTargets.writelock(__FUNCTION__, __LINE__);
  614. luaspell->char_id_targets.clear();
  615. for (target_itr = group->GetMembers()->begin(); target_itr != group->GetMembers()->end(); target_itr++) {
  616. group_member = (*target_itr)->member;
  617. if (!group_member)
  618. continue;
  619. if (group_member == caster)
  620. continue;
  621. client = (*target_itr)->client;
  622. has_effect = false;
  623. if (group_member->GetSpellEffect(spell->GetSpellID(), caster)) {
  624. has_effect = true;
  625. }
  626. if(!has_effect && (std::find(luaspell->removed_targets.begin(),
  627. luaspell->removed_targets.end(), group_member->GetID()) != luaspell->removed_targets.end())) {
  628. continue;
  629. }
  630. // Check if player is within range of the caster
  631. if (!rule_manager.GetGlobalRule(R_Spells, EnableCrossZoneGroupBuffs)->GetInt8() &&
  632. (group_member->GetZone() != caster->GetZone() || caster->GetDistance(group_member) > spell->GetSpellData()->radius)) {
  633. if (has_effect) {
  634. group_member->RemoveSpellEffect(luaspell);
  635. group_member->RemoveSpellBonus(luaspell);
  636. group_member->RemoveSkillBonus(spell->GetSpellID());
  637. if (client) {
  638. packet = ((Player*)group_member)->GetSkills()->GetSkillPacket(client->GetVersion());
  639. if (packet)
  640. client->QueuePacket(packet);
  641. }
  642. //Also remove group buffs from pet
  643. if (group_member->HasPet()) {
  644. pet = group_member->GetPet();
  645. charmed_pet = group_member->GetCharmedPet();
  646. if (pet) {
  647. pet->RemoveSpellEffect(luaspell);
  648. pet->RemoveSpellBonus(luaspell);
  649. }
  650. if (charmed_pet) {
  651. charmed_pet->RemoveSpellEffect(luaspell);
  652. charmed_pet->RemoveSpellBonus(luaspell);
  653. }
  654. }
  655. }
  656. continue;
  657. }
  658. if(group_member->GetZone() != caster->GetZone())
  659. {
  660. SpellProcess::AddSelfAndPetToCharTargets(luaspell, group_member);
  661. }
  662. else
  663. {
  664. //this group member is a target of the spell
  665. new_target_list.push_back(group_member->GetID());
  666. }
  667. if (has_effect)
  668. continue;
  669. pet = 0;
  670. charmed_pet = 0;
  671. if (group_member->HasPet()) {
  672. pet = group_member->GetPet();
  673. charmed_pet = group_member->GetCharmedPet();
  674. }
  675. group_member->AddSpellEffect(luaspell, luaspell->timer.GetRemainingTime() != 0 ? luaspell->timer.GetRemainingTime() : 0);
  676. if (pet)
  677. pet->AddSpellEffect(luaspell, luaspell->timer.GetRemainingTime() != 0 ? luaspell->timer.GetRemainingTime() : 0);
  678. if (charmed_pet)
  679. charmed_pet->AddSpellEffect(luaspell, luaspell->timer.GetRemainingTime() != 0 ? luaspell->timer.GetRemainingTime() : 0);
  680. if (pet)
  681. new_target_list.push_back(pet->GetID());
  682. if (charmed_pet)
  683. new_target_list.push_back(charmed_pet->GetID());
  684. // look for a spell bonus on caster's spell
  685. sb_list = caster->GetAllSpellBonuses(luaspell);
  686. for (int32 x = 0; x < sb_list->size(); x++) {
  687. bv = sb_list->at(x);
  688. group_member->AddSpellBonus(luaspell, bv->type, bv->value, bv->class_req, bv->race_req, bv->faction_req);
  689. if (pet)
  690. pet->AddSpellBonus(luaspell, bv->type, bv->value, bv->class_req, bv->race_req, bv->faction_req);
  691. if (charmed_pet)
  692. charmed_pet->AddSpellBonus(luaspell, bv->type, bv->value, bv->class_req, bv->race_req, bv->faction_req);
  693. }
  694. sb_list->clear();
  695. safe_delete(sb_list);
  696. // look for a skill bonus on the caster's spell
  697. sb = caster->GetSkillBonus(me[i].spell_id);
  698. if (sb) {
  699. for (itr_skills = sb->skills.begin(); itr_skills != sb->skills.end(); itr_skills++)
  700. group_member->AddSkillBonus(sb->spell_id, (*itr_skills).second->skill_id, (*itr_skills).second->value);
  701. }
  702. if (client) {
  703. packet = ((Player*)group_member)->GetSkills()->GetSkillPacket(client->GetVersion());
  704. if (packet)
  705. client->QueuePacket(packet);
  706. }
  707. }
  708. luaspell->targets.swap(new_target_list);
  709. SpellProcess::AddSelfAndPet(luaspell, caster);
  710. luaspell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__);
  711. new_target_list.clear();
  712. }
  713. }
  714. caster->GetMaintainedMutex()->releasereadlock(__FUNCTION__, __LINE__);
  715. }
  716. }
  717. }
  718. bool PlayerGroupManager::IsInGroup(int32 group_id, Entity* member) {
  719. std::shared_lock lock(MGroups);
  720. bool ret = false;
  721. if (m_groups.count(group_id) > 0) {
  722. m_groups[group_id]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  723. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  724. for (int8 i = 0; i < members->size(); i++) {
  725. if (member == members->at(i)->member) {
  726. ret = true;
  727. break;
  728. }
  729. }
  730. m_groups[group_id]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  731. }
  732. return ret;
  733. }
  734. Entity* PlayerGroupManager::IsPlayerInGroup(int32 group_id, int32 character_id) {
  735. std::shared_lock lock(MGroups);
  736. Entity* ret = nullptr;
  737. if (m_groups.count(group_id) > 0) {
  738. m_groups[group_id]->MGroupMembers.readlock(__FUNCTION__, __LINE__);
  739. deque<GroupMemberInfo*>* members = m_groups[group_id]->GetMembers();
  740. for (int8 i = 0; i < members->size(); i++) {
  741. if (members->at(i)->member && members->at(i)->member->IsPlayer() && character_id == ((Player*)members->at(i)->member)->GetCharacterID()) {
  742. ret = members->at(i)->member;
  743. break;
  744. }
  745. }
  746. m_groups[group_id]->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
  747. }
  748. return ret;
  749. }
  750. void PlayerGroup::RemoveClientReference(Client* remove) {
  751. deque<GroupMemberInfo*>::iterator itr;
  752. MGroupMembers.writelock();
  753. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  754. GroupMemberInfo* gmi = *itr;
  755. if (gmi->client && gmi->client == remove)
  756. {
  757. gmi->client = 0;
  758. gmi->member = 0;
  759. break;
  760. }
  761. }
  762. MGroupMembers.releasewritelock();
  763. }
  764. void PlayerGroup::UpdateGroupMemberInfo(Entity* ent, bool groupMembersLocked) {
  765. Player* player = (Player*)ent;
  766. if (!player || !player->GetGroupMemberInfo())
  767. return;
  768. if(!groupMembersLocked)
  769. MGroupMembers.writelock();
  770. GroupMemberInfo* group_member_info = player->GetGroupMemberInfo();
  771. player->GetGroupMemberInfo()->class_id = player->GetAdventureClass();
  772. group_member_info->hp_max = player->GetTotalHP();
  773. group_member_info->hp_current = player->GetHP();
  774. group_member_info->level_max = player->GetLevel();
  775. group_member_info->level_current = player->GetLevel();
  776. group_member_info->name = string(player->GetName());
  777. group_member_info->power_current = player->GetPower();
  778. group_member_info->power_max = player->GetTotalPower();
  779. group_member_info->race_id = player->GetRace();
  780. if (player->GetZone())
  781. group_member_info->zone = player->GetZone()->GetZoneDescription();
  782. else
  783. group_member_info->zone = "Unknown";
  784. if(!groupMembersLocked)
  785. MGroupMembers.releasewritelock();
  786. }
  787. Entity* PlayerGroup::GetGroupMemberByPosition(Entity* seeker, int32 mapped_position) {
  788. Entity* ret = nullptr;
  789. deque<GroupMemberInfo*>::iterator itr;
  790. MGroupMembers.readlock();
  791. int32 count = 1;
  792. for (itr = m_members.begin(); itr != m_members.end(); itr++) {
  793. if ((*itr)->member == seeker) {
  794. continue;
  795. }
  796. count++;
  797. if(count >= mapped_position) {
  798. ret = (Entity*)(*itr)->member;
  799. break;
  800. }
  801. }
  802. MGroupMembers.releasereadlock();
  803. return ret;
  804. }
  805. void PlayerGroup::SetDefaultGroupOptions(GroupOptions* options) {
  806. MGroupMembers.writelock();
  807. if (options != nullptr) {
  808. group_options.loot_method = options->loot_method;
  809. group_options.loot_items_rarity = options->loot_items_rarity;
  810. group_options.auto_split = options->auto_split;
  811. group_options.default_yell = options->default_yell;
  812. group_options.group_lock_method = options->group_lock_method;
  813. group_options.group_autolock = options->group_autolock;
  814. group_options.solo_autolock = options->solo_autolock;
  815. group_options.auto_loot_method = options->auto_loot_method;
  816. }
  817. else {
  818. group_options.loot_method = 1;
  819. group_options.loot_items_rarity = 0;
  820. group_options.auto_split = 1;
  821. group_options.default_yell = 1;
  822. group_options.group_lock_method = 0;
  823. group_options.group_autolock = 0;
  824. group_options.solo_autolock = 0;
  825. group_options.auto_loot_method = 0;
  826. group_options.last_looted_index = 0;
  827. }
  828. MGroupMembers.releasewritelock();
  829. }