Guest User

Untitled

a guest
Dec 1st, 2020
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.24 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. //#define ENABLE_SHOP_BLACKLIST
  23. /* ------------------------------------------------------------------------------------ */
  24. CShop::CShop()
  25. : m_dwVnum(0), m_dwNPCVnum(0), m_pkPC(NULL)
  26. {
  27. m_pGrid = M2_NEW CGrid(5, 8);
  28. #ifdef OFFLINE_SHOP
  29. SetLocked(false);
  30. #endif
  31. }
  32.  
  33. #ifdef SHOP_SEARCH
  34. #ifdef SHOP_SEARCH_PRICE_MIN
  35. inline bool SHOP_SEARCH_PRICE_VAILD(long long item_price,long long price) {return (item_price <= price || price == 0);}
  36. #else
  37. inline bool SHOP_SEARCH_PRICE_VAILD(long long item_price,long long price) {return (item_price >= price);}
  38. #endif
  39. bool CShop::SearchItem(DWORD vnum, long long price,DWORD book)
  40. {
  41. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  42. {
  43. const SHOP_ITEM & item = m_itemVector[i];
  44. if (!item.pkItem)
  45. continue;
  46. if(item.vnum != vnum)
  47. continue;
  48. switch(item.vnum)
  49. {
  50. case 50300://skill book
  51. case 70037://forget skill book
  52. case 70055://forget skill book
  53. if (SHOP_SEARCH_PRICE_VAILD(item.price,price) && item.pkItem->GetSocket(0) == book)
  54. return true;
  55. break;
  56. default:
  57. if (SHOP_SEARCH_PRICE_VAILD(item.price,price))
  58. return true;
  59. break;
  60. }
  61.  
  62. }
  63.  
  64. return false;
  65. }
  66. #endif
  67.  
  68. CShop::~CShop()
  69. {
  70. TPacketGCShop pack;
  71.  
  72. pack.header = HEADER_GC_SHOP;
  73. pack.subheader = SHOP_SUBHEADER_GC_END;
  74. pack.size = sizeof(TPacketGCShop);
  75.  
  76. Broadcast(&pack, sizeof(pack));
  77.  
  78. GuestMapType::iterator it;
  79.  
  80. it = m_map_guest.begin();
  81.  
  82. while (it != m_map_guest.end())
  83. {
  84. LPCHARACTER ch = it->first;
  85. ch->SetShop(NULL);
  86. ++it;
  87. }
  88.  
  89. M2_DELETE(m_pGrid);
  90. }
  91.  
  92. void CShop::SetPCShop(LPCHARACTER ch)
  93. {
  94. m_pkPC = ch;
  95. }
  96.  
  97. bool CShop::Create(DWORD dwVnum, DWORD dwNPCVnum, TShopItemTable * pTable)
  98. {
  99. /*
  100. if (NULL == CMobManager::instance().Get(dwNPCVnum))
  101. {
  102. sys_err("No such a npc by vnum %d", dwNPCVnum);
  103. return false;
  104. }
  105. */
  106. sys_log(0, "SHOP #%d (Shopkeeper %d)", dwVnum, dwNPCVnum);
  107.  
  108. m_dwVnum = dwVnum;
  109. m_dwNPCVnum = dwNPCVnum;
  110.  
  111. BYTE bItemCount;
  112.  
  113. for (bItemCount = 0; bItemCount < SHOP_HOST_ITEM_MAX_NUM; ++bItemCount)
  114. if (0 == (pTable + bItemCount)->vnum)
  115. break;
  116.  
  117. SetShopItems(pTable, bItemCount);
  118. return true;
  119. }
  120.  
  121. void CShop::SetShopItems(TShopItemTable * pTable, BYTE bItemCount)
  122. {
  123. if (bItemCount > SHOP_HOST_ITEM_MAX_NUM)
  124. return;
  125.  
  126. m_pGrid->Clear();
  127.  
  128. m_itemVector.resize(SHOP_HOST_ITEM_MAX_NUM);
  129. memset(&m_itemVector[0], 0, sizeof(SHOP_ITEM) * m_itemVector.size());
  130.  
  131. for (int i = 0; i < bItemCount; ++i)
  132. {
  133. LPITEM pkItem = NULL;
  134. const TItemTable * item_table;
  135.  
  136. if (m_pkPC)
  137. {
  138. pkItem = m_pkPC->GetItem(pTable->pos);
  139.  
  140. if (!pkItem)
  141. {
  142. sys_err("cannot find item on pos (%d, %d) (name: %s)", pTable->pos.window_type, pTable->pos.cell, m_pkPC->GetName());
  143. continue;
  144. }
  145.  
  146. item_table = pkItem->GetProto();
  147. }
  148. else
  149. {
  150. if (!pTable->vnum)
  151. continue;
  152.  
  153. item_table = ITEM_MANAGER::instance().GetTable(pTable->vnum);
  154. }
  155.  
  156. if (!item_table)
  157. {
  158. sys_err("Shop: no item table by item vnum #%d", pTable->vnum);
  159. continue;
  160. }
  161.  
  162. int iPos;
  163.  
  164. if (IsPCShop())
  165. {
  166. sys_log(0, "MyShop: use position %d", pTable->display_pos);
  167. iPos = pTable->display_pos;
  168. }
  169. else
  170. iPos = m_pGrid->FindBlank(1, item_table->bSize);
  171.  
  172. if (iPos < 0)
  173. {
  174. sys_err("not enough shop window");
  175. continue;
  176. }
  177.  
  178. if (!m_pGrid->IsEmpty(iPos, 1, item_table->bSize))
  179. {
  180. if (IsPCShop())
  181. {
  182. sys_err("not empty position for pc shop %s[%d]", m_pkPC->GetName(), m_pkPC->GetPlayerID());
  183. }
  184. else
  185. {
  186. sys_err("not empty position for npc shop");
  187. }
  188. continue;
  189. }
  190.  
  191. m_pGrid->Put(iPos, 1, item_table->bSize);
  192.  
  193. SHOP_ITEM & item = m_itemVector[iPos];
  194.  
  195. item.pkItem = pkItem;
  196. item.itemid = 0;
  197.  
  198. if (item.pkItem)
  199. {
  200. item.vnum = pkItem->GetVnum();
  201. item.count = pkItem->GetCount(); // PC 샵의 경우 아이템 개수는 진짜 아이템의 개수여야 한다.
  202. item.price = pTable->price; // 가격도 사용자가 정한대로..
  203. item.itemid = pkItem->GetID();
  204. }
  205. else
  206. {
  207. item.vnum = pTable->vnum;
  208. item.count = pTable->count;
  209. #ifdef ENABLE_MULTISHOP
  210. item.wPriceVnum = pTable->wPriceVnum;
  211. item.wPrice = pTable->wPrice;
  212. #endif
  213.  
  214. if (IS_SET(item_table->dwFlags, ITEM_FLAG_COUNT_PER_1GOLD))
  215. {
  216. if (item_table->dwGold == 0)
  217. item.price = item.count;
  218. else
  219. item.price = item.count / item_table->dwGold;
  220. }
  221. else
  222. item.price = item_table->dwGold * item.count;
  223. }
  224.  
  225. char name[36];
  226. snprintf(name, sizeof(name), "%-20s(#%-5d) (x %d)", item_table->szName, (int) item.vnum, item.count);
  227.  
  228. sys_log(0, "SHOP_ITEM: %-36s PRICE %-5d", name, item.price);
  229. ++pTable;
  230. }
  231. }
  232.  
  233. #ifdef OFFLINE_SHOP
  234. #include "char.h"
  235. #ifdef ENABLE_YANG_LIMIT
  236. long long CShop::Buy(LPCHARACTER ch, BYTE pos)
  237. #else
  238. int CShop::Buy(LPCHARACTER ch, BYTE pos)
  239. #endif
  240. {
  241. if (IsLocked())
  242. return SHOP_SUBHEADER_GC_END;
  243.  
  244. if (pos >= m_itemVector.size())
  245. {
  246. sys_log(0, "Shop::Buy : invalid position %d : %s", pos, ch->GetName());
  247. return SHOP_SUBHEADER_GC_INVALID_POS;
  248. }
  249.  
  250. sys_log(0, "Shop::Buy : name %s pos %d", ch->GetName(), pos);
  251.  
  252. GuestMapType::iterator it = m_map_guest.find(ch);
  253.  
  254. if (it == m_map_guest.end())
  255. return SHOP_SUBHEADER_GC_END;
  256.  
  257. SHOP_ITEM& r_item = m_itemVector[pos];
  258.  
  259. if (r_item.price < 0)
  260. {
  261. LogManager::instance().HackLog("SHOP_BUY_GOLD_OVERFLOW", ch);
  262. return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
  263. }
  264.  
  265. LPITEM pkSelectedItem = ITEM_MANAGER::instance().Find(r_item.itemid);
  266.  
  267. #ifdef FULL_YANG
  268. long long dwPrice = r_item.price;
  269. #else
  270. DWORD dwPrice = r_item.price;
  271. #endif
  272. #ifdef ENABLE_MULTISHOP
  273. DWORD dwWItemVnum = r_item.wPriceVnum;
  274. DWORD dwWItemPrice = r_item.wPrice;
  275. #endif
  276.  
  277. DWORD dwTax = 0;
  278.  
  279.  
  280. int iVal = quest::CQuestManager::instance().GetEventFlag ("personal_shop");
  281.  
  282. if (0 < iVal)
  283. {
  284. if (iVal > 100)
  285. {
  286. iVal = 100;
  287. }
  288.  
  289. dwTax = dwPrice * iVal / 100;
  290. dwPrice = dwPrice - dwTax;
  291. }
  292. else
  293. {
  294. iVal = 0;
  295. dwTax = 0;
  296. }
  297.  
  298. if (ch->GetGold() < r_item.price)
  299. {
  300. sys_log(1, "Shop::Buy : Not enough money : %s has %d, price %d", ch->GetName(), ch->GetGold(), dwPrice);
  301. return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
  302. }
  303. LPITEM item;
  304.  
  305. if (m_pkPC)
  306. item = r_item.pkItem;
  307. else {
  308. item = ITEM_MANAGER::instance().CreateItem(r_item.vnum, r_item.count);
  309. }
  310. if (!item)
  311. return SHOP_SUBHEADER_GC_SOLD_OUT;
  312.  
  313. int iEmptyPos;
  314. if (item->IsDragonSoul())
  315. {
  316. iEmptyPos = ch->GetEmptyDragonSoulInventory(item);
  317. }
  318. else
  319. {
  320. iEmptyPos = ch->GetEmptyInventory(item->GetSize());
  321. }
  322.  
  323. if (iEmptyPos < 0)
  324. {
  325. if (m_pkPC)
  326. {
  327. sys_log(1, "Shop::Buy at PC Shop : Inventory full : %s size %d", ch->GetName(), item->GetSize());
  328. return SHOP_SUBHEADER_GC_INVENTORY_FULL;
  329. }
  330. else
  331. {
  332. sys_log(1, "Shop::Buy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
  333. M2_DESTROY_ITEM(item);
  334. return SHOP_SUBHEADER_GC_INVENTORY_FULL;
  335. }
  336. }
  337. #ifdef FULL_YANG_OWN
  338. ch->ChangeGold(-dwPrice);
  339. #else
  340. ch->PointChange(POINT_GOLD, -dwPrice, false);
  341. #endif
  342. // ±?AO ˝?˝??? : ??±Y Aˇ?o
  343. if (m_pkPC)
  344. {
  345. if (!m_pkPC->IsPrivShop())
  346. m_pkPC->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 255);
  347.  
  348. char buf[512];
  349. DWORD mpid = (m_pkPC->IsPrivShop() ? m_pkPC->GetPrivShopOwner() : m_pkPC->GetPlayerID());
  350. if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
  351. {
  352. snprintf(buf, sizeof(buf), "%s FROM: %u TO: %u PRICE: %u", item->GetName(), ch->GetPlayerID(), mpid, dwPrice);
  353. LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), SHOP_BUY, buf);
  354. LogManager::instance().GoldBarLog(mpid, item->GetID(), SHOP_SELL, buf);
  355. }
  356. LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(r_item.vnum, r_item.count);
  357.  
  358. if (pkNewItem)
  359. {
  360. for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
  361. {
  362. pkNewItem->SetSocket(i, item->GetSocket(i));
  363. }
  364. // 매직 아이템 설정
  365. item->CopyAttributeTo(pkNewItem);
  366.  
  367. if (pkNewItem->IsDragonSoul())
  368. pkNewItem->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
  369. else
  370. pkNewItem->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
  371. item->RemoveFromCharacter();
  372. M2_DESTROY_ITEM(item);
  373. ITEM_MANAGER::instance().FlushDelayedSave(pkNewItem);
  374. std::string szBuy("SHOP_BUY");
  375. std::string szSell("SHOP_SELL");
  376. if (m_pkPC->IsPrivShop())
  377. {
  378. std::string temp("OFFLINE_");
  379. szBuy = temp + szBuy;
  380. szSell = temp + szSell;
  381. }
  382. #ifdef FULL_YANG
  383. snprintf(buf, sizeof(buf), "%s %u(%s) %lld %u", pkNewItem->GetName(), mpid, m_pkPC->GetName(), dwPrice, pkNewItem->GetCount());
  384. LogManager::instance().ItemLog(ch, pkNewItem, szBuy.c_str(), buf);
  385. snprintf(buf, sizeof(buf), "%s %u(%s) %lld %u", pkNewItem->GetName(), ch->GetPlayerID(), ch->GetName(), dwPrice, pkNewItem->GetCount());
  386. LogManager::instance().ItemLog(m_pkPC, pkNewItem, szSell.c_str(), buf);
  387. #else
  388. snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", pkNewItem->GetName(), mpid, m_pkPC->GetName(), dwPrice, pkNewItem->GetCount());
  389. LogManager::instance().ItemLog(ch, pkNewItem, szBuy.c_str(), buf);
  390. snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", pkNewItem->GetName(), ch->GetPlayerID(), ch->GetName(), dwPrice, pkNewItem->GetCount());
  391. LogManager::instance().ItemLog(m_pkPC, pkNewItem, szSell.c_str(), buf);
  392. #endif
  393.  
  394.  
  395.  
  396. r_item.pkItem = NULL;
  397. BroadcastUpdateItem(pos);
  398. if (m_pkPC->IsPrivShop()) {
  399. LPCHARACTER owner = CHARACTER_MANAGER::instance().FindByPID(m_pkPC->GetPrivShopOwner());
  400.  
  401.  
  402. #ifdef FULL_YANG
  403. DBManager::instance().DirectQuery("UPDATE player_shop SET gold=gold + %lld WHERE id=%d", dwPrice, m_pkPC->GetPrivShop());
  404. #else
  405. DBManager::instance().DirectQuery("UPDATE player_shop SET gold=gold + %d WHERE id=%d", dwPrice, m_pkPC->GetPrivShop());
  406. #endif
  407.  
  408.  
  409. DBManager::instance().DirectQuery("DELETE FROM player_shop_items WHERE shop_id=%d and id = %d", m_pkPC->GetPrivShop(), r_item.itemid);
  410. if (owner)
  411. {
  412. owner->LoadPrivShops();
  413. if (owner->GetGiftPages() > 0)
  414. owner->ChatPacket(CHAT_TYPE_COMMAND, "gift_info %d", owner->GetGiftPages());
  415. }
  416. }
  417. else{
  418. #ifdef FULL_YANG_OWN
  419. m_pkPC->ChangeGold(dwPrice);
  420. #else
  421. m_pkPC->PointChange(POINT_GOLD, dwPrice, false);
  422. #endif
  423. if (iVal > 0)
  424. {
  425. m_pkPC->ChatPacket (CHAT_TYPE_INFO, LC_TEXT ("판매금액의 %d %% 가 세금으로 나가게됩니다"), iVal);
  426. }
  427.  
  428. }
  429. item = pkNewItem;
  430. }
  431. else {
  432. return SHOP_SUBHEADER_GC_INVALID_POS;
  433. }
  434.  
  435.  
  436. }
  437. else
  438. {
  439. if (item->IsDragonSoul())
  440. item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
  441. else
  442. item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
  443. ITEM_MANAGER::instance().FlushDelayedSave(item);
  444. LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());
  445.  
  446. if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
  447. {
  448. LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), PERSONAL_SHOP_BUY, "");
  449. }
  450.  
  451. //DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), -dwPrice);
  452. }
  453.  
  454. if (item)
  455. sys_log(0, "SHOP: BUY: name %s %s(x %d):%u price %u", ch->GetName(), item->GetName(), item->GetCount(), item->GetID(), dwPrice);
  456. ch->Save();
  457. #if defined(SHOP_AUTO_CLOSE) && defined(OFFLINE_SHOP)
  458. if (m_pkPC && m_pkPC->IsPrivShop())
  459. {
  460. if (GetItemCount()<=0)
  461. m_pkPC->DeleteMyShop();
  462. }
  463. #endif
  464. return (SHOP_SUBHEADER_GC_OK);
  465. }
  466. void CShop::RemoveGuests(LPCHARACTER except)
  467. {
  468. GuestMapType::iterator it = m_map_guest.begin();
  469. while (it != m_map_guest.end())
  470. {
  471. LPCHARACTER ch = it->first;
  472. if (except && ch == except)
  473. {
  474. it++;
  475. continue;
  476. }
  477. if (ch)
  478. {
  479. ch->SetShop(NULL);
  480.  
  481. TPacketGCShop pack;
  482.  
  483. pack.header = HEADER_GC_SHOP;
  484. pack.subheader = SHOP_SUBHEADER_GC_END;
  485. pack.size = sizeof(TPacketGCShop);
  486.  
  487. ch->GetDesc()->Packet(&pack, sizeof(pack));
  488. }
  489. m_map_guest.erase(it++);
  490. }
  491. }
  492. void CShop::ClearItems()
  493. {
  494. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  495. {
  496. m_itemVector[i].pkItem = NULL;
  497. BroadcastUpdateItem(i);
  498. }
  499. }
  500. int CShop::GetItemCount()
  501. {
  502. int count = 0;
  503. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  504. {
  505. if (m_itemVector[i].pkItem)
  506. count++;
  507. }
  508. return count;
  509. }
  510. bool CShop::GetItems()
  511. {
  512. if (!m_pkPC)
  513. return false;
  514. if (!m_pkPC)
  515. return false;
  516. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  517. {
  518. if (!m_itemVector[i].pkItem)
  519. continue;
  520. char query[8192];
  521. sprintf(query, "INSERT INTO player_gift SET \
  522. owner_id=%d,vnum=%d,count=%d,reason='%s',`from`=replace(\"%s\",' ','_'),status='WAIT',date_add=NOW()",
  523. m_pkPC->GetPrivShopOwner(), m_itemVector[i].vnum, m_itemVector[i].count, LC_TEXT("SHOP_REASON"), m_pkPC->GetName());
  524.  
  525. for (int s = 0; s < ITEM_SOCKET_MAX_NUM; s++)
  526. {
  527. sprintf(query, "%s, socket%d='%ld'", query, s, m_itemVector[i].pkItem->GetSocket(s));
  528.  
  529. }
  530. for (int ia = 0; ia < ITEM_ATTRIBUTE_MAX_NUM; ia++)
  531. {
  532. const TPlayerItemAttribute& attr = m_itemVector[i].pkItem->GetAttribute(ia);
  533. if (ia < 7)
  534. {
  535. sprintf(query, "%s, attrtype%d='%u'", query, ia, attr.bType);
  536. sprintf(query, "%s, attrvalue%d='%d'", query, ia, attr.sValue);
  537. }
  538. else
  539. {
  540. sprintf(query, "%s, applytype%d='%u'", query, ia-7, attr.bType);
  541. sprintf(query, "%s, applyvalue%d='%d'", query, ia-7, attr.sValue);
  542. }
  543. }
  544. DBManager::instance().DirectQuery(query);
  545.  
  546. DBManager::instance().DirectQuery("delete from player_shop_items where id='%d'", m_itemVector[i].itemid);
  547. m_itemVector[i].pkItem->RemoveFromCharacter();
  548. m_itemVector[i].pkItem = NULL;
  549. BroadcastUpdateItem(i);
  550.  
  551. }
  552.  
  553.  
  554. return true;
  555. }
  556. void CShop::SetPrivShopItems(std::vector<TShopItemTable *> map_shop)
  557. {
  558. m_pGrid->Clear();
  559.  
  560. m_itemVector.resize(SHOP_HOST_ITEM_MAX_NUM);
  561. memset(&m_itemVector[0], 0, sizeof(SHOP_ITEM) * m_itemVector.size());
  562.  
  563. for (DWORD count = 0;count < map_shop.size();count++)
  564. {
  565. TShopItemTable * pTable = map_shop[count];
  566. LPITEM pkItem = NULL;
  567. const TItemTable * item_table;
  568.  
  569. if (!m_pkPC)
  570. return;
  571. pkItem = m_pkPC->GetItem(pTable->pos);
  572.  
  573. if (!pkItem)
  574. {
  575. sys_err("cannot find item on pos (%d, %d) (name: %s)", pTable->pos.window_type, pTable->pos.cell, m_pkPC->GetName());
  576. continue;
  577. }
  578.  
  579. item_table = pkItem->GetProto();
  580.  
  581.  
  582. if (!item_table)
  583. {
  584. sys_err("Shop: no item table by item vnum #%d", pTable->vnum);
  585. continue;
  586. }
  587.  
  588. WORD iPos = pTable->display_pos;
  589. sys_log(0, "MyShop: use position %d", iPos);
  590.  
  591.  
  592. if (iPos < 0)
  593. {
  594. sys_err("not enough shop window");
  595. continue;
  596. }
  597.  
  598. if (!m_pGrid->IsEmpty(iPos, 1, item_table->bSize))
  599. {
  600. sys_err("not empty position for pc shop %s[%d] fixing", m_pkPC->GetName(), m_pkPC->GetPlayerID());
  601. iPos = m_pGrid->FindBlank(1, item_table->bSize);
  602. if (!m_pGrid->IsEmpty(iPos, 1, item_table->bSize))
  603. {
  604. sys_err("not empty position for pc shop %s[%d]", m_pkPC->GetName(), m_pkPC->GetPlayerID());
  605. continue;
  606. }
  607. }
  608.  
  609. m_pGrid->Put(iPos, 1, item_table->bSize);
  610.  
  611. SHOP_ITEM & item = m_itemVector[iPos];
  612.  
  613. item.pkItem = pkItem;
  614. item.itemid = 0;
  615.  
  616. if (item.pkItem)
  617. {
  618. item.vnum = pkItem->GetVnum();
  619. item.count = pkItem->GetCount(); // PC ?? ?? ??? ??? ?? ???? ???? ??.
  620. item.price = pTable->price; // ??? ???? ????..
  621. item.itemid = pkItem->GetRealID();
  622.  
  623. }
  624.  
  625. char name[36];
  626. snprintf(name, sizeof(name), "%-20s(#%-5d) (x %d)", item_table->szName, (int)item.vnum, item.count);
  627.  
  628. sys_log(0, "PRIV_SHOP_ITEM: %-36s PRICE %-5d", name, item.price);
  629. }
  630. }
  631. #else
  632. int CShop::Buy(LPCHARACTER ch, BYTE pos)
  633. {
  634. if (pos >= m_itemVector.size())
  635. {
  636. sys_log(0, "Shop::Buy : invalid position %d : %s", pos, ch->GetName());
  637. return SHOP_SUBHEADER_GC_INVALID_POS;
  638. }
  639.  
  640. sys_log(0, "Shop::Buy : name %s pos %d", ch->GetName(), pos);
  641.  
  642. GuestMapType::iterator it = m_map_guest.find(ch);
  643.  
  644. if (it == m_map_guest.end())
  645. return SHOP_SUBHEADER_GC_END;
  646.  
  647. SHOP_ITEM& r_item = m_itemVector[pos];
  648.  
  649. if (r_item.price <= 0)
  650. {
  651. LogManager::instance().HackLog("SHOP_BUY_GOLD_OVERFLOW", ch);
  652. return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
  653. }
  654.  
  655. LPITEM pkSelectedItem = ITEM_MANAGER::instance().Find(r_item.itemid);
  656.  
  657. if (IsPCShop())
  658. {
  659. if (!pkSelectedItem)
  660. {
  661. sys_log(0, "Shop::Buy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d",
  662. ch->GetPlayerID(),
  663. m_pkPC->GetPlayerID());
  664.  
  665. return SHOP_SUBHEADER_GC_SOLD_OUT; // @fixme132 false to SHOP_SUBHEADER_GC_SOLD_OUT
  666. }
  667.  
  668. if ((pkSelectedItem->GetOwner() != m_pkPC))
  669. {
  670. sys_log(0, "Shop::Buy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d",
  671. ch->GetPlayerID(),
  672. m_pkPC->GetPlayerID());
  673.  
  674. return SHOP_SUBHEADER_GC_SOLD_OUT; // @fixme132 false to SHOP_SUBHEADER_GC_SOLD_OUT
  675. }
  676. }
  677.  
  678. #ifdef FULL_YANG
  679. long long dwPrice = r_item.price;
  680. #else
  681. DWORD dwPrice = r_item.price;
  682. #endif
  683.  
  684. if (it->second) // if other empire, price is triple
  685. dwPrice *= 1;
  686.  
  687. #ifdef ENABLE_MULTISHOP
  688. if (dwWItemVnum > 0)
  689. {
  690. if (ch->CountSpecifyItem(dwWItemVnum) < (int)dwWItemPrice)
  691. return SHOP_SUBHEADER_GC_NOT_ENOUGH_ITEM;
  692. }
  693. else if (ch->GetGold() < (long long) dwPrice)
  694. #else
  695. if (ch->GetGold() < (long long) dwPrice)
  696. #endif
  697. {
  698. #ifdef ENABLE_YANG_LIMIT
  699. sys_log(1, "Shop::Buy : Not enough money : %s has %lld, price %lld", ch->GetName(), ch->GetGold(), dwPrice);
  700. #else
  701. sys_log(1, "Shop::Buy : Not enough money : %s has %d, price %d", ch->GetName(), ch->GetGold(), dwPrice);
  702. #endif
  703. return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
  704. }
  705.  
  706. LPITEM item;
  707.  
  708. if (m_pkPC) // 피씨가 운영하는 샵은 피씨가 실제 아이템을 가지고있어야 한다.
  709. item = r_item.pkItem;
  710. else
  711. item = ITEM_MANAGER::instance().CreateItem(r_item.vnum, r_item.count);
  712.  
  713. if (!item)
  714. return SHOP_SUBHEADER_GC_SOLD_OUT;
  715.  
  716. #ifdef ENABLE_SHOP_BLACKLIST
  717. if (!m_pkPC)
  718. {
  719. if (quest::CQuestManager::instance().GetEventFlag("hivalue_item_sell") == 0)
  720. {
  721. //축복의 구슬 && 만년한철 이벤트
  722. if (item->GetVnum() == 70024 || item->GetVnum() == 70035)
  723. {
  724. return SHOP_SUBHEADER_GC_END;
  725. }
  726. }
  727. }
  728. #endif
  729.  
  730. int iEmptyPos;
  731. if (item->IsDragonSoul())
  732. {
  733. iEmptyPos = ch->GetEmptyDragonSoulInventory(item);
  734. }
  735. else
  736. {
  737. iEmptyPos = ch->GetEmptyInventory(item->GetSize());
  738. }
  739.  
  740. if (iEmptyPos < 0)
  741. {
  742. if (m_pkPC)
  743. {
  744. sys_log(1, "Shop::Buy at PC Shop : Inventory full : %s size %d", ch->GetName(), item->GetSize());
  745. return SHOP_SUBHEADER_GC_INVENTORY_FULL;
  746. }
  747. else
  748. {
  749. sys_log(1, "Shop::Buy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
  750. M2_DESTROY_ITEM(item);
  751. return SHOP_SUBHEADER_GC_INVENTORY_FULL;
  752. }
  753. }
  754.  
  755. #ifdef ENABLE_MULTISHOP
  756. if (dwWItemVnum > 0)
  757. ch->RemoveSpecifyItem(dwWItemVnum, dwWItemPrice);
  758. else
  759. ch->PointChange(POINT_GOLD, -dwPrice, false);
  760. #else
  761. ch->PointChange(POINT_GOLD, -dwPrice, false);
  762. #endif
  763.  
  764. //세금 계산
  765. DWORD dwTax = 0;
  766. int iVal = 0;
  767.  
  768. {
  769. iVal = quest::CQuestManager::instance().GetEventFlag("personal_shop");
  770.  
  771. if (0 < iVal)
  772. {
  773. if (iVal > 100)
  774. iVal = 100;
  775.  
  776. dwTax = dwPrice * iVal / 100;
  777. dwPrice = dwPrice - dwTax;
  778. }
  779. else
  780. {
  781. iVal = 0;
  782. dwTax = 0;
  783. }
  784. }
  785.  
  786. // 상점에서 살‹š 세금 5%
  787. if (!m_pkPC)
  788. {
  789. CMonarch::instance().SendtoDBAddMoney(dwTax, ch->GetEmpire(), ch);
  790. }
  791.  
  792. // 군주 시스템 : 세금 징수
  793. if (m_pkPC)
  794. {
  795. m_pkPC->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 255);
  796.  
  797. if (item->GetVnum() == 90008 || item->GetVnum() == 90009) // VCARD
  798. {
  799. VCardUse(m_pkPC, ch, item);
  800. item = NULL;
  801. }
  802. else
  803. {
  804. char buf[512];
  805.  
  806. if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
  807. {
  808. #ifdef ENABLE_YANG_LIMIT
  809. snprintf(buf, sizeof(buf), "%s FROM: %u TO: %u PRICE: %lld", item->GetName(), ch->GetPlayerID(), m_pkPC->GetPlayerID(), dwPrice);
  810. #else
  811. snprintf(buf, sizeof(buf), "%s FROM: %u TO: %u PRICE: %u", item->GetName(), ch->GetPlayerID(), m_pkPC->GetPlayerID(), dwPrice);
  812. #endif
  813. LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), SHOP_BUY, buf);
  814. LogManager::instance().GoldBarLog(m_pkPC->GetPlayerID(), item->GetID(), SHOP_SELL, buf);
  815. }
  816.  
  817. item->RemoveFromCharacter();
  818. if (item->IsDragonSoul())
  819. item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
  820. else
  821. item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
  822. ITEM_MANAGER::instance().FlushDelayedSave(item);
  823.  
  824. #ifdef ENABLE_YANG_LIMIT
  825. snprintf(buf, sizeof(buf), "%s %u(%s) %lld %u", item->GetName(), m_pkPC->GetPlayerID(), m_pkPC->GetName(), dwPrice, item->GetCount());
  826. #else
  827. snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", item->GetName(), m_pkPC->GetPlayerID(), m_pkPC->GetName(), dwPrice, item->GetCount());
  828. #endif
  829. LogManager::instance().ItemLog(ch, item, "SHOP_BUY", buf);
  830.  
  831. #ifdef ENABLE_YANG_LIMIT
  832. snprintf(buf, sizeof(buf), "%s %u(%s) %lld %u", item->GetName(), ch->GetPlayerID(), ch->GetName(), dwPrice, item->GetCount());
  833. #else
  834. snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", item->GetName(), ch->GetPlayerID(), ch->GetName(), dwPrice, item->GetCount());
  835. #endif
  836. LogManager::instance().ItemLog(m_pkPC, item, "SHOP_SELL", buf);
  837. }
  838.  
  839. r_item.pkItem = NULL;
  840. BroadcastUpdateItem(pos);
  841.  
  842. m_pkPC->PointChange(POINT_GOLD, dwPrice, false);
  843.  
  844. if (iVal > 0)
  845. m_pkPC->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("판매금액의 %d %% 가 세금으로 나가게됩니다"), iVal);
  846.  
  847. CMonarch::instance().SendtoDBAddMoney(dwTax, m_pkPC->GetEmpire(), m_pkPC);
  848. }
  849. else
  850. {
  851. if (item->IsDragonSoul())
  852. item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
  853. else
  854. item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
  855. ITEM_MANAGER::instance().FlushDelayedSave(item);
  856. LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());
  857.  
  858. if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
  859. {
  860. LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), PERSONAL_SHOP_BUY, "");
  861. }
  862.  
  863. DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), -dwPrice);
  864. }
  865.  
  866. if (item)
  867. #ifdef ENABLE_YANG_LIMIT
  868. sys_log(0, "SHOP: BUY: name %s %s(x %d):%u price %lld", ch->GetName(), item->GetName(), item->GetCount(), item->GetID(), dwPrice);
  869. #else
  870. sys_log(0, "SHOP: BUY: name %s %s(x %d):%u price %u", ch->GetName(), item->GetName(), item->GetCount(), item->GetID(), dwPrice);
  871. #endif
  872.  
  873. ch->Save();
  874.  
  875. return (SHOP_SUBHEADER_GC_OK);
  876. }
  877. #endif
  878.  
  879. bool CShop::AddGuest(LPCHARACTER ch, DWORD owner_vid, bool bOtherEmpire)
  880. {
  881. if (!ch)
  882. return false;
  883.  
  884. if (ch->GetExchange())
  885. return false;
  886.  
  887. if (ch->GetShop())
  888. return false;
  889.  
  890. ch->SetShop(this);
  891.  
  892. m_map_guest.insert(GuestMapType::value_type(ch, bOtherEmpire));
  893.  
  894. TPacketGCShop pack;
  895.  
  896. pack.header = HEADER_GC_SHOP;
  897. pack.subheader = SHOP_SUBHEADER_GC_START;
  898.  
  899. TPacketGCShopStart pack2;
  900.  
  901. memset(&pack2, 0, sizeof(pack2));
  902. pack2.owner_vid = owner_vid;
  903.  
  904. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  905. {
  906. const SHOP_ITEM & item = m_itemVector[i];
  907.  
  908. #ifdef ENABLE_SHOP_BLACKLIST
  909. //HIVALUE_ITEM_EVENT
  910. if (quest::CQuestManager::instance().GetEventFlag("hivalue_item_sell") == 0)
  911. {
  912. //축복의 구슬 && 만년한철 이벤트
  913. if (item.vnum == 70024 || item.vnum == 70035)
  914. {
  915. continue;
  916. }
  917. }
  918. #endif
  919. //END_HIVALUE_ITEM_EVENT
  920. if (m_pkPC && !item.pkItem)
  921. continue;
  922.  
  923. pack2.items[i].vnum = item.vnum;
  924.  
  925. // REMOVED_EMPIRE_PRICE_LIFT
  926. #ifdef ENABLE_NEWSTUFF
  927. if (bOtherEmpire && !g_bEmpireShopPriceTripleDisable) // no empire price penalty for pc shop
  928. #else
  929. if (bOtherEmpire) // no empire price penalty for pc shop
  930. #endif
  931. {
  932. pack2.items[i].price = item.price * 1;
  933. }
  934. else
  935. pack2.items[i].price = item.price;
  936. // END_REMOVED_EMPIRE_PRICE_LIFT
  937.  
  938. pack2.items[i].count = item.count;
  939. #ifdef ENABLE_MULTISHOP
  940. pack2.items[i].wPriceVnum = item.wPriceVnum;
  941. pack2.items[i].wPrice = item.wPrice;
  942. #endif
  943.  
  944. if (item.pkItem)
  945. {
  946. thecore_memcpy(pack2.items[i].alSockets, item.pkItem->GetSockets(), sizeof(pack2.items[i].alSockets));
  947. thecore_memcpy(pack2.items[i].aAttr, item.pkItem->GetAttributes(), sizeof(pack2.items[i].aAttr));
  948. #ifdef __CHANGELOOK_SYSTEM__
  949. pack2.items[i].transmutation = item.pkItem->GetTransmutation();
  950. #endif
  951. }
  952. }
  953.  
  954. pack.size = sizeof(pack) + sizeof(pack2);
  955.  
  956. ch->GetDesc()->BufferedPacket(&pack, sizeof(TPacketGCShop));
  957. ch->GetDesc()->Packet(&pack2, sizeof(TPacketGCShopStart));
  958. return true;
  959. }
  960.  
  961. void CShop::RemoveGuest(LPCHARACTER ch)
  962. {
  963. if (ch->GetShop() != this)
  964. return;
  965.  
  966. m_map_guest.erase(ch);
  967. ch->SetShop(NULL);
  968.  
  969. TPacketGCShop pack;
  970.  
  971. pack.header = HEADER_GC_SHOP;
  972. pack.subheader = SHOP_SUBHEADER_GC_END;
  973. pack.size = sizeof(TPacketGCShop);
  974.  
  975. ch->GetDesc()->Packet(&pack, sizeof(pack));
  976. }
  977.  
  978. void CShop::Broadcast(const void * data, int bytes)
  979. {
  980. sys_log(1, "Shop::Broadcast %p %d", data, bytes);
  981.  
  982. GuestMapType::iterator it;
  983.  
  984. it = m_map_guest.begin();
  985.  
  986. while (it != m_map_guest.end())
  987. {
  988. LPCHARACTER ch = it->first;
  989.  
  990. if (ch->GetDesc())
  991. ch->GetDesc()->Packet(data, bytes);
  992.  
  993. ++it;
  994. }
  995. }
  996.  
  997. void CShop::BroadcastUpdateItem(BYTE pos)
  998. {
  999. TPacketGCShop pack;
  1000. TPacketGCShopUpdateItem pack2;
  1001.  
  1002. TEMP_BUFFER buf;
  1003.  
  1004. pack.header = HEADER_GC_SHOP;
  1005. pack.subheader = SHOP_SUBHEADER_GC_UPDATE_ITEM;
  1006. pack.size = sizeof(pack) + sizeof(pack2);
  1007.  
  1008. pack2.pos = pos;
  1009.  
  1010. if (m_pkPC && !m_itemVector[pos].pkItem)
  1011. pack2.item.vnum = 0;
  1012. else
  1013. {
  1014. pack2.item.vnum = m_itemVector[pos].vnum;
  1015. if (m_itemVector[pos].pkItem)
  1016. {
  1017. thecore_memcpy(pack2.item.alSockets, m_itemVector[pos].pkItem->GetSockets(), sizeof(pack2.item.alSockets));
  1018. thecore_memcpy(pack2.item.aAttr, m_itemVector[pos].pkItem->GetAttributes(), sizeof(pack2.item.aAttr));
  1019. }
  1020. else
  1021. {
  1022. memset(pack2.item.alSockets, 0, sizeof(pack2.item.alSockets));
  1023. memset(pack2.item.aAttr, 0, sizeof(pack2.item.aAttr));
  1024. }
  1025. }
  1026.  
  1027. pack2.item.price = m_itemVector[pos].price;
  1028. pack2.item.count = m_itemVector[pos].count;
  1029. #ifdef ENABLE_MULTISHOP
  1030. pack2.item.wPriceVnum = m_itemVector[pos].wPriceVnum;
  1031. pack2.item.wPrice = m_itemVector[pos].wPrice;
  1032. #endif
  1033.  
  1034. buf.write(&pack, sizeof(pack));
  1035. buf.write(&pack2, sizeof(pack2));
  1036.  
  1037. Broadcast(buf.read_peek(), buf.size());
  1038. }
  1039.  
  1040. int CShop::GetNumberByVnum(DWORD dwVnum)
  1041. {
  1042. int itemNumber = 0;
  1043.  
  1044. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  1045. {
  1046. const SHOP_ITEM & item = m_itemVector[i];
  1047.  
  1048. if (item.vnum == dwVnum)
  1049. {
  1050. itemNumber += item.count;
  1051. }
  1052. }
  1053.  
  1054. return itemNumber;
  1055. }
  1056.  
  1057. bool CShop::IsSellingItem(DWORD itemID)
  1058. {
  1059. bool isSelling = false;
  1060.  
  1061. for (DWORD i = 0; i < m_itemVector.size() && i < SHOP_HOST_ITEM_MAX_NUM; ++i)
  1062. {
  1063. if ((unsigned int)(m_itemVector[i].itemid) == itemID)
  1064. {
  1065. isSelling = true;
  1066. break;
  1067. }
  1068. }
  1069.  
  1070. return isSelling;
  1071.  
  1072. }
  1073.  
Advertisement
Add Comment
Please, Sign In to add comment