Details | Compare with Previous | View Log
Line No. | Rev | Author | Line |
---|---|---|---|
1 | 40 | Taonnor-14572 | -- LibGPS2 & its files © sirinsidiator -- |
2 | Taonnor-14572 | -- Distributed under The Artistic License 2.0 (see LICENSE) -- |
|
3 | Taonnor-14572 | ------------------------------------------------------------------ |
|
4 | Taonnor-14572 | ||
5 | Taonnor-14572 | local LIB_NAME = "LibGPS2" |
|
6 | 61 | Taonnor-14572 | local lib = LibStub:NewLibrary(LIB_NAME, 14) |
7 | 40 | Taonnor-14572 | |
8 | Taonnor-14572 | if not lib then |
|
9 | Taonnor-14572 | return |
|
10 | Taonnor-14572 | -- already loaded and no upgrade necessary |
|
11 | Taonnor-14572 | end |
|
12 | Taonnor-14572 | ||
13 | Taonnor-14572 | local LMP = LibStub("LibMapPing", true) |
|
14 | Taonnor-14572 | if(not LMP) then |
|
15 | Taonnor-14572 | error(string.format("[%s] Cannot load without LibMapPing", LIB_NAME)) |
|
16 | Taonnor-14572 | end |
|
17 | Taonnor-14572 | ||
18 | Taonnor-14572 | local DUMMY_PIN_TYPE = LIB_NAME .. "DummyPin" |
|
19 | Taonnor-14572 | local LIB_IDENTIFIER_FINALIZE = LIB_NAME .. "_Finalize" |
|
20 | Taonnor-14572 | lib.LIB_EVENT_STATE_CHANGED = "OnLibGPS2MeasurementChanged" |
|
21 | Taonnor-14572 | ||
22 | Taonnor-14572 | local LOG_WARNING = "Warning" |
|
23 | Taonnor-14572 | local LOG_NOTICE = "Notice" |
|
24 | Taonnor-14572 | local LOG_DEBUG = "Debug" |
|
25 | Taonnor-14572 | ||
26 | Taonnor-14572 | local POSITION_MIN = 0.085 |
|
27 | Taonnor-14572 | local POSITION_MAX = 0.915 |
|
28 | Taonnor-14572 | ||
29 | Taonnor-14572 | local TAMRIEL_MAP_INDEX = 1 |
|
30 | Taonnor-14572 | ||
31 | 49 | Taonnor-14572 | local rootMaps = lib.rootMaps or {} |
32 | Taonnor-14572 | lib.rootMaps = rootMaps |
|
33 | Taonnor-14572 | ||
34 | 40 | Taonnor-14572 | --lib.debugMode = 1 -- TODO |
35 | Taonnor-14572 | lib.mapMeasurements = lib.mapMeasurements or {} |
|
36 | Taonnor-14572 | local mapMeasurements = lib.mapMeasurements |
|
37 | Taonnor-14572 | lib.mapStack = lib.mapStack or {} |
|
38 | Taonnor-14572 | local mapStack = lib.mapStack |
|
39 | Taonnor-14572 | lib.suppressCount = lib.suppressCount or 0 |
|
40 | Taonnor-14572 | ||
41 | Taonnor-14572 | local MAP_PIN_TYPE_PLAYER_WAYPOINT = MAP_PIN_TYPE_PLAYER_WAYPOINT |
|
42 | Taonnor-14572 | local currentWaypointX, currentWaypointY, currentWaypointMapId = 0, 0, nil |
|
43 | Taonnor-14572 | local needWaypointRestore = false |
|
44 | Taonnor-14572 | local orgSetMapToMapListIndex = nil |
|
45 | Taonnor-14572 | local orgSetMapToPlayerLocation = nil |
|
46 | Taonnor-14572 | local orgSetMapFloor = nil |
|
47 | Taonnor-14572 | local orgProcessMapClick = nil |
|
48 | 49 | Taonnor-14572 | local orgFunctions = {} |
49 | 40 | Taonnor-14572 | local measuring = false |
50 | Taonnor-14572 | ||
51 | Taonnor-14572 | SLASH_COMMANDS["/libgpsdebug"] = function(value) |
|
52 | Taonnor-14572 | lib.debugMode = (tonumber(value) == 1) |
|
53 | Taonnor-14572 | df("[%s] debug mode %s", LIB_NAME, lib.debugMode and "enabled" or "disabled") |
|
54 | Taonnor-14572 | end |
|
55 | Taonnor-14572 | ||
56 | Taonnor-14572 | local function LogMessage(type, message, ...) |
|
57 | Taonnor-14572 | if not lib.debugMode then return end |
|
58 | Taonnor-14572 | df("[%s] %s: %s", LIB_NAME, type, zo_strjoin(" ", message, ...)) |
|
59 | Taonnor-14572 | end |
|
60 | Taonnor-14572 | ||
61 | Taonnor-14572 | local function GetAddon() |
|
62 | Taonnor-14572 | local addOn |
|
63 | Taonnor-14572 | local function errornous() addOn = 'a' + 1 end |
|
64 | Taonnor-14572 | local function errorHandler(err) addOn = string.match(err, "'GetAddon'.+user:/AddOns/(.-:.-):") end |
|
65 | Taonnor-14572 | xpcall(errornous, errorHandler) |
|
66 | Taonnor-14572 | return addOn |
|
67 | Taonnor-14572 | end |
|
68 | Taonnor-14572 | ||
69 | Taonnor-14572 | local function FinalizeMeasurement() |
|
70 | Taonnor-14572 | EVENT_MANAGER:UnregisterForUpdate(LIB_IDENTIFIER_FINALIZE) |
|
71 | Taonnor-14572 | while lib.suppressCount > 0 do |
|
72 | Taonnor-14572 | LMP:UnsuppressPing(MAP_PIN_TYPE_PLAYER_WAYPOINT) |
|
73 | Taonnor-14572 | lib.suppressCount = lib.suppressCount - 1 |
|
74 | Taonnor-14572 | end |
|
75 | Taonnor-14572 | if needWaypointRestore then |
|
76 | Taonnor-14572 | LogMessage(LOG_DEBUG, "Update waypoint pin", LMP:GetMapPing(MAP_PIN_TYPE_PLAYER_WAYPOINT)) |
|
77 | Taonnor-14572 | LMP:RefreshMapPin(MAP_PIN_TYPE_PLAYER_WAYPOINT) |
|
78 | Taonnor-14572 | needWaypointRestore = false |
|
79 | Taonnor-14572 | end |
|
80 | Taonnor-14572 | measuring = false |
|
81 | Taonnor-14572 | CALLBACK_MANAGER:FireCallbacks(lib.LIB_EVENT_STATE_CHANGED, measuring) |
|
82 | Taonnor-14572 | end |
|
83 | Taonnor-14572 | ||
84 | Taonnor-14572 | local function HandlePingEvent(pingType, pingTag, x, y, isPingOwner) |
|
85 | Taonnor-14572 | if(not isPingOwner or pingType ~= MAP_PIN_TYPE_PLAYER_WAYPOINT or not measuring) then return end |
|
86 | Taonnor-14572 | -- we delay our handler until all events have been fired and so that other addons can react to it first in case they use IsMeasuring |
|
87 | Taonnor-14572 | EVENT_MANAGER:UnregisterForUpdate(LIB_IDENTIFIER_FINALIZE) |
|
88 | Taonnor-14572 | EVENT_MANAGER:RegisterForUpdate(LIB_IDENTIFIER_FINALIZE, 0, FinalizeMeasurement) |
|
89 | Taonnor-14572 | end |
|
90 | Taonnor-14572 | ||
91 | Taonnor-14572 | local function GetPlayerPosition() |
|
92 | Taonnor-14572 | return GetMapPlayerPosition("player") |
|
93 | Taonnor-14572 | end |
|
94 | Taonnor-14572 | ||
95 | Taonnor-14572 | local function GetPlayerWaypoint() |
|
96 | Taonnor-14572 | return LMP:GetMapPing(MAP_PIN_TYPE_PLAYER_WAYPOINT) |
|
97 | Taonnor-14572 | end |
|
98 | Taonnor-14572 | ||
99 | Taonnor-14572 | local function SetMeasurementWaypoint(x, y) |
|
100 | Taonnor-14572 | -- this waypoint stays invisible for others |
|
101 | Taonnor-14572 | lib.suppressCount = lib.suppressCount + 1 |
|
102 | Taonnor-14572 | LMP:SuppressPing(MAP_PIN_TYPE_PLAYER_WAYPOINT) |
|
103 | Taonnor-14572 | LMP:SetMapPing(MAP_PIN_TYPE_PLAYER_WAYPOINT, MAP_TYPE_LOCATION_CENTERED, x, y) |
|
104 | Taonnor-14572 | end |
|
105 | Taonnor-14572 | ||
106 | Taonnor-14572 | local function SetPlayerWaypoint(x, y) |
|
107 | Taonnor-14572 | LMP:SetMapPing(MAP_PIN_TYPE_PLAYER_WAYPOINT, MAP_TYPE_LOCATION_CENTERED, x, y) |
|
108 | Taonnor-14572 | end |
|
109 | Taonnor-14572 | ||
110 | Taonnor-14572 | local function RemovePlayerWaypoint() |
|
111 | Taonnor-14572 | LMP:RemoveMapPing(MAP_PIN_TYPE_PLAYER_WAYPOINT) |
|
112 | Taonnor-14572 | end |
|
113 | Taonnor-14572 | ||
114 | Taonnor-14572 | local function GetReferencePoints() |
|
115 | Taonnor-14572 | local x1, y1 = GetPlayerPosition() |
|
116 | Taonnor-14572 | local x2, y2 = GetPlayerWaypoint() |
|
117 | Taonnor-14572 | return x1, y1, x2, y2 |
|
118 | Taonnor-14572 | end |
|
119 | Taonnor-14572 | ||
120 | Taonnor-14572 | local function IsMapMeasured(mapId) |
|
121 | Taonnor-14572 | return (mapMeasurements[mapId or GetMapTileTexture()] ~= nil) |
|
122 | Taonnor-14572 | end |
|
123 | Taonnor-14572 | ||
124 | Taonnor-14572 | local function StoreTamrielMapMeasurements() |
|
125 | Taonnor-14572 | -- no need to actually measure the world map |
|
126 | Taonnor-14572 | if (orgSetMapToMapListIndex(TAMRIEL_MAP_INDEX) ~= SET_MAP_RESULT_FAILED) then |
|
127 | 49 | Taonnor-14572 | local measurement = { |
128 | 40 | Taonnor-14572 | scaleX = 1, |
129 | Taonnor-14572 | scaleY = 1, |
|
130 | Taonnor-14572 | offsetX = 0, |
|
131 | Taonnor-14572 | offsetY = 0, |
|
132 | 49 | Taonnor-14572 | mapIndex = TAMRIEL_MAP_INDEX, |
133 | Taonnor-14572 | zoneIndex = GetCurrentMapZoneIndex() |
|
134 | 40 | Taonnor-14572 | } |
135 | 49 | Taonnor-14572 | mapMeasurements[GetMapTileTexture()] = measurement |
136 | Taonnor-14572 | rootMaps[TAMRIEL_MAP_INDEX] = measurement |
|
137 | 40 | Taonnor-14572 | return true |
138 | Taonnor-14572 | end |
|
139 | Taonnor-14572 | ||
140 | Taonnor-14572 | return false |
|
141 | Taonnor-14572 | end |
|
142 | Taonnor-14572 | ||
143 | Taonnor-14572 | local function CalculateMeasurements(mapId, localX, localY) |
|
144 | Taonnor-14572 | -- select the map corner farthest from the player position |
|
145 | Taonnor-14572 | local wpX, wpY = POSITION_MIN, POSITION_MIN |
|
146 | Taonnor-14572 | -- on some maps we cannot set the waypoint to the map border (e.g. Aurdion) |
|
147 | Taonnor-14572 | -- Opposite corner: |
|
148 | Taonnor-14572 | if (localX < 0.5) then wpX = POSITION_MAX end |
|
149 | Taonnor-14572 | if (localY < 0.5) then wpY = POSITION_MAX end |
|
150 | Taonnor-14572 | ||
151 | Taonnor-14572 | SetMeasurementWaypoint(wpX, wpY) |
|
152 | Taonnor-14572 | ||
153 | Taonnor-14572 | -- add local points to seen maps |
|
154 | Taonnor-14572 | local measurementPositions = {} |
|
155 | Taonnor-14572 | table.insert(measurementPositions, { mapId = mapId, pX = localX, pY = localY, wpX = wpX, wpY = wpY }) |
|
156 | Taonnor-14572 | ||
157 | Taonnor-14572 | -- switch to zone map in order to get the mapIndex for the current location |
|
158 | Taonnor-14572 | local x1, y1, x2, y2 |
|
159 | Taonnor-14572 | while not(GetMapType() == MAPTYPE_ZONE and GetMapContentType() ~= MAP_CONTENT_DUNGEON) do |
|
160 | Taonnor-14572 | if (MapZoomOut() ~= SET_MAP_RESULT_MAP_CHANGED) then break end |
|
161 | Taonnor-14572 | -- collect measurements for all maps we come through on our way to the zone map |
|
162 | Taonnor-14572 | x1, y1, x2, y2 = GetReferencePoints() |
|
163 | Taonnor-14572 | table.insert(measurementPositions, { mapId = GetMapTileTexture(), pX = x1, pY = y1, wpX = x2, wpY = y2 }) |
|
164 | Taonnor-14572 | end |
|
165 | Taonnor-14572 | ||
166 | Taonnor-14572 | -- some non-zone maps like Eyevea zoom directly to the Tamriel map |
|
167 | Taonnor-14572 | local mapIndex = GetCurrentMapIndex() or TAMRIEL_MAP_INDEX |
|
168 | 49 | Taonnor-14572 | local zoneIndex = GetCurrentMapZoneIndex() |
169 | 40 | Taonnor-14572 | |
170 | Taonnor-14572 | -- switch to world map so we can calculate the global map scale and offset |
|
171 | Taonnor-14572 | if orgSetMapToMapListIndex(TAMRIEL_MAP_INDEX) == SET_MAP_RESULT_FAILED then |
|
172 | Taonnor-14572 | -- failed to switch to the world map |
|
173 | Taonnor-14572 | LogMessage(LOG_NOTICE, "Could not switch to world map") |
|
174 | Taonnor-14572 | return |
|
175 | Taonnor-14572 | end |
|
176 | Taonnor-14572 | ||
177 | Taonnor-14572 | -- get the two reference points on the world map |
|
178 | Taonnor-14572 | x1, y1, x2, y2 = GetReferencePoints() |
|
179 | Taonnor-14572 | ||
180 | Taonnor-14572 | -- calculate scale and offset for all maps that we saw |
|
181 | Taonnor-14572 | local scaleX, scaleY, offsetX, offsetY |
|
182 | Taonnor-14572 | for _, m in ipairs(measurementPositions) do |
|
183 | Taonnor-14572 | if (mapMeasurements[m.mapId]) then break end -- we always go up in the hierarchy so we can stop once a measurement already exists |
|
184 | Taonnor-14572 | LogMessage(LOG_DEBUG, "Store map measurement for", m.mapId:sub(10, -7)) |
|
185 | Taonnor-14572 | scaleX = (x2 - x1) / (m.wpX - m.pX) |
|
186 | Taonnor-14572 | scaleY = (y2 - y1) / (m.wpY - m.pY) |
|
187 | Taonnor-14572 | offsetX = x1 - m.pX * scaleX |
|
188 | Taonnor-14572 | offsetY = y1 - m.pY * scaleY |
|
189 | Taonnor-14572 | if (math.abs(scaleX - scaleY) > 1e-3) then |
|
190 | Taonnor-14572 | LogMessage(LOG_WARNING, "Current map measurement might be wrong", m.mapId:sub(10, -7), mapIndex, m.pX, m.pY, m.wpX, m.wpY, x1, y1, x2, y2, offsetX, offsetY, scaleX, scaleY) |
|
191 | Taonnor-14572 | end |
|
192 | Taonnor-14572 | ||
193 | Taonnor-14572 | -- store measurements |
|
194 | Taonnor-14572 | mapMeasurements[m.mapId] = { |
|
195 | Taonnor-14572 | scaleX = scaleX, |
|
196 | Taonnor-14572 | scaleY = scaleY, |
|
197 | Taonnor-14572 | offsetX = offsetX, |
|
198 | Taonnor-14572 | offsetY = offsetY, |
|
199 | 49 | Taonnor-14572 | mapIndex = mapIndex, |
200 | Taonnor-14572 | zoneIndex = zoneIndex |
|
201 | 40 | Taonnor-14572 | } |
202 | Taonnor-14572 | end |
|
203 | Taonnor-14572 | return mapIndex |
|
204 | Taonnor-14572 | end |
|
205 | Taonnor-14572 | ||
206 | Taonnor-14572 | local function StoreCurrentWaypoint() |
|
207 | Taonnor-14572 | currentWaypointX, currentWaypointY = GetPlayerWaypoint() |
|
208 | Taonnor-14572 | currentWaypointMapId = GetMapTileTexture() |
|
209 | Taonnor-14572 | end |
|
210 | Taonnor-14572 | ||
211 | Taonnor-14572 | local function ClearCurrentWaypoint() |
|
212 | Taonnor-14572 | currentWaypointX, currentWaypointY = 0, 0, nil |
|
213 | Taonnor-14572 | end |
|
214 | Taonnor-14572 | ||
215 | 49 | Taonnor-14572 | local function GetExtraMapMeasurement(extraMapIndex) |
216 | Taonnor-14572 | -- switch to the map |
|
217 | Taonnor-14572 | orgSetMapToMapListIndex(extraMapIndex) |
|
218 | Taonnor-14572 | local extraMapId = GetMapTileTexture() |
|
219 | Taonnor-14572 | if(not IsMapMeasured(extraMapId)) then |
|
220 | Taonnor-14572 | -- calculate the measurements of map without worrying about the waypoint |
|
221 | Taonnor-14572 | local mapIndex = CalculateMeasurements(extraMapId, GetPlayerPosition()) |
|
222 | Taonnor-14572 | if (mapIndex ~= extraMapIndex) then |
|
223 | Taonnor-14572 | local name = GetMapInfo(extraMapIndex) |
|
224 | Taonnor-14572 | name = zo_strformat("<<C:1>>", name) |
|
225 | Taonnor-14572 | LogMessage(LOG_WARNING, "CalculateMeasurements returned different index while measuring ", name, " map. expected:", extraMapIndex, "actual:", mapIndex) |
|
226 | Taonnor-14572 | if (not IsMapMeasured(extraMapId)) then |
|
227 | Taonnor-14572 | LogMessage(LOG_WARNING, "Failed to measure ", name, " map.") |
|
228 | 40 | Taonnor-14572 | return |
229 | Taonnor-14572 | end |
|
230 | Taonnor-14572 | end |
|
231 | Taonnor-14572 | end |
|
232 | 49 | Taonnor-14572 | return mapMeasurements[extraMapId] |
233 | 40 | Taonnor-14572 | end |
234 | Taonnor-14572 | ||
235 | Taonnor-14572 | local function RestoreCurrentWaypoint() |
|
236 | Taonnor-14572 | if(not currentWaypointMapId) then |
|
237 | Taonnor-14572 | LogMessage(LOG_DEBUG, "Called RestoreCurrentWaypoint without calling StoreCurrentWaypoint.") |
|
238 | Taonnor-14572 | return |
|
239 | Taonnor-14572 | end |
|
240 | Taonnor-14572 | ||
241 | Taonnor-14572 | local wasSet = false |
|
242 | Taonnor-14572 | if (currentWaypointX ~= 0 or currentWaypointY ~= 0) then |
|
243 | Taonnor-14572 | -- calculate waypoint position on the worldmap |
|
244 | Taonnor-14572 | local measurements = mapMeasurements[currentWaypointMapId] |
|
245 | Taonnor-14572 | local x = currentWaypointX * measurements.scaleX + measurements.offsetX |
|
246 | Taonnor-14572 | local y = currentWaypointY * measurements.scaleY + measurements.offsetY |
|
247 | Taonnor-14572 | ||
248 | 49 | Taonnor-14572 | for rootMapIndex, measurements in pairs(rootMaps) do |
249 | Taonnor-14572 | if not measurements then |
|
250 | Taonnor-14572 | measurements = GetExtraMapMeasurement(rootMapIndex) |
|
251 | Taonnor-14572 | rootMaps[rootMapIndex] = measurements |
|
252 | 40 | Taonnor-14572 | end |
253 | Taonnor-14572 | if(measurements) then |
|
254 | 49 | Taonnor-14572 | if(x > measurements.offsetX and x < (measurements.offsetX + measurements.scaleX) and |
255 | Taonnor-14572 | y > measurements.offsetY and y < (measurements.offsetY + measurements.scaleY)) then |
|
256 | Taonnor-14572 | if(orgSetMapToMapListIndex(rootMapIndex) ~= SET_MAP_RESULT_FAILED) then |
|
257 | Taonnor-14572 | -- calculate waypoint coodinates within root map |
|
258 | Taonnor-14572 | x = (x - measurements.offsetX) / measurements.scaleX |
|
259 | Taonnor-14572 | y = (y - measurements.offsetY) / measurements.scaleY |
|
260 | 40 | Taonnor-14572 | SetPlayerWaypoint(x, y) |
261 | Taonnor-14572 | wasSet = true |
|
262 | 49 | Taonnor-14572 | break |
263 | 40 | Taonnor-14572 | end |
264 | Taonnor-14572 | end |
|
265 | Taonnor-14572 | end |
|
266 | Taonnor-14572 | end |
|
267 | 49 | Taonnor-14572 | if (not wasSet) then |
268 | Taonnor-14572 | LogMessage(LOG_DEBUG, "Cannot reset waypoint because it was outside of our reach") |
|
269 | Taonnor-14572 | end |
|
270 | 40 | Taonnor-14572 | end |
271 | Taonnor-14572 | ||
272 | Taonnor-14572 | if(wasSet) then |
|
273 | Taonnor-14572 | LogMessage(LOG_DEBUG, "Waypoint was restored, request pin update") |
|
274 | Taonnor-14572 | needWaypointRestore = true -- we need to update the pin on the worldmap afterwards |
|
275 | Taonnor-14572 | else |
|
276 | Taonnor-14572 | RemovePlayerWaypoint() |
|
277 | Taonnor-14572 | end |
|
278 | Taonnor-14572 | ClearCurrentWaypoint() |
|
279 | Taonnor-14572 | end |
|
280 | Taonnor-14572 | ||
281 | 49 | Taonnor-14572 | local function ConnectToWorldMap() |
282 | Taonnor-14572 | lib.panAndZoom = ZO_WorldMap_GetPanAndZoom() |
|
283 | Taonnor-14572 | lib.mapPinManager = ZO_WorldMap_GetPinManager() |
|
284 | Taonnor-14572 | if (_G[DUMMY_PIN_TYPE]) then return end |
|
285 | Taonnor-14572 | ZO_WorldMap_AddCustomPin(DUMMY_PIN_TYPE, function(pinManager) end , nil, { level = 0, size = 0, texture = "" }) |
|
286 | Taonnor-14572 | ZO_WorldMap_SetCustomPinEnabled(_G[DUMMY_PIN_TYPE], false) |
|
287 | 40 | Taonnor-14572 | end |
288 | Taonnor-14572 | ||
289 | 49 | Taonnor-14572 | local function HookSetMapToFunction(funcName) |
290 | Taonnor-14572 | local orgFunction = _G[funcName] |
|
291 | Taonnor-14572 | orgFunctions[funcName] = orgFunction |
|
292 | Taonnor-14572 | local function NewFunction(...) |
|
293 | Taonnor-14572 | local result = orgFunction(...) |
|
294 | 40 | Taonnor-14572 | if(result ~= SET_MAP_RESULT_MAP_FAILED and not IsMapMeasured()) then |
295 | 49 | Taonnor-14572 | LogMessage(LOG_DEBUG, funcName) |
296 | 40 | Taonnor-14572 | |
297 | 49 | Taonnor-14572 | local success, mapResult = lib:CalculateMapMeasurements(false) |
298 | Taonnor-14572 | if(mapResult ~= SET_MAP_RESULT_CURRENT_MAP_UNCHANGED) then |
|
299 | Taonnor-14572 | result = mapResult |
|
300 | Taonnor-14572 | end |
|
301 | Taonnor-14572 | orgFunction(...) |
|
302 | 40 | Taonnor-14572 | end |
303 | Taonnor-14572 | -- All stuff is done before anyone triggers an "OnWorldMapChanged" event due to this result |
|
304 | Taonnor-14572 | return result |
|
305 | Taonnor-14572 | end |
|
306 | 49 | Taonnor-14572 | _G[funcName] = NewFunction |
307 | 40 | Taonnor-14572 | end |
308 | Taonnor-14572 | ||
309 | Taonnor-14572 | local function HookSetMapToPlayerLocation() |
|
310 | Taonnor-14572 | orgSetMapToPlayerLocation = SetMapToPlayerLocation |
|
311 | 49 | Taonnor-14572 | orgFunctions["SetMapToPlayerLocation"] = orgSetMapToPlayerLocation |
312 | 40 | Taonnor-14572 | local function NewSetMapToPlayerLocation(...) |
313 | Taonnor-14572 | if not DoesUnitExist("player") then return SET_MAP_RESULT_MAP_FAILED end |
|
314 | Taonnor-14572 | local result = orgSetMapToPlayerLocation(...) |
|
315 | Taonnor-14572 | if(result ~= SET_MAP_RESULT_MAP_FAILED and not IsMapMeasured()) then |
|
316 | Taonnor-14572 | LogMessage(LOG_DEBUG, "SetMapToPlayerLocation") |
|
317 | Taonnor-14572 | ||
318 | 49 | Taonnor-14572 | local success, mapResult = lib:CalculateMapMeasurements(false) |
319 | Taonnor-14572 | if(mapResult ~= SET_MAP_RESULT_CURRENT_MAP_UNCHANGED) then |
|
320 | Taonnor-14572 | result = mapResult |
|
321 | Taonnor-14572 | end |
|
322 | 40 | Taonnor-14572 | orgSetMapToPlayerLocation(...) |
323 | Taonnor-14572 | end |
|
324 | Taonnor-14572 | -- All stuff is done before anyone triggers an "OnWorldMapChanged" event due to this result |
|
325 | Taonnor-14572 | return result |
|
326 | Taonnor-14572 | end |
|
327 | Taonnor-14572 | SetMapToPlayerLocation = NewSetMapToPlayerLocation |
|
328 | Taonnor-14572 | end |
|
329 | Taonnor-14572 | ||
330 | Taonnor-14572 | local function HookSetMapToMapListIndex() |
|
331 | Taonnor-14572 | orgSetMapToMapListIndex = SetMapToMapListIndex |
|
332 | 49 | Taonnor-14572 | orgFunctions["SetMapToMapListIndex"] = orgSetMapToMapListIndex |
333 | 40 | Taonnor-14572 | local function NewSetMapToMapListIndex(mapIndex) |
334 | Taonnor-14572 | local result = orgSetMapToMapListIndex(mapIndex) |
|
335 | Taonnor-14572 | if(result ~= SET_MAP_RESULT_MAP_FAILED and not IsMapMeasured()) then |
|
336 | Taonnor-14572 | LogMessage(LOG_DEBUG, "SetMapToMapListIndex") |
|
337 | Taonnor-14572 | ||
338 | 49 | Taonnor-14572 | local success, mapResult = lib:CalculateMapMeasurements(false) |
339 | Taonnor-14572 | if(mapResult ~= SET_MAP_RESULT_CURRENT_MAP_UNCHANGED) then |
|
340 | Taonnor-14572 | result = mapResult |
|
341 | Taonnor-14572 | end |
|
342 | 40 | Taonnor-14572 | orgSetMapToMapListIndex(mapIndex) |
343 | Taonnor-14572 | end |
|
344 | Taonnor-14572 | ||
345 | Taonnor-14572 | -- All stuff is done before anyone triggers an "OnWorldMapChanged" event due to this result |
|
346 | Taonnor-14572 | return result |
|
347 | Taonnor-14572 | end |
|
348 | Taonnor-14572 | SetMapToMapListIndex = NewSetMapToMapListIndex |
|
349 | Taonnor-14572 | end |
|
350 | Taonnor-14572 | ||
351 | Taonnor-14572 | local function HookProcessMapClick() |
|
352 | Taonnor-14572 | orgProcessMapClick = ProcessMapClick |
|
353 | 49 | Taonnor-14572 | orgFunctions["ProcessMapClick"] = orgProcessMapClick |
354 | 40 | Taonnor-14572 | local function NewProcessMapClick(...) |
355 | Taonnor-14572 | local result = orgProcessMapClick(...) |
|
356 | Taonnor-14572 | if(result ~= SET_MAP_RESULT_MAP_FAILED and not IsMapMeasured()) then |
|
357 | Taonnor-14572 | LogMessage(LOG_DEBUG, "ProcessMapClick") |
|
358 | 49 | Taonnor-14572 | local success, mapResult = lib:CalculateMapMeasurements(true) |
359 | Taonnor-14572 | if(mapResult ~= SET_MAP_RESULT_CURRENT_MAP_UNCHANGED) then |
|
360 | Taonnor-14572 | result = mapResult |
|
361 | Taonnor-14572 | end |
|
362 | 40 | Taonnor-14572 | -- Returning is done via clicking already |
363 | Taonnor-14572 | end |
|
364 | Taonnor-14572 | return result |
|
365 | Taonnor-14572 | end |
|
366 | Taonnor-14572 | ProcessMapClick = NewProcessMapClick |
|
367 | Taonnor-14572 | end |
|
368 | Taonnor-14572 | ||
369 | Taonnor-14572 | local function HookSetMapFloor() |
|
370 | Taonnor-14572 | orgSetMapFloor = SetMapFloor |
|
371 | 49 | Taonnor-14572 | orgFunctions["SetMapFloor"] = orgSetMapFloor |
372 | 40 | Taonnor-14572 | local function NewSetMapFloor(...) |
373 | Taonnor-14572 | local result = orgSetMapFloor(...) |
|
374 | Taonnor-14572 | if result ~= SET_MAP_RESULT_MAP_FAILED and not IsMapMeasured() then |
|
375 | Taonnor-14572 | LogMessage(LOG_DEBUG, "SetMapFloor") |
|
376 | 49 | Taonnor-14572 | local success, mapResult = lib:CalculateMapMeasurements(true) |
377 | Taonnor-14572 | if(mapResult ~= SET_MAP_RESULT_CURRENT_MAP_UNCHANGED) then |
|
378 | Taonnor-14572 | result = mapResult |
|
379 | Taonnor-14572 | end |
|
380 | 40 | Taonnor-14572 | orgSetMapFloor(...) |
381 | Taonnor-14572 | end |
|
382 | Taonnor-14572 | return result |
|
383 | Taonnor-14572 | end |
|
384 | Taonnor-14572 | SetMapFloor = NewSetMapFloor |
|
385 | Taonnor-14572 | end |
|
386 | Taonnor-14572 | ||
387 | Taonnor-14572 | local function Initialize() -- wait until we have defined all functions |
|
388 | Taonnor-14572 | --- Unregister handler from older libGPS ( < 3) |
|
389 | Taonnor-14572 | EVENT_MANAGER:UnregisterForEvent("LibGPS2_SaveWaypoint", EVENT_PLAYER_DEACTIVATED) |
|
390 | Taonnor-14572 | EVENT_MANAGER:UnregisterForEvent("LibGPS2_RestoreWaypoint", EVENT_PLAYER_ACTIVATED) |
|
391 | Taonnor-14572 | ||
392 | Taonnor-14572 | --- Unregister handler from older libGPS ( <= 5.1) |
|
393 | Taonnor-14572 | EVENT_MANAGER:UnregisterForEvent(LIB_NAME .. "_Init", EVENT_PLAYER_ACTIVATED) |
|
394 | 49 | Taonnor-14572 | --- Unregister handler from older libGPS, as it is now managed by LibMapPing ( >= 6) |
395 | Taonnor-14572 | EVENT_MANAGER:UnregisterForEvent(LIB_NAME .. "_UnmuteMapPing", EVENT_MAP_PING) |
|
396 | 40 | Taonnor-14572 | |
397 | Taonnor-14572 | if (lib.Unload) then |
|
398 | Taonnor-14572 | -- Undo action from older libGPS ( >= 5.2) |
|
399 | Taonnor-14572 | lib:Unload() |
|
400 | 49 | Taonnor-14572 | if (lib.suppressCount > 0) then |
401 | Taonnor-14572 | if lib.debugMode then zo_callLater(function() LogMessage(LOG_WARNING, "There is a measure in progress before loading is completed.") end, 2000) end |
|
402 | Taonnor-14572 | FinalizeMeasurement() |
|
403 | Taonnor-14572 | end |
|
404 | 61 | Taonnor-14572 | end |
405 | 40 | Taonnor-14572 | |
406 | Taonnor-14572 | --- Register new Unload |
|
407 | Taonnor-14572 | function lib:Unload() |
|
408 | 49 | Taonnor-14572 | for funcName, func in pairs(orgFunctions) do |
409 | Taonnor-14572 | _G[funcName] = func |
|
410 | Taonnor-14572 | end |
|
411 | 40 | Taonnor-14572 | |
412 | Taonnor-14572 | LMP:UnregisterCallback("AfterPingAdded", HandlePingEvent) |
|
413 | Taonnor-14572 | LMP:UnregisterCallback("AfterPingRemoved", HandlePingEvent) |
|
414 | 49 | Taonnor-14572 | |
415 | Taonnor-14572 | rootMaps, mapMeasurements, mapStack = nil, nil, nil |
|
416 | 40 | Taonnor-14572 | end |
417 | Taonnor-14572 | ||
418 | 49 | Taonnor-14572 | ConnectToWorldMap() |
419 | 40 | Taonnor-14572 | |
420 | 49 | Taonnor-14572 | HookSetMapToFunction("SetMapToQuestCondition") |
421 | Taonnor-14572 | HookSetMapToFunction("SetMapToQuestStepEnding") |
|
422 | Taonnor-14572 | HookSetMapToFunction("SetMapToQuestZone") |
|
423 | 40 | Taonnor-14572 | HookSetMapToPlayerLocation() |
424 | Taonnor-14572 | HookSetMapToMapListIndex() |
|
425 | Taonnor-14572 | HookProcessMapClick() |
|
426 | Taonnor-14572 | HookSetMapFloor() |
|
427 | Taonnor-14572 | ||
428 | Taonnor-14572 | StoreTamrielMapMeasurements() |
|
429 | 49 | Taonnor-14572 | |
430 | Taonnor-14572 | local function addRootMap(zoneId) |
|
431 | Taonnor-14572 | local mapIndex = GetMapIndexByZoneId(zoneId) |
|
432 | Taonnor-14572 | if mapIndex then rootMaps[mapIndex] = false end |
|
433 | Taonnor-14572 | end |
|
434 | Taonnor-14572 | addRootMap(347) -- Coldhabour |
|
435 | Taonnor-14572 | addRootMap(980) -- Clockwork City |
|
436 | Taonnor-14572 | -- Any future extra dimension map here |
|
437 | Taonnor-14572 | ||
438 | 40 | Taonnor-14572 | SetMapToPlayerLocation() -- initial measurement so we can get back to where we are currently |
439 | Taonnor-14572 | ||
440 | Taonnor-14572 | LMP:RegisterCallback("AfterPingAdded", HandlePingEvent) |
|
441 | Taonnor-14572 | LMP:RegisterCallback("AfterPingRemoved", HandlePingEvent) |
|
442 | Taonnor-14572 | end |
|
443 | Taonnor-14572 | ||
444 | Taonnor-14572 | ------------------------ public functions ---------------------- |
|
445 | Taonnor-14572 | ||
446 | Taonnor-14572 | --- Returns true as long as the player exists. |
|
447 | Taonnor-14572 | function lib:IsReady() |
|
448 | Taonnor-14572 | return DoesUnitExist("player") |
|
449 | Taonnor-14572 | end |
|
450 | Taonnor-14572 | ||
451 | Taonnor-14572 | --- Returns true if the library is currently doing any measurements. |
|
452 | Taonnor-14572 | function lib:IsMeasuring() |
|
453 | Taonnor-14572 | return measuring |
|
454 | Taonnor-14572 | end |
|
455 | Taonnor-14572 | ||
456 | Taonnor-14572 | --- Removes all cached measurement values. |
|
457 | Taonnor-14572 | function lib:ClearMapMeasurements() |
|
458 | Taonnor-14572 | mapMeasurements = { } |
|
459 | Taonnor-14572 | end |
|
460 | Taonnor-14572 | ||
461 | Taonnor-14572 | --- Removes the cached measurement values for the map that is currently active. |
|
462 | Taonnor-14572 | function lib:ClearCurrentMapMeasurements() |
|
463 | Taonnor-14572 | local mapId = GetMapTileTexture() |
|
464 | Taonnor-14572 | mapMeasurements[mapId] = nil |
|
465 | Taonnor-14572 | end |
|
466 | Taonnor-14572 | ||
467 | Taonnor-14572 | --- Returns a table with the measurement values for the active map or nil if the measurements could not be calculated for some reason. |
|
468 | Taonnor-14572 | --- The table contains scaleX, scaleY, offsetX, offsetY and mapIndex. |
|
469 | Taonnor-14572 | --- scaleX and scaleY are the dimensions of the active map on the Tamriel map. |
|
470 | Taonnor-14572 | --- offsetX and offsetY are the offset of the top left corner on the Tamriel map. |
|
471 | Taonnor-14572 | --- mapIndex is the mapIndex of the parent zone of the current map. |
|
472 | Taonnor-14572 | function lib:GetCurrentMapMeasurements() |
|
473 | Taonnor-14572 | local mapId = GetMapTileTexture() |
|
474 | Taonnor-14572 | if (not mapMeasurements[mapId]) then |
|
475 | Taonnor-14572 | -- try to calculate the measurements if they are not yet available |
|
476 | Taonnor-14572 | lib:CalculateMapMeasurements() |
|
477 | Taonnor-14572 | end |
|
478 | Taonnor-14572 | return mapMeasurements[mapId] |
|
479 | Taonnor-14572 | end |
|
480 | Taonnor-14572 | ||
481 | 49 | Taonnor-14572 | --- Returns the mapIndex and zoneIndex of the parent zone for the currently set map. |
482 | Taonnor-14572 | --- return[1] number - The mapIndex of the parent zone |
|
483 | Taonnor-14572 | --- return[2] number - The zoneIndex of the parent zone |
|
484 | Taonnor-14572 | function lib:GetCurrentMapParentZoneIndices() |
|
485 | Taonnor-14572 | local measurements = lib:GetCurrentMapMeasurements() |
|
486 | Taonnor-14572 | local mapIndex = measurements.mapIndex |
|
487 | Taonnor-14572 | if(not measurements.zoneIndex) then |
|
488 | Taonnor-14572 | lib:PushCurrentMap() |
|
489 | Taonnor-14572 | SetMapToMapListIndex(mapIndex) |
|
490 | Taonnor-14572 | measurements.zoneIndex = GetCurrentMapZoneIndex() |
|
491 | Taonnor-14572 | lib:PopCurrentMap() |
|
492 | Taonnor-14572 | end |
|
493 | Taonnor-14572 | local zoneIndex = measurements.zoneIndex |
|
494 | Taonnor-14572 | return mapIndex, zoneIndex |
|
495 | Taonnor-14572 | end |
|
496 | Taonnor-14572 | ||
497 | 40 | Taonnor-14572 | --- Calculates the measurements for the current map and all parent maps. |
498 | Taonnor-14572 | --- This method does nothing if there is already a cached measurement for the active map. |
|
499 | Taonnor-14572 | --- return[1] boolean - True, if a valid measurement was calculated |
|
500 | Taonnor-14572 | --- return[2] SetMapResultCode - Specifies if the map has changed or failed during measurement (independent of the actual result of the measurement) |
|
501 | Taonnor-14572 | function lib:CalculateMapMeasurements(returnToInitialMap) |
|
502 | Taonnor-14572 | -- cosmic map cannot be measured (GetMapPlayerWaypoint returns 0,0) |
|
503 | Taonnor-14572 | if (GetMapType() == MAPTYPE_COSMIC) then return false, SET_MAP_RESULT_CURRENT_MAP_UNCHANGED end |
|
504 | Taonnor-14572 | ||
505 | Taonnor-14572 | -- no need to take measurements more than once |
|
506 | Taonnor-14572 | local mapId = GetMapTileTexture() |
|
507 | Taonnor-14572 | if (mapMeasurements[mapId] or mapId == "") then return false end |
|
508 | Taonnor-14572 | ||
509 | Taonnor-14572 | if (lib.debugMode) then |
|
510 | Taonnor-14572 | LogMessage("Called from", GetAddon(), "for", mapId) |
|
511 | Taonnor-14572 | end |
|
512 | Taonnor-14572 | ||
513 | Taonnor-14572 | -- get the player position on the current map |
|
514 | Taonnor-14572 | local localX, localY = GetPlayerPosition() |
|
515 | Taonnor-14572 | if (localX == 0 and localY == 0) then |
|
516 | Taonnor-14572 | -- cannot take measurements while player position is not initialized |
|
517 | Taonnor-14572 | return false, SET_MAP_RESULT_CURRENT_MAP_UNCHANGED |
|
518 | Taonnor-14572 | end |
|
519 | Taonnor-14572 | ||
520 | Taonnor-14572 | returnToInitialMap = (returnToInitialMap ~= false) |
|
521 | Taonnor-14572 | ||
522 | Taonnor-14572 | measuring = true |
|
523 | Taonnor-14572 | CALLBACK_MANAGER:FireCallbacks(lib.LIB_EVENT_STATE_CHANGED, measuring) |
|
524 | Taonnor-14572 | ||
525 | Taonnor-14572 | -- check some facts about the current map, so we can reset it later |
|
526 | Taonnor-14572 | -- local oldMapIsZoneMap, oldMapFloor, oldMapFloorCount |
|
527 | Taonnor-14572 | if returnToInitialMap then |
|
528 | Taonnor-14572 | lib:PushCurrentMap() |
|
529 | Taonnor-14572 | end |
|
530 | Taonnor-14572 | ||
531 | Taonnor-14572 | local hasWaypoint = LMP:HasMapPing(MAP_PIN_TYPE_PLAYER_WAYPOINT) |
|
532 | Taonnor-14572 | if(hasWaypoint) then StoreCurrentWaypoint() end |
|
533 | Taonnor-14572 | ||
534 | Taonnor-14572 | local mapIndex = CalculateMeasurements(mapId, localX, localY) |
|
535 | Taonnor-14572 | ||
536 | Taonnor-14572 | -- Until now, the waypoint was abused. Now the waypoint must be restored or removed again (not from Lua only). |
|
537 | Taonnor-14572 | if(hasWaypoint) then |
|
538 | Taonnor-14572 | RestoreCurrentWaypoint() |
|
539 | Taonnor-14572 | else |
|
540 | Taonnor-14572 | RemovePlayerWaypoint() |
|
541 | Taonnor-14572 | end |
|
542 | Taonnor-14572 | ||
543 | Taonnor-14572 | if (returnToInitialMap) then |
|
544 | Taonnor-14572 | local result = lib:PopCurrentMap() |
|
545 | Taonnor-14572 | return true, result |
|
546 | Taonnor-14572 | end |
|
547 | Taonnor-14572 | ||
548 | Taonnor-14572 | return true, (mapId == GetMapTileTexture()) and SET_MAP_RESULT_CURRENT_MAP_UNCHANGED or SET_MAP_RESULT_MAP_CHANGED |
|
549 | Taonnor-14572 | end |
|
550 | Taonnor-14572 | ||
551 | Taonnor-14572 | --- Converts the given map coordinates on the current map into coordinates on the Tamriel map. |
|
552 | Taonnor-14572 | --- Returns x and y on the world map and the mapIndex of the parent zone |
|
553 | Taonnor-14572 | --- or nil if the measurements of the active map are not available. |
|
554 | Taonnor-14572 | function lib:LocalToGlobal(x, y) |
|
555 | Taonnor-14572 | local measurements = lib:GetCurrentMapMeasurements() |
|
556 | Taonnor-14572 | if (measurements) then |
|
557 | Taonnor-14572 | x = x * measurements.scaleX + measurements.offsetX |
|
558 | Taonnor-14572 | y = y * measurements.scaleY + measurements.offsetY |
|
559 | Taonnor-14572 | return x, y, measurements.mapIndex |
|
560 | Taonnor-14572 | end |
|
561 | Taonnor-14572 | end |
|
562 | Taonnor-14572 | ||
563 | Taonnor-14572 | --- Converts the given global coordinates into a position on the active map. |
|
564 | Taonnor-14572 | --- Returns x and y on the current map or nil if the measurements of the active map are not available. |
|
565 | Taonnor-14572 | function lib:GlobalToLocal(x, y) |
|
566 | Taonnor-14572 | local measurements = lib:GetCurrentMapMeasurements() |
|
567 | Taonnor-14572 | if (measurements) then |
|
568 | Taonnor-14572 | x = (x - measurements.offsetX) / measurements.scaleX |
|
569 | Taonnor-14572 | y = (y - measurements.offsetY) / measurements.scaleY |
|
570 | Taonnor-14572 | return x, y |
|
571 | Taonnor-14572 | end |
|
572 | Taonnor-14572 | end |
|
573 | Taonnor-14572 | ||
574 | Taonnor-14572 | --- Converts the given map coordinates on the specified zone map into coordinates on the Tamriel map. |
|
575 | Taonnor-14572 | --- This method is useful if you want to convert global positions from the old LibGPS version into the new format. |
|
576 | Taonnor-14572 | --- Returns x and y on the world map and the mapIndex of the parent zone |
|
577 | Taonnor-14572 | --- or nil if the measurements of the zone map are not available. |
|
578 | Taonnor-14572 | function lib:ZoneToGlobal(mapIndex, x, y) |
|
579 | Taonnor-14572 | lib:GetCurrentMapMeasurements() |
|
580 | Taonnor-14572 | -- measurement done in here: |
|
581 | Taonnor-14572 | SetMapToMapListIndex(mapIndex) |
|
582 | Taonnor-14572 | x, y, mapIndex = lib:LocalToGlobal(x, y) |
|
583 | Taonnor-14572 | return x, y, mapIndex |
|
584 | Taonnor-14572 | end |
|
585 | Taonnor-14572 | ||
586 | Taonnor-14572 | --- This function zooms and pans to the specified position on the active map. |
|
587 | Taonnor-14572 | function lib:PanToMapPosition(x, y) |
|
588 | Taonnor-14572 | -- if we don't have access to the mapPinManager we cannot do anything |
|
589 | 49 | Taonnor-14572 | if (not self.mapPinManager) then return end |
590 | Taonnor-14572 | local mapPinManager = self.mapPinManager |
|
591 | 40 | Taonnor-14572 | -- create dummy pin |
592 | Taonnor-14572 | local pin = mapPinManager:CreatePin(_G[DUMMY_PIN_TYPE], "libgpsdummy", x, y) |
|
593 | Taonnor-14572 | ||
594 | 49 | Taonnor-14572 | self.panAndZoom:PanToPin(pin) |
595 | 40 | Taonnor-14572 | |
596 | Taonnor-14572 | -- cleanup |
|
597 | Taonnor-14572 | mapPinManager:RemovePins(DUMMY_PIN_TYPE) |
|
598 | Taonnor-14572 | end |
|
599 | Taonnor-14572 | ||
600 | Taonnor-14572 | local function FakeZO_WorldMap_IsMapChangingAllowed() return true end |
|
601 | Taonnor-14572 | local function FakeSetMapToMapListIndex() return SET_MAP_RESULT_MAP_CHANGED end |
|
602 | Taonnor-14572 | local FakeCALLBACK_MANAGER = { FireCallbacks = function() end } |
|
603 | Taonnor-14572 | ||
604 | Taonnor-14572 | --- This function sets the current map as player chosen so it won't switch back to the previous map. |
|
605 | Taonnor-14572 | function lib:SetPlayerChoseCurrentMap() |
|
606 | Taonnor-14572 | -- replace the original functions |
|
607 | Taonnor-14572 | local oldIsChangingAllowed = ZO_WorldMap_IsMapChangingAllowed |
|
608 | Taonnor-14572 | ZO_WorldMap_IsMapChangingAllowed = FakeZO_WorldMap_IsMapChangingAllowed |
|
609 | Taonnor-14572 | ||
610 | Taonnor-14572 | local oldSetMapToMapListIndex = SetMapToMapListIndex |
|
611 | Taonnor-14572 | SetMapToMapListIndex = FakeSetMapToMapListIndex |
|
612 | Taonnor-14572 | ||
613 | Taonnor-14572 | local oldCALLBACK_MANAGER = CALLBACK_MANAGER |
|
614 | Taonnor-14572 | CALLBACK_MANAGER = FakeCALLBACK_MANAGER |
|
615 | Taonnor-14572 | ||
616 | Taonnor-14572 | -- make our rigged call to set the player chosen flag |
|
617 | Taonnor-14572 | ZO_WorldMap_SetMapByIndex() |
|
618 | Taonnor-14572 | ||
619 | Taonnor-14572 | -- cleanup |
|
620 | Taonnor-14572 | ZO_WorldMap_IsMapChangingAllowed = oldIsChangingAllowed |
|
621 | Taonnor-14572 | SetMapToMapListIndex = oldSetMapToMapListIndex |
|
622 | Taonnor-14572 | CALLBACK_MANAGER = oldCALLBACK_MANAGER |
|
623 | Taonnor-14572 | end |
|
624 | Taonnor-14572 | ||
625 | 61 | Taonnor-14572 | --- Sets the best matching root map: Tamriel, Cold Harbour or Clockwork City and what ever will come. |
626 | Taonnor-14572 | --- Returns SET_MAP_RESULT_FAILED, SET_MAP_RESULT_MAP_CHANGED depending on the result of the API calls. |
|
627 | Taonnor-14572 | function lib:SetMapToRootMap(x, y) |
|
628 | Taonnor-14572 | local result = SET_MAP_RESULT_FAILED |
|
629 | Taonnor-14572 | for rootMapIndex, measurements in pairs(rootMaps) do |
|
630 | Taonnor-14572 | if (not measurements) then |
|
631 | Taonnor-14572 | measurements = GetExtraMapMeasurement(rootMapIndex) |
|
632 | Taonnor-14572 | rootMaps[rootMapIndex] = measurements |
|
633 | Taonnor-14572 | result = SET_MAP_RESULT_MAP_CHANGED |
|
634 | Taonnor-14572 | end |
|
635 | Taonnor-14572 | if (measurements) then |
|
636 | Taonnor-14572 | if (x > measurements.offsetX and x < (measurements.offsetX + measurements.scaleX) and |
|
637 | Taonnor-14572 | y > measurements.offsetY and y < (measurements.offsetY + measurements.scaleY)) then |
|
638 | Taonnor-14572 | if (orgSetMapToMapListIndex(rootMapIndex) ~= SET_MAP_RESULT_FAILED) then |
|
639 | Taonnor-14572 | return SET_MAP_RESULT_MAP_CHANGED |
|
640 | Taonnor-14572 | end |
|
641 | Taonnor-14572 | end |
|
642 | Taonnor-14572 | end |
|
643 | Taonnor-14572 | end |
|
644 | Taonnor-14572 | return result |
|
645 | Taonnor-14572 | end |
|
646 | Taonnor-14572 | ||
647 | 40 | Taonnor-14572 | --- Repeatedly calls ProcessMapClick on the given global position starting on the Tamriel map until nothing more would happen. |
648 | Taonnor-14572 | --- Returns SET_MAP_RESULT_FAILED, SET_MAP_RESULT_MAP_CHANGED or SET_MAP_RESULT_CURRENT_MAP_UNCHANGED depending on the result of the API calls. |
|
649 | Taonnor-14572 | function lib:MapZoomInMax(x, y) |
|
650 | 61 | Taonnor-14572 | local result = lib:SetMapToRootMap(x, y) |
651 | 40 | Taonnor-14572 | |
652 | Taonnor-14572 | if (result ~= SET_MAP_RESULT_FAILED) then |
|
653 | 61 | Taonnor-14572 | local localX, localY = lib:GlobalToLocal(x, y) |
654 | 40 | Taonnor-14572 | |
655 | Taonnor-14572 | while WouldProcessMapClick(localX, localY) do |
|
656 | Taonnor-14572 | result = orgProcessMapClick(localX, localY) |
|
657 | Taonnor-14572 | if (result == SET_MAP_RESULT_FAILED) then break end |
|
658 | Taonnor-14572 | localX, localY = lib:GlobalToLocal(x, y) |
|
659 | Taonnor-14572 | end |
|
660 | Taonnor-14572 | end |
|
661 | Taonnor-14572 | ||
662 | Taonnor-14572 | return result |
|
663 | Taonnor-14572 | end |
|
664 | Taonnor-14572 | ||
665 | Taonnor-14572 | --- Stores information about how we can back to this map on a stack. |
|
666 | 49 | Taonnor-14572 | -- There is no panAndZoom:GetCurrentOffset(), yet |
667 | Taonnor-14572 | local function CalculateContainerAnchorOffsets() |
|
668 | Taonnor-14572 | local containerCenterX, containerCenterY = ZO_WorldMapContainer:GetCenter() |
|
669 | Taonnor-14572 | local scrollCenterX, scrollCenterY = ZO_WorldMapScroll:GetCenter() |
|
670 | Taonnor-14572 | return containerCenterX - scrollCenterX, containerCenterY - scrollCenterY |
|
671 | Taonnor-14572 | end |
|
672 | 40 | Taonnor-14572 | function lib:PushCurrentMap() |
673 | 49 | Taonnor-14572 | local wasPlayerLocation, targetMapTileTexture, currentMapFloor, currentMapFloorCount, currentMapIndex, zoom, offsetX, offsetY |
674 | 40 | Taonnor-14572 | currentMapIndex = GetCurrentMapIndex() |
675 | 49 | Taonnor-14572 | wasPlayerLocation = DoesCurrentMapMatchMapForPlayerLocation() |
676 | 40 | Taonnor-14572 | targetMapTileTexture = GetMapTileTexture() |
677 | Taonnor-14572 | currentMapFloor, currentMapFloorCount = GetMapFloorInfo() |
|
678 | 49 | Taonnor-14572 | zoom = self.panAndZoom:GetCurrentZoom() |
679 | Taonnor-14572 | offsetX, offsetY = CalculateContainerAnchorOffsets() |
|
680 | 40 | Taonnor-14572 | |
681 | 49 | Taonnor-14572 | mapStack[#mapStack + 1] = { wasPlayerLocation, targetMapTileTexture, currentMapFloor, currentMapFloorCount, currentMapIndex, zoom, offsetX, offsetY } |
682 | 40 | Taonnor-14572 | end |
683 | Taonnor-14572 | ||
684 | Taonnor-14572 | --- Switches to the map that was put on the stack last. |
|
685 | Taonnor-14572 | --- Returns SET_MAP_RESULT_FAILED, SET_MAP_RESULT_MAP_CHANGED or SET_MAP_RESULT_CURRENT_MAP_UNCHANGED depending on the result of the API calls. |
|
686 | Taonnor-14572 | function lib:PopCurrentMap() |
|
687 | Taonnor-14572 | local result = SET_MAP_RESULT_FAILED |
|
688 | Taonnor-14572 | local data = table.remove(mapStack, #mapStack) |
|
689 | Taonnor-14572 | if(not data) then |
|
690 | Taonnor-14572 | LogMessage(LOG_DEBUG, "PopCurrentMap failed. No data on map stack.") |
|
691 | Taonnor-14572 | return result |
|
692 | Taonnor-14572 | end |
|
693 | Taonnor-14572 | ||
694 | 49 | Taonnor-14572 | local wasPlayerLocation, targetMapTileTexture, currentMapFloor, currentMapFloorCount, currentMapIndex, zoom, offsetX, offsetY = unpack(data) |
695 | 40 | Taonnor-14572 | local currentTileTexture = GetMapTileTexture() |
696 | Taonnor-14572 | if(currentTileTexture ~= targetMapTileTexture) then |
|
697 | Taonnor-14572 | if(wasPlayerLocation) then |
|
698 | Taonnor-14572 | result = orgSetMapToPlayerLocation() |
|
699 | Taonnor-14572 | ||
700 | Taonnor-14572 | elseif(currentMapIndex ~= nil and currentMapIndex > 0) then -- set to a zone map |
|
701 | Taonnor-14572 | result = orgSetMapToMapListIndex(currentMapIndex) |
|
702 | Taonnor-14572 | ||
703 | Taonnor-14572 | else -- here is where it gets tricky |
|
704 | Taonnor-14572 | local target = mapMeasurements[targetMapTileTexture] |
|
705 | Taonnor-14572 | if(not target) then -- always just return to player map if we cannot restore the previous map. |
|
706 | Taonnor-14572 | LogMessage(LOG_DEBUG, string.format("No measurement for \"%s\". Returning to player location.", targetMapTileTexture)) |
|
707 | Taonnor-14572 | return orgSetMapToPlayerLocation() |
|
708 | Taonnor-14572 | end |
|
709 | Taonnor-14572 | ||
710 | Taonnor-14572 | -- switch to the parent zone |
|
711 | Taonnor-14572 | if(target.mapIndex == TAMRIEL_MAP_INDEX) then -- zone map has no mapIndex (e.g. Eyevea or Hew's Bane on first PTS patch for update 9) |
|
712 | Taonnor-14572 | -- switch to the tamriel map just in case |
|
713 | Taonnor-14572 | result = orgSetMapToMapListIndex(TAMRIEL_MAP_INDEX) |
|
714 | Taonnor-14572 | if(result == SET_MAP_RESULT_FAILED) then return result end |
|
715 | Taonnor-14572 | -- get global coordinates of target map center |
|
716 | Taonnor-14572 | local x = target.offsetX + (target.scaleX / 2) |
|
717 | Taonnor-14572 | local y = target.offsetY + (target.scaleY / 2) |
|
718 | Taonnor-14572 | if(not WouldProcessMapClick(x, y)) then |
|
719 | Taonnor-14572 | LogMessage(LOG_DEBUG, string.format("Cannot process click at %s/%s on map \"%s\" in order to get to \"%s\". Returning to player location instead.", tostring(x), tostring(y), GetMapTileTexture(), targetMapTileTexture)) |
|
720 | Taonnor-14572 | return orgSetMapToPlayerLocation() |
|
721 | Taonnor-14572 | end |
|
722 | Taonnor-14572 | result = orgProcessMapClick(x, y) |
|
723 | Taonnor-14572 | if(result == SET_MAP_RESULT_FAILED) then return result end |
|
724 | Taonnor-14572 | else |
|
725 | Taonnor-14572 | result = orgSetMapToMapListIndex(target.mapIndex) |
|
726 | Taonnor-14572 | if(result == SET_MAP_RESULT_FAILED) then return result end |
|
727 | Taonnor-14572 | end |
|
728 | Taonnor-14572 | ||
729 | Taonnor-14572 | -- switch to the sub zone |
|
730 | Taonnor-14572 | currentTileTexture = GetMapTileTexture() |
|
731 | Taonnor-14572 | if(currentTileTexture ~= targetMapTileTexture) then |
|
732 | Taonnor-14572 | -- determine where on the zone map we have to click to get to the sub zone map |
|
733 | Taonnor-14572 | -- get global coordinates of target map center |
|
734 | Taonnor-14572 | local x = target.offsetX + (target.scaleX / 2) |
|
735 | Taonnor-14572 | local y = target.offsetY + (target.scaleY / 2) |
|
736 | Taonnor-14572 | -- transform to local coordinates |
|
737 | Taonnor-14572 | local current = mapMeasurements[currentTileTexture] |
|
738 | Taonnor-14572 | if(not current) then |
|
739 | Taonnor-14572 | LogMessage(LOG_DEBUG, string.format("No measurement for \"%s\". Returning to player location.", currentTileTexture)) |
|
740 | Taonnor-14572 | return orgSetMapToPlayerLocation() |
|
741 | Taonnor-14572 | end |
|
742 | Taonnor-14572 | ||
743 | Taonnor-14572 | x = (x - current.offsetX) / current.scaleX |
|
744 | Taonnor-14572 | y = (y - current.offsetY) / current.scaleY |
|
745 | Taonnor-14572 | ||
746 | Taonnor-14572 | if(not WouldProcessMapClick(x, y)) then |
|
747 | Taonnor-14572 | LogMessage(LOG_DEBUG, string.format("Cannot process click at %s/%s on map \"%s\" in order to get to \"%s\". Returning to player location instead.", tostring(x), tostring(y), GetMapTileTexture(), targetMapTileTexture)) |
|
748 | Taonnor-14572 | return orgSetMapToPlayerLocation() |
|
749 | Taonnor-14572 | end |
|
750 | Taonnor-14572 | result = orgProcessMapClick(x, y) |
|
751 | Taonnor-14572 | if(result == SET_MAP_RESULT_FAILED) then return result end |
|
752 | Taonnor-14572 | end |
|
753 | Taonnor-14572 | ||
754 | Taonnor-14572 | -- switch to the correct floor (e.g. Elden Root) |
|
755 | Taonnor-14572 | if (currentMapFloorCount > 0) then |
|
756 | Taonnor-14572 | result = orgSetMapFloor(currentMapFloor) |
|
757 | Taonnor-14572 | end |
|
758 | 49 | Taonnor-14572 | if (result ~= SET_MAP_RESULT_FAILED) then |
759 | Taonnor-14572 | lib.panAndZoom:SetCurrentZoom(zoom) |
|
760 | Taonnor-14572 | lib.panAndZoom:SetCurrentOffset(offsetX, offsetY) |
|
761 | Taonnor-14572 | end |
|
762 | 61 | Taonnor-14572 | end |
763 | 40 | Taonnor-14572 | else |
764 | Taonnor-14572 | result = SET_MAP_RESULT_CURRENT_MAP_UNCHANGED |
|
765 | Taonnor-14572 | end |
|
766 | Taonnor-14572 | ||
767 | Taonnor-14572 | return result |
|
768 | Taonnor-14572 | end |
|
769 | Taonnor-14572 | ||
770 | Taonnor-14572 | Initialize() |