--[[ DynamicData By sarf This mod allows you to access dynamic data in WoW without being forced to rely on strange Blizzard functions Thanks goes to the Sea people, the UltimateUI team and finally the nice (but strange) people at #ultimateuitesters and Blizzard. UltimateUIUI URL: http://www.ultimateuiui.org/forums/viewtopic.php?t=NOT_YET_ANNOUNCED ]] --[[ Information returned by the DynamicData.item.get*Info() methods An array is returned with the following values name -- the name of the item strings -- an array with strings that represent the tooltip of the item count -- the number of items like this the user currently possesses texture cooldown = -- the cooldown of the item { start -- time when the cooldown started duration -- duration of the cooldown enable -- 1 or 0 }; -- each item may have these values: durability -- current durability maxDurability -- maximum durability itemType -- type of item locked -- ? These values are 0 unless the item info derives from a ContainerInfo call (bag >= 0): quality -- degree of commonness readable -- ? These values are 0 or "" unless the item info derives from a InventoryInfo call (bag == -1): broken -- true if broken, false if not slotTexture -- background texture of the slot that the item resides in. ]]-- DYNAMICDATA_ITEM_SCAN_TYPE_TOOLTIP = 1; DYNAMICDATA_ITEM_SCAN_TYPE_ITEMINFO = 2; DYNAMICDATA_ITEM_SCAN_TYPE_COOLDOWN = 4; DYNAMICDATA_ITEM_SCAN_TYPE_EVERYTHING = 7; DYNAMICDATA_ITEM_SCAN_TYPE_QUICK = 6; -- Item information - what the player is wearing and so on. DynamicData.item = { -- public functions -- -- addOnInventoryUpdateHandler (func) -- -- Adds a function name that will be called on inventory updates. -- Function will have two parameters: -- bag, which may be nil. -- scanType, which may be DYNAMICDATA_ITEM_SCAN_TYPE_* -- addOnInventoryUpdateHandler = function (func) return DynamicData.util.addOnWhateverHandler(DynamicData.item.OnInventoryUpdateHandlers, func); end; -- -- removeOnInventoryUpdateHandler (func) -- -- Removes the specified function, so that it will not be called on inventory updates. -- removeOnInventoryUpdateHandler = function (func) return DynamicData.util.removeOnWhateverHandler(DynamicData.item.OnInventoryUpdateHandlers, func); end; -- LEGACY FUNCTION - covered in addOnInventoryUpdateHandler -- -- addOnInventoryCooldownUpdateHandler (func) -- -- Adds a function name that will be called on InventoryCooldown updates. -- Function will have one paremeter - bag, which may be nil. -- addOnInventoryCooldownUpdateHandler = function (func) return DynamicData.util.addOnWhateverHandler(DynamicData.item.OnInventoryCooldownUpdateHandlers, func); end; -- LEGACY FUNCTION - covered in removeOnInventoryUpdateHandler -- -- removeOnInventoryCooldownUpdateHandler (func) -- -- Removes the specified function, so that it will not be called on InventoryCooldown updates. -- removeOnInventoryCooldownUpdateHandler = function (func) return DynamicData.util.removeOnWhateverHandler(DynamicData.item.OnInventoryCooldownUpdateHandlers, func); end; -- -- getEquippedSlotInfo (slot) -- -- Retrieves information about the slot. -- getEquippedSlotInfo = function (slot) if ( ( DynamicData.item.player ) and ( DynamicData.item.player.itemsByBag ) and ( DynamicData.item.player.itemsByBag[-1] ) and ( DynamicData.item.player.itemsByBag[-1][slot] ) ) then return DynamicData.item.player.itemsByBag[-1][slot]; else return DynamicData.item.defaultItem; end end; -- -- getItemInfoByName (itemName) -- -- Retrieves information about an item by name. -- Adds a new variable called position with the position(s) of the item. -- getItemInfoByName = function (itemName) if ( ( DynamicData.item.player ) and ( DynamicData.item.player.itemsByBag ) ) then local element = nil; for bagNumber, bag in DynamicData.item.player.itemsByBag do for slotNumber, slot in bag do if ( slot.name == itemName ) then if ( not element ) then element = DynamicData.item.createBaseItem(slot); else if ( slot.count ) then element.count = element.count + slot.count; end end if ( not element.position ) then element.position = {}; end local positionArray = {}; positionArray.bag = bagNumber; positionArray.slot = slotNumber; table.insert(element.position, positionArray); end end end return element; else return DynamicData.item.defaultItem; end end; -- -- getItemInfoByType (itemType) -- -- Retrieves information about items with the specific type. Includes a new cute variable called totalCount. -- getItemInfoByType = function (itemName) local bagNumber, bag; local slotNumber, itemInfo; local items = {}; for bagNumber, bag in DynamicData.item.player.itemsByBag do for slotNumber, itemInfo in bag do if ( itemInfo.itemType == itemType ) then table.insert(items, DynamicData.item.getItemInfoByName(itemInfo.name)); end end end return items; end; -- -- getEquippedSlotCooldown (slot) -- -- Retrieves cooldown information about the slot. -- getEquippedSlotCooldown = function (slot) if ( ( DynamicData.item.player ) and ( DynamicData.item.player.itemsByBag ) and ( DynamicData.item.player.itemsByBag[-1] ) and ( DynamicData.item.player.itemsByBag[-1][slot] ) ) then local cooldown = DynamicData.item.player.itemsByBag[-1][slot].cooldown; return cooldown[1], cooldown[2], cooldown[3]; else return 0, 0, 0; end end; -- -- getInventoryInfo (bag, slot) -- -- Retrieves information about the bag and slot. -- getInventoryInfo = function (bag, slot) DynamicData.item.scanInventorySlotIfTime(bag, slot); local element = DynamicData.item.player.itemsByBag[bag][slot]; if ( not element ) then element = DynamicData.item.defaultItem; end return element; end; -- -- getInventoryName (bag, slot) -- -- Retrieves the name of the item in the bag and slot. -- getInventoryName = function (bag, slot) if ( ( DynamicData.item.player ) and ( DynamicData.item.player.itemsByBag ) and ( DynamicData.item.player.itemsByBag[bag] ) and ( DynamicData.item.player.itemsByBag[bag][slot] ) ) then local itemInfo = DynamicData.item.getInventoryInfo(bag, slot); if ( ( not itemInfo ) or ( ( itemInfo.texture ) and ( strlen(itemInfo.texture) > 0 ) and ( ( not itemInfo.name ) or ( strlen(itemInfo.name) <= 0 ) ) ) ) then DynamicData.item.scanItem(bag, slot); itemInfo = DynamicData.item.player.itemsByBag[bag][slot]; end return itemInfo.name; else return DynamicData.item.defaultItem.name; end end; -- -- getInventoryCooldownInfo (bag, slot) -- -- Retrieves cooldown information about the bag and slot. -- getInventoryCooldown = function (bag, slot) if ( ( DynamicData.item.player ) and ( DynamicData.item.player.itemsByBag ) and ( DynamicData.item.player.itemsByBag[bag] ) and ( DynamicData.item.player.itemsByBag[bag][slot] ) ) then local cooldown = DynamicData.item.player.itemsByBag[bag][slot].cooldown; return cooldown[1], cooldown[2], cooldown[3]; else return 0, 0, 0; end end; -- -- getEquippedSlotInfoBySlotName (slotName) -- -- Retrieves information about the slot with the specified name. -- getEquippedSlotInfoBySlotName = function (slotName) for key, value in DynamicData.item.inventorySlotNames do if ( value.name == slotName ) then return DynamicData.item.getEquippedSlotInfo(value.id); end end return DynamicData.item.defaultItem; end; -- -- updateItems () -- -- Updates the inventory of the player. -- updateItems = function (bag) params = { func = DynamicData.item.doUpdateItems, params = { bag }, allowInitialUpdate = 1, schedulingName = "DynamicData_item_UpdateItems", }; --DynamicData.util.postpone(params); DynamicData.item.doUpdateItems(bag); end; -- -- updateItemCooldowns () -- -- Updates the cooldowns of the players items. -- updateItemCooldowns = function () local safe = true; --DynamicData.util.safeToUseTooltips({"MerchantFrame", "TradeSkillFrame", "AuctionFrame"}); if ( not safe ) then UltimateUI_ScheduleByName("DynamicData_item_updateItemCooldownsUnspecified", 0.1, DynamicData.item.updateItemCooldowns); return; end DynamicData.item.doQuickScan(); --[[ local bag; for bag = 0,4 do DynamicData.item.doUpdateBagItemsCooldown(bag); end DynamicData.item.doUpdateBagItemsCooldown(-1); bag = nil; DynamicData.item.notifyUpdateHandlers(nil, DYNAMICDATA_ITEM_SCAN_TYPE_COOLDOWN); DynamicData.item.notifyItemCooldownUpdateHandlers(); ]]-- end; -- -- updateItemLocks () -- -- Updates the locks of the players items. -- updateItemLocks = function () DynamicData.item.updateItems(); end; -- -- updateItemAlerts () -- -- Updates the alerts of the players items. -- You can never have too many lerts. -- updateItemAlerts = function () DynamicData.item.updateItems(); end; -- protected functions -- -- doUpdateSeperateBagItems (bag) -- -- Updates a bag seperately from the rest of the inventory of the player. -- Saves some time. -- doUpdateSeperateBagItems = function (bag) if ( not bag ) then return; end if ( DynamicData.item.player.itemsByBag ) then table.remove(DynamicData.item.player.itemsByBag, bag); end DynamicData.item.doUpdateBagItems(bag); end; -- -- doUpdateBagItems (bag) -- -- Updates a bag of the inventory of the player. -- doUpdateBagItems = function (bag) DynamicData.item.scanItemsInBag(bag); end; -- -- doUpdateItems () -- -- Initiates updates of the inventory of the player. -- doUpdateItems = function (bag) local safe = true; --DynamicData.util.safeToUseTooltips({"MerchantFrame", "TradeSkillFrame", "AuctionFrame"}); if ( not safe ) then if ( bag ) then UltimateUI_ScheduleByName("DynamicData_item_doUpdateItems", 0.1, DynamicData.item.doUpdateItems, bag); else UltimateUI_ScheduleByName("DynamicData_item_doUpdateItemsUnspecified", 0.1, DynamicData.item.doUpdateItems); end return; end DynamicData.item.doQuickScan(); if ( ( bag ) and ( DynamicData.item.player ) ) then --DynamicData.item.doQuickScan(bag); --local scanLists = DynamicData.item.generateScanLists(nil, bag); --DynamicData.item.addScans(scanLists); DynamicData.item.makeScanLists(bag); if ( not DynamicData.item.itemScanInProgress ) then --DynamicData.item.doScans(nil, nil, bag); DynamicData.item.doScans(nil, nil, bag); --UltimateUI_ScheduleByName("DynamicData_Item_doScans", 0.1, DynamicData.item.doScans); end --DynamicData.item.doUpdateSeperateBagItems(bag); --DynamicData.item.notifyUpdateHandlers(bag); --DynamicData.item.notifyItemCooldownUpdateHandlers(); else --DynamicData.item.player = {}; --local scanLists = DynamicData.item.generateScanLists(); --DynamicData.item.addScans(scanLists); DynamicData.item.makeScanLists(); --DynamicData.item.doQuickScan(); if ( not DynamicData.item.itemScanInProgress ) then DynamicData.item.doScans(nil); --UltimateUI_ScheduleByName("DynamicData_Item_doScans", 0.1, DynamicData.item.doScans); end end end; -- -- addScans(scanLists) -- -- Adds scan lists to the global scanlist thingy. -- addScans = function (scanLists) for k, v in scanLists do for bag, slot in v do if ( not DynamicData.item.scanList ) then DynamicData.item.scanList = {}; end if ( not DynamicData.item.scanList[bag] ) then DynamicData.item.scanList[bag] = {}; end if ( not DynamicData.item.scanList[bag][slot] ) then DynamicData.item.scanList[bag][slot] = 0; end DynamicData.item.scanList[bag][slot] = 1; end --table.insert(DynamicData.item.scanList, v); end end; -- -- doScans (scanLists, currentIndex) -- -- scans the currently indicated list and schedules next scan list. -- when completed, generates update notification. -- doScans = function (scanLists, currentIndex, bag) scanLists = nil; --[[ if ( not scanLists ) then scanLists = DynamicData.item.scanList; end ]]-- local scheduleName = "DynamicData_Item_doScans"; if ( bag ) then --scheduleName = scheduleName.."_"..bag; end DynamicData.item.itemScanInProgress = true; if ( not currentIndex ) then -- if first time, then we schedule a new scan - this is to prevent the stuttering effect when receiving loads of updates in short succession. --[[ if ( scanLists == DynamicData.item.scanList ) then scanLists = nil; end ]]-- UltimateUI_ScheduleByName(scheduleName, 0.1, DynamicData.item.doScans, scanLists, 1, bag); return; else -- prevents old scans from continuing. UltimateUI_ScheduleByName(scheduleName, 0.1, DynamicData.item.doScans); end local scanType = DYNAMICDATA_ITEM_SCAN_TYPE_TOOLTIP; if ( DynamicData.item.scanItems(scanType) ) then if ( scanLists == DynamicData.item.scanList ) then scanLists = nil; end UltimateUI_ScheduleByName(scheduleName, 0.1, DynamicData.item.doScans, scanLists, currentIndex, bag); return; else if ( scanLists == DynamicData.item.scanList ) then --DynamicData.item.scanList = {}; end DynamicData.item.itemScanInProgress = false; DynamicData.item.notifyUpdateHandlers(bag, scanType); --DynamicData.item.notifyItemCooldownUpdateHandlers(); end end; -- -- doUpdateBagItemsCooldown (bag) -- -- Updates the cooldown a bag of the inventory of the player. -- doUpdateBagItemsCooldown = function (bag) if ( ( DynamicData.item.player ) and ( DynamicData.item.player.itemsByBag ) and ( DynamicData.item.player.itemsByBag[bag] ) ) then if ( bag > -1 ) then local element = nil; for slot = 1,GetContainerNumSlots(bag) do if ( DynamicData.item.player.itemsByBag[bag][slot] ) then local ic_start, ic_duration, ic_enable = GetContainerItemCooldown(bag, slot); local itemCooldown = DynamicData.item.getOldCooldown(bag, slot); itemCooldown[1] = ic_start; itemCooldown[2] = ic_duration; itemCooldown[3] = ic_enable; itemCooldown.start = ic_start; itemCooldown.duration = ic_duration; itemCooldown.enable = ic_enable; DynamicData.item.player.itemsByBag[bag][slot].cooldown = itemCooldown; end end else for k, v in DynamicData.item.inventorySlotNames do slot = v.id; if ( DynamicData.item.player.itemsByBag[bag][slot] ) then local ic_start, ic_duration, ic_enable = GetInventoryItemCooldown("player", slot); local itemCooldown = DynamicData.item.getOldCooldown(bag, slot); itemCooldown[1] = ic_start; itemCooldown[2] = ic_duration; itemCooldown[3] = ic_enable; itemCooldown.start = ic_start; itemCooldown.duration = ic_duration; itemCooldown.enable = ic_enable; DynamicData.item.player.itemsByBag[bag][slot].cooldown = itemCooldown; end end end end end; -- private functions -- -- notifyUpdateHandlers (bag) -- -- Args: -- bag - if not nil, the bag that has been updated -- scanType - the type of scan that has completed -- -- Notifies all update handlers that an update has occurred. -- notifyUpdateHandlers = function (bag, scanType) DynamicData.util.notifyWhateverHandlers(DynamicData.item.OnInventoryUpdateHandlers, bag, scanType); end; -- LEGACY FUNCTION -- -- notifyItemCooldownUpdateHandlers () -- -- Notifies all item cooldown update handlers that an item cooldown has occurred. -- notifyItemCooldownUpdateHandlers = function () DynamicData.util.notifyWhateverHandlers(DynamicData.item.OnInventoryCooldownUpdateHandlers); end; -- -- OnLoad () -- -- Sets up the DynamicData.item for operation. -- In this case, it retrieves the IDs for the inventory slots. -- OnLoad = function () for key, value in DynamicData.item.inventorySlotNames do DynamicData.item.inventorySlotNames[key].id = GetInventorySlotInfo(value.name); end DynamicData.item.doUpdateItems(); UltimateUI_AfterInit(DynamicData.item.doUpdateItems); UltimateUI_AfterInit(UltimateUI_Schedule, 30, DynamicData.item.doUpdateItems); UltimateUI_AfterInit(UltimateUI_Schedule, 60, DynamicData.item.doUpdateItems); UltimateUI_AfterInit(UltimateUI_Schedule, 90, DynamicData.item.doUpdateItems); end; -- variables -- Taken from ItemBuff - thanks, Telo! -- Used for mapping inventory (equipment) ids and slot names inventorySlotNames = { { name = "HeadSlot" }, { name = "NeckSlot" }, { name = "ShoulderSlot" }, { name = "BackSlot" }, { name = "ChestSlot" }, { name = "ShirtSlot" }, { name = "TabardSlot" }, { name = "WristSlot" }, { name = "HandsSlot" }, { name = "WaistSlot" }, { name = "LegsSlot" }, { name = "FeetSlot" }, { name = "Finger0Slot" }, { name = "Finger1Slot" }, { name = "Trinket0Slot" }, { name = "Trinket1Slot" }, { name = "MainHandSlot" }, { name = "SecondaryHandSlot" }, { name = "RangedSlot" }, }; -- Contains lists of items that should be scanned. scanList = {}; -- Contains lists of when item slots were scanned. scanListScanned = {}; -- Whether a scan is in progress or not. itemScanInProgress = false; -- Contains item data about the player's items. player = {}; -- Contains the function pointers to functions that want to be called whenever the inventory updates. -- Will be called AFTER the DynamicData has parsed the inventory. OnInventoryUpdateHandlers = {}; -- Contains the function pointers to functions that want to be called whenever the inventory cooldown updates. -- Will be called AFTER the DynamicData has parsed the inventory. OnInventoryCooldownUpdateHandlers = {}; defaultItem = { name = "", strings = { [1] = {}, [2] = {}, [3] = {}, [4] = {}, [5] = {}, [6] = {}, [7] = {}, [8] = {}, [9] = {}, [10] = {}, [11] = {}, [12] = {}, [13] = {}, [14] = {}, [15] = {} }, count = 0, slotCount = 0, texture = "", cooldown = { [1] = 0, [2] = 0, [3] = 0, start = 0, duration = 0, enable = 0 }, itemType = "", locked = 0, durability = nil, maxDurability = nil, quality = 0, readable = 0, broken = 0, slotTexture = "" }; -- -- createBaseItem () -- -- creates a basic item with all attributes set to defaults. -- createBaseItem = function (baseItem) local newItem = {}; for k, v in DynamicData.item.defaultItem do newItem[k] = v; end if ( baseItem ) then for k, v in baseItem do newItem[k] = v; end end return newItem; end; -- -- makeScanList (numberOfScansPerList, bag) -- -- Makes a list of scans. -- makeScanLists = function (bag) if ( not DynamicData.item.scanList ) then DynamicData.item.scanList = {}; end if ( not bag ) then for bag = 0, 4, 1 do for slot = 1, GetContainerNumSlots(bag), 1 do if ( not DynamicData.item.scanList[bag] ) then DynamicData.item.scanList[bag] = {}; end DynamicData.item.scanList[bag][slot] = 1; end end bag = -1; for slot = 1, 19, 1 do if ( not DynamicData.item.scanList[bag] ) then DynamicData.item.scanList[bag] = {}; end DynamicData.item.scanList[bag][slot] = 1; end elseif ( bag <= -1 ) then bag = -1; if ( not DynamicData.item.scanList[bag] ) then DynamicData.item.scanList[bag] = {}; end for slot = 1, 19, 1 do DynamicData.item.scanList[bag][slot] = 1; end else if ( not DynamicData.item.scanList[bag] ) then DynamicData.item.scanList[bag] = {}; end for slot = 1, GetContainerNumSlots(bag), 1 do DynamicData.item.scanList[bag][slot] = 1; end end end; -- -- generateScanLists (numberOfScansPerList, bag) -- -- Generates a list of scans. -- generateScanLists = function (numberOfScansPerList, bag) if ( not numberOfScansPerList ) then numberOfScansPerList = DYNAMICDATA_DEFAULT_NUMBER_OF_TOOLTIP_SCANS_PER_UPDATE; end local lists = {}; local numberOfCurrentScans = 0; local currentList = {}; local slot; if ( not bag ) then for bag = 0, 4, 1 do for slot = 1, GetContainerNumSlots(bag), 1 do if ( not currentList[bag] ) then currentList[bag] = {}; end table.insert(currentList[bag], slot); numberOfCurrentScans = numberOfCurrentScans + 1; if ( numberOfCurrentScans >= numberOfScansPerList) then table.insert(lists, currentList); currentList = {}; numberOfCurrentScans = 0; end end end bag = -1; for slot = 1, 19, 1 do if ( not currentList[bag] ) then currentList[bag] = {}; end table.insert(currentList[bag], slot); numberOfCurrentScans = numberOfCurrentScans + 1; if ( numberOfCurrentScans >= numberOfScansPerList) then table.insert(lists, currentList); currentList = {}; numberOfCurrentScans = 0; end end elseif ( bag <= -1 ) then bag = -1; for slot = 1, 19, 1 do if ( not currentList[bag] ) then currentList[bag] = {}; end table.insert(currentList[bag], slot); numberOfCurrentScans = numberOfCurrentScans + 1; if ( numberOfCurrentScans >= numberOfScansPerList) then table.insert(lists, currentList); currentList = {}; numberOfCurrentScans = 0; end end else for slot = 1, GetContainerNumSlots(bag), 1 do if ( not currentList[bag] ) then currentList[bag] = {}; end table.insert(currentList[bag], slot); numberOfCurrentScans = numberOfCurrentScans + 1; if ( numberOfCurrentScans >= numberOfScansPerList) then table.insert(lists, currentList); currentList = {}; numberOfCurrentScans = 0; end end end if ( numberOfCurrentScans > 0) then table.insert(lists, currentList); end return lists; end; -- -- doQuickScan (bag) -- -- does a quick scan of the bag (or of the whole inventory if bag is not specified). -- doQuickScan = function(bag) if ( bag ) then DynamicData.item.scanItemsInBag(bag, DYNAMICDATA_ITEM_SCAN_TYPE_QUICK); else for i = 0, 4, 1 do DynamicData.item.scanItemsInBag(i, DYNAMICDATA_ITEM_SCAN_TYPE_QUICK); end DynamicData.item.scanItemsInBag(-1, DYNAMICDATA_ITEM_SCAN_TYPE_QUICK); end DynamicData.item.notifyUpdateHandlers(bag, DYNAMICDATA_ITEM_SCAN_TYPE_QUICK); DynamicData.item.notifyItemCooldownUpdateHandlers(); end; -- -- scanItemsInBag (bag, scanType) -- -- scans all items in bag and puts the info into the database -- can be retailored to only scan the tooltip, everything but the tooltip and everything. -- scanItemsInBag = function(bag, scanType) local bag, slot, v; if ( not bag ) then return; end if ( bag <= -1 ) then for slot = 1, 19, 1 do DynamicData.item.scanItem(-1, slot, scanType); end else for slot = 1, GetContainerNumSlots(bag), 1 do DynamicData.item.scanItem(bag, slot, scanType); end end end; -- -- scanItems (list, scanType) -- -- scans a list of item slots item and puts the info into the database -- can be retailored to only scan the tooltip, everything but the tooltip and everything. -- list format : list[bag] = { slot1, slot2, slot3 ... }; -- scanItems = function(scanType) local curTime = GetTime(); local numberScanned = 0; local scanned = false; for bag, bagValue in DynamicData.item.scanList do for slot, value in bagValue do if ( value == 1 ) then DynamicData.item.scanItem(bag, slot, scanType); DynamicData.item.scanList[bag][slot] = 0; if ( not DynamicData.item.scanListScanned ) then DynamicData.item.scanListScanned = {}; end if ( not DynamicData.item.scanListScanned[bag] ) then DynamicData.item.scanListScanned[bag] = {}; end DynamicData.item.scanListScanned[bag][slot] = curTime; numberScanned = numberScanned + 1; scanned = true; if ( numberScanned >= DYNAMICDATA_DEFAULT_NUMBER_OF_TOOLTIP_SCANS_PER_UPDATE ) then return scanned; end end end end return scanned; --[[ for bag, v in list do for key, slot in v do DynamicData.item.scanItem(bag, slot, scanType); end end ]]-- end; -- -- scanItem (bag, slot) -- -- scans an item and puts the info into the item database -- scanItem = function(bag, slot, scanType) if ( not scanType ) then scanType = DYNAMICDATA_ITEM_SCAN_TYPE_EVERYTHING; end local strings = nil; local itemName = nil; local element = nil; if ( not DynamicData.item.scanListScanned ) then DynamicData.item.scanListScanned = {}; end if ( not DynamicData.item.scanListScanned[bag] ) then DynamicData.item.scanListScanned[bag] = {}; end if ( not DynamicData.item.scanListScanned[bag][slot] ) then DynamicData.item.scanListScanned[bag][slot] = GetTime(); end if ( bag > -1 ) then if ( not DynamicData.item.player ) then DynamicData.item.player = {}; end if ( not DynamicData.item.player.itemsByBag ) then DynamicData.item.player.itemsByBag = {}; end if ( not DynamicData.item.player.itemsByBag[bag] ) then DynamicData.item.player.itemsByBag[bag] = {}; end if ( GetContainerNumSlots(bag) < slot ) then return nil; end if ( not DynamicData.item.player.itemsByBag[bag][slot] ) then DynamicData.item.player.itemsByBag[bag][slot] = DynamicData.item.createBaseItem(); end element = DynamicData.item.player.itemsByBag[bag][slot]; if ( not element.previousElement ) then element.previousElement = {}; end if ( ( scanType and DYNAMICDATA_ITEM_SCAN_TYPE_COOLDOWN ) > 0 ) then local ic_start, ic_duration, ic_enable = GetContainerItemCooldown(bag, slot); local itemCooldown = DynamicData.item.getOldCooldown(bag, slot); itemCooldown[1] = ic_start; itemCooldown[2] = ic_duration; itemCooldown[3] = ic_enable; itemCooldown.start = ic_start; itemCooldown.duration = ic_duration; itemCooldown.enable = ic_enable; element.cooldown = itemCooldown; end if ( ( scanType and DYNAMICDATA_ITEM_SCAN_TYPE_ITEMINFO ) > 0 ) then local textureName, itemCount, itemLocked, itemQuality, itemReadable = GetContainerItemInfo(bag, slot); local name = DynamicData.util.getItemNameFromLink(GetContainerItemLink(bag, slot)); if ( name ) then element.name = name; end element.count = itemCount; element.texture = textureName; element.locked = itemLocked; element.quality = itemQuality; element.readable = itemReadable; end if ( ( scanType and DYNAMICDATA_ITEM_SCAN_TYPE_TOOLTIP ) > 0 ) then if ( scanType == DYNAMICDATA_ITEM_SCAN_TYPE_TOOLTIP ) or ( not element.previousElement ) or ( element.previousElement.name ~= element.name ) or ( element.previousElement.cooldown.start ~= 0 ) or ( element.cooldown.start ~= 0 ) then strings = DynamicData.util.getItemTooltipInfo(bag, slot); if ( strings[1] ) and ( strings[1].left ) then itemName = strings[1].left; else itemName = ""; end element.name = itemName; element.strings = strings; element.itemType = DynamicData.util.getItemStringType(strings); local itemCurrentDurability, itemMaxDurability = DynamicData.util.getCurrentAndMaxDurability(strings); element.durability = itemCurrentDurability; element.maxDurability = itemMaxDurability; if ( not element.previousElement ) then element.previousElement = {}; end for k, v in element do if ( type(v) == "table" ) then if ( not element.previousElement[k] ) then element.previousElement[k] = {}; end for key, value in v do if ( type(value) == "table" ) then if ( not element.previousElement[k][key] ) then element.previousElement[k][key] = {}; end for keyKey, valueValue in value do element.previousElement[k][key][keyKey] = valueValue; end else element.previousElement[k][key] = value; end end else element.previousElement[k] = v; end end end end DynamicData.item.player.itemsByBag[bag][slot] = element; else bag = -1; if ( not DynamicData.item.player ) then DynamicData.item.player = {}; end if ( not DynamicData.item.player.itemsByBag ) then DynamicData.item.player.itemsByBag = {}; end if ( not DynamicData.item.player.itemsByBag[bag] ) then DynamicData.item.player.itemsByBag[bag] = {}; end if ( not DynamicData.item.player.itemsByBag[bag][slot] ) then DynamicData.item.player.itemsByBag[bag][slot] = DynamicData.item.createBaseItem(); end element = DynamicData.item.player.itemsByBag[bag][slot]; if ( ( scanType and DYNAMICDATA_ITEM_SCAN_TYPE_COOLDOWN ) > 0 ) then local ic_start, ic_duration, ic_enable = GetInventoryItemCooldown("player", slot); local itemCooldown = DynamicData.item.getOldCooldown(bag, slot); itemCooldown[1] = ic_start; itemCooldown[2] = ic_duration; itemCooldown[3] = ic_enable; itemCooldown.start = ic_start; itemCooldown.duration = ic_duration; itemCooldown.enable = ic_enable; element.cooldown = itemCooldown; end if ( ( scanType and DYNAMICDATA_ITEM_SCAN_TYPE_ITEMINFO ) > 0 ) then local itemCount = GetInventoryItemCount("player", slot); local textureName = GetInventoryItemTexture("player", slot); element.count = itemCount; element.slotTexture = slotTextureName; element.texture = textureName; element.locked = IsInventoryItemLocked(slot); element.broken = GetInventoryItemBroken("player", slot); --element.quality = GetInventoryItemQuality("player", slot); end if ( ( scanType and DYNAMICDATA_ITEM_SCAN_TYPE_TOOLTIP ) > 0 ) then strings = DynamicData.util.getItemTooltipInfo(-1, slot); element.strings = strings; if ( strings[1] ) and ( strings[1].left ) then itemName = strings[1].left; else itemName = ""; end element.name = itemName; element.itemType = DynamicData.util.getItemStringType(strings); local itemCurrentDurability, itemMaxDurability = DynamicData.util.getCurrentAndMaxDurability(strings); element.durability = itemCurrentDurability; element.maxDurability = itemMaxDurability; end DynamicData.item.player.itemsByBag[bag][slot] = element; end return element; end; getOldCooldown = function(bag, slot) if ( DynamicData.item.player.itemsByBag ) and ( DynamicData.item.player.itemsByBag[bag] ) and ( DynamicData.item.player.itemsByBag[bag][slot] ) and ( DynamicData.item.player.itemsByBag[bag][slot].cooldown ) then itemCooldown = DynamicData.item.player.itemsByBag[bag][slot].cooldown; else itemCooldown = { }; end return itemCooldown; end; -- -- getInventorySlotScanned(bag, slot) -- -- retrieves when the slot was last scanned or nil if never -- getInventorySlotScanned = function (bag, slot) if ( not DynamicData.item.scanListScanned ) then DynamicData.item.scanListScanned = {}; end if ( not DynamicData.item.scanListScanned[bag] ) then DynamicData.item.scanListScanned[bag] = {}; end return DynamicData.item.scanListScanned[bag][slot]; end; -- -- scanInventorySlotIfTime(bag, slot) -- -- scans the slot if necessary. -- scanInventorySlotIfTime = function(bag, slot) local curTime = GetTime(); local lastScanned = DynamicData.item.getInventorySlotScanned(bag, slot); if ( not lastScanned ) or ( ( lastScanned + 0.2 ) < GetTime() ) then DynamicData.item.scanItem(bag, slot, DYNAMICDATA_ITEM_SCAN_TYPE_QUICK); end end; };