You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
9.7 KiB

local API, Titles, _, L = ImmersionAPI, {}, ...
L.TitlesMixin = Titles
-- Upvalue for update scripts
local GetScaledCursorPosition, UIParent = GetScaledCursorPosition, UIParent
local NORMAL_QUEST_DISPLAY = NORMAL_QUEST_DISPLAY:gsub(0, 'f')
local TRIVIAL_QUEST_DISPLAY = TRIVIAL_QUEST_DISPLAY:gsub(0, 'f')
-- Priority
local P_COMPLETE_QUEST = 1
local P_AVAILABLE_QUEST = 2
local P_AVAILABLE_GOSSIP = 3
local P_INCOMPLETE_QUEST = 4
-- Animation divisor
local ANI_DIVISOR = 10
----------------------------------
-- Display
----------------------------------
function Titles:AdjustHeight(newHeight)
self.offset = 0
if ( ANI_DIVISOR == 0 ) then
self:SetHeight(1)
self:OnUpdateOffset()
return
elseif ( ANI_DIVISOR == 1 ) then
self:SetHeight(newHeight)
self:OnUpdateOffset()
return
end
self:SetScript('OnUpdate', function(self)
local height = self:GetHeight()
local diff = newHeight - height
if abs(newHeight - height) < 0.5 then
self:SetHeight(newHeight)
self:SetScript('OnUpdate', nil)
else
self:SetHeight(height + ( diff / ANI_DIVISOR ) )
end
self:OnUpdateOffset()
end)
end
function Titles:OnUpdateOffset()
local anchor, relativeRegion, relativeKey, x, y, offset
if not self.ignoreAtCursor and L('gossipatcursor') then
local posX, posY = GetScaledCursorPosition()
local uiX, uiY = UIParent:GetCenter()
x, y = (posX - uiX), (posY - uiY)
anchor, relativeRegion, relativeKey, offset =
'CENTER', UIParent, 'CENTER', 0
else
anchor, relativeRegion, relativeKey, x, y = self:GetPoint()
offset = (self.offset or 0) + L('titleoffsetY')
end
local diff = ( y - offset )
if ( offset == 0 ) or abs( y - offset ) < 0.3 then
self:SetPoint(anchor, relativeRegion, relativeKey, x, offset)
if self:GetScript('OnUpdate') == self.OnUpdateOffset then
self:SetScript('OnUpdate', nil)
end
else
self:SetPoint(anchor, relativeRegion, relativeKey, x, offset + (ANI_DIVISOR > 1 and (diff / ANI_DIVISOR) or 0))
end
end
function Titles:StopMoving()
self:StopMovingOrSizing()
local centerX, centerY = self:GetCenter()
local scaleOffset = self:GetScale() * self:GetParent():GetScale()
local uiX, uiY = GetScreenWidth() / 2 / scaleOffset, GetScreenHeight() / 2 / scaleOffset
local newHorzVal, newVertVal = (centerX - uiX), (centerY - uiY)
-- Horizontal clip fix
if self:GetLeft() < 0 then
newHorzVal = (self:GetWidth() / 2) - (GetScreenWidth() / 2) + 16
elseif ( GetScreenWidth() - self:GetRight() ) < 0 then
newHorzVal = (GetScreenWidth() / 2) - (self:GetWidth() / 2) - 16
end
-- Vertical clip fix
if self:GetBottom() < 0 then
newVertVal = (self:GetHeight() / 2) - (GetScreenHeight() / 2) + 16
elseif ( GetScreenHeight() - self:GetTop() ) < 0 then
newVertVal = (GetScreenHeight() / 2) - (self:GetHeight() / 2) - 16
end
self:ClearAllPoints()
self:SetPoint('CENTER', UIParent, newHorzVal, newVertVal)
L.Set('titleoffset', newHorzVal)
L.Set('titleoffsetY', newVertVal)
end
function Titles:OnScroll(delta)
self.offset = self.offset and self.offset + (-delta * 40) or (-delta * 40)
self.ignoreAtCursor = true
self:SetScript('OnUpdate', self.OnUpdateOffset)
end
function Titles:ResetPosition()
self.offset = 0
self.ignoreAtCursor = false
end
function Titles:OnEvent(event, ...)
if self[event] then
self[event](self, ...)
else
self:Hide()
end
end
function Titles:OnHide()
for i, button in pairs(self.Buttons) do
button:UnlockHighlight()
button:Hide()
end
wipe(self.Active)
self.numActive = 0
self.idx = 1
end
function Titles:GetNumActive()
return self.numActive or 0
end
function Titles:GetButton(index)
local button = self.Buttons[index]
if not button then
button = L.Create({
type = 'Button',
name = 'TitleButton',
index = index,
parent = self,
inherit = 'ImmersionTitleButtonTemplate',
mixins = {L.ButtonMixin, L.ScalerMixin},
backdrop = L.Backdrops.GOSSIP_TITLE_BG,
})
button:Init(index)
self.Buttons[index] = button
end
button:Show()
return button
end
function Titles:UpdateActive()
local newHeight, numActive = 0, 0
wipe(self.Active)
for i, button in pairs(self.Buttons) do
if button:IsShown() then
newHeight = newHeight + button:GetHeight()
numActive = numActive + 1
self.Active[i] = button
end
end
ANI_DIVISOR = L('anidivisor')
self.ignoreAtCursor = false
self.numActive = numActive
self:ResetPosition()
self:AdjustHeight(newHeight)
if self.SetFocus then
local _, bestOptionIndex = self:GetBestOption()
self:SetFocus(bestOptionIndex)
end
end
function Titles:GetBestOption()
local numActive = self:GetNumActive()
if numActive > 0 then
local option = self.Buttons[1]
for i=2, numActive do
option = option:ComparePriority(self.Buttons[i])
end
return option, option.idx
end
end
----------------------------------
-- Gossip
----------------------------------
function Titles:GOSSIP_SHOW()
self.idx = 1
self.type = 'Gossip'
self:Show()
self:UpdateAvailableQuests(API:GetGossipAvailableQuests())
self:UpdateActiveQuests(API:GetGossipActiveQuests())
self:UpdateGossipOptions(API:GetGossipOptions())
for i = self.idx, #self.Buttons do
self.Buttons[i]:Hide()
end
self:UpdateActive()
end
function Titles:UpdateAvailableQuests(data)
for i, quest in ipairs(data) do
local button = self:GetButton(self.idx)
----------------------------------
local typeOfQ = (quest.isTrivial and TRIVIAL_QUEST_DISPLAY)
button:SetFormattedText(typeOfQ or NORMAL_QUEST_DISPLAY, quest.title)
----------------------------------
local icon, useAtlas = API:GetQuestIconOffer(quest)
button:SetIcon(icon, typeOfQ and 0.5, useAtlas)
----------------------------------
button:SetPriority(P_AVAILABLE_QUEST)
----------------------------------
button:SetID(API.IsWoW10 and quest.questID or i)
button.type = 'Available'
----------------------------------
self.idx = self.idx + 1
end
end
function Titles:UpdateActiveQuests(data)
self.hasActiveQuests = (#data > 0)
for i, quest in ipairs(data) do
local button = self:GetButton(self.idx)
----------------------------------
local typeOfQ = (quest.isTrivial and TRIVIAL_QUEST_DISPLAY)
button:SetFormattedText(typeOfQ or NORMAL_QUEST_DISPLAY, quest.title)
----------------------------------
local icon, useAtlas = API:GetQuestIconActive(quest)
button:SetIcon(icon, typeOfQ and 0.5, useAtlas)
----------------------------------
button:SetPriority(quest.isComplete and P_COMPLETE_QUEST or P_INCOMPLETE_QUEST)
----------------------------------
button:SetID(API.IsWoW10 and quest.questID or i)
button:SetType('Active')
----------------------------------
self.idx = self.idx + 1
end
end
function Titles:UpdateGossipOptions(data)
for i, option in ipairs(data) do
local button = self:GetButton(self.idx)
----------------------------------
button:SetText(option.name)
button:SetGossipIcon(option.type or option.icon)
button:SetPriority(P_AVAILABLE_GOSSIP)
----------------------------------
button:SetID(API:GetGossipOptionID(option))
button:SetType('Gossip')
----------------------------------
self.idx = self.idx + 1
end
end
function Titles:UNIT_QUEST_LOG_CHANGED()
if self:IsVisible() then
if ( self.type == 'Gossip' and self.hasActiveQuests ) then
self:Hide()
self:GOSSIP_SHOW()
elseif ( self.type == 'Quests' ) then
self:Hide()
self:QUEST_GREETING()
end
end
end
----------------------------------
-- Quest
----------------------------------
function Titles:QUEST_GREETING()
self.idx = 1
self.type = 'Quests'
self:Show()
self:UpdateActiveGreetingQuests(API:GetNumActiveQuests())
self:UpdateAvailableGreetingQuests(API:GetNumAvailableQuests())
for i = self.idx, #self.Buttons do
self.Buttons[i]:Hide()
end
self:UpdateActive()
end
function Titles:UpdateActiveGreetingQuests(numActiveQuests)
for i=1, numActiveQuests do
local button = self:GetButton(self.idx)
local title, isComplete = GetActiveTitle(i)
----------------------------------
local qType = ( IsActiveQuestTrivial(i) and TRIVIAL_QUEST_DISPLAY )
button:SetFormattedText(qType or NORMAL_QUEST_DISPLAY, title)
----------------------------------
local icon = ( isComplete and API:IsActiveQuestLegendary(i) and 'ActiveLegendaryQuestIcon' ) or
( isComplete and 'ActiveQuestIcon') or
( 'InCompleteQuestIcon' )
button:SetGossipQuestIcon(icon, qType and 0.75)
button:SetPriority(isComplete and P_COMPLETE_QUEST or P_INCOMPLETE_QUEST)
----------------------------------
button:SetID(i)
button.type = 'ActiveQuest'
----------------------------------
self.idx = self.idx + 1
end
end
function Titles:UpdateAvailableGreetingQuests(numAvailableQuests)
for i=1, numAvailableQuests do
local button = self:GetButton(self.idx)
local title = GetAvailableTitle(i)
local isTrivial, frequency, isRepeatable, isLegendary, questID = API:GetAvailableQuestInfo(i)
----------------------------------
local qType = ( isTrivial and TRIVIAL_QUEST_DISPLAY )
button:SetFormattedText(qType or NORMAL_QUEST_DISPLAY, title)
----------------------------------
local icon = ( isLegendary and 'AvailableLegendaryQuestIcon' ) or
( frequency == LE_QUEST_FREQUENCY_DAILY and 'DailyQuestIcon') or
( frequency == LE_QUEST_FREQUENCY_WEEKLY and 'DailyQuestIcon' ) or
( isRepeatable and 'DailyActiveQuestIcon' ) or
( 'AvailableQuestIcon' )
button:SetGossipQuestIcon(icon, qType and 0.5)
button:SetPriority(P_AVAILABLE_QUEST)
----------------------------------
button:SetID(i)
button.type = 'AvailableQuest'
----------------------------------
self.idx = self.idx + 1
end
end