update to 1.1.10
[QuestHelper.git] / dodads.lua
blob0894f4a40050320f293985a2514ea5d6f1a8cc94
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 QuestHelper.map_overlay = CreateFrame("FRAME", nil, scrolf)
32 scrolf:SetScrollChild(QuestHelper.map_overlay)
33 QuestHelper.map_overlay:SetAllPoints()
35 QuestHelper.map_overlay_uncropped = scrolf
37 local function ClampLine(x1, y1, x2, y2)
38 if x1 and y1 and x2 and y2 then
39 local x_div, y_div = (x2-x1), (y2-y1)
40 local x_0 = y1-x1/x_div*y_div
41 local x_1 = y1+(1-x1)/x_div*y_div
42 local y_0 = x1-y1/y_div*x_div
43 local y_1 = x1+(1-y1)/y_div*x_div
45 if y1 < 0 then
46 x1 = y_0
47 y1 = 0
48 end
50 if y2 < 0 then
51 x2 = y_0
52 y2 = 0
53 end
55 if y1 > 1 then
56 x1 = y_1
57 y1 = 1
58 end
60 if y2 > 1 then
61 x2 = y_1
62 y2 = 1
63 end
65 if x1 < 0 then
66 y1 = x_0
67 x1 = 0
68 end
70 if x2 < 0 then
71 y2 = x_0
72 x2 = 0
73 end
75 if x1 > 1 then
76 y1 = x_1
77 x1 = 1
78 end
80 if x2 > 1 then
81 y2 = x_1
82 x2 = 1
83 end
85 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
86 return x1, y1, x2, y2
87 end
88 end
89 end
91 local walker_loc
93 function QuestHelper:CreateWorldMapWalker()
94 local walker = CreateFrame("Button", nil, QuestHelper.map_overlay)
95 walker_loc = walker
96 walker:SetWidth(0)
97 walker:SetHeight(0)
98 walker:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", 0, 0)
99 walker:Show()
101 walker.phase = 0.0
102 walker.dots = {}
103 walker.points = {}
104 walker.origin = {}
105 walker.frame = self
106 walker.map_dodads = {}
107 walker.used_map_dodads = 0
109 QuestHelper: Assert(self == QuestHelper)
110 QuestHelper: Assert(self.Astrolabe)
112 function walker:OnUpdate(elapsed)
113 local out = 0
115 if QuestHelper_Pref.show_ants then
116 local points = self.points
118 self.phase = self.phase + elapsed * 0.66
119 while self.phase > 1 do self.phase = self.phase - 1 end
121 local w, h = QuestHelper.map_overlay:GetWidth(), -QuestHelper.map_overlay:GetHeight()
123 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
125 local last_x, last_y = self.frame.Astrolabe:TranslateWorldMapPosition(self.frame.c, self.frame.z, self.frame.x, self.frame.y, c, z)
126 local remainder = self.phase
128 for i, pos in ipairs(points) do
129 local new_x, new_y = unpack(pos)
130 local x1, y1, x2, y2 = ClampLine(last_x, last_y, new_x, new_y)
131 last_x, last_y = new_x, new_y
133 if x1 then
134 local len = math.sqrt((x1-x2)*(x1-x2)*16/9+(y1-y2)*(y1-y2))
136 if len > 0.0001 then
137 local interval = .025/len
138 local p = remainder*interval
140 while p < 1 do
141 out = out + 1
142 local dot = self.dots[out]
143 if not dot then
144 dot = QuestHelper:CreateDotTexture(self)
145 dot:SetDrawLayer("BACKGROUND")
146 self.dots[out] = dot
149 dot:ClearAllPoints()
150 dot:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x1*w*(1-p)+x2*w*p, y1*h*(1-p)+y2*h*p)
152 p = p + interval
155 remainder = (p-1)/interval
161 while #self.dots > out do
162 QuestHelper:ReleaseTexture(table.remove(self.dots))
166 function walker:RouteChanged(route)
167 if route then self.route = route end -- we cache it so we can refer to it later when the world map changes
168 if not self.route then return end
170 local dbgstr = string.format("%s %s %s %s", tostring(self), tostring(self.frame), tostring(QuestHelper), tostring(QuestHelper and QuestHelper.Astrolabe))
171 QuestHelper: Assert(self.frame == QuestHelper, dbgstr)
172 QuestHelper: Assert(QuestHelper.Astrolabe, dbgstr)
174 if self.next_item then
175 self.next_item:MarkAsNext(false)
176 self.next_item = nil
179 if self.frame.Astrolabe.WorldMapVisible then
180 local points = self.points
181 local cur = self.frame.pos
183 while #points > 0 do self.frame:ReleaseTable(table.remove(points)) end
185 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
187 -- I'm not quite sure what the point of this is.
188 --[[
189 if self.frame.target then
190 travel_time = math.max(0, self.frame.target_time-time())
191 cur = self.frame.target
192 local t = self.frame:CreateTable()
193 t[1], t[2] = convertLocationToScreen(cur, c, z)
194 table.insert(points, t)
195 end]]
197 for i, obj in ipairs(self.route) do
198 --QuestHelper:TextOut(string.format("%s", tostring(obj)))
200 --[[
201 local t = QuestHelper:CreateTable()
202 t[1], t[2] = convertLocationToScreen(obj.loc, c, z)
204 table.insert(list, t)]]
206 -- We're ignoring travel time for now.
207 --[[
208 travel_time = travel_time + 60
209 obj.travel_time = travel_time]]
210 if i > 1 then -- skip the start location
211 local t = self.frame:CreateTable()
212 t[1], t[2] = convertLocationToScreen(obj.loc, c, z)
214 table.insert(points, t)
216 --if lotsup then print(obj.ignore, obj.loc.x, obj.loc.y, obj.loc.c) end
218 --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])))
220 --lotsup = false
222 local cur_dodad = 1
223 for i = 2, #self.route do -- 2 because we're skipping the player
224 if not self.route[i].ignore then
225 local dodad = self.map_dodads[cur_dodad]
226 if not dodad then
227 self.map_dodads[cur_dodad] = self.frame:CreateWorldMapDodad(self.route[i], i == 2)
228 else
229 self.map_dodads[cur_dodad]:SetObjective(self.route[i], i == 2)
232 if cur_dodad == 1 then
233 self.map_dodads[cur_dodad]:MarkAsNext(true)
234 self.next_item = self.map_dodads[cur_dodad]
236 cur_dodad = cur_dodad + 1
240 if cur_dodad <= self.used_map_dodads then for i = cur_dodad,self.used_map_dodads do
241 self.map_dodads[i]:SetObjective(nil, false)
242 end end
244 self.used_map_dodads = cur_dodad - 1
248 QH_Event("WORLD_MAP_UPDATE", function () walker:RouteChanged() end)
250 QH_Hook(walker, "OnUpdate", walker.OnUpdate)
252 return walker
255 function QuestHelper:GetOverlapObjectives(obj)
256 local w, h = self.map_overlay:GetWidth(), self.map_overlay:GetHeight()
257 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
259 local list = self.overlap_list
261 if not list then
262 list = {}
263 self.overlap_list = list
264 else
265 while table.remove(list) do end
268 local cx, cy = GetCursorPosition()
270 local es = QuestHelper.map_overlay:GetEffectiveScale()
271 local ies = 1/es
273 cx, cy = (cx-self.map_overlay:GetLeft()*es)*ies, (self.map_overlay:GetTop()*es-cy)*ies
275 local s = 10*QuestHelper_Pref.scale
277 for i, o in ipairs(walker_loc.route) do
278 --QuestHelper: Assert(o, string.format("nil dodads pos issue, o %s", tostring(o)))
279 --QuestHelper: Assert(o.pos, string.format("nil dodads pos issue, pos %s", QuestHelper:StringizeTable(o)))
280 if not o.ignore then
281 if o == obj then
282 table.insert(list, o)
283 else
284 local x, y = convertLocationToScreen(o.loc, c, z)
286 if x and y and x > 0 and y > 0 and x < 1 and y < 1 then
287 x, y = x*w, y*h
289 if cx >= x-s and cy >= y-s and cx <= x+s and cy <= y+s then
290 table.insert(list, o)
297 table.sort(list, function(a, b) return (a.distance or 0) < (b.distance or 0) end)
299 return list
302 function QuestHelper:AppendObjectiveProgressToTooltip(o, tooltip, font, depth)
303 if o.progress then
304 local prog_sort_table = {}
306 local theme = self:GetColourTheme()
308 local indent = (" "):rep(depth or 0)
310 for user, progress in pairs(o.progress) do
311 table.insert(prog_sort_table, user)
314 table.sort(prog_sort_table, function(a, b)
315 if o.progress[a][3] < o.progress[b][3] then
316 return true
317 elseif o.progress[a][3] == o.progress[b][3] then
318 return a < b
320 return false
321 end)
323 for i, u in ipairs(prog_sort_table) do
324 tooltip:AddDoubleLine(indent..QHFormat("PEER_PROGRESS", u),
325 self:ProgressString(o.progress[u][1].."/"..o.progress[u][2],
326 o.progress[u][3]), unpack(theme.tooltip))
328 if font then
329 local last, name = tooltip:NumLines(), tooltip:GetName()
330 local left, right = _G[name.."TextLeft"..last], _G[name.."TextRight"..last]
332 left:SetFont(font, 13)
333 right:SetFont(font, 13)
337 while table.remove(prog_sort_table) do end
341 function QuestHelper:AppendObjectiveToTooltip(o)
342 local theme = self:GetColourTheme()
344 QuestHelper: Assert(o.map_desc)
345 for _, v in ipairs(o.map_desc) do
346 self.tooltip:AddLine(v, unpack(theme.tooltip))
347 self.tooltip:GetPrevLines():SetFont(self.font.serif, 14)
350 if o.map_desc_chain then
351 self:AppendObjectiveToTooltip(o.map_desc_chain)
352 else
353 self:AppendObjectiveProgressToTooltip(o, self.tooltip, QuestHelper.font.sans)
355 if QuestHelper_Pref.travel_time then
356 self.tooltip:AddDoubleLine(QHText("TRAVEL_ESTIMATE"), QHFormat("TRAVEL_ESTIMATE_VALUE", o.distance or 0), unpack(theme.tooltip))
357 self.tooltip:GetPrevLines():SetFont(self.font.sans, 11)
362 globx = 0.5
363 globy = 0.5
365 local function rightclick_menu(obj)
366 if obj then
367 local menu = QuestHelper:CreateMenu()
368 local list = QuestHelper:GetOverlapObjectives(obj)
369 local item
371 if #list > 1 then
372 QuestHelper:CreateMenuTitle(menu, "Objectives")
374 for i, o in ipairs(list) do
375 local submenu = QuestHelper:CreateMenu()
376 item = QuestHelper:CreateMenuItem(menu, o.map_desc[1])
377 item:SetSubmenu(submenu)
378 item:AddTexture(QuestHelper:CreateIconTexture(item, o.icon_id or 8), true)
379 QuestHelper:AddObjectiveOptionsToMenu(o, submenu)
381 else
382 QuestHelper:CreateMenuTitle(menu, obj.map_desc[1])
383 QuestHelper:AddObjectiveOptionsToMenu(obj, menu)
386 menu:ShowAtCursor()
390 function QuestHelper:CreateWorldMapDodad(objective, nxt)
391 local icon = CreateFrame("Button", nil, QuestHelper.map_overlay)
392 icon:SetFrameStrata("FULLSCREEN")
394 function icon:SetTooltip(list)
395 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
396 QuestHelper.tooltip:ClearLines()
398 local first = true
400 for i, o in ipairs(list) do
401 if first then
402 first = false
403 else
404 QuestHelper.tooltip:AddLine("|c80ff0000 . . . . . .|r")
405 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.sans, 8)
408 QuestHelper:AppendObjectiveToTooltip(o)
411 QuestHelper.tooltip:Show()
414 function icon:MarkAsNext(nxt)
415 self.next = nxt
417 QH_Hook(self, "OnUpdate", self.OnUpdate)
420 function icon:SetObjective(objective, nxt)
421 self:SetHeight(20*QuestHelper_Pref.scale)
422 self:SetWidth(20*QuestHelper_Pref.scale)
424 if self.dot then
425 QuestHelper:ReleaseTexture(self.dot)
426 self.dot = nil
429 if self.bg then
430 QuestHelper:ReleaseTexture(self.bg)
431 self.bg = nil
434 if objective then
435 self.objective = objective
437 if nxt then
438 self.bg = QuestHelper:CreateIconTexture(self, 13)
439 elseif objective.map_highlight then
440 self.bg = QuestHelper:CreateIconTexture(self, 14)
441 else
442 self.bg = QuestHelper:CreateIconTexture(self, 16)
445 self.dot = QuestHelper:CreateIconTexture(self, objective.icon_id or 8)
447 self.bg:SetDrawLayer("BACKGROUND")
448 self.bg:SetAllPoints()
449 self.dot:SetPoint("TOPLEFT", self, "TOPLEFT", 3*QuestHelper_Pref.scale, -3*QuestHelper_Pref.scale)
450 self.dot:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -3*QuestHelper_Pref.scale, 3*QuestHelper_Pref.scale)
452 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(objective.loc))
453 --QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, 0, 0, globx, globy)
454 else
455 self.objective = nil
456 self:Hide()
457 self.next = false
458 self:OnUpdate(0)
462 local triangle_r, triangle_g, triangle_b = 1.0, 0.3, 0
463 local triangle_opacity = 0.6
465 function icon:CreateTriangles(solid, tritarget, tristartat, linetarget, linestartat, parent)
466 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
468 local function makeline(ax, ay, bx, by)
469 local tri = linetarget[linestartat]
470 if not tri then
471 tri = CreateLine(parent)
472 table.insert(linetarget, tri)
474 linestartat = linestartat + 1
476 tri:SetLine(ax, ay, bx, by)
477 tri:SetVertexColor(0, 0, 0, 0)
478 tri:Show()
481 for _, v in ipairs(solid) do
482 local adjx, adjy = v[1], v[2]
483 local x, y = convertRawToScreen(v.continent, v[1], v[2], c, z)
484 --print("matchup", c, v.continent, x, y)
485 if x and y then
486 local lx, ly = convertRawToScreen(v.continent, adjx + v[3], adjy + v[4], c, z)
487 local linemode = false
489 local lidx = 5
490 while lidx <= #v do
491 if type(v[lidx]) == "string" then
492 if v[lidx] == "d" then
493 lidx = lidx + 1
494 x, y = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
495 lx, ly = convertRawToScreen(v.continent, adjx + v[lidx + 2], adjy + v[lidx + 3], c, z)
496 lidx = lidx + 4
497 elseif v[lidx] == "l" then
498 linemode = true
499 lidx = lidx + 1
500 x, y = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
501 lx, ly = x, y
502 lidx = lidx + 2
503 else
504 QuestHelper: Assert(false)
506 else
507 if not linemode then
508 local tx, ty = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
510 local tri = tritarget[tristartat]
511 if not tri then
512 tri = CreateTriangle(parent)
513 table.insert(tritarget, tri)
515 tristartat = tristartat + 1
517 tri:SetTriangle(x, y, lx, ly, tx, ty)
518 tri:SetVertexColor(0, 0, 0, 0)
519 tri:Show()
521 lx, ly = tx, ty
522 lidx = lidx + 2
523 else
524 local tx, ty = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
526 makeline(x, y, tx, ty)
528 x, y = tx, ty
529 lidx = lidx + 2
534 if linemode then
535 makeline(x, y, lx, ly)
540 return tristartat, linestartat
543 function icon:SetGlow(list)
544 local w, h = QuestHelper.map_overlay:GetWidth(), QuestHelper.map_overlay:GetHeight()
545 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
546 local zw = QuestHelper.Astrolabe:GetZoneWidth(c, z)
548 local solids = {}
550 local gid = 1
551 for _, v in ipairs(list) do
552 --print(v.cluster, v.cluster and v.cluster.solid)
553 if v.cluster and v.cluster.solid then
554 --print("solidified", #v.cluster.solid)
555 solids[v.cluster.solid] = true
556 else
557 local x, y = convertLocationToScreen(v.loc, c, z)
558 if x and y then
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()
578 local tid = 1
579 local lid = 1
581 for k, _ in pairs(solids) do
582 if not self.triangle_list then
583 self.triangle_list = QuestHelper:CreateTable()
585 if not self.line_list then
586 self.line_list = QuestHelper:CreateTable()
589 tid, lid = self:CreateTriangles(k, self.triangle_list, tid, self.line_list, lid, QuestHelper.map_overlay)
591 -- call triangle maker here!
593 if self.triangle_list then
594 while #self.triangle_list >= tid do
595 ReleaseTriangle(table.remove(self.triangle_list))
598 if #self.triangle_list == 0 then
599 QuestHelper:ReleaseTable(self.triangle_list)
600 self.triangle_list = nil
604 if self.glow_list then
605 while #self.glow_list >= gid do
606 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
609 if #self.glow_list == 0 then
610 QuestHelper:ReleaseTable(self.glow_list)
611 self.glow_list = nil
615 if self.line_list then
616 while #self.line_list >= lid do
617 ReleaseLine(table.remove(self.line_list))
620 if #self.line_list == 0 then
621 QuestHelper:ReleaseTable(self.line_list)
622 self.line_list = nil
627 icon.show_glow = false
628 icon.glow_pct = 0.0
629 icon.phase = 0.0
630 icon.old_count = 0
632 function icon:OnUpdate(elapsed)
633 self.phase = (self.phase + elapsed)%6.283185307179586476925286766559005768394338798750211641949889185
635 if self.next and self.objective and self.objective.cluster.solid and QuestHelper_Pref.zones == "next" then
637 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
638 if self.tri_c ~= c or self.tri_z ~= z then
639 -- not entirely happy with this being here, but, welp
640 if not self.local_triangle_list then
641 self.local_triangle_list = QuestHelper:CreateTable()
643 if not self.local_line_list then
644 self.local_line_list = QuestHelper:CreateTable()
647 local tid, lid = self:CreateTriangles(self.objective.cluster.solid, self.local_triangle_list, 1, self.local_line_list, 1, QuestHelper.map_overlay)
649 if self.local_triangle_list then
650 while #self.local_triangle_list >= tid do
651 ReleaseTriangle(table.remove(self.local_triangle_list))
655 if self.local_line_list then
656 while #self.local_line_list >= lid do
657 ReleaseLine(table.remove(self.local_line_list))
662 self.tri_c, self.tri_z = c, z
663 else
664 if self.local_triangle_list then
665 while #self.local_triangle_list > 0 do
666 ReleaseTriangle(table.remove(self.local_triangle_list))
668 QuestHelper:ReleaseTable(self.local_triangle_list)
669 self.local_triangle_list = nil
672 if self.local_line_list then
673 while #self.local_line_list > 0 do
674 ReleaseLine(table.remove(self.local_line_list))
676 QuestHelper:ReleaseTable(self.local_line_list)
677 self.local_line_list = nil
680 self.tri_c, self.tri_z = nil, nil
683 if self.old_count > 0 then
684 local list = QuestHelper:GetOverlapObjectives(self.objective)
686 if #list ~= self.old_count then
687 self:SetTooltip(list)
688 self.old_count = #list
689 self:SetGlow(list)
693 if self.show_glow then
694 self.glow_pct = math.min(1, self.glow_pct+elapsed*1.5)
695 else
696 self.glow_pct = math.max(0, self.glow_pct-elapsed*0.5)
698 if self.glow_pct == 0 then
699 if self.triangle_list then
700 while #self.triangle_list > 0 do
701 ReleaseTriangle(table.remove(self.triangle_list))
703 QuestHelper:ReleaseTable(self.triangle_list)
704 self.triangle_list = nil
707 if self.glow_list then
708 while #self.glow_list > 0 do
709 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
711 QuestHelper:ReleaseTable(self.glow_list)
712 self.glow_list = nil
715 if self.line_list then
716 while #self.line_list > 0 do
717 ReleaseLine(table.remove(self.line_list))
719 QuestHelper:ReleaseTable(self.line_list)
720 self.line_list = nil
723 if not self.next then
724 QH_Hook(self, "OnUpdate", nil)
729 if self.triangle_list then
730 for _, tri in ipairs(self.triangle_list) do
731 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity/2)
734 if self.line_list then
735 for _, tri in ipairs(self.line_list) do
736 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity)
739 if self.glow_list then
740 for _, tri in ipairs(self.glow_list) do
741 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity)
744 if self.local_triangle_list then
745 for _, tri in ipairs(self.local_triangle_list) do
746 tri:SetVertexColor(triangle_b, triangle_g, triangle_r, triangle_opacity/2)
749 if self.local_line_list then
750 for _, tri in ipairs(self.local_line_list) do
751 tri:SetVertexColor(triangle_b, triangle_g, triangle_r, triangle_opacity)
756 function icon:OnEnter()
757 local list = QuestHelper:GetOverlapObjectives(self.objective)
758 self:SetTooltip(list)
759 self.old_count = #list
761 icon.show_glow = true
763 self:SetGlow(list)
765 QH_Hook(self, "OnUpdate", self.OnUpdate)
768 function icon:OnLeave()
769 QuestHelper.tooltip:Hide()
770 self.show_glow = false
771 self.old_count = 0
774 function icon:OnEvent()
775 if self.objective then
776 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(self.objective.loc))
777 else
778 self.objective = nil
779 self:Hide()
783 function icon:OnClick()
784 rightclick_menu(self.objective)
787 QH_Hook(icon, "OnClick", icon.OnClick)
788 QH_Hook(icon, "OnEnter", icon.OnEnter)
789 QH_Hook(icon, "OnLeave", icon.OnLeave)
790 QH_Hook(icon, "OnEvent", icon.OnEvent)
792 icon:RegisterForClicks("RightButtonUp")
794 QH_Event("WORLD_MAP_UPDATE", function () icon:OnEvent() end)
796 icon:SetObjective(objective, nxt)
797 return icon
800 local callbacks = {}
801 local last_c, last_z, last_x, last_y, last_desc
803 function QuestHelper:AddWaypointCallback(func, ...)
804 local cb = self:CreateTable()
805 callbacks[cb] = true
806 local len = select("#", ...)
807 cb.len = len
808 cb.func = func
809 for i = 1,len do cb[i] = select(i, ...) end
810 cb[len+1] = last_c
811 cb[len+2] = last_z
812 cb[len+3] = last_x
813 cb[len+4] = last_y
814 cb[len+5] = last_desc
816 if last_c then
817 func(unpack(cb, 1, len+5))
820 return cb
823 function QuestHelper:RemoveWaypointCallback(cb)
824 callbacks[cb] = nil
825 self:ReleaseTable(cb)
828 function QuestHelper:InvokeWaypointCallbacks(c, z, x, y, desc)
829 QuestHelper: Assert(not c or type(c) == "number")
830 QuestHelper: Assert(not z or type(z) == "number")
831 QuestHelper: Assert(not x or type(x) == "number")
832 QuestHelper: Assert(not y or type(y) == "number")
833 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
835 if not c or (x and y) then
836 if c ~= last_c or z ~= last_z or x ~= last_x or y ~= last_y or desc ~= last_desc then
837 last_c, last_z, last_x, last_y, last_desc = c, z, x, y, desc
838 for cb in pairs(callbacks) do
839 local len = cb.len
840 cb[len+1] = c
841 cb[len+2] = z
842 cb[len+3] = x
843 cb[len+4] = y
844 cb[len+5] = desc
845 cb.func(unpack(cb, 1, len+5))
851 function QuestHelper:SetMinimapObject(minimap)
852 Minimap = minimap
853 QuestHelper.Astrolabe:SetMinimapObject(minimap)
854 QuestHelper.minimap_marker:SetParent(minimap)
855 QuestHelper.Astrolabe.processingFrame:SetParent(minimap)
858 --[[ Small parts of the arrow rendering code are thanks to Tomtom, with the following license:
860 -------------------------------------------------------------------------
861 Copyright (c) 2006-2007, James N. Whitehead II
862 All rights reserved.
864 Redistribution and use in source and binary forms, with or without
865 modification, are permitted provided that the following conditions are
866 met:
868 * Redistributions of source code must retain the above copyright
869 notice, this list of conditions and the following disclaimer.
870 * Redistributions in binary form must reproduce the above
871 copyright notice, this list of conditions and the following
872 disclaimer in the documentation and/or other materials provided
873 with the distribution.
874 * The name or alias of the copyright holder may not be used to endorse
875 or promote products derived from this software without specific prior
876 written permission.
878 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
879 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
880 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
881 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
882 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
883 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
884 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
885 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
886 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
887 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
888 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
889 ---------------------------------------------------------------------------]]
891 function QuestHelper:CreateMipmapDodad()
892 local icon = CreateFrame("Button", nil, Minimap)
893 icon:Hide()
894 icon.recalc_timeout = 0
896 icon.arrow = icon:CreateTexture("BACKGROUND")
897 icon.arrow:SetHeight(40)
898 icon.arrow:SetWidth(40)
899 icon.arrow:SetPoint("CENTER", 0, 0)
900 icon.arrow:SetTexture("Interface\\AddOns\\QuestHelper\\MinimapArrow")
901 icon.arrow:Hide()
903 icon.phase = 0
904 icon.target = {0, 0, 0, 0}
906 icon.bg = QuestHelper:CreateIconTexture(icon, 16)
907 icon.bg:SetDrawLayer("BACKGROUND")
908 icon.bg:SetAllPoints()
910 function icon:OnUpdate(elapsed)
911 local c, z, x, y, textdesc
912 if self.obj then
913 c, z = QuestHelper.collect_rc, QuestHelper.collect_rz
914 if c and z then
915 x, y = convertLocationToScreen(self.obj.loc, c, z)
918 if self.obj.map_desc_chain then
919 -- the first line will just be an "enroute" line
920 textdesc = self.obj.map_desc[1] .. "\n" .. self.obj.map_desc_chain.map_desc[1]
921 else
922 textdesc = self.obj.map_desc[1]
926 QuestHelper: Assert(not c or type(c) == "number")
927 QuestHelper: Assert(not z or type(z) == "number")
929 -- Deal with waypoint callbacks
930 if QuestHelper_Pref.hide or UnitIsDeadOrGhost("player") and not QuestHelper.InBrokenInstance then
931 QuestHelper:InvokeWaypointCallbacks()
932 else
933 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, textdesc)
936 if self.obj and not QuestHelper.InBrokenInstance then
937 self:Show() -- really only triggers if the non-broken-instance code is being poked
939 if not QuestHelper_Pref.hide and QuestHelper.Astrolabe:PlaceIconOnMinimap(self, convertLocation(self.obj.loc)) ~= -1 then
940 local edge = QuestHelper.Astrolabe:IsIconOnEdge(self)
942 if edge then
943 self.arrow:Show()
944 self.dot:Hide()
945 self.bg:Hide()
946 else
947 self.arrow:Hide()
948 self.dot:Show()
949 self.bg:Show()
952 if edge then
953 local angle = QuestHelper.Astrolabe:GetDirectionToIcon(self)
954 if GetCVar("rotateMinimap") == "1" then
955 angle = angle + QuestHelper.Astrolabe:GetFacing()
958 if elapsed then
959 if self.phase > 6.283185307179586476925 then
960 self.phase = self.phase-6.283185307179586476925+elapsed*3.5
961 else
962 self.phase = self.phase+elapsed*3.5
966 local scale = 1.0 + 0.1 * math.sin(self.phase)
968 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)
969 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)
971 else
972 self:Hide()
974 else
975 self:Hide()
979 function icon:SetObjective(obj)
980 self:SetHeight(20*QuestHelper_Pref.scale)
981 self:SetWidth(20*QuestHelper_Pref.scale)
983 if obj ~= self.obj then
984 self.obj = obj
986 self.recalc_timeout = 0
988 if self.dot then QuestHelper:ReleaseTexture(self.dot) self.dot = nil end
990 if self.obj then
991 self.dot = QuestHelper:CreateIconTexture(self, self.obj.icon_id or 8)
992 self.dot:SetPoint("TOPLEFT", icon, "TOPLEFT", 2, -2)
993 self.dot:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -2, 2)
996 self:OnUpdate(0)
1000 function icon:OnEnter()
1001 if self.obj then
1002 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
1003 QuestHelper.tooltip:ClearLines()
1005 --[[if self.target[5] then
1006 QuestHelper.tooltip:AddLine(QHFormat("WAYPOINT_REASON", self.target[5]), unpack(QuestHelper:GetColourTheme().tooltip))
1007 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.serif, 14)
1008 end]]
1010 QuestHelper:AppendObjectiveToTooltip(self.obj)
1011 QuestHelper.tooltip:Show()
1015 function icon:OnLeave()
1016 QuestHelper.tooltip:Hide()
1019 function icon:OnClick()
1020 rightclick_menu(self.obj)
1023 function icon:OnEvent()
1024 if self.obj then
1025 self:Show()
1026 else
1027 self:Hide()
1031 QH_Hook(icon, "OnUpdate", icon.OnUpdate)
1032 QH_Hook(icon, "OnEnter", icon.OnEnter)
1033 QH_Hook(icon, "OnLeave", icon.OnLeave)
1034 QH_Hook(icon, "OnClick", icon.OnClick)
1036 icon:RegisterForClicks("RightButtonUp")
1038 QH_Event("PLAYER_ENTERING_WORLD", function () icon:OnEvent() end)
1040 return icon