SamuraiXXL

shop.cpp

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