Mercurial > wow > askmrrobot
view Export.lua @ 118:5cb881417bbf v55
Added Antorus to auto-logging.
author | yellowfive |
---|---|
date | Fri, 24 Nov 2017 19:46:27 -0800 |
parents | bccce18e12cb |
children | e31b02b24488 |
line wrap: on
line source
local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot") local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true) local AceGUI = LibStub("AceGUI-3.0") local _lastExport = nil local _txt = nil local function createLabel(container, text, width) local lbl = AceGUI:Create("AmrUiLabel") lbl:SetWidth(width or 800) lbl:SetText(text) lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) container:AddChild(lbl) return lbl end local function onSplashClose() Amr:HideCover() Amr.db.char.FirstUse = false end local function onTextChanged(widget) local val = _txt:GetText() if val == "overwolf-bib" then -- go to the gear tab, open import window, and show a cover Amr:ShowTab("Gear") Amr:ShowImportWindow(true) end end -- render a splash screen with first-time help local function renderSplash(container) local panel = Amr:RenderCoverChrome(container, 700, 450) local lbl = createLabel(panel, L.ExportSplashTitle, 650) lbl:SetJustifyH("CENTER") lbl:SetFont(Amr.CreateFont("Bold", 24, Amr.Colors.TextHeaderActive)) lbl:SetPoint("TOP", panel.content, "TOP", 0, -10) local lbl2 = createLabel(panel, L.ExportSplashSubtitle, 650) lbl2:SetJustifyH("CENTER") lbl2:SetFont(Amr.CreateFont("Bold", 18, Amr.Colors.TextTan)) lbl2:SetPoint("TOP", lbl.frame, "BOTTOM", 0, -20) lbl = createLabel(panel, L.ExportSplash1, 650) lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) lbl:SetPoint("TOPLEFT", lbl2.frame, "BOTTOMLEFT", 0, -70) lbl2 = createLabel(panel, L.ExportSplash2, 650) lbl2:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) lbl2:SetPoint("TOPLEFT", lbl.frame, "BOTTOMLEFT", 0, -15) lbl = createLabel(panel, L.ExportSplash3, 650) lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) lbl:SetPoint("TOPLEFT", lbl2.frame, "BOTTOMLEFT", 0, -15) lbl2 = createLabel(panel, L.ExportSplash4, 650) lbl2:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) lbl2:SetPoint("TOPLEFT", lbl.frame, "BOTTOMLEFT", 0, -15) local btn = AceGUI:Create("AmrUiButton") btn:SetText(L.ExportSplashClose) btn:SetBackgroundColor(Amr.Colors.Green) btn:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White)) btn:SetWidth(120) btn:SetHeight(28) btn:SetPoint("BOTTOM", panel.content, "BOTTOM", 0, 20) btn:SetCallback("OnClick", onSplashClose) panel:AddChild(btn) end -- renders the main UI for the Export tab function Amr:RenderTabExport(container) local lbl = createLabel(container, L.ExportTitle) lbl:SetFont(Amr.CreateFont("Bold", 24, Amr.Colors.TextHeaderActive)) lbl:SetPoint("TOPLEFT", container.content, "TOPLEFT", 0, -40) local lbl2 = createLabel(container, L.ExportHelp1) lbl2:SetPoint("TOPLEFT", lbl.frame, "BOTTOMLEFT", 0, -10) lbl = createLabel(container, L.ExportHelp2) lbl:SetPoint("TOPLEFT", lbl2.frame, "BOTTOMLEFT", 0, -10) lbl2 = createLabel(container, L.ExportHelp3) lbl2:SetPoint("TOPLEFT", lbl.frame, "BOTTOMLEFT", 0, -10) _txt = AceGUI:Create("AmrUiTextarea") _txt:SetWidth(800) _txt:SetHeight(300) _txt:SetPoint("TOP", lbl2.frame, "BOTTOM", 0, -20) _txt:SetFont(Amr.CreateFont("Regular", 12, Amr.Colors.Text)) _txt:SetCallback("OnTextChanged", onTextChanged) container:AddChild(_txt) local data = self:ExportCharacter() local txt = Amr.Serializer:SerializePlayerData(data, true) _txt:SetText(txt) _txt:SetFocus(true) -- update shopping list data Amr:UpdateShoppingData(data) -- show help splash if first time a user is using this if Amr.db.char.FirstUse then Amr:ShowCover(renderSplash) AceGUI:ClearFocus() end end function Amr:ReleaseTabExport() end function Amr:GetExportText() return _txt:GetText() end -- use some local variables to deal with the fact that a user can close the bank before a scan completes local _lastBankBagId = nil local _lastBankSlotId = nil local function scanBag(bagId, isBank, bagTable, bagItemsWithCount) local numSlots = GetContainerNumSlots(bagId) for slotId = 1, numSlots do local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId) if itemLink ~= nil then local itemData = Amr.Serializer.ParseItemLink(itemLink) if itemData ~= nil then -- only add equippable items to bag data --if IsEquippableItem(itemLink) or Amr.SetTokenIds[itemData.id] then if isBank then _lastBankBagId = bagId _lastBankSlotId = slotId end table.insert(bagTable, itemLink) --end -- all items and counts, used for e.g. shopping list and reagents, etc. if bagItemsWithCount then if bagItemsWithCount[itemData.id] then bagItemsWithCount[itemData.id] = bagItemsWithCount[itemData.id] + itemCount else bagItemsWithCount[itemData.id] = itemCount end end end end end end -- get the player's current gear and save it, also returns the data from GetPlayerData for efficiency local function getEquipped() local data = Amr.Serializer:GetPlayerData() local spec = GetSpecialization() Amr.db.char.Equipped[spec] = data.Equipped[spec] return data end local function scanBags() local bagItems = {} local itemsAndCounts = {} scanBag(BACKPACK_CONTAINER, false, bagItems, itemsAndCounts) -- backpack for bagId = 1, NUM_BAG_SLOTS do scanBag(bagId, false, bagItems, itemsAndCounts) end Amr.db.char.BagItems = bagItems Amr.db.char.BagItemsAndCounts = itemsAndCounts end -- scan the player's bank and save the contents, must be at the bank local function scanBank() local bankItems = {} local itemsAndCounts = {} scanBag(BANK_CONTAINER, true, bankItems, itemsAndCounts) scanBag(REAGENTBANK_CONTAINER, true, bankItems, itemsAndCounts) for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do scanBag(bagId, true, bankItems, itemsAndCounts) end -- see if the scan completed before the window closed, otherwise we don't overwrite with partial data if _lastBankBagId ~= nil then local itemLink = GetContainerItemLink(_lastBankBagId, _lastBankSlotId) if itemLink ~= nil then --still open Amr.db.char.BankItems = bankItems Amr.db.char.BankItemsAndCounts = itemsAndCounts end end end -- scan the player's void storage and save the contents, must be at void storage local function scanVoid() if IsVoidStorageReady() then local voidItems = {} local VOID_STORAGE_MAX = 80 local VOID_STORAGE_PAGES = 2 for page = 1,VOID_STORAGE_PAGES do for i = 1,VOID_STORAGE_MAX do local itemId = GetVoidItemInfo(page, i) if itemId then local itemLink = GetVoidItemHyperlinkString(((page - 1) * VOID_STORAGE_MAX) + i); if itemLink then tinsert(voidItems, itemLink) end end end end Amr.db.char.VoidItems = voidItems end end local function getRepStanding(factionId) local name, description, standingId, _ = GetFactionInfoByID(factionId) return standingId - 1; -- our rep enum correspond to what the armory returns, are 1 less than what the game returns end local function getReputations() local reps = {} local repList = {1375,1376,1270,1269,1341,1337,1387,1388,1435} for i, repId in pairs(repList) do local standing = getRepStanding(repId) if standing >= 0 then reps[repId] = standing end end return reps end local function scanTalents() local specPos = GetSpecialization() if not specPos or specPos < 1 or specPos > 4 then return end local talentInfo = {} local maxTiers = 7 for tier = 1, maxTiers do for col = 1, 3 do local id, name, _, _, _, spellId, _, t, c, selected = GetTalentInfoBySpecialization(specPos, tier, col) if selected then talentInfo[tier] = col end end end local str = "" for i = 1, maxTiers do if talentInfo[i] then str = str .. talentInfo[i] else str = str .. '0' end end Amr.db.char.Talents[specPos] = str end local function scanCrucible() if not Amr.db or not Amr.db.char or not Amr.db.char.Artifacts or not C_ArtifactRelicForgeUI or not C_ArtifactRelicForgeUI.GetSocketedRelicTalents then return end local equipped = {} local preview = nil for i = 1,4 do local talents = nil if i == 4 then talents = C_ArtifactRelicForgeUI.GetPreviewRelicTalents() --talents = nil else talents = C_ArtifactRelicForgeUI.GetSocketedRelicTalents(i) --[[ -- test data if i == 1 then talents = {} table.insert(talents, { powerID = 1739, isChosen = true }) table.insert(talents, { powerID = 1781, isChosen = true }) table.insert(talents, { powerID = 1770, isChosen = false }) table.insert(talents, { powerID = 791, isChosen = false }) table.insert(talents, { powerID = 786, isChosen = false }) table.insert(talents, { powerID = 1537, isChosen = false }) end ]] end if talents then local obj = { Powers = {}, Active = {} } if i == 4 then obj.ItemLink = C_ArtifactRelicForgeUI.GetPreviewRelicItemLink() if not obj.ItemLink then talents = nil else preview = obj end else table.insert(equipped, obj) end if talents then for k,v in ipairs(talents) do table.insert(obj.Powers, v.powerID) table.insert(obj.Active, v.isChosen) end end elseif i ~= 4 then table.insert(equipped, {}) end end local itemID = C_ArtifactUI.GetArtifactInfo() local spec = Amr.ArtifactIdToSpecNumber[itemID] if spec then -- sometimes this event can fire when no crucible data is available, don't overwrite non-blank crucible data with blank crucible data local badEquipped = false if Amr.db.char.Artifacts[spec] then local oldCrucible = Amr.db.char.Artifacts[spec].Crucible if oldCrucible then if #oldCrucible.Equipped > 0 and oldCrucible.Equipped[1] and not equipped[1] then badEquipped = true end end end local dataz = Amr.db.char.Artifacts[spec] if not dataz then dataz = {} Amr.db.char.Artifacts[spec] = dataz end if not dataz.Crucible then dataz.Crucible = { Equipped = {}, Previewed = {} } end local crucible = dataz.Crucible if not badEquipped then crucible.Equipped = equipped end if preview then local previewKey = {} table.insert(previewKey, preview.ItemLink) for i,v in ipairs(preview.Powers) do table.insert(previewKey, v .. "=" .. tostring(preview.Active[i])) end previewKey = table.concat(previewKey, "_") if not crucible.Previewed then crucible.Previewed = {} end crucible.Previewed[previewKey] = preview end end end local function pruneCrucible() if not Amr.db or not Amr.db.char or not Amr.db.char.Artifacts then return end local spec = GetSpecialization() local dataz = Amr.db.char.Artifacts[spec] if not dataz or not dataz.Crucible then return end local crucible = dataz.Crucible -- this was old format, transform to new format if crucible.Inventory then if not crucible.Previewed then crucible.Previewed = {} end for link,preview in pairs(crucible.Inventory) do local previewKey = {} table.insert(previewKey, preview.ItemLink) for i,v in ipairs(preview.Powers) do table.insert(previewKey, v .. "=" .. tostring(preview.Active[i])) end previewKey = table.concat(previewKey, "_") crucible.Previewed[previewKey] = preview end crucible.Inventory = nil end -- get a hash of every owned, but not-equipped item local ownedItems = {} if Amr.db.char.BagItems then for i,link in ipairs(Amr.db.char.BagItems) do ownedItems[link] = true end end if Amr.db.char.BankItems then for i,link in ipairs(Amr.db.char.BankItems) do ownedItems[link] = true end end if Amr.db.char.VoidItems then for i,link in ipairs(Amr.db.char.VoidItems) do ownedItems[link] = true end end -- prune out any previewed relics that the player no longer owns if crucible.Previewed then local toRemove = {} for k,v in pairs(crucible.Previewed) do if not ownedItems[v.ItemLink] then table.insert(toRemove, k) end end for i,v in ipairs(toRemove) do crucible.Previewed[v] = nil end end end local function scanArtifact() if not Amr.db or not Amr.db.char or not Amr.db.char.Artifacts then return end local powers = C_ArtifactUI.GetPowers() if not powers then return end local powerRanks = {} for k,v in pairs(powers) do local powerInfo = C_ArtifactUI.GetPowerInfo(v) if powerInfo.currentRank - powerInfo.bonusRanks > 0 then powerRanks[v] = powerInfo.currentRank - powerInfo.bonusRanks end end local relicInfo = {} for i = 1,3 do local _, _, _, link = C_ArtifactUI.GetRelicInfo(i); table.insert(relicInfo, link or "") end -- make sure that the artifact UI didn't get closed while we were reading it, GetPowers seems to return nil unless it is open powers = C_ArtifactUI.GetPowers() if not powers then return end -- use the artifact item ID to figure out which spec this is for, since you can open your artifact on any spec local itemID = C_ArtifactUI.GetArtifactInfo() local spec = Amr.ArtifactIdToSpecNumber[itemID] --local spec = GetSpecialization() if spec then -- sometimes this event can fire when no relic data is available, don't overwrite non-blank relic data with blank relic data if Amr.db.char.Artifacts[spec] then local oldRelics = Amr.db.char.Artifacts[spec].Relics if oldRelics then for i = 1,3 do if oldRelics[i] and oldRelics[i] ~= "" and (not relicInfo[i] or relicInfo[i] == "") then relicInfo[i] = oldRelics[i] end end end end local dataz = Amr.db.char.Artifacts[spec] if not dataz then dataz = {} Amr.db.char.Artifacts[spec] = dataz end if not dataz.Crucible then dataz.Crucible = { Equipped = {}, Inventory = {} } end dataz.Powers = powerRanks dataz.Relics = relicInfo end --scanCrucible() end -- Returns a data object containing all information about the current player needed for an export: -- gear, spec, reputations, bag, bank, and void storage items. function Amr:ExportCharacter() local data = getEquipped() scanBags() -- scan current spec's talents just before exporting scanTalents() -- prune crucible info just before each time we export pruneCrucible() data.Talents = Amr.db.char.Talents data.Artifacts = Amr.db.char.Artifacts data.Equipped = Amr.db.char.Equipped data.Reputations = getReputations() data.BagItems = Amr.db.char.BagItems data.BankItems = Amr.db.char.BankItems data.VoidItems = Amr.db.char.VoidItems return data end function Amr:InitializeExport() Amr:AddEventHandler("UNIT_INVENTORY_CHANGED", function(unitID) if unitID and unitID ~= "player" then return end getEquipped() end) end Amr:AddEventHandler("BANKFRAME_OPENED", scanBank) Amr:AddEventHandler("PLAYERBANKSLOTS_CHANGED", scanBank) Amr:AddEventHandler("VOID_STORAGE_OPEN", scanVoid) Amr:AddEventHandler("VOID_STORAGE_CONTENTS_UPDATE", scanVoid) Amr:AddEventHandler("VOID_STORAGE_DEPOSIT_UPDATE", scanVoid) Amr:AddEventHandler("VOID_STORAGE_UPDATE", scanVoid) Amr:AddEventHandler("PLAYER_TALENT_UPDATE", scanTalents) Amr:AddEventHandler("ARTIFACT_UPDATE", scanArtifact) Amr:AddEventHandler("ARTIFACT_RELIC_FORGE_UPDATE", scanCrucible) Amr:AddEventHandler("ARTIFACT_RELIC_FORGE_PREVIEW_RELIC_CHANGED", scanCrucible)