Advertisement
Guest User

shop.cpp

a guest
May 21st, 2019
327
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.16 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "../../libgame/include/grid.h"
  3. #include "constants.h"
  4. #include "utils.h"
  5. #include "config.h"
  6. #include "shop.h"
  7. #include "desc.h"
  8. #include "desc_manager.h"
  9. #include "char.h"
  10. #include "char_manager.h"
  11. #include "item.h"
  12. #include "item_manager.h"
  13. #include "buffer_manager.h"
  14. #include "packet.h"
  15. #include "log.h"
  16. #include "db.h"
  17. #include "questmanager.h"
  18. #include "monarch.h"
  19. #include "mob_manager.h"
  20. #include "locale_service.h"
  21.  
  22. /* ------------------------------------------------------------------------------------ */
  23. CShop::CShop()
  24. : m_dwVnum(0), m_dwNPCVnum(0), m_pkPC(NULL)
  25. {
  26. m_pGrid = M2_NEW CGrid(5, 9);
  27. }
  28.  
  29. CShop::~CShop()
  30. {
  31. TPacketGCShop pack;
  32.  
  33. pack.header = HEADER_GC_SHOP;
  34. pack.subheader = SHOP_SUBHEADER_GC_END;
  35. pack.size = sizeof(TPacketGCShop);
  36.  
  37. Broadcast(&pack, sizeof(pack));
  38.  
  39. GuestMapType::iterator it;
  40.  
  41. it = m_map_guest.begin();
  42.  
  43. while (it != m_map_guest.end())
  44. {
  45. LPCHARACTER ch = it->first;
  46. ch->SetShop(NULL);
  47. ++it;
  48. }
  49.  
  50. M2_DELETE(m_pGrid);
  51. }
  52.  
  53. void CShop::SetPCShop(LPCHARACTER ch)
  54. {
  55. m_pkPC = ch;
  56. }
  57.  
  58. bool CShop::Create(DWORD dwVnum, DWORD dwNPCVnum, TShopItemTable * pTable)
  59. {
  60. /*
  61. if (NULL == CMobManager::instance().Get(dwNPCVnum))
  62. {
  63. sys_err("No such a npc by vnum %d", dwNPCVnum);
  64. return false;
  65. }
  66. */
  67. sys_log(0, "SHOP #%d (Shopkeeper %d)", dwVnum, dwNPCVnum);
  68.  
  69. m_dwVnum = dwVnum;
  70. m_dwNPCVnum = dwNPCVnum;
  71.  
  72. BYTE bItemCount;
  73.  
  74. for (bItemCount = 0; bItemCount < SHOP_HOST_ITEM_MAX_NUM; ++bItemCount)
  75. if (0 == (pTable + bItemCount)->vnum)
  76. break;
  77.  
  78. SetShopItems(pTable, bItemCount);
  79. return true;
  80. }
  81.  
  82. void CShop::SetShopItems(TShopItemTable * pTable, BYTE bItemCount)
  83. {
  84. if (bItemCount > SHOP_HOST_ITEM_MAX_NUM)
  85. return;
  86.  
  87. m_pGrid->Clear();
  88.  
  89. m_itemVector.resize(SHOP_HOST_ITEM_MAX_NUM);
  90. memset(&m_itemVector[0], 0, sizeof(SHOP_ITEM) * m_itemVector.size());
  91.  
  92. for (int i = 0; i < bItemCount; ++i)
  93. {
  94. LPITEM pkItem = NULL;
  95. const TItemTable * item_table;
  96.  
  97. if (m_pkPC)
  98. {
  99. pkItem = m_pkPC->GetItem(pTable->pos);
  100.  
  101. if (!pkItem)
  102. {
  103. sys_err("cannot find item on pos (%d, %d) (name: %s)", pTable->pos.window_type, pTable->pos.cell, m_pkPC->GetName());
  104. continue;
  105. }
  106.  
  107. item_table = pkItem->GetProto();
  108. }
  109. else
  110. {
  111. if (!pTable->vnum)
  112. continue;
  113.  
  114. item_table = ITEM_MANAGER::instance().GetTable(pTable->vnum);
  115. }
  116.  
  117. if (!item_table)
  118. {
  119. sys_err("Shop: no item table by item vnum #%d", pTable->vnum);
  120. continue;
  121. }
  122.  
  123. int iPos;
  124.  
  125. if (IsPCShop())
  126. {
  127. sys_log(0, "MyShop: use position %d", pTable->display_pos);
  128. iPos = pTable->display_pos;
  129. }
  130. else
  131. iPos = m_pGrid->FindBlank(1, item_table->bSize);
  132.  
  133. if (iPos < 0)
  134. {
  135. sys_err("not enough shop window");
  136. continue;
  137. }
  138.  
  139. if (!m_pGrid->IsEmpty(iPos, 1, item_table->bSize))
  140. {
  141. if (IsPCShop())
  142. {
  143. sys_err("not empty position for pc shop %s[%d]", m_pkPC->GetName(), m_pkPC->GetPlayerID());
  144. }
  145. else
  146. {
  147. sys_err("not empty position for npc shop");
  148. }
  149. continue;
  150. }
  151.  
  152. m_pGrid->Put(iPos, 1, item_table->bSize);
  153.  
  154. SHOP_ITEM & item = m_itemVector[iPos];
  155.  
  156. item.pkItem = pkItem;
  157. item.itemid = 0;
  158.  
  159. if (item.pkItem)
  160. {
  161. item.vnum = pkItem->GetVnum();
  162. item.count = pkItem->GetCount(); // PC 샵의 경우 아이템 개수는 진짜 아이템의 개수여야 한다.
  163. item.price = pTable->price; // 가격도 사용자가 정한대로..
  164. #ifdef ENABLE_BUY_WITH_ITEM
  165. item.witemVnum = pTable->witemVnum;
  166. #endif
  167. item.itemid = pkItem->GetID();
  168. }
  169. else
  170. {
  171. item.vnum = pTable->vnum;
  172. item.count = pTable->count;
  173.  
  174. if (IS_SET(item_table->dwFlags, ITEM_FLAG_COUNT_PER_1GOLD))
  175. {
  176. if (item_table->dwGold == 0)
  177. item.price = item.count;
  178. else
  179. item.price = item.count / item_table->dwGold;
  180. }
  181. else
  182. item.price = item_table->dwGold * item.count;
  183. }
  184.  
  185. char name[36];
  186. snprintf(name, sizeof(name), "%-20s(#%-5d) (x %d)", item_table->szName, (int) item.vnum, item.count);
  187.  
  188. sys_log(0, "SHOP_ITEM: %-36s PRICE %-5d", name, item.price);
  189. ++pTable;
  190. }
  191. }
  192.  
  193. int CShop::Buy(LPCHARACTER ch, BYTE pos)
  194. {
  195. if (pos >= m_itemVector.size())
  196. {
  197. sys_log(0, "Shop::Buy : invalid position %d : %s", pos, ch->GetName());
  198. return SHOP_SUBHEADER_GC_INVALID_POS;
  199. }
  200.  
  201. sys_log(0, "Shop::Buy : name %s pos %d", ch->GetName(), pos);
  202.  
  203. GuestMapType::iterator it = m_map_guest.find(ch);
  204.  
  205. if (it == m_map_guest.end())
  206. return SHOP_SUBHEADER_GC_END;
  207.  
  208. SHOP_ITEM& r_item = m_itemVector[pos];
  209.  
  210. if (r_item.price < 0)
  211. {
  212. LogManager::instance().HackLog("SHOP_BUY_GOLD_OVERFLOW", ch);
  213. return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
  214. }
  215.  
  216. LPITEM pkSelectedItem = ITEM_MANAGER::instance().Find(r_item.itemid);
  217.  
  218. if (IsPCShop())
  219. {
  220. if (!pkSelectedItem)
  221. {
  222. sys_log(0, "Shop::Buy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d",
  223. ch->GetPlayerID(),
  224. m_pkPC->GetPlayerID());
  225.  
  226. return false;
  227. }
  228.  
  229. if ((pkSelectedItem->GetOwner() != m_pkPC))
  230. {
  231. sys_log(0, "Shop::Buy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d",
  232. ch->GetPlayerID(),
  233. m_pkPC->GetPlayerID());
  234.  
  235. return false;
  236. }
  237. }
  238.  
  239. DWORD dwPrice = r_item.price;
  240. #ifdef ENABLE_BUY_WITH_ITEM
  241. DWORD dwWItemVnum = r_item.witemVnum;
  242. #endif
  243.  
  244. if (it->second) // if other empire, price is triple
  245. dwPrice *= 3;
  246.  
  247. #ifdef ENABLE_BUY_WITH_ITEM
  248. if (dwWItemVnum > 0)
  249. if (ch->CountSpecifyItem(dwWItemVnum) < (int)dwPrice)
  250. return SHOP_SUBHEADER_GC_NOT_ENOUGH_ITEM;
  251. else if (ch->GetGold() < (int) dwPrice)
  252. #else
  253. if (ch->GetGold() < (int) dwPrice)
  254. #endif
  255.  
  256. LPITEM item;
  257.  
  258. if (m_pkPC) // 피씨가 운영하는 샵은 피씨가 실제 아이템을 가지고있어야 한다.
  259. item = r_item.pkItem;
  260. else
  261. item = ITEM_MANAGER::instance().CreateItem(r_item.vnum, r_item.count);
  262.  
  263. if (!item)
  264. return SHOP_SUBHEADER_GC_SOLD_OUT;
  265.  
  266. /* if (!m_pkPC)
  267. {
  268. if (quest::CQuestManager::instance().GetEventFlag("hivalue_item_sell") == 0)
  269. {
  270. //축복의 구슬 && 만년한철 이벤트
  271. if (item->GetVnum() == 70024 || item->GetVnum() == 70035)
  272. {
  273. return SHOP_SUBHEADER_GC_END;
  274. }
  275. }
  276. */
  277.  
  278. int iEmptyPos;
  279. if (item->IsDragonSoul())
  280. {
  281. iEmptyPos = ch->GetEmptyDragonSoulInventory(item);
  282. }
  283. else
  284. {
  285. iEmptyPos = ch->GetEmptyInventory(item->GetSize());
  286. }
  287.  
  288. if (iEmptyPos < 0)
  289. {
  290. if (m_pkPC)
  291. {
  292. sys_log(1, "Shop::Buy at PC Shop : Inventory full : %s size %d", ch->GetName(), item->GetSize());
  293. return SHOP_SUBHEADER_GC_INVENTORY_FULL;
  294. }
  295. else
  296. {
  297. sys_log(1, "Shop::Buy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
  298. M2_DESTROY_ITEM(item);
  299. return SHOP_SUBHEADER_GC_INVENTORY_FULL;
  300. }
  301. }
  302.  
  303. #ifdef ENABLE_BUY_WITH_ITEM
  304. if (dwWItemVnum > 0)
  305. ch->RemoveSpecifyItem(dwWItemVnum, dwPrice);
  306. else
  307. ch->PointChange(POINT_GOLD, -dwPrice, false);
  308. #else
  309. ch->PointChange(POINT_GOLD, -dwPrice, false);
  310. #endif
  311.  
  312. //세금 계산
  313. DWORD dwTax = 0;
  314. int iVal = 0;
  315.  
  316. if (LC_IsYMIR() || LC_IsKorea())
  317. {
  318. if (0 < (iVal = quest::CQuestManager::instance().GetEventFlag("trade_tax")))
  319. {
  320. if (iVal > 100)
  321. iVal = 100;
  322.  
  323. dwTax = dwPrice * iVal / 100;
  324. dwPrice = dwPrice - dwTax;
  325. }
  326. else
  327. {
  328. iVal = 0;
  329. dwTax = dwPrice * iVal / 100;
  330. dwPrice = dwPrice - dwTax;
  331. }
  332. }
  333. else
  334. {
  335. iVal = quest::CQuestManager::instance().GetEventFlag("personal_shop");
  336.  
  337. if (0 < iVal)
  338. {
  339. if (iVal > 100)
  340. iVal = 100;
  341.  
  342. dwTax = dwPrice * iVal / 100;
  343. dwPrice = dwPrice - dwTax;
  344. }
  345. else
  346. {
  347. iVal = 0;
  348. dwTax = 0;
  349. }
  350. }
  351.  
  352. // 상점에서 살‹š 세금 5%
  353. if (!m_pkPC)
  354. {
  355. CMonarch::instance().SendtoDBAddMoney(dwTax, ch->GetEmpire(), ch);
  356. }
  357.  
  358. // 군주 시스템 : 세금 징수
  359. if (m_pkPC)
  360. {
  361. m_pkPC->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 255);
  362.  
  363. if (item->GetVnum() == 90008 || item->GetVnum() == 90009) // VCARD
  364. {
  365. VCardUse(m_pkPC, ch, item);
  366. item = NULL;
  367. }
  368. else
  369. {
  370. char buf[512];
  371.  
  372. if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
  373. {
  374. snprintf(buf, sizeof(buf), "%s FROM: %u TO: %u PRICE: %u", item->GetName(), ch->GetPlayerID(), m_pkPC->GetPlayerID(), dwPrice);
  375. LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), SHOP_BUY, buf);
  376. LogManager::instance().GoldBarLog(m_pkPC->GetPlayerID(), item->GetID(), SHOP_SELL, buf);
  377. }
  378.  
  379. item->RemoveFromCharacter();
  380. if (item->IsDragonSoul())
  381. item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
  382. else
  383. item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
  384. ITEM_MANAGER::instance().FlushDelayedSave(item);
  385.  
  386.  
  387. snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", item->GetName(), m_pkPC->GetPlayerID(), m_pkPC->GetName(), dwPrice, item->GetCount());
  388. LogManager::instance().ItemLog(ch, item, "SHOP_BUY", buf);
  389.  
  390. snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", item->GetName(), ch->GetPlayerID(), ch->GetName(), dwPrice, item->GetCount());
  391. LogManager::instance().ItemLog(m_pkPC, item, "SHOP_SELL", buf);
  392. }
  393.  
  394. r_item.pkItem = NULL;
  395. BroadcastUpdateItem(pos);
  396.  
  397. m_pkPC->PointChange(POINT_GOLD, dwPrice, false);
  398.  
  399. if (iVal > 0)
  400. m_pkPC->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("판매금액의 %d %% 가 세금으로 나가게됩니다"), iVal);
  401.  
  402. CMonarch::instance().SendtoDBAddMoney(dwTax, m_pkPC->GetEmpire(), m_pkPC);
  403. }
  404. else
  405. {
  406. if (item->IsDragonSoul())
  407. item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
  408. else
  409. item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
  410. ITEM_MANAGER::instance().FlushDelayedSave(item);
  411. LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());
  412.  
  413. if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
  414. {
  415. LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), PERSONAL_SHOP_BUY, "");
  416. }
  417.  
  418. DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), -dwPrice);
  419. }
  420.  
  421. if (item)
  422. sys_log(0, "SHOP: BUY: name %s %s(x %d):%u price %u", ch->GetName(), item->GetName(), item->GetCount(), item->GetID(), dwPrice);
  423.  
  424. ch->Save();
  425.  
  426. return (SHOP_SUBHEADER_GC_OK);
  427. }
  428.  
  429. bool CShop::AddGuest(LPCHARACTER ch, DWORD owner_vid, bool bOtherEmpire)
  430. {
  431. if (!ch)
  432. return false;
  433.  
  434. if (ch->GetExchange())
  435. return false;
  436.  
  437. if (ch->GetShop())
  438. return false;
  439.  
  440. ch->SetShop(this);
  441.  
  442. m_map_guest.insert(GuestMapType::value_type(ch, bOtherEmpire));
  443.  
  444. TPacketGCShop pack;
  445.  
  446. pack.header = HEADER_GC_SHOP;
  447. pack.subheader = SHOP_SUBHEADER_GC_START;
  448.  
  449. TPacketGCShopStart pack2;
  450.  
  451. memset(&pack2, 0, sizeof(pack2));
  452. pack2.owner_vid = owner_vid;
  453.  
  454. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  455. {
  456. const SHOP_ITEM & item = m_itemVector[i];
  457.  
  458. /* //HIVALUE_ITEM_EVENT
  459. if (quest::CQuestManager::instance().GetEventFlag("hivalue_item_sell") == 0)
  460. {
  461. //축복의 구슬 && 만년한철 이벤트
  462. if (item.vnum == 70024 || item.vnum == 70035)
  463. {
  464. continue;
  465. }
  466. }
  467. //END_HIVALUE_ITEM_EVENT
  468. if (m_pkPC && !item.pkItem)
  469. continue;*/
  470.  
  471. pack2.items[i].vnum = item.vnum;
  472.  
  473. if (bOtherEmpire) // no empire price penalty for pc shop
  474. pack2.items[i].price = item.price * 3;
  475. else
  476. pack2.items[i].price = item.price;
  477. #ifdef ENABLE_BUY_WITH_ITEM
  478. pack2.items[i].witemVnum = item.witemVnum;
  479. #endif
  480.  
  481. pack2.items[i].count = item.count;
  482.  
  483. if (item.pkItem)
  484. {
  485. thecore_memcpy(pack2.items[i].alSockets, item.pkItem->GetSockets(), sizeof(pack2.items[i].alSockets));
  486. thecore_memcpy(pack2.items[i].aAttr, item.pkItem->GetAttributes(), sizeof(pack2.items[i].aAttr));
  487. }
  488. }
  489.  
  490. pack.size = sizeof(pack) + sizeof(pack2);
  491.  
  492. ch->GetDesc()->BufferedPacket(&pack, sizeof(TPacketGCShop));
  493. ch->GetDesc()->Packet(&pack2, sizeof(TPacketGCShopStart));
  494. return true;
  495. }
  496.  
  497. void CShop::RemoveGuest(LPCHARACTER ch)
  498. {
  499. if (ch->GetShop() != this)
  500. return;
  501.  
  502. m_map_guest.erase(ch);
  503. ch->SetShop(NULL);
  504.  
  505. TPacketGCShop pack;
  506.  
  507. pack.header = HEADER_GC_SHOP;
  508. pack.subheader = SHOP_SUBHEADER_GC_END;
  509. pack.size = sizeof(TPacketGCShop);
  510.  
  511. ch->GetDesc()->Packet(&pack, sizeof(pack));
  512. }
  513.  
  514. void CShop::Broadcast(const void * data, int bytes)
  515. {
  516. sys_log(1, "Shop::Broadcast %p %d", data, bytes);
  517.  
  518. GuestMapType::iterator it;
  519.  
  520. it = m_map_guest.begin();
  521.  
  522. while (it != m_map_guest.end())
  523. {
  524. LPCHARACTER ch = it->first;
  525.  
  526. if (ch->GetDesc())
  527. ch->GetDesc()->Packet(data, bytes);
  528.  
  529. ++it;
  530. }
  531. }
  532.  
  533. void CShop::BroadcastUpdateItem(BYTE pos)
  534. {
  535. TPacketGCShop pack;
  536. TPacketGCShopUpdateItem pack2;
  537.  
  538. TEMP_BUFFER buf;
  539.  
  540. pack.header = HEADER_GC_SHOP;
  541. pack.subheader = SHOP_SUBHEADER_GC_UPDATE_ITEM;
  542. pack.size = sizeof(pack) + sizeof(pack2);
  543.  
  544. pack2.pos = pos;
  545.  
  546. if (m_pkPC && !m_itemVector[pos].pkItem)
  547. pack2.item.vnum = 0;
  548. else
  549. {
  550. pack2.item.vnum = m_itemVector[pos].vnum;
  551. if (m_itemVector[pos].pkItem)
  552. {
  553. thecore_memcpy(pack2.item.alSockets, m_itemVector[pos].pkItem->GetSockets(), sizeof(pack2.item.alSockets));
  554. thecore_memcpy(pack2.item.aAttr, m_itemVector[pos].pkItem->GetAttributes(), sizeof(pack2.item.aAttr));
  555. }
  556. else
  557. {
  558. memset(pack2.item.alSockets, 0, sizeof(pack2.item.alSockets));
  559. memset(pack2.item.aAttr, 0, sizeof(pack2.item.aAttr));
  560. }
  561. }
  562.  
  563. pack2.item.price = m_itemVector[pos].price;
  564. pack2.item.count = m_itemVector[pos].count;
  565. #ifdef ENABLE_BUY_WITH_ITEM
  566. pack2.item.witemVnum = m_itemVector[pos].witemVnum;
  567. #endif
  568.  
  569. buf.write(&pack, sizeof(pack));
  570. buf.write(&pack2, sizeof(pack2));
  571.  
  572. Broadcast(buf.read_peek(), buf.size());
  573. }
  574.  
  575. int CShop::GetNumberByVnum(DWORD dwVnum)
  576. {
  577. int itemNumber = 0;
  578.  
  579. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  580. {
  581. const SHOP_ITEM & item = m_itemVector[i];
  582.  
  583. if (item.vnum == dwVnum)
  584. {
  585. itemNumber += item.count;
  586. }
  587. }
  588.  
  589. return itemNumber;
  590. }
  591.  
  592. bool CShop::IsSellingItem(DWORD itemID)
  593. {
  594. bool isSelling = false;
  595.  
  596. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  597. {
  598. if (m_itemVector[i].itemid == itemID)
  599. {
  600. isSelling = true;
  601. break;
  602. }
  603. }
  604.  
  605. return isSelling;
  606.  
  607. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement