try to track this thing down better
[QuestHelper.git] / questlog.lua
blob7a14635d438173413c0883cbbd794317e4e4f9a5
1 QuestHelper_File["questlog.lua"] = "Development Version"
2 QuestHelper_Loadtime["questlog.lua"] = GetTime()
4 do return end -- pretty sure this is all dead
6 --[[QuestHelper.debug_objectives =
8 ["Harbinger of Doom"] =
10 cat="quest", what="Harbinger of Doom", sub=
12 ["Slay Harbinger Skyriss"] =
14 cat="monster", what="Harbinger Skyriss"
18 }]]
20 function QuestHelper:LoadDebugObjective(name, data)
21 local obj = self:GetObjective(data.cat, data.what)
23 self:SetObjectivePriority(obj, 3)
24 self:AddObjectiveWatch(obj, name)
26 if data.sub then
27 for name, sdata in pairs(data.sub) do
28 self:ObjectiveObjectDependsOn(obj, QuestHelper:LoadDebugObjective(name, sdata))
29 end
30 end
32 return obj
33 end
35 local ITEM_PATTERN, REPUTATION_PATTERN, MONSTER_PATTERN, OBJECT_PATTERN = false, false, false, false
37 local function buildPatterns()
38 if not ITEM_PATTERN then
39 ITEM_PATTERN = QuestHelper:convertPattern(QUEST_OBJECTS_FOUND)
40 REPUTATION_PATTERN = QuestHelper:convertPattern(QUEST_FACTION_NEEDED)
41 MONSTER_PATTERN = QuestHelper:convertPattern(QUEST_MONSTERS_KILLED)
42 OBJECT_PATTERN = QuestHelper:convertPattern(QUEST_OBJECTS_FOUND)
43 PLAYER_PATTERN = QuestHelper:convertPattern(QUEST_PLAYERS_KILLED)
44 replacePattern = nil
45 end
46 end
48 function QuestHelper:GetQuestLogObjective(quest_index, objective_index)
49 local text, category, done = GetQuestLogLeaderBoard(objective_index, quest_index)
51 buildPatterns()
53 local wanted, verb, have, need
55 if category == "monster" then
56 wanted, have, need = MONSTER_PATTERN(text)
57 verb = QHText("SLAY_VERB")
58 elseif category == "item" then
59 wanted, have, need = ITEM_PATTERN(text)
60 verb = QHText("ACQUIRE_VERB")
61 elseif category == "reputation" then
62 wanted, have, need = REPUTATION_PATTERN(text)
63 elseif category == "object" then
64 wanted, have, need = OBJECT_PATTERN(text)
65 elseif category == "event" then
66 wanted, have, need = text, 0, 1
67 elseif category == "player" then
68 wanted, have, need = PLAYER_PATTERN(text)
69 else
70 QuestHelper:TextOut("Unhandled event type: "..category)
71 end
73 if not wanted then
74 verb = nil
76 _, _, wanted, have, need = string.find(text, "^%s*(.-)%s*:%s*(.-)%s*/%s*(.-)%s*$")
77 if not wanted then
78 _, _, wanted = string.find(text, "^%s*(.-)%s*$")
79 have, need = 0, 1
80 end
81 end
83 if not need then need = 1 end
84 if done then have = need end
86 return category, verb, wanted or text, tonumber(have) or have, tonumber(need) or need
87 end
89 function QuestHelper:FixedGetQuestLogTitle(index)
90 local title, level, qtype, players, header, collapsed, status, daily = GetQuestLogTitle(index)
92 if title and level then
93 local _, _, real_title = string.find(title, "^%["..level.."[^%s]-%]%s?(.+)$")
94 title = real_title or title
95 end
97 return title, level, qtype, players, header, collapsed, status, daily
98 end
100 function QuestHelper:GetQuestLevel(quest_name)
101 local index = 1
102 while true do
103 local title, level, _, _, header = self:FixedGetQuestLogTitle(index)
104 if not title then return 0 end
105 if not header and title == quest_name then
106 local original_entry = GetQuestLogSelection()
107 SelectQuestLogEntry(index)
108 local hash = self:HashString(select(2, GetQuestLogQuestText()))
109 SelectQuestLogEntry(original_entry)
110 return level, hash
112 index = index + 1
116 function QuestHelper:ItemIsForQuest(item_object, item_name)
117 if not item_object.o.quest then
118 return nil
119 else
120 for quest, lq in pairs(self.quest_log) do
121 if lq.goal then
122 for i, lo in ipairs(lq.goal) do
123 if lo.category == "item" and lo.wanted == item_name then
124 return quest
130 return nil
133 local first_time = true
135 function QuestHelper:ScanQuestLog()
136 local original_entry = GetQuestLogSelection()
137 local quests = self.quest_log
139 local party_levels = self.party_levels
140 if not party_levels then
141 party_levels = {}
142 self.party_levels = party_levels
145 local level_average = UnitLevel("player")
146 local users = 1
148 if not QuestHelper_Pref.solo then
149 for n=1,4 do
150 local level = UnitLevel("party"..n)
152 if level and level > 0 then
153 level_average = level_average + level
154 users = users + 1
159 level_average = level_average / users
161 for n = 1,5 do
162 party_levels[n] = level_average+15-15*math.pow(n/users, 0.4)
165 for i, quest in pairs(quests) do
166 -- Will set this to false if the player still has it.
167 quest.removed = true
170 local index = 1
171 while true do
172 local title, level, qtype, players, header, collapsed, status, daily = self:FixedGetQuestLogTitle(index)
173 --QuestHelper:TextOut(string.format("Gathering quests - %s %s", tostring(title), tostring(level)))
175 if not title then break end
177 if players and players <= 0 then
178 players = nil
181 if not players then
182 players = qtype == nil and 1 or 5
183 else
184 players = math.min(5, math.max(1, players))
187 -- Quest was failed if status is -1.
188 if not header and status ~= -1 then
189 SelectQuestLogEntry(index)
190 local hash = self:HashString(select(2, GetQuestLogQuestText()))
191 local quest = self:GetQuest(title, level, hash)
192 local lq = quests[quest]
193 local is_new = false
195 local ignored = party_levels[players]+QuestHelper_Pref.level < level
197 if self.quest_giver and self.quest_giver[title] then
198 quest.o.start = self.quest_giver[title]
199 self.quest_giver[title] = nil
202 if not lq then
203 lq = {}
205 quests[quest] = lq
207 if GetQuestLogTimeLeft() then
208 -- Quest has a timer, so give it a higher than normal priority.
209 self:SetObjectivePriority(quest, 2)
210 else
211 -- Use a normal priority.
212 self:SetObjectivePriority(quest, 3)
216 quest.o.id = self:GetQuestID(index)
218 -- Can't add the objective here, if we don't have it depend on the objectives
219 -- first it'll get added and possibly not be doable.
220 -- We'll add it after the objectives are determined.
221 is_new = true
224 lq.index = index
225 quest.index = index -- guhhh
226 lq.removed = false
228 if GetNumQuestLeaderBoards(index) > 0 then
229 if not lq.goal then lq.goal = {} end
230 for objective = 1, GetNumQuestLeaderBoards(index) do
231 local lo = lq.goal[objective]
232 if not lo then lo = {} lq.goal[objective] = lo end
234 local category, verb, wanted, have, need = self:GetQuestLogObjective(index, objective)
236 if not wanted or not string.find(wanted, "[^%s]") then
237 self.defered_quest_scan = true
238 elseif not lo.objective then
239 -- objective is new.
240 lo.objective = self:GetObjective(category, wanted)
241 lo.objective.o.quest = true -- If I ever decide to prune the DB, I'll have the stuff actually used in quests marked.
242 self:ObjectiveObjectDependsOn(quest, lo.objective)
244 lo.objective.quest = quest
246 if verb then
247 lo.reason = QHFormat("OBJECTIVE_REASON", verb, wanted, title)
248 else
249 lo.reason = QHFormat("OBJECTIVE_REASON_FALLBACK", wanted, title)
252 lo.category = category
253 lo.wanted = wanted
254 lo.have = have
255 lo.need = need
257 if have ~= need then -- If the objective isn't complete, watch it.
258 lo.objective:Share()
259 self:AddObjectiveWatch(lo.objective, lo.reason)
261 elseif lo.have ~= have then
262 if lo.objective.peer then
263 for u, l in pairs(lo.objective.peer) do
264 -- Peers don't know about our progress.
265 lo.objective.peer[u] = math.min(l, 2)
269 if have == need or (type(have) == "number" and have > lo.have) then
270 if category == "item" then
271 self:AppendItemObjectivePosition(lo.objective, wanted, self:PlayerPosition())
272 else
273 self:AppendObjectivePosition(lo.objective, self:PlayerPosition())
277 if lo.have == need then -- The objective was done, but now its not.
278 lo.objective:Share()
279 self:AddObjectiveWatch(lo.objective, lo.reason)
280 elseif have == need then -- The objective is now finished.
281 lo.objective:Unshare()
282 self:RemoveObjectiveWatch(lo.objective, lo.reason)
285 lo.have = have
288 if lo.objective then -- Might not have loaded the objective yet, if it wasn't in the local cache and we defered loading it.
289 lo.objective.filter_level = ignored
290 lo.objective.filter_done = true
291 self:SetObjectiveProgress(lo.objective, UnitName("player"), have, need)
294 else
295 quest.goal = nil
298 if is_new then
299 lq.reason = QHFormat("OBJECTIVE_REASON_TURNIN", title)
300 quest:Share()
301 self:AddObjectiveWatch(quest, lq.reason)
304 index = index + 1
307 for quest, lq in pairs(quests) do
308 if lq.removed then
309 if lq.goal then
310 for i, lo in ipairs(lq.goal) do
311 if lo.objective and lo.have ~= lo.need then
312 lo.objective:Unshare()
313 self:RemoveObjectiveWatch(lo.objective, lo.reason)
316 self:SetObjectiveProgress(lo.objective, UnitName("player"), nil, nil)
320 quest:Unshare()
321 self:RemoveObjectiveWatch(quest, lq.reason)
322 quests[quest] = nil
326 if first_time then
327 first_time = false
328 QH_Timeslice_Bonus(15)
331 SelectQuestLogEntry(original_entry)
333 if QuestHelper_Pref.track then
334 self.tracker:update()