IAmKane Posted October 21, 2020 Share Posted October 21, 2020 Hello all. I've noticed there doesn't seem to be any kind of script out there for a Radar Plot yet so I decided to take a crack at it. Unsurprisingly I immediately ran into issues. I have a bunch of questions, but I'll start off with what I hope is a simple one: In this section of code I'm using getEntries() to get all the available IDs then looping through the IDs to get data for each contact. (I don't actually plan on using all this data, I just want to test and see what I can get to work and pare it down from there.) I'm getting the contact ID's to pull in in the debug but I'm getting errors reading any kind of data about those IDs. Contacts = Radar.getEntries() --list of construct IDs if #Contacts >= 1 then for i,v in ipairs(Contacts) do local cID = Contacts[i] -- construct ID for 'i' local cName = Radar.getConstructName(cID) --name of detected construct [id][name] local pID = Radar.getConstructOwner(cID) --player ID # of construct owner [id][player] local cOwner = database.getPlayer(pID) --resolve player name from player ID local cSize = vec3(Radar.getConstructSize(cID)) --size of the construct bounding box [id][x,y,z] local cType = Radar.getConstructType(cID) --type of construct [id][static/dynamic] local cPos = vec3(Radar.getConstructPos(cID)) --local coordinates of the construct [id][x,y,z] local cVel = vec3(Radar.getConstructVelocity(cID)) --local speed relative to absolute space [id][x,y,z] local cSpeed = cVel:len() --rendered speed based on cVel info above local cAcc = vec3(Radar.getConstructAcceleration(cID)) --local accel relative to absolute space [id][x,y,z] local cWorldPos = vec3(Radar.getConstructWorldPos(cID)) --world coordinates of the construct [id][x,y,z] local cWorldVel = vec3(Radar.getConstructWorldVelocity(cID)) --world speed relative to absolute space [id][x,y,z] local cWorldAcc = vec3(Radar.getConstructWorldAcceleration(cID)) --world accel relative to absolute space [id][x,y,z] It's yelling at me for calling getConstructOwner() saying it's a nil variable. Testing all of the other variables relating to position and speed for the contacts yields the same error. Am I making a mistake in how I am calling them? I checked the API and it looks right to me but then I've been wrong before. As a reference here is the whole code in its current state: Spoiler --RADAR DISPLAY INIT-- RadScreenButtons = {} RadScreenMouseX = 0 RadScreenMouseY = 0 RadScreenMouseDown = false RadScreenButtonSelected = 0 local scanX = 0 local scanY = 0 local t = 0 --GLOBAL VARS-- ThresholdVel = 200.0 --only show contacts above this velocity in m/s SearchType = "Dynamic" --only show constructs of this type: Static/Dynamic/Both RadarMode = "Atmospheric" --type of radar being queried: Atmospheric/Space rcolor = "limegreen" --default color is for atmospheric mode RadarRange = 0.0 --default scan range for radar, set to '0.0' to use max range --Buttons for Velocity Up/Down, Search Type, Mode, Range Up/Down for i = 1,1 do --velocity up local button = {id = ("b"..1), enabled=true, td="<td>", top=83/100, bottom=87/100, left=1/100, right=28/100}--~ height="50" width="250" y="850" x="15" table.insert(RadScreenButtons, button) end for i = 2,2 do --velocity down local button = {id = ("b"..2), enabled=true, td="<td>", top=89/100, bottom=93/100, left=1/100, right=30/100}--~ height="50" width="250" y="910" x="15" table.insert(RadScreenButtons, button) end for i = 3,3 do --switch search type (static/dynamic/both) local button = {id = ("b"..3), enabled=true, td="<td>", top=94/100, bottom=98/100, left=1/100, right=28/100}--~ height="50" width="250" y="970" x="15" table.insert(RadScreenButtons, button) end for i = 4,4 do --toggle mode (atmo/space) local button = {id = ("b"..4), enabled=true, td="<td>", top=83/100, bottom=87/100, left=75/100, right=100/100}--~ height="50" width="250" y="850" x="760" table.insert(RadScreenButtons, button) end for i = 5,5 do --range increase local button = {id = ("b"..5), enabled=true, td="<td>", top=89/100, bottom=93/100, left=75/100, right=100/100}--~ height="50" width="250" y="910" x="760" table.insert(RadScreenButtons, button) end for i = 6,6 do --range decrease local button = {id = ("b"..6), enabled=true, td="<td>", top=94/100, bottom=98/100, left=75/100, right=100/100}--~ height="50" width="250" y="970" x="760" table.insert(RadScreenButtons, button) end for i = 7,7 do local button = {id = ("b"..7), enabled=true, td="<td>", top=90/100, bottom=100/100, left=40/100, right=60/100} table.insert(RadScreenButtons, button) end function evaluateButtons() local selected = 0 if #RadScreenButtons >= 1 the for i, button in ipairs(RadScreenButtons) do if button.left < RadScreenMouseX and RadScreenMouseX < button.right and button.top < RadScreenMouseY and RadScreenMouseY < button.bottom then if RadScreenMouseDown and RadScreenButtons == i then end selected = i end if not button.enabled then end end end return selected end function onButtonDown(buttonNo) local button = RadScreenButtons[buttonNo] if not button or not button.enabled then return end end function onButtonUp(buttonNo) local button = RadScreenButtons[buttonNo] if not button or not button.enabled then return end function onClick(buttonNo) local button = RadScreenButtons[buttonNo] if not button or not button.enabled then return end end if buttonNo == 1 then --increase velocity search threshold ThresholdVel = ThresholdVel + 25.0 elseif buttonNo == 2 then --decrease velocity search threshold ThresholdVel = ThresholdVel - 25.0 elseif buttonNo == 3 then --toggle construct search type if SearchType == "Dynamic" then SearchType = "Both" elseif SearchType == "Both" then SearchType = "Static" elseif SearchType == "Both" then SearchType = "Dynamic" end elseif buttonNo == 4 then --toggle radar search mode if RadarMode == "Atmospheric" then RadarMode = "Space" elseif RadarMode == "Space" then RadarMode = "Atmospheric" end elseif buttonNo == 5 then --increase radar search range RadarRange = RadarRange + 100.0 elseif buttonNo == 6 then --decrease radar search range RadarRange = RadarRange - 100.0 elseif buttonNo == 7 then unit.exit() end end function updateScreen() if t = 360 then t = 0 else t = t + 1 end if RadarMode == "Atmpspheric" then rcolor = "limegreen" elseif RadarMode == "Space" then rcolor = "aqua" end scanX = math.floor(400 * math.cos(t*(3.14/180))) scanY = math.floor(400 * math.sin(t*(3.14/180))) maxRange = Radar.getRange() if RadarRange = 0.0 then scanRange = maxRange elseif RadarRange > maxRange then scanRange = maxRange RadarRange = maxRange elseif RadarRange > 0.0 then scanRange = RadarRange end html= ([[ <svg class="bootstrap" viewBox="0 0 1024 1024" style="width:100%; height:100%"> <circle cx="500" cy="500" r="400" stroke="]]..rcolor..[[" stroke-width="3" transform=""></circle> <circle cx="500" cy="500" r="350" stroke="]]..rcolor..[[" stroke-width="3" transform="" stroke-opacity="0.2"></circle> <circle cx="500" cy="500" r="300" stroke="]]..rcolor..[[" stroke-width="3" transform=""></circle> <circle cx="500" cy="500" r="250" stroke="]]..rcolor..[[" stroke-width="3" transform="" stroke-opacity="0.2"></circle> <circle cx="500" cy="500" r="200" stroke="]]..rcolor..[[" stroke-width="3" transform=""></circle> <circle cx="500" cy="500" r="150" stroke="]]..rcolor..[[" stroke-width="3" transform="" stroke-opacity="0.2"></circle> <circle cx="500" cy="500" r="100" stroke="]]..rcolor..[[" stroke-width="3" transform=""></circle> <circle cx="500" cy="500" r="50" stroke="]]..rcolor..[[" stroke-width="3" transform="" stroke-opacity="0.2"></circle> <circle cx="500" cy="500" r="20" stroke="]]..rcolor..[[" stroke-width="3" transform=""></circle> <circle cx="-0.00" cy="0" r="3" stroke="]]..rcolor..[[" stroke-width="1" fill="]]..rcolor..[[" transform="translate(500,500)"></circle> <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="20" id="svg_8" y="1150" x="55" stroke-width="0" fill="]]..rcolor..[[">Increase Vel.</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="20" id="svg_14" y="1230" x="55" stroke-width="0" fill="]]..rcolor..[[">Decrease Vel.</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="20" id="svg_17" y="1310" x="55" stroke-width="0" fill="]]..rcolor..[[">Search Type</text> <rect rx="10" id="svg_2" height="50" width="250" y="850" x="15" stroke-width="5" stroke="]]..rcolor..[[" fill="none"/> <rect rx="10" id="svg_3" height="50" width="250" y="910" x="15" stroke-width="5" stroke="]]..rcolor..[[" fill="none"/> <rect rx="10" id="svg_4" height="50" width="250" y="970" x="15" stroke-width="5" stroke="]]..rcolor..[[" fill="none"/> <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="20" id="svg_25" y="1150" x="997.163642" stroke-width="0" fill="]]..rcolor..[[">Radar Mode</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="20" id="svg_27" y="1230" x="997.163642" stroke-width="0" fill="]]..rcolor..[[">Increase Range</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="20" id="svg_28" y="1310" x="997.163642" stroke-width="0" fill="]]..rcolor..[[">Decrease Range</text> <rect rx="10" id="svg_5" height="50" width="250" y="850" x="760" stroke-width="5" stroke="]]..rcolor..[[" fill="none"/> <rect rx="10" id="svg_6" height="50" width="250" y="910" x="760" stroke-width="5" stroke="]]..rcolor..[[" fill="none"/> <rect rx="10" id="svg_7" height="50" width="250" y="970" x="760" stroke-width="5" stroke="]]..rcolor..[[" fill="none"/> <line stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_1" y2="]]..scanY..[[" x2="]]..scanX..[[" y1="0" x1="0" transform="translate(500,500)" stroke-width="3" stroke="]]..rcolor..[[" fill="none"/> <text x="-470" y="-420" transform="translate(500,500)"fill="]]..rcolor..[[" font-size= "9vh" font-weight= "bold">TARGET VELOCITY:"]]..ThresholdVel..[["m/s</text> <text x="-420" y="-450" transform="translate(500,500)"fill="]]..rcolor..[[" font-size= "9vh" font-weight= "bold">RADAR RANGE:"]]..scanRange..[["m</text> <text x="-410" y="-480" transform="translate(500,500)"fill="]]..rcolor..[[" font-size= "9vh" font-weight= "bold">RADAR MODE:"]]..RadarMode..[["</text> ]]) Contacts = Radar.getEntries() --list of construct IDs if #Contacts >= 1 then for i,v in ipairs(Contacts) do local cID = Contacts[i] -- construct ID for 'i' local cName = Radar.getConstructName(cID) --name of detected construct [id][name] local pID = Radar.getConstructOwner(cID) --player ID # of construct owner [id][player] local cOwner = database.getPlayer(pID) --resolve player name from player ID local cSize = vec3(Radar.getConstructSize(cID)) --size of the construct bounding box [id][x,y,z] local cType = Radar.getConstructType(cID) --type of construct [id][static/dynamic] local cPos = vec3(Radar.getConstructPos(cID)) --local coordinates of the construct [id][x,y,z] local cVel = vec3(Radar.getConstructVelocity(cID)) --local speed relative to absolute space [id][x,y,z] local cSpeed = cVel:len() --rendered speed based on cVel info above local cAcc = vec3(Radar.getConstructAcceleration(cID)) --local accel relative to absolute space [id][x,y,z] local cWorldPos = vec3(Radar.getConstructWorldPos(cID)) --world coordinates of the construct [id][x,y,z] local cWorldVel = vec3(Radar.getConstructWorldVelocity(cID)) --world speed relative to absolute space [id][x,y,z] local cWorldAcc = vec3(Radar.getConstructWorldAcceleration(cID)) --world accel relative to absolute space [id][x,y,z] --~ rendered coords: if SearchType == "Both" then if cSpeed >= ThresholdVel then local newcoordx = (cPos.x/scanRange)*400 local newcoordy = (cPos.y/scanRange)*400 html = html..[[<circle cx="]]..newcoordx..[[" cy="]]..newcoordy..[[" r="5" stroke="black" stroke-width="1" fill="]]..rcolor..[[" transform="translate(500,500)"></circle> <text x="]]..newcoordx..[[" y="]]..newcoordy..[[" transform="translate(500,500)"fill="]]..rcolor..[[" font-size= "4.5vh" font-weight= "bold">"]]..cOwner..[["</text>]] end elseif SearchType = cType then if SearchType == "Dynamic" then if cSpeed >= ThresholdVel then local newcoordx = (cPos.x/scanRange)*400 local newcoordy = (cPos.y/scanRange)*400 html = html..[[<circle cx="]]..newcoordx..[[" cy="]]..newcoordy..[[" r="5" stroke="black" stroke-width="1" fill="]]..rcolor..[[" transform="translate(500,500)"></circle> <text x="]]..newcoordx..[[" y="]]..newcoordy..[[" transform="translate(500,500)"fill="]]..rcolor..[[" font-size= "4.5vh" font-weight= "bold">"]]..cOwner..[["</text>]] end elseif SearchType == "Static" then local newcoordx = (cPos.x/scanRange)*400 local newcoordy = (cPos.y/scanRange)*400 html = html..[[<circle cx="]]..newcoordx..[[" cy="]]..newcoordy..[[" r="5" stroke="black" stroke-width="1" fill="]]..rcolor..[[" transform="translate(500,500)"></circle> <text x="]]..newcoordx..[[" y="]]..newcoordy..[[" transform="translate(500,500)"fill="]]..rcolor..[[" font-size= "4.5vh" font-weight= "bold">"]]..cOwner..[["</text>]] end end end end html = html..[[ </svg>]] screen.setHTML(html) end unit.setTimer("radardisplay",.08) Link to comment Share on other sites More sharing options...
IAmKane Posted October 24, 2020 Author Share Posted October 24, 2020 UPDATE: Apparently you can't use the radar to resolve the position of a contact unless it has a transponder, which is disappointing. Hopefully this changes later because otherwise this is rather useless. Link to comment Share on other sites More sharing options...
JayleBreak Posted October 27, 2020 Share Posted October 27, 2020 The removed the ability to get position information from the space radar as NQ felt that scripting would diminish game play. They added `getEntries()` recently I guess because 1) Its consensual, and 2) promotes gameplay(?). BTW: for i,v in ipairs(Contacts) do local cID = Contacts[i] -- construct ID for 'i' Can be simplified to: for i,cID in ipairs(Contacts) do Link to comment Share on other sites More sharing options...
IAmKane Posted October 27, 2020 Author Share Posted October 27, 2020 3 hours ago, JayleBreak said: The removed the ability to get position information from the space radar as NQ felt that scripting would diminish game play. They added `getEntries()` recently I guess because 1) Its consensual, and 2) promotes gameplay(?). BTW: for i,v in ipairs(Contacts) do local cID = Contacts[i] -- construct ID for 'i' Can be simplified to: for i,cID in ipairs(Contacts) do Thank you sir! Old table habits, I'm still learning Lua. I hope they rethink that decision in the future because the logic doesn't compute. Link to comment Share on other sites More sharing options...
SGCamera_Beta Posted October 27, 2020 Share Posted October 27, 2020 I don't see them changing that decision, because being able to get the position of enemy ships would allow you to write combat autopilots that would be vastly superior to player pilots. NQ is trying very hard to make the game not be dependent on lua, so I doubt they will add a feature that makes it mandatory in order to be competitive. Link to comment Share on other sites More sharing options...
IAmKane Posted October 27, 2020 Author Share Posted October 27, 2020 54 minutes ago, SGCam said: I don't see them changing that decision, because being able to get the position of enemy ships would allow you to write combat autopilots that would be vastly superior to player pilots. NQ is trying very hard to make the game not be dependent on lua, so I doubt they will add a feature that makes it mandatory in order to be competitive. In that case they should really change the element titles to something more appropriate and adjust the API library where this subject is concerned. At the moment it's quite misleading since it implies capability that doesn't actually exist. Link to comment Share on other sites More sharing options...
SeM Posted October 29, 2020 Share Posted October 29, 2020 On 10/27/2020 at 8:42 PM, SGCam said: I don't see them changing that decision, because being able to get the position of enemy ships would allow you to write combat autopilots that would be vastly superior to player pilots. NQ is trying very hard to make the game not be dependent on lua, so I doubt they will add a feature that makes it mandatory in order to be competitive. Maybe it is worth removing the possibility of creating individual ships? Because someone can build a better one, so that he will have an advantage over others ) Link to comment Share on other sites More sharing options...
SGCamera_Beta Posted October 29, 2020 Share Posted October 29, 2020 1 hour ago, SeM said: Maybe it is worth removing the possibility of creating individual ships? Because someone can build a better one, so that he will have an advantage over others ) Straw man aside, there is a huge difference between building ships and writing programs. Pretty much anyone can build a decent ship if they work at it, and learning how is a core part of the game's learning curve. People expect building things to be part of a sandbox game, and in general people find that building things they can see and use and show off is fun. Knowing how to program is a much rarer skill and frankly isn't fun to most people; NQ has said that they do NOT want to make programming a mandatory thing, since it reduces the interested players for an already niche game. Link to comment Share on other sites More sharing options...
SeM Posted October 29, 2020 Share Posted October 29, 2020 38 minutes ago, SGCam said: if they work at it, and learning key phrase ) someone builds ships better, someone writes programs. they can exchange what they know how to do. using the market. everything is like in life. Isn't that what NQ wanted? Then it's easier to remove the radar from the game altogether, what's the point of using it? ) upd: lua cannot identify, cannot take a target, cannot shoot, cannot ... what can lua be more than a human? ) Link to comment Share on other sites More sharing options...
IAmKane Posted November 2, 2020 Author Share Posted November 2, 2020 I mean really all I wanted was an updated minimap that was more visible, customizable and user friendly than the cluttered tiny mess we've got stuck in the corner. I'm not trying to build bloody SkyNet, just add something that's in basically every first-person game by default. Link to comment Share on other sites More sharing options...
Guest doritto Posted November 17, 2020 Share Posted November 17, 2020 is anyone else only getting "unreachable" for pretty much every getConstruct* function? how do you work with this? Link to comment Share on other sites More sharing options...
Pathalogical Functor Posted December 14, 2020 Share Posted December 14, 2020 On 10/29/2020 at 6:47 PM, SGCam said: Straw man aside, there is a huge difference between building ships and writing programs. I don't agree with this. NQ want players to specialize. I know I'll never be able to build a really beautiful large ship, but if I have the quanta I can buy one off the market from a player who took the time learning voxelmancy and spent hours getting every curve perfect. I might not be much good at PvP, but if I have the quanta I can always hire some mercenaries to fight on my behalf. Why not do the same for programmers writing Lua scripts? Dumbing the game down by nerfing or removing specializations which are "too hard for the average player" just seems insane. Also, I'd like to make the point that writing human-level AI is really, really hard. If the PvP mechanics are so simple that a 1000 line Lua script can perform better than an experienced human then those mechanics are awful and need to be reworked. DU isn't a first-person shooter which can be won by a simple aimbot. Just as in EVE, the outcome of an engagement should be largely decided before the first shot is even fired. Link to comment Share on other sites More sharing options...
SGCamera_Beta Posted December 14, 2020 Share Posted December 14, 2020 1 hour ago, Pathalogical Functor said: I don't agree with this. NQ want players to specialize. I know I'll never be able to build a really beautiful large ship, but if I have the quanta I can buy one off the market from a player who took the time learning voxelmancy and spent hours getting every curve perfect. I might not be much good at PvP, but if I have the quanta I can always hire some mercenaries to fight on my behalf. Why not do the same for programmers writing Lua scripts? Dumbing the game down by nerfing or removing specializations which are "too hard for the average player" just seems insane. I am 100% in favor of letting scripting do nice things, whether its hard to write or not. I was simply pointing out that letting scripts access things that would allow PvP autopilots is a bad idea. There is a reason NASA uses MechJeb - in a full 6 DoF environment, computers are better than humans. They can take all the variables and compute an optimal course and orientation to maximize weapon time on target, minimize enemy hit chance, or even just have a perfect intercept. That may be realistic, but it doesn't make for a fun game. The issue isn't that PvP mechanics are too simple, its that Newtonian Physics is a solved problem. You would be surprised at how much you can do in 1000 lines of Lua script. I agree that the outcome of the engagement should typically be decided ahead of time - logistics, how much gun your side brought, how good your ships are, etc. But in an otherwise equal 1v1 engagement, the ship with the PvP autopilot will win 9 times out of 10. And since the script would increase the combat effectiveness of the ship so much, allowing them basically makes them mandatory. Link to comment Share on other sites More sharing options...
Pathalogical Functor Posted December 14, 2020 Share Posted December 14, 2020 What works for a NASA docking maneuver (cooperative, two-body problem in a controlled environment) won't work quite so well in a multi-ship PvP engagement where there are far more tactical decisions to be made. If you're just ganking an AFK freighter then sure, the autopilot will perform a nice intercept burn and drop you at your guns' optimal range then automatically bring you up along side the wreck so you can loot it. Now try designing a user interface which lets you tell your autopilot, "Get in weapons range of ships A and B, while avoiding the short-range weapons on C and maintaining at least 0.05 rad/s angular velocity around D to avoid getting hit by its heavy guns", then try using that interface in the middle of battle. Anyway, as long as engine control is possible people will still end up automating those kind of intercept maneuvers. It will just require clicking in a user interface to tell the AI what direction the target is in (and possibly its range, if that isn't available through the API). There's no Lua API for the ore scanner either, but people still managed to write scripts to make quadrilateration of ore nodes trivial. WylieFox and GraXXoR 2 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now