arrrrrow
[QuestHelper.git] / dodads.lua
bloba4b343de4b1b35ff5e12359497baa809b4ede419
1 QuestHelper_File["dodads.lua"] = "Development Version"
2 QuestHelper_Loadtime["dodads.lua"] = GetTime()
4 local ofs = 0.000723339 * (GetScreenHeight()/GetScreenWidth() + 1/3) * 70.4;
5 local radius = ofs / 1.166666666666667;
7 local function convertLocation(p)
8 local c, x, y = p[1].c, p[3], p[4]
9 x, y = x/QuestHelper.continent_scales_x[c], y/QuestHelper.continent_scales_y[c]
10 return c, 0, x, y
11 end
13 local function convertLocationToScreen(p, c, z)
14 return QuestHelper.Astrolabe:TranslateWorldMapPosition(p[1].c, 0, p[3]/QuestHelper.continent_scales_x[p[1].c], p[4]/QuestHelper.continent_scales_y[p[1].c], c, z)
15 end
17 local function convertNodeToScreen(n, c, z)
18 return QuestHelper.Astrolabe:TranslateWorldMapPosition(n.c, 0, n.x/QuestHelper.continent_scales_x[n.c], n.y/QuestHelper.continent_scales_y[n.c], c, z)
19 end
21 QuestHelper.map_overlay = CreateFrame("FRAME", nil, WorldMapButton)
22 QuestHelper.map_overlay:SetFrameLevel(WorldMapButton:GetFrameLevel()+1)
23 QuestHelper.map_overlay:SetAllPoints()
24 QuestHelper.map_overlay:SetFrameStrata("FULLSCREEN")
26 local function ClampLine(x1, y1, x2, y2)
27 if x1 and y1 and x2 and y2 then
28 local x_div, y_div = (x2-x1), (y2-y1)
29 local x_0 = y1-x1/x_div*y_div
30 local x_1 = y1+(1-x1)/x_div*y_div
31 local y_0 = x1-y1/y_div*x_div
32 local y_1 = x1+(1-y1)/y_div*x_div
34 if y1 < 0 then
35 x1 = y_0
36 y1 = 0
37 end
39 if y2 < 0 then
40 x2 = y_0
41 y2 = 0
42 end
44 if y1 > 1 then
45 x1 = y_1
46 y1 = 1
47 end
49 if y2 > 1 then
50 x2 = y_1
51 y2 = 1
52 end
54 if x1 < 0 then
55 y1 = x_0
56 x1 = 0
57 end
59 if x2 < 0 then
60 y2 = x_0
61 x2 = 0
62 end
64 if x1 > 1 then
65 y1 = x_1
66 x1 = 1
67 end
69 if x2 > 1 then
70 y2 = x_1
71 x2 = 1
72 end
74 if x1 >= 0 and x2 >= 0 and y1 >= 0 and y2 >= 0 and x1 <= 1 and x2 <= 1 and y1 <= 1 and y2 <= 1 then
75 return x1, y1, x2, y2
76 end
77 end
78 end
80 local function pushPath(list, path, c, z)
81 if path then
82 pushPath(list, path.p, c, z)
83 local t = QuestHelper:CreateTable()
84 t[1], t[2] = QuestHelper.Astrolabe:TranslateWorldMapPosition(path.c, 0, path.x/QuestHelper.continent_scales_x[path.c], path.y/QuestHelper.continent_scales_y[path.c], c, z)
85 table.insert(list, t)
86 end
87 end
89 function QuestHelper:CreateWorldMapWalker()
90 local walker = CreateFrame("Button", nil, QuestHelper.map_overlay)
91 walker:SetWidth(0)
92 walker:SetHeight(0)
93 walker:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", 0, 0)
94 walker:Show()
96 walker.phase = 0.0
97 walker.dots = {}
98 walker.points = {}
99 walker.origin = {}
100 walker.frame = self
101 walker.map_dodads = {}
102 walker.used_map_dodads = 0
104 function walker:OnUpdate(elapsed)
105 local out = 0
107 if QuestHelper_Pref.show_ants then
108 local points = self.points
110 self.phase = self.phase + elapsed * 0.66
111 while self.phase > 1 do self.phase = self.phase - 1 end
113 local w, h = QuestHelper.map_overlay:GetWidth(), -QuestHelper.map_overlay:GetHeight()
115 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
117 local last_x, last_y = self.frame.Astrolabe:TranslateWorldMapPosition(self.frame.c, self.frame.z, self.frame.x, self.frame.y, c, z) local remainder = self.phase
119 for i, pos in ipairs(points) do
120 local new_x, new_y = unpack(pos)
121 local x1, y1, x2, y2 = ClampLine(last_x, last_y, new_x, new_y)
122 last_x, last_y = new_x, new_y
124 if x1 then
125 local len = math.sqrt((x1-x2)*(x1-x2)*16/9+(y1-y2)*(y1-y2))
127 if len > 0.0001 then
128 local interval = .025/len
129 local p = remainder*interval
131 while p < 1 do
132 out = out + 1
133 local dot = self.dots[out]
134 if not dot then
135 dot = QuestHelper:CreateDotTexture(self)
136 dot:SetDrawLayer("BACKGROUND")
137 self.dots[out] = dot
140 dot:ClearAllPoints()
141 dot:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x1*w*(1-p)+x2*w*p, y1*h*(1-p)+y2*h*p)
143 p = p + interval
146 remainder = (p-1)/interval
152 while #self.dots > out do
153 QuestHelper:ReleaseTexture(table.remove(self.dots))
157 function walker:RouteChanged()
158 if self.frame.Astrolabe.WorldMapVisible then
159 for i, obj in pairs(self.frame.route) do
160 if not obj.pos then
161 -- No. Just no.
162 --QuestHelper:AppendNotificationError("10-10-2008 pathfinding/dodads nil coroutine race condition bug")
163 return -- return "failure :("
167 local points = self.points
168 local cur = self.frame.pos
170 while #points > 0 do self.frame:ReleaseTable(table.remove(points)) end
172 local travel_time = 0.0
174 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
176 if self.frame.target then
177 travel_time = math.max(0, self.frame.target_time-time())
178 cur = self.frame.target
179 local t = self.frame:CreateTable()
180 t[1], t[2] = convertLocationToScreen(cur, c, z)
181 table.insert(points, t)
184 for i, obj in pairs(self.frame.route) do
185 local path, d = self.frame:ComputeRoute(cur, obj.pos)
187 pushPath(points, path, c, z)
189 travel_time = travel_time + d
190 obj.travel_time = travel_time
192 cur = obj.pos
194 local t = self.frame:CreateTable()
195 t[1], t[2] = convertLocationToScreen(cur, c, z)
197 table.insert(points, t)
200 for i = 1, #self.frame.route do
201 local dodad = self.map_dodads[i]
202 if not dodad then
203 self.map_dodads[i] = self.frame:CreateWorldMapDodad(self.frame.route[i], i)
204 else
205 self.map_dodads[i]:SetObjective(self.frame.route[i], i)
209 for i = #self.frame.route+1,self.used_map_dodads do
210 self.map_dodads[i]:SetObjective(nil, 0)
213 self.used_map_dodads = #self.frame.route
217 walker:SetScript("OnEvent", walker.RouteChanged)
218 walker:RegisterEvent("WORLD_MAP_UPDATE")
220 walker:SetScript("OnUpdate", walker.OnUpdate)
222 return walker
225 function QuestHelper:GetOverlapObjectives(obj)
226 local w, h = self.map_overlay:GetWidth(), self.map_overlay:GetHeight()
227 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
229 local list = self.overlap_list
231 if not list then
232 list = {}
233 self.overlap_list = list
234 else
235 while table.remove(list) do end
238 local cx, cy = GetCursorPosition()
240 local es = QuestHelper.map_overlay:GetEffectiveScale()
241 local ies = 1/es
243 cx, cy = (cx-self.map_overlay:GetLeft()*es)*ies, (self.map_overlay:GetTop()*es-cy)*ies
245 local s = 10*QuestHelper_Pref.scale
247 for i, o in ipairs(self.route) do
248 --QuestHelper: Assert(o, string.format("nil dodads pos issue, o %s", tostring(o)))
249 --QuestHelper: Assert(o.pos, string.format("nil dodads pos issue, pos %s", QuestHelper:StringizeTable(o)))
250 if o == obj then
251 table.insert(list, o)
252 elseif o.pos then -- as near as I can tell, there's some curious coroutine contention going on here, and it's possible that things don't have a position even though they're in the route. If they don't have a position, we don't need to add them to a list - this function is (I think) only called for the tooltips. Therefore, either it no longer exists on the main map, or it's about to vanish from the main map. Go go gadget someone-else's-problem-field!
253 local x, y = o.pos[3], o.pos[4]
254 x, y = x / self.continent_scales_x[o.pos[1].c], y / self.continent_scales_y[o.pos[1].c]
255 x, y = self.Astrolabe:TranslateWorldMapPosition(o.pos[1].c, 0, x, y, c, z)
257 if x and y and x > 0 and y > 0 and x < 1 and y < 1 then
258 x, y = x*w, y*h
260 if cx >= x-s and cy >= y-s and cx <= x+s and cy <= y+s then
261 table.insert(list, o)
267 table.sort(list, function(a, b) return (a.travel_time or 0) < (b.travel_time or 0) end)
269 return list
272 local prog_sort_table = {}
274 function QuestHelper:AppendObjectiveProgressToTooltip(o, tooltip, font, depth)
275 if o.progress then
276 local theme = self:GetColourTheme()
278 local indent = (" "):rep(depth or 0)
280 for user, progress in pairs(o.progress) do
281 table.insert(prog_sort_table, user)
284 table.sort(prog_sort_table, function(a, b)
285 if o.progress[a][3] < o.progress[b][3] then
286 return true
287 elseif o.progress[a][3] == o.progress[b][3] then
288 return a < b
290 return false
291 end)
293 for i, u in ipairs(prog_sort_table) do
294 tooltip:AddDoubleLine(indent..QHFormat("PEER_PROGRESS", u),
295 self:ProgressString(o.progress[u][1].."/"..o.progress[u][2],
296 o.progress[u][3]), unpack(theme.tooltip))
298 if font then
299 local last, name = tooltip:NumLines(), tooltip:GetName()
300 local left, right = _G[name.."TextLeft"..last], _G[name.."TextRight"..last]
302 left:SetFont(font, 13)
303 right:SetFont(font, 13)
307 while table.remove(prog_sort_table) do end
311 function QuestHelper:AppendObjectiveToTooltip(o)
312 local theme = self:GetColourTheme()
314 self.tooltip:AddLine(o:Reason(), unpack(theme.tooltip))
315 self.tooltip:GetPrevLines():SetFont(self.font.serif, 14)
317 self:AppendObjectiveProgressToTooltip(o, self.tooltip, QuestHelper.font.sans)
319 self.tooltip:AddDoubleLine(QHText("TRAVEL_ESTIMATE"), QHFormat("TRAVEL_ESTIMATE_VALUE", o.travel_time or 0), unpack(theme.tooltip))
320 self.tooltip:GetPrevLines():SetFont(self.font.sans, 11)
321 select(2, self.tooltip:GetPrevLines()):SetFont(self.font.sans, 11)
324 function QuestHelper:CreateWorldMapDodad(objective, index)
325 local icon = CreateFrame("Button", nil, QuestHelper.map_overlay)
326 icon:SetFrameStrata("FULLSCREEN")
328 function icon:SetTooltip(list)
329 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
330 QuestHelper.tooltip:ClearLines()
332 local first = true
334 for i, o in ipairs(list) do
335 if first then
336 first = false
337 else
338 QuestHelper.tooltip:AddLine("|c80ff0000 . . . . . .|r")
339 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.sans, 8)
342 QuestHelper:AppendObjectiveToTooltip(o)
345 QuestHelper.tooltip:Show()
348 function icon:SetObjective(objective, i)
349 self:SetHeight(20*QuestHelper_Pref.scale)
350 self:SetWidth(20*QuestHelper_Pref.scale)
352 if self.dot then
353 QuestHelper:ReleaseTexture(self.dot)
354 self.dot = nil
357 if self.bg then
358 QuestHelper:ReleaseTexture(self.bg)
359 self.bg = nil
362 if objective then
363 self.objective = objective
364 self.index = i
366 if i == 1 then
367 -- if it's the very next objective, give it the green background
368 self.bg = QuestHelper:CreateIconTexture(self, 13)
369 elseif objective.filter_blocked then
370 -- if there are still prerequisites, make it grey
371 -- filter_blocked is updated by [Add|Remove]ObjectiveWatch and ObjectiveObjectDependsOn,
372 -- and will be true if there are other objectives that need to be completed before this one.
373 self.bg = QuestHelper:CreateIconTexture(self, 16)
374 else
375 -- otherwise give it the background selected by the objective
376 self.bg = QuestHelper:CreateIconTexture(self, objective.icon_bg)
379 self.dot = QuestHelper:CreateIconTexture(self, objective.icon_id)
381 self.bg:SetDrawLayer("BACKGROUND")
382 self.bg:SetAllPoints()
383 self.dot:SetPoint("TOPLEFT", self, "TOPLEFT", 3*QuestHelper_Pref.scale, -3*QuestHelper_Pref.scale)
384 self.dot:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -3*QuestHelper_Pref.scale, 3*QuestHelper_Pref.scale)
386 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(objective.pos))
387 else
388 self.objective = nil
389 self:Hide()
393 function icon:SetGlow(list)
394 local w, h = QuestHelper.map_overlay:GetWidth(), QuestHelper.map_overlay:GetHeight()
395 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
396 local _, x_size, y_size = QuestHelper.Astrolabe:ComputeDistance(c, z, 0.25, 0.25, c, z, 0.75, 0.75)
398 x_size = math.max(25, 200 / x_size * w)
399 y_size = math.max(25, 200 / y_size * h)
401 local out = 1
402 for _, objective in ipairs(list) do
403 if objective.p then for _, list in pairs(objective.p) do
404 for _, p in ipairs(list) do
405 local x, y = p[3], p[4]
406 x, y = x / QuestHelper.continent_scales_x[p[1].c], y / QuestHelper.continent_scales_y[p[1].c]
407 x, y = QuestHelper.Astrolabe:TranslateWorldMapPosition(p[1].c, 0, x, y, c, z)
408 if x and y and x > 0 and y > 0 and x < 1 and y < 1 then
409 if not self.glow_list then
410 self.glow_list = QuestHelper:CreateTable()
413 tex = self.glow_list[out]
414 if not tex then
415 tex = QuestHelper:CreateGlowTexture(self)
416 table.insert(self.glow_list, tex)
418 out = out + 1
420 tex:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x*w, -y*h)
421 tex:SetVertexColor(1,1,1,0)
422 tex:SetWidth(x_size)
423 tex:SetHeight(y_size)
424 tex:Show()
425 tex.max_alpha = 1/p[5]
427 end end
431 if self.glow_list then
432 for i = out,#self.glow_list do
433 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
436 if #self.glow_list == 0 then
437 QuestHelper:ReleaseTable(self.glow_list)
438 self.glow_list = nil
443 icon.show_glow = false
444 icon.glow_pct = 0.0
445 icon.phase = 0.0
446 icon.old_count = 0
448 function icon:OnUpdate(elapsed)
449 self.phase = (self.phase + elapsed)%6.283185307179586476925286766559005768394338798750211641949889185
451 if self.old_count > 0 then
452 local list = QuestHelper:GetOverlapObjectives(self.objective)
453 if #list ~= self.old_count then
454 self:SetTooltip(list)
455 self.old_count = #list
456 self:SetGlow(list)
460 if self.show_glow then
461 self.glow_pct = math.min(1, self.glow_pct+elapsed*1.5)
462 else
463 self.glow_pct = math.max(0, self.glow_pct-elapsed*0.5)
465 if self.glow_pct == 0 then
466 if self.glow_list then
467 while #self.glow_list > 0 do
468 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
470 QuestHelper:ReleaseTable(self.glow_list)
471 self.glow_list = nil
474 self:SetScript("OnUpdate", nil)
475 return
479 if self.glow_list then
480 -- You know, these numbers are harmonics of pi. Would SETI detected them, or would they just be seen as noise?
481 -- I'd vote for the later.
483 -- Pi - circumference over diameter - when was the last time you actually cared about diameters in math?
485 -- Pretty much everything in computer geometry depends on the pythagorean theorem, which you can use for
486 -- circles, spheres, and hyper-spheres, if you use radius.
488 -- It's even the basis of special relativity, with time being multiplied by c so that you get a distance
489 -- that you can use with the spatial dimensions. We're all in agreement that space traveling aliens are
490 -- going to know about relativity, right?
492 -- And if you ever do trig, a full circle would be exactly (circumference over radius) radians instead of
493 -- (circumference over diameter)*2 radians.
495 -- Obviously aliens are much more likely to prefer 6.283185307179586... as constant than our pi.
497 -- Important update: I just noticed that large factorials can be approximated using (2*pi*n)^.5*(n/e)^n
498 -- There's that 2 times pi thing again.
499 local r, g, b = math.sin(self.phase)*0.25+0.75,
500 math.sin(self.phase+2.094395102393195492308428922186335256131446266250070547316629728)*0.25+0.75,
501 math.sin(self.phase+4.188790204786390984616857844372670512262892532500141094633259456)*0.25+0.75
503 for i, tex in ipairs(self.glow_list) do
504 tex:SetVertexColor(r, g, b, self.glow_pct*tex.max_alpha)
509 function icon:OnEnter()
510 local list = QuestHelper:GetOverlapObjectives(self.objective)
511 self:SetTooltip(list)
512 self.old_count = #list
514 icon.show_glow = true
516 self:SetGlow(list)
518 self:SetScript("OnUpdate", self.OnUpdate)
521 function icon:OnLeave()
522 QuestHelper.tooltip:Hide()
523 self.show_glow = false
524 self.old_count = 0
527 function icon:OnEvent(event)
528 if self.objective and self.objective.pos then
529 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(self.objective.pos))
530 else
531 self.objective = nil
532 self:Hide()
536 function icon:OnClick()
537 if self.objective then
538 local menu = QuestHelper:CreateMenu()
539 local list = QuestHelper:GetOverlapObjectives(self.objective)
540 local item
542 if #list > 1 then
543 QuestHelper:CreateMenuTitle(menu, "Objectives")
545 for i, o in ipairs(list) do
546 local submenu = QuestHelper:CreateMenu()
547 item = QuestHelper:CreateMenuItem(menu, o:Reason(true))
548 item:SetSubmenu(submenu)
549 item:AddTexture(QuestHelper:CreateIconTexture(item, o.icon_id), true)
550 QuestHelper:AddObjectiveOptionsToMenu(o, submenu)
552 else
553 QuestHelper:CreateMenuTitle(menu, self.objective:Reason(true))
554 QuestHelper:AddObjectiveOptionsToMenu(self.objective, menu)
557 menu:ShowAtCursor()
561 icon:SetScript("OnClick", icon.OnClick)
562 icon:SetScript("OnEnter", icon.OnEnter)
563 icon:SetScript("OnLeave", icon.OnLeave)
564 icon:SetScript("OnEvent", icon.OnEvent)
566 icon:RegisterForClicks("RightButtonUp")
568 icon:RegisterEvent("WORLD_MAP_UPDATE")
570 icon:SetObjective(objective, index)
571 return icon
574 local callbacks = {}
575 local last_c, last_z, last_x, last_y, last_desc
577 function QuestHelper:AddWaypointCallback(func, ...)
578 local cb = self:CreateTable()
579 callbacks[cb] = true
580 local len = select("#", ...)
581 cb.len = len
582 cb.func = func
583 for i = 1,len do cb[i] = select(i, ...) end
584 cb[len+1] = last_c
585 cb[len+2] = last_z
586 cb[len+3] = last_x
587 cb[len+4] = last_y
588 cb[len+5] = last_desc
590 if last_c then
591 func(unpack(cb, 1, len+5))
594 return cb
597 function QuestHelper:RemoveWaypointCallback(cb)
598 callbacks[cb] = nil
599 self:ReleaseTable(cb)
602 function QuestHelper:InvokeWaypointCallbacks(c, z, x, y, desc)
603 if c ~= last_c or z ~= last_z or x ~= last_x or y ~= last_y or desc ~= last_desc then
604 last_c, last_z, last_x, last_y, last_desc = c, z, x, y, desc
605 for cb in pairs(callbacks) do
606 local len = cb.len
607 cb[len+1] = c
608 cb[len+2] = z
609 cb[len+3] = x
610 cb[len+4] = y
611 cb[len+5] = desc
612 cb.func(unpack(cb, 1, len+5))
617 --[[ Small parts of the arrow rendering code are thanks to Tomtom, with the following license:
619 -------------------------------------------------------------------------
620 Copyright (c) 2006-2007, James N. Whitehead II
621 All rights reserved.
623 Redistribution and use in source and binary forms, with or without
624 modification, are permitted provided that the following conditions are
625 met:
627 * Redistributions of source code must retain the above copyright
628 notice, this list of conditions and the following disclaimer.
629 * Redistributions in binary form must reproduce the above
630 copyright notice, this list of conditions and the following
631 disclaimer in the documentation and/or other materials provided
632 with the distribution.
633 * The name or alias of the copyright holder may not be used to endorse
634 or promote products derived from this software without specific prior
635 written permission.
637 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
638 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
639 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
640 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
641 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
642 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
643 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
644 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
645 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
646 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
647 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
648 ---------------------------------------------------------------------------]]
650 function QuestHelper:CreateMipmapDodad()
651 local icon = CreateFrame("Button", nil, Minimap)
652 icon:Hide()
653 icon.recalc_timeout = 0
655 icon.arrow = icon:CreateTexture("BACKGROUND")
656 icon.arrow:SetHeight(40)
657 icon.arrow:SetWidth(40)
658 icon.arrow:SetPoint("CENTER", 0, 0)
659 icon.arrow:SetTexture("Interface\\AddOns\\QuestHelper\\MinimapArrow")
660 icon.arrow:Hide()
662 icon.phase = 0
663 icon.target = {0, 0, 0, 0}
664 icon.icon_id = 7
666 icon.bg = QuestHelper:CreateIconTexture(icon, 16)
667 icon.bg:SetDrawLayer("BACKGROUND")
668 icon.bg:SetAllPoints()
670 function icon:NextObjective()
671 for i, o in ipairs(QuestHelper.route) do
672 if not QuestHelper.to_remove[o] and o.pos and not o.filter_blocked then
673 return o
677 return nil
680 function icon:OnUpdate(elapsed)
681 if self.objective and not QuestHelper.InBrokenInstance then
682 if not self.objective.pos then
683 self.objective = self:NextObjective()
684 if not self.objective then
685 self:Hide()
686 return
690 self:Show()
692 if self.recalc_timeout <= 0 and not QuestHelper.graph_in_limbo and QuestHelper.Routing.map_walker then
693 self.recalc_timeout = 50
695 self.objective = self:NextObjective()
697 if not self.objective then
698 self:Hide()
699 return
702 local path, travel_time
704 if QuestHelper.target then
706 -- Okay, this is another "fix the symptom without fixing the cause" hack. Not good, but a lot of this is going away anyway.
707 local has_path = true
708 for i in ipairs(QuestHelper.target[1]) do if not QuestHelper.target[2][i] then has_path = false end end
709 if has_path then
710 path, travel_time = QuestHelper:ComputeRoute(QuestHelper.target, self.objective.pos)
711 travel_time = travel_time + math.max(0, QuestHelper.target_time-time())
712 else
713 --QuestHelper:TextOut("yes here is the nil bug")
715 else
716 path, travel_time = QuestHelper:ComputeRoute(QuestHelper.pos, self.objective.pos)
719 local t = self.target
720 local id = self.objective.icon_id
721 t[1], t[2], t[3], t[4] = convertLocation(self.objective.pos)
722 t[5] = nil
724 self.objective.travel_time = travel_time
726 while path do
727 if path.g > 10.0 then
728 id = 8
729 t[1] = path.c
730 t[2] = 0
731 t[3] = path.x / QuestHelper.continent_scales_x[path.c]
732 t[4] = path.y / QuestHelper.continent_scales_y[path.c]
733 t[5] = path.name or "waypoint"
735 path = path.p
738 if not self.dot or id ~= self.icon_id then
739 self.icon_id = id
740 if self.dot then QuestHelper:ReleaseTexture(self.dot) end
741 self.dot = QuestHelper:CreateIconTexture(self, self.icon_id)
742 self.dot:SetPoint("TOPLEFT", icon, "TOPLEFT", 2, -2)
743 self.dot:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -2, 2)
746 if UnitIsDeadOrGhost("player") then
747 QuestHelper:InvokeWaypointCallbacks()
748 else
749 local reason = (t[5] and (QHFormat("WAYPOINT_REASON", t[5]).."\n"..self.objective:Reason(true)))
750 or self.objective:Reason(true)
752 if QuestHelper.c == t[1] then
753 -- Translate the position to the zone the player is standing in.
754 local c, z = QuestHelper.c, QuestHelper.z
755 local x, y = QuestHelper.Astrolabe:TranslateWorldMapPosition(t[1], t[2], t[3], t[4], c, z)
756 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, reason)
757 else
758 -- Try to find the nearest zone on the continent the objective is in.
759 local index, distsqr, x, y
760 for z, i in pairs(QuestHelper_IndexLookup[t[1]]) do
761 local _x, _y = QuestHelper.Astrolabe:TranslateWorldMapPosition(t[1], t[2], t[3], t[4], t[1], z)
762 local d = (_x-0.5)*(_x-0.5)+(_y-0.5)*(_y-0.5)
763 if not index or d < distsqr then
764 index, distsqr, x, y = i, d, _x, _y
767 local c, z = QuestHelper_IndexLookup[index]
768 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, reason)
772 QuestHelper.Astrolabe:PlaceIconOnMinimap(self, unpack(self.target))
773 else
774 self.recalc_timeout = self.recalc_timeout - 1
777 local edge = QuestHelper.Astrolabe:IsIconOnEdge(self)
779 if edge then
780 self.arrow:Show()
781 self.dot:Hide()
782 self.bg:Hide()
783 else
784 self.arrow:Hide()
785 self.dot:Show()
786 self.bg:Show()
789 if edge then
790 local angle = QuestHelper.Astrolabe:GetDirectionToIcon(self)
792 if GetCVar("rotateMinimap") == "1" then
793 angle = angle + QuestHelper.Astrolabe:GetFacing()
796 if self.phase > 6.283185307179586476925 then
797 self.phase = self.phase-6.283185307179586476925+elapsed*3.5
798 else
799 self.phase = self.phase+elapsed*3.5
802 local scale = 1.0 + 0.1 * math.sin(self.phase)
804 local x, y = scale * math.sin(angle + 3.14159 * 0.75) * math.sqrt(0.5), scale * math.cos(angle + 3.14159 * 0.75) * math.sqrt(0.5)
805 self.arrow:SetTexCoord(0.5 - x, 0.5 + y, 0.5 + y, 0.5 + x, 0.5 - y, 0.5 - x, 0.5 + x, 0.5 - y)
807 else
808 self:Hide()
812 function icon:SetObjective(objective)
813 self:SetHeight(20*QuestHelper_Pref.scale)
814 self:SetWidth(20*QuestHelper_Pref.scale)
816 if objective ~= self.objective then
817 if objective and not QuestHelper_Pref.hide then
818 self:Show()
819 else
820 QuestHelper:InvokeWaypointCallbacks()
821 self:Hide()
824 self.objective = objective
825 self.recalc_timeout = 0
829 function icon:OnEnter()
830 if self.objective then
831 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
832 QuestHelper.tooltip:ClearLines()
834 if self.target[5] then
835 QuestHelper.tooltip:AddLine(QHFormat("WAYPOINT_REASON", self.target[5]), unpack(QuestHelper:GetColourTheme().tooltip))
836 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.serif, 14)
839 QuestHelper:AppendObjectiveToTooltip(self.objective)
840 QuestHelper.tooltip:Show()
844 function icon:OnLeave()
845 QuestHelper.tooltip:Hide()
848 function icon:OnClick()
849 if self.objective then
850 local menu = QuestHelper:CreateMenu()
851 QuestHelper:CreateMenuTitle(menu, self.objective:Reason(true))
852 QuestHelper:AddObjectiveOptionsToMenu(self.objective, menu)
853 menu:ShowAtCursor()
857 function icon:OnEvent()
858 if self.objective and self.objective.pos then
859 self:Show()
860 else
861 self:Hide()
865 icon:SetScript("OnUpdate", icon.OnUpdate)
866 icon:SetScript("OnEnter", icon.OnEnter)
867 icon:SetScript("OnLeave", icon.OnLeave)
868 icon:SetScript("OnEvent", icon.OnEvent)
869 icon:SetScript("OnClick", icon.OnClick)
871 icon:RegisterForClicks("RightButtonUp")
872 icon:RegisterEvent("PLAYER_ENTERING_WORLD")
874 return icon