关灯
开启左侧

一个用脚本实现,不需要数据库支持的NPC销售员

  [复制链接]
admin实名认证 发表于 2016-4-25 22:42:24 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
 
这个代码,我们都没有测试过,看起来,是直接在脚本中来发送操作码信息

总体说来,我觉得还是比较有研究价值的关于变态魔兽世界私服的一些脚本代码。

/*
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "GameEventMgr.h"
#include "Player.h"
#include "WorldSession.h"

class Vendor
{
private:
    int m_GUID;
    GossipOptionIcon m_Icon;
    std::string m_Message;
public:
    Vendor() {}
    Vendor(int guid, GossipOptionIcon icon, std::string message)
    {
        m_GUID = guid;
        m_Icon = icon;
        m_Message = message;
    }

    Vendor(int guid, GossipOptionIcon icon, std::string message, VendorItemData* item_list)
    {
        m_GUID = guid;
        m_Icon = icon;
        m_Message = message;
        for(int i = 0; i < item_list->GetItemCount(); i++)
            items.AddItem(item_list->m_items->item, 0, 0, item_list->m_items->ExtendedCost);
    }

    VendorItemData items;

    int getGuid() { return m_GUID; }
    void setGuid(int guid) { m_GUID = guid; }
    GossipOptionIcon getIcon() { return m_Icon; }
    void setIcon(GossipOptionIcon icon) { m_Icon = icon; }
    std::string getMessage() { return m_Message; }
    void setMessage(std::string message) { m_Message = message; }
};

class ItemList
{
public:
    ItemList() { /* Called while looping through vendors to find ours */ }

    ItemList(Vendor* myVendor)
    {
        m_vendor = Vendor(myVendor->getGuid(), myVendor->getIcon(), myVendor->getMessage());
    }

    ItemList(Vendor* myVendor, VendorItemData* item_list)
    {
        m_vendor = Vendor(myVendor->getGuid(), myVendor->getIcon(), myVendor->getMessage());
        for(int i = 0; i < item_list->GetItemCount(); i++)
            m_vendor.items.AddItem(item_list->m_items->item, 0, 0, item_list->m_items->ExtendedCost);
    }

    void AddItem(uint32 item_id, uint32 extended_cost = 0) { m_vendor.items.AddItem(item_id, 0, 0, extended_cost); }
    void RemoveItem(uint32 item_id) { m_vendor.items.RemoveItem(item_id); }
    uint8 GetItemCount() { return m_vendor.items.GetItemCount(); }
    Vendor GetVendor() { return m_vendor; }
private:
    Vendor m_vendor;
};

class SmsgListInventory
{
private:
    uint32 m_opcode;
    uint64 m_vendorGuid;
    uint8  m_itemCount;
    uint8  m_status;
    WorldSession* m_session;
    VendorItemData m_vendorItemData;
    VendorItemData m_completeVendorItemData;
    std::vector<ItemList> m_vendors;

    struct packetItem
    {
        uint32 m_slot;
        uint32 m_item;
        uint32 m_displayId;
        int32  m_inStock;
        uint32 m_price;
        uint32 m_durability;
        uint32 m_buyCount;
        uint32 m_extendedCost;
    };

    bool SkipItem(const ItemTemplate* item_template, Player* player, int slot)
    {
        /* Calculate relative slot position */
        if(m_vendors[0].GetItemCount() > 0)
        {
            if( (slot + 1) > (m_vendors[0].GetItemCount()))
            {
                int totalItemsChecked = 0;
                /* For each vendor */
                for(int i = 0; i < m_vendors.size(); i++)
                {
                    if((totalItemsChecked + m_vendors.GetItemCount()) < (slot + 1))
                    {
                        totalItemsChecked += m_vendors.GetItemCount();
                        continue;
                    }

                    slot -= totalItemsChecked;
                    break;
                }
            }
        }

        /* Account for duplicate items across vendors */
        if(VendorItem* vendor_item = m_vendorItemData.GetItem(slot))
        {
            if(vendor_item->item != item_template->ItemId)
                return true;
        }
        else
            return true; // the item doesn't even exist why would we send it

        /* GM's are exceptions */
        if(player->isGameMaster())
            return false;

        /* If the item is class specific and Bind on Pickup */
        if (!(item_template->AllowableClass & player->getClassMask()) && item_template->Bonding == BIND_WHEN_PICKED_UP)
            return true;

        /* If the item is faction specific and player is wrong faction */
        if ((item_template->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && player->GetTeam() == ALLIANCE) ||
            (item_template->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && player->GetTeam() == HORDE))
            return true;

        /* Anything else */
        return false;
    }

public: SmsgListInventory(uint64 vendor_guid, WorldSession* player_session, VendorItemData* vendor_item_data, std::vector<ItemList> vendors)
        {
            m_opcode = SMSG_LIST_INVENTORY;
            m_vendorGuid = vendor_guid;
            m_itemCount = 0;
            for(int i = 0; i < vendors.size(); i++)
                m_itemCount += vendors.GetItemCount();

            m_status = 0;
            m_session = player_session;
            for(int i = 0; i < vendors.size(); i++)
                for(int i2 = 0; i2 < vendors.GetItemCount(); i2++)
                    m_completeVendorItemData.AddItem(vendors.GetVendor().items.m_items[i2]->item, 0, 0, vendors.GetVendor().items.m_items[i2]->ExtendedCost);

            for(int i = 0; i < vendor_item_data->GetItemCount(); i++)
                m_vendorItemData.AddItem(vendor_item_data->m_items->item, 0, 0, vendor_item_data->m_items->ExtendedCost);

            for(int i = 0; i < vendors.size(); i++)
                m_vendors.push_back(vendors);
        }

