vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | ---------------------------------------------------------------------------- |
2 | -- TomTom: A navigational assistant for World of Warcraft |
||
3 | -- CrazyTaxi: A crazy-taxi style arrow used for waypoint navigation. |
||
4 | -- concept taken from MapNotes2 (Thanks to Mery for the idea, along |
||
5 | -- with the artwork.) |
||
6 | ---------------------------------------------------------------------------- |
||
7 | local function log(msg) DEFAULT_CHAT_FRAME:AddMessage(msg) end -- alias for convenience |
||
8 | --------------------------------------------------------------------------------------------------- |
||
9 | math.modf = function(number) |
||
10 | local fractional = Questie:Modulo(number, 1) |
||
11 | local integral = number - fractional |
||
12 | return integral, fractional |
||
13 | end |
||
14 | --------------------------------------------------------------------------------------------------- |
||
15 | function GetPlayerFacing() |
||
16 | local p = Minimap |
||
17 | local m = ({p:GetChildren()})[9] |
||
18 | return m:GetFacing() |
||
19 | end |
||
20 | --------------------------------------------------------------------------------------------------- |
||
21 | local sformat = string.format |
||
22 | local function ColorGradient(perc, tablee) |
||
23 | local num = table.getn(tablee) |
||
24 | local hexes = tablee[1] == "string" |
||
25 | if perc == 1 then |
||
26 | return tablee[num-2], tablee[num-1], tablee[num] |
||
27 | end |
||
28 | num = num / 3 |
||
29 | local segment, relperc = math.modf(perc*(num-1)) |
||
30 | local r1, g1, b1, r2, g2, b2 |
||
31 | r1, g1, b1 = tablee[(segment*3)+1], tablee[(segment*3)+2], tablee[(segment*3)+3] |
||
32 | r2, g2, b2 = tablee[(segment*3)+4], tablee[(segment*3)+5], tablee[(segment*3)+6] |
||
33 | if not r1 then return end |
||
34 | if not r2 or not g2 or not b2 then |
||
35 | return r1, g1, b1 |
||
36 | else |
||
37 | return r1 + (r2-r1)*relperc, |
||
38 | g1 + (g2-g1)*relperc, |
||
39 | b1 + (b2-b1)*relperc |
||
40 | end |
||
41 | end |
||
42 | --------------------------------------------------------------------------------------------------- |
||
43 | local twopi = math.pi * 2 |
||
44 | function WayFrame_OnClick() |
||
45 | if (MouseIsOver(TomTomCrazyArrow) ~= nil) and (arg1 == "RightButton") then |
||
46 | TomTomCrazyArrow:Hide() |
||
47 | end |
||
48 | end |
||
49 | --------------------------------------------------------------------------------------------------- |
||
50 | local wayframe = CreateFrame("Button", "TomTomCrazyArrow", UIParent) |
||
51 | wayframe:SetHeight(42) |
||
52 | wayframe:SetWidth(56) |
||
53 | wayframe:SetPoint("CENTER", 0, 0) |
||
54 | wayframe:EnableMouse(true) |
||
55 | wayframe:SetMovable(true) |
||
56 | wayframe:Hide() |
||
57 | -- Frame used to control the scaling of the title and friends |
||
58 | local titleframe = CreateFrame("Frame", nil, wayframe) |
||
59 | wayframe.title = titleframe:CreateFontString("OVERLAY", nil, "GameFontHighlightSmall") |
||
60 | wayframe.status = titleframe:CreateFontString("OVERLAY", nil, "GameFontNormalSmall") |
||
61 | wayframe.tta = titleframe:CreateFontString("OVERLAY", nil, "GameFontNormalSmall") |
||
62 | wayframe.title:SetPoint("TOP", wayframe, "BOTTOM", 0, 0) |
||
63 | wayframe.status:SetPoint("TOP", wayframe.title, "BOTTOM", 0, 0) |
||
64 | wayframe.tta:SetPoint("TOP", wayframe.status, "BOTTOM", 0, 0) |
||
65 | --------------------------------------------------------------------------------------------------- |
||
66 | local function OnDragStart(self, button) |
||
67 | if IsControlKeyDown() and IsShiftKeyDown() then |
||
68 | this:StartMoving() |
||
69 | wayframe:SetClampedToScreen(true); |
||
70 | end |
||
71 | end |
||
72 | --------------------------------------------------------------------------------------------------- |
||
73 | local function OnDragStop(self, button) |
||
74 | this:StopMovingOrSizing() |
||
75 | end |
||
76 | --------------------------------------------------------------------------------------------------- |
||
77 | local function OnEvent(self, event, ...) |
||
78 | if event == "ZONE_CHANGED_NEW_AREA" then |
||
79 | self:Show() |
||
80 | end |
||
81 | end |
||
82 | --------------------------------------------------------------------------------------------------- |
||
83 | wayframe:SetScript("OnDragStart", OnDragStart) |
||
84 | wayframe:SetScript("OnDragStop", OnDragStop) |
||
85 | wayframe:RegisterForDrag("LeftButton") |
||
86 | wayframe:RegisterEvent("ZONE_CHANGED_NEW_AREA") |
||
87 | wayframe:SetScript("OnEvent", OnEvent) |
||
88 | wayframe.arrow = wayframe:CreateTexture("OVERLAY") |
||
89 | wayframe.arrow:SetTexture("Interface\\AddOns\\!Questie\\Images\\Arrow") |
||
90 | wayframe.arrow:SetAllPoints() |
||
91 | --------------------------------------------------------------------------------------------------- |
||
92 | local active_point, arrive_distance, showDownArrow, point_title, arrow_objective, isHide |
||
93 | function SetCrazyArrow(point, dist, title) |
||
94 | active_point = point |
||
95 | arrive_distance = dist |
||
96 | point_title = title |
||
97 | if active_point and not isHide then |
||
98 | wayframe.title:SetText(point_title or "Unknown waypoint") |
||
99 | wayframe:Show() |
||
100 | else |
||
101 | wayframe:Hide() |
||
102 | end |
||
103 | end |
||
104 | --------------------------------------------------------------------------------------------------- |
||
105 | function SetArrowFromIcon(icon) |
||
106 | local targetPoint = { |
||
107 | ["c"] = icon.data.continent, |
||
108 | ["z"] = icon.data.zoneid, |
||
109 | ["x"] = icon.averageX, |
||
110 | ["y"] = icon.averageY |
||
111 | } |
||
112 | local quest = QuestieHashMap[icon.data.questHash] |
||
113 | local data = { |
||
114 | ["point"] = targetPoint, |
||
115 | ["questName"] = quest.name, |
||
116 | ["questLevel"] = quest.questLevel |
||
117 | } |
||
118 | SetArrowFromData(data) |
||
119 | end |
||
120 | --------------------------------------------------------------------------------------------------- |
||
121 | function SetArrowFromData(data) |
||
122 | local colorString = "|c" .. QuestieTracker:GetDifficultyColor(data.questLevel) |
||
123 | local title = colorString |
||
124 | title = title .. "[" .. data.questLevel .. "] " |
||
125 | if QuestieConfig.boldColors then |
||
126 | title = title .. "|r|cFFFFFFFF" .. data.questName .. "|r" |
||
127 | else |
||
128 | title = title .. data.questName .. "|r" |
||
129 | end |
||
130 | SetCrazyArrow(data.point, 0, title) |
||
131 | arrow_objective = nil |
||
132 | arrow_data = data |
||
133 | end |
||
134 | --------------------------------------------------------------------------------------------------- |
||
135 | function SetArrowObjective(hash) |
||
136 | if arrow_objective == hash then |
||
137 | wayframe:Hide(); |
||
138 | arrow_objective = 0; |
||
139 | return; |
||
140 | end |
||
141 | arrow_objective = hash |
||
142 | arrow_data = nil |
||
143 | if not QuestieCachedQuests[hash] or not QuestieCachedQuests[hash]["arrowPoint"] then return end |
||
144 | local objective = QuestieCachedQuests[hash]["arrowPoint"] |
||
145 | SetCrazyArrow(objective, objective.dist, objective.title) |
||
146 | end |
||
147 | --------------------------------------------------------------------------------------------------- |
||
148 | function RemoveCrazyArrow(hash) |
||
149 | if hash then |
||
150 | if (TomTomCrazyArrow:IsVisible() ~= nil) and (arrow_objective == hash or arrow_data) then |
||
151 | TomTomCrazyArrow:Hide() |
||
152 | end |
||
153 | end |
||
154 | if (QuestieConfig.arrowEnabled == false) then |
||
155 | TomTomCrazyArrow:Hide() |
||
156 | end |
||
157 | end |
||
158 | --------------------------------------------------------------------------------------------------- |
||
159 | local status = wayframe.status; |
||
160 | local tta = wayframe.tta; |
||
161 | local arrow = wayframe.arrow; |
||
162 | local arrowLastUpdate = 0; |
||
163 | local LastPlayerPosition = {}; |
||
164 | local count = 0; |
||
165 | local last_distance = 0; |
||
166 | local tta_throttle = 0; |
||
167 | local speed = 0; |
||
168 | local speed_count = 0; |
||
169 | local function OnUpdate(self, elapsed) |
||
170 | local self = this |
||
171 | local elapsed = 1/GetFramerate() |
||
172 | local dist,x,y |
||
173 | if not UnitIsDeadOrGhost("player") then |
||
174 | if arrow_objective then |
||
175 | if QuestieCachedQuests[arrow_objective] then |
||
176 | local objective = QuestieCachedQuests[arrow_objective]["arrowPoint"] |
||
177 | if objective then |
||
178 | SetCrazyArrow(objective, objective.dist, objective.title) |
||
179 | end |
||
180 | else |
||
181 | self:Hide() |
||
182 | end |
||
183 | elseif arrow_data then |
||
184 | SetArrowFromData(arrow_data) |
||
185 | end |
||
186 | if not active_point then |
||
187 | self:Hide() |
||
188 | return |
||
189 | end |
||
190 | end |
||
191 | --While dead this maintains the corpseArrow |
||
192 | if UnitIsDeadOrGhost("player") and (UnitIsDead("player") ~= 1) and (bgactive == false) then |
||
193 | Questie:OnUpdate(elapsed) |
||
194 | end |
||
195 | local dist,x,y = GetDistanceToIcon(active_point) |
||
196 | if GetTime() - arrowLastUpdate >= .04 then |
||
197 | if (TomTomCrazyArrow:IsVisible() ~= nil) then |
||
198 | if not dist or IsInInstance() then |
||
199 | if not active_point.x and not active_point.y then |
||
200 | active_point = nil |
||
201 | end |
||
202 | self:Hide() |
||
203 | return |
||
204 | end |
||
205 | status:SetText(sformat("%d yards", dist)) |
||
206 | local cell |
||
207 | -- Showing the arrival arrow? |
||
208 | if dist <= 5 then |
||
209 | if not showDownArrow then |
||
210 | arrow:SetHeight(70) |
||
211 | arrow:SetWidth(53) |
||
212 | arrow:SetTexture("Interface\\AddOns\\!Questie\\Images\\Arrow-UP") |
||
213 | arrow:SetVertexColor(0, 1, 0) |
||
214 | showDownArrow = true |
||
215 | end |
||
216 | count = count + 1 |
||
217 | if count >= 55 then |
||
218 | count = 0 |
||
219 | end |
||
220 | cell = count |
||
221 | local column = Questie:Modulo(cell, 9) |
||
222 | local row = floor(cell / 9) |
||
223 | local xstart = (column * 53) / 512 |
||
224 | local ystart = (row * 70) / 512 |
||
225 | local xend = ((column + 1) * 53) / 512 |
||
226 | local yend = ((row + 1) * 70) / 512 |
||
227 | arrow:SetTexCoord(xstart,xend,ystart,yend) |
||
228 | else |
||
229 | if showDownArrow then |
||
230 | arrow:SetHeight(56) |
||
231 | arrow:SetWidth(42) |
||
232 | arrow:SetTexture("Interface\\AddOns\\!Questie\\Images\\Arrow") |
||
233 | showDownArrow = false |
||
234 | end |
||
235 | local degtemp = GetDirectionToIcon(active_point); |
||
236 | if degtemp < 0 then degtemp = degtemp + 360; end |
||
237 | local angle = math.rad(degtemp) |
||
238 | local player = GetPlayerFacing() + 0.1 |
||
239 | angle = angle - player |
||
240 | local perc = 1- math.abs(((math.pi - math.abs(angle)) / math.pi)) |
||
241 | local gr,gg,gb = 1, 1, 1 |
||
242 | local mr,mg,mb = 0.75, 0.75, 0.75 |
||
243 | local br,bg,bb = 0.5, 0.5, 0.5 |
||
244 | local tablee = {}; |
||
245 | table.insert(tablee, gr) |
||
246 | table.insert(tablee, gg) |
||
247 | table.insert(tablee, gb) |
||
248 | table.insert(tablee, mr) |
||
249 | table.insert(tablee, mg) |
||
250 | table.insert(tablee, mb) |
||
251 | table.insert(tablee, br) |
||
252 | table.insert(tablee, bg) |
||
253 | table.insert(tablee, bb) |
||
254 | local r,g,b = ColorGradient(perc,tablee) |
||
255 | if not g then |
||
256 | g = 0; |
||
257 | end |
||
258 | arrow:SetVertexColor(1-g,-1+g*2,0) |
||
259 | cell = Questie:Modulo(floor(angle / twopi * 108 + 0.5), 108); |
||
260 | local column = Questie:Modulo(cell, 9) |
||
261 | local row = floor(cell / 9) |
||
262 | local xstart = (column * 56) / 512 |
||
263 | local ystart = (row * 42) / 512 |
||
264 | local xend = ((column + 1) * 56) / 512 |
||
265 | local yend = ((row + 1) * 42) / 512 |
||
266 | arrow:SetTexCoord(xstart,xend,ystart,yend) |
||
267 | end |
||
268 | arrowLastUpdate = GetTime() |
||
269 | end |
||
270 | end |
||
271 | if (QuestieConfig.arrowTime == true) then |
||
272 | -- Calculate the TTA every second (%01d:%02d) |
||
273 | tta_throttle = tta_throttle + elapsed |
||
274 | if tta_throttle >= 1 then |
||
275 | -- Calculate the speed in yards per sec at which we're moving |
||
276 | local current_speed = (last_distance - dist) / tta_throttle |
||
277 | if last_distance == 0 then |
||
278 | current_speed = 0 |
||
279 | end |
||
280 | if speed_count < 2 then |
||
281 | speed = (speed + current_speed) / 2 |
||
282 | speed_count = speed_count + 1 |
||
283 | else |
||
284 | speed_count = 0 |
||
285 | speed = current_speed |
||
286 | end |
||
287 | if speed > 0 then |
||
288 | local eta = math.abs(dist / speed) |
||
289 | local text = string.format("%01d:%02d", eta / 60, Questie:Modulo(eta, 60)) |
||
290 | tta:SetText(text) |
||
291 | else |
||
292 | tta:SetText("***") |
||
293 | end |
||
294 | last_distance = dist |
||
295 | tta_throttle = 0 |
||
296 | end |
||
297 | end |
||
298 | end |
||
299 | --------------------------------------------------------------------------------------------------- |
||
300 | function ShowHideCrazyArrow() |
||
301 | if wayframe:IsShown() then |
||
302 | wayframe:Show() |
||
303 | if true then |
||
304 | wayframe:EnableMouse(false) |
||
305 | else |
||
306 | wayframe:EnableMouse(true) |
||
307 | end |
||
308 | -- Set the scale and alpha |
||
309 | wayframe:SetScale(1) |
||
310 | wayframe:SetAlpha(1) |
||
311 | local width = 80 |
||
312 | local height = 80 |
||
313 | local scale = 1 |
||
314 | wayframe.title:SetWidth(width) |
||
315 | wayframe.title:SetHeight(height) |
||
316 | titleframe:SetScale(scale) |
||
317 | titleframe:SetAlpha(1) |
||
318 | if true then |
||
319 | tta:Show() |
||
320 | else |
||
321 | tta:Hide() |
||
322 | end |
||
323 | else |
||
324 | wayframe:Hide() |
||
325 | end |
||
326 | end |
||
327 | --------------------------------------------------------------------------------------------------- |
||
328 | function ArrowHidden() |
||
329 | isHide = true |
||
330 | end |
||
331 | --------------------------------------------------------------------------------------------------- |
||
332 | function ArrowShown() |
||
333 | isHide = false |
||
334 | end |
||
335 | --------------------------------------------------------------------------------------------------- |
||
336 | wayframe:SetScript("OnUpdate", OnUpdate) |
||
337 | wayframe:RegisterForClicks("RightButtonUp") |
||
338 | wayframe:SetScript("OnClick", WayFrame_OnClick) |
||
339 | local function getCoords(column, row) |
||
340 | local xstart = (column * 56) / 512 |
||
341 | local ystart = (row * 42) / 512 |
||
342 | local xend = ((column + 1) * 56) / 512 |
||
343 | local yend = ((row + 1) * 42) / 512 |
||
344 | return xstart, xend, ystart, yend |
||
345 | end |
||
346 | --------------------------------------------------------------------------------------------------- |
||
347 | --this is where texcoords are extracted incorrectly (I think), leading the arrow to not point in the correct direction |
||
348 | local texcoords = setmetatable({}, {__index = function(t, k) |
||
349 | -- this was k:match("(%d+):(%d+)") - so we need string.match, but that's not in Lua 5.0 |
||
350 | local fIndex, lIndex = string.find(k, "(%d+)") |
||
351 | local col = string.sub(k, fIndex, lIndex) |
||
352 | fIndex2, lIndex2 = string.find(k, ":(%d+)") |
||
353 | local row = string.sub(k, fIndex2+1, lIndex2) |
||
354 | col,row = tonumber(col), tonumber(row) |
||
355 | local obj = {getCoords(col, row)} |
||
356 | rawset(t, k, obj) |
||
357 | return obj |
||
358 | end}) |
||
359 | --------------------------------------------------------------------------------------------------- |
||
360 | wayframe:RegisterEvent("ADDON_LOADED") |
||
361 | local runonce = true |
||
362 | wayframe:SetScript("OnEvent", function(self, event, arg1, ...) |
||
363 | if runonce == true then |
||
364 | local feed_crazy = CreateFrame("Frame") |
||
365 | local crazyFeedFrame = CreateFrame("Frame") |
||
366 | local throttle = 1 |
||
367 | local counter = 0 |
||
368 | crazyFeedFrame:SetScript("OnUpdate", function(self, elapsed) |
||
369 | elapsed = 1/GetFramerate() |
||
370 | counter = counter + elapsed |
||
371 | if counter < throttle then |
||
372 | return |
||
373 | end |
||
374 | counter = 0 |
||
375 | local angle = GetDirectionToIcon(active_point) |
||
376 | local player = GetPlayerFacing() |
||
377 | if not angle or not player then |
||
378 | feed_crazy.iconCoords = texcoords["1:1"] |
||
379 | feed_crazy.iconR = 0.2 |
||
380 | feed_crazy.iconG = 1.0 |
||
381 | feed_crazy.iconB = 0.2 |
||
382 | feed_crazy.text = "No waypoint" |
||
383 | return |
||
384 | end |
||
385 | angle = angle - player |
||
386 | local perc = math.abs((math.pi - math.abs(angle)) / math.pi) |
||
387 | local gr,gg,gb = 1, 1, 1 |
||
388 | local mr,mg,mb = 0.75, 0.75, 0.75 |
||
389 | local br,bg,bb = 0.5, 0.5, 0.5 |
||
390 | local tablee = {}; |
||
391 | table.insert(tablee, gr) |
||
392 | table.insert(tablee, gg) |
||
393 | table.insert(tablee, gb) |
||
394 | table.insert(tablee, mr) |
||
395 | table.insert(tablee, mg) |
||
396 | table.insert(tablee, mb) |
||
397 | table.insert(tablee, br) |
||
398 | table.insert(tablee, bg) |
||
399 | table.insert(tablee, bb) |
||
400 | local r,g,b = ColorGradient(perc, tablee) |
||
401 | feed_crazy.iconR = r |
||
402 | feed_crazy.iconG = g |
||
403 | feed_crazy.iconB = b |
||
404 | cell = Questie:Modulo(floor(angle / twopi * 108 + 0.5) ,108) |
||
405 | local column = Questie:Modulo(cell, 9) |
||
406 | local row = floor(cell / 9) |
||
407 | local key = column .. ":" .. row |
||
408 | feed_crazy.iconCoords = texcoords[key] |
||
409 | feed_crazy.text = point_title or "Unknown waypoint" |
||
410 | end) |
||
411 | end |
||
412 | runonce = false |
||
413 | end) |
||
414 | --------------------------------------------------------------------------------------------------- |
||
415 | -- calculations have to be redone - we are NOT actually working with Astrolabe "icons" here as TomTom did and want the arrow API |
||
416 | -- to be accessible to everyone |
||
417 | function GetDirectionToIcon( point ) |
||
418 | if not point then return end |
||
419 | local C,Z,X,Y = Astrolabe:GetCurrentPlayerPosition() -- continent, zone, x, y |
||
420 | local dist, xDelta, yDelta = Astrolabe:ComputeDistance( C, Z, X, Y, point.c, point.z, point.x, point.y ) |
||
421 | if not xDelta or not yDelta then return end |
||
422 | local dir = atan2(xDelta, -(yDelta)) |
||
423 | if ( dir > 0 ) then |
||
424 | return twopi - dir; |
||
425 | else |
||
426 | return -dir; |
||
427 | end |
||
428 | end |
||
429 | --------------------------------------------------------------------------------------------------- |
||
430 | function GetDistanceToIcon( point ) |
||
431 | local C,Z,X,Y = Astrolabe:GetCurrentPlayerPosition() -- continent, zone, x, y |
||
432 | local dist, xDelta, yDelta = Astrolabe:ComputeDistance( C, Z, X, Y, point.c, point.z, point.x, point.y ) |
||
433 | return dist, xDelta, yDelta |
||
434 | end |