1 QuestHelper_File
["arrow.lua"] = "Development Version"
2 QuestHelper_Loadtime
["arrow.lua"] = GetTime()
4 --[[ This entire file is pretty liberally ganked from TomTom (and then modified) under the following license:
6 -------------------------------------------------------------------------
7 Copyright (c) 2006-2007, James N. Whitehead II
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are
14 * Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above
17 copyright notice, this list of conditions and the following
18 disclaimer in the documentation and/or other materials provided
19 with the distribution.
20 * The name or alias of the copyright holder may not be used to endorse
21 or promote products derived from this software without specific prior
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 ---------------------------------------------------------------------------
39 local function ColorGradient(perc
, ...)
40 local num
= select("#", ...)
41 local hexes
= type(select(1, ...)) == "string"
44 return select(num
-2, ...), select(num
-1, ...), select(num
, ...)
49 local segment
, relperc
= math
.modf(perc
*(num
-1))
50 local r1
, g1
, b1
, r2
, g2
, b2
51 r1
, g1
, b1
= select((segment
*3)+1, ...), select((segment
*3)+2, ...), select((segment
*3)+3, ...)
52 r2
, g2
, b2
= select((segment
*3)+4, ...), select((segment
*3)+5, ...), select((segment
*3)+6, ...)
54 if not r2
or not g2
or not b2
then
57 return r1
+ (r2
-r1
)*relperc
,
63 local wayframe
= CreateFrame("Button", "QHArrowFrame", UIParent
)
64 wayframe
:SetPoint("CENTER", -300, 300)
65 wayframe
:EnableMouse(true)
66 wayframe
:SetMovable(true)
67 wayframe
:SetUserPlaced(true)
72 -- Frame used to control the scaling of the title and friends
73 local titleframe
= CreateFrame("Frame", nil, wayframe
)
75 wayframe
.title
= titleframe
:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
76 wayframe
.status
= titleframe
:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
77 wayframe
.tta
= titleframe
:CreateFontString("OVERLAY", nil, "GameFontNormalSmall")
78 wayframe
.title
:SetPoint("TOP", wayframe
, "BOTTOM", 0, 0)
79 wayframe
.status
:SetPoint("TOP", wayframe
.title
, "BOTTOM", 0, 0)
80 wayframe
.tta
:SetPoint("TOP", wayframe
.status
, "BOTTOM", 0, 0)
81 local default_font_name
, default_font_size
, default_font_flags
= wayframe
.title
:GetFont()
84 local r
, g
, b
, a
= wayframe
.status
:GetTextColor()
85 r
, g
, b
= r
- 0.2, g
- 0.2, b
- 0.2
86 wayframe
.status
:SetTextColor(r
, g
, b
, a
)
91 local function OnDragStart(self
, button
)
92 if not QuestHelper_Pref
.arrow_locked
then -- TODO TWEAKERY
97 local function OnDragStop(self
, button
)
98 self
:StopMovingOrSizing()
101 local function OnEvent(self
, event
, ...)
102 if event
== "ZONE_CHANGED_NEW_AREA" and QuestHelper_Pref
.arrow
and not QuestHelper_Pref
.hide
then -- TODO TWEAKERY
108 wayframe
:SetScript("OnDragStart", OnDragStart
)
109 wayframe
:SetScript("OnDragStop", OnDragStop
)
110 wayframe
:RegisterForDrag("LeftButton")
111 wayframe
:RegisterEvent("ZONE_CHANGED_NEW_AREA")
112 wayframe
:SetScript("OnEvent", OnEvent
)
114 wayframe
.arrow
= wayframe
:CreateTexture("OVERLAY")
115 --wayframe.arrow:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image_down") -- if we don't do this, the image doesn't seem to end up cached. :blizzard:
116 wayframe
.arrow
:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image")
117 wayframe
.arrow
:SetAllPoints()
119 local active_point
, arrive_distance
, showDownArrow
, point_title
122 function QH_Arrow_Show()
126 function QH_Arrow_Reset()
127 QuestHelper_Pref
.arrow
= true
128 wayframe
:ClearAllPoints()
129 wayframe
:SetPoint("CENTER", 0, 0)
130 QuestHelper_Pref
.arrow_locked
= false -- they're probably going to want to move it
134 function QH_Arrow_SetScale(scale
)
136 QuestHelper_Pref
.arrow_arrowsize
= scale
138 scale
= QuestHelper_Pref
.arrow_arrowsize
141 if not showDownArrow
then
142 wayframe
:SetHeight(42 * scale
)
143 wayframe
:SetWidth(56 * scale
)
146 wayframe
:SetHeight(70 * scale
)
147 wayframe
:SetWidth(53 * scale
)
151 function QH_Arrow_SetTextScale(scale
)
153 QuestHelper_Pref
.arrow_textsize
= scale
155 scale
= QuestHelper_Pref
.arrow_textsize
158 wayframe
.title
:SetFont(default_font_name
, default_font_size
* scale
, default_font_flags
)
159 wayframe
.status
:SetFont(default_font_name
, default_font_size
* scale
, default_font_flags
)
160 wayframe
.tta
:SetFont(default_font_name
, default_font_size
* scale
, default_font_flags
)
163 local function wpupdate(c
, z
, x
, y
, desc
)
165 QuestHelper
: Assert(z
)
166 QuestHelper
: Assert(x
)
167 QuestHelper
: Assert(y
)
169 QuestHelper
: Assert(not z
)
170 QuestHelper
: Assert(not x
)
171 QuestHelper
: Assert(not y
)
173 active_point
.c
, active_point
.z
, active_point
.x
, active_point
.y
= c
, z
, x
, y
174 wayframe
.title
:SetText(desc
)
176 OnUpdate(wayframe
, nil)
179 QuestHelper
:AddWaypointCallback(wpupdate
)
181 local status
= wayframe
.status
182 local tta
= wayframe
.tta
183 local arrow
= wayframe
.arrow
184 local last_distance
= 0
185 local tta_throttle
= 0
187 local speed_count
= 0
189 OnUpdate
= function(self
, elapsed
)
190 QuestHelper
: Assert(self
)
192 if not active_point
.c
or QuestHelper
.collect_rc
~= active_point
.c
or QuestHelper
.collect_delayed
or QuestHelper
.InBrokenInstance
or not QuestHelper_Pref
.arrow
then
197 local dist
, dx
, dy
= QuestHelper
.Astrolabe
:ComputeDistance(QuestHelper
.collect_rc
, QuestHelper
.collect_rz
, QuestHelper
.collect_rx
, QuestHelper
.collect_ry
, active_point
.c
, active_point
.z
, active_point
.x
, active_point
.y
)
202 -- I had support for miles and kilometers, but decided that distances were rarely large
203 -- enough to warrent it.
204 if QuestHelper_Pref
.metric
then
205 text
= QHFormat("DISTANCE_METRES", math
.floor(0.5+dist
*0.9144))
207 text
= QHFormat("DISTANCE_YARDS", math
.floor(0.5 + dist
))
213 -- Showing the arrival arrow?
214 if dist
and dist
<= 10 then
215 if not showDownArrow
then
218 arrow
:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image_down")
219 arrow
:SetVertexColor(0, 1, 0)
222 local cell
= math
.floor(mod(GetTime() * 20, 55)) -- 20 fps seems to be around the right number
224 local column
= cell
% 9
225 local row
= floor(cell
/ 9)
227 local xstart
= (column
* 53) / 512
228 local ystart
= (row
* 70) / 512
229 local xend
= ((column
+ 1) * 53) / 512
230 local yend
= ((row
+ 1) * 70) / 512
231 arrow
:SetTexCoord(xstart
,xend
,ystart
,yend
)
233 if showDownArrow
then
234 showDownArrow
= false
236 arrow
:SetTexture("Interface\\AddOns\\QuestHelper\\arrow_image")
237 showDownArrow
= false
240 local angle
= atan2(-dx
, -dy
) / 360 * (math
.pi
* 2) -- degrees. seriously what
241 --if angle < 0 then angle = angle + math.pi * 2 end
242 local player
= GetPlayerFacing()
243 angle
= angle
- player
245 local perc
= math
.abs((math
.pi
- math
.abs(angle
)) / math
.pi
)
246 if perc
> 1 then perc
= 2 - perc
end -- siiigh
248 local gr
,gg
,gb
= 0, 1, 0
249 local mr
,mg
,mb
= 1, 1, 0
250 local br
,bg
,bb
= 1, 0, 0
251 local r
,g
,b
= ColorGradient(perc
, br
, bg
, bb
, mr
, mg
, mb
, gr
, gg
, gb
)
252 arrow
:SetVertexColor(r
,g
,b
)
255 local cell
= floor(angle
/ (math
.pi
* 2) * 108 + 0.5) % 108
256 local column
= cell
% 9
257 local row
= floor(cell
/ 9)
259 local xstart
= (column
* 56) / 512
260 local ystart
= (row
* 42) / 512
261 local xend
= ((column
+ 1) * 56) / 512
262 local yend
= ((row
+ 1) * 42) / 512
263 arrow
:SetTexCoord(xstart
,xend
,ystart
,yend
)
266 -- Calculate the TTA every second (%01d:%02d)
270 tta_throttle = tta_throttle + elapsed
272 if tta_throttle >= 1.0 then
273 -- Calculate the speed in yards per sec at which we're moving
274 local current_speed = (last_distance - dist) / tta_throttle
276 if last_distance == 0 then
280 if speed_count < 2 then
281 speed = (speed + current_speed) / 2
282 speed_count = speed_count + 1
285 speed = current_speed
289 local eta = math.abs(dist / speed)
290 tta:SetFormattedText("%01d:%02d", eta / 60, eta % 60)
302 wayframe
:SetScript("OnUpdate", OnUpdate
)
305 local function spacer()
306 local htex
= QuestHelper
:CreateIconTexture(item
, 10)
307 htex
:SetVertexColor(1, 1, 1, 0)
311 function QH_Arrow_PopulateMenu(menu
)
312 local hide
= QuestHelper
:CreateMenuItem(menu
, QuestHelper_Pref
.arrow
and QHText("QH_BUTTON_HIDE") or QHText("QH_BUTTON_SHOW"))
313 hide
:SetFunction(function () QuestHelper
:ToggleArrow() end)
314 --hide:AddTexture(spacer(), true)
315 --hide:AddTexture(spacer(), false)
317 local lock
= QuestHelper
:CreateMenuItem(menu
, "Lock")
318 local ltex
= QuestHelper
:CreateIconTexture(item
, 10)
319 lock
:SetFunction(function () QuestHelper_Pref
.arrow_locked
= not QuestHelper_Pref
.arrow_locked
end)
320 lock
:AddTexture(ltex
, true)
321 lock
:AddTexture(spacer(), false)
322 ltex
:SetVertexColor(1, 1, 1, QuestHelper_Pref
.arrow_locked
and 1 or 0)
324 local scale
= QuestHelper
:CreateMenuItem(menu
, "Arrow Scale")
325 local scale_menu
= QuestHelper
:CreateMenu()
326 scale
:SetSubmenu(scale_menu
)
327 scale
:AddTexture(spacer(), true)
329 local it
= QuestHelper
:CreateMenuItem(scale_menu
, string.format("%d%%", i
* 10))
331 it
:SetFunction(function () QH_Arrow_SetScale(ix
/ 10) end)
332 local icon
= QuestHelper
:CreateIconTexture(item
, 10)
333 if QuestHelper_Pref
.arrow_arrowsize
== ix
/ 10 then
334 icon
:SetVertexColor(1, 1, 1, 1)
336 icon
:SetVertexColor(1, 1, 1, 0)
341 local tscale
= QuestHelper
:CreateMenuItem(menu
, "Text Scale")
342 local tscale_menu
= QuestHelper
:CreateMenu()
343 tscale
:SetSubmenu(tscale_menu
)
344 tscale
:AddTexture(spacer(), true)
346 local it
= QuestHelper
:CreateMenuItem(tscale_menu
, string.format("%d%%", i
* 10))
348 it
:SetFunction(function () QH_Arrow_SetTextScale(ix
/ 10) end)
349 local icon
= QuestHelper
:CreateIconTexture(item
, 10)
350 if QuestHelper_Pref
.arrow_textsize
== ix
/ 10 then
351 icon
:SetVertexColor(1, 1, 1, 1)
353 icon
:SetVertexColor(1, 1, 1, 0)
358 local reset
= QuestHelper
:CreateMenuItem(menu
, QHText("SETTINGS_MENU_ARROW_RESET"))
359 reset
:SetFunction(function () QH_Arrow_Reset() end)
362 local function WayFrame_OnClick(self
, button
)
363 local menu
= QuestHelper
:CreateMenu()
364 QuestHelper
:CreateMenuTitle(menu
, QHText("SETTINGS_ARROWLINK_ARROW"))
366 QH_Arrow_PopulateMenu(menu
)
371 wayframe
:RegisterForClicks("RightButtonUp")
372 wayframe
:SetScript("OnClick", WayFrame_OnClick
)