Files
pfQuest/journal.lua

287 lines
9.6 KiB
Lua

-- multi api compat
local compat = pfQuestCompat
-- Performance: cache frequently-used globals
local pairs = pairs
local min, max = math.min, math.max
local getn = table.getn
local date = date
local GetTime = GetTime
local MouseIsOver = MouseIsOver
local collapsed = {}
local function tablesize(tbl)
local count = 0
for _ in pairs(tbl) do
count = count + 1
end
return count
end
local function OnEnter()
-- show remove button and highlight for quest entries (not column headers)
if not this.column then
this.remove:Show()
this.bg:Show()
end
if this.id then
-- show extended quest tooltip
pfDatabase:ShowExtendedTooltip(this.id, GameTooltip, this, "ANCHOR_LEFT", 0, -10)
-- add level of completion
if pfQuest_history[this.id] and pfQuest_history[this.id][2] then
local level = pfQuest_history[this.id][2]
local color = pfQuestCompat.GetDifficultyColor(level)
GameTooltip:AddLine("|cffffffff" .. pfQuest_Loc["Completed Level"] .. ": |r" .. level, color.r, color.g, color.b)
end
GameTooltip:Show()
end
end
local function OnLeave()
-- The remove button is a child of the row. Vanilla fires the row's
-- OnLeave while the cursor crosses onto that child, so hiding it here makes
-- the X flicker away before its click can register.
if this.remove and MouseIsOver(this.remove) then return end
this.remove:Hide()
this.bg:Hide()
GameTooltip:Hide()
end
local function OnClick()
if this.id and IsShiftKeyDown() then
if tonumber(this.id) then
pfQuestCompat.InsertQuestLink(this.id)
else
pfQuestCompat.InsertQuestLink(0, this.id)
end
elseif this.id then
local maps = pfDatabase:SearchQuestID(this.id, meta)
pfMap:ShowMapID(pfDatabase:GetBestMap(maps))
elseif this.column then
collapsed[this.column] = not collapsed[this.column]
this.remove.view:ReloadJournal()
end
end
local function RemoveOnClick()
if this.entry.id then
local questid = tonumber(this.entry.id) or this.entry.id
pfQuest_history[questid] = nil
local active = pfQuest.questlog and pfQuest.questlog[questid]
if active and active.qlogid and pfQuest_config["trackingmethod"] ~= 4 then
-- Shift-clicking an active map quest records it in the Journal and
-- removes its PFQUEST nodes. Removing that Journal entry must rebuild
-- the active objectives, not merely refresh available quest givers.
local meta = { addon = "PFQUEST", qlogid = active.qlogid }
if type(pfDatabase.SearchQuestIDHDB) ~= "function"
or not pfDatabase:SearchQuestIDHDB(questid, meta) then
pfDatabase:SearchQuestID(questid, meta)
end
pfMap.queue_update = GetTime()
else
-- A quest no longer in the log may become available again, while its
-- follow-ups may cease to qualify when completion history is removed.
pfQuest.updateQuestGivers = true
end
this.view:ReloadJournal()
end
end
local function RemoveOnEnter()
this:Show()
this.entry.bg:Show()
end
local function RemoveOnLeave()
if MouseIsOver(this.entry) then return end
this:Hide()
this.entry.bg:Hide()
GameTooltip:Hide()
end
local function CreateEntry(self, index)
if self[index] then
return
end
self[index] = CreateFrame("Button", nil, self)
self[index]:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -(index - 1) * 19 - 10)
self[index]:SetPoint("TOPRIGHT", self, "TOPRIGHT", 0, -(index - 1) * 19 - 10)
self[index]:SetHeight(18)
self[index]:SetScript("OnEnter", OnEnter)
self[index]:SetScript("OnLeave", OnLeave)
self[index]:SetScript("OnClick", OnClick)
self[index].text = self[index]:CreateFontString("Caption", "LOW", "GameFontWhite")
self[index].text:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
self[index].text:SetPoint("TOPLEFT", self[index], "TOPLEFT", 10, 0)
self[index].text:SetPoint("BOTTOMRIGHT", self[index], "BOTTOMRIGHT", -10, 0)
self[index].text:SetJustifyH("LEFT")
self[index].bg = self[index]:CreateTexture(nil, "BACKGROUND")
self[index].bg:SetAllPoints(self[index].text)
self[index].bg:SetTexture(1, 1, 1, 0.02)
self[index].bg:Hide()
self[index].remove = CreateFrame("Button", nil, self[index])
self[index].remove:SetPoint("RIGHT", -5, 0)
self[index].remove:SetHeight(20)
self[index].remove:SetWidth(20)
self[index].remove:Hide()
self[index].remove:SetScript("OnClick", RemoveOnClick)
self[index].remove:SetScript("OnEnter", RemoveOnEnter)
self[index].remove:SetScript("OnLeave", RemoveOnLeave)
self[index].remove.entry = self[index]
self[index].remove.view = self
self[index].remove.texture = self[index].remove:CreateTexture("pfQuestionDialogCloseTex")
self[index].remove.texture:SetTexture(pfQuestConfig.path .. "\\compat\\close")
self[index].remove.texture:ClearAllPoints()
self[index].remove.texture:SetVertexColor(1, 0.25, 0.25, 1)
self[index].remove.texture:SetPoint("TOPLEFT", self[index].remove, "TOPLEFT", 4, -4)
self[index].remove.texture:SetPoint("BOTTOMRIGHT", self[index].remove, "BOTTOMRIGHT", -4, 4)
end
local function UpdateEntry(self, index)
if self[index].column then
self[index].remove:Hide()
self[index].bg:Hide()
self[index].text:SetText((collapsed[self[index].column] and "|cff338855" or "|cff33ffcc") .. self[index].column)
self[index]:Show()
elseif self[index].id then
local qid = tonumber(self[index].id) or UNKNOWN
local name = pfDB["quests"]["loc"][self[index].id] and pfDB["quests"]["loc"][self[index].id]["T"] or self[index].id
local log = pfQuest_history[self[index].id][1]
local level = pfQuest_history[self[index].id][2]
self[index].text:SetText(
" |cffffffff" .. date("%H:%M:%S", log) .. " |cffffcc00[" .. (name or UNKNOWN) .. "]|cffaaaaaa (" .. qid .. ")"
)
self[index]:Show()
else
self[index]:Hide()
end
end
local journal = {}
local function ReloadJournal(self)
local self = self or this
local index = 1
local maxcolumns = 24
local lastcolumn, column
for questid, data in pfQuest:SortedPairs(pfQuest_history, 1) do
column = data[1] == 0 and UNKNOWN or date("%A, %B %d (%Y)", data[1])
if column ~= lastcolumn then -- add columns to the view
lastcolumn = column
journal[index] = journal[index] or {}
journal[index].column = column
journal[index].id = nil
index = index + 1
end
if not collapsed[column] then -- add regular entries
journal[index] = journal[index] or {}
journal[index].column = nil
journal[index].id = questid
index = index + 1
end
end
for index = index, table.getn(journal) do
journal[index] = nil
end
-- push offset into limits
self.offset = self.offset or 0
self.offset = min(table.getn(journal) - maxcolumns + 1, self.offset)
self.offset = max(0, self.offset)
-- draw journal into view
for id = 1, maxcolumns do
CreateEntry(self, id)
self[id].id = journal[id + self.offset] and journal[id + self.offset].id or nil
self[id].column = journal[id + self.offset] and journal[id + self.offset].column or nil
UpdateEntry(self, id)
end
end
-- browser window
pfJournal = CreateFrame("Frame", "pfQuestJournal", UIParent)
pfJournal:Hide()
pfJournal:SetWidth(340)
pfJournal:SetHeight(520)
pfJournal:SetPoint("RIGHT", -80, 0)
pfJournal:SetFrameStrata("FULLSCREEN_DIALOG")
pfJournal:SetMovable(true)
pfJournal:EnableMouse(true)
pfJournal:SetScript("OnMouseDown", function()
this:StartMoving()
end)
pfJournal:SetScript("OnMouseUp", function()
this:StopMovingOrSizing()
end)
pfUI.api.CreateBackdrop(pfJournal, nil, true, 0.75)
table.insert(UISpecialFrames, "pfQuestJournal")
pfJournal.title = pfJournal:CreateFontString("Status", "LOW", "GameFontNormal")
pfJournal.title:SetFontObject(GameFontWhite)
pfJournal.title:SetPoint("TOP", pfJournal, "TOP", 0, -8)
pfJournal.title:SetJustifyH("LEFT")
pfJournal.title:SetFont(pfUI.font_default, 14)
pfJournal.title:SetText("|cff33ffccpf|rQuest " .. pfQuest_Loc["Journal"])
pfJournal.close = CreateFrame("Button", "pfQuestJournalClose", pfJournal)
pfJournal.close:SetPoint("TOPRIGHT", -5, -5)
pfJournal.close:SetHeight(20)
pfJournal.close:SetWidth(20)
pfJournal.close:SetScript("OnClick", function()
this:GetParent():Hide()
end)
pfJournal.close.texture = pfJournal.close:CreateTexture("pfQuestionDialogCloseTex")
pfJournal.close.texture:SetTexture(pfQuestConfig.path .. "\\compat\\close")
pfJournal.close.texture:ClearAllPoints()
pfJournal.close.texture:SetVertexColor(1, 0.25, 0.25, 1)
pfJournal.close.texture:SetPoint("TOPLEFT", pfJournal.close, "TOPLEFT", 4, -4)
pfJournal.close.texture:SetPoint("BOTTOMRIGHT", pfJournal.close, "BOTTOMRIGHT", -4, 4)
pfUI.api.SkinButton(pfJournal.close, 1, 0.5, 0.5)
pfJournal.entries = CreateFrame("Button", "pfQuestJournalEntries", pfJournal)
pfJournal.entries.ReloadJournal = ReloadJournal
pfJournal.entries:EnableMouseWheel(true)
pfJournal.entries:SetPoint("TOPLEFT", pfJournal, "TOPLEFT", 10, -35)
pfJournal.entries:SetPoint("BOTTOMRIGHT", pfJournal, "BOTTOMRIGHT", -10, 10)
pfJournal.entries:SetScript("OnMouseWheel", function()
this.offset = this.offset and this.offset - arg1 or 0
this:ReloadJournal()
end)
pfJournal.entries:SetScript("OnClick", pfJournal.entries.ReloadJournal)
pfJournal.entries:SetScript("OnUpdate", function()
-- Only reload when dirty flag is set (avoids polling every second)
-- The dirty flag is set by quest.lua when pfQuest_history changes
if not pfJournal.dirty then
return
end
if (this.tick or 1) > GetTime() then
return
end
this.tick = GetTime() + 0.5
pfJournal.dirty = nil
this:ReloadJournal()
end)
-- Mark journal dirty when shown (initial load)
pfJournal:SetScript("OnShow", function()
pfJournal.dirty = true
end)
pfUI.api.CreateBackdrop(pfJournal.entries)