1 QuestHelper_File
["pathfinding.lua"] = "Development Version"
3 local IRONFORGE_PORTAL
= {25,0.255,0.084, "Ironforge portal site"}
4 local STORMWIND_CITY_PORTAL
= {36,0.387,0.802, "Stormwind City portal site"}
5 local DARNASSUS_PORTAL
= {21,0.397,0.824, "Darnassus portal site"}
6 local EXODAR_PORTAL
= {12,0.476,0.598, "Exodar portal site"}
8 local SHATTRATH_CITY_PORTAL
= {60,0.530,0.492, "Shattrath City portal site"}
9 local MOONGLADE_PORTAL
= {20,0.563,0.320, "Moonglade portal site"}
11 local SILVERMOON_CITY_PORTAL
= {52,0.583,0.192, "Silvermoon City portal site"}
12 local UNDERCITY_PORTAL
= {45,0.846,0.163, "Undercity portal site"}
13 local ORGRIMMAR_PORTAL
= {1,0.386,0.859, "Orgrimmar portal site"}
14 local THUNDER_BLUFF_PORTAL
= {23,0.222,0.168, "Thunder Bluff portal site"}
16 local static_horde_routes
=
18 {{7, 0.505, 0.124}, {38, 0.313, 0.303}, 210}, -- Durotar <--> Grom'gol Base Camp
19 {{38, 0.316, 0.289}, {43, 0.621, 0.591}, 210}, -- Grom'gol Base Camp <--> Tirisfal Glades
20 {{43, 0.605, 0.587}, {7, 0.509, 0.141}, 210}, -- Tirisfal Glades <--> Durotar
21 {{45, 0.549, 0.11}, {52, 0.495, 0.148}, 5}, -- Undercity <--> Silvermoon City
23 {{60, 0.592, 0.483}, SILVERMOON_CITY_PORTAL
, 5, true, nil, "SILVERMOON_CITY_PORTAL"}, -- Shattrath City --> Silvermoon City
24 {{60, 0.528, 0.531}, THUNDER_BLUFF_PORTAL
, 5, true, nil, "THUNDER_BLUFF_PORTAL"}, -- Shattrath City --> Thunder Bluff
25 {{60, 0.522, 0.529}, ORGRIMMAR_PORTAL
, 5, true, nil, "ORGRIMMAR_PORTAL"}, -- Shattrath City --> Orgrimmar
26 {{60, 0.517, 0.525}, UNDERCITY_PORTAL
, 5, true, nil, "UNDERCITY_PORTAL"} -- Shattrath City --> Undercity
29 local static_alliance_routes
=
31 {{36, 0.639, 0.083}, {25, 0.764, 0.512}, 120}, -- Deeprun Tram
32 {{51, 0.044, 0.569}, {16, 0.323, 0.441}, 210}, --Menethil Harbor <--> Auberdine
33 {{10, 0.718, 0.565}, {51, 0.047, 0.636}, 210}, -- Theramore Isle <--> Menethil Harmor
35 {{60, 0.558, 0.366}, STORMWIND_CITY_PORTAL
, 5, true, nil, "STORMWIND_CITY_PORTAL"}, -- Shattrath City --> Stormwind City
36 {{60, 0.563, 0.37}, IRONFORGE_PORTAL
, 5, true, nil, "IRONFORGE_PORTAL"}, -- Shattrath City --> Ironforge
37 {{60, 0.552, 0.364}, DARNASSUS_PORTAL
, 5, true, nil, "DARNASSUS_PORTAL"}, -- Shattrath City --> Darnassus
38 {{60, 0.596, 0.467}, EXODAR_PORTAL
, 5, true, nil, "EXODAR_PORTAL"} -- Shattrath City --> Exodar
41 local static_shared_routes
=
43 {{11, 0.638, 0.387}, {38, 0.257, 0.73}, 210}, -- Ratchet <--> Booty Bay
44 {{40, 0.318, 0.503}, {32, 0.347, 0.84}, 130}, -- Burning Steppes <--> Searing Gorge
46 -- More Alliance routes than anything, but without them theres no valid path to these areas for Horde characters.
47 {{24, 0.559, 0.896}, {21, 0.305, 0.414}, 5}, -- Rut'Theran Village <--> Darnassus
48 {{16, 0.332, 0.398}, {24, 0.548, 0.971}, 210}, -- Auberdine <--> Rut'Theran Village
49 {{16, 0.306, 0.409}, {3, 0.2, 0.546}, 210}, -- Auberdine <--> Azuremyst Isle
51 -- Route to new zone. Not valid, exists only to keep routing from exploding if you don't have the flight routes there.
52 {{41, 0.5, 0.5}, {64, 0.5, 0.5}, 7200} -- Eversong Woods <--> Sunwell
55 -- Darkportal is handled specially, depending on whether or not you're level 58+ or not.
56 local dark_portal_route
= {{33, 0.587, 0.599}, {56, 0.898, 0.502}, 5}
58 local static_zone_transitions
=
60 {2, 11, 0.687, 0.872}, -- Ashenvale <--> The Barrens
61 {2, 6, 0.423, 0.711}, -- Ashenvale <--> Stonetalon Mountains
62 {2, 15, 0.954, 0.484}, -- Ashenvale <--> Azshara
63 {2, 16, 0.289, 0.144}, -- Ashenvale <--> Darkshore
64 {2, 13, 0.557, 0.29}, -- Ashenvale <--> Felwood
65 {21, 24, 0.894, 0.358}, -- Darnassus <--> Teldrassil
66 {22, 11, 0.697, 0.604}, -- Mulgore <--> The Barrens
67 {22, 23, 0.376, 0.33}, -- Mulgore <--> Thunder Bluff
68 {22, 23, 0.403, 0.193}, -- Mulgore <--> Thunder Bluff
69 {3, 12, 0.247, 0.494}, -- Azuremyst Isle <--> The Exodar
70 {3, 12, 0.369, 0.469}, -- Azuremyst Isle <--> The Exodar
71 {3, 9, 0.42, 0.013}, -- Azuremyst Isle <--> Bloodmyst Isle
72 {4, 6, 0.539, 0.032}, -- Desolace <--> Stonetalon Mountains
73 {4, 17, 0.428, 0.976}, -- Desolace <--> Feralas
74 {5, 18, 0.865, 0.115}, -- Silithus <--> Un'Goro Crater
75 {7, 11, 0.341, 0.424}, -- Durotar <--> The Barrens
76 {7, 1, 0.455, 0.121}, -- Durotar <--> Orgrimmar
77 {8, 18, 0.269, 0.516}, -- Tanaris <--> Un'Goro Crater
78 {8, 14, 0.512, 0.21}, -- Tanaris <--> Thousand Needles
79 {10, 11, 0.287, 0.472}, -- Dustwallow Marsh <--> The Barrens
80 {10, 11, 0.563, 0.077}, -- Dustwallow Marsh <--> The Barrens
81 {11, 14, 0.442, 0.915}, -- The Barrens <--> Thousand Needles
82 {13, 19, 0.685, 0.06}, -- Felwood <--> Winterspring
83 {13, 20, 0.669, -0.063}, -- Felwood <--> Moonglade
84 {1, 11, 0.118, 0.69}, -- Orgrimmar <--> The Barrens
85 {17, 14, 0.899, 0.46}, -- Feralas <--> Thousand Needles
86 {6, 11, 0.836, 0.973}, -- Stonetalon Mountains <--> The Barrens
87 {26, 48, 0.521, 0.7}, -- Alterac Mountains <--> Hillsbrad Foothills
88 {26, 35, 0.173, 0.482}, -- Alterac Mountains <--> Silverpine Forest
89 {26, 50, 0.807, 0.347}, -- Alterac Mountains <--> Western Plaguelands
90 {39, 51, 0.454, 0.89}, -- Arathi Highlands <--> Wetlands
91 {39, 48, 0.2, 0.293}, -- Arathi Highlands <--> Hillsbrad Foothills
92 {27, 29, 0.49, 0.071}, -- Badlands <--> Loch Modan
93 {27, 32, -0.005, 0.636}, -- Badlands <--> Searing Gorge
94 {33, 46, 0.519, 0.051}, -- Blasted Lands <--> Swamp of Sorrows
95 {40, 30, 0.79, 0.842}, -- Burning Steppes <--> Redridge Mountains
96 {47, 31, 0.324, 0.363}, -- Deadwind Pass <--> Duskwood
97 {47, 46, 0.605, 0.41}, -- Deadwind Pass <--> Swamp of Sorrows
98 {28, 25, 0.534, 0.349}, -- Dun Morogh <--> Ironforge
99 {28, 29, 0.863, 0.514}, -- Dun Morogh <--> Loch Modan
100 {28, 29, 0.844, 0.31}, -- Dun Morogh <--> Loch Modan
101 {31, 37, 0.801, 0.158}, -- Duskwood <--> Elwynn Forest
102 {31, 37, 0.15, 0.214}, -- Duskwood <--> Elwynn Forest
103 {31, 38, 0.447, 0.884}, -- Duskwood <--> Stranglethorn Vale
104 {31, 38, 0.209, 0.863}, -- Duskwood <--> Stranglethorn Vale
105 {31, 30, 0.941, 0.103}, -- Duskwood <--> Redridge Mountains
106 {31, 49, 0.079, 0.638}, -- Duskwood <--> Westfall
107 {34, 50, 0.107, 0.726}, -- Eastern Plaguelands <--> Western Plaguelands
108 {34, 44, 0.625, 0.03}, -- Eastern Plaguelands <--> Ghostlands
109 {37, 36, 0.321, 0.493}, -- Elwynn Forest <--> Stormwind City
110 {37, 49, 0.202, 0.804}, -- Elwynn Forest <--> Westfall
111 {37, 30, 0.944, 0.724}, -- Elwynn Forest <--> Redridge Mountains
112 {41, 52, 0.567, 0.494}, -- Eversong Woods <--> Silvermoon City
113 {41, 44, 0.486, 0.916}, -- Eversong Woods <--> Ghostlands
114 {35, 43, 0.678, 0.049}, -- Silverpine Forest <--> Tirisfal Glades
115 {42, 50, 0.217, 0.264}, -- The Hinterlands <--> Western Plaguelands
116 {43, 45, 0.619, 0.651}, -- Tirisfal Glades <--> Undercity
117 {43, 50, 0.851, 0.703}, -- Tirisfal Glades <--> Western Plaguelands
118 {38, 49, 0.292, 0.024}, -- Stranglethorn Vale <--> Westfall
119 {48, 35, 0.137, 0.458}, -- Hillsbrad Foothills <--> Silverpine Forest
120 {48, 42, 0.899, 0.253}, -- Hillsbrad Foothills <--> The Hinterlands
121 {29, 51, 0.252, 0}, -- Loch Modan <--> Wetlands
123 -- These are just guesses, since I haven't actually been to these areas.
124 {58, 60, 0.783, 0.545}, -- Nagrand <--> Shattrath City
125 {60, 55, 0.782, 0.492}, -- Shattrath City <--> Terokkar Forest
126 {54, 59, 0.842, 0.284}, -- Blade's Edge Mountains <--> Netherstorm
127 {54, 57, 0.522, 0.996}, -- Blade's Edge Mountains <--> Zangarmarsh
128 {54, 57, 0.312, 0.94}, -- Blade's Edge Mountains <--> Zangarmarsh
129 {56, 55, 0.353, 0.901}, -- Hellfire Peninsula <--> Terokkar Forest
130 {56, 57, 0.093, 0.519}, -- Hellfire Peninsula <--> Zangarmarsh
131 {58, 55, 0.8, 0.817}, -- Nagrand <--> Terokkar Forest
132 {58, 57, 0.343, 0.159}, -- Nagrand <--> Zangarmarsh
133 {58, 57, 0.754, 0.331}, -- Nagrand <--> Zangarmarsh
134 {53, 55, 0.208, 0.271}, -- Shadowmoon Valley <--> Terokkar Forest
135 {55, 57, 0.341, 0.098}, -- Terokkar Forest <--> Zangarmarsh
138 local walkspeed_multiplier
= 1/7 -- Every yard walked takes this many seconds.
140 QuestHelper
.prepared_objectives
= {}
141 QuestHelper
.named_nodes
= {}
143 local function cont_dist(a
, b
)
144 local x
, y
= a
.x
-b
.x
, a
.y
-b
.y
145 return math
.sqrt(x
*x
+y
*y
)
148 function QuestHelper
:ComputeRoute(p1
, p2
)
149 if not p1
or not p2
then QuestHelper
:Error("Boom!") end
150 local graph
= self
.world_graph
152 graph
:PrepareSearch()
156 for i
, n
in ipairs(el
) do
162 for i
, n
in ipairs(p1
[1]) do
163 graph
:AddRouteStartNode(n
, l
[i
], el
)
166 local e
= graph
:DoRouteSearch(el
)
172 if p1
[1] == p2
[1] then
173 local x
, y
= p1
[3]-p2
[3], p1
[4]-p2
[4]
174 local d2
= math
.sqrt(x
*x
+y
*y
)
184 function QuestHelper
:ComputeTravelTime(p1
, p2
)
185 if not p1
or not p2
then QuestHelper
:Error("Boom!") end
186 local graph
= self
.world_graph
188 graph
:PrepareSearch()
192 for i
, n
in ipairs(el
) do
199 for i
, n
in ipairs(p1
[1]) do
200 graph
:AddStartNode(n
, l
[i
], el
)
203 local e
= graph
:DoSearch(el
)
209 if p1
[1] == p2
[1] then
210 local x
, y
= p1
[3]-p2
[3], p1
[4]-p2
[4]
211 d
= math
.min(d
, math
.sqrt(x
*x
+y
*y
))
217 function QuestHelper
:CreateGraphNode(c
, x
, y
, n
)
218 local node
= self
.world_graph
:CreateNode()
226 local cont
, zone
= unpack(QuestHelper_ZoneLookup
[c
[1]]
)
228 node
.x
, node
.y
= self
.Astrolabe
:TranslateWorldMapPosition(cont
, zone
, c
[2], c
[3], cont
, 0)
229 node
.x
= node
.x
* self
.continent_scales_x
[node
.c
]
230 node
.y
= node
.y
* self
.continent_scales_y
[node
.c
]
231 node
.name
= c
[5] or QuestHelper_NameLookup
[c
[1]]
238 function QuestHelper
:CreateAndAddZoneNode(z
, c
, x
, y
)
239 local node
= self
:CreateGraphNode(c
, x
, y
)
241 -- Not going to merge nodes.
242 --[[local closest, travel_time = nil, 0
244 for i, n in ipairs(z) do
245 local t = math.sqrt((n.x-node.x)*(n.x-node.x)+(n.y-node.y)*(n.y-node.y))
246 if not closest or t < travel_time then
247 closest, travel_time = n, t
251 if closest and travel_time < 10 then
252 closest.x = (closest.x * closest.w + node.x)/(closest.w+1)
253 closest.y = (closest.y * closest.w + node.y)/(closest.w+1)
254 closest.w = closest.w + 1
255 self.world_graph:DestroyNode(node)
258 table.insert(z
, node
)
263 function QuestHelper
:CreateAndAddStaticNodePair(data
)
266 if data
[5] and self
.named_nodes
[data
[5]]
then
267 node1
= self
.named_nodes
[data
[5]]
269 node1
= self
:CreateAndAddZoneNode(self
.zone_nodes
[data
[1][1]]
, data
[1])
270 if data
[5] then self
.named_nodes
[data
[5]]
= node1
end
273 if data
[6] and self
.named_nodes
[data
[6]]
then
274 node2
= self
.named_nodes
[data
[6]]
276 node2
= self
:CreateAndAddZoneNode(self
.zone_nodes
[data
[2][1]]
, data
[2])
277 if data
[6] then self
.named_nodes
[data
[6]]
= node2
end
280 node1
.name
= node1
.name
or "route to "..QuestHelper_NameLookup
[data
[2][1]]
281 node2
.name
= node2
.name
or "route to "..QuestHelper_NameLookup
[data
[1][1]]
283 node1
:Link(node2
, data
[3])
285 if not data
[4] then -- If data[4] is true, then this is a one-way trip.
286 node2
:Link(node1
, data
[3])
289 self
:yieldIfNeeded(0.1)
293 function QuestHelper
:GetNodeByName(name
, fallback_data
)
294 local node
= self
.named_nodes
[name
]
295 if not node
and fallback_data
then
296 node
= self
:CreateAndAddZoneNode(self
.zone_nodes
[fallback_data
[1]]
, fallback_data
)
297 self
.named_nodes
[name
] = node
302 local function nodeLeavesContinent(node
, c
)
304 for n
, d
in pairs(node
.n
) do
313 local function isGoodPath(start_node
, end_node
, i
, j
)
314 -- Checks to make sure a path doesn't leave the continent only to reenter it.
317 if end_node
.c
== i
then
320 end_node
= end_node
.p
321 if end_node
.c
== j
then
325 return end_node
== start_node
330 local function shouldLink(a
, b
)
331 -- TODO: Need to have objectives not create links to unreachable nodes.
337 for id in pairs(a.id_from) do
338 if not b.id_to[id] then
339 for id in pairs(b.id_to) do
340 if not a.id_from[id] then
351 local function getNPCNode(npc
)
352 local npc_objective
= QuestHelper
:GetObjective("monster", npc
)
353 if npc_objective
:Known() then
354 npc_objective
:PrepareRouting()
355 local p
= npc_objective
:Position()
359 node
= QuestHelper
:CreateAndAddZoneNode(p
[1], p
[1].c
, p
[3], p
[4])
362 npc_objective
:DoneRouting()
368 function QuestHelper
:CreateAndAddTransitionNode(z1
, z2
, pos
)
369 local node
= self
:CreateGraphNode(pos
)
371 local closest
, travel_time
= nil, 0
373 for i
, n
in ipairs(z1
) do
374 local t
= math
.sqrt((n
.x
-node
.x
)*(n
.x
-node
.x
)+(n
.y
-node
.y
)*(n
.y
-node
.y
))
375 if not closest
or t
< travel_time
then
376 closest
, travel_time
= n
, t
381 for i
, n
in ipairs(z2
) do
382 local t
= math
.sqrt((n
.x
-node
.x
)*(n
.x
-node
.x
)+(n
.y
-node
.y
)*(n
.y
-node
.y
))
383 if not closest
or t
< travel_time
then
384 closest
, travel_time
= n
, t
389 if closest
and travel_time
< 10 then
390 --QuestHelper:TextOut("Node already exists at "..closest.x..", "..closest.y..", name="..(closest.name or "nil"))
391 closest
.x
= (closest
.x
* closest
.w
+ node
.x
)/(closest
.w
+1)
392 closest
.y
= (closest
.y
* closest
.w
+ node
.y
)/(closest
.w
+1)
393 closest
.w
= closest
.w
+ 1
394 local z1_has
, z2_has
= false, false
396 -- Just because the node already exists, doesn't mean its already in both lists!
398 for i
, n
in ipairs(z1
) do
406 for i
, n
in ipairs(z2
) do
416 if not z1_has
then table.insert(z1
, closest
) end
417 if not z2_has
then table.insert(z2
, closest
) end
419 self
.world_graph
:DestroyNode(node
)
420 self
:yieldIfNeeded(0.2)
423 table.insert(z1
, node
)
424 if z1
~= z2
then table.insert(z2
, node
) end
425 self
:yieldIfNeeded(0.1)
430 function QuestHelper
:ReleaseObjectivePathingInfo(o
)
432 for z
, pl
in pairs(o
.p
) do
433 self
:ReleaseTable(o
.d
[z
])
435 for i
, p
in ipairs(pl
) do
436 self
:ReleaseTable(p
[2])
440 self
:ReleaseTable(pl
)
443 self
:ReleaseTable(o
.d
)
444 self
:ReleaseTable(o
.p
)
445 self
:ReleaseTable(o
.nm
)
446 self
:ReleaseTable(o
.nm2
)
447 self
:ReleaseTable(o
.nl
)
449 local cache
= o
.distance_cache
450 for k
, v
in pairs(cache
) do
454 self
:ReleaseTable(cache
)
456 o
.d
, o
.p
, o
.nm
, o
.nm2
, o
.nl
= nil, nil, nil, nil, nil
457 o
.distance_cache
= nil
458 o
.pos
, o
.sop
= nil, nil -- ResetPathing will preserve these values if needed.
463 function QuestHelper
:SetupTeleportInfo(info
, can_create
)
464 self
:TeleportInfoClear(info
)
466 if QuestHelper_Home
then
467 local node
= self
:GetNodeByName("HOME_PORTAL", can_create
and QuestHelper_Home
)
469 local cooldown
= self
:ItemCooldown(6948)
471 self
:SetTeleportInfoTarget(info
, node
, GetTime()-60*60+cooldown
, 60*60, 10)
474 self
.defered_graph_reset
= true
478 -- TODO: Compact this. . . and find a better way to tell if the player has a spell.
480 if GetSpellTexture("Teleport: Darnassus") then
481 local node
= self
:GetNodeByName("DARNASSUS_PORTAL", can_create
and DARNASSUS_PORTAL
)
482 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
485 if GetSpellTexture("Teleport: Exodar") then
486 local node
= self
:GetNodeByName("EXODAR_PORTAL", can_create
and EXODAR_PORTAL
)
487 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
490 if GetSpellTexture("Teleport: Ironforge") then
491 local node
= self
:GetNodeByName("IRONFORGE_PORTAL", can_create
and IRONFORGE_PORTAL
)
492 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
495 if GetSpellTexture("Teleport: Moonglade") then
496 local node
= self
:GetNodeByName("MOONGLADE_PORTAL", can_create
and MOONGLADE_PORTAL
)
497 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10) else self
.defered_graph_reset
= true end
500 if GetSpellTexture("Teleport: Orgrimmar") then
501 local node
= self
:GetNodeByName("ORGRIMMAR_PORTAL", can_create
and ORGRIMMAR_PORTAL
)
502 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
505 if GetSpellTexture("Teleport: Shattrath") then
506 local node
= self
:GetNodeByName("SHATTRATH_CITY_PORTAL", can_create
and SHATTRATH_CITY_PORTAL
)
507 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
510 if GetSpellTexture("Teleport: Silvermoon") then
511 local node
= self
:GetNodeByName("SILVERMOON_CITY_PORTAL", can_create
and SILVERMOON_CITY_PORTAL
)
512 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
515 if GetSpellTexture("Teleport: Stormwind") then
516 local node
= self
:GetNodeByName("STORMWIND_CITY_PORTAL", can_create
and STORMWIND_CITY_PORTAL
)
517 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
520 if GetSpellTexture("Teleport: Thunder Bluff") then
521 local node
= self
:GetNodeByName("THUNDER_BLUFF_PORTAL", can_create
and THUNDER_BLUFF_PORTAL
)
522 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
525 if GetSpellTexture("Teleport: Undercity") then
526 local node
= self
:GetNodeByName("UNDERCITY_PORTAL", can_create
and UNDERCITY_PORTAL
)
527 if node
then self
:SetTeleportInfoTarget(info
, node
, 0, 0, 10, 17031) else self
.defered_graph_reset
= true end
530 self
:SetTeleportInfoReagent(info
, 17031, self
:CountItem(17031))
533 function QuestHelper
:ResetPathing()
534 for key
in pairs(self
.named_nodes
) do
535 self
.named_nodes
[key
] = nil
538 -- Objectives may include cached information that depends on the world graph.
541 while i
<= #self
.prepared_objectives
do
542 local o
= self
.prepared_objectives
[i
]
544 if o
.setup_count
== 0 then
545 table.remove(self
.prepared_objectives
, i
)
546 self
:ReleaseObjectivePathingInfo(o
)
548 -- Routing should reset the positions of objectives in the route after the reset is complete.
550 self
:ReleaseObjectivePathingInfo(o
)
555 local to_readd
= self
.prepared_objectives
556 self
.prepared_objectives
= self
.old_prepared_objectives
or {}
557 self
.old_prepared_objectives
= to_readd
559 local zone_nodes
= self
.zone_nodes
560 if not zone_nodes
then
562 self
.zone_nodes
= zone_nodes
565 local flight_master_nodes
= self
.flight_master_nodes
566 if not flight_master_nodes
then
567 flight_master_nodes
= {}
568 self
.flight_master_nodes
= flight_master_nodes
570 for key
in pairs(flight_master_nodes
) do
571 flight_master_nodes
[key
] = nil
575 self
.world_graph
:Reset()
576 self
:yieldIfNeeded(0.1)
578 local continent_scales_x
, continent_scales_y
= self
.continent_scales_x
, self
.continent_scales_y
579 if not continent_scales_x
then
580 continent_scales_x
= {}
581 continent_scales_y
= {}
582 self
.continent_scales_x
= continent_scales_x
583 self
.continent_scales_y
= continent_scales_y
586 for c
=1,select("#", GetMapContinents()) do
587 if not continent_scales_x
[c
] then
588 local _
, x
, y
= self
.Astrolabe
:ComputeDistance(c
, 0, 0.25, 0.25, c
, 0, 0.75, 0.75)
590 continent_scales_x
[c
] = x
*walkspeed_multiplier
*2
591 continent_scales_y
[c
] = y
*walkspeed_multiplier
*2
595 for i
, name
in pairs(QuestHelper_NameLookup
) do
596 local z
= zone_nodes
[i
]
600 z
.i
, z
.c
, z
.z
= i
, unpack(QuestHelper_ZoneLookup
[i
])
602 for key
in pairs(z
) do
605 z
.i
, z
.c
, z
.z
= i
, unpack(QuestHelper_ZoneLookup
[i
])
609 self
:SetupTeleportInfo(self
.teleport_info
, true)
610 self
:yieldIfNeeded(0.1)
612 --[[for node, info in pairs(self.teleport_info.node) do
613 self:TextOut("You can teleport to "..(node.name or "nil").. " in "..self:TimeString(info[1]+info[2]-GetTime()))
616 if self
.faction
== 1 then
617 for i
, data
in ipairs(static_alliance_routes
) do
618 self
:CreateAndAddStaticNodePair(data
)
620 elseif self
.faction
== 2 then
621 for i
, data
in ipairs(static_horde_routes
) do
622 self
:CreateAndAddStaticNodePair(data
)
626 for i
, data
in ipairs(static_shared_routes
) do
627 self
:CreateAndAddStaticNodePair(data
)
630 if self
.player_level
>= 58 then
631 dark_portal_route
[3] = 5
633 -- If you can't take the route yet, we'll still add it and just pretend it will take a really long time.
634 dark_portal_route
[3] = 86400
637 self
:CreateAndAddStaticNodePair(dark_portal_route
)
639 local st
= self
:CreateTable()
641 for i
, data
in pairs(static_zone_transitions
) do
642 st
[1], st
[2], st
[3] = data
[1], data
[3], data
[4]
644 self
:CreateAndAddTransitionNode(zone_nodes
[data
[1]]
,
646 st
).name
= QHFormat("ZONE_BORDER", QuestHelper_NameLookup
[data
[1]]
, QuestHelper_NameLookup
[data
[2]]
)
649 self
:ReleaseTable(st
)
651 -- Create and link the flight route nodes.
652 local flight_times
= self
.flight_times
653 if not flight_times
then
654 self
:buildFlightTimes()
655 flight_times
= self
.flight_times
658 for start
, list
in pairs(flight_times
) do
659 for dest
, duration
in pairs(list
) do
660 local a_npc
, b_npc
= self
:getFlightInstructor(start
), self
:getFlightInstructor(dest
)
662 if a_npc
and b_npc
then
663 local a
, b
= flight_master_nodes
[start
], flight_master_nodes
[dest
]
666 a
= getNPCNode(a_npc
)
668 flight_master_nodes
[start
] = a
669 a
.name
= (select(3, string.find(start
, "^(.*),")) or start
).." flight point"
674 b
= getNPCNode(b_npc
)
676 flight_master_nodes
[dest
] = b
677 b
.name
= (select(3, string.find(dest
, "^(.*),")) or dest
).." flight point"
682 a
:Link(b
, duration
+5)
686 self
:yieldIfNeeded(0.1)
689 -- id_from, id_to, and id_local will be used in determining whether there is a point to linking nodes together.
690 for i
, n
in ipairs(self
.world_graph
.nodes
) do
691 n
.id_from
= self
:CreateTable()
692 n
.id_to
= self
:CreateTable()
693 n
.id_local
= self
:CreateTable()
696 -- Setup the local ids a node exists in.
697 for i
, list
in pairs(zone_nodes
) do
698 for _
, n
in ipairs(list
) do
705 -- Figure out where each node can come from or go to.
706 for i
, list
in pairs(zone_nodes
) do
707 for _
, node
in ipairs(list
) do
708 for n
in pairs(node
.n
) do
709 for id
in pairs(n
.id_local
) do node
.id_to
[id
] = true end
710 for id
in pairs(node
.id_local
) do n
.id_from
[id
] = true end
715 -- We'll treat 0 as a special id for where ever it is the player happens to be.
716 for node
in pairs(self
.teleport_info
.node
) do
717 node
.id_from
[0] = true
720 -- Will go through each zone and link all the nodes we have so far with every other node.
721 for _
, list
in pairs(zone_nodes
) do
724 if shouldLink(list
[i
], list
[j
]) then
725 list
[i
]:Link(list
[j
], cont_dist(list
[i
], list
[j
]))
731 self
:yieldIfNeeded(0.1)
733 -- We don't need to know where the nodes can go or come from now.
734 for i
, n
in ipairs(self
.world_graph
.nodes
) do
735 self
:ReleaseTable(n
.id_from
)
736 self
:ReleaseTable(n
.id_to
)
737 self
:ReleaseTable(n
.id_local
)
738 n
.id_from
, n
.id_to
, n
.id_local
= nil, nil, nil
741 -- TODO: This is a work around until I fix shouldLink
742 for start
, list
in pairs(flight_times
) do
743 for dest
, duration
in pairs(list
) do
744 local a
, b
= flight_master_nodes
[start
], flight_master_nodes
[dest
]
746 a
:Link(b
, duration
+5)
751 self
:yieldIfNeeded(0.1)
752 -- self.world_graph:SanityCheck()
754 -- Remove objectives again, since we created some for the flight masters.
756 local o
= table.remove(self
.prepared_objectives
)
757 if not o
then break end
759 self
:ReleaseObjectivePathingInfo(o
)
761 if o
.setup_count
> 0 then
762 -- There's a chance an objective could end up in the list twice, but we'll deal with that by not actually
763 -- adding locations for it if it's already setup.
764 table.insert(to_readd
, o
)
769 local obj
= table.remove(to_readd
)
770 if not obj
then break end
772 if not obj
.setup
then -- In case the objective was added multiple times to the to_readd list.
773 obj
.d
= QuestHelper
:CreateTable()
774 obj
.p
= QuestHelper
:CreateTable()
775 obj
.nm
= QuestHelper
:CreateTable()
776 obj
.nm2
= QuestHelper
:CreateTable()
777 obj
.nl
= QuestHelper
:CreateTable()
778 obj
.distance_cache
= QuestHelper
:CreateTable()
779 obj
:AppendPositions(obj
, 1, nil)
785 self
.pos
[1] = self
.zone_nodes
[self
.i
]
786 for i
, n
in ipairs(self
.pos
[1]) do
787 local a
, b
= n
.x
-self
.pos
[3], n
.y
-self
.pos
[4]
788 self
.pos
[2][i
] = math
.sqrt(a
*a
+b
*b
)
792 -- And if all went according to plan, we now have a graph we can follow to get from anywhere to anywhere.
794 if self
.graph_walker
then
795 self
.graph_walker
:GraphChanged()