midoking

Multi-Vendor

Jan 13th, 2013
371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.04 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify it
  5.  * under the terms of the GNU General Public License as published by the
  6.  * Free Software Foundation; either version 2 of the License, or (at your
  7.  * option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful, but WITHOUT
  10.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11.  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12.  * more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License along
  15.  * with this program. If not, see <http://www.gnu.org/licenses/>.
  16.  */
  17.  
  18. #include "ScriptMgr.h"
  19. #include "ScriptedCreature.h"
  20. #include "ScriptedGossip.h"
  21. #include "GameEventMgr.h"
  22. #include "Player.h"
  23. #include "WorldSession.h"
  24.  
  25. class Vendor
  26. {
  27. private:
  28.     int m_GUID;
  29.     GossipOptionIcon m_Icon;
  30.     std::string m_Message;
  31. public:
  32.     Vendor() {}
  33.     Vendor(int guid, GossipOptionIcon icon, std::string message)
  34.     {
  35.         m_GUID = guid;
  36.         m_Icon = icon;
  37.         m_Message = message;
  38.     }
  39.    
  40.     Vendor(int guid, GossipOptionIcon icon, std::string message, VendorItemData* item_list)
  41.     {
  42.         m_GUID = guid;
  43.         m_Icon = icon;
  44.         m_Message = message;
  45.         for(int i = 0; i < item_list->GetItemCount(); i++)
  46.             items.AddItem(item_list->m_items[i]->item, 0, 0, item_list->m_items[i]->ExtendedCost);
  47.     }
  48.  
  49.     VendorItemData items;
  50.  
  51.     int getGuid() { return m_GUID; }
  52.     void setGuid(int guid) { m_GUID = guid; }
  53.     GossipOptionIcon getIcon() { return m_Icon; }
  54.     void setIcon(GossipOptionIcon icon) { m_Icon = icon; }
  55.     std::string getMessage() { return m_Message; }
  56.     void setMessage(std::string message) { m_Message = message; }
  57. };
  58.  
  59. class ItemList
  60. {
  61. public:
  62.     ItemList() { /* Called while looping through vendors to find ours */ }
  63.  
  64.     ItemList(Vendor* myVendor)
  65.     {
  66.         m_vendor = Vendor(myVendor->getGuid(), myVendor->getIcon(), myVendor->getMessage());
  67.     }
  68.  
  69.     ItemList(Vendor* myVendor, VendorItemData* item_list)
  70.     {
  71.         m_vendor = Vendor(myVendor->getGuid(), myVendor->getIcon(), myVendor->getMessage());
  72.         for(int i = 0; i < item_list->GetItemCount(); i++)
  73.             m_vendor.items.AddItem(item_list->m_items[i]->item, 0, 0, item_list->m_items[i]->ExtendedCost);
  74.     }
  75.  
  76.     void AddItem(uint32 item_id, uint32 extended_cost = 0) { m_vendor.items.AddItem(item_id, 0, 0, extended_cost); }
  77.     void RemoveItem(uint32 item_id) { m_vendor.items.RemoveItem(item_id); }
  78.     uint8 GetItemCount() { return m_vendor.items.GetItemCount(); }
  79.     Vendor GetVendor() { return m_vendor; }
  80. private:
  81.     Vendor m_vendor;
  82. };
  83.  
  84. class SmsgListInventory
  85. {
  86. private:
  87.     uint32 m_opcode;
  88.     uint64 m_vendorGuid;
  89.     uint8  m_itemCount;
  90.     uint8  m_status;
  91.     WorldSession* m_session;
  92.     VendorItemData m_vendorItemData;
  93.     VendorItemData m_completeVendorItemData;
  94.     std::vector<ItemList> m_vendors;
  95.  
  96.     struct packetItem
  97.     {
  98.         uint32 m_slot;
  99.         uint32 m_item;
  100.         uint32 m_displayId;
  101.         int32  m_inStock;
  102.         uint32 m_price;
  103.         uint32 m_durability;
  104.         uint32 m_buyCount;
  105.         uint32 m_extendedCost;
  106.     };
  107.  
  108.     bool SkipItem(const ItemTemplate* item_template, Player* player, int slot)
  109.     {
  110.         /* Calculate relative slot position */
  111.         if(m_vendors[0].GetItemCount() > 0)
  112.         {
  113.             if( (slot + 1) > (m_vendors[0].GetItemCount()))
  114.             {
  115.                 int totalItemsChecked = 0;
  116.                 /* For each vendor */
  117.                 for(int i = 0; i < m_vendors.size(); i++)
  118.                 {
  119.                     if((totalItemsChecked + m_vendors[i].GetItemCount()) < (slot + 1))
  120.                     {
  121.                         totalItemsChecked += m_vendors[i].GetItemCount();
  122.                         continue;
  123.                     }
  124.  
  125.                     slot -= totalItemsChecked;
  126.                     break;
  127.                 }
  128.             }
  129.         }
  130.  
  131.         /* Account for duplicate items across vendors */
  132.         if(VendorItem* vendor_item = m_vendorItemData.GetItem(slot))
  133.         {
  134.             if(vendor_item->item != item_template->ItemId)
  135.                 return true;
  136.         }
  137.         else
  138.             return true; // the item doesn't even exist why would we send it
  139.  
  140.         /* GM's are exceptions */
  141.         if(player->isGameMaster())
  142.             return false;
  143.  
  144.         /* If the item is class specific and Bind on Pickup */
  145.         if (!(item_template->AllowableClass & player->getClassMask()) && item_template->Bonding == BIND_WHEN_PICKED_UP)
  146.             return true;
  147.        
  148.         /* If the item is faction specific and player is wrong faction */
  149.         if ((item_template->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && player->GetTeam() == ALLIANCE) ||
  150.             (item_template->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && player->GetTeam() == HORDE))
  151.             return true;
  152.  
  153.         /* Anything else */
  154.         return false;
  155.     }
  156.  
  157. public: SmsgListInventory(uint64 vendor_guid, WorldSession* player_session, VendorItemData* vendor_item_data, std::vector<ItemList> vendors)
  158.         {
  159.             m_opcode = SMSG_LIST_INVENTORY;
  160.             m_vendorGuid = vendor_guid;
  161.             m_itemCount = 0;
  162.             for(int i = 0; i < vendors.size(); i++)
  163.                 m_itemCount += vendors[i].GetItemCount();
  164.  
  165.             m_status = 0;
  166.             m_session = player_session;
  167.             for(int i = 0; i < vendors.size(); i++)
  168.                 for(int i2 = 0; i2 < vendors[i].GetItemCount(); i2++)
  169.                     m_completeVendorItemData.AddItem(vendors[i].GetVendor().items.m_items[i2]->item, 0, 0, vendors[i].GetVendor().items.m_items[i2]->ExtendedCost);
  170.  
  171.             for(int i = 0; i < vendor_item_data->GetItemCount(); i++)
  172.                 m_vendorItemData.AddItem(vendor_item_data->m_items[i]->item, 0, 0, vendor_item_data->m_items[i]->ExtendedCost);
  173.  
  174.             for(int i = 0; i < vendors.size(); i++)
  175.                 m_vendors.push_back(vendors[i]);
  176.         }
  177.  
  178.         void Send(Creature* originalVendor, Player* player)
  179.         {
  180.             uint8 item_count = 0;
  181.             std::vector<packetItem> items_to_send;
  182.             ItemList item_list_to_send;
  183.             bool haveUpdatedVendor = false;
  184.             if(const VendorItemData* vendor_item_data = originalVendor->GetVendorItems())
  185.                 if(vendor_item_data->GetItemCount() > 0)
  186.                     haveUpdatedVendor = true;
  187.  
  188.             for(int slot = 0; slot < m_itemCount; slot++)
  189.                 if(VendorItem const* item = m_completeVendorItemData.GetItem(slot))
  190.                     if(ItemTemplate const* item_template = sObjectMgr->GetItemTemplate(item->item))
  191.                     {
  192.                         if(!haveUpdatedVendor)
  193.                             sObjectMgr->AddVendorItem(originalVendor->GetEntry(), item->item, 0, 0, item->ExtendedCost, false);
  194.  
  195.                         if(SkipItem(item_template, player, slot))
  196.                             continue;
  197.  
  198.                         item_list_to_send.AddItem(item->item, item->ExtendedCost);
  199.  
  200.                         item_count++;
  201.  
  202.                         int32 price = item->IsGoldRequired(item_template) ? uint32(item_template->BuyPrice) : 0;
  203.  
  204.                         packetItem packet;
  205.                         packet.m_slot = slot + 1;
  206.                         packet.m_item = item->item;
  207.                         packet.m_displayId = item_template->DisplayInfoID;
  208.                         packet.m_inStock = 0xFFFFFFFF;
  209.                         packet.m_price = price;
  210.                         packet.m_durability = item_template->MaxDurability;
  211.                         packet.m_buyCount = item_template->BuyCount;
  212.                         packet.m_extendedCost = item->ExtendedCost;
  213.                         items_to_send.push_back(packet);
  214.                     }
  215.  
  216.             WorldPacket packet(m_opcode, 8 + 1 + (m_itemCount > 0 ? m_itemCount * 8 * 4 : 1));
  217.             packet << m_vendorGuid;
  218.             packet << item_count;
  219.             for(int i = 0; i < items_to_send.size(); i++)
  220.             {
  221.                 packet << items_to_send[i].m_slot;
  222.                 packet << items_to_send[i].m_item;
  223.                 packet << items_to_send[i].m_displayId;
  224.                 packet << items_to_send[i].m_inStock;
  225.                 packet << items_to_send[i].m_price;
  226.                 packet << items_to_send[i].m_durability;
  227.                 packet << items_to_send[i].m_buyCount;
  228.                 packet << items_to_send[i].m_extendedCost;
  229.             }
  230.             m_session->SendPacket(&packet);
  231.         }
  232. };
  233.  
  234. class npc_multivendor : public CreatureScript
  235. {
  236. public:
  237.     npc_multivendor() : CreatureScript("npc_multivendor"){ }
  238.  
  239.     std::vector<ItemList> GetVendorList()
  240.     {
  241.         std::vector<ItemList> itemlists;
  242.        
  243.         /* ONLY EDIT THINGS BELOW THIS COMMENT BLOCK
  244.          * DO NOT EDIT ANYTHING ELSE
  245.          *
  246.          * Example vendor:
  247.  
  248.         Vendor vendor_1(700000, GOSSIP_ICON_VENDOR, "Look at all the weapons I have");
  249.         ItemList items_1(&vendor_1);
  250.         items_1.AddItem(18582); // Azzinoth
  251.         items_1.AddItem(13262); // Ashbringer
  252.         itemlists.push_back(items_1);
  253.        
  254.         * The first line creates a "Vendor" object named vendor_1 with:
  255.         *     GUID 700000 (this must be different to all your other vendors)
  256.         *     Displays the moneybag icon in the gossip list
  257.         *     Displays the text "Look at all the weapons I have" in the gossip list
  258.         *
  259.         * The second line creates an instance of the ItemList object named items1.
  260.         *     We pass it a reference to the vendor we created before. The class does the rest.
  261.         *
  262.         * The third and fourth lines are examples of adding items to our item list (named items_1).
  263.         *     You can give an item an extended_cost by passing a second parameter to the function.
  264.         *     This script does not support time-limited or respawning items
  265.         *
  266.         * The final line is the most important. This line adds your vendor to the internal list of vendors that will be processed by the script.
  267.         *
  268.         *
  269.         * END OF EXPLANATION
  270.         * I REPEAT ONCE MORE PLEASE DO NOT TOUCH ANYTHING ELSE IN THE FILE IT IS EXTREMELY DELICATE AND EXTREMELY COMPLEX
  271.         */
  272.  
  273.         Vendor vendor_1(700000, GOSSIP_ICON_VENDOR, "Look at all the weapons I have");
  274.         ItemList items_1(&vendor_1);
  275.         items_1.AddItem(18582); // Azzinoth
  276.         items_1.AddItem(13262); // Ashbringer
  277.         itemlists.push_back(items_1);
  278.  
  279.         Vendor vendor_2(700001, GOSSIP_ICON_VENDOR, "Look at all the armour I have");
  280.         ItemList items_2(&vendor_2);
  281.         items_2.AddItem(42949); // Polished Spaulders of Valor
  282.         items_2.AddItem(48685); // Polished Breastplate of Valor
  283.         itemlists.push_back(items_2);
  284.  
  285.         /* DO NOT EDIT ANYTHING BELOW HERE EITHER
  286.          * THIS IS THE END OF THE EDITABLE SECTION
  287.          * ONLY EDIT THINGS ABOVE THIS COMMENT BLOCK UNLESS YOU _REALLY_ KNOW WHAT YOU'RE DOING
  288.          *
  289.          * Peace out
  290.          * Evilfairy~ */
  291.  
  292.         return itemlists;
  293.     }
  294.  
  295.     bool OnGossipHello(Player* player, Creature* creature)
  296.     {
  297.         std::vector<ItemList> vendors = GetVendorList();
  298.  
  299.         /* DO NOT EDIT ANYTHING BELOW THIS LINE */
  300.         for(int i = 0; i < vendors.size(); i++) // icon message sender guid
  301.             player->ADD_GOSSIP_ITEM(vendors[i].GetVendor().getIcon(), vendors[i].GetVendor().getMessage(), GOSSIP_SENDER_MAIN, vendors[i].GetVendor().getGuid());
  302.  
  303.         player->TalkedToCreature(creature->GetEntry(), creature->GetGUID());
  304.         player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
  305.         return true;
  306.     }
  307.  
  308.     bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
  309.     {
  310.         player->PlayerTalkClass->ClearMenus();
  311.         player->CLOSE_GOSSIP_MENU();
  312.        
  313.         SendInventoryCustom(player, creature, action);
  314.        
  315.         return true;
  316.     }
  317.  
  318.     void SendInventoryCustom(Player* player, Creature* vendor, int guid)
  319.     {
  320.         /* Remove Feign Death effects */
  321.         if (player->HasUnitState(UNIT_STATE_DIED))
  322.             player->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
  323.  
  324.         /* Stop NPC moving */
  325.         if (vendor->isMoving())
  326.             vendor->StopMoving();
  327.  
  328.         std::vector<ItemList> vendors = GetVendorList();
  329.         ItemList myVendor;
  330.         for(int i = 0; i < vendors.size(); i++)
  331.         {
  332.             if(vendors[i].GetVendor().getGuid() == guid)
  333.             {
  334.                 myVendor = ItemList(&vendors[i].GetVendor(), &vendors[i].GetVendor().items);
  335.                 break;
  336.             }
  337.         }
  338.  
  339.         SmsgListInventory inventory_packet(vendor->GetGUID(), player->GetSession(), &myVendor.GetVendor().items, vendors);
  340.         inventory_packet.Send(vendor, player);
  341.     }
  342. };
  343.  
  344. void AddSC_npc_multivendor()
  345. {
  346.     new npc_multivendor;
  347. }
Advertisement
Add Comment
Please, Sign In to add comment