Arrgh
[QuestHelper.git] / collect_achievement.lua
blob51fcdd8be2c9c717ce43f3b5b5ad41330e252209
1 QuestHelper_File["collect_achievement.lua"] = "Development Version"
2 QuestHelper_Loadtime["collect_achievement.lua"] = GetTime()
4 local QHCA
6 local GetLoc
7 local Merger
9 local AchievementDB
11 --X 0 is a monster kill, asset is the monster ID
12 --X 1 is winning PvP objectives in a thorough manner (holding all bases, controlling all flags)
13 --X 7 is weapon skill, asset is probably a skill ID of some sort
14 --X 8 is another achievement, asset is achievement ID
15 --X 9 is completing quests globally
16 --X 10 is completing a daily quest every day
17 --X 11 is completing quests in specific areas
18 --X 14 is completing daily quests
19 --X 27 is a quest, asset is quest ID
20 --X 28 is getting a spell cast on you, asset is a spell ID
21 --X 29 is casting a spell (often crafting), asset is a spell ID
22 --X 30 is PvP objectives (flags, assaulting, defending)
23 --X 31 is PvP kills in battleground PvP locations
24 --X 32 is winning ranked arena matches in specific locations (asset is probably a location ID)
25 --X 34 is the Squashling (owning a specific pet?), asset is the spell ID
26 --X 35 is PvP kills while under the influence of something
27 --X 36 is acquiring items (soulbound), asset is an item ID
28 --X 37 is winning arenas
29 --X 41 is eating or drinking a specific item, asset is item ID
30 --X 42 is fishing things up, asset is item ID
31 --X 43 is exploration, asset is a location ID?
32 --X 45 is purchasing 7 bank slots
33 --X 46 is exalted rep, asset is presumably some kind of faction ID
34 --X 47 is 5 reputations to exalted
35 --X 49 is equipping items, asset is a slot ID (quality is presumably encoded into flags)
36 --X 52 is killing specific classes of player
37 --X 53 is kill-a-given-race, asset is race ID?
38 -- 54 is using emotes on targets, asset ID is likely the emote ID
39 --X 56 is being a wrecking ball in Alterac Valley
40 --X 62 is getting gold from quest rewards
41 --X 67 is looting gold
42 -- 68 is reading books
43 -- 70 is killing players in world PvP locations
44 -- 72 is fishing things from schools or wreckage
45 --X 73 is killing Mal'Ganis on Heroic. Why? Who can say.
46 --X 75 is obtaining mounts
47 -- 109 is fishing, either in general or in specific locations
48 -- 110 is casting spells on specific targets, asset ID is the spell ID
49 --X 112 is learning cooking recipes
50 --X 113 is honorable kills
51 local achievement_type_blacklist = {}
52 for _, v in pairs({0, 1, 7, 8, 9, 10, 11, 14, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 41, 42, 46, 47, 49, 52, 53, 56, 62, 67, 73, 75, 112, 113}) do
53 achievement_type_blacklist[v] = true
54 end
56 local achievement_list = {}
58 --local crittypes = {}
59 --QuestHelper_ZorbaForgotToRemoveThis = {}
61 local qhdinfo = false
62 local qhdinfodump = {}
63 local function qhadumpy()
64 for k, v in pairs(qhdinfodump) do
65 local ct = 0
66 local some
67 for tk, tv in pairs(v) do
68 ct = ct + 1
69 some = tk
70 end
71 QuestHelper:TextOut(string.format("%d: %d, %s", k, ct, some))
72 end
73 end
75 local function registerAchievement(id)
76 --if db.achievements[id] then return end
78 local _, title, _, complete = GetAchievementInfo(id)
79 --QuestHelper:TextOut(string.format("Registering %d (%s)", id, title))
80 local prev = GetPreviousAchievement(id)
81 local record = false
83 --[[
84 db.achievements[id] = {
85 previous = prev,
86 compete = complete,
87 name = title,
88 criterialist = {}
90 local dbi = db.achievements[id]
93 if prev then
94 registerAchievement(prev)
95 end
97 local critcount = GetAchievementNumCriteria(id)
98 if critcount == 0 then record = true end
100 for i = 1, critcount do
101 local crit_name, crit_type, crit_complete, crit_quantity, crit_reqquantity, _, _, crit_asset, _, crit_id = GetAchievementCriteriaInfo(id, i)
103 if qhdinfo and not achievement_type_blacklist[crit_type] then
104 if not qhdinfodump[crit_type] then qhdinfodump[crit_type] = {} end
105 qhdinfodump[crit_type][title .. " --- " .. crit_name] = true
108 --[[
109 table.insert(dbi.criterialist, crit_id)
110 ass ert (not db.criteria[crit_id])
111 crittypes[crit_type] = (crittypes[crit_type] or 0) + 1]]
113 if not achievement_type_blacklist[crit_type] then record = true end
115 --[[
116 db.criteria[crit_id] = {
117 name = crit_name,
118 type = crit_type,
119 complete = crit_complete,
120 progress = crit_quantity,
121 progress_total = crit_reqquantity,
122 asset = crit_asset,
126 if record then achievement_list[id] = true end
129 function createAchievementList()
130 for _, catid in pairs(GetCategoryList()) do
131 for d = 1, GetCategoryNumAchievements(catid) do
132 registerAchievement(GetAchievementInfo(catid, d), db)
137 local achievement_stop_time = 0
139 local GetAchievementInfo = GetAchievementInfo
140 local GetAchievementNumCriteria = GetAchievementNumCriteria
141 local GetAchievementCriteriaInfo = GetAchievementCriteriaInfo
143 local function retrieveAchievement(id, db)
144 QH_Timeslice_Yield()
146 local _, _, _, complete = GetAchievementInfo(id)
147 --QuestHelper:TextOut(string.format("Registering %d (%s)", id, title))
149 db.achievements[id] = QuestHelper:CreateTable("collect_achievement achievement")
150 db.achievements[id].complete = complete
152 local dbi = db.achievements[id]
154 local critcount = GetAchievementNumCriteria(id)
156 --QuestHelper:TextOut(string.format("%d criteria", crit))
157 for i = 1, critcount do
158 QuestHelper: Assert(not db.criteria[crit_id])
159 local _, _, crit_complete, crit_quantity, crit_reqquantity, _, _, _, _, crit_id = GetAchievementCriteriaInfo(id, i)
161 db.criteria[crit_id] = QuestHelper:CreateTable("collect_achievement criteria")
162 db.criteria[crit_id].complete = crit_complete
163 db.criteria[crit_id].progress = crit_quantity
164 db.criteria[crit_id].parent = id
168 local function getAchievementDB()
169 local db = {}
170 db.achievements = {}
171 db.criteria = {}
173 local ct = 0
174 for k in pairs(achievement_list) do
175 retrieveAchievement(k, db)
176 ct = ct + 1
178 --QuestHelper: TextOut(tostring(ct))
180 return db
183 local updating = false
185 local function ScanAchievements()
186 local cloc = GetLoc() -- yoink
188 --QuestHelper:TextOut("Scanning")
189 local newADB = getAchievementDB()
190 --QuestHelper:TextOut("GADB done")
191 local oldADB = AchievementDB
193 local changes = 0
194 for k, v in pairs(newADB.achievements) do
195 if v.complete ~= oldADB.achievements[k].complete then
196 changes = changes + 1
199 for k, v in pairs(newADB.criteria) do
200 if v.complete and not oldADB.criteria[k].complete then
201 changes = changes + 1
205 if changes < 10 then -- if someone gets 10 criteria at once, well, I guess that's just what happens
206 for k, v in pairs(newADB.achievements) do
207 if v.complete ~= oldADB.achievements[k].complete then
208 QuestHelper: Assert(v.complete and not oldADB.achievements[k].complete)
209 if not QHCA[k] then QHCA[k] = {} end
210 QHCA[k].achieved = (QHCA[k].achieved or "") .. cloc
212 --QuestHelper:TextOut(string.format("Achievement complete, %s", select(2, GetAchievementInfo(k))))
216 for k, v in pairs(newADB.criteria) do
217 if v.complete and not oldADB.criteria[k].complete then -- Note that it's possible for objectives to be "uncompleted" when it's things like "do a bunch of shit in one run of this battleground" (see: isle of conquest)
218 --QuestHelper:TextOut(string.format("Criteria complete, %d", k))
219 --QuestHelper:TextOut(string.format("Criteria complete, %s", select(1, GetAchievementCriteriaInfo(k))))
220 if not QHCA[v.parent] then QHCA[v.parent] = {} end
221 QHCA[v.parent][k] = (QHCA[v.parent][k] or "") .. cloc
222 elseif v.progress > oldADB.criteria[k].progress then
223 --QuestHelper:TextOut(string.format("Criteria progress, %d", k))
224 --QuestHelper:TextOut(string.format("Criteria progress, %s", select(1, GetAchievementCriteriaInfo(k))))
229 AchievementDB = newADB
231 for k, v in pairs(oldADB.achievements) do QuestHelper:ReleaseTable(v) end
232 for k, v in pairs(oldADB.criteria) do QuestHelper:ReleaseTable(v) end
234 updating = false -- This prevents error spam.
235 --QuestHelper:TextOut("Done scan")
238 local function OnEvent()
239 if not updating and AchievementDB then
240 QH_Timeslice_Add(ScanAchievements, "criteria")
241 updating = true
244 --qhaach = OnEvent
246 function QH_Collect_Achievement_Init(QHCData, API)
247 if not QHCData.achievement then QHCData.achievement = {} end
248 QHCA = QHCData.achievement
250 createAchievementList()
251 AchievementDB = getAchievementDB() -- 'coz we're lazy
253 GetLoc = API.Callback_LocationBolusCurrent
254 QuestHelper: Assert(GetLoc)
256 Merger = API.Utility_Merger
257 QuestHelper: Assert(Merger)
259 QH_Event("CRITERIA_UPDATE", OnEvent)
260 QH_Event("ACHIEVEMENT_EARNED", OnEvent)
262 OnEvent() -- kick it into its first update cycle