-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathElmsMarkers.lua
More file actions
252 lines (215 loc) · 9.09 KB
/
Copy pathElmsMarkers.lua
File metadata and controls
252 lines (215 loc) · 9.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
function ElmsMarkers.OnAddOnLoaded( eventCode, addonName )
if (addonName ~= ElmsMarkers.name) then return end
EVENT_MANAGER:UnregisterForEvent(ElmsMarkers.name, EVENT_ADD_ON_LOADED)
ElmsMarkers.savedVars = ZO_SavedVars:NewCharacterIdSettings("ElmsMarkersSavedVariables", ElmsMarkers.variableVersion, nil, ElmsMarkers.defaults, nil, GetWorldName())
SLASH_COMMANDS["/elms"] = ElmsMarkers.HandleCommandInput
EVENT_MANAGER:RegisterForEvent(ElmsMarkers.name, EVENT_PLAYER_ACTIVATED, ElmsMarkers.CheckActivation)
EVENT_MANAGER:RegisterForEvent(ElmsMarkers.name, EVENT_ZONE_CHANGED, ElmsMarkers.CheckActivation)
EVENT_MANAGER:RegisterForUpdate(ElmsMarkers.name .. 'cycle', 100, ElmsMarkers.Cycle)
ElmsMarkers.buildMenu()
ElmsMarkers.setupUI()
ElmsMarkers.shareMapData = LibDataShare:RegisterMap("ElmsMarkers", 2, ElmsMarkers.HandleData)
end
function ElmsMarkers.HandleData(tag, data)
if tag and data then
if(tag == GetGroupLeaderUnitTag() and ElmsMarkers.savedVars.subscribeToLead) then
local dataIdentifier = data % 10
if dataIdentifier == 1 then
local wX = data / 100000
local iconId = data % 100000 / 10
elseif dataIdentifier == 2 then
local wZ = data / 100000
local zone = data % 100000 / 10
elseif dataIdentifier == 9 then
local wY = data / 1000
local isAdd = data % 1000 / 100
end
end
end
end
function ElmsMarkers.Cycle()
if LibDataShare:IsSendWindow() then
end
end
function ElmsMarkers.HandleCommandInput(args)
args = args:gsub("%s+", "")
if not args or args == "" then
ElmsMarkers.UI.frame:SetHidden(false)
elseif args == "toggle" or args == "t" then
ElmsMarkers.savedVars.enabled = not ElmsMarkers.savedVars.enabled
CHAT_SYSTEM:AddMessage("[ElmsMarkers] " .. (ElmsMarkers.savedVars.enabled and "Enabled" or "Disabled"))
ElmsMarkers.CheckActivation()
elseif args == "publish" or args == "pp" then
local location = ElmsMarkers.PlaceAndPublish()
if(location) then
CHAT_SYSTEM:AddMessage("[ElmsMarkers] Published new marker at " .. location[2] .. ", " .. location[3] .. ", " .. location[4])
end
elseif args == "place" or args == "p" then
local location = ElmsMarkers.PlaceAtMe()
CHAT_SYSTEM:AddMessage("[ElmsMarkers] Placed new marker at " .. location[2] .. ", " .. location[3] .. ", " .. location[4])
elseif args == "remove" or args == "r" then
local location = ElmsMarkers.RemoveNearestMarker()
if(location) then
CHAT_SYSTEM:AddMessage("[ElmsMarkers] Removed marker at " .. location[2] .. ", " .. location[3] .. ", " .. location[4])
end
end
end
function ElmsMarkers.CheckActivation( eventCode )
local zoneId = GetZoneId(GetUnitZoneIndex("player"))
for zone, markers in pairs(ElmsMarkers.savedVars.positions) do
ElmsMarkers.RemovePositionIcons(zone)
end
if (ElmsMarkers.savedVars.positions[zoneId] and ElmsMarkers.savedVars.enabled) then
ElmsMarkers.PlacePositionIcons(ElmsMarkers.savedVars.positions[zoneId], zoneId)
end
ElmsMarkers.CreateConfigString()
end
function ElmsMarkers.PlacePositionIcons(positions, zoneId)
if not ElmsMarkers.placedIcons[zoneId] then
ElmsMarkers.placedIcons[zoneId] = {}
end
if OSI and OSI.CreatePositionIcon then
for i, iconLocation in pairs(positions) do
if iconLocation then
ElmsMarkers.DoPlaceIcon(zoneId, iconLocation[1], iconLocation[2], iconLocation[3], ElmsMarkers.iconData[iconLocation[4]])
end
end
end
end
function ElmsMarkers.RemovePositionIcons(zoneId)
if ElmsMarkers.placedIcons[zoneId] then
for k, v in pairs(ElmsMarkers.placedIcons[zoneId]) do
if OSI and OSI.DiscardPositionIcon then
OSI.DiscardPositionIcon(v)
end
end
end
ElmsMarkers.placedIcons[zoneId] = nil
end
function ElmsMarkers.PlaceAtMe()
local zone, wX, wY, wZ = GetUnitRawWorldPosition( "player" )
return ElmsMarkers.PlaceAtLocation({zone, wX, wY, wZ})
end
function ElmsMarkers.PlaceAtLocation(location)
if not OSI or not OSI.CreatePositionIcon then return end
local zone, wX, wY, wZ = unpack(location)
local zonePositions = ElmsMarkers.savedVars.positions[zone]
if not zonePositions then
ElmsMarkers.savedVars.positions[zone] = { [1] = {wX, wY, wZ, ElmsMarkers.savedVars.selectedIconTexture} }
else
table.insert(ElmsMarkers.savedVars.positions[zone], {wX, wY, wZ, ElmsMarkers.savedVars.selectedIconTexture})
end
if not ElmsMarkers.placedIcons[zone] then
ElmsMarkers.placedIcons[zone] = {}
end
ElmsMarkers.DoPlaceIcon(zone, wX, wY, wZ, ElmsMarkers.iconData[ElmsMarkers.savedVars.selectedIconTexture])
ElmsMarkers.CreateConfigString()
return {zone, wX, wY, wZ, ElmsMarkers.savedVars.selectedIconTexture}
end
function ElmsMarkers.PlaceAndPublish()
local timeNow = GetGameTimeMilliseconds()
if(ElmsMarkers.lastPingTime == nil or (timeNow - ElmsMarkers.lastPingTime > ElmsMarkers.PING_RATE)) then
if AreUnitsEqual(GetGroupLeaderUnitTag(), 'player') then
local location = ElmsMarkers.PlaceAtMe()
ElmsMarkers.EncodeEnqueuePublish(location, true)
return location
else
CHAT_SYSTEM:AddMessage("[ElmsMarkers] You must be the group lead to publish markers!")
end
else
CHAT_SYSTEM:AddMessage("[ElmsMarkers] You're publishing too quickly! Publish not sent, try again later.")
end
end
function ElmsMarkers.EncodeEnqueuePublish(location, isAdd)
local zone, wX, wY, wZ, iconId = unpack(location)
-- ping 1: wX iconId
-- ping 2: wZ zone
-- ping 3: wY isAdd/isRemove endSignature
local addBit = isAdd and 1 or 0
local endSignature = 99
local dataPacket1 = wX * 100000 + iconId * 10 + 1
local dataPacket2 = wZ * 100000 + zone * 10 + 2
local dataPacket3 = wY * 1000 + addBit * 100 + endSignature
local wX = math.floor(dataPacket1 / 100000)
local iconId = math.floor(dataPacket1 % 100000 / 10)
local wZ = math.floor(dataPacket2 / 100000)
local zone = math.floor(dataPacket2 % 100000 / 10)
local wY = math.floor(dataPacket3 / 1000)
local isAdd = math.floor(dataPacket3 % 1000 / 100)
d(wX, wY, wZ, zone, iconId, isAdd)
zo_callLater(ElmsMarkers.shareMapData:SendData(dataPacket1), 100)
zo_callLater(ElmsMarkers.shareMapData:SendData(dataPacket2), 200)
zo_callLater(ElmsMarkers.shareMapData:SendData(dataPacket3), 300)
ElmsMarkers.lastPingTime = GetGameTimeMilliseconds()
end
function ElmsMarkers.RemoveNearestMarker()
if not OSI or not OSI.DiscardPositionIcon then return end
local zone, wX, wY, wZ = GetUnitRawWorldPosition( "player" )
local zonePositions = ElmsMarkers.placedIcons[zone]
if(not zonePositions) then return end
local closestMarker
local closestMarkerIndex
local shortestDistance = 9999
local currentDistance
for i, pos in pairs(zonePositions) do
currentDistance = (zo_sqrt((pos.x - wX)^2 + (pos.z - wZ)^2) / 100)
if currentDistance < shortestDistance then
shortestDistance = currentDistance
closestMarker = pos
closestMarkerIndex = i
end
end
if closestMarker then
OSI.DiscardPositionIcon(closestMarker)
ElmsMarkers.placedIcons[zone][closestMarkerIndex] = nil
for k,v in pairs(ElmsMarkers.savedVars.positions[zone]) do
if v[1] == closestMarker.x and v[2] == closestMarker.y and v[3] == closestMarker.z then
closestMarkerIndex = k
end
end
ElmsMarkers.savedVars.positions[zone][closestMarkerIndex] = nil
return {zone, closestMarker.x, closestMarker.y, closestMarker.z, ElmsMarkers.savedVars.selectedIconTexture}
end
ElmsMarkers.CreateConfigString()
end
function ElmsMarkers.ClearZone()
if not OSI or not OSI.DiscardPositionIcon then return end
local zone = GetUnitRawWorldPosition( "player" )
for k, v in pairs(ElmsMarkers.placedIcons[zone]) do
OSI.DiscardPositionIcon(v)
end
ElmsMarkers.placedIcons[zone] = nil
ElmsMarkers.savedVars.positions[zone] = nil
ElmsMarkers.CreateConfigString()
end
function ElmsMarkers.DoPlaceIcon(zone, x, y, z, texture)
local iconSize = ElmsMarkers.savedVars.selectedIconSize / 64.0
table.insert(ElmsMarkers.placedIcons[zone], OSI.CreatePositionIcon( x, y, z, texture, iconSize * OSI.GetIconSize()))
end
function ElmsMarkers.CreateConfigString()
local zone = GetUnitRawWorldPosition( "player" )
local configString = ""
local zonePositions = ElmsMarkers.savedVars.positions[zone]
if zonePositions then
for k, v in pairs(zonePositions) do
configString = configString .. "/" .. zone .. "//" .. v[1] .. "," .. v[2] .. "," .. v[3] .. "," .. v[4] .. "/"
end
end
ElmsMarkers.savedVars.configStringExport = configString
end
function ElmsMarkers.ParseImportConfigString()
for zone, x, y, z, iconKey in string.gmatch(ElmsMarkers.savedVars.configStringImport, "/(%d+)//(%d+),(%d+),(%d+),(%d+)/") do
zone = tonumber(zone)
x = tonumber(x)
y = tonumber(y)
z = tonumber(z)
iconKey = tonumber(iconKey)
if not ElmsMarkers.savedVars.positions[zone] then
ElmsMarkers.savedVars.positions[zone] = {}
end
table.insert(ElmsMarkers.savedVars.positions[zone], {x, y, z, iconKey})
end
ElmsMarkers.savedVars.configStringImport = ""
ElmsMarkers.CheckActivation()
end
EVENT_MANAGER:RegisterForEvent(ElmsMarkers.name, EVENT_ADD_ON_LOADED, ElmsMarkers.OnAddOnLoaded)