From 63efdfe2a232110857d2716a23ca15183cbd5f54 Mon Sep 17 00:00:00 2001 From: "Nathanial.C.Jones" Date: Thu, 31 Jan 2013 01:27:10 +0000 Subject: [PATCH] Modified collect.lua Put all session info into a tab delimited string containing, in order, svnversion (QH build), realm, buildInfo (WoW version), locale and faction. This string is inserted into a sub-table of QuestHelper_Collector called sessions, with a key of session time. Put all data into a sub-table of QuestHelper_Collector called data. Creates session data table on the new data sub-table and sets the key to session time. QH_Collector_SetupData now returns QuestHelper_Collector.data[sessiontime] Changed Collector Current Version to 9... This might be useful for future changes to data layout. Modified collect_location Made BolusizeLocation accept the right arguments. Calculated the distance from either Azeroth map center or Outland map center to the provided point for inclusion. (See comments in code for what is collected and why.) Converted the information into a string. If we couldn't compute a distance to either map center, we leave it out for now, since we are probably in an instance. --- QuestHelper/collect.lua | 624 +++++++++++++++---------------- QuestHelper/collect_location.lua | 56 ++- 2 files changed, 341 insertions(+), 339 deletions(-) diff --git a/QuestHelper/collect.lua b/QuestHelper/collect.lua index ce7d938..737dfb0 100644 --- a/QuestHelper/collect.lua +++ b/QuestHelper/collect.lua @@ -1,321 +1,303 @@ - -local GetTime = QuestHelper_GetTime - -QuestHelper_File["collect.lua"] = "4.0.1.$svnversion$" -QuestHelper_Loadtime["collect.lua"] = GetTime() - -local --[[ static ]] MINSVNVERSION = 255 -local --[[ static ]] PURGEDEV = true -local debug_output = false -if QuestHelper_File["collect.lua"] == "Development Version" then debug_output = true end - -local QuestHelper_Collector_Version_Current = 8 - -QuestHelper_Collector = {} -QuestHelper_Collector_Version = QuestHelper_Collector_Version_Current - -local OnUpdateRegistrar = {} -local TooltipRegistrar = {} - -local function OnUpdateHookRegistrar(func) - QuestHelper: Assert(func) - table.insert(OnUpdateRegistrar, func) -end - -local suppress = false - - -- real tooltips don't use this function -local SetTextScript = GameTooltip.SetText -GameTooltip.SetText = function (...) - suppress = true - SetTextScript(...) - suppress = false -end - -local function CollectTooltippery(self) - if not self then self = GameTooltip end - - for k, v in pairs(TooltipRegistrar) do - v(self) - end - - -- anything past here is not my fault -end - -local ottsu = GameTooltip:GetScript("OnTooltipSetUnit") -QH_Hook(GameTooltip, "OnTooltipSetUnit", function (self, ...) - CollectTooltippery(self) - if ottsu then return QH_Hook_NotMyFault(ottsu, self, ...) end -end, "collection OnTooltipSetUnit") - -local ottsi = GameTooltip:GetScript("OnTooltipSetItem") -QH_Hook(GameTooltip, "OnTooltipSetItem", function (self, ...) - CollectTooltippery(self) - if ottsi then return QH_Hook_NotMyFault(ottsi, self, ...) end -end, "collection OnTooltipSetItem") - -local ottsh = GameTooltip:GetScript("OnShow") -QH_Hook(GameTooltip, "OnShow", function (self, ...) - CollectTooltippery(self) - if ottsh then return QH_Hook_NotMyFault(ottsh, self, ...) end -end, "collection OnShow") - - -local function TooltipHookRegistrar(func) - QuestHelper: Assert(func) - table.insert(TooltipRegistrar, func) -end - -local API = { - Registrar_OnUpdateHook = OnUpdateHookRegistrar, - Registrar_TooltipHook = TooltipHookRegistrar, - Callback_Location_Raw = function () return QuestHelper:Location_RawRetrieve() end, - Callback_Location_Absolute = function () return QuestHelper:Location_AbsoluteRetrieve() end, -} - --- We do these early, because some things that aren't in collect may rely on these. Yes I realize that avoiding this was one of my main goals in the separate collect system, shut up go away I hate you (in all seriousness: crunch mode + lazy = some nasty bits.) --- TODO: Make a common collect/mainmodule system, then rely on that better. -QH_Collect_Util_Init(nil, API) -- Some may actually add their own functions to the API, and should go first. There's no real formalized order, I just know which depend on others, and it's heavily asserted so it will break if it goes in the wrong order. -QH_Collect_Merger_Init(nil, API) -QH_Collect_Bitstream_Init(nil, API) -QH_Collect_Location_Init(nil, API) -QH_Collect_Patterns_Init(nil, API) -QH_Collect_Notifier_Init(nil, API) -QH_Collect_Spec_Init(nil, API) -QH_Collect_LZW_Init(nil, API) - -local CompressCollection - -function QH_Collector_SetupData() - local svnversion = "$svnversion$" - local buildInfo, locale, faction = GetBuildInfo(), GetLocale(), QuestHelper:PlayerFaction() - local altfaction = "" - if faction == "Alliance" then - altfaction = "Alliance" - elseif faction == "Horde" then - altfaction = "Horde" - else - altfaction = "Neutral" - end - local realm = GetRealmName() - - if not QuestHelper_Collector.created then - QuestHelper_Collector.created = time(); - end - - -- Swap buildInfo and svnversion once first alteration is complete. - -- Perhaps move locale out of the "signature" - if not QuestHelper_Collector[svnversion] then - QuestHelper_Collector[svnversion] = {} - end - - if not QuestHelper_Collector[svnversion][realm] then - QuestHelper_Collector[svnversion][realm] = {} - end - - if not QuestHelper_Collector[svnversion][realm][buildInfo] then - QuestHelper_Collector[svnversion][realm][buildInfo] = {} - end - - if not QuestHelper_Collector[svnversion][realm][buildInfo][locale] then - QuestHelper_Collector[svnversion][realm][buildInfo][locale] = {} - end - - if not QuestHelper_Collector[svnversion][realm][buildInfo][locale][altfaction] then - QuestHelper_Collector[svnversion][realm][buildInfo][locale][altfaction] = {} - end - - local sessiontime = time() - if not QuestHelper_Collector[svnversion][realm][buildInfo][locale][altfaction][sessiontime] then - QuestHelper_Collector[svnversion][realm][buildInfo][locale][altfaction][sessiontime] = {} - end - - --if not QuestHelper_Collector[sig] or QuestHelper_Collector[sig].compressed then QuestHelper_Collector[sig] = {version = QuestHelper_Collector_Version} end -- fuckin' bullshit, man - return QuestHelper_Collector[svnversion][realm][buildInfo][locale][altfaction][sessiontime] -end - -function QH_Collector_FactionChange() - local QHCData = QH_Collector_SetupData() - - QH_Collect_Achievement_FactionChange(QHCData, API) - QH_Collect_Zone_FactionChange(QHCData, API) - QH_Collect_Hearth_FactionChange(QHCData, API) - QH_Collect_Monster_FactionChange(QHCData, API) - QH_Collect_Item_FactionChange(QHCData, API) - QH_Collect_Object_FactionChange(QHCData, API) - QH_Collect_Flight_FactionChange(QHCData, API) - QH_Collect_Quest_FactionChange(QHCData, API) - QH_Collect_Warp_FactionChange(QHCData, API) -end - -function QH_Collector_Init() - -- Dunno why, but these statements cause the 1% issue. - --[[ - QH_Collector_UpgradeAll(QuestHelper_Collector) - - for _, v in pairs(QuestHelper_Collector) do - if not v.modified then v.modified = time() - 7 * 24 * 60 * 60 end -- eugh. Yeah, we set it to be a week ago. It's pretty grim. - end - --]] - QuestHelper_Collector_Version = QuestHelper_Collector_Version_Current - - local remove_sigs = {} - for k, v in pairs(QuestHelper_Collector) do - local sig = k:match("^(%d)a$") or k:match("^(%d)b$") or k:match("^(%d)r$") - if sig then - if tonumber(sig) < MINSVNVERSION then - table.insert(remove_sigs, sig) - end - elseif k ~= svnversion then - table.insert(remove_sigs, k) - elseif k == "$svnversion\$" and PURGEDEV then - table.insert(remove_sigs, k) - end - end - - for _, v in ipairs(remove_sigs) do - QuestHelper_Collector[v] = nil - end - - local QHCData = QH_Collector_SetupData() - QuestHelper: Assert(not QHCData.compressed) - - - QH_Collect_Achievement_Init(QHCData, API) - QH_Collect_Traveled_Init(QHCData, API) - QH_Collect_Zone_Init(QHCData, API) - QH_Collect_Hearth_Init(QHCData, API) - QH_Collect_Monster_Init(QHCData, API) - QH_Collect_Item_Init(QHCData, API) - QH_Collect_Object_Init(QHCData, API) - QH_Collect_Flight_Init(QHCData, API) - QH_Collect_Quest_Init(QHCData, API) - QH_Collect_Warp_Init(QHCData, API) - - QH_Collect_Loot_Init(QHCData, API) - QH_Collect_Equip_Init(QHCData, API) - QH_Collect_Merchant_Init(QHCData, API) - - if false then -- this will be disabled in most public releases, or set to a very rare probabalistic thing - if not QHCData.routing_dump then QHCData.routing_dump = {} end - local nt = {} - table.insert(QHCData.routing_dump, nt) - QH_Collect_Routing_Dump = nt - end - - -- So, why do we delay it? - -- It's simple. People are gonna update to this version, and then they're going to look at the memory usage. Then they will panic because omg this version uses so much more memory, I bet that will somehow hurt my framerates in a way which is not adequately explained! - -- So instead, we just wait half an hour before compressing. Compression will still get done, and I won't have to deal with panicked comments about how bloated QH has gotten. - -- addendum: yeah naturally I'm getting all sorts of panicked comments about how bloated qh has gotten, sigh - --API.Utility_Notifier(GetTime() + (debug_output and 0 or (30 * 60)), function() CompressCollection(QHCData, QuestHelper_Collector[sig_altfaction], API.Utility_Merger, API.Utility_LZW.Compress) end) - QH_Event("NEUTRAL_FACTION_SELECT_RESULT", QH_Collector_FactionChange) -end - -QH_OnUpdate(function () - local tstart = GetTime() - for _, v in pairs(OnUpdateRegistrar) do - v() - end - QH_Timeslice_Increment(GetTime() - tstart, "collect_update") -end) - - - ---- I've tossed the compression stuff down here just 'cause I don't feel like making an entire file for it (even though I probably should.) - -local noncompressible = { - modified = true, - version = true, -} - -local squarify - -local seritem - -local serializers = { - ["nil"] = function(item, add) - add("nil") - end, - ["number"] = function(item, add) - add(tostring(item)) - end, - ["string"] = function(item, add) - add(string.format("%q", item)) - end, - ["boolean"] = function(item, add) - add(item and "true" or "false") - end, - ["table"] = function(item, add) - add("{") - local first = true - for k, v in pairs(item) do - if not first then add(",") end - first = false - add("[") - seritem(k, add) - add("]=") - seritem(v, add) - end - add("}") - end, -} - -seritem = function(item, add) - QH_Timeslice_Yield() - serializers[type(item)](item, add) -end - -local function DoCompress(item, merger, comp) - if debug_output then QuestHelper: TextOut("Item condensing") end - local ts = GetTime() - - local target = {} - for k, v in pairs(item) do - if not noncompressible[k] then - target[k] = v - end - end - - local mg = {} - seritem(target, function(dat) merger.Add(mg, dat) end) - - local tg = merger.Finish(mg) - if debug_output then QuestHelper: TextOut(string.format("Item condensed to %d bytes, %f taken so far", #tg, GetTime() - ts)) end - mg = nil - - local cmp = {} - local cmptot = 0 - - local doublecheck = "" - for chunk = 1, #tg, 1048576 do - local fragment = tg:sub(chunk, chunk + 1048575) - doublecheck = doublecheck .. fragment - local ite = comp(fragment, 256, 8) - cmptot = cmptot + #ite - table.insert(cmp, ite) - end - QuestHelper: Assert(doublecheck == tg) - - if #cmp == 1 then cmp = cmp[1] end - - for k, v in pairs(target) do - if not noncompressible[k] then - item[k] = nil - end - end - item.compressed = cmp - - if debug_output then QuestHelper: TextOut(string.format("Item compressed to %d bytes in %d shards (previously %d), %f taken", cmptot, type(cmp) == "table" and #cmp or 1, #tg, GetTime() - ts)) end -end - -CompressCollection = function(active, active2, merger, comp) - for _, v in pairs(QuestHelper_Collector) do - if v ~= active and v ~= active2 and not v.compressed then - QH_Timeslice_Add(function () - DoCompress(v, merger, comp) - CompressCollection(active, active2, merger, comp) - end, "compress") - break - end - end -end + +local GetTime = QuestHelper_GetTime + +QuestHelper_File["collect.lua"] = "4.0.1.$svnversion$" +QuestHelper_Loadtime["collect.lua"] = GetTime() + +local --[[ static ]] MINSVNVERSION = 283 +local --[[ static ]] PURGEDEV = true +local debug_output = false +if QuestHelper_File["collect.lua"] == "Development Version" then debug_output = true end + +local QuestHelper_Collector_Version_Current = 9 + +QuestHelper_Collector = {} +QuestHelper_Collector_Version = QuestHelper_Collector_Version_Current + +local OnUpdateRegistrar = {} +local TooltipRegistrar = {} + +local function OnUpdateHookRegistrar(func) + QuestHelper: Assert(func) + table.insert(OnUpdateRegistrar, func) +end + +local suppress = false + + -- real tooltips don't use this function +local SetTextScript = GameTooltip.SetText +GameTooltip.SetText = function (...) + suppress = true + SetTextScript(...) + suppress = false +end + +local function CollectTooltippery(self) + if not self then self = GameTooltip end + + for k, v in pairs(TooltipRegistrar) do + v(self) + end + + -- anything past here is not my fault +end + +local ottsu = GameTooltip:GetScript("OnTooltipSetUnit") +QH_Hook(GameTooltip, "OnTooltipSetUnit", function (self, ...) + CollectTooltippery(self) + if ottsu then return QH_Hook_NotMyFault(ottsu, self, ...) end +end, "collection OnTooltipSetUnit") + +local ottsi = GameTooltip:GetScript("OnTooltipSetItem") +QH_Hook(GameTooltip, "OnTooltipSetItem", function (self, ...) + CollectTooltippery(self) + if ottsi then return QH_Hook_NotMyFault(ottsi, self, ...) end +end, "collection OnTooltipSetItem") + +local ottsh = GameTooltip:GetScript("OnShow") +QH_Hook(GameTooltip, "OnShow", function (self, ...) + CollectTooltippery(self) + if ottsh then return QH_Hook_NotMyFault(ottsh, self, ...) end +end, "collection OnShow") + + +local function TooltipHookRegistrar(func) + QuestHelper: Assert(func) + table.insert(TooltipRegistrar, func) +end + +local API = { + Registrar_OnUpdateHook = OnUpdateHookRegistrar, + Registrar_TooltipHook = TooltipHookRegistrar, + Callback_Location_Raw = function () return QuestHelper:Location_RawRetrieve() end, + Callback_Location_Absolute = function () return QuestHelper:Location_AbsoluteRetrieve() end, +} + +-- We do these early, because some things that aren't in collect may rely on these. Yes I realize that avoiding this was one of my main goals in the separate collect system, shut up go away I hate you (in all seriousness: crunch mode + lazy = some nasty bits.) +-- TODO: Make a common collect/mainmodule system, then rely on that better. +QH_Collect_Util_Init(nil, API) -- Some may actually add their own functions to the API, and should go first. There's no real formalized order, I just know which depend on others, and it's heavily asserted so it will break if it goes in the wrong order. +QH_Collect_Merger_Init(nil, API) +QH_Collect_Bitstream_Init(nil, API) +QH_Collect_Location_Init(nil, API) +QH_Collect_Patterns_Init(nil, API) +QH_Collect_Notifier_Init(nil, API) +QH_Collect_Spec_Init(nil, API) +QH_Collect_LZW_Init(nil, API) + +local CompressCollection + +function QH_Collector_SetupData() + local svnversion = "$svnversion$" + local buildInfo, locale, faction = GetBuildInfo(), GetLocale(), QuestHelper:PlayerFaction() + local altfaction = "" + if faction == "Alliance" then + altfaction = "Alliance" + elseif faction == "Horde" then + altfaction = "Horde" + else + altfaction = "Neutral" + end + local realm = GetRealmName() + + if not QuestHelper_Collector.created then + QuestHelper_Collector.created = time(); + end + + local session = string.format("%q\t%q\t%q\t%q\t%q", svnversion, realm, buildInfo, locale, altfaction) + + if not QuestHelper_Collector.sessions then QuestHelper_Collector.sessions = {} end + + QuestHelper_Collector.sessions[sessiontime] = session + + if not QuestHelper_Collector.data then QuestHelper_Collector.data = {} end + + QuestHelper_Collector.data[sessiontime] = {} + + return QuestHelper_Collector.data[sessiontime] +end + +function QH_Collector_FactionChange() + local QHCData = QH_Collector_SetupData() + + QH_Collect_Achievement_FactionChange(QHCData, API) + QH_Collect_Zone_FactionChange(QHCData, API) + QH_Collect_Hearth_FactionChange(QHCData, API) + QH_Collect_Monster_FactionChange(QHCData, API) + QH_Collect_Item_FactionChange(QHCData, API) + QH_Collect_Object_FactionChange(QHCData, API) + QH_Collect_Flight_FactionChange(QHCData, API) + QH_Collect_Quest_FactionChange(QHCData, API) + QH_Collect_Warp_FactionChange(QHCData, API) +end + +function QH_Collector_Init() + -- Dunno why, but these statements cause the 1% issue. + --[[ + QH_Collector_UpgradeAll(QuestHelper_Collector) + + for _, v in pairs(QuestHelper_Collector) do + if not v.modified then v.modified = time() - 7 * 24 * 60 * 60 end -- eugh. Yeah, we set it to be a week ago. It's pretty grim. + end + --]] + QuestHelper_Collector_Version = QuestHelper_Collector_Version_Current + + local remove_sigs = {} + for k, v in pairs(QuestHelper_Collector) do + local sig = k:match("^(%d)a$") or k:match("^(%d)b$") or k:match("^(%d)r$") + if sig then + if tonumber(sig) < MINSVNVERSION then + table.insert(remove_sigs, sig) + end + elseif k ~= svnversion then + table.insert(remove_sigs, k) + elseif k == "$svnversion\$" and PURGEDEV then + table.insert(remove_sigs, k) + end + end + + for _, v in ipairs(remove_sigs) do + QuestHelper_Collector[v] = nil + end + + local QHCData = QH_Collector_SetupData() + QuestHelper: Assert(not QHCData.compressed) + + + QH_Collect_Achievement_Init(QHCData, API) + QH_Collect_Traveled_Init(QHCData, API) + QH_Collect_Zone_Init(QHCData, API) + QH_Collect_Hearth_Init(QHCData, API) + QH_Collect_Monster_Init(QHCData, API) + QH_Collect_Item_Init(QHCData, API) + QH_Collect_Object_Init(QHCData, API) + QH_Collect_Flight_Init(QHCData, API) + QH_Collect_Quest_Init(QHCData, API) + QH_Collect_Warp_Init(QHCData, API) + + QH_Collect_Loot_Init(QHCData, API) + QH_Collect_Equip_Init(QHCData, API) + QH_Collect_Merchant_Init(QHCData, API) + + if false then -- this will be disabled in most public releases, or set to a very rare probabalistic thing + if not QHCData.routing_dump then QHCData.routing_dump = {} end + local nt = {} + table.insert(QHCData.routing_dump, nt) + QH_Collect_Routing_Dump = nt + end + + -- So, why do we delay it? + -- It's simple. People are gonna update to this version, and then they're going to look at the memory usage. Then they will panic because omg this version uses so much more memory, I bet that will somehow hurt my framerates in a way which is not adequately explained! + -- So instead, we just wait half an hour before compressing. Compression will still get done, and I won't have to deal with panicked comments about how bloated QH has gotten. + -- addendum: yeah naturally I'm getting all sorts of panicked comments about how bloated qh has gotten, sigh + --API.Utility_Notifier(GetTime() + (debug_output and 0 or (30 * 60)), function() CompressCollection(QHCData, QuestHelper_Collector[sig_altfaction], API.Utility_Merger, API.Utility_LZW.Compress) end) + QH_Event("NEUTRAL_FACTION_SELECT_RESULT", QH_Collector_FactionChange) +end + +QH_OnUpdate(function () + local tstart = GetTime() + for _, v in pairs(OnUpdateRegistrar) do + v() + end + QH_Timeslice_Increment(GetTime() - tstart, "collect_update") +end) + + + +--- I've tossed the compression stuff down here just 'cause I don't feel like making an entire file for it (even though I probably should.) + +local noncompressible = { + modified = true, + version = true, +} + +local squarify + +local seritem + +local serializers = { + ["nil"] = function(item, add) + add("nil") + end, + ["number"] = function(item, add) + add(tostring(item)) + end, + ["string"] = function(item, add) + add(string.format("%q", item)) + end, + ["boolean"] = function(item, add) + add(item and "true" or "false") + end, + ["table"] = function(item, add) + add("{") + local first = true + for k, v in pairs(item) do + if not first then add(",") end + first = false + add("[") + seritem(k, add) + add("]=") + seritem(v, add) + end + add("}") + end, +} + +seritem = function(item, add) + QH_Timeslice_Yield() + serializers[type(item)](item, add) +end + +local function DoCompress(item, merger, comp) + if debug_output then QuestHelper: TextOut("Item condensing") end + local ts = GetTime() + + local target = {} + for k, v in pairs(item) do + if not noncompressible[k] then + target[k] = v + end + end + + local mg = {} + seritem(target, function(dat) merger.Add(mg, dat) end) + + local tg = merger.Finish(mg) + if debug_output then QuestHelper: TextOut(string.format("Item condensed to %d bytes, %f taken so far", #tg, GetTime() - ts)) end + mg = nil + + local cmp = {} + local cmptot = 0 + + local doublecheck = "" + for chunk = 1, #tg, 1048576 do + local fragment = tg:sub(chunk, chunk + 1048575) + doublecheck = doublecheck .. fragment + local ite = comp(fragment, 256, 8) + cmptot = cmptot + #ite + table.insert(cmp, ite) + end + QuestHelper: Assert(doublecheck == tg) + + if #cmp == 1 then cmp = cmp[1] end + + for k, v in pairs(target) do + if not noncompressible[k] then + item[k] = nil + end + end + item.compressed = cmp + + if debug_output then QuestHelper: TextOut(string.format("Item compressed to %d bytes in %d shards (previously %d), %f taken", cmptot, type(cmp) == "table" and #cmp or 1, #tg, GetTime() - ts)) end +end + +CompressCollection = function(active, active2, merger, comp) + for _, v in pairs(QuestHelper_Collector) do + if v ~= active and v ~= active2 and not v.compressed then + QH_Timeslice_Add(function () + DoCompress(v, merger, comp) + CompressCollection(active, active2, merger, comp) + end, "compress") + break + end + end +end diff --git a/QuestHelper/collect_location.lua b/QuestHelper/collect_location.lua index 853b063..27c7d8e 100644 --- a/QuestHelper/collect_location.lua +++ b/QuestHelper/collect_location.lua @@ -73,24 +73,44 @@ local function float(c) return ret end -local function BolusizeLocation(delayed, c, z, x, y, dl, mid, mf, f) - -- c and z are *signed* integers that fit within an 8-bit int. - -- x and y are floating-point values, generally between 0 and 1. We'll dedicate 24 bits to the fractional part, largely because we can. - -- Overall we're using a weird 11 bytes on this. Meh. - -- Also, any nil values are being turned into MIN_WHATEVER. - local float_x = x - local float_y = y - local loc = {} - --local locStr = (delayed and 1 or 0) .. lgToHex(mid) .. tohex(dl) .. float(x) .. float(y) - loc["delayed"] = (delayed and 1 or 0) - loc["c"] = c - loc["z"] = z - loc["x"] = float_x - loc["y"] = float_y - loc["dungeonLevel"] = dl - loc["mapid"] = mid - loc["mapfile"] = mf - loc["facing"] = f +local function rep_comma(val) + return string.gsub(tostring(val), ",", ".") +end + +local function BolusizeLocation(m, f, x, y) + -- m and f are positive integers. + -- x and y are floating-point values, generally between 0 and 1. We'll convert to string and then replace any "," decimal separator (because it'll be easier later to import on an enUS machine). + local str_x = rep_comma(x) + local str_y = rep_comma(y) + + -- Next, we are going to calculate the distance this point is from either Azeroth 50,50 or Outland 50,50. + -- We will only keep the dx and dy values, since we can compute distance from those (dist = sqrt(dx*dx + dy*dy)). We can also compute a bearing from dx and dy, since we are going relative to (50,50) + -- Said bearing is the inverse tangent of dy/dx, trig people, trig. SOHCAHTOA. I have all three values, so I could use any pair, but dx and dy make the most sense. + -- Of course, the bearing DOES need adjusting, since WoW sets 0 to be north. Normally, angles increase counter-clockwise, WoW does the same... SO, all we'd have to do is add 90 degrees, or pi/2 radians to the result of the inverse tangent. + -- This discourse is of no real consequence, beyond explaining the WHY of collecting dx and dy, rather than just the distance. + local _, dxAz, dyAz = QuestHelper.Astrolabe:ComputeDistance( 0, 0, 0.5, 0.5, m, f, x, y) + local _, dxOl, dyOl = QuestHelper.Astrolabe:ComputeDistance(466, 0, 0.5, 0.5, m, f, x, y) + + local dx_str, dy_str + local dist_rel + if dxAz then + dx_str = rep_comma(dxAz) + dy_str = rep_comma(dyAz) + dist_rel = "A" + elseif dxOl then + dx_str = rep_comma(dxOl) + dy_str = rep_comma(dyOl) + dist_rel = "A" + end + + -- Finally, we are going to go back to doing a string for the location bolus, but it will be tab delimited in the form "m\tf\tx\t\y\tA\tdx\tdy" or "m\tf\tx\t\y\tO\tdx\tdy" where A means dx,dy are relative to Azeroth (50,50) (in yards) and O means they are relative to Outland (50,50) + -- Note: if only four values are present, then we couldn't compute a distance... Probably because we are in an instance of some kind. + + local loc = string.format("%d\t%d\t%s\t%s", m, f, str_x, str_y) + if dxAz or dxOl then + loc = string.format("%s\t%s\t%s\t%s", loc, dist_rel, dx_str, dy_str) + end + return loc; --return string.format("%s,%s,%s,%s,%s", signed(delayed and 1 or 0), signed(c), signed(z), float_x, float_y) --return signed(delayed and 1 or 0) .. signed(c) .. signed(z) .. float_x .. float_y