Guest User

Untitled

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