Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local lootCmd = "char loot";
- -- Maximum loot shown on use of the loot command.
- local MAX_LOOT_VALUE = 20;
- -- Maximum results the loot table may contain, default: 500.
- -- NOTE: This is the lua table, so everything will be stored as normal.
- local MAX_RESULTS = 500;
- -- Player events.
- local PLAYER_EVENT_ON_USE_COMMAND = 42;
- local PLAYER_EVENT_ON_LOOT_ITEM = 32;
- -- Userdata types.
- local USERDATA_TYPE_PLAYER = 4;
- -- Pre-set queries.
- local QUERY_SELECT_DEFAULT = 1;
- local QUERY_SELECT_SPECIFIC = 2;
- local QUERY_INSERT_DEFAULT = 3;
- local QUERY_SELECT_COUNT = 4;
- local query = {
- [[
- SELECT date_time, player, item_id, item_count
- FROM player_loots
- WHERE player = '%s';
- ]],
- [[
- SELECT date_time, player, item_id, item_count
- FROM player_loots
- WHERE player = '%s' AND item_id = '%d';
- ]],
- [[
- INSERT INTO player_loots
- VALUES ('%d', '%s', '%d', '%d', '%d', '0');
- ]],
- [[
- SELECT count(*)
- FROM player_loots
- ]],
- __call = function (tab, n, ...)
- return CharDBQuery(tab[n]:format(...));
- end
- };
- setmetatable(query, query);
- -- We need the length of the player_loots table.
- local tableLength = query(QUERY_SELECT_COUNT):GetUInt32(0)+1;
- -- Function to convert the time from the
- -- database to an actual date.
- local function getDate(date_time)
- return os.date("%x [%X]", date_time);
- end
- -- Table that will hold the loot information.
- local mtLoot = {
- -- Function that will keep the table clean,
- -- we don't want to many entries ...
- __newindex = function (tab, key, value)
- if #tab >= MAX_RESULTS then
- collectgarbage();
- end
- rawset(tab, key, value);
- end,
- -- Weak table so collectgarbage() can do its job.
- __mode = 'kv',
- -- Should we notify that we are cleaning the table?
- __gc = function() print"Wiping the loot table." end,
- __len = function (t)
- local length = 0;
- for _, tab in pairs(t) do
- length = length + #tab;
- end
- return length;
- end
- };
- local lootTable = setmetatable({}, mtLoot);
- local function prepareResult(result)
- -- If the result is nil, we should return it
- -- right away to prevent errors.
- if result == nil then return {}; end
- -- Result isn't nil so we can process the results.
- local lootTable = {};
- for i=1, result:GetRowCount() do
- lootTable[i] = {
- getDate(result:GetUInt32(0)), -- date_time
- result:GetString(1), -- player
- GetItemLink(result:GetUInt32(2)), -- item_id
- result:GetUInt8(3) -- item_count
- };
- -- No point in loading data we won't use ...
- if #lootTable == MAX_LOOT_VALUE then
- break;
- end
- result:NextRow();
- end
- return lootTable;
- end
- -- Function to properly load the result. We will check if the result
- -- exists already first, if not, then and only then we will run a query
- -- to get the results we need.
- local function loadResult(player, item)
- local key = player .. (item or "");
- local result = lootTable[key];
- if type(result) ~= "table" then
- -- Which query shall we use?
- local q;
- if type(item) == "number" then
- q = QUERY_SELECT_SPECIFIC;
- else -- No item so default select query.
- q = QUERY_SELECT_DEFAULT;
- end
- -- Grabbing and assigning the result.
- result = prepareResult(query(q, player, item));
- lootTable[key] = result;
- end
- return result;
- end
- local function getLoot(target, item, ...)
- local result;
- if tonumber(item) then
- result = loadResult(target, tonumber(item));
- elseif select(1, ...) then
- return {}; -- If there are arguments in ... then we have to many arguments.
- else -- No extra arguments ...
- result = loadResult(target);
- end
- return type(result) == "table" and result or {};
- end
- -- Function that will handle the command.
- local lootMsg = "%s: %s has looted item: %s, count: %d";
- local function handleLootCommand(plr, msg)
- local arguments = {};
- if msg:find(lootCmd .. " ") == 1 then
- -- Grabbing the words and processing them.
- msg:gsub(lootCmd .. " ", ""):gsub("(%w+)", function (w) table.insert(arguments, w) end);
- end
- -- We want to run this if there aren't any extra arguments but also
- -- if the only argument is an item id.
- if msg:find(lootCmd .. " ") ~= 1 or #arguments == 1 and tonumber(arguments[1]) then
- local target = plr:GetSelection();
- -- Making sure we have a target, and that target
- -- is a player .. creatures don't loot >.>.
- if type(target) ~= "userdata" then
- return plr:SendAreaTriggerMessage("No target selected.");
- elseif target:GetTypeId() ~= USERDATA_TYPE_PLAYER then
- return plr:SendAreaTriggerMessage("Invalid target selected, expecting a player.");
- end
- table.insert(arguments, 1, target:GetName());
- end
- -- Search for loot, if any..., and send the information
- -- to the requester.
- local loot = getLoot(table.unpack(arguments));
- if next(loot) == nil then
- return plr:SendAreaTriggerMessage("No results found.");
- end
- for index, value in ipairs(loot) do
- plr:SendBroadcastMessage(lootMsg:format(table.unpack(value)));
- -- Letting the requester know there is more loot, we
- -- just won't show it.
- if index == MAX_LOOT_VALUE then
- plr:SendBroadcastMessage(("More than %d results found, aborting."):format(MAX_LOOT_VALUE));
- end
- end
- return false;
- end
- -- A separate function to handle the command,
- -- so we only have to use 'return false' once.
- local function onLootCommand(_, plr, msg)
- if msg:find(lootCmd) == 1 then
- if plr:GetGMRank() > 0 then
- handleLootCommand(plr, msg);
- end
- return false;
- end
- -- We don't want any message displaying now,
- -- do we?
- end
- -- Function to catch every item that is looted
- -- and put the information in the database.
- local function registerPlayerLoot(_, plr, item, count)
- local date_time = os.time();
- local player = plr:GetName();
- local entry = item:GetEntry();
- -- Gotta add it to the existing table aswell.
- if lootTable[player] ~= nil then
- table.insert(lootTable[player], {getDate(date_time), player, GetItemLink(entry), count});
- end
- if lootTable[player .. entry] ~= nil then
- table.insert(lootTable[player .. entry], {getDate(date_time), player, GetItemLink(entry), count});
- end
- -- Insert the data into the database and incrementing tableLength
- -- by one so it stays valid.
- query(QUERY_INSERT_DEFAULT, tableLength, player, date_time, entry, count);
- tableLength = tableLength + 1;
- end
- RegisterPlayerEvent(PLAYER_EVENT_ON_USE_COMMAND, onLootCommand);
- RegisterPlayerEvent(PLAYER_EVENT_ON_LOOT_ITEM, registerPlayerLoot);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement