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