whups
[QuestHelper.git] / graph_flightpath.lua
blob6eed6ddded37709d15f876f5fc20e17eb73b16da
1 QuestHelper_File["graph_flightpath.lua"] = "Development Version"
2 QuestHelper_Loadtime["graph_flightpath.lua"] = GetTime()
4 -- Name to Name, gives {time, accurate}
5 QH_Flight_Distances = {}
7 function QH_redo_flightpath()
8 QuestHelper: Assert(DB_Ready())
10 local globby
11 if QuestHelper.loading_flightpath then
12 globby = QuestHelper.loading_flightpath
13 else
14 QuestHelper.flightpathing = QuestHelper.CreateLoadingCounter()
15 globby = QuestHelper.flightpathing
16 end
18 local load_earlyload = globby:MakeSubcategory(1)
19 local load_preroll = globby:MakeSubcategory(1)
20 local load_floyd = globby:MakeSubcategory(1)
21 local load_postroll = globby:MakeSubcategory(0.1)
23 load_preroll:SetPercentage(0)
25 -- First, let's figure out if the player can fly.
26 -- The logic we're using: if he has 225 or 300, then he can fly in Outland. If he's got Cold Weather Flying and those levels, he can fly in Northrend.
28 local ridingLevel = (select(4,GetAchievementInfo(892)) and 300) or (select(4,GetAchievementInfo(890)) and 225) or (select(4,GetAchievementInfo(889)) and 150) or (select(4,GetAchievementInfo(891)) and 75) or 0 -- this is thanks to Maldivia, who is a fucking genius
29 local has_cwf = not not GetSpellInfo(GetSpellInfo(54197))
31 local speed
32 if ridingLevel == 225 then
33 speed = 11
34 elseif ridingLevel == 300 then
35 speed = 27
36 end
38 if ridingLevel >= 225 then
39 QH_Graph_Flyplaneset(3, speed) -- Outland
40 end
42 if ridingLevel >= 225 and has_cwf then
43 QH_Graph_Flyplaneset(4, speed) -- Northrend
44 end
45 end
47 local flightids = DB_ListItems("flightmasters")
48 local flightdb = {}
50 local has = {}
51 local has_count = 0
53 local fidcount = 0
54 for k, v in pairs(flightids) do
55 flightdb[v] = DB_GetItem("flightmasters", v, true, true)
56 if QuestHelper_KnownFlightRoutes[flightdb[v].name] then
57 has[k] = true
58 has_count = has_count + 1
59 end
61 fidcount = fidcount + 1
62 load_earlyload:SetPercentage(fidcount / QuestHelper:TableSize(flightids))
63 end
65 local adjacency = {}
67 local important = {}
69 QH_Timeslice_Yield()
71 local has_seen = 0
72 for k, v in pairs(has) do
73 local tdb = DB_GetItem("flightpaths", k, true, true)
74 if tdb then
75 for dest, dat in pairs(tdb) do
76 if has[dest] then
77 for _, route in ipairs(dat) do
78 local passes = true
79 if route.path then for _, intermed in ipairs(route.path) do
80 if not has[intermed] then passes = false break end
81 end end
83 if passes then
84 --QuestHelper:TextOut(string.format("Found link between %s and %s, cost %f", flightdb[k].name, flightdb[dest].name, route.distance))
85 if not adjacency[k] then adjacency[k] = {} end
86 if not adjacency[dest] then adjacency[dest] = {} end
87 QuestHelper: Assert(not (adjacency[k][dest] and adjacency[k][dest].time))
88 adjacency[k][dest] = {time = route.distance, dist = route.distance, original = true}
90 -- no such thing as strongly asymmetric routes
91 -- note that we're only hitting up adjacency here, because we don't have "time info"
92 if not adjacency[dest][k] then
93 adjacency[dest][k] = {dist = route.distance * 1.1, original = true} -- It's original because, in theory, we may end up basing other links on this one. It's still not time-authoritative, though.
94 end
96 important[k] = true
97 important[dest] = true
98 break
99 end
103 DB_ReleaseItem(tdb)
106 has_seen = has_seen + 1
107 load_preroll:SetPercentage(has_seen / has_count)
110 QH_Timeslice_Yield()
112 local imp_flat = {}
113 local flightmasters = {}
114 for k, v in pairs(important) do
115 table.insert(imp_flat, k)
116 if flightdb[k].mid then
117 local fmx = DB_GetItem("monster", flightdb[k].mid, true, true)
118 if fmx.loc then
119 flightmasters[k] = QuestHelper:CreateTable("flightmaster cachey")
120 for tk, v in pairs(fmx.loc[1]) do
121 if not tk:match("__.*") then
122 flightmasters[k][tk] = v
123 QuestHelper:Assert(type(tk) ~= "table")
124 QuestHelper:Assert(type(v) ~= "table")
127 else
128 --QuestHelper:TextOut(string.format("Missing flightmaster location for node %d/%s", k, tostring(flightdb[k].name)))
130 DB_ReleaseItem(fmx)
131 else
132 --QuestHelper:TextOut(string.format("Missing flightmaster for node %d/%s", k, tostring(flightdb[k].name)))
135 table.sort(imp_flat)
137 for _, v in ipairs(imp_flat) do
138 adjacency[v] = adjacency[v] or {}
141 for idx, pivot in ipairs(imp_flat) do
142 QH_Timeslice_Yield()
143 for _, i in ipairs(imp_flat) do
144 for _, j in ipairs(imp_flat) do
145 if adjacency[i][pivot] and adjacency[pivot][j] then
146 local cst = adjacency[i][pivot].dist + adjacency[pivot][j].dist
147 if not adjacency[i][j] or adjacency[i][j].dist > cst then
148 if not adjacency[i][j] then adjacency[i][j] = {} end
149 adjacency[i][j].dist = cst
150 adjacency[i][j].original = nil
156 load_floyd:SetPercentage(idx / #imp_flat)
159 QH_Timeslice_Yield()
162 local clustaken = {}
164 for src, t in pairs(adjacency) do
165 if not clustaken[src] then
166 local tcst = {}
167 local tcct = 0
168 local ctd = {}
169 table.insert(ctd, src)
171 while #ctd > 0 do
172 local ite = table.remove(ctd)
173 QuestHelper: Assert(not clustaken[ite] or tcst[ite])
175 if not tcst[ite] then
176 clustaken[ite] = true
177 tcst[ite] = true
178 for _, dst in pairs(imp_flat) do
179 if adjacency[ite][dst] and not tcst[dst] then
180 table.insert(ctd, dst)
184 tcct = tcct + 1
188 --QuestHelper: TextOut(string.format("Starting with %d, cluster of %d", src, tcct))
193 QH_Graph_Plane_Destroylinks("flightpath")
195 -- reset!
196 QH_Flight_Distances = {}
198 for src, t in pairs(adjacency) do
199 QH_Timeslice_Yield()
200 for dest, dat in pairs(t) do
202 local fms = flightmasters[src]
203 local fmd = flightmasters[dest]
204 if fms and fmd then
205 local fmsc = QuestHelper_ParentLookup[fms.p]
206 local fmdc = QuestHelper_ParentLookup[fmd.p]
207 QuestHelper: Assert(fmsc == fmdc)
212 local sname = flightdb[src].name
213 local dname = flightdb[dest].name
215 if not QH_Flight_Distances[sname] then QH_Flight_Distances[sname] = {} end
216 QuestHelper: Assert(not QH_Flight_Distances[sname][dname])
217 QH_Flight_Distances[sname][dname] = {adjacency[src][dest].dist, not adjacency[src][dest].original}
220 if dat.original and not (src > dest and adjacency[dest][src] and adjacency[dest][src].original) then
221 local fms = flightmasters[src]
222 local fmd = flightmasters[dest]
223 if fms and fmd then
224 local snode = {x = fms.x, y = fms.y, c = QuestHelper_ParentLookup[fms.p], p = fms.p, map_desc = {QHFormat("WAYPOINT_REASON", QHFormat("FLIGHT_POINT", flightdb[dest].name))}, condense_class = "flightpath"}
225 local dnode = {x = fmd.x, y = fmd.y, c = QuestHelper_ParentLookup[fmd.p], p = fmd.p, map_desc = {QHFormat("WAYPOINT_REASON", QHFormat("FLIGHT_POINT", flightdb[src].name))}, condense_class = "flightpath"}
227 local ret = adjacency[dest][src] and adjacency[dest][src].original and adjacency[dest][src].dist
228 QH_Graph_Plane_Makelink("flightpath", snode, dnode, dat.dist, ret)
234 for _, v in pairs(flightdb) do
235 DB_ReleaseItem(v)
237 for _, v in pairs(flightmasters) do
238 QuestHelper:ReleaseTable(v)
241 load_postroll:SetPercentage(1)
243 if not QuestHelper.loading_flightpath then
244 QuestHelper.flightpathing = nil