1 --[[QuestHelper.debug_objectives =
3 ["Harbinger of Doom"] =
5 cat="quest", what="Harbinger of Doom", sub=
7 ["Slay Harbinger Skyriss"] =
9 cat="monster", what="Harbinger Skyriss"
15 function QuestHelper
:LoadDebugObjective(name
, data
)
16 local obj
= self
:GetObjective(data
.cat
, data
.what
)
18 self
:SetObjectivePriority(obj
, 3)
19 self
:AddObjectiveWatch(obj
, name
)
22 for name
, sdata
in pairs(data
.sub
) do
23 self
:ObjectiveObjectDependsOn(obj
, QuestHelper
:LoadDebugObjective(name
, sdata
))
30 local ITEM_PATTERN
, REPUTATION_PATTERN
, MONSTER_PATTERN
, OBJECT_PATTERN
= false, false, false, false
32 local function buildPatterns()
33 if not ITEM_PATTERN
then
34 ITEM_PATTERN
= QuestHelper
:convertPattern(QUEST_OBJECTS_FOUND
)
35 REPUTATION_PATTERN
= QuestHelper
:convertPattern(QUEST_FACTION_NEEDED
)
36 MONSTER_PATTERN
= QuestHelper
:convertPattern(QUEST_MONSTERS_KILLED
)
37 OBJECT_PATTERN
= QuestHelper
:convertPattern(QUEST_OBJECTS_FOUND
)
42 function QuestHelper
:GetQuestLogObjective(quest_index
, objective_index
)
43 local text
, category
, done
= GetQuestLogLeaderBoard(objective_index
, quest_index
)
47 local wanted
, verb
, have
, need
49 if category
== "monster" then
50 wanted
, have
, need
= MONSTER_PATTERN(text
)
51 verb
= QHText("SLAY_VERB")
52 elseif category
== "item" then
53 wanted
, have
, need
= ITEM_PATTERN(text
)
54 verb
= QHText("ACQUIRE_VERB")
55 elseif category
== "reputation" then
56 wanted
, have
, need
= REPUTATION_PATTERN(text
)
57 elseif category
== "object" then
58 wanted
, have
, need
= OBJECT_PATTERN(text
)
59 elseif category
== "event" then
60 wanted
, have
, need
= text
, 0, 1
62 QuestHelper
:TextOut("Unhandled event type: "..category
)
68 _
, _
, wanted
, have
, need
= string.find(text
, "^%s*(.-)%s*:%s*(.-)%s*/%s*(.-)%s*$")
70 _
, _
, wanted
= string.find("^%s*(.-)%s*$")
75 if not need
then need
= 1 end
76 if done
then have
= need
end
78 return category
, verb
, wanted
or text
, tonumber(have
) or have
, tonumber(need
) or need
81 function QuestHelper
:FixedGetQuestLogTitle(index
)
82 local title
, level
, qtype
, players
, header
, collapsed
, status
, daily
= GetQuestLogTitle(index
)
84 if title
and level
then
85 local _
, _
, real_title
= string.find(title
, "^%["..level
.."[^%s]-%]%s?(.+)$")
86 title
= real_title
or title
89 return title
, level
, qtype
, players
, header
, collapsed
, status
, daily
92 function QuestHelper
:GetQuestLevel(quest_name
)
95 local title
, level
= self
:FixedGetQuestLogTitle(index
)
96 if not title
then return 0 end
97 if title
== quest_name
then
98 local original_entry
= GetQuestLogSelection()
99 SelectQuestLogEntry(index
)
100 local hash
= self
:HashString(select(2, GetQuestLogQuestText()))
101 SelectQuestLogEntry(original_entry
)
108 function QuestHelper
:ItemIsForQuest(item_object
, item_name
)
109 if not item_object
.o
.quest
then
112 for quest
, lq
in pairs(self
.quest_log
) do
114 for i
, lo
in ipairs(lq
.goal
) do
115 if lo
.category
== "item" and lo
.wanted
== item_name
then
125 local first_time
= true
127 function QuestHelper
:ScanQuestLog()
128 local original_entry
= GetQuestLogSelection()
129 local quests
= self
.quest_log
131 local party_levels
= self
.party_levels
132 if not party_levels
then
134 self
.party_levels
= party_levels
137 local level_average
= UnitLevel("player")
140 if not QuestHelper_Pref
.solo
then
142 local level
= UnitLevel("party"..n
)
144 if level
and level
> 0 then
145 level_average
= level_average
+ level
151 level_average
= level_average
/ users
154 party_levels
[n
] = level_average
+15-15*math
.pow(n
/users
, 0.4)
157 for i
, quest
in pairs(quests
) do
158 -- Will set this to false if the player still has it.
164 local title
, level
, qtype
, players
, header
, collapsed
, status
, daily
= self
:FixedGetQuestLogTitle(index
)
166 if not title
then break end
168 if players
and players
<= 0 then
173 players
= qtype
== nil and 1 or 5
175 players
= math
.min(5, math
.max(1, players
))
179 SelectQuestLogEntry(index
)
180 local hash
= self
:HashString(select(2, GetQuestLogQuestText()))
181 local quest
= self
:GetQuest(title
, level
, hash
)
182 local lq
= quests
[quest
]
185 local ignored
= party_levels
[players
]+QuestHelper_Pref
.level
< level
187 if self
.quest_giver
and self
.quest_giver
[title
] then
188 quest
.o
.start
= self
.quest_giver
[title
]
189 self
.quest_giver
[title
] = nil
197 if GetQuestLogTimeLeft() then
198 -- Quest has a timer, so give it a higher than normal priority.
199 self
:SetObjectivePriority(quest
, 2)
201 -- Use a normal priority.
202 self
:SetObjectivePriority(quest
, 3)
206 quest
.o
.id
= self
:GetQuestID(index
)
208 -- Can't add the objective here, if we don't have it depend on the objectives
209 -- first it'll get added and possibly not be doable.
210 -- We'll add it after the objectives are determined.
216 if GetNumQuestLeaderBoards(index
) > 0 then
217 if not lq
.goal
then lq
.goal
= {} end
218 for objective
= 1, GetNumQuestLeaderBoards(index
) do
219 local lo
= lq
.goal
[objective
]
220 if not lo
then lo
= {} lq
.goal
[objective
] = lo
end
221 local category
, verb
, wanted
, have
, need
= self
:GetQuestLogObjective(index
, objective
)
223 if not wanted
or not string.find(wanted
, "[^%s]") then
224 self
.defered_quest_scan
= true
225 elseif not lo
.objective
then
227 lo
.objective
= self
:GetObjective(category
, wanted
)
228 lo
.objective
.o
.quest
= true -- If I ever decide to prune the DB, I'll have the stuff actually used in quests marked.
229 self
:ObjectiveObjectDependsOn(quest
, lo
.objective
)
231 if category
== "item" then
232 -- So the objective knows in what context we're getting the item.
233 lo
.objective
.quest
= quest
237 lo
.reason
= QHFormat("OBJECTIVE_REASON", verb
, wanted
, title
)
239 lo
.reason
= QHFormat("OBJECTIVE_REASON_FALLBACK", wanted
, title
)
242 lo
.category
= category
247 QuestHelper
:SetObjectiveProgress(lo
.objective
, UnitName("player"), have
, need
)
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 QuestHelper
:SetObjectiveProgress(lo
.objective
, UnitName("player"), have
, need
)
256 if lo
.objective
.peer
then
257 for u
, l
in pairs(lo
.objective
.peer
) do
258 -- Peers don't know about our progress.
259 lo
.objective
.peer
[u
] = math
.min(l
, 2)
263 if have
== need
or (type(have
) == "number" and have
> lo
.have
) then
264 if category
== "item" then
265 self
:AppendItemObjectivePosition(lo
.objective
, wanted
, self
:PlayerPosition())
267 self
:AppendObjectivePosition(lo
.objective
, self
:PlayerPosition())
271 if lo
.have
== need
then -- The objective was done, but now its not.
273 self
:AddObjectiveWatch(lo
.objective
, lo
.reason
)
274 elseif have
== need
then -- The objective is now finished.
275 lo
.objective
:Unshare()
276 self
:RemoveObjectiveWatch(lo
.objective
, lo
.reason
)
282 if lo
.objective
then -- Might not have loaded the objective yet, if it wasn't in the local cache and we defered loading it.
283 lo
.objective
.filter_level
= ignored
284 lo
.objective
.filter_done
= true
285 lo
.objective
.filter_blocked
= not lo
.objective
:CouldBeFirst()
293 lq
.reason
= QHFormat("OBJECTIVE_REASON_TURNIN", title
)
295 self
:AddObjectiveWatch(quest
, lq
.reason
)
298 -- Note whether the quest turn-in objective is blocked (i.e. quest not complete)
299 quest
.filter_blocked
= not quest
:CouldBeFirst()
304 for quest
, lq
in pairs(quests
) do
307 for i
, lo
in ipairs(lq
.goal
) do
308 if lo
.objective
and lo
.have
~= lo
.need
then
309 QuestHelper
:SetObjectiveProgress(lo
.objective
, UnitName("player"), nil, nil)
311 lo
.objective
:Unshare()
312 self
:RemoveObjectiveWatch(lo
.objective
, lo
.reason
)
318 self
:RemoveObjectiveWatch(quest
, lq
.reason
)
325 self
:ForceRouteUpdate(3)
328 SelectQuestLogEntry(original_entry
)