Initial commit
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| /build | ||||
							
								
								
									
										6
									
								
								src/aliases/galaxy-map/aliases.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/aliases/galaxy-map/aliases.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "gmap-refresh", | ||||
|     "regex": "^gmap refresh$" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										5
									
								
								src/aliases/galaxy-map/gmap-refresh.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/aliases/galaxy-map/gmap-refresh.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| lotj.galaxyMap.resetData() | ||||
|  | ||||
| enableTrigger("galaxy-map-refresh") | ||||
| send("starsystems", false) | ||||
| send("planets", false) | ||||
							
								
								
									
										7
									
								
								src/aliases/mapper/aliases.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/aliases/mapper/aliases.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "map", | ||||
|     "regex": "^map( ?.*)$", | ||||
|     "script": "lotj.mapper.mapCommand(matches[2])" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										6
									
								
								src/aliases/system-map/aliases.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/aliases/system-map/aliases.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "radar", | ||||
|     "regex": "^r(a(d(a(r)?)?)?)?$" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										4
									
								
								src/aliases/system-map/radar.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/aliases/system-map/radar.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| -- Intercept the radar command to enable our radar scraping triggers. | ||||
| -- We don't want them to potentially fire on unrelated lines. | ||||
| enableTrigger("system-map-radar") | ||||
| send("radar", false) | ||||
							
								
								
									
										
											BIN
										
									
								
								src/resources/space.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/resources/space.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 90 KiB | 
							
								
								
									
										34
									
								
								src/scripts/chat/chat.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/scripts/chat/chat.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| lotj = lotj or {} | ||||
| lotj.chat = lotj.chat or {} | ||||
|  | ||||
| registerAnonymousEventHandler("lotjUICreated", function() | ||||
|   for keyword, contentsContainer in pairs(lotj.layout.lowerRightTabData.contents) do | ||||
|     lotj.chat[keyword] = Geyser.MiniConsole:new({ | ||||
|       x = "1%", y = "1%", | ||||
|       width = "98%", | ||||
|       height = "98%", | ||||
|       autoWrap = false, | ||||
|       color = "black", | ||||
|       scrollBar = true, | ||||
|       fontSize = 14, | ||||
|     }, contentsContainer) | ||||
|  | ||||
|   -- Set the wrap at a few characters short of the full width to avoid the scroll bar showing over text | ||||
|   local charsPerLine = lotj.chat[keyword]:getColumnCount()-3 | ||||
|   lotj.chat[keyword]:setWrap(charsPerLine) | ||||
|     registerAnonymousEventHandler("sysWindowResizeEvent", function() | ||||
|       local charsPerLine = lotj.chat[keyword]:getColumnCount()-3 | ||||
|       lotj.chat[keyword]:setWrap(charsPerLine) | ||||
|     end) | ||||
|   end | ||||
| end) | ||||
|  | ||||
| function lotj.chat.routeMessage(type) | ||||
|   selectCurrentLine() | ||||
|   copy() | ||||
|   lotj.chat[type]:cecho("<reset>"..getTime(true, "hh:mm:ss").." ") | ||||
|   lotj.chat[type]:appendBuffer() | ||||
|  | ||||
|   lotj.chat.all:cecho("<reset>"..getTime(true, "hh:mm:ss").." ") | ||||
|   lotj.chat.all:appendBuffer() | ||||
| end | ||||
							
								
								
									
										5
									
								
								src/scripts/chat/scripts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/scripts/chat/scripts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "chat" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										319
									
								
								src/scripts/galaxy-map/galaxy-map.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								src/scripts/galaxy-map/galaxy-map.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,319 @@ | ||||
| lotj = lotj or {} | ||||
| lotj.galaxyMap = lotj.galaxyMap or { | ||||
|   data = { | ||||
|     labelAsPlanets = true, | ||||
|     systems = {}, | ||||
|     planets = {}, | ||||
|     govToColor = { | ||||
|       ["Neutral Government"] = "#AAAAAA", | ||||
|     }, | ||||
|   } | ||||
| } | ||||
|  | ||||
| local dataFileName = getMudletHomeDir().."/galaxyMap" | ||||
| registerAnonymousEventHandler("lotjUICreated", function() | ||||
|   lotj.galaxyMap.container = Geyser.Label:new({ | ||||
|     name = "galaxy", | ||||
|     x = 0, y = 0, | ||||
|     width = "100%", | ||||
|     height = "100%", | ||||
|   }, lotj.layout.upperRightTabData.contents["galaxy"]) | ||||
|   lotj.galaxyMap.container:setBackgroundImage(getMudletHomeDir().."/@PKGNAME@/space.jpg") | ||||
|    | ||||
|   lotj.galaxyMap.refreshButton = Geyser.Label:new({ | ||||
|     name = "galaxyMapRefresh", | ||||
|     x = "20%", y = "35%", | ||||
|     width = "60%", height = 40, | ||||
|   }, lotj.galaxyMap.container) | ||||
|   lotj.galaxyMap.refreshButton:setStyleSheet([[ | ||||
|     background-color: grey; | ||||
|     border: 1px solid white; | ||||
|   ]]) | ||||
|   lotj.galaxyMap.refreshButton:echo("Click here to populate this map.", "white", "c14") | ||||
|   lotj.galaxyMap.refreshButton:setClickCallback(function() | ||||
|     expandAlias("gmap refresh", false) | ||||
|   end) | ||||
|    | ||||
|   disableTrigger("galaxy-map-refresh") | ||||
|   if io.exists(dataFileName) then | ||||
|     table.load(dataFileName, lotj.galaxyMap.data) | ||||
|     lotj.galaxyMap.log("Loaded map data.") | ||||
|     lotj.galaxyMap.drawSystems() | ||||
|   end | ||||
|  | ||||
|   registerAnonymousEventHandler("msdp.SHIPGALY", lotj.galaxyMap.setShipGalCoords) | ||||
| end) | ||||
|  | ||||
|  | ||||
| function lotj.galaxyMap.log(text) | ||||
|   cecho("[<cyan>LOTJ Galaxy Map<reset>] "..text.."\n") | ||||
| end | ||||
|  | ||||
| function lotj.galaxyMap.setShipGalCoords() | ||||
|   -- Assume "0" in both values means we don't have valid coordinates and leave them what they were. | ||||
|   -- TODO: Find a way to support a system actually located at 0, 0 | ||||
|   if msdp.SHIPGALX ~= "0" or msdp.SHIPGALY ~= "0" then | ||||
|     lotj.galaxyMap.currentX = tonumber(msdp.SHIPGALX) | ||||
|     lotj.galaxyMap.currentY = tonumber(msdp.SHIPGALY) | ||||
|     lotj.galaxyMap.drawSystems() | ||||
|   end | ||||
| end | ||||
|  | ||||
| local function container() | ||||
|   return lotj.galaxyMap.container | ||||
| end | ||||
|  | ||||
| -- Fire off any showplanet commands we still need to run to load data for all known planets | ||||
| function lotj.galaxyMap.enqueuePendingRefreshCommands() | ||||
|   for planet in pairs(gatherPlanetsState.pendingBasic) do | ||||
|     send("showplanet \""..planet.."\"", false) | ||||
|     gatherPlanetsState.pendingCommands = gatherPlanetsState.pendingCommands + 1 | ||||
|   end | ||||
|   for planet in pairs(gatherPlanetsState.pendingResources) do | ||||
|     send("showplanet \""..planet.."\" resources", false) | ||||
|     gatherPlanetsState.pendingCommands = gatherPlanetsState.pendingCommands + 1 | ||||
|   end | ||||
|  | ||||
|   -- We didn't have to retry any, so we're done getting info. | ||||
|   if gatherPlanetsState.pendingCommands == 0 then | ||||
|     disableTrigger("galaxy-map-refresh") | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   echo("\n") | ||||
|   lotj.galaxyMap.log("Enqueueing "..gatherPlanetsState.pendingCommands.." showplanet commands.") | ||||
| end | ||||
|  | ||||
| function lotj.galaxyMap.resetData() | ||||
|   lotj.galaxyMap.data.planets = {} | ||||
|   lotj.galaxyMap.data.systems = {} | ||||
| end | ||||
|  | ||||
| local govColorIdx = 1 | ||||
| local govColorList = {} | ||||
| table.insert(govColorList, "#E69F00") | ||||
| table.insert(govColorList, "#56B4E9") | ||||
| table.insert(govColorList, "#009E73") | ||||
| table.insert(govColorList, "#F0E442") | ||||
| table.insert(govColorList, "#D55E00") | ||||
| table.insert(govColorList, "#CC79A7") | ||||
|  | ||||
| function lotj.galaxyMap.recordSystem(name, x, y) | ||||
|   lotj.galaxyMap.data.systems = lotj.galaxyMap.data.systems or {} | ||||
|   lotj.galaxyMap.data.systems[name] = { | ||||
|     name = name, | ||||
|     planets = {}, | ||||
|     gov = "Neutral Government", | ||||
|     x = x, | ||||
|     y = y, | ||||
|   } | ||||
|   table.save(dataFileName, lotj.galaxyMap.data) | ||||
|    | ||||
|   lotj.galaxyMap.drawSystems() | ||||
| end | ||||
|  | ||||
| function lotj.galaxyMap.recordPlanet(planetData) | ||||
|   if not lotj.galaxyMap.data.planets[planetData.name] then | ||||
|     lotj.galaxyMap.data.planets[planetData.name] = { | ||||
|       name = planetData.name, | ||||
|       gov = planetData.gov, | ||||
|       system = planetData.system, | ||||
|     } | ||||
|  | ||||
|     local system = lotj.galaxyMap.data.systems[planetData.system] | ||||
|     if system ~= nil then | ||||
|       system.gov = planetData.gov | ||||
|       table.insert(system.planets, planetData.name) | ||||
|     else | ||||
|       lotj.galaxyMap.log("Unable to find system "..planetData.system.." for planet "..planetData.name) | ||||
|     end | ||||
|  | ||||
|     if lotj.galaxyMap.data.govToColor[planetData.gov] == nil then | ||||
|       govColorIdx = govColorIdx+1 | ||||
|       lotj.galaxyMap.data.govToColor[planetData.gov] = govColorList[govColorIdx] | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   if planetData.coords ~= nil then | ||||
|     lotj.galaxyMap.data.planets[planetData.name].coords = planetData.coords | ||||
|   end | ||||
|   if planetData.freeport ~= nil then | ||||
|     lotj.galaxyMap.data.planets[planetData.name].freeport = planetData.freeport | ||||
|   end | ||||
|   if planetData.taxRate ~= nil then | ||||
|     lotj.galaxyMap.data.planets[planetData.name].taxRate = planetData.taxRate | ||||
|   end | ||||
|   if planetData.resources ~= nil then | ||||
|     lotj.galaxyMap.data.planets[planetData.name].resources = planetData.resources | ||||
|   end | ||||
|  | ||||
|   table.save(dataFileName, lotj.galaxyMap.data) | ||||
|  | ||||
|   lotj.galaxyMap.drawSystems() | ||||
| end | ||||
|  | ||||
| local systemPointSize = 14 | ||||
| local function stylePoint(point, gov, currentSystem) | ||||
|   local backgroundColor = lotj.galaxyMap.data.govToColor[gov] or "#AAAAAA" | ||||
|   local borderStyle = "" | ||||
|   if currentSystem then | ||||
|     borderStyle = "border: 2px solid red;" | ||||
|   end | ||||
|   point:setStyleSheet([[ | ||||
|     border-radius: ]]..math.floor(systemPointSize/2)..[[px; | ||||
|     background-color: ]]..backgroundColor..[[; | ||||
|     ]]..borderStyle..[[ | ||||
|   ]]) | ||||
| end | ||||
|  | ||||
| local function systemDisplayName(system) | ||||
|   if lotj.galaxyMap.data.labelAsPlanets and #(system.planets or {}) > 0 then | ||||
|     local labelString = "" | ||||
|     for _, planet in ipairs(system.planets) do | ||||
|       if #labelString > 0 then | ||||
|         labelString = labelString..", " | ||||
|       end | ||||
|       labelString = labelString..planet | ||||
|     end | ||||
|     return labelString | ||||
|   else | ||||
|     -- Cut off common extra words from the system name to keep labels short | ||||
|     local labelString = system.name | ||||
|     labelString = string.gsub(labelString, " System$", "") | ||||
|     labelString = string.gsub(labelString, " Sector$", "") | ||||
|     return labelString | ||||
|   end | ||||
| end | ||||
|  | ||||
| function lotj.galaxyMap.drawSystems() | ||||
|   local minX, _, _, maxY = lotj.galaxyMap.coordRange() | ||||
|   local xOffset, yOffset, pxPerCoord = lotj.galaxyMap.calculateSizing() | ||||
|    | ||||
|   lotj.galaxyMap.systemPoints = lotj.galaxyMap.systemPoints or {} | ||||
|   for _, point in pairs(lotj.galaxyMap.systemPoints) do | ||||
|     point:hide() | ||||
|   end | ||||
|  | ||||
|   lotj.galaxyMap.systemLabels = lotj.galaxyMap.systemLabels or {} | ||||
|   for _, label in pairs(lotj.galaxyMap.systemLabels) do | ||||
|     label:hide() | ||||
|   end | ||||
|  | ||||
|    | ||||
|   local foundCurrentLocation = false | ||||
|   local systemsToDraw = {} | ||||
|   for _, system in pairs(lotj.galaxyMap.data.systems) do | ||||
|     table.insert(systemsToDraw, system) | ||||
|     if system.x == lotj.galaxyMap.currentX and system.y == lotj.galaxyMap.currentY then | ||||
|       foundCurrentLocation = true | ||||
|     end | ||||
|   end | ||||
|   if not foundCurrentLocation and lotj.galaxyMap.currentX and lotj.galaxyMap.currentY then | ||||
|     table.insert(systemsToDraw, { | ||||
|       name = "Current", | ||||
|       x = lotj.galaxyMap.currentX, | ||||
|       y = lotj.galaxyMap.currentY | ||||
|     }) | ||||
|   end | ||||
|  | ||||
|   -- Hide or show the refresh button accordingly, based on whether we have any data. | ||||
|   if #systemsToDraw > 0 then | ||||
|     lotj.galaxyMap.refreshButton:hide() | ||||
|   else | ||||
|     lotj.galaxyMap.refreshButton:show() | ||||
|   end | ||||
|    | ||||
|   for _, system in ipairs(systemsToDraw) do | ||||
|     local point = lotj.galaxyMap.systemPoints[system.name] | ||||
|     if point == nil then | ||||
|       point = Geyser.Label:new({width=systemPointSize, height=systemPointSize}, container()) | ||||
|       stylePoint(point, system.gov, false) | ||||
|       lotj.galaxyMap.systemPoints[system.name] = point | ||||
|     else | ||||
|       point:show() | ||||
|     end | ||||
|  | ||||
|     local label = lotj.galaxyMap.systemLabels[system.name] | ||||
|     if label == nil then | ||||
|       label = Geyser.Label:new({ | ||||
|         height = 16, width = 100, | ||||
|         fillBg = 0, | ||||
|       }, container()) | ||||
|        | ||||
|       lotj.galaxyMap.systemLabels[system.name] = label | ||||
|     else | ||||
|       label:show() | ||||
|     end | ||||
|     label:echo(systemDisplayName(system), "white", "12c") | ||||
|      | ||||
|     local sysX = math.floor(xOffset + (system.x-minX)*pxPerCoord - systemPointSize/2 + 0.5) | ||||
|     local sysY = math.floor(yOffset + (maxY-system.y)*pxPerCoord - systemPointSize/2 + 0.5) | ||||
|     point:move(sysX, sysY) | ||||
|     if system.x == lotj.galaxyMap.currentX and system.y == lotj.galaxyMap.currentY then | ||||
|       stylePoint(point, system.gov, true) | ||||
|     else | ||||
|       stylePoint(point, system.gov, false) | ||||
|     end | ||||
|      | ||||
|     label:move(math.max(sysX-45, 0), sysY+systemPointSize) | ||||
|   end | ||||
| end | ||||
|  | ||||
| -- Returns X starting point, Y starting point, and pixels per coordinate | ||||
| function lotj.galaxyMap.calculateSizing() | ||||
|   local minX, maxX, minY, maxY = lotj.galaxyMap.coordRange() | ||||
|   local xRange = maxX-minX | ||||
|   local yRange = maxY-minY | ||||
|   local contWidth = container():get_width() | ||||
|   local contHeight = container():get_height() | ||||
|    | ||||
|   -- Determine whether the map would be limited by height or width first. | ||||
|   local mapWidth = nil | ||||
|   local mapHeight = nil | ||||
|   local pxPerCoord = nil | ||||
|   local pxHeightIfLimitedByWidth = (contWidth/xRange)*yRange | ||||
|   local pxWidthIfLimitedByHeight = (contHeight/yRange)*xRange | ||||
|   if pxHeightIfLimitedByWidth <= contHeight then | ||||
|     -- Width was the limiting factor, so use it to determine sizing | ||||
|     mapWidth = contWidth | ||||
|     mapHeight = pxHeightIfLimitedByWidth | ||||
|     pxPerCoord = contWidth/xRange | ||||
|   elseif pxWidthIfLimitedByHeight <= contWidth then | ||||
|     -- Width was the limiting factor, so use it to determine sizing | ||||
|     mapWidth = pxWidthIfLimitedByHeight | ||||
|     mapHeight = contHeight | ||||
|     pxPerCoord = contHeight/yRange | ||||
|   else | ||||
|     echo("Unable to determine appropriate galaxy map dimensions. This is a script bug.\n") | ||||
|   end | ||||
|    | ||||
|   local mapAnchorX = (contWidth-mapWidth)/2 | ||||
|   local mapAnchorY = (contHeight-mapHeight)/2 | ||||
|    | ||||
|   return mapAnchorX, mapAnchorY, pxPerCoord | ||||
| end | ||||
|  | ||||
| function lotj.galaxyMap.coordRange() | ||||
|   local minX = 0 | ||||
|   local maxX = 0 | ||||
|   local minY = 0 | ||||
|   local maxY = 0 | ||||
|    | ||||
|   for _, system in pairs(lotj.galaxyMap.data.systems) do | ||||
|     if minX > system.x then | ||||
|       minX = system.x | ||||
|     end | ||||
|     if maxX < system.x then | ||||
|       maxX = system.x | ||||
|     end | ||||
|     if minY > system.y then | ||||
|       minY = system.y | ||||
|     end | ||||
|     if maxY < system.y then | ||||
|       maxY = system.y | ||||
|     end | ||||
|   end | ||||
|    | ||||
|   -- Pad all values by 10 to ensure points are displayed reasonably. | ||||
|   return minX-10, maxX+10, minY-10, maxY+10 | ||||
| end | ||||
							
								
								
									
										5
									
								
								src/scripts/galaxy-map/scripts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/scripts/galaxy-map/scripts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "galaxy-map" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										369
									
								
								src/scripts/info-panel/info-panel.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										369
									
								
								src/scripts/info-panel/info-panel.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,369 @@ | ||||