        void Send(Creature* originalVendor, Player* player)
        {
            uint8 item_count = 0;
            std::vector<packetItem> items_to_send;
            ItemList item_list_to_send;
            bool haveUpdatedVendor = false;
            if(const VendorItemData* vendor_item_data = originalVendor->GetVendorItems())
                if(vendor_item_data->GetItemCount() > 0)
                    haveUpdatedVendor = true;

            for(int slot = 0; slot < m_itemCount; slot++)
                if(VendorItem const* item = m_completeVendorItemData.GetItem(slot))
                    if(ItemTemplate const* item_template = sObjectMgr->GetItemTemplate(item->item))
                    {
                        if(!haveUpdatedVendor)
                            sObjectMgr->AddVendorItem(originalVendor->GetEntry(), item->item, 0, 0, item->ExtendedCost, false);

                        if(SkipItem(item_template, player, slot))
                            continue;

                        item_list_to_send.AddItem(item->item, item->ExtendedCost);

                        item_count++;

                        int32 price = item->IsGoldRequired(item_template) ? uint32(item_template->BuyPrice) : 0;

                        packetItem packet;
                        packet.m_slot = slot + 1;
                        packet.m_item = item->item;
                        packet.m_displayId = item_template->DisplayInfoID;
                        packet.m_inStock = 0xFFFFFFFF;
                        packet.m_price = price;
                        packet.m_durability = item_template->MaxDurability;
                        packet.m_buyCount = item_template->BuyCount;
                        packet.m_extendedCost = item->ExtendedCost;
                        items_to_send.push_back(packet);
                    }

            WorldPacket packet(m_opcode, 8 + 1 + (m_itemCount > 0 ? m_itemCount * 8 * 4 : 1));
            packet << m_vendorGuid;
            packet << item_count;
            for(int i = 0; i < items_to_send.size(); i++)
            {
                packet << items_to_send.m_slot;
                packet << items_to_send.m_item;
                packet << items_to_send.m_displayId;
                packet << items_to_send.m_inStock;
                packet << items_to_send.m_price;
                packet << items_to_send.m_durability;
                packet << items_to_send.m_buyCount;
                packet << items_to_send.m_extendedCost;
            }
            m_session->SendPacket(&packet);
        }
};

class npc_multivendor : public CreatureScript
{
public:
    npc_multivendor() : CreatureScript("npc_multivendor"){ }

