Jump to content

Resource

Alpha Tester
  • Posts

    19
  • Joined

  • Last visited

Profile Information

  • backer_title
    Patron
  • Alpha
    Yes

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

Resource's Achievements

  1. If NQ made decorative items non-destructible ship builders would be more likely to use them to decorate their ships and make them look great. Builders and players avoid decorations because they do not like having to repair dozens (or more) of items all over the ship. Removing destruction from decorative items would negate the need for dynamic properties to be stored on many of the elements considered decorative. I am proposing this because of the overwhelming support I have received from everyone I've talked to about this.
  2. I could not be more angry about your destruction of org core limits. I think you have lost your mind.
  3. Welcome Nouredine Abboud. I sincerely hope your influence will encourage your team to minimize negative gaming experiences, game breaking changes piled up and delivered all at once, and to add large wings and xl atmo engines.
  4. @NQPann and & @NQDeckard: The element collision changes modified the collision boxes of existing elements. This will cause ship builders who believed they were building ships that were "as nq intended" and sold ships as "not stacked" to have customers come to them reporting that the element list is showing stacked elements. Compounding the problem is that it only reports the type of element that is now "stacked" without giving any visual indicator as to which specific element is considered "stacked". You have told us it's your intention to disable elements considered stacked. Additionally you are changing brakes so the tops have to be exposed to the outside of the ship (without actually changing the indicating visual that shows the leading edge as the impacted portion that needs to be exposed). This change will cause most ships in the game to become obsolete without major changes. These two changes are game breaking. Why are you pushing two game breaking changes while also fundamentally changing how resources are allocated, collected, and imposing a 1m per week tax per territory on every player in the game? This feels like the kind of upset I heard from my friends who no longer play the game before the .23 patch went live. Please explain why this is necessary and how you are going to keep this from becoming another exodus.
  5. Medium, Small, and transparent large I don't have an XL sorry.
  6. Just update your unit > start() with this code for a better looking map: function Atlas() return { [0] = { [1]={ GM=6930729684, bodyId=1, center={x=17465536.000,y=22665536.000,z=-34464.000}, name='Madis', planetarySystemId=0, radius=44300 }, [2]={ GM=157470826617, bodyId=2, center={x=-8.000,y=-8.000,z=-126303.000}, name='Alioth', planetarySystemId=0, radius=126068 }, [3]={ GM=11776905000, bodyId=3, center={x=29165536.000,y=10865536.000,z=65536.000}, name='Thades', planetarySystemId=0, radius=49000 }, [4]={ GM=14893847582, bodyId=4, center={x=-13234464.000,y=55765536.000,z=465536.000}, name='Talemai', planetarySystemId=0, radius=57450 }, [5]={ GM=16951680000, bodyId=5, center={x=-43534464.000,y=22565536.000,z=-48934464.000}, name='Feli', planetarySystemId=0, radius=60000 }, [6]={ GM=10502547741, bodyId=6, center={x=52765536.000,y=27165538.000,z=52065535.000}, name='Sicari', planetarySystemId=0, radius=51100 }, [7]={ GM=13033380591, bodyId=7, center={x=58665538.000,y=29665535.000,z=58165535.000}, name='Sinnen', planetarySystemId=0, radius=54950 }, [8]={ GM=18477723600, bodyId=8, center={x=80865538.000,y=54665536.000,z=-934463.940}, name='Teoma', planetarySystemId=0, radius=62000 }, [9]={ GM=18606274330, bodyId=9, center={x=-94134462.000,y=12765534.000,z=-3634464.000}, name='Jago', planetarySystemId=0, radius=61590 }, [10]={ GM=78480000, bodyId=10, center={x=17448118.224,y=22966846.286,z=143078.820}, name='Madis Moon 1', planetarySystemId=0, radius=10000 }, [11]={ GM=237402000, bodyId=11, center={x=17194626.000,y=22243633.880,z=-214962.810}, name='Madis Moon 2', planetarySystemId=0, radius=11000 }, [12]={ GM=265046609, bodyId=12, center={x=17520614.000,y=22184730.000,z=-309989.990}, name='Madis Moon 3', planetarySystemId=0, radius=15005 }, [21]={ GM=2118960000, bodyId=21, center={x=457933.000,y=-1509011.000,z=115524.000}, name='Alioth Moon 1', planetarySystemId=0, radius=30000 }, [22]={ GM=2165833514, bodyId=22, center={x=-1692694.000,y=729681.000,z=-411464.000}, name='Alioth Moon 4', planetarySystemId=0, radius=30330 }, [26]={ GM=68234043600, bodyId=26, center={x=-1404835.000,y=562655.000,z=-285074.000}, name='Sanctuary', planetarySystemId=0, radius=83400 }, [30]={ GM=211564034, bodyId=30, center={x=29214402.000,y=10907080.695,z=433858.200}, name='Thades Moon 1', planetarySystemId=0, radius=14002 }, [31]={ GM=264870000, bodyId=31, center={x=29404193.000,y=10432768.000,z=19554.131}, name='Thades Moon 2', planetarySystemId=0, radius=15000 }, [40]={ GM=141264000, bodyId=40, center={x=-13503090.000,y=55594325.000,z=769838.640}, name='Talemai Moon 2', planetarySystemId=0, radius=12000 }, [41]={ GM=106830900, bodyId=41, center={x=-12800515.000,y=55700259.000,z=325207.840}, name='Talemai Moon 3', planetarySystemId=0, radius=11000 }, [42]={ GM=264870000, bodyId=42, center={x=-13058408.000,y=55781856.000,z=740177.760}, name='Talemai Moon 1', planetarySystemId=0, radius=15000 }, [50]={ GM=499917600, bodyId=50, center={x=-43902841.780,y=22261034.700,z=-48862386.000}, name='Feli Moon 1', planetarySystemId=0, radius=14000 }, [70]={ GM=396912600, bodyId=70, center={x=58969616.000,y=29797945.000,z=57969449.000}, name='Sinnen Moon 1', planetarySystemId=0, radius=17000 }, [100]={ GM=13975172474, bodyId=100, center={x=98865536.000,y=-13534464.000,z=-934461.990}, name='Lacobus', planetarySystemId=0, radius=55650 }, [101]={ GM=264870000, bodyId=101, center={x=98905288.170,y=-13950921.100,z=-647589.530}, name='Lacobus Moon 3', planetarySystemId=0, radius=15000 }, [102]={ GM=444981600, bodyId=102, center={x=99180968.000,y=-13783862.000,z=-926156.400}, name='Lacobus Moon 1', planetarySystemId=0, radius=18000 }, [103]={ GM=211503600, bodyId=103, center={x=99250052.000,y=-13629215.000,z=-1059341.400}, name='Lacobus Moon 2', planetarySystemId=0, radius=14000 }, [110]={ GM=9204742375, bodyId=110, center={x=14165536.000,y=-85634465.000,z=-934464.300}, name='Symeon', planetarySystemId=0, radius=49050 }, [120]={ GM=7135606629, bodyId=120, center={x=2865536.700,y=-99034464.000,z=-934462.020}, name='Ion', planetarySystemId=0, radius=44950 }, [121]={ GM=106830900, bodyId=121, center={x=2472916.800,y=-99133747.000,z=-1133582.800}, name='Ion Moon 1', planetarySystemId=0, radius=11000 }, [122]={ GM=176580000, bodyId=122, center={x=2995424.500,y=-99275010.000,z=-1378480.700}, name='Ion Moon 2', planetarySystemId=0, radius=15000 } } } end function PlanetRef() --[[ Provide coordinate transforms and access to kinematic related parameters Author: JayleBreak Usage (unit.start): PlanetaryReference = require('planetref') galaxyReference = PlanetaryReference(referenceTableSource) helios = galaxyReference[0] -- PlanetaryReference.PlanetarySystem instance alioth = helios[2] -- PlanetaryReference.BodyParameters instance Methods: PlanetaryReference:getPlanetarySystem - based on planetary system ID. PlanetaryReference.isMapPosition - 'true' if an instance of 'MapPosition' PlanetaryReference.createBodyParameters - for entry into reference table PlanetaryReference.BodyParameters - a class containing a body's information. PlanetaryReference.MapPosition - a class for map coordinates PlanetaryReference.PlanetarySystem - a container for planetary system info. PlanetarySystem:castIntersections - from a position in a given direction. PlanetarySystem:closestBody - to the specified coordinates. PlanetarySystem:convertToBodyIdAndWorldCoordinates - from map coordinates. PlanetarySystem:getBodyParameters - from reference table. PlanetarySystem:getPlanetarySystemId - for the instance. BodyParameters:convertToWorldCoordinates - from map coordinates BodyParameters:convertToMapPosition - from world coordinates BodyParameters:getAltitude - of world coordinates BodyParameters:getDistance - from center to world coordinates BodyParameters:getGravity - at a given position in world coordinates. Description An instance of the 'PlanetaryReference' "class" can contain transform and kinematic reference information for all planetary systems in DualUniverse. Each planetary system is identified by a numeric identifier. Currently, the only planetary system, Helios, has the identifier: zero. This "class" supports the indexing ('[]') operation which is equivalent to the use of the 'getPlanetarySystem' method. It also supports the 'pairs()' method for iterating over planetary systems. An instance of the 'PlanetarySystem' "class" contains all reference information for a specific system. It supports the indexing ('[]') and 'pairs()' functions which allows iteration over each "body" in the system where the key is the numeric body ID. It also supports the 'tostring()' method. An instance of the 'BodyParameters' "class" contains all reference information for a single celestial "body" (a moon or planet). It supports the 'tostring()' method, and contains the data members: planetarySystemId - numeric planetary system ID bodyId - numeric body ID radius - radius of the body in meters (zero altitude) center - world coordinates of the body's center position GM - the gravitation parameter (g = GM/radius^2) Note that the user is allowed to add custom fields (e.g. body name), but should insure that complex table values have the '__tostring' metamethod implemented. Transform and Kinematics: "World" coordinates is a cartesian coordinate system with an origin at an arbitrary fixed point in a planetary system and with distances measured in meters. The coordinates are expressible either as a simple table of 3 values or an instance of the 'vec3' class. In either case, the planetary system identity is implicit. "Map" coordinates is a geographic coordinate system with an origin at the center of an identified (by a numeric value) celestial body which is a member of an identified (also a numeric value) planetary system. Note that the convention that latitude, longitude, and altitude values will be the position's x, y, and z world coordinates in the special case of body ID 0. The kinematic parameters in the reference data permit calculations of the gravitational attraction of the celestial body on other objects. Reference Data: This is an example of reference data with a single entry assigned to planetary system ID 0, and body ID 2 ('Alioth'): referenceTable = { [0] = { [2] = { planetarySystemId = 0, bodyId = 2, radius = 126068, center = vec3({x=-8, y=-8, z=-126303}), GM = 1.572199+11 } -- as in F=-GMm/r^2 } } ref=PlanetaryReference(referenceTable) Collecting Reference Data: A combination of information from the "Map" screen in the DU user interface, and values reported by the DU Lua API can be the source of the reference table's data (planetarySystemId, bodyId, and surfaceArea is from the user interface): referenceTable = {} referenceTable[planetarySystemId][bodyId] = PlanetaryReference.createBodyParameters(planetarySystemId, bodyId, surfaceArea, core.getConstructWorldPos(), core.getWorldVertical(), core.getAltitude(), core.g()) Adapting Data Sources: Other sources of data can be adapted or converted. An example of adapting a table, defined in the file: 'planets.lua', containing information on a single planetary system and using celestial body name as the key follows (note that a 'name' field is added to the BodyParameters instance transparently after construction, and the '__pairs' meta function is required to support the 'closestBody' and '__tostring' methods): ref=PlanetaryReference( {[0] = setmetatable(require('planets'), { __index = function(bodies, bodyId) for _,v in pairs(bodies) do if v and v.bodyId == bodyId then return v end end return nil end, __pairs = function(bodies) return function(t, k) local nk, nv = next(t, k) if nv then local GM = nv.gravity * nv.radius^2 local bp = BodyParameters(0, nv.id, nv.radius, nv.pos, GM) bp.name = nk return nk, bp end return nk, nv end, bodies, nil end }) }) Converting Data Sources: An instance of 'PlanetaryReference' that has been adapted to a data source can be used to convert that source to simple table. For example, using the adapted instance shown above: load('convertedData=' .. tostring(ref))() newRef=PlanetaryReference(convertedData) Also See: kepler.lua ]]-- --[[ START OF LOCAL IMPLEMENTATION DETAILS ]]-- -- Type checks local function isNumber(n) return type(n) == 'number' end local function isSNumber(n) return type(tonumber(n)) == 'number' end local function isTable(t) return type(t) == 'table' end local function isString(s) return type(s) == 'string' end local function isVector(v) return isTable(v) and isNumber(v.x and v.y and v.z) end local function isMapPosition(m) return isTable(m) and isNumber(m.latitude and m.longitude and m.altitude and m.bodyId and m.systemId) end -- Constants local deg2rad = math.pi/180 local rad2deg = 180/math.pi local epsilon = 1e-10 local num = ' *([+-]?%d+%.?%d*e?[+-]?%d*)' local posPattern = '::pos{' .. num .. ',' .. num .. ',' .. num .. ',' .. num .. ',' .. num .. '}' -- Utilities local utils = require('cpml.utils') local vec3 = require('cpml.vec3') local clamp = utils.clamp local function float_eq(a,b) if a == 0 then return math.abs(b) < 1e-09 end if b == 0 then return math.abs(a) < 1e-09 end return math.abs(a - b) < math.max(math.abs(a),math.abs(b))*epsilon end local function formatNumber(n) local result = string.gsub( string.reverse(string.format('%.4f',n)), '^0*%.?','') return result == '' and '0' or string.reverse(result) end local function formatValue(obj) if isVector(obj) then return string.format('{x=%.3f,y=%.3f,z=%.3f}', obj.x, obj.y, obj.z) end if isTable(obj) and not getmetatable(obj) then local list = {} local nxt = next(obj) if type(nxt) == 'nil' or nxt == 1 then -- assume this is an array list = obj else for k,v in pairs(obj) do local value = formatValue(v) if type(k) == 'number' then table.insert(list, string.format('[%s]=%s', k, value)) else table.insert(list, string.format('%s=%s', k, value)) end end end return string.format('{%s}', table.concat(list, ',')) end if isString(obj) then return string.format("'%s'", obj:gsub("'",[[\']])) end return tostring(obj) end -- CLASSES -- BodyParameters: Attributes of planetary bodies (planets and moons) local BodyParameters = {} BodyParameters.__index = BodyParameters BodyParameters.__tostring = function(obj, indent) local sep = indent or '' local keys = {} for k in pairs(obj) do table.insert(keys, k) end table.sort(keys) local list = {} for _, k in ipairs(keys) do local value = formatValue(obj[k]) if type(k) == 'number' then table.insert(list, string.format('[%s]=%s', k, value)) else table.insert(list, string.format('%s=%s', k, value)) end end if indent then return string.format('%s%s', indent, table.concat(list, ',\n' .. indent)) end return string.format('{%s}', table.concat(list, ',')) end BodyParameters.__eq = function(lhs, rhs) return lhs.planetarySystemId == rhs.planetarySystemId and lhs.bodyId == rhs.bodyId and float_eq(lhs.radius, rhs.radius) and float_eq(lhs.center.x, rhs.center.x) and float_eq(lhs.center.y, rhs.center.y) and float_eq(lhs.center.z, rhs.center.z) and float_eq(lhs.GM, rhs.GM) end local function mkBodyParameters(systemId, bodyId, radius, worldCoordinates, GM) -- 'worldCoordinates' can be either table or vec3 assert(isSNumber(systemId), 'Argument 1 (planetarySystemId) must be a number:' .. type(systemId)) assert(isSNumber(bodyId), 'Argument 2 (bodyId) must be a number:' .. type(bodyId)) assert(isSNumber(radius), 'Argument 3 (radius) must be a number:' .. type(radius)) assert(isTable(worldCoordinates), 'Argument 4 (worldCoordinates) must be a array or vec3.' .. type(worldCoordinates)) assert(isSNumber(GM), 'Argument 5 (GM) must be a number:' .. type(GM)) return setmetatable({planetarySystemId = tonumber(systemId), bodyId = tonumber(bodyId), radius = tonumber(radius), center = vec3(worldCoordinates), GM = tonumber(GM) }, BodyParameters) end -- MapPosition: Geographical coordinates of a point on a planetary body. local MapPosition = {} MapPosition.__index = MapPosition MapPosition.__tostring = function(p) return string.format('::pos{%d,%d,%s,%s,%s}', p.systemId, p.bodyId, formatNumber(p.latitude*rad2deg), formatNumber(p.longitude*rad2deg), formatNumber(p.altitude)) end MapPosition.__eq = function(lhs, rhs) return lhs.bodyId == rhs.bodyId and lhs.systemId == rhs.systemId and float_eq(lhs.latitude, rhs.latitude) and float_eq(lhs.altitude, rhs.altitude) and (float_eq(lhs.longitude, rhs.longitude) or float_eq(lhs.latitude, math.pi/2) or float_eq(lhs.latitude, -math.pi/2)) end -- latitude and longitude are in degrees while altitude is in meters local function mkMapPosition(overload, bodyId, latitude, longitude, altitude) local systemId = overload -- Id or '::pos{...}' string if isString(overload) and not longitude and not altitude and not bodyId and not latitude then systemId, bodyId, latitude, longitude, altitude = string.match(overload, posPattern) assert(systemId, 'Argument 1 (position string) is malformed.') else assert(isSNumber(systemId), 'Argument 1 (systemId) must be a number:' .. type(systemId)) assert(isSNumber(bodyId), 'Argument 2 (bodyId) must be a number:' .. type(bodyId)) assert(isSNumber(latitude), 'Argument 3 (latitude) must be in degrees:' .. type(latitude)) assert(isSNumber(longitude), 'Argument 4 (longitude) must be in degrees:' .. type(longitude)) assert(isSNumber(altitude), 'Argument 5 (altitude) must be in meters:' .. type(altitude)) end systemId = tonumber(systemId) bodyId = tonumber(bodyId) latitude = tonumber(latitude) longitude = tonumber(longitude) altitude = tonumber(altitude) if bodyId == 0 then -- this is a hack to represent points in space return setmetatable({latitude = latitude, longitude = longitude, altitude = altitude, bodyId = bodyId, systemId = systemId}, MapPosition) end return setmetatable({latitude = deg2rad*clamp(latitude, -90, 90), longitude = deg2rad*(longitude % 360), altitude = altitude, bodyId = bodyId, systemId = systemId}, MapPosition) end -- PlanetarySystem - map body IDs to BodyParameters local PlanetarySystem = {} PlanetarySystem.__index = PlanetarySystem PlanetarySystem.__tostring = function (obj, indent) local sep = indent and (indent .. ' ' ) local bdylist = {} local keys = {} for k in pairs(obj) do table.insert(keys, k) end table.sort(keys) for _, bi in ipairs(keys) do bdy = obj[bi] local bdys = BodyParameters.__tostring(bdy, sep) if indent then table.insert(bdylist, string.format('[%s]={\n%s\n%s}', bi, bdys, indent)) else table.insert(bdylist, string.format(' [%s]=%s', bi, bdys)) end end if indent then return string.format('\n%s%s%s', indent, table.concat(bdylist, ',\n' .. indent), indent) end return string.format('{\n%s\n}', table.concat(bdylist, ',\n')) end local function mkPlanetarySystem(referenceTable) local atlas = {} local pid for _, v in pairs(referenceTable) do local id = v.planetarySystemId if type(id) ~= 'number' then error('Invalid planetary system ID: ' .. tostring(id)) elseif pid and id ~= pid then error('Mismatch planetary system IDs: ' .. id .. ' and ' .. pid) end local bid = v.bodyId if type(bid) ~= 'number' then error('Invalid body ID: ' .. tostring(bid)) elseif atlas[bid] then error('Duplicate body ID: ' .. tostring(bid)) end setmetatable(v.center, getmetatable(vec3.unit_x)) atlas[bid] = setmetatable(v, BodyParameters) pid = id end return setmetatable(atlas, PlanetarySystem) end -- PlanetaryReference - map planetary system ID to PlanetarySystem PlanetaryReference = {} local function mkPlanetaryReference(referenceTable) return setmetatable({ galaxyAtlas = referenceTable or {} }, PlanetaryReference) end PlanetaryReference.__index = function(t,i) if type(i) == 'number' then local system = t.galaxyAtlas[i] return mkPlanetarySystem(system) end return rawget(PlanetaryReference, i) end PlanetaryReference.__pairs = function(obj) return function(t, k) local nk, nv = next(t, k) return nk, nv and mkPlanetarySystem(nv) end, obj.galaxyAtlas, nil end PlanetaryReference.__tostring = function (obj) local pslist = {} for _,ps in pairs(obj or {}) do local psi = ps:getPlanetarySystemId() local pss = PlanetarySystem.__tostring(ps, ' ') table.insert(pslist, string.format(' [%s]={%s\n }', psi, pss)) end return string.format('{\n%s\n}\n', table.concat(pslist,',\n')) end --[[ START OF PUBLIC INTERFACE ]]-- -- PlanetaryReference CLASS METHODS: -- -- BodyParameters - create an instance of BodyParameters class -- planetarySystemId [in]: the body's planetary system ID. -- bodyId [in]: the body's ID. -- radius [in]: the radius in meters of the planetary body. -- bodyCenter [in]: the world coordinates of the center (vec3 or table). -- GM [in]: the body's standard gravitational parameter. -- return: an instance of BodyParameters class. -- PlanetaryReference.BodyParameters = mkBodyParameters -- -- MapPosition - create an instance of the MapPosition class -- overload [in]: either a planetary system ID or a position string ('::pos...') -- bodyId [in]: (ignored if overload is a position string) the body's ID. -- latitude [in]: (ignored if overload is a position string) the latitude. -- longitude [in]:(ignored if overload is a position string) the longitude. -- altitude [in]: (ignored if overload is a position string) the altitude. -- return: the class instance -- PlanetaryReference.MapPosition = mkMapPosition -- -- PlanetarySystem - create an instance of PlanetarySystem class -- referenceData [in]: a table (indexed by bodyId) of body reference info. -- return: the class instance -- PlanetaryReference.PlanetarySystem = mkPlanetarySystem -- -- createBodyParameters - create an instance of BodyParameters class -- planetarySystemId [in]: the body's planetary system ID. -- bodyId [in]: the body's ID. -- surfaceArea [in]: the body's surface area in square meters. -- aPosition [in]: world coordinates of a position near the body. -- verticalAtPosition [in]: a vector pointing towards the body center. -- altitudeAtPosition [in]: the altitude in meters at the position. -- gravityAtPosition [in]: the magnitude of the gravitational acceleration. -- return: an instance of BodyParameters class. -- function PlanetaryReference.createBodyParameters(planetarySystemId, bodyId, surfaceArea, aPosition, verticalAtPosition, altitudeAtPosition, gravityAtPosition) assert(isSNumber(planetarySystemId), 'Argument 1 (planetarySystemId) must be a number:' .. type(planetarySystemId)) assert(isSNumber(bodyId), 'Argument 2 (bodyId) must be a number:' .. type(bodyId)) assert(isSNumber(surfaceArea), 'Argument 3 (surfaceArea) must be a number:' .. type(surfaceArea)) assert(isTable(aPosition), 'Argument 4 (aPosition) must be an array or vec3:' .. type(aPosition)) assert(isTable(verticalAtPosition), 'Argument 5 (verticalAtPosition) must be an array or vec3:' .. type(verticalAtPosition)) assert(isSNumber(altitudeAtPosition), 'Argument 6 (altitude) must be in meters:' .. type(altitudeAtPosition)) assert(isSNumber(gravityAtPosition), 'Argument 7 (gravityAtPosition) must be number:' .. type(gravityAtPosition)) local radius = math.sqrt(surfaceArea/4/math.pi) local distance = radius + altitudeAtPosition local center = vec3(aPosition) + distance*vec3(verticalAtPosition) local GM = gravityAtPosition * distance * distance return mkBodyParameters(planetarySystemId, bodyId, radius, center, GM) end -- -- isMapPosition - check for the presence of the 'MapPosition' fields -- valueToTest [in]: the value to be checked -- return: 'true' if all required fields are present in the input value -- PlanetaryReference.isMapPosition = isMapPosition -- PlanetaryReference INSTANCE METHODS: -- -- getPlanetarySystem - get the planetary system using ID or MapPosition as key -- overload [in]: either the planetary system ID or a MapPosition that has it. -- return: instance of 'PlanetarySystem' class or nil on error -- function PlanetaryReference:getPlanetarySystem(overload) --if galaxyAtlas then local planetarySystemId = overload if isMapPosition(overload) then planetarySystemId = overload.systemId end if type(planetarySystemId) == 'number' then local system = self.galaxyAtlas[i] if system then if getmetatable(nv) ~= PlanetarySystem then system = mkPlanetarySystem(system) end return system end end --end --return nil end -- PlanetarySystem INSTANCE METHODS: -- -- castIntersections - Find the closest body that intersects a "ray cast". -- origin [in]: the origin of the "ray cast" in world coordinates -- direction [in]: the direction of the "ray cast" as a 'vec3' instance. -- sizeCalculator [in]: (default: returns 1.05*radius) Returns size given body. -- bodyIds[in]: (default: all IDs in system) check only the given IDs. -- return: The closest body that blocks the cast or 'nil' if none. -- function PlanetarySystem:castIntersections(origin, direction, sizeCalculator, bodyIds) local sizeCalculator = sizeCalculator or function (body) return 1.05*body.radius end local candidates = {} if bodyIds then for _,i in ipairs(bodyIds) do candidates[i] = self[i] end else bodyIds = {} for k,body in pairs(self) do table.insert(bodyIds, k) candidates[k] = body end end local function compare(b1,b2) local v1 = candidates[b1].center - origin local v2 = candidates[b2].center - origin return v1:len() < v2:len() end table.sort(bodyIds, compare) local dir = direction:normalize() for i, id in ipairs(bodyIds) do local body = candidates[id] local c_oV3 = body.center - origin local radius = sizeCalculator(body) local dot = c_oV3:dot(dir) local desc = dot^2 - (c_oV3:len2() - radius^2) if desc >= 0 then local root = math.sqrt(desc) local farSide = dot + root local nearSide = dot - root if nearSide > 0 then return body, farSide, nearSide elseif farSide > 0 then return body, farSide, nil end end end return nil, nil, nil end -- -- closestBody - find the closest body to a given set of world coordinates -- coordinates [in]: the world coordinates of position in space -- return: an instance of the BodyParameters object closest to 'coordinates' -- function PlanetarySystem:closestBody(coordinates) assert(type(coordinates) == 'table', 'Invalid coordinates.') local minDistance2, body local coord = vec3(coordinates) for _,params in pairs(self) do local distance2 = (params.center - coord):len2() if not body or distance2 < minDistance2 then body = params minDistance2 = distance2 end end return body end -- -- convertToBodyIdAndWorldCoordinates - map to body Id and world coordinates -- overload [in]: an instance of MapPosition or a position string ('::pos...) -- return: a vec3 instance containing the world coordinates or 'nil' on error. -- function PlanetarySystem:convertToBodyIdAndWorldCoordinates(overload) local mapPosition = overload if isString(overload) then mapPosition = mkMapPosition(overload) end if mapPosition.bodyId == 0 then return 0, vec3(mapPosition.latitude, mapPosition.longitude, mapPosition.altitude) end local params = self:getBodyParameters(mapPosition) if params then return mapPosition.bodyId, params:convertToWorldCoordinates(mapPosition) end end -- -- getBodyParameters - get or create an instance of BodyParameters class -- overload [in]: either an instance of MapPosition or a body's ID. -- return: a BodyParameters instance or 'nil' if body ID is not found. -- function PlanetarySystem:getBodyParameters(overload) local bodyId = overload if isMapPosition(overload) then bodyId = overload.bodyId end assert(isSNumber(bodyId), 'Argument 1 (bodyId) must be a number:' .. type(bodyId)) return self[bodyId] end -- -- getPlanetarySystemId - get the planetary system ID for this instance -- return: the planetary system ID or nil if no planets are in the system. -- function PlanetarySystem:getPlanetarySystemId() local k, v = next(self) return v and v.planetarySystemId end -- BodyParameters INSTANCE METHODS: -- -- convertToMapPosition - create an instance of MapPosition from coordinates -- worldCoordinates [in]: the world coordinates of the map position. -- return: an instance of MapPosition class -- function BodyParameters:convertToMapPosition(worldCoordinates) assert(isTable(worldCoordinates), 'Argument 1 (worldCoordinates) must be an array or vec3:' .. type(worldCoordinates)) local worldVec = vec3(worldCoordinates) if self.bodyId == 0 then return setmetatable({latitude = worldVec.x, longitude = worldVec.y, altitude = worldVec.z, bodyId = 0, systemId = self.planetarySystemId}, MapPosition) end local coords = worldVec - self.center local distance = coords:len() local altitude = distance - self.radius local latitude = 0 local longitude = 0 if not float_eq(distance, 0) then local phi = math.atan(coords.y, coords.x) longitude = phi >= 0 and phi or (2*math.pi + phi) latitude = math.pi/2 - math.acos(coords.z/distance) end return setmetatable({latitude = latitude, longitude = longitude, altitude = altitude, bodyId = self.bodyId, systemId = self.planetarySystemId}, MapPosition) end -- -- convertToWorldCoordinates - convert a map position to world coordinates -- overload [in]: an instance of MapPosition or a position string ('::pos...') -- function BodyParameters:convertToWorldCoordinates(overload) local mapPosition = isString(overload) and mkMapPosition(overload) or overload if mapPosition.bodyId == 0 then -- support deep space map position return vec3(mapPosition.latitude, mapPosition.longitude, mapPosition.altitude) end assert(isMapPosition(mapPosition), 'Argument 1 (mapPosition) is not an instance of "MapPosition".') assert(mapPosition.systemId == self.planetarySystemId, 'Argument 1 (mapPosition) has a different planetary system ID.') assert(mapPosition.bodyId == self.bodyId, 'Argument 1 (mapPosition) has a different planetary body ID.') local xproj = math.cos(mapPosition.latitude) return self.center + (self.radius + mapPosition.altitude) * vec3(xproj*math.cos(mapPosition.longitude), xproj*math.sin(mapPosition.longitude), math.sin(mapPosition.latitude)) end -- -- getAltitude - calculate the altitude of a point given in world coordinates. -- worldCoordinates [in]: the world coordinates of the point. -- return: the altitude in meters -- function BodyParameters:getAltitude(worldCoordinates) return (vec3(worldCoordinates) - self.center):len() - self.radius end -- -- getDistance - calculate the distance to a point given in world coordinates. -- worldCoordinates [in]: the world coordinates of the point. -- return: the distance in meters -- function BodyParameters:getDistance(worldCoordinates) return (vec3(worldCoordinates) - self.center):len() end -- -- getGravity - calculate the gravity vector induced by the body. -- worldCoordinates [in]: the world coordinates of the point. -- return: the gravity vector in meter/seconds^2 -- function BodyParameters:getGravity(worldCoordinates) local radial = self.center - vec3(worldCoordinates) -- directed towards body local len2 = radial:len2() return (self.GM/len2) * radial/math.sqrt(len2) end -- end of module return setmetatable(PlanetaryReference, { __call = function(_,...) return mkPlanetaryReference(...) end }) end function Keplers() --[[ Provides methods for computing orbital information for an object Usage: Kepler = require('autoconf.custom.kepler') alioth = Kepler({ GM=157470826617, bodyId=2, center={x=-8.000,y=-8.000,z=-126303.000}, name='Alioth', planetarySystemId=0, radius=126068 }) altitude = 6000 position = '::pos{0,2,0,0,6000}' e, o = alioth:escapeAndOrbitalSpeed(altitude) orbit = alioth:orbitalParameters(position, {0, o+1, 0}) print("Eccentricity " .. orbit.eccentricity) print("Perihelion " .. orbit.periapsis.altitude) print("Max. speed " .. orbit.periapsis.speed) print("Circular orbit speed " .. orbit.periapsis.circularOrbitSpeed) print("Aphelion " .. orbit.apoapsis.altitude) print("Min. speed " .. orbit.apoapsis.speed) print("Orbital period " .. orbit.period) --- output: Eccentricity 0.0018324307017878 Perihelion 6000.0 Max. speed 1092.9462297033 Circular orbit speed 1091.9462297033 Aphelion 6484.8994605062 Min. speed 1088.9480596194 Orbital period 762.02818214049 Methods: Kepler:escapeAndOrbitalSpeed - for a given celestial body and altitude. Kepler:orbitalParameters - for a given massless object and a celestial body. Description The motion of an object in the vicinity of substantially larger mass is in the domain of the "2-body problem". By assuming the object whose motion is of interest is of negligable mass simplifies the calculations of: the speed to escape the body, the speed of a circular orbit, and the parameters defining the orbit of the object (or the lack of orbit as the case may be). Orbital Parameters: periapsis - the closest approach to the planet apoapsis - the furthest point from the planet if in orbit (otherwise nil) eccentricity - 0 for circular orbits <1 for elliptical orbits 1 for parabiolic trajectory >1 for hyperbolic trajectory period - time (in seconds) to complete an orbit Also See: planetref.lua ]]-- local vec3 = require('cpml.vec3') local PlanetRef = PlanetRef() local function isString(s) return type(s) == 'string' end local function isTable(t) return type(t) == 'table' end local function float_eq(a,b) if a == 0 then return math.abs(b) < 1e-09 end if b == 0 then return math.abs(a) < 1e-09 end return math.abs(a - b) < math.max(math.abs(a),math.abs(b))*epsilon end Kepler = {} Kepler.__index = Kepler -- -- escapeAndOrbitalSpeed - speed required to escape and for a circular orbit -- altitude [in]: the height of the orbit in meters above "sea-level" -- return: the speed in m/s needed to escape the celestial body and to orbit it. -- function Kepler:escapeAndOrbitalSpeed(altitude) assert(self.body) -- P = -GMm/r and KE = mv^2/2 (no lorentz factor used) -- mv^2/2 = GMm/r -- v^2 = 2GM/r -- v = sqrt(2GM/r1) local distance = altitude + self.body.radius if not float_eq(distance, 0) then local orbit = math.sqrt(self.body.GM/distance) return math.sqrt(2)*orbit, orbit end return nil, nil end -- -- orbitalParameters: determine the orbital elements for a two-body system. -- overload [in]: the world coordinates or map coordinates of a massless object. -- velocity [in]: The velocity of the massless point object in m/s. -- return: the 6 orbital elements for the massless object. -- function Kepler:orbitalParameters(overload, velocity) assert(self.body) assert(isTable(overload) or isString(overload)) assert(isTable(velocity)) local pos = (isString(overload) or PlanetRef.isMapPosition(overload)) and self.body:convertToWorldCoordinates(overload) or vec3(overload) local v = vec3(velocity) local r = pos - self.body.center local v2 = v:len2() local d = r:len() local mu = self.body.GM local e = ((v2 - mu/d)*r - r:dot(v)*v)/mu local a = mu/(2*mu/d - v2) local ecc = e:len() local dir = e:normalize() local pd = a*(1-ecc) local ad = a*(1+ecc) local per = pd*dir + self.body.center local apo = ecc <= 1 and -ad*dir + self.body.center or nil local trm = math.sqrt(a*mu*(1-ecc*ecc)) local Period = apo and 2*math.pi*math.sqrt(a^3/mu) -- These are great and all, but, I need more. local trueAnomaly = math.acos((e:dot(r))/(ecc*d)) if r:dot(v) < 0 then trueAnomaly = -(trueAnomaly - 2*math.pi) end -- Apparently... cos(EccentricAnomaly) = (cos(trueAnomaly) + eccentricity)/(1 + eccentricity * cos(trueAnomaly)) local EccentricAnomaly = math.acos((math.cos(trueAnomaly) + ecc)/(1 + ecc * math.cos(trueAnomaly))) -- Then.... apparently if this is below 0, we should add 2pi to it -- I think also if it's below 0, we're past the apoapsis? local timeTau = EccentricAnomaly if timeTau < 0 then timeTau = timeTau + 2*math.pi end -- So... time since periapsis... -- Is apparently easy if you get mean anomly. t = M/n where n is mean motion, = 2*pi/Period local MeanAnomaly = timeTau - ecc * math.sin(timeTau) local TimeSincePeriapsis = MeanAnomaly/(2*math.pi/Period) --system.print(MeanAnomaly .. " - " .. TimeSincePeriapsis .. " - " .. Period .. " - " .. EccentricAnomaly .. " - " .. timeTau .. " - " .. trueAnomaly) -- Mean anom is 0 at periapsis, positive before it... and positive after it. -- I guess this is why I needed to use timeTau and not EccentricAnomaly here local TimeToPeriapsis = Period - TimeSincePeriapsis local TimeToApoapsis = TimeToPeriapsis + Period/2 if trueAnomaly - math.pi > 0 then -- TBH I think something's wrong in my formulas because I needed this. TimeToPeriapsis = TimeSincePeriapsis TimeToApoapsis = TimeToPeriapsis + Period/2 end if TimeToApoapsis > Period then TimeToApoapsis = TimeToApoapsis - Period end return { periapsis = { position = per, speed = trm/pd, circularOrbitSpeed = math.sqrt(mu/pd), altitude = pd - self.body.radius}, apoapsis = apo and { position = apo, speed = trm/ad, circularOrbitSpeed = math.sqrt(mu/ad), altitude = ad - self.body.radius}, currentVelocity = v, currentPosition = pos, eccentricity = ecc, period = Period, eccentricAnomaly = EccentricAnomaly, meanAnomaly = MeanAnomaly, timeToPeriapsis = TimeToPeriapsis, timeToApoapsis = TimeToApoapsis } end local function new(bodyParameters) local params = PlanetRef.BodyParameters(bodyParameters.planetarySystemId, bodyParameters.bodyId, bodyParameters.radius, bodyParameters.center, bodyParameters.GM) return setmetatable({body = params}, Kepler) end return setmetatable(Kepler, { __call = function(_,...) return new(...) end }) end function Kinematics() --[[ DualUniverse kinematic equations Author: JayleBreak Usage (unit.start): Kinematics = require('autoconf.custom.kinematics') Methods: computeAccelerationTime - "relativistic" version of t = (vf - vi)/a computeDistanceAndTime - Return distance & time needed to reach final speed. computeTravelTime - "relativistic" version of t=(sqrt(2ad+v^2)-v)/a Description DualUniverse increases the effective mass of constructs as their absolute speed increases by using the "lorentz" factor (from relativity) as the scale factor. This results in an upper bound on the absolute speed of constructs (excluding "warp" drive) that is set to 30 000 KPH (8 333 MPS). This module provides utilities for computing some physical quantities taking this scaling into account. ]]-- local Kinematic = {} -- just a namespace local C = 30000000/3600 local C2 = C*C local ITERATIONS = 100 -- iterations over engine "warm-up" period local function lorentz(v) return 1/math.sqrt(1 - v*v/C2) end -- -- computeAccelerationTime - "relativistic" version of t = (vf - vi)/a -- initial [in]: initial (positive) speed in meters per second. -- acceleration [in]: constant acceleration until 'finalSpeed' is reached. -- final [in]: the speed at the end of the time interval. -- return: the time in seconds spent in traversing the distance -- function Kinematic.computeAccelerationTime(initial, acceleration, final) -- The low speed limit of following is: t=(vf-vi)/a (from: vf=vi+at) local k1 = C*math.asin(initial/C) return (C * math.asin(final/C) - k1)/acceleration end -- -- computeDistanceAndTime - Return distance & time needed to reach final speed. -- initial[in]: Initial speed in meters per second. -- final[in]: Final speed in meters per second. -- restMass[in]: Mass of the construct at rest in Kg. -- thrust[in]: Engine's maximum thrust in Newtons. -- t50[in]: (default: 0) Time interval to reach 50% thrust in seconds. -- brakeThrust[in]: (default: 0) Constant thrust term when braking. -- return: Distance (in meters), time (in seconds) required for change. -- function Kinematic.computeDistanceAndTime(initial, final, restMass, thrust, t50, brakeThrust) -- This function assumes that the applied thrust is colinear with the -- velocity. Furthermore, it does not take into account the influence -- of gravity, not just in terms of its impact on velocity, but also -- its impact on the orientation of thrust relative to velocity. -- These factors will introduce (usually) small errors which grow as -- the length of the trip increases. t50 = t50 or 0 brakeThrust = brakeThrust or 0 -- usually zero when accelerating local tau0 = lorentz(initial) local speedUp = initial <= final local a0 = thrust * (speedUp and 1 or -1)/restMass local b0 = -brakeThrust/restMass local totA = a0+b0 if speedUp and totA <= 0 or not speedUp and totA >= 0 then return -1, -1 -- no solution end local distanceToMax, timeToMax = 0, 0 -- If, the T50 time is set, then assume engine is at zero thrust and will -- reach full thrust in 2*T50 seconds. Thrust curve is given by: -- Thrust: F(z)=(a0*(1+sin(z))+2*b0)/2 where z=pi*(t/t50 - 1)/2 -- Acceleration is given by F(z)/m(z) where m(z) = m/sqrt(1-v^2/c^2) -- or v(z)' = (a0*(1+sin(z))+2*b0)*sqrt(1-v(z)^2/c^2)/2 if a0 ~= 0 and t50 > 0 then -- Closed form solution for velocity exists: -- v(t) = -c*tan(w)/sqrt(tan(w)^2+1) => w = -asin(v/c) -- w=(pi*t*(a0/2+b0)-a0*t50*sin(pi*t/2/t50)+*pi*c*k1)/pi/c -- @ t=0, v(0) = vi -- pi*c*k1/pi/c = -asin(vi/c) -- k1 = asin(vi/c) local k1 = math.asin(initial/C) local c1 = math.pi*(a0/2+b0) local c2 = a0*t50 local c3 = C*math.pi local v = function(t) local w = (c1*t - c2*math.sin(math.pi*t/2/t50) + c3*k1)/c3 local tan = math.tan(w) return C*tan/math.sqrt(tan*tan+1) end local speedchk = speedUp and function(s) return s >= final end or function(s) return s <= final end timeToMax = 2*t50 if speedchk(v(timeToMax)) then local lasttime = 0 while math.abs(timeToMax - lasttime) > 0.5 do local t = (timeToMax + lasttime)/2 if speedchk(v(t)) then timeToMax = t else lasttime = t end end end -- There is no closed form solution for distance in this case. -- Numerically integrate for time t=0 to t=2*T50 (or less) local lastv = initial local tinc = timeToMax/ITERATIONS for step = 1, ITERATIONS do local speed = v(step*tinc) distanceToMax = distanceToMax + (speed+lastv)*tinc/2 lastv = speed end if timeToMax < 2*t50 then return distanceToMax, timeToMax end initial = lastv end -- At full thrust, acceleration only depends on the Lorentz factor: -- v(t)' = (F/m(v)) = a*sqrt(1-v(t)^2/c^2) where a = a0+b0 -- -> v = c*sin((at+k1)/c) -- @ t=0, v=vi: k1 = c*asin(vi/c) -- -> t = (c*asin(v/c) - k1)/a -- x(t)' = c*sin((at+k1)/c) -- x = k2 - c^2 cos((at+k1)/c)/a -- @ t=0, x=0: k2 = c^2 * cos(k1/c)/a local k1 = C*math.asin(initial/C) local time = (C * math.asin(final/C) - k1)/totA local k2 = C2 *math.cos(k1/C)/totA local distance = k2 - C2 * math.cos((totA*time + k1)/C)/totA return distance+distanceToMax, time+timeToMax end -- -- computeTravelTime - "relativistic" version of t=(sqrt(2ad+v^2)-v)/a -- initialSpeed [in]: initial (positive) speed in meters per second -- acceleration [in]: constant acceleration until 'distance' is traversed -- distance [in]: the distance traveled in meters -- return: the time in seconds spent in traversing the distance -- function Kinematic.computeTravelTime(initial, acceleration, distance) -- The low speed limit of following is: t=(sqrt(2ad+v^2)-v)/a -- (from: d=vt+at^2/2) if distance == 0 then return 0 end if acceleration > 0 then local k1 = C*math.asin(initial/C) local k2 = C2*math.cos(k1/C)/acceleration return (C*math.acos(acceleration*(k2 - distance)/C2) - k1)/acceleration end assert(initial > 0, 'Acceleration and initial speed are both zero.') return distance/initial end function Kinematic.lorentz(v) return lorentz(v) end return Kinematic end PlanetaryReference = PlanetRef() galaxyReference = PlanetaryReference(Atlas()) Kinematic = Kinematics() Kep = Keplers() function getDistanceDisplayString(distance) local su = distance > 100000 local result = "" if su then -- Convert to SU result = round(distance/1000/200,1) .. " SU" else -- Convert to KM result = round(distance/1000,1) .. " KM" end return result end PlanetaryReference = PlanetRef() galaxyReference = PlanetaryReference(Atlas()) MapScreenButtons = {} MapScreenMouseX = 0 MapScreenMouseY = 0 MapScreenMouseDown = false MapScreenButtonSelected = 0 local worldPos = vec3(core.getConstructWorldPos()) local locX = (worldPos.x/400000) local locY = (worldPos.y/400000)*(-1) local destX = 0 local destY = 0 local sudistance = 0 local loc = vec3(core.getConstructWorldPos()) local ion = galaxyReference[0][120] ---uses Atlas functions local thades = vec3(29165536.000, 10865536.000, 65536.000) local sinnen = vec3(58665536.000, 29665536.000, 58165536.000) local alioth = galaxyReference[0][2] ---uses Atlas functions local madis = vec3(17465536.000, 22665536.000, -34464.000) local jago = vec3(-94134464.000, 12765536.000, -3634464.000) local symeon = vec3(14165536.000, -85634464.000, -934464.000) local lacobus = vec3(98865536.000, -13534464.000, -934464.000) local teoma = vec3(80865536.000, 54665536.000, -934464.000) local feli = vec3(-43534464.000, 22565536.000, -48934464.000) local talemai = vec3(-13234464.000, 55765536.000, 465536.000) local sicari = vec3(52765536.000, 27165536.000, 52065536.000) local distion = math.floor(ion:getDistance(loc)/200000) ---uses getDistance functions---- local distthades = string.format("%.2f", math.sqrt((loc.x-thades.x)^2+(loc.y-thades.y)^2+(loc.z-thades.z)^2)/200000) local distalioth = math.floor(alioth:getDistance(loc)/200000) ---uses getDistance functions---- local distmadis = string.format("%.2f", math.sqrt((loc.x-madis.x)^2+(loc.y-madis.y)^2+(loc.z-madis.z)^2)/200000) local distjago = string.format("%.2f", math.sqrt((loc.x-jago.x)^2+(loc.y-jago.y)^2+(loc.z-jago.z)^2)/200000) local distlacobus = string.format("%.2f", math.sqrt((loc.x-lacobus.x)^2+(loc.y-lacobus.y)^2+(loc.z-lacobus.z)^2)/200000) local distteoma = string.format("%.2f", math.sqrt((loc.x-teoma.x)^2+(loc.y-teoma.y)^2+(loc.z-teoma.z)^2)/200000) local distsymeon = string.format("%.2f", math.sqrt((loc.x-symeon.x)^2+(loc.y-symeon.y)^2+(loc.z-symeon.z)^2)/200000) local distfeli = string.format("%.2f", math.sqrt((loc.x-feli.x)^2+(loc.y-feli.y)^2+(loc.z-feli.z)^2)/200000) local distsinnen = string.format("%.2f", math.sqrt((loc.x-sinnen.x)^2+(loc.y-sinnen.y)^2+(loc.z-sinnen.z)^2)/200000) local disttalemai = string.format("%.2f", math.sqrt((loc.x-talemai.x)^2+(loc.y-talemai.y)^2+(loc.z-talemai.z)^2)/200000) local distsicari = string.format("%.2f", math.sqrt((loc.x-sicari.x)^2+(loc.y-sicari.y)^2+(loc.z-sicari.z)^2)/200000) selection = 0 for i = 1,1 do local button = {id = ("b"..1), enabled=true, td="<td>", top=2/100, bottom=13/100, left=1/100, right=28/100} table.insert(MapScreenButtons, button) end for i = 2,2 do local button = {id = ("b"..2), enabled=true, td="<td>", top=15/100, bottom=26/100, left=1/100, right=30/100} table.insert(MapScreenButtons, button) end for i = 3,3 do local button = {id = ("b"..3), enabled=true, td="<td>", top=27/100, bottom=38/100, left=1/100, right=28/100} table.insert(MapScreenButtons, button) end for i = 4,4 do local button = {id = ("b"..4), enabled=true, td="<td>", top=39/100, bottom=50/100, left=1/100, right=28/100} table.insert(MapScreenButtons, button) end for i = 5,5 do local button = {id = ("b"..5), enabled=true, td="<td>", top=51/100, bottom=62/100, left=1/100, right=28/100} table.insert(MapScreenButtons, button) end for i = 6,6 do local button = {id = ("b"..6), enabled=true, td="<td>", top=64/100, bottom=75/100, left=1/100, right=28/100} table.insert(MapScreenButtons, button) end for i = 7,7 do local button = {id = ("b"..7), enabled=true, td="<td>", top=2/100, bottom=13/100, left=75/100, right=100/100} table.insert(MapScreenButtons, button) end for i = 8,8 do local button = {id = ("b"..8), enabled=true, td="<td>", top=15/100, bottom=26/100, left=75/100, right=100/100} table.insert(MapScreenButtons, button) end for i = 9,9 do local button = {id = ("b"..9), enabled=true, td="<td>", top=27/100, bottom=38/100, left=75/100, right=100/100} table.insert(MapScreenButtons, button) end for i = 10,10 do local button = {id = ("b"..10), enabled=true, td="<td>", top=39/100, bottom=50/100, left=75/100, right=100/100} table.insert(MapScreenButtons, button) end for i = 11,11 do local button = {id = ("b"..11), enabled=true, td="<td>", top=51/100, bottom=62/100, left=75/100, right=100/100} table.insert(MapScreenButtons, button) end for i = 12,12 do local button = {id = ("b"..12), enabled=true, td="<td>", top=64/100, bottom=75/100, left=75/100, right=100/100} table.insert(MapScreenButtons, button) end for i = 13,13 do local button = {id = ("b"..13), enabled=true, td="<td>", top=90/100, bottom=100/100, left=1/100, right=18/100} table.insert(MapScreenButtons, button) end function evaluateButtons() local selected = 0 if #MapScreenButtons >= 1 then -- Set button styles for i, button in ipairs(MapScreenButtons) do if button.left < MapScreenMouseX and MapScreenMouseX < button.right and button.top < MapScreenMouseY and MapScreenMouseY < button.bottom then if MapScreenMouseDown and MapScreenButtonSelected == i then end selected = i end if not button.enabled then end end end return selected end function onButtonDown(buttonNo) local button = MapScreenButtons[buttonNo] if not button or not button.enabled then return end end function onButtonUp(buttonNo) local button = MapScreenButtons[buttonNo] if not button or not button.enabled then return end function onClick(buttonNo) local button = MapScreenButtons[buttonNo] if not button or not button.enabled then return end end if buttonNo == 1 then destX = 0 destY = 0 selection = 1 sudistance = distalioth elseif buttonNo == 2 then destX = 43 destY = -56 selection = 2 sudistance = distmadis elseif buttonNo == 3 then destX = 73 destY = -27 selection = 3 sudistance = distthades elseif buttonNo == 4 then destX = -33 destY = -139 selection = 4 sudistance = disttalemai elseif buttonNo == 5 then destX = -109 destY = -56 selection = 5 sudistance = distfeli elseif buttonNo == 6 then destX = 131 destY = -68 selection = 6 sudistance = distsicari elseif buttonNo == 7 then destX = 35 destY = 214 selection = 7 sudistance = distsymeon elseif buttonNo == 8 then destX = 146 destY = -74 selection = 8 sudistance = distsinnen elseif buttonNo == 9 then destX = -235 destY = -32 selection = 9 sudistance = distjago elseif buttonNo == 10 then destX = 202 destY = -137 selection = 10 sudistance = distteoma elseif buttonNo == 11 then destX = 7 destY = 247 selection = 11 sudistance = distion elseif buttonNo == 12 then destX = 247 destY = 34 selection = 12 sudistance = distlacobus elseif buttonNo == 13 then unit.exit() end end local floor = math.floor local concat = table.concat local secondsInMinute = 60 local secondsInHour = secondsInMinute * 60 local secondsInDay = secondsInHour * 24 local secondsInYear = 365.2419 * secondsInDay local minTotalSecondsToShowOnlyYears = secondsInYear * 10 ---@param totalSeconds number ---@param maxComponents nil|number local function formatTimeWithUnits (totalSeconds, maxComponents) maxComponents = maxComponents or 2 local buffer = {} if totalSeconds < 0 then buffer[#buffer + 1] = "-" totalSeconds = -totalSeconds maxComponents = maxComponents + 1 end local showOnlyYears = totalSeconds > minTotalSecondsToShowOnlyYears local years = floor(totalSeconds / secondsInYear) if years > 0 then buffer[#buffer + 1] = years .. "y" end if #buffer < maxComponents and not showOnlyYears then local days = floor(totalSeconds % secondsInYear / secondsInDay) if days > 0 then buffer[#buffer + 1] = days .. "d" end end if #buffer < maxComponents and not showOnlyYears then local hours = floor(totalSeconds % secondsInDay / secondsInHour) if hours > 0 then buffer[#buffer + 1] = hours .. "h" end end if #buffer < maxComponents and not showOnlyYears then local minutes = floor(totalSeconds % secondsInHour / secondsInMinute) if minutes > 0 then buffer[#buffer + 1] = minutes .. "m" end end if #buffer < maxComponents and not showOnlyYears then local seconds = floor(totalSeconds % secondsInMinute) if seconds > 0 then buffer[#buffer + 1] = seconds .. "s" end end if #buffer == 0 then return "0s" end return concat(buffer, " ") end function updateScreen() loc = vec3(core.getConstructWorldPos()) local shipVelocity = vec3(core.getVelocity()):len() * 3.6 local shipAcceleration = vec3(core.getVelocity()):len() * 3.6 local time_to_distance = 0 local display_selection = "" if selection == 1 then alioth = galaxyReference[0][2] ---uses Atlas functions distalioth = math.floor(alioth:getDistance(loc)/200000) ---uses getDistance functions---- time_to_distance = distalioth * 200 / shipVelocity display_selection = "alioth" elseif selection == 2 then madis = vec3(17465536.000, 22665536.000, -34464.000) distmadis = string.format("%.2f", math.sqrt((loc.x-madis.x)^2+(loc.y-madis.y)^2+(loc.z-madis.z)^2)/200000) time_to_distance = distmadis * 200 / shipVelocity display_selection = "madis" elseif selection == 3 then thades = vec3(29165536.000, 10865536.000, 65536.000) distthades = string.format("%.2f", math.sqrt((loc.x-thades.x)^2+(loc.y-thades.y)^2+(loc.z-thades.z)^2)/200000) time_to_distance = distthades * 200 / shipVelocity display_selection = "thades" elseif selection == 4 then talemai = vec3(-13234464.000, 55765536.000, 465536.000) disttalemai = string.format("%.2f", math.sqrt((loc.x-talemai.x)^2+(loc.y-talemai.y)^2+(loc.z-talemai.z)^2)/200000) time_to_distance = disttalemai * 200 / shipVelocity display_selection = "talemai" elseif selection == 5 then feli = vec3(-43534464.000, 22565536.000, -48934464.000) distfeli = string.format("%.2f", math.sqrt((loc.x-feli.x)^2+(loc.y-feli.y)^2+(loc.z-feli.z)^2)/200000) time_to_distance = distfeli * 200 / shipVelocity display_selection = "feli" elseif selection == 6 then sicari = vec3(52765536.000, 27165536.000, 52065536.000) distsicari = string.format("%.2f", math.sqrt((loc.x-sicari.x)^2+(loc.y-sicari.y)^2+(loc.z-sicari.z)^2)/200000) time_to_distance = distsicari * 200 / shipVelocity display_selection = "sicari" elseif selection == 7 then symeon = vec3(14165536.000, -85634464.000, -934464.000) distsymeon = string.format("%.2f", math.sqrt((loc.x-symeon.x)^2+(loc.y-symeon.y)^2+(loc.z-symeon.z)^2)/200000) time_to_distance = distsymeon * 200 / shipVelocity display_selection = "symeon" elseif selection == 8 then sinnen = vec3(58665536.000, 29665536.000, 58165536.000) distsinnen = string.format("%.2f", math.sqrt((loc.x-sinnen.x)^2+(loc.y-sinnen.y)^2+(loc.z-sinnen.z)^2)/200000) time_to_distance = distsinnen * 200 / shipVelocity display_selection = "sinnen" elseif selection == 9 then jago = vec3(-94134464.000, 12765536.000, -3634464.000) distjago = string.format("%.2f", math.sqrt((loc.x-jago.x)^2+(loc.y-jago.y)^2+(loc.z-jago.z)^2)/200000) time_to_distance = distjago * 200 / shipVelocity display_selection = "jago" elseif selection == 10 then teoma = vec3(80865536.000, 54665536.000, -934464.000) distteoma = string.format("%.2f", math.sqrt((loc.x-teoma.x)^2+(loc.y-teoma.y)^2+(loc.z-teoma.z)^2)/200000) time_to_distance = distteoma * 200 / shipVelocity display_selection = "teoma" elseif selection == 11 then ion = galaxyReference[0][120] ---uses Atlas functions distion = math.floor(ion:getDistance(loc)/200000) ---uses getDistance functions---- time_to_distance = distion * 200 / shipVelocity display_selection = "ion" elseif selection == 12 then lacobus = vec3(98865536.000, -13534464.000, -934464.000) distlacobus = string.format("%.2f", math.sqrt((loc.x-lacobus.x)^2+(loc.y-lacobus.y)^2+(loc.z-lacobus.z)^2)/200000) time_to_distance = distlacobus * 200 / shipVelocity display_selection = "lacobus" else time_to_distance = sudistance * 200 / shipVelocity display_selection = "none" end shipVelocity = string.format("%.2f", shipVelocity) warpmath = math.floor(math.floor(core.getConstructMass()/ 1000) * sudistance * 0.00025) time_to_distance_min = time_to_distance * 60 time_to_distance_min_sec = time_to_distance_min * 60 time_to_distance = formatTimeWithUnits (time_to_distance_min_sec, 3) html= ([[ <svg class="bootstrap" viewBox="0 0 1000 970" style="width:100%; height:100%; margin-top:-5em;"> <circle cx="500" cy="500" r="400" stroke="#5a79c8" stroke-width="5" transform=""></circle> <circle cx="500" cy="500" r="350" stroke="#5a79c8" stroke-width="5" transform="" stroke-opacity="0.2"></circle> <circle cx="500" cy="500" r="300" stroke="#5a79c8" stroke-width="5" transform=""></circle> <circle cx="500" cy="500" r="250" stroke="#5a79c8" stroke-width="5" transform="" stroke-opacity="0.2"></circle> <circle cx="500" cy="500" r="200" stroke="#5a79c8" stroke-width="5" transform=""></circle> <circle cx="500" cy="500" r="150" stroke="#5a79c8" stroke-width="5" transform="" stroke-opacity="0.2"></circle> <circle cx="500" cy="500" r="100" stroke="#5a79c8" fill="#5fb7cf" stroke-width="2" transform="" fill-opacity="0.2"></circle> <circle cx="500" cy="500" r="50" stroke="#5a79c8" stroke-width="2" transform="" stroke-opacity="0.2"></circle> <circle cx="500" cy="500" r="20" stroke="#ffdf91" stroke-width="1.5" transform=""></circle> <text x="525" y="504" fill="#ffdf91"font-size="15">Helios</text> <circle cx="-0.00" cy="0" r="10" stroke="black" stroke-width="1" fill="#61a7ff" transform="translate(500,500)"></circle> <text x="-95.00" y="25" transform="translate(500,480)" fill="#61a7ff" font-size="20">Alioth</text> <circle cx="5.41" cy="244.09" r="10" stroke="black" stroke-width="1" fill="#e1e1e1" transform="translate(500,500)"></circle> <text x="-30" y="270" transform="translate(480,480)" fill="#e1e1e1" font-size="20">Ion</text> <circle cx="35.41" cy="214.09" r="10" stroke="black" stroke-width="1" fill="#7c90ff" transform="translate(500,500)"></circle> <text x="-62" y="239" transform="translate(500,480)" fill="#7c90ff" font-size="20">Symeon</text> <circle cx="202.16" cy="-136.66" r="10" stroke="black" stroke-width="1" fill="#bddeff" transform="translate(500,500)"></circle> <text x="112" y="-109" transform="translate(500,480)" fill="#bddeff" font-size="20">Teoma</text> <circle cx="-33.09" cy="-139.41" r="10" stroke="black" stroke-width="1" fill="#cfffdd" transform="translate(500,500)"></circle> <text x="-139" y="-112" transform="translate(500,480)" fill="#cfffdd" font-size="20">Talemai</text> <circle cx="-108.84" cy="-56.41" r="10" stroke="black" stroke-width="1" fill="#c6a668" transform="translate(500,500)"></circle> <text x="-164" y="-30" transform="translate(500,480)" fill="#c6a668" font-size="20">Feli</text> <circle cx="-235.34" cy="-31.91" r="10" stroke="black" stroke-width="1" fill="#8dc0e5" transform="translate(500,500)"></circle> <text x="-297" y="-5" transform="translate(500,480)" fill="#8dc0e5" font-size="20">Jago</text> <circle cx="43.66" cy="-56.66" r="10" stroke="black" stroke-width="1" fill="#8a9fff" transform="translate(500,500)"></circle> <text x="-38" y="-28" transform="translate(500,480)" fill="#8a9fff" font-size="20">Madis</text> <circle cx="72.91" cy="-27.16" r="10" stroke="black" stroke-width="1" fill="#ffaf6a" transform="translate(500,500)"></circle> <text x="88" y="-7" transform="translate(500,485)" fill="#ffaf6a" font-size="20">Thades</text> <circle cx="247.16" cy="33.84" r="10" stroke="black" stroke-width="1" fill="#cacaca" transform="translate(500,500)"></circle> <text x="263" y="62" transform="translate(500,480)" fill="#cacaca" font-size="20">Lacobus</text> <circle cx="-108.84" cy="-56.41" r="10" stroke="black" stroke-width="1" fill="#c6a668" transform="translate(500,500)"></circle> <text x="-165.84" y="-30.41" transform="translate(500,480)" fill="#c6a668" font-size="20">Feli</text> <circle cx="131.91" cy="-67.91" r="10" stroke="black" stroke-width="1" fill="#ffac71" transform="translate(500,500)"></circle> <text x="81" y="-40" transform="translate(475,480)" fill="#ffac71" font-size="20">Sicari</text> <circle cx="146.66" cy="-74.16" r="10" stroke="black" stroke-width="1" fill="#ffa775" transform="translate(500,500)"></circle> <text x="146" y="-46" transform="translate(515,480)" fill="#ffa775" font-size="20">Sinnen</text> <line stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_1" y2="]]..destY..[[" x2="]]..destX..[[" y1="]]..locY..[[" x1="]]..locX..[[" transform="translate(500,500)" stroke-width="5" stroke="#ffb400" fill="none"/> <circle cx="]]..locX..[[" cy="]]..locY..[[" r="3" stroke="black" stroke-width="1" fill="limegreen" transform="translate(500,500)"></circle> <text x="]]..locX..[[" y="]]..locY..[[" transform="translate(500,500)" fill="limegreen" font-size= "4.5vh" font-weight= "bold">&nbsp;&nbsp;&nbsp;&nbsp;SHIP POSITION</text> </svg> <svg class="bootstrap" viewBox="0 0 1024 612" style="width:100%; height:100%"> <g> <title>Layer 1</title> <g id="svg_12"> <rect rx="10" id="svg_1" height="50" width="230" y="30" x="15" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_3" height="50" width="230" y="105" x="15" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_7" height="50" width="230" y="180" x="15" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_9" height="50" width="230" y="255" x="15" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_10" height="50" width="230" y="330" x="15" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_11" height="50" width="230" y="405" x="15" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> </g> <g id="svg_24"> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_8" y="75" x="40" stroke-width="0" fill="black">Alioth :]]..distalioth..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_14" y="175" x="40" stroke-width="0" fill="black">Madis :]]..distmadis..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_17" y="275" x="40" stroke-width="0" fill="black">Thades :]]..distthades..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_20" y="372" x="40" stroke-width="0" fill="black">Talemai :]]..disttalemai..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_23" y="469" x="40" stroke-width="0" fill="black">Feli :]]..distfeli..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_26" y="568" x="40" stroke-width="0" fill="black">Sicari :]]..distsicari..[[ SU</text> </g> <g id="svg_40"> <g id="svg_39"> <rect rx="10" id="svg_33" height="50" width="230" y="30" x="780" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_34" height="50" width="230" y="105" x="780" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_35" height="50" width="230" y="180" x="780" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_36" height="50" width="230" y="255" x="780" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_37" height="50" width="230" y="330" x="780" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> <rect rx="10" id="svg_38" height="50" width="230" y="405" x="780" stroke-width="4" stroke="#aee4ed" fill="#5fb7cf"/> </g> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_25" y="75" x="1007.163642" stroke-width="0" fill="black">Symeon :]]..distsymeon..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_27" y="175" x="1007.163642" stroke-width="0" fill="black">Sinnen :]]..distsinnen..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_28" y="275" x="1007.163642" stroke-width="0" fill="black">Jago :]]..distjago..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_30" y="372" x="1007.163642" stroke-width="0" fill="black">Teoma :]]..distteoma..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_31" y="469" x="1007.163642" stroke-width="0" fill="black">Ion :]]..distion..[[ SU</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_32" y="568" x="1007.163642" stroke-width="0" fill="black">Lacobus :]]..distlacobus..[[ SU</text> </g> </g> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_32" y="700" x="20" stroke-width="0" fill="#976eb0">Est. Warp Cost: ]]..warpmath..[[</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_32" y="750" x="20" stroke-width="0" fill="#976eb0">Construct Weight: ]]..math.floor(core.getConstructMass()/ 1000)..[[ tons</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_32" y="700" x="500" stroke-width="0" fill="#976eb0">TTD: ]]..time_to_distance..[[ </text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_32" y="750" x="500" stroke-width="0" fill="#976eb0">VELOC: ]]..shipVelocity..[[ km/h</text> <text stroke="null" transform="matrix(0.7907331239400577,0,0,0.7600725676692406,3.135703637258853,5.731969683147472) " xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="30" id="svg_32" y="700" x="900" stroke-width="0" fill="#976eb0">DEST: ]]..display_selection..[[ </text> </svg> ]]) screen.setHTML(html) --screen2.setHTML(html) end unit.setTimer("spacemap",.08)
  7. Only 200k with a Free Blueprint! Available in District 3 Alioth
  8. Is there somewhere I can find the max number of input and output plugs for a given item whether it be a container hub, container, construction equipment, assembly array, transfer unit, etc? Thank you for your help! Resource
×
×
  • Create New...