Advertisement
Guest User

Untitled

a guest
Aug 20th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.06 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "utils.h"
  3. #include "char.h"
  4. #include "party.h"
  5. #include "char_manager.h"
  6. #include "config.h"
  7. #include "p2p.h"
  8. #include "desc_client.h"
  9. #include "dungeon.h"
  10. #include "unique_item.h"
  11.  
  12. CPartyManager::CPartyManager()
  13. {
  14. Initialize();
  15. }
  16.  
  17. CPartyManager::~CPartyManager()
  18. {
  19. }
  20.  
  21. void CPartyManager::Initialize()
  22. {
  23. m_bEnablePCParty = false;
  24. }
  25.  
  26. void CPartyManager::DeleteAllParty()
  27. {
  28. TPCPartySet::iterator it = m_set_pkPCParty.begin();
  29.  
  30. while (it != m_set_pkPCParty.end())
  31. {
  32. DeleteParty(*it);
  33. it = m_set_pkPCParty.begin();
  34. }
  35. }
  36.  
  37. bool CPartyManager::SetParty(LPCHARACTER ch) // PC만 사용해야 한다!!
  38. {
  39. TPartyMap::iterator it = m_map_pkParty.find(ch->GetPlayerID());
  40.  
  41. if (it == m_map_pkParty.end())
  42. return false;
  43.  
  44. LPPARTY pParty = it->second;
  45. pParty->Link(ch);
  46. return true;
  47. }
  48.  
  49. void CPartyManager::P2PLogin(DWORD pid, const char* name)
  50. {
  51. TPartyMap::iterator it = m_map_pkParty.find(pid);
  52.  
  53. if (it == m_map_pkParty.end())
  54. return;
  55.  
  56. it->second->UpdateOnlineState(pid, name);
  57. }
  58. void CPartyManager::P2PLogout(DWORD pid)
  59. {
  60. TPartyMap::iterator it = m_map_pkParty.find(pid);
  61.  
  62. if (it == m_map_pkParty.end())
  63. return;
  64.  
  65. it->second->UpdateOfflineState(pid);
  66. }
  67.  
  68. void CPartyManager::P2PJoinParty(DWORD leader, DWORD pid, BYTE role)
  69. {
  70. TPartyMap::iterator it = m_map_pkParty.find(leader);
  71.  
  72. if (it != m_map_pkParty.end())
  73. {
  74. it->second->P2PJoin(pid);
  75.  
  76. if (role >= PARTY_ROLE_MAX_NUM)
  77. role = PARTY_ROLE_NORMAL;
  78.  
  79. it->second->SetRole(pid, role, true);
  80. }
  81. else
  82. {
  83. sys_err("No such party with leader [%d]", leader);
  84. }
  85. }
  86.  
  87. void CPartyManager::P2PQuitParty(DWORD pid)
  88. {
  89. TPartyMap::iterator it = m_map_pkParty.find(pid);
  90.  
  91. if (it != m_map_pkParty.end())
  92. {
  93. it->second->P2PQuit(pid);
  94. }
  95. else
  96. {
  97. sys_err("No such party with member [%d]", pid);
  98. }
  99. }
  100.  
  101. LPPARTY CPartyManager::P2PCreateParty(DWORD pid)
  102. {
  103. TPartyMap::iterator it = m_map_pkParty.find(pid);
  104. if (it != m_map_pkParty.end())
  105. return it->second;
  106.  
  107. LPPARTY pParty = M2_NEW CParty;
  108.  
  109. m_set_pkPCParty.insert(pParty);
  110.  
  111. SetPartyMember(pid, pParty);
  112. pParty->SetPCParty(true);
  113. pParty->P2PJoin(pid);
  114.  
  115. return pParty;
  116. }
  117.  
  118. void CPartyManager::P2PDeleteParty(DWORD pid)
  119. {
  120. TPartyMap::iterator it = m_map_pkParty.find(pid);
  121.  
  122. if (it != m_map_pkParty.end())
  123. {
  124. m_set_pkPCParty.erase(it->second);
  125. M2_DELETE(it->second);
  126. }
  127. else
  128. sys_err("PARTY P2PDeleteParty Cannot find party [%u]", pid);
  129. }
  130.  
  131. LPPARTY CPartyManager::CreateParty(LPCHARACTER pLeader)
  132. {
  133. if (pLeader->GetParty())
  134. return pLeader->GetParty();
  135.  
  136. LPPARTY pParty = M2_NEW CParty;
  137.  
  138. if (pLeader->IsPC())
  139. {
  140. //TPacketGGParty p;
  141. //p.header = HEADER_GG_PARTY;
  142. //p.subheader = PARTY_SUBHEADER_GG_CREATE;
  143. //p.pid = pLeader->GetPlayerID();
  144. //P2P_MANAGER::instance().Send(&p, sizeof(p));
  145. TPacketPartyCreate p;
  146. p.dwLeaderPID = pLeader->GetPlayerID();
  147.  
  148. db_clientdesc->DBPacket(HEADER_GD_PARTY_CREATE, 0, &p, sizeof(TPacketPartyCreate));
  149.  
  150. sys_log(0, "PARTY: Create %s pid %u", pLeader->GetName(), pLeader->GetPlayerID());
  151. pParty->SetPCParty(true);
  152. pParty->Join(pLeader->GetPlayerID());
  153.  
  154. m_set_pkPCParty.insert(pParty);
  155. }
  156. else
  157. {
  158. pParty->SetPCParty(false);
  159. pParty->Join(pLeader->GetVID());
  160. }
  161.  
  162. pParty->Link(pLeader);
  163. return (pParty);
  164. }
  165.  
  166. void CPartyManager::DeleteParty(LPPARTY pParty)
  167. {
  168. //TPacketGGParty p;
  169. //p.header = HEADER_GG_PARTY;
  170. //p.subheader = PARTY_SUBHEADER_GG_DESTROY;
  171. //p.pid = pParty->GetLeaderPID();
  172. //P2P_MANAGER::instance().Send(&p, sizeof(p));
  173. TPacketPartyDelete p;
  174. p.dwLeaderPID = pParty->GetLeaderPID();
  175.  
  176. db_clientdesc->DBPacket(HEADER_GD_PARTY_DELETE, 0, &p, sizeof(TPacketPartyDelete));
  177.  
  178. m_set_pkPCParty.erase(pParty);
  179. M2_DELETE(pParty);
  180. }
  181.  
  182. void CPartyManager::SetPartyMember(DWORD dwPID, LPPARTY pParty)
  183. {
  184. TPartyMap::iterator it = m_map_pkParty.find(dwPID);
  185.  
  186. if (pParty == NULL)
  187. {
  188. if (it != m_map_pkParty.end())
  189. m_map_pkParty.erase(it);
  190. }
  191. else
  192. {
  193. if (it != m_map_pkParty.end())
  194. {
  195. if (it->second != pParty)
  196. {
  197. it->second->Quit(dwPID);
  198. it->second = pParty;
  199. }
  200. }
  201. else
  202. m_map_pkParty.insert(TPartyMap::value_type(dwPID, pParty));
  203. }
  204. }
  205.  
  206. EVENTINFO(party_update_event_info)
  207. {
  208. DWORD pid;
  209.  
  210. party_update_event_info()
  211. : pid( 0 )
  212. {
  213. }
  214. };
  215.  
  216. /////////////////////////////////////////////////////////////////////////////
  217. //
  218. // CParty begin!
  219. //
  220. /////////////////////////////////////////////////////////////////////////////
  221. EVENTFUNC(party_update_event)
  222. {
  223. party_update_event_info* info = dynamic_cast<party_update_event_info*>( event->info );
  224.  
  225. if ( info == NULL )
  226. {
  227. sys_err( "party_update_event> <Factor> Null pointer" );
  228. return 0;
  229. }
  230.  
  231. DWORD pid = info->pid;
  232. LPCHARACTER leader = CHARACTER_MANAGER::instance().FindByPID(pid);
  233.  
  234. if (leader && leader->GetDesc())
  235. {
  236. LPPARTY pParty = leader->GetParty();
  237.  
  238. if (pParty)
  239. pParty->Update();
  240. }
  241.  
  242. return PASSES_PER_SEC(3);
  243. }
  244.  
  245. CParty::CParty()
  246. {
  247. Initialize();
  248. }
  249.  
  250. CParty::~CParty()
  251. {
  252. Destroy();
  253. }
  254.  
  255. void CParty::Initialize()
  256. {
  257. sys_log(2, "Party::Initialize");
  258.  
  259. m_iExpDistributionMode = PARTY_EXP_DISTRIBUTION_NON_PARITY;
  260. m_pkChrExpCentralize = NULL;
  261.  
  262. m_dwLeaderPID = 0;
  263.  
  264. m_eventUpdate = NULL;
  265.  
  266. memset(&m_anRoleCount, 0, sizeof(m_anRoleCount));
  267. memset(&m_anMaxRole, 0, sizeof(m_anMaxRole));
  268. m_anMaxRole[PARTY_ROLE_LEADER] = 1;
  269. m_anMaxRole[PARTY_ROLE_NORMAL] = 32;
  270.  
  271. m_dwPartyStartTime = get_dword_time();
  272. m_iLongTimeExpBonus = 0;
  273.  
  274. m_dwPartyHealTime = get_dword_time();
  275. m_bPartyHealReady = false;
  276. m_bCanUsePartyHeal = false;
  277.  
  278. m_iLeadership = 0;
  279. m_iExpBonus = 0;
  280. m_iAttBonus = 0;
  281. m_iDefBonus = 0;
  282.  
  283. m_itNextOwner = m_memberMap.begin();
  284.  
  285. m_iCountNearPartyMember = 0;
  286.  
  287. m_pkChrLeader = NULL;
  288. m_bPCParty = false;
  289. m_pkDungeon = NULL;
  290. m_pkDungeon_for_Only_party = NULL;
  291. }
  292.  
  293.  
  294. void CParty::Destroy()
  295. {
  296. sys_log(2, "Party::Destroy");
  297.  
  298. // PC가 만든 파티면 파티매니저에 맵에서 PID를 삭제해야 한다.
  299. if (m_bPCParty)
  300. {
  301. for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  302. CPartyManager::instance().SetPartyMember(it->first, NULL);
  303. }
  304.  
  305. event_cancel(&m_eventUpdate);
  306.  
  307. RemoveBonus();
  308.  
  309. TMemberMap::iterator it = m_memberMap.begin();
  310.  
  311. DWORD dwTime = get_dword_time();
  312.  
  313. while (it != m_memberMap.end())
  314. {
  315. TMember & rMember = it->second;
  316. ++it;
  317.  
  318. if (rMember.pCharacter)
  319. {
  320. if (rMember.pCharacter->GetDesc())
  321. {
  322. TPacketGCPartyRemove p;
  323. p.header = HEADER_GC_PARTY_REMOVE;
  324. p.pid = rMember.pCharacter->GetPlayerID();
  325. rMember.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  326. rMember.pCharacter->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티가 해산 되었습니다."));
  327. }
  328. else
  329. {
  330. // NPC일 경우 일정 시간 후 전투 중이 아닐 때 사라지게 하는 이벤트를 시작시킨다.
  331. rMember.pCharacter->SetLastAttacked(dwTime);
  332. rMember.pCharacter->StartDestroyWhenIdleEvent();
  333. }
  334.  
  335. rMember.pCharacter->SetParty(NULL);
  336. }
  337. }
  338.  
  339. m_memberMap.clear();
  340. m_itNextOwner = m_memberMap.begin();
  341.  
  342. if (m_pkDungeon_for_Only_party != NULL)
  343. {
  344. m_pkDungeon_for_Only_party->SetPartyNull();
  345. m_pkDungeon_for_Only_party = NULL;
  346. }
  347. }
  348.  
  349. void CParty::ChatPacketToAllMember(BYTE type, const char* format, ...)
  350. {
  351. char chatbuf[CHAT_MAX_LEN + 1];
  352. va_list args;
  353.  
  354. va_start(args, format);
  355. vsnprintf(chatbuf, sizeof(chatbuf), format, args);
  356. va_end(args);
  357.  
  358. TMemberMap::iterator it;
  359.  
  360. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  361. {
  362. TMember & rMember = it->second;
  363.  
  364. if (rMember.pCharacter)
  365. {
  366. if (rMember.pCharacter->GetDesc())
  367. {
  368. rMember.pCharacter->ChatPacket(type, "%s", chatbuf);
  369. }
  370. }
  371. }
  372. }
  373.  
  374. DWORD CParty::GetLeaderPID()
  375. {
  376. return m_dwLeaderPID;
  377. }
  378.  
  379. DWORD CParty::GetMemberCount()
  380. {
  381. return m_memberMap.size();
  382. }
  383.  
  384. void CParty::P2PJoin(DWORD dwPID)
  385. {
  386. TMemberMap::iterator it = m_memberMap.find(dwPID);
  387.  
  388. if (it == m_memberMap.end())
  389. {
  390. TMember Member;
  391.  
  392. Member.pCharacter = NULL;
  393. Member.bNear = false;
  394.  
  395. if (m_memberMap.empty())
  396. {
  397. Member.bRole = PARTY_ROLE_LEADER;
  398. m_dwLeaderPID = dwPID;
  399. }
  400. else
  401. Member.bRole = PARTY_ROLE_NORMAL;
  402.  
  403. if (m_bPCParty)
  404. {
  405. LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(dwPID);
  406.  
  407. if (ch)
  408. {
  409. sys_log(0, "PARTY: Join %s pid %u leader %u", ch->GetName(), dwPID, m_dwLeaderPID);
  410. Member.strName = ch->GetName();
  411.  
  412. if (Member.bRole == PARTY_ROLE_LEADER)
  413. m_iLeadership = ch->GetLeadershipSkillLevel();
  414. }
  415. else
  416. {
  417. CCI * pcci = P2P_MANAGER::instance().FindByPID(dwPID);
  418.  
  419. if (!pcci);
  420. else if (pcci->bChannel == g_bChannel)
  421. Member.strName = pcci->szName;
  422. else
  423. sys_err("member is not in same channel PID: %u channel %d, this channel %d", dwPID, pcci->bChannel, g_bChannel);
  424. }
  425. }
  426.  
  427. sys_log(2, "PARTY[%d] MemberCountChange %d -> %d", GetLeaderPID(), GetMemberCount(), GetMemberCount()+1);
  428.  
  429. m_memberMap.insert(TMemberMap::value_type(dwPID, Member));
  430.  
  431. if (m_memberMap.size() == 1)
  432. m_itNextOwner = m_memberMap.begin();
  433.  
  434. if (m_bPCParty)
  435. {
  436. CPartyManager::instance().SetPartyMember(dwPID, this);
  437. SendPartyJoinOneToAll(dwPID);
  438.  
  439. LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(dwPID);
  440.  
  441. if (ch)
  442. SendParameter(ch);
  443. }
  444. }
  445.  
  446. if (m_pkDungeon)
  447. {
  448. m_pkDungeon->QuitParty(this);
  449. }
  450. }
  451.  
  452. void CParty::Join(DWORD dwPID)
  453. {
  454. P2PJoin(dwPID);
  455.  
  456. if (m_bPCParty)
  457. {
  458. TPacketPartyAdd p;
  459. p.dwLeaderPID = GetLeaderPID();
  460. p.dwPID = dwPID;
  461. p.bState = PARTY_ROLE_NORMAL; // #0000790: [M2EU] CZ 크래쉬 증가: 초기화 중요!
  462. db_clientdesc->DBPacket(HEADER_GD_PARTY_ADD, 0, &p, sizeof(p));
  463. }
  464. }
  465.  
  466. void CParty::P2PQuit(DWORD dwPID)
  467. {
  468. TMemberMap::iterator it = m_memberMap.find(dwPID);
  469.  
  470. if (it == m_memberMap.end())
  471. return;
  472.  
  473. if (m_bPCParty)
  474. SendPartyRemoveOneToAll(dwPID);
  475.  
  476. if (it == m_itNextOwner)
  477. IncreaseOwnership();
  478.  
  479. if (m_bPCParty)
  480. RemoveBonusForOne(dwPID);
  481.  
  482. LPCHARACTER ch = it->second.pCharacter;
  483. BYTE bRole = it->second.bRole;
  484.  
  485. m_memberMap.erase(it);
  486.  
  487. sys_log(2, "PARTY[%d] MemberCountChange %d -> %d", GetLeaderPID(), GetMemberCount(), GetMemberCount() - 1);
  488.  
  489. if (bRole < PARTY_ROLE_MAX_NUM)
  490. {
  491. --m_anRoleCount[bRole];
  492. }
  493. else
  494. {
  495. sys_err("ROLE_COUNT_QUIT_ERROR: INDEX(%d) > MAX(%d)", bRole, PARTY_ROLE_MAX_NUM);
  496. }
  497.  
  498. if (ch)
  499. {
  500. ch->SetParty(NULL);
  501. ComputeRolePoint(ch, bRole, false);
  502. }
  503.  
  504. if (m_bPCParty)
  505. CPartyManager::instance().SetPartyMember(dwPID, NULL);
  506.  
  507. // 리더가 나가면 파티는 해산되어야 한다.
  508. if (bRole == PARTY_ROLE_LEADER)
  509. CPartyManager::instance().DeleteParty(this);
  510.  
  511. // 이 아래는 코드를 추가하지 말 것!!! 위 DeleteParty 하면 this는 없다.
  512. }
  513.  
  514. void CParty::Quit(DWORD dwPID)
  515. {
  516. // Always PC
  517. P2PQuit(dwPID);
  518.  
  519. if (m_bPCParty && dwPID != GetLeaderPID())
  520. {
  521. //TPacketGGParty p;
  522. //p.header = HEADER_GG_PARTY;
  523. //p.subheader = PARTY_SUBHEADER_GG_QUIT;
  524. //p.pid = dwPID;
  525. //p.leaderpid = GetLeaderPID();
  526. //P2P_MANAGER::instance().Send(&p, sizeof(p));
  527. TPacketPartyRemove p;
  528. p.dwPID = dwPID;
  529. p.dwLeaderPID = GetLeaderPID();
  530. db_clientdesc->DBPacket(HEADER_GD_PARTY_REMOVE, 0, &p, sizeof(p));
  531. }
  532. }
  533.  
  534. void CParty::Link(LPCHARACTER pkChr)
  535. {
  536. TMemberMap::iterator it;
  537.  
  538. if (pkChr->IsPC())
  539. it = m_memberMap.find(pkChr->GetPlayerID());
  540. else
  541. it = m_memberMap.find(pkChr->GetVID());
  542.  
  543. if (it == m_memberMap.end())
  544. {
  545. sys_err("%s is not member of this party", pkChr->GetName());
  546. return;
  547. }
  548.  
  549. // 플레이어 파티일 경우 업데이트 이벤트 생성
  550. if (m_bPCParty && !m_eventUpdate)
  551. {
  552. party_update_event_info* info = AllocEventInfo<party_update_event_info>();
  553. info->pid = m_dwLeaderPID;
  554. m_eventUpdate = event_create(party_update_event, info, PASSES_PER_SEC(3));
  555. }
  556.  
  557. if (it->second.bRole == PARTY_ROLE_LEADER)
  558. m_pkChrLeader = pkChr;
  559.  
  560. sys_log(2, "PARTY[%d] %s linked to party", GetLeaderPID(), pkChr->GetName());
  561.  
  562. it->second.pCharacter = pkChr;
  563. pkChr->SetParty(this);
  564.  
  565. if (pkChr->IsPC())
  566. {
  567. if (it->second.strName.empty())
  568. {
  569. it->second.strName = pkChr->GetName();
  570. }
  571.  
  572. SendPartyJoinOneToAll(pkChr->GetPlayerID());
  573.  
  574. SendPartyJoinAllToOne(pkChr);
  575. SendPartyLinkOneToAll(pkChr);
  576. SendPartyLinkAllToOne(pkChr);
  577. SendPartyInfoAllToOne(pkChr);
  578. SendPartyInfoOneToAll(pkChr);
  579.  
  580. SendParameter(pkChr);
  581.  
  582. //sys_log(0, "PARTY-DUNGEON connect %p %p", this, GetDungeon());
  583. if (GetDungeon() && GetDungeon()->GetMapIndex() == pkChr->GetMapIndex())
  584. {
  585. pkChr->SetDungeon(GetDungeon());
  586. }
  587.  
  588. RequestSetMemberLevel(pkChr->GetPlayerID(), pkChr->GetLevel());
  589.  
  590. }
  591. }
  592.  
  593. void CParty::RequestSetMemberLevel(DWORD pid, BYTE level)
  594. {
  595. TPacketPartySetMemberLevel p;
  596. p.dwLeaderPID = GetLeaderPID();
  597. p.dwPID = pid;
  598. p.bLevel = level;
  599. db_clientdesc->DBPacket(HEADER_GD_PARTY_SET_MEMBER_LEVEL, 0, &p, sizeof(TPacketPartySetMemberLevel));
  600. }
  601.  
  602. void CParty::P2PSetMemberLevel(DWORD pid, BYTE level)
  603. {
  604. if (!m_bPCParty)
  605. return;
  606.  
  607. TMemberMap::iterator it;
  608.  
  609. sys_log(0, "PARTY P2PSetMemberLevel leader %d pid %d level %d", GetLeaderPID(), pid, level);
  610.  
  611. it = m_memberMap.find(pid);
  612. if (it != m_memberMap.end())
  613. {
  614. it->second.bLevel = level;
  615. }
  616. }
  617.  
  618. namespace
  619. {
  620. struct FExitDungeon
  621. {
  622. void operator()(LPCHARACTER ch)
  623. {
  624. ch->ExitToSavedLocation();
  625. }
  626. };
  627. }
  628.  
  629. void CParty::Unlink(LPCHARACTER pkChr)
  630. {
  631. TMemberMap::iterator it;
  632.  
  633. if (pkChr->IsPC())
  634. it = m_memberMap.find(pkChr->GetPlayerID());
  635. else
  636. it = m_memberMap.find(pkChr->GetVID());
  637.  
  638. if (it == m_memberMap.end())
  639. {
  640. sys_err("%s is not member of this party", pkChr->GetName());
  641. return;
  642. }
  643.  
  644. if (pkChr->IsPC())
  645. {
  646. SendPartyUnlinkOneToAll(pkChr);
  647. //SendPartyUnlinkAllToOne(pkChr); // 끊기는 것이므로 구지 Unlink 패킷을 보낼 필요 없다.
  648.  
  649. if (it->second.bRole == PARTY_ROLE_LEADER)
  650. {
  651. RemoveBonus();
  652.  
  653. if (it->second.pCharacter->GetDungeon())
  654. {
  655. // TODO: 던젼에 있으면 나머지도 나간다
  656. FExitDungeon f;
  657. ForEachNearMember(f);
  658. }
  659. }
  660. }
  661.  
  662. if (it->second.bRole == PARTY_ROLE_LEADER)
  663. m_pkChrLeader = NULL;
  664.  
  665. it->second.pCharacter = NULL;
  666. pkChr->SetParty(NULL);
  667. }
  668.  
  669. void CParty::SendPartyRemoveOneToAll(DWORD pid)
  670. {
  671. TMemberMap::iterator it;
  672.  
  673. TPacketGCPartyRemove p;
  674. p.header = HEADER_GC_PARTY_REMOVE;
  675. p.pid = pid;
  676.  
  677. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  678. {
  679. if (it->second.pCharacter && it->second.pCharacter->GetDesc())
  680. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  681. }
  682. }
  683.  
  684. void CParty::SendPartyJoinOneToAll(DWORD pid)
  685. {
  686. const TMember& r = m_memberMap[pid];
  687.  
  688. TPacketGCPartyAdd p;
  689.  
  690. p.header = HEADER_GC_PARTY_ADD;
  691. p.pid = pid;
  692. strlcpy(p.name, r.strName.c_str(), sizeof(p.name));
  693.  
  694. for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  695. {
  696. if (it->second.pCharacter && it->second.pCharacter->GetDesc())
  697. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  698. }
  699. }
  700.  
  701. void CParty::SendPartyJoinAllToOne(LPCHARACTER ch)
  702. {
  703. if (!ch->GetDesc())
  704. return;
  705.  
  706. TPacketGCPartyAdd p;
  707.  
  708. p.header = HEADER_GC_PARTY_ADD;
  709. p.name[CHARACTER_NAME_MAX_LEN] = '\0';
  710.  
  711. for (TMemberMap::iterator it = m_memberMap.begin();it!= m_memberMap.end(); ++it)
  712. {
  713. p.pid = it->first;
  714. strlcpy(p.name, it->second.strName.c_str(), sizeof(p.name));
  715. ch->GetDesc()->Packet(&p, sizeof(p));
  716. }
  717. }
  718.  
  719. void CParty::SendPartyUnlinkOneToAll(LPCHARACTER ch)
  720. {
  721. if (!ch->GetDesc())
  722. return;
  723.  
  724. TMemberMap::iterator it;
  725.  
  726. TPacketGCPartyLink p;
  727. p.header = HEADER_GC_PARTY_UNLINK;
  728. p.pid = ch->GetPlayerID();
  729. p.vid = (DWORD)ch->GetVID();
  730.  
  731. for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it)
  732. {
  733. if (it->second.pCharacter && it->second.pCharacter->GetDesc())
  734. {
  735. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  736. }
  737. }
  738. }
  739.  
  740. void CParty::SendPartyLinkOneToAll(LPCHARACTER ch)
  741. {
  742. if (!ch->GetDesc())
  743. return;
  744.  
  745. TMemberMap::iterator it;
  746.  
  747. TPacketGCPartyLink p;
  748. p.header = HEADER_GC_PARTY_LINK;
  749. p.vid = ch->GetVID();
  750. p.pid = ch->GetPlayerID();
  751.  
  752. for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it)
  753. {
  754. if (it->second.pCharacter && it->second.pCharacter->GetDesc())
  755. {
  756. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  757. }
  758. }
  759. }
  760.  
  761. void CParty::SendPartyLinkAllToOne(LPCHARACTER ch)
  762. {
  763. if (!ch->GetDesc())
  764. return;
  765.  
  766. TMemberMap::iterator it;
  767.  
  768. TPacketGCPartyLink p;
  769. p.header = HEADER_GC_PARTY_LINK;
  770.  
  771. for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it)
  772. {
  773. if (it->second.pCharacter)
  774. {
  775. p.vid = it->second.pCharacter->GetVID();
  776. p.pid = it->second.pCharacter->GetPlayerID();
  777. ch->GetDesc()->Packet(&p, sizeof(p));
  778. }
  779. }
  780. }
  781.  
  782. void CParty::SendPartyInfoOneToAll(DWORD pid)
  783. {
  784. TMemberMap::iterator it = m_memberMap.find(pid);
  785.  
  786. if (it == m_memberMap.end())
  787. return;
  788.  
  789. if (it->second.pCharacter)
  790. {
  791. SendPartyInfoOneToAll(it->second.pCharacter);
  792. return;
  793. }
  794.  
  795. // Data Building
  796. TPacketGCPartyUpdate p;
  797. memset(&p, 0, sizeof(p));
  798. p.header = HEADER_GC_PARTY_UPDATE;
  799. p.pid = pid;
  800. p.percent_hp = 255;
  801. p.role = it->second.bRole;
  802.  
  803. for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it)
  804. {
  805. if ((it->second.pCharacter) && (it->second.pCharacter->GetDesc()))
  806. {
  807. //sys_log(2, "PARTY send info %s[%d] to %s[%d]", ch->GetName(), (DWORD)ch->GetVID(), it->second.pCharacter->GetName(), (DWORD)it->second.pCharacter->GetVID());
  808. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  809. }
  810. }
  811. }
  812.  
  813. void CParty::SendPartyInfoOneToAll(LPCHARACTER ch)
  814. {
  815. if (!ch->GetDesc())
  816. return;
  817.  
  818. TMemberMap::iterator it;
  819.  
  820. // Data Building
  821. TPacketGCPartyUpdate p;
  822. ch->BuildUpdatePartyPacket(p);
  823.  
  824. for (it = m_memberMap.begin();it!= m_memberMap.end(); ++it)
  825. {
  826. if ((it->second.pCharacter) && (it->second.pCharacter->GetDesc()))
  827. {
  828. sys_log(2, "PARTY send info %s[%d] to %s[%d]", ch->GetName(), (DWORD)ch->GetVID(), it->second.pCharacter->GetName(), (DWORD)it->second.pCharacter->GetVID());
  829. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  830. }
  831. }
  832. }
  833.  
  834. void CParty::SendPartyInfoAllToOne(LPCHARACTER ch)
  835. {
  836. TMemberMap::iterator it;
  837.  
  838. TPacketGCPartyUpdate p;
  839.  
  840. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  841. {
  842. if (!it->second.pCharacter)
  843. {
  844. DWORD pid = it->first;
  845. memset(&p, 0, sizeof(p));
  846. p.header = HEADER_GC_PARTY_UPDATE;
  847. p.pid = pid;
  848. p.percent_hp = 255;
  849. p.role = it->second.bRole;
  850. ch->GetDesc()->Packet(&p, sizeof(p));
  851. continue;
  852. }
  853.  
  854. it->second.pCharacter->BuildUpdatePartyPacket(p);
  855. sys_log(2, "PARTY send info %s[%d] to %s[%d]", it->second.pCharacter->GetName(), (DWORD)it->second.pCharacter->GetVID(), ch->GetName(), (DWORD)ch->GetVID());
  856. ch->GetDesc()->Packet(&p, sizeof(p));
  857. }
  858. }
  859.  
  860. void CParty::SendMessage(LPCHARACTER ch, BYTE bMsg, DWORD dwArg1, DWORD dwArg2)
  861. {
  862. if (ch->GetParty() != this)
  863. {
  864. sys_err("%s is not member of this party %p", ch->GetName(), this);
  865. return;
  866. }
  867.  
  868. switch (bMsg)
  869. {
  870. case PM_ATTACK:
  871. break;
  872.  
  873. case PM_RETURN:
  874. {
  875. TMemberMap::iterator it = m_memberMap.begin();
  876.  
  877. while (it != m_memberMap.end())
  878. {
  879. TMember & rMember = it->second;
  880. ++it;
  881.  
  882. LPCHARACTER pkChr;
  883.  
  884. if ((pkChr = rMember.pCharacter) && ch != pkChr)
  885. {
  886. DWORD x = dwArg1 + number(-500, 500);
  887. DWORD y = dwArg2 + number(-500, 500);
  888.  
  889. pkChr->SetVictim(NULL);
  890. pkChr->SetRotationToXY(x, y);
  891.  
  892. if (pkChr->Goto(x, y))
  893. {
  894. LPCHARACTER victim = pkChr->GetVictim();
  895. sys_log(0, "%s %p RETURN victim %p", pkChr->GetName(), get_pointer(pkChr), get_pointer(victim));
  896. pkChr->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
  897. }
  898. }
  899. }
  900. }
  901. break;
  902.  
  903. case PM_ATTACKED_BY: // 공격 받았음, 리더에게 도움을 요청
  904. {
  905. // 리더가 없을 때
  906. LPCHARACTER pkChrVictim = ch->GetVictim();
  907.  
  908. if (!pkChrVictim)
  909. return;
  910.  
  911. TMemberMap::iterator it = m_memberMap.begin();
  912.  
  913. while (it != m_memberMap.end())
  914. {
  915. TMember & rMember = it->second;
  916. ++it;
  917.  
  918. LPCHARACTER pkChr;
  919.  
  920. if ((pkChr = rMember.pCharacter) && ch != pkChr)
  921. {
  922. if (pkChr->CanBeginFight())
  923. pkChr->BeginFight(pkChrVictim);
  924. }
  925. }
  926. }
  927. break;
  928.  
  929. case PM_AGGRO_INCREASE:
  930. {
  931. LPCHARACTER victim = CHARACTER_MANAGER::instance().Find(dwArg2);
  932.  
  933. if (!victim)
  934. return;
  935.  
  936. TMemberMap::iterator it = m_memberMap.begin();
  937.  
  938. while (it != m_memberMap.end())
  939. {
  940. TMember & rMember = it->second;
  941. ++it;
  942.  
  943. LPCHARACTER pkChr;
  944.  
  945. if ((pkChr = rMember.pCharacter) && ch != pkChr)
  946. {
  947. pkChr->UpdateAggrPoint(victim, DAMAGE_TYPE_SPECIAL, dwArg1);
  948. }
  949. }
  950. }
  951. break;
  952. }
  953. }
  954.  
  955. LPCHARACTER CParty::GetLeaderCharacter()
  956. {
  957. return m_memberMap[GetLeaderPID()].pCharacter;
  958. }
  959.  
  960. bool CParty::SetRole(DWORD dwPID, BYTE bRole, bool bSet)
  961. {
  962. TMemberMap::iterator it = m_memberMap.find(dwPID);
  963.  
  964. if (it == m_memberMap.end())
  965. {
  966. return false;
  967. }
  968.  
  969. LPCHARACTER ch = it->second.pCharacter;
  970.  
  971. if (bSet)
  972. {
  973. if (m_anRoleCount[bRole] >= m_anMaxRole[bRole])
  974. return false;
  975.  
  976. if (it->second.bRole != PARTY_ROLE_NORMAL)
  977. return false;
  978.  
  979. it->second.bRole = bRole;
  980.  
  981. if (ch && GetLeader())
  982. ComputeRolePoint(ch, bRole, true);
  983.  
  984. if (bRole < PARTY_ROLE_MAX_NUM)
  985. {
  986. ++m_anRoleCount[bRole];
  987. }
  988. else
  989. {
  990. sys_err("ROLE_COUNT_INC_ERROR: INDEX(%d) > MAX(%d)", bRole, PARTY_ROLE_MAX_NUM);
  991. }
  992. }
  993. else
  994. {
  995. if (it->second.bRole == PARTY_ROLE_LEADER)
  996. return false;
  997.  
  998. if (it->second.bRole == PARTY_ROLE_NORMAL)
  999. return false;
  1000.  
  1001. it->second.bRole = PARTY_ROLE_NORMAL;
  1002.  
  1003. if (ch && GetLeader())
  1004. ComputeRolePoint(ch, PARTY_ROLE_NORMAL, false);
  1005.  
  1006. if (bRole < PARTY_ROLE_MAX_NUM)
  1007. {
  1008. --m_anRoleCount[bRole];
  1009. }
  1010. else
  1011. {
  1012. sys_err("ROLE_COUNT_DEC_ERROR: INDEX(%d) > MAX(%d)", bRole, PARTY_ROLE_MAX_NUM);
  1013. }
  1014. }
  1015.  
  1016. SendPartyInfoOneToAll(dwPID);
  1017. return true;
  1018. }
  1019.  
  1020. BYTE CParty::GetRole(DWORD pid)
  1021. {
  1022. TMemberMap::iterator it = m_memberMap.find(pid);
  1023.  
  1024. if (it == m_memberMap.end())
  1025. return PARTY_ROLE_NORMAL;
  1026. else
  1027. return it->second.bRole;
  1028. }
  1029.  
  1030. bool CParty::IsRole(DWORD pid, BYTE bRole)
  1031. {
  1032. TMemberMap::iterator it = m_memberMap.find(pid);
  1033.  
  1034. if (it == m_memberMap.end())
  1035. return false;
  1036.  
  1037. return it->second.bRole == bRole;
  1038. }
  1039.  
  1040. void CParty::RemoveBonus()
  1041. {
  1042. TMemberMap::iterator it;
  1043.  
  1044. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1045. {
  1046. LPCHARACTER ch;
  1047.  
  1048. if ((ch = it->second.pCharacter))
  1049. {
  1050. ComputeRolePoint(ch, it->second.bRole, false);
  1051. }
  1052.  
  1053. it->second.bNear = false;
  1054. }
  1055. }
  1056.  
  1057. void CParty::RemoveBonusForOne(DWORD pid)
  1058. {
  1059. TMemberMap::iterator it = m_memberMap.find(pid);
  1060.  
  1061. if (it == m_memberMap.end())
  1062. return;
  1063.  
  1064. LPCHARACTER ch;
  1065.  
  1066. if ((ch = it->second.pCharacter))
  1067. ComputeRolePoint(ch, it->second.bRole, false);
  1068. }
  1069.  
  1070. void CParty::HealParty()
  1071. {
  1072. // XXX DELETEME 클라이언트 완료될때까지
  1073. {
  1074. return;
  1075. }
  1076. if (!m_bPartyHealReady)
  1077. return;
  1078.  
  1079. TMemberMap::iterator it;
  1080. LPCHARACTER l = GetLeaderCharacter();
  1081.  
  1082. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1083. {
  1084. if (!it->second.pCharacter)
  1085. continue;
  1086.  
  1087. LPCHARACTER ch = it->second.pCharacter;
  1088.  
  1089. if (DISTANCE_APPROX(l->GetX()-ch->GetX(), l->GetY()-ch->GetY()) < PARTY_DEFAULT_RANGE)
  1090. {
  1091. ch->PointChange(POINT_HP, ch->GetMaxHP()-ch->GetHP());
  1092. ch->PointChange(POINT_SP, ch->GetMaxSP()-ch->GetSP());
  1093. }
  1094. }
  1095.  
  1096. m_bPartyHealReady = false;
  1097. m_dwPartyHealTime = get_dword_time();
  1098. }
  1099.  
  1100. void CParty::SummonToLeader(DWORD pid)
  1101. {
  1102. int xy[12][2] =
  1103. {
  1104. { 250, 0 },
  1105. { 216, 125 },
  1106. { 125, 216 },
  1107. { 0, 250 },
  1108. { -125, 216 },
  1109. { -216, 125 },
  1110. { -250, 0 },
  1111. { -216, -125 },
  1112. { -125, -216 },
  1113. { 0, -250 },
  1114. { 125, -216 },
  1115. { 216, -125 },
  1116. };
  1117.  
  1118. int n = 0;
  1119. int x[12], y[12];
  1120.  
  1121. SECTREE_MANAGER & s = SECTREE_MANAGER::instance();
  1122. LPCHARACTER l = GetLeaderCharacter();
  1123.  
  1124. if (m_memberMap.find(pid) == m_memberMap.end())
  1125. {
  1126. l->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 소환하려는 대상을 찾을 수 없습니다."));
  1127. return;
  1128. }
  1129.  
  1130. LPCHARACTER ch = m_memberMap[pid].pCharacter;
  1131.  
  1132. if (!ch)
  1133. {
  1134. l->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 소환하려는 대상을 찾을 수 없습니다."));
  1135. return;
  1136. }
  1137.  
  1138. if (!ch->CanSummon(m_iLeadership))
  1139. {
  1140. l->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 대상을 소환할 수 없습니다."));
  1141. return;
  1142. }
  1143.  
  1144. for (int i = 0; i < 12; ++i)
  1145. {
  1146. PIXEL_POSITION p;
  1147.  
  1148. if (s.GetMovablePosition(l->GetMapIndex(), l->GetX() + xy [i][0], l->GetY() + xy[i][1], p))
  1149. {
  1150. x[n] = p.x;
  1151. y[n] = p.y;
  1152. n++;
  1153. }
  1154. }
  1155.  
  1156. if (n == 0)
  1157. l->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<파티> 파티원을 현재 위치로 소환할 수 없습니다."));
  1158. else
  1159. {
  1160. int i = number(0, n - 1);
  1161. ch->Show(l->GetMapIndex(), x[i], y[i]);
  1162. ch->Stop();
  1163. }
  1164. }
  1165.  
  1166. void CParty::IncreaseOwnership()
  1167. {
  1168. if (m_memberMap.empty())
  1169. {
  1170. m_itNextOwner = m_memberMap.begin();
  1171. return;
  1172. }
  1173.  
  1174. if (m_itNextOwner == m_memberMap.end())
  1175. m_itNextOwner = m_memberMap.begin();
  1176. else
  1177. {
  1178. m_itNextOwner++;
  1179.  
  1180. if (m_itNextOwner == m_memberMap.end())
  1181. m_itNextOwner = m_memberMap.begin();
  1182. }
  1183. }
  1184.  
  1185. LPCHARACTER CParty::GetNextOwnership(LPCHARACTER ch, long x, long y)
  1186. {
  1187. if (m_itNextOwner == m_memberMap.end())
  1188. return ch;
  1189.  
  1190. int size = m_memberMap.size();
  1191.  
  1192. while (size-- > 0)
  1193. {
  1194. LPCHARACTER pkMember = m_itNextOwner->second.pCharacter;
  1195.  
  1196. if (pkMember && DISTANCE_APPROX(pkMember->GetX() - x, pkMember->GetY() - y) < 3000)
  1197. {
  1198. IncreaseOwnership();
  1199. return pkMember;
  1200. }
  1201.  
  1202. IncreaseOwnership();
  1203. }
  1204.  
  1205. return ch;
  1206. }
  1207.  
  1208. void CParty::ComputeRolePoint(LPCHARACTER ch, BYTE bRole, bool bAdd)
  1209. {
  1210. if (!bAdd)
  1211. {
  1212. ch->PointChange(POINT_PARTY_ATTACKER_BONUS, -ch->GetPoint(POINT_PARTY_ATTACKER_BONUS));
  1213. ch->PointChange(POINT_PARTY_TANKER_BONUS, -ch->GetPoint(POINT_PARTY_TANKER_BONUS));
  1214. ch->PointChange(POINT_PARTY_BUFFER_BONUS, -ch->GetPoint(POINT_PARTY_BUFFER_BONUS));
  1215. ch->PointChange(POINT_PARTY_SKILL_MASTER_BONUS, -ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS));
  1216. ch->PointChange(POINT_PARTY_DEFENDER_BONUS, -ch->GetPoint(POINT_PARTY_DEFENDER_BONUS));
  1217. ch->PointChange(POINT_PARTY_HASTE_BONUS, -ch->GetPoint(POINT_PARTY_HASTE_BONUS));
  1218. ch->ComputeBattlePoints();
  1219. return;
  1220. }
  1221.  
  1222. //SKILL_POWER_BY_LEVEL
  1223. float k = (float) ch->GetSkillPowerByLevel( MIN(SKILL_MAX_LEVEL, m_iLeadership ) )/ 100.0f;
  1224. //float k = (float) aiSkillPowerByLevel[MIN(SKILL_MAX_LEVEL, m_iLeadership)] / 100.0f;
  1225. //
  1226. //sys_log(0,"ComputeRolePoint %fi %d, %d ", k, SKILL_MAX_LEVEL, m_iLeadership );
  1227. //END_SKILL_POWER_BY_LEVEL
  1228.  
  1229. switch (bRole)
  1230. {
  1231. case PARTY_ROLE_ATTACKER:
  1232. {
  1233. //int iBonus = (int) (10 + 90 * k);
  1234. int iBonus = (int) (10 + 60 * k);
  1235.  
  1236. if (ch->GetPoint(POINT_PARTY_ATTACKER_BONUS) != iBonus)
  1237. {
  1238. ch->PointChange(POINT_PARTY_ATTACKER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_ATTACKER_BONUS));
  1239. ch->ComputePoints();
  1240. }
  1241. }
  1242. break;
  1243.  
  1244. case PARTY_ROLE_TANKER:
  1245. {
  1246. int iBonus = (int) (50 + 1450 * k);
  1247.  
  1248. if (ch->GetPoint(POINT_PARTY_TANKER_BONUS) != iBonus)
  1249. {
  1250. ch->PointChange(POINT_PARTY_TANKER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_TANKER_BONUS));
  1251. ch->ComputePoints();
  1252. }
  1253. }
  1254. break;
  1255.  
  1256. case PARTY_ROLE_BUFFER:
  1257. {
  1258. int iBonus = (int) (5 + 45 * k);
  1259.  
  1260. if (ch->GetPoint(POINT_PARTY_BUFFER_BONUS) != iBonus)
  1261. {
  1262. ch->PointChange(POINT_PARTY_BUFFER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_BUFFER_BONUS));
  1263. }
  1264. }
  1265. break;
  1266.  
  1267. case PARTY_ROLE_SKILL_MASTER:
  1268. {
  1269. int iBonus = (int) (25 + 600 * k);
  1270.  
  1271. if (ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS) != iBonus)
  1272. {
  1273. ch->PointChange(POINT_PARTY_SKILL_MASTER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS));
  1274. ch->ComputePoints();
  1275. }
  1276. }
  1277. break;
  1278. case PARTY_ROLE_HASTE:
  1279. {
  1280. int iBonus = (int) (1+5*k);
  1281. if (ch->GetPoint(POINT_PARTY_HASTE_BONUS) != iBonus)
  1282. {
  1283. ch->PointChange(POINT_PARTY_HASTE_BONUS, iBonus - ch->GetPoint(POINT_PARTY_HASTE_BONUS));
  1284. ch->ComputePoints();
  1285. }
  1286. }
  1287. break;
  1288. case PARTY_ROLE_DEFENDER:
  1289. {
  1290. int iBonus = (int) (5+30*k);
  1291. if (ch->GetPoint(POINT_PARTY_DEFENDER_BONUS) != iBonus)
  1292. {
  1293. ch->PointChange(POINT_PARTY_DEFENDER_BONUS, iBonus - ch->GetPoint(POINT_PARTY_DEFENDER_BONUS));
  1294. ch->ComputePoints();
  1295. }
  1296. }
  1297. break;
  1298. }
  1299. }
  1300.  
  1301. void CParty::Update()
  1302. {
  1303. sys_log(1, "PARTY::Update");
  1304.  
  1305. LPCHARACTER l = GetLeaderCharacter();
  1306.  
  1307. if (!l)
  1308. return;
  1309.  
  1310. TMemberMap::iterator it;
  1311.  
  1312. int iNearMember = 0;
  1313. bool bResendAll = false;
  1314.  
  1315. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1316. {
  1317. LPCHARACTER ch = it->second.pCharacter;
  1318.  
  1319. it->second.bNear = false;
  1320.  
  1321. if (!ch)
  1322. continue;
  1323.  
  1324. if (l->GetDungeon())
  1325. it->second.bNear = l->GetDungeon() == ch->GetDungeon();
  1326. else
  1327. it->second.bNear = (DISTANCE_APPROX(l->GetX()-ch->GetX(), l->GetY()-ch->GetY()) < PARTY_DEFAULT_RANGE);
  1328.  
  1329. if (it->second.bNear)
  1330. {
  1331. ++iNearMember;
  1332. //sys_log(0,"NEAR %s", ch->GetName());
  1333. }
  1334. }
  1335.  
  1336. if (iNearMember <= 1 && !l->GetDungeon())
  1337. {
  1338. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1339. it->second.bNear = false;
  1340.  
  1341. iNearMember = 0;
  1342. }
  1343.  
  1344. if (iNearMember != m_iCountNearPartyMember)
  1345. {
  1346. m_iCountNearPartyMember = iNearMember;
  1347. bResendAll = true;
  1348. }
  1349.  
  1350. m_iLeadership = l->GetLeadershipSkillLevel();
  1351. int iNewExpBonus = ComputePartyBonusExpPercent();
  1352. m_iAttBonus = ComputePartyBonusAttackGrade();
  1353. m_iDefBonus = ComputePartyBonusDefenseGrade();
  1354.  
  1355. if (m_iExpBonus != iNewExpBonus)
  1356. {
  1357. bResendAll = true;
  1358. m_iExpBonus = iNewExpBonus;
  1359. }
  1360.  
  1361. bool bLongTimeExpBonusChanged = false;
  1362.  
  1363. // 파티 결성 후 충분한 시간이 지나면 경험치 보너스를 받는다.
  1364. if (!m_iLongTimeExpBonus && (get_dword_time() - m_dwPartyStartTime > PARTY_ENOUGH_MINUTE_FOR_EXP_BONUS * 60 * 1000 / (g_iUseLocale?1:2)))
  1365. {
  1366. bLongTimeExpBonusChanged = true;
  1367. m_iLongTimeExpBonus = 5;
  1368. bResendAll = true;
  1369. }
  1370.  
  1371. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1372. {
  1373. LPCHARACTER ch = it->second.pCharacter;
  1374.  
  1375. if (!ch)
  1376. continue;
  1377.  
  1378. if (bLongTimeExpBonusChanged && ch->GetDesc())
  1379. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("파티의 협동력이 높아져 지금부터 추가 경험치 보너스를 받습니다."));
  1380.  
  1381. bool bNear = it->second.bNear;
  1382.  
  1383. ComputeRolePoint(ch, it->second.bRole, bNear);
  1384.  
  1385. if (bNear)
  1386. {
  1387. if (!bResendAll)
  1388. SendPartyInfoOneToAll(ch);
  1389. }
  1390. }
  1391.  
  1392. // PARTY_ROLE_LIMIT_LEVEL_BUG_FIX
  1393. m_anMaxRole[PARTY_ROLE_ATTACKER] = m_iLeadership >= 10 ? 1 : 0;
  1394. m_anMaxRole[PARTY_ROLE_HASTE] = m_iLeadership >= 20 ? 1 : 0;
  1395. m_anMaxRole[PARTY_ROLE_TANKER] = m_iLeadership >= 20 ? 1 : 0;
  1396. m_anMaxRole[PARTY_ROLE_BUFFER] = m_iLeadership >= 25 ? 1 : 0;
  1397. m_anMaxRole[PARTY_ROLE_SKILL_MASTER] = m_iLeadership >= 35 ? 1 : 0;
  1398. m_anMaxRole[PARTY_ROLE_DEFENDER] = m_iLeadership >= 40 ? 1 : 0;
  1399. m_anMaxRole[PARTY_ROLE_ATTACKER] += m_iLeadership >= 40 ? 1 : 0;
  1400. // END_OF_PARTY_ROLE_LIMIT_LEVEL_BUG_FIX
  1401.  
  1402. // Party Heal Update
  1403. if (!m_bPartyHealReady)
  1404. {
  1405. if (!m_bCanUsePartyHeal && m_iLeadership >= 18)
  1406. m_dwPartyHealTime = get_dword_time();
  1407.  
  1408. m_bCanUsePartyHeal = m_iLeadership >= 18; // 통솔력 18 이상은 힐을 사용할 수 있음.
  1409.  
  1410. // 통솔력 40이상은 파티 힐 쿨타임이 적다.
  1411. DWORD PartyHealCoolTime = (m_iLeadership >= 40) ? PARTY_HEAL_COOLTIME_SHORT * 60 * 1000 : PARTY_HEAL_COOLTIME_LONG * 60 * 1000;
  1412.  
  1413. if (m_bCanUsePartyHeal)
  1414. {
  1415. if (get_dword_time() > m_dwPartyHealTime + PartyHealCoolTime)
  1416. {
  1417. m_bPartyHealReady = true;
  1418.  
  1419. // send heal ready
  1420. if (0) // XXX DELETEME 클라이언트 완료될때까지
  1421. if (GetLeaderCharacter())
  1422. GetLeaderCharacter()->ChatPacket(CHAT_TYPE_COMMAND, "PartyHealReady");
  1423. }
  1424. }
  1425. }
  1426.  
  1427. if (bResendAll)
  1428. {
  1429. for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1430. if (it->second.pCharacter)
  1431. SendPartyInfoOneToAll(it->second.pCharacter);
  1432. }
  1433. }
  1434.  
  1435. void CParty::UpdateOnlineState(DWORD dwPID, const char* name)
  1436. {
  1437. TMember& r = m_memberMap[dwPID];
  1438.  
  1439. TPacketGCPartyAdd p;
  1440.  
  1441. p.header = HEADER_GC_PARTY_ADD;
  1442. p.pid = dwPID;
  1443. r.strName = name;
  1444. strlcpy(p.name, name, sizeof(p.name));
  1445.  
  1446. for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1447. {
  1448. if (it->second.pCharacter && it->second.pCharacter->GetDesc())
  1449. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  1450. }
  1451. }
  1452. void CParty::UpdateOfflineState(DWORD dwPID)
  1453. {
  1454. TPacketGCPartyAdd p;
  1455. p.header = HEADER_GC_PARTY_ADD;
  1456. p.pid = dwPID;
  1457. memset(p.name, 0, CHARACTER_NAME_MAX_LEN + 1);
  1458. for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1459. {
  1460. if (it->second.pCharacter && it->second.pCharacter->GetDesc())
  1461. {
  1462. if (it->second.pCharacter->GetDungeon())
  1463. it->second.pCharacter->GetDungeon()->ExitAllToStartPosition();
  1464. else
  1465. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  1466. }
  1467. }
  1468. }
  1469.  
  1470.  
  1471. int CParty::GetFlag(const std::string& name)
  1472. {
  1473. TFlagMap::iterator it = m_map_iFlag.find(name);
  1474.  
  1475. if (it != m_map_iFlag.end())
  1476. {
  1477. //sys_log(0,"PARTY GetFlag %s %d", name.c_str(), it->second);
  1478. return it->second;
  1479. }
  1480.  
  1481. //sys_log(0,"PARTY GetFlag %s 0", name.c_str());
  1482. return 0;
  1483. }
  1484.  
  1485. void CParty::SetFlag(const std::string& name, int value)
  1486. {
  1487. TFlagMap::iterator it = m_map_iFlag.find(name);
  1488.  
  1489. //sys_log(0,"PARTY SetFlag %s %d", name.c_str(), value);
  1490. if (it == m_map_iFlag.end())
  1491. {
  1492. m_map_iFlag.insert(make_pair(name, value));
  1493. }
  1494. else if (it->second != value)
  1495. {
  1496. it->second = value;
  1497. }
  1498. }
  1499.  
  1500. void CParty::SetDungeon(LPDUNGEON pDungeon)
  1501. {
  1502. m_pkDungeon = pDungeon;
  1503. m_map_iFlag.clear();
  1504. }
  1505.  
  1506. LPDUNGEON CParty::GetDungeon()
  1507. {
  1508. return m_pkDungeon;
  1509. }
  1510.  
  1511. void CParty::SetDungeon_for_Only_party(LPDUNGEON pDungeon)
  1512. {
  1513. m_pkDungeon_for_Only_party = pDungeon;
  1514. }
  1515.  
  1516. LPDUNGEON CParty::GetDungeon_for_Only_party()
  1517. {
  1518. return m_pkDungeon_for_Only_party;
  1519. }
  1520.  
  1521.  
  1522. bool CParty::IsPositionNearLeader(LPCHARACTER ch)
  1523. {
  1524. if (!m_pkChrLeader)
  1525. return false;
  1526.  
  1527. if (DISTANCE_APPROX(ch->GetX() - m_pkChrLeader->GetX(), ch->GetY() - m_pkChrLeader->GetY()) >= PARTY_DEFAULT_RANGE)
  1528. return false;
  1529.  
  1530. return true;
  1531. }
  1532.  
  1533.  
  1534. int CParty::GetExpBonusPercent()
  1535. {
  1536. if (GetNearMemberCount() <= 1)
  1537. return 0;
  1538.  
  1539. return m_iExpBonus + m_iLongTimeExpBonus;
  1540. }
  1541.  
  1542. bool CParty::IsNearLeader(DWORD pid)
  1543. {
  1544. TMemberMap::iterator it = m_memberMap.find(pid);
  1545.  
  1546. if (it == m_memberMap.end())
  1547. return false;
  1548.  
  1549. return it->second.bNear;
  1550. }
  1551.  
  1552. BYTE CParty::CountMemberByVnum(DWORD dwVnum)
  1553. {
  1554. if (m_bPCParty)
  1555. return 0;
  1556.  
  1557. LPCHARACTER tch;
  1558. BYTE bCount = 0;
  1559.  
  1560. TMemberMap::iterator it;
  1561.  
  1562. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1563. {
  1564. if (!(tch = it->second.pCharacter))
  1565. continue;
  1566.  
  1567. if (tch->IsPC())
  1568. continue;
  1569.  
  1570. if (tch->GetMobTable().dwVnum == dwVnum)
  1571. ++bCount;
  1572. }
  1573.  
  1574. return bCount;
  1575. }
  1576.  
  1577. void CParty::SendParameter(LPCHARACTER ch)
  1578. {
  1579. TPacketGCPartyParameter p;
  1580.  
  1581. p.bHeader = HEADER_GC_PARTY_PARAMETER;
  1582. p.bDistributeMode = m_iExpDistributionMode;
  1583.  
  1584. LPDESC d = ch->GetDesc();
  1585.  
  1586. if (d)
  1587. {
  1588. d->Packet(&p, sizeof(TPacketGCPartyParameter));
  1589. }
  1590. }
  1591.  
  1592. void CParty::SendParameterToAll()
  1593. {
  1594. if (!m_bPCParty)
  1595. return;
  1596.  
  1597. TMemberMap::iterator it;
  1598.  
  1599. for (it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1600. if (it->second.pCharacter)
  1601. SendParameter(it->second.pCharacter);
  1602. }
  1603.  
  1604. void CParty::SetParameter(int iMode)
  1605. {
  1606. if (iMode >= PARTY_EXP_DISTRIBUTION_MAX_NUM)
  1607. {
  1608. sys_err("Invalid exp distribution mode %d", iMode);
  1609. return;
  1610. }
  1611.  
  1612. m_iExpDistributionMode = iMode;
  1613. SendParameterToAll();
  1614. }
  1615.  
  1616. int CParty::GetExpDistributionMode()
  1617. {
  1618. return m_iExpDistributionMode;
  1619. }
  1620.  
  1621. void CParty::SetExpCentralizeCharacter(DWORD dwPID)
  1622. {
  1623. TMemberMap::iterator it = m_memberMap.find(dwPID);
  1624.  
  1625. if (it == m_memberMap.end())
  1626. return;
  1627.  
  1628. m_pkChrExpCentralize = it->second.pCharacter;
  1629. }
  1630.  
  1631. LPCHARACTER CParty::GetExpCentralizeCharacter()
  1632. {
  1633. return m_pkChrExpCentralize;
  1634. }
  1635.  
  1636. BYTE CParty::GetMemberMaxLevel()
  1637. {
  1638. BYTE bMax = 0;
  1639.  
  1640. itertype(m_memberMap) it = m_memberMap.begin();
  1641. while (it!=m_memberMap.end())
  1642. {
  1643. if (!it->second.bLevel)
  1644. {
  1645. ++it;
  1646. continue;
  1647. }
  1648.  
  1649. if (!bMax)
  1650. bMax = it->second.bLevel;
  1651. else if (it->second.bLevel)
  1652. bMax = MAX(bMax, it->second.bLevel);
  1653. ++it;
  1654. }
  1655. return bMax;
  1656. }
  1657.  
  1658. BYTE CParty::GetMemberMinLevel()
  1659. {
  1660. BYTE bMin = PLAYER_MAX_LEVEL_CONST;
  1661.  
  1662. itertype(m_memberMap) it = m_memberMap.begin();
  1663. while (it!=m_memberMap.end())
  1664. {
  1665. if (!it->second.bLevel)
  1666. {
  1667. ++it;
  1668. continue;
  1669. }
  1670.  
  1671. if (!bMin)
  1672. bMin = it->second.bLevel;
  1673. else if (it->second.bLevel)
  1674. bMin = MIN(bMin, it->second.bLevel);
  1675. ++it;
  1676. }
  1677. return bMin;
  1678. }
  1679.  
  1680. int CParty::ComputePartyBonusExpPercent()
  1681. {
  1682. if (GetNearMemberCount() <= 1)
  1683. return 0;
  1684.  
  1685. LPCHARACTER leader = GetLeaderCharacter();
  1686.  
  1687. int iBonusPartyExpFromItem = 0;
  1688.  
  1689. // UPGRADE_PARTY_BONUS
  1690. int iMemberCount=MIN(8, GetNearMemberCount());
  1691.  
  1692. if (leader && (leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP) || leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP_MALL)
  1693. || leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP_GIFT) || leader->IsEquipUniqueGroup(10010)))
  1694. {
  1695. // 중국측 육도 적용을 확인해야한다.
  1696. if (g_iUseLocale)
  1697. {
  1698. iBonusPartyExpFromItem = 30;
  1699. }
  1700. else
  1701. {
  1702. iBonusPartyExpFromItem = KOR_aiUniqueItemPartyBonusExpPercentByMemberCount[iMemberCount];
  1703. }
  1704. }
  1705.  
  1706. if (g_iUseLocale)
  1707. return iBonusPartyExpFromItem + CHN_aiPartyBonusExpPercentByMemberCount[iMemberCount];
  1708. else
  1709. return iBonusPartyExpFromItem + KOR_aiPartyBonusExpPercentByMemberCount[iMemberCount];
  1710. // END_OF_UPGRADE_PARTY_BONUS
  1711. }
  1712.  
  1713. void CParty::UpdateOfflineState(DWORD dwPID)
  1714. {
  1715. TPacketGCPartyAdd p;
  1716. p.header = HEADER_GC_PARTY_ADD;
  1717. p.pid = dwPID;
  1718. memset(p.name, 0, CHARACTER_NAME_MAX_LEN+1);
  1719. for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
  1720. {
  1721. if (it->second.pCharacter && it->second.pCharacter->GetDesc()) {
  1722. if (it->second.pCharacter->GetDungeon()) {
  1723. LPDUNGEON dung=it->second.pCharacter->GetDungeon();
  1724. dung->ExitAllToStartPosition();
  1725. }else{
  1726. it->second.pCharacter->GetDesc()->Packet(&p, sizeof(p));
  1727. }
  1728. }
  1729. }
  1730. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement