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
, 0, 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 function Astrolabe
:GetMapDiameter()
477 local minimapZoom
= Minimap
:GetZoom()
478 if ( Astrolabe
.minimapOutside
) then
479 return MinimapSize
.outdoor
[minimapZoom
];
481 return MinimapSize
.indoor
[minimapZoom
];
485 local function placeIconOnMinimap( minimap
, minimapZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
)
487 if ( Astrolabe
.minimapOutside
) then
488 mapDiameter
= MinimapSize
.outdoor
[minimapZoom
];
490 mapDiameter
= MinimapSize
.indoor
[minimapZoom
];
492 local mapRadius
= mapDiameter
/ 2;
493 local xScale
= mapDiameter
/ mapWidth
;
494 local yScale
= mapDiameter
/ mapHeight
;
495 local iconDiameter
= ((icon
:GetWidth() / 2) + 3) * xScale
;
496 local iconOnEdge
= nil;
497 local isRound
= true;
499 if ( minimapRotationEnabled
) then
500 local sinTheta
= sin(minimapRotationOffset
)
501 local cosTheta
= cos(minimapRotationOffset
)
504 The math that is acutally going on in the next 3 lines is:
505 local dx, dy = xDist, -yDist
506 xDist = (dx * cosTheta) + (dy * sinTheta)
507 yDist = -((-dx * sinTheta) + (dy * cosTheta))
509 This is because the origin for map coordinates is the top left corner
510 of the map, not the bottom left, and so we have to reverse the vertical
511 distance when doing the our rotation, and then reverse the result vertical
512 distance because this rotation formula gives us a result with the origin based
513 in the bottom left corner (of the (+, +) quadrant).
514 The actual code is a simplification of the above.
516 local dx
, dy
= xDist
, yDist
517 xDist
= (dx
* cosTheta
) - (dy
* sinTheta
)
518 yDist
= (dx
* sinTheta
) + (dy
* cosTheta
)
521 if ( minimapShape
and not (xDist
== 0 or yDist
== 0) ) then
522 isRound
= (xDist
< 0) and 1 or 3;
523 if ( yDist
< 0 ) then
524 isRound
= minimapShape
[isRound
];
526 isRound
= minimapShape
[isRound
+ 1];
530 -- for non-circular portions of the Minimap edge
531 if not ( isRound
) then
532 dist
= max(abs(xDist
), abs(yDist
))
535 if ( (dist
+ iconDiameter
) > mapRadius
) then
536 -- position along the outside of the Minimap
538 local factor
= (mapRadius
- iconDiameter
) / dist
;
539 xDist
= xDist
* factor
;
540 yDist
= yDist
* factor
;
543 if ( Astrolabe
.IconsOnEdge
[icon
] ~= iconOnEdge
) then
544 Astrolabe
.IconsOnEdge
[icon
] = iconOnEdge
;
545 Astrolabe
.IconsOnEdgeChanged
= true;
548 icon
:ClearAllPoints();
549 icon
:SetPoint("CENTER", minimap
, "CENTER", xDist
/xScale
, -yDist
/yScale
);
552 function Astrolabe
:PlaceIconOnMinimap( icon
, continent
, zone
, xPos
, yPos
)
553 -- check argument types
554 argcheck(icon
, 2, "table");
555 assert(3, icon
.SetPoint
and icon
.ClearAllPoints
, "Usage Message");
556 argcheck(continent
, 3, "number");
557 argcheck(zone
, 4, "number", "nil");
558 argcheck(xPos
, 5, "number");
559 argcheck(yPos
, 6, "number");
561 local lC
, lZ
, lx
, ly
= unpack(self
.LastPlayerPosition
);
562 local dist
, xDist
, yDist
= self
:ComputeDistance(lC
, lZ
, lx
, ly
, continent
, zone
, xPos
, yPos
);
564 --icon's position has no meaningful position relative to the player's current location
568 local iconData
= GetWorkingTable(icon
);
569 if ( self
.MinimapIcons
[icon
] ) then
570 self
.MinimapIcons
[icon
] = nil;
572 self
.MinimapIconCount
= self
.MinimapIconCount
+ 1
575 -- We know this icon's position is valid, so we need to make sure the icon placement
576 -- system is active. We call this here so that if this is the first icon being added to
577 -- an empty buffer, the full recalc will not completely redo the work done by this function
578 -- because the icon has not yet actually been placed in the buffer.
579 self
.processingFrame
:Show()
581 AddedOrUpdatedIcons
[icon
] = iconData
582 iconData
.continent
= continent
;
583 iconData
.zone
= zone
;
584 iconData
.xPos
= xPos
;
585 iconData
.yPos
= yPos
;
586 iconData
.dist
= dist
;
587 iconData
.xDist
= xDist
;
588 iconData
.yDist
= yDist
;
590 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
591 if ( minimapRotationEnabled
) then
592 minimapRotationOffset
= -Astrolabe
.GetFacing()
595 -- check Minimap Shape
596 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
598 -- place the icon on the Minimap and :Show() it
600 placeIconOnMinimap(map
, map
:GetZoom(), map
:GetWidth(), map
:GetHeight(), icon
, dist
, xDist
, yDist
);
606 function Astrolabe
:RemoveIconFromMinimap( icon
)
607 if not ( self
.MinimapIcons
[icon
] ) then
610 AddedOrUpdatedIcons
[icon
] = nil
611 self
.MinimapIcons
[icon
] = nil;
612 self
.IconsOnEdge
[icon
] = nil;
615 local MinimapIconCount
= self
.MinimapIconCount
- 1
616 if ( MinimapIconCount
<= 0 ) then
617 -- no icons left to manage
618 self
.processingFrame
:Hide()
619 MinimapIconCount
= 0 -- because I'm paranoid
621 self
.MinimapIconCount
= MinimapIconCount
626 function Astrolabe
:RemoveAllMinimapIcons()
627 self
:DumpNewIconsCache()
628 local MinimapIcons
= self
.MinimapIcons
;
629 local IconsOnEdge
= self
.IconsOnEdge
;
630 for k
, v
in pairs(MinimapIcons
) do
631 MinimapIcons
[k
] = nil;
632 IconsOnEdge
[k
] = nil;
635 self
.MinimapIconCount
= 0
636 self
.processingFrame
:Hide()
639 local lastZoom
; -- to remember the last seen Minimap zoom level
641 -- local variables to track the status of the two update coroutines
642 local fullUpdateInProgress
= true
643 local resetIncrementalUpdate
= false
644 local resetFullUpdate
= false
646 -- Incremental Update Code
648 -- local variables to track the incremental update coroutine
649 local incrementalUpdateCrashed
= true
650 local incrementalUpdateThread
652 local function UpdateMinimapIconPositions( self
)
656 self
:DumpNewIconsCache() -- put new/updated icons into the main datacache
658 resetIncrementalUpdate
= false -- by definition, the incremental update is reset if it is here
660 local C
, Z
, x
, y
= self
:GetCurrentPlayerPosition();
661 if ( C
and C
~= -1 ) then
662 local lastPosition
= self
.LastPlayerPosition
;
663 local lC
, lZ
, lx
, ly
= unpack(lastPosition
);
665 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
666 if ( minimapRotationEnabled
) then
667 minimapRotationOffset
= -Astrolabe
.GetFacing()
670 -- check current frame rate
671 local numPerCycle
= min(50, GetFramerate() * (self
.MinimapUpdateMultiplier
or 1))
673 -- check Minimap Shape
674 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
676 if ( lC
== C
and lZ
== Z
and lx
== x
and ly
== y
) then
677 -- player has not moved since the last update
678 if ( lastZoom
~= Minimap
:GetZoom() or self
.ForceNextUpdate
or minimapRotationEnabled
) then
679 local currentZoom
= Minimap
:GetZoom();
680 lastZoom
= currentZoom
;
681 local mapWidth
= Minimap
:GetWidth();
682 local mapHeight
= Minimap
:GetHeight();
683 numPerCycle
= numPerCycle
* 2
685 for icon
, data
in pairs(self
.MinimapIcons
) do
686 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, data
.dist
, data
.xDist
, data
.yDist
);
689 if ( count
> numPerCycle
) then
692 -- check if the incremental update cycle needs to be reset
693 -- because a full update has been run
694 if ( resetIncrementalUpdate
) then
699 self
.ForceNextUpdate
= false;
702 local dist
, xDelta
, yDelta
= self
:ComputeDistance(lC
, lZ
, lx
, ly
, C
, Z
, x
, y
);
704 local currentZoom
= Minimap
:GetZoom();
705 lastZoom
= currentZoom
;
706 local mapWidth
= Minimap
:GetWidth();
707 local mapHeight
= Minimap
:GetHeight();
709 for icon
, data
in pairs(self
.MinimapIcons
) do
710 local xDist
= data
.xDist
- xDelta
;
711 local yDist
= data
.yDist
- yDelta
;
712 local dist
= sqrt(xDist
*xDist
+ yDist
*yDist
);
713 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
);
720 if ( count
>= numPerCycle
) then
723 -- check if the incremental update cycle needs to be reset
724 -- because a full update has been run
725 if ( resetIncrementalUpdate
) then
730 if not ( resetIncrementalUpdate
) then
737 self
:RemoveAllMinimapIcons()
745 if not ( self
.WorldMapVisible
) then
746 self
.processingFrame
:Hide();
750 -- if we've been reset, then we want to start the new cycle immediately
751 if not ( resetIncrementalUpdate
) then
757 function Astrolabe
:UpdateMinimapIconPositions()
758 if ( fullUpdateInProgress
) then
759 -- if we're in the middle a a full update, we want to finish that first
760 self
:CalculateMinimapIconPositions()
762 if ( incrementalUpdateCrashed
) then
763 incrementalUpdateThread
= coroutine
.wrap(UpdateMinimapIconPositions
)
764 incrementalUpdateThread(self
) --initialize the thread
766 incrementalUpdateCrashed
= true
767 incrementalUpdateThread()
768 incrementalUpdateCrashed
= false
775 -- local variables to track the full update coroutine
776 local fullUpdateCrashed
= true
777 local fullUpdateThread
779 local function CalculateMinimapIconPositions( self
)
783 self
:DumpNewIconsCache() -- put new/updated icons into the main datacache
785 resetFullUpdate
= false -- by definition, the full update is reset if it is here
787 fullUpdateInProgress
= true -- set the flag the says a full update is in progress
789 local C
, Z
, x
, y
= self
:GetCurrentPlayerPosition();
790 if ( C
and C
~= -1 ) then
791 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
792 if ( minimapRotationEnabled
) then
793 minimapRotationOffset
= Astrolabe
.GetFacing()
796 -- check current frame rate
797 local numPerCycle
= GetFramerate() * (self
.MinimapUpdateMultiplier
or 1) * 2
799 -- check Minimap Shape
800 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
802 local currentZoom
= Minimap
:GetZoom();
803 lastZoom
= currentZoom
;
804 local mapWidth
= Minimap
:GetWidth();
805 local mapHeight
= Minimap
:GetHeight();
807 for icon
, data
in pairs(self
.MinimapIcons
) do
808 local dist
, xDist
, yDist
= self
:ComputeDistance(C
, Z
, x
, y
, data
.continent
, data
.zone
, data
.xPos
, data
.yPos
);
810 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
);
816 self
:RemoveIconFromMinimap(icon
)
820 if ( count
>= numPerCycle
) then
823 -- check if we need to restart due to the full update being reset
824 if ( resetFullUpdate
) then
830 if not ( resetFullUpdate
) then
831 local lastPosition
= self
.LastPlayerPosition
;
837 resetIncrementalUpdate
= true
840 if not ( self
.WorldMapVisible
) then
841 self
.processingFrame
:Hide();
845 -- if we've been reset, then we want to start the new cycle immediately
846 if not ( resetFullUpdate
) then
847 fullUpdateInProgress
= false
853 function Astrolabe
:CalculateMinimapIconPositions( reset
)
854 if ( fullUpdateCrashed
) then
855 fullUpdateThread
= coroutine
.wrap(CalculateMinimapIconPositions
)
856 fullUpdateThread(self
) --initialize the thread
857 elseif ( reset
) then
858 resetFullUpdate
= true
860 fullUpdateCrashed
= true
862 fullUpdateCrashed
= false
864 -- return result flag
865 if ( fullUpdateInProgress
) then
866 return 1 -- full update started, but did not complete on this cycle
869 if ( resetIncrementalUpdate
) then
870 return 0 -- update completed
872 return -1 -- full update did no occur for some reason
879 function Astrolabe
:GetDistanceToIcon( icon
)
880 local data
= self
.MinimapIcons
[icon
];
882 return data
.dist
, data
.xDist
, data
.yDist
;
886 function Astrolabe
:IsIconOnEdge( icon
)
887 return self
.IconsOnEdge
[icon
];
890 function Astrolabe
:GetDirectionToIcon( icon
)
891 local data
= self
.MinimapIcons
[icon
];
893 local dir
= atan2(data
.xDist
, -(data
.yDist
))
902 function Astrolabe
:Register_OnEdgeChanged_Callback( func
, ident
)
903 -- check argument types
904 argcheck(func
, 2, "function");
906 self
.IconsOnEdge_GroupChangeCallbacks
[func
] = ident
;
909 --*****************************************************************************
910 -- INTERNAL USE ONLY PLEASE!!!
911 -- Calling this function at the wrong time can cause errors
912 --*****************************************************************************
913 function Astrolabe
:DumpNewIconsCache()
914 local MinimapIcons
= self
.MinimapIcons
915 for icon
, data
in pairs(AddedOrUpdatedIcons
) do
916 MinimapIcons
[icon
] = data
917 AddedOrUpdatedIcons
[icon
] = nil
919 -- we now need to restart any updates that were in progress
920 resetIncrementalUpdate
= true
921 resetFullUpdate
= true
925 --------------------------------------------------------------------------------------------------------------
926 -- World Map Icon Placement
927 --------------------------------------------------------------------------------------------------------------
929 function Astrolabe
:PlaceIconOnWorldMap( worldMapFrame
, icon
, continent
, zone
, xPos
, yPos
)
930 -- check argument types
931 argcheck(worldMapFrame
, 2, "table");
932 assert(3, worldMapFrame
.GetWidth
and worldMapFrame
.GetHeight
, "Usage Message");
933 argcheck(icon
, 3, "table");
934 assert(3, icon
.SetPoint
and icon
.ClearAllPoints
, "Usage Message");
935 argcheck(continent
, 4, "number");
936 argcheck(zone
, 5, "number", "nil");
937 argcheck(xPos
, 6, "number");
938 argcheck(yPos
, 7, "number");
940 local C
, Z
= self
:GetCurrentVirtualMapCZ();
941 local nX
, nY
= self
:TranslateWorldMapPosition(continent
, zone
, xPos
, yPos
, C
, Z
);
943 -- anchor and :Show() the icon if it is within the boundry of the current map, :Hide() it otherwise
944 if ( nX
and nY
and (0 < nX
and nX
<= 1) and (0 < nY
and nY
<= 1) ) then
945 icon
:ClearAllPoints();
946 icon
:SetPoint("CENTER", worldMapFrame
, "TOPLEFT", nX
* worldMapFrame
:GetWidth(), -nY
* worldMapFrame
:GetHeight());
955 --------------------------------------------------------------------------------------------------------------
957 --------------------------------------------------------------------------------------------------------------
959 function Astrolabe
:OnEvent( frame
, event
)
960 if ( event
== "MINIMAP_UPDATE_ZOOM" ) then
961 -- update minimap zoom scale
962 local curZoom
= Minimap
:GetZoom();
963 if ( GetCVar("minimapZoom") == GetCVar("minimapInsideZoom") ) then
964 if ( curZoom
< 2 ) then
965 Minimap
:SetZoom(curZoom
+ 1);
967 Minimap
:SetZoom(curZoom
- 1);
970 if ( GetCVar("minimapZoom")+0 == Minimap
:GetZoom() ) then
971 self
.minimapOutside
= true;
973 self
.minimapOutside
= false;
975 Minimap
:SetZoom(curZoom
);
977 -- re-calculate all Minimap Icon positions
978 if ( frame
:IsVisible() ) then
979 self
:CalculateMinimapIconPositions(true);
982 elseif ( event
== "PLAYER_LEAVING_WORLD" ) then
983 frame
:Hide(); -- yes, I know this is redunant
984 self
:RemoveAllMinimapIcons(); --dump all minimap icons
986 elseif ( event
== "PLAYER_ENTERING_WORLD" ) then
988 if not ( frame
:IsVisible() ) then
989 -- do the minimap recalculation anyways if the OnShow script didn't execute
990 -- this is done to ensure the accuracy of information about icons that were
991 -- inserted while the Player was in the process of zoning
992 self
:CalculateMinimapIconPositions(true);
995 elseif ( event
== "ZONE_CHANGED_NEW_AREA" ) then
1002 function Astrolabe
:OnUpdate( frame
, elapsed
)
1003 -- on-edge group changed call-backs
1004 if ( self
.IconsOnEdgeChanged
) then
1005 self
.IconsOnEdgeChanged
= false;
1006 for func
in pairs(self
.IconsOnEdge_GroupChangeCallbacks
) do
1011 self
:UpdateMinimapIconPositions();
1014 function Astrolabe
:OnShow( frame
)
1015 -- set the world map to a zoom with a valid player position
1016 if not ( self
.WorldMapVisible
) then
1017 SetMapToCurrentZone();
1019 local C
, Z
= Astrolabe
:GetCurrentPlayerPosition();
1020 if ( C
and C
~= -1 ) then
1021 if C
>= 0 then -- If we're in Wackyland, we can't change the world map anyway, so at least it's probably right
1029 -- re-calculate minimap icon positions
1030 self
:CalculateMinimapIconPositions(true);
1032 if ( self
.MinimapIconCount
<= 0 ) then
1033 -- no icons left to manage
1034 self
.processingFrame
:Hide()
1038 -- called by AstrolabMapMonitor when all world maps are hidden
1039 function Astrolabe
:AllWorldMapsHidden()
1040 if ( IsLoggedIn() ) then
1041 self
.processingFrame
:Hide();
1042 self
.processingFrame
:Show();
1046 function Astrolabe
:SetMinimapObject(minimap
)
1048 self
:UpdateMinimapIconPositions()
1050 function Astrolabe
:GetMinimapObject()
1054 --------------------------------------------------------------------------------------------------------------
1055 -- Library Registration
1056 --------------------------------------------------------------------------------------------------------------
1058 local function activate( newInstance
, oldInstance
)
1059 if ( oldInstance
) then -- this is an upgrade activate
1060 if ( oldInstance
.DumpNewIconsCache
) then
1061 oldInstance
:DumpNewIconsCache()
1063 for k
, v
in pairs(oldInstance
) do
1064 if ( type(v
) ~= "function" and (not configConstants
[k
]) ) then
1068 -- sync up the current MinimapIconCount value
1070 for _
in pairs(newInstance
.MinimapIcons
) do
1071 iconCount
= iconCount
+ 1
1073 newInstance
.MinimapIconCount
= iconCount
1075 Astrolabe
= oldInstance
;
1077 local frame
= CreateFrame("Frame");
1078 newInstance
.processingFrame
= frame
;
1080 newInstance
.ContinentList
= Astrolabe
:GetMapVirtualContinents();
1082 for C
in pairs(newInstance
.ContinentList
) do
1083 local zones
= Astrolabe
:GetMapVirtualZones(C
);
1084 newInstance
.ContinentList
[C
] = zones
;
1085 for Z
in ipairs(zones
) do
1086 zones
[Z
] = Astrolabe
:GetMapTexture(C
, Z
);
1090 configConstants
= nil -- we don't need this anymore
1092 local frame
= newInstance
.processingFrame
;
1094 frame
:SetParent("Minimap");
1095 frame
:UnregisterAllEvents();
1096 frame
:RegisterEvent("MINIMAP_UPDATE_ZOOM");
1097 frame
:RegisterEvent("PLAYER_LEAVING_WORLD");
1098 frame
:RegisterEvent("PLAYER_ENTERING_WORLD");
1099 frame
:RegisterEvent("ZONE_CHANGED_NEW_AREA");
1100 frame
:SetScript("OnEvent",
1101 function( frame
, event
, ... )
1102 Astrolabe
:OnEvent(frame
, event
, ...);
1105 frame
:SetScript("OnUpdate",
1106 function( frame
, elapsed
)
1107 Astrolabe
:OnUpdate(frame
, elapsed
);
1110 frame
:SetScript("OnShow",
1112 Astrolabe
:OnShow(frame
);
1116 setmetatable(Astrolabe
.MinimapIcons
, MinimapIconsMetatable
)
1119 --------------------------------------------------------------------------------------------------------------
1121 --------------------------------------------------------------------------------------------------------------
1123 -- diameter of the Minimap in game yards at
1124 -- the various possible zoom levels
1135 [0] = 466 + 2/3, -- scale
1137 [2] = 333 + 1/3, -- 1.4
1138 [3] = 266 + 2/6, -- 1.75
1140 [5] = 133 + 1/3, -- 3.5
1144 ValidMinimapShapes
= {
1145 -- { upper-left, lower-left, upper-right, lower-right }
1146 ["SQUARE"] = { false, false, false, false },
1147 ["CORNER-TOPLEFT"] = { true, false, false, false },
1148 ["CORNER-TOPRIGHT"] = { false, false, true, false },
1149 ["CORNER-BOTTOMLEFT"] = { false, true, false, false },
1150 ["CORNER-BOTTOMRIGHT"] = { false, false, false, true },
1151 ["SIDE-LEFT"] = { true, true, false, false },
1152 ["SIDE-RIGHT"] = { false, false, true, true },
1153 ["SIDE-TOP"] = { true, false, true, false },
1154 ["SIDE-BOTTOM"] = { false, true, false, true },
1155 ["TRICORNER-TOPLEFT"] = { true, true, true, false },
1156 ["TRICORNER-TOPRIGHT"] = { true, false, true, true },
1157 ["TRICORNER-BOTTOMLEFT"] = { true, true, false, true },
1158 ["TRICORNER-BOTTOMRIGHT"] = { false, true, true, true },
1161 -- distances across and offsets of the world maps
1164 -- World Map of Azeroth
1166 parentContinent
= 0,
1167 height
= 29688.932932224,
1168 width
= 44537.340058402,
1172 parentContinent
= 0,
1173 height
= 24533.025279205,
1174 width
= 36800.210572494,
1175 xOffset
= -8311.793923510446,
1176 yOffset
= 1815.215685280706,
1179 height
= 3843.722811451077,
1180 width
= 5766.728884700476,
1181 xOffset
= 15366.76755576002,
1182 yOffset
= 8126.925260781192,
1186 height
= 3381.225696279877,
1187 width
= 5070.888165752819,
1188 xOffset
= 20343.90485013144,
1189 yOffset
= 7458.180046130774,
1193 height
= 2714.561862167815,
1194 width
= 4070.883253576282,
1195 xOffset
= 9966.70736478994,
1196 yOffset
= 5460.278138661794,
1200 height
= 6756.202067150937,
1201 width
= 10133.44343943073,
1202 xOffset
= 14443.84117394525,
1203 yOffset
= 11187.32013604393,
1207 height
= 2174.984710698752,
1208 width
= 3262.517428121028,
1209 xOffset
= 9541.713418184554,
1210 yOffset
= 3424.874558234072,
1214 height
= 4366.636219106706,
1215 width
= 6550.06962983463,
1216 xOffset
= 14125.08809600818,
1217 yOffset
= 4466.534412478246,
1221 height
= 705.7248633938184,
1222 width
= 1058.342927027606,
1223 xOffset
= 14128.39258617903,
1224 yOffset
= 2561.565012455802,
1228 height
= 2997.895174253872,
1229 width
= 4495.882023201739,
1230 xOffset
= 12833.40729836031,
1231 yOffset
= 12347.72848626745,
1235 height
= 3524.975114832228,
1236 width
= 5287.558038649864,
1237 xOffset
= 19029.30699887344,
1238 yOffset
= 10991.48801260963,
1242 height
= 3499.975146240067,
1243 width
= 5250.057259791282,
1244 xOffset
= 18041.79657043901,
1245 yOffset
= 14833.12751666842,
1249 height
= 3833.305958270781,
1250 width
= 5750.062034325837,
1251 xOffset
= 15425.10163773161,
1252 yOffset
= 5666.526367166872,
1256 height
= 4633.30011661694,
1257 width
= 6950.075260353015,
1258 xOffset
= 11625.06045254075,
1259 yOffset
= 15166.45834829251,
1263 height
= 1539.572509508711,
1264 width
= 2308.356845256911,
1265 xOffset
= 18448.05172159372,
1266 yOffset
= 4308.20254319874,
1270 height
= 3424.975945100366,
1271 width
= 5137.555355060729,
1272 xOffset
= 15018.84750987729,
1273 yOffset
= 13072.72336630089,
1277 height
= 935.4100697456119,
1278 width
= 1402.621211455915,
1279 xOffset
= 20747.42666130799,
1280 yOffset
= 10525.94769396873,
1284 height
= 2322.899061688691,
1285 width
= 3483.371975265956,
1286 xOffset
= 14529.25864164056,
1287 yOffset
= 18758.10068625832,
1290 StonetalonMountains
= {
1291 height
= 3256.226691571251,
1292 width
= 4883.385977951072,
1293 xOffset
= 13820.91773479217,
1294 yOffset
= 9883.162892509636,
1298 height
= 4599.965662459992,
1299 width
= 6900.073766103516,
1300 xOffset
= 17285.539010128,
1301 yOffset
= 18674.7673661939,
1305 height
= 3393.726923234355,
1306 width
= 5091.720903621394,
1307 xOffset
= 13252.16205313556,
1308 yOffset
= 968.6418744503761,
1312 height
= 704.6826864472878,
1313 width
= 1056.781131437323,
1314 xOffset
= 10533.08314172693,
1315 yOffset
= 6276.205331713322,
1319 height
= 2933.312180524323,
1320 width
= 4400.046681282484,
1321 xOffset
= 17500.12437633161,
1322 yOffset
= 16766.44698282704,
1326 height
= 695.8282721105132,
1327 width
= 1043.761263579803,
1328 xOffset
= 16550.11410485969,
1329 yOffset
= 13649.80260929285,
1333 height
= 2466.647220780505,
1334 width
= 3700.040077455555,
1335 xOffset
= 16533.44712326324,
1336 yOffset
= 18766.4334494793,
1340 height
= 4733.299561046713,
1341 width
= 7100.077599808275,
1342 xOffset
= 17383.45606038691,
1343 yOffset
= 4266.536453420381,
1350 parentContinent
= 0,
1351 height
= 27149.795290881,
1352 width
= 40741.175327834,
1353 xOffset
= 14407.1086092051,
1354 yOffset
= 290.3230897653046,
1357 height
= 1866.673586850316,
1358 width
= 2800.000436369314,
1359 xOffset
= 17388.63313899802,
1360 yOffset
= 9676.382605411302,
1364 height
= 2400.0092446309,
1365 width
= 3599.999380663208,
1366 xOffset
= 19038.63328411639,
1367 yOffset
= 11309.72201070757,
1371 height
= 1658.340965090961,
1372 width
= 2487.498490907989,
1373 xOffset
= 20251.1337564772,
1374 yOffset
= 17065.99404487956,
1378 height
= 2233.343415116865,
1379 width
= 3349.999381676505,
1380 xOffset
= 19413.63362865575,
1381 yOffset
= 21743.09582955139,
1385 height
= 1952.091972408385,
1386 width
= 2929.16694293186,
1387 xOffset
= 18438.633261567,
1388 yOffset
= 18207.66513379744,
1392 height
= 1666.673818905317,
1393 width
= 2499.999888210889,
1394 xOffset
= 19005.29993968603,
1395 yOffset
= 21043.0932328648,
1399 height
= 3283.345779814337,
1400 width
= 4924.998791911572,
1401 xOffset
= 16369.8840376619,
1402 yOffset
= 15053.48695195484,
1406 height
= 1800.007653419076,
1407 width
= 2699.999669551933,
1408 xOffset
= 17338.63354148773,
1409 yOffset
= 20893.09259181909,
1412 EasternPlaguelands
= {
1413 height
= 2687.510360231216,
1414 width
= 4031.249051993366,
1415 xOffset
= 20459.46801235962,
1416 yOffset
= 7472.207045901617,
1420 height
= 2314.591970284716,
1421 width
= 3470.831971412848,
1422 xOffset
= 16636.55099386465,
1423 yOffset
= 19116.0027890283,
1427 height
= 3283.346366715794,
1428 width
= 4924.998483501337,
1429 xOffset
= 20259.46725884782,
1430 yOffset
= 2534.687567863296,
1434 height
= 2200.008945183733,
1435 width
= 3300.002855743766,
1436 xOffset
= 21055.29786070095,
1437 yOffset
= 5309.698546426793,
1441 height
= 2133.341840477916,
1442 width
= 3200.000391416799,
1443 xOffset
= 17105.29968281043,
1444 yOffset
= 10776.38652289269,
1448 height
= 2566.676323518885,
1449 width
= 3849.998492380244,
1450 xOffset
= 19746.96704279287,
1451 yOffset
= 9709.715966757984,
1455 height
= 527.6056771582851,
1456 width
= 790.6252518322632,
1457 xOffset
= 18885.55815177769,
1458 yOffset
= 15745.64795436116,
1462 height
= 1839.590356444166,
1463 width
= 2758.33360594204,
1464 xOffset
= 20165.71623436714,
1465 yOffset
= 15663.90573348468,
1469 height
= 1447.922213393415,
1470 width
= 2170.833229570681,
1471 xOffset
= 19742.79960560691,
1472 yOffset
= 19751.42209395218,
1476 height
= 1487.505203229038,
1477 width
= 2231.250200533406,
1478 xOffset
= 18494.88325409831,
1479 yOffset
= 17276.41231120941,
1483 height
= 806.7751969249011,
1484 width
= 1211.458551923779,
1485 xOffset
= 22172.71573747824,
1486 yOffset
= 3422.647395021269,
1490 height
= 2800.011187621704,
1491 width
= 4200.000573479695,
1492 xOffset
= 14721.96646274185,
1493 yOffset
= 9509.714741967448,
1497 height
= 1158.33686894901,
1498 width
= 1737.498058940429,
1499 xOffset
= 16449.05164642256,
1500 yOffset
= 19172.25350774846,
1504 height
= 4254.18312444072,
1505 width
= 6381.248484543122,
1506 xOffset
= 15951.13375783437,
1507 yOffset
= 22345.18258706305,
1511 height
= 2218.756638064149,
1512 width
= 3327.084777999942,
1513 xOffset
= 21074.0484502027,
1514 yOffset
= 7.595267688679496,
1518 height
= 1529.173695058727,
1519 width
= 2293.753807610138,
1520 xOffset
= 20394.88183258176,
1521 yOffset
= 20797.25913588854,
1525 height
= 3012.510490816506,
1526 width
= 4518.749381850256,
1527 xOffset
= 15138.63417865412,
1528 yOffset
= 7338.874503644808,
1532 height
= 640.1067253394195,
1533 width
= 959.3752013853186,
1534 xOffset
= 17298.77399735696,
1535 yOffset
= 9298.435338905521,
1538 WesternPlaguelands
= {
1539 height
= 2866.677213191588,
1540 width
= 4299.998717025251,
1541 xOffset
= 17755.30067544475,
1542 yOffset
= 7809.708745090687,
1546 height
= 2333.342039971409,
1547 width
= 3500.001170481545,
1548 xOffset
= 15155.29922254704,
1549 yOffset
= 20576.42557120998,
1553 height
= 2756.260286844545,
1554 width
= 4135.414389381328,
1555 xOffset
= 18561.55091405621,
1556 yOffset
= 13324.31339403164,
1563 parentContinent
= 3,
1564 height
= 11642.355227091,
1565 width
= 17463.987300595,
1567 BladesEdgeMountains
= {
1568 height
= 3616.553511321226,
1569 width
= 5424.972055480694,
1570 xOffset
= 4150.184214583454,
1571 yOffset
= 1412.98225932006,
1575 height
= 3443.642450656037,
1576 width
= 5164.556104714847,
1577 xOffset
= 7456.417230912641,
1578 yOffset
= 4339.973750274888,
1582 height
= 3683.218538167106,
1583 width
= 5524.971495006054,
1584 xOffset
= 2700.192018521809,
1585 yOffset
= 5779.511974812862,
1589 height
= 3716.550608724641,
1590 width
= 5574.970083688359,
1591 xOffset
= 7512.667416095402,
1592 yOffset
= 365.0979827402549,
1595 ShadowmoonValley
= {
1596 height
= 3666.552070430093,
1597 width
= 5499.971770418525,
1598 xOffset
= 8770.993458280615,
1599 yOffset
= 7769.033264592288,
1603 height
= 870.8059516186869,
1604 width
= 1306.242821388422,
1605 xOffset
= 6860.744740098593,
1606 yOffset
= 7295.086120456203,
1610 height
= 3599.887783533737,
1611 width
= 5399.971351016305,
1612 xOffset
= 5912.675516998205,
1613 yOffset
= 6821.146319031154,
1617 height
= 3351.978710181591,
1618 width
= 5027.057650868489,
1619 xOffset
= 3521.020638264577,
1620 yOffset
= 3885.821278366336,
1627 --- WotLK Adjustments, now permanently enabled. Someday I should probably merge these in.
1629 WorldMapSize
[0].height
= 31809.64859753034;
1630 WorldMapSize
[0].width
= 47714.27770954026;
1632 WorldMapSize
[1].xOffset
= -8590.409362625034;
1633 WorldMapSize
[1].yOffset
= 5628.694276155668;
1635 WorldMapSize
[2].xOffset
= 18542.31268111796;
1636 WorldMapSize
[2].yOffset
= 3585.574682467752;
1640 parentContinent
= 0,
1641 height
= 11834.31067391958,
1642 width
= 17751.3936186856,
1643 xOffset
= 16020.94093549576,
1644 yOffset
= 454.2464807713226,
1647 height
= 3843.765503862232,
1648 width
= 5764.58206497758,
1649 xOffset
= 646.3186767730767,
1650 yOffset
= 5695.480016983896,
1653 CrystalsongForest
= {
1654 height
= 1814.590053385046,
1655 width
= 2722.916164555434,
1656 xOffset
= 7773.400227973558,
1657 yOffset
= 4091.307437548815,
1661 height
= 553.3419356683534,
1662 width
= 830.014625253355,
1663 xOffset
= 8164.640128758279,
1664 yOffset
= 4526.722218200071,
1668 height
= 3739.597759999098,
1669 width
= 5608.331259502691,
1670 xOffset
= 5590.067753073641,
1671 yOffset
= 5018.394106536425,
1675 height
= 3500.013349296343,
1676 width
= 5249.9986179934,
1677 xOffset
= 10327.56614428777,
1678 yOffset
= 5076.727864214266,
1682 height
= 4031.266275060274,
1683 width
= 6045.831339550668,
1684 xOffset
= 10615.0658552538,
1685 yOffset
= 7476.736868262738,
1689 height
= 4181.266519840844,
1690 width
= 6270.832975322177,
1691 xOffset
= 3773.401695036191,
1692 yOffset
= 1166.296622984233,
1696 height
= 1983.342901980711,
1697 width
= 2974.999377667768,
1698 xOffset
= 4887.984320612982,
1699 yOffset
= 4876.725348039468,
1703 height
= 2904.177559586215,
1704 width
= 4356.248328680455,
1705 xOffset
= 2287.985279107324,
1706 yOffset
= 3305.887993444818,
1710 height
= 4741.684940421732,
1711 width
= 7112.498205872217,
1712 xOffset
= 7375.483315518691,
1713 yOffset
= 395.4596828327046,
1717 height
= 3329.179510740043,
1718 width
= 4993.747919923504,
1719 xOffset
= 9817.150055203074,
1720 yOffset
= 2924.636381254688,
1723 HrothgarsLanding
= {
1726 xOffset
= 23967.599 - 17549.182,
1727 yOffset
= 1027.392 - 1215.431,
1732 local function VContinent(index
, name
, size
)
1733 assert(1, not WorldMapSize
[index
], "denied")
1735 WorldMapSize
[index
] = {
1736 parentContinent
= index
,
1741 WorldMapSize
[index
].zoneData
[name
] = {
1749 VContinent(-77, "ScarletEnclave", 2125)
1752 VContinent(-80, "UtgardeKeep1", 100) -- temporary value
1753 VContinent(-81, "UtgardeKeep2", 100) -- temporary value
1754 VContinent(-82, "UtgardeKeep3", 100) -- temporary value
1756 VContinent(-83, "TheNexus", 734.2)
1758 VContinent(-84, "AzjolNerub1", 100) -- temporary value
1759 VContinent(-85, "AzjolNerub2", 100) -- temporary value
1760 VContinent(-86, "AzjolNerub3", 100) -- temporary value
1762 VContinent(-87, "Ahnkahet", 648.3)
1764 VContinent(-88, "DrakTharonKeep1", 100) -- temporary value
1765 VContinent(-89, "DrakTharonKeep2", 100) -- temporary value
1767 VContinent(-90, "VioletHold", 170.83)
1769 VContinent(-91, "Gundrak", 603.35)
1771 VContinent(-92, "Ulduar77", 613.5) -- Halls of Stone
1773 VContinent(-93, "HallsofLightning1", 100) -- temporary value
1774 VContinent(-94, "HallsofLightning2", 100) -- temporary value
1776 VContinent(-95, "Nexus801", 100) -- temporary value -- Oculus
1777 VContinent(-96, "Nexus802", 100) -- temporary value
1778 VContinent(-97, "Nexus803", 100) -- temporary value
1779 VContinent(-98, "Nexus804", 100) -- temporary value
1781 VContinent(-99, "CoTStratholme1", 750.2)
1782 VContinent(-100, "CoTStratholme2", 1216.66)
1784 VContinent(-101, "UtgardePinnacle1", 100) -- temporary value -- hey they spelled it right
1785 VContinent(-102, "UtgardePinnacle2", 100) -- temporary value
1787 VContinent(-103, "VaultofArchavon", 603.25) -- temporary value -- Weirdly, Emalon is actually within the "Vault of Archavon"
1789 VContinent(-104, "Naxxramas1", 1237.5) -- construct quarter
1790 VContinent(-105, "Naxxramas2", 1237.5) -- arachnid quarter
1791 VContinent(-106, "Naxxramas3", 1237.5) -- military quarter
1792 VContinent(-107, "Naxxramas4", 1237.5) -- plague quarter
1793 VContinent(-108, "Naxxramas5", 1379.9) -- overview
1794 VContinent(-109, "Naxxramas6", 437.3) -- lair
1796 VContinent(-110, "TheObsidianSanctum", 775.1)
1798 VContinent(-111, "TheEyeOfEternity", 286.7)
1800 VContinent(-112, "Ulduar", 2191.7) -- temporary value
1801 VContinent(-113, "Ulduar1", 446.5) -- temporary value
1802 VContinent(-114, "Ulduar2", 885.6) -- temporary value
1803 VContinent(-115, "Ulduar3", 100) -- temporary value
1804 VContinent(-116, "Ulduar4", 100) -- temporary value
1806 VContinent(-117, "TheForgeofSouls", 965.4) -- temporary value
1807 VContinent(-118, "PitofSaron", 1022.3)
1810 VirtualContinentIndexes
= { -- Don't change values here, since programs might want to store them
1811 ["ScarletEnclave"] = -77,
1813 ["UtgardeKeep1"] = -80,
1814 ["UtgardeKeep2"] = -81,
1815 ["UtgardeKeep3"] = -82,
1819 ["AzjolNerub1"] = -84,
1820 ["AzjolNerub2"] = -85,
1821 ["AzjolNerub3"] = -86,
1825 ["DrakTharonKeep1"] = -88,
1826 ["DrakTharonKeep2"] = -89,
1828 ["VioletHold"] = -90,
1832 ["Ulduar77"] = -92, -- Halls of Stone
1834 ["HallsofLightning1"] = -93,
1835 ["HallsofLightning2"] = -94,
1837 ["Nexus801"] = -95, -- Oculus
1842 ["CoTStratholme1"] = -99,
1843 ["CoTStratholme2"] = -100,
1845 ["UtgardePinnacle1"] = -101, -- hey they spelled it right
1846 ["UtgardePinnacle2"] = -102,
1848 ["VaultofArchavon"] = -103, -- Weirdly, Emalon is actually within the "Vault of Archavon"
1850 ["Naxxramas1"] = -104,
1851 ["Naxxramas2"] = -105,
1852 ["Naxxramas3"] = -106,
1853 ["Naxxramas4"] = -107,
1854 ["Naxxramas5"] = -108,
1855 ["Naxxramas6"] = -109,
1857 ["TheObsidianSanctum"] = -110,
1859 ["TheEyeOfEternity"] = -111,
1867 ["TheForgeofSouls"] = -117,
1868 ["PitofSaron"] = -118,
1871 DongleStub
:Register(Astrolabe
, activate
)
1874 zeroData
= { xOffset
= 0, height
= 0, yOffset
= 0, width
= 0, __index
= function() return zeroData
end };
1875 setmetatable(zeroData
, zeroData
);
1876 setmetatable(WorldMapSize
, zeroData
);
1878 for continent
, zones
in pairs(Astrolabe
.ContinentList
) do
1879 local mapData
= WorldMapSize
[continent
];
1880 for index
, mapName
in pairs(zones
) do
1881 if not ( mapData
.zoneData
[mapName
] ) then
1882 --WE HAVE A PROBLEM!!!
1883 ChatFrame1
:AddMessage("Astrolabe is missing data for "..select(index
, GetMapZones(continent
))..".");
1884 mapData
.zoneData
[mapName
] = zeroData
;
1886 mapData
[index
] = mapData
.zoneData
[mapName
];
1887 mapData
.zoneData
[mapName
] = nil;
1892 -- register this library with AstrolabeMapMonitor, this will cause a full update if PLAYER_LOGIN has already fired
1893 local AstrolabeMapMonitor
= DongleStub("AstrolabeMapMonitor");
1894 AstrolabeMapMonitor
:RegisterAstrolabeLibrary(Astrolabe
, LIBRARY_VERSION_MAJOR
);
1897 QH_Astrolabe_Ready
= true