Nenue@62: -- Veneer Nenue@62: -- PaperDoll.lua Nenue@62: -- Created: 8/16/2016 8:18 AM Nenue@62: -- %file-revision% Nenue@80: -- Displays the item level and modifications of character sheet equipment, including artifact power Nenue@93: local print = DEVIAN_WORKSPACE and function(...) print('PaperDoll', ...) end or nop Nenue@96: local artifactSlot Nenue@93: local slot_overlays = {} Nenue@93: VeneerPaperDollMixin = { Nenue@93: anchorFrame = 'CharacterFrame', Nenue@93: anchorPoint = 'TOPLEFT', Nenue@93: KnownRelics = {}, Nenue@93: } Nenue@93: Nenue@93: local relic_slot_paths = { Nenue@93: Arcane = {"Relic-Arcane-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.849609375, 0.919921875, 0.1181640625, 0.1884765625, false, false}, Nenue@93: Blood = {"Relic-Blood-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.921875, 0.9921875, 0.1181640625, 0.1884765625, false, false}, Nenue@93: Fel = {"Relic-Fel-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.59765625, 0.66796875, 0.572265625, 0.642578125, false, false}, Nenue@93: Fire = {"Relic-Fire-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.669921875, 0.740234375, 0.572265625, 0.642578125, false, false}, Nenue@93: Frost = {"Relic-Frost-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.7421875, 0.8125, 0.572265625, 0.642578125, false, false}, Nenue@93: Holy = {"Relic-Holy-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.814453125, 0.884765625, 0.572265625, 0.642578125, false, false}, Nenue@93: Iron = {"Relic-Iron-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.88671875, 0.95703125, 0.572265625, 0.642578125, false, false}, Nenue@93: Life = {"Relic-Life-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.59765625, 0.66796875, 0.64453125, 0.71484375, false, false}, Nenue@93: Shadow = {"Relic-Shadow-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.59765625, 0.66796875, 0.716796875, 0.787109375, false, false}, Nenue@93: Water = {"Relic-Water-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.59765625, 0.66796875, 0.7890625, 0.859375, false, false}, Nenue@93: Wind = {"Relic-Wind-Slot", [[Interface\Artifacts\Artifacts.BLP]], 72, 72, 0.59765625, 0.66796875, 0.861328125, 0.931640625, false, false}, Nenue@93: } Nenue@93: Nenue@93: local slots_left = {'TOPLEFT', 'TOPRIGHT', 1, 0, 'TOPLEFT', 'BOTTOMLEFT', 0, -1} Nenue@93: local slots_right = {'TOPRIGHT', 'TOPLEFT', -1, 0, 'TOPRIGHT', 'BOTTOMRIGHT', 0, -1} Nenue@93: local slots_bottomleft = {'BOTTOMRIGHT', 'TOPRIGHT', 0, 1, 'BOTTOMRIGHT', 'TOPRIGHT', 0, 1 } Nenue@93: local slots_bottomright = {'BOTTOMLEFT', 'TOPLEFT', 0, -1, 'BOTTOMLEFT', 'TOPLEFT', 0, 1} Nenue@62: Nenue@64: local slot_anchors = { Nenue@93: [1] = slots_left, Nenue@93: [2] = slots_left, Nenue@93: [3] = slots_left, Nenue@93: [15] = slots_left, Nenue@93: [5] = slots_left, Nenue@93: [9] = slots_left, Nenue@62: Nenue@93: [10] = slots_right, Nenue@93: [6] = slots_right, Nenue@93: [7] = slots_right, Nenue@93: [8] = slots_right, Nenue@93: [11] = slots_right, Nenue@93: [12] = slots_right, Nenue@93: [13] = slots_right, Nenue@93: [14] = slots_right, Nenue@64: Nenue@93: [16] = slots_bottomleft, Nenue@93: [17] = slots_bottomright, Nenue@64: } Nenue@64: Nenue@64: Nenue@93: function VeneerPaperDollMixin:OnLoad() Nenue@93: hooksecurefunc("PaperDollItemSlotButton_Update", function(...) Nenue@93: self:GetSlotButton(PaperDollItemsFrame, ...) Nenue@93: end) Nenue@64: Nenue@93: hooksecurefunc("PaperDollFrame_UpdateStats", function(...) Nenue@93: self:GetStats(PaperDollItemsFrame, ...) Nenue@93: end) Nenue@64: Nenue@93: self:RegisterEvent('INSPECT_READY') Nenue@102: Veneer:AddHandler(self) Nenue@80: end Nenue@80: Nenue@93: function VeneerPaperDollMixin:SetupInspectFrame() Nenue@93: hooksecurefunc("InspectPaperDollItemSlotButton_Update", function(...) Nenue@93: self:GetSlotButton(InspectFrame, ...) Nenue@93: end) Nenue@93: self:RegisterEvent('INSPECT_READY') Nenue@93: end Nenue@93: function VeneerPaperDollMixin:SetupArtifactUI() Nenue@80: end Nenue@80: Nenue@93: function VeneerPaperDollMixin:Setup() Nenue@93: VeneerData.PaperDoll = VeneerData.PaperDoll or {} Nenue@93: VeneerData.PaperDoll.KnownRelics = VeneerData.PaperDoll.KnownRelics or {} Nenue@93: self.KnownRelics = VeneerData.PaperDoll.KnownRelics Nenue@80: Nenue@93: self:RegisterEvent('UNIT_INVENTORY_CHANGED') Nenue@93: self:RegisterEvent('PLAYER_EQUIPMENT_CHANGED') Nenue@93: self:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED') Nenue@96: self:RegisterEvent('ARTIFACT_UPDATE') Nenue@80: Nenue@93: self:MarkForUpdate() Nenue@62: end Nenue@62: Nenue@93: function VeneerPaperDollMixin:MarkForUpdate() Nenue@93: for frame, overlays in pairs(slot_overlays) do Nenue@93: for slot, overlay in pairs(overlays) do Nenue@93: if overlay:IsVisible() then Nenue@93: overlay:Update() Nenue@93: else Nenue@93: overlay.isDirty = true Nenue@93: end Nenue@64: end Nenue@64: end Nenue@64: end Nenue@64: Nenue@93: function VeneerPaperDollMixin:GetStats() Nenue@93: end Nenue@93: function VeneerPaperDollMixin:GetSlotButton(panel, frame) Nenue@93: print('|cFF00FF88'..self:GetName()..':GetSlotButton()', frame:GetName(), frame:GetID()) Nenue@93: local slot = frame:GetID() Nenue@93: local unit = panel.unit or 'player' Nenue@93: if slot_anchors[slot] then Nenue@93: slot_overlays[panel] = slot_overlays[panel] or {} Nenue@93: local overlay = slot_overlays[panel][slot] Nenue@93: if not overlay then Nenue@96: print('creating slot overlay', slot) Nenue@93: overlay = CreateFrame('Frame', 'VeneerPaperDollSlot' .. unit .. slot, frame, 'VeneerPaperDollSlotInfoTemplate') Nenue@93: overlay:SetID(slot) Nenue@93: slot_overlays[panel][slot] = overlay Nenue@93: overlay.checkRelic = frame.checkRelic Nenue@71: Nenue@93: local anchorPoint, relativePoint, dX, dY, statPoint, statRelative, statdX, statdY = unpack(slot_anchors[slot]) Nenue@93: local offset = 7 Nenue@93: overlay:SetPoint(anchorPoint, frame, relativePoint, dX * offset, dY * offset) Nenue@93: overlay:SetSize(frame:GetWidth()*3, frame:GetHeight()) Nenue@93: Nenue@93: local relativeFrame = overlay Nenue@93: for i, region in ipairs(overlay.StatsLeft) do Nenue@93: region:ClearAllPoints() Nenue@93: print(statPoint, relativeFrame, (i == 1) and statPoint or statRelative) Nenue@93: region:SetPoint(statPoint, relativeFrame, (i == 1) and statPoint or statRelative, 0, 0) Nenue@93: relativeFrame = region Nenue@93: end Nenue@93: if slot == 16 then Nenue@93: overlay.Sockets:ClearAllPoints() Nenue@93: overlay.Sockets:SetPoint('BOTTOM', CharacterFrameInsetBg, 'BOTTOM', 0, frame:GetHeight() + 14) Nenue@93: overlay.ItemLevel:SetFontObject(VeneerNumberFontLarge) Nenue@93: overlay.ItemLevel:ClearAllPoints() Nenue@93: overlay.ItemLevel:SetPoint('BOTTOM', overlay.Sockets, 'TOP', 0, 4) Nenue@96: if unit == 'player' then Nenue@96: artifactSlot = overlay Nenue@96: end Nenue@96: Nenue@93: end Nenue@93: Nenue@93: print(overlay.Sockets:GetPoint(1)) Nenue@93: overlay.anchors = slot_anchors[slot] Nenue@93: end Nenue@93: Nenue@93: overlay.unit = unit Nenue@93: overlay.checkRelic = (unit == 'player' and slot == 16) Nenue@93: Nenue@93: Nenue@93: if frame.hasItem then Nenue@93: overlay.isDirty = true Nenue@93: overlay:Show() Nenue@93: else Nenue@93: overlay:Hide() Nenue@93: end Nenue@64: end Nenue@64: end Nenue@64: Nenue@80: Nenue@64: Nenue@93: function VeneerPaperDollMixin:OnEvent(event, arg) Nenue@93: print(event, arg) Nenue@93: if event == 'ADDON_LOADED' then Nenue@93: if IsLoggedIn() and not self.initialized then Nenue@93: self:Setup() Nenue@93: self.initialized = true Nenue@93: end Nenue@64: Nenue@64: Nenue@93: if arg == 'Blizzard_InspectUI' then Nenue@93: self:SetupInspectFrame() Nenue@93: end Nenue@93: if arg == 'Blizzard_ArtifactUI' then Nenue@93: self:SetupArtifactUI() Nenue@93: self:MarkForUpdate() Nenue@93: end Nenue@93: elseif event == 'ARTIFACT_UPDATE' then Nenue@96: Nenue@96: if artifactSlot then Nenue@96: print('just udpate artifact slot') Nenue@96: artifactSlot:Update(true) Nenue@96: end Nenue@96: Nenue@96: Nenue@93: else Nenue@93: if (event == 'PLAYER_SPECIALIZATION_CHANGED' or event == 'UNIT_INVENTORY_CHANGED') then Nenue@93: if arg ~= 'player' then Nenue@93: return Nenue@93: end Nenue@93: elseif event == 'INSPECT_READY' then Nenue@80: Nenue@65: end Nenue@64: Nenue@93: self:MarkForUpdate() Nenue@66: Nenue@65: end Nenue@80: end Nenue@66: Nenue@64: Nenue@93: VeneerPaperDollSlotMixin = {} Nenue@66: Nenue@93: function VeneerPaperDollSlotMixin:OnLoad() Nenue@93: self.SocketText = {} Nenue@93: self.SocketType = {} Nenue@93: self.SocketLink = {} Nenue@93: end Nenue@93: function VeneerPaperDollSlotMixin:OnShow() Nenue@93: if self.isDirty then Nenue@93: self:Update() Nenue@93: end Nenue@93: end Nenue@93: function VeneerPaperDollSlotMixin:OnUpdate() Nenue@93: if self.isDirty then Nenue@93: --print('|cFF00FF00pushing update for', self:GetID()) Nenue@93: self:Update() Nenue@93: end Nenue@80: Nenue@93: if self.checkRelic then Nenue@93: self.tooltipLink = nil Nenue@93: for i = 1, 3 do Nenue@93: if self.SocketLink[i] and self.Sockets.SocketIcon[i]:IsMouseOver() then Nenue@93: self.tooltipLink = self.SocketLink[i] Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: if self.tooltipLink then Nenue@93: if not GameTooltip:IsOwned(self) then Nenue@93: GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') Nenue@93: GameTooltip:SetHyperlink(self.tooltipLink) Nenue@93: Nenue@93: GameTooltip:Show() Nenue@93: end Nenue@93: else Nenue@93: if GameTooltip:IsOwned(self) then Nenue@93: GameTooltip:Hide() Nenue@93: end Nenue@93: end Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: function VeneerPaperDollSlotMixin:UpdateRelicInfo() Nenue@93: Nenue@93: Nenue@93: local itemID = GetInventoryItemID(self.unit, 16) Nenue@93: if not itemID then Nenue@93: return Nenue@93: end Nenue@93: print('|cFF00FFFFRelic Sweep:', itemID) Nenue@93: Nenue@93: Nenue@93: local guid = UnitGUID(self.unit or 'player') Nenue@93: local relicCache = VeneerPaperDoll.KnownRelics[guid] and VeneerPaperDoll.KnownRelics[guid][itemID] Nenue@93: if VeneerPaperDoll.KnownRelics[guid] then Nenue@93: for k, v in pairs(VeneerPaperDoll.KnownRelics[guid]) do Nenue@93: if tonumber(k) and tonumber(k) < 72 then Nenue@93: VeneerPaperDoll.KnownRelics[guid][k] = nil Nenue@93: end Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: Nenue@93: if not relicCache then Nenue@93: relicCache = {} Nenue@93: VeneerPaperDoll.KnownRelics[guid] = VeneerPaperDoll.KnownRelics[guid] or {} Nenue@93: VeneerPaperDoll.KnownRelics[guid][itemID] = relicCache Nenue@93: end Nenue@93: Nenue@93: local numRelics = C_ArtifactUI.GetNumRelicSlots() Nenue@93: local isEquipped = C_ArtifactUI.IsViewedArtifactEquipped() Nenue@93: local tooltip = VeneerPaperDollTooltip Nenue@93: tooltip:SetOwner(self, 'ANCHOR_NONE') Nenue@93: self.hasRelicSlots = true Nenue@93: if numRelics and isEquipped then Nenue@93: print('Relic Query:', itemID, numRelics) Nenue@93: for i = 1, numRelics do Nenue@93: local lockedReason, relicName, relicIcon, relicLink = C_ArtifactUI.GetRelicInfo(i); Nenue@93: local relicType = C_ArtifactUI.GetRelicSlotType(i); Nenue@93: if relicIcon then Nenue@93: tooltip:SetHyperlink(relicLink) Nenue@93: print(tooltip:NumLines()) Nenue@93: Nenue@93: local line1 = _G['VeneerPaperDollTooltipTextLeft2'] Nenue@93: local line2 = _G['VeneerPaperDollTooltipTextLeft3'] Nenue@93: local text1 = line1 and line1:GetText() Nenue@93: local text2 = line2 and line2:GetText() Nenue@93: if text1 or text2 then Nenue@93: self.SocketText[i] = text1:match('Item Level (%d+)') or text2:match('Item Level (%d+)') Nenue@93: end Nenue@93: Nenue@93: self.SocketInfo[i] = relicIcon Nenue@93: self.SocketType[i] = relicType Nenue@93: self.SocketLink[i] = relicLink Nenue@93: print('storing', i, self.SocketInfo[i], self.SocketText[i], self.SocketType[i], self.SocketLink[i]) Nenue@93: else Nenue@93: Nenue@93: self.SocketInfo[i] = "Interface\\CharacterFrame\\TempPortraitAlphaMask" Nenue@93: self.SocketType[i] = relicType Nenue@93: self.SocketLink[i] = nil Nenue@93: end Nenue@93: Nenue@93: relicCache[i] = {self.SocketInfo[i], self.SocketText[i], self.SocketType[i], self.SocketLink[i]} Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: for i = 1, 3 do Nenue@93: if relicCache[i] then Nenue@93: local relicIcon, relicLevel, relicType, relicLink = unpack(relicCache[i]) Nenue@93: Nenue@93: print('loading', i, relicIcon, relicLevel, relicType, relicLink) Nenue@93: self.SocketInfo[i] = relicIcon Nenue@93: self.SocketText[i] = relicLevel Nenue@93: self.SocketType[i] = relicType Nenue@93: self.SocketLink[i] = relicLink Nenue@93: end Nenue@93: end Nenue@93: end Nenue@93: Nenue@96: function VeneerPaperDollSlotMixin:Update(forced) Nenue@93: local id = self:GetID() Nenue@93: Nenue@93: self.SocketInfo = self.SocketInfo or {} Nenue@93: table.wipe(self.SocketInfo) Nenue@93: self.ItemLevel:SetText(nil) Nenue@93: Nenue@93: local tooltip = VeneerPaperDollTooltip Nenue@93: tooltip:SetOwner(self, 'ANCHOR_NONE') Nenue@96: if forced then Nenue@96: print('refresh', self.unit, id) Nenue@96: end Nenue@96: Nenue@93: tooltip:SetInventoryItem(self.unit or 'player', id) Nenue@93: tooltip:Show() Nenue@93: Nenue@93: local numLines = tooltip:NumLines() Nenue@93: local numTextures = 0 Nenue@93: local itemLevel Nenue@93: local itemLevelLine Nenue@96: --print('|cFFFFFF00Sockets scan:', numLines) Nenue@93: for i = 1, numLines do Nenue@93: local line = _G['VeneerPaperDollTooltipTextLeft'..i] Nenue@93: local text = line and line:GetText() Nenue@93: if text then Nenue@93: itemLevel = text:match('Item Level (%d+)') Nenue@93: if itemLevel then Nenue@93: self.ItemLevel:SetText(itemLevel) Nenue@93: break Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: local texture = _G['VeneerPaperDollTooltipTexture'..i] Nenue@93: if texture and texture:IsShown() then Nenue@93: numTextures = numTextures + 1 Nenue@96: --print('picked up socket', numTextures, texture:GetTexture()) Nenue@93: self.SocketInfo[numTextures] = texture:GetTexture() Nenue@93: end Nenue@93: end Nenue@93: if self.checkRelic then Nenue@93: self:UpdateRelicInfo() Nenue@93: end Nenue@93: Nenue@93: Nenue@93: local relativeIcon Nenue@93: local socketsWidth = 0 Nenue@93: local socketsHeight = 24 Nenue@93: for index, icon in ipairs(self.Sockets.SocketIcon) do Nenue@93: if self.SocketInfo[index] then Nenue@96: --print('|cFF0088FFsocketInfo|r', index, self.SocketInfo[index]) Nenue@93: icon:ClearAllPoints() Nenue@93: Nenue@93: icon:SetTexture(self.SocketInfo[index]) Nenue@93: icon:SetSize(16, 16) Nenue@93: icon:Show() Nenue@93: if index == 1 then Nenue@93: icon:SetPoint('LEFT', self.Sockets, 'LEFT', 0, 0) Nenue@93: socketsWidth = socketsWidth + icon:GetWidth() Nenue@93: socketsHeight = icon:GetHeight() Nenue@93: else Nenue@93: if id == 16 then Nenue@93: icon:SetPoint('LEFT', relativeIcon, 'RIGHT', 14, 0) Nenue@93: socketsWidth = socketsWidth + 14 Nenue@93: else Nenue@93: icon:SetPoint('LEFT', relativeIcon, 'RIGHT', 2, 0) Nenue@93: socketsWidth = socketsWidth + 2 Nenue@93: end Nenue@93: socketsWidth = socketsWidth + icon:GetWidth() Nenue@93: end Nenue@96: print( '|cFFFF4400', icon:GetPoint(1)) Nenue@93: Nenue@93: local label = self.Sockets.SocketLabel[index] Nenue@93: label:ClearAllPoints() Nenue@93: label:SetPoint('BOTTOM', icon, 'TOP',0, 2) Nenue@93: label:SetFontObject(VeneerNumberFont) Nenue@93: label:SetText(self.SocketText[index]) Nenue@93: Nenue@93: if self.checkRelic then Nenue@93: local relicAtlasName = ("Relic-%s-Slot"):format(self.SocketType[index]); Nenue@93: self.Sockets.SocketBg = self.Sockets.SocketBg or {} Nenue@93: self.Sockets.SocketBg[index] = self.Sockets.SocketBg[index] or self.Sockets:CreateTexture() Nenue@93: self.Sockets.SocketBg[index]:SetAtlas(relicAtlasName) Nenue@93: self.Sockets.SocketBg[index]:SetPoint('TOPRIGHT', icon, 'TOPRIGHT', 12, 12) Nenue@93: self.Sockets.SocketBg[index]:SetPoint('BOTTOMLEFT', icon, 'BOTTOMLEFT', -12,-12) Nenue@96: --print('', self.SocketType[index], relicAtlasName) Nenue@93: Nenue@93: socketsHeight = self.Sockets.SocketBg[index]:GetHeight() Nenue@96: print(socketsWidth, socketsHeight) Nenue@93: end Nenue@93: Nenue@93: Nenue@93: relativeIcon = icon Nenue@93: else Nenue@93: if self.checkRelic and self.Sockets.SocketBg and self.Sockets.SocketBg[index] then Nenue@93: self.Sockets.SocketBg[index]:SetTexture(nil) Nenue@93: self.Sockets.SocketLabel[index]:SetText(nil) Nenue@93: end Nenue@93: Nenue@93: icon:Hide() Nenue@93: end Nenue@93: Nenue@93: Nenue@93: end Nenue@93: self.Sockets:SetWidth(socketsWidth) Nenue@93: self.Sockets:SetHeight(socketsHeight) Nenue@93: Nenue@93: Nenue@93: Nenue@93: Nenue@93: Nenue@93: self.isDirty = nil Nenue@93: end