Back to Home

ESO Lua File v101044

ingame/crafting/universaldeconstructionpanel_shared.lua

[◄ back to folders ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
    local jewelryCraftingCollectibleId = GetJewelrycraftingCollectibleId()
    return ZO_COLLECTIBLE_DATA_MANAGER:GetCollectibleDataById(jewelryCraftingCollectibleId)
end
    -- Since this function is called at load time, not accessing the collectible data manager here can fascilitate loading the data manager via coroutine
    local jewelryCraftingCollectibleId = GetJewelrycraftingCollectibleId()
    return IsCollectibleUnlocked(jewelryCraftingCollectibleId)
end
    -- Since this function is called at load time, not accessing the collectible data manager here can fascilitate loading the data manager via coroutine
    local jewelryCraftingCollectibleId = GetJewelrycraftingCollectibleId()
    if jewelryCraftingCollectibleId ~= 0 then
        return ZO_CachedStrFormat(SI_COLLECTIBLE_NAME_FORMATTER, GetCollectibleName(jewelryCraftingCollectibleId))
    end
    return nil
end
    if ZO_IsJewelryCraftingEnabled() then
        return data and data.activeTabText or nil
    end
    local jewelryCraftingTradeskillName = GetString("SI_TRADESKILLTYPE", CRAFTING_TYPE_JEWELRYCRAFTING)
    local jewelryCraftingCollectibleId = GetJewelrycraftingCollectibleId()
    -- Since this function is called at load time, not accessing the collectible data manager here can fascilitate loading the data manager via coroutine
    return ZO_ERROR_COLOR:Colorize(zo_strformat(SI_SMITHING_CRAFTING_TYPE_LOCKED, GetCollectibleName(jewelryCraftingCollectibleId), jewelryCraftingTradeskillName))
end
ZO_UNIVERSAL_DECONSTRUCTION_CRAFTING_TYPES =
{
    CRAFTING_TYPE_BLACKSMITHING,
    CRAFTING_TYPE_CLOTHIER,
    CRAFTING_TYPE_ENCHANTING,
    CRAFTING_TYPE_JEWELRYCRAFTING,
    CRAFTING_TYPE_WOODWORKING,
}
ZO_UNIVERSAL_DECONSTRUCTION_FILTER_TYPES =
{
    {
        key = "enchantments",
        filter =
        {
            itemTypes =
            {
                ITEMTYPE_GLYPH_ARMOR,
                ITEMTYPE_GLYPH_JEWELRY,
                ITEMTYPE_GLYPH_WEAPON,
            },
        },
        displayName = GetString("SI_ITEMTYPEDISPLAYCATEGORY", ITEM_TYPE_DISPLAY_CATEGORY_GLYPH),
        iconUp = "EsoUI/Art/Inventory/inventory_tabIcon_Craftbag_enchanting_up.dds",
        iconDown = "EsoUI/Art/Inventory/inventory_tabIcon_Craftbag_enchanting_down.dds",
        iconOver = "EsoUI/Art/Inventory/inventory_tabIcon_Craftbag_enchanting_over.dds",
        iconDisabled = "EsoUI/Art/Inventory/inventory_tabIcon_Craftbag_enchanting_disabled.dds",
    },
    {
        key = "jewelry",
        enabled = ZO_IsJewelryCraftingEnabled,
        filter =
        {
            itemFilterTypes =
            {
                ITEMFILTERTYPE_JEWELRY,
            },
        },
        displayName = GetString("SI_SMITHINGFILTERTYPE", SMITHING_FILTER_TYPE_JEWELRY),
        iconUp = "EsoUI/Art/Crafting/jewelry_tabIcon_icon_up.dds",
        iconDown = "EsoUI/Art/Crafting/jewelry_tabIcon_down.dds",
        iconOver = "EsoUI/Art/Crafting/jewelry_tabIcon_icon_over.dds",
        iconDisabled = "EsoUI/Art/Crafting/jewelry_tabIcon_icon_disabled.dds",
    },
    {
        key = "armor",
        filter =
        {
            itemFilterTypes =
            {
                ITEMFILTERTYPE_ARMOR,
            },
        },
        displayName = GetString("SI_SMITHINGFILTERTYPE", SMITHING_FILTER_TYPE_ARMOR),
        iconUp = "EsoUI/Art/Inventory/inventory_tabIcon_armor_up.dds",
        iconDown = "EsoUI/Art/Inventory/inventory_tabIcon_armor_down.dds",
        iconOver = "EsoUI/Art/Inventory/inventory_tabIcon_armor_over.dds",
        iconDisabled = "EsoUI/Art/Inventory/inventory_tabIcon_armor_disabled.dds",
    },
    {
        key = "weapons",
        filter =
        {
            itemFilterTypes =
            {
                ITEMFILTERTYPE_WEAPONS,
            },
        },
        displayName = GetString("SI_SMITHINGFILTERTYPE", SMITHING_FILTER_TYPE_WEAPONS),
        iconUp = "EsoUI/Art/Inventory/inventory_tabIcon_weapons_up.dds",
        iconDown = "EsoUI/Art/Inventory/inventory_tabIcon_weapons_down.dds",
        iconOver = "EsoUI/Art/Inventory/inventory_tabIcon_weapons_over.dds",
        iconDisabled = "EsoUI/Art/Inventory/inventory_tabIcon_weapons_disabled.dds",
    },
    {
        key = "all",
        filter = nil, -- Show all deconstructable items
        displayName = GetString("SI_ITEMTYPEDISPLAYCATEGORY", ITEM_TYPE_DISPLAY_CATEGORY_ALL),
        iconUp = "EsoUI/Art/Inventory/inventory_tabIcon_all_up.dds",
        iconDown = "EsoUI/Art/Inventory/inventory_tabIcon_all_down.dds",
        iconOver = "EsoUI/Art/Inventory/inventory_tabIcon_all_over.dds",
        iconDisabled = "EsoUI/Art/Inventory/inventory_tabIcon_all_disabled.dds",
    },
}
    for _, filterType in ipairs(ZO_UNIVERSAL_DECONSTRUCTION_FILTER_TYPES) do
        if filterKey == filterType.key then
            return filterType
        end
    end
end
ZO_UniversalDeconstructionPanel_Shared = ZO_InitializingCallbackObject:Subclass()
function ZO_UniversalDeconstructionPanel_Shared:Initialize(control, universalDeconstructionParent, extractionSlotControl, extractLabel)
    self.control = control
    control.object = self
    self.universalDeconstructionParent = universalDeconstructionParent
    self.extractionSlotControl = extractionSlotControl
    self.extractLabel = extractLabel
end
function ZO_UniversalDeconstructionPanel_Shared:GetExtractionSlotTextures()
    local emptyTexture, multipleItemsTexture
    if IsInGamepadPreferredMode() then
        emptyTexture = "EsoUI/Art/Crafting/Gamepad/gp_smithing_weaponSlot.dds"
        multipleItemsTexture = "EsoUI/Art/Crafting/Gamepad/GP_smithing_multiple_armorWeaponSlot.dds"
    else
        emptyTexture = "EsoUI/Art/Crafting/smithing_weaponSlot.dds"
        multipleItemsTexture = "EsoUI/Art/Crafting/smithing_multiple_armorWeaponSlot.dds"
    end
    return emptyTexture, multipleItemsTexture
end
function ZO_UniversalDeconstructionPanel_Shared:InitExtractionSlot(sceneName)
    self.extractionSlot = ZO_SmithingExtractionSlot:New(self, self.extractionSlotControl, self.inventory)
    local emptyTexture, multipleItemsTexture = self:GetExtractionSlotTextures()
    self.extractionSlot:SetEmptyTexture(emptyTexture)
    self.extractionSlot:SetMultipleItemsTexture(multipleItemsTexture)
    self.extractionSlot:RegisterCallback("ItemsChanged", function()
        self:OnSlotChanged()
    end)
    self.slotAnimation = ZO_CraftingSmithingExtractSlotAnimation:New(sceneName, function()
        return not self.extractionSlotControl:IsHidden()
    end)
    self.slotAnimation:AddSlot(self.extractionSlot)
end
function ZO_UniversalDeconstructionPanel_Shared.IsDeconstructableBagItem(bagId, slotIndex, filterTypes)
    if IsItemPlayerLocked(bagId, slotIndex) then
        return false
    end
    -- No crafting filter types have been specified; just verify that the item is deconstructable.
    if filterTypes == nil or ZO_IsTableEmpty(filterTypes) then
        return CanItemBeDeconstructed(bagId, slotIndex)
    end
    -- One or more crafting filter types have been specified; verify that the item is deconstructable using at least one of those crafting types.
    for filterType in pairs(filterTypes) do
        if CanItemBeDeconstructed(bagId, slotIndex, filterType) then
            return true
        end
    end
    return false
end
function ZO_UniversalDeconstructionPanel_Shared.IsDeconstructableItem(itemData, filterTypes)
    return ZO_UniversalDeconstructionPanel_Shared.IsDeconstructableBagItem(itemData.bagId, itemData.slotIndex, filterTypes)
end
function ZO_UniversalDeconstructionPanel_Shared.DoesItemPassFilter(bagId, slotIndex, filterType)
    local itemFilterTypes = {GetItemFilterTypeInfo(bagId, slotIndex)}
    if ZO_IsElementInNumericallyIndexedTable(itemFilterTypes, ITEMFILTERTYPE_JEWELRY) and not ZO_IsJewelryCraftingEnabled() then
        return false
    end
    if filterType then
        if filterType.itemTypes then
            local itemType = GetItemType(bagId, slotIndex)
            if not ZO_AreIntersectingNumericallyIndexedTables(filterType.itemTypes, itemType) then
                return false
            end
        end
        if filterType.itemFilterTypes then
            if not ZO_AreIntersectingNumericallyIndexedTables(filterType.itemFilterTypes, itemFilterTypes) then
                return false
            end
        end
    end
    return true
end
function ZO_UniversalDeconstructionPanel_Shared:OnInventoryUpdate(validItems, filterType)
    self.extractionSlot:ValidateSlottedItem(validItems)
end
function ZO_UniversalDeconstructionPanel_Shared:ShowAppropriateSlotDropCallouts()
    self.extractionSlot:ShowDropCallout(true)
end
function ZO_UniversalDeconstructionPanel_Shared:HideAllSlotDropCallouts()
    self.extractionSlot:HideDropCallout()
end
function ZO_UniversalDeconstructionPanel_Shared:OnSlotChanged()
    self.inventory:HandleVisibleDirtyEvent()
    self.universalDeconstructionParent:OnExtractionSlotChanged()
end
-- Required by ZO_Smithing_Common
function ZO_UniversalDeconstructionPanel_Shared:CanItemBeAddedToCraft(bagId, slotIndex)
    return true
end
function ZO_UniversalDeconstructionPanel_Shared:OnItemReceiveDrag(slotControl, bagId, slotIndex)
    self:AddItemToCraft(bagId, slotIndex)
end
function ZO_UniversalDeconstructionPanel_Shared:IsItemAlreadySlottedToCraft(bagId, slotIndex)
    return self.extractionSlot:ContainsBagAndSlot(bagId, slotIndex)
end
function ZO_UniversalDeconstructionPanel_Shared:AddItemToCraft(bagId, slotIndex)
    if self.extractionSlot:HasItems() then
        if self.extractionSlot:GetNumItems() >= MAX_ITEM_SLOTS_PER_DECONSTRUCTION then
            ZO_Alert(UI_ALERT_CATEGORY_ERROR, SOUNDS.NEGATIVE_CLICK, GetString("SI_TRADESKILLRESULT", CRAFTING_RESULT_TOO_MANY_CRAFTING_INPUTS))
            return
        end
        local newStackCount = self.extractionSlot:GetStackCount() + self.inventory:GetStackCount(bagId, slotIndex)
        if newStackCount > MAX_ITERATIONS_PER_DECONSTRUCTION then
            -- prevent slotting if it would take us above the iteration limit, but allow it if nothing else has been slotted yet so we can support single stacks that are larger than the limit
            ZO_Alert(UI_ALERT_CATEGORY_ERROR, SOUNDS.NEGATIVE_CLICK, GetString("SI_TRADESKILLRESULT", CRAFTING_RESULT_TOO_MANY_CRAFTING_ITERATIONS))
            return
        end
    end
    self.extractionSlot:AddItem(bagId, slotIndex)
end
function ZO_UniversalDeconstructionPanel_Shared:RemoveItemFromCraft(bagId, slotIndex)
    self.extractionSlot:RemoveItem(bagId, slotIndex)
end
function ZO_UniversalDeconstructionPanel_Shared:IsSlotted(bagId, slotIndex)
    return self.extractionSlot:ContainsBagAndSlot(bagId, slotIndex)
end
function ZO_UniversalDeconstructionPanel_Shared:ExtractSingle()
    local QUANTITY = 1
    self:ExtractPartialStack(QUANTITY)
end
function ZO_UniversalDeconstructionPanel_Shared:ExtractPartialStack(quantity)
    local bagId, slotIndex = self.extractionSlot:GetItemBagAndSlot(1)
    if AddItemToDeconstructMessage(bagId, slotIndex, quantity) then
        SendDeconstructMessage()
    end
end
do
    local function CompareExtractingItems(left, right)
        return left.quantity < right.quantity
    end
    function ZO_UniversalDeconstructionPanel_Shared:ExtractAll()
        PrepareDeconstructMessage()
        local sortedItems = {}
        for index = 1, self.extractionSlot:GetNumItems() do
            local bagId, slotIndex = self.extractionSlot:GetItemBagAndSlot(index)
            local quantity = self.inventory:GetStackCount(bagId, slotIndex)
            table.insert(sortedItems, {bagId = bagId, slotIndex = slotIndex, quantity = quantity})
        end
        table.sort(sortedItems, CompareExtractingItems)
        local addedAllItems = true
        for _, item in ipairs(sortedItems) do
            if not AddItemToDeconstructMessage(item.bagId, item.slotIndex, item.quantity) then
                addedAllItems = false
                break
            end
        end
        if addedAllItems then
            SendDeconstructMessage()
        end
    end
end
function ZO_UniversalDeconstructionPanel_Shared:ConfirmExtractAll()
    local isMultiExtract = self:IsMultiExtract()
    local numItems = isMultiExtract and self.extractionSlot:GetNumItems() or 1
    local isAnyItemInArmoryBuild = false
    for index = 1, numItems do
        local bagId, slotIndex = self.extractionSlot:GetItemBagAndSlot(index)
        if IsItemInArmory(bagId, slotIndex) then
            isAnyItemInArmoryBuild = true
            break
        end
    end
    if isAnyItemInArmoryBuild or isMultiExtract then
        local dialogData =
        {
            deconstructFn = function()
                if isMultiExtract then
                    self:ExtractAll()
                else
                    self:ExtractSingle()
                end
            end,
            verb = DECONSTRUCT_ACTION_NAME_DECONSTRUCT,
            isAnyItemInArmoryBuild = isAnyItemInArmoryBuild,
        }
        local dialogName
        if isMultiExtract then
            dialogName = (not IsInGamepadPreferredMode() and isAnyItemInArmoryBuild) and "CONFIRM_MULTI_DECONSTRUCT_ARMORY_ITEM" or "CONFIRM_DECONSTRUCT_MULTIPLE_ITEMS"
        else
            dialogName = IsInGamepadPreferredMode() and "CONFIRM_DECONSTRUCT_ARMORY_ITEM_GAMEPAD" or "CONFIRM_DECONSTRUCT_ARMORY_ITEM"
        end
        ZO_Dialogs_ShowPlatformDialog(dialogName, dialogData, { mainTextParams = { ZO_CommaDelimitNumber(self.extractionSlot:GetStackCount()) } })
    else
        -- Extraction of a single item does not require a confirmation dialog.
        self:ExtractSingle()
    end
end
function ZO_UniversalDeconstructionPanel_Shared:IsExtractable()
    return self.extractionSlot:HasItems()
end
function ZO_UniversalDeconstructionPanel_Shared:IsMultiExtract()
    return self.extractionSlot:HasMultipleItems()
end
function ZO_UniversalDeconstructionPanel_Shared:HasSelections()
    return self.extractionSlot:HasItems()
end
function ZO_UniversalDeconstructionPanel_Shared:ClearSelections()
    self.extractionSlot:ClearItems()
end
function ZO_UniversalDeconstructionPanel_Shared:GetFilterType()
    return self.inventory:GetCurrentFilterType()
end