Advertisement
Guest User

Untitled

a guest
Oct 18th, 2017
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.78 KB | None | 0 0
  1. /*
  2. * Filename : offline_shop.cpp
  3. * Version : 0.1
  4. * Description : --
  5. */
  6.  
  7. #include "stdafx.h"
  8. #include "../../libgame/include/grid.h"
  9. #include "constants.h"
  10. #include "utils.h"
  11. #include "config.h"
  12. #include "desc.h"
  13. #include "desc_manager.h"
  14. #include "char.h"
  15. #include "char_manager.h"
  16. #include "item.h"
  17. #include "item_manager.h"
  18. #include "buffer_manager.h"
  19. #include "packet.h"
  20. #include "log.h"
  21. #include "db.h"
  22. #include "questmanager.h"
  23. #include "monarch.h"
  24. #include "mob_manager.h"
  25. #include "locale_service.h"
  26. #include "offline_shop.h"
  27. #include "p2p.h"
  28.  
  29.  
  30. COfflineShop::COfflineShop() : m_pkOfflineShopNPC(NULL)
  31. {
  32. m_pGrid = M2_NEW CGrid(12, 10);
  33. }
  34.  
  35.  
  36. COfflineShop::~COfflineShop()
  37. {
  38. TPacketGCShop pack;
  39. pack.header = HEADER_GC_OFFLINE_SHOP;
  40. pack.subheader = SHOP_SUBHEADER_GC_END;
  41. pack.size = sizeof(TPacketGCShop);
  42.  
  43. Broadcast(&pack, sizeof(pack));
  44.  
  45. for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); ++it)
  46. {
  47. LPCHARACTER ch = it->first;
  48. ch->SetOfflineShop(NULL);
  49. }
  50.  
  51. M2_DELETE(m_pGrid);
  52. }
  53.  
  54. void COfflineShop::SetOfflineShopNPC(LPCHARACTER npc)
  55. {
  56. m_pkOfflineShopNPC = npc;
  57. }
  58.  
  59. bool COfflineShop::AddGuest(LPCHARACTER ch, LPCHARACTER npc)
  60. {
  61. // If there is no ch, return false
  62. if (!ch)
  63. return false;
  64.  
  65. // If ch is exchanging, return false
  66. if (ch->GetExchange())
  67. return false;
  68.  
  69. // If target is shopping, return false
  70. if (ch->GetShop())
  71. return false;
  72.  
  73. // If target is look at private shop, return false
  74. if (ch->GetMyShop())
  75. return false;
  76.  
  77. // If target is look at offline shop, return false
  78. if (ch->GetOfflineShop())
  79. return false;
  80.  
  81. // If the npc is nullptr, return false
  82. if (!npc)
  83. return false;
  84.  
  85. // Start process
  86. ch->SetOfflineShop(this);
  87. m_map_guest.insert(GuestMapType::value_type(ch, false));
  88.  
  89. TPacketGCShop pack;
  90. pack.header = HEADER_GC_OFFLINE_SHOP;
  91. pack.subheader = SHOP_SUBHEADER_GC_START;
  92.  
  93. TPacketGCOfflineShopStart pack2;
  94. memset(&pack2, 0, sizeof(pack2));
  95. pack2.owner_vid = npc->GetVID();
  96.  
  97. std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM offline_shop_item%s WHERE owner_id = %u", get_table_postfix(), npc ? npc->GetOfflineShopRealOwner() : 0));
  98.  
  99. if (pMsg->Get()->uiNumRows == 0)
  100. {
  101. DBManager::instance().DirectQuery("DELETE FROM player.offline_shop_npc WHERE owner_id = %u", npc->GetOfflineShopRealOwner());
  102. ch->SetOfflineShop(NULL);
  103. ch->SetOfflineShopOwner(NULL);
  104. M2_DESTROY_CHARACTER(npc);
  105. return false;
  106. }
  107.  
  108. MYSQL_ROW row;
  109. while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
  110. {
  111. BYTE bPos = 0;
  112. str_to_number(bPos, row[0]);
  113.  
  114. str_to_number(pack2.items[bPos].count, row[1]);
  115. str_to_number(pack2.items[bPos].vnum, row[2]);
  116. str_to_number(pack2.items[bPos].price, row[3]);
  117.  
  118. DWORD alSockets[ITEM_SOCKET_MAX_NUM];
  119. for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
  120. str_to_number(alSockets[i], row[n]);
  121.  
  122. TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
  123. for (int i = 0, iStartType = 7, iStartValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartType += 2, iStartValue += 2)
  124. {
  125. str_to_number(aAttr[i].bType, row[iStartType]);
  126. str_to_number(aAttr[i].sValue, row[iStartValue]);
  127. }
  128.  
  129. thecore_memcpy(pack2.items[bPos].alSockets, alSockets, sizeof(pack2.items[bPos].alSockets));
  130. thecore_memcpy(pack2.items[bPos].aAttr, aAttr, sizeof(pack2.items[bPos].aAttr));
  131. }
  132.  
  133. pack.size = sizeof(pack) + sizeof(pack2);
  134.  
  135. if (ch->GetDesc())
  136. {
  137. ch->GetDesc()->BufferedPacket(&pack, sizeof(TPacketGCShop));
  138. ch->GetDesc()->Packet(&pack2, sizeof(TPacketGCOfflineShopStart));
  139. }
  140.  
  141. return true;
  142. }
  143.  
  144. void COfflineShop::RemoveGuest(LPCHARACTER ch)
  145. {
  146. // If this offline shop is not equal to this, break it
  147. if (ch->GetOfflineShop() != this)
  148. return;
  149.  
  150. m_map_guest.erase(ch);
  151. ch->SetOfflineShop(NULL);
  152.  
  153. TPacketGCShop pack;
  154. pack.header = HEADER_GC_OFFLINE_SHOP;
  155. pack.subheader = SHOP_SUBHEADER_GC_END;
  156. pack.size = sizeof(TPacketGCShop);
  157.  
  158. if (ch->GetDesc())
  159. ch->GetDesc()->Packet(&pack, sizeof(pack));
  160. }
  161.  
  162. void COfflineShop::RemoveAllGuest()
  163. {
  164. TPacketGCShop pack;
  165. pack.header = HEADER_GC_OFFLINE_SHOP;
  166. pack.subheader = SHOP_SUBHEADER_GC_END;
  167. pack.size = sizeof(TPacketGCShop);
  168.  
  169. Broadcast(&pack, sizeof(pack));
  170.  
  171. for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); ++it)
  172. {
  173. LPCHARACTER ch = it->first;
  174. ch->SetOfflineShop(NULL);
  175. }
  176. }
  177.  
  178. void COfflineShop::Destroy(LPCHARACTER npc)
  179. {
  180. DBManager::instance().Query("DELETE FROM %soffline_shop_npc WHERE owner_id = %u", get_table_postfix(), npc->GetOfflineShopRealOwner());
  181. RemoveAllGuest();
  182. M2_DESTROY_CHARACTER(npc);
  183. }
  184.  
  185. int COfflineShop::Buy(LPCHARACTER ch, BYTE bPos)
  186. {
  187. if (ch->GetOfflineShopOwner()->GetOfflineShopRealOwner() == ch->GetPlayerID())
  188. {
  189. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't buy anything from your offline shop."));
  190. return SHOP_SUBHEADER_GC_OK;
  191. }
  192.  
  193. if (bPos >= OFFLINE_SHOP_HOST_ITEM_MAX_NUM)
  194. {
  195. sys_log(0, "OfflineShop::Buy : invalid position %d : %s", bPos, ch->GetName());
  196. return SHOP_SUBHEADER_GC_INVALID_POS;
  197. }
  198.  
  199. sys_log(0, "OfflineShop::Buy : name %s pos %d", ch->GetName(), bPos);
  200.  
  201. GuestMapType::iterator it = m_map_guest.find(ch);
  202. if (it == m_map_guest.end())
  203. return SHOP_SUBHEADER_GC_END;
  204.  
  205. char szQuery[1024];
  206. snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM offline_shop_item%s WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetOfflineShopOwner()->GetOfflineShopRealOwner(), bPos);
  207. std::auto_ptr<SQLMsg> pMsg(DBManager::Instance().DirectQuery(szQuery));
  208.  
  209. MYSQL_ROW row;
  210.  
  211. long long llPrice = 0;
  212. DWORD dwItemVnum = 0;
  213. BYTE bCount = 0;
  214. DWORD alSockets[ITEM_SOCKET_MAX_NUM];
  215. TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
  216.  
  217. while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
  218. {
  219. str_to_number(bCount, row[1]);
  220. str_to_number(dwItemVnum, row[2]);
  221. str_to_number(llPrice, row[3]);
  222.  
  223. // Set Sockets
  224. for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
  225. str_to_number(alSockets[i], row[n]);
  226. // End Of Sockets
  227.  
  228. // Set Attributes
  229. for (int i = 0, iStartAttributeType = 7, iStartAttributeValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartAttributeType += 2, iStartAttributeValue += 2)
  230. {
  231. str_to_number(aAttr[i].bType, row[iStartAttributeType]);
  232. str_to_number(aAttr[i].sValue, row[iStartAttributeValue]);
  233. }
  234. // End Of Set Attributes
  235. }
  236.  
  237. // Brazil server is not use gold option.
  238. if (!LC_IsBrazil())
  239. {
  240. if (ch->GetGold() < static_cast<long long>(llPrice))
  241. {
  242. sys_log(1, "OfflineShop::Buy: Não possui gold suficiente: %s tem %u, preço: %u", ch->GetName(), ch->GetGold(), llPrice);
  243. return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
  244. }
  245. }
  246. else
  247. {
  248. int iItemCount = quest::CQuestManager::instance().GetCurrentCharacterPtr()->CountSpecifyItem(30183);
  249. if (iItemCount < static_cast<long long>(llPrice))
  250. {
  251. sys_log(1, "OfflineShop::Buy : Not enough gold mask : %s has %d, gold mask %lld", ch->GetName(), iItemCount, llPrice);
  252. return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
  253. }
  254. }
  255.  
  256. LPITEM pItem = ITEM_MANAGER::Instance().CreateItem(dwItemVnum, bCount);
  257. if (!pItem)
  258. return SHOP_SUBHEADER_GC_SOLD_OUT;
  259.  
  260. // Set Attributes, Sockets
  261. pItem->SetAttributes(aAttr);
  262. for (BYTE i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
  263. pItem->SetSocket(i, alSockets[i]);
  264. // End Of Set Attributes, Sockets
  265.  
  266. // If item is a dragon soul item or normal item
  267. int iEmptyPos = 0;
  268. if (pItem->IsDragonSoul())
  269. iEmptyPos = ch->GetEmptyDragonSoulInventory(pItem);
  270. else
  271. iEmptyPos = ch->GetEmptyInventory(pItem->GetSize());
  272.  
  273. // If iEmptyPos is less than 0, return inventory is full
  274. if (iEmptyPos < 0)
  275. return SHOP_SUBHEADER_GC_INVENTORY_FULL;
  276.  
  277. // If item is a dragon soul, add this item in dragon soul inventory
  278. if (pItem->IsDragonSoul())
  279. pItem->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
  280. else
  281. pItem->AddToCharacter(ch, TItemPos(INVENTORY,iEmptyPos));
  282.  
  283. if (pItem)
  284. sys_log(0, "OFFLINE_SHOP: BUY: name %s %s(x %u):%u price %lld", ch->GetName(), pItem->GetName(), pItem->GetCount(), pItem->GetID(), llPrice);
  285.  
  286.  
  287. // Check if the player is online
  288. LPCHARACTER tch = CHARACTER_MANAGER::instance().FindByPID(ch->GetOfflineShopOwner()->GetOfflineShopRealOwner());
  289. /*sys_log(0, "OFFLINE_SHOP: BUY - GOLD PHASE : buyer name and pid (%s : %d) , shop owner name and pid (%s : %d) , raw owner id taken from the shop pointer (%u)",ch->
  290. GetName(),ch->GetPlayerID(),tch->GetName(),tch->GetPlayerID(),ch->GetOfflineShopOwner()->GetOfflineShopRealOwner());*/
  291. if (!LC_IsBrazil())
  292. {
  293. if (tch)
  294. {
  295. bool bIsOverFlow = tch->GetGold() + llPrice > GOLD_MAX - 1 ? true : false;
  296. if (bIsOverFlow)
  297. DBManager::instance().DirectQuery("UPDATE player%s SET money2 = money2 + %lld WHERE id = %u", get_table_postfix(), llPrice, tch->GetPlayerID());
  298. else
  299. DBManager::instance().DirectQuery("UPDATE player%s SET money2 = money2 + %lld WHERE id = %u", get_table_postfix(), llPrice, tch->GetPlayerID());
  300. tch->PointChange(POINT_GOLD, llPrice, false);
  301. }
  302. else
  303. DBManager::instance().DirectQuery("UPDATE player%s SET money2 = money2 + %lld WHERE id = %u", get_table_postfix(), llPrice, ch->GetOfflineShopOwner()->GetOfflineShopRealOwner());
  304. }
  305.  
  306. RemoveItem(ch->GetOfflineShopOwner()->GetOfflineShopRealOwner(), bPos);
  307. BroadcastUpdateItem(bPos, ch->GetOfflineShopOwner()->GetOfflineShopRealOwner(), true);
  308. ch->PointChange(POINT_GOLD, -llPrice, false);
  309. ch->Save();
  310. LogManager::instance().ItemLog(ch, pItem, "BUY ITEM FROM OFFLINE SHOP", "");
  311.  
  312. BYTE bLeftItemCount = GetLeftItemCount(ch->GetOfflineShopOwner()->GetOfflineShopRealOwner());
  313. if (bLeftItemCount == 0)
  314. Destroy(ch->GetOfflineShopOwner());
  315.  
  316. return (SHOP_SUBHEADER_GC_OK);
  317. }
  318.  
  319. void COfflineShop::BroadcastUpdateItem(BYTE bPos, DWORD dwPID, bool bDestroy)
  320. {
  321. TPacketGCShop pack;
  322. TPacketGCShopUpdateItem pack2;
  323.  
  324. TEMP_BUFFER buf;
  325.  
  326. pack.header = HEADER_GC_OFFLINE_SHOP;
  327. pack.subheader = SHOP_SUBHEADER_GC_UPDATE_ITEM;
  328. pack.size = sizeof(pack) + sizeof(pack2);
  329. pack2.pos = bPos;
  330.  
  331. if (bDestroy)
  332. {
  333. pack2.item.vnum = 0;
  334. pack2.item.count = 0;
  335. pack2.item.price = 0;
  336. memset(pack2.item.alSockets, 0, sizeof(pack2.item.alSockets));
  337. memset(pack2.item.aAttr, 0, sizeof(pack2.item.aAttr));
  338. }
  339. else
  340. {
  341. char szQuery[1024];
  342. snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM offline_shop_item%s WHERE owner_id = %u and pos = %d", get_table_postfix(), dwPID, bPos);
  343.  
  344. std::auto_ptr<SQLMsg> pMsg(DBManager::Instance().DirectQuery(szQuery));
  345. MYSQL_ROW row;
  346. while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
  347. {
  348. str_to_number(pack2.item.count, row[1]);
  349. str_to_number(pack2.item.vnum, row[2]);
  350. str_to_number(pack2.item.price, row[3]);
  351.  
  352. // Set Sockets
  353. for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
  354. str_to_number(pack2.item.alSockets[i], row[n]);
  355. // End Of Sockets
  356.  
  357. // Set Attributes
  358. for (int i = 0, iStartAttributeType = 7, iStartAttributeValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartAttributeType += 2, iStartAttributeValue += 2)
  359. {
  360. str_to_number(pack2.item.aAttr[i].bType, row[iStartAttributeType]);
  361. str_to_number(pack2.item.aAttr[i].sValue, row[iStartAttributeValue]);
  362. }
  363. // End Of Set Attributes
  364. }
  365. }
  366.  
  367. buf.write(&pack, sizeof(pack));
  368. buf.write(&pack2, sizeof(pack2));
  369. Broadcast(buf.read_peek(), buf.size());
  370. }
  371.  
  372. void COfflineShop::BroadcastUpdatePrice(BYTE bPos, long long llPrice)
  373. {
  374. TPacketGCShop pack;
  375. TPacketGCShopUpdatePrice pack2;
  376.  
  377. TEMP_BUFFER buf;
  378.  
  379. pack.header = HEADER_GC_OFFLINE_SHOP;
  380. pack.subheader = SHOP_SUBHEADER_GC_UPDATE_PRICE;
  381. pack.size = sizeof(pack) + sizeof(pack2);
  382.  
  383. pack2.bPos = bPos;
  384. pack2.llPrice = llPrice;
  385.  
  386. buf.write(&pack, sizeof(pack));
  387. buf.write(&pack2, sizeof(pack2));
  388.  
  389. Broadcast(buf.read_peek(), buf.size());
  390. }
  391.  
  392. void COfflineShop::Refresh(LPCHARACTER ch)
  393. {
  394. TPacketGCShop pack;
  395. pack.header = HEADER_GC_OFFLINE_SHOP;
  396. pack.subheader = SHOP_SUBHEADER_GC_UPDATE_ITEM2;
  397.  
  398. TPacketGCOfflineShopStart pack2;
  399. memset(&pack2, 0, sizeof(pack2));
  400. pack2.owner_vid = 0;
  401.  
  402. std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM offline_shop_item%s WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID()));
  403. MYSQL_ROW row;
  404. while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
  405. {
  406. BYTE bPos = 0;
  407. str_to_number(bPos, row[0]);
  408.  
  409. str_to_number(pack2.items[bPos].count, row[1]);
  410. str_to_number(pack2.items[bPos].vnum, row[2]);
  411. str_to_number(pack2.items[bPos].price, row[3]);
  412.  
  413. DWORD alSockets[ITEM_SOCKET_MAX_NUM];
  414. for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
  415. str_to_number(alSockets[i], row[n]);
  416.  
  417. TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
  418. for (int i = 0, iStartType = 7, iStartValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartType += 2, iStartValue += 2)
  419. {
  420. str_to_number(aAttr[i].bType, row[iStartType]);
  421. str_to_number(aAttr[i].sValue, row[iStartValue]);
  422. }
  423.  
  424. thecore_memcpy(pack2.items[bPos].alSockets, alSockets, sizeof(pack2.items[bPos].alSockets));
  425. thecore_memcpy(pack2.items[bPos].aAttr, aAttr, sizeof(pack2.items[bPos].aAttr));
  426. }
  427.  
  428. pack.size = sizeof(pack) + sizeof(pack2);
  429. ch->GetDesc()->BufferedPacket(&pack, sizeof(TPacketGCShop));
  430. ch->GetDesc()->Packet(&pack2, sizeof(TPacketGCOfflineShopStart));
  431. }
  432.  
  433. bool COfflineShop::RemoveItem(DWORD dwVID, BYTE bPos)
  434. {
  435. std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("DELETE FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), dwVID, bPos));
  436. return pMsg->Get()->uiAffectedRows > 0;
  437. }
  438.  
  439. BYTE COfflineShop::GetLeftItemCount(DWORD dwPID)
  440. {
  441. std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT COUNT(*) FROM %soffline_shop_item WHERE owner_id = %u and status = 0", get_table_postfix(), dwPID));
  442. if (pMsg->Get()->uiNumRows == 0)
  443. return 0;
  444.  
  445. MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
  446. BYTE bCount = 0;
  447. str_to_number(bCount, row[0]);
  448. return bCount;
  449. }
  450.  
  451. void COfflineShop::Broadcast(const void * data, int bytes)
  452. {
  453. sys_log(1, "OfflineShop::Broadcast %p %d", data, bytes);
  454.  
  455. for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); ++it)
  456. {
  457. LPCHARACTER ch = it->first;
  458. if (ch->GetDesc())
  459. ch->GetDesc()->Packet(data, bytes);
  460. }
  461. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement