1. #include "stdafx.h"
  2. #include "../../libgame/include/grid.h"
  3. #include "utils.h"
  4. #include "desc.h"
  5. #include "desc_client.h"
  6. #include "char.h"
  7. #include "item.h"
  8. #include "item_manager.h"
  9. #include "packet.h"
  10. #include "log.h"
  11. #include "db.h"
  12. #include "locale_service.h"
  13. #include "../../common/length.h"
  14. #include "exchange.h"
  15. #include "DragonSoul.h"
  16. #include "questmanager.h"
  17. void exchange_packet(LPCHARACTER ch, BYTE sub_header, bool is_me, DWORD arg1, TItemPos arg2, DWORD arg3, void * pvData = NULL);
  18. void exchange_packet(LPCHARACTER ch, BYTE sub_header, bool is_me, DWORD arg1, TItemPos arg2, DWORD arg3, void * pvData)
  19. {
  20. if (!ch->GetDesc())
  21. return;
  22. struct packet_exchange pack_exchg;
  23. pack_exchg.header = HEADER_GC_EXCHANGE;
  24. pack_exchg.sub_header = sub_header;
  25. pack_exchg.is_me = is_me;
  26. pack_exchg.arg1 = arg1;
  27. pack_exchg.arg2 = arg2;
  28. pack_exchg.arg3 = arg3;
  29. if (sub_header == EXCHANGE_SUBHEADER_GC_ITEM_ADD && pvData)
  30. {
  31. thecore_memcpy(&pack_exchg.alSockets, ((LPITEM) pvData)->GetSockets(), sizeof(pack_exchg.alSockets));
  32. thecore_memcpy(&pack_exchg.aAttr, ((LPITEM) pvData)->GetAttributes(), sizeof(pack_exchg.aAttr));
  33. }
  34. else
  35. {
  36. memset(&pack_exchg.alSockets, 0, sizeof(pack_exchg.alSockets));
  37. memset(&pack_exchg.aAttr, 0, sizeof(pack_exchg.aAttr));
  38. }
  39. ch->GetDesc()->Packet(&pack_exchg, sizeof(pack_exchg));
  40. }
  41. bool CHARACTER::ExchangeStart(LPCHARACTER victim)
  42. {
  43. if (this == victim)
  44. return false;
  45. if (IsObserverMode())
  46. {
  47. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ????? ??? ? ? ????."));
  48. return false;
  49. }
  50. if (victim->IsNPC())
  51. return false;
  52. //PREVENT_TRADE_WINDOW
  53. if ( IsOpenSafebox() || GetShopOwner() || GetMyShop() || IsCubeOpen())
  54. {
  55. ChatPacket( CHAT_TYPE_INFO, LC_TEXT("?? ???? ?????? ??? ?? ????." ) );
  56. return false;
  57. }
  58. if ( victim->IsOpenSafebox() || victim->GetShopOwner() || victim->GetMyShop() || victim->IsCubeOpen() )
  59. {
  60. ChatPacket( CHAT_TYPE_INFO, LC_TEXT("???? ?? ????? ??? ?? ????." ) );
  61. return false;
  62. }
  63. //END_PREVENT_TRADE_WINDOW
  64. int iDist = DISTANCE_APPROX(GetX() - victim->GetX(), GetY() - victim->GetY());
  65. if (iDist >= EXCHANGE_MAX_DISTANCE)
  66. return false;
  67. if (GetExchange())
  68. return false;
  69. if (victim->GetExchange())
  70. {
  71. exchange_packet(this, EXCHANGE_SUBHEADER_GC_ALREADY, 0, 0, NPOS, 0);
  72. return false;
  73. }
  74. if (victim->IsBlockMode(BLOCK_EXCHANGE))
  75. {
  76. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ?? ?? ?????."));
  77. return false;
  78. }
  79. SetExchange(M2_NEW CExchange(this));
  80. victim->SetExchange(M2_NEW CExchange(victim));
  81. victim->GetExchange()->SetCompany(GetExchange());
  82. GetExchange()->SetCompany(victim->GetExchange());
  83. SetExchangeTime();
  84. victim->SetExchangeTime();
  85. exchange_packet(victim, EXCHANGE_SUBHEADER_GC_START, 0, GetVID(), NPOS, 0);
  86. exchange_packet(this, EXCHANGE_SUBHEADER_GC_START, 0, victim->GetVID(), NPOS, 0);
  87. return true;
  88. }
  89. CExchange::CExchange(LPCHARACTER pOwner)
  90. {
  91. m_pCompany = NULL;
  92. m_bAccept = false;
  93. for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
  94. {
  95. m_apItems[i] = NULL;
  96. m_aItemPos[i] = NPOS;
  97. m_abItemDisplayPos[i] = 0;
  98. }
  99. m_lGold = 0;
  100. m_pOwner = pOwner;
  101. pOwner->SetExchange(this);
  102. m_pGrid = M2_NEW CGrid(4,3);
  103. }
  104. CExchange::~CExchange()
  105. {
  106. M2_DELETE(m_pGrid);
  107. }
  108. bool CExchange::AddItem(TItemPos item_pos, BYTE display_pos)
  109. {
  110. assert(m_pOwner != NULL && GetCompany());
  111. if (!item_pos.IsValidItemPosition())
  112. return false;
  113. if (item_pos.IsEquipPosition())
  114. return false;
  115. LPITEM item;
  116. if (!(item = m_pOwner->GetItem(item_pos)))
  117. return false;
  118. if (IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_GIVE))
  119. {
  120. m_pOwner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ??? ? ????."));
  121. return false;
  122. }
  123. if (true == item->isLocked())
  124. {
  125. return false;
  126. }
  127. if (item->IsExchanging())
  128. {
  129. sys_log(0, "EXCHANGE under exchanging");
  130. return false;
  131. }
  132. if (!m_pGrid->IsEmpty(display_pos, 1, item->GetSize()))
  133. {
  134. sys_log(0, "EXCHANGE not empty item_pos %d %d %d", display_pos, 1, item->GetSize());
  135. return false;
  136. }
  137. Accept(false);
  138. GetCompany()->Accept(false);
  139. for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
  140. {
  141. if (m_apItems[i])
  142. continue;
  143. m_apItems[i] = item;
  144. m_aItemPos[i] = item_pos;
  145. m_abItemDisplayPos[i] = display_pos;
  146. m_pGrid->Put(display_pos, 1, item->GetSize());
  147. item->SetExchanging(true);
  148. exchange_packet(m_pOwner,
  149. EXCHANGE_SUBHEADER_GC_ITEM_ADD,
  150. true,
  151. item->GetVnum(),
  152. TItemPos(RESERVED_WINDOW, display_pos),
  153. item->GetCount(),
  154. item);
  155. exchange_packet(GetCompany()->GetOwner(),
  156. EXCHANGE_SUBHEADER_GC_ITEM_ADD,
  157. false,
  158. item->GetVnum(),
  159. TItemPos(RESERVED_WINDOW, display_pos),
  160. item->GetCount(),
  161. item);
  162. sys_log(0, "EXCHANGE AddItem success %s pos(%d, %d) %d", item->GetName(), item_pos.window_type, item_pos.cell, display_pos);
  163. return true;
  164. }
  165. return false;
  166. }
  167. bool CExchange::RemoveItem(BYTE pos)
  168. {
  169. if (pos >= EXCHANGE_ITEM_MAX_NUM)
  170. return false;
  171. if (!m_apItems[pos])
  172. return false;
  173. TItemPos PosOfInventory = m_aItemPos[pos];
  174. m_apItems[pos]->SetExchanging(false);
  175. m_pGrid->Get(m_abItemDisplayPos[pos], 1, m_apItems[pos]->GetSize());
  176. exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_ITEM_DEL, true, pos, NPOS, 0);
  177. exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_ITEM_DEL, false, pos, PosOfInventory, 0);
  178. Accept(false);
  179. GetCompany()->Accept(false);
  180. m_apItems[pos] = NULL;
  181. m_aItemPos[pos] = NPOS;
  182. m_abItemDisplayPos[pos] = 0;
  183. return true;
  184. }
  185. bool CExchange::AddGold(long gold)
  186. {
  187. if (gold <= 0)
  188. return false;
  189. if (GetOwner()->GetGold() < gold)
  190. {
  191. exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_LESS_GOLD, 0, 0, NPOS, 0);
  192. return false;
  193. }
  194. if (m_lGold > 0)
  195. return false;
  196. Accept(false);
  197. GetCompany()->Accept(false);
  198. m_lGold = gold;
  199. exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_GOLD_ADD, true, m_lGold, NPOS, 0);
  200. exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_GOLD_ADD, false, m_lGold, NPOS, 0);
  201. return true;
  202. }
  203. bool CExchange::Check(int * piItemCount)
  204. {
  205. if (GetOwner()->GetGold() < m_lGold)
  206. return false;
  207. int item_count = 0;
  208. for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
  209. {
  210. if (!m_apItems[i])
  211. continue;
  212. if (!m_aItemPos[i].IsValidItemPosition())
  213. return false;
  214. if (m_apItems[i] != GetOwner()->GetItem(m_aItemPos[i]))
  215. return false;
  216. ++item_count;
  217. }
  218. *piItemCount = item_count;
  219. return true;
  220. }
  221. bool CExchange::CheckSpace()
  222. {
  223. static CGrid s_grid1(INVENTORY_PAGE_COLUMN, INVENTORY_PAGE_ROW); // inven page 1
  224. static CGrid s_grid2(INVENTORY_PAGE_COLUMN, INVENTORY_PAGE_ROW); // inven page 2
  225. #ifdef ENABLE_EXTEND_INVEN_SYSTEM
  226. static CGrid s_grid3(INVENTORY_PAGE_COLUMN, INVENTORY_PAGE_ROW); // inven page 3
  227. static CGrid s_grid4(INVENTORY_PAGE_COLUMN, INVENTORY_PAGE_ROW); // inven page 4
  228. #endif
  229. #ifdef ENABLE_SPLIT_INVENTORY_SYSTEM
  230. LPCHARACTER me = GetOwner();
  231. static CGrid s_grid5(5, SKILL_BOOK_INVENTORY_MAX_NUM / 5 / 3);
  232. static CGrid s_grid6(5, SKILL_BOOK_INVENTORY_MAX_NUM / 5 / 3);
  233. static CGrid s_grid7(5, SKILL_BOOK_INVENTORY_MAX_NUM / 5 / 3);
  234. static CGrid s_grid8(5, UPGRADE_ITEMS_INVENTORY_MAX_NUM / 5 / 3);
  235. static CGrid s_grid9(5, UPGRADE_ITEMS_INVENTORY_MAX_NUM / 5 / 3);
  236. static CGrid s_grid10(5, UPGRADE_ITEMS_INVENTORY_MAX_NUM / 5 / 3);
  237. static CGrid s_grid11(5, STONE_INVENTORY_MAX_NUM / 5 / 3);
  238. static CGrid s_grid12(5, STONE_INVENTORY_MAX_NUM / 5 / 3);
  239. static CGrid s_grid13(5, STONE_INVENTORY_MAX_NUM / 5 / 3);
  240. static CGrid s_grid14(5, BOX_INVENTORY_MAX_NUM / 5 / 3);
  241. static CGrid s_grid15(5, BOX_INVENTORY_MAX_NUM / 5 / 3);
  242. static CGrid s_grid16(5, BOX_INVENTORY_MAX_NUM / 5 / 3);
  243. static CGrid s_grid17(5, EFSUN_INVENTORY_MAX_NUM / 5 / 3);
  244. static CGrid s_grid18(5, EFSUN_INVENTORY_MAX_NUM / 5 / 3);
  245. static CGrid s_grid19(5, EFSUN_INVENTORY_MAX_NUM / 5 / 3);
  246. static CGrid s_grid20(5, CICEK_INVENTORY_MAX_NUM / 5 / 3);
  247. static CGrid s_grid21(5, CICEK_INVENTORY_MAX_NUM / 5 / 3);
  248. static CGrid s_grid22(5, CICEK_INVENTORY_MAX_NUM / 5 / 3);
  249. #endif
  250. s_grid1.Clear();
  251. s_grid2.Clear();
  252. #ifdef ENABLE_EXTEND_INVEN_SYSTEM
  253. s_grid3.Clear();
  254. s_grid4.Clear();
  255. #endif
  256. #ifdef ENABLE_SPLIT_INVENTORY_SYSTEM
  257. s_grid5.Clear();
  258. s_grid6.Clear();
  259. s_grid7.Clear();
  260. s_grid8.Clear();
  261. s_grid9.Clear();
  262. s_grid10.Clear();
  263. s_grid11.Clear();
  264. s_grid12.Clear();
  265. s_grid13.Clear();
  266. s_grid14.Clear();
  267. s_grid15.Clear();
  268. s_grid16.Clear();
  269. s_grid17.Clear();
  270. s_grid18.Clear();
  271. s_grid19.Clear();
  272. s_grid20.Clear();
  273. s_grid21.Clear();
  274. s_grid22.Clear();
  275. #endif
  276. LPCHARACTER victim = GetCompany()->GetOwner();
  277. LPITEM item;
  278. int i;
  279. for (i = 0; i < INVENTORY_PAGE_SIZE*1; ++i)
  280. {
  281. if (!(item = victim->GetInventoryItem(i)))
  282. continue;
  283. s_grid1.Put(i, 1, item->GetSize());
  284. }
  285. for (i = INVENTORY_PAGE_SIZE*1; i < INVENTORY_PAGE_SIZE*2; ++i)
  286. {
  287. if (!(item = victim->GetInventoryItem(i)))
  288. continue;
  289. s_grid2.Put(i - INVENTORY_PAGE_SIZE*1, 1, item->GetSize());
  290. }
  291. #ifdef ENABLE_EXTEND_INVEN_SYSTEM
  292. for (i = INVENTORY_PAGE_SIZE*2; i < INVENTORY_PAGE_SIZE*3; ++i)
  293. {
  294. if (!(item = victim->GetInventoryItem(i)))
  295. continue;
  296. s_grid3.Put(i - INVENTORY_PAGE_SIZE*2, 1, item->GetSize());
  297. }
  298. for (i = INVENTORY_PAGE_SIZE*3; i < INVENTORY_PAGE_SIZE*4; ++i)
  299. {
  300. if (!(item = victim->GetInventoryItem(i)))
  301. continue;
  302. s_grid4.Put(i - INVENTORY_PAGE_SIZE*3, 1, item->GetSize());
  303. }
  304. #endif
  305. #ifdef ENABLE_SPLIT_INVENTORY_SYSTEM
  306. int b;
  307. int v;
  308. int u;
  309. int r;
  310. int a;
  311. int l;
  312. const int perPageSkillBookSlotCount = 45;
  313. const int perPageUpgradeItemsSlotCount = 45;
  314. const int perPageStoneSlotCount = 45;
  315. const int perPageBoxSlotCount = 45;
  316. const int perPageEfsunSlotCount = 45;
  317. const int perPageCicekSlotCount = 45;
  318. for (b = 0; b < SKILL_BOOK_INVENTORY_MAX_NUM; ++b) {
  319. if (!(item = me->GetSkillBookInventoryItem(b)))
  320. continue;
  321. BYTE itemSize = item->GetSize();
  322. if (i < perPageSkillBookSlotCount) // Notice: This is adjusted for 3 Pages only!
  323. s_grid5.Put(i, 1, itemSize);
  324. else if (i < perPageSkillBookSlotCount * 2)
  325. s_grid6.Put(i - perPageSkillBookSlotCount, 1, itemSize);
  326. else if (i < perPageSkillBookSlotCount * 3)
  327. s_grid7.Put(i - perPageSkillBookSlotCount * 2, 1, itemSize);
  328. }
  329. for (v = 0; v < UPGRADE_ITEMS_INVENTORY_MAX_NUM; ++v) {
  330. if (!(item = me->GetUpgradeItemsInventoryItem(v)))
  331. continue;
  332. BYTE itemSize = item->GetSize();
  333. if (i < perPageUpgradeItemsSlotCount) // Notice: This is adjusted for 3 Pages only!
  334. s_grid8.Put(i, 1, itemSize);
  335. else if (i < perPageUpgradeItemsSlotCount * 2)
  336. s_grid9.Put(i - perPageUpgradeItemsSlotCount, 1, itemSize);
  337. else if (i < perPageUpgradeItemsSlotCount * 3)
  338. s_grid10.Put(i - perPageUpgradeItemsSlotCount * 2, 1, itemSize);
  339. }
  340. for (u = 0; u < STONE_INVENTORY_MAX_NUM; ++u) {
  341. if (!(item = me->GetStoneInventoryItem(u)))
  342. continue;
  343. BYTE itemSize = item->GetSize();
  344. if (i < perPageStoneSlotCount) // Notice: This is adjusted for 3 Pages only!
  345. s_grid11.Put(i, 1, itemSize);
  346. else if (i < perPageStoneSlotCount * 2)
  347. s_grid12.Put(i - perPageStoneSlotCount, 1, itemSize);
  348. else if (i < perPageStoneSlotCount * 3)
  349. s_grid13.Put(i - perPageStoneSlotCount * 2, 1, itemSize);
  350. }
  351. for (r = 0; r < BOX_INVENTORY_MAX_NUM; ++r) {
  352. if (!(item = me->GetBoxInventoryItem(r)))
  353. continue;
  354. BYTE itemSize = item->GetSize();
  355. if (i < perPageBoxSlotCount) // Notice: This is adjusted for 3 Pages only!
  356. s_grid14.Put(i, 1, itemSize);
  357. else if (i < perPageBoxSlotCount * 2)
  358. s_grid15.Put(i - perPageBoxSlotCount, 1, itemSize);
  359. else if (i < perPageBoxSlotCount * 3)
  360. s_grid16.Put(i - perPageBoxSlotCount * 2, 1, itemSize);
  361. }
  362. for (a = 0; a < EFSUN_INVENTORY_MAX_NUM; ++a) {
  363. if (!(item = me->GetEfsunInventoryItem(a)))
  364. continue;
  365. BYTE itemSize = item->GetSize();
  366. if (i < perPageEfsunSlotCount) // Notice: This is adjusted for 3 Pages only!
  367. s_grid17.Put(i, 1, itemSize);
  368. else if (i < perPageEfsunSlotCount * 2)
  369. s_grid18.Put(i - perPageEfsunSlotCount, 1, itemSize);
  370. else if (i < perPageEfsunSlotCount * 3)
  371. s_grid19.Put(i - perPageEfsunSlotCount * 2, 1, itemSize);
  372. }
  373. for (l = 0; l < CICEK_INVENTORY_MAX_NUM; ++l) {
  374. if (!(item = me->GetCicekInventoryItem(l)))
  375. continue;
  376. BYTE itemSize = item->GetSize();
  377. if (i < perPageCicekSlotCount) // Notice: This is adjusted for 3 Pages only!
  378. s_grid20.Put(i, 1, itemSize);
  379. else if (i < perPageCicekSlotCount * 2)
  380. s_grid21.Put(i - perPageCicekSlotCount, 1, itemSize);
  381. else if (i < perPageCicekSlotCount * 3)
  382. s_grid22.Put(i - perPageCicekSlotCount * 2, 1, itemSize);
  383. }
  384. #endif
  385. static std::vector <WORD> s_vDSGrid(DRAGON_SOUL_INVENTORY_MAX_NUM);
  386. bool bDSInitialized = false;
  387. for (i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
  388. {
  389. if (!(item = m_apItems[i]))
  390. continue;
  391. if (item->IsDragonSoul())
  392. {
  393. if (!victim->DragonSoul_IsQualified())
  394. {
  395. return false;
  396. }
  397. if (!bDSInitialized)
  398. {
  399. bDSInitialized = true;
  400. victim->CopyDragonSoulItemGrid(s_vDSGrid);
  401. }
  402. bool bExistEmptySpace = false;
  403. WORD wBasePos = DSManager::instance().GetBasePosition(item);
  404. if (wBasePos >= DRAGON_SOUL_INVENTORY_MAX_NUM)
  405. return false;
  406. for (int i = 0; i < DRAGON_SOUL_BOX_SIZE; i++)
  407. {
  408. WORD wPos = wBasePos + i;
  409. if (0 == s_vDSGrid[wPos])
  410. {
  411. bool bEmpty = true;
  412. for (int j = 1; j < item->GetSize(); j++)
  413. {
  414. if (s_vDSGrid[wPos + j * DRAGON_SOUL_BOX_COLUMN_NUM])
  415. {
  416. bEmpty = false;
  417. break;
  418. }
  419. }
  420. if (bEmpty)
  421. {
  422. for (int j = 0; j < item->GetSize(); j++)
  423. {
  424. s_vDSGrid[wPos + j * DRAGON_SOUL_BOX_COLUMN_NUM] = wPos + 1;
  425. }
  426. bExistEmptySpace = true;
  427. break;
  428. }
  429. }
  430. if (bExistEmptySpace)
  431. break;
  432. }
  433. if (!bExistEmptySpace)
  434. return false;
  435. }
  436. #ifdef ENABLE_SPLIT_INVENTORY_SYSTEM
  437. else if (item->IsSkillBook())
  438. {
  439. BYTE itemSize = item->GetSize();
  440. int iPos = s_grid5.FindBlank(1, itemSize);
  441. if (iPos >= 0) {
  442. s_grid5.Put(iPos, 1, itemSize);
  443. continue;
  444. }
  445. iPos = s_grid6.FindBlank(1, itemSize);
  446. if (iPos >= 0) {
  447. s_grid6.Put(iPos, 1, itemSize);
  448. continue;
  449. }
  450. iPos = s_grid7.FindBlank(1, itemSize);
  451. if (iPos >= 0) {
  452. s_grid7.Put(iPos, 1, itemSize);
  453. continue;
  454. }
  455. return false;
  456. }
  457. else if (item->IsUpgradeItem())
  458. {
  459. BYTE itemSize = item->GetSize();
  460. int iPos = s_grid8.FindBlank(1, itemSize);
  461. if (iPos >= 0) {
  462. s_grid8.Put(iPos, 1, itemSize);
  463. continue;
  464. }
  465. iPos = s_grid9.FindBlank(1, itemSize);
  466. if (iPos >= 0) {
  467. s_grid9.Put(iPos, 1, itemSize);
  468. continue;
  469. }
  470. iPos = s_grid10.FindBlank(1, itemSize);
  471. if (iPos >= 0) {
  472. s_grid10.Put(iPos, 1, itemSize);
  473. continue;
  474. }
  475. return false;
  476. }
  477. else if (item->IsStone())
  478. {
  479. BYTE itemSize = item->GetSize();
  480. int iPos = s_grid11.FindBlank(1, itemSize);
  481. if (iPos >= 0) {
  482. s_grid11.Put(iPos, 1, itemSize);
  483. continue;
  484. }
  485. iPos = s_grid12.FindBlank(1, itemSize);
  486. if (iPos >= 0) {
  487. s_grid12.Put(iPos, 1, itemSize);
  488. continue;
  489. }
  490. iPos = s_grid13.FindBlank(1, itemSize);
  491. if (iPos >= 0) {
  492. s_grid13.Put(iPos, 1, itemSize);
  493. continue;
  494. }
  495. return false;
  496. }
  497. else if (item->IsBox())
  498. {
  499. BYTE itemSize = item->GetSize();
  500. int iPos = s_grid14.FindBlank(1, itemSize);
  501. if (iPos >= 0) {
  502. s_grid14.Put(iPos, 1, itemSize);
  503. continue;
  504. }
  505. iPos = s_grid15.FindBlank(1, itemSize);
  506. if (iPos >= 0) {
  507. s_grid15.Put(iPos, 1, itemSize);
  508. continue;
  509. }
  510. iPos = s_grid16.FindBlank(1, itemSize);
  511. if (iPos >= 0) {
  512. s_grid16.Put(iPos, 1, itemSize);
  513. continue;
  514. }
  515. return false;
  516. }
  517. else if (item->IsEfsun())
  518. {
  519. BYTE itemSize = item->GetSize();
  520. int iPos = s_grid17.FindBlank(1, itemSize);
  521. if (iPos >= 0) {
  522. s_grid17.Put(iPos, 1, itemSize);
  523. continue;
  524. }
  525. iPos = s_grid18.FindBlank(1, itemSize);
  526. if (iPos >= 0) {
  527. s_grid18.Put(iPos, 1, itemSize);
  528. continue;
  529. }
  530. iPos = s_grid19.FindBlank(1, itemSize);
  531. if (iPos >= 0) {
  532. s_grid19.Put(iPos, 1, itemSize);
  533. continue;
  534. }
  535. return false;
  536. }
  537. else if (item->IsCicek())
  538. {
  539. BYTE itemSize = item->GetSize();
  540. int iPos = s_grid20.FindBlank(1, itemSize);
  541. if (iPos >= 0) {
  542. s_grid20.Put(iPos, 1, itemSize);
  543. continue;
  544. }
  545. iPos = s_grid21.FindBlank(1, itemSize);
  546. if (iPos >= 0) {
  547. s_grid21.Put(iPos, 1, itemSize);
  548. continue;
  549. }
  550. iPos = s_grid22.FindBlank(1, itemSize);
  551. if (iPos >= 0) {
  552. s_grid22.Put(iPos, 1, itemSize);
  553. continue;
  554. }
  555. return false;
  556. }
  557. #endif
  558. else
  559. {
  560. int iPos;
  561. if ((iPos = s_grid1.FindBlank(1, item->GetSize())) >= 0)
  562. {
  563. s_grid1.Put(iPos, 1, item->GetSize());
  564. }
  565. else if ((iPos = s_grid2.FindBlank(1, item->GetSize())) >= 0)
  566. {
  567. s_grid2.Put(iPos, 1, item->GetSize());
  568. }
  569. #ifdef ENABLE_EXTEND_INVEN_SYSTEM
  570. else if ((iPos = s_grid3.FindBlank(1, item->GetSize())) >= 0)
  571. {
  572. s_grid3.Put(iPos, 1, item->GetSize());
  573. }
  574. else if ((iPos = s_grid4.FindBlank(1, item->GetSize())) >= 0)
  575. {
  576. s_grid4.Put(iPos, 1, item->GetSize());
  577. }
  578. #endif
  579. else
  580. return false;
  581. }
  582. }
  583. return true;
  584. }
  585. bool CExchange::Done()
  586. {
  587. int empty_pos, i;
  588. LPITEM item;
  589. LPCHARACTER victim = GetCompany()->GetOwner();
  590. for (i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
  591. {
  592. if (!(item = m_apItems[i]))
  593. continue;
  594. if (item->IsDragonSoul())
  595. empty_pos = victim->GetEmptyDragonSoulInventory(item);
  596. #ifdef ENABLE_SPLIT_INVENTORY_SYSTEM
  597. else if (item->IsSkillBook())
  598. empty_pos = victim->GetEmptySkillBookInventory(item->GetSize());
  599. else if (item->IsUpgradeItem())
  600. empty_pos = victim->GetEmptyUpgradeItemsInventory(item->GetSize());
  601. else if (item->IsStone())
  602. empty_pos = victim->GetEmptyStoneInventory(item->GetSize());
  603. else if (item->IsBox())
  604. empty_pos = victim->GetEmptyBoxInventory(item->GetSize());
  605. else if (item->IsEfsun())
  606. empty_pos = victim->GetEmptyEfsunInventory(item->GetSize());
  607. else if (item->IsCicek())
  608. empty_pos = victim->GetEmptyCicekInventory(item->GetSize());
  609. #endif
  610. else
  611. empty_pos = victim->GetEmptyInventory(item->GetSize());
  612. if (empty_pos < 0)
  613. {
  614. sys_err("Exchange::Done : Cannot find blank position in inventory %s <-> %s item %s",
  615. m_pOwner->GetName(), victim->GetName(), item->GetName());
  616. continue;
  617. }
  618. assert(empty_pos >= 0);
  619. m_pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 255);
  620. item->RemoveFromCharacter();
  621. if (item->IsDragonSoul())
  622. item->AddToCharacter(victim, TItemPos(DRAGON_SOUL_INVENTORY, empty_pos));
  623. #ifdef ENABLE_SPLIT_INVENTORY_SYSTEM
  624. else if (item->IsSkillBook())
  625. item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
  626. else if (item->IsUpgradeItem())
  627. item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
  628. else if (item->IsStone())
  629. item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
  630. else if (item->IsBox())
  631. item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
  632. else if (item->IsEfsun())
  633. item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
  634. else if (item->IsCicek())
  635. item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
  636. #endif
  637. else
  638. item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
  639. ITEM_MANAGER::instance().FlushDelayedSave(item);
  640. item->SetExchanging(false);
  641. {
  642. char exchange_buf[51];
  643. snprintf(exchange_buf, sizeof(exchange_buf), "%s %u %u", item->GetName(), GetOwner()->GetPlayerID(), item->GetCount());
  644. LogManager::instance().ItemLog(victim, item, "EXCHANGE_TAKE", exchange_buf);
  645. snprintf(exchange_buf, sizeof(exchange_buf), "%s %u %u", item->GetName(), victim->GetPlayerID(), item->GetCount());
  646. LogManager::instance().ItemLog(GetOwner(), item, "EXCHANGE_GIVE", exchange_buf);
  647. if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
  648. {
  649. LogManager::instance().GoldBarLog(victim->GetPlayerID(), item->GetID(), EXCHANGE_TAKE, "");
  650. LogManager::instance().GoldBarLog(GetOwner()->GetPlayerID(), item->GetID(), EXCHANGE_GIVE, "");
  651. }
  652. }
  653. m_apItems[i] = NULL;
  654. }
  655. if (m_lGold)
  656. {
  657. GetOwner()->PointChange(POINT_GOLD, -m_lGold, true);
  658. victim->PointChange(POINT_GOLD, m_lGold, true);
  659. if (m_lGold > 1000)
  660. {
  661. char exchange_buf[51];
  662. snprintf(exchange_buf, sizeof(exchange_buf), "%u %s", GetOwner()->GetPlayerID(), GetOwner()->GetName());
  663. LogManager::instance().CharLog(victim, m_lGold, "EXCHANGE_GOLD_TAKE", exchange_buf);
  664. snprintf(exchange_buf, sizeof(exchange_buf), "%u %s", victim->GetPlayerID(), victim->GetName());
  665. LogManager::instance().CharLog(GetOwner(), m_lGold, "EXCHANGE_GOLD_GIVE", exchange_buf);
  666. }
  667. }
  668. m_pGrid->Clear();
  669. return true;
  670. }
  671. bool CExchange::Accept(bool bAccept)
  672. {
  673. if (m_bAccept == bAccept)
  674. return true;
  675. m_bAccept = bAccept;
  676. if (m_bAccept && GetCompany()->m_bAccept)
  677. {
  678. int iItemCount;
  679. LPCHARACTER victim = GetCompany()->GetOwner();
  680. //PREVENT_PORTAL_AFTER_EXCHANGE
  681. GetOwner()->SetExchangeTime();
  682. victim->SetExchangeTime();
  683. //END_PREVENT_PORTAL_AFTER_EXCHANGE
  684. // @fixme150 BEGIN
  685. if (quest::CQuestManager::instance().GetPCForce(GetOwner()->GetPlayerID())->IsRunning() == true)
  686. {
  687. GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You cannot trade if you're using quests"));
  688. victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You cannot trade if the other part using quests"));
  689. goto EXCHANGE_END;
  690. }
  691. else if (quest::CQuestManager::instance().GetPCForce(victim->GetPlayerID())->IsRunning() == true)
  692. {
  693. victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You cannot trade if you're using quests"));
  694. GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You cannot trade if the other part using quests"));
  695. goto EXCHANGE_END;
  696. }
  697. // @fixme150 END
  698. if (!Check(&iItemCount))
  699. {
  700. GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ????? ???? ???? ????."));
  701. victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ?? ????? ???? ???? ????."));
  702. goto EXCHANGE_END;
  703. }
  704. if (!CheckSpace())
  705. {
  706. GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ???? ? ??? ????."));
  707. victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ? ??? ????."));
  708. goto EXCHANGE_END;
  709. }
  710. if (!GetCompany()->Check(&iItemCount))
  711. {
  712. victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("?? ????? ???? ???? ????."));
  713. GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ?? ????? ???? ???? ????."));
  714. goto EXCHANGE_END;
  715. }
  716. if (!GetCompany()->CheckSpace())
  717. {
  718. victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ???? ? ??? ????."));
  719. GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ? ??? ????."));
  720. goto EXCHANGE_END;
  721. }
  722. if (db_clientdesc->GetSocket() == INVALID_SOCKET)
  723. {
  724. sys_err("Cannot use exchange feature while DB cache connection is dead.");
  725. victim->ChatPacket(CHAT_TYPE_INFO, "Unknown error");
  726. GetOwner()->ChatPacket(CHAT_TYPE_INFO, "Unknown error");
  727. goto EXCHANGE_END;
  728. }
  729. if (Done())
  730. {
  731. if (m_lGold)
  732. GetOwner()->Save();
  733. if (GetCompany()->Done())
  734. {
  735. if (GetCompany()->m_lGold)
  736. victim->Save();
  737. // INTERNATIONAL_VERSION
  738. GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s ??? ??? ?? ?????."), victim->GetName());
  739. victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s ??? ??? ?? ?????."), GetOwner()->GetName());
  740. // END_OF_INTERNATIONAL_VERSION
  741. }
  742. }
  743. EXCHANGE_END:
  744. Cancel();
  745. return false;
  746. }
  747. else
  748. {
  749. exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_ACCEPT, true, m_bAccept, NPOS, 0);
  750. exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_ACCEPT, false, m_bAccept, NPOS, 0);
  751. return true;
  752. }
  753. }
  754. void CExchange::Cancel()
  755. {
  756. exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_END, 0, 0, NPOS, 0);
  757. GetOwner()->SetExchange(NULL);
  758. for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
  759. {
  760. if (m_apItems[i])
  761. m_apItems[i]->SetExchanging(false);
  762. }
  763. if (GetCompany())
  764. {
  765. GetCompany()->SetCompany(NULL);
  766. GetCompany()->Cancel();
  767. }
  768. M2_DELETE(this);
  769. }