take two
[QuestHelper.git] / dodads.lua
blob54b9f1c27ba55b72eaf28a754a74778193a1bf0b
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;
6 local Minimap = _G.Minimap
8 -- These conversions are nasty, and this entire section needs a serious cleanup.
9 local function convertLocation(p)
10 local c, x, y = QuestHelper.Astrolabe:FromAbsoluteContinentPosition(p.c, p.x, p.y)
11 return c, 0, x, y
12 end
14 local function convertLocationToScreen(p, c, z)
15 local pc, _, px, py = convertLocation(p)
16 local ox, oy = QuestHelper.Astrolabe:TranslateWorldMapPosition(pc, 0, px, py, c, z)
17 --QuestHelper:TextOut(string.format("%f/%f/%f to %f/%f/%f to %f/%f %f/%f", p.c, p.x, p.y, pc, px, py, c, z, ox, oy))
18 return ox, oy
19 end
21 local function convertRawToScreen(tc, x, y, c, z)
22 local rc, rx, ry = QuestHelper.Astrolabe:FromAbsoluteContinentPosition(tc, x, y)
23 return QuestHelper.Astrolabe:TranslateWorldMapPosition(rc, 0, rx, ry, c, z)
24 end
26 local scrolf = CreateFrame("SCROLLFRAME", nil, WorldMapButton)
27 scrolf:SetFrameLevel(WorldMapButton:GetFrameLevel()+1)
28 scrolf:SetAllPoints()
29 scrolf:SetFrameStrata("FULLSCREEN")
31 local local_high_parent = CreateFrame("FRAME", nil, scrolf)
32 local_high_parent:SetFrameLevel(2)
33 local_high_parent:SetAllPoints()
35 local local_low_parent = CreateFrame("FRAME", nil, scrolf)
36 local_low_parent:SetFrameLevel(1)
37 local_low_parent:SetAllPoints()
39 QuestHelper.map_overlay = CreateFrame("FRAME", nil, scrolf)
40 scrolf:SetScrollChild(QuestHelper.map_overlay)
41 QuestHelper.map_overlay:SetAllPoints()
43 local function ClampLine(x1, y1, x2, y2)
44 if x1 and y1 and x2 and y2 then
45 local x_div, y_div = (x2-x1), (y2-y1)
46 local x_0 = y1-x1/x_div*y_div
47 local x_1 = y1+(1-x1)/x_div*y_div
48 local y_0 = x1-y1/y_div*x_div
49 local y_1 = x1+(1-y1)/y_div*x_div
51 if y1 < 0 then
52 x1 = y_0
53 y1 = 0
54 end
56 if y2 < 0 then
57 x2 = y_0
58 y2 = 0
59 end
61 if y1 > 1 then
62 x1 = y_1
63 y1 = 1
64 end
66 if y2 > 1 then
67 x2 = y_1
68 y2 = 1
69 end
71 if x1 < 0 then
72 y1 = x_0
73 x1 = 0
74 end
76 if x2 < 0 then
77 y2 = x_0
78 x2 = 0
79 end
81 if x1 > 1 then
82 y1 = x_1
83 x1 = 1
84 end
86 if x2 > 1 then
87 y2 = x_1
88 x2 = 1
89 end
91 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
92 return x1, y1, x2, y2
93 end
94 end
95 end
97 local walker_loc
99 function QuestHelper:CreateWorldMapWalker()
100 local walker = CreateFrame("Button", nil, QuestHelper.map_overlay)
101 walker_loc = walker
102 walker:SetWidth(0)
103 walker:SetHeight(0)
104 walker:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", 0, 0)
105 walker:Show()
107 walker.phase = 0.0
108 walker.dots = {}
109 walker.points = {}
110 walker.origin = {}
111 walker.frame = self
112 walker.map_dodads = {}
113 walker.used_map_dodads = 0
115 QuestHelper: Assert(self == QuestHelper)
116 QuestHelper: Assert(self.Astrolabe)
118 function walker:OnUpdate(elapsed)
119 local out = 0
121 if QuestHelper_Pref.show_ants then
122 local points = self.points
124 self.phase = self.phase + elapsed * 0.66
125 while self.phase > 1 do self.phase = self.phase - 1 end
127 local w, h = QuestHelper.map_overlay:GetWidth(), -QuestHelper.map_overlay:GetHeight()
129 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
131 local last_x, last_y = self.frame.Astrolabe:TranslateWorldMapPosition(self.frame.c, self.frame.z, self.frame.x, self.frame.y, c, z)
132 local remainder = self.phase
134 for i, pos in ipairs(points) do
135 local new_x, new_y = unpack(pos)
136 local x1, y1, x2, y2 = ClampLine(last_x, last_y, new_x, new_y)
137 last_x, last_y = new_x, new_y
139 if x1 then
140 local len = math.sqrt((x1-x2)*(x1-x2)*16/9+(y1-y2)*(y1-y2))
142 if len > 0.0001 then
143 local interval = .025/len
144 local p = remainder*interval
146 while p < 1 do
147 out = out + 1
148 local dot = self.dots[out]
149 if not dot then
150 dot = QuestHelper:CreateDotTexture(self)
151 dot:SetDrawLayer("BACKGROUND")
152 self.dots[out] = dot
155 dot:ClearAllPoints()
156 dot:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x1*w*(1-p)+x2*w*p, y1*h*(1-p)+y2*h*p)
158 p = p + interval
161 remainder = (p-1)/interval
167 while #self.dots > out do
168 QuestHelper:ReleaseTexture(table.remove(self.dots))
172 function walker:RouteChanged(route)
173 if route then self.route = route end -- we cache it so we can refer to it later when the world map changes
174 if not self.route then return end
176 local dbgstr = string.format("%s %s %s %s", tostring(self), tostring(self.frame), tostring(QuestHelper), tostring(QuestHelper and QuestHelper.Astrolabe))
177 QuestHelper: Assert(self.frame == QuestHelper, dbgstr)
178 QuestHelper: Assert(QuestHelper.Astrolabe, dbgstr)
180 if self.next_item then
181 self.next_item:MarkAsNext(false)
184 if self.frame.Astrolabe.WorldMapVisible then
185 local points = self.points
186 local cur = self.frame.pos
188 while #points > 0 do self.frame:ReleaseTable(table.remove(points)) end
190 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
192 -- I'm not quite sure what the point of this is.
193 --[[
194 if self.frame.target then
195 travel_time = math.max(0, self.frame.target_time-time())
196 cur = self.frame.target
197 local t = self.frame:CreateTable()
198 t[1], t[2] = convertLocationToScreen(cur, c, z)
199 table.insert(points, t)
200 end]]
202 for i, obj in ipairs(self.route) do
203 --QuestHelper:TextOut(string.format("%s", tostring(obj)))
205 --[[
206 local t = QuestHelper:CreateTable()
207 t[1], t[2] = convertLocationToScreen(obj.loc, c, z)
209 table.insert(list, t)]]
211 -- We're ignoring travel time for now.
212 --[[
213 travel_time = travel_time + 60
214 obj.travel_time = travel_time]]
215 if i > 1 then -- skip the start location
216 local t = self.frame:CreateTable()
217 t[1], t[2] = convertLocationToScreen(obj.loc, c, z)
219 table.insert(points, t)
221 --if lotsup then print(obj.ignore, obj.loc.x, obj.loc.y, obj.loc.c) end
223 --QuestHelper:TextOut(string.format("%s/%s/%s to %s/%s", tostring(obj.c), tostring(obj.x), tostring(obj.y), tostring(t[1]), tostring(t[2])))
225 --lotsup = false
227 local cur_dodad = 1
228 for i = 2, #self.route do -- 2 because we're skipping the player
229 if not self.route[i].ignore then
230 local dodad = self.map_dodads[cur_dodad]
231 if not dodad then
232 self.map_dodads[cur_dodad] = self.frame:CreateWorldMapDodad(self.route[i], i == 2)
233 else
234 self.map_dodads[cur_dodad]:SetObjective(self.route[i], i == 2)
237 if cur_dodad == 1 then
238 self.map_dodads[cur_dodad]:MarkAsNext(true)
240 cur_dodad = cur_dodad + 1
244 if cur_dodad <= self.used_map_dodads then for i = cur_dodad,self.used_map_dodads do
245 self.map_dodads[i]:SetObjective(nil, false)
246 end end
248 self.used_map_dodads = cur_dodad - 1
252 QH_Event("WORLD_MAP_UPDATE", function () walker:RouteChanged() end)
254 QH_Hook(walker, "OnUpdate", walker.OnUpdate)
256 return walker
259 function QuestHelper:GetOverlapObjectives(obj)
260 local w, h = self.map_overlay:GetWidth(), self.map_overlay:GetHeight()
261 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
263 local list = self.overlap_list
265 if not list then
266 list = {}
267 self.overlap_list = list
268 else
269 while table.remove(list) do end
272 local cx, cy = GetCursorPosition()
274 local es = QuestHelper.map_overlay:GetEffectiveScale()
275 local ies = 1/es
277 cx, cy = (cx-self.map_overlay:GetLeft()*es)*ies, (self.map_overlay:GetTop()*es-cy)*ies
279 local s = 10*QuestHelper_Pref.scale
281 for i, o in ipairs(walker_loc.route) do
282 --QuestHelper: Assert(o, string.format("nil dodads pos issue, o %s", tostring(o)))
283 --QuestHelper: Assert(o.pos, string.format("nil dodads pos issue, pos %s", QuestHelper:StringizeTable(o)))
284 if not o.ignore then
285 if o == obj then
286 table.insert(list, o)
287 else
288 local x, y = convertLocationToScreen(o.loc, c, z)
290 if x and y and x > 0 and y > 0 and x < 1 and y < 1 then
291 x, y = x*w, y*h
293 if cx >= x-s and cy >= y-s and cx <= x+s and cy <= y+s then
294 table.insert(list, o)
301 table.sort(list, function(a, b) return (a.distance or 0) < (b.distance or 0) end)
303 return list
306 function QuestHelper:AppendObjectiveProgressToTooltip(o, tooltip, font, depth)
307 if o.progress then
308 local prog_sort_table = {}
310 local theme = self:GetColourTheme()
312 local indent = (" "):rep(depth or 0)
314 for user, progress in pairs(o.progress) do
315 table.insert(prog_sort_table, user)
318 table.sort(prog_sort_table, function(a, b)
319 if o.progress[a][3] < o.progress[b][3] then
320 return true
321 elseif o.progress[a][3] == o.progress[b][3] then
322 return a < b
324 return false
325 end)
327 for i, u in ipairs(prog_sort_table) do
328 tooltip:AddDoubleLine(indent..QHFormat("PEER_PROGRESS", u),
329 self:ProgressString(o.progress[u][1].."/"..o.progress[u][2],
330 o.progress[u][3]), unpack(theme.tooltip))
332 if font then
333 local last, name = tooltip:NumLines(), tooltip:GetName()
334 local left, right = _G[name.."TextLeft"..last], _G[name.."TextRight"..last]
336 left:SetFont(font, 13)
337 right:SetFont(font, 13)
341 while table.remove(prog_sort_table) do end
345 function QuestHelper:AppendObjectiveToTooltip(o)
346 local theme = self:GetColourTheme()
348 QuestHelper: Assert(o.map_desc)
349 for _, v in ipairs(o.map_desc) do
350 self.tooltip:AddLine(v, unpack(theme.tooltip))
351 self.tooltip:GetPrevLines():SetFont(self.font.serif, 14)
354 if o.map_desc_chain then
355 self:AppendObjectiveToTooltip(o.map_desc_chain)
356 else
357 --[[self:AppendObjectiveProgressToTooltip(o, self.tooltip, QuestHelper.font.sans)
359 self.tooltip:AddDoubleLine(QHText("TRAVEL_ESTIMATE"), QHFormat("TRAVEL_ESTIMATE_VALUE", o.distance or 0), unpack(theme.tooltip))
360 self.tooltip:GetPrevLines():SetFont(self.font.sans, 11)
361 select(2, self.tooltip:GetPrevLines()):SetFont(self.font.sans, 11)]]
365 globx = 0.5
366 globy = 0.5
368 local function rightclick_menu(obj)
369 if obj then
370 local menu = QuestHelper:CreateMenu()
371 local list = QuestHelper:GetOverlapObjectives(obj)
372 local item
374 if #list > 1 then
375 QuestHelper:CreateMenuTitle(menu, "Objectives")
377 for i, o in ipairs(list) do
378 local submenu = QuestHelper:CreateMenu()
379 item = QuestHelper:CreateMenuItem(menu, o.map_desc[1])
380 item:SetSubmenu(submenu)
381 item:AddTexture(QuestHelper:CreateIconTexture(item, o.icon_id or 8), true)
382 QuestHelper:AddObjectiveOptionsToMenu(o, submenu)
384 else
385 QuestHelper:CreateMenuTitle(menu, obj.map_desc[1])
386 QuestHelper:AddObjectiveOptionsToMenu(obj, menu)
389 menu:ShowAtCursor()
393 function QuestHelper:CreateWorldMapDodad(objective, nxt)
394 local icon = CreateFrame("Button", nil, QuestHelper.map_overlay)
395 icon:SetFrameStrata("FULLSCREEN")
397 function icon:SetTooltip(list)
398 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
399 QuestHelper.tooltip:ClearLines()
401 local first = true
403 for i, o in ipairs(list) do
404 if first then
405 first = false
406 else
407 QuestHelper.tooltip:AddLine("|c80ff0000 . . . . . .|r")
408 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.sans, 8)
411 QuestHelper:AppendObjectiveToTooltip(o)
414 QuestHelper.tooltip:Show()
417 function icon:MarkAsNext(nxt)
418 self.next = nxt
420 QH_Hook(self, "OnUpdate", self.OnUpdate)
423 function icon:SetObjective(objective, nxt)
424 self:SetHeight(20*QuestHelper_Pref.scale)
425 self:SetWidth(20*QuestHelper_Pref.scale)
427 if self.dot then
428 QuestHelper:ReleaseTexture(self.dot)
429 self.dot = nil
432 if self.bg then
433 QuestHelper:ReleaseTexture(self.bg)
434 self.bg = nil
437 if objective then
438 self.objective = objective
440 if nxt then
441 self.bg = QuestHelper:CreateIconTexture(self, 13)
442 elseif objective.map_highlight then
443 self.bg = QuestHelper:CreateIconTexture(self, 14)
444 else
445 self.bg = QuestHelper:CreateIconTexture(self, 16)
448 self.dot = QuestHelper:CreateIconTexture(self, objective.icon_id or 8)
450 self.bg:SetDrawLayer("BACKGROUND")
451 self.bg:SetAllPoints()
452 self.dot:SetPoint("TOPLEFT", self, "TOPLEFT", 3*QuestHelper_Pref.scale, -3*QuestHelper_Pref.scale)
453 self.dot:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -3*QuestHelper_Pref.scale, 3*QuestHelper_Pref.scale)
455 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(objective.loc))
456 --QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, 0, 0, globx, globy)
457 else
458 self.objective = nil
459 self:Hide()
463 local triangle_r, triangle_g, triangle_b = 1.0, 0.3, 0
464 local triangle_opacity = 0.6
466 function icon:CreateTriangles(solid, tritarget, tristartat, linetarget, linestartat, parent)
467 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
469 local function makeline(ax, ay, bx, by)
470 local tri = linetarget[linestartat]
471 if not tri then
472 tri = CreateLine(parent)
473 table.insert(linetarget, tri)
475 linestartat = linestartat + 1
477 tri:SetLine(ax, ay, bx, by)
478 tri:SetVertexColor(0, 0, 0, 0)
479 tri:Show()
482 for _, v in ipairs(solid) do
483 local adjx, adjy = v[1], v[2]
484 local x, y = convertRawToScreen(v.continent, v[1], v[2], c, z)
485 --print("matchup", c, v.continent, x, y)
486 if x and y then
487 local lx, ly = convertRawToScreen(v.continent, adjx + v[3], adjy + v[4], c, z)
488 local linemode = false
490 local lidx = 5
491 while lidx <= #v do
492 if type(v[lidx]) == "string" then
493 if v[lidx] == "d" then
494 lidx = lidx + 1
495 x, y = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
496 lx, ly = convertRawToScreen(v.continent, adjx + v[lidx + 2], adjy + v[lidx + 3], c, z)
497 lidx = lidx + 4
498 elseif v[lidx] == "l" then
499 linemode = true
500 lidx = lidx + 1
501 x, y = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
502 lx, ly = x, y
503 lidx = lidx + 2
504 else
505 QuestHelper: Assert(false)
507 else
508 if not linemode then
509 local tx, ty = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
511 local tri = tritarget[tristartat]
512 if not tri then
513 tri = CreateTriangle(parent)
514 table.insert(tritarget, tri)
516 tristartat = tristartat + 1
518 tri:SetTriangle(x, y, lx, ly, tx, ty)
519 tri:SetVertexColor(0, 0, 0, 0)
520 tri:Show()
522 lx, ly = tx, ty
523 lidx = lidx + 2
524 else
525 local tx, ty = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
527 makeline(x, y, tx, ty)
529 x, y = tx, ty
530 lidx = lidx + 2
535 if linemode then
536 makeline(x, y, lx, ly)
541 return tristartat, linestartat
544 function icon:SetGlow(list)
545 local w, h = QuestHelper.map_overlay:GetWidth(), QuestHelper.map_overlay:GetHeight()
546 local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
547 local zw = QuestHelper.Astrolabe:GetZoneWidth(c, z)
549 local solids = {}
551 local gid = 1
552 for _, v in ipairs(list) do
553 --print(v.cluster, v.cluster and v.cluster.solid)
554 if v.cluster and v.cluster.solid then
555 --print("solidified", #v.cluster.solid)
556 solids[v.cluster.solid] = true
557 else
558 local x, y = convertLocationToScreen(v.loc, c, z)
559 if not self.glow_list then
560 self.glow_list = QuestHelper:CreateTable()
562 local glo = self.glow_list[gid]
563 if not glo then
564 glo = QuestHelper:CreateGlowTexture(self)
565 self.glow_list[gid] = glo
567 gid = gid + 1
569 glo:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x*w, -y*h)
570 glo:SetVertexColor(triangle_r, triangle_g, triangle_b, 1)
571 glo:SetWidth(h / 20)
572 glo:SetHeight(h / 20)
573 glo:Show()
577 local tid = 1
578 local lid = 1
580 for k, _ in pairs(solids) do
581 if not self.triangle_list then
582 self.triangle_list = QuestHelper:CreateTable()
584 if not self.line_list then
585 self.line_list = QuestHelper:CreateTable()
588 tid, lid = self:CreateTriangles(k, self.triangle_list, tid, self.line_list, lid, local_low_parent)
590 -- call triangle maker here!
592 if self.triangle_list then
593 while #self.triangle_list >= tid do
594 ReleaseTriangle(table.remove(self.triangle_list))
597 if #self.triangle_list == 0 then
598 QuestHelper:ReleaseTable(self.triangle_list)
599 self.triangle_list = nil
603 if self.glow_list then
604 while #self.glow_list >= gid do
605 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
608 if #self.glow_list == 0 then
609 QuestHelper:ReleaseTable(self.glow_list)
610 self.glow_list = nil
614 if self.line_list then
615 while #self.line_list >= lid do
616 ReleaseLine(table.remove(self.line_list))
619 if #self.line_list == 0 then
620 QuestHelper:ReleaseTable(self.line_list)
621 self.line_list = nil
626 icon.show_glow = false
627 icon.glow_pct = 0.0
628 icon.phase = 0.0
629 icon.old_count = 0
631 function icon:OnUpdate(elapsed)
632 self.phase = (self.phase + elapsed)%6.283185307179586476925286766559005768394338798750211641949889185
634 if self.next and self.objective and self.objective.cluster.solid then
635 -- not entirely happy with this being here, but, welp
636 if not self.local_triangle_list then
637 self.local_triangle_list = QuestHelper:CreateTable()
639 if not self.local_line_list then
640 self.local_line_list = QuestHelper:CreateTable()
643 tid, lid = self:CreateTriangles(self.objective.cluster.solid, self.local_triangle_list, 1, self.local_line_list, 1, local_high_parent)
645 if self.local_triangle_list then
646 while #self.local_triangle_list >= tid do
647 ReleaseTriangle(table.remove(self.local_triangle_list))
651 if self.local_line_list then
652 while #self.local_line_list >= lid do
653 ReleaseLine(table.remove(self.local_line_list))
656 else
657 if self.local_triangle_list then
658 while #self.local_triangle_list > 0 do
659 ReleaseTriangle(table.remove(self.local_triangle_list))
661 QuestHelper:ReleaseTable(self.local_triangle_list)
662 self.local_triangle_list = nil
665 if self.local_line_list then
666 while #self.local_line_list > 0 do
667 ReleaseLine(table.remove(self.local_line_list))
669 QuestHelper:ReleaseTable(self.local_line_list)
670 self.local_line_list = nil
674 if self.old_count > 0 then
675 local list = QuestHelper:GetOverlapObjectives(self.objective)
677 if #list ~= self.old_count then
678 self:SetTooltip(list)
679 self.old_count = #list
680 self:SetGlow(list)
684 if self.show_glow then
685 self.glow_pct = math.min(1, self.glow_pct+elapsed*1.5)
686 else
687 self.glow_pct = math.max(0, self.glow_pct-elapsed*0.5)
689 if self.glow_pct == 0 then
690 if self.triangle_list then
691 while #self.triangle_list > 0 do
692 ReleaseTriangle(table.remove(self.triangle_list))
694 QuestHelper:ReleaseTable(self.triangle_list)
695 self.triangle_list = nil
698 if self.glow_list then
699 while #self.glow_list > 0 do
700 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
702 QuestHelper:ReleaseTable(self.glow_list)
703 self.glow_list = nil
706 if self.line_list then
707 while #self.line_list > 0 do
708 ReleaseLine(table.remove(self.line_list))
710 QuestHelper:ReleaseTable(self.line_list)
711 self.line_list = nil
714 if not self.next then QH_Hook(self, "OnUpdate", nil) end
718 if self.triangle_list then
719 for _, tri in ipairs(self.triangle_list) do
720 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity/2)
723 if self.line_list then
724 for _, tri in ipairs(self.line_list) do
725 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity)
728 if self.glow_list then
729 for _, tri in ipairs(self.glow_list) do
730 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity)
733 if self.local_triangle_list then
734 for _, tri in ipairs(self.local_triangle_list) do
735 tri:SetVertexColor(triangle_b, triangle_g, triangle_r, triangle_opacity/2)
738 if self.local_line_list then
739 for _, tri in ipairs(self.local_line_list) do
740 tri:SetVertexColor(triangle_b, triangle_g, triangle_r, triangle_opacity)
745 function icon:OnEnter()
746 local list = QuestHelper:GetOverlapObjectives(self.objective)
747 self:SetTooltip(list)
748 self.old_count = #list
750 icon.show_glow = true
752 self:SetGlow(list)
754 QH_Hook(self, "OnUpdate", self.OnUpdate)
757 function icon:OnLeave()
758 QuestHelper.tooltip:Hide()
759 self.show_glow = false
760 self.old_count = 0
763 function icon:OnEvent()
764 if self.objective then
765 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(self.objective.loc))
766 else
767 self.objective = nil
768 self:Hide()
772 function icon:OnClick()
773 rightclick_menu(self.objective)
776 QH_Hook(icon, "OnClick", icon.OnClick)
777 QH_Hook(icon, "OnEnter", icon.OnEnter)
778 QH_Hook(icon, "OnLeave", icon.OnLeave)
779 QH_Hook(icon, "OnEvent", icon.OnEvent)
781 icon:RegisterForClicks("RightButtonUp")
783 QH_Event("WORLD_MAP_UPDATE", function () icon:OnEvent() end)
785 icon:SetObjective(objective, nxt)
786 return icon
789 local callbacks = {}
790 local last_c, last_z, last_x, last_y, last_desc
792 function QuestHelper:AddWaypointCallback(func, ...)
793 local cb = self:CreateTable()
794 callbacks[cb] = true
795 local len = select("#", ...)
796 cb.len = len
797 cb.func = func
798 for i = 1,len do cb[i] = select(i, ...) end
799 cb[len+1] = last_c
800 cb[len+2] = last_z
801 cb[len+3] = last_x
802 cb[len+4] = last_y
803 cb[len+5] = last_desc
805 if last_c then
806 func(unpack(cb, 1, len+5))
809 return cb
812 function QuestHelper:RemoveWaypointCallback(cb)
813 callbacks[cb] = nil
814 self:ReleaseTable(cb)
817 function QuestHelper:InvokeWaypointCallbacks(c, z, x, y, desc)
818 QuestHelper: Assert(not c or type(c) == "number")
819 QuestHelper: Assert(not z or type(z) == "number")
820 QuestHelper: Assert(not x or type(x) == "number")
821 QuestHelper: Assert(not y or type(y) == "number")
822 if c == last_c and z == last_z and desc == last_desc and not x and not y then x, y = last_x, last_y end -- sometimes we may not have up-to-date location, but could still in theory be pointing at the same spot
824 if not c or (x and y) then
825 if c ~= last_c or z ~= last_z or x ~= last_x or y ~= last_y or desc ~= last_desc then
826 last_c, last_z, last_x, last_y, last_desc = c, z, x, y, desc
827 for cb in pairs(callbacks) do
828 local len = cb.len
829 cb[len+1] = c
830 cb[len+2] = z
831 cb[len+3] = x
832 cb[len+4] = y
833 cb[len+5] = desc
834 cb.func(unpack(cb, 1, len+5))
840 function QuestHelper:SetMinimapObject(minimap)
841 Minimap = minimap
842 QuestHelper.Astrolabe:SetMinimapObject(minimap)
843 QuestHelper.minimap_marker:SetParent(minimap)
844 QuestHelper.Astrolabe.processingFrame:SetParent(minimap)
847 --[[ Small parts of the arrow rendering code are thanks to Tomtom, with the following license:
849 -------------------------------------------------------------------------
850 Copyright (c) 2006-2007, James N. Whitehead II
851 All rights reserved.
853 Redistribution and use in source and binary forms, with or without
854 modification, are permitted provided that the following conditions are
855 met:
857 * Redistributions of source code must retain the above copyright
858 notice, this list of conditions and the following disclaimer.
859 * Redistributions in binary form must reproduce the above
860 copyright notice, this list of conditions and the following
861 disclaimer in the documentation and/or other materials provided
862 with the distribution.
863 * The name or alias of the copyright holder may not be used to endorse
864 or promote products derived from this software without specific prior
865 written permission.
867 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
868 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
869 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
870 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
871 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
872 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
873 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
874 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
875 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
876 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
877 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
878 ---------------------------------------------------------------------------]]
880 function QuestHelper:CreateMipmapDodad()
881 local icon = CreateFrame("Button", nil, Minimap)
882 icon:Hide()
883 icon.recalc_timeout = 0
885 icon.arrow = icon:CreateTexture("BACKGROUND")
886 icon.arrow:SetHeight(40)
887 icon.arrow:SetWidth(40)
888 icon.arrow:SetPoint("CENTER", 0, 0)
889 icon.arrow:SetTexture("Interface\\AddOns\\QuestHelper\\MinimapArrow")
890 icon.arrow:Hide()
892 icon.phase = 0
893 icon.target = {0, 0, 0, 0}
895 icon.bg = QuestHelper:CreateIconTexture(icon, 16)
896 icon.bg:SetDrawLayer("BACKGROUND")
897 icon.bg:SetAllPoints()
899 function icon:OnUpdate(elapsed)
900 local c, z, x, y, textdesc
901 if self.obj then
902 c, z = QuestHelper.collect_rc, QuestHelper.collect_rz
903 if c and z then
904 x, y = convertLocationToScreen(self.obj.loc, c, z)
907 if self.obj.map_desc_chain then
908 -- the first line will just be an "enroute" line
909 textdesc = self.obj.map_desc[1] .. "\n" .. self.obj.map_desc_chain.map_desc[1]
910 else
911 textdesc = self.obj.map_desc[1]
915 QuestHelper: Assert(not c or type(c) == "number")
916 QuestHelper: Assert(not z or type(z) == "number")
918 -- Deal with waypoint callbacks
919 if QuestHelper_Pref.hide or UnitIsDeadOrGhost("player") and not QuestHelper.InBrokenInstance then
920 QuestHelper:InvokeWaypointCallbacks()
921 else
922 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, textdesc)
925 if self.obj and not QuestHelper.InBrokenInstance then
926 self:Show() -- really only triggers if the non-broken-instance code is being poked
928 if not QuestHelper_Pref.hide and QuestHelper.Astrolabe:PlaceIconOnMinimap(self, convertLocation(self.obj.loc)) ~= -1 then
929 local edge = QuestHelper.Astrolabe:IsIconOnEdge(self)
931 if edge then
932 self.arrow:Show()
933 self.dot:Hide()
934 self.bg:Hide()
935 else
936 self.arrow:Hide()
937 self.dot:Show()
938 self.bg:Show()
941 if edge then
942 local angle = QuestHelper.Astrolabe:GetDirectionToIcon(self)
943 if GetCVar("rotateMinimap") == "1" then
944 angle = angle + QuestHelper.Astrolabe:GetFacing()
947 if elapsed then
948 if self.phase > 6.283185307179586476925 then
949 self.phase = self.phase-6.283185307179586476925+elapsed*3.5
950 else
951 self.phase = self.phase+elapsed*3.5
955 local scale = 1.0 + 0.1 * math.sin(self.phase)
957 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)
958 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)
960 else
961 self:Hide()
963 else
964 self:Hide()
968 function icon:SetObjective(obj)
969 self:SetHeight(20*QuestHelper_Pref.scale)
970 self:SetWidth(20*QuestHelper_Pref.scale)
972 if obj ~= self.obj then
973 self.obj = obj
975 self.recalc_timeout = 0
977 if self.dot then QuestHelper:ReleaseTexture(self.dot) self.dot = nil end
979 if self.obj then
980 self.dot = QuestHelper:CreateIconTexture(self, self.obj.icon_id or 8)
981 self.dot:SetPoint("TOPLEFT", icon, "TOPLEFT", 2, -2)
982 self.dot:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -2, 2)
985 self:OnUpdate()
989 function icon:OnEnter()
990 if self.obj then
991 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
992 QuestHelper.tooltip:ClearLines()
994 --[[if self.target[5] then
995 QuestHelper.tooltip:AddLine(QHFormat("WAYPOINT_REASON", self.target[5]), unpack(QuestHelper:GetColourTheme().tooltip))
996 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.serif, 14)
997 end]]
999 QuestHelper:AppendObjectiveToTooltip(self.obj)
1000 QuestHelper.tooltip:Show()
1004 function icon:OnLeave()
1005 QuestHelper.tooltip:Hide()
1008 function icon:OnClick()
1009 rightclick_menu(self.obj)
1012 function icon:OnEvent()
1013 if self.obj then
1014 self:Show()
1015 else
1016 self:Hide()
1020 QH_Hook(icon, "OnUpdate", icon.OnUpdate)
1021 QH_Hook(icon, "OnEnter", icon.OnEnter)
1022 QH_Hook(icon, "OnLeave", icon.OnLeave)
1023 QH_Hook(icon, "OnClick", icon.OnClick)
1025 icon:RegisterForClicks("RightButtonUp")
1027 QH_Event("PLAYER_ENTERING_WORLD", function () icon:OnEvent() end)
1029 return icon