Guest User

pvp.cpp

a guest
Nov 11th, 2024
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.49 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "constants.h"
  3. #include "pvp.h"
  4. #include "crc32.h"
  5. #include "packet.h"
  6. #include "desc.h"
  7. #include "desc_manager.h"
  8. #include "char.h"
  9. #include "char_manager.h"
  10. #include "config.h"
  11. #include "sectree_manager.h"
  12. #include "buffer_manager.h"
  13. #include "locale_service.h"
  14.  
  15. using namespace std;
  16.  
  17. CPVP::CPVP(DWORD dwPID1, DWORD dwPID2)
  18. {
  19. if (dwPID1 > dwPID2)
  20. {
  21. m_players[0].dwPID = dwPID1;
  22. m_players[1].dwPID = dwPID2;
  23. m_players[0].bAgree = true;
  24. }
  25. else
  26. {
  27. m_players[0].dwPID = dwPID2;
  28. m_players[1].dwPID = dwPID1;
  29. m_players[1].bAgree = true;
  30. }
  31.  
  32. DWORD adwID[2];
  33. adwID[0] = m_players[0].dwPID;
  34. adwID[1] = m_players[1].dwPID;
  35. m_dwCRC = GetFastHash((const char *) &adwID, 8);
  36. m_bRevenge = false;
  37.  
  38. SetLastFightTime();
  39. }
  40.  
  41. CPVP::CPVP(CPVP & k)
  42. {
  43. m_players[0] = k.m_players[0];
  44. m_players[1] = k.m_players[1];
  45.  
  46. m_dwCRC = k.m_dwCRC;
  47. m_bRevenge = k.m_bRevenge;
  48.  
  49. SetLastFightTime();
  50. }
  51.  
  52. CPVP::~CPVP()
  53. {
  54. }
  55.  
  56. void CPVP::Packet(bool bDelete)
  57. {
  58. if (!m_players[0].dwVID || !m_players[1].dwVID)
  59. {
  60. if (bDelete)
  61. sys_err("null vid when removing %u %u", m_players[0].dwVID, m_players[0].dwVID);
  62.  
  63. return;
  64. }
  65.  
  66. TPacketGCPVP pack;
  67.  
  68. pack.bHeader = HEADER_GC_PVP;
  69.  
  70. if (bDelete)
  71. {
  72. pack.bMode = PVP_MODE_NONE;
  73. pack.dwVIDSrc = m_players[0].dwVID;
  74. pack.dwVIDDst = m_players[1].dwVID;
  75. }
  76. else if (IsFight())
  77. {
  78. pack.bMode = PVP_MODE_FIGHT;
  79. pack.dwVIDSrc = m_players[0].dwVID;
  80. pack.dwVIDDst = m_players[1].dwVID;
  81. }
  82. else
  83. {
  84. pack.bMode = m_bRevenge ? PVP_MODE_REVENGE : PVP_MODE_AGREE;
  85.  
  86. if (m_players[0].bAgree)
  87. {
  88. pack.dwVIDSrc = m_players[0].dwVID;
  89. pack.dwVIDDst = m_players[1].dwVID;
  90. }
  91. else
  92. {
  93. pack.dwVIDSrc = m_players[1].dwVID;
  94. pack.dwVIDDst = m_players[0].dwVID;
  95. }
  96. }
  97.  
  98. const DESC_MANAGER::DESC_SET & c_rSet = DESC_MANAGER::instance().GetClientSet();
  99. DESC_MANAGER::DESC_SET::const_iterator it = c_rSet.begin();
  100.  
  101. while (it != c_rSet.end())
  102. {
  103. LPDESC d = *it++;
  104.  
  105. if (d->IsPhase(PHASE_GAME) || d->IsPhase(PHASE_DEAD))
  106. d->Packet(&pack, sizeof(pack));
  107. }
  108. }
  109.  
  110. bool CPVP::Agree(DWORD dwPID)
  111. {
  112. m_players[m_players[0].dwPID != dwPID ? 1 : 0].bAgree = true;
  113.  
  114. if (IsFight())
  115. {
  116. Packet();
  117. return true;
  118. }
  119.  
  120. return false;
  121. }
  122.  
  123. bool CPVP::IsFight()
  124. {
  125. return (m_players[0].bAgree == m_players[1].bAgree) && m_players[0].bAgree;
  126. }
  127.  
  128. void CPVP::Win(DWORD dwPID)
  129. {
  130. int iSlot = m_players[0].dwPID != dwPID ? 1 : 0;
  131.  
  132. m_bRevenge = true;
  133.  
  134. m_players[iSlot].bAgree = true; // ŔÚµżŔ¸·Î µżŔÇ
  135. m_players[!iSlot].bCanRevenge = true;
  136. m_players[!iSlot].bAgree = false;
  137.  
  138. Packet();
  139. }
  140.  
  141. bool CPVP::CanRevenge(DWORD dwPID)
  142. {
  143. return m_players[m_players[0].dwPID != dwPID ? 1 : 0].bCanRevenge;
  144. }
  145.  
  146. void CPVP::SetVID(DWORD dwPID, DWORD dwVID)
  147. {
  148. if (m_players[0].dwPID == dwPID)
  149. m_players[0].dwVID = dwVID;
  150. else
  151. m_players[1].dwVID = dwVID;
  152. }
  153.  
  154. void CPVP::SetLastFightTime()
  155. {
  156. m_dwLastFightTime = get_dword_time();
  157. }
  158.  
  159. DWORD CPVP::GetLastFightTime()
  160. {
  161. return m_dwLastFightTime;
  162. }
  163.  
  164. CPVPManager::CPVPManager()
  165. {
  166. }
  167.  
  168. CPVPManager::~CPVPManager()
  169. {
  170. }
  171.  
  172. void CPVPManager::Insert(LPCHARACTER pkChr, LPCHARACTER pkVictim)
  173. {
  174. if (pkChr->IsDead() || pkVictim->IsDead())
  175. return;
  176.  
  177. CPVP kPVP(pkChr->GetPlayerID(), pkVictim->GetPlayerID());
  178.  
  179. CPVP * pkPVP;
  180.  
  181. if ((pkPVP = Find(kPVP.m_dwCRC)))
  182. {
  183. // şąĽöÇŇ Ľö ŔÖŔ¸¸é ąŮ·Î ˝Îżň!
  184. if (pkPVP->Agree(pkChr->GetPlayerID()))
  185. {
  186. pkVictim->ChatPacket(CHAT_TYPE_INFO, "[LS;730;%s]", pkChr->GetName());
  187. pkChr->ChatPacket(CHAT_TYPE_INFO, "[LS;730;%s]", pkVictim->GetName());
  188. }
  189. return;
  190. }
  191.  
  192. pkPVP = M2_NEW CPVP(kPVP);
  193.  
  194. pkPVP->SetVID(pkChr->GetPlayerID(), pkChr->GetVID());
  195. pkPVP->SetVID(pkVictim->GetPlayerID(), pkVictim->GetVID());
  196.  
  197. m_map_pkPVP.insert(map<DWORD, CPVP *>::value_type(pkPVP->m_dwCRC, pkPVP));
  198.  
  199. m_map_pkPVPSetByID[pkChr->GetPlayerID()].insert(pkPVP);
  200. m_map_pkPVPSetByID[pkVictim->GetPlayerID()].insert(pkPVP);
  201.  
  202. pkPVP->Packet();
  203.  
  204. char msg[CHAT_MAX_LEN + 1];
  205. snprintf(msg, sizeof(msg), "[LS;732;%s]", pkChr->GetName());
  206.  
  207. pkVictim->ChatPacket(CHAT_TYPE_INFO, msg);
  208. pkChr->ChatPacket(CHAT_TYPE_INFO, "[LS;731;%s]", pkVictim->GetName());
  209.  
  210. // NOTIFY_PVP_MESSAGE
  211. LPDESC pkVictimDesc = pkVictim->GetDesc();
  212. if (pkVictimDesc)
  213. {
  214. TPacketGCWhisper pack;
  215.  
  216. int len = MIN(CHAT_MAX_LEN, strlen(msg) + 1);
  217.  
  218. pack.bHeader = HEADER_GC_WHISPER;
  219. pack.wSize = sizeof(TPacketGCWhisper) + strlen(msg) + 1;
  220.  
  221. pack.bType = WHISPER_TYPE_SYSTEM;
  222. pack.bCanFormat = true;
  223. strlcpy(pack.szNameFrom, pkChr->GetName(), sizeof(pack.szNameFrom));
  224.  
  225. TEMP_BUFFER buf;
  226.  
  227. buf.write(&pack, sizeof(TPacketGCWhisper));
  228. buf.write(msg, strlen(msg) + 1);
  229.  
  230. pkVictimDesc->Packet(buf.read_peek(), buf.size());
  231. }
  232. }
  233.  
  234. void CPVPManager::ConnectEx(LPCHARACTER pkChr, bool bDisconnect)
  235. {
  236. CPVPSetMap::iterator it = m_map_pkPVPSetByID.find(pkChr->GetPlayerID());
  237.  
  238. if (it == m_map_pkPVPSetByID.end())
  239. return;
  240.  
  241. DWORD dwVID = bDisconnect ? 0 : pkChr->GetVID();
  242.  
  243. std::unordered_set<CPVP*>::iterator it2 = it->second.begin();
  244.  
  245. while (it2 != it->second.end())
  246. {
  247. CPVP * pkPVP = *it2++;
  248. pkPVP->SetVID(pkChr->GetPlayerID(), dwVID);
  249. }
  250. }
  251.  
  252. void CPVPManager::Connect(LPCHARACTER pkChr)
  253. {
  254. ConnectEx(pkChr, false);
  255. }
  256.  
  257. void CPVPManager::Disconnect(LPCHARACTER playerCharacter)
  258. {
  259. auto pvpSetIterator = m_map_pkPVPSetByID.find(playerCharacter->GetPlayerID());
  260.  
  261. if (pvpSetIterator == m_map_pkPVPSetByID.end())
  262. {
  263. return;
  264. }
  265.  
  266. for (auto* pvpInstance : pvpSetIterator->second)
  267. {
  268. if (pvpInstance->m_players[0].dwPID == playerCharacter->GetPlayerID() || pvpInstance->m_players[1].dwPID == playerCharacter->GetPlayerID())
  269. {
  270. pvpInstance->SetVID(playerCharacter->GetPlayerID(), 0);
  271. pvpInstance->Packet(true);
  272. Delete(pvpInstance);
  273. }
  274. }
  275. }
  276.  
  277. void CPVPManager::GiveUp(LPCHARACTER pkChr, DWORD dwKillerPID) // This method is calling from no where yet.
  278. {
  279. CPVPSetMap::iterator it = m_map_pkPVPSetByID.find(pkChr->GetPlayerID());
  280.  
  281. if (it == m_map_pkPVPSetByID.end())
  282. return;
  283.  
  284. sys_log(1, "PVPManager::Dead %d", pkChr->GetPlayerID());
  285. std::unordered_set<CPVP*>::iterator it2 = it->second.begin();
  286.  
  287. while (it2 != it->second.end())
  288. {
  289. CPVP * pkPVP = *it2++;
  290.  
  291. DWORD dwCompanionPID;
  292.  
  293. if (pkPVP->m_players[0].dwPID == pkChr->GetPlayerID())
  294. dwCompanionPID = pkPVP->m_players[1].dwPID;
  295. else
  296. dwCompanionPID = pkPVP->m_players[0].dwPID;
  297.  
  298. if (dwCompanionPID != dwKillerPID)
  299. continue;
  300.  
  301. pkPVP->SetVID(pkChr->GetPlayerID(), 0);
  302.  
  303. m_map_pkPVPSetByID.erase(dwCompanionPID);
  304.  
  305. it->second.erase(pkPVP);
  306.  
  307. if (it->second.empty())
  308. m_map_pkPVPSetByID.erase(it);
  309.  
  310. m_map_pkPVP.erase(pkPVP->m_dwCRC);
  311.  
  312. pkPVP->Packet(true);
  313. M2_DELETE(pkPVP);
  314. break;
  315. }
  316. }
  317.  
  318. // ¸®ĹϰŞ: 0 = PK, 1 = PVP
  319. // PVP¸¦ ¸®ĹĎÇĎ¸é °ćÇčġłŞ ľĆŔĚĹŰŔ» ¶ł±¸°í PK¸é ¶ł±¸Áö ľĘ´Â´Ů.
  320. bool CPVPManager::Dead(LPCHARACTER pkChr, DWORD dwKillerPID)
  321. {
  322. CPVPSetMap::iterator it = m_map_pkPVPSetByID.find(pkChr->GetPlayerID());
  323.  
  324. if (it == m_map_pkPVPSetByID.end())
  325. return false;
  326.  
  327. bool found = false;
  328.  
  329. sys_log(1, "PVPManager::Dead %d", pkChr->GetPlayerID());
  330. std::unordered_set<CPVP*>::iterator it2 = it->second.begin();
  331.  
  332. while (it2 != it->second.end())
  333. {
  334. CPVP * pkPVP = *it2++;
  335.  
  336. DWORD dwCompanionPID;
  337.  
  338. if (pkPVP->m_players[0].dwPID == pkChr->GetPlayerID())
  339. dwCompanionPID = pkPVP->m_players[1].dwPID;
  340. else
  341. dwCompanionPID = pkPVP->m_players[0].dwPID;
  342.  
  343. if (dwCompanionPID == dwKillerPID)
  344. {
  345. if (pkPVP->IsFight())
  346. {
  347. pkPVP->SetLastFightTime();
  348. pkPVP->Win(dwKillerPID);
  349. found = true;
  350. break;
  351. }
  352. else if (get_dword_time() - pkPVP->GetLastFightTime() <= 15000)
  353. {
  354. found = true;
  355. break;
  356. }
  357. }
  358. }
  359.  
  360. return found;
  361. }
  362.  
  363. bool CPVPManager::CanAttack(LPCHARACTER pkChr, LPCHARACTER pkVictim)
  364. {
  365. switch (pkVictim->GetCharType())
  366. {
  367. case CHAR_TYPE_NPC:
  368. case CHAR_TYPE_WARP:
  369. case CHAR_TYPE_GOTO:
  370. return false;
  371. }
  372.  
  373. if (pkChr == pkVictim)
  374. return false;
  375.  
  376. if (pkVictim->IsNPC() && pkChr->IsNPC() && !pkChr->IsGuardNPC())
  377. return false;
  378.  
  379. if( true == pkChr->IsHorseRiding() )
  380. {
  381. if( pkChr->GetHorseLevel() > 0 && 1 == pkChr->GetHorseGrade() )
  382. return false;
  383. }
  384. else
  385. {
  386. switch( pkChr->GetMountVnum() )
  387. {
  388. case 0:
  389. case 20030:
  390.  
  391. case 20110: //mount test for metin2.dev
  392. case 20111:
  393. case 20112:
  394. case 20113:
  395. case 20114:
  396. case 20115:
  397. case 20116:
  398. case 20117:
  399. case 20118:
  400. case 20119:
  401. case 20120:
  402. case 20121:
  403. case 20122:
  404. case 20123:
  405. case 20124:
  406. case 20125:
  407. case 20126:
  408. case 20127:
  409. case 20128:
  410.  
  411.  
  412. case 20201:
  413. case 20202:
  414. case 20203:
  415. case 20204:
  416. case 20205:
  417. case 20206:
  418. case 20207:
  419. case 20208:
  420. case 20209:
  421. case 20210:
  422. case 20211:
  423. case 20212:
  424. case 20213:
  425. case 20214:
  426. case 20215:
  427. case 20216:
  428. case 20217:
  429. case 20218:
  430. case 20219:
  431. case 20220:
  432. case 20221:
  433. case 20222:
  434.  
  435.  
  436. break;
  437.  
  438. default:
  439. return false;
  440. }
  441. }
  442.  
  443. if (pkVictim->IsNPC() || pkChr->IsNPC())
  444. {
  445. return true;
  446. }
  447.  
  448. if (pkVictim->IsObserverMode() || pkChr->IsObserverMode())
  449. return false;
  450.  
  451. {
  452. BYTE bMapEmpire = SECTREE_MANAGER::instance().GetEmpireFromMapIndex(pkChr->GetMapIndex());
  453.  
  454. if ( pkChr->GetPKMode() == PK_MODE_PROTECT && pkChr->GetEmpire() == bMapEmpire ||
  455. pkVictim->GetPKMode() == PK_MODE_PROTECT && pkVictim->GetEmpire() == bMapEmpire )
  456. {
  457. return false;
  458. }
  459. }
  460.  
  461. if (pkChr->GetEmpire() != pkVictim->GetEmpire())
  462. {
  463. if ( LC_IsYMIR() == true || LC_IsKorea() == true )
  464. {
  465. if ( pkChr->GetPKMode() == PK_MODE_PROTECT || pkVictim->GetPKMode() == PK_MODE_PROTECT )
  466. {
  467. return false;
  468. }
  469. }
  470.  
  471. return true;
  472. }
  473.  
  474. bool beKillerMode = false;
  475.  
  476. if (pkVictim->GetParty() && pkVictim->GetParty() == pkChr->GetParty())
  477. {
  478. return false;
  479. // Cannot attack same party on any pvp model
  480. }
  481. else
  482. {
  483. if (pkVictim->IsKillerMode())
  484. {
  485. return true;
  486. }
  487.  
  488. if (pkChr->GetAlignment() < 0 && pkVictim->GetAlignment() >= 0)
  489. {
  490. if (g_protectNormalPlayer)
  491. {
  492. // ąüąýŔÚ´Â ĆňČ­¸đµĺŔÎ ÂřÇŃ»ç¶÷Ŕ» °ř°ÝÇŇ Ľö ľř´Ů.
  493. if (PK_MODE_PEACE == pkVictim->GetPKMode())
  494. return false;
  495. }
  496. }
  497.  
  498.  
  499. switch (pkChr->GetPKMode())
  500. {
  501. case PK_MODE_PEACE:
  502. case PK_MODE_REVENGE:
  503. // Cannot attack same guild
  504. if (pkVictim->GetGuild() && pkVictim->GetGuild() == pkChr->GetGuild())
  505. break;
  506.  
  507. if (pkChr->GetPKMode() == PK_MODE_REVENGE)
  508. {
  509. //if (!g_iUseLocale)
  510. if (1)
  511. {
  512. if (pkChr->GetAlignment() < 0 && pkVictim->GetAlignment() >= 0)
  513. {
  514. pkChr->SetKillerMode(true);
  515. return true;
  516. }
  517. else if (pkChr->GetAlignment() >= 0 && pkVictim->GetAlignment() < 0)
  518. return true;
  519. }
  520. else
  521. {
  522. if (pkChr->GetAlignment() < 0 && pkVictim->GetAlignment() < 0)
  523. break;
  524. else if (pkChr->GetAlignment() >= 0 && pkVictim->GetAlignment() >= 0)
  525. break;
  526.  
  527. beKillerMode = true;
  528. }
  529. }
  530. break;
  531.  
  532. case PK_MODE_GUILD:
  533. // Same implementation from PK_MODE_FREE except for attacking same guild
  534. if (!pkChr->GetGuild() || (pkVictim->GetGuild() != pkChr->GetGuild()))
  535. {
  536. if (1)
  537. //if (!g_iUseLocale)
  538. {
  539. if (pkVictim->GetAlignment() >= 0)
  540. pkChr->SetKillerMode(true);
  541. else if (pkChr->GetAlignment() < 0 && pkVictim->GetAlignment() < 0)
  542. pkChr->SetKillerMode(true);
  543.  
  544. return true;
  545. }
  546. else
  547. beKillerMode = true;
  548. }
  549. break;
  550.  
  551. case PK_MODE_FREE:
  552. //if (!g_iUseLocale)
  553. if (1)
  554. {
  555. if (pkVictim->GetAlignment() >= 0)
  556. pkChr->SetKillerMode(true);
  557. else if (pkChr->GetAlignment() < 0 && pkVictim->GetAlignment() < 0)
  558. pkChr->SetKillerMode(true);
  559.  
  560. return true;
  561. }
  562. else
  563. beKillerMode = true;
  564. break;
  565. }
  566. }
  567.  
  568. CPVP kPVP(pkChr->GetPlayerID(), pkVictim->GetPlayerID());
  569. CPVP * pkPVP = Find(kPVP.m_dwCRC);
  570.  
  571. if (!pkPVP || !pkPVP->IsFight())
  572. {
  573. if (beKillerMode)
  574. pkChr->SetKillerMode(true);
  575.  
  576. return (beKillerMode);
  577. }
  578.  
  579. pkPVP->SetLastFightTime();
  580. return true;
  581. }
  582.  
  583. CPVP * CPVPManager::Find(DWORD dwCRC)
  584. {
  585. map<DWORD, CPVP *>::iterator it = m_map_pkPVP.find(dwCRC);
  586.  
  587. if (it == m_map_pkPVP.end())
  588. return NULL;
  589.  
  590. return it->second;
  591. }
  592.  
  593. void CPVPManager::Delete(CPVP * pkPVP)
  594. {
  595. map<DWORD, CPVP *>::iterator it = m_map_pkPVP.find(pkPVP->m_dwCRC);
  596.  
  597. if (it == m_map_pkPVP.end())
  598. return;
  599.  
  600. m_map_pkPVP.erase(it);
  601. m_map_pkPVPSetByID[pkPVP->m_players[0].dwPID].erase(pkPVP);
  602. m_map_pkPVPSetByID[pkPVP->m_players[1].dwPID].erase(pkPVP);
  603.  
  604. M2_DELETE(pkPVP);
  605. }
  606.  
  607. void CPVPManager::SendList(LPDESC d)
  608. {
  609. map<DWORD, CPVP *>::iterator it = m_map_pkPVP.begin();
  610.  
  611. DWORD dwVID = d->GetCharacter()->GetVID();
  612.  
  613. TPacketGCPVP pack;
  614.  
  615. pack.bHeader = HEADER_GC_PVP;
  616.  
  617. while (it != m_map_pkPVP.end())
  618. {
  619. CPVP * pkPVP = (it++)->second;
  620.  
  621. if (!pkPVP->m_players[0].dwVID || !pkPVP->m_players[1].dwVID)
  622. continue;
  623.  
  624. // VID°ˇ µŃ´Ů ŔÖŔ» °ćżěżˇ¸¸ ş¸ł˝´Ů.
  625. if (pkPVP->IsFight())
  626. {
  627. pack.bMode = PVP_MODE_FIGHT;
  628. pack.dwVIDSrc = pkPVP->m_players[0].dwVID;
  629. pack.dwVIDDst = pkPVP->m_players[1].dwVID;
  630. }
  631. else
  632. {
  633. pack.bMode = pkPVP->m_bRevenge ? PVP_MODE_REVENGE : PVP_MODE_AGREE;
  634.  
  635. if (pkPVP->m_players[0].bAgree)
  636. {
  637. pack.dwVIDSrc = pkPVP->m_players[0].dwVID;
  638. pack.dwVIDDst = pkPVP->m_players[1].dwVID;
  639. }
  640. else
  641. {
  642. pack.dwVIDSrc = pkPVP->m_players[1].dwVID;
  643. pack.dwVIDDst = pkPVP->m_players[0].dwVID;
  644. }
  645. }
  646.  
  647. d->Packet(&pack, sizeof(pack));
  648. sys_log(1, "PVPManager::SendList %d %d", pack.dwVIDSrc, pack.dwVIDDst);
  649.  
  650. if (pkPVP->m_players[0].dwVID == dwVID)
  651. {
  652. LPCHARACTER ch = CHARACTER_MANAGER::instance().Find(pkPVP->m_players[1].dwVID);
  653. if (ch && ch->GetDesc())
  654. {
  655. LPDESC d = ch->GetDesc();
  656. d->Packet(&pack, sizeof(pack));
  657. }
  658. }
  659. else if (pkPVP->m_players[1].dwVID == dwVID)
  660. {
  661. LPCHARACTER ch = CHARACTER_MANAGER::instance().Find(pkPVP->m_players[0].dwVID);
  662. if (ch && ch->GetDesc())
  663. {
  664. LPDESC d = ch->GetDesc();
  665. d->Packet(&pack, sizeof(pack));
  666. }
  667. }
  668. }
  669. }
  670.  
  671. void CPVPManager::Process()
  672. {
  673. map<DWORD, CPVP *>::iterator it = m_map_pkPVP.begin();
  674.  
  675. while (it != m_map_pkPVP.end())
  676. {
  677. CPVP * pvp = (it++)->second;
  678.  
  679. if (get_dword_time() - pvp->GetLastFightTime() > 600000) // 10şĐ ŔĚ»ó ˝ÎżňŔĚ ľřľúŔ¸¸é
  680. {
  681. pvp->Packet(true);
  682. Delete(pvp);
  683. }
  684. }
  685. }
  686.  
Advertisement
Add Comment
Please, Sign In to add comment