diff --git a/FCOISLink.lua b/FCOISLink.lua index 0c7d29a..446811a 100644 --- a/FCOISLink.lua +++ b/FCOISLink.lua @@ -132,12 +132,13 @@ function FCOISL:GetIndexedMark(mark) end function FCOISL:GetMarkIndex(markText) - if not FCOISL:hasAddon() then return nil end if markText == TXT_NO_CARE then return nil elseif markText == TXT_NO_MARK then return I_NO_MARK elseif markText == TXT_ANY_MARK then return I_ANY_MARK - else return FCOISL:GetDynamicIconList()[markText] + else + if not FCOISL:hasAddon() then return nil end + return FCOISL:GetDynamicIconList()[markText] end end @@ -147,12 +148,15 @@ function FCOISL:IsNoMark(mark) return mark == I_NO_MARK end function FCOISL:IsAnyMark(mark) return mark == I_ANY_MARK end -function FCOISL:GetDynamicIconChoices() +function FCOISL:GetIconChoices() if DIChoices then return DIChoices end - if not self:hasAddon() then return { TXT_NO_CARE } end - DIChoices = { TXT_NO_CARE, TXT_NO_MARK, TXT_ANY_MARK } + + -- We abuse this function to generate choices for other addons, too, so provide at least the generic set. + -- TODO: If I have to extend it further, provide an abstraction layer for inventory savers. Joy... + if not self:hasAddon() then return DIChoices end + for _, v in pairs(staticIconList) do DIChoices[#DIChoices + 1] = FCOISL:GetIconText(v) end diff --git a/InventoryManager.lua b/InventoryManager.lua index edb6270..97274f9 100644 --- a/InventoryManager.lua +++ b/InventoryManager.lua @@ -36,7 +36,11 @@ function InventoryManager:ProcessSingleItem(dryrun, data) elseif action == self.ACTION_SELL then SellInventoryItem(data.bagId, data.slotId, data.count ) elseif action == self.ACTION_LAUNDER then - LaunderItem(data.bagId, data.slotId, data.count ) + LaunderItem(data.bagId, data.slotId, data.count ) + elseif action == self.ACTION_GB_STASH then + TransferToGuildBank(data.bagId, data.slotId) + elseif action == self.ACTION_GB_RETRIEVE then + TransferFromGuildBank(data.slotId) end end IM:ReportAction(data, dryrun, action, data.index, data.text) @@ -127,6 +131,7 @@ function InventoryManager:GetItemData(slotId, _inv) data.quality = GetItemLinkQuality(itemLink) data.stolen = IsItemLinkStolen(itemLink) data.crafted = IsItemLinkCrafted(itemLink) + data.unique = IsItemLinkUnique(itemLink) data.unknownself, data.unknownothers = self.CSL:isUnknown(itemLink) return data diff --git a/InventoryManager.txt b/InventoryManager.txt index 43e6ae7..64128ea 100644 --- a/InventoryManager.txt +++ b/InventoryManager.txt @@ -2,7 +2,7 @@ ## APIVersion: 100019 ## OptionalDependsOn: LibAddonMenu-2.0 ## SavedVariables: IMSavedVars -## Version: 1.4.0 +## Version: 1.5.0 ## Author: iwontsay ## Description: iwontsay's Inventory Manager @@ -28,12 +28,14 @@ InventoryManager.lua Modules/DelayedProcessor.lua Modules/Data.lua Modules/Banking.lua +Modules/GuildBanking.lua Modules/Junker.lua Modules/Seller.lua Modules/Extractor.lua CraftStoreLink.lua FCOISLink.lua +ItemSaverLink.lua Rulesets.lua UI/RuleEdit.lua diff --git a/ItemSaverLink.lua b/ItemSaverLink.lua new file mode 100644 index 0000000..1c1541c --- /dev/null +++ b/ItemSaverLink.lua @@ -0,0 +1,39 @@ +local DEBUG = +-- function() end +d + +local function _tr(str) + return str +end + +local TXT_NO_CARE +local TXT_NO_MARK +local TXT_ANY_MARK + +local I_NO_CARE = -3 +local I_NO_MARK = -2 +local I_ANY_MARK = -1 + +local ISL = { } +local IM = InventoryManager + +IM.ISL = ISL; + +function ISL:hasAddon() + return ItemSaver_IsItemSaved ~= nil +end + +function ISL:FitMark(instanceId, mark, bagId, slotIndex) + -- If we have switched off this addon, render this filter setting as irrelevant + if not ISL:hasAddon() then return true end + + if not mark then return true end + + DEBUG(ItemSaver_IsItemSaved(bagId, slotIndex)) + if mark == I_NO_MARK then return not ItemSaver_IsItemSaved(bagId, slotIndex) + elseif mark == I_ANY_MARK then return ItemSaver_IsItemSaved(bagId, slotIndex) + end + + -- Could happen if we did use FCOIS once and the rule has an old specific marking. That would not match anymore + return true +end diff --git a/Modules/Banking.lua b/Modules/Banking.lua index 5e66eee..f0c5910 100644 --- a/Modules/Banking.lua +++ b/Modules/Banking.lua @@ -152,7 +152,7 @@ local function CollectSingleDirection(action, bagType) for i,_ in pairs(InventoryManager.currentInventory) do local data = InventoryManager:GetItemData(i) - if action == InventoryManager.currentRuleset:Match(data) then + if action == InventoryManager.currentRuleset:Match(data, action) then _moveSlots[#_moveSlots + 1] = i end end diff --git a/Modules/Data.lua b/Modules/Data.lua index 2e486d8..9504710 100644 --- a/Modules/Data.lua +++ b/Modules/Data.lua @@ -28,7 +28,9 @@ InventoryManager.ACTION_DECONSTRUCT = 5 InventoryManager.ACTION_LOCK = 6 InventoryManager.ACTION_UNLOCK = 7 InventoryManager.ACTION_STASH = 10 +InventoryManager.ACTION_GB_STASH = 11 InventoryManager.ACTION_RETRIEVE = 20 +InventoryManager.ACTION_GB_RETRIEVE = 21 IM_Ruleset.ITEM_TRAIT_TYPE_ANY = -1 IM_Ruleset.ITEM_TRAIT_TYPE_ANYUNKOTHERS = -2 @@ -117,6 +119,8 @@ InventoryManager.actionorder = { { InventoryManager.ACTION_DESTROY }, { InventoryManager.ACTION_STASH }, { InventoryManager.ACTION_RETRIEVE }, + { InventoryManager.ACTION_GB_STASH }, + { InventoryManager.ACTION_GB_RETRIEVE }, { InventoryManager.ACTION_SELL }, { InventoryManager.ACTION_LAUNDER }, { InventoryManager.ACTION_DECONSTRUCT }, diff --git a/Modules/DelayedProcessor.lua b/Modules/DelayedProcessor.lua index b26d27b..964b007 100644 --- a/Modules/DelayedProcessor.lua +++ b/Modules/DelayedProcessor.lua @@ -98,7 +98,7 @@ function IM:DoDelayedProcessing(list, loop_fn, finish_fn, run_delay, init_delay) zo_callLater(ProcessLoop, _Init_Delay) end -function IM:CreateInventoryList(bagId, filter_fn, list) +function IM:CreateInventoryList(bagId, action, filter_fn, list) self:SetCurrentInventory(bagId) if not list then list = { } else @@ -112,9 +112,9 @@ function IM:CreateInventoryList(bagId, filter_fn, list) for i,_ in pairs(self.currentInventory) do if #list > 90 then break end local data = self:GetItemData(i) - data.action, data.index, data.text = self.currentRuleset:Match(data) + data.action, data.index, data.text = self.currentRuleset:Match(data, action) - if filter_fn(data) then + if ((not action) or data.action == action) and filter_fn(data) then list[#list + 1] = data end end @@ -128,14 +128,14 @@ function IM:CreateInventoryList(bagId, filter_fn, list) return list end -function IM:ProcessBag(bagId, filter_fn, loop_fn, finish_fn, run_delay, init_delay) - local list = IM:CreateInventoryList(bagId, filter_fn) +function IM:ProcessBag(bagId, action, filter_fn, loop_fn, finish_fn, run_delay, init_delay) + local list = IM:CreateInventoryList(bagId, action, filter_fn) self:DoDelayedProcessing(list, loop_fn, finish_fn, run_delay, init_delay) end -function IM:EventProcessBag(bagId, filter_fn, loop_fn, finish_fn, loop_event, abort_event, run_delay, event_filter_fn) - local list = IM:CreateInventoryList(bagId, filter_fn) +function IM:EventProcessBag(bagId, action, filter_fn, loop_fn, finish_fn, loop_event, abort_event, run_delay, event_filter_fn) + local list = IM:CreateInventoryList(bagId, action, filter_fn) self:DoEventProcessing(list, loop_fn, finish_fn, loop_event, abort_event, run_delay, event_filter_fn) end diff --git a/Modules/Extractor.lua b/Modules/Extractor.lua index 5fdf1a8..03f2554 100644 --- a/Modules/Extractor.lua +++ b/Modules/Extractor.lua @@ -69,8 +69,6 @@ local function GetTradeskillUsed() end local function filter_for_deconstruction(tradeskill, data) - if data.action ~= IM.ACTION_DECONSTRUCT then return false end - local ts = GetItemTradeSkill(data) if ts ~= tradeskill then return false end @@ -94,14 +92,14 @@ end local function InitDeconstruction(tradeskill) InventoryManager.currentRuleset:ResetCounters() - local list = IM:CreateInventoryList(BAG_BACKPACK, + local list = IM:CreateInventoryList(BAG_BACKPACK, IM.ACTION_DECONSTRUCT, function(data) return filter_for_deconstruction(tradeskill, data) end) - list = IM:CreateInventoryList(BAG_BANK, + list = IM:CreateInventoryList(BAG_BANK, IM.ACTION_DECONSTRUCT, function(data) return filter_for_deconstruction(tradeskill, data) end, list) - list = IM:CreateInventoryList(BAG_SUBSCRIBER_BANK, + list = IM:CreateInventoryList(BAG_SUBSCRIBER_BANK, IM.ACTION_DECONSTRUCT, function(data) return filter_for_deconstruction(tradeskill, data) end, list) diff --git a/Modules/GuildBanking.lua b/Modules/GuildBanking.lua new file mode 100644 index 0000000..6556b84 --- /dev/null +++ b/Modules/GuildBanking.lua @@ -0,0 +1,106 @@ +local DEBUG = +function() end +-- d + +local function _tr(str) + return str +end + +local IM = InventoryManager + +local current_gn = nil +local sequence_count = nil + +local function finish_gb_transfers() + local result + result = GetString(IM_BANK_OK) + + if result ~= "" then + CHAT_SYSTEM:AddMessage(result) + end +end + +local function filter_for_gb_retrieve(data) + if current_gn ~= data.guildbank then + DEBUG(" -- filter_for_gb_retrieve: Item intended for different bank") + return false + end + + return true +end + +local function finish_gb_stashes() + IM:EventProcessBag(BAG_GUILDBANK, IM.ACTION_GB_RETRIEVE, + filter_for_gb_retrieve, + function(data) IM:ProcessSingleItem(false, data) end, + finish_gb_transfers, + EVENT_GUILD_BANK_ITEM_REMOVED, + EVENT_CLOSE_GUILD_BANK, + IM.settings.bankMoveDelay) +end + +local function filter_for_gb_stash(data) + if data.stolen then return false end + + if current_gn ~= data.guildbank then + DEBUG(" -- filter_for_gb_stash: Item intended for different bank") + return false + end + + if IM.FCOISL:IsProtectedAction( + IM.ACTION_SELL, -- Maybe another action. + data.bagId, + data.slotId, + fence) then return false end + return true +end + +local function doStashGuildBank() + IM:EventProcessBag(BAG_BACKPACK, IM.ACTION_GB_STASH, + filter_for_gb_stash, + function(data) IM:ProcessSingleItem(false, data) end, + finish_gb_stashes, + EVENT_GUILD_BANK_ITEM_ADDED, + EVENT_CLOSE_GUILD_BANK, + IM.settings.bankMoveDelay) +end + +local function trySettleGuildBank(old_sequence_count) + DEBUG("--- trySettleGuildBank: old_sequence_count=" .. old_sequence_count .. ", sequence_count=" .. sequence_count) + if old_sequence_count ~= sequence_count then + zo_callLater(function() trySettleGuildBank(sequence_count) end, 1000) + return + end + + DEBUG("No new event fired, seems we're good to go.") + doStashGuildBank() +end + +function received_event() + local gid = GetSelectedGuildBankId() + local gn = GetGuildName(gid) + + DEBUG(" -- received_event: gn=" .. gn .. ", current_gn = " .. (current_gn or "(nil)")) + + if gn ~= current_gn then + current_gn = gn + sequence_count = 0 + DEBUG("Starting settle loop...") + zo_callLater(function() trySettleGuildBank(sequence_count) end, IM.settings.bankInitDelay + 2000) + else + sequence_count = sequence_count + 1 + end +end + +function IM:OnGuildBankReady() + received_event() +end + +function IM:OnGuildBankOpened() + current_gn = "" + sequence_count = 0 + received_event() +end + +EVENT_MANAGER:RegisterForEvent(InventoryManager.name, EVENT_GUILD_BANK_ITEMS_READY, function() IM:OnGuildBankReady() end) +EVENT_MANAGER:RegisterForEvent(InventoryManager.name, EVENT_OPEN_GUILD_BANK, function() IM:OnGuildBankOpened() end) diff --git a/Modules/Junker.lua b/Modules/Junker.lua index b993dc2..3ed5f32 100644 --- a/Modules/Junker.lua +++ b/Modules/Junker.lua @@ -34,7 +34,7 @@ local function filter_for_backpack_action(dryrun, data) -- List other inventory actions only if it's a dryrun. -- Else we need to get to the specific stations to actually perform them - if data.action ~= IM.ACTION_KEEP and data.action ~= IM.ACTION_RETRIEVE and dryrun then + if data.action ~= IM.ACTION_KEEP and data.action ~= IM.ACTION_RETRIEVE and data.action ~= IM.ACTION_GB_RETRIEVE and dryrun then return true end return false @@ -42,7 +42,7 @@ end function IM:WorkBackpack(dryrun) InventoryManager.currentRuleset:ResetCounters() - self:ProcessBag(BAG_BACKPACK, + self:ProcessBag(BAG_BACKPACK, nil, function(data) return filter_for_backpack_action(dryrun, data) end, function(data) IM:ProcessSingleItem(dryrun, data) end, function() IM:CheckAndDestroy() end, diff --git a/Modules/Seller.lua b/Modules/Seller.lua index 8ebacf2..6f50554 100644 --- a/Modules/Seller.lua +++ b/Modules/Seller.lua @@ -16,12 +16,8 @@ local function do_sell(data, eventCode, itemName, itemQuantity, money) end local function filter_for_sale(fence, data) - data.action, data.index, data.text = InventoryManager.currentRuleset:Match(data) - if data.stolen ~= fence then return false end - if data.action ~= InventoryManager.ACTION_SELL then return false end - if InventoryManager.FCOISL:IsProtectedAction( InventoryManager.ACTION_SELL, data.bagId, @@ -31,8 +27,6 @@ local function filter_for_sale(fence, data) end local function filter_for_launder(data) - if data.action ~= InventoryManager.ACTION_LAUNDER then return false end - if InventoryManager.FCOISL:IsProtectedAction( InventoryManager.ACTION_LAUNDER, data.bagId, @@ -54,7 +48,7 @@ function InventoryManager:SellItems(stolen) _Gain = _Gain + money end InventoryManager.currentRuleset:ResetCounters() - InventoryManager:EventProcessBag(BAG_BACKPACK, + InventoryManager:EventProcessBag(BAG_BACKPACK, InventoryManager.ACTION_LAUNDER, filter_for_launder, function(data) InventoryManager:ProcessSingleItem(false, data) end, function(abort) end_fn(abort) end, @@ -65,7 +59,7 @@ function InventoryManager:SellItems(stolen) _Gain = 0 InventoryManager.currentRuleset:ResetCounters() - self:EventProcessBag(BAG_BACKPACK, + self:EventProcessBag(BAG_BACKPACK, InventoryManager.ACTION_SELL, function(data) return filter_for_sale(stolen, data) end, do_sell, ((stolen and launder_run) or end_fn), diff --git a/Rulesets.lua b/Rulesets.lua index f64a90c..9d92cca 100644 --- a/Rulesets.lua +++ b/Rulesets.lua @@ -70,7 +70,7 @@ function IM_Rule:ToString() itemDescription = GetString(IM_RULETXT_JUNKED) .. " " .. itemDescription end - if InventoryManager.FCOISL:hasAddon() and self.FCOISMark then + if (InventoryManager.FCOISL:hasAddon() or InventoryManager.ISL:hasAddon()) and self.FCOISMark then if InventoryManager.FCOISL:IsNoMark(self.FCOISMark) then itemDescription = GetString(IM_FCOIS_UNMARKED) .. " " .. itemDescription elseif InventoryManager.FCOISL:IsAnyMark(self.FCOISMark) then @@ -163,7 +163,8 @@ function IM_Rule:Filter(data) -- FCO ItemSaver marker? -- Call with parameters suitable for both API's and let FCOISL sort it out. - if not InventoryManager.FCOISL:FitMark(data.itemInstanceId, self.FCOISMark, data.bagId, data.slotId) then return false end + if (not InventoryManager.FCOISL:FitMark(data.itemInstanceId, self.FCOISMark, data.bagId, data.slotId)) or + (not InventoryManager.ISL:FitMark(data.itemInstanceId, self.FCOISMark, data.bagId, data.slotId)) then return false end -- Junked? if self.junk and not data.junk then return false end @@ -209,7 +210,7 @@ function IM_Ruleset:ResetCounters() ExecCounters = nil end -function IM_Ruleset:Match(data) +function IM_Ruleset:Match(data, action) if not ExecCounters then ExecCounters = { } end for k, v in pairs(self.rules) do @@ -224,6 +225,9 @@ function IM_Ruleset:Match(data) end end + -- If we want a specific action, skip if it's not the one. + if action and action ~= v.action then res = false end + -- If we reached the max execution count for that particular rule, skip it. if res and v.maxCount and ExecCounters[k] and ExecCounters[k] >= v.maxCount then res = false @@ -231,6 +235,8 @@ function IM_Ruleset:Match(data) if res then ExecCounters[k] = (ExecCounters[k] or 0) + 1 + data.action = v.action + data.guildbank = v.guildbank return v.action, k, v:ToString() end end diff --git a/TODO b/TODO index 329365c..d3f5a12 100644 --- a/TODO +++ b/TODO @@ -1,5 +1 @@ - * "Include bank" for Deconstruct - or - - * Exclude list: Pass over inapplicable rules - * Execution count for rules - * Guild bank management diff --git a/UI/RuleEdit.lua b/UI/RuleEdit.lua index 6285b6e..dd55992 100644 --- a/UI/RuleEdit.lua +++ b/UI/RuleEdit.lua @@ -93,6 +93,15 @@ function RE:GetControls() RE.actionList = getChoiceboxLists(IM.actionorder, function(n) return GetString("IM_ACTIONTXT", n) end) RE.qualityList = getChoiceboxListsAssoc(IM.qualityorder) + local guilds = { } + for i = 1, GetNumGuilds(), 1 do + local gn = GetGuildName(i) + if gn ~= "" then + guilds[#guilds + 1] = { gn, i } + end + end + RE.guildList = getChoiceboxListsAssoc(guilds) + RE.editingRule = IM.IM_Ruleset:NewRule() local rule = RE.editingRule RE:UpdateFilterSpecList(rule.filterType, rule.filterSubType) @@ -167,6 +176,16 @@ function RE:GetControls() setFunc = function(value) RE.editingRule.action = RE.actionList["reverse"][value] end, }, { + type = "dropdown", + name = GetString(IM_RE_GUILDBANK), + tooltip = GetString(IM_RE_GUILDBANK_TT), + width = "half", + choices = RE.guildList["order"], + getFunc = function() return RE.editingRule.guildbank or RE.guildList["seltext"] end, + setFunc = function(value) RE.editingRule.guildbank = value end, + disabled = function() return RE:GetChoGBDisabled() end, + }, + { type = "slider", name = GetString(IM_SET_EXECOUNT), tooltip = GetString(IM_SET_EXECOUNT_TT), @@ -179,6 +198,11 @@ function RE:GetControls() width = "half", --or "half" (optional) }, { + type = "description", + text = "", + width = "half", + }, + { type = "dropdown", name = GetString(IM_RE_GENTYPE), width = "half", @@ -232,10 +256,10 @@ function RE:GetControls() type = "dropdown", name = GetString(IM_FCOIS_CHOICE), width = "half", - choices = IM.FCOISL:GetDynamicIconChoices(), + choices = IM.FCOISL:GetIconChoices(), getFunc = function() return IM.FCOISL:GetIndexedMark(RE.editingRule.FCOISMark) end, setFunc = function(value) RE.editingRule.FCOISMark = IM.FCOISL:GetMarkIndex(value) end, - disabled = function() return not IM.FCOISL:hasAddon() end + disabled = function() return not IM.FCOISL:hasAddon() and not IM.ISL:hasAddon() end }, { type = "checkbox", @@ -351,6 +375,10 @@ function RE:GetBtnMoveDownDisabled() return not RE.selectedRule or RE.selectedRule == #RE.ruleList end +function RE:GetChoGBDisabled() + return RE.editingRule.action ~= IM.ACTION_GB_STASH and RE.editingRule.action ~= IM.ACTION_GB_RETRIEVE +end + function RE:UpdateTraitList(filterType, filterSubType) DEBUG("--- UpdateTraitList", filterType, filterSubType) RE.traitList = getSpecificTraitTypes(filterType, filterSubType) diff --git a/lang/de.lua b/lang/de.lua index 3fd7609..1537f82 100644 --- a/lang/de.lua +++ b/lang/de.lua @@ -23,7 +23,9 @@ local lang = { IM_ACTIONTXT6 = "Sperren", IM_ACTIONTXT7 = "Entsperren", IM_ACTIONTXT10 = "Einlagern", + IM_ACTIONTXT11 = "Einlagern in Gildenbank", IM_ACTIONTXT20 = "Auslagern", + IM_ACTIONTXT21 = "Auslagern aus Gildenbank", IM_TAKENACTION0 = "Würde <<z:1>>: |t16:16:<<2>>|t <<3>> wegen Regel <<4>>: <<5>>.", IM_TAKENACTION1 = "<<1>>: |t16:16:<<2>>|t <<3>>", @@ -108,6 +110,8 @@ local lang = { IM_RE_CRAFTED = "Hergestellt", IM_RE_EMPTY = "(leer)", IM_RE_INJUNK = "Im Müll", + IM_RE_GUILDBANK = "Gildenbank", + IM_RE_GUILDBANK_TT = "Die zu benutzende Gildenbank, wenn die Aktion eine erfordert", IM_PE_PROFILES = "Profile", IM_PE_LOADPROFILE = "Profil laden", diff --git a/lang/en.lua b/lang/en.lua index 20bd194..6a93ad8 100644 --- a/lang/en.lua +++ b/lang/en.lua @@ -23,7 +23,9 @@ local lang = { IM_ACTIONTXT6 = "Lock", IM_ACTIONTXT7 = "Unlock", IM_ACTIONTXT10 = "Put in bank", + IM_ACTIONTXT11 = "Put in guild bank", IM_ACTIONTXT20 = "Pull from bank", + IM_ACTIONTXT21 = "Pull from guild bank", IM_TAKENACTION0 = "Would <<z:1>>: |t16:16:<<2>>|t <<3>> because of Rule <<4>>: <<5>>.", IM_TAKENACTION1 = "<<1>>: |t16:16:<<2>>|t <<3>>", @@ -108,6 +110,9 @@ local lang = { IM_RE_CRAFTED = "crafted", IM_RE_EMPTY = "(empty)", IM_RE_INJUNK = "In Junk", + IM_RE_GUILDBANK = "Guild bank", + IM_RE_GUILDBANK_TT = "Guild bank to use in operation where is one involved", + IM_PE_PROFILES = "Profiles", IM_PE_LOADPROFILE = "Load Profile",