vanilla-wow-addons – Rev 1
?pathlinks?
-- Utility functions for FlightMap
FlightMapUtil = {};
------- Data access functions
-- Break up a "Town, Zone" string into town and zone components. If
-- there's no comma, ie, Moonglade, the string will be returned for
-- both town and zone.
FlightMapUtil.getNameAndZone = function(taxipath)
local comma = string.find(taxipath, FLIGHTMAP_SEP_STRING, 1, true);
if (comma) then
local name = string.sub(taxipath, 1, comma - 1);
local zone = string.sub(taxipath,
comma + string.len(FLIGHTMAP_SEP_STRING),
-1 - string.len(FLIGHTMAP_SEP_POSTAMBLE));
return name, zone;
else
return taxipath, taxipath;
end
end
-- Construct a node name from its continent and taxi coordinates
FlightMapUtil.makeNodeName = function(continent, taxiX, taxiY)
return string.format("%d:%d:%d", continent, taxiX * 1000, taxiY * 1000);
end
-- Return the flight map data appropriate to the current character
FlightMapUtil.getFlightMap = function()
-- Return default flight data for the specified faction
local function lGetFactionDefaults(faction)
if faction == FLIGHTMAP_ALLIANCE then
return FLIGHTMAP_ALLIANCE_FLIGHTS;
elseif faction == FLIGHTMAP_HORDE then
return FLIGHTMAP_HORDE_FLIGHTS;
end
return {}; -- Catch all
end
local _, faction = UnitFactionGroup("player");
if not faction then return {}; end
if not FlightMap[faction] then
FlightMap[faction] = lGetFactionDefaults(faction);
end
return FlightMap[faction];
end
-- Returns true if the current character has seen a given node;
-- if the second argument is a true value, teaches the character of
-- the node's existence.
FlightMapUtil.knownNode = function(node, learning)
local name = UnitName("player");
local realm = GetCVar("realmName");
-- Conglomerate key
local key = name .. "@" .. realm;
-- If nothing is known for this character, make it known!
if not FlightMap.Knowledge[key] then
FlightMap.Knowledge[key] = {};
end
if learning then
FlightMap.Knowledge[key][node] = true;
end
return FlightMap.Knowledge[key][node];
end
-- TODO: put elsewhere
FlightMapUtil.lZoneNameMap = {};
FlightMapUtil.lContinentNameMap = {};
local function LoadNames(map, ...)
for i=1, arg.n, 1 do
map[i] = arg[i];
end
end
FlightMapUtil.getContinentName = function(c)
if not FlightMapUtil.lContinentNameMap[c] then
LoadNames(FlightMapUtil.lContinentNameMap, GetMapContinents());
end
return FlightMapUtil.lContinentNameMap[c];
end
-- Return the name of the current map zone
FlightMapUtil.getZoneName = function()
local cNum = GetCurrentMapContinent();
local zNum = GetCurrentMapZone();
if not FlightMapUtil.lZoneNameMap[cNum] then
FlightMapUtil.lZoneNameMap[cNum] = {};
LoadNames(FlightMapUtil.lZoneNameMap[cNum], GetMapZones(cNum));
end
return FlightMapUtil.lZoneNameMap[cNum][zNum];
end
-- Returns a table of nodes in a given zone; if second optional
-- argument is present and true, also returns subzone nodes.
FlightMapUtil.getNodesInZone = function(zone, subZones)
local map = FlightMapUtil.getFlightMap();
local nodes = {};
for k, v in map do
if v.Zone == zone then
nodes[k] = v;
elseif subZones and FLIGHTMAP_SUBZONES[v.Zone] == zone then
nodes[k] = v;
end
end
return nodes;
end
-- Get the current continent number
FlightMapUtil.getContinent = function()
SetMapToCurrentZone();
return GetCurrentMapContinent();
end
------- Format and display functions
-- Format a second amount into m:ss, returning "-:--" for zero seconds
-- unless the "showZero" argument is true
FlightMapUtil.formatTime = function(secs, showZero)
if secs == 0 and not showZero then return "-:--"; end
return string.format("%d:%02d", secs / 60, math.mod(secs, 60));
end
-- Format a copper amount into a gold, silver, copper string
FlightMapUtil.formatMoney = function(amount)
local FORMAT_GOLD = "|cffddbb00%d%s|r";
local FORMAT_SILVER = "|cffcccccc%d%s|r";
local FORMAT_COPPER = "|cffcc9010%d%s|r";
local copper = math.mod(amount, 100);
local silver = math.mod(math.floor(amount/100), 100);
local gold = math.floor(amount/10000);
local result = "";
local pad = "";
-- Only show gold and silver if they are non-zero
if gold > 0 then
local s = string.format(FORMAT_GOLD, gold, FLIGHTMAP_MONEY_GOLD);
result = result .. s;
pad = " ";
end
if silver > 0 then
local s = string.format(FORMAT_SILVER, silver, FLIGHTMAP_MONEY_SILVER);
result = result .. pad .. s;
pad = " ";
end
-- But show copper anyway if there's neither gold nor silver..
if (gold == 0 and silver == 0) or copper > 0 then
local s = string.format(FORMAT_COPPER, copper, FLIGHTMAP_MONEY_COPPER);
result = result .. pad .. s;
end
return result;
end
-- Draw a line by stretching the texture widget given in texture
-- across the parent frame given in parent. The coordinates
-- should be expressed as a number between 0 and 1, representing
-- the homogenized space of the parent. (0, 0) is the lower left
-- corner.
FlightMapUtil.drawLine = function(parent, texture, x1, y1, x2, y2)
texture:ClearAllPoints();
-- Get the line deltas in pixels
local dx = abs((x1 - x2) * parent:GetWidth());
local dy = abs((y1 - y2) * parent:GetHeight());
-- Seven possible cases:
-- 1) Horizontal line (dy = 0)
-- 2) Vertical line (dx = 0)
-- 3) source is ABOVE and RIGHT of dest
-- 4) source is BELOW and RIGHT of dest
-- 5) source is ABOVE and LEFT of dest
-- 6) source is BELOW and LEFT of dest
-- 7) Source and destination are equal
-- Equal points is the easiest case.
if dx == 0 and dy == 0 then
texture:Hide();
return false;
end
-- The remaining cases can be reduced to four by swapping the
-- source and destination points to ensure the source point is
-- always to the left of the destination point:
if x1 > x2 then
local tmpX = x1;
local tmpY = y1;
x1 = x2; x2 = tmpX;
y1 = y2; y2 = tmpY;
end
-- And then further reduced to two by making sure no lines really
-- are horizontal or vertical
if dy < 1 then dy = 1; end
if dx < 1 then dx = 1; end
-- Clip the texture if either delta is smaller than the base size
-- This prevents the texture from being scaled down, which could result
-- in parts of the line vanishing during interpolation.
local clipsize = dx;
if dy < dx then clipsize = dy; end
-- Now normalize the clipping size to 0-1
clipsize = clipsize / FLIGHTMAP_LINE_SIZE;
if clipsize > 1 then clipsize = 1; end
local anchorPoint = "NONE";
if y1 > y2 then -- Case 1: source ABOVE dest
-- Set correct texture
texture:SetTexture(FLIGHTMAP_TEX_UP);
-- Use the bottom left corner of it
texture:SetTexCoord(0, clipsize, 1 - clipsize, 1);
-- Place the bottom left corner
anchorPoint = "BOTTOMLEFT";
else -- Case 2: source BELOW dest
-- Set correct texture
texture:SetTexture(FLIGHTMAP_TEX_DOWN);
-- Use the top left corner of it
texture:SetTexCoord(0, clipsize, 0, clipsize);
-- Place the top left corner
anchorPoint = "TOPLEFT";
end
-- Set the origin, using whichever anchor point is appropriate
texture:SetPoint(anchorPoint, parent, "TOPLEFT",
x1 * parent:GetWidth(),
-y1 * parent:GetHeight());
-- Set the texture's width and height
texture:SetWidth(dx);
texture:SetHeight(dy);
-- Show the texture
texture:Show();
-- Success :)
return true;
end