|
|
|
--[[
|
|
|
|
* The MIT License (MIT)
|
|
|
|
*
|
|
|
|
* Copyright (c) 2014 MalRD
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
]]--
|
|
|
|
|
|
|
|
_addon.author = 'MalRD, zombie343';
|
|
|
|
_addon.name = 'Find';
|
|
|
|
_addon.version = '3.2.0';
|
|
|
|
|
|
|
|
local slips = require('slips');
|
|
|
|
|
|
|
|
local STORAGES = {
|
|
|
|
[1] = { id=0, name='Inventory' },
|
|
|
|
[2] = { id=1, name='Safe' },
|
|
|
|
[3] = { id=2, name='Storage' },
|
|
|
|
[4] = { id=3, name='Temporary' },
|
|
|
|
[5] = { id=4, name='Locker' },
|
|
|
|
[6] = { id=5, name='Satchel' },
|
|
|
|
[7] = { id=6, name='Sack' },
|
|
|
|
[8] = { id=7, name='Case' },
|
|
|
|
[9] = { id=8, name='Wardrobe' },
|
|
|
|
[10]= { id=9, name='Safe 2' },
|
|
|
|
[11]= { id=10, name='Wardrobe 2' },
|
|
|
|
[12]= { id=11, name='Wardrobe 3' },
|
|
|
|
[13]= { id=12, name='Wardrobe 4' },
|
|
|
|
[14]= { id=13, name='Wardrobe 5' },
|
|
|
|
[15]= { id=14, name='Wardrobe 6' },
|
|
|
|
[16]= { id=15, name='Wardrobe 7' },
|
|
|
|
[17]= { id=16, name='Wardrobe 8' }
|
|
|
|
};
|
|
|
|
|
|
|
|
local default_config =
|
|
|
|
{
|
|
|
|
language = 0
|
|
|
|
};
|
|
|
|
local config = default_config;
|
|
|
|
local inventory = AshitaCore:GetDataManager():GetInventory();
|
|
|
|
local resources = AshitaCore:GetResourceManager();
|
|
|
|
local MINSLIP = 1;
|
|
|
|
local MAXSLIP = #slips.ids;
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
--Returns the real ID and name for the given inventory storage index. --
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
local function getStorage(storageIndex)
|
|
|
|
return STORAGES[storageIndex].id, STORAGES[storageIndex].name;
|
|
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
ashita.register_event('load', function()
|
|
|
|
end );
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
ashita.register_event('unload', function()
|
|
|
|
end );
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- func : printf
|
|
|
|
-- desc : Because printing without formatting is for the birds.
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
function printf(s,...)
|
|
|
|
print(s:format(...));
|
|
|
|
end;
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- func: find
|
|
|
|
-- desc: Attempts to match the supplied cleanString to the supplied item.
|
|
|
|
-- args: item -> the item being matched against.
|
|
|
|
-- cleanString -> the cleaned string being searched for.
|
|
|
|
-- useDescription -> true if the item description should be searched.
|
|
|
|
-- returns: true if a match is found, otherwise false.
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
local function find(item, cleanString, useDescription)
|
|
|
|
if (item == nil) then return false end;
|
|
|
|
if (cleanString == nil) then return false end;
|
|
|
|
|
|
|
|
if (string.lower(item.Name[config.language]):find(cleanString)) then
|
|
|
|
return true;
|
|
|
|
elseif (item.LogNameSingular[config.language] ~= nil and string.lower(item.LogNameSingular[config.language]):find(cleanString)) then
|
|
|
|
return true;
|
|
|
|
elseif (item.LogNamePlural[config.language] ~= nil and string.lower(item.LogNamePlural[config.language]):find(cleanString)) then
|
|
|
|
return true;
|
|
|
|
elseif (useDescription and item.Description ~= nil and item.Description[config.language] ~= nil) then
|
|
|
|
return (string.lower(item.Description[config.language]):find(cleanString));
|
|
|
|
end
|
|
|
|
|
|
|
|
return false;
|
|
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- func: search
|
|
|
|
-- desc: Searches the player's inventory for an item that matches the supplied
|
|
|
|
-- string.
|
|
|
|
-- args: searchString -> the string that is being searched for.
|
|
|
|
-- useDescription -> true if the item description should be searched.
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
local function search(searchString, useDescription)
|
|
|
|
if (searchString == nil) then return; end
|
|
|
|
local cleanString = ParseAutoTranslate(searchString, false);
|
|
|
|
|
|
|
|
if (cleanString == nil) then return; end
|
|
|
|
cleanString = string.lower(cleanString);
|
|
|
|
|
|
|
|
printf("\30\08Finding \"%s\"...", cleanString);
|
|
|
|
local inventory = AshitaCore:GetDataManager():GetInventory();
|
|
|
|
local resources = AshitaCore:GetResourceManager();
|
|
|
|
|
|
|
|
local found = { };
|
|
|
|
local result = { };
|
|
|
|
local storageSlips = { };
|
|
|
|
|
|
|
|
for k,v in ipairs(STORAGES) do
|
|
|
|
local foundCount = 1;
|
|
|
|
for j = 0, inventory:GetContainerMax(v.id), 1 do
|
|
|
|
local itemEntry = inventory:GetItem(v.id, j);
|
|
|
|
if (itemEntry.Id ~= 0 and itemEntry.Id ~= 65535) then
|
|
|
|
local item = resources:GetItemById(itemEntry.Id);
|
|
|
|
|
|
|
|
if (item ~= nil) then
|
|
|
|
if (find(item, cleanString, useDescription)) then
|
|
|
|
quantity = 1;
|
|
|
|
if (itemEntry.Count ~= nil and item.StackSize > 1) then
|
|
|
|
quantity = itemEntry.Count;
|
|
|
|
end
|
|
|
|
|
|
|
|
if result[k] == nil then
|
|
|
|
result[k] = { };
|
|
|
|
found[k] = { };
|
|
|
|
end
|
|
|
|
|
|
|
|
if found[k][itemEntry.Id] == nil then
|
|
|
|
found[k][itemEntry.Id] = foundCount;
|
|
|
|
result[k][foundCount] = { name = item.Name[config.language], count = 0 };
|
|
|
|
foundCount = foundCount + 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
result[k][found[k][itemEntry.Id]].count = result[k][found[k][itemEntry.Id]].count + quantity;
|
|
|
|
end
|
|
|
|
|
|
|
|
if find(item, 'storage slip ', false) then
|
|
|
|
storageSlips[#storageSlips + 1] = {item, itemEntry};
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local total = 0;
|
|
|
|
for k,v in ipairs(STORAGES) do
|
|
|
|
if result[k] ~= nil then
|
|
|
|
storageID, storageName = getStorage(k);
|
|
|
|
for _,item in ipairs(result[k]) do
|
|
|
|
quantity = '';
|
|
|
|
if item.count > 1 then
|
|
|
|
quantity = string.format('[%d]', item.count)
|
|
|
|
end
|
|
|
|
printf('%s: %s %s', storageName, item.name, quantity);
|
|
|
|
total = total + item.count;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
for k,v in ipairs(storageSlips) do
|
|
|
|
local slip = resources:GetItemById(v[1].ItemId);
|
|
|
|
local slipItems = slips.items[v[1].ItemId];
|
|
|
|
local extra = v[2].Extra;
|
|
|
|
|
|
|
|
for i,slipItemID in ipairs(slipItems) do
|
|
|
|
local slipItem = resources:GetItemById(slipItemID);
|
|
|
|
if (find(slipItem, cleanString, useDescription)) then
|
|
|
|
local byte = extra[math.floor((i - 1) / 8)];
|
|
|
|
if byte < 0 then
|
|
|
|
byte = byte + 256;
|
|
|
|
end
|
|
|
|
|
|
|
|
if (hasBit(byte, bit((i - 1) % 8 + 1))) then
|
|
|
|
printf('%s: %s', slip.Name[config.language], slipItem.Name[config.language]);
|
|
|
|
total = total + 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
printf('\30\08Found %d matching items.', total);
|
|
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
function bit(p)
|
|
|
|
return 2 ^ (p - 1);
|
|
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
function hasBit(x, p)
|
|
|
|
return x % (p + p) >= p;
|
|
|
|
end
|
|
|
|
|
|
|
|
local function findinslip(searchslip, item)
|
|
|
|
if (item == nil) then
|
|
|
|
return nil,nil
|
|
|
|
end;
|
|
|
|
|
|
|
|
if searchslip == 0 then
|
|
|
|
for k,v in pairs(slips.items) do
|
|
|
|
local slip = resources:GetItemById(k);
|
|
|
|
for x = 1, #v do
|
|
|
|
if item.Id == v[x] then
|
|
|
|
local slipItem = resources:GetItemById(item.Id);
|
|
|
|
--printf('%s: %s', slip.Name[config.language], slipItem.Name[config.language]);
|
|
|
|
return slip.Name[config.language], slipItem.Name[config.language];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
elseif searchslip >= MINSLIP and searchslip <= MAXSLIP then
|
|
|
|
local slip = resources:GetItemById(slips.ids[searchslip]);
|
|
|
|
for x = 1, #slips.items[slips.ids[searchslip]] do
|
|
|
|
if item.Id == slips.items[slips.ids[searchslip]][x] then
|
|
|
|
local slipItem = resources:GetItemById(item.Id);
|
|
|
|
--printf('%s: %s', slip.Name[config.language], slipItem.Name[config.language]);
|
|
|
|
return slip.Name[config.language], slipItem.Name[config.language];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
printf('\30\08Please enter a valid storage slip between %i and %i, inclusive.', MINSLIP, MAXSLIP);
|
|
|
|
end
|
|
|
|
return nil,nil;
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
local function getFindArgs(cmd)
|
|
|
|
if (not cmd:find('/find', 1, true)) then return nil; end
|
|
|
|
|
|
|
|
local indexOf = cmd:find(' ', 1, true);
|
|
|
|
if (cmd:find('/findslips', 1, true) or cmd:find('/finddupes', 1, true)) and indexOf == nil then
|
|
|
|
cmdTable = {
|
|
|
|
[1] = cmd
|
|
|
|
};
|
|
|
|
return cmdTable;
|
|
|
|
end
|
|
|
|
|
|
|
|
--Specific /findxyz command inputs that require second argument but don't have one specified
|
|
|
|
if indexOf == nil then
|
|
|
|
return nil;
|
|
|
|
end
|
|
|
|
|
|
|
|
--All other inputs that have /find and a space " ", return both words:
|
|
|
|
cmdTable = {
|
|
|
|
[1] = cmd:sub(1,indexOf-1),
|
|
|
|
[2] = cmd:sub(indexOf+1),
|
|
|
|
};
|
|
|
|
|
|
|
|
return cmdTable;
|
|
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- func: printslips
|
|
|
|
-- desc: Searches the player's inventory for any items that can be stored in
|
|
|
|
-- storage slips.
|
|
|
|
--
|
|
|
|
-- args: searchslip -> Indicates search all slips (0) OR specifies slip to
|
|
|
|
-- search for (1-27 index into slip_data:slip.items[])
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
local function printslips(searchslip)
|
|
|
|
|
|
|
|
local found = { };
|
|
|
|
local foundSlip, foundItem;
|
|
|
|
local result = { };
|
|
|
|
local keyset = {};
|
|
|
|
|
|
|
|
if searchslip == 0 then
|
|
|
|
printf('\30\08Searching for any items that can be stored on any storage slips...');
|
|
|
|
elseif searchslip >= MINSLIP and searchslip <= MAXSLIP then
|
|
|
|
printf('\30\08Searching for any items that can be stored on Storage Slip #%i...', searchslip);
|
|
|
|
else
|
|
|
|
printf('\30\08Please enter a valid storage slip between %i and %i, inclusive.', MINSLIP, MAXSLIP);
|
|
|
|
return;
|
|
|
|
end
|
|
|
|
|
|
|
|
for k,v in ipairs(STORAGES) do
|
|
|
|
for j = 0, inventory:GetContainerMax(v.id), 1 do
|
|
|
|
local itemEntry = inventory:GetItem(v.id, j);
|
|
|
|
if (itemEntry.Id ~= 0 and itemEntry.Id ~= 65535) then
|
|
|
|
local item = resources:GetItemById(itemEntry.Id);
|
|
|
|
if (item ~= nil) then
|
|
|
|
--printf('%s: %s', item.Name[config.language], itemEntry.Id)
|
|
|
|
foundSlip,foundItem = findinslip(searchslip, itemEntry)
|
|
|
|
if (foundSlip ~= nil) then
|
|
|
|
--keyset[#keyset+1] = foundSlip
|
|
|
|
--printf('%s: %s', foundSlip, foundItem)
|
|
|
|
--result[foundSlip] = foundItem;
|
|
|
|
--table.insert(found, foundItem)
|
|
|
|
if result[foundSlip] == nil then
|
|
|
|
result[foundSlip] = {}
|
|
|
|
table.insert(result[foundSlip], foundItem);
|
|
|
|
keyset[#keyset+1] = foundSlip
|
|
|
|
--result[foundSlip][itemEntry] = {};
|
|
|
|
else
|
|
|
|
table.insert(result[foundSlip], foundItem);
|
|
|
|
--result[foundSlip].itemEntry = item.Name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
--table.sort()
|
|
|
|
local keysize = #keyset;
|
|
|
|
local resultsize = 0;
|
|
|
|
if keysize > 0 then
|
|
|
|
table.sort(keyset)
|
|
|
|
for slipIndex=1, keysize, 1 do
|
|
|
|
for _,item in pairs(result[keyset[slipIndex]]) do
|
|
|
|
printf('%s: %s', keyset[slipIndex],item);
|
|
|
|
resultsize = resultsize + 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if searchslip == 0 then
|
|
|
|
printf("\30\08Found %i occurrence(s) of storable items in %i slips.", resultsize, keysize);
|
|
|
|
else
|
|
|
|
printf("\30\08Found %i occurrence(s) of storable items in storage slip #%i.", resultsize, searchslip);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
printf('\30\08No slip-storable items found.');
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- func: printdupes
|
|
|
|
-- desc: Searches the player's inventory for items that occupy more than one
|
|
|
|
-- inventory slot. (Note, stacks or single items will both count as 1.
|
|
|
|
-- Therefore, 2 stacks of 99 HP-Bayld will have a count of 2.)
|
|
|
|
--
|
|
|
|
-- args: none
|
|
|
|
--
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
local function printdupes()
|
|
|
|
|
|
|
|
local result = { };
|
|
|
|
local dupes = {};
|
|
|
|
local resultsize = 0;
|
|
|
|
local dupesize = 0;
|
|
|
|
|
|
|
|
printf('\30\08Searching for duplicate items...');
|
|
|
|
for k,v in ipairs(STORAGES) do
|
|
|
|
for j = 0, inventory:GetContainerMax(v.id), 1 do
|
|
|
|
local itemEntry = inventory:GetItem(v.id, j);
|
|
|
|
if (itemEntry.Id ~= 0 and itemEntry.Id ~= 65535) then
|
|
|
|
local item = resources:GetItemById(itemEntry.Id);
|
|
|
|
if (item ~= nil) then
|
|
|
|
if result[item.ItemId] == nil then
|
|
|
|
result[item.ItemId] = 1;
|
|
|
|
else
|
|
|
|
cnt = result[item.ItemId] + 1
|
|
|
|
result[item.ItemId] = cnt;
|
|
|
|
if cnt == 2 then
|
|
|
|
resultsize = resultsize + 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--printf('(itemName)=%s: (itemID):%s, (result[itemID]):%s', item.Name[config.language], item.ItemId, result[item.ItemId]);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
dupesize = 0;
|
|
|
|
if (resultsize > 0) then
|
|
|
|
for id,cnt in pairs(result) do
|
|
|
|
if ( tonumber(cnt) > 1 ) then
|
|
|
|
--printf('I %s: %d', id, cnt);
|
|
|
|
local dupeitem = resources:GetItemById(id);
|
|
|
|
dupes[id] = { name = dupeitem.Name[config.language], count=cnt };
|
|
|
|
dupesize = dupesize + 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if (dupesize > 0) then
|
|
|
|
for k,v in pairs(dupes) do
|
|
|
|
printf('%s: %d', v.name, v.count);
|
|
|
|
end
|
|
|
|
printf("\30\08Found %i occurrence(s) of duplicate items.", dupesize);
|
|
|
|
else
|
|
|
|
printf('\30\08No duplicate items found.');
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
ashita.register_event('command', function(cmd, nType)
|
|
|
|
local args = getFindArgs(cmd);
|
|
|
|
if (args == nil) then return false; end
|
|
|
|
|
|
|
|
if (args[1]:lower() == '/find' and #args <= 2) then
|
|
|
|
search(args[2]:lower(), false);
|
|
|
|
return true;
|
|
|
|
elseif (args[1]:lower() == '/findmore' and #args <= 2) then
|
|
|
|
search(args[2]:lower(), true);
|
|
|
|
return true;
|
|
|
|
elseif (args[1]:lower() == '/finddupes' and #args <= 1) then
|
|
|
|
printdupes();
|
|
|
|
return true;
|
|
|
|
elseif (args[1]:lower() == '/findslips' and #args <= 2) then
|
|
|
|
if #args >= 2 then
|
|
|
|
searchslip = tonumber(args[2]:lower());
|
|
|
|
if not searchslip then
|
|
|
|
printf('\30\08Please enter a valid storage slip between %i and %i, inclusive.', MINSLIP, MAXSLIP);
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
printslips(searchslip);
|
|
|
|
return true;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
printslips(0);
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
return false;
|
|
|
|
end );
|