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.

646 lines
20 KiB

--Quest Log
--[[
C_QuestLog.GetInfo(questLogIndex);
C_CampaignInfo.GetAvailableCampaigns()
C_CampaignInfo.GetCampaignChapterInfo(campaignChapterID)
C_CampaignInfo.GetCampaignID(questID)
C_CampaignInfo.GetCampaignInfo(campaignID)
C_CampaignInfo.GetChapterIDs(campaignID)
C_CampaignInfo.GetCurrentChapterID(campaignID)
C_CampaignInfo.GetFailureReason(campaignID)
C_CampaignInfo.GetState(campaignID)
C_CampaignInfo.IsCampaignQuest(questID)
C_CampaignInfo.UsesNormalQuestIcons(campaignID)
C_LoreText.RequestLoreTextForCampaignID(campaignID)
QuestScrollFrame.campaignHeaderFramePool
covenantCallingsHeaderFramePool
headerFramePool:GetNumActive();
ORBIT_CAMERA_MOUSE_MODE_NOTHING = 0;
ORBIT_CAMERA_MOUSE_MODE_YAW_ROTATION = 1;
ORBIT_CAMERA_MOUSE_MODE_PITCH_ROTATION = 2;
ORBIT_CAMERA_MOUSE_MODE_ROLL_ROTATION = 3;
ORBIT_CAMERA_MOUSE_MODE_TARGET_HORIZONTAL = 4;
ORBIT_CAMERA_MOUSE_MODE_TARGET_VERTICAL = 5;
ORBIT_CAMERA_MOUSE_MODE_ZOOM = 6;
ORBIT_CAMERA_MOUSE_PAN_HORIZONTAL = 7;
ORBIT_CAMERA_MOUSE_PAN_VERTICAL = 8;
campaignID:
1 Alliance
2 Horde
3 Test
125 Shadowlands Campaign 0/2 Through the Shattered Sky/ Arrival in the Shadowlands
131 Threads of Fate 0/5
126 The Looming Dark Choose Covenant
114 Bastion 0/7 Eternity's Call Tidings of War
118 Blade of the Primus 0/7 Champion of Pain / The Empty Throne
124 The Groves of Ardenweald 0/8 Welcome to Ardenweald / Awaken the Dreamer
111 The Master of Revendreth 0/7 Welcome to Revendreth / The Master of Lies
113 Venthyr Campaign
115 Art of War Maldraxxus
--]]
local After = C_Timer.After;
local strsplit = strsplit;
local strtrim = strtrim;
local sin = math.sin;
local cos = math.cos;
local pi = math.pi;
local pow = math.pow;
local abs = math.abs;
local function outQuart(t, b, e, d)
t = t / d - 1;
return (b - e) * (pow(t, 4) - 1) + b
end
local function outSine(t, b, e, d)
return (e - b) * sin(t / d * (pi / 2)) + b
end
local function inOutSine(t, b, e, d)
return (b - e) / 2 * (cos(pi * t / d) - 1) + b
end
local MainFrame;
local LoreBook = CreateFrame("Frame");
local DataProvider = {};
DataProvider.contents = {};
DataProvider.headers = {};
DataProvider.comparisonMode = false;
function DataProvider:GetCampaignIDFromQuestLog()
local questLogIndex = 1;
local info = C_QuestLog.GetInfo(questLogIndex);
if info and info.campaignID then
print("CampaignID: "..info.campaignID);
return info.campaignID
end
end
function DataProvider:RequestLoreText(campaignID)
if campaignID then
LoreBook:RegisterEvent("LORE_TEXT_UPDATED_CAMPAIGN");
C_LoreText.RequestLoreTextForCampaignID(campaignID);
end
end
function DataProvider:Initialize()
local campaignID = self:GetCampaignIDFromQuestLog();
if not campaignID then
if UnitFactionGroup("player") == "Alliance" then
campaignID = 1;
else
campaignID = 2;
end
end
if campaignID then
self:RequestLoreText(campaignID);
end
end
local tempEntries;
function DataProvider:UpdateEntries(textEntries)
--One update per second
--start from 0.5s after the event fires
tempEntries = textEntries;
if self.pauseUpdate then
--print("Update Paused");
return
else
self.pauseUpdate = true;
After(0.5, function()
--print("Start Update");
self:FormatEntries(tempEntries);
self.pauseUpdate = nil;
tempEntries = nil;
end);
end
end
function DataProvider:FormatEntries(textEntries)
LoreBook:UnregisterEvent("LORE_TEXT_UPDATED_CAMPAIGN");
if not textEntries or type(textEntries) ~= "table" then
return
end
local headerText = " ";
local rawText, tempTable;
local index = 1;
local uiOrder = 0;
local comparisonMode = self.comparisonMode;
for i = 1, #textEntries do
rawText = textEntries[i].text;
if textEntries[i].isHeader then
headerText = rawText;
if not self.contents[headerText] then
self.contents[headerText] = {};
end
uiOrder = uiOrder + 1;
self.contents[headerText].uiOrder = uiOrder;
self.headers[uiOrder] = headerText;
index = 1;
else
--print("Header: "..headerText);
if headerText and self.contents[headerText] then
tempTable = {strsplit("\n", rawText)};
for j = 1, #tempTable do
tempTable[j] = strtrim(tempTable[j]);
if tempTable[j] ~= "" then
if comparisonMode then
if not self.contents[headerText][index] then
self.contents[headerText][index] = {text = tempTable[j], isNew = true};
NarciLoreAlert:SetUp(headerText, uiOrder);
end
else
self.contents[headerText][index] = {text = tempTable[j], isNew = false};
end
index = index + 1;
end
end
end
end
end
if not self.comparisonMode then
self.comparisonMode = true;
MainFrame:ShowPage(1);
end
MainFrame.numChapters = uiOrder;
end
function DataProvider:GetChapterTexts(index)
local headerText = self.headers[index];
if headerText then
return headerText, self.contents[headerText]
end
end
local function PrintLoreTable(textEntries)
for i = 1, #textEntries do
if textEntries[i].isHeader then
textEntries[i].text = "|cFFFFD100".. textEntries[i].text .. "|r";
end
--print(textEntries[i].text);
end
end
LoreBook:RegisterEvent("PLAYER_ENTERING_WORLD");
LoreBook:RegisterEvent("QUEST_TURNED_IN");
--LoreBook:RegisterEvent("QUEST_ACCEPTED");
LoreBook:SetScript("OnEvent", function(self, event, ...)
if event == "LORE_TEXT_UPDATED_CAMPAIGN" then
local campaignID, textEntries = ...;
TEXTENRY = textEntries
DataProvider:UpdateEntries(textEntries);
elseif event == "PLAYER_ENTERING_WORLD" then
self:UnregisterEvent("PLAYER_ENTERING_WORLD");
DataProvider:Initialize();
elseif event == "QUEST_TURNED_IN" then
local questID = ...;
if questID and C_CampaignInfo.IsCampaignQuest(questID) then
--print("QuestID: "..questID)
After(0.5, function()
local campaignID = C_CampaignInfo.GetCampaignID(questID);
DataProvider:RequestLoreText(campaignID)
end)
end
end
--print(event)
end);
local AssetPool = {};
function AssetPool:GetObject(parentFrame)
if not self.pool then
self.pool = {};
end
for i = 1, #self.pool do
if not self.pool[i]:IsShown() then
self.pool[i]:SetParent(parentFrame);
self.pool[i]:Show();
return self.pool[i];
end
end
local newObject = parentFrame:CreateFontString(nil, "OVERLAY", self.template, 0);
tinsert(self.pool, newObject);
return newObject;
end
function AssetPool:Recycle()
if self.pool then
for i = 1, #self.pool do
if self.pool[i].unused then
self.pool[i]:Hide();
self.pool[i]:ClearAllPoints();
end
end
end
end
function AssetPool:ReleaseAll()
if self.pool then
for i = 1, #self.pool do
self.pool[i]:Hide();
self.pool[i]:ClearAllPoints();
end
end
end
local HeaderPool = CreateFromMixins(AssetPool);
HeaderPool.template = "NarciLoreBookHeaderTemplate";
local TextPool = CreateFromMixins(AssetPool);
TextPool.template = "NarciLoreBookTextTemplate";
local AnimPage = NarciAPI_CreateAnimationFrame(0.5);
AnimPage:SetScript("OnUpdate", function(self, elapsed)
self.total = self.total + elapsed;
local x = self.easeFunc(self.total, self.fromX, self.toX, self.duration);
local width = self.easeFunc(self.total, 342, 0.01, self.duration);
local ratio = self.total/self.duration;
local alpha1 = 2 - 2*ratio;
local alpha2;
if ratio <= 0.5 then
alpha2 = ratio;
if alpha2 > 1 then
alpha2 = 1;
end
else
alpha2 = 1 - ratio;
if alpha2 < 0 then
alpha2 = 0;
end
end
if alpha1 > 1 then
alpha1 = 1;
elseif alpha1 < 0 then
alpha1 = 0;
end
if self.total >= self.duration then
x = self.toX;
alpha1 = 0;
self:Hide();
end
self.movingPage:SetPoint(self.point, self.relativeTo, self.relativePoint, x, 0);
self.movingPage:SetWidth(342 - width);
self.movingPage.ClipFrame.CurveShadow:SetAlpha(alpha1);
self.movingPage.RightShadow:SetAlpha(alpha2);
self.movingPage.LeftShadow:SetAlpha(alpha2);
self.topPage:SetWidth(width);
end);
function AnimPage:PlayPage(movingPage, topPage)
if self:IsShown() then
return
end
self.movingPage = movingPage;
self.topPage = topPage;
self.point, self.relativeTo, self.relativePoint = movingPage:GetPoint();
local isRightPage = movingPage.isRightPage;
if isRightPage then
self.duration = 0.4;
self.easeFunc = outSine;
self.fromX = -342;
self.toX = 342;
self.next = false;
else
self.duration = 0.5;
self.easeFunc = inOutSine;
self.fromX = 342;
self.toX = -342;
self.next = true;
end
self:Show();
end
local FormatUtil = {};
local strsub = strsub;
function FormatUtil:GetTruncatedText(fontString, text)
if fontString:IsTruncated() then
local x = fontString:GetRight();
local y = fontString:GetBottom();
local characterIndex, isInside = fontString:FindCharacterIndexAtCoordinate(x, y); --causing FPS drop, no solutions
local tempText = text or fontString:GetText();
fontString:SetText(strsub(tempText, 1, characterIndex - 1))
return strsub(tempText, characterIndex);
end
end
NarciLoreBookMixin = {};
function NarciLoreBookMixin:OnLoad()
MainFrame = self;
self.page = 1;
self:SetPadding(32);
self:ResetPageLevel(-1);
tinsert(UISpecialFrames, self:GetName());
end
function NarciLoreBookMixin:SetPadding(value)
self.padding = value;
self.textWidth = 342 - 2 * value;
end
function NarciLoreBookMixin:OnMouseWheel(delta)
--Pause update during page turning
if AnimPage:IsShown() then
return
end
if delta < 0 then
if self.page < self.numChapters then
self.page = self.page + 1;
else
return
end
else
if self.page > 1 then
self.page = self.page - 1;
else
return
end
end
self:FlipPage(delta);
end
local function SetMirrorAnchor(frame, mirrorMode)
local frameWitdh = frame:GetWidth();
if not frameWitdh then return end
local point, relativeTo, relativePoint, x, y = frame:GetPoint();
frame:ClearAllPoints();
if frame.isRightPage then
if mirrorMode then
frame:SetPoint("RIGHT", relativeTo, relativePoint, 342, y);
frame.anchorToRight = false;
else
frame:SetPoint("LEFT", relativeTo, relativePoint, 0, y);
frame.anchorToRight = true;
end
else
if mirrorMode then
frame:SetPoint("LEFT", relativeTo, relativePoint, -342, y);
frame.anchorToRight = false;
else
frame:SetPoint("RIGHT", relativeTo, relativePoint, 0, y);
frame.anchorToRight = true;
end
end
end
function NarciLoreBookMixin:ResetPageLevel(direction)
local baseLevel = self:GetFrameLevel();
local topPageRight, topPageLeft, bottomPageRight, bottomPageLeft;
if self.page % 2 == 0 then
--even number ~ full width 342 & lower level
topPageRight = self.PageContainer.RightPage1;
bottomPageRight = self.PageContainer.RightPage2;
topPageLeft = self.PageContainer.LeftPage1;
bottomPageLeft = self.PageContainer.LeftPage2;
else
topPageRight = self.PageContainer.RightPage2;
bottomPageRight = self.PageContainer.RightPage1;
topPageLeft = self.PageContainer.LeftPage2;
bottomPageLeft = self.PageContainer.LeftPage1;
end
if not direction or direction < 0 then
topPageRight:SetFrameLevel(baseLevel + 2);
bottomPageRight:SetFrameLevel(baseLevel + 1);
topPageLeft:SetFrameLevel(baseLevel + 4);
bottomPageLeft:SetFrameLevel(baseLevel + 3);
SetMirrorAnchor(topPageRight, false);
SetMirrorAnchor(bottomPageRight, true);
SetMirrorAnchor(bottomPageLeft, false);
SetMirrorAnchor(topPageLeft, true);
self:SetTextAnchorToRight(topPageRight, false);
self:SetTextAnchorToRight(bottomPageRight, false);
else
topPageRight:SetFrameLevel(baseLevel + 4);
bottomPageRight:SetFrameLevel(baseLevel + 3);
topPageLeft:SetFrameLevel(baseLevel + 2);
bottomPageLeft:SetFrameLevel(baseLevel + 1);
bottomPageLeft:SetFrameLevel(baseLevel + 3);
SetMirrorAnchor(topPageRight, true);
SetMirrorAnchor(bottomPageRight, false);
SetMirrorAnchor(bottomPageLeft, true);
SetMirrorAnchor(topPageLeft, false);
self:SetTextAnchorToRight(topPageRight, true);
self:SetTextAnchorToRight(bottomPageLeft, true);
end
topPageRight:SetWidth(342);
bottomPageRight:SetWidth(342);
topPageLeft:SetWidth(342);
bottomPageLeft:SetWidth(342);
return topPageRight, topPageLeft, bottomPageRight, bottomPageLeft
end
function NarciLoreBookMixin:FormatExtraText(pageFrame, loreText)
if loreText then
local frame = pageFrame.ClipFrame --self.PageContainer[pageKey].ClipFrame;
frame.Header:Hide();
local Lore = frame.Lore; --TextPool:GetObject(frame);
Lore:SetPoint("TOPLEFT", frame, "TOPLEFT", self.padding, -self.padding);
Lore:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", self.padding, self.padding);
Lore:SetWidth(self.textWidth);
Lore:SetText(loreText);
end
end
function NarciLoreBookMixin:SetTextAnchorToRight(pageFrame, anchorToRight)
local frame = pageFrame.ClipFrame;
local Header = frame.Header;
local Lore = frame.Lore;
local textHeight = Header:GetHeight() + 24;
Header:ClearAllPoints();
Lore:ClearAllPoints();
pageFrame.anchorToRight = anchorToRight;
if anchorToRight then
Header:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -self.padding, -self.padding);
Lore:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -self.padding, -self.padding - textHeight);
Lore:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -self.padding, self.padding);
else
Header:SetPoint("TOPLEFT", frame, "TOPLEFT", self.padding, -self.padding);
Lore:SetPoint("TOPLEFT", frame, "TOPLEFT", self.padding, -self.padding - textHeight);
Lore:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", self.padding, self.padding);
end
end
function NarciLoreBookMixin:FormatPage(pageIndex, pageFrame, getTextOnTheNextPage)
if not pageFrame then return end
local headerText, contents = DataProvider:GetChapterTexts(pageIndex);
local frame = pageFrame.ClipFrame --self.PageContainer[pageKey].ClipFrame;
local Header = frame.Header; --HeaderPool:GetObject(frame);
local Lore = frame.Lore;
if contents then
local textHeight = 0;
--print(headerText)
Header:ClearAllPoints();
local anchorToRight = pageFrame.anchorToRight;
if anchorToRight then
Header:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -self.padding, -self.padding);
else
Header:SetPoint("TOPLEFT", frame, "TOPLEFT", self.padding, -self.padding);
end
Header:SetWidth(self.textWidth);
Header:SetText(headerText);
textHeight = textHeight + Header:GetHeight();
textHeight = textHeight + 24;
local loreText = contents[1].text or "";
for i = 2, #contents do
if contents[i].text then
loreText = loreText.."\n\n"..contents[i].text;
end
end
Lore:ClearAllPoints();
if anchorToRight then
Lore:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -self.padding, -self.padding - textHeight);
Lore:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -self.padding, self.padding);
else
Lore:SetPoint("TOPLEFT", frame, "TOPLEFT", self.padding, -self.padding - textHeight);
Lore:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", self.padding, self.padding);
end
Lore:SetWidth(self.textWidth);
Lore:SetText(loreText);
if getTextOnTheNextPage then
self.nextPageText = FormatUtil:GetTruncatedText(Lore, loreText);
end
--Debug
LORE = Lore;
self.LoreObject = Lore;
else
Header:SetText("");
Lore:SetText("")
end
end
function NarciLoreBookMixin:FlipPage(direction)
--HeaderPool:ReleaseAll();
--TextPool:ReleaseAll();
--self:FormatPage(self.page - 1, "RightPage2");
local page = self.page;
local topPageRight, topPageLeft, bottomPageRight, bottomPageLeft = self:ResetPageLevel(direction);
--self:FormatExtraText(bottomPageLeft, self.nextPageText);
self.nextPageText = nil;
--self.PageContainer.LeftPage1.ClipFrame.Picture:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\LoreBook\\Picture"..page);
--self.PageContainer.LeftPage2.ClipFrame.Picture:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\LoreBook\\Picture"..(page + 1));
if direction < 0 then
--Next page, move right page to the left
self:FormatPage(page, bottomPageRight, true);
if direction ~= self.direction then
self:FormatPage(page - 1, topPageRight, true);
self.direction = direction;
end
AnimPage:PlayPage(topPageLeft, topPageRight);
else
--Previous page, move left page to the right
self:FormatPage(page, topPageRight, true);
if direction ~= self.direction then
self:FormatPage(page + 1, bottomPageRight, true);
self.direction = direction;
end
AnimPage:PlayPage(topPageRight, topPageLeft);
end
end
function NarciLoreBookMixin:ShowPage(pageIndex, showFrame)
self.page = pageIndex;
local topPageRight, topPageLeft, bottomPageRight, bottomPageLeft = self:ResetPageLevel(-1);
topPageRight:SetWidth(0.01);
self.direction = nil;
self:FormatPage(self.page, bottomPageRight, true);
self:SetAlpha(1);
if showFrame then
self:Show();
end
end
function NarciLoreBookMixin:GetScaledCursorPosition()
local scale = self:GetEffectiveScale();
local x, y = GetCursorPosition();
return x / scale, y / scale;
end
function NarciLoreBookMixin:OnMouseDown()
--FormatUtil:GetTruncatedText(self.LoreObject)
--print(strsub(self.LoreObject:GetText(), characterIndex))
end
NarciLoreAlertMixin = {};
function NarciLoreAlertMixin:OnLoad()
--tinsert(UISpecialFrames, self:GetName());
end
function NarciLoreAlertMixin:OnHide()
end
function NarciLoreAlertMixin:OnClick()
self:Hide();
MainFrame:ShowPage(self.pageIndex, true);
end
function NarciLoreAlertMixin:SetUp(headerText, id)
self:StopAnimating();
self.Name:SetText(headerText);
self.pageIndex = id;
self:Show();
self.fadeIn:Play();
end
--[[
NarciLoreBookModelSceneMixin = CreateFromMixins(PanningModelSceneMixin);
NarciLoreBookMixin = {};
function NarciLoreBookMixin:OnShow()
self.ModelScene:TransitionToModelSceneID(290, CAMERA_TRANSITION_TYPE_IMMEDIATE, CAMERA_MODIFICATION_TYPE_DISCARD, true);
local sheatheWeapons = true;
local autoDress = false;
local itemModifiedAppearanceIDs = nil;
SetupPlayerForModelScene(self.ModelScene, itemModifiedAppearanceIDs, sheatheWeapons, autoDress);
local actor = self.ModelScene:GetPlayerActor();
actor:SetSpellVisualKit(29521);
actor:SetAnimation(520);
ACTOR = actor
CAM = self.ModelScene:GetActiveCamera();
CAM.buttonModes.leftY = 2;
end
--]]