local TalkBox, GetOffset, _, L = {}, UIParent.GetBottom, ... ---------------------------------- -- Offsets ---------------------------------- function TalkBox:SetOffset(x, y) --[[if self:UpdateNameplateAnchor() then return end]] local point = L('boxpoint') local anidivisor = L('anidivisor') x = x or L('boxoffsetX') y = y or L('boxoffsetY') self.offsetX = x self.offsetY = y local isBottom = ( point:match('Bottom') ) y = y + ( isBottom and self.extraY or 0 ) local comp = y if ( not isBottom ) or ( anidivisor <= 1 ) or ( not self:IsVisible() ) then self:SetPoint(point, UIParent, x, y) return end self:SetScript('OnUpdate', function(self) self.isOffsetting = true local offset = (GetOffset(self) or 0) - (GetOffset(UIParent) or 0) local diff = ( comp - offset ) if (offset == 0) or abs( comp - offset ) < 0.3 then self:SetPoint(point, UIParent, x, y) self.isOffsetting = false self:SetScript('OnUpdate', nil) else self:SetPoint(point, UIParent, x, offset + ( diff / anidivisor )) end end) end -- Temporarily increase the frame offset, in case we want to show extra stuff, -- like quest descriptions, quest rewards, items needed for quest progress, etc. function TalkBox:SetExtraOffset(newOffset) local currX = ( self.offsetX or L('boxoffsetX') ) local currY = ( self.offsetY or L('boxoffsetY') ) local allowExtra = L('anidivisor') > 0 self.extraY = allowExtra and newOffset or 0 self:SetOffset(currX, currY) end function TalkBox:UpdateNameplateAnchor() if self.plateInHiding then self.plateInHiding:SetAlpha(1) self.plateInHiding = nil end if L('nameplatemode') then local plate = API:GetNamePlateForUnit('npc') if plate then if self.isOffsetting then self:SetScript('OnUpdate', nil) self.isOffsetting = false end self:ClearAllPoints() self:SetPoint('CENTER', plate, 'TOP', 0, self.extraY or 0) if plate.UnitFrame then self.plateInHiding = plate.UnitFrame self.plateInHiding:SetAlpha(0) end return true end end end ---------------------------------- -- Scripts ---------------------------------- function TalkBox:OnEnter() -- Highlight the button when it can be clicked if not L('disableboxhighlight') then local lastEvent = self.lastEvent if L('immersivemode') or ( ( ( lastEvent == 'QUEST_COMPLETE' ) and not (self.Elements.itemChoice == 0 and GetNumQuestChoices() > 1) ) or ( lastEvent == 'QUEST_ACCEPTED' ) or ( lastEvent == 'QUEST_DETAIL' ) or ( lastEvent == 'ITEM_TEXT_READY' ) or ( lastEvent ~= 'GOSSIP_SHOW' and IsQuestCompletable() ) ) then L.UIFrameFadeIn(self.Hilite, 0.15, self.Hilite:GetAlpha(), 1) end end end function TalkBox:OnLeave() L.UIFrameFadeOut(self.Hilite, 0.15, self.Hilite:GetAlpha(), 0) end function TalkBox:OnDragStart() if ( L('boxlock') or self.isOffsetting ) then return end self:StartMoving() end function TalkBox:OnDragStop() if ( L('boxlock') or self.isOffsetting ) then return end self:StopMovingOrSizing() local point, _, _, x, y = self:GetPoint() point = point:sub(1,1) .. point:sub(2):lower() -- convert center point to bottom if ( point == 'Center' ) then point = 'Bottom' -- calculate the horz offset from the center of the screen x = ( self:GetCenter() * ImmersionFrame:GetScale() ) - ( GetScreenWidth() / 2 ) y = self:GetBottom() end local isBottom = point == 'Bottom' if isBottom then y = y - (self.extraY or 0) end self:ClearAllPoints() self.offsetX, self.offsetY = x, y L.Set('boxpoint', point) L.Set('boxoffsetX', x) L.Set('boxoffsetY', y) self:SetPoint(point, UIParent, point, x, isBottom and y + (self.extraY or 0) or y) end function TalkBox:OnLeftClick() -- Complete quest if self.lastEvent == 'QUEST_COMPLETE' then self.Elements:CompleteQuest() -- Accept quest elseif self.lastEvent == 'QUEST_DETAIL' or self.lastEvent == 'QUEST_ACCEPTED' then self.Elements:AcceptQuest() elseif self.lastEvent == 'ITEM_TEXT_READY' then local text = self.TextFrame.Text if text:GetNumRemaining() > 1 and text:IsSequence() then text:ForceNext() else API:CloseItemText() end -- Progress quest to completion elseif self.lastEvent == 'QUEST_PROGRESS' then if IsQuestCompletable() then CompleteQuest() else ImmersionFrame:ForceClose() end else ImmersionFrame:ForceClose() end end function TalkBox:OnClick(button) if L('flipshortcuts') then button = button == 'LeftButton' and 'RightButton' or 'LeftButton' end if button == 'LeftButton' then if L('immersivemode') then L.Inputs.accept(ImmersionFrame) else self:OnLeftClick() end elseif button == 'RightButton' then local text = self.TextFrame.Text if text:GetNumRemaining() > 1 and text:IsSequence() then text:ForceNext() elseif text:IsSequence() then if ( ImmersionFrame.playbackEvent == 'IMMERSION_TOAST' ) then ImmersionFrame:RemoveToastByText(text.storedText) else text:RepeatTexts() end end end end function TalkBox:Dim() L.UIFrameFadeOut(self, 0.15, self:GetAlpha(), 0.05) end function TalkBox:Undim() L.UIFrameFadeIn(self, 0.15, self:GetAlpha(), 1) end ---------------------------------- -- Mixin with scripts ---------------------------------- L.Mixin(L.frame.TalkBox, TalkBox)