├── Code ├── system_actionStart_option9 ├── system_actionStart_option2 ├── system_actionStart_option1 ├── unit_start1 ├── system_actionStart_option3 └── unit_start2 ├── README.md └── OreFinder LUA Code /Code/system_actionStart_option9: -------------------------------------------------------------------------------- 1 | measureCount=0 2 | system.print("system restarted") 3 | system.print("submit a first measurement") 4 | -------------------------------------------------------------------------------- /Code/system_actionStart_option2: -------------------------------------------------------------------------------- 1 | current_di=current_di+1 2 | if current_di>#distance_list then 3 | current_di=1 4 | end 5 | 6 | hudHTML=[[ 7 | 8 | ]] 9 | 10 | cx=button_r 11 | cy=button_r 12 | for index,d in pairs(distance_list) do 13 | if d==distance_list[current_di] then 14 | stroke_color="#CCBB44" 15 | else 16 | stroke_color="white" 17 | end 18 | hudHTML=hudHTML..[[ 19 | 20 | ]]..d..[[ 21 | ]] 22 | cx=cx+2*button_r+dx 23 | end 24 | 25 | hudHTML=hudHTML..[[ 26 | 27 | ]] 28 | 29 | system.setScreen(hudHTML) 30 | -------------------------------------------------------------------------------- /Code/system_actionStart_option1: -------------------------------------------------------------------------------- 1 | current_di=current_di-1 2 | if current_di==0 then 3 | current_di=#distance_list 4 | end 5 | 6 | hudHTML=[[ 7 | 8 | ]] 9 | 10 | cx=button_r 11 | cy=button_r 12 | for index,d in pairs(distance_list) do 13 | if d==distance_list[current_di] then 14 | stroke_color="#CCBB44" 15 | else 16 | stroke_color="white" 17 | end 18 | hudHTML=hudHTML..[[ 19 | 20 | ]]..d..[[ 21 | ]] 22 | cx=cx+2*button_r+dx 23 | end 24 | 25 | hudHTML=hudHTML..[[ 26 | 27 | ]] 28 | 29 | system.setScreen(hudHTML) 30 | -------------------------------------------------------------------------------- /Code/unit_start1: -------------------------------------------------------------------------------- 1 | --[[ 2 | Version 2.0.0 3 | ]] 4 | 5 | distance_list={400,375,350,325,300,275,250,225,200,175,150,125,100,75,50,45,40,35,30,25,20,15,10,5} 6 | button_r=25 7 | dx=5 8 | current_di=1 9 | margin=0.10 10 | 11 | hudHTML=[[ 12 | 13 | ]] 14 | 15 | cx=button_r 16 | cy=button_r 17 | for index,d in pairs(distance_list) do 18 | if d==distance_list[current_di] then 19 | stroke_color="#CCBB44" 20 | else 21 | stroke_color="white" 22 | end 23 | hudHTML=hudHTML..[[ 24 | 25 | ]]..d..[[ 26 | ]] 27 | cx=cx+2*button_r+dx 28 | end 29 | 30 | hudHTML=hudHTML..[[ 31 | 32 | ]] 33 | 34 | 35 | measureCount=0 36 | 37 | system.print("Welcome to SimplePiMans Ore Finder") 38 | system.print("Alt+1 moves the selected measurement left") 39 | system.print("Alt+2 moves the selected measurement right") 40 | system.print("Alt+3 locks in the measurement") 41 | system.print("Alt+9 resets the system allowing for a fresh search") 42 | system.print("Every masurement after the 2nd will give a ::pos tag") 43 | system.print("For the best guess of where the ore is located") 44 | system.print("You can right click to set as a destination") 45 | 46 | system.setScreen(hudHTML) 47 | system.showScreen(1) 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Status Update 2 | I just wanted to add a note up here to let anybody who happens by here know that I've stopped playing DU so am no longer supporting this code. With that said everybody is free to modify and use it as you wish. :-) 3 | 4 | # DU-LUA-Ore-Finder 5 | This is a LUA script that creates a HUD on your character which allows you to triangulate ore locations while mining 6 | 7 | It works by creating a series of buttons along the top of your screen. Each of which indicates a measurement from your scanning device. 8 | These measurements coincide with the horizontal lines on your scanner. When you have a reading that is on one of those lines you 9 | then use alt+1 or alt+2 to move the highlighted measurment left/right (it wraps around) and once your measurement is highlighted 10 | you use alt+3 to lock it in. 11 | 12 | Once you have locked in 3 or more measurements it prints out a pos:: marker in the LUA chat that you can right click to set as a marker. 13 | This is it's current best guess at where the ore is. You keep feeding it measurements until it gets you close enough for the directional 14 | scanner. 15 | 16 | The search algorithm is 2-fold. 17 | First, it creates a bounding box using your location and measurements to define a limit to where the ore can be. It then does a quick search 18 | within that region for the spot that best matches your measurements. That is the point it directs you to next. It allows for a 10% margin of error 19 | in your measurements. It will also give an error message letting you know if it is no longer able to define a search region, at which point you start over 20 | and feed it different measurements in an attempt to get a vaild result. 21 | 22 | Finally, once you have found the ore, you can use alt+9 to reset the search so you can start finding a new ore. 23 | 24 | # Installation 25 | 26 | 1) open the code and copy it to your clipboard 27 | 2) in game, right click on the programming board, go to advanced and then "paste LUA config from clipboard" 28 | 3) this should load the code into the programming board, you know it was done correctly if circles appear at the top of your screen when activated 29 | 4) Information is given through the LUA chat, this can be accessed by hitting ENTER and selecting the LUA tab in the chat window 30 | 5) there are instructions included when you first start the program 31 | 32 | # Tutorials 33 | 34 | Below is a link to a tutorial video I made that also walks through the code explaining how it works 35 | 36 | https://www.youtube.com/watch?v=3jPoMpvkLp0&feature=youtu.be 37 | 38 | Below is a link to a tutorial that explains how to customize various parts of the script 39 | 40 | https://youtu.be/lQ0f-HiWKSo 41 | -------------------------------------------------------------------------------- /Code/system_actionStart_option3: -------------------------------------------------------------------------------- 1 | dist=distance_list[current_di] 2 | if dist>=50 then 3 | margin=12.5 4 | else 5 | margin=2.5 6 | end 7 | player_id=unit.getMasterPlayerId() 8 | player_pos=vec3(system.getPlayerWorldPos(player_id)) 9 | player_marker=GetPosString(player_pos.x,player_pos.y,player_pos.z) 10 | system.print("You are here:") 11 | system.print(player_marker) 12 | measureCount=measureCount+1 13 | if measureCount==1 then 14 | measureList={} 15 | table.insert(measureList,{player_pos.x,player_pos.y,player_pos.z,dist^2}) 16 | boxXmin=player_pos.x-(dist+margin) 17 | boxXmax=player_pos.x+(dist+margin) 18 | boxYmin=player_pos.y-(dist+margin) 19 | boxYmax=player_pos.y+(dist+margin) 20 | boxZmin=player_pos.z-(dist+margin) 21 | boxZmax=player_pos.z+(dist+margin) 22 | 23 | start_x=player_pos.x 24 | start_y=player_pos.y 25 | start_z=player_pos.z 26 | start_d2=(1.25*dist)^2 27 | system.print("registered first measurement") 28 | else 29 | table.insert(measureList,{player_pos.x,player_pos.y,player_pos.z,dist^2}) 30 | 31 | dist_from_start=(player_pos.x-start_x)^2+(player_pos.y-start_y)^2+(player_pos.z-start_z)^2 32 | if dist_from_start>start_d2 then 33 | system.print("ERROR: location out of bounds") 34 | system.print("ignoring measure, submit a new one") 35 | system.print("that is within range of first measurement") 36 | measureCount=measureCount-1 37 | else 38 | box2Xmin=player_pos.x-(dist+margin) 39 | box2Xmax=player_pos.x+(dist+margin) 40 | box2Ymin=player_pos.y-(dist+margin) 41 | box2Ymax=player_pos.y+(dist+margin) 42 | box2Zmin=player_pos.z-(dist+margin) 43 | box2Zmax=player_pos.z+(dist+margin) 44 | 45 | boxXmin=math.max(boxXmin,box2Xmin) 46 | boxXmax=math.min(boxXmax,box2Xmax) 47 | boxYmin=math.max(boxYmin,box2Ymin) 48 | boxYmax=math.min(boxYmax,box2Ymax) 49 | boxZmin=math.max(boxZmin,box2Zmin) 50 | boxZmax=math.min(boxZmax,box2Zmax) 51 | 52 | 53 | 54 | if boxXmin>=boxXmax or boxYmin>=boxYmax or boxZmin>=boxZmax then 55 | system.print("ERROR: unable to define bounding box") 56 | system.print("Please start over") 57 | measureCount=0 58 | elseif measureCount>2 then 59 | 60 | system.print("search box updated.") 61 | 62 | chunks=5 63 | xdelta=(boxXmax-boxXmin)/chunks 64 | ydelta=(boxYmax-boxYmin)/chunks 65 | zdelta=(boxZmax-boxZmin)/chunks 66 | 67 | found_marker=0 68 | 69 | minError=1000000000 70 | x=boxXmin 71 | while x<=boxXmax do 72 | y=boxYmin 73 | while y<=boxYmax do 74 | z=boxZmin 75 | while z<=boxZmax do 76 | curError=0 77 | out_of_bounds=0 78 | for i=1,#measureList do 79 | measure=measureList[i] 80 | mx=measure[1] 81 | my=measure[2] 82 | mz=measure[3] 83 | m2=measure[4] 84 | d2=(mx-x)^2+(my-y)^2+(mz-z)^2 85 | e=math.abs(d2-m2) 86 | if e>1.5625*m2 then 87 | out_of_bounds=1 88 | break 89 | end 90 | curError=curError+e 91 | end 92 | if curError=0 and phi or (2*math.pi+phi) 282 | lat= math.pi/2 - math.acos(z/d) 283 | 284 | alt_str=string.format('%.4f',alt) 285 | lon_str=string.format('%.4f',lon*rad2deg) 286 | lat_str=string.format('%.4f',lat*rad2deg) 287 | 288 | pos_str='::pos{0,'..minindex..','..lat_str..','..lon_str..','..alt_str..'}' 289 | return pos_str 290 | end 291 | -------------------------------------------------------------------------------- /OreFinder LUA Code: -------------------------------------------------------------------------------- 1 | {"slots":{"0":{"name":"Screen","type":{"events":[],"methods":[]}},"1":{"name":"slot2","type":{"events":[],"methods":[]}},"2":{"name":"slot3","type":{"events":[],"methods":[]}},"3":{"name":"slot4","type":{"events":[],"methods":[]}},"4":{"name":"slot5","type":{"events":[],"methods":[]}},"5":{"name":"slot6","type":{"events":[],"methods":[]}},"6":{"name":"slot7","type":{"events":[],"methods":[]}},"7":{"name":"slot8","type":{"events":[],"methods":[]}},"8":{"name":"slot9","type":{"events":[],"methods":[]}},"9":{"name":"slot10","type":{"events":[],"methods":[]}},"-1":{"name":"unit","type":{"events":[],"methods":[]}},"-2":{"name":"system","type":{"events":[],"methods":[]}},"-3":{"name":"library","type":{"events":[],"methods":[]}}},"handlers":[{"code":"function GetPosString(px,py,pz)\n Atlas={\n [0] = {\n [1]={\n GM=6930729684,\n bodyId=1,\n center={x=17465536.000,y=22665536.000,z=-34464.000},\n name='Madis',\n planetarySystemId=0,\n radius=44300\n },\n [2]={\n GM=157470826617,\n bodyId=2,\n center={x=-8.000,y=-8.000,z=-126303.000},\n name='Alioth',\n planetarySystemId=0,\n radius=126067.8984\n },\n [3]={\n GM=11776905000,\n bodyId=3,\n center={x=29165536.000,y=10865536.000,z=65536.000},\n name='Thades',\n planetarySystemId=0,\n radius=49000\n },\n [4]={\n GM=14893847582,\n bodyId=4,\n center={x=-13234464.000,y=55765536.000,z=465536.000},\n name='Talemai',\n planetarySystemId=0,\n radius=57450\n },\n [5]={\n GM=16951680000,\n bodyId=5,\n center={x=-43534464.000,y=22565536.000,z=-48934464.000},\n name='Feli',\n planetarySystemId=0,\n radius=41800\n },\n [6]={\n GM=10502547741,\n bodyId=6,\n center={x=52765536.000,y=27165538.000,z=52065535.000},\n name='Sicari',\n planetarySystemId=0,\n radius=51100\n },\n [7]={\n GM=13033380591,\n bodyId=7,\n center={x=58665538.000,y=29665535.000,z=58165535.000},\n name='Sinnen',\n planetarySystemId=0,\n radius=54950\n },\n [8]={\n GM=18477723600,\n bodyId=8,\n center={x=80865538.000,y=54665536.000,z=-934463.940},\n name='Teoma',\n planetarySystemId=0,\n radius=62000\n },\n [9]={\n GM=18606274330,\n bodyId=9,\n center={x=-94134462.000,y=12765534.000,z=-3634464.000},\n name='Jago',\n planetarySystemId=0,\n radius=61590\n },\n [10]={\n GM=78480000,\n bodyId=10,\n center={x=17448118.224,y=22966846.286,z=143078.820},\n name='Madis Moon 1',\n planetarySystemId=0,\n radius=10000\n },\n [11]={\n GM=237402000,\n bodyId=11,\n center={x=17194626.000,y=22243633.880,z=-214962.810},\n name='Madis Moon 2',\n planetarySystemId=0,\n radius=11000\n },\n [12]={\n GM=265046609,\n bodyId=12,\n center={x=17520614.000,y=22184730.000,z=-309989.990},\n name='Madis Moon 3',\n planetarySystemId=0,\n radius=15005\n },\n [21]={\n GM=2118960000,\n bodyId=21,\n center={x=457933.000,y=-1509011.000,z=115524.000},\n name='Alioth Moon 1',\n planetarySystemId=0,\n radius=30000\n },\n [22]={\n GM=2165833514,\n bodyId=22,\n center={x=-1692694.000,y=729681.000,z=-411464.000},\n name='Alioth Moon 4',\n planetarySystemId=0,\n radius=30330\n },\n [26]={\n GM=68234043600,\n bodyId=26,\n center={x=-1404835.000,y=562655.000,z=-285074.000},\n name='Sanctuary',\n planetarySystemId=0,\n radius=83400\n },\n [30]={\n GM=211564034,\n bodyId=30,\n center={x=29214402.000,y=10907080.695,z=433858.200},\n name='Thades Moon 1',\n planetarySystemId=0,\n radius=14002\n },\n [31]={\n GM=264870000,\n bodyId=31,\n center={x=29404193.000,y=10432768.000,z=19554.131},\n name='Thades Moon 2',\n planetarySystemId=0,\n radius=15000\n },\n [40]={\n GM=141264000,\n bodyId=40,\n center={x=-13503090.000,y=55594325.000,z=769838.640},\n name='Talemai Moon 2',\n planetarySystemId=0,\n radius=12000\n },\n [41]={\n GM=106830900,\n bodyId=41,\n center={x=-12800515.000,y=55700259.000,z=325207.840},\n name='Talemai Moon 3',\n planetarySystemId=0,\n radius=11000\n },\n [42]={\n GM=264870000,\n bodyId=42,\n center={x=-13058408.000,y=55781856.000,z=740177.760},\n name='Talemai Moon 1',\n planetarySystemId=0,\n radius=15000\n },\n [50]={\n GM=499917600,\n bodyId=50,\n center={x=-43902841.780,y=22261034.700,z=-48862386.000},\n name='Feli Moon 1',\n planetarySystemId=0,\n radius=14000\n },\n [70]={\n GM=396912600,\n bodyId=70,\n center={x=58969616.000,y=29797945.000,z=57969449.000},\n name='Sinnen Moon 1',\n planetarySystemId=0,\n radius=17000\n },\n [100]={\n GM=13975172474,\n bodyId=100,\n center={x=98865536.000,y=-13534464.000,z=-934461.990},\n name='Lacobus',\n planetarySystemId=0,\n radius=55650\n },\n [101]={\n GM=264870000,\n bodyId=101,\n center={x=98905288.170,y=-13950921.100,z=-647589.530},\n name='Lacobus Moon 3',\n planetarySystemId=0,\n radius=15000\n },\n [102]={\n GM=444981600,\n bodyId=102,\n center={x=99180968.000,y=-13783862.000,z=-926156.400},\n name='Lacobus Moon 1',\n planetarySystemId=0,\n radius=18000\n },\n [103]={\n GM=211503600,\n bodyId=103,\n center={x=99250052.000,y=-13629215.000,z=-1059341.400},\n name='Lacobus Moon 2',\n planetarySystemId=0,\n radius=14000\n },\n [110]={\n GM=9204742375,\n bodyId=110,\n center={x=14165536.000,y=-85634465.000,z=-934464.300},\n name='Symeon',\n planetarySystemId=0,\n radius=49050\n },\n [120]={\n GM=7135606629,\n bodyId=120,\n center={x=2865536.700,y=-99034464.000,z=-934462.020},\n name='Ion',\n planetarySystemId=0,\n radius=44950\n },\n [121]={\n GM=106830900,\n bodyId=121,\n center={x=2472916.800,y=-99133747.000,z=-1133582.800},\n name='Ion Moon 1',\n planetarySystemId=0,\n radius=11000\n },\n [122]={\n GM=176580000,\n bodyId=122,\n center={x=2995424.500,y=-99275010.000,z=-1378480.700},\n name='Ion Moon 2',\n planetarySystemId=0,\n radius=15000\n } \n }\n }\n mindist2=nil\n for index,data in pairs(Atlas[0]) do\n r=data.radius\n center=data.center\n cx=center.x\n cy=center.y\n cz=center.z\n dist2=(px-cx)^2+(py-cy)^2+(pz-cz)^2\n if mindist2==nil then\n mindist2=dist2\n mincx=cx\n mincy=cy\n mincz=cz\n minr=r\n minindex=index\n elseif dist2=0 and phi or (2*math.pi+phi)\n lat= math.pi/2 - math.acos(z/d)\n \n alt_str=string.format('%.4f',alt)\n lon_str=string.format('%.4f',lon*rad2deg)\n lat_str=string.format('%.4f',lat*rad2deg)\n\n pos_str='::pos{0,'..minindex..','..lat_str..','..lon_str..','..alt_str..'}'\n return pos_str\nend","filter":{"args":[],"signature":"start()","slotKey":"-1"},"key":"0"},{"code":"--[[\nVersion 2.0.0\n]]\n\ndistance_list={400,375,350,325,300,275,250,225,200,175,150,125,100,75,50,45,40,35,30,25,20,15,10,5}\nbutton_r=25\ndx=5\ncurrent_di=1\nmargin=0.10\n\nhudHTML=[[\n\n]]\n\ncx=button_r\ncy=button_r\nfor index,d in pairs(distance_list) do\n if d==distance_list[current_di] then\n stroke_color=\"#CCBB44\"\n else\n stroke_color=\"white\"\n end\n hudHTML=hudHTML..[[\n \n ]]..d..[[\n ]]\n cx=cx+2*button_r+dx\n end\n\nhudHTML=hudHTML..[[\n\n]]\n\n\nmeasureCount=0\n\nsystem.print(\"Welcome to SimplePiMans Ore Finder\")\nsystem.print(\"Alt+1 moves the selected measurement left\")\nsystem.print(\"Alt+2 moves the selected measurement right\")\nsystem.print(\"Alt+3 locks in the measurement\")\nsystem.print(\"Alt+9 resets the system allowing for a fresh search\")\nsystem.print(\"Every masurement after the 2nd will give a ::pos tag\")\nsystem.print(\"For the best guess of where the ore is located\")\nsystem.print(\"You can right click to set as a destination\")\n\nsystem.setScreen(hudHTML)\nsystem.showScreen(1)","filter":{"args":[],"signature":"start()","slotKey":"-1"},"key":"1"},{"code":"current_di=current_di-1\nif current_di==0 then\n current_di=#distance_list\nend\n\nhudHTML=[[\n\n]]\n\ncx=button_r\ncy=button_r\nfor index,d in pairs(distance_list) do\n if d==distance_list[current_di] then\n stroke_color=\"#CCBB44\"\n else\n stroke_color=\"white\"\n end\n hudHTML=hudHTML..[[\n \n ]]..d..[[\n ]]\n cx=cx+2*button_r+dx\n end\n\nhudHTML=hudHTML..[[\n\n]]\n\nsystem.setScreen(hudHTML)","filter":{"args":[{"value":"option1"}],"signature":"actionStart(action)","slotKey":"-2"},"key":"2"},{"code":"current_di=current_di+1\nif current_di>#distance_list then\n current_di=1\nend\n\nhudHTML=[[\n\n]]\n\ncx=button_r\ncy=button_r\nfor index,d in pairs(distance_list) do\n if d==distance_list[current_di] then\n stroke_color=\"#CCBB44\"\n else\n stroke_color=\"white\"\n end\n hudHTML=hudHTML..[[\n \n ]]..d..[[\n ]]\n cx=cx+2*button_r+dx\n end\n\nhudHTML=hudHTML..[[\n\n]]\n\nsystem.setScreen(hudHTML)","filter":{"args":[{"value":"option2"}],"signature":"actionStart(action)","slotKey":"-2"},"key":"3"},{"code":"dist=distance_list[current_di]\nif dist>=50 then\n margin=12.5\nelse\n margin=2.5\nend\nplayer_id=unit.getMasterPlayerId()\nplayer_pos=vec3(system.getPlayerWorldPos(player_id))\nplayer_marker=GetPosString(player_pos.x,player_pos.y,player_pos.z)\nsystem.print(\"You are here:\")\nsystem.print(player_marker)\nmeasureCount=measureCount+1\nif measureCount==1 then\n measureList={}\n table.insert(measureList,{player_pos.x,player_pos.y,player_pos.z,dist^2})\n boxXmin=player_pos.x-(dist+margin)\n boxXmax=player_pos.x+(dist+margin)\n boxYmin=player_pos.y-(dist+margin)\n boxYmax=player_pos.y+(dist+margin)\n boxZmin=player_pos.z-(dist+margin)\n boxZmax=player_pos.z+(dist+margin)\n \n start_x=player_pos.x\n start_y=player_pos.y\n start_z=player_pos.z\n start_d2=(1.25*dist)^2\n system.print(\"registered first measurement\")\nelse\n table.insert(measureList,{player_pos.x,player_pos.y,player_pos.z,dist^2})\n \n dist_from_start=(player_pos.x-start_x)^2+(player_pos.y-start_y)^2+(player_pos.z-start_z)^2\n if dist_from_start>start_d2 then\n system.print(\"ERROR: location out of bounds\")\n system.print(\"ignoring measure, submit a new one\")\n system.print(\"that is within range of first measurement\")\n measureCount=measureCount-1\n else\n box2Xmin=player_pos.x-(dist+margin)\n box2Xmax=player_pos.x+(dist+margin)\n box2Ymin=player_pos.y-(dist+margin)\n box2Ymax=player_pos.y+(dist+margin)\n box2Zmin=player_pos.z-(dist+margin)\n box2Zmax=player_pos.z+(dist+margin)\n\n boxXmin=math.max(boxXmin,box2Xmin)\n boxXmax=math.min(boxXmax,box2Xmax)\n boxYmin=math.max(boxYmin,box2Ymin)\n boxYmax=math.min(boxYmax,box2Ymax)\n boxZmin=math.max(boxZmin,box2Zmin)\n boxZmax=math.min(boxZmax,box2Zmax)\n \n \n\n if boxXmin>=boxXmax or boxYmin>=boxYmax or boxZmin>=boxZmax then\n system.print(\"ERROR: unable to define bounding box\")\n system.print(\"Please start over\")\n measureCount=0\n elseif measureCount>2 then\n \n system.print(\"search box updated.\")\n\n chunks=5\n xdelta=(boxXmax-boxXmin)/chunks\n ydelta=(boxYmax-boxYmin)/chunks\n zdelta=(boxZmax-boxZmin)/chunks\n \n found_marker=0\n\n minError=1000000000\n x=boxXmin\n while x<=boxXmax do\n y=boxYmin\n while y<=boxYmax do\n z=boxZmin\n while z<=boxZmax do\n curError=0\n out_of_bounds=0\n for i=1,#measureList do\n measure=measureList[i]\n mx=measure[1]\n my=measure[2]\n mz=measure[3]\n m2=measure[4]\n d2=(mx-x)^2+(my-y)^2+(mz-z)^2\n e=math.abs(d2-m2)\n if e>1.5625*m2 then\n out_of_bounds=1\n break\n end\n curError=curError+e\n end\n if curError