summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/closetCleaner.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/closetCleaner.lua')
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/closetCleaner.lua377
1 files changed, 377 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/closetCleaner.lua b/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/closetCleaner.lua
new file mode 100644
index 0000000..50a35ef
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/closetCleaner.lua
@@ -0,0 +1,377 @@
+--Copyright © 2016-2017, Brimstone
+--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 closetCleaner 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 Brimstone 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.
+
+-- _addon.version = '1.0'
+
+local cc = {}
+config = require ('config')
+cc.sandbox = {}
+cc.sandbox.windower = setmetatable({}, {__index = windower})
+cc.sandbox.windower.coroutine = functions.empty
+cc.sandbox.windower.register_event = functions.empty
+cc.sandbox.windower.raw_register_event = functions.empty
+cc.sandbox.windower.register_unhandled_command = functions.empty
+
+defaults = T{}
+-- Jobs you want to execute with, recomment put all active jobs you have lua for will look for <job>.lua or <playername>_<job>.lua files
+defaults.ccjobs = { 'BLM', 'BLU', 'BRD', 'BST', 'COR', 'DNC', 'DRG', 'DRK', 'GEO', 'MNK', 'NIN', 'PLD', 'PUP', 'RDM', 'RNG', 'RUN', 'SAM', 'SCH', 'SMN', 'THF', 'WAR', 'WHM' }
+-- Put any items in your inventory here you don't want to show up in the final report
+-- recommended for furniture, food, meds, pop items or any gear you know you want to keep for some reason
+-- use * for anything.
+defaults.ccignore = S{ "Rem's Tale*", "Storage Slip *" }
+-- Set to nil or delete for unlimited
+defaults.ccmaxuse = nil
+-- List bags you want to not check against, needs to match "Location" column in <player>_report.txt
+defaults.ccskipBags = S{ 'Storage', 'Temporary' }
+-- this prints out the _sets _ignored and _inventory files
+ccDebug = false
+
+settings = config.load('ccConfig.xml',defaults)
+
+register_unhandled_command(function(command)
+ command = command and command:lower() or nil
+ if command ~= 'cc' and command ~= 'closetcleaner' then
+ return
+ end
+ setmetatable(cc.sandbox, {__index = gearswap.user_env})
+ cc.sandbox.itemsBylongName = T{}
+ cc.sandbox.itemsByName = T{}
+ cc.sandbox.inventoryGear = T{}
+ cc.sandbox.gsGear = T{}
+ for k,v in pairs(gearswap.res.items) do
+ cc.sandbox.itemsBylongName[gearswap.res.items[k].name_log:lower()] = k
+ cc.sandbox.itemsByName[gearswap.res.items[k].name:lower()] = k
+ end
+ cc.sandbox.jobs = {}
+ for k,v in pairs(gearswap.res.jobs) do
+ cc.sandbox.jobs[gearswap.res.jobs[k].english_short] = k
+ end
+ if not windower.dir_exists(windower.addon_path..'report') then
+ windower.create_dir(windower.addon_path..'report')
+ end
+ local path = windower.addon_path:gsub('\\','/')
+ path = path..'report/'..player.name
+ cc.run_report(path)
+ cc.sandbox = {}
+ cc.sandbox.windower = setmetatable({}, {__index = windower})
+ cc.sandbox.windower.register_event = functions.empty
+ cc.sandbox.windower.raw_register_event = functions.empty
+ cc.sandbox.windower.register_unhandled_command = functions.empty
+ return true
+end)
+
+-- This function creates the report and generates the calls to the other functions
+function cc.run_report(path)
+ mainReportName = path..'_report.txt'
+ local f = io.open(mainReportName,'w+')
+ f:write('closetCleaner Report:\n')
+ f:write('=====================\n\n')
+ cc.export_inv(path)
+ cc.export_sets(path)
+ for k,v in pairs(cc.sandbox.inventoryGear) do
+ if cc.sandbox.gsGear[k] == nil then
+ cc.sandbox.gsGear[k] = 0
+ end
+ end
+ data = T{"Name", " | ", "Count", " | ", "Location", " | ", "Jobs Used", " | ", "Long Name"}
+ form = T{"%25s", "%3s", "%10s", "%3s", "%20s", "%3s", "%-88s", "%3s", "%60s"}
+ cc.print_row(f, data, form)
+ cc.print_break(f, form)
+ if ccDebug then
+ ignoredReportName = path..'_ignored.txt'
+ f2 = io.open(ignoredReportName,'w+')
+ f2:write('closetCleaner ignored Report:\n')
+ f2:write('=====================\n\n')
+ cc.print_row(f2, data, form)
+ cc.print_break(f2, form)
+ end
+ for k,v in cc.spairs(cc.sandbox.gsGear, function(t,a,b) return t[b] > t[a] end) do
+ if settings.ccmaxuse == nil or v <= settings.ccmaxuse then
+ printthis = 1
+ if not cc.job_used[k] then
+ cc.job_used[k] = " "
+ end
+ for s in pairs(settings.ccignore) do
+ if windower.wc_match(gearswap.res.items[k].english, s) then
+ printthis = nil
+ if cc.sandbox.inventoryGear[k] == nil then
+ data = T{gearswap.res.items[k].english, " | ", tostring(v), " | ", "NOT FOUND", " | ", cc.job_used[k], " | ", gearswap.res.items[k].english_log}
+ else
+ data = T{gearswap.res.items[k].english, " | ", tostring(v), " | ", cc.sandbox.inventoryGear[k], " | ", cc.job_used[k], " | ", gearswap.res.items[k].english_log}
+ end
+ if ccDebug then
+ cc.print_row(f2, data, form)
+ end
+ break
+ end
+ end
+ if printthis then
+ if cc.sandbox.inventoryGear[k] == nil then
+ data = T{gearswap.res.items[k].english, " | ", tostring(v), " | ", "NOT FOUND", " | ", cc.job_used[k], " | ", gearswap.res.items[k].english_log}
+ else
+ data = T{gearswap.res.items[k].english, " | ", tostring(v), " | ", cc.sandbox.inventoryGear[k], " | ", cc.job_used[k], " | ", gearswap.res.items[k].english_log}
+ end
+ cc.print_row(f, data, form)
+ end
+ end
+ end
+ if ccDebug then
+ f2:close()
+ print("File created: "..ignoredReportName)
+ end
+ f:close()
+ print("File created: "..mainReportName)
+end
+
+ -- This function tallies all the gear in your inventory
+function cc.export_inv(path)
+ if ccDebug then
+ reportName = path..'_inventory.txt'
+ finv = io.open(reportName,'w+')
+ finv:write('closetCleaner Inventory Report:\n')
+ finv:write('=====================\n\n')
+ end
+
+ local item_list = T{}
+ checkbag = true
+ for n = 0, #gearswap.res.bags do
+ if not settings.ccskipBags:contains(gearswap.res.bags[n].english) then
+ for i,v in ipairs(gearswap.get_item_list(gearswap.items[gearswap.res.bags[n].english:gsub(' ', ''):lower()])) do
+ if v.name ~= empty then
+ local slot = gearswap.xmlify(tostring(v.slot))
+ local name = gearswap.xmlify(tostring(v.name)):gsub('NUM1','1')
+
+ if cc.sandbox.itemsByName[name:lower()] ~= nil then
+ itemid = cc.sandbox.itemsByName[name:lower()]
+ elseif cc.sandbox.itemsBylongName[name:lower()] ~= nil then
+ itemid = cc.sandbox.itemsBylongName[name:lower()]
+ else
+ print("Item: "..name.." not found in gearswap.resources!")
+ end
+ if ccDebug then
+ finv:write("Name: "..name.." Slot: "..slot.." Bag: "..gearswap.res.bags[n].english.."\n")
+ end
+ if cc.sandbox.inventoryGear[itemid] == nil then
+ cc.sandbox.inventoryGear[itemid] = gearswap.res.bags[n].english
+ else
+ cc.sandbox.inventoryGear[itemid] = cc.sandbox.inventoryGear[itemid]..", "..gearswap.res.bags[n].english
+ end
+ end
+ end
+ end
+ end
+ if ccDebug then
+ finv:close()
+ print("File created: "..reportName)
+ end
+end
+
+-- loads all the relevant jobs.lua files and inserts the sets tables into a supersets table:
+-- supersets.<JOB>.sets....
+function cc.export_sets(path)
+ if ccDebug then
+ reportName = path..'_sets.txt'
+ fsets = io.open(reportName,'w+')
+ fsets:write('closetCleaner sets Report:\n')
+ fsets:write('=====================\n\n')
+ end
+ cc.supersets = {}
+ cc.job_used = T{}
+ cc.job_logged = T()
+ fpath = windower.addon_path:gsub('\\','/')
+ fpath = fpath:gsub('//','/')
+ fpath = string.lower(fpath)
+ dpath = fpath..'data/'
+ for i,v in ipairs(settings.ccjobs) do
+ dname = string.lower(dpath..player.name..'/'..v..'.lua')
+ lname = string.lower(dpath..player.name..'_'..v..'.lua')
+ lgname = string.lower(dpath..player.name..'_'..v..'_gear.lua')
+ sname = string.lower(dpath..v..'.lua')
+ sgname = string.lower(dpath..v..'_gear.lua')
+ if windower.file_exists(lgname) then
+ cc.supersets[v] = cc.extract_sets(lgname)
+ elseif windower.file_exists(lname) then
+ cc.supersets[v] = cc.extract_sets(lname)
+ elseif windower.file_exists(sgname) then
+ cc.supersets[v] = cc.extract_sets(sgname)
+ elseif windower.file_exists(sname) then
+ cc.supersets[v] = cc.extract_sets(sname)
+ elseif windower.file_exists(dname) then
+ cc.supersets[v] = cc.extract_sets(dname)
+ else
+ print('lua file for '..v..' not found!')
+ end
+ end
+ cc.list_sets(cc.supersets, fsets)
+ cc.supersets = nil
+ if ccDebug then
+ fsets:close()
+ print("File created: "..reportName)
+ end
+end
+
+-- sets the 'sets' and puts them into supersets based off file name.
+function cc.extract_sets(file)
+ local user_file = gearswap.loadfile(file)
+ if user_file then
+ gearswap.setfenv(user_file, cc.sandbox)
+ cc.sandbox.sets = {}
+ user_file()
+ local def_gear = cc.sandbox.init_get_sets or cc.sandbox.get_sets
+ if def_gear then
+ def_gear()
+ end
+ return table.copy(cc.sandbox.sets)
+ else
+ print('lua file for '..file..' not found!')
+ end
+end
+
+-- this function tallies the items used in each lua file
+function cc.list_sets(t, f)
+ write_sets = T{}
+ local print_r_cache={}
+ local function sub_print_r(t,fromTab)
+ if (type(t)=="table") then
+ for pos,val in pairs(t) do
+ if S{"WAR", "MNK", "WHM", "BLM", "RDM", "THF", "PLD", "DRK", "BST", "BRD", "RNG", "SAM", "NIN", "DRG", "SMN", "BLU", "COR", "PUP", "DNC", "SCH", "GEO", "RUN"}:contains(pos) then
+ job = pos
+ end
+ if (type(val)=="table") then
+ sub_print_r(val,job)
+ elseif (type(val)=="string") then
+ if val ~= "" and val ~= "empty" then
+ if S{"name", "main", "sub", "range", "ammo", "head", "neck", "left_ear", "right_ear", "body", "hands", "left_ring", "right_ring", "back", "waist", "legs", "feet", "ear1", "ear2", "ring1", "ring2", "lear", "rear", "lring", "rring"}:contains(pos) then
+ if cc.sandbox.itemsByName[val:lower()] ~= nil then
+ itemid = cc.sandbox.itemsByName[val:lower()]
+ elseif cc.sandbox.itemsBylongName[val:lower()] ~= nil then
+ itemid = cc.sandbox.itemsBylongName[val:lower()]
+ else
+ print("Item: '"..val.."' not found in gearswap.resources! "..pos)
+ end
+ if ccDebug then
+ f:write('Processing '..job..' name for val '..val..' id '..itemid..'\n')
+ end
+ if write_sets[itemid] == nil then
+ write_sets[itemid] = 1
+ if cc.job_used[itemid] == nil then
+ cc.job_used[itemid] = job
+ cc.job_logged[itemid..job] = 1
+ else
+ cc.job_used[itemid] = cc.job_used[itemid]..","..job
+ cc.job_logged[itemid..job] = 1
+ end
+ else
+ write_sets[itemid] = write_sets[itemid] + 1
+ if cc.job_logged[itemid..job] == nil then
+ cc.job_used[itemid] = cc.job_used[itemid]..","..job
+ cc.job_logged[itemid..job] = 1
+ end
+ end
+ end
+ end
+ elseif (type(val)=="number") then
+ print("Found Number: "..val.." from "..pos.." table "..t)
+ else
+ print("Error: Val needs to be table or string "..type(val))
+ end
+ end
+ end
+ end
+ sub_print_r(t,nil)
+ if ccDebug then
+ data = T{"Name", " | ", "Count", " | ", "Jobs", " | ", "Long Name"}
+ form = T{"%22s", "%3s", "%10s", "%3s", "%88s", "%3s", "%60s"}
+ cc.print_row(f, data, form)
+ cc.print_break(f, form)
+ f:write('\n')
+ for k,v in pairs(write_sets) do
+ data = T{gearswap.res.items[k].english, " | ", tostring(v), " | ", cc.job_used[k], " | ", gearswap.res.items[k].english_log}
+ cc.print_row(f, data, form)
+ cc.sandbox.gsGear[k] = v
+ end
+ f:write()
+ else
+ for k,v in pairs(write_sets) do
+ cc.sandbox.gsGear[k] = v
+ end
+ end
+end
+
+-- interate throught table in a sorted order.
+function cc.spairs(t, order)
+ -- collect the keys
+ local keys = {}
+ for k in pairs(t) do keys[#keys+1] = k end
+
+ -- if order function given, sort by it by passing the table and keys a, b,
+ -- otherwise just sort the keys
+ if order then
+ table.sort(keys, function(a,b) return order(t, a, b) end)
+ else
+ table.sort(keys)
+ end
+
+ -- return the iterator function
+ local i = 0
+ return function()
+ i = i + 1
+ if keys[i] then
+ return keys[i], t[keys[i]]
+ end
+ end
+end
+
+-- pass in file handle and a table of formats and table of data
+function cc.print_row(f, data, form)
+ for k,v in pairs(data) do
+ f:write(string.format(form[k], v))
+ end
+ f:write('\n')
+end
+
+-- pass in file handle and a table of formats and table of data
+function cc.print_break(f, form)
+ for k,v in pairs(form) do
+ number = string.match(v,"%d+")
+ for i=1,number do
+ f:write('-')
+ end
+ -- f:write(' ') -- can add characters to end here like spaces but subtract from number in the for loop above
+ end
+ f:write('\n')
+end
+
+
+function cc.include(str)
+ str = str:lower()
+ if not (str == 'closetcleaner' or str == 'closetcleaner.lua') then
+ include(str, cc.sandbox)
+ end
+end
+
+cc.sandbox.include = cc.include
+cc.sandbox.require = cc.include \ No newline at end of file