I shouldn't be logging to nlog
[QuestHelper.git] / dodads.lua
blob2245d6319325c3aa190fb9e0f30f5fc62cfd02f6
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 function QuestHelper:CreateMipmapDodad()
618 local icon = CreateFrame("Button", nil, Minimap)
619 icon:Hide()
620 icon.recalc_timeout = 0
622 icon.arrow = CreateFrame("Model", nil, icon)
623 icon.arrow:SetHeight(140.8)
624 icon.arrow:SetWidth(140.8)
625 icon.arrow:SetPoint("CENTER", Minimap, "CENTER", 0, 0)
626 icon.arrow:SetModel("Interface\\Minimap\\Rotating-MinimapArrow.mdx")
627 icon.arrow:Hide()
629 icon.phase = 0
630 icon.target = {0, 0, 0, 0}
631 icon.icon_id = 7
633 icon.bg = QuestHelper:CreateIconTexture(icon, 16)
634 icon.bg:SetDrawLayer("BACKGROUND")
635 icon.bg:SetAllPoints()
637 function icon:NextObjective()
638 for i, o in ipairs(QuestHelper.route) do
639 if not QuestHelper.to_remove[o] and o.pos and not o.filter_blocked then
640 return o
644 return nil
647 function icon:OnUpdate(elapsed)
648 if self.objective then
649 if not self.objective.pos then
650 self.objective = self:NextObjective()
651 if not self.objective then
652 self:Hide()
653 return
657 self:Show()
659 if self.recalc_timeout <= 0 and not QuestHelper.graph_in_limbo and QuestHelper.Routing.map_walker then
660 self.recalc_timeout = 50
662 self.objective = self:NextObjective()
664 if not self.objective then
665 self:Hide()
666 return
669 local path, travel_time
671 if QuestHelper.target then
673 -- Okay, this is another "fix the symptom without fixing the cause" hack. Not good, but a lot of this is going away anyway.
674 local has_path = true
675 for i in ipairs(QuestHelper.target[1]) do if not QuestHelper.target[2][i] then has_path = false end end
676 if has_path then
677 path, travel_time = QuestHelper:ComputeRoute(QuestHelper.target, self.objective.pos)
678 travel_time = travel_time + math.max(0, QuestHelper.target_time-time())
679 else
680 --QuestHelper:TextOut("yes here is the nil bug")
682 else
683 path, travel_time = QuestHelper:ComputeRoute(QuestHelper.pos, self.objective.pos)
686 local t = self.target
687 local id = self.objective.icon_id
688 t[1], t[2], t[3], t[4] = convertLocation(self.objective.pos)
689 t[5] = nil
691 self.objective.travel_time = travel_time
693 while path do
694 if path.g > 10.0 then
695 id = 8
696 t[1] = path.c
697 t[2] = 0
698 t[3] = path.x / QuestHelper.continent_scales_x[path.c]
699 t[4] = path.y / QuestHelper.continent_scales_y[path.c]
700 t[5] = path.name or "waypoint"
702 path = path.p
705 if not self.dot or id ~= self.icon_id then
706 self.icon_id = id
707 if self.dot then QuestHelper:ReleaseTexture(self.dot) end
708 self.dot = QuestHelper:CreateIconTexture(self, self.icon_id)
709 self.dot:SetPoint("TOPLEFT", icon, "TOPLEFT", 2, -2)
710 self.dot:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -2, 2)
713 if UnitIsDeadOrGhost("player") then
714 QuestHelper:InvokeWaypointCallbacks()
715 else
716 local reason = (t[5] and (QHFormat("WAYPOINT_REASON", t[5]).."\n"..self.objective:Reason(true)))
717 or self.objective:Reason(true)
719 if QuestHelper.c == t[1] then
720 -- Translate the position to the zone the player is standing in.
721 local c, z = QuestHelper.c, QuestHelper.z
722 local x, y = QuestHelper.Astrolabe:TranslateWorldMapPosition(t[1], t[2], t[3], t[4], c, z)
723 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, reason)
724 else
725 -- Try to find the nearest zone on the continent the objective is in.
726 local index, distsqr, x, y
727 for z, i in pairs(QuestHelper_IndexLookup[t[1]]) do
728 local _x, _y = QuestHelper.Astrolabe:TranslateWorldMapPosition(t[1], t[2], t[3], t[4], t[1], z)
729 local d = (_x-0.5)*(_x-0.5)+(_y-0.5)*(_y-0.5)
730 if not index or d < distsqr then
731 index, distsqr, x, y = i, d, _x, _y
734 local c, z = QuestHelper_IndexLookup[index]
735 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, reason)
739 QuestHelper.Astrolabe:PlaceIconOnMinimap(self, unpack(self.target))
740 else
741 self.recalc_timeout = self.recalc_timeout - 1
744 local edge = QuestHelper.Astrolabe:IsIconOnEdge(self)
746 if edge then
747 self.arrow:Show()
748 self.dot:Hide()
749 self.bg:Hide()
750 else
751 self.arrow:Hide()
752 self.dot:Show()
753 self.bg:Show()
756 if edge then
757 local angle = QuestHelper.Astrolabe:GetDirectionToIcon(self)
758 if GetCVar("rotateMinimap") == "1" then
759 angle = angle + QuestHelper.Astrolabe:GetFacing()
762 self.arrow:SetFacing(angle)
763 self.arrow:SetPosition(ofs * (137 / 140) - radius * math.sin(angle),
764 ofs + radius * math.cos(angle), 0);
766 if self.phase > 6.283185307179586476925 then
767 self.phase = self.phase-6.283185307179586476925+elapsed*3.5
768 else
769 self.phase = self.phase+elapsed*3.5
771 self.arrow:SetModelScale(0.600000023841879+0.1*math.sin(self.phase))
773 else
774 self:Hide()
778 function icon:SetObjective(objective)
779 self:SetHeight(20*QuestHelper_Pref.scale)
780 self:SetWidth(20*QuestHelper_Pref.scale)
782 if objective ~= self.objective then
783 if objective and not QuestHelper_Pref.hide then
784 self:Show()
785 else
786 QuestHelper:InvokeWaypointCallbacks()
787 self:Hide()
790 self.objective = objective
791 self.recalc_timeout = 0
795 function icon:OnEnter()
796 if self.objective then
797 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
798 QuestHelper.tooltip:ClearLines()
800 if self.target[5] then
801 QuestHelper.tooltip:AddLine(QHFormat("WAYPOINT_REASON", self.target[5]), unpack(QuestHelper:GetColourTheme().tooltip))
802 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.serif, 14)
805 QuestHelper:AppendObjectiveToTooltip(self.objective)
806 QuestHelper.tooltip:Show()
810 function icon:OnLeave()
811 QuestHelper.tooltip:Hide()
814 function icon:OnClick()
815 if self.objective then
816 local menu = QuestHelper:CreateMenu()
817 QuestHelper:CreateMenuTitle(menu, self.objective:Reason(true))
818 QuestHelper:AddObjectiveOptionsToMenu(self.objective, menu)
819 menu:ShowAtCursor()
823 function icon:OnEvent()
824 if self.objective and self.objective.pos then
825 self:Show()
826 else
827 self:Hide()
831 icon:SetScript("OnUpdate", icon.OnUpdate)
832 icon:SetScript("OnEnter", icon.OnEnter)
833 icon:SetScript("OnLeave", icon.OnLeave)
834 icon:SetScript("OnEvent", icon.OnEvent)
835 icon:SetScript("OnClick", icon.OnClick)
837 icon:RegisterForClicks("RightButtonUp")
838 icon:RegisterEvent("PLAYER_ENTERING_WORLD")
840 return icon