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
44 -- DO NOT MAKE CHANGES TO THIS LIBRARY WITHOUT FIRST CHANGING THE LIBRARY_VERSION_MAJOR
45 -- STRING (to something unique) OR ELSE YOU MAY BREAK OTHER ADDONS THAT USE THIS LIBRARY!!!
46 local LIBRARY_VERSION_MAJOR
= "Astrolabe-0.4-QuestHelper"
47 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
49 if not DongleStub
then error(LIBRARY_VERSION_MAJOR
.. " requires DongleStub.") end
50 if not DongleStub
:IsNewerVersion(LIBRARY_VERSION_MAJOR
, LIBRARY_VERSION_MINOR
) then return end
54 local Minimap
= _G
.Minimap
56 -- define local variables for Data Tables (defined at the end of this file)
57 local WorldMapSize
, MinimapSize
, ValidMinimapShapes
, VirtualContinentIndexes
;
59 function Astrolabe
:GetVersion()
60 return LIBRARY_VERSION_MAJOR
, LIBRARY_VERSION_MINOR
;
64 --------------------------------------------------------------------------------------------------------------
66 --------------------------------------------------------------------------------------------------------------
68 local configConstants
= {
69 MinimapUpdateMultiplier
= true,
72 -- this constant is multiplied by the current framerate to determine
73 -- how many icons are updated each frame
74 Astrolabe
.MinimapUpdateMultiplier
= 1;
77 --------------------------------------------------------------------------------------------------------------
79 --------------------------------------------------------------------------------------------------------------
81 Astrolabe
.LastPlayerPosition
= { 0, 0, 0, 0 };
82 Astrolabe
.MinimapIcons
= {};
83 Astrolabe
.IconsOnEdge
= {};
84 Astrolabe
.IconsOnEdge_GroupChangeCallbacks
= {};
86 Astrolabe
.MinimapIconCount
= 0
87 Astrolabe
.ForceNextUpdate
= false;
88 Astrolabe
.IconsOnEdgeChanged
= false;
90 -- This variable indicates whether we know of a visible World Map or not.
91 -- The state of this variable is controlled by the AstrolabeMapMonitor library.
92 Astrolabe
.WorldMapVisible
= false;
94 local AddedOrUpdatedIcons
= {}
95 local MinimapIconsMetatable
= { __index
= AddedOrUpdatedIcons
}
98 --------------------------------------------------------------------------------------------------------------
99 -- Local Pointers for often used API functions
100 --------------------------------------------------------------------------------------------------------------
102 local twoPi
= math
.pi
* 2;
103 local atan2 = math
.atan2;
104 local sin = math
.sin;
105 local cos = math
.cos;
106 local abs = math
.abs;
107 local sqrt = math
.sqrt;
110 local yield
= coroutine
.yield
111 local GetFramerate
= GetFramerate
114 --------------------------------------------------------------------------------------------------------------
115 -- Internal Utility Functions
116 --------------------------------------------------------------------------------------------------------------
118 local function assert(level
,condition
,message
)
119 if not condition
then
124 local function argcheck(value
, num
, ...)
125 assert(1, type(num
) == "number", "Bad argument #2 to 'argcheck' (number expected, got " .. type(level
) .. ")")
127 for i
=1,select("#", ...) do
128 if type(value
) == select(i
, ...) then return end
131 local types
= strjoin(", ", ...)
132 local name
= string.match(debugstack(2,2,0), ": in function [`<](.-)['>]")
133 error(string.format("Bad argument #%d to 'Astrolabe.%s' (%s expected, got %s)", num
, name
, types
, type(value
)), 3)
136 local function getContPosition( zoneData
, z
, x
, y
)
138 zoneData
= zoneData
[z
];
139 x
= x
* zoneData
.width
+ zoneData
.xOffset
;
140 y
= y
* zoneData
.height
+ zoneData
.yOffset
;
142 x
= x
* zoneData
.width
;
143 y
= y
* zoneData
.height
;
148 --------------------------------------------------------------------------------------------------------------
149 -- Virtual Continent Functions
150 --------------------------------------------------------------------------------------------------------------
152 function Astrolabe
:GetCurrentVirtualMapCZ()
153 local C
, Z
= GetCurrentMapContinent(), GetCurrentMapZone();
154 if C
== -1 and Z
== 0 then
156 local mapname
= GetMapInfo()
157 if VirtualContinentIndexes
[mapname
] and GetCurrentMapDungeonLevel() == 0 then
158 C
= VirtualContinentIndexes
[mapname
]
160 elseif mapname
and VirtualContinentIndexes
[mapname
.. GetCurrentMapDungeonLevel()] then
161 C
= VirtualContinentIndexes
[mapname
.. GetCurrentMapDungeonLevel()]
163 elseif mapname
== "CoTStratholme" and GetCurrentMapDungeonLevel() == 0 then
164 -- why do you gotta make me angry, baby
165 C
= VirtualContinentIndexes
["CoTStratholme2"]
172 function Astrolabe
:GetCurrentVirtualMapContinent() local C
, Z
= self
:GetCurrentVirtualMapCZ() return C
end
173 function Astrolabe
:GetCurrentVirtualMapZone() local C
, Z
= self
:GetCurrentVirtualMapCZ() return Z
end
175 -- Does much the same as GetMapContinents, but returns as an array and includes the virtual continents in the mix
176 function Astrolabe
:GetMapVirtualContinents()
177 local rv
= {GetMapContinents()}
178 for k
, v
in pairs(VirtualContinentIndexes
) do
179 rv
[v
] = k
.. "_Continent"
184 -- Does much the same as GetMapContinents, but returns as an array and includes the virtual continents in the mix
185 function Astrolabe
:GetMapVirtualZones(zone
)
186 for k
, v
in pairs(VirtualContinentIndexes
) do
192 return {GetMapZones(zone
)}
195 function Astrolabe
:GetMapTexture(c
, z
)
196 for k
, v
in pairs(VirtualContinentIndexes
) do
197 if v
== c
and z
== 0 then
198 return k
.. "_Continent"
199 elseif v
== c
and z
== 1 then
205 return (GetMapInfo())
208 --------------------------------------------------------------------------------------------------------------
209 -- General Utility Functions
210 --------------------------------------------------------------------------------------------------------------
212 function Astrolabe
:ComputeDistance( c1
, z1
, x1
, y1
, c2
, z2
, x2
, y2
)
213 QuestHelper
: Assert(c1
and z1
and x1
and y1
and c2
and z2
and x2
and y2
)
215 argcheck(c1, 2, "number");
216 assert(3, c1 >= 0, "ComputeDistance: Illegal continent index to c1: "..c1);
217 argcheck(z1, 3, "number", "nil");
218 argcheck(x1, 4, "number");
219 argcheck(y1, 5, "number");
220 argcheck(c2, 6, "number");
221 assert(3, c2 >= 0, "ComputeDistance: Illegal continent index to c2: "..c2);
222 argcheck(z2, 7, "number", "nil");
223 argcheck(x2, 8, "number");
224 argcheck(y2, 9, "number");
230 local dist
, xDelta
, yDelta
;
231 if ( c1
== c2
and z1
== z2
) then
232 -- points in the same zone
233 local zoneData
= WorldMapSize
[c1
];
235 zoneData
= zoneData
[z1
];
237 xDelta
= (x2
- x1
) * zoneData
.width
;
238 yDelta
= (y2
- y1
) * zoneData
.height
;
240 elseif ( c1
== c2
) then
241 -- points on the same continent
242 local zoneData
= WorldMapSize
[c1
];
243 x1
, y1
= getContPosition(zoneData
, z1
, x1
, y1
);
244 x2
, y2
= getContPosition(zoneData
, z2
, x2
, y2
);
248 elseif ( c1
and c2
) then
249 local cont1
= WorldMapSize
[c1
];
250 local cont2
= WorldMapSize
[c2
];
251 if ( cont1
.parentContinent
== cont2
.parentContinent
) then
252 x1
, y1
= getContPosition(cont1
, z1
, x1
, y1
);
253 x2
, y2
= getContPosition(cont2
, z2
, x2
, y2
);
254 if ( c1
~= cont1
.parentContinent
) then
255 x1
= x1
+ cont1
.xOffset
;
256 y1
= y1
+ cont1
.yOffset
;
258 if ( c2
~= cont2
.parentContinent
) then
259 x2
= x2
+ cont2
.xOffset
;
260 y2
= y2
+ cont2
.yOffset
;
268 if ( xDelta
and yDelta
) then
269 dist
= sqrt(xDelta
*xDelta
+ yDelta
*yDelta
);
271 return dist
, xDelta
, yDelta
;
274 function Astrolabe
:TranslateWorldMapPosition( C
, Z
, xPos
, yPos
, nC
, nZ
)
276 argcheck(C, 2, "number");
277 argcheck(Z, 3, "number", "nil");
278 argcheck(xPos, 4, "number");
279 argcheck(yPos, 5, "number");
280 argcheck(nC, 6, "number");
281 argcheck(nZ, 7, "number", "nil");
286 if ( nC
< 0 and nC
> -77 ) then
291 if ( C
== nC
and Z
== nZ
) then
294 elseif ( C
== nC
) then
295 -- points on the same continent
296 zoneData
= WorldMapSize
[C
];
297 xPos
, yPos
= getContPosition(zoneData
, Z
, xPos
, yPos
);
299 zoneData
= WorldMapSize
[C
][nZ
];
300 xPos
= xPos
- zoneData
.xOffset
;
301 yPos
= yPos
- zoneData
.yOffset
;
304 elseif ( C
and nC
) and ( WorldMapSize
[C
].parentContinent
== WorldMapSize
[nC
].parentContinent
) then
305 -- different continents, same world
306 zoneData
= WorldMapSize
[C
];
307 local parentContinent
= zoneData
.parentContinent
;
308 xPos
, yPos
= getContPosition(zoneData
, Z
, xPos
, yPos
);
309 if ( C
~= parentContinent
) then
310 -- translate up to world map if we aren't there already
311 xPos
= xPos
+ zoneData
.xOffset
;
312 yPos
= yPos
+ zoneData
.yOffset
;
313 zoneData
= WorldMapSize
[parentContinent
];
315 if ( nC
~= parentContinent
) then
316 -- translate down to the new continent
317 zoneData
= WorldMapSize
[nC
];
318 xPos
= xPos
- zoneData
.xOffset
;
319 yPos
= yPos
- zoneData
.yOffset
;
321 zoneData
= zoneData
[nZ
];
322 xPos
= xPos
- zoneData
.xOffset
;
323 yPos
= yPos
- zoneData
.yOffset
;
331 return (xPos
/ zoneData
.width
), (yPos
/ zoneData
.height
);
334 function Astrolabe
:GetAbsoluteContinentPosition( C
, Z
, xPos
, yPos
)
335 if C
== -1 then -- We're in a battleground that doesn't have a virtual continent, we're just kind of fucked.
339 assert(0, type(WorldMapSize
[C
].parentContinent
) == "number")
341 local x
, y
= Astrolabe
:TranslateWorldMapPosition(C
, Z
, xPos
, yPos
, WorldMapSize
[C
].parentContinent
, 0)
342 if not x
or not y
then return end
343 local zoneData
= WorldMapSize
[WorldMapSize
[C
].parentContinent
]
344 return WorldMapSize
[C
].parentContinent
, (x
* zoneData
.width
), (y
* zoneData
.height
)
347 function Astrolabe
:FromAbsoluteContinentPosition(C
, xPos
, yPos
)
348 return C
, xPos
/ WorldMapSize
[C
].width
, yPos
/ WorldMapSize
[C
].height
351 function Astrolabe
:GetZoneWidth(c
, z
)
353 return WorldMapSize
[c
][z
].width
355 return WorldMapSize
[c
].width
359 --*****************************************************************************
360 -- This function will do its utmost to retrieve some sort of valid position
361 -- for the specified unit, including changing the current map zoom (if needed).
362 -- Map Zoom is returned to its previous setting before this function returns.
363 --*****************************************************************************
364 function Astrolabe
:GetUnitPosition( unit
, noMapChange
)
365 local x
, y
= GetPlayerMapPosition(unit
);
366 if ( x
<= 0 and y
<= 0 ) then
367 if ( noMapChange
) then
368 -- no valid position on the current map, and we aren't allowed
369 -- to change map zoom, so return
372 local lastCont
, lastZone
= GetCurrentMapContinent(), GetCurrentMapZone();
373 SetMapToCurrentZone();
374 x
, y
= GetPlayerMapPosition(unit
);
375 if ( x
<= 0 and y
<= 0 ) then
376 SetMapZoom(GetCurrentMapContinent());
377 x
, y
= GetPlayerMapPosition(unit
);
378 if ( x
<= 0 and y
<= 0 ) then
379 -- we are in an instance or otherwise off the continent map
383 local C
, Z
= GetCurrentMapContinent(), GetCurrentMapZone();
384 if ( C
~= lastCont
or Z
~= lastZone
) then
385 SetMapZoom(lastCont
, lastZone
); -- set map zoom back to what it was before
389 return self
:GetCurrentVirtualMapContinent(), self
:GetCurrentVirtualMapZone(), x
, y
;
392 --*****************************************************************************
393 -- This function will do its utmost to retrieve some sort of valid position
394 -- for the specified unit, including changing the current map zoom (if needed).
395 -- However, if a monitored WorldMapFrame (See AstrolabeMapMonitor.lua) is
396 -- visible, then will simply return nil if the current zoom does not provide
397 -- a valid position for the player unit. Map Zoom is returned to its previous
398 -- setting before this function returns, if it was changed.
399 --*****************************************************************************
400 function Astrolabe
:GetCurrentPlayerPosition()
401 local x
, y
= GetPlayerMapPosition("player");
402 if ( x
<= 0 and y
<= 0 ) then
403 if ( self
.WorldMapVisible
) then
404 -- we know there is a visible world map, so don't cause
405 -- WORLD_MAP_UPDATE events by changing map zoom
408 local lastCont
, lastZone
= GetCurrentMapContinent(), GetCurrentMapZone();
409 SetMapToCurrentZone();
410 x
, y
= GetPlayerMapPosition("player");
411 if ( x
<= 0 and y
<= 0 ) then
412 SetMapZoom(GetCurrentMapContinent());
413 x
, y
= GetPlayerMapPosition("player");
414 if ( x
<= 0 and y
<= 0 ) then
415 -- we are in an instance or otherwise off the continent map
419 local C
, Z
= GetCurrentMapContinent(), GetCurrentMapZone();
421 if ( C
~= lastCont
or Z
~= lastZone
) then
422 SetMapZoom(lastCont
, lastZone
); --set map zoom back to what it was before
427 return self
:GetCurrentVirtualMapContinent(), self
:GetCurrentVirtualMapZone(), x
, y
;
431 --------------------------------------------------------------------------------------------------------------
432 -- Working Table Cache System
433 --------------------------------------------------------------------------------------------------------------
435 local tableCache
= {};
436 tableCache
["__mode"] = "v";
437 setmetatable(tableCache
, tableCache
);
439 local function GetWorkingTable( icon
)
440 if ( tableCache
[icon
] ) then
441 return tableCache
[icon
];
444 tableCache
[icon
] = T
;
450 --------------------------------------------------------------------------------------------------------------
451 -- Minimap Icon Placement
452 --------------------------------------------------------------------------------------------------------------
454 --*****************************************************************************
455 -- local variables specifically for use in this section
456 --*****************************************************************************
457 local minimapRotationEnabled
= false;
458 local minimapShape
= false;
460 local MinimapCompassTexture
= MinimapCompassTexture
;
461 local MinimapCompassRing
= MiniMapCompassRing
;
462 function Astrolabe
:GetFacing()
463 if MinimapCompassRing
then -- 3.1 hackery
464 return MinimapCompassRing
:GetFacing()
466 return -GetPlayerFacing()
469 local minimapRotationOffset
= -Astrolabe
.GetFacing()
471 local function placeIconOnMinimap( minimap
, minimapZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
)
473 if ( Astrolabe
.minimapOutside
) then
474 mapDiameter
= MinimapSize
.outdoor
[minimapZoom
];
476 mapDiameter
= MinimapSize
.indoor
[minimapZoom
];
478 local mapRadius
= mapDiameter
/ 2;
479 local xScale
= mapDiameter
/ mapWidth
;
480 local yScale
= mapDiameter
/ mapHeight
;
481 local iconDiameter
= ((icon
:GetWidth() / 2) + 3) * xScale
;
482 local iconOnEdge
= nil;
483 local isRound
= true;
485 if ( minimapRotationEnabled
) then
486 local sinTheta
= sin(minimapRotationOffset
)
487 local cosTheta
= cos(minimapRotationOffset
)
490 The math that is acutally going on in the next 3 lines is:
491 local dx, dy = xDist, -yDist
492 xDist = (dx * cosTheta) + (dy * sinTheta)
493 yDist = -((-dx * sinTheta) + (dy * cosTheta))
495 This is because the origin for map coordinates is the top left corner
496 of the map, not the bottom left, and so we have to reverse the vertical
497 distance when doing the our rotation, and then reverse the result vertical
498 distance because this rotation formula gives us a result with the origin based
499 in the bottom left corner (of the (+, +) quadrant).
500 The actual code is a simplification of the above.
502 local dx
, dy
= xDist
, yDist
503 xDist
= (dx
* cosTheta
) - (dy
* sinTheta
)
504 yDist
= (dx
* sinTheta
) + (dy
* cosTheta
)
507 if ( minimapShape
and not (xDist
== 0 or yDist
== 0) ) then
508 isRound
= (xDist
< 0) and 1 or 3;
509 if ( yDist
< 0 ) then
510 isRound
= minimapShape
[isRound
];
512 isRound
= minimapShape
[isRound
+ 1];
516 -- for non-circular portions of the Minimap edge
517 if not ( isRound
) then
518 dist
= max(abs(xDist
), abs(yDist
))
521 if ( (dist
+ iconDiameter
) > mapRadius
) then
522 -- position along the outside of the Minimap
524 local factor
= (mapRadius
- iconDiameter
) / dist
;
525 xDist
= xDist
* factor
;
526 yDist
= yDist
* factor
;
529 if ( Astrolabe
.IconsOnEdge
[icon
] ~= iconOnEdge
) then
530 Astrolabe
.IconsOnEdge
[icon
] = iconOnEdge
;
531 Astrolabe
.IconsOnEdgeChanged
= true;
534 icon
:ClearAllPoints();
535 icon
:SetPoint("CENTER", minimap
, "CENTER", xDist
/xScale
, -yDist
/yScale
);
538 function Astrolabe
:PlaceIconOnMinimap( icon
, continent
, zone
, xPos
, yPos
)
539 -- check argument types
540 argcheck(icon
, 2, "table");
541 assert(3, icon
.SetPoint
and icon
.ClearAllPoints
, "Usage Message");
542 argcheck(continent
, 3, "number");
543 argcheck(zone
, 4, "number", "nil");
544 argcheck(xPos
, 5, "number");
545 argcheck(yPos
, 6, "number");
547 local lC
, lZ
, lx
, ly
= unpack(self
.LastPlayerPosition
);
548 local dist
, xDist
, yDist
= self
:ComputeDistance(lC
, lZ
, lx
, ly
, continent
, zone
, xPos
, yPos
);
550 --icon's position has no meaningful position relative to the player's current location
554 local iconData
= GetWorkingTable(icon
);
555 if ( self
.MinimapIcons
[icon
] ) then
556 self
.MinimapIcons
[icon
] = nil;
558 self
.MinimapIconCount
= self
.MinimapIconCount
+ 1
561 -- We know this icon's position is valid, so we need to make sure the icon placement
562 -- system is active. We call this here so that if this is the first icon being added to
563 -- an empty buffer, the full recalc will not completely redo the work done by this function
564 -- because the icon has not yet actually been placed in the buffer.
565 self
.processingFrame
:Show()
567 AddedOrUpdatedIcons
[icon
] = iconData
568 iconData
.continent
= continent
;
569 iconData
.zone
= zone
;
570 iconData
.xPos
= xPos
;
571 iconData
.yPos
= yPos
;
572 iconData
.dist
= dist
;
573 iconData
.xDist
= xDist
;
574 iconData
.yDist
= yDist
;
576 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
577 if ( minimapRotationEnabled
) then
578 minimapRotationOffset
= -Astrolabe
.GetFacing()
581 -- check Minimap Shape
582 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
584 -- place the icon on the Minimap and :Show() it
586 placeIconOnMinimap(map
, map
:GetZoom(), map
:GetWidth(), map
:GetHeight(), icon
, dist
, xDist
, yDist
);
592 function Astrolabe
:RemoveIconFromMinimap( icon
)
593 if not ( self
.MinimapIcons
[icon
] ) then
596 AddedOrUpdatedIcons
[icon
] = nil
597 self
.MinimapIcons
[icon
] = nil;
598 self
.IconsOnEdge
[icon
] = nil;
601 local MinimapIconCount
= self
.MinimapIconCount
- 1
602 if ( MinimapIconCount
<= 0 ) then
603 -- no icons left to manage
604 self
.processingFrame
:Hide()
605 MinimapIconCount
= 0 -- because I'm paranoid
607 self
.MinimapIconCount
= MinimapIconCount
612 function Astrolabe
:RemoveAllMinimapIcons()
613 self
:DumpNewIconsCache()
614 local MinimapIcons
= self
.MinimapIcons
;
615 local IconsOnEdge
= self
.IconsOnEdge
;
616 for k
, v
in pairs(MinimapIcons
) do
617 MinimapIcons
[k
] = nil;
618 IconsOnEdge
[k
] = nil;
621 self
.MinimapIconCount
= 0
622 self
.processingFrame
:Hide()
625 local lastZoom
; -- to remember the last seen Minimap zoom level
627 -- local variables to track the status of the two update coroutines
628 local fullUpdateInProgress
= true
629 local resetIncrementalUpdate
= false
630 local resetFullUpdate
= false
632 -- Incremental Update Code
634 -- local variables to track the incremental update coroutine
635 local incrementalUpdateCrashed
= true
636 local incrementalUpdateThread
638 local function UpdateMinimapIconPositions( self
)
642 self
:DumpNewIconsCache() -- put new/updated icons into the main datacache
644 resetIncrementalUpdate
= false -- by definition, the incremental update is reset if it is here
646 local C
, Z
, x
, y
= self
:GetCurrentPlayerPosition();
647 if ( C
and C
~= -1 ) then
648 local lastPosition
= self
.LastPlayerPosition
;
649 local lC
, lZ
, lx
, ly
= unpack(lastPosition
);
651 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
652 if ( minimapRotationEnabled
) then
653 minimapRotationOffset
= -Astrolabe
.GetFacing()
656 -- check current frame rate
657 local numPerCycle
= min(50, GetFramerate() * (self
.MinimapUpdateMultiplier
or 1))
659 -- check Minimap Shape
660 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
662 if ( lC
== C
and lZ
== Z
and lx
== x
and ly
== y
) then
663 -- player has not moved since the last update
664 if ( lastZoom
~= Minimap
:GetZoom() or self
.ForceNextUpdate
or minimapRotationEnabled
) then
665 local currentZoom
= Minimap
:GetZoom();
666 lastZoom
= currentZoom
;
667 local mapWidth
= Minimap
:GetWidth();
668 local mapHeight
= Minimap
:GetHeight();
669 numPerCycle
= numPerCycle
* 2
671 for icon
, data
in pairs(self
.MinimapIcons
) do
672 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, data
.dist
, data
.xDist
, data
.yDist
);
675 if ( count
> numPerCycle
) then
678 -- check if the incremental update cycle needs to be reset
679 -- because a full update has been run
680 if ( resetIncrementalUpdate
) then
685 self
.ForceNextUpdate
= false;
688 local dist
, xDelta
, yDelta
= self
:ComputeDistance(lC
, lZ
, lx
, ly
, C
, Z
, x
, y
);
690 local currentZoom
= Minimap
:GetZoom();
691 lastZoom
= currentZoom
;
692 local mapWidth
= Minimap
:GetWidth();
693 local mapHeight
= Minimap
:GetHeight();
695 for icon
, data
in pairs(self
.MinimapIcons
) do
696 local xDist
= data
.xDist
- xDelta
;
697 local yDist
= data
.yDist
- yDelta
;
698 local dist
= sqrt(xDist
*xDist
+ yDist
*yDist
);
699 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
);
706 if ( count
>= numPerCycle
) then
709 -- check if the incremental update cycle needs to be reset
710 -- because a full update has been run
711 if ( resetIncrementalUpdate
) then
716 if not ( resetIncrementalUpdate
) then
723 self
:RemoveAllMinimapIcons()
731 if not ( self
.WorldMapVisible
) then
732 self
.processingFrame
:Hide();
736 -- if we've been reset, then we want to start the new cycle immediately
737 if not ( resetIncrementalUpdate
) then
743 function Astrolabe
:UpdateMinimapIconPositions()
744 if ( fullUpdateInProgress
) then
745 -- if we're in the middle a a full update, we want to finish that first
746 self
:CalculateMinimapIconPositions()
748 if ( incrementalUpdateCrashed
) then
749 incrementalUpdateThread
= coroutine
.wrap(UpdateMinimapIconPositions
)
750 incrementalUpdateThread(self
) --initialize the thread
752 incrementalUpdateCrashed
= true
753 incrementalUpdateThread()
754 incrementalUpdateCrashed
= false
761 -- local variables to track the full update coroutine
762 local fullUpdateCrashed
= true
763 local fullUpdateThread
765 local function CalculateMinimapIconPositions( self
)
769 self
:DumpNewIconsCache() -- put new/updated icons into the main datacache
771 resetFullUpdate
= false -- by definition, the full update is reset if it is here
773 fullUpdateInProgress
= true -- set the flag the says a full update is in progress
775 local C
, Z
, x
, y
= self
:GetCurrentPlayerPosition();
776 if ( C
and C
~= -1 ) then
777 minimapRotationEnabled
= GetCVar("rotateMinimap") ~= "0"
778 if ( minimapRotationEnabled
) then
779 minimapRotationOffset
= Astrolabe
.GetFacing()
782 -- check current frame rate
783 local numPerCycle
= GetFramerate() * (self
.MinimapUpdateMultiplier
or 1) * 2
785 -- check Minimap Shape
786 minimapShape
= GetMinimapShape
and ValidMinimapShapes
[GetMinimapShape()];
788 local currentZoom
= Minimap
:GetZoom();
789 lastZoom
= currentZoom
;
790 local mapWidth
= Minimap
:GetWidth();
791 local mapHeight
= Minimap
:GetHeight();
793 for icon
, data
in pairs(self
.MinimapIcons
) do
794 local dist
, xDist
, yDist
= self
:ComputeDistance(C
, Z
, x
, y
, data
.continent
, data
.zone
, data
.xPos
, data
.yPos
);
796 placeIconOnMinimap(Minimap
, currentZoom
, mapWidth
, mapHeight
, icon
, dist
, xDist
, yDist
);
802 self
:RemoveIconFromMinimap(icon
)
806 if ( count
>= numPerCycle
) then
809 -- check if we need to restart due to the full update being reset
810 if ( resetFullUpdate
) then
816 if not ( resetFullUpdate
) then
817 local lastPosition
= self
.LastPlayerPosition
;
823 resetIncrementalUpdate
= true
826 if not ( self
.WorldMapVisible
) then
827 self
.processingFrame
:Hide();
831 -- if we've been reset, then we want to start the new cycle immediately
832 if not ( resetFullUpdate
) then
833 fullUpdateInProgress
= false
839 function Astrolabe
:CalculateMinimapIconPositions( reset
)
840 if ( fullUpdateCrashed
) then
841 fullUpdateThread
= coroutine
.wrap(CalculateMinimapIconPositions
)
842 fullUpdateThread(self
) --initialize the thread
843 elseif ( reset
) then
844 resetFullUpdate
= true
846 fullUpdateCrashed
= true
848 fullUpdateCrashed
= false
850 -- return result flag
851 if ( fullUpdateInProgress
) then
852 return 1 -- full update started, but did not complete on this cycle
855 if ( resetIncrementalUpdate
) then
856 return 0 -- update completed
858 return -1 -- full update did no occur for some reason
865 function Astrolabe
:GetDistanceToIcon( icon
)
866 local data
= self
.MinimapIcons
[icon
];
868 return data
.dist
, data
.xDist
, data
.yDist
;
872 function Astrolabe
:IsIconOnEdge( icon
)
873 return self
.IconsOnEdge
[icon
];
876 function Astrolabe
:GetDirectionToIcon( icon
)
877 local data
= self
.MinimapIcons
[icon
];
879 local dir
= atan2(data
.xDist
, -(data
.yDist
))
888 function Astrolabe
:Register_OnEdgeChanged_Callback( func
, ident
)
889 -- check argument types
890 argcheck(func
, 2, "function");
892 self
.IconsOnEdge_GroupChangeCallbacks
[func
] = ident
;
895 --*****************************************************************************
896 -- INTERNAL USE ONLY PLEASE!!!
897 -- Calling this function at the wrong time can cause errors
898 --*****************************************************************************
899 function Astrolabe
:DumpNewIconsCache()
900 local MinimapIcons
= self
.MinimapIcons
901 for icon
, data
in pairs(AddedOrUpdatedIcons
) do
902 MinimapIcons
[icon
] = data
903 AddedOrUpdatedIcons
[icon
] = nil
905 -- we now need to restart any updates that were in progress
906 resetIncrementalUpdate
= true
907 resetFullUpdate
= true
911 --------------------------------------------------------------------------------------------------------------
912 -- World Map Icon Placement
913 --------------------------------------------------------------------------------------------------------------
915 function Astrolabe
:PlaceIconOnWorldMap( worldMapFrame
, icon
, continent
, zone
, xPos
, yPos
)
916 -- check argument types
917 argcheck(worldMapFrame
, 2, "table");
918 assert(3, worldMapFrame
.GetWidth
and worldMapFrame
.GetHeight
, "Usage Message");
919 argcheck(icon
, 3, "table");
920 assert(3, icon
.SetPoint
and icon
.ClearAllPoints
, "Usage Message");
921 argcheck(continent
, 4, "number");
922 argcheck(zone
, 5, "number", "nil");
923 argcheck(xPos
, 6, "number");
924 argcheck(yPos
, 7, "number");
926 local C
, Z
= self
:GetCurrentVirtualMapCZ();
927 local nX
, nY
= self
:TranslateWorldMapPosition(continent
, zone
, xPos
, yPos
, C
, Z
);
929 -- anchor and :Show() the icon if it is within the boundry of the current map, :Hide() it otherwise
930 if ( nX
and nY
and (0 < nX
and nX
<= 1) and (0 < nY
and nY
<= 1) ) then
931 icon
:ClearAllPoints();
932 icon
:SetPoint("CENTER", worldMapFrame
, "TOPLEFT", nX
* worldMapFrame
:GetWidth(), -nY
* worldMapFrame
:GetHeight());
941 --------------------------------------------------------------------------------------------------------------
943 --------------------------------------------------------------------------------------------------------------
945 function Astrolabe
:OnEvent( frame
, event
)
946 if ( event
== "MINIMAP_UPDATE_ZOOM" ) then
947 -- update minimap zoom scale
948 local curZoom
= Minimap
:GetZoom();
949 if ( GetCVar("minimapZoom") == GetCVar("minimapInsideZoom") ) then
950 if ( curZoom
< 2 ) then
951 Minimap
:SetZoom(curZoom
+ 1);
953 Minimap
:SetZoom(curZoom
- 1);
956 if ( GetCVar("minimapZoom")+0 == Minimap
:GetZoom() ) then
957 self
.minimapOutside
= true;
959 self
.minimapOutside
= false;
961 Minimap
:SetZoom(curZoom
);
963 -- re-calculate all Minimap Icon positions
964 if ( frame
:IsVisible() ) then
965 self
:CalculateMinimapIconPositions(true);
968 elseif ( event
== "PLAYER_LEAVING_WORLD" ) then
969 frame
:Hide(); -- yes, I know this is redunant
970 self
:RemoveAllMinimapIcons(); --dump all minimap icons
972 elseif ( event
== "PLAYER_ENTERING_WORLD" ) then
974 if not ( frame
:IsVisible() ) then
975 -- do the minimap recalculation anyways if the OnShow script didn't execute
976 -- this is done to ensure the accuracy of information about icons that were
977 -- inserted while the Player was in the process of zoning
978 self
:CalculateMinimapIconPositions(true);
981 elseif ( event
== "ZONE_CHANGED_NEW_AREA" ) then
988 function Astrolabe
:OnUpdate( frame
, elapsed
)
989 -- on-edge group changed call-backs
990 if ( self
.IconsOnEdgeChanged
) then
991 self
.IconsOnEdgeChanged
= false;
992 for func
in pairs(self
.IconsOnEdge_GroupChangeCallbacks
) do
997 self
:UpdateMinimapIconPositions();
1000 function Astrolabe
:OnShow( frame
)
1001 -- set the world map to a zoom with a valid player position
1002 if not ( self
.WorldMapVisible
) then
1003 SetMapToCurrentZone();
1005 local C
, Z
= Astrolabe
:GetCurrentPlayerPosition();
1006 if ( C
and C
~= -1 ) then
1007 if C
>= 0 then -- If we're in Wackyland, we can't change the world map anyway, so at least it's probably right
1015 -- re-calculate minimap icon positions
1016 self
:CalculateMinimapIconPositions(true);
1018 if ( self
.MinimapIconCount
<= 0 ) then
1019 -- no icons left to manage
1020 self
.processingFrame
:Hide()
1024 -- called by AstrolabMapMonitor when all world maps are hidden
1025 function Astrolabe
:AllWorldMapsHidden()
1026 if ( IsLoggedIn() ) then
1027 self
.processingFrame
:Hide();
1028 self
.processingFrame
:Show();
1032 function Astrolabe
:SetMinimapObject(minimap
)
1034 self
:UpdateMinimapIconPositions()
1037 --------------------------------------------------------------------------------------------------------------
1038 -- Library Registration
1039 --------------------------------------------------------------------------------------------------------------
1041 local function activate( newInstance
, oldInstance
)
1042 if ( oldInstance
) then -- this is an upgrade activate
1043 if ( oldInstance
.DumpNewIconsCache
) then
1044 oldInstance
:DumpNewIconsCache()
1046 for k
, v
in pairs(oldInstance
) do
1047 if ( type(v
) ~= "function" and (not configConstants
[k
]) ) then
1051 -- sync up the current MinimapIconCount value
1053 for _
in pairs(newInstance
.MinimapIcons
) do
1054 iconCount
= iconCount
+ 1
1056 newInstance
.MinimapIconCount
= iconCount
1058 Astrolabe
= oldInstance
;
1060 local frame
= CreateFrame("Frame");
1061 newInstance
.processingFrame
= frame
;
1063 newInstance
.ContinentList
= Astrolabe
:GetMapVirtualContinents();
1065 for C
in pairs(newInstance
.ContinentList
) do
1066 local zones
= Astrolabe
:GetMapVirtualZones(C
);
1067 newInstance
.ContinentList
[C
] = zones
;
1068 for Z
in ipairs(zones
) do
1069 zones
[Z
] = Astrolabe
:GetMapTexture(C
, Z
);
1073 configConstants
= nil -- we don't need this anymore
1075 local frame
= newInstance
.processingFrame
;
1077 frame
:SetParent("Minimap");
1078 frame
:UnregisterAllEvents();
1079 frame
:RegisterEvent("MINIMAP_UPDATE_ZOOM");
1080 frame
:RegisterEvent("PLAYER_LEAVING_WORLD");
1081 frame
:RegisterEvent("PLAYER_ENTERING_WORLD");
1082 frame
:RegisterEvent("ZONE_CHANGED_NEW_AREA");
1083 frame
:SetScript("OnEvent",
1084 function( frame
, event
, ... )
1085 Astrolabe
:OnEvent(frame
, event
, ...);
1088 frame
:SetScript("OnUpdate",
1089 function( frame
, elapsed
)
1090 Astrolabe
:OnUpdate(frame
, elapsed
);
1093 frame
:SetScript("OnShow",
1095 Astrolabe
:OnShow(frame
);
1099 setmetatable(Astrolabe
.MinimapIcons
, MinimapIconsMetatable
)
1102 --------------------------------------------------------------------------------------------------------------
1104 --------------------------------------------------------------------------------------------------------------
1106 -- diameter of the Minimap in game yards at
1107 -- the various possible zoom levels
1118 [0] = 466 + 2/3, -- scale
1120 [2] = 333 + 1/3, -- 1.4
1121 [3] = 266 + 2/6, -- 1.75
1123 [5] = 133 + 1/3, -- 3.5
1127 ValidMinimapShapes
= {
1128 -- { upper-left, lower-left, upper-right, lower-right }
1129 ["SQUARE"] = { false, false, false, false },
1130 ["CORNER-TOPLEFT"] = { true, false, false, false },
1131 ["CORNER-TOPRIGHT"] = { false, false, true, false },
1132 ["CORNER-BOTTOMLEFT"] = { false, true, false, false },
1133 ["CORNER-BOTTOMRIGHT"] = { false, false, false, true },
1134 ["SIDE-LEFT"] = { true, true, false, false },
1135 ["SIDE-RIGHT"] = { false, false, true, true },
1136 ["SIDE-TOP"] = { true, false, true, false },
1137 ["SIDE-BOTTOM"] = { false, true, false, true },
1138 ["TRICORNER-TOPLEFT"] = { true, true, true, false },
1139 ["TRICORNER-TOPRIGHT"] = { true, false, true, true },
1140 ["TRICORNER-BOTTOMLEFT"] = { true, true, false, true },
1141 ["TRICORNER-BOTTOMRIGHT"] = { false, true, true, true },
1144 -- distances across and offsets of the world maps
1147 -- World Map of Azeroth
1149 parentContinent
= 0,
1150 height
= 29688.932932224,
1151 width
= 44537.340058402,
1155 parentContinent
= 0,
1156 height
= 24533.025279205,
1157 width
= 36800.210572494,
1158 xOffset
= -8311.793923510446,
1159 yOffset
= 1815.215685280706,
1162 height
= 3843.722811451077,
1163 width
= 5766.728884700476,
1164 xOffset
= 15366.76755576002,
1165 yOffset
= 8126.925260781192,
1169 height
= 3381.225696279877,
1170 width
= 5070.888165752819,
1171 xOffset
= 20343.90485013144,
1172 yOffset
= 7458.180046130774,
1176 height
= 2714.561862167815,
1177 width
= 4070.883253576282,
1178 xOffset
= 9966.70736478994,
1179 yOffset
= 5460.278138661794,
1183 height
= 6756.202067150937,
1184 width
= 10133.44343943073,
1185 xOffset
= 14443.84117394525,
1186 yOffset
= 11187.32013604393,
1190 height
= 2174.984710698752,
1191 width
= 3262.517428121028,
1192 xOffset
= 9541.713418184554,
1193 yOffset
= 3424.874558234072,
1197 height
= 4366.636219106706,
1198 width
= 6550.06962983463,
1199 xOffset
= 14125.08809600818,
1200 yOffset
= 4466.534412478246,
1204 height
= 705.7248633938184,
1205 width
= 1058.342927027606,
1206 xOffset
= 14128.39258617903,
1207 yOffset
= 2561.565012455802,
1211 height
= 2997.895174253872,
1212 width
= 4495.882023201739,
1213 xOffset
= 12833.40729836031,
1214 yOffset
= 12347.72848626745,
1218 height
= 3524.975114832228,
1219 width
= 5287.558038649864,
1220 xOffset
= 19029.30699887344,
1221 yOffset
= 10991.48801260963,
1225 height
= 3499.975146240067,
1226 width
= 5250.057259791282,
1227 xOffset
= 18041.79657043901,
1228 yOffset
= 14833.12751666842,
1232 height
= 3833.305958270781,
1233 width
= 5750.062034325837,
1234 xOffset
= 15425.10163773161,
1235 yOffset
= 5666.526367166872,
1239 height
= 4633.30011661694,
1240 width
= 6950.075260353015,
1241 xOffset
= 11625.06045254075,
1242 yOffset
= 15166.45834829251,
1246 height
= 1539.572509508711,
1247 width
= 2308.356845256911,
1248 xOffset
= 18448.05172159372,
1249 yOffset
= 4308.20254319874,
1253 height
= 3424.975945100366,
1254 width
= 5137.555355060729,
1255 xOffset
= 15018.84750987729,
1256 yOffset
= 13072.72336630089,
1260 height
= 935.4100697456119,
1261 width
= 1402.621211455915,
1262 xOffset
= 20747.42666130799,
1263 yOffset
= 10525.94769396873,
1267 height
= 2322.899061688691,
1268 width
= 3483.371975265956,
1269 xOffset
= 14529.25864164056,
1270 yOffset
= 18758.10068625832,
1273 StonetalonMountains
= {
1274 height
= 3256.226691571251,
1275 width
= 4883.385977951072,
1276 xOffset
= 13820.91773479217,
1277 yOffset
= 9883.162892509636,
1281 height
= 4599.965662459992,
1282 width
= 6900.073766103516,
1283 xOffset
= 17285.539010128,
1284 yOffset
= 18674.7673661939,
1288 height
= 3393.726923234355,
1289 width
= 5091.720903621394,
1290 xOffset
= 13252.16205313556,
1291 yOffset
= 968.6418744503761,
1295 height
= 704.6826864472878,
1296 width
= 1056.781131437323,
1297 xOffset
= 10533.08314172693,
1298 yOffset
= 6276.205331713322,
1302 height
= 2933.312180524323,
1303 width
= 4400.046681282484,
1304 xOffset
= 17500.12437633161,
1305 yOffset
= 16766.44698282704,
1309 height
= 695.8282721105132,
1310 width
= 1043.761263579803,
1311 xOffset
= 16550.11410485969,
1312 yOffset
= 13649.80260929285,
1316 height
= 2466.647220780505,
1317 width
= 3700.040077455555,
1318 xOffset
= 16533.44712326324,
1319 yOffset
= 18766.4334494793,
1323 height
= 4733.299561046713,
1324 width
= 7100.077599808275,
1325 xOffset
= 17383.45606038691,
1326 yOffset
= 4266.536453420381,
1333 parentContinent
= 0,
1334 height
= 27149.795290881,
1335 width
= 40741.175327834,
1336 xOffset
= 14407.1086092051,
1337 yOffset
= 290.3230897653046,
1340 height
= 1866.673586850316,
1341 width
= 2800.000436369314,
1342 xOffset
= 17388.63313899802,
1343 yOffset
= 9676.382605411302,
1347 height
= 2400.0092446309,
1348 width
= 3599.999380663208,
1349 xOffset
= 19038.63328411639,
1350 yOffset
= 11309.72201070757,
1354 height
= 1658.340965090961,
1355 width
= 2487.498490907989,
1356 xOffset
= 20251.1337564772,
1357 yOffset
= 17065.99404487956,
1361 height
= 2233.343415116865,
1362 width
= 3349.999381676505,
1363 xOffset
= 19413.63362865575,
1364 yOffset
= 21743.09582955139,
1368 height
= 1952.091972408385,
1369 width
= 2929.16694293186,
1370 xOffset
= 18438.633261567,
1371 yOffset
= 18207.66513379744,
1375 height
= 1666.673818905317,
1376 width
= 2499.999888210889,
1377 xOffset
= 19005.29993968603,
1378 yOffset
= 21043.0932328648,
1382 height
= 3283.345779814337,
1383 width
= 4924.998791911572,
1384 xOffset
= 16369.8840376619,
1385 yOffset
= 15053.48695195484,
1389 height
= 1800.007653419076,
1390 width
= 2699.999669551933,
1391 xOffset
= 17338.63354148773,
1392 yOffset
= 20893.09259181909,
1395 EasternPlaguelands
= {
1396 height
= 2687.510360231216,
1397 width
= 4031.249051993366,
1398 xOffset
= 20459.46801235962,
1399 yOffset
= 7472.207045901617,
1403 height
= 2314.591970284716,
1404 width
= 3470.831971412848,
1405 xOffset
= 16636.55099386465,
1406 yOffset
= 19116.0027890283,
1410 height
= 3283.346366715794,
1411 width
= 4924.998483501337,
1412 xOffset
= 20259.46725884782,
1413 yOffset
= 2534.687567863296,
1417 height
= 2200.008945183733,
1418 width
= 3300.002855743766,
1419 xOffset
= 21055.29786070095,
1420 yOffset
= 5309.698546426793,
1424 height
= 2133.341840477916,
1425 width
= 3200.000391416799,
1426 xOffset
= 17105.29968281043,
1427 yOffset
= 10776.38652289269,
1431 height
= 2566.676323518885,
1432 width
= 3849.998492380244,
1433 xOffset
= 19746.96704279287,
1434 yOffset
= 9709.715966757984,
1438 height
= 527.6056771582851,
1439 width
= 790.6252518322632,
1440 xOffset
= 18885.55815177769,
1441 yOffset
= 15745.64795436116,
1445 height
= 1839.590356444166,
1446 width
= 2758.33360594204,
1447 xOffset
= 20165.71623436714,
1448 yOffset
= 15663.90573348468,
1452 height
= 1447.922213393415,
1453 width
= 2170.833229570681,
1454 xOffset
= 19742.79960560691,
1455 yOffset
= 19751.42209395218,
1459 height
= 1487.505203229038,
1460 width
= 2231.250200533406,
1461 xOffset
= 18494.88325409831,
1462 yOffset
= 17276.41231120941,
1466 height
= 806.7751969249011,
1467 width
= 1211.458551923779,
1468 xOffset
= 22172.71573747824,
1469 yOffset
= 3422.647395021269,
1473 height
= 2800.011187621704,
1474 width
= 4200.000573479695,
1475 xOffset
= 14721.96646274185,
1476 yOffset
= 9509.714741967448,
1480 height
= 1158.33686894901,
1481 width
= 1737.498058940429,
1482 xOffset
= 16449.05164642256,
1483 yOffset
= 19172.25350774846,
1487 height
= 4254.18312444072,
1488 width
= 6381.248484543122,
1489 xOffset
= 15951.13375783437,
1490 yOffset
= 22345.18258706305,
1494 height
= 2218.756638064149,
1495 width
= 3327.084777999942,
1496 xOffset
= 21074.0484502027,
1497 yOffset
= 7.595267688679496,
1501 height
= 1529.173695058727,
1502 width
= 2293.753807610138,
1503 xOffset
= 20394.88183258176,
1504 yOffset
= 20797.25913588854,
1508 height
= 3012.510490816506,
1509 width
= 4518.749381850256,
1510 xOffset
= 15138.63417865412,
1511 yOffset
= 7338.874503644808,
1515 height
= 640.1067253394195,
1516 width
= 959.3752013853186,
1517 xOffset
= 17298.77399735696,
1518 yOffset
= 9298.435338905521,
1521 WesternPlaguelands
= {
1522 height
= 2866.677213191588,
1523 width
= 4299.998717025251,
1524 xOffset
= 17755.30067544475,
1525 yOffset
= 7809.708745090687,
1529 height
= 2333.342039971409,
1530 width
= 3500.001170481545,
1531 xOffset
= 15155.29922254704,
1532 yOffset
= 20576.42557120998,
1536 height
= 2756.260286844545,
1537 width
= 4135.414389381328,
1538 xOffset
= 18561.55091405621,
1539 yOffset
= 13324.31339403164,
1546 parentContinent
= 3,
1547 height
= 11642.355227091,
1548 width
= 17463.987300595,
1550 BladesEdgeMountains
= {
1551 height
= 3616.553511321226,
1552 width
= 5424.972055480694,
1553 xOffset
= 4150.184214583454,
1554 yOffset
= 1412.98225932006,
1558 height
= 3443.642450656037,
1559 width
= 5164.556104714847,
1560 xOffset
= 7456.417230912641,
1561 yOffset
= 4339.973750274888,
1565 height
= 3683.218538167106,
1566 width
= 5524.971495006054,
1567 xOffset
= 2700.192018521809,
1568 yOffset
= 5779.511974812862,
1572 height
= 3716.550608724641,
1573 width
= 5574.970083688359,
1574 xOffset
= 7512.667416095402,
1575 yOffset
= 365.0979827402549,
1578 ShadowmoonValley
= {
1579 height
= 3666.552070430093,
1580 width
= 5499.971770418525,
1581 xOffset
= 8770.993458280615,
1582 yOffset
= 7769.033264592288,
1586 height
= 870.8059516186869,
1587 width
= 1306.242821388422,
1588 xOffset
= 6860.744740098593,
1589 yOffset
= 7295.086120456203,
1593 height
= 3599.887783533737,
1594 width
= 5399.971351016305,
1595 xOffset
= 5912.675516998205,
1596 yOffset
= 6821.146319031154,
1600 height
= 3351.978710181591,
1601 width
= 5027.057650868489,
1602 xOffset
= 3521.020638264577,
1603 yOffset
= 3885.821278366336,
1610 --- WotLK Adjustments, now permanently enabled. Someday I should probably merge these in.
1612 WorldMapSize
[0].height
= 31809.64859753034;
1613 WorldMapSize
[0].width
= 47714.27770954026;
1615 WorldMapSize
[1].xOffset
= -8590.409362625034;
1616 WorldMapSize
[1].yOffset
= 5628.694276155668;
1618 WorldMapSize
[2].xOffset
= 18542.31268111796;
1619 WorldMapSize
[2].yOffset
= 3585.574682467752;
1623 parentContinent
= 0,
1624 height
= 11834.31067391958,
1625 width
= 17751.3936186856,
1626 xOffset
= 16020.94093549576,
1627 yOffset
= 454.2464807713226,
1630 height
= 3843.765503862232,
1631 width
= 5764.58206497758,
1632 xOffset
= 646.3186767730767,
1633 yOffset
= 5695.480016983896,
1636 CrystalsongForest
= {
1637 height
= 1814.590053385046,
1638 width
= 2722.916164555434,
1639 xOffset
= 7773.400227973558,
1640 yOffset
= 4091.307437548815,
1644 height
= 553.3419356683534,
1645 width
= 830.014625253355,
1646 xOffset
= 8164.640128758279,
1647 yOffset
= 4526.722218200071,
1651 height
= 3739.597759999098,
1652 width
= 5608.331259502691,
1653 xOffset
= 5590.067753073641,
1654 yOffset
= 5018.394106536425,
1658 height
= 3500.013349296343,
1659 width
= 5249.9986179934,
1660 xOffset
= 10327.56614428777,
1661 yOffset
= 5076.727864214266,
1665 height
= 4031.266275060274,
1666 width
= 6045.831339550668,
1667 xOffset
= 10615.0658552538,
1668 yOffset
= 7476.736868262738,
1672 height
= 4181.266519840844,
1673 width
= 6270.832975322177,
1674 xOffset
= 3773.401695036191,
1675 yOffset
= 1166.296622984233,
1679 height
= 1983.342901980711,
1680 width
= 2974.999377667768,
1681 xOffset
= 4887.984320612982,
1682 yOffset
= 4876.725348039468,
1686 height
= 2904.177559586215,
1687 width
= 4356.248328680455,
1688 xOffset
= 2287.985279107324,
1689 yOffset
= 3305.887993444818,
1693 height
= 4741.684940421732,
1694 width
= 7112.498205872217,
1695 xOffset
= 7375.483315518691,
1696 yOffset
= 395.4596828327046,
1700 height
= 3329.179510740043,
1701 width
= 4993.747919923504,
1702 xOffset
= 9817.150055203074,
1703 yOffset
= 2924.636381254688,
1706 HrothgarsLanding
= {
1709 xOffset
= 23967.599 - 17549.182,
1710 yOffset
= 1027.392 - 1215.431,
1715 local function VContinent(index
, name
, size
)
1716 assert(1, not WorldMapSize
[index
], "denied")
1718 WorldMapSize
[index
] = {
1719 parentContinent
= index
,
1724 WorldMapSize
[index
].zoneData
[name
] = {
1732 VContinent(-77, "ScarletEnclave", 2125)
1735 VContinent(-80, "UtgardeKeep1", 100) -- temporary value
1736 VContinent(-81, "UtgardeKeep2", 100) -- temporary value
1737 VContinent(-82, "UtgardeKeep3", 100) -- temporary value
1739 VContinent(-83, "TheNexus", 734.2)
1741 VContinent(-84, "AzjolNerub1", 100) -- temporary value
1742 VContinent(-85, "AzjolNerub2", 100) -- temporary value
1743 VContinent(-86, "AzjolNerub3", 100) -- temporary value
1745 VContinent(-87, "Ahnkahet", 648.3)
1747 VContinent(-88, "DrakTharonKeep1", 100) -- temporary value
1748 VContinent(-89, "DrakTharonKeep2", 100) -- temporary value
1750 VContinent(-90, "VioletHold", 170.83)
1752 VContinent(-91, "Gundrak", 603.35)
1754 VContinent(-92, "Ulduar77", 613.5) -- Halls of Stone
1756 VContinent(-93, "HallsofLightning1", 100) -- temporary value
1757 VContinent(-94, "HallsofLightning2", 100) -- temporary value
1759 VContinent(-95, "Nexus801", 100) -- temporary value -- Oculus
1760 VContinent(-96, "Nexus802", 100) -- temporary value
1761 VContinent(-97, "Nexus803", 100) -- temporary value
1762 VContinent(-98, "Nexus804", 100) -- temporary value
1764 VContinent(-99, "CoTStratholme1", 750.2)
1765 VContinent(-100, "CoTStratholme2", 1216.66)
1767 VContinent(-101, "UtgardePinnacle1", 100) -- temporary value -- hey they spelled it right
1768 VContinent(-102, "UtgardePinnacle2", 100) -- temporary value
1770 VContinent(-103, "VaultofArchavon", 603.25) -- temporary value -- Weirdly, Emalon is actually within the "Vault of Archavon"
1772 VContinent(-104, "Naxxramas1", 1237.5) -- construct quarter
1773 VContinent(-105, "Naxxramas2", 1237.5) -- arachnid quarter
1774 VContinent(-106, "Naxxramas3", 1237.5) -- military quarter
1775 VContinent(-107, "Naxxramas4", 1237.5) -- plague quarter
1776 VContinent(-108, "Naxxramas5", 1379.9) -- overview
1777 VContinent(-109, "Naxxramas6", 437.3) -- lair
1779 VContinent(-110, "TheObsidianSanctum", 775.1)
1781 VContinent(-111, "TheEyeOfEternity", 286.7)
1783 VContinent(-112, "Ulduar", 2191.7) -- temporary value
1784 VContinent(-113, "Ulduar1", 446.5) -- temporary value
1785 VContinent(-114, "Ulduar2", 885.6) -- temporary value
1786 VContinent(-115, "Ulduar3", 100) -- temporary value
1787 VContinent(-116, "Ulduar4", 100) -- temporary value
1790 VirtualContinentIndexes
= { -- Don't change values here, since programs might want to store them
1791 ["ScarletEnclave"] = -77,
1793 ["UtgardeKeep1"] = -80,
1794 ["UtgardeKeep2"] = -81,
1795 ["UtgardeKeep3"] = -82,
1799 ["AzjolNerub1"] = -84,
1800 ["AzjolNerub2"] = -85,
1801 ["AzjolNerub3"] = -86,
1805 ["DrakTharonKeep1"] = -88,
1806 ["DrakTharonKeep2"] = -89,
1808 ["VioletHold"] = -90,
1812 ["Ulduar77"] = -92, -- Halls of Stone
1814 ["HallsofLightning1"] = -93,
1815 ["HallsofLightning2"] = -94,
1817 ["Nexus801"] = -95, -- Oculus
1822 ["CoTStratholme1"] = -99,
1823 ["CoTStratholme2"] = -100,
1825 ["UtgardePinnacle1"] = -101, -- hey they spelled it right
1826 ["UtgardePinnacle2"] = -102,
1828 ["VaultofArchavon"] = -103, -- Weirdly, Emalon is actually within the "Vault of Archavon"
1830 ["Naxxramas1"] = -104,
1831 ["Naxxramas2"] = -105,
1832 ["Naxxramas3"] = -106,
1833 ["Naxxramas4"] = -107,
1834 ["Naxxramas5"] = -108,
1835 ["Naxxramas6"] = -109,
1837 ["TheObsidianSanctum"] = -110,
1839 ["TheEyeOfEternity"] = -111,
1848 DongleStub
:Register(Astrolabe
, activate
)
1851 zeroData
= { xOffset
= 0, height
= 0, yOffset
= 0, width
= 0, __index
= function() return zeroData
end };
1852 setmetatable(zeroData
, zeroData
);
1853 setmetatable(WorldMapSize
, zeroData
);
1855 for continent
, zones
in pairs(Astrolabe
.ContinentList
) do
1856 local mapData
= WorldMapSize
[continent
];
1857 for index
, mapName
in pairs(zones
) do
1858 if not ( mapData
.zoneData
[mapName
] ) then
1859 --WE HAVE A PROBLEM!!!
1860 ChatFrame1
:AddMessage("Astrolabe is missing data for "..select(index
, GetMapZones(continent
))..".");
1861 mapData
.zoneData
[mapName
] = zeroData
;
1863 mapData
[index
] = mapData
.zoneData
[mapName
];
1864 mapData
.zoneData
[mapName
] = nil;
1869 -- register this library with AstrolabeMapMonitor, this will cause a full update if PLAYER_LOGIN has already fired
1870 local AstrolabeMapMonitor
= DongleStub("AstrolabeMapMonitor");
1871 AstrolabeMapMonitor
:RegisterAstrolabeLibrary(Astrolabe
, LIBRARY_VERSION_MAJOR
);