diff options
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/validate.lua')
-rw-r--r-- | Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/validate.lua | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/validate.lua b/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/validate.lua new file mode 100644 index 0000000..5969878 --- /dev/null +++ b/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/validate.lua @@ -0,0 +1,319 @@ +--Copyright (c) 2013~2016, Byrthnoth +--All rights reserved. + +--Redistribution and use in source and binary forms, with or without +--modification, are permitted provided that the following conditions are met: + +-- * Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- * Neither the name of <addon name> nor the +-- names of its contributors may be used to endorse or promote products +-- derived from this software without specific prior written permission. + +--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +--ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +--WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +--DISCLAIMED. IN NO EVENT SHALL <your name> BE LIABLE FOR ANY +--DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +--(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +--LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +--ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +--(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------------------------------------------- +-- Primary entry point. +------------------------------------------------------------------------------------------------------------------- + +-- Validate either gear sets or inventory. +-- gs validate [inv|set] [filterlist] +-- Where inv == i or inv or inventory +-- Where set == s or set or sets +-- Where filterlist can use - to negate a value (eg: -charis for everything except charis, instead of only charis) +function validate(options) + local validateType = 'sets' + if options and #options > 0 then + if S{'sets','set','s'}:contains(options[1]:lower()) then + table.remove(options,1) + elseif S{'inventory','inv','i'}:contains(options[1]:lower()) then + validateType = 'inv' + table.remove(options,1) + end + end + + if validateType == 'inv' then + validate_inventory(options) + else + validate_sets(options) + end +end + +------------------------------------------------------------------------------------------------------------------- +-- Functions to handle the primary logic separation. +------------------------------------------------------------------------------------------------------------------- + +-- Function for determining and displaying which items from a player's inventory are not in their gear sets. +function validate_inventory(filter) + msg.addon_msg(123,'Checking for items in inventory that are not used in your gear sets.') + + local extra_items = search_sets_for_items_in_bag(items.inventory, filter) + + local display_list = get_item_names(extra_items):sort(insensitive_sort) + display_list:map(function(item) msg.add_to_chat(120, windower.to_shift_jis((string.gsub(item, "^%l", string.upper))) ) end) + msg.addon_msg(123,'Final count = '..tostring(display_list:length())) +end + +-- Function for determining and displaying which items of a player's gear sets are not in their inventory. +function validate_sets(filter) + msg.addon_msg(123,'Checking for items in gear sets that are not in your inventory.') + + local missing_items = search_bags_for_items_in_set(sets, filter) + + local display_list = get_item_names(missing_items):sort(insensitive_sort) + display_list:map(function(item) msg.add_to_chat(120, windower.to_shift_jis((string.gsub(item, "^%l", string.upper))) ) end) + msg.addon_msg(123,'Final count = '..tostring(display_list:length())) +end + +------------------------------------------------------------------------------------------------------------------- +-- Utility functions for output and id>name conversion. +------------------------------------------------------------------------------------------------------------------- + +-- Given a set of item IDs, create a set of item names. +function get_item_names(item_set) + return item_set:map(get_item_name) +end + +-- Get the name of an item. Handle the various types of items that can be passed to this function. +function get_item_name(item) + local name = '' + local aug = '' + + if type(item) == 'string' then + name = item + elseif type(item) == 'table' then + if item.id then + name = get_formal_name_by_item_id(item.id) + elseif item.name then + name = item.name + end + + + local aug = item.aug and table.concat(item.aug,', ') or get_augment_string(item) + if aug then + name = name .. ' {' .. aug .. '}' + end + end + + return name +end + +-- Get the (preferably) capitalized version of an item's name, or the +-- log version if the short version is abbreviated. +function get_formal_name_by_item_id(id) + local shortname = get_short_name_by_item_id(id) + local logname = get_log_name_by_item_id(id) + + return (#logname > #shortname) and logname or shortname +end + +-- Given an item id, get the log item name. +function get_log_name_by_item_id(id) + return res.items[id][language..'_log'] +end + +-- Given an item id, get the short item name. +function get_short_name_by_item_id(id) + return res.items[id][language] +end + +-- If the provided item has augments on it, return a string containing the list of augments. +function get_augment_string(item) + local augments + if item.extdata then + augments = extdata.decode(item).augments or {} + else + augments = item.augment or item.augments + end + + local started = false + if augments and #augments > 0 then + local aug_str = '' + for aug_ind,augment in pairs(augments) do + if augment ~= 'none' then + if started then + aug_str = aug_str .. ',' + end + + aug_str = aug_str.."'"..augment.."'" + started = true + end + end + + return aug_str + end +end + +------------------------------------------------------------------------------------------------------------------- +-- Utility functions for searching. +------------------------------------------------------------------------------------------------------------------- + +-- General search to find what 'extra' items are in inventory +function search_sets_for_items_in_bag(bag, filter) + local extra_bag_items = S{} + for _,item in ipairs(bag) do + if item.id ~= 0 and tryfilter(lowercase_name(get_log_name_by_item_id(item.id)), filter) then + if not find_in_sets(item, sets) then + extra_bag_items:add(item) + end + end + end + + return extra_bag_items +end + +-- General search to find what 'extra' items are in the job's gear sets +function search_bags_for_items_in_set(gear_table, filter, missing_items, stack) + if stack and stack:contains(gear_table) then return end + if type(gear_table) ~= 'table' then return end + if missing_items == nil then missing_items = S{} end + + for i,v in pairs(gear_table) do + local name = (type(v) == 'table' and v.name) or v + local aug = (type (v) == 'table' and (v.augments or v.augment)) + + if type(aug) == 'string' then aug = {aug} end + if type(name) == 'string' and name ~= 'empty' and name ~= '' and type(i) == 'string' then + if not slot_map[i] then + msg.addon_msg(123,windower.to_shift_jis(tostring(i))..' contains a "name" element but is not a valid slot.') + elseif tryfilter(lowercase_name(name), filter) and not find_in_equippable_inventories(name, aug) then + -- This is one spot where inventory names will be left hardcoded until an equippable bool is added to the resources + missing_items:add({name=lowercase_name(name),aug=aug}) + end + elseif type(name) == 'table' and name ~= empty then + if not stack then stack = S{} end + + stack:add(gear_table) + search_bags_for_items_in_set(v, filter, missing_items, stack) + stack:remove(gear_table) + end + end + + return missing_items +end + +-- Utility function to search equippable inventories +function find_in_equippable_inventories(name,aug) + for _,bag in pairs(equippable_item_bags) do + if find_in_inv(items[to_windower_bag_api(bag.en)], name, aug) then + return true + end + end +end + +-- Utility function to help search sets +function find_in_sets(item, tab, stack) + if stack and stack:contains(tab) then + return false + end + + local item_short_name = lowercase_name(get_short_name_by_item_id(item.id)) + local item_log_name = lowercase_name(get_log_name_by_item_id(item.id)) + + for _,v in pairs(tab) do + local name = (type(v) == 'table' and v.name) or v + local aug = (type(v) == 'table' and (v.augments or v.augment)) + if type(aug) == 'string' then aug = {aug} end + if type(name) == 'string' then + if compare_item(item, name, aug, item_short_name, item_log_name) then + return true + end + elseif type(v) == 'table' then + if not stack then stack = S{} end + + stack:add(tab) + local try = find_in_sets(item, v, stack) + stack:remove(tab) + + if try then + return true + end + end + end + + return false +end + +-- Utility function to help search inventory +function find_in_inv(bag, name, aug) + for _,item in ipairs(bag) do + if compare_item(item, name, aug) then + return true + end + end + return false +end + +-- Utility function to compare items that may possibly be augmented. +function compare_item(item, name, aug, item_short_name, item_log_name) + if item.id == 0 or not res.items[item.id] then + return false + end + + name = lowercase_name(name) + item_short_name = lowercase_name(item_short_name or get_short_name_by_item_id(item.id)) + item_log_name = lowercase_name(item_log_name or get_log_name_by_item_id(item.id)) + + if item_short_name == name or item_log_name == name then + if not aug or extdata.compare_augments(aug, extdata.decode(item).augments) then + return true + end + end + + return false +end + + +------------------------------------------------------------------------------------------------------------------- +-- Utility functions for filtering. +------------------------------------------------------------------------------------------------------------------- + +function tryfilter(itemname, filter) + if not filter or #filter == 0 then + return true + end + + local pass = true + for _,v in pairs(filter) do + if v[1] == '-' then + pass = false + v = v:sub(2) + end + if not v or type(v) ~= 'string' then + print_set(filter,'filter with bad v') + end + if itemname:contains(lowercase_name(v)) then + return pass + end + end + return not pass +end + + +function lowercase_name(name) + if type(name) == 'string' then + return name:lower() + else + return name + end +end + +function insensitive_sort(item1, item2) + if type(item1) == 'string' and type(item2) == 'string' then + return item1:lower() < item2:lower() + else + return item1 < item2 + end +end |