| lotj = lotj or {} | ||||
| lotj.infoPanel = lotj.infoPanel or {} | ||||
|  | ||||
|  | ||||
| registerAnonymousEventHandler("lotjUICreated", function() | ||||
|   local basicStatsContainer = Geyser.Label:new({ | ||||
|     h_stretch_factor = 0.9 | ||||
|   }, lotj.layout.lowerInfoPanel) | ||||
|   local combatContainer = Geyser.Label:new({ | ||||
|     h_stretch_factor = 0.9 | ||||
|   }, lotj.layout.lowerInfoPanel) | ||||
|   local chatContainer = Geyser.Label:new({ | ||||
|     h_stretch_factor = 1 | ||||
|   }, lotj.layout.lowerInfoPanel) | ||||
|   local spaceContainer = Geyser.Label:new({ | ||||
|     h_stretch_factor = 2.2 | ||||
|   }, lotj.layout.lowerInfoPanel) | ||||
|    | ||||
|   lotj.infoPanel.createBasicStats(basicStatsContainer) | ||||
|   lotj.infoPanel.createOpponentStats(combatContainer) | ||||
|   lotj.infoPanel.createChatInfo(chatContainer) | ||||
|   lotj.infoPanel.createSpaceStats(spaceContainer) | ||||
| end) | ||||
|  | ||||
|  | ||||
| -- Utility functions | ||||
| local function gaugeFrontStyle(step1, step2, step3, step4, step5) | ||||
|   return [[ | ||||
|     background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 ]]..step1..[[, stop: 0.1 ]]..step2..[[, stop: 0.49 ]]..step3..[[, stop: 0.5 ]]..step4..[[, stop: 1 ]]..step5..[[); | ||||
|     border-top: 1px black solid; | ||||
|     border-left: 1px black solid; | ||||
|     border-bottom: 1px black solid; | ||||
|     padding: 3px; | ||||
|   ]] | ||||
| end | ||||
|  | ||||
| local function gaugeBackStyle(step1, step2, step3, step4, step5) | ||||
|   return [[ | ||||
|     background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 ]]..step1..[[, stop: 0.1 ]]..step2..[[, stop: 0.49 ]]..step3..[[, stop: 0.5 ]]..step4..[[, stop: 1 ]]..step5..[[); | ||||
|     border-width: 1px; | ||||
|     border-color: black; | ||||
|     border-style: solid; | ||||
|     padding: 3px; | ||||
|   ]] | ||||
| end | ||||
|  | ||||
| local function styleGaugeText(gauge, fontSize) | ||||
|   gauge.text:setStyleSheet([[ | ||||
|     padding-right: 10px; | ||||
|   ]]) | ||||
|   gauge:setAlignment("r") | ||||
|   gauge:setFontSize(fontSize) | ||||
| end | ||||
|  | ||||
| -- Wires up MSDP subscriptions for a gauge. | ||||
| -- statName is the short version of the stat name to show after the value (mv, hp, etc) | ||||
| local function wireGaugeUpdate(gauge, valueVarName, maxVarName, statName) | ||||
|   local function doUpdate() | ||||
|     local current = tonumber(msdp[valueVarName] or "0") | ||||
|     local max = tonumber(msdp[maxVarName] or "0") | ||||
|     if max > 0 then | ||||
|       gauge:setValue(current, max, current.."/"..max.." "..statName) | ||||
|     else | ||||
|       gauge:setValue(0, 1, "") | ||||
|     end | ||||
|   end | ||||
|   registerAnonymousEventHandler("msdp."..valueVarName, doUpdate) | ||||
|   registerAnonymousEventHandler("msdp."..maxVarName, doUpdate) | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.infoPanel.createBasicStats(container) | ||||
|   -- Health gauge | ||||
|   local healthGauge = Geyser.Gauge:new({ | ||||
|     x="5%", y=4, | ||||
|     width="90%", height=16, | ||||
|   }, container) | ||||
|   healthGauge.front:setStyleSheet(gaugeFrontStyle("#f04141", "#ef2929", "#cc0000", "#a40000", "#cc0000")) | ||||
|   healthGauge.back:setStyleSheet(gaugeBackStyle("#3f1111", "#3f0707", "#330000", "#220000", "#330000")) | ||||
|   styleGaugeText(healthGauge, 12) | ||||
|   wireGaugeUpdate(healthGauge, "HEALTH", "HEALTHMAX", "hp") | ||||
|    | ||||
|   local wimpyBar = Geyser.Label:new({ | ||||
|     x=0, y=0, | ||||
|     width=2, height="100%", | ||||
|   }, healthGauge.front) | ||||
|   wimpyBar:setStyleSheet([[ | ||||
|     background-color: yellow; | ||||
|   ]]) | ||||
|  | ||||
|   registerAnonymousEventHandler("msdp.WIMPY", function() | ||||
|     local health = tonumber(msdp.HEALTH or 0) | ||||
|     local healthMax = tonumber(msdp.HEALTHMAX or 0) | ||||
|     local wimpy = tonumber(msdp.WIMPY or 0) | ||||
|     if healthMax > 0 then | ||||
|       if wimpy > 0 and health > 0 and wimpy < health then | ||||
|         wimpyBar:show() | ||||
|         wimpyBar:move(math.floor(wimpy*100/health).."%", nil) | ||||
|       else | ||||
|         wimpyBar:hide() | ||||
|       end | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|   -- Movement gauge | ||||
|   local movementGauge = Geyser.Gauge:new({ | ||||
|     x="5%", y=23, | ||||
|     width="90%", height=16, | ||||
|   }, container) | ||||
|   movementGauge.front:setStyleSheet(gaugeFrontStyle("#41f041", "#29ef29", "#00cc00", "#00a400", "#00cc00")) | ||||
|   movementGauge.back:setStyleSheet(gaugeBackStyle("#113f11", "#073f07", "#003300", "#002200", "#003300")) | ||||
|   styleGaugeText(movementGauge, 12) | ||||
|   wireGaugeUpdate(movementGauge, "MOVEMENT", "MOVEMENTMAX", "mv") | ||||
|  | ||||
|   -- Mana gauge (will be hidden later if we do not have mana) | ||||
|   local manaGauge = Geyser.Gauge:new({ | ||||
|     x="5%", y=42, | ||||
|     width="90%", height=16, | ||||
|   }, container) | ||||
|   manaGauge.front:setStyleSheet(gaugeFrontStyle("#4141f0", "#2929ef", "#0000cc", "#0000a4", "#0000cc")) | ||||
|   manaGauge.back:setStyleSheet(gaugeBackStyle("#11113f", "#07073f", "#000033", "#000022", "#000011")) | ||||
|   styleGaugeText(manaGauge, 12) | ||||
|   wireGaugeUpdate(manaGauge, "MANA", "MANAMAX", "mn") | ||||
|    | ||||
|   registerAnonymousEventHandler("msdp.MANAMAX", function() | ||||
|     local manaMax = tonumber(msdp.MANAMAX or 0) | ||||
|     if manaMax > 0 then | ||||
|       healthGauge:move(nil, 4) | ||||
|       healthGauge:resize(nil, 16) | ||||
|       healthGauge:setFontSize("12") | ||||
|    | ||||
|       movementGauge:move(nil, 23) | ||||
|       movementGauge:resize(nil, 16) | ||||
|       movementGauge:setFontSize("12") | ||||
|    | ||||
|       manaGauge:show() | ||||
|       manaGauge:move(nil, 42) | ||||
|       manaGauge:resize(nil, 16) | ||||
|       manaGauge:setFontSize("12") | ||||
|     else | ||||
|       healthGauge:move(nil, 6) | ||||
|       healthGauge:resize(nil, 22) | ||||
|       healthGauge:setFontSize("13") | ||||
|    | ||||
|       movementGauge:move(nil, 32) | ||||
|       movementGauge:resize(nil, 22) | ||||
|       movementGauge:setFontSize("13") | ||||
|    | ||||
|       manaGauge:hide() | ||||
|     end | ||||
|   end) | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.infoPanel.createOpponentStats(container) | ||||
|   -- Opponent health gauge | ||||
|   local opponentGauge = Geyser.Gauge:new({ | ||||
|     x="5%", y=6, | ||||
|     width="90%", height=48, | ||||
|   }, container) | ||||
|   opponentGauge.front:setStyleSheet(gaugeFrontStyle("#bd7833", "#bd6e20", "#994c00", "#703800", "#994c00")) | ||||
|   opponentGauge.back:setStyleSheet(gaugeBackStyle("#442511", "#441d08", "#331100", "#200900", "#331100")) | ||||
|   opponentGauge.text:setStyleSheet("padding: 10px;") | ||||
|   opponentGauge:setAlignment("c") | ||||
|   opponentGauge:setFontSize("12") | ||||
|  | ||||
|   local function update() | ||||
|     local opponentName = string.gsub(msdp.OPPONENTNAME or "", "&.", "") | ||||
|     -- Opponent name seems to always be empty string even when fighting, so fall back to something reasonable | ||||
|     if opponentName == "" then | ||||
|       opponentName = "Current target" | ||||
|     end | ||||
|     local opponentHealth = tonumber(msdp.OPPONENTHEALTH or "0") | ||||
|     local opponentHealthMax = tonumber(msdp.OPPONENTHEALTHMAX or "0") | ||||
|     if opponentHealth > 0 then | ||||
|       opponentGauge:setValue(opponentHealth, opponentHealthMax, opponentName.."<br>"..opponentHealth.."%") | ||||
|     else | ||||
|       opponentGauge:setValue(0, 1, "Not fighting") | ||||
|     end | ||||
|   end | ||||
|   registerAnonymousEventHandler("msdp.OPPONENTNAME", update) | ||||
|   registerAnonymousEventHandler("msdp.OPPONENTHEALTH", update) | ||||
|   registerAnonymousEventHandler("msdp.OPPONENTHEALTHMAX", update) | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.infoPanel.createChatInfo(container) | ||||
|   -- Commnet channel/code | ||||
|   local commnetLabel = Geyser.Label:new({ | ||||
|     x="3%", y=6, | ||||
|     width="20%", height=24, | ||||
|   }, container) | ||||
|   commnetLabel:echo("Comm:", nil, "rb13") | ||||
|   local commnetInfo = Geyser.Label:new({ | ||||
|     x = "25%", y = 6, | ||||
|     width = "75%", height = 24 | ||||
|   }, container) | ||||
|  | ||||
|   local function updateCommnet() | ||||
|     local commChannel = msdp.COMMCHANNEL or "0" | ||||
|     local commEncrypt = msdp.COMMENCRYPT or "0" | ||||
|     if commEncrypt == "0" then | ||||
|       commnetInfo:echo(commChannel, nil, "l13") | ||||
|     else | ||||
|       commnetInfo:echo(commChannel.." (E "..commEncrypt..")", nil, "l13") | ||||
|     end | ||||
|   end | ||||
|   registerAnonymousEventHandler("msdp.COMMCHANNEL", updateCommnet) | ||||
|   registerAnonymousEventHandler("msdp.COMMENCRYPT", updateCommnet) | ||||
|  | ||||
|   -- OOC meter | ||||
|   local oocLabel = Geyser.Label:new({ | ||||
|     x="3%", y=32, | ||||
|     width="20%", height=24, | ||||
|   }, container) | ||||
|   oocLabel:echo("OOC:", nil, "rb13") | ||||
|   local oocGauge = Geyser.Gauge:new({ | ||||
|     x="25%", y=32, | ||||
|     width="40%", height=20, | ||||
|   }, container) | ||||
|   oocGauge.front:setStyleSheet(gaugeFrontStyle("#31d0d0", "#22cfcf", "#00b2b2", "#009494", "#00b2b2")) | ||||
|   oocGauge.back:setStyleSheet(gaugeBackStyle("#113f3f", "#073f3f", "#003333", "#002222", "#001111")) | ||||
|  | ||||
|   registerAnonymousEventHandler("msdp.OOCLIMIT", function() | ||||
|     local oocLeft = tonumber(msdp.OOCLIMIT or 0) | ||||
|     local oocMax = 6 | ||||
|     oocGauge:setValue(oocLeft, oocMax) | ||||
|   end) | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.infoPanel.createSpaceStats(container) | ||||
|   local energyGauge = Geyser.Gauge:new({ | ||||
|     x="3%", y=4, | ||||
|     width="30%", height=16, | ||||
|   }, container) | ||||
|   energyGauge.front:setStyleSheet(gaugeFrontStyle("#7a7a7a", "#777777", "#656565", "#505050", "#656565")) | ||||
|   energyGauge.back:setStyleSheet(gaugeBackStyle("#383838", "#303030", "#222222", "#151515", "#222222")) | ||||
|   styleGaugeText(energyGauge, 12) | ||||
|   wireGaugeUpdate(energyGauge, "SHIPENERGY", "SHIPMAXENERGY", "en") | ||||
|  | ||||
|   local hullGauge = Geyser.Gauge:new({ | ||||
|     x="3%", y=23, | ||||
|     width="30%", height=16, | ||||
|   }, container) | ||||
|   hullGauge.front:setStyleSheet(gaugeFrontStyle("#bd7833", "#bd6e20", "#994c00", "#703800", "#994c00")) | ||||
|   hullGauge.back:setStyleSheet(gaugeBackStyle("#442511", "#441d08", "#331100", "#200900", "#331100")) | ||||
|   styleGaugeText(hullGauge, 12) | ||||
|   wireGaugeUpdate(hullGauge, "SHIPHULL", "SHIPMAXHULL", "hl") | ||||
|  | ||||
|   local shieldGauge = Geyser.Gauge:new({ | ||||
|     x="3%", y=42, | ||||
|     width="30%", height=16, | ||||
|   }, container) | ||||
|   shieldGauge.front:setStyleSheet(gaugeFrontStyle("#31d0d0", "#22cfcf", "#00b2b2", "#009494", "#00b2b2")) | ||||
|   shieldGauge.back:setStyleSheet(gaugeBackStyle("#113f3f", "#073f3f", "#003333", "#002222", "#001111")) | ||||
|   styleGaugeText(shieldGauge, 12) | ||||
|   wireGaugeUpdate(shieldGauge, "SHIPSHIELD", "SHIPMAXSHIELD", "sh") | ||||
|  | ||||
|    | ||||
|   -- Piloting indicator | ||||
|   local pilotLabel = Geyser.Label:new({ | ||||
|     x="35%", y=6, | ||||
|     width="13%", height=24 | ||||
|   }, container) | ||||
|   pilotLabel:echo("Pilot:", nil, "lb12") | ||||
|  | ||||
|   local pilotBoxCont = Geyser.Label:new({ | ||||
|     x="48%", y=10, | ||||
|     width="8%", height=16 | ||||
|   }, container) | ||||
|   local pilotBox = Geyser.Label:new({ | ||||
|     x=2, y=0, | ||||
|     width=16, height=16 | ||||
|   }, pilotBoxCont) | ||||
|  | ||||
|   registerAnonymousEventHandler("msdp.PILOTING", function() | ||||
|     local piloting = tonumber(msdp.PILOTING or "0") | ||||
|     if piloting == 1 then | ||||
|       pilotBox:setStyleSheet("background-color: #29efef; border: 2px solid #eeeeee;") | ||||
|     else | ||||
|       pilotBox:setStyleSheet("background-color: #073f3f; border: 2px solid #eeeeee;") | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|  | ||||
|   local speedGauge = Geyser.Label:new({ | ||||
|     x="56%", y=6, | ||||
|     width="19%", height=24, | ||||
|   }, container) | ||||
|    | ||||
|   local function updateSpeed() | ||||
|     local speed = tonumber(msdp.SHIPSPEED or "0") | ||||
|     local maxSpeed = tonumber(msdp.SHIPMAXSPEED or "0") | ||||
|     speedGauge:echo("<b>Sp:</b> "..speed.."<b>/</b>"..maxSpeed, nil, "l12") | ||||
|   end | ||||
|   registerAnonymousEventHandler("msdp.SHIPSPEED", updateSpeed) | ||||
|   registerAnonymousEventHandler("msdp.SHIPMAXSPEED", updateSpeed) | ||||
|  | ||||
|  | ||||
|   local coordsInfo = Geyser.Label:new({ | ||||
|     x="35%", y=32, | ||||
|     width="40%", height=24, | ||||
|   }, container) | ||||
|  | ||||
|   local function updateCoords() | ||||
|     local shipX = tonumber(msdp.SHIPSYSX or "0") | ||||
|     local shipY = tonumber(msdp.SHIPSYSY or "0") | ||||
|     local shipZ = tonumber(msdp.SHIPSYSZ or "0") | ||||
|     coordsInfo:echo("<b>Coords:</b> "..shipX.." "..shipY.." "..shipZ, nil, "l12") | ||||
|   end | ||||
|   registerAnonymousEventHandler("msdp.SHIPSYSX", updateCoords) | ||||
|   registerAnonymousEventHandler("msdp.SHIPSYSY", updateCoords) | ||||
|   registerAnonymousEventHandler("msdp.SHIPSYSZ", updateCoords) | ||||
|  | ||||
|   lotj.infoPanel.spaceTickCounter = Geyser.Label:new({ | ||||
|     x="77%", y=6, | ||||
|     width="20%", height=24, | ||||
|   }, container) | ||||
|  | ||||
|   lotj.infoPanel.chaffIndicator = Geyser.Label:new({ | ||||
|     x="77%", y=32, | ||||
|     width="20%", height=24, | ||||
|   }, container) | ||||
|   lotj.infoPanel.chaffIndicator:echo("[Chaff]", "yellow", "c13b") | ||||
|   lotj.infoPanel.chaffIndicator:hide() | ||||
| end | ||||
|  | ||||
| -- Sets up timers to refresh the space tick counter | ||||
| function lotj.infoPanel.markSpaceTick() | ||||
|   for _, timerId in ipairs(lotj.infoPanel.spaceTickTimers or {}) do | ||||
|     killTimer(timerId) | ||||
|   end | ||||
|  | ||||
|   lotj.infoPanel.spaceTickCounter:show() | ||||
|   lotj.infoPanel.spaceTickTimers = {} | ||||
|   for i = 0,20,1 do | ||||
|     local timerId = tempTimer(i, function() | ||||
|       lotj.infoPanel.spaceTickCounter:echo("<b>Tick:</b> "..20-i, nil, "c13") | ||||
|     end) | ||||
|     table.insert(lotj.infoPanel.spaceTickTimers, timerId) | ||||
|   end | ||||
|  | ||||
|   -- A few seconds after the next tick should happen, hide the counter. | ||||
|   -- This will be canceled if we see another tick before then. | ||||
|   local timerId = tempTimer(23, function() | ||||
|     lotj.infoPanel.spaceTickCounter:hide() | ||||
|   end) | ||||
|   table.insert(lotj.infoPanel.spaceTickTimers, timerId) | ||||
| end | ||||
|  | ||||
| function lotj.infoPanel.markChaff() | ||||
|   lotj.infoPanel.clearChaff() | ||||
|   lotj.infoPanel.chaffIndicator:show() | ||||
|  | ||||
|   -- In case we miss the "chaff cleared" message somehow, set a 20 second timer to get rid of this | ||||
|   lotj.infoPanel.chaffTimer = tempTimer(20, function() | ||||
|     lotj.infoPanel.clearChaff() | ||||
|   end) | ||||
| end | ||||
|  | ||||
| function lotj.infoPanel.clearChaff() | ||||
|   if lotj.infoPanel.chaffTimer ~= nil then | ||||
|     killTimer(lotj.infoPanel.chaffTimer) | ||||
|     lotj.infoPanel.chaffTimer = nil | ||||
|   end | ||||
|  | ||||
|   lotj.infoPanel.chaffIndicator:hide() | ||||
| end | ||||
							
								
								
									
										5
									
								
								src/scripts/info-panel/scripts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/scripts/info-panel/scripts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "info-panel" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										140
									
								
								src/scripts/layout/layout.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/scripts/layout/layout.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| lotj = lotj or {} | ||||
| lotj.layout = lotj.layout or {} | ||||
|  | ||||
| local rightPanelWidthPct = 40 | ||||
| local upperRightHeightPct = 50 | ||||
|  | ||||
| local inactiveTabStyle = [[ | ||||
|   background-color: #333333; | ||||
|   border: 1px solid #00aaaa; | ||||
|   margin: 3px 3px 0px 3px; | ||||
|   font-family: "Bitstream Vera Sans Mono"; | ||||
| ]] | ||||
|  | ||||
| local activeTabStyle = [[ | ||||
|   background-color: #336666; | ||||
|   border: 1px solid #00aaaa; | ||||
|   border-bottom: none; | ||||
|   margin: 3px 3px 0px 3px; | ||||
|   font-family: "Bitstream Vera Sans Mono"; | ||||
| ]] | ||||
|  | ||||
|  | ||||
| local function createTabbedPanel(tabData, container, tabList) | ||||
|   tabData.tabs = {} | ||||
|   tabData.contents = {} | ||||
|  | ||||
|   local tabContainer = Geyser.HBox:new({ | ||||
|     x = "2%", y = 0, | ||||
|     width = "96%", height = 30, | ||||
|   }, container) | ||||
|  | ||||
|   local contentsContainer = Geyser.Label:new({ | ||||
|     x = 0, y = 30, | ||||
|     width = "100%", | ||||
|   }, container) | ||||
|  | ||||
|   lotj.layout.resizeTabContents(container, tabContainer, contentsContainer) | ||||
|   registerAnonymousEventHandler("sysWindowResizeEvent", function() | ||||
|     lotj.layout.resizeTabContents(container, tabContainer, contentsContainer) | ||||
|   end) | ||||
|  | ||||
|   for _, tabInfo in ipairs(tabList) do | ||||
|     local keyword = tabInfo.keyword | ||||
|     local label = tabInfo.label | ||||
|      | ||||
|     tabData.tabs[keyword] = Geyser.Label:new({}, tabContainer) | ||||
|     tabData.tabs[keyword]:setClickCallback("lotj.layout.selectTab", tabData, keyword) | ||||
|     tabData.tabs[keyword]:setFontSize(12) | ||||
|     tabData.tabs[keyword]:echo("<center>"..label) | ||||
|      | ||||
|     tabData.contents[keyword] = Geyser.Label:new({ | ||||
|       x = 0, y = 0, | ||||
|       width = "100%", | ||||
|       height = "100%", | ||||
|     }, contentsContainer) | ||||
|   end | ||||
| end | ||||
|  | ||||
| function lotj.layout.selectTab(tabData, tabName) | ||||
|   for _, tab in pairs(tabData.tabs) do | ||||
|     tab:setStyleSheet(inactiveTabStyle) | ||||
|     tab:setBold(false) | ||||
|   end | ||||
|   for _, contents in pairs(tabData.contents) do | ||||
|     contents:hide() | ||||
|   end | ||||
|  | ||||
|   tabData.tabs[tabName]:setStyleSheet(activeTabStyle) | ||||
|   tabData.tabs[tabName]:setBold(true) | ||||
|   tabData.contents[tabName]:show() | ||||
| end | ||||
|  | ||||
| function lotj.layout.resizeTabContents(parentContainer, tabContainer, contentsContainer) | ||||
|   local newHeight = parentContainer:get_height()-tabContainer:get_height() | ||||
|   contentsContainer:resize(nil, newHeight) | ||||
| end | ||||
|  | ||||
|  | ||||
| registerAnonymousEventHandler("sysLoadEvent", function() | ||||
|   local rightPanel = Geyser.Container:new({ | ||||
|     width = rightPanelWidthPct.."%", | ||||
|     x = (100-rightPanelWidthPct).."%", | ||||
|     y = 0, height = "100%", | ||||
|   }) | ||||
|   registerAnonymousEventHandler("sysWindowResizeEvent", function() | ||||
|     local newBorder = math.floor(rightPanel:get_width()) | ||||
|     if getBorderRight() ~= newBorder then | ||||
|       setBorderRight(newBorder) | ||||
|     end | ||||
|   end) | ||||
|  | ||||
|  | ||||
|   -- Upper-right pane, for maps | ||||
|   local upperContainer = Geyser.Container:new({ | ||||
|     x = 0, y = 0, | ||||
|     width = "100%", | ||||
|     height = upperRightHeightPct.."%", | ||||
|   }, rightPanel) | ||||
|    | ||||
|   local upperTabList = {} | ||||
|   table.insert(upperTabList, {keyword = "map", label = "Map"}) | ||||
|   table.insert(upperTabList, {keyword = "system", label = "System"}) | ||||
|   table.insert(upperTabList, {keyword = "galaxy", label = "Galaxy"}) | ||||
|    | ||||
|   lotj.layout.upperRightTabData = {} | ||||
|   createTabbedPanel(lotj.layout.upperRightTabData, upperContainer, upperTabList) | ||||
|  | ||||
|  | ||||
|   -- Lower-right panel, for chat history | ||||
|   local lowerContainer = Geyser.Container:new({ | ||||
|     x = 0, y = upperRightHeightPct.."%", | ||||
|     width = "100%", | ||||
|     height = (100-upperRightHeightPct).."%", | ||||
|   }, rightPanel) | ||||
|  | ||||
|   local lowerTabList = {} | ||||
|   table.insert(lowerTabList, {keyword = "all", label = "All"}) | ||||
|   table.insert(lowerTabList, {keyword = "commnet", label = "CommNet"}) | ||||
|   table.insert(lowerTabList, {keyword = "clan", label = "Clan"}) | ||||
|   table.insert(lowerTabList, {keyword = "ooc", label = "OOC"}) | ||||
|   table.insert(lowerTabList, {keyword = "tell", label = "Tell"}) | ||||
|   table.insert(lowerTabList, {keyword = "imm", label = "Imm"}) | ||||
|  | ||||
|   lotj.layout.lowerRightTabData = {} | ||||
|   createTabbedPanel(lotj.layout.lowerRightTabData, lowerContainer, lowerTabList) | ||||
|  | ||||
|  | ||||
|   -- Lower info panel, for prompt hp/move gauges and other basic status | ||||
|   lotj.layout.lowerInfoPanel = Geyser.HBox:new({ | ||||
|     x = 0, y = -60, | ||||
|     width = (100-rightPanelWidthPct).."%", | ||||
|     height = 60, | ||||
|   }) | ||||
|   setBorderBottom(60) | ||||
|  | ||||
|   raiseEvent("lotjUICreated") | ||||
|  | ||||
|   lotj.layout.selectTab(lotj.layout.upperRightTabData, "map") | ||||
|   lotj.layout.selectTab(lotj.layout.lowerRightTabData, "all") | ||||
| end) | ||||
							
								
								
									
										5
									
								
								src/scripts/layout/scripts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/scripts/layout/scripts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "layout" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										527
									
								
								src/scripts/mapper/mapper.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										527
									
								
								src/scripts/mapper/mapper.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,527 @@ | ||||
| mudlet = mudlet or {}; mudlet.mapper_script = true | ||||
| lotj = lotj or {} | ||||
| lotj.mapper = lotj.mapper or {} | ||||
|  | ||||
|  | ||||
| local dirs = {} | ||||
| -- The order of these is important. The indices of the directions must match | ||||
| -- https://github.com/Mudlet/Mudlet/blob/9c13f8f946f5b82c0c2e817dab5f42588cee17e0/src/TRoom.h#L38 | ||||
| table.insert(dirs, {short="n",  long="north",     rev="s",  xyzDiff = { 0, 1, 0}}) | ||||
| table.insert(dirs, {short="ne", long="northeast", rev="sw", xyzDiff = { 1, 1, 0}}) | ||||
| table.insert(dirs, {short="nw", long="northwest", rev="se", xyzDiff = {-1, 1, 0}}) | ||||
| table.insert(dirs, {short="e",  long="east",      rev="w",  xyzDiff = { 1, 0, 0}}) | ||||
| table.insert(dirs, {short="w",  long="west",      rev="e",  xyzDiff = {-1, 0, 0}}) | ||||
| table.insert(dirs, {short="s",  long="south",     rev="n",  xyzDiff = { 0,-1, 0}}) | ||||
| table.insert(dirs, {short="se", long="southeast", rev="nw", xyzDiff = { 1,-1, 0}}) | ||||
| table.insert(dirs, {short="sw", long="southwest", rev="ne", xyzDiff = {-1,-1, 0}}) | ||||
| table.insert(dirs, {short="u",  long="up",        rev="d",  xyzDiff = { 0, 0, 1}}) | ||||
| table.insert(dirs, {short="d",  long="down",      rev="u",  xyzDiff = { 0, 0,-1}}) | ||||
|  | ||||
| -- Given a direction short or long name, or a direction number, return an object representing it. | ||||
| local function dirObj(arg) | ||||
|   if dirs[arg] ~= nil then | ||||
|     return dirs[arg] | ||||
|   end | ||||
|  | ||||
|   for _, dir in ipairs(dirs) do | ||||
|     if arg == dir.short or arg == dir.long then | ||||
|       return dir | ||||
|     end | ||||
|   end | ||||
|   return nil | ||||
| end | ||||
|  | ||||
| -- Given a direction short or long name, or a direction number, return an object representing its opposite | ||||
| local function revDirObj(arg) | ||||
|   local dir = dirObj(arg) | ||||
|   if dir ~= nil then | ||||
|     return dirObj(dir.rev) | ||||
|   end | ||||
|   return nil | ||||
| end | ||||
|  | ||||
| -- Configuration of an amenity name to the environment code to use on rooms with it | ||||
| local amenityEnvCodes = { | ||||
|   bacta = 269, | ||||
|   bank = 267, | ||||
|   broadcast = 270, | ||||
|   hotel = 265, | ||||
|   library = 261, | ||||
|   locker = 263, | ||||
|   package = 262, | ||||
|   workshop = 266, | ||||
| } | ||||
|  | ||||
| local function trim(s) | ||||
|   return (s:gsub("^%s*(.-)%s*$", "%1")) | ||||
| end | ||||
|  | ||||
|  | ||||
| ------------------------------------------------------------------------------ | ||||
| -- Command Handlers | ||||
| ------------------------------------------------------------------------------ | ||||
|  | ||||
| -- Main "map" command handler | ||||
| function lotj.mapper.mapCommand(input) | ||||
|   input = trim(input) | ||||
|   if #input == 0 then | ||||
|     lotj.mapper.printMainMenu() | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   _, _, cmd, args = string.find(input, "([^%s]+)%s*(.*)") | ||||
|   cmd = string.lower(cmd) | ||||
|  | ||||
|   if cmd == "help" then | ||||
|     lotj.mapper.printHelp() | ||||
|   elseif cmd == "start" then | ||||
|     lotj.mapper.startMapping(args) | ||||
|   elseif cmd == "stop" then | ||||
|     lotj.mapper.stopMapping() | ||||
|   elseif cmd == "deletearea" then | ||||
|     lotj.mapper.deleteArea(args) | ||||
|   elseif cmd == "shift" then | ||||
|     lotj.mapper.shiftCurrentRoom(args) | ||||
|   elseif cmd == "save" then | ||||
|     lotj.mapper.saveMap() | ||||
|   else | ||||
|     lotj.mapper.logError("Unknown map command. Try <yellow>map help<reset>.") | ||||
|   end | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.mapper.printMainMenu() | ||||
|   lotj.mapper.log("Mapper Introduction and Status") | ||||
|   cecho([[ | ||||
|  | ||||
| The LOTJ Mapper plugin tracks movement using MSDP variables. To begin, try <yellow>map start <current area><reset>. | ||||
| Once mapping is started, move <red>slowly<reset> between rooms to map them. Moving too quickly will cause the | ||||
| mapper to skip rooms. You should wait for the map to reflect your movements before moving again | ||||
| whenever you are in mapping mode. | ||||
|  | ||||
| When you are finished mapping, use <yellow>map stop<reset> to stop recording your movements, and be sure to | ||||
| <yellow>map save<reset>! Map data will not be saved automatically. | ||||
|  | ||||
| Other commands are available to adjust mapping as you go. <yellow>map shift <direction><reset>, for example, | ||||
| will move your current room. See <yellow>map help<reset> for a full list of available commands. | ||||
|  | ||||
| The map GUI also offers editing functionality and is ideal for moving groups of rooms, deleting | ||||
| or coloring rooms, etc. | ||||
|  | ||||
| ]]) | ||||
|  | ||||
|   if lotj.mapper.mappingArea ~= nil then | ||||
|     cecho("Mapper status: <green>Mapping<reset> in area <yellow>"..lotj.mapper.mappingArea.."<reset>\n") | ||||
|   else | ||||
|     cecho("Mapper status: <red>Off<reset>\n") | ||||
|   end | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.mapper.printHelp() | ||||
|   lotj.mapper.log("Mapper Command List") | ||||
|   cecho([[ | ||||
|  | ||||
| <yellow>map start <area name><reset> | ||||
|  | ||||
| Begin mapping. Any new rooms you enter while mapping will be added to this area name, so you | ||||
| should be sure to stop mapping before entering a ship or moving to a different zone. | ||||
|  | ||||
| Some tips to remember: | ||||
|  - <white>Move slowly<reset>, and wait for the map to reflect your movements before going to the next room. | ||||
|    The MUD sends data about your current room after some delay, so moving too fast will make the | ||||
|    mapper skip rooms or draw exits which aren't there. | ||||
|  - Use a light while mapping. Entering a dark room where you can't see will not update the map. | ||||
|  - Use <yellow>map shift<reset> to adjust room positioning, especially after going through turbolifts or | ||||
|    voice-activated doors. It's faster to click-and-drag with the GUI to move large blocks of | ||||
|    rooms, though. | ||||
|  - Rooms in ships are all unique, even if they are the same model. In practice, mapping ships | ||||
|    really isn't supported yet, although platforms or ships you use frequently may be worth it. | ||||
|  | ||||
| <yellow>map stop<reset> | ||||
|  | ||||
| Stop editing the map based on your movements. | ||||
|  | ||||
| <yellow>map save<reset> | ||||
|  | ||||
| Save the map to the map.dat file in your Mudlet profile's directory. | ||||
|  | ||||
| <yellow>map deletearea <area name><reset> | ||||
|  | ||||
| Deletes all data for an area. There's no confirmation and no undo! | ||||
|  | ||||
| <yellow>map shift <direction><reset> | ||||
|  | ||||
| Moves the current room in whichever direction you enter. Useful for adjusting placement of | ||||
| rooms when you need to space them out. | ||||
| ]]) | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.mapper.startMapping(areaName) | ||||
|   areaName = trim(areaName) | ||||
|   if #areaName == 0 then | ||||
|     lotj.mapper.log("Syntax: map start <yellow><area name><reset>") | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   if lotj.mapper.mappingArea ~= nil then | ||||
|     lotj.mapper.logError("Mapper already running in <yellow>"..lotj.mapper.mappingArea.."<reset>.") | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   local areaTable = getAreaTable() | ||||
|   if areaTable[areaName] == nil then | ||||
|     addAreaName(areaName) | ||||
|     lotj.mapper.log("Mapping in new area <yellow>"..areaName.."<reset>.") | ||||
|  | ||||
|     if lotj.mapper.noAreasPrompt ~= nil then | ||||
|       lotj.mapper.noAreasPrompt:hide() | ||||
|       lotj.mapper.noAreasPrompt = nil | ||||
|       lotj.mapper.mapperInstance:show() | ||||
|     end | ||||
|   else | ||||
|     lotj.mapper.log("Mapping in existing area <yellow>"..areaName.."<reset>.") | ||||
|   end | ||||
|    | ||||
|   lotj.mapper.mappingArea = areaName | ||||
|   lotj.mapper.processCurrentRoom() | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.mapper.stopMapping() | ||||
|   if lotj.mapper.mappingArea == nil then | ||||
|     lotj.mapper.logError("Mapper not running.") | ||||
|     return | ||||
|   end | ||||
|   lotj.mapper.mappingArea = nil | ||||
|   lotj.mapper.log("Mapping <red>stopped<reset>. Don't forget to <yellow>map save<reset>!") | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.mapper.deleteArea(areaName) | ||||
|   areaName = trim(areaName) | ||||
|   if #areaName == 0 then | ||||
|     lotj.mapper.log("Syntax: map deletearea <yellow><area name><reset>") | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   local areaTable = getAreaTable() | ||||
|   if areaTable[areaName] == nil then | ||||
|     lotj.mapper.logError("Area <yellow>"..areaName.."<reset> does not exist.") | ||||
|     return | ||||
|   end | ||||
|    | ||||
|   if areaName == lotj.mapper.mappingArea then | ||||
|     lotj.mapper.stopMapping() | ||||
|   end | ||||
|  | ||||
|   deleteArea(areaName) | ||||
|   lotj.mapper.log("Area <yellow>"..areaName.."<reset> deleted.") | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.mapper.shiftCurrentRoom(direction) | ||||
|   direction = trim(direction) | ||||
|   if #direction == 0 then | ||||
|     lotj.mapper.log("Syntax: map shift <yellow><direction><reset>") | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   local dir = dirObj(direction) | ||||
|   if dir == nil then | ||||
|     lotj.mapper.logError("Direction unknown: <yellow>"..direction.."<reset>") | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   local vnum = lotj.mapper.current.vnum | ||||
|   local room = lotj.mapper.getRoomByVnum(vnum) | ||||
|   if room ~= nil then | ||||
|     currentX, currentY, currentZ = getRoomCoordinates(vnum) | ||||
|     dx, dy, dz = unpack(dir.xyzDiff) | ||||
|     setRoomCoordinates(vnum, currentX+dx, currentY+dy, currentZ+dz) | ||||
|     updateMap() | ||||
|     centerview(vnum) | ||||
|   end | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.mapper.saveMap() | ||||
|   saveMap(getMudletHomeDir() .. "/map.dat") | ||||
|   lotj.mapper.log("Map saved.") | ||||
| end | ||||
|  | ||||
|  | ||||
| ------------------------------------------------------------------------------ | ||||
| -- Event Handlers | ||||
| ------------------------------------------------------------------------------ | ||||
|  | ||||
|  | ||||
| registerAnonymousEventHandler("lotjUICreated", function() | ||||
|   lotj.mapper.mapperInstance = Geyser.Mapper:new({ | ||||
|     x = 0, y = 0, | ||||
|     width = "100%", | ||||
|     height = "100%", | ||||
|   }, lotj.layout.upperRightTabData.contents["map"]) | ||||
|   setMapZoom(15) | ||||
|  | ||||
|   local hasAnyAreas = false | ||||
|   for name, id in pairs(getAreaTable()) do | ||||
|     if name ~= "Default Area" then | ||||
|       hasAnyAreas = true | ||||
|     end | ||||
|   end | ||||
|   if not hasAnyAreas then | ||||
|     lotj.mapper.mapperInstance:hide() | ||||
|     lotj.mapper.noAreasPrompt = Geyser.Label:new({ | ||||
|       x = 0, y = 0, | ||||
|       width = "100%", | ||||
|       height = "100%" | ||||
|     }, lotj.layout.upperRightTabData.contents["map"]) | ||||
|     lotj.mapper.noAreasPrompt:echo("No map data.<br><br>Use <b>map help</b> to get started.", nil, "c14") | ||||
|   end | ||||
|  | ||||
|   registerAnonymousEventHandler("sysDataSendRequest", "lotj.mapper.handleSentCommand") | ||||
|   registerAnonymousEventHandler("msdp.ROOMVNUM", "lotj.mapper.onEnterRoom") | ||||
| end) | ||||
|  | ||||
|  | ||||
| -- Track the most recent movement command so we know which direction we moved when automapping | ||||
| function lotj.mapper.handleSentCommand(event, cmd) | ||||
|   -- If we're not mapping, don't bother | ||||
|   if lotj.mapper.mappingArea == nil then | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   local dir = dirObj(trim(cmd)) | ||||
|   if dir ~= nil then | ||||
|     lotj.mapper.lastMoveDir = dir | ||||
|   end | ||||
| end | ||||
|  | ||||
|  | ||||
| -- Function used to handle a room that we've moved into. This will use the data on | ||||
| -- lotj.mapper.current, compared with lotj.mapper.last, to potentially create a new room and | ||||
| -- link it with an exit on the previous room. | ||||
| function lotj.mapper.processCurrentRoom() | ||||
|   local vnum = lotj.mapper.current.vnum | ||||
|   local moveDir = lotj.mapper.lastMoveDir | ||||
|   local room = lotj.mapper.getRoomByVnum(vnum) | ||||
|  | ||||
|   if lotj.mapper.mappingArea == nil and room == nil then | ||||
|     lotj.mapper.logDebug("Room not found, but mapper not running.") | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   local lastRoom = nil | ||||
|   if lotj.mapper.last ~= nil then | ||||
|     lastRoom = lotj.mapper.getRoomByVnum(lotj.mapper.last.vnum) | ||||
|   end | ||||
|  | ||||
|   -- Create the room if we don't have it yet | ||||
|   if room == nil then | ||||
|     lotj.mapper.log("Added new room: <yellow>"..lotj.mapper.current.name.."<reset>") | ||||
|     addRoom(vnum) | ||||
|     setRoomArea(vnum, lotj.mapper.mappingArea) | ||||
|     setRoomCoordinates(vnum, 0, 0, 0) | ||||
|     setRoomName(vnum, lotj.mapper.current.name) | ||||
|     room = lotj.mapper.getRoomByVnum(vnum) | ||||
|  | ||||
|     -- Create stub exits in any known direction we see | ||||
|     for dir, state in pairs(lotj.mapper.current.exits) do | ||||
|       local exitDir = dirObj(dir) | ||||
|       if exitDir ~= nil then | ||||
|         setExitStub(vnum, exitDir.short, true) | ||||
|         if state == "C" then | ||||
|           setDoor(vnum, exitDir.short, 2) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|      | ||||
|     -- Position the room relative to the room we came from | ||||
|     if lastRoom ~= nil then | ||||
|       local lastX, lastY, lastZ = getRoomCoordinates(lotj.mapper.last.vnum) | ||||
|        | ||||
|       -- If we recorded a valid movement command, use that direction to position this room | ||||
|       if moveDir ~= nil then | ||||
|         local dx, dy, dz = unpack(moveDir.xyzDiff) | ||||
|         setRoomCoordinates(vnum, lastX+dx, lastY+dy, lastZ+dz) | ||||
|       else | ||||
|         -- We didn't have a valid movement command but we still changed rooms, so try to guess | ||||
|         -- where this room should be relative to the last. | ||||
|          | ||||
|         -- Find a stub with a door on the last room which matches a stub with a door on this room | ||||
|         -- This aims to handle cases where you've used a voice-activated locked door | ||||
|         local lastDoors = getDoors(lotj.mapper.last.vnum) | ||||
|         local currentDoors = getDoors(vnum) | ||||
|         local matchingStubDir = nil | ||||
|         for _, lastRoomStubDirNum in ipairs(getExitStubs1(lotj.mapper.last.vnum) or {}) do | ||||
|           local lastRoomStubDir = dirObj(lastRoomStubDirNum) | ||||
|  | ||||
|           for _, currentRoomStubDirNum in ipairs(getExitStubs1(vnum) or {}) do | ||||
|             local currentRoomStubDir = dirObj(currentRoomStubDirNum) | ||||
|             if lastRoomStubDir.short == currentRoomStubDir.rev | ||||
|               and lastDoors[lastRoomStubDir.short] == 2 | ||||
|               and currentDoors[currentRoomStubDir.short] == 2 then | ||||
|  | ||||
|               matchingStubDir = lastRoomStubDir | ||||
|             end | ||||
|           end | ||||
|         end | ||||
|          | ||||
|         if matchingStubDir ~= nil then | ||||
|           local dx, dy, dz = unpack(matchingStubDir.xyzDiff) | ||||
|           setRoomCoordinates(vnum, lastX+dx, lastY+dy, lastZ+dz) | ||||
|           lotj.mapper.log("Positioning new room "..matchingStubDir.long.." of the previous room based on matching closed doors.") | ||||
|         else | ||||
|           -- If no matching stubs were found, just find a nearby location which isn't taken by either a stub or a real room. | ||||
|           for dir in pairs({"n", "e", "w", "s", "ne", "nw", "se", "sw", "u", "d"}) do | ||||
|             local dx, dy, dz = unpack(dirObj(dir).xyzDiff) | ||||
|             local overlappingRoomId = lotj.mapper.getRoomByCoords(lotj.mapper.mappingArea, lastX+dx, lastY+dy, lastZ+dz) | ||||
|              | ||||
|             local hasOverlappingStub = false | ||||
|             for _, stubDirNum in ipairs(getExitStubs1(lotj.mapper.last.vnum) or {}) do | ||||
|               if dirObj(stubDirNum) == dirObj(dir) then | ||||
|                 hasOverlappingStub = true | ||||
|               end | ||||
|             end | ||||
|  | ||||
|             if overlappingRoomId == nil and not hasOverlappingStub then | ||||
|               lotj.mapper.log("Exit unknown. Positioning new room "..dirObj(dir).long.." of the previous room.") | ||||
|               setRoomCoordinates(vnum, lastX+dx, lastY+dy, lastZ+dz) | ||||
|               break | ||||
|             end | ||||
|           end | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|    | ||||
|   -- Link this room with the previous one if they have a matching set of exit stubs | ||||
|   if lastRoom ~= nil and moveDir ~= nil then | ||||
|     -- Always set the exit we took even if it wasn't a stub. The direction we just moved is our best | ||||
|     -- evidence of how rooms are connected, overriding any reverse-created exits made earlier if they | ||||
|     -- are different. | ||||
|     setExit(lotj.mapper.last.vnum, vnum, moveDir.short) | ||||
|  | ||||
|     -- Only set the reverse exit (from current room back to where we came from) if it's a stub. | ||||
|     -- In the case of mazes or asymmetrical exits, this may be wrong but will be fixed on moving back | ||||
|     -- out through this exit. | ||||
|     for _, currentRoomStubDirNum in ipairs(getExitStubs1(vnum) or {}) do | ||||
|       local currentRoomStubDir = dirObj(currentRoomStubDirNum) | ||||
|       if moveDir.rev == currentRoomStubDir.short then | ||||
|         setExit(vnum, lotj.mapper.last.vnum, moveDir.rev) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   centerview(vnum) | ||||
| end | ||||
|  | ||||
|  | ||||
| function lotj.mapper.checkAmenityLine(roomName, amenityName, wasPending) | ||||
|   if lotj.mapper.mappingArea == nil then | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   envCode = amenityEnvCodes[string.lower(amenityName)] | ||||
|   if envCode == nil then | ||||
|     return | ||||
|   end | ||||
|    | ||||
|   local addAmenityRoom = nil | ||||
|   if lotj.mapper.current.name == roomName then | ||||
|     addAmenityRoom = lotj.mapper.current | ||||
|   elseif lotj.mapper.last.name == roomName then | ||||
|     addAmenityRoom = lotj.mapper.last | ||||
|   end | ||||
|    | ||||
|   -- If this wasn't stored for later use, we need a newline since this is being invoked on | ||||
|   -- seeing a room name and we don't want it mushed into that line. | ||||
|   if not wasPending then | ||||
|     echo("\n") | ||||
|   end | ||||
|  | ||||
|   if addAmenityRoom == nil then | ||||
|     -- The room name we're triggering on might be the room we just entered but we haven't | ||||
|     -- received the MSDP event yet, so we'll store this for the next time we do. | ||||
|     lotj.mapper.pendingAmenity = { | ||||
|       roomName = roomName, | ||||
|       amenityName = amenityName, | ||||
|     } | ||||
|   else | ||||
|     lotj.mapper.log("Set amenity <yellow>"..amenityName.."<reset> on room <yellow>"..addAmenityRoom.name.."<reset>") | ||||
|     setRoomEnv(addAmenityRoom.vnum, envCode) | ||||
|     updateMap() | ||||
|   end | ||||
| end | ||||
|  | ||||
|  | ||||
| -- The vnum is always sent after the name and exits, so we can use it as a trigger for | ||||
| -- handling movement to a new room | ||||
| function lotj.mapper.onEnterRoom() | ||||
|   if lotj.mapper.current ~= nil then | ||||
|     lotj.mapper.last = lotj.mapper.current | ||||
|   end | ||||
|   local exits = {} | ||||
|   if msdp.ROOMEXITS ~= "" then | ||||
|     exits = msdp.ROOMEXITS | ||||
|   end | ||||
|   lotj.mapper.current = { | ||||
|     vnum = tonumber(msdp.ROOMVNUM), | ||||
|     name = string.gsub(msdp.ROOMNAME, "&.", ""), | ||||
|     exits = exits, | ||||
|   } | ||||
|    | ||||
|   lotj.mapper.processCurrentRoom() | ||||
|  | ||||
|   -- Since we've handled the move, we don't want the last move command to get | ||||
|   -- used by anything else. | ||||
|   lotj.mapper.lastMoveDir = nil | ||||
|    | ||||
|   local pendingAmenity = lotj.mapper.pendingAmenity | ||||
|   if pendingAmenity ~= nil then | ||||
|     lotj.mapper.checkAmenityLine(pendingAmenity.roomName, pendingAmenity.amenityName, true) | ||||
|     lotj.mapper.pendingAmenity = nil | ||||
|   end | ||||
| end | ||||
|  | ||||
|  | ||||
| ------------------------------------------------------------------------------ | ||||
| -- Utility Functions | ||||
| ------------------------------------------------------------------------------ | ||||
|  | ||||
|  | ||||
| function lotj.mapper.log(text) | ||||
|   cecho("[<cyan>LOTJ Mapper<reset>] "..text.."\n") | ||||
| end | ||||
|  | ||||
| function lotj.mapper.logDebug(text) | ||||
|   if lotj.mapper.debug then | ||||
|     lotj.mapper.log("<green>Debug:<reset> "..text) | ||||
|   end | ||||
| end | ||||
|  | ||||
| function lotj.mapper.logError(text) | ||||
|   lotj.mapper.log("<red>Error:<reset> "..text) | ||||
| end | ||||
|  | ||||
| function lotj.mapper.getRoomByVnum(vnum) | ||||
|   return getRooms()[vnum] | ||||
| end | ||||
|  | ||||
| function lotj.mapper.getRoomByCoords(areaName, x, y, z) | ||||
|   local areaRooms = getAreaRooms(getAreaTable()[areaName]) or {} | ||||
|   for _, roomId in pairs(areaRooms) do | ||||
|     local roomX, roomY, roomZ = getRoomCoordinates(roomId) | ||||
|     if roomX == x and roomY == y and roomZ == z then | ||||
|       return roomId | ||||
|     end | ||||
|   end | ||||
|   return nil | ||||
| end | ||||
|  | ||||
| function doSpeedWalk() | ||||
|   echo("Path we need to take: " .. table.concat(speedWalkDir, ", ") .. "\n") | ||||
|   echo("A future version of the mapper script might actually execute these commands.\n") | ||||
| end | ||||
							
								
								
									
										5
									
								
								src/scripts/mapper/scripts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/scripts/mapper/scripts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "mapper" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										45
									
								
								src/scripts/msdp/msdp.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/scripts/msdp/msdp.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| registerAnonymousEventHandler("sysLoadEvent", function() | ||||
|   registerAnonymousEventHandler("msdp.COMMANDS", function() | ||||
|     local msdpVars = {} | ||||
|  | ||||
|     table.insert(msdpVars, "HEALTH") | ||||
|     table.insert(msdpVars, "HEALTHMAX") | ||||
|     table.insert(msdpVars, "WIMPY") | ||||
|     table.insert(msdpVars, "MOVEMENT") | ||||
|     table.insert(msdpVars, "MOVEMENTMAX") | ||||
|     table.insert(msdpVars, "MANA") | ||||
|     table.insert(msdpVars, "MANAMAX") | ||||
|      | ||||
|     table.insert(msdpVars, "OPPONENTNAME") | ||||
|     table.insert(msdpVars, "OPPONENTHEALTH") | ||||
|     table.insert(msdpVars, "OPPONENTHEALTHMAX") | ||||
|      | ||||
|     table.insert(msdpVars, "COMMCHANNEL") | ||||
|     table.insert(msdpVars, "COMMENCRYPT") | ||||
|     table.insert(msdpVars, "OOCLIMIT") | ||||
|      | ||||
|     table.insert(msdpVars, "ROOMNAME") | ||||
|     table.insert(msdpVars, "ROOMEXITS") | ||||
|     table.insert(msdpVars, "ROOMVNUM") | ||||
|      | ||||
|     table.insert(msdpVars, "PILOTING") | ||||
|     table.insert(msdpVars, "SHIPSPEED") | ||||
|     table.insert(msdpVars, "SHIPMAXSPEED") | ||||
|     table.insert(msdpVars, "SHIPHULL") | ||||
|     table.insert(msdpVars, "SHIPMAXHULL") | ||||
|     table.insert(msdpVars, "SHIPSHIELD") | ||||
|     table.insert(msdpVars, "SHIPMAXSHIELD") | ||||
|     table.insert(msdpVars, "SHIPENERGY") | ||||
|     table.insert(msdpVars, "SHIPMAXENERGY") | ||||
|     table.insert(msdpVars, "SHIPSYSX") | ||||
|     table.insert(msdpVars, "SHIPSYSY") | ||||
|     table.insert(msdpVars, "SHIPSYSZ") | ||||
|     table.insert(msdpVars, "SHIPGALX") | ||||
|     table.insert(msdpVars, "SHIPGALY") | ||||
|     table.insert(msdpVars, "SHIPSYSNAME") | ||||
|      | ||||
|     for _, varName in ipairs(msdpVars) do | ||||
|       sendMSDP("REPORT", varName) | ||||
|     end | ||||
|   end) | ||||
| end) | ||||
							
								
								
									
										5
									
								
								src/scripts/msdp/scripts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/scripts/msdp/scripts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "msdp" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										5
									
								
								src/scripts/system-map/scripts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/scripts/system-map/scripts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "system-map" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										326
									
								
								src/scripts/system-map/system-map.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								src/scripts/system-map/system-map.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,326 @@ | ||||
| lotj = lotj or {} | ||||
| lotj.systemMap = lotj.systemMap or { | ||||
|   mapRange = 2000, | ||||
|   radarItems = {}, | ||||
|   genPoints = {}, | ||||
|   genLabels = {} | ||||
| } | ||||
| local pointSize = 12 | ||||
| local labelWidth = 200 | ||||
| local labelHeight = 16 | ||||
|  | ||||
| local controlButtonStyle = [[ | ||||
|   background-color: grey; | ||||
|   border: 2px solid white; | ||||
| ]] | ||||
|  | ||||
| registerAnonymousEventHandler("lotjUICreated", function() | ||||
|   disableTrigger("system-map-radar") | ||||
|  | ||||
|   local tabContents = lotj.layout.upperRightTabData.contents["system"] | ||||
|   lotj.systemMap.container = Geyser.Label:new({}, tabContents) | ||||
|   lotj.systemMap.container:setStyleSheet([[ | ||||
|     background-color: black; | ||||
|   ]]) | ||||
|   lotj.systemMap.resizeToSquare() | ||||
|   registerAnonymousEventHandler("sysWindowResizeEvent", lotj.systemMap.resizeToSquare) | ||||
|  | ||||
|   local zoomInButton = Geyser.Label:new({ | ||||
|     x = "2%", y = 10, | ||||
|     width = 28, height = 28, | ||||
|   }, tabContents) | ||||
|   zoomInButton:setStyleSheet(controlButtonStyle) | ||||
|   zoomInButton:echo("+", "white", "c16b") | ||||
|   zoomInButton:setClickCallback(function() | ||||
|     if lotj.systemMap.mapRange > 1000 then | ||||
|       lotj.systemMap.mapRange = lotj.systemMap.mapRange - 1000 | ||||
|     elseif lotj.systemMap.mapRange == 1000 then | ||||
|       lotj.systemMap.mapRange = 500 | ||||
|     else | ||||
|       return | ||||
|     end | ||||
|     lotj.systemMap.drawMap() | ||||
|   end) | ||||
|  | ||||
|   local zoomOutButton = Geyser.Label:new({ | ||||
|     x = "2%", y = 44, | ||||
|     width = 28, height = 28, | ||||
|   }, tabContents) | ||||
|   zoomOutButton:setStyleSheet(controlButtonStyle) | ||||
|   zoomOutButton:echo("-", "white", "c16b") | ||||
|   zoomOutButton:setClickCallback(function() | ||||
|     if lotj.systemMap.mapRange >= 1000 then | ||||
|       lotj.systemMap.mapRange = lotj.systemMap.mapRange + 1000 | ||||
|     elseif lotj.systemMap.mapRange == 500 then | ||||
|       lotj.systemMap.mapRange = 1000 | ||||
|     else | ||||
|       return | ||||
|     end | ||||
|     lotj.systemMap.drawMap() | ||||
|   end) | ||||
|  | ||||
|   local refreshButton = Geyser.Label:new({ | ||||
|     x = "2%", y = 78, | ||||
|     width = 28, height = 28, | ||||
|   }, tabContents) | ||||
|   refreshButton:setStyleSheet(controlButtonStyle) | ||||
|   refreshButton:echo("R", "white", "c16b") | ||||
|   refreshButton:setClickCallback(function() | ||||
|     lotj.systemMap.maskNextRadarOutput = true | ||||
|     expandAlias("radar", false) | ||||
|   end) | ||||
|  | ||||
|  | ||||
|   local rangeCircle = rangeCircle or Geyser.Label:new({fillBg = 0}, lotj.systemMap.container) | ||||
|   rangeCircle:move(0, 0) | ||||
|  | ||||
|   lotj.systemMap.rangeLabel = lotj.systemMap.rangeLabel or Geyser.Label:new({fillBg = 0}, lotj.systemMap.container) | ||||
|   lotj.systemMap.rangeLabel:resize(50, 20) | ||||
|   lotj.systemMap.rangeLabel:echo(lotj.systemMap.mapRange, "green", "10c") | ||||
|  | ||||
|   local function positionRangeCircle() | ||||
|     local containerSize = lotj.systemMap.container:get_height() | ||||
|     lotj.systemMap.rangeLabel:move(containerSize-math.ceil(containerSize/10)-25, math.ceil(containerSize/10)) | ||||
|     rangeCircle:resize(containerSize, containerSize) | ||||
|     rangeCircle:setStyleSheet([[ | ||||
|       border: 1px dashed green; | ||||
|       border-radius: ]]..math.floor(containerSize/2)..[[px; | ||||
|     ]]) | ||||
|   end | ||||
|   positionRangeCircle() | ||||
|   registerAnonymousEventHandler("sysWindowResizeEvent", positionRangeCircle) | ||||
|  | ||||
|   registerAnonymousEventHandler("msdp.SHIPSYSX", "lotj.systemMap.drawMap") | ||||
|   registerAnonymousEventHandler("msdp.SHIPSYSY", "lotj.systemMap.drawMap") | ||||
|   registerAnonymousEventHandler("msdp.SHIPSYSZ", "lotj.systemMap.drawMap") | ||||
| end) | ||||
|  | ||||
| function lotj.systemMap.resetItems() | ||||
|   lotj.systemMap.radarItems = {} | ||||
| end | ||||
|  | ||||
| function lotj.systemMap.addItem(item) | ||||
|   table.insert(lotj.systemMap.radarItems, item) | ||||
| end | ||||
|  | ||||
| function lotj.systemMap.drawMap() | ||||
|   lotj.systemMap.rangeLabel:echo(lotj.systemMap.mapRange, "green", "10c") | ||||
|  | ||||
|   -- Hide any previously generated elements which we may be displaying | ||||
|   for _, elem in ipairs(lotj.systemMap.genPoints) do | ||||
|     elem:hide() | ||||
|   end | ||||
|   for _, elem in ipairs(lotj.systemMap.genLabels) do | ||||
|     elem:hide() | ||||
|   end | ||||
|  | ||||
|   -- We use ship max speed as a proxy for "do we have ship data at all" | ||||
|   if tonumber(msdp.SHIPMAXSPEED or "0") == 0 then | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   local shipX = tonumber(msdp.SHIPSYSX or "0") | ||||
|   local shipY = tonumber(msdp.SHIPSYSY or "0") | ||||
|   local shipZ = tonumber(msdp.SHIPSYSZ or "0") | ||||
|   local selfData = {name="You", x=shipX, y=shipY, z=shipZ} | ||||
|  | ||||
|   local itemsToDraw = {} | ||||
|   table.insert(itemsToDraw, selfData) | ||||
|   for _, item in ipairs(lotj.systemMap.radarItems) do | ||||
|     if lotj.systemMap.dist(selfData, item) <= lotj.systemMap.mapRange then | ||||
|       table.insert(itemsToDraw, item) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   local drawnItems = {} | ||||
|   for i, item in ipairs(itemsToDraw) do | ||||
|     local point, label = lotj.systemMap.pointAndLabel(i) | ||||
|  | ||||
|     local color = "yellow" | ||||
|     if item.class and string.match(item.class, "Pirated") then | ||||
|       color = "red" | ||||
|     elseif item == selfData then | ||||
|       color = "white" | ||||
|     end | ||||
|  | ||||
|     point:resize(pointSize, pointSize) | ||||
|     point:setStyleSheet([[ | ||||
|       border-radius: ]]..math.floor(pointSize/2)..[[px; | ||||
|       background-color: ]]..color..[[; | ||||
|     ]]) | ||||
|  | ||||
|     local x, y = lotj.systemMap.computeXY(selfData, item) | ||||
|     point:show() | ||||
|     point:move(x, y) | ||||
|  | ||||
|     local labelXOffset, labelYOffset = lotj.systemMap.computeLabelPos(drawnItems, x, y) | ||||
|     local labelX = x+labelXOffset | ||||
|     local labelY = y+labelYOffset | ||||
|     label:show() | ||||
|     label:move(labelX, labelY) | ||||
|     lotj.systemMap.printLabels(point, label, color, labelXOffset, item, selfData) | ||||
|  | ||||
|     table.insert(drawnItems, {x = x, y = y, labelX = labelX, labelY = labelY, labelXOffset = labelXOffset, labelYOffset = labelYOffset}) | ||||
|   end | ||||
| end | ||||
|  | ||||
| -- Add appropriate text to the point and label | ||||
| function lotj.systemMap.printLabels(point, label, color, labelXOffset, item, selfData) | ||||
|   local labelStr = item.name | ||||
|  | ||||
|   -- Prepend an up/down arrow to show Z diff | ||||
|   local zDiff = item.z - selfData.z | ||||
|   if zDiff ~= 0 then | ||||
|     local arrowFontSize = 3 + math.floor(11 * math.abs(zDiff) / lotj.systemMap.mapRange + 0.5) | ||||
|     local arrowChar = "▲" -- Up arrow | ||||
|     if zDiff < 0 then | ||||
|       arrowChar = "▼" -- Down arrow | ||||
|     end | ||||
|     point:echo(arrowChar, "black", arrowFontSize.."c") | ||||
|   else | ||||
|     point:echo("") | ||||
|   end | ||||
|  | ||||
|   -- Append proximity and class | ||||
|   if item ~= selfData then | ||||
|     labelStr = labelStr.." ("..math.floor(lotj.systemMap.dist(item, selfData) + 0.5) | ||||
|     if item.class ~= nil then | ||||
|       labelStr = labelStr..", "..item.class | ||||
|     end | ||||
|     labelStr = labelStr..")" | ||||
|   end | ||||
|  | ||||
|   -- Set alignment based on whether the label is to the right or left of the point | ||||
|   if labelXOffset > 0 then | ||||
|     label:echo(labelStr, color, "11l") | ||||
|   else | ||||
|     label:echo(labelStr, color, "11r") | ||||
|   end | ||||
| end | ||||
|  | ||||
| -- Based on the position, size of map, and zoom level, determine the X and Y placement for the given item | ||||
| function lotj.systemMap.computeXY(selfData, item) | ||||
|   local mapMinX = selfData.x-lotj.systemMap.mapRange | ||||
|   local mapMinY = selfData.y-lotj.systemMap.mapRange | ||||
|   local containerSize = lotj.systemMap.container:get_height() | ||||
|  | ||||
|   local x = math.floor(containerSize * ((item.x - mapMinX) / (lotj.systemMap.mapRange*2)) + 0.5) | ||||
|   local y = math.floor(containerSize * (1 - (item.y - mapMinY) / (lotj.systemMap.mapRange*2)) + 0.5) | ||||
|  | ||||
|   return x-pointSize/2, y-pointSize/2 | ||||
| end | ||||
|  | ||||
| -- Return true if the first rectancle overlaps with any part of the second rectangle | ||||
| local function overlaps(x1, y1, w1, h1, x2, y2, w2, h2) | ||||
|   local xOverlap = (x1 >= x2 and x1 <= x2+w2) or (x1+w1 >= x2 and x1+w1 <= x2+w2) | ||||
|   local yOverlap = (y1 >= y2 and y1 <= y2+h2) or (y1+h1 >= y2 and y1+h1 <= y2+h2) | ||||
|   return xOverlap and yOverlap | ||||
| end | ||||
|  | ||||
| -- Determine whether a given rectangle overlaps with the points or labels in the given array of items | ||||
| local function anyOverlaps(x, y, w, h, items) | ||||
|   for _, item in ipairs(items) do | ||||
|     -- Overlap with this item's point? | ||||
|     if overlaps(x, y, w, h, item.x, item.y, pointSize, pointSize) then | ||||
|       return true | ||||
|     end | ||||
|     -- Overlap with this item's label? | ||||
|     if overlaps(x, y, w, h, item.labelX, item.labelY, labelWidth, labelHeight) then | ||||
|       return true | ||||
|     end | ||||
|   end | ||||
|   return false | ||||
| end | ||||
|  | ||||
| -- Find a suitable label X and Y offset for a new label, attempting to avoid overlap with anything previously drawn | ||||
| function lotj.systemMap.computeLabelPos(drawnItems, itemX, itemY) | ||||
|   local labelXOffset = pointSize | ||||
|   local labelYOffset = pointSize | ||||
|  | ||||
|   -- If we find an item at the same coords, simply put the label below the last one for those coords | ||||
|   local foundSameCoords = false | ||||
|   for _, item in ipairs(drawnItems) do | ||||
|     if item.x == itemX and item.y == itemY then | ||||
|       foundSameCoords = true | ||||
|       if item.labelY > item.y then | ||||
|         labelYOffset = item.labelYOffset + labelHeight | ||||
|       else | ||||
|         labelYOffset = item.labelYOffset - labelHeight | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|   if foundSameCoords then | ||||
|     return labelXOffset, labelYOffset | ||||
|   end | ||||
|  | ||||
|   -- Try four different label positions to find one without any overlap | ||||
|   local offsetsToTry = {} | ||||
|   table.insert(offsetsToTry, {x = pointSize, y = pointSize}) | ||||
|   table.insert(offsetsToTry, {x = pointSize, y = labelHeight * -1}) | ||||
|   table.insert(offsetsToTry, {x = labelWidth * -1, y = labelHeight * -1}) | ||||
|   table.insert(offsetsToTry, {x = labelWidth * -1, y = pointSize}) | ||||
|   for _, offsets in ipairs(offsetsToTry) do | ||||
|     if not anyOverlaps(itemX+offsets.x, itemY+offsets.y, labelWidth, labelHeight, drawnItems) then | ||||
|       return offsets.x, offsets.y | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   -- We couldn't find a non-overlapping position, so just put it to the lower right | ||||
|   return labelXOffset, labelYOffset | ||||
| end | ||||
|  | ||||
| -- Return existing (or create new) Geyser labels for a given point and label | ||||
| -- We store and reuse these so that we don't accumulate infinite label objects, since Geyser doesn't give us a way to delete elements, only hide them | ||||
| function lotj.systemMap.pointAndLabel(idx) | ||||
|   lotj.systemMap.genPoints[idx] = lotj.systemMap.genPoints[idx] or Geyser.Label:new({}, lotj.systemMap.container) | ||||
|   lotj.systemMap.genLabels[idx] = lotj.systemMap.genLabels[idx] or Geyser.Label:new({fillBg = 0, width = labelWidth, height = labelHeight}, lotj.systemMap.container) | ||||
|   return lotj.systemMap.genPoints[idx], lotj.systemMap.genLabels[idx] | ||||
| end | ||||
|  | ||||
| -- Compute distance between one X/Y/Z coord and another | ||||
| function lotj.systemMap.dist(coordsA, coordsB) | ||||
|   local xDiff = math.abs(coordsA.x-coordsB.x) | ||||
|   local yDiff = math.abs(coordsA.y-coordsB.y) | ||||
|   local zDiff = math.abs(coordsA.z-coordsB.z) | ||||
|  | ||||
|   local xyDiff = math.sqrt(xDiff*xDiff + yDiff*yDiff) | ||||
|   local totalDiff = math.sqrt(xyDiff*xyDiff + zDiff*zDiff) | ||||
|   return totalDiff | ||||
| end | ||||
|  | ||||
| -- Resize the map to the largest possible square when the window dimensions change | ||||
| function lotj.systemMap.resizeToSquare() | ||||
|   local tabContents = lotj.layout.upperRightTabData.contents["system"] | ||||
|   local contH = tabContents:get_height() | ||||
|   local contW = tabContents:get_width() | ||||
|  | ||||
|   local x = 0 | ||||
|   local y = 0 | ||||
|   local width = "100%" | ||||
|   local height = "100%" | ||||
|   if contW >= contH then | ||||
|     width = contH | ||||
|     x = (contW-contH)/2 | ||||
|   else | ||||
|     height = contW | ||||
|     y = (contH-contW)/2 | ||||
|   end | ||||
|  | ||||
|   lotj.systemMap.container:move(x, y) | ||||
|   lotj.systemMap.container:resize(width, height) | ||||
| end | ||||
|  | ||||
| function lotj.systemMap.findTarget(targetName) | ||||
|   targetName = targetName:lower() | ||||
|   local target = nil | ||||
|   for _, item in ipairs(lotj.systemMap.radarItems) do | ||||
|     if item.name:lower():sub(1, #targetName) == targetName then | ||||
|       target = item | ||||
|     end | ||||
|   end | ||||
|   return target | ||||
| end | ||||
|  | ||||
| function lotj.systemMap.log(text) | ||||
|   cecho("[<cyan>System Map<reset>] "..text.."\n") | ||||
| end | ||||
							
								
								
									
										6
									
								
								src/triggers/chat/commnet-translated.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/triggers/chat/commnet-translated.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| if lotj.chat.commnetLastChannel == matches[2] and lotj.chat.commnetLastMessage == matches[3] then | ||||
|   deleteLine() | ||||
|   echo(" (Translated)") | ||||
| else | ||||
|   lotj.chat.routeMessage("commnet") | ||||
| end | ||||
							
								
								
									
										6
									
								
								src/triggers/chat/commnet.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/triggers/chat/commnet.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| lotj.chat.routeMessage("commnet") | ||||
|  | ||||
| -- Track commnet messages to potentially squash a redundant translation | ||||
| -- message on the next line | ||||
| lotj.chat.commnetLastChannel = matches[2] | ||||
| lotj.chat.commnetLastMessage = matches[3] | ||||
							
								
								
									
										76
									
								
								src/triggers/chat/triggers.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/triggers/chat/triggers.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "commnet", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "^CommNet ([0-9]+) \\[.*\\][()a-zA-Z<> ]*: (.*)", | ||||
|         "type": "regex" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "name": "commnet-translated", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "^.* buzzes '\\(Translating channel ([0-9]+)\\) (.*)'$", | ||||
|         "type": "regex" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "name": "clan", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "{.*}<.*>\\[[a-zA-Z ]+\\][()<>A-Za-z ]*: ", | ||||
|         "type": "regex" | ||||
|       }, | ||||
|       { | ||||
|         "pattern": "[Incoming Transmission from", | ||||
|         "type": "substring" | ||||
|       }, | ||||
|       { | ||||
|         "pattern": "[Outgoing Transmission to", | ||||
|         "type": "substring" | ||||
|       } | ||||
|     ], | ||||
|     "script": "lotj.chat.routeMessage(\"clan\")" | ||||
|   }, | ||||
|   { | ||||
|     "name": "ooc", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "^\\((OOC|IMM|RPC|NEWBIE)\\) [*]?[A-Za-z]+: .*$", | ||||
|         "type": "regex" | ||||
|       } | ||||
|     ], | ||||
|     "script": "lotj.chat.routeMessage(\"ooc\")" | ||||
|   }, | ||||
|   { | ||||
|     "name": "immchat", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "^\\( IMM \\| CHAT \\) .* mortchats to you '.*'$", | ||||
|         "type": "regex" | ||||
|       }, | ||||
|       { | ||||
|         "pattern": "^\\( IMM \\| CHAT \\)\\[.*\\]: '.*'$", | ||||
|         "type": "regex" | ||||
|       } | ||||
|     ], | ||||
|     "script": "lotj.chat.routeMessage(\"imm\")" | ||||
|   }, | ||||
|   { | ||||
|     "name": "tell", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "^\\(OOC\\) .* tells you '.*'$", | ||||
|         "type": "regex" | ||||
|       }, | ||||
|       { | ||||
|         "pattern": "^\\(OOC\\) You tell .* '.*'$", | ||||
|         "type": "regex" | ||||
|       } | ||||
|     ], | ||||
|     "script": "lotj.chat.routeMessage(\"tell\")" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										5
									
								
								src/triggers/galaxy-map/any-planet-line.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/triggers/galaxy-map/any-planet-line.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| -- Swallow lines and extend the triggers as long as we haven't found the end of the planet yet | ||||
