4 $Date: 2008-10-05 17:22:44 -0700 (Sun, 05 Oct 2008) $
5 Author(s): Esamynn (esamynn at wowinterface.com), Zorba (see questhelper docs)
6 Inspired By: Gatherer by Norganna
7 MapLibrary by Kristofer Karlsson (krka at kth.se)
8 Documentation: http://wiki.esamynn.org/Astrolabe
9 SVN: http://svn.esamynn.org/astrolabe/
11 This is a library for the World of Warcraft UI system to place
12 icons accurately on both the Minimap and on Worldmaps.
13 This library also manages and updates the position of Minimap icons
16 Modified to support Death Knight starting zone.
18 Copyright (C) 2006-2008 James Carrothers
21 This library is free software; you can redistribute it and/or
22 modify it under the terms of the GNU Lesser General Public
23 License as published by the Free Software Foundation; either
24 version 2.1 of the License, or (at your option) any later version.
26 This library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
31 You should have received a copy of the GNU Lesser General Public
32 License along with this library; if not, write to the Free Software
33 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
36 This library's source code is specifically designed to work with
37 World of Warcraft's interpreted AddOn system. You have an implicit
38 licence to use this library with these facilities since that is its
39 designated purpose as per:
40 http://www.fsf.org/licensing/licenses/gpl-faq.html#InterpreterIncompat
43 QuestHelper_File
["AstrolabeQH/Astrolabe.lua"] = "Development Version"
44 QuestHelper_Loadtime
["AstrolabeQH/Astrolabe.lua"] = GetTime()
47 -- DO NOT MAKE CHANGES TO THIS LIBRARY WITHOUT FIRST CHANGING THE LIBRARY_VERSION_MAJOR
48 -- STRING (to something unique) OR ELSE YOU MAY BREAK OTHER ADDONS THAT USE THIS LIBRARY!!!
49 local LIBRARY_VERSION_MAJOR
= "Astrolabe-0.4-QuestHelper"
50 local LIBRARY_VERSION_MINOR
= 105 -- this is a completely randomly chosen number, the only point being that it was larger than the original 92 and larger than the later 100
52 if not DongleStub
then error(LIBRARY_VERSION_MAJOR
.. " requires DongleStub.") end
53 if not DongleStub
:IsNewerVersion(LIBRARY_VERSION_MAJOR
, LIBRARY_VERSION_MINOR
) then return end
57 local Minimap
= _G
.Minimap
59 -- define local variables for Data Tables (defined at the end of this file)
60 local WorldMapSize
, MinimapSize
, ValidMinimapShapes
, VirtualContinentIndexes
;
62 function Astrolabe
:GetVersion()
63 return LIBRARY_VERSION_MAJOR
, LIBRARY_VERSION_MINOR
;
67 --------------------------------------------------------------------------------------------------------------
69 --------------------------------------------------------------------------------------------------------------
71 local configConstants
= {
72 MinimapUpdateMultiplier
= true,
75 -- this constant is multiplied by the current framerate to determine
76 -- how many icons are updated each frame
77 Astrolabe
.MinimapUpdateMultiplier
= 1;
80 --------------------------------------------------------------------------------------------------------------
82 --------------------------------------------------------------------------------------------------------------
84 Astrolabe
.LastPlayerPosition
= { 0, 0, 0, 0 };
85 Astrolabe
.MinimapIcons
= {};
86 Astrolabe
.IconsOnEdge
= {};
87 Astrolabe
.IconsOnEdge_GroupChangeCallbacks
= {};
89 Astrolabe
.MinimapIconCount
= 0
90 Astrolabe
.ForceNextUpdate
= false;
91 Astrolabe
.IconsOnEdgeChanged
= false;
93 -- This variable indicates whether we know of a visible World Map or not.
94 -- The state of this variable is controlled by the AstrolabeMapMonitor library.
95 Astrolabe
.WorldMapVisible
= false;
97 local AddedOrUpdatedIcons
= {}
98 local MinimapIconsMetatable
= { __index
= AddedOrUpdatedIcons
}
101 --------------------------------------------------------------------------------------------------------------
102 -- Local Pointers for often used API functions
103 --------------------------------------------------------------------------------------------------------------
105 local twoPi
= math
.pi
* 2;
106 local atan2 = math
.atan2;
107 local sin = math
.sin;
108 local cos = math
.cos;
109 local abs = math
.abs;
110 local sqrt = math
.sqrt;
113 local yield
= coroutine
.yield
114 local GetFramerate
= GetFramerate
117 --------------------------------------------------------------------------------------------------------------
118 -- Internal Utility Functions
119 --------------------------------------------------------------------------------------------------------------
121 local function assert(level
,condition
,message
)
122 if not condition
then
127 local function argcheck(value
, num
, ...)
128 assert(1, type(num
) == "number", "Bad argument #2 to 'argcheck' (number expected, got " .. type(level
) .. ")")
130 for i
=1,select("#", ...) do
131 if type(value
) == select(i
, ...) then return end
134 local types
= strjoin(", ", ...)
135 local name
= string.match(debugstack(2,2,0), ": in function [`<](.-)['>]")
136 error(string.format("Bad argument #%d to 'Astrolabe.%s' (%s expected, got %s)", num
, name
, types
, type(value
)), 3)
139 local function getContPosition( zoneData
, z
, x
, y
)
141 zoneData
= zoneData
[z
];
142 if not zoneData
then return end
143 x
= x
* zoneData
.width
+ zoneData
.xOffset
;
144 y
= y
* zoneData
.height
+ zoneData
.yOffset
;
146 x
= x
* zoneData
.width
;
147 y
= y
* zoneData
.height
;
152 --------------------------------------------------------------------------------------------------------------
153 -- Virtual Continent Functions
154 --------------------------------------------------------------------------------------------------------------
156 function Astrolabe
:GetCurrentVirtualMapCZ()
157 local C
, Z
= GetCurrentMapContinent(), GetCurrentMapZone();
158 if C
== -1 and Z
== 0 then
160 local mapname
= GetMapInfo()
161 if VirtualContinentIndexes
[mapname
] and GetCurrentMapDungeonLevel() == 0 then
162 C
= VirtualContinentIndexes
[mapname
]
164 elseif mapname
and VirtualContinentIndexes
[mapname
.. GetCurrentMapDungeonLevel()] then
165 C
= VirtualContinentIndexes
[mapname
.. GetCurrentMapDungeonLevel()]
167 elseif mapname
== "CoTStratholme" and GetCurrentMapDungeonLevel() == 0 then
168 -- why do you gotta make me angry, baby
169 C
= VirtualContinentIndexes
["CoTStratholme2"]
176 function Astrolabe
:GetCurrentVirtualMapContinent() local C
, Z
= self
:GetCurrentVirtualMapCZ() return C
end
177 function Astrolabe
:GetCurrentVirtualMapZone() local C
, Z
= self
:GetCurrentVirtualMapCZ() return Z
end
179 -- Does much the same as GetMapContinents, but returns as an array and includes the virtual continents in the mix
180 function Astrolabe
:GetMapVirtualContinents()
181 local rv
= {GetMapContinents()}
182 for k
, v
in pairs(VirtualContinentIndexes
) do
183 rv
[v
] = k
.. "_Continent"
188 -- Does much the same as GetMapContinents, but returns as an array and includes the virtual continents in the mix
189 function Astrolabe
:GetMapVirtualZones(zone
)
190 for k
, v
in pairs(VirtualContinentIndexes
) do
196 return {GetMapZones(zone
)}
199 function Astrolabe
:GetMapTexture(c
, z
)
200 for k
, v
in pairs(VirtualContinentIndexes
) do
201 if v
== c
and z
== 0 then
202 return k
.. "_Continent"
203 elseif v
== c
and z
== 1 then
209 return (GetMapInfo())
212 --------------------------------------------------------------------------------------------------------------
213 -- General Utility Functions
214 --------------------------------------------------------------------------------------------------------------
216 function Astrolabe
:ComputeDistance( c1
, z1
, x1
, y1
, c2
, z2
, x2
, y2
)
217 QuestHelper
: Assert(c1
and z1
and x1
and y1
and c2
and z2
and x2
and y2
)
219 argcheck(c1, 2, "number");
220 assert(3, c1 >= 0, "ComputeDistance: Illegal continent index to c1: "..c1);
221 argcheck(z1, 3, "number", "nil");
222 argcheck(x1, 4, "number");
223 argcheck(y1, 5, "number");
224 argcheck(c2, 6, "number");
225 assert(3, c2 >= 0, "ComputeDistance: Illegal continent index to c2: "..c2);
226 argcheck(z2, 7, "number", "nil");
227 argcheck(x2, 8, "number");
228 argcheck(y2, 9, "number");
234 local dist
, xDelta
, yDelta
;
235 if ( c1
== c2
and z1
== z2
) then
236 -- points in the same zone
237 local zoneData
= WorldMapSize
[c1
];
239 zoneData
= zoneData
[z1
];
241 xDelta
= (x2
- x1
) * zoneData
.width
;
242 yDelta
= (y2
- y1
) * zoneData
.height
;
244 elseif ( c1
== c2
) then
245 -- points on the same continent
246 local zoneData
= WorldMapSize
[c1
];
247 x1
, y1
= getContPosition(zoneData
, z1
, x1
, y1
);
248 x2
, y2
= getContPosition(zoneData
, z2
, x2
, y2
);
252 elseif ( c1
and c2
) then
253 local cont1
= WorldMapSize
[c1
];
254 local cont2
= WorldMapSize
[c2
];
255 if ( cont1
.parentContinent
== cont2
.parentContinent
) then
256 x1
, y1
= getContPosition(cont1
, z1
, x1
, y1
);
257 x2
, y2
= getContPosition(cont2
, z2
, x2
, y2
);
258 if ( c1
~= cont1
.parentContinent
) then
259 x1
= x1
+ cont1
.xOffset
;
260 y1
= y1
+ cont1
.yOffset
;
262 if ( c2
~= cont2
.parentContinent
) then
263 x2
= x2
+ cont2
.xOffset
;
264 y2
= y2
+ cont2
.yOffset
;
272 if ( xDelta
and yDelta
) then
273 dist
= sqrt(xDelta
*xDelta
+ yDelta
*yDelta
);
275 return dist
, xDelta
, yDelta
;
278 function Astrolabe
:TranslateWorldMapPosition( C
, Z
, xPos
, yPos
, nC
, nZ
)
280 argcheck(C, 2, "number");
281 argcheck(Z, 3, "number", "nil");
282 argcheck(xPos, 4, "number");
283 argcheck(yPos, 5, "number");
284 argcheck(nC, 6, "number");
285 argcheck(nZ, 7, "number", "nil");
290 if ( nC
< 0 and nC
> -77 ) then
295 if ( C
== nC
and Z
== nZ
) then
298 elseif ( C
== nC
) then
299 -- points on the same continent
300 zoneData
= WorldMapSize
[C
];
301 xPos
, yPos
= getContPosition(zoneData
, Z
, xPos
, yPos
);
303 zoneData
= WorldMapSize
[C
][nZ
];
304 xPos
= xPos
- zoneData
.xOffset
;
305 yPos
= yPos
- zoneData
.yOffset
;
308 elseif ( C
and nC
) and ( WorldMapSize
[C
].parentContinent
== WorldMapSize
[nC
].parentContinent
) then
309 -- different continents, same world
310 zoneData
= WorldMapSize
[C
];
311 local parentContinent
= zoneData
.parentContinent
;
312 xPos
, yPos
= getContPosition(zoneData
, Z
, xPos
, yPos
);
313 if not xPos
or not yPos
then return end -- there is no such zone. why are you asking me such silly things? you are a terrible person. leave me in my despair.
314 if ( C
~= parentContinent
) then
315 -- translate up to world map if we aren't there already
316 xPos
= xPos
+ zoneData
.xOffset
;
317 yPos
= yPos
+ zoneData
.yOffset
;
318 zoneData
= WorldMapSize
[parentContinent
];
320 if ( nC
~= parentContinent
) then
321 -- translate down to the new continent
322 zoneData
= WorldMapSize
[nC
];
323 xPos
= xPos
- zoneData
.xOffset
;
324 yPos
= yPos
- zoneData
.yOffset
;
326 zoneData
= zoneData
[nZ
];
327 xPos
= xPos
- zoneData
.xOffset
;
328 yPos
= yPos
- zoneData
.yOffset
;
336 return (xPos
/ zoneData
.width
), (yPos
/ zoneData
.height
);
339 function Astrolabe
:GetAbsoluteContinentPosition( C
, Z
, xPos
, yPos
)
340 if C
== -1 then -- We're in a battleground that doesn't have a virtual continent, we're just kind of fucked.
344 assert(0, type(WorldMapSize
[C
].parentContinent
) == "number")
346 local x
, y
= Astrolabe
:TranslateWorldMapPosition(C
, Z
, xPos
, yPos
, WorldMapSize
[C
].parentContinent
, 0)
347 if not x
or not y
then return end
348 local zoneData
= WorldMapSize
[WorldMapSize
[C
].parentContinent
]
349 return WorldMapSize
[C
].parentContinent
, (x
* zoneData
.width
), (y
* zoneData
.height
)
352 function Astrolabe
:FromAbsoluteContinentPosition(C
, xPos
, yPos
)
353 return C
, xPos
/ WorldMapSize
[C
].width
, yPos
/ WorldMapSize
[C
].height
356 function Astrolabe
:GetZoneWidth(c
, z
)
358 return WorldMapSize
[c
][z
].width
360 return WorldMapSize
[c
].width
364 --*****************************************************************************
365 -- This function will do its utmost to retrieve some sort of valid position
366 -- for the specified unit, including changing the current map zoom (if needed).
367 -- Map Zoom is returned to its previous setting before this function returns.
368 --*****************************************************************************
369 function Astrolabe
:GetUnitPosition( unit
, noMapChange
)
370 local x
, y
= GetPlayerMapPosition(unit
);
371 if ( x
<= 0 and y
<= 0 ) then
372 if ( noMapChange
) then
373 -- no valid position on the current map, and we aren't allowed
374 -- to change map zoom, so return
377 local lastCont
, lastZone
= GetCurrentMapContinent(), GetCurrentMapZone();
378 SetMapToCurrentZone();
379 x
, y
= GetPlayerMapPosition(unit
);
380 if ( x
<= 0 and y
<= 0 ) then
381 SetMapZoom(GetCurrentMapContinent());
382 x
, y
= GetPlayerMapPosition(unit
);
383 if ( x
<= 0 and y
<= 0 ) then
384 -- we are in an instance or otherwise off the continent map
388 local C
, Z
= GetCurrentMapContinent(), GetCurrentMapZone();
389 if ( C
~= lastCont
or Z
~= lastZone
) then
390 SetMapZoom(lastCont
, lastZone
); -- set map zoom back to what it was before
394 return self
:GetCurrentVirtualMapContinent(), self
:GetCurrentVirtualMapZone(), x
, y
;
397 --*****************************************************************************
398 -- This function will do its utmost to retrieve some sort of valid position
399 -- for the specified unit, including changing the current map zoom (if needed).
400 -- However, if a monitored WorldMapFrame (See AstrolabeMapMonitor.lua) is
401 -- visible, then will simply return nil if the current zoom does not provide
402 -- a valid position for the player unit. Map Zoom is returned to its previous
403 -- setting before this function returns, if it was changed.
404 --*****************************************************************************
405 function Astrolabe
:GetCurrentPlayerPosition()
406 local x
, y
= GetPlayerMapPosition("player");
407 if ( x
<= 0 and y
<= 0 ) then
408 if ( self
.WorldMapVisible
) then
409 -- we know there is a visible world map, so don't cause
410 -- WORLD_MAP_UPDATE events by changing map zoom
413 local lastCont
, lastZone
= GetCurrentMapContinent(), GetCurrentMapZone();
414 SetMapToCurrentZone();
415 x
, y
= GetPlayerMapPosition("player");
416 if ( x
<= 0 and y
<= 0 ) then
417 SetMapZoom(GetCurrentMapContinent());
418 x
, y
= GetPlayerMapPosition("player");
419 if ( x
<= 0 and y
<= 0 ) then
420 -- we are in an instance or otherwise off the continent map
424 local C
, Z
= GetCurrentMapContinent(), GetCurrentMapZone();
426 if ( C
~= lastCont
or Z
~= lastZone
) then
427 SetMapZoom(lastCont
, lastZone
); --set map zoom back to what it was before
432 return self
:GetCurrentVirtualMapContinent(), self
:GetCurrentVirtualMapZone(), x
, y
;
436 --------------------------------------------------------------------------------------------------------------
437 -- Working Table Cache System
438 --------------------------------------------------------------------------------------------------------------
440 local tableCache
= {};
441 tableCache
["__mode"] = "v";
442 setmetatable(tableCache
, tableCache
);
444 local function GetWorkingTable( icon
)
445 if ( tableCache
[icon
] ) then
446 return tableCache
[icon
];
449 tableCache
[icon
] = T
;
455 --------------------------------------------------------------------------------------------------------------
456 -- Minimap Icon Placement
457 --------------------------------------------------------------------------------------------------------------
459 --*****************************************************************************
460 -- local variables specifically for use in this section
461 --*****************************************************************************
462 local minimapRotationEnabled
= false;
463 local minimapShape
= false;
465 local MinimapCompassTexture
= MinimapCompassTexture
;
466 local MinimapCompassRing
= MiniMapCompassRing
;
467 function Astrolabe
:GetFacing()
468 if MinimapCompassRing
then -- 3.1 hackery
469 return MinimapCompassRing
:GetFacing()
471 return -GetPlayerFacing()
474 local minimapRotationOffset
= -Astrolabe
.GetFacing()
476 local function placeIconOnMinimap( minimap
, minimapZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
)
478 if ( Astrolabe
.minimapOutside
) then
479 mapDiameter
= MinimapSize
.outdoor
[minimapZoom
];
481 mapDiameter
= MinimapSize
.indoor
[minimapZoom
];
483 local mapRadius
= mapDiameter
/ 2;
484 local xScale
= mapDiameter
/ mapWidth
;
485 local yScale
= mapDiameter
/ mapHeight
;
486 local iconDiameter
= ((icon
:GetWidth() / 2) + 3) * xScale
;
487 local iconOnEdge
= nil;
488 local isRound
= true;
490 if ( minimapRotationEnabled
) then
491 local sinTheta
= sin(minimapRotationOffset
)
492 local cosTheta
= cos(minimapRotationOffset
)
495 The math that is acutally going on in the next 3 lines is:
496 local dx, dy = xDist, -yDist
497 xDist = (dx * cosTheta) + (dy * sinTheta)
498 yDist = -((-dx * sinTheta) + (dy * cosTheta))
500 This is because the origin for map coordinates is the top left corner
501 of the map, not the bottom left, and so we have to reverse the vertical
502 distance when doing the our rotation, and then reverse the result vertical
503 distance because this rotation formula gives us a result with the origin based
504 in the bottom left corner (of the (+, +) quadrant).
505 The actual code is a simplification of the above.
507 local dx
, dy
= xDist
, yDist
508 xDist
= (dx
* cosTheta
) - (dy
* sinTheta
)
509 yDist
= (dx
* sinTheta
) + (dy
* cosTheta
)
512 if ( minimapShape
and not (xDist
== 0 or yDist
== 0) ) then
513 isRound
= (xDist
< 0) and 1 or 3;
514 if ( yDist
< 0 ) then
515 isRound
= minimapShape
[isRound
];
517 isRound
= minimapShape
[isRound
+ 1];
521 -- for non-circular portions of the Minimap edge
522 if not ( isRound
) then
523 dist
= max(abs(xDist
), abs(yDist
))
526 if ( (dist
+ iconDiameter
) > mapRadius
) then
527 -- position along the outside of the Minimap
529 local factor
= (mapRadius
- iconDiameter
) / dist
;
530 xDist
= xDist
* factor
;
531 yDist
= yDist
* factor
;
534 if ( Astrolabe
.IconsOnEdge
[icon
] ~= iconOnEdge
) then
535 Astrolabe
.IconsOnEdge
[icon
] = iconOnEdge
;
536 Astrolabe
.IconsOnEdgeChanged
= true;
539 icon
:ClearAllPoints();
540 icon
:SetPoint("CENTER", minimap
, "CENTER", xDist
/xScale
, -yDist
/yScale
);
543 function Astrolabe
:PlaceIconOnMinimap( icon
, continent
, zone
, xPos
, yPos
)
544 -- check argument types
545 argcheck(icon
, 2, "table");
546 assert(3, icon
.SetPoint
and icon
.ClearAllPoints
, "Usage Message");
547 argcheck(continent
, 3, "number");
548 argcheck(zone
, 4, "number", "nil");
549 argcheck(xPos
, 5, "number");
550 argcheck(yPos
, 6, "number");
552 local lC
, lZ
, lx
, ly
= unpack(self
.LastPlayerPosition
);
553 local dist
, xDist
, yDist
= self
:ComputeDistance(lC
, lZ
, lx
, ly
, continent
, zone
, xPos
, yPos
);
555 --icon's position has no meaningful position relative to the player's current location
559 local iconData
= GetWorkingTable(icon
);
560 if ( self
.MinimapIcons
[icon
] ) then
561 self
.MinimapIcons
[icon
] = nil;
563 self
.MinimapIconCount
= self
.MinimapIconCount
+ 1
566 -- We know this icon's position is valid, so we need to make sure the icon placement
567 -- system is active. We call this here so that if this is the first icon being added to
568 -- an empty buffer, the full recalc will not completely redo the work done by this function
569 -- because the icon has not yet actually been placed in the buffer.
570 self
.processingFrame
:Show()
572 AddedOrUpdatedIcons
[icon
] = iconData
573 iconData
.continent
= continent
;
574 iconData
.zone
= zone
;
575 iconData
.xPos
= xPos
;
576 iconData
.yPos
= yPos
;
577 iconData
.dist
= dist
;
578 iconData
.xDist
= xDist
;
579 iconData
.yDist
= yDist
;
581 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
582 if ( minimapRotationEnabled
) then
583 minimapRotationOffset
= -Astrolabe
.GetFacing()
586 -- check Minimap Shape
587 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
589 -- place the icon on the Minimap and :Show() it
591 placeIconOnMinimap(map
, map
:GetZoom(), map
:GetWidth(), map
:GetHeight(), icon
, dist
, xDist
, yDist
);
597 function Astrolabe
:RemoveIconFromMinimap( icon
)
598 if not ( self
.MinimapIcons
[icon
] ) then
601 AddedOrUpdatedIcons
[icon
] = nil
602 self
.MinimapIcons
[icon
] = nil;
603 self
.IconsOnEdge
[icon
] = nil;
606 local MinimapIconCount
= self
.MinimapIconCount
- 1
607 if ( MinimapIconCount
<= 0 ) then
608 -- no icons left to manage
609 self
.processingFrame
:Hide()
610 MinimapIconCount
= 0 -- because I'm paranoid
612 self
.MinimapIconCount
= MinimapIconCount
617 function Astrolabe
:RemoveAllMinimapIcons()
618 self
:DumpNewIconsCache()
619 local MinimapIcons
= self
.MinimapIcons
;
620 local IconsOnEdge
= self
.IconsOnEdge
;
621 for k
, v
in pairs(MinimapIcons
) do
622 MinimapIcons
[k
] = nil;
623 IconsOnEdge
[k
] = nil;
626 self
.MinimapIconCount
= 0
627 self
.processingFrame
:Hide()
630 local lastZoom
; -- to remember the last seen Minimap zoom level
632 -- local variables to track the status of the two update coroutines
633 local fullUpdateInProgress
= true
634 local resetIncrementalUpdate
= false
635 local resetFullUpdate
= false
637 -- Incremental Update Code
639 -- local variables to track the incremental update coroutine
640 local incrementalUpdateCrashed
= true
641 local incrementalUpdateThread
643 local function UpdateMinimapIconPositions( self
)
647 self
:DumpNewIconsCache() -- put new/updated icons into the main datacache
649 resetIncrementalUpdate
= false -- by definition, the incremental update is reset if it is here
651 local C
, Z
, x
, y
= self
:GetCurrentPlayerPosition();
652 if ( C
and C
~= -1 ) then
653 local lastPosition
= self
.LastPlayerPosition
;
654 local lC
, lZ
, lx
, ly
= unpack(lastPosition
);
656 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
657 if ( minimapRotationEnabled
) then
658 minimapRotationOffset
= -Astrolabe
.GetFacing()
661 -- check current frame rate
662 local numPerCycle
= min(50, GetFramerate() * (self
.MinimapUpdateMultiplier
or 1))
664 -- check Minimap Shape
665 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
667 if ( lC
== C
and lZ
== Z
and lx
== x
and ly
== y
) then
668 -- player has not moved since the last update
669 if ( lastZoom
~= Minimap
:GetZoom() or self
.ForceNextUpdate
or minimapRotationEnabled
) then
670 local currentZoom
= Minimap
:GetZoom();
671 lastZoom
= currentZoom
;
672 local mapWidth
= Minimap
:GetWidth();
673 local mapHeight
= Minimap
:GetHeight();
674 numPerCycle
= numPerCycle
* 2
676 for icon
, data
in pairs(self
.MinimapIcons
) do
677 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, data
.dist
, data
.xDist
, data
.yDist
);
680 if ( count
> numPerCycle
) then
683 -- check if the incremental update cycle needs to be reset
684 -- because a full update has been run
685 if ( resetIncrementalUpdate
) then
690 self
.ForceNextUpdate
= false;
693 local dist
, xDelta
, yDelta
= self
:ComputeDistance(lC
, lZ
, lx
, ly
, C
, Z
, x
, y
);
695 local currentZoom
= Minimap
:GetZoom();
696 lastZoom
= currentZoom
;
697 local mapWidth
= Minimap
:GetWidth();
698 local mapHeight
= Minimap
:GetHeight();
700 for icon
, data
in pairs(self
.MinimapIcons
) do
701 local xDist
= data
.xDist
- xDelta
;
702 local yDist
= data
.yDist
- yDelta
;
703 local dist
= sqrt(xDist
*xDist
+ yDist
*yDist
);
704 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
);
711 if ( count
>= numPerCycle
) then
714 -- check if the incremental update cycle needs to be reset
715 -- because a full update has been run
716 if ( resetIncrementalUpdate
) then
721 if not ( resetIncrementalUpdate
) then
728 self
:RemoveAllMinimapIcons()
736 if not ( self
.WorldMapVisible
) then
737 self
.processingFrame
:Hide();
741 -- if we've been reset, then we want to start the new cycle immediately
742 if not ( resetIncrementalUpdate
) then
748 function Astrolabe
:UpdateMinimapIconPositions()
749 if ( fullUpdateInProgress
) then
750 -- if we're in the middle a a full update, we want to finish that first
751 self
:CalculateMinimapIconPositions()
753 if ( incrementalUpdateCrashed
) then
754 incrementalUpdateThread
= coroutine
.wrap(UpdateMinimapIconPositions
)
755 incrementalUpdateThread(self
) --initialize the thread
757 incrementalUpdateCrashed
= true
758 incrementalUpdateThread()
759 incrementalUpdateCrashed
= false
766 -- local variables to track the full update coroutine
767 local fullUpdateCrashed
= true
768 local fullUpdateThread
770 local function CalculateMinimapIconPositions( self
)
774 self
:DumpNewIconsCache() -- put new/updated icons into the main datacache
776 resetFullUpdate
= false -- by definition, the full update is reset if it is here
778 fullUpdateInProgress
= true -- set the flag the says a full update is in progress
780 local C
, Z
, x
, y
= self
:GetCurrentPlayerPosition();
781 if ( C
and C
~= -1 ) then
782 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
783 if ( minimapRotationEnabled
) then
784 minimapRotationOffset
= Astrolabe
.GetFacing()
787 -- check current frame rate
788 local numPerCycle
= GetFramerate() * (self
.MinimapUpdateMultiplier
or 1) * 2
790 -- check Minimap Shape
791 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
793 local currentZoom
= Minimap
:GetZoom();
794 lastZoom
= currentZoom
;
795 local mapWidth
= Minimap
:GetWidth();
796 local mapHeight
= Minimap
:GetHeight();
798 for icon
, data
in pairs(self
.MinimapIcons
) do
799 local dist
, xDist
, yDist
= self
:ComputeDistance(C
, Z
, x
, y
, data
.continent
, data
.zone
, data
.xPos
, data
.yPos
);
801 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
);
807 self
:RemoveIconFromMinimap(icon
)
811 if ( count
>= numPerCycle
) then
814 -- check if we need to restart due to the full update being reset
815 if ( resetFullUpdate
) then
821 if not ( resetFullUpdate
) then
822 local lastPosition
= self
.LastPlayerPosition
;
828 resetIncrementalUpdate
= true
831 if not ( self
.WorldMapVisible
) then
832 self
.processingFrame
:Hide();
836 -- if we've been reset, then we want to start the new cycle immediately
837 if not ( resetFullUpdate
) then
838 fullUpdateInProgress
= false
844 function Astrolabe
:CalculateMinimapIconPositions( reset
)
845 if ( fullUpdateCrashed
) then
846 fullUpdateThread
= coroutine
.wrap(CalculateMinimapIconPositions
)
847 fullUpdateThread(self
) --initialize the thread
848 elseif ( reset
) then
849 resetFullUpdate
= true
851 fullUpdateCrashed
= true
853 fullUpdateCrashed
= false
855 -- return result flag
856 if ( fullUpdateInProgress
) then
857 return 1 -- full update started, but did not complete on this cycle
860 if ( resetIncrementalUpdate
) then
861 return 0 -- update completed
863 return -1 -- full update did no occur for some reason
870 function Astrolabe
:GetDistanceToIcon( icon
)
871 local data
= self
.MinimapIcons
[icon
];
873 return data
.dist
, data
.xDist
, data
.yDist
;
877 function Astrolabe
:IsIconOnEdge( icon
)
878 return self
.IconsOnEdge
[icon
];
881 function Astrolabe
:GetDirectionToIcon( icon
)
882 local data
= self
.MinimapIcons
[icon
];
884 local dir
= atan2(data
.xDist
, -(data
.yDist
))
893 function Astrolabe
:Register_OnEdgeChanged_Callback( func
, ident
)
894 -- check argument types
895 argcheck(func
, 2, "function");
897 self
.IconsOnEdge_GroupChangeCallbacks
[func
] = ident
;
900 --*****************************************************************************
901 -- INTERNAL USE ONLY PLEASE!!!
902 -- Calling this function at the wrong time can cause errors
903 --*****************************************************************************
904 function Astrolabe
:DumpNewIconsCache()
905 local MinimapIcons
= self
.MinimapIcons
906 for icon
, data
in pairs(AddedOrUpdatedIcons
) do
907 MinimapIcons
[icon
] = data
908 AddedOrUpdatedIcons
[icon
] = nil
910 -- we now need to restart any updates that were in progress
911 resetIncrementalUpdate
= true
912 resetFullUpdate
= true
916 --------------------------------------------------------------------------------------------------------------
917 -- World Map Icon Placement
918 --------------------------------------------------------------------------------------------------------------
920 function Astrolabe
:PlaceIconOnWorldMap( worldMapFrame
, icon
, continent
, zone
, xPos
, yPos
)
921 -- check argument types
922 argcheck(worldMapFrame
, 2, "table");
923 assert(3, worldMapFrame
.GetWidth
and worldMapFrame
.GetHeight
, "Usage Message");
924 argcheck(icon
, 3, "table");
925 assert(3, icon
.SetPoint
and icon
.ClearAllPoints
, "Usage Message");
926 argcheck(continent
, 4, "number");
927 argcheck(zone
, 5, "number", "nil");
928 argcheck(xPos
, 6, "number");
929 argcheck(yPos
, 7, "number");
931 local C
, Z
= self
:GetCurrentVirtualMapCZ();
932 local nX
, nY
= self
:TranslateWorldMapPosition(continent
, zone
, xPos
, yPos
, C
, Z
);
934 -- anchor and :Show() the icon if it is within the boundry of the current map, :Hide() it otherwise
935 if ( nX
and nY
and (0 < nX
and nX
<= 1) and (0 < nY
and nY
<= 1) ) then
936 icon
:ClearAllPoints();
937 icon
:SetPoint("CENTER", worldMapFrame
, "TOPLEFT", nX
* worldMapFrame
:GetWidth(), -nY
* worldMapFrame
:GetHeight());
946 --------------------------------------------------------------------------------------------------------------
948 --------------------------------------------------------------------------------------------------------------
950 function Astrolabe
:OnEvent( frame
, event
)
951 if ( event
== "MINIMAP_UPDATE_ZOOM" ) then
952 -- update minimap zoom scale
953 local curZoom
= Minimap
:GetZoom();
954 if ( GetCVar("minimapZoom") == GetCVar("minimapInsideZoom") ) then
955 if ( curZoom
< 2 ) then
956 Minimap
:SetZoom(curZoom
+ 1);
958 Minimap
:SetZoom(curZoom
- 1);
961 if ( GetCVar("minimapZoom")+0 == Minimap
:GetZoom() ) then
962 self
.minimapOutside
= true;
964 self
.minimapOutside
= false;
966 Minimap
:SetZoom(curZoom
);
968 -- re-calculate all Minimap Icon positions
969 if ( frame
:IsVisible() ) then
970 self
:CalculateMinimapIconPositions(true);
973 elseif ( event
== "PLAYER_LEAVING_WORLD" ) then
974 frame
:Hide(); -- yes, I know this is redunant
975 self
:RemoveAllMinimapIcons(); --dump all minimap icons
977 elseif ( event
== "PLAYER_ENTERING_WORLD" ) then
979 if not ( frame
:IsVisible() ) then
980 -- do the minimap recalculation anyways if the OnShow script didn't execute
981 -- this is done to ensure the accuracy of information about icons that were
982 -- inserted while the Player was in the process of zoning
983 self
:CalculateMinimapIconPositions(true);
986 elseif ( event
== "ZONE_CHANGED_NEW_AREA" ) then
993 function Astrolabe
:OnUpdate( frame
, elapsed
)
994 -- on-edge group changed call-backs
995 if ( self
.IconsOnEdgeChanged
) then
996 self
.IconsOnEdgeChanged
= false;
997 for func
in pairs(self
.IconsOnEdge_GroupChangeCallbacks
) do
1002 self
:UpdateMinimapIconPositions();
1005 function Astrolabe
:OnShow( frame
)
1006 -- set the world map to a zoom with a valid player position
1007 if not ( self
.WorldMapVisible
) then
1008 SetMapToCurrentZone();
1010 local C
, Z
= Astrolabe
:GetCurrentPlayerPosition();
1011 if ( C
and C
~= -1 ) then
1012 if C
>= 0 then -- If we're in Wackyland, we can't change the world map anyway, so at least it's probably right
1020 -- re-calculate minimap icon positions
1021 self
:CalculateMinimapIconPositions(true);
1023 if ( self
.MinimapIconCount
<= 0 ) then
1024 -- no icons left to manage
1025 self
.processingFrame
:Hide()
1029 -- called by AstrolabMapMonitor when all world maps are hidden
1030 function Astrolabe
:AllWorldMapsHidden()
1031 if ( IsLoggedIn() ) then
1032 self
.processingFrame
:Hide();
1033 self
.processingFrame
:Show();
1037 function Astrolabe
:SetMinimapObject(minimap
)
1039 self
:UpdateMinimapIconPositions()
1042 --------------------------------------------------------------------------------------------------------------
1043 -- Library Registration
1044 --------------------------------------------------------------------------------------------------------------
1046 local function activate( newInstance
, oldInstance
)
1047 if ( oldInstance
) then -- this is an upgrade activate
1048 if ( oldInstance
.DumpNewIconsCache
) then
1049 oldInstance
:DumpNewIconsCache()
1051 for k
, v
in pairs(oldInstance
) do
1052 if ( type(v
) ~= "function" and (not configConstants
[k
]) ) then
1056 -- sync up the current MinimapIconCount value
1058 for _
in pairs(newInstance
.MinimapIcons
) do
1059 iconCount
= iconCount
+ 1
1061 newInstance
.MinimapIconCount
= iconCount
1063 Astrolabe
= oldInstance
;
1065 local frame
= CreateFrame("Frame");
1066 newInstance
.processingFrame
= frame
;
1068 newInstance
.ContinentList
= Astrolabe
:GetMapVirtualContinents();
1070 for C
in pairs(newInstance
.ContinentList
) do
1071 local zones
= Astrolabe
:GetMapVirtualZones(C
);
1072 newInstance
.ContinentList
[C
] = zones
;
1073 for Z
in ipairs(zones
) do
1074 zones
[Z
] = Astrolabe
:GetMapTexture(C
, Z
);
1078 configConstants
= nil -- we don't need this anymore
1080 local frame
= newInstance
.processingFrame
;
1082 frame
:SetParent("Minimap");
1083 frame
:UnregisterAllEvents();
1084 frame
:RegisterEvent("MINIMAP_UPDATE_ZOOM");
1085 frame
:RegisterEvent("PLAYER_LEAVING_WORLD");
1086 frame
:RegisterEvent("PLAYER_ENTERING_WORLD");
1087 frame
:RegisterEvent("ZONE_CHANGED_NEW_AREA");
1088 frame
:SetScript("OnEvent",
1089 function( frame
, event
, ... )
1090 Astrolabe
:OnEvent(frame
, event
, ...);
1093 frame
:SetScript("OnUpdate",
1094 function( frame
, elapsed
)
1095 Astrolabe
:OnUpdate(frame
, elapsed
);
1098 frame
:SetScript("OnShow",
1100 Astrolabe
:OnShow(frame
);
1104 setmetatable(Astrolabe
.MinimapIcons
, MinimapIconsMetatable
)
1107 --------------------------------------------------------------------------------------------------------------
1109 --------------------------------------------------------------------------------------------------------------
1111 -- diameter of the Minimap in game yards at
1112 -- the various possible zoom levels
1123 [0] = 466 + 2/3, -- scale
1125 [2] = 333 + 1/3, -- 1.4
1126 [3] = 266 + 2/6, -- 1.75
1128 [5] = 133 + 1/3, -- 3.5
1132 ValidMinimapShapes
= {
1133 -- { upper-left, lower-left, upper-right, lower-right }
1134 ["SQUARE"] = { false, false, false, false },
1135 ["CORNER-TOPLEFT"] = { true, false, false, false },
1136 ["CORNER-TOPRIGHT"] = { false, false, true, false },
1137 ["CORNER-BOTTOMLEFT"] = { false, true, false, false },
1138 ["CORNER-BOTTOMRIGHT"] = { false, false, false, true },
1139 ["SIDE-LEFT"] = { true, true, false, false },
1140 ["SIDE-RIGHT"] = { false, false, true, true },
1141 ["SIDE-TOP"] = { true, false, true, false },
1142 ["SIDE-BOTTOM"] = { false, true, false, true },
1143 ["TRICORNER-TOPLEFT"] = { true, true, true, false },
1144 ["TRICORNER-TOPRIGHT"] = { true, false, true, true },
1145 ["TRICORNER-BOTTOMLEFT"] = { true, true, false, true },
1146 ["TRICORNER-BOTTOMRIGHT"] = { false, true, true, true },
1149 -- distances across and offsets of the world maps
1152 -- World Map of Azeroth
1154 parentContinent
= 0,
1155 height
= 29688.932932224,
1156 width
= 44537.340058402,
1160 parentContinent
= 0,
1161 height
= 24533.025279205,
1162 width
= 36800.210572494,
1163 xOffset
= -8311.793923510446,
1164 yOffset
= 1815.215685280706,
1167 height
= 3843.722811451077,
1168 width
= 5766.728884700476,
1169 xOffset
= 15366.76755576002,
1170 yOffset
= 8126.925260781192,
1174 height
= 3381.225696279877,
1175 width
= 5070.888165752819,
1176 xOffset
= 20343.90485013144,
1177 yOffset
= 7458.180046130774,
1181 height
= 2714.561862167815,
1182 width
= 4070.883253576282,
1183 xOffset
= 9966.70736478994,
1184 yOffset
= 5460.278138661794,
1188 height
= 6756.202067150937,
1189 width
= 10133.44343943073,
1190 xOffset
= 14443.84117394525,
1191 yOffset
= 11187.32013604393,
1195 height
= 2174.984710698752,
1196 width
= 3262.517428121028,
1197 xOffset
= 9541.713418184554,
1198 yOffset
= 3424.874558234072,
1202 height
= 4366.636219106706,
1203 width
= 6550.06962983463,
1204 xOffset
= 14125.08809600818,
1205 yOffset
= 4466.534412478246,
1209 height
= 705.7248633938184,
1210 width
= 1058.342927027606,
1211 xOffset
= 14128.39258617903,
1212 yOffset
= 2561.565012455802,
1216 height
= 2997.895174253872,
1217 width
= 4495.882023201739,
1218 xOffset
= 12833.40729836031,
1219 yOffset
= 12347.72848626745,
1223 height
= 3524.975114832228,
1224 width
= 5287.558038649864,
1225 xOffset
= 19029.30699887344,
1226 yOffset
= 10991.48801260963,
1230 height
= 3499.975146240067,
1231 width
= 5250.057259791282,
1232 xOffset
= 18041.79657043901,
1233 yOffset
= 14833.12751666842,
1237 height
= 3833.305958270781,
1238 width
= 5750.062034325837,
1239 xOffset
= 15425.10163773161,
1240 yOffset
= 5666.526367166872,
1244 height
= 4633.30011661694,
1245 width
= 6950.075260353015,
1246 xOffset
= 11625.06045254075,
1247 yOffset
= 15166.45834829251,
1251 height
= 1539.572509508711,
1252 width
= 2308.356845256911,
1253 xOffset
= 18448.05172159372,
1254 yOffset
= 4308.20254319874,
1258 height
= 3424.975945100366,
1259 width
= 5137.555355060729,
1260 xOffset
= 15018.84750987729,
1261 yOffset
= 13072.72336630089,
1265 height
= 935.4100697456119,
1266 width
= 1402.621211455915,
1267 xOffset
= 20747.42666130799,
1268 yOffset
= 10525.94769396873,
1272 height
= 2322.899061688691,
1273 width
= 3483.371975265956,
1274 xOffset
= 14529.25864164056,
1275 yOffset
= 18758.10068625832,
1278 StonetalonMountains
= {
1279 height
= 3256.226691571251,
1280 width
= 4883.385977951072,
1281 xOffset
= 13820.91773479217,
1282 yOffset
= 9883.162892509636,
1286 height
= 4599.965662459992,
1287 width
= 6900.073766103516,
1288 xOffset
= 17285.539010128,
1289 yOffset
= 18674.7673661939,
1293 height
= 3393.726923234355,
1294 width
= 5091.720903621394,
1295 xOffset
= 13252.16205313556,
1296 yOffset
= 968.6418744503761,
1300 height
= 704.6826864472878,
1301 width
= 1056.781131437323,
1302 xOffset
= 10533.08314172693,
1303 yOffset
= 6276.205331713322,
1307 height
= 2933.312180524323,
1308 width
= 4400.046681282484,
1309 xOffset
= 17500.12437633161,
1310 yOffset
= 16766.44698282704,
1314 height
= 695.8282721105132,
1315 width
= 1043.761263579803,
1316 xOffset
= 16550.11410485969,
1317 yOffset
= 13649.80260929285,
1321 height
= 2466.647220780505,
1322 width
= 3700.040077455555,
1323 xOffset
= 16533.44712326324,
1324 yOffset
= 18766.4334494793,
1328 height
= 4733.299561046713,
1329 width
= 7100.077599808275,
1330 xOffset
= 17383.45606038691,
1331 yOffset
= 4266.536453420381,
1338 parentContinent
= 0,
1339 height
= 27149.795290881,
1340 width
= 40741.175327834,
1341 xOffset
= 14407.1086092051,
1342 yOffset
= 290.3230897653046,
1345 height
= 1866.673586850316,
1346 width
= 2800.000436369314,
1347 xOffset
= 17388.63313899802,
1348 yOffset
= 9676.382605411302,
1352 height
= 2400.0092446309,
1353 width
= 3599.999380663208,
1354 xOffset
= 19038.63328411639,
1355 yOffset
= 11309.72201070757,
1359 height
= 1658.340965090961,
1360 width
= 2487.498490907989,
1361 xOffset
= 20251.1337564772,
1362 yOffset
= 17065.99404487956,
1366 height
= 2233.343415116865,
1367 width
= 3349.999381676505,
1368 xOffset
= 19413.63362865575,
1369 yOffset
= 21743.09582955139,
1373 height
= 1952.091972408385,
1374 width
= 2929.16694293186,
1375 xOffset
= 18438.633261567,
1376 yOffset
= 18207.66513379744,
1380 height
= 1666.673818905317,
1381 width
= 2499.999888210889,
1382 xOffset
= 19005.29993968603,
1383 yOffset
= 21043.0932328648,
1387 height
= 3283.345779814337,
1388 width
= 4924.998791911572,
1389 xOffset
= 16369.8840376619,
1390 yOffset
= 15053.48695195484,
1394 height
= 1800.007653419076,
1395 width
= 2699.999669551933,
1396 xOffset
= 17338.63354148773,
1397 yOffset
= 20893.09259181909,
1400 EasternPlaguelands
= {
1401 height
= 2687.510360231216,
1402 width
= 4031.249051993366,
1403 xOffset
= 20459.46801235962,
1404 yOffset
= 7472.207045901617,
1408 height
= 2314.591970284716,
1409 width
= 3470.831971412848,
1410 xOffset
= 16636.55099386465,
1411 yOffset
= 19116.0027890283,
1415 height
= 3283.346366715794,
1416 width
= 4924.998483501337,
1417 xOffset
= 20259.46725884782,
1418 yOffset
= 2534.687567863296,
1422 height
= 2200.008945183733,
1423 width
= 3300.002855743766,
1424 xOffset
= 21055.29786070095,
1425 yOffset
= 5309.698546426793,
1429 height
= 2133.341840477916,
1430 width
= 3200.000391416799,
1431 xOffset
= 17105.29968281043,
1432 yOffset
= 10776.38652289269,
1436 height
= 2566.676323518885,
1437 width
= 3849.998492380244,
1438 xOffset
= 19746.96704279287,
1439 yOffset
= 9709.715966757984,
1443 height
= 527.6056771582851,
1444 width
= 790.6252518322632,
1445 xOffset
= 18885.55815177769,
1446 yOffset
= 15745.64795436116,
1450 height
= 1839.590356444166,
1451 width
= 2758.33360594204,
1452 xOffset
= 20165.71623436714,
1453 yOffset
= 15663.90573348468,
1457 height
= 1447.922213393415,
1458 width
= 2170.833229570681,
1459 xOffset
= 19742.79960560691,
1460 yOffset
= 19751.42209395218,
1464 height
= 1487.505203229038,
1465 width
= 2231.250200533406,
1466 xOffset
= 18494.88325409831,
1467 yOffset
= 17276.41231120941,
1471 height
= 806.7751969249011,
1472 width
= 1211.458551923779,
1473 xOffset
= 22172.71573747824,
1474 yOffset
= 3422.647395021269,
1478 height
= 2800.011187621704,
1479 width
= 4200.000573479695,
1480 xOffset
= 14721.96646274185,
1481 yOffset
= 9509.714741967448,
1485 height
= 1158.33686894901,
1486 width
= 1737.498058940429,
1487 xOffset
= 16449.05164642256,
1488 yOffset
= 19172.25350774846,
1492 height
= 4254.18312444072,
1493 width
= 6381.248484543122,
1494 xOffset
= 15951.13375783437,
1495 yOffset
= 22345.18258706305,
1499 height
= 2218.756638064149,
1500 width
= 3327.084777999942,
1501 xOffset
= 21074.0484502027,
1502 yOffset
= 7.595267688679496,
1506 height
= 1529.173695058727,
1507 width
= 2293.753807610138,
1508 xOffset
= 20394.88183258176,
1509 yOffset
= 20797.25913588854,
1513 height
= 3012.510490816506,
1514 width
= 4518.749381850256,
1515 xOffset
= 15138.63417865412,
1516 yOffset
= 7338.874503644808,
1520 height
= 640.1067253394195,
1521 width
= 959.3752013853186,
1522 xOffset
= 17298.77399735696,
1523 yOffset
= 9298.435338905521,
1526 WesternPlaguelands
= {
1527 height
= 2866.677213191588,
1528 width
= 4299.998717025251,
1529 xOffset
= 17755.30067544475,
1530 yOffset
= 7809.708745090687,
1534 height
= 2333.342039971409,
1535 width
= 3500.001170481545,
1536 xOffset
= 15155.29922254704,
1537 yOffset
= 20576.42557120998,
1541 height
= 2756.260286844545,
1542 width
= 4135.414389381328,
1543 xOffset
= 18561.55091405621,
1544 yOffset
= 13324.31339403164,
1551 parentContinent
= 3,
1552 height
= 11642.355227091,
1553 width
= 17463.987300595,
1555 BladesEdgeMountains
= {
1556 height
= 3616.553511321226,
1557 width
= 5424.972055480694,
1558 xOffset
= 4150.184214583454,
1559 yOffset
= 1412.98225932006,
1563 height
= 3443.642450656037,
1564 width
= 5164.556104714847,
1565 xOffset
= 7456.417230912641,
1566 yOffset
= 4339.973750274888,
1570 height
= 3683.218538167106,
1571 width
= 5524.971495006054,
1572 xOffset
= 2700.192018521809,
1573 yOffset
= 5779.511974812862,
1577 height
= 3716.550608724641,
1578 width
= 5574.970083688359,
1579 xOffset
= 7512.667416095402,
1580 yOffset
= 365.0979827402549,
1583 ShadowmoonValley
= {
1584 height
= 3666.552070430093,
1585 width
= 5499.971770418525,
1586 xOffset
= 8770.993458280615,
1587 yOffset
= 7769.033264592288,
1591 height
= 870.8059516186869,
1592 width
= 1306.242821388422,
1593 xOffset
= 6860.744740098593,
1594 yOffset
= 7295.086120456203,
1598 height
= 3599.887783533737,
1599 width
= 5399.971351016305,
1600 xOffset
= 5912.675516998205,
1601 yOffset
= 6821.146319031154,
1605 height
= 3351.978710181591,
1606 width
= 5027.057650868489,
1607 xOffset
= 3521.020638264577,
1608 yOffset
= 3885.821278366336,
1615 --- WotLK Adjustments, now permanently enabled. Someday I should probably merge these in.
1617 WorldMapSize
[0].height
= 31809.64859753034;
1618 WorldMapSize
[0].width
= 47714.27770954026;
1620 WorldMapSize
[1].xOffset
= -8590.409362625034;
1621 WorldMapSize
[1].yOffset
= 5628.694276155668;
1623 WorldMapSize
[2].xOffset
= 18542.31268111796;
1624 WorldMapSize
[2].yOffset
= 3585.574682467752;
1628 parentContinent
= 0,
1629 height
= 11834.31067391958,
1630 width
= 17751.3936186856,
1631 xOffset
= 16020.94093549576,
1632 yOffset
= 454.2464807713226,
1635 height
= 3843.765503862232,
1636 width
= 5764.58206497758,
1637 xOffset
= 646.3186767730767,
1638 yOffset
= 5695.480016983896,
1641 CrystalsongForest
= {
1642 height
= 1814.590053385046,
1643 width
= 2722.916164555434,
1644 xOffset
= 7773.400227973558,
1645 yOffset
= 4091.307437548815,
1649 height
= 553.3419356683534,
1650 width
= 830.014625253355,
1651 xOffset
= 8164.640128758279,
1652 yOffset
= 4526.722218200071,
1656 height
= 3739.597759999098,
1657 width
= 5608.331259502691,
1658 xOffset
= 5590.067753073641,
1659 yOffset
= 5018.394106536425,
1663 height
= 3500.013349296343,
1664 width
= 5249.9986179934,
1665 xOffset
= 10327.56614428777,
1666 yOffset
= 5076.727864214266,
1670 height
= 4031.266275060274,
1671 width
= 6045.831339550668,
1672 xOffset
= 10615.0658552538,
1673 yOffset
= 7476.736868262738,
1677 height
= 4181.266519840844,
1678 width
= 6270.832975322177,
1679 xOffset
= 3773.401695036191,
1680 yOffset
= 1166.296622984233,
1684 height
= 1983.342901980711,
1685 width
= 2974.999377667768,
1686 xOffset
= 4887.984320612982,
1687 yOffset
= 4876.725348039468,
1691 height
= 2904.177559586215,
1692 width
= 4356.248328680455,
1693 xOffset
= 2287.985279107324,
1694 yOffset
= 3305.887993444818,
1698 height
= 4741.684940421732,
1699 width
= 7112.498205872217,
1700 xOffset
= 7375.483315518691,
1701 yOffset
= 395.4596828327046,
1705 height
= 3329.179510740043,
1706 width
= 4993.747919923504,
1707 xOffset
= 9817.150055203074,
1708 yOffset
= 2924.636381254688,
1711 HrothgarsLanding
= {
1714 xOffset
= 23967.599 - 17549.182,
1715 yOffset
= 1027.392 - 1215.431,
1720 local function VContinent(index
, name
, size
)
1721 assert(1, not WorldMapSize
[index
], "denied")
1723 WorldMapSize
[index
] = {
1724 parentContinent
= index
,
1729 WorldMapSize
[index
].zoneData
[name
] = {
1737 VContinent(-77, "ScarletEnclave", 2125)
1740 VContinent(-80, "UtgardeKeep1", 100) -- temporary value
1741 VContinent(-81, "UtgardeKeep2", 100) -- temporary value
1742 VContinent(-82, "UtgardeKeep3", 100) -- temporary value
1744 VContinent(-83, "TheNexus", 734.2)
1746 VContinent(-84, "AzjolNerub1", 100) -- temporary value
1747 VContinent(-85, "AzjolNerub2", 100) -- temporary value
1748 VContinent(-86, "AzjolNerub3", 100) -- temporary value
1750 VContinent(-87, "Ahnkahet", 648.3)
1752 VContinent(-88, "DrakTharonKeep1", 100) -- temporary value
1753 VContinent(-89, "DrakTharonKeep2", 100) -- temporary value
1755 VContinent(-90, "VioletHold", 170.83)
1757 VContinent(-91, "Gundrak", 603.35)
1759 VContinent(-92, "Ulduar77", 613.5) -- Halls of Stone
1761 VContinent(-93, "HallsofLightning1", 100) -- temporary value
1762 VContinent(-94, "HallsofLightning2", 100) -- temporary value
1764 VContinent(-95, "Nexus801", 100) -- temporary value -- Oculus
1765 VContinent(-96, "Nexus802", 100) -- temporary value
1766 VContinent(-97, "Nexus803", 100) -- temporary value
1767 VContinent(-98, "Nexus804", 100) -- temporary value
1769 VContinent(-99, "CoTStratholme1", 750.2)
1770 VContinent(-100, "CoTStratholme2", 1216.66)
1772 VContinent(-101, "UtgardePinnacle1", 100) -- temporary value -- hey they spelled it right
1773 VContinent(-102, "UtgardePinnacle2", 100) -- temporary value
1775 VContinent(-103, "VaultofArchavon", 603.25) -- temporary value -- Weirdly, Emalon is actually within the "Vault of Archavon"
1777 VContinent(-104, "Naxxramas1", 1237.5) -- construct quarter
1778 VContinent(-105, "Naxxramas2", 1237.5) -- arachnid quarter
1779 VContinent(-106, "Naxxramas3", 1237.5) -- military quarter
1780 VContinent(-107, "Naxxramas4", 1237.5) -- plague quarter
1781 VContinent(-108, "Naxxramas5", 1379.9) -- overview
1782 VContinent(-109, "Naxxramas6", 437.3) -- lair
1784 VContinent(-110, "TheObsidianSanctum", 775.1)
1786 VContinent(-111, "TheEyeOfEternity", 286.7)
1788 VContinent(-112, "Ulduar", 2191.7) -- temporary value
1789 VContinent(-113, "Ulduar1", 446.5) -- temporary value
1790 VContinent(-114, "Ulduar2", 885.6) -- temporary value
1791 VContinent(-115, "Ulduar3", 100) -- temporary value
1792 VContinent(-116, "Ulduar4", 100) -- temporary value
1794 VContinent(-117, "TheForgeofSouls", 965.4) -- temporary value
1795 VContinent(-118, "PitofSaron", 1022.3)
1798 VirtualContinentIndexes
= { -- Don't change values here, since programs might want to store them
1799 ["ScarletEnclave"] = -77,
1801 ["UtgardeKeep1"] = -80,
1802 ["UtgardeKeep2"] = -81,
1803 ["UtgardeKeep3"] = -82,
1807 ["AzjolNerub1"] = -84,
1808 ["AzjolNerub2"] = -85,
1809 ["AzjolNerub3"] = -86,
1813 ["DrakTharonKeep1"] = -88,
1814 ["DrakTharonKeep2"] = -89,
1816 ["VioletHold"] = -90,
1820 ["Ulduar77"] = -92, -- Halls of Stone
1822 ["HallsofLightning1"] = -93,
1823 ["HallsofLightning2"] = -94,
1825 ["Nexus801"] = -95, -- Oculus
1830 ["CoTStratholme1"] = -99,
1831 ["CoTStratholme2"] = -100,
1833 ["UtgardePinnacle1"] = -101, -- hey they spelled it right
1834 ["UtgardePinnacle2"] = -102,
1836 ["VaultofArchavon"] = -103, -- Weirdly, Emalon is actually within the "Vault of Archavon"
1838 ["Naxxramas1"] = -104,
1839 ["Naxxramas2"] = -105,
1840 ["Naxxramas3"] = -106,
1841 ["Naxxramas4"] = -107,
1842 ["Naxxramas5"] = -108,
1843 ["Naxxramas6"] = -109,
1845 ["TheObsidianSanctum"] = -110,
1847 ["TheEyeOfEternity"] = -111,
1855 ["TheForgeofSouls"] = -117,
1856 ["PitofSaron"] = -118,
1859 DongleStub
:Register(Astrolabe
, activate
)
1862 zeroData
= { xOffset
= 0, height
= 0, yOffset
= 0, width
= 0, __index
= function() return zeroData
end };
1863 setmetatable(zeroData
, zeroData
);
1864 setmetatable(WorldMapSize
, zeroData
);
1866 for continent
, zones
in pairs(Astrolabe
.ContinentList
) do
1867 local mapData
= WorldMapSize
[continent
];
1868 for index
, mapName
in pairs(zones
) do
1869 if not ( mapData
.zoneData
[mapName
] ) then
1870 --WE HAVE A PROBLEM!!!
1871 ChatFrame1
:AddMessage("Astrolabe is missing data for "..select(index
, GetMapZones(continent
))..".");
1872 mapData
.zoneData
[mapName
] = zeroData
;
1874 mapData
[index
] = mapData
.zoneData
[mapName
];
1875 mapData
.zoneData
[mapName
] = nil;
1880 -- register this library with AstrolabeMapMonitor, this will cause a full update if PLAYER_LOGIN has already fired
1881 local AstrolabeMapMonitor
= DongleStub("AstrolabeMapMonitor");
1882 AstrolabeMapMonitor
:RegisterAstrolabeLibrary(Astrolabe
, LIBRARY_VERSION_MAJOR
);
1885 QH_Astrolabe_Ready
= true