HOWTO: Use Earth to create a QuestLog/Part 2
From WoWWiki
Continuation from HOWTO: Use Earth to create a QuestLog.
Contents |
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.
- 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
Abandon and Share
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.
