Continuation from HOWTO: Use Earth to create a QuestLog.
Summary[]
The goal of this tutorial is to create a fancier quest log. Using the tools provided by Earth's Tree template, along with the functions available in Sea and Chronos, we've created a list of the quests with little trouble. Now we want to display the actual quest text.
- Tools Used:
- Coding Time: 30 minutes
- Tutorial Length: 2-3 hours
- Difficulty: 3/5
Making the Actual Quest Frame[]
Okay, so we have our QuestLog, with all the Quests inside of it. Now we need to make a quest log. This looks identical to the one in the normal game, so there's minimal screenshots. First, add the XML for the QuestLogFrame:
<Frame name="PartyQuestsLogFrame" inherits="EarthBookTemplate" hidden="true"> <Size> <AbsDimension x="384" y="492"/> </Size> <Anchors> <Anchor point="TOPLEFT"> <Offset> <AbsDimension x="320" y="0"/> </Offset> </Anchor> </Anchors> <Frames> <ScrollFrame name="PartyQuestsLogDetailScrollFrame" inherits="UIPanelScrollFrameTemplate"> <Anchors> <Anchor point="TOPLEFT"> <Offset> <AbsDimension x="27" y="-80"/> </Offset> </Anchor> </Anchors> <Size> <AbsDimension x="296" y="316"/> </Size> <ScrollChild> </ScrollChild> </ScrollFrame> </Frames> <Scripts> <OnLoad> PartyQuests_LogFrame_OnLoad(); </OnLoad> </Scripts> </Frame>
Now, inside the <ScrollChild> add:
<Frame name="PartyQuestsLog" inherits="EarthQuestLogTemplate"/>
This is the template we'll be using for the QuestLog.
Once this is done, we now add some code to actually collect the quest information, and return it as a table.
--Get Quest Information --
function PartyQuests_GetPlayerQuestInfo(questID)
if ( not Sea.wow.questLog.protectQuestLog() ) then
return false;
end
local questInfo = {};
local tooltip = GameTooltip;
-- Expand everything
ExpandQuestHeader(0);
-- Select it
SelectQuestLogEntry(questID);
questInfo.id = questID;
questInfo.title = GetQuestLogTitle(questID);
questInfo.failed = IsCurrentQuestFailed();
questInfo.description, questInfo.objectives = GetQuestLogQuestText();
questInfo.timer = GetQuestLogTimeLeft();
questInfo.objectives = {};
for i=1, GetNumQuestLeaderBoards(), 1 do
local item = {};
item.text, item.questType, item.finished = GetQuestLogLeaderBoard(i);
table.insert(questInfo.objectives, item);
end
if ( GetQuestLogRequiredMoney() > 0 ) then
questInfo.requiredMoney = GetQuestLogRequiredMoney();
end
questInfo.rewardMoney = GetQuestLogRewardMoney();
questInfo.rewards = {};
questInfo.choices = {};
for i=1, GetNumQuestLogChoices(), 1 do
local item = {};
item.name, item.texture, item.numItems, item.quality, item.isUsable = GetQuestLogChoiceInfo(i);
item.info = GetQuestLogItemLink("choice", i );
table.insert(questInfo.choices, item);
end
for i=1, GetNumQuestLogRewards(), 1 do
local item = {};
item.name, item.texture, item.numItems, item.quality, item.isUsable = GetQuestLogRewardInfo(i);
item.info = GetQuestLogItemLink("reward", i );
table.insert(questInfo.rewards, item);
end
if ( GetRewardSpell() ) then
questInfo.spellReward={};
questInfo.spellReward.texture, questInfo.spellReward.name = GetQuestLogRewardSpell();
end
-- Unprotect
Sea.wow.questLog.unprotectQuestLog();
return questInfo;
end
Now we actually change the onClick handler inside of PartyQuests_LoadGui to actually refer to a real function:
local eTree = PartyQuests_ConvertQuestTreeToEnhancedTree(tree, {onClick=PartyQuests_OnQuestClick});
Then we implement that function:
-- Open the specified quest log function PartyQuests_OnQuestClick(id) if ( id > GetNumQuestLogEntries() ) then else -- Show the frame here end end
Now, to show the actual quest, we first check to make sure the Quest it already has isn't the same as the one we're displaying.
-- Get the current log local activeLog = EarthQuestLog_GetQuest("PartyQuestsLog"); -- Update and display or hide if ( not activeLog or not (activeLog.id == id ) or not (getglobal("PartyQuestsLogFrame"):IsVisible()) ) then -- Load the quest and update EarthQuestLog_LoadQuest("PartyQuestsLog", questInfo); EarthQuestLog_Update("PartyQuestsLog"); -- Show the other frame ShowUIPanel(getglobal("PartyQuestsLogFrame")); else HideUIPanel(getglobal("PartyQuestsLogFrame")); end
[]
Next, we'll add a couple buttons: One for Abandon and one for Share.
<Button name="$parentAbandonButton" inherits="EarthPanelButtonTemplate" text="PARTYQUESTS_BUTTON_ABANDON_TEXT"> <Size> <AbsDimension x="80" y="21"/> </Size> <Anchors> <Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="BOTTOMLEFT"> <Offset> <AbsDimension x="17" y="74"/> </Offset> </Anchor> </Anchors> <Scripts> <OnLoad> PartyQuests_LogFrame_Abandon_OnLoad() </OnLoad> </Scripts> </Button>
And the code to abandon a quest:
--Log Frame Abandon Button --
function PartyQuests_LogFrame_Abandon_OnLoad()
this.onClick = PartyQuests_LogFrame_Abandon_OnClick;
end
function PartyQuests_LogFrame_Abandon_OnClick()
if ( not Sea.wow.questLog.protectQuestLog() ) then
return false;
end
-- Expand everything
ExpandQuestHeader(0);
if ( PartyQuestsLog.questInfo ) then
-- Select it
SelectQuestLogEntry(PartyQuestsLog.questInfo.id);
SetAbandonQuest();
StaticPopup_Show("ABANDON_QUEST", GetAbandonQuestName());
end
-- Unprotect
Sea.wow.questLog.unprotectQuestLog();
end
Next we add a Share button.
<Button name="$parentShareButton" inherits="EarthPanelButtonTemplate" text="PARTYQUESTS_BUTTON_SHARE_TEXT"> <Size> <AbsDimension x="80" y="21"/> </Size> <Anchors> <Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="BOTTOMLEFT"> <Offset> <AbsDimension x="97" y="74"/> </Offset> </Anchor> </Anchors> <Scripts> <OnLoad> PartyQuests_LogFrame_Share_OnLoad() </OnLoad> </Scripts> </Button>
And the code to share quests:
--Log Frame Share Button --
function PartyQuests_LogFrame_Share_OnLoad()
this.onClick = PartyQuests_LogFrame_Share_OnClick;
end
function PartyQuests_LogFrame_Share_OnClick()
if ( not Sea.wow.questLog.protectQuestLog() ) then
return false;
end
-- Expand everything
ExpandQuestHeader(0);
if ( PartyQuestsLog.questInfo ) then
-- Select it
SelectQuestLogEntry(PartyQuestsLog.questInfo.id);
QuestLogPushQuest();
end
-- Unprotect
Sea.wow.questLog.unprotectQuestLog();
end
Bonus Points[]
If you want to be extra-special, you can add an overlay to show the number of quests you have total. Put this inside the PartyQuestsLogFrame:
<Layers> <Layer level="OVERLAY"> <Texture name="$parentCountRight" file="Interface\Common\Common-Input-Border"> <Size> <AbsDimension x="8" y="20"/> </Size> <Anchors> <Anchor point="TOPRIGHT"> <Offset> <AbsDimension x="-47" y="-50"/> </Offset> </Anchor> </Anchors> <TexCoords left="0.9375" right="1.0" top="0" bottom="0.625"/> </Texture> <Texture name="$parentCountMiddle" file="Interface\Common\Common-Input-Border"> <Size> <AbsDimension x="80" y="20"/> </Size> <Anchors> <Anchor point="RIGHT" relativeTo="$parentCountRight" relativePoint="LEFT"/> </Anchors> <TexCoords left="0.0625" right="0.9375" top="0" bottom="0.625"/> </Texture> <Texture name="$parentCountLeft" file="Interface\Common\Common-Input-Border"> <Size> <AbsDimension x="8" y="20"/> </Size> <Anchors> <Anchor point="RIGHT" relativeTo="$parentCountMiddle" relativePoint="LEFT"/> </Anchors> <TexCoords left="0" right="0.0625" top="0" bottom="0.625"/> </Texture> <FontString name="$parentQuestCount" inherits="GameFontNormalSmall"> <Anchors> <Anchor point="RIGHT" relativeTo="$parentCountRight"> <Offset> <AbsDimension x="-6" y="0"/> </Offset> </Anchor> </Anchors> </FontString> </Layer> </Layers>
Then you add the following to make the quest numbers show up:
local questInfo = PartyQuests_GetPlayerQuestInfo(id); local numEntries, numQuests = GetNumQuestLogEntries(); -- Set the Number of quests: PartyQuestsLogFrameQuestCount:SetText(string.format(QUEST_LOG_COUNT_TEMPLATE, numQuests, MAX_QUESTLOG_QUESTS)); PartyQuestsLogFrameCountMiddle:SetWidth(PartyQuestsLogFrameQuestCount:GetWidth());
Wrap Up[]
Thats it. Its not hard, just a lot more work to obtain the quest information.