    std::vector<ItemList> GetVendorList()
    {
        std::vector<ItemList> itemlists;

        /* ONLY EDIT THINGS BELOW THIS COMMENT BLOCK
         * DO NOT EDIT ANYTHING ELSE
         *
         * Example vendor:

        Vendor vendor_1(700000, GOSSIP_ICON_VENDOR, "Look at all the weapons I have");
        ItemList items_1(&vendor_1);
        items_1.AddItem(18582); // Azzinoth
        items_1.AddItem(13262); // Ashbringer
        itemlists.push_back(items_1);

        * The first line creates a "Vendor" object named vendor_1 with:
        *     GUID 700000 (this must be different to all your other vendors)
        *     Displays the moneybag icon in the gossip list
        *     Displays the text "Look at all the weapons I have" in the gossip list
        *
        * The second line creates an instance of the ItemList object named items1.
        *     We pass it a reference to the vendor we created before. The class does the rest.
        *
        * The third and fourth lines are examples of adding items to our item list (named items_1).
        *     You can give an item an extended_cost by passing a second parameter to the function.
        *     This script does not support time-limited or respawning items
        *
        * 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.
        *
        *
        * END OF EXPLANATION
        * I REPEAT ONCE MORE PLEASE DO NOT TOUCH ANYTHING ELSE IN THE FILE IT IS EXTREMELY DELICATE AND EXTREMELY COMPLEX
        */

        Vendor vendor_1(700000, GOSSIP_ICON_VENDOR, "Look at all the weapons I have");
        ItemList items_1(&vendor_1);
        items_1.AddItem(18582); // Azzinoth
        items_1.AddItem(13262); // Ashbringer
        itemlists.push_back(items_1);

        Vendor vendor_2(700001, GOSSIP_ICON_VENDOR, "Look at all the armour I have");
        ItemList items_2(&vendor_2);
        items_2.AddItem(42949); // Polished Spaulders of Valor
        items_2.AddItem(48685); // Polished Breastplate of Valor
        itemlists.push_back(items_2);

        /* DO NOT EDIT ANYTHING BELOW HERE EITHER
         * THIS IS THE END OF THE EDITABLE SECTION
         * ONLY EDIT THINGS ABOVE THIS COMMENT BLOCK UNLESS YOU _REALLY_ KNOW WHAT YOU'RE DOING
         *
         * Peace out
         * Evilfairy~ */

        return itemlists;
    }

    bool OnGossipHello(Player* player, Creature* creature)
    {
        std::vector<ItemList> vendors = GetVendorList();

        /* DO NOT EDIT ANYTHING BELOW THIS LINE */
        for(int i = 0; i < vendors.size(); i++) // icon message sender guid
            player->ADD_GOSSIP_ITEM(vendors.GetVendor().getIcon(), vendors.GetVendor().getMessage(), GOSSIP_SENDER_MAIN, vendors.GetVendor().getGuid());

        player->TalkedToCreature(creature->GetEntry(), creature->GetGUID());
        player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
        return true;
    }

    bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
    {
        player->PlayerTalkClass->ClearMenus();
        player->CLOSE_GOSSIP_MENU();

        SendInventoryCustom(player, creature, action);

        return true;
    }

    void SendInventoryCustom(Player* player, Creature* vendor, int guid)
    {
        /* Remove Feign Death effects */
        if (player->HasUnitState(UNIT_STATE_DIED))
            player->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);

        /* Stop NPC moving */
        if (vendor->isMoving())
            vendor->StopMoving();

        std::vector<ItemList> vendors = GetVendorList();
        ItemList myVendor;
        for(int i = 0; i < vendors.size(); i++)
        {
            if(vendors.GetVendor().getGuid() == guid)
            {
                myVendor = ItemList(&vendors.GetVendor(), &vendors.GetVendor().items);
                break;
            }
        }

        SmsgListInventory inventory_packet(vendor->GetGUID(), player->GetSession(), &myVendor.GetVendor().items, vendors);
        inventory_packet.Send(vendor, player);
    }
};

void AddSC_npc_multivendor()
{
    new npc_multivendor;
}

具体的就不多说了,因为我也没有测试过,有兴趣的朋友可以去测试测试,本代码支持T端

完整代码回复下载
游客,如果您要查看本帖隐藏内容请回复

 

精彩评论1

倒序浏览
kabron 发表于 2016-12-24 20:59:54 | 显示全部楼层
 
支持吾爱尚玩,依照《金币》快速获取指南,即可获得金币免费下载游戏!
 
VIP介绍
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 最佳新人

    注册账号后积极发帖的会员
  • 活跃会员

    经常参与各类话题的讨论,发帖内容较有主见
  • 热心会员

    经常帮助其他会员答疑
  • 推广达人

    积极宣传本站,为本站带来更多注册会员
  • 宣传达人

    积极宣传本站,为本站带来更多的用户访问量
  • 灌水之王

    经常在论坛发帖,且发帖量较大
  • 突出贡献

    长期对论坛的繁荣而不断努力,或多次提出建设性意见
  • 优秀版主

    活跃且尽责职守的版主
  • 荣誉管理

    曾经为论坛做出突出贡献目前已离职的版主
  • 论坛元老

    为论坛做出突出贡献的会员

0关注

5粉丝

3421帖子

排行榜
作者专栏

QQ交流群&&微信订阅号

QQ交流群

微信订阅号

吾爱尚玩资源基地永久域名:

Www.523Play.Com

在线管理员QQ:1589479632

邮箱:Email@523play.com

QQ交流群:558936238

Copyright   ©2015-2116  吾爱尚玩资源基地|523play.comPowered by©523Pplay.Com技术支持:吾爱尚玩资源基地