Mercurial > wow > bloodhound2
diff Bloodhound2.lua @ 0:ff01eb61abab
Initial beta version
Updated original addon herb and ore database
Fixed the configuration options (maybe - requires testing)
Added the 2 new zones in Pandaria (Isle of Giants and Isle of Thunder)
author | only1yzerman |
---|---|
date | Thu, 09 May 2013 18:53:18 -0400 |
parents | |
children | 6ab5b23877a6 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Bloodhound2.lua Thu May 09 18:53:18 2013 -0400 @@ -0,0 +1,425 @@ + +-------- SINGLE OBJECT IN GLOBAL NAMESPACE + +Bloodhound2 = {}; + + +-------- CREATE OUR INVISIBLE FRAME TO RECEIVE EVENTS AND UPDATES + +local frame = CreateFrame("Frame", nil, UIParent); +Bloodhound2.Frame = frame; + + +-------- DEFINE AND REGISTER EVENT HANDLERS + +local events = {}; + +function events:MINIMAP_UPDATE_TRACKING(...) + if player and player.Z then + Bloodhound2.UpdateMinimap(); + end +end + +frame:SetScript("OnEvent", + function(self, event, ...) + events[event](self, ...); + end); + +local k, v; + +for k, v in pairs(events) do + frame:RegisterEvent(k); +end + + + + + + +---------------------------------------------------------------------------------------------------- +-------- STORES A POINTER TO THE MINIMAP LOCALLY SO IT CAN BE CHANGED BY A RE-PARENTING FUNCTION +-------- - Added by Zasurus(www.curseforge.com/profiles/Zasurus/) for MiniHugeHUD +---------------------------------------------------------------------------------------------------- +local Minimap = _G.Minimap; +Minimap.MinimapName = "Minimap"; +---------------------------------------------------------------------------------------------------- + + + + + + +-------- WORK AROUND WOW BUG THAT CAUSES GetPlayerMapPosition TO RETURN 0,0 + +WorldMapFrame:Show() +WorldMapFrame:Hide() + + +-------- HOOK INTO PER-FRAME UPDATE HANDLER + +local player = {}; -- player position +local totalElapsed = 0.0; -- time elapsed since last update +local updatePeriod = 0.1; -- sec. interval for each minimap update +local cpuThrottle = 0.05; -- throttle to 5% usage while moving +local minUpdatePeriod = 0.04; -- sec. don't update more often than this +local lastzoom = 0; -- previous minimap zoom level +local updateTotalTime = 0; -- time spent updating minimap +local updateCount = 0; -- number of times minimap updated + +---------------------------------------------------------------------------------------------------- +-------- MOVED OnUpdate Script into seperate function so it could be called by re-parent function +-------- - Added by Zasurus(www.curseforge.com/profiles/Zasurus/) for MiniHugeHUD +---------------------------------------------------------------------------------------------------- +frame:SetScript("OnUpdate", function(self, elapsed) Bloodhound2.OnUpdateScript(self, elapsed) end); +function Bloodhound2.OnUpdateScript(self, elapsed) + totalElapsed = totalElapsed + elapsed; -- measure total elapsed time + + if (totalElapsed >= updatePeriod) then -- if enough time has passed + totalElapsed = mod(totalElapsed, updatePeriod); + local isInInstance, instanceType = IsInInstance() + + if isInInstance ~= nil then + Bloodhound2.DrawArrow(0, 0, 0, 0) + return + end + + local cmap = GetCurrentMapContinent(); + local zmap = GetCurrentMapZone(); + SetMapToCurrentZone(); + local c = GetCurrentMapContinent(); -- get current player position + local z = GetCurrentMapZone(); + local x, y = GetPlayerMapPosition("player"); + local f = GetPlayerFacing(); + local m = Minimap:GetZoom(); + SetMapZoom(cmap, zmap); + + if (c ~= player.C and c ~= 0) then -- reload continent data if continent has changed + Bloodhound2.HerbNodes, Bloodhound2.ContinentHerbs = Bloodhound2.ReloadNodes(Bloodhound2.HerbDatabase[c], Bloodhound2.ZoneDatum[c]); + Bloodhound2.OreNodes, Bloodhound2.ContinentOre = Bloodhound2.ReloadNodes(Bloodhound2.OreDatabase[c], Bloodhound2.ZoneDatum[c]); + end + + if (c ~= player.C or z ~= player.Z or x ~= player.X or y ~= player.Y or f ~= player.F or m ~= lastzoom) then + player.C = c; + player.Z = z; + player.X = x; + player.Y = y; + player.F = f; + lastzoom = m; + local t0 = GetTime(); + Bloodhound2.UpdateMinimap(); -- player has moved or minimap scale has changed + local t1 = GetTime() - t0; + + -- calculate and throttle CPU usage to 5% + updateTotalTime = updateTotalTime + t1 + + if updateCount > 10 then + local avgTime = updateTotalTime / updateCount + updatePeriod = avgTime / cpuThrottle + Print(updateCount); + + if updatePeriod < minUpdatePeriod then + updatePeriod = minUpdatePeriod + end + + if updateCount >= 100 then + updateTotalTime = updateTotalTime / 2 + updateCount = updateCount / 2 + end + end + end + end + end + +function Bloodhound2.UpdateMinimap() + local facing = 0 + + if GetCVar("rotateMinimap") ~= "0" then + facing = GetPlayerFacing() * 57.2957795; + end + + local cf = cos(facing); + local sf = sin(facing); + local gx, gy = Bloodhound2.CalculateForce(cf, sf); + Bloodhound2.DrawArrow(gx, gy, cf, sf); +end + + +-------- DATABASE LOADING + +Bloodhound2.HerbNodes = {}; +Bloodhound2.OreNodes = {}; +Bloodhound2.ContinentHerbs = {}; +Bloodhound2.ContinentOre = {}; + +function Bloodhound2.ReloadNodes(database, zoneDatum) + + if (database == nil) then return {}; end + + local nodes = {}; + local db = {}; + + local zoneNode, positions; + for zoneNode, positions in pairs(database) do + local _, _, zone, node = string.find(zoneNode, "Z(%d+)N(%d+)"); + local z = tonumber(zone); + local datum = zoneDatum[z]; + local n = tonumber(node); + db[n] = true; + local pxy = 0 + + for _,pos in ipairs(positions) do + local xy = pos + pxy + pxy = xy + local x = floor(xy / 1000); + local y = xy - 1000 * x; + x, y = Bloodhound2.ZoneDatum.LocalToGlobal(x / 1000.0, y / 1000.0, datum); + tinsert(nodes, {Z = z, N = n, X = x, Y = y, TimeStamp = time() - 60 - 3600 * math.random() }); + end + end + + return nodes, db; +end + + +-------- UTILITY FUNCTIONS + +function Print(message) + DEFAULT_CHAT_FRAME:AddMessage(message); +end + + + +-------- ARROW LOADING AND DISPLAY + +local function GetArrowTexture() + + local tex = Bloodhound2.GravityTexture + + if not ( tex ) then + tex = Minimap:CreateTexture(); + tex:SetTexture("Interface\\AddOns\\Bloodhound2\\MinimapArrow"); + Bloodhound2.GravityTexture = tex + end + + return tex +end + +function Bloodhound2.DrawArrow(grx, gry, cf, sf) + + local gravityX = grx * cf - gry * sf; + local gravityY = gry * cf + grx * sf; + local gravityTexture = GetArrowTexture() + + if (gravityX == 0 and gravityY == 0) then + gravityTexture:Hide(); + return; + end + + local gravityScale = sqrt(gravityX * gravityX + gravityY * gravityY) + gravityX = gravityX / gravityScale + gravityY = gravityY / gravityScale + + -- determine rotated and scaled texture coordinates + local gy = (gravityX + gravityY) / 2.82843 + local gx = (gravityX - gravityY) / 2.82843 + + gravityTexture:SetTexCoord( + 0.5 - gx, 0.5 + gy, + 0.5 + gy, 0.5 + gx, + 0.5 - gy, 0.5 - gx, + 0.5 + gx, 0.5 - gy); + + gravityTexture:SetPoint("CENTER", Minimap, "CENTER", 40 * gravityX, -40 * gravityY) + gravityTexture:Show() +end + + +-------- "RUBY" MANAGEMENT (REUSE RUBIES AND ONLY CREATE NEW ONES WHEN NEEDED) + +local circles = {}; +local nextCircle = 1; +local circleScale = 1; + +function Bloodhound2.ResetCircles() + nextCircle = 1; + circleScale = Minimap:GetHeight() * 0.015 / (7 - Minimap:GetZoom()); +end + +function Bloodhound2.SetCircle(dx, dy, alpha) + local circle; + if (#circles < nextCircle) then + circle = Minimap:CreateTexture(); + circles[nextCircle] = circle; + circle:SetTexture("Interface\\AddOns\\Bloodhound2\\Circle"); + circle:SetWidth(12); + circle:SetHeight(12); + circle:SetAlpha(1); + else + circle = circles[nextCircle]; + end + + nextCircle = nextCircle + 1; + circle:SetPoint("CENTER", Minimap, "CENTER", dx * circleScale, -dy * circleScale); + circle:SetAlpha(alpha); + circle:Show(); +end + +function Bloodhound2.HideExtraCircles() + for i=nextCircle,#circles,1 do + circles[i]:Hide(); + end +end + + + +-------- MAIN FUNCTION FOR CALCULATING RECOMMENDED DIRECTION OF TRAVEL + +function Bloodhound2.CalculateForce(cf, sf) + + local c = player.C; -- get player position + local z = player.Z; + local x = player.X; + local y = player.Y; + + if c == 0 or z == 0 then return 0,0 end -- don't draw arrow if using world coordinates + if not Bloodhound2.ZoneDatum then return 0,0 end + + local datum = Bloodhound2.ZoneDatum[c][z]; -- get scale and offset for current zone map + if datum == nil then return 0,0 end + + local gx, gy = Bloodhound2.ZoneDatum.LocalToGlobal(x, y, datum); -- convert player position to world coordinates + local now = time(); -- value to use for time-stamping visited nodes + local fx = 0; -- cumulative force, X-component + local fy = 0; -- cumulative force, Y-component + local multiZone = true; -- whether to include more than the current zone + local inspectionRadius = 60; + + if Settings then + if Settings.MultiZoneMode==0 then + multiZone = IsFlying(); + elseif Settings.MultiZoneMode==1 then + multiZone = true; + else + multiZone = false; + end + + if Settings.InspectionRadius then + inspectionRadius = Settings.InspectionRadius; + end + end + + local settingsFilter = {}; -- which node types to ignore + local nodes = {}; -- which nodes to track + + for i=1,GetNumTrackingTypes(),1 do + local name, _, active, _ = GetTrackingInfo(i); + if (active == 1) then + if (name == L["Find Herbs"]) then + for k,v in pairs(Settings.HerbFilter) do settingsFilter[k] = v end + for k,v in pairs(Bloodhound2.HerbNodes) do tinsert(nodes, v) end + elseif (name == L["Find Minerals"]) then + for k,v in pairs(Settings.OreFilter) do settingsFilter[k] = v end + for k,v in pairs(Bloodhound2.OreNodes) do tinsert(nodes, v) end + end + end + end + + local avoidZones = {}; -- which zones to avoid + + if multiZone then + local cmc = GetCurrentMapContinent() + + if not Settings.ZoneFilter[cmc] then + Settings.ZoneFilter[cmc] = {} + end + + for k,v in pairs(Settings.ZoneFilter[GetCurrentMapContinent()]) do + avoidZones[k] = true; + end + end + + local avoidNodes = {}; -- which node types to ignore + + if settingsFilter then + for k,v in pairs(settingsFilter) do + avoidNodes[k] = true; + end + end + + local minimapSize = Minimap:GetWidth() / 2 - 2; + Bloodhound2.ResetCircles(); + + for key, node in pairs(nodes) do + if (avoidNodes[node.N] ~= true) and (avoidZones[node.Z] ~= true) and (multiZone or (node.Z == z)) then + local dx = node.X - gx; + local dy = node.Y - gy; + local rsqrd = dx * dx + dy * dy; + local r = sqrt(rsqrd); -- distance to node + local age = now - node.TimeStamp; -- time since last inspected + + if (r < inspectionRadius) then + node.TimeStamp = now; + else + --[[ + The magnitude of the force is proportional to the age and inversely + proportional to the square of the distance, and the direction is towards + the node. The math for this starts out as + + local force = age / rsqrd + local angle = math.atan2(dy, dx) + fx = fx + force * math.cos(angle) + fy = fy + force * math.sin(angle) + + But cos(angle) is just dx/r and sin(angle) is just dy/r, so we don't + actually need atan2, cos, and sin and instead we can write this as + ]] + local force = age / (r * rsqrd) + fx = fx + force * dx + fy = fy + force * dy + end + + if (r * circleScale < minimapSize) and (age > 60) then -- draw ruby + local alpha = r / (minimapSize / circleScale) / 0.7 - 0.3; + alpha = max(0, alpha); + Bloodhound2.SetCircle(dx * cf - dy * sf, dy * cf + dx * sf, alpha); + end + end + end + + Bloodhound2.HideExtraCircles(); + return fx, fy; +end + + + + + + + +---------------------------------------------------------------------------------------------------- +-------- REPARENT THE MINIMAP FOR 3RD PARTY MINIMAPS AND HUDS +-------- - Added by Zasurus(www.curseforge.com/profiles/Zasurus/) for MiniHugeHUD +---------------------------------------------------------------------------------------------------- +function Bloodhound2.ReparentMinimap(NewMinimap, MinimapName) + Bloodhound2.OnUpdateScript(nil, 1000000) + -- Hide the circles currently on the minimap + Bloodhound2.ResetCircles(); + Bloodhound2.HideExtraCircles(); + -- Hide this minimap's copy of the arrow + if Bloodhound2.GravityTexture then + Bloodhound2.GravityTexture:Hide(); + end; + -- Store the current set of circles and arrow on this minimap for later + Minimap.Bloodhound2Circles = circles; + Minimap.Bloodhound2Arrow = Bloodhound2.GravityTexture; + -- Pull back (or create for circles) the arrow and circles for this minimap + circles = NewMinimap.Bloodhound2Circles or {}; + ZasCircles = circles; + Bloodhound2.GravityTexture = NewMinimap.Bloodhound2Arrow; + -- Move Bloodhound2's Local Minimap pointer to the new minimap + Minimap = NewMinimap; + Minimap.MinimapName = MinimapName; + -- Update all points + Bloodhound2.UpdateMinimap(); +end +---------------------------------------------------------------------------------------------------- \ No newline at end of file