Merge branch 'master' of git://cams.pavlovian.net/questhelper
[QuestHelper.git] / dodads.lua
blob9cd3019449048e1a6fd426ba37c80c5b8eb43f63
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 return QuestHelper.Astrolabe:FromAbsoluteContinentPosition(p.c, p.x, p.y)
11 end
13 local function convertLocationToScreen(p, c, z)
14 local pc, _, px, py = convertLocation(p)
15 local ox, oy = QuestHelper.Astrolabe:TranslateWorldMapPosition(pc, 0, px, py, c, z)
16 --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))
17 return ox, oy
18 end
20 local function convertRawToScreen(tc, x, y, c, z)
21 local rc, _, rx, ry = QuestHelper.Astrolabe:FromAbsoluteContinentPosition(tc, x, y)
22 return QuestHelper.Astrolabe:TranslateWorldMapPosition(rc, 0, rx, ry, c, z)
23 end
25 local scrolf = CreateFrame("SCROLLFRAME", nil, WorldMapButton)
26 scrolf:SetFrameLevel(WorldMapButton:GetFrameLevel()+1)
27 scrolf:SetAllPoints()
28 scrolf:SetFrameStrata("FULLSCREEN")
30 QuestHelper.map_overlay = CreateFrame("FRAME", nil, scrolf)
31 scrolf:SetScrollChild(QuestHelper.map_overlay)
32 QuestHelper.map_overlay:SetAllPoints()
34 QuestHelper.map_overlay_uncropped = scrolf
36 local function ClampLine(x1, y1, x2, y2)
37 if x1 and y1 and x2 and y2 then
38 local x_div, y_div = (x2-x1), (y2-y1)
39 local x_0 = y1-x1/x_div*y_div
40 local x_1 = y1+(1-x1)/x_div*y_div
41 local y_0 = x1-y1/y_div*x_div
42 local y_1 = x1+(1-y1)/y_div*x_div
44 if y1 < 0 then
45 x1 = y_0
46 y1 = 0
47 end
49 if y2 < 0 then
50 x2 = y_0
51 y2 = 0
52 end
54 if y1 > 1 then
55 x1 = y_1
56 y1 = 1
57 end
59 if y2 > 1 then
60 x2 = y_1
61 y2 = 1
62 end
64 if x1 < 0 then
65 y1 = x_0
66 x1 = 0
67 end
69 if x2 < 0 then
70 y2 = x_0
71 x2 = 0
72 end
74 if x1 > 1 then
75 y1 = x_1
76 x1 = 1
77 end
79 if x2 > 1 then
80 y2 = x_1
81 x2 = 1
82 end
84 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
85 return x1, y1, x2, y2
86 end
87 end
88 end
90 local poi = {}
91 local poi_changed = false
93 local poi_dodads = {}
95 function QH_POI_Reset()
96 while poi[1] do
97 QuestHelper:ReleaseTable(table.remove(poi))
98 end
99 poi_changed = true
101 function QH_POI_Add(p, x, y, d)
102 local tab = QuestHelper:CreateTable("dodads_poi")
103 tab.p = p
104 tab.x = x
105 tab.y = y
106 tab.desc = d
107 table.insert(poi, tab)
108 poi_changed = true
112 local walker_loc
114 function QuestHelper:CreateWorldMapWalker()
115 if not self.Astrolabe or not QuestHelper then return end
116 QuestHelper: Assert(self == QuestHelper)
117 QuestHelper: Assert(self.Astrolabe)
119 local walker = CreateFrame("Button", nil, QuestHelper.map_overlay)
120 walker_loc = walker
121 walker:SetWidth(0)
122 walker:SetHeight(0)
123 walker:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", 0, 0)
124 walker:Show()
126 walker.phase = 0.0
127 walker.dots = {}
128 walker.points = {}
129 walker.origin = {}
130 walker.frame = self
131 walker.map_dodads = {}
132 walker.used_map_dodads = 0
134 function walker:OnUpdate(elapsed)
135 if poi_changed then self:RouteChanged() end -- bzzzzt
137 local out = 0
139 if QuestHelper_Pref.show_ants then
140 local points = self.points
142 self.phase = self.phase + elapsed * 0.66
143 while self.phase > 1 do self.phase = self.phase - 1 end
145 local w, h = QuestHelper.map_overlay:GetWidth(), -QuestHelper.map_overlay:GetHeight()
147 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
149 local last_x, last_y = self.frame.Astrolabe:TranslateWorldMapPosition(self.frame.c, self.frame.z, self.frame.x, self.frame.y, c, z)
150 local remainder = self.phase
152 for i, pos in ipairs(points) do
153 local new_x, new_y = unpack(pos)
154 local x1, y1, x2, y2 = ClampLine(last_x, last_y, new_x, new_y)
155 last_x, last_y = new_x, new_y
157 if x1 then
158 local len = math.sqrt((x1-x2)*(x1-x2)*16/9+(y1-y2)*(y1-y2))
160 if len > 0.0001 then
161 local interval = .025/len
162 local p = remainder*interval
164 while p < 1 do
165 out = out + 1
166 local dot = self.dots[out]
167 if not dot then
168 dot = QuestHelper:CreateDotTexture(self)
169 dot:SetDrawLayer("BACKGROUND")
170 self.dots[out] = dot
173 dot:ClearAllPoints()
174 dot:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x1*w*(1-p)+x2*w*p, y1*h*(1-p)+y2*h*p)
176 p = p + interval
179 remainder = (p-1)/interval
185 while #self.dots > out do
186 QuestHelper:ReleaseTexture(table.remove(self.dots))
190 function walker:RouteChanged(route)
191 if route then self.route = route end -- we cache it so we can refer to it later when the world map changes
192 if not self.route then return end
194 local dbgstr = string.format("%s %s %s %s", tostring(self), tostring(self.frame), tostring(QuestHelper), tostring(QuestHelper and QuestHelper.Astrolabe))
195 QuestHelper: Assert(self.frame == QuestHelper, dbgstr)
196 QuestHelper: Assert(QuestHelper.Astrolabe, dbgstr)
198 if self.next_item then
199 self.next_item:MarkAsNext(false)
200 self.next_item = nil
203 if self.frame.Astrolabe.WorldMapVisible then
204 local points = self.points
205 local cur = self.frame.pos
207 while #points > 0 do self.frame:ReleaseTable(table.remove(points)) end
209 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
211 for i, obj in ipairs(self.route) do
212 --QuestHelper:TextOut(string.format("%s", tostring(obj)))
214 --[[
215 local t = QuestHelper:CreateTable()
216 t[1], t[2] = convertLocationToScreen(obj.loc, c, z)
218 table.insert(list, t)]]
220 -- We're ignoring travel time for now.
221 --[[
222 travel_time = travel_time + 60
223 obj.travel_time = travel_time]]
224 if i > 1 then -- skip the start location
225 local t = self.frame:CreateTable()
226 t[1], t[2] = convertLocationToScreen(obj.loc, c, z)
228 table.insert(points, t)
230 --if lotsup then print(obj.ignore, obj.loc.x, obj.loc.y, obj.loc.c) end
232 --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])))
234 --lotsup = false
236 local cur_dodad = 1
237 for i = 2, #self.route do -- 2 because we're skipping the player
238 if not self.route[i].ignore or qh_hackery_show_all_map_nodes then
239 local dodad = self.map_dodads[cur_dodad]
240 if not dodad then
241 self.map_dodads[cur_dodad] = self.frame:CreateWorldMapDodad(self.route[i], i == 2)
242 else
243 self.map_dodads[cur_dodad]:SetObjective(self.route[i], i == 2)
246 if cur_dodad == 1 then
247 self.map_dodads[cur_dodad]:MarkAsNext(true)
248 self.next_item = self.map_dodads[cur_dodad]
250 cur_dodad = cur_dodad + 1
254 if cur_dodad <= self.used_map_dodads then for i = cur_dodad,self.used_map_dodads do
255 self.map_dodads[i]:SetObjective(nil, false)
256 end end
258 self.used_map_dodads = cur_dodad - 1
260 while #poi > #poi_dodads do
261 table.insert(poi_dodads, self.frame:CreateWorldMapMinidad())
264 for i = 1, #poi do
265 poi_dodads[i]:SetPosition(poi[i])
267 for i = #poi + 1, #poi_dodads do
268 poi_dodads[i]:SetPosition()
273 QH_Event("WORLD_MAP_UPDATE", function () walker:RouteChanged() end)
275 QH_Hook(walker, "OnUpdate", walker.OnUpdate)
277 return walker
282 function QuestHelper:GetOverlapObjectives(obj)
283 local w, h = self.map_overlay:GetWidth(), self.map_overlay:GetHeight()
284 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
286 local list = self.overlap_list
288 if not list then
289 list = {}
290 self.overlap_list = list
291 else
292 while table.remove(list) do end
295 local cx, cy = GetCursorPosition()
297 local es = QuestHelper.map_overlay:GetEffectiveScale()
298 local ies = 1/es
300 cx, cy = (cx-self.map_overlay:GetLeft()*es)*ies, (self.map_overlay:GetTop()*es-cy)*ies
302 local s = 10*QuestHelper_Pref.scale
304 for i, o in ipairs(walker_loc.route) do
305 --QuestHelper: Assert(o, string.format("nil dodads pos issue, o %s", tostring(o)))
306 --QuestHelper: Assert(o.pos, string.format("nil dodads pos issue, pos %s", QuestHelper:StringizeTable(o)))
307 if not o.ignore or qh_hackery_show_all_map_nodes then
308 if o == obj then
309 table.insert(list, o)
310 else
311 local x, y = convertLocationToScreen(o.loc, c, z)
313 if x and y and x > 0 and y > 0 and x < 1 and y < 1 then
314 x, y = x*w, y*h
316 if cx >= x-s and cy >= y-s and cx <= x+s and cy <= y+s then
317 table.insert(list, o)
324 table.sort(list, function(a, b) return (a.distance or 0) < (b.distance or 0) end)
326 return list
329 function QuestHelper:AppendObjectiveProgressToTooltip(o, tooltip, font, depth)
330 if o.progress then
331 local prog_sort_table = {}
333 local theme = self:GetColourTheme()
335 local indent = (" "):rep(depth or 0)
337 for user, progress in pairs(o.progress) do
338 table.insert(prog_sort_table, user)
341 table.sort(prog_sort_table, function(a, b)
342 if o.progress[a][3] < o.progress[b][3] then
343 return true
344 elseif o.progress[a][3] == o.progress[b][3] then
345 return a < b
347 return false
348 end)
350 for i, u in ipairs(prog_sort_table) do
351 tooltip:AddDoubleLine(indent..QHFormat("PEER_PROGRESS", u),
352 self:ProgressString(o.progress[u][1].."/"..o.progress[u][2],
353 o.progress[u][3]), unpack(theme.tooltip))
355 if font then
356 local last, name = tooltip:NumLines(), tooltip:GetName()
357 local left, right = _G[name.."TextLeft"..last], _G[name.."TextRight"..last]
359 left:SetFont(font, 13)
360 right:SetFont(font, 13)
364 while table.remove(prog_sort_table) do end
368 function QuestHelper:AppendObjectiveToTooltip(o)
369 local theme = self:GetColourTheme()
371 QuestHelper: Assert(o.map_desc)
372 for _, v in ipairs(o.map_desc) do
373 self.tooltip:AddLine(v, unpack(theme.tooltip))
374 self.tooltip:GetPrevLines():SetFont(self.font.serif, 14)
377 if o.map_desc_chain then
378 self:AppendObjectiveToTooltip(o.map_desc_chain)
379 else
380 self:AppendObjectiveProgressToTooltip(o, self.tooltip, QuestHelper.font.sans)
382 if QuestHelper_Pref.travel_time then
383 self.tooltip:AddDoubleLine(QHText("TRAVEL_ESTIMATE"), QHFormat("TRAVEL_ESTIMATE_VALUE", o.distance or 0), unpack(theme.tooltip))
384 self.tooltip:GetPrevLines():SetFont(self.font.sans, 11)
389 globx = 0.5
390 globy = 0.5
392 function QH_Append_NextObjective(menu)
393 local obj = QuestHelper.minimap_marker.obj
394 if not obj then return end
396 QuestHelper:AddObjectiveOptionsToMenu(obj, menu)
399 local function rightclick_menu(obj)
400 if obj then
401 local menu = QuestHelper:CreateMenu()
402 local list = QuestHelper:GetOverlapObjectives(obj)
403 local item
405 if #list > 1 then
406 QuestHelper:CreateMenuTitle(menu, "Objectives")
408 for i, o in ipairs(list) do
409 local submenu = QuestHelper:CreateMenu()
410 item = QuestHelper:CreateMenuItem(menu, o.map_desc[1])
411 item:SetSubmenu(submenu)
412 item:AddTexture(QuestHelper:CreateIconTexture(item, o.icon_id or 8), true)
413 QuestHelper:AddObjectiveOptionsToMenu(o, submenu)
415 else
416 QuestHelper:CreateMenuTitle(menu, obj.map_desc[1])
417 QuestHelper:AddObjectiveOptionsToMenu(obj, menu)
420 menu:ShowAtCursor()
424 function QuestHelper:CreateWorldMapDodad(objective, nxt)
425 local icon = CreateFrame("Button", nil, QuestHelper.map_overlay)
426 icon:SetFrameStrata("FULLSCREEN")
428 function icon:SetTooltip(list)
429 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
430 QuestHelper.tooltip:ClearLines()
432 local first = true
434 for i, o in ipairs(list) do
435 if first then
436 first = false
437 else
438 QuestHelper.tooltip:AddLine("|c80ff0000 . . . . . .|r")
439 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.sans, 8)
442 QuestHelper:AppendObjectiveToTooltip(o)
445 QuestHelper.tooltip:Show()
448 function icon:MarkAsNext(nxt)
449 self.next = nxt
451 QH_Hook(self, "OnUpdate", self.OnUpdate)
454 function icon:SetObjective(objective, nxt)
455 self:SetHeight(20*QuestHelper_Pref.scale)
456 self:SetWidth(20*QuestHelper_Pref.scale)
458 if self.dot then
459 QuestHelper:ReleaseTexture(self.dot)
460 self.dot = nil
463 if self.bg then
464 QuestHelper:ReleaseTexture(self.bg)
465 self.bg = nil
468 if objective then
469 self.objective = objective
471 if nxt then
472 self.bg = QuestHelper:CreateIconTexture(self, 13)
473 elseif objective.map_highlight then
474 self.bg = QuestHelper:CreateIconTexture(self, 14)
475 else
476 self.bg = QuestHelper:CreateIconTexture(self, 16)
479 self.dot = QuestHelper:CreateIconTexture(self, objective.icon_id or 8)
481 self.bg:SetDrawLayer("BACKGROUND")
482 self.bg:SetAllPoints()
483 self.dot:SetPoint("TOPLEFT", self, "TOPLEFT", 3*QuestHelper_Pref.scale, -3*QuestHelper_Pref.scale)
484 self.dot:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -3*QuestHelper_Pref.scale, 3*QuestHelper_Pref.scale)
486 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(objective.loc))
487 --QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, 0, 0, globx, globy)
488 else
489 self.objective = nil
490 self:Hide()
491 self.next = false
492 self:OnUpdate(0)
496 local triangle_r, triangle_g, triangle_b = 1.0, 0.3, 0
497 local triangle_opacity = 0.6
499 function icon:CreateTriangles(solid, tritarget, tristartat, linetarget, linestartat, parent)
500 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
502 local function makeline(ax, ay, bx, by)
503 local tri = linetarget[linestartat]
504 if not tri then
505 tri = CreateLine(parent)
506 table.insert(linetarget, tri)
508 linestartat = linestartat + 1
510 tri:SetLine(ax, ay, bx, by)
511 tri:SetVertexColor(0, 0, 0, 0)
512 tri:Show()
515 for _, v in ipairs(solid) do
516 local adjx, adjy = v[1], v[2]
517 local x, y = convertRawToScreen(v.continent, v[1], v[2], c, z)
518 --print("matchup", c, v.continent, x, y)
519 if x and y then
520 local lx, ly = convertRawToScreen(v.continent, adjx + v[3], adjy + v[4], c, z)
521 local linemode = false
523 local lidx = 5
524 while lidx <= #v do
525 if type(v[lidx]) == "string" then
526 if v[lidx] == "d" then
527 QuestHelper: Assert(type(lidx) == "number") -- what
528 lidx = lidx + 1
529 x, y = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
530 lx, ly = convertRawToScreen(v.continent, adjx + v[lidx + 2], adjy + v[lidx + 3], c, z)
531 lidx = lidx + 4
532 elseif v[lidx] == "l" then
533 linemode = true
534 lidx = lidx + 1
535 x, y = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
536 lx, ly = x, y
537 lidx = lidx + 2
538 else
539 QuestHelper: Assert(false)
541 else
542 if not linemode then
543 local tx, ty = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
545 local tri = tritarget[tristartat]
546 if not tri then
547 tri = CreateTriangle(parent)
548 table.insert(tritarget, tri)
550 tristartat = tristartat + 1
552 tri:SetTriangle(x, y, lx, ly, tx, ty)
553 tri:SetVertexColor(0, 0, 0, 0)
554 tri:Show()
556 lx, ly = tx, ty
557 lidx = lidx + 2
558 else
559 local tx, ty = convertRawToScreen(v.continent, adjx + v[lidx], adjy + v[lidx + 1], c, z)
561 makeline(x, y, tx, ty)
563 x, y = tx, ty
564 lidx = lidx + 2
569 if linemode then
570 makeline(x, y, lx, ly)
575 return tristartat, linestartat
578 function icon:SetGlow(list)
579 local w, h = QuestHelper.map_overlay:GetWidth(), QuestHelper.map_overlay:GetHeight()
580 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
581 local zw = QuestHelper.Astrolabe:GetZoneWidth(c, z)
583 local solids = {}
585 local gid = 1
586 for _, v in ipairs(list) do
587 --print(v.cluster, v.cluster and v.cluster.solid)
588 if v.cluster and v.cluster.solid then
589 --print("solidified", #v.cluster.solid)
590 solids[v.cluster.solid] = true
591 else
592 local x, y = convertLocationToScreen(v.loc, c, z)
593 if x and y then
594 if not self.glow_list then
595 self.glow_list = QuestHelper:CreateTable()
597 local glo = self.glow_list[gid]
598 if not glo then
599 glo = QuestHelper:CreateGlowTexture(self)
600 self.glow_list[gid] = glo
602 gid = gid + 1
604 glo:SetPoint("CENTER", QuestHelper.map_overlay, "TOPLEFT", x*w, -y*h)
605 glo:SetVertexColor(triangle_r, triangle_g, triangle_b, 1)
606 glo:SetWidth(h / 20)
607 glo:SetHeight(h / 20)
608 glo:Show()
613 local tid = 1
614 local lid = 1
616 for k, _ in pairs(solids) do
617 if not self.triangle_list then
618 self.triangle_list = QuestHelper:CreateTable()
620 if not self.line_list then
621 self.line_list = QuestHelper:CreateTable()
624 tid, lid = self:CreateTriangles(k, self.triangle_list, tid, self.line_list, lid, QuestHelper.map_overlay)
626 -- call triangle maker here!
628 if self.triangle_list then
629 while #self.triangle_list >= tid do
630 ReleaseTriangle(table.remove(self.triangle_list))
633 if #self.triangle_list == 0 then
634 QuestHelper:ReleaseTable(self.triangle_list)
635 self.triangle_list = nil
639 if self.glow_list then
640 while #self.glow_list >= gid do
641 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
644 if #self.glow_list == 0 then
645 QuestHelper:ReleaseTable(self.glow_list)
646 self.glow_list = nil
650 if self.line_list then
651 while #self.line_list >= lid do
652 ReleaseLine(table.remove(self.line_list))
655 if #self.line_list == 0 then
656 QuestHelper:ReleaseTable(self.line_list)
657 self.line_list = nil
662 icon.show_glow = false
663 icon.glow_pct = 0.0
664 icon.phase = 0.0
665 icon.old_count = 0
667 function icon:OnUpdate(elapsed)
668 self.phase = (self.phase + elapsed)%6.283185307179586476925286766559005768394338798750211641949889185
670 if self.next and self.objective and self.objective.cluster.solid and QuestHelper_Pref.zones == "next" then
672 local c, z = QuestHelper.Astrolabe:GetCurrentVirtualMapCZ()
673 if self.tri_c ~= c or self.tri_z ~= z then
674 -- not entirely happy with this being here, but, welp
675 if not self.local_triangle_list then
676 self.local_triangle_list = QuestHelper:CreateTable()
678 if not self.local_line_list then
679 self.local_line_list = QuestHelper:CreateTable()
682 local tid, lid = self:CreateTriangles(self.objective.cluster.solid, self.local_triangle_list, 1, self.local_line_list, 1, QuestHelper.map_overlay)
684 if self.local_triangle_list then
685 while #self.local_triangle_list >= tid do
686 ReleaseTriangle(table.remove(self.local_triangle_list))
690 if self.local_line_list then
691 while #self.local_line_list >= lid do
692 ReleaseLine(table.remove(self.local_line_list))
697 self.tri_c, self.tri_z = c, z
698 else
699 if self.local_triangle_list then
700 while #self.local_triangle_list > 0 do
701 ReleaseTriangle(table.remove(self.local_triangle_list))
703 QuestHelper:ReleaseTable(self.local_triangle_list)
704 self.local_triangle_list = nil
707 if self.local_line_list then
708 while #self.local_line_list > 0 do
709 ReleaseLine(table.remove(self.local_line_list))
711 QuestHelper:ReleaseTable(self.local_line_list)
712 self.local_line_list = nil
715 self.tri_c, self.tri_z = nil, nil
718 if self.old_count > 0 then
719 local list = QuestHelper:GetOverlapObjectives(self.objective)
721 if #list ~= self.old_count then
722 self:SetTooltip(list)
723 self.old_count = #list
724 self:SetGlow(list)
728 if self.show_glow then
729 self.glow_pct = math.min(1, self.glow_pct+elapsed*1.5)
730 else
731 self.glow_pct = math.max(0, self.glow_pct-elapsed*0.5)
733 if self.glow_pct == 0 then
734 if self.triangle_list then
735 while #self.triangle_list > 0 do
736 ReleaseTriangle(table.remove(self.triangle_list))
738 QuestHelper:ReleaseTable(self.triangle_list)
739 self.triangle_list = nil
742 if self.glow_list then
743 while #self.glow_list > 0 do
744 QuestHelper:ReleaseTexture(table.remove(self.glow_list))
746 QuestHelper:ReleaseTable(self.glow_list)
747 self.glow_list = nil
750 if self.line_list then
751 while #self.line_list > 0 do
752 ReleaseLine(table.remove(self.line_list))
754 QuestHelper:ReleaseTable(self.line_list)
755 self.line_list = nil
758 if not self.next then
759 QH_Hook(self, "OnUpdate", nil)
764 if self.triangle_list then
765 for _, tri in ipairs(self.triangle_list) do
766 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity/2)
769 if self.line_list then
770 for _, tri in ipairs(self.line_list) do
771 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity)
774 if self.glow_list then
775 for _, tri in ipairs(self.glow_list) do
776 tri:SetVertexColor(triangle_r, triangle_g, triangle_b, self.glow_pct*triangle_opacity)
779 if self.local_triangle_list then
780 for _, tri in ipairs(self.local_triangle_list) do
781 tri:SetVertexColor(triangle_b, triangle_g, triangle_r, triangle_opacity/2)
784 if self.local_line_list then
785 for _, tri in ipairs(self.local_line_list) do
786 tri:SetVertexColor(triangle_b, triangle_g, triangle_r, triangle_opacity)
791 function icon:OnEnter()
792 local list = QuestHelper:GetOverlapObjectives(self.objective)
793 self:SetTooltip(list)
794 self.old_count = #list
796 icon.show_glow = true
798 self:SetGlow(list)
800 QH_Hook(self, "OnUpdate", self.OnUpdate)
803 function icon:OnLeave()
804 QuestHelper.tooltip:Hide()
805 self.show_glow = false
806 self.old_count = 0
809 function icon:OnEvent()
810 if self.objective then
811 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, convertLocation(self.objective.loc))
812 else
813 self.objective = nil
814 self:Hide()
818 function icon:OnClick()
819 rightclick_menu(self.objective)
822 QH_Hook(icon, "OnClick", icon.OnClick)
823 QH_Hook(icon, "OnEnter", icon.OnEnter)
824 QH_Hook(icon, "OnLeave", icon.OnLeave)
825 QH_Hook(icon, "OnEvent", icon.OnEvent)
827 icon:RegisterForClicks("RightButtonUp")
829 QH_Event("WORLD_MAP_UPDATE", function () icon:OnEvent() end)
831 icon:SetObjective(objective, nxt)
832 return icon
836 function QuestHelper:CreateWorldMapMinidad(objective, nxt)
837 local icon = CreateFrame("Button", nil, QuestHelper.map_overlay)
838 icon:SetFrameStrata("FULLSCREEN")
840 function icon:SetPosition(objective)
841 self:SetHeight(16*QuestHelper_Pref.scale)
842 self:SetWidth(16*QuestHelper_Pref.scale)
844 if self.dot then
845 QuestHelper:ReleaseTexture(self.dot)
846 self.dot = nil
849 if objective then
850 self.objective = objective
852 self.dot = QuestHelper:CreateIconTexture(self, 15)
853 self.dot:SetAllPoints()
854 self.dot:SetDrawLayer("BACKGROUND")
856 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, QuestHelper.Astrolabe:FromAbsoluteContinentPosition(QuestHelper_ParentLookup[self.objective.p], self.objective.x, self.objective.y))
857 else
858 self.objective = nil
859 self:Hide()
864 function icon:OnEnter()
865 local list = QuestHelper:GetOverlapObjectives(self.objective)
866 self.old_count = #list
867 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
868 QuestHelper.tooltip:ClearLines()
870 QuestHelper.tooltip:AddLine(self.objective.desc)
872 QuestHelper.tooltip:Show()
875 function icon:OnLeave()
876 QuestHelper.tooltip:Hide()
879 function icon:OnEvent()
880 if self.objective then
881 QuestHelper.Astrolabe:PlaceIconOnWorldMap(QuestHelper.map_overlay, self, QuestHelper.Astrolabe:FromAbsoluteContinentPosition(QuestHelper_ParentLookup[self.objective.p], self.objective.x, self.objective.y))
882 else
883 self.objective = nil
884 self:Hide()
888 --function icon:OnClick()
889 --rightclick_menu(self.objective)
890 --end
892 --QH_Hook(icon, "OnClick", icon.OnClick)
893 QH_Hook(icon, "OnEnter", icon.OnEnter)
894 QH_Hook(icon, "OnLeave", icon.OnLeave)
895 QH_Hook(icon, "OnEvent", icon.OnEvent)
897 --icon:RegisterForClicks("RightButtonUp")
899 QH_Event("WORLD_MAP_UPDATE", function () icon:OnEvent() end)
901 icon:SetPosition(objective)
902 return icon
905 local callbacks = {}
906 local last_c, last_z, last_x, last_y, last_desc
908 function QuestHelper:AddWaypointCallback(func, ...)
909 local cb = self:CreateTable()
910 callbacks[cb] = true
911 local len = select("#", ...)
912 cb.len = len
913 cb.func = func
914 for i = 1,len do cb[i] = select(i, ...) end
915 cb[len+1] = last_c
916 cb[len+2] = last_z
917 cb[len+3] = last_x
918 cb[len+4] = last_y
919 cb[len+5] = last_desc
921 if last_c then
922 func(unpack(cb, 1, len+5))
925 return cb
928 function QuestHelper:RemoveWaypointCallback(cb)
929 callbacks[cb] = nil
930 self:ReleaseTable(cb)
933 function QuestHelper:InvokeWaypointCallbacks(c, z, x, y, desc)
934 QuestHelper: Assert(not c or type(c) == "number")
935 QuestHelper: Assert(not z or type(z) == "number")
936 QuestHelper: Assert(not x or type(x) == "number")
937 QuestHelper: Assert(not y or type(y) == "number")
938 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
940 if not c or (x and y) then
941 if c ~= last_c or z ~= last_z or x ~= last_x or y ~= last_y or desc ~= last_desc then
942 last_c, last_z, last_x, last_y, last_desc = c, z, x, y, desc
943 for cb in pairs(callbacks) do
944 local len = cb.len
945 cb[len+1] = c
946 cb[len+2] = z
947 cb[len+3] = x
948 cb[len+4] = y
949 cb[len+5] = desc
950 cb.func(unpack(cb, 1, len+5))
956 function QuestHelper:SetMinimapObject(minimap)
957 Minimap = minimap
958 QuestHelper.Astrolabe:SetMinimapObject(minimap)
959 QuestHelper.minimap_marker:SetParent(minimap)
960 QuestHelper.Astrolabe.processingFrame:SetParent(minimap)
963 --[[ Small parts of the arrow rendering code are thanks to Tomtom, with the following license:
965 -------------------------------------------------------------------------
966 Copyright (c) 2006-2007, James N. Whitehead II
967 All rights reserved.
969 Redistribution and use in source and binary forms, with or without
970 modification, are permitted provided that the following conditions are
971 met:
973 * Redistributions of source code must retain the above copyright
974 notice, this list of conditions and the following disclaimer.
975 * Redistributions in binary form must reproduce the above
976 copyright notice, this list of conditions and the following
977 disclaimer in the documentation and/or other materials provided
978 with the distribution.
979 * The name or alias of the copyright holder may not be used to endorse
980 or promote products derived from this software without specific prior
981 written permission.
983 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
984 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
985 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
986 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
987 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
988 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
989 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
990 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
991 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
992 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
993 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
994 ---------------------------------------------------------------------------]]
996 function QuestHelper:CreateMipmapDodad()
997 local icon = CreateFrame("Button", nil, Minimap)
998 icon:Hide()
999 icon.recalc_timeout = 0
1001 icon.arrow = icon:CreateTexture("BACKGROUND")
1002 icon.arrow:SetHeight(40)
1003 icon.arrow:SetWidth(40)
1004 icon.arrow:SetPoint("CENTER", 0, 0)
1005 icon.arrow:SetTexture("Interface\\AddOns\\QuestHelper\\MinimapArrow")
1006 icon.arrow:Hide()
1008 icon.phase = 0
1009 icon.target = {0, 0, 0, 0}
1011 icon.bg = QuestHelper:CreateIconTexture(icon, 16)
1012 icon.bg:SetDrawLayer("BACKGROUND")
1013 icon.bg:SetAllPoints()
1015 function icon:OnUpdate(elapsed)
1016 local c, z, x, y, textdesc
1017 if self.obj then
1018 c, z = QuestHelper.collect_rc, QuestHelper.collect_rz
1019 if c and z then
1020 x, y = convertLocationToScreen(self.obj.loc, c, z)
1023 if self.obj.map_desc_chain then
1024 -- the first line will just be an "enroute" line
1025 textdesc = (self.obj.arrow_desc or self.obj.map_desc[1]) .. "\n" .. (self.obj.map_desc_chain.arrow_desc or self.obj.map_desc_chain.map_desc[1])
1026 else
1027 textdesc = (self.obj.arrow_desc or self.obj.map_desc[1])
1030 if self.obj.arrow_desc then
1031 textdesc = self.obj.arrow_desc
1035 QuestHelper: Assert(not c or type(c) == "number")
1036 QuestHelper: Assert(not z or type(z) == "number")
1038 -- Deal with waypoint callbacks
1039 if QuestHelper_Pref.hide or UnitIsDeadOrGhost("player") and not QuestHelper.InBrokenInstance then
1040 QuestHelper:InvokeWaypointCallbacks()
1041 else
1042 QuestHelper:InvokeWaypointCallbacks(c, z, x, y, textdesc)
1045 if self.obj and not QuestHelper.InBrokenInstance then
1046 self:Show() -- really only triggers if the non-broken-instance code is being poked
1048 if not QuestHelper_Pref.hide and QuestHelper.Astrolabe:PlaceIconOnMinimap(self, convertLocation(self.obj.loc)) ~= -1 then
1049 local edge = QuestHelper.Astrolabe:IsIconOnEdge(self)
1051 if edge then
1052 self.arrow:Show()
1053 self.dot:Hide()
1054 self.bg:Hide()
1055 else
1056 self.arrow:Hide()
1057 self.dot:Show()
1058 self.bg:Show()
1060 self.dot:SetAlpha(QuestHelper_Pref.mini_opacity)
1061 self.bg:SetAlpha(QuestHelper_Pref.mini_opacity)
1064 if edge then
1065 local angle = QuestHelper.Astrolabe:GetDirectionToIcon(self)
1066 if GetCVar("rotateMinimap") == "1" then
1067 angle = angle + QuestHelper.Astrolabe:GetFacing()
1070 if elapsed then
1071 if self.phase > 6.283185307179586476925 then
1072 self.phase = self.phase-6.283185307179586476925+elapsed*3.5
1073 else
1074 self.phase = self.phase+elapsed*3.5
1078 local scale = 1.0 + 0.1 * math.sin(self.phase)
1080 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)
1081 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)
1083 else
1084 self:Hide()
1086 else
1087 self:Hide()
1091 function icon:SetObjective(obj)
1092 self:SetHeight(20*QuestHelper_Pref.scale)
1093 self:SetWidth(20*QuestHelper_Pref.scale)
1095 if obj ~= self.obj then
1096 self.obj = obj
1098 self.recalc_timeout = 0
1100 if self.dot then QuestHelper:ReleaseTexture(self.dot) self.dot = nil end
1102 if self.obj then
1103 self.dot = QuestHelper:CreateIconTexture(self, self.obj.icon_id or 8)
1104 self.dot:SetPoint("TOPLEFT", icon, "TOPLEFT", 2, -2)
1105 self.dot:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -2, 2)
1108 self:OnUpdate(0)
1112 function icon:OnEnter()
1113 if self.obj then
1114 QuestHelper.tooltip:SetOwner(self, "ANCHOR_CURSOR")
1115 QuestHelper.tooltip:ClearLines()
1117 --[[if self.target[5] then
1118 QuestHelper.tooltip:AddLine(QHFormat("WAYPOINT_REASON", self.target[5]), unpack(QuestHelper:GetColourTheme().tooltip))
1119 QuestHelper.tooltip:GetPrevLines():SetFont(QuestHelper.font.serif, 14)
1120 end]]
1122 QuestHelper:AppendObjectiveToTooltip(self.obj)
1123 QuestHelper.tooltip:Show()
1127 function icon:OnLeave()
1128 QuestHelper.tooltip:Hide()
1131 function icon:OnClick()
1132 rightclick_menu(self.obj)
1135 function icon:OnEvent()
1136 if self.obj then
1137 self:Show()
1138 else
1139 self:Hide()
1143 QH_Hook(icon, "OnUpdate", icon.OnUpdate)
1144 QH_Hook(icon, "OnEnter", icon.OnEnter)
1145 QH_Hook(icon, "OnLeave", icon.OnLeave)
1146 QH_Hook(icon, "OnClick", icon.OnClick)
1148 icon:RegisterForClicks("RightButtonUp")
1150 QH_Event("PLAYER_ENTERING_WORLD", function () icon:OnEvent() end)
1152 return icon