TourGuide
[WoW-TourGuide.git] / TourGuide.lua
blob2ea5a5ddbada006e7193e85a405cefe5fc156075
2 TourGuide = DongleStub("Dongle-1.0"):New("TourGuide")
4 TourGuide.icons = setmetatable({
5 ACCEPT = "Interface\\GossipFrame\\AvailableQuestIcon",
6 COMPLETE = "Interface\\Icons\\Ability_DualWield",
7 TURNIN = "Interface\\GossipFrame\\ActiveQuestIcon",
8 RUN = "Interface\\Icons\\Ability_Tracking",
9 MAP = "Interface\\Icons\\Ability_Spy",
10 FLY = "Interface\\Icons\\Ability_Druid_FlightForm",
11 TRAIN = "Interface\\GossipFrame\\trainerGossipIcon",
12 SETHEARTH = "Interface\\Icons\\Spell_Holy_ElunesGrace",
13 HEARTH = "Interface\\Icons\\INV_Misc_Rune_01",
14 NOTE = "Interface\\Icons\\INV_Misc_Note_01",
15 GRIND = "Interface\\Icons\\INV_Stone_GrindingStone_05",
16 ITEM = "Interface\\Icons\\INV_Misc_Bag_08",
17 BUY = "Interface\\Icons\\INV_Misc_Coin_01",
18 }, {__index = function() return "Interface\\Icons\\INV_Misc_QuestionMark" end})
21 local actiontypes = {
22 A = "ACCEPT",
23 C = "COMPLETE",
24 T = "TURNIN",
25 R = "RUN",
26 t = "TRAIN",
27 H = "HEARTH",
28 h = "SETHEARTH",
29 G = "GRIND",
30 I = "ITEM",
31 F = "FLY",
32 N = "NOTE",
33 B = "BUY",
37 function TourGuide:Initialize()
38 self.db = self:InitializeDB("TourGuideAlphaDB", {
39 char = {
40 turnedin = {},
41 cachedturnins = {},
44 self.turnedin = self.db.char.turnedin
45 self.cachedturnins = self.db.char.cachedturnins
46 end
49 function TourGuide:Enable()
50 for _,event in pairs(self.TrackEvents) do self:RegisterEvent(event) end
51 self.TrackEvents = nil
52 self:UpdateStatusFrame()
53 end
56 function TourGuide:GetQuestLogIndexByName(name)
57 name = name or self.quests[self.current]
58 for i=1,GetNumQuestLogEntries() do
59 if GetQuestLogTitle(i) == name then return i end
60 end
61 end
63 function TourGuide:GetQuestDetails(name)
64 local i = self:GetQuestLogIndexByName(name)
65 local complete = i and select(7, GetQuestLogTitle(i)) == 1
66 return i, complete
67 end
70 local function FindBagSlot(itemid)
71 for bag=0,4 do
72 for slot=1,GetContainerNumSlots(bag) do
73 local item = GetContainerItemLink(bag, slot)
74 if item and string.find(item, "item:"..itemid) then return bag, slot end
75 end
76 end
77 end
80 function TourGuide:GetCurrentObjectiveInfo()
81 return self:GetObjectiveInfo(self.current)
82 end
85 function TourGuide:GetObjectiveInfo(i)
86 local action, quest, note = self.actions[i], self.quests[i], self.notes[i]
87 if not action then return end
89 local logi, complete = self:GetQuestDetails(quest)
90 local hasitem = action == "ITEM" and self.questitems[i] and FindBagSlot(self.questitems[i])
92 return action, quest:gsub("@.*@", ""), note, logi, complete, hasitem, self.turnedin[quest], quest
93 end
96 local isdebugging = false
97 local titlematches = {"For", "A", "The", "Or", "In", "Then", "From", "Our"}
98 local accepts, turnins, completes = {}, {}, {}
99 local function ParseQuests(...)
100 local uniqueid = 1
101 local actions, notes, quests, items = {}, {}, {}, {}
103 for i=1,select("#", ...) do
104 local text = select(i, ...)
105 if text ~= "" then
106 local _, _, action, quest = text:find("^(%a) ([^|]*)")
107 local _, _, detailtype, detail = string.find(text, "|(.)|([^|]+)|?")
108 quest = quest:trim()
109 if not (action == "I" or action == "A" or action =="C" or action =="T") then
110 quest = quest.."@"..uniqueid.."@"
111 uniqueid = uniqueid + 1
114 actions[i], quests[i] = actiontypes[action], quest
115 if detailtype == "N" then notes[i] = detail end
116 if action == "I" then items[i] = select(3, string.find(text, "|I|(%d+)|")) end
118 -- Debuggery
119 if isdebugging and action == "A" then accepts[quest] = true
120 elseif isdebugging and action == "T" then turnins[quest] = true
121 elseif isdebugging and action == "C" then completes[quest] = true end
123 if isdebugging and (action == "A" or action == "C" or action == "T") then
124 -- Catch bad Title Case
125 for _,word in pairs(titlematches) do
126 if quest:find("[^:]%s"..word.."%s") or quest:find("[^:]%s"..word.."$") or quest:find("[^:]%s"..word.."@") then
127 TourGuide:PrintF("%s %s -- Contains bad title case", action, quest)
134 -- More debug
135 if isdebugging then
136 for quest in pairs(accepts) do if not turnins[quest] then TourGuide:PrintF("Quest has no 'turnin' objective: %s", quest) end end
137 for quest in pairs(turnins) do if not accepts[quest] then TourGuide:PrintF("Quest has no 'accept' objective: %s", quest) end end
138 for quest in pairs(completes) do if not accepts[quest] and not turnins[quest] then TourGuide:PrintF("Quest has no 'accept' and 'turnin' objectives: %s", quest) end end
141 return actions, notes, quests, items
145 function TourGuide:ParseObjectives(text, showdebug)
146 isdebugging = showdebug
147 self.actions, self.notes, self.quests, self.questitems = ParseQuests(string.split("\n", text))
151 function TourGuide:SetTurnedIn(i, value)
152 if not i then
153 i = self.current
154 value = true
157 self.turnedin[self.quests[i]] = value
158 self:UpdateStatusFrame()