|
|
|
|
--[[--------------------------------------------------------------------------
|
|
|
|
|
-- TomTom - A navigational assistant for World of Warcraft
|
|
|
|
|
--
|
|
|
|
|
-- CrazyTaxi: A crazy-taxi style arrow used for waypoint navigation.
|
|
|
|
|
-- concept taken from MapNotes2 (Thanks to Mery for the idea, along
|
|
|
|
|
-- with the original artwork.)
|
|
|
|
|
----------------------------------------------------------------------------]]
|
|
|
|
|
|
|
|
|
|
local addonName, addon = ...
|
|
|
|
|
|
|
|
|
|
local L = TomTomLocals
|
|
|
|
|
local ldb = LibStub("LibDataBroker-1.1")
|
|
|
|
|
|
|
|
|
|
local IMAGE_ARROW = "Interface\\Addons\\TomTom\\Images\\Arrow-1024"
|
|
|
|
|
local IMAGE_ARROW_UP = "Interface\\AddOns\\TomTom\\Images\\Arrow-UP-1024"
|
|
|
|
|
local IMAGE_STATIC_ARROW = "Interface\\Addons\\TomTom\\Images\\StaticArrow"
|
|
|
|
|
|
|
|
|
|
local themeHandler = addon.CrazyArrowThemeHandler
|
|
|
|
|
|
|
|
|
|
local twopi = math.pi * 2
|
|
|
|
|
|
|
|
|
|
local wayframe = CreateFrame("Button", "TomTomCrazyArrow", UIParent)
|
|
|
|
|
wayframe:EnableMouse(true)
|
|
|
|
|
wayframe:SetMovable(true)
|
|
|
|
|
wayframe:SetClampedToScreen(true)
|
|
|
|
|
wayframe:Hide()
|
|
|
|
|
|
|
|
|
|
-- Frame used to control the scaling of the title and friends
|
|
|
|
|
local titleframe = CreateFrame("Frame", nil, wayframe)
|
|
|
|
|
|
|
|
|
|
wayframe.title = titleframe:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
|
|
|
|
|
wayframe.status = titleframe:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
|
|
|
wayframe.tta = titleframe:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
|
|
|
wayframe.title:SetPoint("TOP", wayframe, "BOTTOM", 0, 0)
|
|
|
|
|
wayframe.status:SetPoint("TOP", wayframe.title, "BOTTOM", 0, 0)
|
|
|
|
|
wayframe.tta:SetPoint("TOP", wayframe.status, "BOTTOM", 0, 0)
|
|
|
|
|
|
|
|
|
|
local function ShowCrazyArrow()
|
|
|
|
|
wayframe:Show()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function OnDragStart(self, button)
|
|
|
|
|
if not TomTom.db.profile.arrow.lock then
|
|
|
|
|
self:StartMoving()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function OnDragStop(self, button)
|
|
|
|
|
self:StopMovingOrSizing()
|
|
|
|
|
self:SetUserPlaced(false)
|
|
|
|
|
-- point, relativeTo, relativePoint, xOfs, yOfs
|
|
|
|
|
TomTom.profile.arrow.position = { self:GetPoint() }
|
|
|
|
|
TomTom.profile.arrow.position[2] = nil -- Note we are relative to UIParent
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function OnEvent(self, event, ...)
|
|
|
|
|
if (event == "ZONE_CHANGED_NEW_AREA" or event == "ZONE_CHANGED") and TomTom.profile.arrow.enable then
|
|
|
|
|
ShowCrazyArrow()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
if (event == "PLAYER_ENTERING_WORLD") then
|
|
|
|
|
wayframe:ClearAllPoints()
|
|
|
|
|
if not TomTom.profile.arrow.position then
|
|
|
|
|
TomTom.profile.arrow.position = {"CENTER", nil , "CENTER", 0, 0}
|
|
|
|
|
end
|
|
|
|
|
local pos = TomTom.profile.arrow.position
|
|
|
|
|
wayframe:SetPoint(pos[1], UIParent, pos[3], pos[4], pos[5])
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wayframe:SetScript("OnDragStart", OnDragStart)
|
|
|
|
|
wayframe:SetScript("OnDragStop", OnDragStop)
|
|
|
|
|
wayframe:RegisterForDrag("LeftButton")
|
|
|
|
|
wayframe:RegisterEvent("ZONE_CHANGED_NEW_AREA")
|
|
|
|
|
wayframe:RegisterEvent("ZONE_CHANGED")
|
|
|
|
|
wayframe:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
|
|
|
wayframe:SetScript("OnEvent", OnEvent)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local active_point, arrive_distance, showDownArrow, point_title
|
|
|
|
|
|
|
|
|
|
function TomTom:SetCrazyArrow(uid, dist, title)
|
|
|
|
|
if active_point and active_point.corpse and self.db.profile.arrow.stickycorpse then
|
|
|
|
|
-- do not change the waypoint arrow from corpse
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
active_point = uid
|
|
|
|
|
arrive_distance = dist
|
|
|
|
|
point_title = title
|
|
|
|
|
|
|
|
|
|
if self.profile.arrow.enable then
|
|
|
|
|
wayframe.title:SetText(title or L["Unknown waypoint"])
|
|
|
|
|
ShowCrazyArrow()
|
|
|
|
|
if wayframe.crazyFeedFrame then
|
|
|
|
|
wayframe.crazyFeedFrame:Show()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function TomTom:IsCrazyArrowEmpty()
|
|
|
|
|
return not active_point
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local status = wayframe.status
|
|
|
|
|
local tta = wayframe.tta
|
|
|
|
|
local arrow = wayframe.arrow
|
|
|
|
|
local last_distance = 0
|
|
|
|
|
local tta_throttle = 0
|
|
|
|
|
local speed = 0
|
|
|
|
|
local speed_count = 0
|
|
|
|
|
|
|
|
|
|
local function OnUpdate(self, elapsed)
|
|
|
|
|
if not active_point then
|
|
|
|
|
self:Hide()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local dist,x,y = TomTom:GetDistanceToWaypoint(active_point)
|
|
|
|
|
|
|
|
|
|
-- The only time we cannot calculate the distance is when the waypoint
|
|
|
|
|
-- is on another continent, or we are in an instance
|
|
|
|
|
if not dist then
|
|
|
|
|
if not TomTom:IsValidWaypoint(active_point) then
|
|
|
|
|
active_point = nil
|
|
|
|
|
-- Change the crazy arrow to point at the closest waypoint
|
|
|
|
|
if TomTom.profile.arrow.setclosest then
|
|
|
|
|
TomTom:SetClosestWaypoint()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self:Hide()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
status:SetText(addon:GetFormattedDistance(dist))
|
|
|
|
|
|
|
|
|
|
-- Showing the arrival arrow?
|
|
|
|
|
if dist <= arrive_distance then
|
|
|
|
|
if not showDownArrow then
|
|
|
|
|
themeHandler:SwitchToArrivalArrow(wayframe)
|
|
|
|
|
showDownArrow = true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
themeHandler:ArrivalArrow_OnUpdate(elapsed)
|
|
|
|
|
else
|
|
|
|
|
if showDownArrow then
|
|
|
|
|
themeHandler:SwitchToNavigationArrow(wayframe)
|
|
|
|
|
showDownArrow = false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local angle = TomTom:GetDirectionToWaypoint(active_point)
|
|
|
|
|
local player = GetPlayerFacing()
|
|
|
|
|
|
|
|
|
|
if not player then
|
|
|
|
|
if not TomTom:IsValidWaypoint(active_point) then
|
|
|
|
|
active_point = nil
|
|
|
|
|
-- Change the crazy arrow to point at the closest waypoint
|
|
|
|
|
if TomTom.profile.arrow.setclosest then
|
|
|
|
|
TomTom:SetClosestWaypoint()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
self:Hide()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
angle = angle - player
|
|
|
|
|
|
|
|
|
|
themeHandler:NavigationArrow_OnUpdate(elapsed, angle)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Calculate the TTA every second (%01d:%02d)
|
|
|
|
|
|
|
|
|
|
tta_throttle = tta_throttle + elapsed
|
|
|
|
|
|
|
|
|
|
if tta_throttle >= 1.0 then
|
|
|
|
|
-- Calculate the speed in yards per sec at which we're moving
|
|
|
|
|
local current_speed = (last_distance - dist) / tta_throttle
|
|
|
|
|
|
|
|
|
|
if last_distance == 0 then
|
|
|
|
|
current_speed = 0
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if speed_count < 2 then
|
|
|
|
|
speed = (speed + current_speed) / 2
|
|
|
|
|
speed_count = speed_count + 1
|
|
|
|
|
else
|
|
|
|
|
speed_count = 0
|
|
|
|
|
speed = current_speed
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if speed > 0 then
|
|
|
|
|
local eta = math.abs(dist / speed)
|
|
|
|
|
tta:SetFormattedText("%s:%02d", math.floor(eta / 60), math.floor(eta % 60))
|
|
|
|
|
else
|
|
|
|
|
tta:SetText("***")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
last_distance = dist
|
|
|
|
|
tta_throttle = 0
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function TomTom:ShowHideCrazyArrow()
|
|
|
|
|
if self.profile.arrow.enable then
|
|
|
|
|
if self.profile.arrow.hideDuringPetBattles and C_PetBattles and C_PetBattles.IsInBattle() then
|
|
|
|
|
wayframe:Hide()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
ShowCrazyArrow()
|
|
|
|
|
|
|
|
|
|
if self.profile.arrow.noclick then
|
|
|
|
|
wayframe:EnableMouse(false)
|
|
|
|
|
else
|
|
|
|
|
wayframe:EnableMouse(true)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Set the scale and alpha
|
|
|
|
|
wayframe:SetScale(TomTom.db.profile.arrow.scale)
|
|
|
|
|
-- Do not allow the arrow to be invisible
|
|
|
|
|
if TomTom.db.profile.arrow.alpha < 0.1 then
|
|
|
|
|
TomTom.db.profile.arrow.alpha = 1.0
|
|
|
|
|
end
|
|
|
|
|
-- Set the stratum
|
|
|
|
|
if TomTom.db.profile.arrow.highstrata then
|
|
|
|
|
wayframe:SetFrameStrata("HIGH")
|
|
|
|
|
else
|
|
|
|
|
wayframe:SetFrameStrata("MEDIUM")
|
|
|
|
|
end
|
|
|
|
|
wayframe:SetAlpha(TomTom.db.profile.arrow.alpha)
|
|
|
|
|
local width = TomTom.db.profile.arrow.title_width
|
|
|
|
|
local height = TomTom.db.profile.arrow.title_height
|
|
|
|
|
local scale = TomTom.db.profile.arrow.title_scale
|
|
|
|
|
|
|
|
|
|
wayframe.title:SetWidth(width)
|
|
|
|
|
wayframe.title:SetHeight(height)
|
|
|
|
|
titleframe:SetScale(scale)
|
|
|
|
|
titleframe:SetAlpha(TomTom.db.profile.arrow.title_alpha)
|
|
|
|
|
|
|
|
|
|
if self.profile.arrow.showdistance then
|
|
|
|
|
wayframe.status:Show()
|
|
|
|
|
wayframe.tta:ClearAllPoints()
|
|
|
|
|
wayframe.tta:SetPoint("TOP", wayframe.status, "BOTTOM", 0, 0)
|
|
|
|
|
else
|
|
|
|
|
wayframe.status:Hide()
|
|
|
|
|
wayframe.tta:ClearAllPoints()
|
|
|
|
|
wayframe.tta:SetPoint("TOP", wayframe, "BOTTOM", 0, 0)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Set the theme
|
|
|
|
|
local theme = self.profile.arrow.theme
|
|
|
|
|
themeHandler:SetActiveTheme(wayframe, theme, showDownArrow)
|
|
|
|
|
|
|
|
|
|
if self.profile.arrow.showtta then
|
|
|
|
|
tta:Show()
|
|
|
|
|
else
|
|
|
|
|
tta:Hide()
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
wayframe:Hide()
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wayframe:SetScript("OnUpdate", OnUpdate)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--[[-------------------------------------------------------------------------
|
|
|
|
|
-- Dropdown
|
|
|
|
|
-------------------------------------------------------------------------]]--
|
|
|
|
|
|
|
|
|
|
local function crazyArrowDropdownGenerator(owner, rootDescription)
|
|
|
|
|
rootDescription:CreateTitle(L["TomTom Waypoint Arrow"]);
|
|
|
|
|
|
|
|
|
|
-- Waypoint communications
|
|
|
|
|
local sendWaypoint = rootDescription:CreateButton(L["Send waypoint to"])
|
|
|
|
|
sendWaypoint:CreateTitle(L["Waypoint communication"])
|
|
|
|
|
sendWaypoint:CreateButton(L["Send to party"], function()
|
|
|
|
|
addon:SendWaypoint(addon.dropdown_uid, "PARTY")
|
|
|
|
|
end)
|
|
|
|
|
sendWaypoint:CreateButton(L["Send to raid"], function()
|
|
|
|
|
addon:SendWaypoint(addon.dropdown_uid, "RAID")
|
|
|
|
|
end)
|
|
|
|
|
sendWaypoint:CreateButton(L["Send to battleground"], function()
|
|
|
|
|
addon:SendWaypoint(addon.dropdown_uid, "BATTLEGROUND")
|
|
|
|
|
end)
|
|
|
|
|
sendWaypoint:CreateButton(L["Send to guild"], function()
|
|
|
|
|
addon:SendWaypoint(addon.dropdown_uid, "GUILD")
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
rootDescription:CreateButton(L["Clear waypoint from crazy arrow"], function()
|
|
|
|
|
addon:ClearCrazyArrowPoint(false)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
rootDescription:CreateButton(L["Remove waypoint"], function()
|
|
|
|
|
addon:ClearCrazyArrowPoint(true)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
rootDescription:CreateButton(L["Remove all waypoints from this zone"], function()
|
|
|
|
|
local uid = addon.dropdown_uid
|
|
|
|
|
local data = uid
|
|
|
|
|
local mapId = data[1]
|
|
|
|
|
for key, waypoint in pairs(addon.waypoints[mapId]) do
|
|
|
|
|
addon:RemoveWaypoint(waypoint)
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
rootDescription:CreateButton(L["Remove all waypoints"], function()
|
|
|
|
|
if addon.db.profile.general.confirmremoveall then
|
|
|
|
|
StaticPopup_Show("TOMTOM_REMOVE_ALL_CONFIRM")
|
|
|
|
|
else
|
|
|
|
|
StaticPopupDialogs["TOMTOM_REMOVE_ALL_CONFIRM"].OnAccept()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
local maybeLocked = addon.db.profile.arrow.lock and L["Unlock crazy arrow"] or L["Lock crazy arrow"]
|
|
|
|
|
rootDescription:CreateButton(L[maybeLocked], function()
|
|
|
|
|
addon.db.profile.arrow.lock = not addon.db.profile.arrow.lock
|
|
|
|
|
addon:ShowHideCrazyArrow()
|
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function WayFrame_OnClick(self, button)
|
|
|
|
|
if active_point then
|
|
|
|
|
if addon.db.profile.arrow.menu then
|
|
|
|
|
addon.dropdown_uid = active_point
|
|
|
|
|
MenuUtil.CreateContextMenu(self, crazyArrowDropdownGenerator)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wayframe:RegisterForClicks("RightButtonUp")
|
|
|
|
|
wayframe:SetScript("OnClick", WayFrame_OnClick)
|
|
|
|
|
|
|
|
|
|
local function getCoords(column, row)
|
|
|
|
|
local xstart = (column * 56) / 512
|
|
|
|
|
local ystart = (row * 42) / 512
|
|
|
|
|
local xend = ((column + 1) * 56) / 512
|
|
|
|
|
local yend = ((row + 1) * 42) / 512
|
|
|
|
|
return xstart, xend, ystart, yend
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local texcoords = setmetatable({}, {__index = function(t, k)
|
|
|
|
|
local col,row = k:match("(%d+):(%d+)")
|
|
|
|
|
col,row = tonumber(col), tonumber(row)
|
|
|
|
|
local obj = {getCoords(col, row)}
|
|
|
|
|
rawset(t, k, obj)
|
|
|
|
|
return obj
|
|
|
|
|
end})
|
|
|
|
|
|
|
|
|
|
wayframe:RegisterEvent("ADDON_LOADED")
|
|
|
|
|
local function wayframe_OnEvent(self, event, arg1, ...)
|
|
|
|
|
if arg1 == "TomTom" then
|
|
|
|
|
if TomTom.db.profile.feeds.arrow then
|
|
|
|
|
-- Create a data feed for coordinates
|
|
|
|
|
local feed_crazy = ldb:NewDataObject("TomTom_CrazyArrow", {
|
|
|
|
|
type = "data source",
|
|
|
|
|
icon = IMAGE_ARROW,
|
|
|
|
|
staticIcon = IMAGE_STATIC_ARROW,
|
|
|
|
|
text = "Crazy",
|
|
|
|
|
iconR = 0.2,
|
|
|
|
|
iconG = 1.0,
|
|
|
|
|
iconB = 0.2,
|
|
|
|
|
iconCoords = texcoords["1:1"],
|
|
|
|
|
OnTooltipShow = function(tooltip)
|
|
|
|
|
local dist = TomTom:GetDistanceToWaypoint(active_point)
|
|
|
|
|
if dist then
|
|
|
|
|
tooltip:AddLine(point_title or L["Unknown waypoint"])
|
|
|
|
|
tooltip:AddLine(string.format(L["%d yards"], dist), 1, 1, 1)
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
OnClick = WayFrame_OnClick,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
local crazyFeedFrame = CreateFrame("Frame")
|
|
|
|
|
local throttle = TomTom.db.profile.feeds.arrow_throttle
|
|
|
|
|
local counter = 0
|
|
|
|
|
|
|
|
|
|
function TomTom:UpdateArrowFeedThrottle()
|
|
|
|
|
throttle = TomTom.db.profile.feeds.arrow_throttle
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wayframe.crazyFeedFrame = crazyFeedFrame
|
|
|
|
|
crazyFeedFrame:SetScript("OnUpdate", function(self, elapsed)
|
|
|
|
|
counter = counter + elapsed
|
|
|
|
|
if counter < throttle then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
counter = 0
|
|
|
|
|
if not active_point then
|
|
|
|
|
self:Hide()
|
|
|
|
|
end
|
|
|
|
|
local angle = TomTom:GetDirectionToWaypoint(active_point)
|
|
|
|
|
local player = GetPlayerFacing()
|
|
|
|
|
if not angle or not player then
|
|
|
|
|
feed_crazy.iconCoords = texcoords["1:1"]
|
|
|
|
|
feed_crazy.iconR = 0.2
|
|
|
|
|
feed_crazy.iconG = 1.0
|
|
|
|
|
feed_crazy.iconB = 0.2
|
|
|
|
|
feed_crazy.text = "No waypoint"
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
angle = angle - player
|
|
|
|
|
|
|
|
|
|
local perc = math.abs((math.pi - math.abs(angle)) / math.pi)
|
|
|
|
|
|
|
|
|
|
local gr,gg,gb = unpack(TomTom.db.profile.arrow.goodcolor)
|
|
|
|
|
local mr,mg,mb = unpack(TomTom.db.profile.arrow.middlecolor)
|
|
|
|
|
local br,bg,bb = unpack(TomTom.db.profile.arrow.badcolor)
|
|
|
|
|
local r,g,b = addon:ColorGradient(perc, br, bg, bb, mr, mg, mb, gr, gg, gb)
|
|
|
|
|
|
|
|
|
|
-- If we're 98% heading in the right direction, then use the exact
|
|
|
|
|
-- color instead of the gradient. This allows us to distinguish 'good'
|
|
|
|
|
-- from 'on target'. Thanks to Gregor_Curse for the suggestion.
|
|
|
|
|
if perc > 0.98 then
|
|
|
|
|
r,g,b = unpack(TomTom.db.profile.arrow.exactcolor)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
feed_crazy.iconR = r
|
|
|
|
|
feed_crazy.iconG = g
|
|
|
|
|
feed_crazy.iconB = b
|
|
|
|
|
|
|
|
|
|
local cell = floor(angle / twopi * 108 + 0.5) % 108
|
|
|
|
|
local column = cell % 9
|
|
|
|
|
local row = floor(cell / 9)
|
|
|
|
|
|
|
|
|
|
local key = column .. ":" .. row
|
|
|
|
|
feed_crazy.iconCoords = texcoords[key]
|
|
|
|
|
feed_crazy.text = point_title or L["Unknown waypoint"]
|
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wayframe:HookScript("OnEvent", wayframe_OnEvent)
|
|
|
|
|
|
|
|
|
|
--[[-------------------------------------------------------------------------
|
|
|
|
|
-- API for manual control of Crazy Arrow
|
|
|
|
|
--
|
|
|
|
|
-- This allow for an addon to specify their own control of the waypoint
|
|
|
|
|
-- arrow without needing to tip-toe around the API. It may not integrate
|
|
|
|
|
-- properly, but in general it should work.
|
|
|
|
|
--
|
|
|
|
|
-- Example Usage:
|
|
|
|
|
--
|
|
|
|
|
-- if not TomTom:CrazyArrowIsHijacked() then
|
|
|
|
|
-- TomTom:HijackCrazyArrow(function(self, elapsed)
|
|
|
|
|
-- -- Random angle
|
|
|
|
|
-- local angle = math.random(math.pi * 2)
|
|
|
|
|
-- TomTom:SetCrazyArrowDirection(angle)
|
|
|
|
|
-- -- Random color
|
|
|
|
|
-- local r = math.random(100) / 100
|
|
|
|
|
-- local g = math.random(100) / 100
|
|
|
|
|
-- local b = math.random(100) / 100
|
|
|
|
|
-- TomTom:SetCrazyArrowColor(r, g, b)
|
|
|
|
|
-- -- Titles
|
|
|
|
|
-- TomTom:SetCrazyArrowTitle("Hijacked arrow", "Hijacked", "You will never arrive")
|
|
|
|
|
-- end)
|
|
|
|
|
-- end
|
|
|
|
|
--
|
|
|
|
|
-- -- At some point later
|
|
|
|
|
-- TomTom:ReleaseCrazyArrow()
|
|
|
|
|
-------------------------------------------------------------------------]]--
|
|
|
|
|
|
|
|
|
|
-- Set the direction of the crazy arrow without taking the player's facing
|
|
|
|
|
-- into consideration. This can be accomplished by subtracting
|
|
|
|
|
-- GetPlayerFacing() from the angle before passing it in.
|
|
|
|
|
function TomTom:SetCrazyArrowDirection(angle)
|
|
|
|
|
local cell = floor(angle / twopi * 108 + 0.5) % 108
|
|
|
|
|
local column = cell % 9
|
|
|
|
|
local row = floor(cell / 9)
|
|
|
|
|
|
|
|
|
|
local key = column .. ":" .. row
|
|
|
|
|
arrow:SetTexCoord(unpack(texcoords[key]))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Convenience function to set the color of the crazy arrow
|
|
|
|
|
function TomTom:SetCrazyArrowColor(r, g, b, a)
|
|
|
|
|
arrow:SetVertexColor(r, g, b, a)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Convenience function to set the title/status and time to arrival text
|
|
|
|
|
-- of the crazy arrow.
|
|
|
|
|
function TomTom:SetCrazyArrowTitle(title, status, tta)
|
|
|
|
|
wayframe.title:SetText(title)
|
|
|
|
|
wayframe.status:SetText(status)
|
|
|
|
|
wayframe.tta:SetText(tta)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Function to actually hijack the crazy arrow by replacing the OnUpdate script
|
|
|
|
|
function TomTom:HijackCrazyArrow(onupdate)
|
|
|
|
|
wayframe:SetScript("OnUpdate", onupdate)
|
|
|
|
|
wayframe.hijacked = true
|
|
|
|
|
ShowCrazyArrow()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Releases the crazy arrow by restoring the original OnUpdate script
|
|
|
|
|
function TomTom:ReleaseCrazyArrow()
|
|
|
|
|
wayframe:SetScript("OnUpdate", OnUpdate)
|
|
|
|
|
wayframe.hijacked = false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Returns whether or not the crazy arrow is currently hijacked
|
|
|
|
|
function TomTom:CrazyArrowIsHijacked()
|
|
|
|
|
return wayframe.hijacked
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Logs Crazy Arrow status
|
|
|
|
|
function TomTom:DebugCrazyArrow()
|
|
|
|
|
local msg
|
|
|
|
|
msg = string.format(L["|cffffff78TomTom:|r CrazyArrow %s hijacked"], (wayframe.hijacked and L["is"]) or L["not"])
|
|
|
|
|
ChatFrame1:AddMessage(msg)
|
|
|
|
|
msg = string.format(L["|cffffff78TomTom:|r CrazyArrow %s visible"], (wayframe:IsVisible() and L["is"]) or L["not"])
|
|
|
|
|
ChatFrame1:AddMessage(msg)
|
|
|
|
|
msg = string.format(L["|cffffff78TomTom:|r Waypoint %s valid"], (active_point and TomTom:IsValidWaypoint(active_point) and L["is"]) or L["not"])
|
|
|
|
|
ChatFrame1:AddMessage(msg)
|
|
|
|
|
|
|
|
|
|
local dist,x,y = TomTom:GetDistanceToWaypoint(active_point)
|
|
|
|
|
msg = string.format("|cffffff78TomTom:|r Waypoint distance=%s", tostring(dist))
|
|
|
|
|
ChatFrame1:AddMessage(msg)
|
|
|
|
|
|
|
|
|
|
if wayframe:IsVisible() then
|
|
|
|
|
local point, relativeTo, relativePoint, xOfs, yOfs = wayframe:GetPoint(1)
|
|
|
|
|
relativeTo = (relativeTo and relativeTo:GetName()) or "UIParent"
|
|
|
|
|
msg = string.format("|cffffff78TomTom:|r CrazyArrow point=%s frame=%s rpoint=%s xo=%.2f yo=%.2f", point, relativeTo, relativePoint, xOfs, yOfs)
|
|
|
|
|
ChatFrame1:AddMessage(msg)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Clear the waypoint from the crazy arrow
|
|
|
|
|
-- remove: true if the waypoint should be removed entirely, otherwise
|
|
|
|
|
-- this method only clears it from the crazy arrow itself.
|
|
|
|
|
function TomTom:ClearCrazyArrowPoint(remove)
|
|
|
|
|
if active_point then
|
|
|
|
|
if remove then
|
|
|
|
|
local uid = active_point
|
|
|
|
|
TomTom:RemoveWaypoint(uid)
|
|
|
|
|
else
|
|
|
|
|
local prior = active_point
|
|
|
|
|
active_point = nil
|
|
|
|
|
if TomTom.profile.arrow.setclosest then
|
|
|
|
|
local uid = TomTom:GetClosestWaypoint()
|
|
|
|
|
if uid and uid ~= prior then
|
|
|
|
|
TomTom:SetClosestWaypoint()
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local regionsAreMetric = {
|
|
|
|
|
false, -- US
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function TomTom:RegionIsMetric()
|
|
|
|
|
if self.accountRegion == nil then
|
|
|
|
|
local gameAccountInfo = C_BattleNet.GetGameAccountInfoByGUID(UnitGUID("player"))
|
|
|
|
|
local regionID = gameAccountInfo and gameAccountInfo.regionID or GetCurrentRegion()
|
|
|
|
|
self.accountRegion = regionID
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if regionsAreMetric[self.accountRegion] ~= nil then
|
|
|
|
|
return regionsAreMetric[self.accountRegion]
|
|
|
|
|
else
|
|
|
|
|
-- Default to true
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local floor = math.floor
|
|
|
|
|
|
|
|
|
|
local function yardsToMeters(yards)
|
|
|
|
|
local meters = yards * 0.9144
|
|
|
|
|
return meters
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function humanizeYardsMiles(yards)
|
|
|
|
|
local yardsInMile = 1760 -- yards in a mile
|
|
|
|
|
local miles = floor(yards / yardsInMile)
|
|
|
|
|
local remaining = floor(yards % yardsInMile)
|
|
|
|
|
return miles, remaining
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function humanizeYardsKilometers(yards)
|
|
|
|
|
local meters = yards * 0.9144
|
|
|
|
|
local km = floor(meters / 1000)
|
|
|
|
|
local remaining = floor(meters % 1000)
|
|
|
|
|
return km, remaining
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Return the formatted distance, taking the player options
|
|
|
|
|
-- into account and converting to Metric in appropriate circumstances
|
|
|
|
|
-- Thanks to Lotimar for the contribution
|
|
|
|
|
function TomTom:GetFormattedDistance(distanceInYards)
|
|
|
|
|
local distanceMode = "humanmeters"
|
|
|
|
|
|
|
|
|
|
if self.db.profile.arrow.distanceUnits == "auto" then
|
|
|
|
|
if not self:RegionIsMetric() then
|
|
|
|
|
distanceMode = "yards"
|
|
|
|
|
end
|
|
|
|
|
elseif self.db.profile.arrow.distanceUnits == "yards" then
|
|
|
|
|
distanceMode = "yards"
|
|
|
|
|
elseif self.db.profile.arrow.distanceUnits == "meters" then
|
|
|
|
|
distanceMode = "meters"
|
|
|
|
|
elseif self.db.profile.arrow.distanceUnits == "humanyards" then
|
|
|
|
|
distanceMode = "humanyards"
|
|
|
|
|
elseif self.db.profile.arrow.distanceUnits == "humanmeters" then
|
|
|
|
|
distanceMode = "humanmeters"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if distanceMode == "humanmeters" then
|
|
|
|
|
local km, meters = humanizeYardsKilometers(distanceInYards)
|
|
|
|
|
if km == 0 then
|
|
|
|
|
return L["%dm away"]:format(meters)
|
|
|
|
|
else
|
|
|
|
|
return L["%dkm %dm away"]:format(km, meters)
|
|
|
|
|
end
|
|
|
|
|
elseif distanceMode == "humanyards" then
|
|
|
|
|
local miles, yards = humanizeYardsMiles(distanceInYards)
|
|
|
|
|
if miles == 0 then
|
|
|
|
|
return L["%d yards away"]:format(yards)
|
|
|
|
|
elseif miles == 1 then
|
|
|
|
|
return L["%d mile %d yards away"]:format(miles, yards)
|
|
|
|
|
else
|
|
|
|
|
return L["%d miles %d yards away"]:format(miles, yards)
|
|
|
|
|
end
|
|
|
|
|
elseif distanceMode == "meters" then
|
|
|
|
|
local meters = yardsToMeters(distanceInYards)
|
|
|
|
|
return L["%dm away"]:format(meters)
|
|
|
|
|
elseif distanceMode == "yards" then
|
|
|
|
|
return L["%d yards away"]:format(distanceInYards)
|
|
|
|
|
end
|
|
|
|
|
end
|