View difference between Paste ID: T0Shr85w and vJcEBCQ1
SHOW: | | - or go back to the newest paste.
1
// Scriptname to put into creature_template: PreviewVendor
2
// dont forget to add vendor flags to the NPC (128)
3
4-
#include "ScriptPCH.h"
4+
#include "Common.h"
5
#include "ScriptMgr.h"
6-
static UNORDERED_MAP<uint32, std::vector<uint32> > itemList; // holds items from DB after startup
6+
#include "Player.h"
7
#include "Creature.h"
8
#include "ObjectGuid.h"
9
#include "WorldPacket.h"
10
#include "WorldSession.h"
11
12
static std::unordered_map<uint32, std::vector<uint32> > itemList; // holds items from DB after startup
13
14
class PreviewLoader : public WorldScript // script that loads items from DB so you can customize the vendors without recompile and restart
15
{
16
public:
17
    PreviewLoader() : WorldScript("PreviewLoader") { }
18
19
    void OnStartup()
20
    {
21
        itemList.clear(); // reload
22
        QueryResult result = WorldDatabase.Query("SELECT entry, item FROM npc_vendor_preview");
23
        if (!result)
24
            return;
25
        do
26
        {
27
            uint32 entry = (*result)[0].GetUInt32();
28
            uint32 item = (*result)[1].GetUInt32();
29
            if (sObjectMgr->GetItemTemplate(item))
30
                itemList[entry].push_back(item);
31
        } while (result->NextRow());
32
    }
33
34
    // you can reload config to reload the items.
35
    // Too lazy to make a command since all the RBAC stuff changes all the time now and not sure how you have it
36
    void OnConfigLoad(bool reload)
37
    {
38
        if (reload)
39
            OnStartup();
40
    }
41
};
42
43
44
class PreviewVendor : public CreatureScript
45
{
46
public:
47
    PreviewVendor() : CreatureScript("PreviewVendor") { }
48
49-
    void CustomSendListInventory(Player* player, uint64 vendorGuid)
49+
50
    {
51-
        TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Sent custom SMSG_LIST_INVENTORY");
51+
52
        return true; // stop normal actions
53
    }
54
55
    void CustomSendListInventory(Player* player, ObjectGuid vendorGuid)
56
    {
57
        TC_LOG_DEBUG("network", "WORLD: Sent custom SMSG_LIST_INVENTORY");
58-
            TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorGuid)));
58+
59-
            player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0);
59+
60
61
        Creature* vendor = player->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR);
62
        if (!vendor)
63
        {
64
            TC_LOG_DEBUG("network", "WORLD: SendListInventory - %s not found or you can not interact with him.", vendorGuid.ToString().c_str());
65
            player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, ObjectGuid::Empty, 0);
66
            return;
67
        }
68
69
        // remove fake death
70
        if (player->HasUnitState(UNIT_STATE_DIED))
71
            player->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
72
73
        // Stop the npc if moving
74
        if (vendor->HasUnitState(UNIT_STATE_MOVING))
75
            vendor->StopMoving();
76
77
        // VendorItemData const* items = vendor->GetVendorItems();
78
        if (itemList.find(vendor->GetEntry()) == itemList.end())
79
        {
80
            WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + 1);
81
            data << uint64(vendorGuid);
82
            data << uint8(0);                                   // count == 0, next will be error code
83
            data << uint8(0);                                   // "Vendor has no inventory"
84
            session->SendPacket(&data);
85
            return;
86
        }
87
88
        std::vector<uint32> items = itemList[vendor->GetEntry()];
89
        uint8 itemCount = items.size();
90
        uint8 count = 0;
91
92
        WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + itemCount * 8 * 4);
93
        data << uint64(vendorGuid);
94
95
        size_t countPos = data.wpos();
96
        data << uint8(count);
97
98
        // float discountMod = player->GetReputationPriceDiscount(vendor);
99
100
        for (uint8 slot = 0; slot < itemCount; ++slot)
101
        {
102
            if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(items[slot]))
103
            {
104
                if (!(itemTemplate->AllowableClass & player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP && !player->IsGameMaster())
105
                    continue;
106
                // Only display items in vendor lists for the team the
107
                // player is on. If GM on, display all items.
108
                if (!player->IsGameMaster() && ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && player->GetTeam() == ALLIANCE) || (itemTemplate->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && player->GetTeam() == HORDE)))
109
                    continue;
110
111-
                ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(vendor->GetEntry(), items[slot]);
111+
112-
                if (!sConditionMgr->IsObjectMeetToConditions(player, vendor, conditions))
112+
113
                // if (!player->IsGameMaster() && !leftInStock)
114-
                    TC_LOG_DEBUG(LOG_FILTER_CONDITIONSYS, "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), items[slot]);
114+
115
                uint32 leftInStock = 0xFFFFFFFF; // show all items
116
117
                if (!sConditionMgr->IsObjectMeetingVendorItemConditions(vendor->GetEntry(), items[slot], player, vendor))
118
                {
119
                    TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), items[slot]);
120
                    continue;
121
                }
122
123
                // reputation discount
124
                // int32 price = item->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
125
                int32 price = 0;
126
127
                data << uint32(slot + 1);       // client expects counting to start at 1
128
                data << uint32(items[slot]);
129
                data << uint32(itemTemplate->DisplayInfoID);
130
                data << int32(leftInStock); // left in stock
131
                data << uint32(price); // price
132
                data << uint32(itemTemplate->MaxDurability);
133
                data << uint32(itemTemplate->BuyCount);
134
                data << uint32(0); // extended cost
135
136
                if (++count >= MAX_VENDOR_ITEMS)
137
                    break;
138
            }
139
        }
140
141
        if (count == 0)
142
        {
143
            data << uint8(0);
144
            session->SendPacket(&data);
145
            return;
146
        }
147
148
        data.put<uint8>(countPos, count);
149
        session->SendPacket(&data);
150
    }
151
};
152
153
void AddSC_PreviewVendor()
154
{
155
    new PreviewLoader;
156
    new PreviewVendor;
157
}