Clone of UAS2 @ https://github.com/drudgedance/uas2

Fellowship.cpp 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. /*
  2. * This file is part of UAS2.
  3. *
  4. * UAS2 is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * UAS2 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 UASv1; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. /**
  18. * @file Fellowship.cpp
  19. * Implements general functionality for fellowships.
  20. *
  21. * TODO: Separate static and non-static (instance-based) functions.
  22. * (Static functions should probably be in a fellowship manager file.)
  23. * Make fellowship stat update messages active (sent periodically) rather than passive (sent for every change).
  24. */
  25. #pragma warning(disable:4786) //warning: identifier was truncated to '255' characters in the browser information
  26. #include "Client.h"
  27. #include "Fellowship.h"
  28. #include "MasterServer.h"
  29. cFellowship::cFellowship()
  30. {
  31. m_ID = 0;
  32. m_Name = "";
  33. m_LeaderGUID = 0;
  34. m_Size = 0;
  35. m_CreationTime = 0;
  36. m_IsOpen = false;
  37. m_ShareXP = true;
  38. m_ShareLoot = false;
  39. m_ProportionXP = false;
  40. }
  41. cFellowship::~cFellowship()
  42. {
  43. }
  44. DWORD cFellowship::NewFellowship(DWORD dwLeaderGUID, std::string name, char felName[50], bool shareXP, bool shareLoot)
  45. {
  46. cFellowship* newFellowship = new cFellowship();
  47. return newFellowship->CreateFellowship(dwLeaderGUID, name, felName, shareXP, shareLoot);
  48. }
  49. DWORD cFellowship::CreateFellowship(DWORD dwLeaderGUID, std::string name, char felName[50], bool shareXP, bool shareLoot)
  50. {
  51. m_ID = cMasterServer::NewFellowID();
  52. m_LeaderGUID = dwLeaderGUID;
  53. m_Name = felName;
  54. m_Size = 0;
  55. m_CreationTime = time(NULL);
  56. m_IsOpen = false;
  57. m_ShareXP = shareXP;
  58. m_ShareLoot = shareLoot;
  59. m_ProportionXP = false;
  60. cMasterServer::m_FellowshipList.push_back( this );
  61. AddMember(dwLeaderGUID);
  62. return m_ID;
  63. }
  64. cFellowship* cFellowship::GetFellowshipByID(DWORD dwFellowshipID)
  65. {
  66. for ( std::vector<cFellowship *>::iterator itr = cMasterServer::m_FellowshipList.begin() ; itr != cMasterServer::m_FellowshipList.end() ; ++itr )
  67. {
  68. if ((*itr)->GetID() == dwFellowshipID)
  69. {
  70. return *itr;
  71. }
  72. }
  73. return NULL;
  74. }
  75. void cFellowship::Disband()
  76. {
  77. ClearMembers();
  78. delete this;
  79. }
  80. /**
  81. * Clears all members from the fellowship.
  82. */
  83. void cFellowship::ClearMembers()
  84. {
  85. cClient* pcClient;
  86. cAvatar* pcAvatar;
  87. // vector of fellowship member count (1 per member)
  88. std::map<DWORD, FellowMem>::iterator itrMember;
  89. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  90. {
  91. pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  92. if (pcClient)
  93. {
  94. pcAvatar = pcClient->m_pcAvatar;
  95. if (pcAvatar)
  96. {
  97. pcAvatar->SetFellowshipID(0);
  98. pcAvatar->inFellow = false;
  99. cMessage cmRemove = DisbandMessage(itrMember->second.m_dwGUID, ++pcClient->m_dwF7B0Sequence);
  100. pcClient->AddPacket( WORLD_SERVER, cmRemove, 4 );
  101. }
  102. }
  103. }
  104. members.clear();
  105. }
  106. /**
  107. * Handles the opening or closing of the fellowship.
  108. *
  109. * @param dwIsOpen - Value for whether the fellowship should be opened or closed
  110. */
  111. bool cFellowship::SetOpenClose(DWORD dwIsOpen)
  112. {
  113. cMessage cmOpenCloseText;
  114. char szTextBuffer[255];
  115. DWORD dwColor = 0x17L;
  116. if (dwIsOpen == 1)
  117. {
  118. sprintf(&szTextBuffer[0],"%s is now an open fellowship; anyone may recruit new members.", this->GetName().c_str());
  119. this->m_IsOpen = true;
  120. }
  121. else
  122. {
  123. sprintf(&szTextBuffer[0],"%s is now a closed fellowship.", this->GetName().c_str());
  124. this->m_IsOpen = false;
  125. }
  126. cmOpenCloseText << 0xF62CL << szTextBuffer << dwColor;
  127. cClient* pcClient;
  128. cAvatar* pcAvatar;
  129. std::map<DWORD, FellowMem>::iterator itrMember;
  130. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  131. {
  132. pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  133. if (pcClient)
  134. {
  135. pcAvatar = pcClient->m_pcAvatar;
  136. if (pcAvatar)
  137. {
  138. pcClient->AddPacket( WORLD_SERVER, cmOpenCloseText, 4 );
  139. cMessage cmOpenCloseMessage = JoinMessage( pcAvatar->GetGUID(), ++pcClient->m_dwF7B0Sequence );
  140. pcClient->AddPacket( WORLD_SERVER, cmOpenCloseMessage, 4 );
  141. }
  142. }
  143. }
  144. return true;
  145. }
  146. /**
  147. * Handles the promotion of a member of the fellowship to leader.
  148. *
  149. * @param dwNewLeaderGUID - The GUID for the member that is being promoted to leader.
  150. */
  151. bool cFellowship::SetLeader(DWORD dwNewLeaderGUID)
  152. {
  153. cMessage cmNewLeaderText;
  154. char szTextBuffer[255];
  155. DWORD dwColor = 0x04L;
  156. FellowMem* member = this->FindMember(dwNewLeaderGUID);
  157. if (member)
  158. {
  159. this->m_LeaderGUID = 2;
  160. sprintf(&szTextBuffer[0],"%s is now the leader of this fellowship.", member->m_szName.c_str());
  161. cmNewLeaderText << 0xF62CL << szTextBuffer << dwColor;
  162. cClient* pcClient;
  163. cAvatar* pcAvatar;
  164. std::map<DWORD, FellowMem>::iterator itrMember;
  165. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  166. {
  167. pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  168. if (pcClient)
  169. {
  170. pcAvatar = pcClient->m_pcAvatar;
  171. if (pcAvatar)
  172. {
  173. cMessage cmNewLeaderMessage = JoinMessage( pcAvatar->GetGUID(), ++pcClient->m_dwF7B0Sequence );
  174. pcClient->AddPacket( WORLD_SERVER, cmNewLeaderMessage, 4 );
  175. pcClient->AddPacket( WORLD_SERVER, cmNewLeaderText, 4 );
  176. }
  177. }
  178. }
  179. return true;
  180. }
  181. return false;
  182. }
  183. /**
  184. * Handles the addition of a member of the fellowship.
  185. *
  186. * @param dwMemberGUID - The GUID for the member that is being added to the fellowship.
  187. */
  188. bool cFellowship::AddMember(DWORD dwAvatarGUID)
  189. {
  190. this->InsertMember(dwAvatarGUID);
  191. return true;
  192. }
  193. /**
  194. * Handles the removal of a member of the fellowship.
  195. *
  196. * @param dwMemberGUID - The GUID for the member that quit the fellowship.
  197. */
  198. bool cFellowship::RemMember(DWORD dwMemberGUID)
  199. {
  200. FellowMem* member = this->FindMember(dwMemberGUID);
  201. if (member)
  202. {
  203. if (member->m_dwGUID == this->m_LeaderGUID)
  204. {
  205. this->Disband();
  206. }
  207. else
  208. {
  209. DeleteMember(dwMemberGUID, false);
  210. }
  211. return true;
  212. }
  213. return false;
  214. }
  215. /**
  216. * Handles the dismissal of a member from the fellowship.
  217. *
  218. * @param dwMemberGUID - The GUID for the member that was dismissed.
  219. */
  220. bool cFellowship::DismissMember(DWORD dwMemberGUID)
  221. {
  222. DeleteMember(dwMemberGUID, true);
  223. return true;
  224. }
  225. /**
  226. * Handles the death of a member of the fellowship.
  227. *
  228. * @param dwMemberGUID - The GUID for the member that died.
  229. */
  230. bool cFellowship::MemberDeath(DWORD dwMemberGUID)
  231. {
  232. FellowMem* member = this->FindMember(dwMemberGUID);
  233. if (member)
  234. {
  235. cMessage cmMemberDeathText;
  236. char szTextBuffer[255];
  237. DWORD dwColor = 0x17L;
  238. sprintf(&szTextBuffer[0],"Your fellow %s has died!", member->m_szName.c_str());
  239. cmMemberDeathText << 0xF62CL << szTextBuffer << dwColor;
  240. cClient* pcClient;
  241. cAvatar* pcAvatar;
  242. std::map<DWORD, FellowMem>::iterator itrMember;
  243. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  244. {
  245. pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  246. if (pcClient && itrMember->second.m_dwGUID != dwMemberGUID)
  247. {
  248. pcAvatar = pcClient->m_pcAvatar;
  249. if (pcAvatar)
  250. {
  251. pcClient->AddPacket( WORLD_SERVER, cmMemberDeathText, 4 );
  252. cMessage cmUpdate = UpdMemberMessage(itrMember->second.m_dwGUID, ++pcClient->m_dwF7B0Sequence, dwMemberGUID);
  253. pcClient->AddPacket( WORLD_SERVER, cmUpdate, 4 );
  254. }
  255. }
  256. }
  257. return true;
  258. }
  259. return false;
  260. }
  261. /**
  262. * Inserts an avatar into the fellowship member map.
  263. *
  264. * The function is used when a player should be inserted into a fellowship.
  265. *
  266. * @param dwAvatarGUID - The GUID for the avatar that should be inserted.
  267. */
  268. bool cFellowship::InsertMember(DWORD dwAvatarGUID)
  269. {
  270. FellowMem newMember;
  271. cClient* pcClient;
  272. cAvatar* pcAvatar;
  273. pcClient = cClient::FindClient(dwAvatarGUID);
  274. pcAvatar = pcClient->m_pcAvatar;
  275. if (pcAvatar)
  276. {
  277. newMember.m_dwGUID = pcAvatar->GetGUID();
  278. newMember.m_wUnk1 = 0;
  279. newMember.m_dwLevel = pcAvatar->m_cStats.m_dwLevel;
  280. newMember.m_dwHealthTot = pcAvatar->GetTotalHealth();
  281. newMember.m_dwStaminaTot = pcAvatar->GetTotalStamina();
  282. newMember.m_dwManaTot = pcAvatar->GetTotalMana();
  283. newMember.m_dwHealthCur = pcAvatar->m_cStats.m_lpcVitals[0].m_lTrueCurrent;
  284. newMember.m_dwStaminaCur = pcAvatar->m_cStats.m_lpcVitals[1].m_lTrueCurrent;
  285. newMember.m_dwManaCur = pcAvatar->m_cStats.m_lpcVitals[2].m_lTrueCurrent;
  286. (pcAvatar->m_dwOptions & 0x00100000) ? newMember.m_bShareLoot = 1 : newMember.m_bShareLoot = 0;
  287. newMember.m_szName = pcAvatar->Name();
  288. newMember.m_timeJoin = time(NULL);
  289. this->members.insert(MemberList::value_type(newMember.m_dwGUID, newMember));
  290. this->m_Size++;
  291. pcClient = cClient::FindClient(dwAvatarGUID);
  292. if (pcClient)
  293. {
  294. cMessage cmJoinMessage = JoinMessage( newMember.m_dwGUID, ++pcClient->m_dwF7B0Sequence );
  295. pcClient->AddPacket( WORLD_SERVER, cmJoinMessage, 4 );
  296. }
  297. if (this->m_Size > 1)
  298. {
  299. RelayMemberUpdate(newMember.m_dwGUID);
  300. }
  301. return true;
  302. }
  303. return false;
  304. }
  305. /**
  306. * Removes an avatar from the fellowship member map.
  307. *
  308. * The function is used when a player should be removed from a fellowship.
  309. *
  310. * @param dwAvatarGUID - The GUID for the avatar that should be removed.
  311. * @param wasDismissed - Value to determine whether the member was dismissed (or else quit).
  312. */
  313. bool cFellowship::DeleteMember(DWORD dwMemberGUID, bool wasDismissed)
  314. {
  315. this->members.erase(dwMemberGUID); // erase the member from the fellowship
  316. this->m_Size--; // update the fellowship size
  317. if (this->m_Size > 0)
  318. {
  319. if (wasDismissed)
  320. RelayMemberDismiss(dwMemberGUID);
  321. else
  322. RelayMemberDelete(dwMemberGUID);
  323. }
  324. return true;
  325. }
  326. /**
  327. * Updates the information for a member of the fellowship in the member map.
  328. *
  329. * The function is used whenever the fellowship information should be updated for a fellowship member.
  330. *
  331. * @param dwMemberGUID - The GUID for the member whose information should be updated.
  332. */
  333. bool cFellowship::UpdateMember(DWORD dwMemberGUID)
  334. {
  335. FellowMem* member = this->FindMember(dwMemberGUID);
  336. if (member)
  337. {
  338. cClient* pcClient;
  339. cAvatar* pcAvatar;
  340. pcClient = cClient::FindClient(member->m_dwGUID);
  341. pcAvatar = pcClient->m_pcAvatar;
  342. if (pcAvatar)
  343. {
  344. if (member->m_dwLevel != pcAvatar->m_cStats.m_dwLevel)
  345. {
  346. CalcShareXP();
  347. }
  348. member->m_dwLevel = pcAvatar->m_cStats.m_dwLevel;
  349. member->m_dwHealthTot = pcAvatar->GetTotalHealth();
  350. member->m_dwStaminaTot = pcAvatar->GetTotalStamina();
  351. member->m_dwManaTot = pcAvatar->GetTotalMana();
  352. member->m_dwHealthCur = pcAvatar->m_cStats.m_lpcVitals[0].m_lTrueCurrent;
  353. member->m_dwStaminaCur = pcAvatar->m_cStats.m_lpcVitals[1].m_lTrueCurrent;
  354. member->m_dwManaCur = pcAvatar->m_cStats.m_lpcVitals[2].m_lTrueCurrent;
  355. }
  356. return true;
  357. }
  358. return false;
  359. }
  360. /**
  361. * Relays a member update to all members of the fellowship.
  362. *
  363. * @param dwMemberGUID - The GUID for the member whose information has been updated.
  364. */
  365. void cFellowship::RelayMemberUpdate(DWORD dwMemberGUID)
  366. {
  367. std::map<DWORD, FellowMem>::iterator itrMember;
  368. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  369. {
  370. cClient* pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  371. if (pcClient)
  372. {
  373. cMessage cmUpdate = UpdMemberMessage(itrMember->second.m_dwGUID, ++pcClient->m_dwF7B0Sequence, dwMemberGUID);
  374. pcClient->AddPacket( WORLD_SERVER, cmUpdate, 4 );
  375. }
  376. }
  377. }
  378. /**
  379. * Relays a member deletion to all members of the fellowship.
  380. *
  381. * @param dwMemberGUID - The GUID for the member who has left the fellowship.
  382. */
  383. void cFellowship::RelayMemberDelete(DWORD dwMemberGUID)
  384. {
  385. std::map<DWORD, FellowMem>::iterator itrMember;
  386. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  387. {
  388. cClient* pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  389. if (pcClient)
  390. {
  391. cMessage cmRemove = RemMemberMessage(itrMember->second.m_dwGUID, ++pcClient->m_dwF7B0Sequence, dwMemberGUID);
  392. pcClient->AddPacket( WORLD_SERVER, cmRemove, 4 );
  393. }
  394. }
  395. }
  396. /**
  397. * Relays a member dismissal to all members of the fellowship.
  398. *
  399. * @param dwMemberGUID - The GUID for the member who has been dismissed from the fellowship.
  400. */
  401. void cFellowship::RelayMemberDismiss(DWORD dwMemberGUID)
  402. {
  403. std::map<DWORD, FellowMem>::iterator itrMember;
  404. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  405. {
  406. cClient* pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  407. if (pcClient)
  408. {
  409. cMessage cmDismiss = DisMemberMessage(itrMember->second.m_dwGUID, ++pcClient->m_dwF7B0Sequence, dwMemberGUID);
  410. pcClient->AddPacket( WORLD_SERVER, cmDismiss, 4 );
  411. }
  412. }
  413. }
  414. /**
  415. * Handles the message sent for joining the fellowship.
  416. *
  417. * @parem dwClGUID - The client's GUID.
  418. * @parem clF7B0Sequence - The client's present F7B0 sequence value.
  419. *
  420. * @return cMessage - Returns an 0x0000F7B0 server message.
  421. */
  422. cMessage cFellowship::JoinMessage(DWORD dwClGUID, DWORD dwClF7B0Sequence)
  423. {
  424. cMessage cmMessage;
  425. cmMessage << 0xF7B0L
  426. << dwClGUID
  427. << dwClF7B0Sequence
  428. // << 0x02BEL; //ToD
  429. << 0x00AFL;
  430. cmMessage << WORD(this->m_Size) // fellow count
  431. << WORD(0x0010); // unknown1
  432. // vector of fellowship member count (1 per member)
  433. std::map<DWORD, FellowMem>::iterator itrMember;
  434. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  435. {
  436. cmMessage << DWORD(itrMember->second.m_dwGUID) // this member's GUID
  437. << WORD(itrMember->second.m_wUnk1) // unknown1
  438. << WORD(itrMember->second.m_dwLevel) // Level
  439. << DWORD(itrMember->second.m_dwHealthTot) // maximum Health
  440. << DWORD(itrMember->second.m_dwStaminaTot) // maximum Stamina
  441. << DWORD(itrMember->second.m_dwManaTot) // maximum Mana
  442. << DWORD(itrMember->second.m_dwHealthCur) // current Health
  443. << DWORD(itrMember->second.m_dwStaminaCur) // current Stamina
  444. << DWORD(itrMember->second.m_dwManaCur) // current Mana
  445. << DWORD(itrMember->second.m_bShareLoot) // share loot - 0x00 = no, 0x10 = yes (0 default)
  446. << itrMember->second.m_szName.c_str(); // member's name
  447. }
  448. cmMessage << this->m_Name.c_str() // fellowship name
  449. << DWORD(this->m_LeaderGUID) // leader's GUID
  450. << 0x01L // unknown3
  451. << DWORD(this->m_ShareXP) // share Experience - 0x00 = no, 0x10 = yes (1 default)
  452. << DWORD(this->m_IsOpen) // open fellowship - 0x00 = no, 0x10 = yes (0 default)
  453. << 0x00L; // unknown4
  454. // << 0x00200000L // unknown5
  455. // << 0x00200000L;
  456. return cmMessage;
  457. }
  458. /**
  459. * Handles the message sent for disbanding the fellowship.
  460. *
  461. * @parem dwClGUID - The client's GUID.
  462. * @parem clF7B0Sequence - The client's present F7B0 sequence value.
  463. *
  464. * @return cMessage - Returns an 0x0000F7B0 server message.
  465. */
  466. cMessage cFellowship::DisbandMessage(DWORD dwClGUID, DWORD dwClF7B0Sequence)
  467. {
  468. cMessage cmMessage;
  469. cmMessage << 0xF7B0L
  470. << dwClGUID
  471. << dwClF7B0Sequence
  472. // << 0x0361L; //ToD
  473. << 0x00B3L;
  474. return cmMessage;
  475. }
  476. /**
  477. * Handles the message sent for updating the fellowship member's information.
  478. *
  479. * @parem dwClGUID - The client's GUID.
  480. * @parem clF7B0Sequence - The client's present F7B0 sequence value.
  481. * @parem clF7B0Sequence - The GUID for the member whose information has been updated.
  482. *
  483. * @return cMessage - Returns an 0x0000F7B0 server message.
  484. */
  485. cMessage cFellowship::UpdMemberMessage(DWORD dwClGUID, DWORD dwClF7B0Sequence, DWORD dwMemberGUID)
  486. {
  487. UpdateMember(dwMemberGUID);
  488. cMessage cmMessage;
  489. cmMessage << 0xF7B0L
  490. << dwClGUID
  491. << dwClF7B0Sequence
  492. // << 0x02C0L; //ToD
  493. << 0x00B0L;
  494. // vector of fellowship member count (1 per member)
  495. std::map<DWORD, FellowMem>::iterator itrMember;
  496. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  497. {
  498. if (dwMemberGUID == itrMember->second.m_dwGUID)
  499. {
  500. cmMessage << DWORD(itrMember->second.m_dwGUID) // this member's GUID
  501. << WORD(itrMember->second.m_wUnk1) // unknown1
  502. << WORD(itrMember->second.m_dwLevel) // Level
  503. << DWORD(itrMember->second.m_dwHealthTot) // maximum Health
  504. << DWORD(itrMember->second.m_dwStaminaTot) // maximum Stamina
  505. << DWORD(itrMember->second.m_dwManaTot) // maximum Mana
  506. << DWORD(itrMember->second.m_dwHealthCur) // current Health
  507. << DWORD(itrMember->second.m_dwStaminaCur) // current Stamina
  508. << DWORD(itrMember->second.m_dwManaCur) // current Mana
  509. << DWORD(itrMember->second.m_bShareLoot) // share loot - 0x00 = no, 0x10 = yes (0 default)
  510. << itrMember->second.m_szName.c_str(); // member's name
  511. }
  512. }
  513. cmMessage << 0x01L; // unknown; share Experience or Loot?
  514. return cmMessage;
  515. }
  516. /**
  517. * Handles the message sent for a player who has left the fellowship.
  518. *
  519. * @parem dwClGUID - The client's GUID.
  520. * @parem clF7B0Sequence - The client's present F7B0 sequence value.
  521. * @parem clF7B0Sequence - The GUID for the player who left the fellowship.
  522. *
  523. * @return cMessage - Returns an 0x0000F7B0 server message.
  524. */
  525. cMessage cFellowship::RemMemberMessage(DWORD dwClGUID, DWORD dwClF7B0Sequence, DWORD dwMemberGUID)
  526. {
  527. cMessage cmMessage;
  528. cmMessage << 0xF7B0L
  529. << dwClGUID
  530. << dwClF7B0Sequence
  531. // << 0x00A3L; //ToD
  532. << 0x00A7L;
  533. cmMessage << dwMemberGUID;
  534. return cmMessage;
  535. }
  536. /**
  537. * Handles the message sent for a player who has been dismissed from the fellowship.
  538. *
  539. * @parem dwClGUID - The client's GUID.
  540. * @parem clF7B0Sequence - The client's present F7B0 sequence value.
  541. * @parem clF7B0Sequence - The GUID for the player who been dismissed from the fellowship.
  542. *
  543. * @return cMessage - Returns an 0x0000F7B0 server message.
  544. */
  545. cMessage cFellowship::DisMemberMessage(DWORD dwClGUID, DWORD dwClF7B0Sequence, DWORD dwMemberGUID)
  546. {
  547. cMessage cmMessage;
  548. cmMessage << 0xF7B0L
  549. << dwClGUID
  550. << dwClF7B0Sequence
  551. // << 0x00A4L; //ToD
  552. << 0x00B1L;
  553. cmMessage << dwMemberGUID;
  554. return cmMessage;
  555. }
  556. /**
  557. * Handles the distribution of experience among fellowship members.
  558. *
  559. * This function only accounts for experience earned by fellowship members by hunting creatures.
  560. *
  561. * @parem dwMemberGUID - The GUID of the member who has earned the experience.
  562. * @parem memberLoc - The location of the member who has earned the experience.
  563. * @parem dwExperience - The amount of experience earned.
  564. */
  565. void cFellowship::DistributeXP(DWORD dwMemberGUID, cLocation memberLoc, DWORD dwExperience)
  566. {
  567. if (this->m_ShareXP)
  568. {
  569. if (this->m_ProportionXP)
  570. {
  571. std::map<DWORD, FellowMem>::iterator itrMember;
  572. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  573. {
  574. cClient* pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  575. if (pcClient)
  576. {
  577. cAvatar* pcAvatar = pcClient->m_pcAvatar;
  578. if (pcAvatar)
  579. {
  580. dwExperience = dwExperience * itrMember->second.m_fShareOfXP;
  581. pcAvatar->UpdateFellowshipExp(dwExperience);
  582. }
  583. }
  584. }
  585. }
  586. else
  587. {
  588. dwExperience = dwExperience * CalcFellowFactor(this->GetSize());
  589. std::map<DWORD, FellowMem>::iterator itrMember;
  590. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  591. {
  592. cClient* pcClient = cClient::FindClient(itrMember->second.m_dwGUID);
  593. if (pcClient)
  594. {
  595. cAvatar* pcAvatar = pcClient->m_pcAvatar;
  596. if (pcAvatar)
  597. {
  598. dwExperience = dwExperience * CalcDistanceFactor(memberLoc, pcAvatar->m_Location);
  599. pcAvatar->UpdateFellowshipExp(dwExperience);
  600. }
  601. }
  602. }
  603. }
  604. }
  605. else
  606. {
  607. cClient* pcClient = cClient::FindClient(dwMemberGUID);
  608. if (pcClient)
  609. {
  610. cAvatar* pcAvatar = pcClient->m_pcAvatar;
  611. if (pcAvatar)
  612. {
  613. pcAvatar->UpdateFellowshipExp(dwExperience);
  614. }
  615. }
  616. }
  617. }
  618. /**
  619. * Calculates the proportion by which to distribute experience among fellowship members.
  620. */
  621. void cFellowship::CalcShareXP()
  622. {
  623. int leaderLevel, levelDiff = 0;
  624. int minLevel = MAX_LEVEL;
  625. FellowMem* leader = this->FindMember(this->m_LeaderGUID);
  626. leaderLevel = leader->m_dwLevel;
  627. std::map<DWORD, FellowMem>::iterator itrMember;
  628. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  629. {
  630. if (abs(leaderLevel - itrMember->second.m_dwLevel) > levelDiff)
  631. levelDiff = abs(leaderLevel - itrMember->second.m_dwLevel);
  632. if (itrMember->second.m_dwLevel < minLevel)
  633. minLevel = itrMember->second.m_dwLevel;
  634. }
  635. if (levelDiff > 10 && minLevel < 50)
  636. {
  637. this->m_ProportionXP = true;
  638. CalcProportionXP(this->m_Size, levelDiff, minLevel);
  639. }
  640. else
  641. {
  642. this->m_ProportionXP = false;
  643. CalcNonProportionXP(this->m_Size);
  644. }
  645. }
  646. /**
  647. * Calculates the distribution of proportional experience among fellowship members.
  648. *
  649. * @parem numFellows - The number of fellows in the fellowship.
  650. * @parem levelDiff - The difference between the lowest and highest level members of the fellowship.
  651. * @parem minLevel - The lowest level of all members of the fellowship.
  652. */
  653. void cFellowship::CalcProportionXP(int numFellows, int levelDiff, int minLevel)
  654. {
  655. std::map<DWORD, FellowMem>::iterator itrMember;
  656. for ( itrMember = this->members.begin() ; itrMember != this->members.end() ; ++itrMember )
  657. {
  658. // TODO: Find true formula.
  659. itrMember->second.m_fShareOfXP = (100/numFellows) + (itrMember->second.m_dwLevel - minLevel);
  660. }
  661. }
  662. /**
  663. * Calculates the distribution of non-proportional experience among fellowship members.
  664. *
  665. * @parem numFellows - The number of fellows in the fellowship.
  666. */
  667. void cFellowship::CalcNonProportionXP(int numFellows)
  668. {
  669. }
  670. /**
  671. * Calculates the fellow factor for a fellowship.
  672. *
  673. * @parem numFellows - The number of fellows in the fellowship.
  674. *
  675. * @return float - Returns the fellowship factor.
  676. */
  677. float cFellowship::CalcFellowFactor(int numFellows)
  678. {
  679. /*
  680. Pre-ToD?:
  681. * 2 players in fellowship earn 75% of normal experience
  682. * 3 players in fellowship earn 60% of normal experience
  683. * 4 players in fellowship earn 55% of normal experience
  684. * 5 players in fellowship earn 50% of normal experience
  685. * 6 players in fellowship earn 45% of normal experience
  686. * 7 players in fellowship earn 40% of normal experience
  687. * 8 players in fellowship earn 35% of normal experience
  688. * 9 players in fellowship earn 31% of normal experience
  689. * 10 players in fellowship earn 28% of normal experience
  690. ToD:
  691. * 2 players in fellowship earn 75% of normal experience
  692. * 3 players in fellowship earn 60% of normal experience
  693. * 4 players in fellowship earn 55% of normal experience
  694. * 5 players in fellowship earn 50% of normal experience
  695. * 6 players in fellowship earn 45% of normal experience
  696. * 7 players in fellowship earn 40% of normal experience
  697. * 8 players in fellowship earn 35% of normal experience
  698. * 9 players in fellowship earn 30% of normal experience
  699. */
  700. float fellowFactor;
  701. if (OLD_PASSTHROUGH)
  702. {
  703. switch (numFellows)
  704. {
  705. case 1: fellowFactor = 1.00f; break;
  706. case 2: fellowFactor = 0.75f; break;
  707. case 3: fellowFactor = 0.60f; break;
  708. case 4: fellowFactor = 0.55f; break;
  709. case 5: fellowFactor = 0.50f; break;
  710. case 6: fellowFactor = 0.45f; break;
  711. case 7: fellowFactor = 0.40f; break;
  712. case 8: fellowFactor = 0.35f; break;
  713. case 9: fellowFactor = 0.31f; break;
  714. case 10: fellowFactor = 0.28f; break;
  715. default: fellowFactor = 1.00f; break;
  716. }
  717. }
  718. else
  719. {
  720. switch (numFellows)
  721. {
  722. case 1: fellowFactor = 1.00f; break;
  723. case 2: fellowFactor = 0.75f; break;
  724. case 3: fellowFactor = 0.60f; break;
  725. case 4: fellowFactor = 0.55f; break;
  726. case 5: fellowFactor = 0.50f; break;
  727. case 6: fellowFactor = 0.45f; break;
  728. case 7: fellowFactor = 0.40f; break;
  729. case 8: fellowFactor = 0.35f; break;
  730. case 9: fellowFactor = 0.30f; break;
  731. default: fellowFactor = 1.00f; break;
  732. }
  733. }
  734. return fellowFactor * SHARED_XP_MULT;
  735. }
  736. /**
  737. * Calculates the distance factor for a member of a fellowship.
  738. *
  739. * This function is used to determine how a member's experience earnings are affected
  740. * by his/her distance from the fellow that earned the experience.
  741. *
  742. * @parem earnMemLoc - The location of the fellow that earned the experience.
  743. * @parem recvMemLoc - The location of the fellow receiving apportioned experience.
  744. *
  745. * @return float - Returns the distance factor.
  746. */
  747. float cFellowship::CalcDistanceFactor(cLocation earnMemLoc, cLocation recvMemLoc)
  748. {
  749. // OLD: < ~8 = 100%; 48 ~= 50%
  750. // NEW: < ~2.5 = 100%; 5 ~= 0%
  751. float flDistance = cPhysics::GetRange(earnMemLoc, recvMemLoc);
  752. if (OLD_FELLOW_RANGE)
  753. {
  754. if (flDistance < 8 * FELLOW_RANGE_MULT)
  755. {
  756. return 1;
  757. }
  758. else
  759. {
  760. return 1; //TODO: formula
  761. }
  762. }
  763. else
  764. {
  765. if (flDistance < 2.5 * FELLOW_RANGE_MULT)
  766. {
  767. return 1;
  768. }
  769. else
  770. {
  771. return 1; //TODO: formula
  772. }
  773. }
  774. }