Merge branch 'master' into achievements
[QuestHelper.git] / tooltip.lua
blob9b203eb3cb9710c83c45fa312b81a739b7678fc5
1 QuestHelper_File["tooltip.lua"] = "Development Version"
2 QuestHelper_Loadtime["tooltip.lua"] = GetTime()
4 if QuestHelper_File["tooltip.lua"] == "Development Version" then
5 qh_hackery_nosuppress = true
6 end
10 local function DoTooltip(self, data, lines, prefix)
11 local indent = 1
13 if prefix then
14 self:AddLine((" "):rep(indent) .. prefix, 1, 1, 1)
15 indent = indent + 1
16 end
18 --QuestHelper:TextOut(QuestHelper:StringizeTable(data))
19 --QuestHelper:TextOut(QuestHelper:StringizeTable(lines))
20 for _, v in ipairs(lines) do
21 self:AddLine((" "):rep(indent) .. v, 1, 1, 1)
22 indent = indent + 1
23 end
24 self:AddLine((" "):rep(indent) .. data.desc, 1, 1, 1)
25 QuestHelper:AppendObjectiveProgressToTooltip(data, self, nil, indent + 1)
26 end
28 local function DoTooltipDefault(self, qname, text)
29 self:AddLine(" " .. QHFormat("TOOLTIP_SLAY", text), 1, 1, 1)
30 self:AddLine(" " .. QHFormat("TOOLTIP_QUEST", qname), 1, 1, 1)
31 end
33 local ctts = {}
35 -- Format:
36 -- { ["monster@@1234"] = {{"Slay for blah blah blah"}, (Objective)} }
37 -- ("Slay for" is frequently an empty table)
38 function QH_Tooltip_Canned_Add(tooltips)
39 for k, v in pairs(tooltips) do
40 local typ, id = k:match("([^@]+)@@([^@]+)")
41 --[[print(k)
42 for tk, tv in pairs(v[1]) do
43 print(" ", 1, tk, tv)
44 end
45 for tk, tv in pairs(v[2]) do
46 print(" ", 2, tk, tv)
47 end]]
48 QuestHelper: Assert(typ and id, k)
49 if not ctts[typ] then ctts[typ] = {} end
50 if not ctts[typ][id] then ctts[typ][id] = {} end
51 QuestHelper: Assert(not ctts[typ][id][v[2]])
52 ctts[typ][id][v[2]] = v[1]
53 end
54 end
55 function QH_Tooltip_Canned_Remove(tooltips)
56 for k, v in pairs(tooltips) do
57 local typ, id = k:match("([^@]+)@@([^@]+)")
58 QuestHelper: Assert(typ and id, k)
59 QuestHelper: Assert(ctts[typ][id][v[2]])
60 ctts[typ][id][v[2]] = nil
62 local cleanup = true
63 for _, _ in pairs(ctts[typ][id]) do
64 cleanup = false
65 end
67 if cleanup then
68 ctts[typ][id] = nil
69 end
70 end
71 end
73 local deferences = {}
74 local deference_default = {} -- this is just a unique value that we can use to lookup
76 -- think about what we want out of this
77 -- If it matches quest/objective, we suppress it and show our canned text
78 -- If it matches quest, but has unknown objectives, we suppress it and show some synthesized "Canned thing, for Quest Blahblahblah"
80 -- tooltips is the same slay/objective pair in the above thing
81 function QH_Tooltip_Defer_Add(questname, objective, tooltips)
82 --print("defer add", questname, objective)
83 local objo = objective
84 if not objective then objective = deference_default end
86 if not deferences[questname] then deferences[questname] = {} end
87 if not deferences[questname][objective] then deferences[questname][objective] = {} end
89 for k, v in pairs(deferences[questname][objective]) do
90 QuestHelper: Assert(v ~= tooltips)
91 end
92 table.insert(deferences[questname][objective], tooltips)
94 --print("adding", questname, objective)
95 end
96 function QH_Tooltip_Defer_Remove(questname, objective, tooltips)
97 local objo = objective
98 if not objective then objective = deference_default end
100 --print("remove", questname, objective)
101 --print("removing", questname, objective, deferences[questname][objective])
102 QuestHelper: Assert(deferences[questname][objective], string.format("%s %s %s", tostring(questname), tostring(objective), tostring(objo)))
104 local remmed = false
105 for k, v in pairs(deferences[questname][objective]) do
106 if v == tooltips then
107 table.remove(deferences[questname][objective], k)
108 remmed = true
109 break
112 QuestHelper: Assert(remmed)
114 if #deferences[questname][objective] == 0 then
115 deferences[questname][objective] = nil
118 local cleanup = true
119 for _ in pairs(deferences[questname]) do
120 cleanup = false
123 if cleanup then
124 deferences[questname] = nil
127 function QH_Tooltip_Defer_Dump()
128 for k, v in pairs(deferences) do
129 print(k)
130 for t, m in pairs(v) do
131 print(" ", t, #m)
136 -- TODO: move this into some common file, I hate that I'm duplicating them but I just want this to work. entire codebase will need a going-over soon
137 local function IsMonsterGUID(guid)
138 QuestHelper: Assert(#guid == 18, "guid len " .. guid) -- 64 bits, plus the 0x prefix
139 QuestHelper: Assert(guid:sub(1, 2) == "0x", "guid 0x-prefix " .. guid)
140 return guid:sub(5, 5) == "3" or guid:sub(5, 5) == "5"
143 local function GetMonsterType(guid)
144 QuestHelper: Assert(#guid == 18, "guid len " .. guid) -- 64 bits, plus the 0x prefix
145 QuestHelper: Assert(guid:sub(1, 2) == "0x", "guid 0x-prefix " .. guid)
146 QuestHelper: Assert(guid:sub(5, 5) == "3" or guid:sub(5, 5) == "5", "guid 3-prefix " .. guid) -- It *shouldn't* be a player or a pet by the time we've gotten here. If so, something's gone wrong.
147 if GetBuildInfo():sub(1, 3) == "3.2" then
148 return tonumber(guid:sub(9, 12), 16) -- here's our actual identifier
149 else
150 return tonumber(guid:sub(7, 10), 16) -- 3.3 and in the future, including 0.3.0
154 local function GetItemType(link, vague)
155 return tonumber(string.match(link,
156 (vague and "" or "^") .. "|cff%x%x%x%x%x%x|Hitem:(%d+):[%d:-]+|h%[[^%]]*%]|h|r".. (vague and "" or "$")
160 local function CopyOver(to, from)
161 to:SetFont(from:GetFont())
162 to:SetFontObject(from:GetFontObject())
163 to:SetText(from:GetText())
164 to:SetTextColor(from:GetTextColor())
165 to:SetSpacing(from:GetSpacing())
166 to:SetShadowOffset(from:GetShadowOffset())
167 to:SetShadowColor(from:GetShadowColor())
168 to:Show()
171 local sigil_bar = CreateFrame("Frame", GameTooltip)
172 sigil_bar:SetFrameStrata("TOOLTIP")
173 sigil_bar:SetPoint("LEFT", GameTooltip, "LEFT", 10, 0)
174 sigil_bar:SetPoint("RIGHT", GameTooltip, "RIGHT", -10, 0)
175 sigil_bar:SetHeight(0.5)
176 sigil_bar:SetFrameLevel(10)
177 sigil_bar:Hide()
179 local sigil_bar_filler = sigil_bar:CreateTexture()
180 sigil_bar_filler:SetTexture(1, 1, 1)
181 sigil_bar_filler:SetAllPoints()
183 local sigil = GameTooltip:CreateTexture()
184 sigil:SetParent(sigil_bar)
185 sigil:SetHeight(16)
186 sigil:SetWidth(16)
187 --sigil:SetPoint("CENTER", 0, 0)
188 sigil:SetTexture("Interface\\AddOns\\QuestHelper\\sigil")
189 sigil:SetPoint("TOPRIGHT", sigil_bar, "BOTTOMRIGHT", 2, -2)
190 local sigil_text
191 local sigil_item
193 local bar_split = 10
195 local fixes_src = {}
196 local fixes_returnto = {}
197 local fixes_from = {}
199 local function FixBlizzTooltip()
200 for k = 1, #fixes_src do
201 for i = 1, fixes_src[k]:GetNumPoints() do
202 local point, relative, rlpoint, x, y = fixes_src[k]:GetPoint(i)
203 if point == "TOPLEFT" then
204 --print("recombining", y, fixes_returnto[k], y == fixes_from[k], fixes_from[k])
205 y = fixes_returnto[k]
206 fixes_src[k]:SetPoint(point, relative, rlpoint, x, y)
211 wipe(fixes_src)
212 wipe(fixes_returnto)
213 wipe(fixes_from)
216 local function cachechange(src, targ, dist, absolute)
217 for i = 1, src:GetNumPoints() do
218 local point, relative, rlpoint, x, y = src:GetPoint(i)
219 if point == "TOPLEFT" and relative == targ then
220 table.insert(fixes_src, src)
221 table.insert(fixes_returnto, y)
222 if absolute then y = dist else y = y - dist end
223 table.insert(fixes_from, y)
224 --print("caching", fixes_returnto[#fixes_returnto], y)
225 src:SetPoint(point, relative, rlpoint, x, y)
230 local function StripBlizzQHTooltipClone(ttp)
231 --do return end
232 if not UnitExists("mouseover") then return end
235 local changed = false
236 local removed = 0
238 local qobj = nil
239 local qobj_name = nil
241 local done = QuestHelper:CreateTable("tooltip")
243 local linemax
245 local line = 2
246 while _G["GameTooltipTextLeft" .. line] and _G["GameTooltipTextLeft" .. line]:IsShown() do
247 linemax = line
248 line = line + 1
252 for line = 2, linemax do
253 local r, g, b, a = _G["GameTooltipTextLeft" .. line]:GetTextColor()
254 r, g, b, a = math.floor(r * 255 + 0.5), math.floor(g * 255 + 0.5), math.floor(b * 255 + 0.5), math.floor(a * 255 + 0.5)
256 if qh_tooltip_print_a_lot then print(thistext, r, g, b, a, qobj) end
258 local thistext = _G["GameTooltipTextLeft" .. line]:GetText()
259 local hideme
260 local thistextm = thistext:match(" %- (.*)")
262 --print(thistext, thistextm)
264 if r == 255 and g == 210 and b == 0 and a == 255 and deferences[thistext] then
265 qobj = deferences[thistext]
266 qobj_name = thistext
267 hideme = true
268 elseif r == 255 and g == 255 and b == 255 and a == 255 and qobj and thistextm and qobj[thistextm] then
269 if not done[qobj[thistextm]] then
270 done[qobj[thistextm]] = true -- Blizzard, why do you show duplicates of your *own quest objectives*?
271 local ite = qobj[thistextm][1]
272 QuestHelper: Assert(ite)
274 local ttsplat = thistextm:match("(.*): ([0-9]+)/([0-9]+)")
275 if ttsplat == ttp:GetUnit() then
276 ttsplat = nil
278 DoTooltip(ttp, ite[2], ite[1], ttsplat and QHFormat("TOOLTIP_SLAY", ttsplat))
279 hideme = true
281 elseif r == 255 and g == 255 and b == 255 and a == 255 and qobj and thistextm and not qobj[thistextm] and thistextm:find(":") then
282 hideme = true -- it parses as an objective, but we don't know about it, so it's probably a completed objective. todo: actually store completed objectives.
283 elseif r == 255 and g == 255 and b == 255 and a == 255 and qobj and thistextm and not thistextm:find(":") then -- Blizzard cleverly does not suppress tooltips when the user has finished getting certain items, so we do instead
284 DoTooltipDefault(ttp, qobj_name, thistextm)
285 hideme = true
288 if hideme and not qh_hackery_nosuppress then
289 _G["GameTooltipTextLeft" .. line]:SetText(nil)
290 _G["GameTooltipTextLeft" .. line]:SetHeight(0)
291 cachechange(_G["GameTooltipTextLeft" .. line], _G["GameTooltipTextLeft" .. (line - 1)], 1, true)
292 changed = true
293 removed = removed + 1
297 if changed then
298 ttp:Show()
301 local qhstart = linemax + 1
302 if _G["GameTooltipTextLeft" .. qhstart] and _G["GameTooltipTextLeft" .. qhstart]:IsShown() then
303 sigil_item = _G["GameTooltipTextLeft" .. qhstart]
304 sigil_text = sigil_item:GetText()
305 cachechange(sigil_item, _G["GameTooltipTextLeft" .. (qhstart - 1)], bar_split, false)
306 sigil_bar:SetPoint("TOP", sigil_item, "TOP", 0, bar_split / 2)
307 --sigil_bar:SetParent(sigil_item)
308 --sigil:SetPoint("TOP", sigil_item, "TOP", 0, 3)
309 --sigil:SetPoint("LEFT", GameTooltip, "LEFT")
310 sigil_bar:Show()
311 bar_boost = true
315 QuestHelper:ReleaseTable(done)
317 return removed
320 local glob_strip = 0
321 function CreateTooltip(self)
322 FixBlizzTooltip()
324 glob_strip = 0
325 bar_boost = nil
327 if QuestHelper_Pref.tooltip then
328 local inu, ilink = self:GetItem()
329 local un, ulink = self:GetUnit()
330 if ulink then ulink = UnitGUID(ulink) end
332 --[[
333 if ilink then
334 local ite = tostring(GetItemType(ilink))
336 if ctts["item"] and ctts["item"][ite] then
337 DoTooltip(self, ctts["item"][ite])
340 self:Show()
341 end]]
343 if qh_tooltip_print_a_lot then print("wut", ulink, IsMonsterGUID(ulink)) print(ulink) print(IsMonsterGUID(ulink)) end
344 if ulink and IsMonsterGUID(ulink) then
345 if qh_tooltip_print_a_lot then print("huhwuzat") print(QH_filter_hints) end
347 glob_strip = StripBlizzQHTooltipClone(self) or 0
349 local ite = tostring(GetMonsterType(ulink))
351 if ctts["monster"] and ctts["monster"][ite] then
352 for data, lines in pairs(ctts["monster"][ite]) do
353 DoTooltip(self, data, lines)
357 self:Show()
362 local unit_to_adjust = nil
364 -- SmoothQuest and possibly others
365 QH_AddNotifier(GetTime() + 5, function ()
366 local ottsu = GameTooltip:GetScript("OnTooltipSetUnit")
367 QH_Hook(GameTooltip, "OnTooltipSetUnit", function (self, ...)
368 if qh_tooltip_print_a_lot then print("lol") end
369 CreateTooltip(self)
370 if ottsu then QH_Hook_NotMyFault(ottsu, self, ...) end
371 unit_to_adjust = self:GetUnit()
372 end, "tooltip OnTooltipSetUnit")
374 local ottsi = GameTooltip:GetScript("OnTooltipSetItem")
375 QH_Hook(GameTooltip, "OnTooltipSetItem", function (self, ...)
376 QH_Hook_NotMyFault(CreateTooltip, self)
377 if ottsi then return QH_Hook_NotMyFault(ottsi, self, ...) end
378 end, "tooltip OnTooltipSetItem")
380 local ttsx = GameTooltip:GetScript("OnUpdate")
381 QH_Hook(GameTooltip, "OnUpdate", function (self, ...)
382 if sigil_bar:IsShown() then
383 sigil_bar:SetAlpha(GameTooltip:GetAlpha())
384 if not (sigil_bar:IsShown() and sigil_item and sigil_item:GetText() == sigil_text) then
385 sigil_bar:Hide()
386 FixBlizzTooltip()
389 if ttsx then QH_Hook_NotMyFault(ttsx, self, ...) end
390 if (glob_strip > 0 or bar_boost) and unit_to_adjust and unit_to_adjust == self:GetUnit() then
391 self:SetHeight(self:GetHeight() - glob_strip * 3 + (bar_boost and bar_split or 0)) -- maaaaaagic
392 unit_to_adjust = nil
394 end, "tooltip OnUpdate")
395 end)