| if gatherPlanetState ~= nil then | ||||
|   setTriggerStayOpen("gather-planet", 1) | ||||
| end | ||||
| deleteLine() | ||||
							
								
								
									
										7
									
								
								src/triggers/galaxy-map/gather-planet.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/triggers/galaxy-map/gather-planet.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| gatherPlanetState = { | ||||
|   section = "basics" | ||||
| } | ||||
|  | ||||
| deleteLine() | ||||
| moveCursor(0,getLineNumber()-1) | ||||
| deleteLine() | ||||
							
								
								
									
										7
									
								
								src/triggers/galaxy-map/gather-planets.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/triggers/galaxy-map/gather-planets.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| deleteLine() | ||||
|  | ||||
| gatherPlanetsState = { | ||||
|   pendingBasic = {}, | ||||
|   pendingResources = {}, | ||||
|   pendingCommands = 0, | ||||
| } | ||||
							
								
								
									
										3
									
								
								src/triggers/galaxy-map/no-datapad.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/triggers/galaxy-map/no-datapad.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| echo("\n") | ||||
| lotj.galaxyMap.log("Error gathering galaxy map data. Please fix the problem and try again.") | ||||
| disableTrigger("galaxy-map-refresh") | ||||
							
								
								
									
										2
									
								
								src/triggers/galaxy-map/no-resources.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/triggers/galaxy-map/no-resources.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| gatherPlanetState.section = "resources" | ||||
