mirror of
https://github.com/rivi-s/pfQuest.git
synced 2026-11-10 20:17:36 +00:00
946 lines
32 KiB
Lua
946 lines
32 KiB
Lua
-- multi api compat
|
|
local compat = pfQuestCompat
|
|
|
|
-- Performance: cache frequently-used globals
|
|
local pairs = pairs
|
|
local format = string.format
|
|
local getn = table.getn
|
|
local GetTime = GetTime
|
|
|
|
-- default config
|
|
pfBrowser_fav = { ["units"] = {}, ["objects"] = {}, ["items"] = {}, ["quests"] = {} }
|
|
|
|
local tooltip_limit = 5
|
|
local search_limit = 512
|
|
|
|
-- Reusable tooltip maps table (cleared and reused to avoid GC)
|
|
local tooltip_maps = {}
|
|
local function clear_tooltip_maps()
|
|
for k in pairs(tooltip_maps) do
|
|
tooltip_maps[k] = nil
|
|
end
|
|
end
|
|
|
|
-- add database shortcuts
|
|
local items = pfDB["items"]["data"]
|
|
local units = pfDB["units"]["data"]
|
|
local objects = pfDB["objects"]["data"]
|
|
local refloot = pfDB["refloot"]["data"]
|
|
local quests = pfDB["quests"]["data"]
|
|
local zones = pfDB["zones"]["loc"]
|
|
|
|
local function ShowTooltip()
|
|
if not this.tooltips then
|
|
return
|
|
end
|
|
GameTooltip_SetDefaultAnchor(GameTooltip, this)
|
|
GameTooltip:ClearLines()
|
|
for k, v in pairs(this.tooltips) do
|
|
if k == 1 then
|
|
GameTooltip:AddLine(v, 1, 1, 1)
|
|
else
|
|
GameTooltip:AddLine(v)
|
|
end
|
|
end
|
|
GameTooltip:Show()
|
|
end
|
|
|
|
local function EnableTooltips(frame, tooltips)
|
|
frame.tooltips = tooltips
|
|
frame:SetScript("OnEnter", ShowTooltip)
|
|
frame:SetScript("OnLeave", function()
|
|
GameTooltip:Hide()
|
|
end)
|
|
end
|
|
|
|
local function ResultButtonEnter()
|
|
this.tex:SetTexture(1, 1, 1, 0.1)
|
|
|
|
-- quest
|
|
if this.btype == "quests" then
|
|
pfDatabase:ShowExtendedTooltip(this.id, GameTooltip, this, "ANCHOR_LEFT", -10, -5)
|
|
|
|
-- item
|
|
elseif this.btype == "items" then
|
|
GameTooltip:SetOwner(this, "ANCHOR_LEFT", -10, -5)
|
|
GameTooltip:SetHyperlink("item:" .. this.id .. pfQuestCompat.itemsuffix)
|
|
GameTooltip:Show()
|
|
|
|
-- units / objects
|
|
else
|
|
local id = this.id
|
|
local name = this.name
|
|
-- Reuse tooltip_maps table instead of creating new one each hover
|
|
clear_tooltip_maps()
|
|
local maps = tooltip_maps
|
|
GameTooltip:SetOwner(this, "ANCHOR_LEFT", -10, -5)
|
|
GameTooltip:SetText(name, 0.3, 1, 0.8)
|
|
if this.btype == "units" then
|
|
local unitData = units[id]
|
|
|
|
if unitData and unitData.lvl then
|
|
GameTooltip:AddLine(" ")
|
|
GameTooltip:AddDoubleLine(pfQuest_Loc["Level"], unitData.lvl, 1, 1, 0.8, 1, 1, 1)
|
|
end
|
|
|
|
local reactionStringA = "|c00ff0000" .. pfQuest_Loc["Hostile"] .. "|r"
|
|
local reactionStringH = "|c00ff0000" .. pfQuest_Loc["Hostile"] .. "|r"
|
|
if unitData and unitData.fac then
|
|
if unitData.fac == "AH" then
|
|
reactionStringA = "|c0000ff00" .. pfQuest_Loc["Friendly"] .. "|r"
|
|
reactionStringH = "|c0000ff00" .. pfQuest_Loc["Friendly"] .. "|r"
|
|
elseif unitData.fac == "A" then
|
|
reactionStringA = "|c0000ff00" .. pfQuest_Loc["Friendly"] .. "|r"
|
|
elseif unitData.fac == "H" then
|
|
reactionStringH = "|c0000ff00" .. pfQuest_Loc["Friendly"] .. "|r"
|
|
end
|
|
end
|
|
GameTooltip:AddLine("\n" .. pfQuest_Loc["Reaction"], 1, 1, 0.8)
|
|
GameTooltip:AddDoubleLine(pfQuest_Loc["Alliance"], reactionStringA, 1, 1, 1, 0, 0, 0)
|
|
GameTooltip:AddDoubleLine(pfQuest_Loc["Horde"], reactionStringH, 1, 1, 1, 0, 0, 0)
|
|
end
|
|
GameTooltip:AddLine("\n" .. pfQuest_Loc["Location"], 1, 1, 0.8)
|
|
if pfDB[this.btype]["data"][id] and pfDB[this.btype]["data"][id]["coords"] then
|
|
for _, data in pairs(pfDB[this.btype]["data"][id]["coords"]) do
|
|
maps[data[3]] = maps[data[3]] or { count = 0 }
|
|
maps[data[3]].count = maps[data[3]].count + 1
|
|
end
|
|
end
|
|
|
|
local unknown = true
|
|
for zone, obj in pfQuest:SortedPairs(maps, "count", nil) do
|
|
GameTooltip:AddDoubleLine((zone and pfMap:GetMapNameByID(zone) or UNKNOWN), obj.count, 1, 1, 1, 0.3, 1, 0.8)
|
|
unknown = nil
|
|
end
|
|
|
|
if unknown then
|
|
GameTooltip:AddLine(UNKNOWN, 1, 0.5, 0.5)
|
|
end
|
|
|
|
GameTooltip:Show()
|
|
end
|
|
end
|
|
|
|
local function ResultButtonUpdate()
|
|
this.refreshCount = this.refreshCount + 1
|
|
|
|
if not this.itemColor then
|
|
GameTooltip:SetHyperlink("item:" .. this.id .. pfQuestCompat.itemsuffix)
|
|
GameTooltip:Hide()
|
|
|
|
local _, _, itemQuality = GetItemInfo(this.id)
|
|
if itemQuality then
|
|
local r = ceil(ITEM_QUALITY_COLORS[itemQuality].r * 255)
|
|
local g = ceil(ITEM_QUALITY_COLORS[itemQuality].g * 255)
|
|
local b = ceil(ITEM_QUALITY_COLORS[itemQuality].b * 255)
|
|
this.itemColor = "|c" .. string.format("ff%02x%02x%02x", r, g, b)
|
|
end
|
|
end
|
|
|
|
if this.itemColor then
|
|
local custom = pfQuest_server["items"][this.id] and " [|cff33ffcc!|r]" or ""
|
|
this.text:SetText(
|
|
this.itemColor .. "|Hitem:" .. this.id .. pfQuestCompat.itemsuffix .. "|h[" .. this.name .. "]|h|r" .. custom
|
|
)
|
|
this.text:SetWidth(this.text:GetStringWidth())
|
|
end
|
|
|
|
if this.refreshCount > 10 or this.itemColor then
|
|
this:SetScript("OnUpdate", nil)
|
|
end
|
|
end
|
|
|
|
local function ResultButtonClick()
|
|
local meta = { ["addon"] = "PFDB" }
|
|
|
|
if this.btype == "items" then
|
|
local link = "item:" .. this.id .. pfQuestCompat.itemsuffix
|
|
local text = (this.itemColor or "|cffffffff") .. "|H" .. link .. "|h[" .. this.name .. "]|h|r"
|
|
SetItemRef(link, text, arg1)
|
|
elseif this.btype == "quests" then
|
|
if IsShiftKeyDown() then
|
|
pfQuestCompat.InsertQuestLink(this.id)
|
|
elseif pfBrowser.selectState then
|
|
local maps = pfDatabase:SearchQuest(this.name, meta)
|
|
pfMap:ShowMapID(pfDatabase:GetBestMap(maps))
|
|
else
|
|
local maps = pfDatabase:SearchQuestID(this.id, meta)
|
|
pfMap:ShowMapID(pfDatabase:GetBestMap(maps))
|
|
end
|
|
elseif this.btype == "units" then
|
|
if pfBrowser.selectState then
|
|
local maps = pfDatabase:SearchMob(this.name, meta)
|
|
pfMap:ShowMapID(pfDatabase:GetBestMap(maps))
|
|
else
|
|
local maps = pfDatabase:SearchMobID(this.id, meta)
|
|
pfMap.queue_update = GetTime()
|
|
pfMap:ShowMapID(pfDatabase:GetBestMap(maps))
|
|
end
|
|
elseif this.btype == "objects" then
|
|
if pfBrowser.selectState then
|
|
local maps = pfDatabase:SearchObject(this.name, meta)
|
|
pfMap:ShowMapID(pfDatabase:GetBestMap(maps))
|
|
else
|
|
local maps = pfDatabase:SearchObjectID(this.id, meta)
|
|
pfMap.queue_update = GetTime()
|
|
pfMap:ShowMapID(pfDatabase:GetBestMap(maps))
|
|
end
|
|
end
|
|
end
|
|
|
|
local function ResultButtonClickFav()
|
|
local parent = this:GetParent()
|
|
if pfBrowser_fav[parent.btype][parent.id] then
|
|
pfBrowser_fav[parent.btype][parent.id] = nil
|
|
this.icon:SetVertexColor(1, 1, 1, 0.1)
|
|
else
|
|
pfBrowser_fav[parent.btype][parent.id] = parent.name
|
|
this.icon:SetVertexColor(1, 1, 1, 1)
|
|
end
|
|
end
|
|
|
|
local function ResultButtonLeave()
|
|
if pfBrowser.selectState then
|
|
pfBrowser.selectState = "clean"
|
|
end
|
|
|
|
if compat.mod(this:GetID(), 2) == 1 then
|
|
this.tex:SetTexture(1, 1, 1, 0.02)
|
|
else
|
|
this.tex:SetTexture(1, 1, 1, 0.04)
|
|
end
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local function ResultButtonClickSpecial()
|
|
local param = this:GetParent()[this.parameter]
|
|
local meta = { ["addon"] = "PFDB" }
|
|
local maps = {}
|
|
if this.buttonType == "O" or this.buttonType == "U" then
|
|
if this.selectState then
|
|
maps = pfDatabase:SearchItem(this:GetParent().name, meta)
|
|
else
|
|
maps = pfDatabase:SearchItemID(param, meta, nil, { [this.buttonType] = true })
|
|
end
|
|
elseif this.buttonType == "V" then
|
|
maps = pfDatabase:SearchVendor(param, meta)
|
|
end
|
|
pfMap.queue_update = GetTime()
|
|
pfMap:ShowMapID(pfDatabase:GetBestMap(maps))
|
|
end
|
|
|
|
local function ResultButtonEnterSpecial()
|
|
local id = this:GetParent().id
|
|
local count = 0
|
|
local skip = false
|
|
|
|
GameTooltip:SetOwner(pfBrowser, "ANCHOR_CURSOR")
|
|
|
|
-- unit
|
|
if this.buttonType == "U" then
|
|
if items[id]["U"] then
|
|
GameTooltip:SetText(pfQuest_Loc["Looted from"], 0.3, 1, 0.8)
|
|
for unitID, chance in pairs(items[id]["U"]) do
|
|
count = count + 1
|
|
if count > tooltip_limit then
|
|
skip = true
|
|
end
|
|
if units[unitID] and not skip then
|
|
local name = pfDB.units.loc[unitID]
|
|
local zone = nil
|
|
if units[unitID].coords and units[unitID].coords[1] then
|
|
zone = units[unitID].coords[1][3]
|
|
end
|
|
GameTooltip:AddDoubleLine(name, (zone and pfMap:GetMapNameByID(zone) or UNKNOWN), 1, 1, 1, 0.5, 0.5, 0.5)
|
|
end
|
|
end
|
|
|
|
-- reference tables
|
|
if items[id]["R"] then
|
|
for ref, chance in pairs(items[id]["R"]) do
|
|
if refloot[ref] and refloot[ref]["U"] then
|
|
for unit in pairs(refloot[ref]["U"]) do
|
|
count = count + 1
|
|
if count > tooltip_limit then
|
|
skip = true
|
|
end
|
|
if units[unit] and not skip then
|
|
local name = pfDB.units.loc[unit]
|
|
local zone = nil
|
|
if units[unit].coords and units[unit].coords[1] then
|
|
zone = units[unit].coords[1][3]
|
|
end
|
|
GameTooltip:AddDoubleLine(
|
|
name,
|
|
(zone and pfMap:GetMapNameByID(zone) or UNKNOWN),
|
|
1,
|
|
1,
|
|
1,
|
|
0.5,
|
|
0.5,
|
|
0.5
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- object
|
|
elseif this.buttonType == "O" then
|
|
if items[id]["O"] then
|
|
GameTooltip:SetText(pfQuest_Loc["Looted from"], 0.3, 1, 0.8)
|
|
for objectID, chance in pairs(items[id]["O"]) do
|
|
count = count + 1
|
|
if count > tooltip_limit then
|
|
skip = true
|
|
end
|
|
if objects[objectID] and not skip then
|
|
local name = pfDB.objects.loc[objectID] or objectID
|
|
local zone = nil
|
|
if objects[objectID].coords and objects[objectID].coords[1] then
|
|
zone = objects[objectID].coords[1][3]
|
|
end
|
|
GameTooltip:AddDoubleLine(name, (zone and pfMap:GetMapNameByID(zone) or UNKNOWN), 1, 1, 1, 0.5, 0.5, 0.5)
|
|
end
|
|
end
|
|
|
|
-- reference tables
|
|
if items[id]["R"] then
|
|
for ref, chance in pairs(items[id]["R"]) do
|
|
if refloot[ref] and refloot[ref]["O"] then
|
|
for unit in pairs(refloot[ref]["O"]) do
|
|
count = count + 1
|
|
if count > tooltip_limit then
|
|
skip = true
|
|
end
|
|
if objects[unit] and not skip then
|
|
local name = pfDB.objects.loc[unit]
|
|
local zone = nil
|
|
if objects[unit].coords and objects[unit].coords[1] then
|
|
zone = objects[unit].coords[1][3]
|
|
end
|
|
GameTooltip:AddDoubleLine(
|
|
name,
|
|
(zone and pfMap:GetMapNameByID(zone) or UNKNOWN),
|
|
1,
|
|
1,
|
|
1,
|
|
0.5,
|
|
0.5,
|
|
0.5
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- vendor
|
|
elseif this.buttonType == "V" then
|
|
if items[id]["V"] then
|
|
GameTooltip:SetText(pfQuest_Loc["Sold by"], 0.3, 1, 0.8)
|
|
for unitID, sellcount in pairs(items[id]["V"]) do
|
|
count = count + 1
|
|
if count > tooltip_limit then
|
|
skip = true
|
|
end
|
|
if units[unitID] and not skip then
|
|
local name = pfDB.units.loc[unitID]
|
|
if sellcount ~= 0 then
|
|
name = name .. " (" .. sellcount .. ")"
|
|
end
|
|
local zone = units[unitID].coords and units[unitID].coords[1] and units[unitID].coords[1][3]
|
|
GameTooltip:AddDoubleLine(name, (zone and pfMap:GetMapNameByID(zone) or UNKNOWN), 1, 1, 1, 0.5, 0.5, 0.5)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if count > tooltip_limit then
|
|
GameTooltip:AddLine(
|
|
"\n" .. pfQuest_Loc["and"] .. " " .. (count - tooltip_limit) .. " " .. pfQuest_Loc["others"],
|
|
0.8,
|
|
0.8,
|
|
0.8
|
|
)
|
|
end
|
|
GameTooltip:Show()
|
|
end
|
|
|
|
local function ResultButtonLeaveSpecial()
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local function ResultButtonReload(self)
|
|
self.idText:SetText("ID: " .. self.id)
|
|
|
|
if pfQuest_config.showids == "1" then
|
|
self.idText:Show()
|
|
else
|
|
self.idText:Hide()
|
|
end
|
|
|
|
self.itemColor = nil
|
|
|
|
-- update faction
|
|
if self.btype ~= "items" then
|
|
self.factionA:Hide()
|
|
self.factionH:Hide()
|
|
|
|
local raceMask = pfDatabase:GetRaceMaskByID(self.id, self.btype)
|
|
if (bit.band(77, raceMask) > 0) or (raceMask == 0 and self.btype == "quests") then
|
|
self.factionA:Show()
|
|
end
|
|
if (bit.band(178, raceMask) > 0) or (raceMask == 0 and self.btype == "quests") then
|
|
self.factionH:Show()
|
|
end
|
|
end
|
|
|
|
-- activate fav buttons if needed
|
|
if pfBrowser_fav and pfBrowser_fav[self.btype] and pfBrowser_fav[self.btype][self.id] then
|
|
self.fav.icon:SetVertexColor(1, 1, 1, 1)
|
|
else
|
|
self.fav.icon:SetVertexColor(1, 1, 1, 0.1)
|
|
end
|
|
|
|
-- actions by search type
|
|
if self.btype == "quests" then
|
|
self.name = pfDB[self.btype]["loc"][self.id]["T"]
|
|
local level = pfDB[self.btype]["data"][self.id] and pfDB[self.btype]["data"][self.id]["lvl"] or 0
|
|
self.text:SetText("|cffffcc00|Hquest:" .. self.id .. ":" .. level .. "|h[" .. self.name .. "]|h|r")
|
|
elseif self.btype == "units" or self.btype == "objects" then
|
|
local level = pfDB[self.btype]["data"][self.id] and pfDB[self.btype]["data"][self.id]["lvl"] or ""
|
|
if level and level ~= "" then
|
|
level = " (" .. level .. ")"
|
|
end
|
|
self.text:SetText(self.name .. "|cffaaaaaa" .. level)
|
|
|
|
if pfDB[self.btype]["data"][self.id] and pfDB[self.btype]["data"][self.id]["coords"] then
|
|
self.text:SetTextColor(1, 1, 1)
|
|
else
|
|
self.text:SetTextColor(0.5, 0.5, 0.5)
|
|
end
|
|
elseif self.btype == "items" then
|
|
for _, key in ipairs({ "U", "O", "V" }) do
|
|
if items[self.id] and items[self.id][key] then
|
|
self[key]:Show()
|
|
else
|
|
self[key]:Hide()
|
|
end
|
|
end
|
|
|
|
self.text:SetText("|cffff5555[?] |cffffffff" .. self.name)
|
|
|
|
self.refreshCount = 0
|
|
self:SetScript("OnUpdate", ResultButtonUpdate)
|
|
end
|
|
|
|
self.text:SetWidth(self.text:GetStringWidth())
|
|
self:Show()
|
|
end
|
|
|
|
local function ResultButtonCreate(i, resultType)
|
|
local f = CreateFrame("Button", nil, pfBrowser.tabs[resultType].list)
|
|
f:SetPoint("TOPLEFT", pfBrowser.tabs[resultType].list, "TOPLEFT", 10, -i * 30 + 5)
|
|
f:SetPoint("BOTTOMRIGHT", pfBrowser.tabs[resultType].list, "TOPRIGHT", 10, -i * 30 - 15)
|
|
f:Hide()
|
|
f:SetID(i)
|
|
|
|
f.btype = resultType
|
|
f.pfResultButton = true
|
|
|
|
f.tex = f:CreateTexture("BACKGROUND")
|
|
f.tex:SetAllPoints(f)
|
|
f.tex:SetTexture(1, 1, 1, (compat.mod(i, 2) == 1 and 0.02 or 0.04))
|
|
|
|
-- text properties
|
|
f.text = f:CreateFontString("Caption", "LOW", "GameFontWhite")
|
|
f.text:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
|
|
f.text:SetAllPoints(f)
|
|
f.text:SetJustifyH("CENTER")
|
|
f.idText = f:CreateFontString("ID", "LOW", "GameFontDisable")
|
|
f.idText:SetPoint("LEFT", f, "LEFT", 30, 0)
|
|
|
|
-- favourite button
|
|
f.fav = CreateFrame("Button", nil, f)
|
|
f.fav:SetHitRectInsets(-3, -3, -3, -3)
|
|
f.fav:SetPoint("LEFT", 0, 0)
|
|
f.fav:SetWidth(16)
|
|
f.fav:SetHeight(16)
|
|
f.fav.icon = f.fav:CreateTexture("OVERLAY")
|
|
f.fav.icon:SetTexture(pfQuestConfig.path .. "\\img\\fav")
|
|
f.fav.icon:SetAllPoints(f.fav)
|
|
|
|
-- faction icons
|
|
if resultType ~= "items" then
|
|
f.factionA = f:CreateTexture("OVERLAY")
|
|
f.factionA:SetTexture(pfQuestConfig.path .. "\\img\\icon_alliance")
|
|
f.factionA:SetWidth(16)
|
|
f.factionA:SetHeight(16)
|
|
f.factionA:SetPoint("RIGHT", -5, 0)
|
|
f.factionH = f:CreateTexture("OVERLAY")
|
|
f.factionH:SetTexture(pfQuestConfig.path .. "\\img\\icon_horde")
|
|
f.factionH:SetWidth(16)
|
|
f.factionH:SetHeight(16)
|
|
f.factionH:SetPoint("RIGHT", -24, 0)
|
|
end
|
|
|
|
-- drop, loot, vendor buttons
|
|
if resultType == "items" then
|
|
local buttons = {
|
|
["U"] = { ["offset"] = -5, ["icon"] = "icon_npc", ["parameter"] = "id" },
|
|
["O"] = { ["offset"] = -24, ["icon"] = "icon_object", ["parameter"] = "id" },
|
|
["V"] = { ["offset"] = -43, ["icon"] = "icon_vendor", ["parameter"] = "name" },
|
|
}
|
|
|
|
for button, settings in pairs(buttons) do
|
|
f[button] = CreateFrame("Button", nil, f)
|
|
f[button]:SetHitRectInsets(-3, -3, -3, -3)
|
|
f[button]:SetPoint("RIGHT", settings.offset, 0)
|
|
f[button]:SetWidth(16)
|
|
f[button]:SetHeight(16)
|
|
|
|
f[button].buttonType = button
|
|
f[button].parameter = settings.parameter
|
|
|
|
f[button].icon = f[button]:CreateTexture("OVERLAY")
|
|
f[button].icon:SetAllPoints(f[button])
|
|
f[button].icon:SetTexture(pfQuestConfig.path .. "\\img\\" .. settings.icon)
|
|
|
|
f[button]:SetScript("OnEnter", ResultButtonEnterSpecial)
|
|
f[button]:SetScript("OnLeave", ResultButtonLeaveSpecial)
|
|
f[button]:SetScript("OnClick", ResultButtonClickSpecial)
|
|
end
|
|
end
|
|
|
|
-- bind functions
|
|
f.Reload = ResultButtonReload
|
|
f:SetScript("OnLeave", ResultButtonLeave)
|
|
f:SetScript("OnEnter", ResultButtonEnter)
|
|
f:SetScript("OnClick", ResultButtonClick)
|
|
f.fav:SetScript("OnClick", ResultButtonClickFav)
|
|
|
|
return f
|
|
end
|
|
|
|
local function SelectView(view)
|
|
for id, frame in pairs(pfBrowser.tabs) do
|
|
pfUI.api.SetButtonFontColor(frame.button, 1, 1, 1, 0.7)
|
|
frame:Hide()
|
|
end
|
|
pfUI.api.SetButtonFontColor(view.button, 0.2, 1, 0.8, 1)
|
|
view.button:Hide()
|
|
view.button:Show()
|
|
view:Show()
|
|
end
|
|
|
|
-- sets the browser result values when they change
|
|
local function RefreshView(i, key, caption)
|
|
pfBrowser.tabs[key].list:Hide()
|
|
pfBrowser.tabs[key].list:SetHeight(i * 30)
|
|
pfBrowser.tabs[key].list:Show()
|
|
pfBrowser.tabs[key].list:GetParent():SetScrollChild(pfBrowser.tabs[key].list)
|
|
pfBrowser.tabs[key].list:GetParent():SetVerticalScroll(0)
|
|
|
|
if not pfBrowser.tabs[key].list.warn then
|
|
pfBrowser.tabs[key].list.warn = pfBrowser.tabs[key].list:CreateFontString("Caption", "LOW", "GameFontWhite")
|
|
pfBrowser.tabs[key].list.warn:SetTextColor(1, 0.2, 0.2, 1)
|
|
pfBrowser.tabs[key].list.warn:SetJustifyH("CENTER")
|
|
pfBrowser.tabs[key].list.warn:SetPoint("TOP", 5, -5)
|
|
pfBrowser.tabs[key].list.warn:SetText(
|
|
"!! |cffffffff" .. pfQuest_Loc["Too many entries. Results shown"] .. ": " .. search_limit .. "|r !!"
|
|
)
|
|
end
|
|
|
|
if i >= search_limit then
|
|
pfBrowser.tabs[key].list.warn:Show()
|
|
else
|
|
pfBrowser.tabs[key].list.warn:Hide()
|
|
end
|
|
|
|
pfBrowser.tabs[key].button:SetText(
|
|
pfQuest_Loc[caption] .. " " .. "|cffaaaaaa(" .. (i >= search_limit and "*" or i) .. ")"
|
|
)
|
|
for j = i + 1, table.getn(pfBrowser.tabs[key].buttons) do
|
|
if pfBrowser.tabs[key].buttons[j] then
|
|
pfBrowser.tabs[key].buttons[j]:Hide()
|
|
pfBrowser.tabs[key].buttons[j].id = nil
|
|
pfBrowser.tabs[key].buttons[j].name = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
-- sets up all the browse windows and their activation buttons
|
|
local function CreateBrowseWindow(fname, name, parent, anchor, x, y)
|
|
if not parent.tabs then
|
|
parent.tabs = {}
|
|
end
|
|
parent.tabs[fname] = pfUI.api.CreateScrollFrame(name, parent)
|
|
parent.tabs[fname]:SetPoint("TOPLEFT", parent, "TOPLEFT", 10, -65)
|
|
parent.tabs[fname]:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", -10, 45)
|
|
parent.tabs[fname]:Hide()
|
|
parent.tabs[fname].buttons = {}
|
|
|
|
parent.tabs[fname].backdrop = CreateFrame("Frame", name .. "Backdrop", parent.tabs[fname])
|
|
parent.tabs[fname].backdrop:SetFrameLevel(1)
|
|
parent.tabs[fname].backdrop:SetPoint("TOPLEFT", parent.tabs[fname], "TOPLEFT", -5, 5)
|
|
parent.tabs[fname].backdrop:SetPoint("BOTTOMRIGHT", parent.tabs[fname], "BOTTOMRIGHT", 5, -5)
|
|
pfUI.api.CreateBackdrop(parent.tabs[fname].backdrop, nil, true)
|
|
|
|
parent.tabs[fname].button = CreateFrame("Button", name .. "Button", parent)
|
|
parent.tabs[fname].button:SetPoint(anchor, x, y)
|
|
parent.tabs[fname].button:SetWidth(153)
|
|
parent.tabs[fname].button:SetHeight(30)
|
|
parent.tabs[fname].button:SetScript("OnClick", function()
|
|
SelectView(parent.tabs[fname])
|
|
end)
|
|
|
|
if fname == "units" then
|
|
EnableTooltips(parent.tabs[fname].button, {
|
|
pfQuest_Loc["Units"],
|
|
pfQuest_Loc["Display related creatures and NPCs"],
|
|
})
|
|
elseif fname == "objects" then
|
|
EnableTooltips(parent.tabs[fname].button, {
|
|
pfQuest_Loc["Objects"],
|
|
pfQuest_Loc["Display related objects like ores, herbs, chests, etc."],
|
|
})
|
|
elseif fname == "items" then
|
|
EnableTooltips(parent.tabs[fname].button, {
|
|
pfQuest_Loc["Items"],
|
|
pfQuest_Loc["Display related items"],
|
|
})
|
|
elseif fname == "quests" then
|
|
EnableTooltips(parent.tabs[fname].button, {
|
|
pfQuest_Loc["Quests"],
|
|
pfQuest_Loc["Display related quests"],
|
|
})
|
|
end
|
|
|
|
pfUI.api.SkinButton(parent.tabs[fname].button)
|
|
parent.tabs[fname].list = pfUI.api.CreateScrollChild(name .. "Scroll", parent.tabs[fname])
|
|
parent.tabs[fname].list:SetWidth(600)
|
|
end
|
|
|
|
-- browser window
|
|
pfBrowser = CreateFrame("Frame", "pfQuestBrowser", UIParent)
|
|
pfBrowser:Hide()
|
|
pfBrowser:SetWidth(640)
|
|
pfBrowser:SetHeight(480)
|
|
pfBrowser:SetPoint("CENTER", 0, 0)
|
|
pfBrowser:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
pfBrowser:SetMovable(true)
|
|
pfBrowser:EnableMouse(true)
|
|
pfBrowser:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
pfBrowser:SetScript("OnEvent", function()
|
|
-- queue favorites for incremental processing rather than running all
|
|
-- Search*ID calls synchronously in one PLAYER_ENTERING_WORLD frame.
|
|
-- each entry is drained one per OnUpdate tick (see OnUpdate below).
|
|
if pfQuest_config.favonlogin == "1" then
|
|
pfBrowser.favqueue = {}
|
|
for id, name in pairs(pfBrowser_fav.units) do
|
|
table.insert(pfBrowser.favqueue, { "units", id })
|
|
end
|
|
for id, name in pairs(pfBrowser_fav.objects) do
|
|
table.insert(pfBrowser.favqueue, { "objects", id })
|
|
end
|
|
for id, name in pairs(pfBrowser_fav.items) do
|
|
table.insert(pfBrowser.favqueue, { "items", id })
|
|
end
|
|
for id, name in pairs(pfBrowser_fav.quests) do
|
|
table.insert(pfBrowser.favqueue, { "quests", id })
|
|
end
|
|
end
|
|
end)
|
|
pfBrowser:SetScript("OnMouseDown", function()
|
|
this:StartMoving()
|
|
end)
|
|
|
|
pfBrowser:SetScript("OnMouseUp", function()
|
|
this:StopMovingOrSizing()
|
|
end)
|
|
|
|
pfUI.api.CreateBackdrop(pfBrowser, nil, true, 0.75)
|
|
table.insert(UISpecialFrames, "pfQuestBrowser")
|
|
|
|
pfBrowser.title = pfBrowser:CreateFontString("Status", "LOW", "GameFontNormal")
|
|
pfBrowser.title:SetFontObject(GameFontWhite)
|
|
pfBrowser.title:SetPoint("TOP", pfBrowser, "TOP", 0, -8)
|
|
pfBrowser.title:SetJustifyH("LEFT")
|
|
pfBrowser.title:SetFont(pfUI.font_default, 14)
|
|
pfBrowser.title:SetText("|cff33ffccpf|rQuest")
|
|
|
|
pfBrowser.close = CreateFrame("Button", "pfQuestBrowserClose", pfBrowser)
|
|
pfBrowser.close:SetPoint("TOPRIGHT", -5, -5)
|
|
pfBrowser.close:SetHeight(20)
|
|
pfBrowser.close:SetWidth(20)
|
|
pfBrowser.close.texture = pfBrowser.close:CreateTexture("pfQuestionDialogCloseTex")
|
|
pfBrowser.close.texture:SetTexture(pfQuestConfig.path .. "\\compat\\close")
|
|
pfBrowser.close.texture:ClearAllPoints()
|
|
pfBrowser.close.texture:SetVertexColor(1, 0.25, 0.25, 1)
|
|
pfBrowser.close.texture:SetPoint("TOPLEFT", pfBrowser.close, "TOPLEFT", 4, -4)
|
|
pfBrowser.close.texture:SetPoint("BOTTOMRIGHT", pfBrowser.close, "BOTTOMRIGHT", -4, 4)
|
|
pfBrowser.close:SetScript("OnClick", function()
|
|
this:GetParent():Hide()
|
|
end)
|
|
EnableTooltips(pfBrowser.close, {
|
|
pfQuest_Loc["Close"],
|
|
pfQuest_Loc["Hide browser window"],
|
|
})
|
|
pfUI.api.SkinButton(pfBrowser.close, 1, 0.5, 0.5)
|
|
|
|
pfBrowser.journal = CreateFrame("Button", "pfQuestJournalOpen", pfBrowser)
|
|
pfBrowser.journal:SetPoint("TOPRIGHT", -30, -5)
|
|
pfBrowser.journal:SetHeight(20)
|
|
pfBrowser.journal:SetWidth(20)
|
|
pfBrowser.journal.texture = pfBrowser.journal:CreateTexture("pfQuestionDialogCloseTex")
|
|
pfBrowser.journal.texture:SetTexture(pfQuestConfig.path .. "\\img\\tracker_quests")
|
|
pfBrowser.journal.texture:ClearAllPoints()
|
|
pfBrowser.journal.texture:SetPoint("TOPLEFT", pfBrowser.journal, "TOPLEFT", 2, -2)
|
|
pfBrowser.journal.texture:SetPoint("BOTTOMRIGHT", pfBrowser.journal, "BOTTOMRIGHT", -2, 2)
|
|
pfBrowser.journal:SetScript("OnClick", function()
|
|
if pfJournal:IsShown() then
|
|
pfJournal:Hide()
|
|
else
|
|
pfJournal:Show()
|
|
end
|
|
end)
|
|
EnableTooltips(pfBrowser.journal, {
|
|
pfQuest_Loc["Journal"],
|
|
pfQuest_Loc["Toggle completed quest browser"],
|
|
})
|
|
pfUI.api.SkinButton(pfBrowser.journal)
|
|
|
|
pfBrowser.clean = CreateFrame("Button", "pfQuestBrowserClean", pfBrowser)
|
|
pfBrowser.clean:SetPoint("TOPRIGHT", pfBrowser, "TOPRIGHT", -5, -30)
|
|
pfBrowser.clean:SetPoint("BOTTOMRIGHT", pfBrowser, "TOPRIGHT", 0, -55)
|
|
pfBrowser.clean:SetScript("OnClick", function()
|
|
pfMap:DeleteNode("PFDB")
|
|
pfMap:UpdateNodes()
|
|
-- Database-result pins can also become the route arrow's explicit target.
|
|
-- Update the remaining pins first, then clear the route so that this same
|
|
-- refresh cannot immediately replace the removed database result with an
|
|
-- automatic quest route.
|
|
if pfQuest.route then
|
|
pfQuest.route.SetTarget(nil)
|
|
pfQuest.route:Clear()
|
|
end
|
|
pfMap.queue_update = nil
|
|
end)
|
|
pfBrowser.clean.text = pfBrowser.clean:CreateFontString("Caption", "LOW", "GameFontWhite")
|
|
pfBrowser.clean.text:SetAllPoints(pfBrowser.clean)
|
|
pfBrowser.clean.text:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
|
|
pfBrowser.clean.text:SetText(pfQuest_Loc["Clean Map"])
|
|
local width = pfBrowser.clean.text:GetStringWidth() > 90 and pfBrowser.clean.text:GetStringWidth() + 20 or 90
|
|
pfBrowser.clean:SetWidth(width)
|
|
EnableTooltips(pfBrowser.clean, {
|
|
pfQuest_Loc["Clean Map"],
|
|
pfQuest_Loc["Remove all manually searched objects from the map"],
|
|
})
|
|
pfUI.api.SkinButton(pfBrowser.clean)
|
|
|
|
CreateBrowseWindow("units", "pfQuestBrowserUnits", pfBrowser, "BOTTOMLEFT", 5, 5)
|
|
CreateBrowseWindow("objects", "pfQuestBrowserObjects", pfBrowser, "BOTTOMLEFT", 164, 5)
|
|
CreateBrowseWindow("items", "pfQuestBrowserItems", pfBrowser, "BOTTOMRIGHT", -164, 5)
|
|
CreateBrowseWindow("quests", "pfQuestBrowserQuests", pfBrowser, "BOTTOMRIGHT", -5, 5)
|
|
|
|
SelectView(pfBrowser.tabs["units"])
|
|
|
|
pfBrowser.input = CreateFrame("EditBox", "pfQuestBrowserSearch", pfBrowser)
|
|
pfBrowser.input:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
|
|
pfBrowser.input:SetFontObject("GameFontDisable")
|
|
pfBrowser.input:SetAutoFocus(false)
|
|
pfBrowser.input:SetText(pfQuest_Loc["Search"])
|
|
pfBrowser.input:SetJustifyH("LEFT")
|
|
pfBrowser.input:SetPoint("TOPLEFT", pfBrowser, "TOPLEFT", 5, -30)
|
|
pfBrowser.input:SetPoint("BOTTOMRIGHT", pfBrowser.clean, "BOTTOMLEFT", -5, 0)
|
|
pfBrowser.input:SetTextInsets(24, 12, 4, 4)
|
|
|
|
pfBrowser.input.searchIcon = pfBrowser.input:CreateTexture("$parentSearchIcon", "OVERLAY")
|
|
pfBrowser.input.searchIcon:SetTexture(pfQuestConfig.path .. "\\img\\tracker_search")
|
|
pfBrowser.input.searchIcon:SetHeight(14)
|
|
pfBrowser.input.searchIcon:SetWidth(14)
|
|
pfBrowser.input.searchIcon:SetVertexColor(0.6, 0.6, 0.6)
|
|
pfBrowser.input.searchIcon:SetPoint("LEFT", pfBrowser.input, "LEFT", 6, 0)
|
|
|
|
pfBrowser.input.clearButton = CreateFrame("Button", "$parentClearButton", pfBrowser.input)
|
|
pfBrowser.input.clearButton:Hide()
|
|
pfBrowser.input.clearButton:SetHeight(17)
|
|
pfBrowser.input.clearButton:SetWidth(17)
|
|
pfBrowser.input.clearButton:SetPoint("RIGHT", pfBrowser.input, "RIGHT", -3, 0)
|
|
pfBrowser.input.clearButton.texture = pfBrowser.input.clearButton:CreateTexture(nil, "ARTWORK")
|
|
pfBrowser.input.clearButton.texture:SetTexture(pfQuestConfig.path .. "\\img\\tracker_close")
|
|
pfBrowser.input.clearButton.texture:SetHeight(17)
|
|
pfBrowser.input.clearButton.texture:SetWidth(17)
|
|
pfBrowser.input.clearButton.texture:SetAlpha(0.5)
|
|
pfBrowser.input.clearButton.texture:SetPoint("TOPLEFT", pfBrowser.input.clearButton, "TOPLEFT", 0, 0)
|
|
pfBrowser.input.clearButton:SetScript("OnEnter", function()
|
|
this.texture:SetAlpha(1.0)
|
|
end)
|
|
pfBrowser.input.clearButton:SetScript("OnLeave", function()
|
|
this.texture:SetAlpha(0.5)
|
|
end)
|
|
pfBrowser.input.clearButton:SetScript("OnMouseDown", function()
|
|
if this:IsEnabled() then
|
|
this.texture:SetPoint("TOPLEFT", this, "TOPLEFT", 1, -1)
|
|
end
|
|
end)
|
|
pfBrowser.input.clearButton:SetScript("OnMouseUp", function()
|
|
this.texture:SetPoint("TOPLEFT", this, "TOPLEFT", 0, 0)
|
|
end)
|
|
pfBrowser.input.clearButton:SetScript("OnClick", function()
|
|
PlaySound("igMainMenuOptionCheckBoxOn")
|
|
pfBrowser.input:SetText("")
|
|
--[[
|
|
If there is no focus, then the ClearFocus() method does not call the OnEditFocusLost script.
|
|
In 1.12, there is no HasFocus() method, so there is no way to check for focus. therefore,
|
|
for ease of implementation and to avoid double calling the OnEditFocusLost script, I use the
|
|
SetFocus() method to accurately ensure that the OnEditFocusLost script is called.
|
|
--]]
|
|
pfBrowser.input:SetFocus()
|
|
pfBrowser.input:ClearFocus()
|
|
end)
|
|
|
|
pfBrowser.input:SetScript("OnEscapePressed", function()
|
|
this:ClearFocus()
|
|
end)
|
|
pfBrowser.input:SetScript("OnEnterPressed", function()
|
|
this:ClearFocus()
|
|
end)
|
|
pfBrowser.input:SetScript("OnEditFocusGained", function()
|
|
this:HighlightText()
|
|
this:SetFontObject("GameFontWhite")
|
|
this.searchIcon:SetVertexColor(1.0, 1.0, 1.0)
|
|
if this:GetText() == pfQuest_Loc["Search"] then
|
|
this:SetText("")
|
|
end
|
|
this.clearButton:Show()
|
|
end)
|
|
|
|
pfBrowser.input:SetScript("OnEditFocusLost", function()
|
|
this:HighlightText(0, 0)
|
|
this:SetFontObject("GameFontDisable")
|
|
this.searchIcon:SetVertexColor(0.6, 0.6, 0.6)
|
|
if this:GetText() == "" then
|
|
this:SetText(pfQuest_Loc["Search"])
|
|
this.clearButton:Hide()
|
|
end
|
|
end)
|
|
|
|
-- This script updates all the search tabs when the search text changes
|
|
local searchPending = false
|
|
local searchText = ""
|
|
pfBrowser.input:SetScript("OnTextChanged", function()
|
|
local text = this:GetText()
|
|
if text == pfQuest_Loc["Search"] then
|
|
text = ""
|
|
end
|
|
searchText = text
|
|
searchPending = true
|
|
end)
|
|
|
|
-- Deferred search runner: fires at most once per 0.5s after the last keystroke.
|
|
-- Scanning the database four times synchronously on every keystroke caused
|
|
-- visible stuttering; this collapses rapid typing into a single search.
|
|
local searchElapsed = 0
|
|
pfBrowser:SetScript("OnUpdate", function()
|
|
this.elapsed = (this.elapsed or 0) + arg1
|
|
if this.elapsed < 0.1 then
|
|
return
|
|
end
|
|
this.elapsed = 0
|
|
|
|
-- drain one favorite search per tick to spread login cost across frames
|
|
if pfBrowser.favqueue and table.getn(pfBrowser.favqueue) > 0 then
|
|
local entry = table.remove(pfBrowser.favqueue, 1)
|
|
local ftype, id = entry[1], entry[2]
|
|
if ftype == "units" then
|
|
pfDatabase:SearchMobID(id)
|
|
end
|
|
if ftype == "objects" then
|
|
pfDatabase:SearchObjectID(id)
|
|
end
|
|
if ftype == "items" then
|
|
pfDatabase:SearchItemID(id)
|
|
end
|
|
if ftype == "quests" then
|
|
pfDatabase:SearchQuestID(id)
|
|
end
|
|
pfMap.queue_update = GetTime()
|
|
end
|
|
|
|
-- run pending search once debounce interval has elapsed
|
|
if searchPending then
|
|
searchElapsed = searchElapsed + 0.1
|
|
if searchElapsed >= 0.5 then
|
|
searchElapsed = 0
|
|
searchPending = false
|
|
|
|
local text = searchText
|
|
local custom = string.find(text, "^custom:")
|
|
text = string.gsub(text, "^custom:", "")
|
|
|
|
for _, caption in ipairs({ "Units", "Objects", "Items", "Quests" }) do
|
|
local searchType = strlower(caption)
|
|
local data = (strlen(text) >= 3 or custom) and pfDatabase:GetIDByName(text, searchType, true, custom)
|
|
or pfBrowser_fav[searchType]
|
|
|
|
local i = 0
|
|
for id, text in pairs(data) do
|
|
i = i + 1
|
|
if i >= search_limit then
|
|
break
|
|
end
|
|
pfBrowser.tabs[searchType].buttons[i] = pfBrowser.tabs[searchType].buttons[i]
|
|
or ResultButtonCreate(i, searchType)
|
|
pfBrowser.tabs[searchType].buttons[i].id = id
|
|
pfBrowser.tabs[searchType].buttons[i].name = text
|
|
pfBrowser.tabs[searchType].buttons[i]:Reload()
|
|
end
|
|
|
|
RefreshView(i, searchType, caption)
|
|
end
|
|
end
|
|
else
|
|
searchElapsed = 0
|
|
end
|
|
|
|
-- skip multi-select machinery entirely when Ctrl is not held and no
|
|
-- selection is in progress — avoids an unconditional GetMouseFocus()
|
|
-- call every 0.1s when the feature is idle
|
|
if not IsControlKeyDown() and not this.selectState then
|
|
return
|
|
end
|
|
|
|
-- Cache GetMouseFocus to avoid multiple calls
|
|
local focus = GetMouseFocus()
|
|
|
|
-- multi-select handling
|
|
if not this.selectState and IsControlKeyDown() and focus and focus.pfResultButton then
|
|
for id, frame in pairs(pfBrowser.tabs) do
|
|
for id, button in pairs(frame.buttons) do
|
|
if button.name == focus.name then
|
|
button.tex:SetTexture(0.3, 1, 0.8, 0.4)
|
|
end
|
|
end
|
|
end
|
|
this.selectState = "active"
|
|
elseif this.selectState and (this.selectState == "clean" or not IsControlKeyDown()) then
|
|
for id, frame in pairs(pfBrowser.tabs) do
|
|
for id, button in pairs(frame.buttons) do
|
|
if compat.mod(button:GetID(), 2) == 1 then
|
|
button.tex:SetTexture(1, 1, 1, 0.02)
|
|
else
|
|
button.tex:SetTexture(1, 1, 1, 0.04)
|
|
end
|
|
end
|
|
end
|
|
this.selectState = nil
|
|
end
|
|
end)
|
|
|
|
pfUI.api.CreateBackdrop(pfBrowser.input, nil, true)
|