update changes
[QuestHelper.git] / dodads.lua
blobd9857f1264fbd3d0d3e63135e727978f354cd2bf
1 QuestHelper_File["dodads.lua"] = "Development Version"
3 local ofs = 0.000723339 * (GetScreenHeight()/GetScreenWidth() + 1/3) * 70.4;
4 local radius = ofs / 1.166666666666667;
6 local function convertLocation(p)
7 local c, x, y = p[1].c, p[3], p[4]
8 x, y = x/QuestHelper.continent_scales_x[c], y/QuestHelper.continent_scales_y[c]
9 return c, 0, x, y
10 end
12 local function convertLocationToScreen(p, c, z)
13 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)
14 end
16 local function convertNodeToScreen(n, c, z)
17 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)
18 end
20 QuestHelper.map_overlay = CreateFrame("FRAME", nil, WorldMapButton)
21 QuestHelper.map_overlay:SetFrameLevel(WorldMapButton:GetFrameLevel()+1)
22 QuestHelper.map_overlay:SetAllPoints()
23 QuestHelper.map_overlay:SetFrameStrata("FULLSCREEN")
25 local function ClampLine(x1, y1, x2, y2)
26 if x1 and y1 and x2 and y2 then
27 local x_div, y_div = (x2-x1), (y2-y1)
28 local x_0 = y1-x1/x_div*y_div
29 local x_1 = y1+(1-x1)/x_div*y_div
30 local y_0 = x1-y1/y_div*x_div
31 local y_1 = x1+(1-y1)/y_div*x_div
33 if y1 < 0 then
34 x1 = y_0
35 y1 = 0
36 end
38 if y2 < 0 then
39 x2 = y_0
40 y2 = 0
41 end
43 if y1 > 1 then
44 x1 = y_1
45 y1 = 1
46 end
48 if y2 > 1 then
49 x2 = y_1
50 y2 = 1
51 end
53 if x1 < 0 then
54 y1 = x_0
55 x1 = 0
56 end
58 if x2 < 0 then
59 y2 = x_0
60 x2 = 0
61 end
63 if x1 > 1 then
64 y1 = x_1
65 x1 = 1
66 end
68 if x2 > 1 then
69 y2 = x_1
70 x2 = 1
71 end
73 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
74 return x1, y1, x2, y2
75 end
76 end
77 end
79 local function pushPath(list, path, c, z)
80 if path then
81 pushPath(list, path.p, c, z)
82 local t = QuestHelper:CreateTable()
83 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)
84 table.insert(list, t)
85 end
86 end
88 function QuestHelper:CreateWorldMapWalker()
89 local walker = CreateFrame("Button", nil, QuestHelper.map_overlay)
90 walker:SetWidth(0)
91 walker:SetHeight(0)
92 walker:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", 0, 0)
93 walker:Show()
95 walker.phase = 0.0
96 walker.dots = {}
97 walker.points = {}
98 walker.origin = {}
99 walker.frame = self
100 walker.map_dodads = {}
101 walker.used_map_dodads = 0
103 function walker:OnUpdate(elapsed)
104 local out = 0
106 if QuestHelper_Pref.show_ants then
107 local points = self.points
109 self.phase = self.phase + elapsed * 0.66
110 while self.phase > 1 do self.phase = self.phase - 1 end
112 local w, h = QuestHelper.map_overlay:GetWidth(), -QuestHelper.map_overlay:GetHeight()
114 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
116 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
118 for i, pos in ipairs(points) do
119 local new_x, new_y = unpack(pos)
120 local x1, y1, x2, y2 = ClampLine(last_x, last_y, new_x, new_y)
121 last_x, last_y = new_x, new_y
123 if x1 then
124 local len = math.sqrt((x1-x2)*(x1-x2)*16/9+(y1-y2)*(y1-y2))
126 if len > 0.0001 then
127 local interval = .025/len
128 local p = remainder*interval
130 while p < 1 do
131 out = out + 1
132 local dot = self.dots[out]
133 if not dot then
134 dot = QuestHelper:CreateDotTexture(self)
135 dot:SetDrawLayer("BACKGROUND")
136 self.dots[out] = dot
139 dot:ClearAllPoints()
140 dot:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x1*w*(1-p)+x2*w*p, y1*h*(1-p)+y2*h*p)
142 p = p + interval
145 remainder = (p-1)/interval
151 while #self.dots > out do
152 QuestHelper:ReleaseTexture(table.remove(self.dots))
156 function walker:RouteChanged()
157 if self.frame.Astrolabe.WorldMapVisible then
158 for i, obj in pairs(self.frame.route) do
159 if not obj.pos then
160 -- No. Just no.
161 QuestHelper:AppendNotificationError("10-10-2008 pathfinding/dodads nil coroutine race condition bug")
162 return -- return "failure :("
166 local points = self.points
167 local cur = self.frame.pos
169 while #points > 0 do self.frame:ReleaseTable(table.remove(points)) end
171 local travel_time = 0.0
173 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
175 if self.frame.target then
176 travel_time = math.max(0, self.frame.target_time-time())
177 cur = self.frame.target
178 local t = self.frame:CreateTable()
179 t[1], t[2] = convertLocationToScreen(cur, c, z)
180 table.insert(points, t)
183 for i, obj in pairs(self.frame.route) do
184 local path, d = self.frame:ComputeRoute(cur, obj.pos)
186 pushPath(points, path, c, z)
188 travel_time = travel_time + d
189 obj.travel_time = travel_time
191 cur = obj.pos
193 local t = self.frame:CreateTable()
194 t[1], t[2] = convertLocationToScreen(cur, c, z)
196 table.insert(points, t)
199 for i = 1, #self.frame.route do
200 local dodad = self.map_dodads[i]
201 if not dodad then
202 self.map_dodads[i] = self.frame:CreateWorldMapDodad(self.frame.route[i], i)
203 else
204 self.map_dodads[i]:SetObjective(self.frame.route[i], i)
208 for i = #self.frame.route+1,self.used_map_dodads do
209 self.map_dodads[i]:SetObjective(nil, 0)
212 self.used_map_dodads = #self.frame.route
216 walker:SetScript("OnEvent", walker.RouteChanged)
217 walker:RegisterEvent("WORLD_MAP_UPDATE")
219 walker:SetScript("OnUpdate", walker.OnUpdate)
221 return walker
224 function QuestHelper:GetOverlapObjectives(obj)
225 local w, h = self.map_overlay:GetWidth(), self.map_overlay:GetHeight()
226 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
228 local list = self.overlap_list
230 if not list then
231 list = {}
232 self.overlap_list = list
233 else
234 while table.remove(list) do end
237 local cx, cy = GetCursorPosition()
239 local es = QuestHelper.map_overlay:GetEffectiveScale()
240 local ies = 1/es
242 cx, cy = (cx-self.map_overlay:GetLeft()*es)*ies, (self.map_overlay:GetTop()*es-cy)*ies
244 local s = 10*QuestHelper_Pref.scale
246 for i, o in ipairs(self.route) do
247 if o == obj then
248 table.insert(list, o)
249 else
250 local x, y = o.pos[3], o.pos[4]
251 x, y = x / self.continent_scales_x[o.pos[1].c], y / self.continent_scales_y[o.pos[1].c]
252 x, y = self.Astrolabe:TranslateWorldMapPosition(o.pos[1].c, 0, x, y, c, z)
254 if x and y and x > 0 and y > 0 and x < 1 and y < 1 then
255 x, y = x*w, y*h
257 if cx >= x-s and cy >= y-s and cx <= x+s and cy <= y+s then
258 table.insert(list, o)
264 table.sort(list, function(a, b) return (a.travel_time or 0) < (b.travel_time or 0) end)
266 return list
269 local prog_sort_table = {}
271 function QuestHelper:AppendObjectiveProgressToTooltip(o, tooltip, font, depth)
272 if o.progress then
273 local theme = self:GetColourTheme()
275 local indent = (" "):rep(depth or 0)
277 for user, progress in pairs(o.progress) do
278 table.insert(prog_sort_table, user)
281 table.sort(prog_sort_table, function(a, b)
282 if o.progress[a][3] < o.progress[b][3] then
283 return true
284 elseif o.progress[a][3] == o.progress[b][3] then
285 return a < b
287 return false
288 end)
290 for i, u in ipairs(prog_sort_table) do
291 tooltip:AddDoubleLine(indent..QHFormat("PEER_PROGRESS", u),
292 self:ProgressString(o.progress[u][1].."/"..o.progress[u][2],
293 o.progress[u][3]), unpack(theme.tooltip))
295 if font then
296 local last, name = tooltip:NumLines(), tooltip:GetName()
297 local left, right = _G[name.."TextLeft"..last], _G[name.."TextRight"..last]
299 left:SetFont(font, 13)
300 right:SetFont(font, 13)
304 while table.remove(prog_sort_table) do end
308 function QuestHelper:AppendObjectiveToTooltip(o)
309 local theme = self:GetColourTheme()
311 self.tooltip:AddLine(o:Reason(), unpack(theme.tooltip))
312 self.tooltip:GetPrevLines():SetFont(self.font.serif, 14)
314 self:AppendObjectiveProgressToTooltip(o, self.tooltip, QuestHelper.font.sans)
316 self.tooltip:AddDoubleLine(QHText("TRAVEL_ESTIMATE"), QHFormat("TRAVEL_ESTIMATE_VALUE", o.travel_time or 0), unpack(theme.tooltip))
317 self.tooltip:GetPrevLines():SetFont(self.font.sans, 11)
318 select(2, self.tooltip:GetPrevLines()):SetFont(self.font.sans, 11)
321 function QuestHelper:CreateWorldMapDodad(objective, index)
322 local icon = CreateFrame("Button", nil, QuestHelper.map_overlay)
323 icon:SetFrameStrata("FULLSCREEN")
325 function icon:SetTooltip(list)
326 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
327 QuestHelper.tooltip:ClearLines()
329 local first = true
331 for i, o in ipairs(list) do
332 if first then
333 first = false
334 else
335 QuestHelper.tooltip:AddLine("|c80ff0000 . . . . . .|r")
336 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.sans, 8)
339 QuestHelper:AppendObjectiveToTooltip(o)
342 QuestHelper.tooltip:Show()
345 function icon:SetObjective(objective, i)
346 self:SetHeight(20*QuestHelper_Pref.scale)
347 self:SetWidth(20*QuestHelper_Pref.scale)
349 if self.dot then
350 QuestHelper:ReleaseTexture(self.dot)
351 self.dot = nil
354 if self.bg then
355 QuestHelper:ReleaseTexture(self.bg)
356 self.bg = nil
359 if objective then
360 self.objective = objective
361 self.index = i
363 if i == 1 then
364 -- if it's the very next objective, give it the green background
365 self.bg = QuestHelper:CreateIconTexture(self, 13)
366 elseif objective.filter_blocked then
367 -- if there are still prerequisites, make it grey
368 -- filter_blocked is updated by [Add|Remove]ObjectiveWatch and ObjectiveObjectDependsOn,
369 -- and will be true if there are other objectives that need to be completed before this one.
370 self.bg = QuestHelper:CreateIconTexture(self, 16)
371 else
372 -- otherwise give it the background selected by the objective
373 self.bg = QuestHelper:CreateIconTexture(self, objective.icon_bg)
376 self.dot = QuestHelper:CreateIconTexture(self, objective.icon_id)
378 self.bg:SetDrawLayer("BACKGROUND")
379 self.bg:SetAllPoints()
380 self.dot:SetPoint("TOPLEFT", self, "TOPLEFT", 3*QuestHelper_Pref.scale, -3*QuestHelper_Pref.scale)
381 self.dot:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -3*QuestHelper_Pref.scale, 3*QuestHelper_Pref.scale)
383 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(objective.pos))
384 else
385 self.objective = nil
386 self:Hide()
390 function icon:SetGlow(list)
391 local w, h = QuestHelper.map_overlay:GetWidth(), QuestHelper.map_overlay:GetHeight()
392 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
393 local _, x_size, y_size = QuestHelper.Astrolabe:ComputeDistance(c, z, 0.25, 0.25, c, z, 0.75, 0.75)
395 x_size = math.max(25, 200 / x_size * w)
396 y_size = math.max(25, 200 / y_size * h)
398 local out = 1
399 for _, objective in ipairs(list) do
400 if objective.p then for _, list in pairs(objective.p) do
401 for _, p in ipairs(list) do
402 local x, y = p[3], p[4]
403 x, y = x / QuestHelper.continent_scales_x[p[1].c], y / QuestHelper.continent_scales_y[p[1].c]
404 x, y = QuestHelper.Astrolabe:TranslateWorldMapPosition(p[1].c, 0, x, y, c, z)
405 if x and y and x > 0 and y > 0 and x < 1 and y < 1 then
406 if not self.glow_list then
407 self.glow_list = QuestHelper:CreateTable()
410 tex = self.glow_list[out]
411 if not tex then
412 tex = QuestHelper:CreateGlowTexture(self)
413 table.insert(self.glow_list, tex)
415 out = out + 1
417 tex:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x*w, -y*h)
418 tex:SetVertexColor(1,1,1,0)
419 tex:SetWidth(x_size)
420 tex:SetHeight(y_size)
421 tex:Show()
422 tex.max_alpha = 1/p[5]
424 end end
428 if self.glow_list then
429 for i = out,#self.glow_list do
430 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
433 if #self.glow_list == 0 then
434 QuestHelper:ReleaseTable(self.glow_list)
435 self.glow_list = nil
440 icon.show_glow = false
441 icon.glow_pct = 0.0
442 icon.phase = 0.0
443 icon.old_count = 0
445 function icon:OnUpdate(elapsed)
446 self.phase = (self.phase + elapsed)%6.283185307179586476925286766559005768394338798750211641949889185
448 if self.old_count > 0 then
449 local list = QuestHelper:GetOverlapObjectives(self.objective)
450 if #list ~= self.old_count then
451 self:SetTooltip(list)
452 self.old_count = #list
453 self:SetGlow(list)
457 if self.show_glow then
458 self.glow_pct = math.min(1, self.glow_pct+elapsed*1.5)
459 else
460 self.glow_pct = math.max(0, self.glow_pct-elapsed*0.5)
462 if self.glow_pct == 0 then
463 if self.glow_list then
464 while #self.glow_list > 0 do
465 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
467 QuestHelper:ReleaseTable(self.glow_list)
468 self.glow_list = nil
471 self:SetScript("OnUpdate", nil)
472 return
476 if self.glow_list then
477 -- You know, these numbers are harmonics of pi. Would SETI detected them, or would they just be seen as noise?
478 -- I'd vote for the later.
480 -- Pi - circumference over diameter - when was the last time you actually cared about diameters in math?
482 -- Pretty much everything in computer geometry depends on the pythagorean theorem, which you can use for
483 -- circles, spheres, and hyper-spheres, if you use radius.
485 -- It's even the basis of special relativity, with time being multiplied by c so that you get a distance
486 -- that you can use with the spatial dimensions. We're all in agreement that space traveling aliens are
487 -- going to know about relativity, right?
489 -- And if you ever do trig, a full circle would be exactly (circumference over radius) radians instead of
490 -- (circumference over diameter)*2 radians.
492 -- Obviously aliens are much more likely to prefer 6.283185307179586... as constant than our pi.
494 -- Important update: I just noticed that large factorials can be approximated using (2*pi*n)^.5*(n/e)^n
495 -- There's that 2 times pi thing again.
496 local r, g, b = math.sin(self.phase)*0.25+0.75,
497 math.sin(self.phase+2.094395102393195492308428922186335256131446266250070547316629728)*0.25+0.75,
498 math.sin(self.phase+4.188790204786390984616857844372670512262892532500141094633259456)*0.25+0.75
500 for i, tex in ipairs(self.glow_list) do
501 tex:SetVertexColor(r, g, b, self.glow_pct*tex.max_alpha)
506 function icon:OnEnter()
507 local list = QuestHelper:GetOverlapObjectives(self.objective)
508 self:SetTooltip(list)
509 self.old_count = #list
511 icon.show_glow = true
513 self:SetGlow(list)
515 self:SetScript("OnUpdate", self.OnUpdate)
518 function icon:OnLeave()
519 QuestHelper.tooltip:Hide()
520 self.show_glow = false
521 self.old_count = 0
524 function icon:OnEvent(event)
525 if self.objective and self.objective.pos then
526 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(self.objective.pos))
527 else
528 self.objective = nil
529 self:Hide()
533 function icon:OnClick()
534 if self.objective then
535 local menu = QuestHelper:CreateMenu()
536 local list = QuestHelper:GetOverlapObjectives(self.objective)
537 local item
539 if #list > 1 then
540 QuestHelper:CreateMenuTitle(menu, "Objectives")
542 for i, o in ipairs(list) do
543 local submenu = QuestHelper:CreateMenu()
544 item = QuestHelper:CreateMenuItem(menu, o:Reason(true))
545 item:SetSubmenu(submenu)
546 item:AddTexture(QuestHelper:CreateIconTexture(item, o.icon_id), true)
547 QuestHelper:AddObjectiveOptionsToMenu(o, submenu)
549 else
550 QuestHelper:CreateMenuTitle(menu, self.objective:Reason(true))
551 QuestHelper:AddObjectiveOptionsToMenu(self.objective, menu)
554 menu:ShowAtCursor()
558 icon:SetScript("OnClick", icon.OnClick)
559 icon:SetScript("OnEnter", icon.OnEnter)
560 icon:SetScript("OnLeave", icon.OnLeave)
561 icon:SetScript("OnEvent", icon.OnEvent)
563 icon:RegisterForClicks("RightButtonUp")
565 icon:RegisterEvent("WORLD_MAP_UPDATE")
567 icon:SetObjective(objective, index)
568 return icon
571 local callbacks = {}
572 local last_c, last_z, last_x, last_y, last_desc
574 function QuestHelper:AddWaypointCallback(func, ...)
575 local cb = self:CreateTable()
576 callbacks[cb] = true
577 local len = select("#", ...)
578 cb.len = len
579 cb.func = func
580 for i = 1,len do cb[i] = select(i, ...) end
581 cb[len+1] = last_c
582 cb[len+2] = last_z
583 cb[len+3] = last_x
584 cb[len+4] = last_y
585 cb[len+5] = last_desc
587 if last_c then
588 func(unpack(cb, 1, len+5))
591 return cb
594 function QuestHelper:RemoveWaypointCallback(cb)
595 callbacks[cb] = nil
596 self:ReleaseTable(cb)
599 function QuestHelper:InvokeWaypointCallbacks(c, z, x, y, desc)
600 if c ~= last_c or z ~= last_z or x ~= last_x or y ~= last_y or desc ~= last_desc then
601 last_c, last_z, last_x, last_y, last_desc = c, z, x, y, desc
602 for cb in pairs(callbacks) do
603 local len = cb.len
604 cb[len+1] = c
605 cb[len+2] = z
606 cb[len+3] = x
607 cb[len+4] = y
608 cb[len+5] = desc
609 cb.func(unpack(cb, 1, len+5))
614 function QuestHelper:CreateMipmapDodad()
615 local icon = CreateFrame("Button", nil, Minimap)
616 icon:Hide()
617 icon.recalc_timeout = 0
619 icon.arrow = CreateFrame("Model", nil, icon)
620 icon.arrow:SetHeight(140.8)
621 icon.arrow:SetWidth(140.8)
622 icon.arrow:SetPoint("CENTER", Minimap, "CENTER", 0, 0)
623 icon.arrow:SetModel("Interface\\Minimap\\Rotating-MinimapArrow.mdx")
624 icon.arrow:Hide()
626 icon.phase = 0
627 icon.target = {0, 0, 0, 0}
628 icon.icon_id = 7
630 icon.bg = QuestHelper:CreateIconTexture(icon, 16)
631 icon.bg:SetDrawLayer("BACKGROUND")
632 icon.bg:SetAllPoints()
634 function icon:NextObjective()
635 for i, o in ipairs(QuestHelper.route) do
636 if not QuestHelper.to_remove[o] and o.pos and not o.filter_blocked then
637 return o
641 return nil
644 function icon:OnUpdate(elapsed)
645 if self.objective then
646 if not self.objective.pos then
647 self.objective = self:NextObjective()
648 if not self.objective then
649 self:Hide()
650 return
654 self:Show()
656 if self.recalc_timeout <= 0 and not QuestHelper.graph_in_limbo then
657 self.recalc_timeout = 50
659 self.objective = self:NextObjective()
661 if not self.objective then
662 self:Hide()
663 return
666 local path, travel_time
668 if QuestHelper.target then
669 path, travel_time = QuestHelper:ComputeRoute(QuestHelper.target, self.objective.pos)
670 travel_time = travel_time + math.max(0, QuestHelper.target_time-time())
671 else
672 path, travel_time = QuestHelper:ComputeRoute(QuestHelper.pos, self.objective.pos)
675 local t = self.target
676 local id = self.objective.icon_id
677 t[1], t[2], t[3], t[4] = convertLocation(self.objective.pos)
678 t[5] = nil
680 self.objective.travel_time = travel_time
682 while path do
683 if path.g > 10.0 then
684 id = 8
685 t[1] = path.c
686 t[2] = 0
687 t[3] = path.x / QuestHelper.continent_scales_x[path.c]
688 t[4] = path.y / QuestHelper.continent_scales_y[path.c]
689 t[5] = path.name or "waypoint"
691 path = path.p
694 if not self.dot or id ~= self.icon_id then
695 self.icon_id = id
696 if self.dot then QuestHelper:ReleaseTexture(self.dot) end
697 self.dot = QuestHelper:CreateIconTexture(self, self.icon_id)
698 self.dot:SetPoint("TOPLEFT", icon, "TOPLEFT", 2, -2)
699 self.dot:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -2, 2)
702 if UnitIsDeadOrGhost("player") then
703 QuestHelper:InvokeWaypointCallbacks()
704 else
705 local reason = (t[5] and (QHFormat("WAYPOINT_REASON", t[5]).."\n"..self.objective:Reason(true)))
706 or self.objective:Reason(true)
708 if QuestHelper.c == t[1] then
709 -- Translate the position to the zone the player is standing in.
710 local c, z = QuestHelper.c, QuestHelper.z
711 local x, y = QuestHelper.Astrolabe:TranslateWorldMapPosition(t[1], t[2], t[3], t[4], c, z)
712 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, reason)
713 else
714 -- Try to find the nearest zone on the continent the objective is in.
715 local index, distsqr, x, y
716 for z, i in pairs(QuestHelper_IndexLookup[t[1]]) do
717 local _x, _y = QuestHelper.Astrolabe:TranslateWorldMapPosition(t[1], t[2], t[3], t[4], t[1], z)
718 local d = (_x-0.5)*(_x-0.5)+(_y-0.5)*(_y-0.5)
719 if not index or d < distsqr then
720 index, distsqr, x, y = i, d, _x, _y
723 local c, z = QuestHelper_IndexLookup[index]
724 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, reason)
728 QuestHelper.Astrolabe:PlaceIconOnMinimap(self, unpack(self.target))
729 else
730 self.recalc_timeout = self.recalc_timeout - 1
733 local edge = QuestHelper.Astrolabe:IsIconOnEdge(self)
735 if edge then
736 self.arrow:Show()
737 self.dot:Hide()
738 self.bg:Hide()
739 else
740 self.arrow:Hide()
741 self.dot:Show()
742 self.bg:Show()
745 if edge then
746 local angle = QuestHelper.Astrolabe:GetDirectionToIcon(self)
747 if GetCVar("rotateMinimap") == "1" then
748 angle = angle + MiniMapCompassRing:GetFacing()
751 self.arrow:SetFacing(angle)
752 self.arrow:SetPosition(ofs * (137 / 140) - radius * math.sin(angle),
753 ofs + radius * math.cos(angle), 0);
755 if self.phase > 6.283185307179586476925 then
756 self.phase = self.phase-6.283185307179586476925+elapsed*3.5
757 else
758 self.phase = self.phase+elapsed*3.5
760 self.arrow:SetModelScale(0.600000023841879+0.1*math.sin(self.phase))
762 else
763 self:Hide()
767 function icon:SetObjective(objective)
768 self:SetHeight(20*QuestHelper_Pref.scale)
769 self:SetWidth(20*QuestHelper_Pref.scale)
771 if objective ~= self.objective then
772 if objective and not QuestHelper_Pref.hide then
773 self:Show()
774 else
775 QuestHelper:InvokeWaypointCallbacks()
776 self:Hide()
779 self.objective = objective
780 self.recalc_timeout = 0
784 function icon:OnEnter()
785 if self.objective then
786 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
787 QuestHelper.tooltip:ClearLines()
789 if self.target[5] then
790 QuestHelper.tooltip:AddLine(QHFormat("WAYPOINT_REASON", self.target[5]), unpack(QuestHelper:GetColourTheme().tooltip))
791 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.serif, 14)
794 QuestHelper:AppendObjectiveToTooltip(self.objective)
795 QuestHelper.tooltip:Show()
799 function icon:OnLeave()
800 QuestHelper.tooltip:Hide()
803 function icon:OnClick()
804 if self.objective then
805 local menu = QuestHelper:CreateMenu()
806 QuestHelper:CreateMenuTitle(menu, self.objective:Reason(true))
807 QuestHelper:AddObjectiveOptionsToMenu(self.objective, menu)
808 menu:ShowAtCursor()
812 function icon:OnEvent()
813 if self.objective and self.objective.pos then
814 self:Show()
815 else
816 self:Hide()
820 icon:SetScript("OnUpdate", icon.OnUpdate)
821 icon:SetScript("OnEnter", icon.OnEnter)
822 icon:SetScript("OnLeave", icon.OnLeave)
823 icon:SetScript("OnEvent", icon.OnEvent)
824 icon:SetScript("OnClick", icon.OnClick)
826 icon:RegisterForClicks("RightButtonUp")
827 icon:RegisterEvent("PLAYER_ENTERING_WORLD")
829 return icon