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"
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
)
24 for name
, sdata
in pairs(data
.sub
) do
25 self
:ObjectiveObjectDependsOn(obj
, QuestHelper
:LoadDebugObjective(name
, sdata
))
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
)
44 function QuestHelper
:GetQuestLogObjective(quest_index
, objective_index
)
45 local text
, category
, done
= GetQuestLogLeaderBoard(objective_index
, quest_index
)
49 local wanted
, verb
, have
, need
51 if category
== "monster" then
52 wanted
, have
, need
= MONSTER_PATTERN(text
)
53 verb
= QHText("SLAY_VERB")
54 elseif category
== "item" then
55 wanted
, have
, need
= ITEM_PATTERN(text
)
56 verb
= QHText("ACQUIRE_VERB")
57 elseif category
== "reputation" then
58 wanted
, have
, need
= REPUTATION_PATTERN(text
)
59 elseif category
== "object" then
60 wanted
, have
, need
= OBJECT_PATTERN(text
)
61 elseif category
== "event" then
62 wanted
, have
, need
= text
, 0, 1
64 QuestHelper
:TextOut("Unhandled event type: "..category
)
70 _
, _
, wanted
, have
, need
= string.find(text
, "^%s*(.-)%s*:%s*(.-)%s*/%s*(.-)%s*$")
72 _
, _
, wanted
= string.find("^%s*(.-)%s*$")
77 if not need
then need
= 1 end
78 if done
then have
= need
end
80 return category
, verb
, wanted
or text
, tonumber(have
) or have
, tonumber(need
) or need
83 function QuestHelper
:FixedGetQuestLogTitle(index
)
84 local title
, level
, qtype
, players
, header
, collapsed
, status
, daily
= GetQuestLogTitle(index
)
86 if title
and level
then
87 local _
, _
, real_title
= string.find(title
, "^%["..level
.."[^%s]-%]%s?(.+)$")
88 title
= real_title
or title
91 return title
, level
, qtype
, players
, header
, collapsed
, status
, daily
94 function QuestHelper
:GetQuestLevel(quest_name
)
97 local title
, level
= self
:FixedGetQuestLogTitle(index
)
98 if not title
then return 0 end
99 if title
== quest_name
then
100 local original_entry
= GetQuestLogSelection()
101 SelectQuestLogEntry(index
)
102 local hash
= self
:HashString(select(2, GetQuestLogQuestText()))
103 SelectQuestLogEntry(original_entry
)
110 function QuestHelper
:ItemIsForQuest(item_object
, item_name
)
111 if not item_object
.o
.quest
then
114 for quest
, lq
in pairs(self
.quest_log
) do
116 for i
, lo
in ipairs(lq
.goal
) do
117 if lo
.category
== "item" and lo
.wanted
== item_name
then
127 local first_time
= true
129 function QuestHelper
:ScanQuestLog()
130 local original_entry
= GetQuestLogSelection()
131 local quests
= self
.quest_log
133 local party_levels
= self
.party_levels
134 if not party_levels
then
136 self
.party_levels
= party_levels
139 local level_average
= UnitLevel("player")
142 if not QuestHelper_Pref
.solo
then
144 local level
= UnitLevel("party"..n
)
146 if level
and level
> 0 then
147 level_average
= level_average
+ level
153 level_average
= level_average
/ users
156 party_levels
[n
] = level_average
+15-15*math
.pow(n
/users
, 0.4)
159 for i
, quest
in pairs(quests
) do
160 -- Will set this to false if the player still has it.
166 local title
, level
, qtype
, players
, header
, collapsed
, status
, daily
= self
:FixedGetQuestLogTitle(index
)
168 if not title
then break end
170 if players
and players
<= 0 then
175 players
= qtype
== nil and 1 or 5
177 players
= math
.min(5, math
.max(1, players
))
180 -- Quest was failed if status is -1.
181 if not header
and status
~= -1 then
182 SelectQuestLogEntry(index
)
183 local hash
= self
:HashString(select(2, GetQuestLogQuestText()))
184 local quest
= self
:GetQuest(title
, level
, hash
)
185 local lq
= quests
[quest
]
188 local ignored
= party_levels
[players
]+QuestHelper_Pref
.level
< level
190 if self
.quest_giver
and self
.quest_giver
[title
] then
191 quest
.o
.start
= self
.quest_giver
[title
]
192 self
.quest_giver
[title
] = nil
200 if GetQuestLogTimeLeft() then
201 -- Quest has a timer, so give it a higher than normal priority.
202 self
:SetObjectivePriority(quest
, 2)
204 -- Use a normal priority.
205 self
:SetObjectivePriority(quest
, 3)
209 quest
.o
.id
= self
:GetQuestID(index
)
211 -- Can't add the objective here, if we don't have it depend on the objectives
212 -- first it'll get added and possibly not be doable.
213 -- We'll add it after the objectives are determined.
220 if GetNumQuestLeaderBoards(index
) > 0 then
221 if not lq
.goal
then lq
.goal
= {} end
222 for objective
= 1, GetNumQuestLeaderBoards(index
) do
223 local lo
= lq
.goal
[objective
]
224 if not lo
then lo
= {} lq
.goal
[objective
] = lo
end
226 local category
, verb
, wanted
, have
, need
= self
:GetQuestLogObjective(index
, objective
)
228 if not wanted
or not string.find(wanted
, "[^%s]") then
229 self
.defered_quest_scan
= true
230 elseif not lo
.objective
then
232 lo
.objective
= self
:GetObjective(category
, wanted
)
233 lo
.objective
.o
.quest
= true -- If I ever decide to prune the DB, I'll have the stuff actually used in quests marked.
234 self
:ObjectiveObjectDependsOn(quest
, lo
.objective
)
236 lo
.objective
.quest
= quest
239 lo
.reason
= QHFormat("OBJECTIVE_REASON", verb
, wanted
, title
)
241 lo
.reason
= QHFormat("OBJECTIVE_REASON_FALLBACK", wanted
, title
)
244 lo
.category
= category
249 if have
~= need
then -- If the objective isn't complete, watch it.
251 self
:AddObjectiveWatch(lo
.objective
, lo
.reason
)
253 elseif lo
.have
~= have
then
254 if lo
.objective
.peer
then
255 for u
, l
in pairs(lo
.objective
.peer
) do
256 -- Peers don't know about our progress.
257 lo
.objective
.peer
[u
] = math
.min(l
, 2)
261 if have
== need
or (type(have
) == "number" and have
> lo
.have
) then
262 if category
== "item" then
263 self
:AppendItemObjectivePosition(lo
.objective
, wanted
, self
:PlayerPosition())
265 self
:AppendObjectivePosition(lo
.objective
, self
:PlayerPosition())
269 if lo
.have
== need
then -- The objective was done, but now its not.
271 self
:AddObjectiveWatch(lo
.objective
, lo
.reason
)
272 elseif have
== need
then -- The objective is now finished.
273 lo
.objective
:Unshare()
274 self
:RemoveObjectiveWatch(lo
.objective
, lo
.reason
)
280 if lo
.objective
then -- Might not have loaded the objective yet, if it wasn't in the local cache and we defered loading it.
281 lo
.objective
.filter_level
= ignored
282 lo
.objective
.filter_done
= true
283 self
:SetObjectiveProgress(lo
.objective
, UnitName("player"), have
, need
)
291 lq
.reason
= QHFormat("OBJECTIVE_REASON_TURNIN", title
)
293 self
:AddObjectiveWatch(quest
, lq
.reason
)
299 for quest
, lq
in pairs(quests
) do
302 for i
, lo
in ipairs(lq
.goal
) do
303 if lo
.objective
and lo
.have
~= lo
.need
then
304 lo
.objective
:Unshare()
305 self
:RemoveObjectiveWatch(lo
.objective
, lo
.reason
)
308 self
:SetObjectiveProgress(lo
.objective
, UnitName("player"), nil, nil)
313 self
:RemoveObjectiveWatch(quest
, lq
.reason
)
320 self
:ForceRouteUpdate(3)
323 SelectQuestLogEntry(original_entry
)
325 if QuestHelper_Pref
.track
then
326 self
.tracker
:update()