disable the flight stuff for now, we'll fix it after thanksgiving
[QuestHelper.git] / questlog.lua
blob17e9cffe5902e02e737f5a4ee418646e083d6e8f
1 QuestHelper_File["questlog.lua"] = "Development Version"
3 --[[QuestHelper.debug_objectives =
5 ["Harbinger of Doom"] =
7 cat="quest", what="Harbinger of Doom", sub=
9 ["Slay Harbinger Skyriss"] =
11 cat="monster", what="Harbinger Skyriss"
15 }]]
17 function QuestHelper:LoadDebugObjective(name, data)
18 local obj = self:GetObjective(data.cat, data.what)
20 self:SetObjectivePriority(obj, 3)
21 self:AddObjectiveWatch(obj, name)
23 if data.sub then
24 for name, sdata in pairs(data.sub) do
25 self:ObjectiveObjectDependsOn(obj, QuestHelper:LoadDebugObjective(name, sdata))
26 end
27 end
29 return obj
30 end
32 local ITEM_PATTERN, REPUTATION_PATTERN, MONSTER_PATTERN, OBJECT_PATTERN = false, false, false, false
34 local function buildPatterns()
35 if not ITEM_PATTERN then
36 ITEM_PATTERN = QuestHelper:convertPattern(QUEST_OBJECTS_FOUND)
37 REPUTATION_PATTERN = QuestHelper:convertPattern(QUEST_FACTION_NEEDED)
38 MONSTER_PATTERN = QuestHelper:convertPattern(QUEST_MONSTERS_KILLED)
39 OBJECT_PATTERN = QuestHelper:convertPattern(QUEST_OBJECTS_FOUND)
40 PLAYER_PATTERN = QuestHelper:convertPattern(QUEST_PLAYERS_KILLED)
41 replacePattern = nil
42 end
43 end
45 function QuestHelper:GetQuestLogObjective(quest_index, objective_index)
46 local text, category, done = GetQuestLogLeaderBoard(objective_index, quest_index)
48 buildPatterns()
50 local wanted, verb, have, need
52 if category == "monster" then
53 wanted, have, need = MONSTER_PATTERN(text)
54 verb = QHText("SLAY_VERB")
55 elseif category == "item" then
56 wanted, have, need = ITEM_PATTERN(text)
57 verb = QHText("ACQUIRE_VERB")
58 elseif category == "reputation" then
59 wanted, have, need = REPUTATION_PATTERN(text)
60 elseif category == "object" then
61 wanted, have, need = OBJECT_PATTERN(text)
62 elseif category == "event" then
63 wanted, have, need = text, 0, 1
64 elseif category == "player" then
65 wanted, have, need = PLAYER_PATTERN(text)
66 else
67 QuestHelper:TextOut("Unhandled event type: "..category)
68 end
70 if not wanted then
71 verb = nil
73 _, _, wanted, have, need = string.find(text, "^%s*(.-)%s*:%s*(.-)%s*/%s*(.-)%s*$")
74 if not wanted then
75 _, _, wanted = string.find("^%s*(.-)%s*$")
76 have, need = 0, 1
77 end
78 end
80 if not need then need = 1 end
81 if done then have = need end
83 return category, verb, wanted or text, tonumber(have) or have, tonumber(need) or need
84 end
86 function QuestHelper:FixedGetQuestLogTitle(index)
87 local title, level, qtype, players, header, collapsed, status, daily = GetQuestLogTitle(index)
89 if title and level then
90 local _, _, real_title = string.find(title, "^%["..level.."[^%s]-%]%s?(.+)$")
91 title = real_title or title
92 end
94 return title, level, qtype, players, header, collapsed, status, daily
95 end
97 function QuestHelper:GetQuestLevel(quest_name)
98 local index = 1
99 while true do
100 local title, level, _, _, header = self:FixedGetQuestLogTitle(index)
101 if not title then return 0 end
102 if not header and title == quest_name then
103 local original_entry = GetQuestLogSelection()
104 SelectQuestLogEntry(index)
105 local hash = self:HashString(select(2, GetQuestLogQuestText()))
106 SelectQuestLogEntry(original_entry)
107 return level, hash
109 index = index + 1
113 function QuestHelper:ItemIsForQuest(item_object, item_name)
114 if not item_object.o.quest then
115 return nil
116 else
117 for quest, lq in pairs(self.quest_log) do
118 if lq.goal then
119 for i, lo in ipairs(lq.goal) do
120 if lo.category == "item" and lo.wanted == item_name then
121 return quest
127 return nil
130 local first_time = true
132 function QuestHelper:ScanQuestLog()
133 local original_entry = GetQuestLogSelection()
134 local quests = self.quest_log
136 local party_levels = self.party_levels
137 if not party_levels then
138 party_levels = {}
139 self.party_levels = party_levels
142 local level_average = UnitLevel("player")
143 local users = 1
145 if not QuestHelper_Pref.solo then
146 for n=1,4 do
147 local level = UnitLevel("party"..n)
149 if level and level > 0 then
150 level_average = level_average + level
151 users = users + 1
156 level_average = level_average / users
158 for n = 1,5 do
159 party_levels[n] = level_average+15-15*math.pow(n/users, 0.4)
162 for i, quest in pairs(quests) do
163 -- Will set this to false if the player still has it.
164 quest.removed = true
167 local index = 1
168 while true do
169 local title, level, qtype, players, header, collapsed, status, daily = self:FixedGetQuestLogTitle(index)
171 if not title then break end
173 if players and players <= 0 then
174 players = nil
177 if not players then
178 players = qtype == nil and 1 or 5
179 else
180 players = math.min(5, math.max(1, players))
183 -- Quest was failed if status is -1.
184 if not header and status ~= -1 then
185 SelectQuestLogEntry(index)
186 local hash = self:HashString(select(2, GetQuestLogQuestText()))
187 local quest = self:GetQuest(title, level, hash)
188 local lq = quests[quest]
189 local is_new = false
191 local ignored = party_levels[players]+QuestHelper_Pref.level < level
193 if self.quest_giver and self.quest_giver[title] then
194 quest.o.start = self.quest_giver[title]
195 self.quest_giver[title] = nil
198 if not lq then
199 lq = {}
201 quests[quest] = lq
203 if GetQuestLogTimeLeft() then
204 -- Quest has a timer, so give it a higher than normal priority.
205 self:SetObjectivePriority(quest, 2)
206 else
207 -- Use a normal priority.
208 self:SetObjectivePriority(quest, 3)
212 quest.o.id = self:GetQuestID(index)
214 -- Can't add the objective here, if we don't have it depend on the objectives
215 -- first it'll get added and possibly not be doable.
216 -- We'll add it after the objectives are determined.
217 is_new = true
220 lq.index = index
221 lq.removed = false
223 if GetNumQuestLeaderBoards(index) > 0 then
224 if not lq.goal then lq.goal = {} end
225 for objective = 1, GetNumQuestLeaderBoards(index) do
226 local lo = lq.goal[objective]
227 if not lo then lo = {} lq.goal[objective] = lo end
229 local category, verb, wanted, have, need = self:GetQuestLogObjective(index, objective)
231 if not wanted or not string.find(wanted, "[^%s]") then
232 self.defered_quest_scan = true
233 elseif not lo.objective then
234 -- objective is new.
235 lo.objective = self:GetObjective(category, wanted)
236 lo.objective.o.quest = true -- If I ever decide to prune the DB, I'll have the stuff actually used in quests marked.
237 self:ObjectiveObjectDependsOn(quest, lo.objective)
239 lo.objective.quest = quest
241 if verb then
242 lo.reason = QHFormat("OBJECTIVE_REASON", verb, wanted, title)
243 else
244 lo.reason = QHFormat("OBJECTIVE_REASON_FALLBACK", wanted, title)
247 lo.category = category
248 lo.wanted = wanted
249 lo.have = have
250 lo.need = need
252 if have ~= need then -- If the objective isn't complete, watch it.
253 lo.objective:Share()
254 self:AddObjectiveWatch(lo.objective, lo.reason)
256 elseif lo.have ~= have then
257 if lo.objective.peer then
258 for u, l in pairs(lo.objective.peer) do
259 -- Peers don't know about our progress.
260 lo.objective.peer[u] = math.min(l, 2)
264 if have == need or (type(have) == "number" and have > lo.have) then
265 if category == "item" then
266 self:AppendItemObjectivePosition(lo.objective, wanted, self:PlayerPosition())
267 else
268 self:AppendObjectivePosition(lo.objective, self:PlayerPosition())
272 if lo.have == need then -- The objective was done, but now its not.
273 lo.objective:Share()
274 self:AddObjectiveWatch(lo.objective, lo.reason)
275 elseif have == need then -- The objective is now finished.
276 lo.objective:Unshare()
277 self:RemoveObjectiveWatch(lo.objective, lo.reason)
280 lo.have = have
283 if lo.objective then -- Might not have loaded the objective yet, if it wasn't in the local cache and we defered loading it.
284 lo.objective.filter_level = ignored
285 lo.objective.filter_done = true
286 self:SetObjectiveProgress(lo.objective, UnitName("player"), have, need)
289 else
290 quest.goal = nil
293 if is_new then
294 lq.reason = QHFormat("OBJECTIVE_REASON_TURNIN", title)
295 quest:Share()
296 self:AddObjectiveWatch(quest, lq.reason)
299 index = index + 1
302 for quest, lq in pairs(quests) do
303 if lq.removed then
304 if lq.goal then
305 for i, lo in ipairs(lq.goal) do
306 if lo.objective and lo.have ~= lo.need then
307 lo.objective:Unshare()
308 self:RemoveObjectiveWatch(lo.objective, lo.reason)
311 self:SetObjectiveProgress(lo.objective, UnitName("player"), nil, nil)
315 quest:Unshare()
316 self:RemoveObjectiveWatch(quest, lq.reason)
317 quests[quest] = nil
321 if first_time then
322 first_time = false
323 QH_Timeslice_Bonus(15)
326 SelectQuestLogEntry(original_entry)
328 if QuestHelper_Pref.track then
329 self.tracker:update()