| gatherPlanetState.resources = {} | ||||
							
								
								
									
										5
									
								
								src/triggers/galaxy-map/planet-coords.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/triggers/galaxy-map/planet-coords.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| gatherPlanetState.coords = { | ||||
|   x = tonumber(matches[2]), | ||||
|   y = tonumber(matches[3]), | ||||
|   z = tonumber(matches[4]), | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/triggers/galaxy-map/planet-empty-line.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/triggers/galaxy-map/planet-empty-line.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| -- If we've gotten into the list of resources, an empty line means we're done | ||||
| if gatherPlanetState and gatherPlanetState.section == "resources" then | ||||
|   echo("\n") | ||||
|   lotj.galaxyMap.log("Collected resource data for "..gatherPlanetState.name) | ||||
|   lotj.galaxyMap.recordPlanet(gatherPlanetState) | ||||
|    | ||||
|   gatherPlanetsState.pendingResources[gatherPlanetState.name] = nil | ||||
|   gatherPlanetsState.pendingCommands = gatherPlanetsState.pendingCommands - 1 | ||||
|   if gatherPlanetsState.pendingCommands == 0 then | ||||
|     lotj.galaxyMap.enqueuePendingRefreshCommands() | ||||
|   end | ||||
|  | ||||
|   gatherPlanetState = nil | ||||
| end | ||||
							
								
								
									
										11
									
								
								src/triggers/galaxy-map/planet-end.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/triggers/galaxy-map/planet-end.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| echo("\n") | ||||
| lotj.galaxyMap.log("Collected basic data for "..gatherPlanetState.name) | ||||
| lotj.galaxyMap.recordPlanet(gatherPlanetState) | ||||
|  | ||||
| gatherPlanetsState.pendingBasic[gatherPlanetState.name] = nil | ||||
| gatherPlanetsState.pendingCommands = gatherPlanetsState.pendingCommands - 1 | ||||
| if gatherPlanetsState.pendingCommands == 0 then | ||||
|   lotj.galaxyMap.enqueuePendingRefreshCommands() | ||||
| end | ||||
|  | ||||
| gatherPlanetState = nil | ||||
							
								
								
									
										29
									
								
								src/triggers/galaxy-map/planets-line.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/triggers/galaxy-map/planets-line.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| deleteLine() | ||||
|  | ||||
| local line = matches[2] | ||||
|  | ||||
| local function starts_with(str, start) | ||||
|    return str:sub(1, #start) == start | ||||
| end | ||||
|  | ||||
| if starts_with(line, "Use SHOWPLANET for more information.") then | ||||
|   lotj.galaxyMap.enqueuePendingRefreshCommands() | ||||
|   return | ||||
| end | ||||
|  | ||||
| line = line:gsub("%(UFG%)", "") | ||||
| line = line:gsub("  +", ";") | ||||
| local _, _, planet, system, gov, support = line:find("([^;]+);([^;]+);([^;]+);([^;]+)") | ||||
|  | ||||
| if planet ~= "Planet" then | ||||
|   lotj.galaxyMap.recordPlanet({ | ||||
|     name = planet, | ||||
|     system = system, | ||||
|     gov = gov, | ||||
|   }) | ||||
|  | ||||
|   gatherPlanetsState.pendingBasic[planet] = true | ||||
|   gatherPlanetsState.pendingResources[planet] = true | ||||
| end | ||||
|  | ||||
| setTriggerStayOpen("gather-planets", 1) | ||||
							
								
								
									
										7
									
								
								src/triggers/galaxy-map/resource-price.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/triggers/galaxy-map/resource-price.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| gatherPlanetState.section = "resources" | ||||
|  | ||||
| local resource = matches[2]:match "^%s*(.-)%s*$" | ||||
| local price = tonumber(matches[3]) | ||||
|  | ||||
| gatherPlanetState.resources = gatherPlanetState.resources or {} | ||||
| gatherPlanetState.resources[resource] = price | ||||
							
								
								
									
										4
									
								
								src/triggers/galaxy-map/showplanet-fail
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/triggers/galaxy-map/showplanet-fail
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| gatherPlanetsState.pendingCommands = gatherPlanetsState.pendingCommands - 1 | ||||
| if gatherPlanetsState.pendingCommands == 0 then | ||||
|   lotj.galaxyMap.enqueuePendingRefreshCommands() | ||||
| end | ||||
							
								
								
									
										8
									
								
								src/triggers/galaxy-map/system-line.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/triggers/galaxy-map/system-line.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| local systemName = matches[2]:match "^%s*(.-)%s*$" | ||||
| local xCoord = tonumber(matches[3]) | ||||
| local yCoord = tonumber(matches[4]) | ||||
|  | ||||
| lotj.galaxyMap.recordSystem(systemName, xCoord, yCoord) | ||||
|  | ||||
| setTriggerStayOpen("gather-starsystems", 1) | ||||
| deleteLine() | ||||
							
								
								
									
										211
									
								
								src/triggers/galaxy-map/triggers.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								src/triggers/galaxy-map/triggers.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,211 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "galaxy-map-refresh", | ||||
|     "isActive": "no", | ||||
|     "isFolder": "yes", | ||||
|     "children": [ | ||||
|       { | ||||
|         "name": "gather-planets", | ||||
|         "fireLength": 1, | ||||
|         "patterns": [ | ||||
|           { | ||||
|             "pattern": "Planet\\s+Starsystem\\s+Governed By\\s+Popular Support", | ||||
|             "type": "regex" | ||||
|           } | ||||
|         ], | ||||
|         "children": [ | ||||
|           { | ||||
|             "name": "planets-line", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "(.*)", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         "name": "gather-planet", | ||||
|         "multiline": "yes", | ||||
|         "multilineDelta": 1, | ||||
|         "fireLength": 4, | ||||
|         "patterns": [ | ||||
|           { | ||||
|             "pattern": "You use the datapad to lookup the information.", | ||||
|             "type": "substring" | ||||
|           }, | ||||
|           { | ||||
|             "pattern": "--Planet Data: -------------------------------", | ||||
|             "type": "substring" | ||||
|           } | ||||
|         ], | ||||
|         "children": [ | ||||
|           { | ||||
|             "name": "planet-name", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "Planet: (.*)", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ], | ||||
|             "script": "gatherPlanetState.name = matches[2]" | ||||
|           }, | ||||
|           { | ||||
|             "name": "planet-starsys", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "Starsystem: (.*)", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ], | ||||
|             "script": "gatherPlanetState.system = matches[2]" | ||||
|           }, | ||||
|           { | ||||
|             "name": "planet-coords", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "Coordinates: ([0-9-]+) ([0-9-]+) ([0-9-]+)", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ] | ||||
|           }, | ||||
|           { | ||||
|             "name": "planet-gov", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "Governed By: (.*)", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ], | ||||
|             "script": "gatherPlanetState.gov = matches[2]" | ||||
|           }, | ||||
|           { | ||||
|             "name": "planet-description-hdr", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "--Planetary Information: ---------------------", | ||||
|                 "type": "substring" | ||||
|               } | ||||
|             ], | ||||
|             "script": "gatherPlanetState.section = \"description\"" | ||||
|           }, | ||||
|           { | ||||
|             "name": "planet-resources-hdr", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "--Planetary Resources: -----------------------", | ||||
|                 "type": "substring" | ||||
|               } | ||||
|             ], | ||||
|             "script": "gatherPlanetState.section = \"resources-basic\"" | ||||
|           }, | ||||
|           { | ||||
|             "name": "resource-price", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "^([\\w ]*)\\s+\\( Price per unit: ([0-9.]+)\\s*\\)", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ] | ||||
|           }, | ||||
|           { | ||||
|             "name": "no-resources", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "(No resources available on this planet)", | ||||
|                 "type": "substring" | ||||
|               } | ||||
|             ] | ||||
|           }, | ||||
|           { | ||||
|             "name": "freeport", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "(.*) is a freeport.", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ], | ||||
|             "script": "gatherPlanetState.freeport = true" | ||||
|           }, | ||||
|           { | ||||
|             "name": "tax", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "Tax Rate: ([0-9]+)%", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ], | ||||
|             "script": "gatherPlanetState.taxRate = tonumber(matches[2])" | ||||
|           }, | ||||
|           { | ||||
|             "name": "any-planet-line", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "(.*)", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ] | ||||
|           }, | ||||
|           { | ||||
|             "name": "planet-empty-line", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "^$", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ] | ||||
|           }, | ||||
|           { | ||||
|             "name": "planet-end", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "Use 'SHOWPLANET <planet> RESOURCES' for current resources.", | ||||
|                 "type": "prefix" | ||||
|               } | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         "name": "gather-starsystems", | ||||
|         "fireLength": 1, | ||||
|         "patterns": [ | ||||
|           { | ||||
|             "pattern": "Listing publicly known starsystems:", | ||||
|             "type": "substring" | ||||
|           } | ||||
|         ], | ||||
|         "children": [ | ||||
|           { | ||||
|             "name": "system-line", | ||||
|             "patterns": [ | ||||
|               { | ||||
|                 "pattern": "^(.*) \\( ([0-9-]+), ([0-9-]+) \\)$", | ||||
|                 "type": "regex" | ||||
|               } | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         "name": "no-datapad", | ||||
|         "patterns": [ | ||||
|           { | ||||
|             "pattern": "You must hold a datapad to do this.", | ||||
|             "type": "substring" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         "name": "showplanet-fail", | ||||
|         "patterns": [ | ||||
|           { | ||||
|             "pattern": "^You fail.$", | ||||
|             "type": "regex" | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										32
									
								
								src/triggers/info-panel/triggers.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/triggers/info-panel/triggers.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "spacetick", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "^Remaining jump time:", | ||||
|         "type": "regex" | ||||
|       } | ||||
|     ], | ||||
|     "script": "lotj.infoPanel.markSpaceTick()" | ||||
|   }, | ||||
|   { | ||||
|     "name": "chaff", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "A burst of chaff is released from the ship.", | ||||
|         "type": "substring" | ||||
|       } | ||||
|     ], | ||||
|     "script": "lotj.infoPanel.markChaff()" | ||||
|   }, | ||||
|   { | ||||
|     "name": "chaff-cleared", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "The chaff has cleared, leaving the ship vulnerable again.", | ||||
|         "type": "substring" | ||||
|       } | ||||
|     ], | ||||
|     "script": "lotj.infoPanel.clearChaff()" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										1
									
								
								src/triggers/layout/leave-ship.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/triggers/layout/leave-ship.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| lotj.layout.selectTab(lotj.layout.upperRightTabData, "map") | ||||
							
								
								
									
										1
									
								
								src/triggers/layout/ship-launched.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/triggers/layout/ship-launched.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| lotj.layout.selectTab(lotj.layout.upperRightTabData, "system") | ||||
							
								
								
									
										20
									
								
								src/triggers/layout/triggers.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/triggers/layout/triggers.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "leave-ship", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "You exit the ship.", | ||||
|         "type": "substring" | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "name": "ship-launched", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "The ship leaves the platform far behind as it flies into space", | ||||
|         "type": "substring" | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										12
									
								
								src/triggers/mapper/triggers.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/triggers/mapper/triggers.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "room-amenities", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "^(.*) \\[([^]]+)\\]$", | ||||
|         "type": "regex" | ||||
|       } | ||||
|     ], | ||||
|     "script": "lotj.mapper.checkAmenityLine(matches[2], matches[3])" | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										2
									
								
								src/triggers/system-map/auto-radar.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/triggers/system-map/auto-radar.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| lotj.systemMap.maskNextRadarOutput = true | ||||
| expandAlias("radar", false) | ||||
							
								
								
									
										5
									
								
								src/triggers/system-map/radar-blank-line.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/triggers/system-map/radar-blank-line.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| if lotj.systemMap.maskNextRadarOutput then | ||||
|   deleteLine() | ||||
| end | ||||
|  | ||||
| setTriggerStayOpen("system-map-radar", 1) | ||||
							
								
								
									
										32
									
								
								src/triggers/system-map/radar-item.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/triggers/system-map/radar-item.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| local trimName = matches[2]:gsub("^%s*(.-)%s*$", "%1") | ||||
|  | ||||
| if trimName == "Your Coordinates:" then | ||||
|   setTriggerStayOpen("system-map-radar", 0) | ||||
|   disableTrigger("system-map-radar") | ||||
|  | ||||
|   echo("\n") | ||||
|   lotj.systemMap.log("Radar data collected.") | ||||
|   lotj.systemMap.maskNextRadarOutput = false | ||||
|   lotj.systemMap.inRadarOutput = false | ||||
|   lotj.systemMap.drawMap() | ||||
|  | ||||
|   return | ||||
| end | ||||
|  | ||||
| _, _, class, name = trimName:find("(.*) '(.*)'") | ||||
| if name == nil then | ||||
|   name = trimName | ||||
| end | ||||
|  | ||||
| lotj.systemMap.addItem({ | ||||
|   class = class, | ||||
|   name = name, | ||||
|   x = tonumber(matches[3]), | ||||
|   y = tonumber(matches[4]), | ||||
|   z = tonumber(matches[5]), | ||||
| }) | ||||
|  | ||||
| if lotj.systemMap.maskNextRadarOutput then | ||||
|   deleteLine() | ||||
| end | ||||
| setTriggerStayOpen("system-map-radar", 1) | ||||
							
								
								
									
										22
									
								
								src/triggers/system-map/system-map-radar.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/triggers/system-map/system-map-radar.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| -- Trigger groups seem to fire the parent trigger on child matches | ||||
| if not matches or #matches == 0 then | ||||
|   return | ||||
| end | ||||
|  | ||||
| -- Occasionally we catch the space prompt here. We want to ignore that. | ||||
| if string.match(matches[2], "Fuel Level:") then | ||||
|   return | ||||
| end | ||||
|  | ||||
| if lotj.systemMap.maskNextRadarOutput then | ||||
|   deleteLine() | ||||
| end | ||||
|  | ||||
| -- If we're already in the block of radar output, don't do any top-level setup | ||||
| if lotj.systemMap.inRadarOutput then | ||||
|   return | ||||
| end | ||||
|  | ||||
| setTriggerStayOpen("system-map-radar", 1) | ||||
| lotj.systemMap.resetItems() | ||||
| lotj.systemMap.inRadarOutput = true | ||||
							
								
								
									
										45
									
								
								src/triggers/system-map/triggers.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/triggers/system-map/triggers.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| [ | ||||
|   { | ||||
|     "name": "system-map-radar", | ||||
|     "isActive": "no", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "^(.*)\\s+([-0-9]+) ([-0-9]+) ([-0-9]+)$", | ||||
|         "type": "regex" | ||||
|       } | ||||
|     ], | ||||
|     "children": [ | ||||
|       { | ||||
|         "name": "radar-blank-line", | ||||
|         "patterns": [ | ||||
|           { | ||||
|             "pattern": "^$", | ||||
|             "type": "regex" | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         "name": "radar-item", | ||||
|         "patterns": [ | ||||
|           { | ||||
|             "pattern": "^(.*)\\s+([-0-9]+) ([-0-9]+) ([-0-9]+)$", | ||||
|             "type": "regex" | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "name": "auto-radar", | ||||
|     "patterns": [ | ||||
|       { | ||||
|         "pattern": "The ship leaves the platform far behind as it flies into space", | ||||
|         "type": "substring" | ||||
|       }, | ||||
|       { | ||||
|         "pattern": "Hyperjump complete", | ||||
|         "type": "substring" | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| ] | ||||
		Reference in New Issue
	
	Block a user