| yellowfive@57 | 1 local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot") | 
| yellowfive@57 | 2 local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true) | 
| yellowfive@57 | 3 local AceGUI = LibStub("AceGUI-3.0") | 
| yellowfive@57 | 4 | 
| yellowfive@57 | 5 local _lastExport = nil | 
| yellowfive@57 | 6 local _txt = nil | 
| yellowfive@57 | 7 | 
| yellowfive@57 | 8 local function createLabel(container, text, width) | 
| yellowfive@57 | 9 	local lbl = AceGUI:Create("AmrUiLabel") | 
| yellowfive@57 | 10 	lbl:SetWidth(width or 800) | 
| yellowfive@57 | 11 	lbl:SetText(text) | 
| yellowfive@57 | 12 	lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) | 
| yellowfive@57 | 13 	container:AddChild(lbl) | 
| yellowfive@57 | 14 	return lbl | 
| yellowfive@57 | 15 end | 
| yellowfive@57 | 16 | 
| yellowfive@57 | 17 local function onSplashClose() | 
| yellowfive@57 | 18 	Amr:HideCover() | 
| yellowfive@57 | 19 	Amr.db.char.FirstUse = false | 
| yellowfive@57 | 20 end | 
| yellowfive@57 | 21 | 
| yellowfive@69 | 22 local function onTextChanged(widget) | 
| yellowfive@69 | 23 	local val = _txt:GetText() | 
| yellowfive@69 | 24 	if val == "overwolf-bib" then | 
| yellowfive@69 | 25 		-- go to the gear tab, open import window, and show a cover | 
| yellowfive@69 | 26 		Amr:ShowTab("Gear") | 
| yellowfive@69 | 27 		Amr:ShowImportWindow(true) | 
| yellowfive@69 | 28 	end | 
| yellowfive@69 | 29 end | 
| yellowfive@69 | 30 | 
| yellowfive@57 | 31 -- render a splash screen with first-time help | 
| yellowfive@57 | 32 local function renderSplash(container) | 
| yellowfive@57 | 33 	local panel = Amr:RenderCoverChrome(container, 700, 450) | 
| yellowfive@57 | 34 | 
| yellowfive@57 | 35 	local lbl = createLabel(panel, L.ExportSplashTitle, 650) | 
| yellowfive@57 | 36 	lbl:SetJustifyH("CENTER") | 
| yellowfive@57 | 37 	lbl:SetFont(Amr.CreateFont("Bold", 24, Amr.Colors.TextHeaderActive)) | 
| yellowfive@57 | 38 	lbl:SetPoint("TOP", panel.content, "TOP", 0, -10) | 
| yellowfive@57 | 39 | 
| yellowfive@57 | 40 	local lbl2 = createLabel(panel, L.ExportSplashSubtitle, 650) | 
| yellowfive@57 | 41 	lbl2:SetJustifyH("CENTER") | 
| yellowfive@57 | 42 	lbl2:SetFont(Amr.CreateFont("Bold", 18, Amr.Colors.TextTan)) | 
| yellowfive@57 | 43 	lbl2:SetPoint("TOP", lbl.frame, "BOTTOM", 0, -20) | 
| yellowfive@57 | 44 | 
| yellowfive@57 | 45 	lbl = createLabel(panel, L.ExportSplash1, 650) | 
| yellowfive@57 | 46 	lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) | 
| yellowfive@57 | 47 	lbl:SetPoint("TOPLEFT", lbl2.frame, "BOTTOMLEFT", 0, -70) | 
| yellowfive@57 | 48 | 
| yellowfive@57 | 49 	lbl2 = createLabel(panel, L.ExportSplash2, 650) | 
| yellowfive@57 | 50 	lbl2:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) | 
| yellowfive@57 | 51 	lbl2:SetPoint("TOPLEFT", lbl.frame, "BOTTOMLEFT", 0, -15) | 
| yellowfive@57 | 52 | 
| yellowfive@57 | 53 	lbl = createLabel(panel, L.ExportSplash3, 650) | 
| yellowfive@57 | 54 	lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) | 
| yellowfive@57 | 55 	lbl:SetPoint("TOPLEFT", lbl2.frame, "BOTTOMLEFT", 0, -15) | 
| yellowfive@81 | 56 | 
| yellowfive@81 | 57 	lbl2 = createLabel(panel, L.ExportSplash4, 650) | 
| yellowfive@81 | 58 	lbl2:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.Text)) | 
| yellowfive@81 | 59 	lbl2:SetPoint("TOPLEFT", lbl.frame, "BOTTOMLEFT", 0, -15) | 
| yellowfive@57 | 60 | 
| yellowfive@57 | 61 	local btn = AceGUI:Create("AmrUiButton") | 
| yellowfive@57 | 62 	btn:SetText(L.ExportSplashClose) | 
| yellowfive@57 | 63 	btn:SetBackgroundColor(Amr.Colors.Green) | 
| yellowfive@57 | 64 	btn:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White)) | 
| yellowfive@57 | 65 	btn:SetWidth(120) | 
| yellowfive@57 | 66 	btn:SetHeight(28) | 
| yellowfive@57 | 67 	btn:SetPoint("BOTTOM", panel.content, "BOTTOM", 0, 20) | 
| yellowfive@57 | 68 	btn:SetCallback("OnClick", onSplashClose) | 
| yellowfive@57 | 69 	panel:AddChild(btn) | 
| yellowfive@57 | 70 end | 
| yellowfive@57 | 71 | 
| yellowfive@57 | 72 -- renders the main UI for the Export tab | 
| yellowfive@57 | 73 function Amr:RenderTabExport(container) | 
| yellowfive@57 | 74 | 
| yellowfive@57 | 75 	local lbl = createLabel(container, L.ExportTitle) | 
| yellowfive@57 | 76 	lbl:SetFont(Amr.CreateFont("Bold", 24, Amr.Colors.TextHeaderActive)) | 
| yellowfive@57 | 77 	lbl:SetPoint("TOPLEFT", container.content, "TOPLEFT", 0, -40) | 
| yellowfive@57 | 78 | 
| yellowfive@57 | 79 	local lbl2 = createLabel(container, L.ExportHelp1) | 
| yellowfive@57 | 80 	lbl2:SetPoint("TOPLEFT", lbl.frame, "BOTTOMLEFT", 0, -10) | 
| yellowfive@57 | 81 | 
| yellowfive@57 | 82 	lbl = createLabel(container, L.ExportHelp2) | 
| yellowfive@57 | 83 	lbl:SetPoint("TOPLEFT", lbl2.frame, "BOTTOMLEFT", 0, -10) | 
| yellowfive@57 | 84 | 
| yellowfive@57 | 85 	lbl2 = createLabel(container, L.ExportHelp3) | 
| yellowfive@57 | 86 	lbl2:SetPoint("TOPLEFT", lbl.frame, "BOTTOMLEFT", 0, -10) | 
| yellowfive@57 | 87 | 
| yellowfive@57 | 88 	_txt = AceGUI:Create("AmrUiTextarea") | 
| yellowfive@57 | 89 	_txt:SetWidth(800) | 
| yellowfive@57 | 90 	_txt:SetHeight(300) | 
| yellowfive@81 | 91 	_txt:SetPoint("TOP", lbl2.frame, "BOTTOM", 0, -20) | 
| yellowfive@57 | 92 	_txt:SetFont(Amr.CreateFont("Regular", 12, Amr.Colors.Text)) | 
| yellowfive@69 | 93 	_txt:SetCallback("OnTextChanged", onTextChanged) | 
| yellowfive@57 | 94 	container:AddChild(_txt) | 
| yellowfive@57 | 95 | 
| yellowfive@57 | 96 	local data = self:ExportCharacter() | 
| yellowfive@57 | 97 	local txt = Amr.Serializer:SerializePlayerData(data, true) | 
| yellowfive@57 | 98 	_txt:SetText(txt) | 
| yellowfive@57 | 99 	_txt:SetFocus(true) | 
| yellowfive@57 | 100 | 
| yellowfive@57 | 101 	-- update shopping list data | 
| yellowfive@57 | 102 	Amr:UpdateShoppingData(data) | 
| yellowfive@57 | 103 | 
| yellowfive@57 | 104 	-- show help splash if first time a user is using this | 
| yellowfive@57 | 105 	if Amr.db.char.FirstUse then | 
| yellowfive@57 | 106 		Amr:ShowCover(renderSplash) | 
| yellowfive@57 | 107 		AceGUI:ClearFocus() | 
| yellowfive@57 | 108 	end | 
| yellowfive@57 | 109 end | 
| yellowfive@57 | 110 | 
| yellowfive@57 | 111 function Amr:ReleaseTabExport() | 
| yellowfive@57 | 112 end | 
| yellowfive@57 | 113 | 
| yellowfive@57 | 114 function Amr:GetExportText() | 
| yellowfive@57 | 115 	return _txt:GetText() | 
| yellowfive@57 | 116 end | 
| yellowfive@57 | 117 | 
| yellowfive@57 | 118 | 
| yellowfive@57 | 119 -- use some local variables to deal with the fact that a user can close the bank before a scan completes | 
| yellowfive@57 | 120 local _lastBankBagId = nil | 
| yellowfive@57 | 121 local _lastBankSlotId = nil | 
| yellowfive@57 | 122 | 
| yellowfive@57 | 123 local function scanBag(bagId, isBank, bagTable, bagItemsWithCount) | 
| yellowfive@57 | 124 	local numSlots = GetContainerNumSlots(bagId) | 
| yellowfive@57 | 125 	for slotId = 1, numSlots do | 
| yellowfive@57 | 126 		local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId) | 
| yellowfive@57 | 127 		if itemLink ~= nil then | 
| yellowfive@57 | 128 			local itemData = Amr.Serializer.ParseItemLink(itemLink) | 
| yellowfive@57 | 129 			if itemData ~= nil then | 
| yellowfive@85 | 130 | 
| yellowfive@57 | 131 				-- only add equippable items to bag data | 
| yellowfive@85 | 132 				--if IsEquippableItem(itemLink) or Amr.SetTokenIds[itemData.id] then | 
| yellowfive@57 | 133 	                if isBank then | 
| yellowfive@57 | 134                     	_lastBankBagId = bagId | 
| yellowfive@57 | 135                     	_lastBankSlotId = slotId | 
| yellowfive@57 | 136                 	end | 
| yellowfive@57 | 137 | 
| yellowfive@57 | 138                 	table.insert(bagTable, itemLink) | 
| yellowfive@85 | 139                 --end | 
| yellowfive@57 | 140 | 
| yellowfive@57 | 141 				-- all items and counts, used for e.g. shopping list and reagents, etc. | 
| yellowfive@57 | 142                 if bagItemsWithCount then | 
| yellowfive@57 | 143                 	if bagItemsWithCount[itemData.id] then | 
| yellowfive@57 | 144                 		bagItemsWithCount[itemData.id] = bagItemsWithCount[itemData.id] + itemCount | 
| yellowfive@57 | 145                 	else | 
| yellowfive@57 | 146                 		bagItemsWithCount[itemData.id] = itemCount | 
| yellowfive@57 | 147                 	end | 
| yellowfive@57 | 148                 end | 
| yellowfive@57 | 149             end | 
| yellowfive@57 | 150 		end | 
| yellowfive@57 | 151 	end | 
| yellowfive@57 | 152 end | 
| yellowfive@57 | 153 | 
| yellowfive@57 | 154 -- get the player's current gear and save it, also returns the data from GetPlayerData for efficiency | 
| yellowfive@57 | 155 local function getEquipped() | 
| yellowfive@81 | 156 	local data = Amr.Serializer:GetPlayerData() | 
| yellowfive@81 | 157 	local spec = GetSpecialization() | 
| yellowfive@57 | 158 | 
| yellowfive@57 | 159 	Amr.db.char.Equipped[spec] = data.Equipped[spec] | 
| yellowfive@57 | 160 | 
| yellowfive@57 | 161 	return data | 
| yellowfive@57 | 162 end | 
| yellowfive@57 | 163 | 
| yellowfive@57 | 164 local function scanBags() | 
| yellowfive@57 | 165 | 
| yellowfive@57 | 166 	local bagItems = {} | 
| yellowfive@57 | 167 	local itemsAndCounts = {} | 
| yellowfive@57 | 168 | 
| yellowfive@57 | 169 	scanBag(BACKPACK_CONTAINER, false, bagItems, itemsAndCounts) -- backpack | 
| yellowfive@57 | 170 	for bagId = 1, NUM_BAG_SLOTS do | 
| yellowfive@57 | 171 		scanBag(bagId, false, bagItems, itemsAndCounts) | 
| yellowfive@57 | 172 	end | 
| yellowfive@57 | 173 | 
| yellowfive@57 | 174 	Amr.db.char.BagItems = bagItems | 
| yellowfive@57 | 175 	Amr.db.char.BagItemsAndCounts = itemsAndCounts | 
| yellowfive@57 | 176 end | 
| yellowfive@57 | 177 | 
| yellowfive@57 | 178 -- scan the player's bank and save the contents, must be at the bank | 
| yellowfive@57 | 179 local function scanBank() | 
| yellowfive@57 | 180 | 
| yellowfive@57 | 181 	local bankItems = {} | 
| yellowfive@57 | 182 	local itemsAndCounts = {} | 
| yellowfive@57 | 183 | 
| yellowfive@57 | 184 	scanBag(BANK_CONTAINER, true, bankItems, itemsAndCounts) | 
| yellowfive@57 | 185 	scanBag(REAGENTBANK_CONTAINER, true, bankItems, itemsAndCounts) | 
| yellowfive@57 | 186 	for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do | 
| yellowfive@57 | 187 		scanBag(bagId, true, bankItems, itemsAndCounts) | 
| yellowfive@57 | 188 	end | 
| yellowfive@57 | 189 | 
| yellowfive@57 | 190 	-- see if the scan completed before the window closed, otherwise we don't overwrite with partial data | 
| yellowfive@57 | 191 	if _lastBankBagId ~= nil then | 
| yellowfive@57 | 192 		local itemLink = GetContainerItemLink(_lastBankBagId, _lastBankSlotId) | 
| yellowfive@57 | 193 		if itemLink ~= nil then --still open | 
| yellowfive@57 | 194             Amr.db.char.BankItems = bankItems | 
| yellowfive@57 | 195             Amr.db.char.BankItemsAndCounts = itemsAndCounts | 
| yellowfive@57 | 196 		end | 
| yellowfive@57 | 197 	end | 
| yellowfive@57 | 198 | 
| yellowfive@57 | 199 end | 
| yellowfive@57 | 200 | 
| yellowfive@57 | 201 -- scan the player's void storage and save the contents, must be at void storage | 
| yellowfive@57 | 202 local function scanVoid() | 
| yellowfive@57 | 203 | 
| yellowfive@57 | 204 	if IsVoidStorageReady() then | 
| yellowfive@57 | 205 		local voidItems = {} | 
| yellowfive@57 | 206 		local VOID_STORAGE_MAX = 80 | 
| yellowfive@57 | 207 		local VOID_STORAGE_PAGES = 2 | 
| yellowfive@57 | 208 | 
| yellowfive@57 | 209 		for page = 1,VOID_STORAGE_PAGES do | 
| yellowfive@57 | 210 			for i = 1,VOID_STORAGE_MAX do | 
| yellowfive@57 | 211 				local itemId = GetVoidItemInfo(page, i) | 
| yellowfive@57 | 212 				if itemId then | 
| yellowfive@57 | 213 					local itemLink = GetVoidItemHyperlinkString(((page - 1) * VOID_STORAGE_MAX) + i); | 
| yellowfive@57 | 214 					if itemLink then | 
| yellowfive@57 | 215 						tinsert(voidItems, itemLink) | 
| yellowfive@57 | 216 					end | 
| yellowfive@57 | 217 				end | 
| yellowfive@57 | 218 			end | 
| yellowfive@57 | 219 		end | 
| yellowfive@57 | 220 | 
| yellowfive@57 | 221 		Amr.db.char.VoidItems = voidItems | 
| yellowfive@57 | 222 	end | 
| yellowfive@57 | 223 | 
| yellowfive@57 | 224 end | 
| yellowfive@57 | 225 | 
| yellowfive@57 | 226 local function getRepStanding(factionId) | 
| yellowfive@57 | 227     local name, description, standingId, _ = GetFactionInfoByID(factionId) | 
| yellowfive@57 | 228     return standingId - 1; -- our rep enum correspond to what the armory returns, are 1 less than what the game returns | 
| yellowfive@57 | 229 end | 
| yellowfive@57 | 230 | 
| yellowfive@57 | 231 local function getReputations() | 
| yellowfive@57 | 232     local reps = {} | 
| yellowfive@57 | 233 | 
| yellowfive@57 | 234     local repList = {1375,1376,1270,1269,1341,1337,1387,1388,1435} | 
| yellowfive@57 | 235     for i, repId in pairs(repList) do | 
| yellowfive@57 | 236         local standing = getRepStanding(repId) | 
| yellowfive@57 | 237         if standing >= 0 then | 
| yellowfive@57 | 238             reps[repId] = standing | 
| yellowfive@57 | 239         end | 
| yellowfive@57 | 240     end | 
| yellowfive@57 | 241 | 
| yellowfive@57 | 242     return reps | 
| yellowfive@57 | 243 end | 
| yellowfive@57 | 244 | 
| yellowfive@81 | 245 local function scanTalents() | 
| yellowfive@81 | 246 	local specPos = GetSpecialization() | 
| yellowfive@81 | 247 	if not specPos or specPos < 1 or specPos > 4 then return end | 
| yellowfive@81 | 248 | 
| yellowfive@81 | 249 	local talentInfo = {} | 
| yellowfive@81 | 250     local maxTiers = 7 | 
| yellowfive@81 | 251     for tier = 1, maxTiers do | 
| yellowfive@81 | 252         for col = 1, 3 do | 
| yellowfive@81 | 253             local id, name, _, _, _, spellId, _, t, c, selected = GetTalentInfoBySpecialization(specPos, tier, col) | 
| yellowfive@81 | 254             if selected then | 
| yellowfive@81 | 255                 talentInfo[tier] = col | 
| yellowfive@81 | 256             end | 
| yellowfive@81 | 257         end | 
| yellowfive@81 | 258     end | 
| yellowfive@81 | 259 | 
| yellowfive@81 | 260     local str = "" | 
| yellowfive@81 | 261     for i = 1, maxTiers do | 
| yellowfive@81 | 262     	if talentInfo[i] then | 
| yellowfive@81 | 263     		str = str .. talentInfo[i] | 
| yellowfive@81 | 264     	else | 
| yellowfive@81 | 265     		str = str .. '0' | 
| yellowfive@81 | 266     	end | 
| yellowfive@81 | 267     end | 
| yellowfive@81 | 268 | 
| yellowfive@81 | 269 	Amr.db.char.Talents[specPos] = str | 
| yellowfive@81 | 270 end | 
| yellowfive@81 | 271 | 
| yellowfive@112 | 272 local function scanCrucible() | 
| yellowfive@112 | 273 	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 | 
| yellowfive@112 | 274 | 
| yellowfive@112 | 275 	local equipped = {} | 
| yellowfive@112 | 276 	local preview = nil | 
| yellowfive@112 | 277 | 
| yellowfive@112 | 278 	for i = 1,4 do | 
| yellowfive@112 | 279 		local talents = nil | 
| yellowfive@112 | 280 		if i == 4 then | 
| yellowfive@112 | 281 			talents = C_ArtifactRelicForgeUI.GetPreviewRelicTalents() | 
| yellowfive@112 | 282 			--talents = nil | 
| yellowfive@112 | 283 		else | 
| yellowfive@112 | 284 			talents = C_ArtifactRelicForgeUI.GetSocketedRelicTalents(i) | 
| yellowfive@112 | 285 | 
| yellowfive@112 | 286 			--[[ | 
| yellowfive@114 | 287 			-- test data | 
| yellowfive@112 | 288 			if i == 1 then | 
| yellowfive@112 | 289 				talents = {} | 
| yellowfive@112 | 290 				table.insert(talents, { | 
| yellowfive@112 | 291 					powerID = 1739, | 
| yellowfive@112 | 292 					isChosen = true | 
| yellowfive@112 | 293 				}) | 
| yellowfive@112 | 294 				table.insert(talents, { | 
| yellowfive@112 | 295 					powerID = 1781, | 
| yellowfive@112 | 296 					isChosen = true | 
| yellowfive@112 | 297 				}) | 
| yellowfive@112 | 298 				table.insert(talents, { | 
| yellowfive@112 | 299 					powerID = 1770, | 
| yellowfive@112 | 300 					isChosen = false | 
| yellowfive@112 | 301 				}) | 
| yellowfive@112 | 302 				table.insert(talents, { | 
| yellowfive@112 | 303 					powerID = 791, | 
| yellowfive@112 | 304 					isChosen = false | 
| yellowfive@112 | 305 				}) | 
| yellowfive@112 | 306 				table.insert(talents, { | 
| yellowfive@112 | 307 					powerID = 786, | 
| yellowfive@112 | 308 					isChosen = false | 
| yellowfive@112 | 309 				}) | 
| yellowfive@112 | 310 				table.insert(talents, { | 
| yellowfive@112 | 311 					powerID = 1537, | 
| yellowfive@112 | 312 					isChosen = false | 
| yellowfive@112 | 313 				}) | 
| yellowfive@112 | 314 			end | 
| yellowfive@112 | 315 			]] | 
| yellowfive@112 | 316 		end | 
| yellowfive@112 | 317 | 
| yellowfive@112 | 318 		if talents then | 
| yellowfive@112 | 319 			local obj = { | 
| yellowfive@112 | 320 				Powers = {}, | 
| yellowfive@112 | 321 				Active = {} | 
| yellowfive@112 | 322 			} | 
| yellowfive@112 | 323 | 
| yellowfive@112 | 324 			if i == 4 then | 
| yellowfive@112 | 325 				obj.ItemLink = C_ArtifactRelicForgeUI.GetPreviewRelicItemLink() | 
| yellowfive@112 | 326 				if not obj.ItemLink then | 
| yellowfive@112 | 327 					talents = nil | 
| yellowfive@112 | 328 				else | 
| yellowfive@112 | 329 					preview = obj | 
| yellowfive@112 | 330 				end | 
| yellowfive@112 | 331 			else | 
| yellowfive@112 | 332 				table.insert(equipped, obj) | 
| yellowfive@112 | 333 			end | 
| yellowfive@112 | 334 | 
| yellowfive@112 | 335 			if talents then | 
| yellowfive@112 | 336 				for k,v in ipairs(talents) do | 
| yellowfive@112 | 337 					table.insert(obj.Powers, v.powerID) | 
| yellowfive@112 | 338 					table.insert(obj.Active, v.isChosen) | 
| yellowfive@112 | 339 				end | 
| yellowfive@112 | 340 			end | 
| yellowfive@112 | 341 | 
| yellowfive@112 | 342 		elseif i ~= 4 then | 
| yellowfive@112 | 343 			table.insert(equipped, {}) | 
| yellowfive@112 | 344 		end | 
| yellowfive@112 | 345 	end | 
| yellowfive@112 | 346 | 
| yellowfive@112 | 347 | 
| yellowfive@112 | 348 	local itemID = C_ArtifactUI.GetArtifactInfo() | 
| yellowfive@112 | 349 	local spec = Amr.ArtifactIdToSpecNumber[itemID] | 
| yellowfive@112 | 350 | 
| yellowfive@112 | 351 	if spec then | 
| yellowfive@112 | 352 | 
| yellowfive@112 | 353 		-- sometimes this event can fire when no crucible data is available, don't overwrite non-blank crucible data with blank crucible data | 
| yellowfive@118 | 354 		local badEquipped = false | 
| yellowfive@112 | 355 		if Amr.db.char.Artifacts[spec] then | 
| yellowfive@112 | 356 			local oldCrucible = Amr.db.char.Artifacts[spec].Crucible | 
| yellowfive@112 | 357 			if oldCrucible then | 
| yellowfive@112 | 358 				if #oldCrucible.Equipped > 0 and oldCrucible.Equipped[1] and not equipped[1] then | 
| yellowfive@118 | 359 					badEquipped = true | 
| yellowfive@112 | 360 				end | 
| yellowfive@112 | 361 			end | 
| yellowfive@112 | 362 		end | 
| yellowfive@112 | 363 | 
| yellowfive@112 | 364 		local dataz = Amr.db.char.Artifacts[spec] | 
| yellowfive@112 | 365 		if not dataz then | 
| yellowfive@112 | 366 			dataz = {} | 
| yellowfive@112 | 367 			Amr.db.char.Artifacts[spec] = dataz | 
| yellowfive@112 | 368 		end | 
| yellowfive@112 | 369 | 
| yellowfive@112 | 370 		if not dataz.Crucible then | 
| yellowfive@112 | 371 			dataz.Crucible = { | 
| yellowfive@112 | 372 				Equipped = {}, | 
| yellowfive@114 | 373 				Previewed = {} | 
| yellowfive@112 | 374 			} | 
| yellowfive@112 | 375 		end | 
| yellowfive@112 | 376 | 
| yellowfive@112 | 377 		local crucible = dataz.Crucible | 
| yellowfive@118 | 378 | 
| yellowfive@118 | 379 		if not badEquipped then | 
| yellowfive@118 | 380 			crucible.Equipped = equipped | 
| yellowfive@118 | 381 		end | 
| yellowfive@118 | 382 | 
| yellowfive@112 | 383 		if preview then | 
| yellowfive@114 | 384 			local previewKey = {} | 
| yellowfive@114 | 385 			table.insert(previewKey, preview.ItemLink) | 
| yellowfive@114 | 386 			for i,v in ipairs(preview.Powers) do | 
| yellowfive@114 | 387 				table.insert(previewKey, v .. "=" .. tostring(preview.Active[i])) | 
| yellowfive@114 | 388 			end | 
| yellowfive@114 | 389 			previewKey = table.concat(previewKey, "_") | 
| yellowfive@114 | 390 | 
| yellowfive@116 | 391 			if not crucible.Previewed then | 
| yellowfive@116 | 392 				crucible.Previewed = {} | 
| yellowfive@116 | 393 			end | 
| yellowfive@114 | 394 			crucible.Previewed[previewKey] = preview | 
| yellowfive@112 | 395 		end | 
| yellowfive@112 | 396 	end | 
| yellowfive@112 | 397 end | 
| yellowfive@112 | 398 | 
| yellowfive@114 | 399 local function pruneCrucible() | 
| yellowfive@114 | 400 	if not Amr.db or not Amr.db.char or not Amr.db.char.Artifacts then return end | 
| yellowfive@114 | 401 | 
| yellowfive@114 | 402 	local spec = GetSpecialization() | 
| yellowfive@114 | 403 	local dataz = Amr.db.char.Artifacts[spec] | 
| yellowfive@114 | 404 	if not dataz or not dataz.Crucible then return end | 
| yellowfive@114 | 405 | 
| yellowfive@114 | 406 	local crucible = dataz.Crucible | 
| yellowfive@114 | 407 | 
| yellowfive@114 | 408 	-- this was old format, transform to new format | 
| yellowfive@114 | 409 	if crucible.Inventory then | 
| yellowfive@114 | 410 		if not crucible.Previewed then | 
| yellowfive@114 | 411 			crucible.Previewed = {} | 
| yellowfive@114 | 412 		end | 
| yellowfive@114 | 413 | 
| yellowfive@114 | 414 		for link,preview in pairs(crucible.Inventory) do | 
| yellowfive@114 | 415 			local previewKey = {} | 
| yellowfive@114 | 416 			table.insert(previewKey, preview.ItemLink) | 
| yellowfive@114 | 417 			for i,v in ipairs(preview.Powers) do | 
| yellowfive@114 | 418 				table.insert(previewKey, v .. "=" .. tostring(preview.Active[i])) | 
| yellowfive@114 | 419 			end | 
| yellowfive@114 | 420 			previewKey = table.concat(previewKey, "_") | 
| yellowfive@114 | 421 | 
| yellowfive@114 | 422 			crucible.Previewed[previewKey] = preview | 
| yellowfive@114 | 423 		end | 
| yellowfive@114 | 424 | 
| yellowfive@114 | 425 		crucible.Inventory = nil | 
| yellowfive@114 | 426 	end | 
| yellowfive@114 | 427 | 
| yellowfive@114 | 428 	-- get a hash of every owned, but not-equipped item | 
| yellowfive@114 | 429 	local ownedItems = {} | 
| yellowfive@114 | 430 	if Amr.db.char.BagItems then | 
| yellowfive@114 | 431 		for i,link in ipairs(Amr.db.char.BagItems) do | 
| yellowfive@114 | 432 			ownedItems[link] = true | 
| yellowfive@114 | 433 		end | 
| yellowfive@114 | 434 	end | 
| yellowfive@114 | 435 	if Amr.db.char.BankItems then | 
| yellowfive@114 | 436 		for i,link in ipairs(Amr.db.char.BankItems) do | 
| yellowfive@114 | 437 			ownedItems[link] = true | 
| yellowfive@114 | 438 		end | 
| yellowfive@114 | 439 	end | 
| yellowfive@114 | 440 	if Amr.db.char.VoidItems then | 
| yellowfive@114 | 441 		for i,link in ipairs(Amr.db.char.VoidItems) do | 
| yellowfive@114 | 442 			ownedItems[link] = true | 
| yellowfive@114 | 443 		end | 
| yellowfive@114 | 444 	end | 
| yellowfive@114 | 445 | 
| yellowfive@114 | 446 	-- prune out any previewed relics that the player no longer owns | 
| yellowfive@114 | 447 	if crucible.Previewed then | 
| yellowfive@114 | 448 		local toRemove = {} | 
| yellowfive@114 | 449 		for k,v in pairs(crucible.Previewed) do | 
| yellowfive@114 | 450 			if not ownedItems[v.ItemLink] then | 
| yellowfive@114 | 451 				table.insert(toRemove, k) | 
| yellowfive@114 | 452 			end | 
| yellowfive@114 | 453 		end | 
| yellowfive@114 | 454 		for i,v in ipairs(toRemove) do | 
| yellowfive@114 | 455 			crucible.Previewed[v] = nil | 
| yellowfive@114 | 456 		end | 
| yellowfive@114 | 457 	end | 
| yellowfive@114 | 458 | 
| yellowfive@114 | 459 end | 
| yellowfive@114 | 460 | 
| yellowfive@81 | 461 local function scanArtifact() | 
| yellowfive@91 | 462 	if not Amr.db or not Amr.db.char or not Amr.db.char.Artifacts then return end | 
| yellowfive@91 | 463 | 
| yellowfive@81 | 464 	local powers = C_ArtifactUI.GetPowers() | 
| yellowfive@81 | 465 	if not powers then return end | 
| yellowfive@81 | 466 | 
| yellowfive@81 | 467 	local powerRanks = {} | 
| yellowfive@81 | 468 	for k,v in pairs(powers) do | 
| yellowfive@106 | 469 		local powerInfo = C_ArtifactUI.GetPowerInfo(v) | 
| yellowfive@106 | 470 		if powerInfo.currentRank - powerInfo.bonusRanks > 0 then | 
| yellowfive@106 | 471 			powerRanks[v] = powerInfo.currentRank - powerInfo.bonusRanks | 
| yellowfive@81 | 472 		end | 
| yellowfive@81 | 473 	end | 
| yellowfive@81 | 474 | 
| yellowfive@81 | 475 	local relicInfo = {} | 
| yellowfive@81 | 476 	for i = 1,3 do | 
| yellowfive@81 | 477 		local _, _, _, link = C_ArtifactUI.GetRelicInfo(i); | 
| yellowfive@81 | 478 		table.insert(relicInfo, link or "") | 
| yellowfive@81 | 479 	end | 
| yellowfive@81 | 480 | 
| yellowfive@81 | 481 	-- make sure that the artifact UI didn't get closed while we were reading it, GetPowers seems to return nil unless it is open | 
| yellowfive@81 | 482 	powers = C_ArtifactUI.GetPowers() | 
| yellowfive@81 | 483 	if not powers then return end | 
| yellowfive@81 | 484 | 
| yellowfive@89 | 485 	-- use the artifact item ID to figure out which spec this is for, since you can open your artifact on any spec | 
| yellowfive@91 | 486 	local itemID = C_ArtifactUI.GetArtifactInfo() | 
| yellowfive@89 | 487 	local spec = Amr.ArtifactIdToSpecNumber[itemID] | 
| yellowfive@89 | 488 	--local spec = GetSpecialization() | 
| yellowfive@89 | 489 | 
| yellowfive@91 | 490 	if spec then | 
| yellowfive@112 | 491 | 
| yellowfive@112 | 492 		-- sometimes this event can fire when no relic data is available, don't overwrite non-blank relic data with blank relic data | 
| yellowfive@112 | 493 		if Amr.db.char.Artifacts[spec] then | 
| yellowfive@112 | 494 			local oldRelics = Amr.db.char.Artifacts[spec].Relics | 
| yellowfive@112 | 495 			if oldRelics then | 
| yellowfive@112 | 496 				for i = 1,3 do | 
| yellowfive@112 | 497 					if oldRelics[i] and oldRelics[i] ~= "" and (not relicInfo[i] or relicInfo[i] == "") then | 
| yellowfive@112 | 498 						relicInfo[i] = oldRelics[i] | 
| yellowfive@112 | 499 					end | 
| yellowfive@112 | 500 				end | 
| yellowfive@112 | 501 			end | 
| yellowfive@112 | 502 		end | 
| yellowfive@112 | 503 | 
| yellowfive@112 | 504 		local dataz = Amr.db.char.Artifacts[spec] | 
| yellowfive@112 | 505 		if not dataz then | 
| yellowfive@112 | 506 			dataz = {} | 
| yellowfive@112 | 507 			Amr.db.char.Artifacts[spec] = dataz | 
| yellowfive@112 | 508 		end | 
| yellowfive@112 | 509 | 
| yellowfive@112 | 510 		if not dataz.Crucible then | 
| yellowfive@112 | 511 			dataz.Crucible = { | 
| yellowfive@112 | 512 				Equipped = {}, | 
| yellowfive@112 | 513 				Inventory = {} | 
| yellowfive@112 | 514 			} | 
| yellowfive@112 | 515 		end | 
| yellowfive@112 | 516 | 
| yellowfive@112 | 517 		dataz.Powers = powerRanks | 
| yellowfive@112 | 518 		dataz.Relics = relicInfo | 
| yellowfive@112 | 519 | 
| yellowfive@91 | 520 	end | 
| yellowfive@112 | 521 | 
| yellowfive@112 | 522 	--scanCrucible() | 
| yellowfive@81 | 523 end | 
| yellowfive@81 | 524 | 
| yellowfive@57 | 525 -- Returns a data object containing all information about the current player needed for an export: | 
| yellowfive@57 | 526 -- gear, spec, reputations, bag, bank, and void storage items. | 
| yellowfive@57 | 527 function Amr:ExportCharacter() | 
| yellowfive@57 | 528 | 
| yellowfive@57 | 529 	local data = getEquipped() | 
| yellowfive@57 | 530 	scanBags() | 
| yellowfive@57 | 531 | 
| yellowfive@81 | 532 	-- scan current spec's talents just before exporting | 
| yellowfive@81 | 533 	scanTalents() | 
| yellowfive@81 | 534 | 
| yellowfive@114 | 535 	-- prune crucible info just before each time we export | 
| yellowfive@114 | 536 	pruneCrucible() | 
| yellowfive@114 | 537 | 
| yellowfive@81 | 538 	data.Talents = Amr.db.char.Talents | 
| yellowfive@81 | 539 	data.Artifacts = Amr.db.char.Artifacts | 
| yellowfive@57 | 540 	data.Equipped = Amr.db.char.Equipped | 
| yellowfive@57 | 541 	data.Reputations = getReputations() | 
| yellowfive@57 | 542 	data.BagItems = Amr.db.char.BagItems | 
| yellowfive@57 | 543 	data.BankItems = Amr.db.char.BankItems | 
| yellowfive@57 | 544 	data.VoidItems = Amr.db.char.VoidItems | 
| yellowfive@57 | 545 | 
| yellowfive@57 | 546 	return data | 
| yellowfive@57 | 547 end | 
| yellowfive@57 | 548 | 
| yellowfive@57 | 549 function Amr:InitializeExport() | 
| yellowfive@57 | 550 	Amr:AddEventHandler("UNIT_INVENTORY_CHANGED", function(unitID) | 
| yellowfive@57 | 551 		if unitID and unitID ~= "player" then return end | 
| yellowfive@57 | 552 		getEquipped() | 
| yellowfive@57 | 553 	end) | 
| yellowfive@57 | 554 end | 
| yellowfive@57 | 555 | 
| yellowfive@57 | 556 Amr:AddEventHandler("BANKFRAME_OPENED", scanBank) | 
| yellowfive@57 | 557 Amr:AddEventHandler("PLAYERBANKSLOTS_CHANGED", scanBank) | 
| yellowfive@57 | 558 | 
| yellowfive@57 | 559 Amr:AddEventHandler("VOID_STORAGE_OPEN", scanVoid) | 
| yellowfive@57 | 560 Amr:AddEventHandler("VOID_STORAGE_CONTENTS_UPDATE", scanVoid) | 
| yellowfive@57 | 561 Amr:AddEventHandler("VOID_STORAGE_DEPOSIT_UPDATE", scanVoid) | 
| yellowfive@57 | 562 Amr:AddEventHandler("VOID_STORAGE_UPDATE", scanVoid) | 
| yellowfive@81 | 563 | 
| yellowfive@81 | 564 Amr:AddEventHandler("PLAYER_TALENT_UPDATE", scanTalents) | 
| yellowfive@81 | 565 Amr:AddEventHandler("ARTIFACT_UPDATE", scanArtifact) | 
| yellowfive@112 | 566 Amr:AddEventHandler("ARTIFACT_RELIC_FORGE_UPDATE", scanCrucible) | 
| yellowfive@112 | 567 Amr:AddEventHandler("ARTIFACT_RELIC_FORGE_PREVIEW_RELIC_CHANGED", scanCrucible) |