View difference between Paste ID: rwtE1x6e and B3JLC2jH
SHOW: | | - or go back to the newest paste.
1
if warpdriveCommons then os.unloadAPI("warpdriveCommons") end
2
if not os.loadAPI("warpdrive/warpdriveCommons") then error("missing warpdriveCommons") end
3
local w = warpdriveCommons.w
4
5
local data
6
7
----------- Ship support
8
9
local miningLaser
10-
local laserCamera
10+
11
local useMiningLaserOffset = true
12
local forwardBackMov =0
13
local leftRightMov = 0
14
local ship
15
local ship_front = 0
16
local ship_right = 0
17
local ship_up = 0
18
local ship_back = 0
19
local ship_left = 0
20
local ship_down = 0
21
local ship_isInHyper = false
22
local ship_x, ship_y, ship_z = 0, 0, 0
23
local ship_xTarget, ship_yTarget, ship_zTarget = 0, 0, 0
24
local ship_actualDistance = 0
25
local ship_energyRequired = 0
26
local ship_movement = { 0, 0, 0 }
27
local ship_rotationSteps = 0
28
local ship_indexPlayer = 0
29
local ship_arrayPlayers = { }
30
local ship_indexTarget = 0
31
32
local lx = 0
33
local ly = 0
34
local lz = 0
35
36
function ship_read(parData)
37
  data = parData
38
end
39
40
function ship_name(parName)
41
  if ship == nil or ship.isInterfaced() == nil then
42
    return ''
43
  end
44
  return ship.name(parName)
45
end
46
47
function ship_boot()
48
  if ship == nil or ship.isInterfaced() == nil then
49
    return
50
  end
51
  
52
  w.setColorNormal()
53
  w.writeLn("Booting Ship")
54
  
55
  w.write("- acquiring parameters: ")
56
  ship_front, ship_right, ship_up = ship.dim_positive()
57
  ship_back, ship_left, ship_down = ship.dim_negative()
58
  ship_isInHyper = ship.isInHyperspace()
59
  ship_movement = { ship.movement() }
60
  ship_rotationSteps = ship.rotationSteps()
61
  w.setColorSuccess()
62
  w.writeLn("ok")
63
  
64
  w.setColorNormal()
65
  w.write("- checking assembly   : ")
66
  local timeout = 10
67
  local isValid, message
68
  repeat
69
    isValid, message = ship.getAssemblyStatus()
70
    w.sleep(0.05)
71
    timeout = timeout - 1
72
  until isValid == true or timeout < 0
73
  if timeout < 0 then
74
    w.setColorWarning()
75
    w.writeLn("failed")
76
    w.writeLn(message)
77
    w.setColorNormal()
78
    w.sleep(6)
79
    -- don't reboot as the player might need to set new dimensions to fix it
80
  else
81
    w.setColorSuccess()
82
    w.writeLn("passed")
83
  end
84
  w.sleep(0.2)
85
  
86
  w.setColorNormal()
87
  w.write("- celestial position  : ")
88
  timeout = 10
89
  local pos
90
  repeat
91
    pos = ship.getLocalPosition()
92
    w.sleep(0.05)
93
    timeout = timeout - 1
94
  until pos ~= nil or timeout < 0
95
  if timeout < 0 then
96
    w.setColorWarning()
97
    w.writeLn("failed")
98
    w.writeLn("")
99
    w.writeLn("Something is wrong here, rebooting...")
100
    w.setColorNormal()
101
    w.sleep(2)
102
    w.reboot()
103
  else
104
    w.setColorSuccess()
105
    w.writeLn("triangulated")
106
  end
107
  ship_updateMovementStats()
108
  w.sleep(0.2)
109
  
110
  w.setColorNormal()
111
  w.write("- integrity check     : ")
112
  timeout = 10
113
  local shipSize
114
  repeat
115
    shipSize = ship.getShipSize()
116
    w.sleep(0.05)
117
    timeout = timeout - 1
118
  until (shipSize ~= nil and shipSize ~= 0) or timeout < 0
119
  if timeout < 0 then
120
    w.setColorWarning()
121
    w.writeLn("ongoing...")
122
    w.setColorNormal()
123
    w.sleep(2)
124
  else
125
    w.setColorSuccess()
126
    w.writeLn("passed")
127
  end
128
  
129
  ship.enable(true)
130
  ship.command("IDLE", true)
131
  w.sleep(0.3)
132
end
133
134
function ship_writeMovement(prefix)
135
  local message = prefix
136
  local count = 0
137
  if ship_movement[1] > 0 then
138
    message = message .. w.format_integer(ship_movement[1]) .. " front"
139
    count = count + 1
140
  elseif ship_movement[1] < 0 then
141
    message = message .. w.format_integer(- ship_movement[1]) .. " back"
142
    count = count + 1
143
  end
144
  if ship_movement[2] > 0 then
145
    if count > 0 then message = message .. ", " end
146
    message = message .. w.format_integer(ship_movement[2]) .. " up"
147
    count = count + 1
148
  elseif ship_movement[2] < 0 then
149
    if count > 0 then message = message .. ", " end
150
    message = message .. w.format_integer(- ship_movement[2]) .. " down"
151
    count = count + 1
152
  end
153
  if ship_movement[3] > 0 then
154
    if count > 0 then message = message .. ", " end
155
    message = message .. w.format_integer(ship_movement[3]) .. " right"
156
    count = count + 1
157
  elseif ship_movement[3] < 0 then
158
    if count > 0 then message = message .. ", " end
159
    message = message .. w.format_integer(- ship_movement[3]) .. " left"
160
    count = count + 1
161
  end
162
  
163
  if ship_rotationSteps == 1 then
164
    if count > 0 then message = message .. ", " end
165
    message = message .. "Turn right"
166
    count = count + 1
167
  elseif ship_rotationSteps == 2 then
168
    if count > 0 then message = message .. ", " end
169
    message = message .. "Turn back"
170
    count = count + 1
171
  elseif ship_rotationSteps == 3 then
172
    if count > 0 then message = message .. ", " end
173
    message = message .. "Turn left"
174
    count = count + 1
175
  end
176
  
177
  if count == 0 then
178
    message = message .. "(none)"
179
  end
180
  w.writeLn(message)
181
end
182
183
function ship_writeRotation()
184
  if ship_rotationSteps == 0 then
185
    w.writeLn(" Rotation         = Front    ")
186
  elseif ship_rotationSteps == 1 then
187
    w.writeLn(" Rotation         = Right +90")
188
  elseif ship_rotationSteps == 2 then
189
    w.writeLn(" Rotation         = Back 180 ")
190
  elseif ship_rotationSteps == 3 then
191
    w.writeLn(" Rotation         = Left -90 ")
192
  end
193
end
194
195
function ship_updateMovementStats()
196
  -- get current position
197
  ship_x, ship_y, ship_z = ship.getLocalPosition()
198
  if ship_x == nil then
199
    ship_x, ship_y, ship_z = 0, 0, 0
200
  end
201
  
202
  -- compute movement
203
  local dx, dy, dz = ship.getOrientation()
204
  if dx == nil then
205
    dx, dy, dz = 0, 0, 0
206
  end
207
  local worldMovement = { x = 0, y = 0, z = 0 }
208
  worldMovement.x = dx * ship_movement[1] - dz * ship_movement[3]
209
  worldMovement.y = ship_movement[2]
210
  worldMovement.z = dz * ship_movement[1] + dx * ship_movement[3]
211
  ship_actualDistance = math.ceil(math.sqrt(worldMovement.x * worldMovement.x + worldMovement.y * worldMovement.y + worldMovement.z * worldMovement.z))
212
  ship_xTarget = ship_x + worldMovement.x
213
  ship_yTarget = ship_y + worldMovement.y
214
  ship_zTarget = ship_z + worldMovement.z
215
  
216
  -- update energy requirement
217
  local success, result = ship.getEnergyRequired()
218
  if success then
219
    ship_energyRequired = result
220
  else
221
    w.status_showWarning(result)
222
  end
223
end
224
225
function ship_warp()
226
  -- rs.setOutput(alarm_side, true)
227
  if w.input_readConfirmation("Engage jump drive? (Y/n)") then
228
    -- rs.setOutput(alarm_side, false)
229
    ship.command("MANUAL", false)
230
    ship.movement(ship_movement[1], ship_movement[2], ship_movement[3])
231
    ship.rotationSteps(ship_rotationSteps)
232
    ship.command("MANUAL", true)
233
    -- ship = nil
234
  end
235
  -- rs.setOutput(alarm_side, false)
236
end
237
238
function ship_page_setMovement()
239
  -- force manual jump so we get proper max jump distance
240
  ship.command("MANUAL", false)
241
  
242
  local success, maxJumpDistance = ship.getMaxJumpDistance()
243
  if success ~= true then
244
    w.status_showWarning("" .. maxJumpDistance)
245
    return
246
  end
247
  
248
  w.page_begin("<==== Set ship movement ====>")
249
  w.setCursorPos(1, 3)
250
  w.setColorNormal()
251
  ship_writeMovement("Current movement is ")
252
  w.setCursorPos(1, 5)
253
  
254
  ship_movement[1] = ship_page_setDistanceAxis(4, "Forward/back", "Forward", "Backward", ship_movement[1], math.abs(ship_front + ship_back  + 1), maxJumpDistance)
255
  ship_movement[2] = ship_page_setDistanceAxis(6, "Up/down"     , "Up"     , "Down"    , ship_movement[2], math.abs(ship_up    + ship_down  + 1), maxJumpDistance)
256
  ship_movement[3] = ship_page_setDistanceAxis(8, "Right/left"  , "Right"  , "Left"    , ship_movement[3], math.abs(ship_left  + ship_right + 1), maxJumpDistance)
257
  ship_movement = { ship.movement(ship_movement[1], ship_movement[2], ship_movement[3]) }
258
  ship_updateMovementStats()
259
end
260
261
function ship_page_setDistanceAxis(line, axis, positive, negative, userEntry, shipLength, maxJumpDistance)
262
  local maximumDistance = math.floor(shipLength + maxJumpDistance)
263
  w.setCursorPos(1, line + 2)
264
  w.setColorHelp()
265
  w.writeFullLine(" Enter between " .. math.floor( shipLength + 1) .. " and " ..  maximumDistance .. " to move " ..  positive .. ".")
266
  w.writeFullLine(" Enter 0 to keep position on this axis.")
267
  w.writeFullLine(" Enter between " .. -maximumDistance .. " and " .. math.floor(-shipLength - 1) .. " to move " ..  negative .. ".")
268
  
269
  repeat
270
    w.setCursorPos(1, line)
271
    w.setColorNormal()
272
    w.write(axis .. " movement: ")
273
    userEntry = w.input_readInteger(userEntry)
274
    if userEntry ~= 0 and (math.abs(userEntry) <= shipLength or math.abs(userEntry) > maximumDistance) then
275
      w.status_showWarning("Wrong distance. Try again.")
276
    end
277
  until userEntry == 0 or (math.abs(userEntry) > shipLength and math.abs(userEntry) <= maximumDistance)
278
  w.setCursorPos(1, line + 2)
279
  w.clearLine()
280
  w.setCursorPos(1, line + 3)
281
  w.clearLine()
282
  w.setCursorPos(1, line + 4)
283
  w.clearLine()
284
  
285
  return userEntry
286
end
287
288
function ship_page_setRotation()
289
  local inputAbort = false
290
  w.page_begin("<==== Set ship rotation ====>")
291
  w.setCursorPos(1, 8)
292
  w.setColorHelp()
293
  w.writeFullLine(" Select ship rotation (Up, Down, Left, Right).")
294
  w.writeFullLine(" Select Front to keep current orientation.")
295
  w.writeFullLine(" Press Enter to save your selection.")
296
  repeat
297
    w.setCursorPos(1, 3)
298
    w.setColorNormal()
299
    ship_writeRotation()
300
    local params = { os.pullEventRaw() }
301
    local eventName = params[1]
302
    local address = params[2]
303
    if address == nil then address = "none" end
304
    if eventName == "key" then
305
      local keycode = params[2]
306
      if keycode == 200 then
307
        ship_rotationSteps = 0
308
      elseif keycode == 203 then
309
        ship_rotationSteps = 3
310
      elseif keycode == 205 then
311
        ship_rotationSteps = 1
312
      elseif keycode == 208 then
313
        ship_rotationSteps = 2
314
      elseif keycode == 28 then
315
        inputAbort = true
316
      else
317
        w.status_showWarning("Key " .. keycode .. " is invalid")
318
      end
319
    elseif eventName == "terminate" then
320
      inputAbort = true
321
    elseif not w.event_handler(eventName, params[2]) then
322
      w.status_showWarning("Event '" .. eventName .. "', " .. address .. " is unsupported")
323
    end
324
  until inputAbort
325
  ship_rotationSteps = ship.rotationSteps(ship_rotationSteps)
326
end
327
328
function ship_page_setDimensions()
329
  w.page_begin("<==== Set ship dimensions ====>")
330
  w.setCursorPos(1, 14)
331
  w.setColorHelp()
332
  w.writeFullLine(" Enter ship size in blocks (0-9).")
333
  w.writeFullLine(" First block next to Ship counts as 1.")
334
  w.writeFullLine(" ")
335
  w.writeFullLine(" Press Enter to save your selection.")
336
  
337
  w.setCursorPos(1, 3)
338
  w.setColorNormal()
339
  w.write(" Front (".. w.format_integer(ship_front) ..") : ")
340
  ship_front = w.input_readInteger(ship_front)
341
  w.write(" Right (".. w.format_integer(ship_right) ..") : ")
342
  ship_right = w.input_readInteger(ship_right)
343
  w.write(" Up    (".. w.format_integer(ship_up) ..") : ")
344
  ship_up = w.input_readInteger(ship_up)
345
  w.write(" Back  (".. w.format_integer(ship_back) ..") : ")
346
  ship_back = w.input_readInteger(ship_back)
347
  w.write(" Left  (".. w.format_integer(ship_left) ..") : ")
348
  ship_left = w.input_readInteger(ship_left)
349
  w.write(" Down  (".. w.format_integer(ship_down) ..") : ")
350
  ship_down = w.input_readInteger(ship_down)
351
  w.write("Setting dimensions...")
352
  ship_front, ship_right, ship_up = ship.dim_positive(ship_front, ship_right, ship_up)
353
  ship_back, ship_left, ship_down = ship.dim_negative(ship_back, ship_left, ship_down)
354
end
355
356
function ship_page_summon() -- no longer used
357
  w.page_begin("<==== Summon players ====>")
358
  local stringPlayers = ship.getAttachedPlayers()
359
  if stringPlayers == "" then
360
    w.writeLn("~ no players registered ~")
361
    w.writeLn("")
362
    w.setColorHelp()
363
    w.writeFullLine(" Press enter to exit.")
364
    w.setColorNormal()
365
    w.input_readInteger("")
366
    return
367
  end
368
  local arrayPlayers = w.data_splitString(stringPlayers, ",")
369
  for i = 1, #arrayPlayers do
370
    w.writeLn(i .. ". " .. arrayPlayers[i])
371
  end
372
  w.setColorHelp()
373
  w.writeFullLine(" Enter player number")
374
  w.writeFullLine(" or press enter to summon everyone.")
375
  w.setColorNormal()
376
  
377
  w.write(":")
378
  ship.command("SUMMON", false)
379
  local input = w.input_readInteger("")
380
  if input == "" then
381
    ship.targetName("")
382
  else
383
    input = tonumber(input)
384
    ship.targetName(arrayPlayers[input - 1])
385
  end
386
  ship.command("SUMMON", true)
387
end
388
389
function ship_page_jumpToGate()
390
  w.page_begin("<==== Jump through Jumpgate ====>")
391
  w.writeLn("")
392
  w.writeLn("Your ship should be already inside a jumpgate")
393
  
394
  w.setCursorPos(1, 16)
395
  w.setColorHelp()
396
  w.writeFullLine(" Enter target jumpgate name (a-z, 0-9).")
397
  w.writeFullLine(" Press enter to save jumpgate name.")
398
  
399
  w.setCursorPos(1, 5)
400
  w.setColorNormal()
401
  w.write("Target jumpgate name: ")
402
  local targetName = w.input_readText("")
403
  -- rs.setOutput(alarm_side, true)
404
  if w.input_readConfirmation("Engage gate jumping? (Y/n)") then
405
    -- rs.setOutput(alarm_side, false)
406
    ship.command("GATE", false)
407
    ship.targetName(targetName)
408
    ship.command("GATE", true)
409
    -- ship = nil
410
  end
411
  -- rs.setOutput(alarm_side, false)
412
end
413
414
function ship_page_controls()
415
  w.page_begin(w.data_getName() .. " - Ship controls")
416
  if ship == nil or ship.isInterfaced() == nil then
417
    w.status_showWarning("No ship controller detected")
418
  else
419
    local isValid, message = ship.getAssemblyStatus()
420
    if isValid ~= true then
421
      w.status_showWarning(message)
422
    else
423
      local isEnabled = ship.enable()
424
      if not isEnabled then
425
        ship.command("MANUAL", false)
426
        ship_updateMovementStats()
427
      end
428
    end
429
    
430
    w.setCursorPos(1, 2)
431
    w.writeLn("Ship:")
432
    w.writeLn(" Current position = " .. w.format_integer(ship_x) .. ", " .. w.format_integer(ship_y) .. ", " .. w.format_integer(ship_z))
433
    local energyStored, energyMax, energyUnits = ship.getEnergyStatus()
434
    if energyStored == nil then energyStored = 0 end
435
    if energyMax == nil or energyMax == 0 then energyMax = 1 end
436
    w.writeLn(" Energy           = " .. math.floor(energyStored / energyMax * 100) .. " % (" .. w.format_integer(energyStored) .. " " .. energyUnits .. ")")
437
    
438
    w.writeLn("")
439
    w.writeLn("Dimensions:")
440
    w.writeLn(" Front, Right, Up = " .. w.format_integer(ship_front) .. ", " .. w.format_integer(ship_right) .. ", " .. w.format_integer(ship_up) .. " blocks")
441
    w.writeLn(" Back, Left, Down = " .. w.format_integer(ship_back) .. ", " .. w.format_integer(ship_left) .. ", " .. w.format_integer(ship_down) .. " blocks")
442
    local shipMass, shipVolume = ship.getShipSize()
443
    if shipMass == nil then
444
      shipMass = 0
445
      shipVolume = 0
446
    end
447
    w.write(" Mass, Volume     = ")
448
    if shipMass == 0 then
449
      w.write("?")
450
    else
451
      w.write(w.format_integer(shipMass))
452
    end
453
    w.write(" tons, ")
454
    if shipVolume == 0 then
455
      w.write("?")
456
    else
457
      w.write(w.format_integer(shipVolume))
458
    end
459
    w.writeLn(" blocks")
460
    
461
    if isValid == true then
462
      w.writeLn("")
463
      w.writeLn("Warp data:")
464
      ship_writeMovement(" Movement         = ")
465
      w.writeLn(" Distance         = " .. w.format_integer(ship_actualDistance) .. " m (" .. w.format_integer(ship_energyRequired) .. " " .. energyUnits .. ", " .. math.floor(energyStored / ship_energyRequired) .. " jumps)")
466
      w.writeLn(" Target position  = " .. w.format_integer(ship_xTarget) .. ", " .. w.format_integer(ship_yTarget) .. ", " .. w.format_integer(ship_zTarget))
467
    end
468
  end
469
  
470
  w.setCursorPos(1, 16)
471
  w.setColorControl()
472
  w.writeFullLine(" set ship Name (N), dImensions (I), Movement (M)")
473
  if ship_isInHyper then
474
    w.writeFullLine(" Jump to move ship (M/J), exit Hyperspace (H)")
475
  else
476
    w.writeFullLine(" Jump to move ship (M/J), enter Hyperspace (H)")
477
  end
478
end
479
480
function ship_key_controls(character, keycode)
481
  if character == 'm' or character == 'M' then
482
    ship_page_setMovement()
483
    ship_page_setRotation()
484
    ship_warp()
485
    return true
486
  elseif character == 'i' or character == 'I' then
487
    ship_page_setDimensions()
488
    return true
489
  elseif character == 'j' or character == 'J' then
490
    ship_warp()
491
    return true
492
  elseif character == 'h' or character == 'H' then
493
    -- rs.setOutput(alarm_side, true)
494
    local isConfirmed
495
    if ship_isInHyper then
496
      isConfirmed = w.input_readConfirmation("Disengage hyperdrive? (Y/n)")
497
    else
498
      isConfirmed = w.input_readConfirmation("Engage hyperdrive? (Y/n)")
499
    end
500
    if isConfirmed then
501
      -- rs.setOutput(alarm_side, false)
502
      ship.command("HYPERDRIVE", true)
503
      ship_updateMovementStats()
504
      -- ship = nil
505
    end
506
    -- rs.setOutput(alarm_side, false)
507
    return true
508
  elseif character == 'n' or character == 'N' then
509
    w.data_setName()
510
    return true
511
  end
512
  return false
513
end
514
515
function ship_writeArray(arrayValues, indexSelected)
516
  if indexSelected then
517
    indexSelected = (indexSelected + #arrayValues) % #arrayValues
518
  end
519
  
520
  local indexSplit = math.ceil(#arrayValues / 2)
521
  for i = 1, indexSplit do
522
    if indexSelected and i == indexSelected + 1 then
523
      w.setColorSelected()
524
      w.write(">" .. string.sub(arrayValues[i] .. "                        ", 1, 24))
525
      w.setColorNormal()
526
    else
527
      w.write(" " .. string.sub(arrayValues[i] .. "                        ", 1, 24))
528
    end
529
    if arrayValues[i + indexSplit] ~= nil then
530
      if indexSelected and i + indexSplit == indexSelected + 1 then
531
        w.setColorSelected()
532
        w.writeLn(">" .. string.sub(arrayValues[i + indexSplit] .. "                        ", 1, 24))
533
        w.setColorNormal()
534
      else
535
        w.writeLn(" " .. arrayValues[i + indexSplit])
536
      end
537
    else
538
      w.writeLn("")
539
    end
540
  end
541
  return indexSelected
542
end
543
544
function ship_page_crew()
545
  w.page_begin(w.data_getName() .. " - Ship crew")
546
  if ship == nil or ship.isInterfaced() == nil then
547
    w.status_showWarning("No ship controller detected")
548
  else
549
    local isValid, message = ship.getAssemblyStatus()
550
    if isValid ~= true then
551
      w.status_showWarning(message)
552
    else
553
      w.writeLn("Attached players:")
554
      -- local stringPlayers, _ = ship.getAttachedPlayers()
555
      if stringPlayers == nil or stringPlayers == "" then
556
        stringPlayers = "~ no registered player ~"
557
      end
558
      ship_arrayPlayers = w.data_splitString(stringPlayers, ",")
559
      ship_indexPlayer = ship_writeArray(ship_arrayPlayers, ship_indexPlayer)
560
    end
561
  end
562
  
563
  w.setCursorPos(1, 16)
564
  w.setColorControl()
565
  w.writeFullLine(" Summon all crew (S)")
566
  w.writeFullLine(" select crew (Up, Down), summon slctd crew (enter)")
567
end
568
569
function ship_key_crew(character, keycode)
570
  if character == 's' or character == 'S' then -- S
571
    ship.command("SUMMON", false)
572
    ship.targetName("")
573
    ship.command("SUMMON", true)
574
    return true
575
  elseif keycode == 28 then -- Enter
576
    local namePlayer = ship_arrayPlayers[ship_indexPlayer + 1]
577
    ship.command("SUMMON", false)
578
    ship.targetName(namePlayer)
579
    ship.command("SUMMON", true)
580
    w.status_showSuccess("Engaging teleportation for " .. namePlayer .. "...")
581
    return true
582
  elseif keycode == 200 or keycode == 203 or character == '-' then -- Up or Left or -
583
    ship_indexPlayer = ship_indexPlayer - 1
584
    return true
585
  elseif keycode == 208 or keycode == 205 or character == '+' then -- Down or Right or +
586
    ship_indexPlayer = ship_indexPlayer + 1
587
    return true
588
  end
589
  return false
590
end
591
592
function ship_page_navigation()
593
  w.page_begin(w.data_getName() .. " - Ship navigation")
594
  if ship == nil or ship.isInterfaced() == nil then
595
    w.status_showWarning("No ship controller detected")
596
  else
597
    local isValid, message = ship.getAssemblyStatus()
598
    if isValid ~= true then
599
      w.status_showWarning(message)
600
    else
601
      local locationCurrent = "somewhere..."  -- @TODO ship.getLocation()
602
      w.writeLn("Current ship location        : " .. locationCurrent)
603
      w.writeLn("Jumpgates or beacons in range:")
604
      local stringTargets, _ = "not implemented", nil -- ship.getTargets()
605
      if stringTargets == nil or stringTargets == "" then
606
        stringTargets = "~ no beacon nor jumpgate in range ~"
607
      end
608
      local arrayTargets = w.data_splitString(stringTargets, ",")
609
      ship_indexTarget = ship_writeArray(arrayTargets, ship_indexTarget)
610
    end
611
  end
612
  
613
  w.setCursorPos(1, 16)
614
  w.setColorControl()
615
  w.writeFullLine(" select target (Up, Down), register target (enter)")
616
  w.writeFullLine(" jump through Gate (G)")
617
end
618
619
function ship_key_navigation(character, keycode)
620
  if keycode == 28 then -- Enter
621
--    local success, xxx = ship.xxx(ship_indexTarget)
622
--    if success then
623
--      w.status_showSuccess("Engaging jumpgate jump to " .. xxx .. "...")
624
--    else
625
--      w.status_showWarning("Failed to summon crew member")
626
--    end
627
    return true
628
--  elseif character == 'b' or character == 'B' then -- B
629
--    ship_page_jumpToBeacon()
630
--    return true
631
  elseif character == 'g' or character == 'G' then -- G
632
    ship_page_jumpToGate()
633
    return true
634
  elseif keycode == 200 or keycode == 203 or character == '-' then -- Up or Left or -
635
    ship_indexTarget = ship_indexTarget - 1
636
    return true
637
  elseif keycode == 208 or keycode == 205 or character == '+' then -- Down or Right or +
638
    ship_indexTarget = ship_indexTarget + 1
639
    return true
640
  end
641
  return false
642
end
643
644
function ship_register()
645
  local numberOfLaserCameras = 3 -- Assuming you have 3 laser cameras
646
  local laserCameras = {} -- Initialize the laserCameras array
647
648
  w.device_register("warpdriveShipController",
649
      function(deviceType, address, wrap) ship = wrap end,
650
      function() end)
651
  w.device_register("warpdriveShipCore",
652
      function(deviceType, address, wrap) ship = wrap end,
653-
  w.device_register("warpdriveLaserCamera", function(deviceType, address, wrap) laserCamera = wrap end, function() end)
653+
654-
  w.event_register("shipCoreCooldownDone"  , function() w.status_showWarning("Ship core cooldown done")   return false end )
654+
655
656
  -- Register laser cameras
657
  w.device_register("warpdriveLaserCamera", 
658
    function(deviceType, address, wrap)
659
      table.insert(laserCameras, wrap)
660
      if #laserCameras > numberOfLaserCameras then
661
        -- Handle error or warning if too many laser cameras are registered
662
      end
663
    end, function() 
664
      -- Handle unregistration if needed
665
    end)
666
667
  w.event_register("shipCoreCooldownDone", function() w.status_showWarning("Ship core cooldown done") return false end )
668
  w.event_register("laserScanning", function() laser_sendEvent() return false end )
669
  w.data_register("ship", ship_read, nil, ship_name)
670
end
671
672
----------- connections status
673
674
function connections_page(isBooting)
675
  w.page_begin(w.data_getName() .. " - Connections")
676
  
677
  w.writeLn("")
678
  
679
  local monitors = w.device_getMonitors()
680
  if #monitors == 0 then
681
    w.setColorDisabled()
682
    w.writeLn("No Monitor detected")
683
  elseif #monitors == 1 then
684
    w.setColorSuccess()
685
    w.writeLn("1 monitor detected")
686
  else
687
    w.setColorSuccess()
688
    w.writeLn(#monitors .. " Monitors detected")
689
  end
690
  
691
  if ship == nil or ship.isInterfaced() == nil then
692
    w.setColorDisabled()
693
    w.writeLn("No ship controller detected")
694
  else
695
    w.setColorSuccess()
696
    w.writeLn("Ship controller detected")
697
    if isBooting then
698
      ship_boot()
699
    end
700
  end
701
  
702
  w.writeLn("")
703
  w.setColorNormal()
704
  w.writeLn("This is a keyboard controlled user interface.")
705
  w.write("Key controls are written like so: ")
706
  w.setColorControl()
707
  w.write("Action (key)")
708
  w.setColorNormal()
709
  w.writeLn(".")
710
  w.write("For example, typing ")
711
  w.setColorControl()
712
  w.write(" 1 ")
713
  w.setColorNormal()
714
  w.writeLn(" will open Ship controls.")
715
end
716
717
function laser_guide_page()
718
  w.page_begin(w.data_getName() .. " - Laser Guidance") 
719
  if ship == nil or ship.isInterfaced() == nil then
720
    w.status_showWarning("No ship controller detected")
721
  elseif laserCamera == nil or laserCamera.isInterfaced() == nil then
722
	    w.status_showWarning("No laser camera detected")
723
  elseif laserCamera.laserMediumCount() < 1 then
724
		w.status_showWarning("No laser mediums detected")
725
  else
726
	if (miningLaser == nil or miningLaser.isInterfaced() == nil) then
727
		useMiningLaserOffset = false
728
	end
729
	laserGuideOn = "true"
730
	if (laserGuideEnabled) then
731
		laserGuideOn = "true"
732
	else
733
		laserGuideOn = "false"
734
	end
735
	w.writeLn("Laser Guidance Enabled = " .. laserGuideOn)
736
	w.writeLn("Mining Laser Offset Enabled = " .. tostring(useMiningLaserOffset))
737
	w.writeLn("Target Position = " .. " x:" .. lx .. " z:" .. lz) 
738
	
739
	local forwardBack = " Forward, "
740
	local leftRight = " Right"
741
	if forwardBackMov < 0 then
742
		forwardBack = " Back, "
743
	end
744
	if leftRightMov < 0 then
745
		leftRight = " Left"
746
	end
747
	w.writeLn("Ship Movement = " .. math.abs(forwardBackMov) .. forwardBack .. math.abs(leftRightMov) .. leftRight)
748
  end
749
  
750
  w.setCursorPos(1, 16)
751
  w.setColorControl()
752
  w.writeFullLine("Toggle Laser Guidance (t), Clear Data (c)")
753
  w.writeFullLine("Mining Laser Offset (g)")
754
end
755
function laser_key(character, keycode)
756
  if character == 't' or character == 'T' then
757
	if laserGuideEnabled then
758
		laserGuideEnabled = false
759
	else
760
		laserGuideEnabled = true
761
	end
762
	return true
763
  elseif character == 'c' or character == 'C' then
764
	lx = 0
765
	ly = 0
766
	lz = 0
767
	leftRightMov = 0
768
	forwardBackMov = 0
769
	return true
770
  elseif character == 'g' or character == 'G' then
771
	if miningLaser == nil or miningLaser.isInterfaced() == nil then
772-
	if (laserCamera ~= nil and laserCamera.isInterfaced()) then
772+
773-
		if (miningLaser == nil or miningLaser.isInterfaced() == nil) then
773+
774
	else
775
		if useMiningLaserOffset then
776-
		local resType, x, y, z, id, meta, res = laserCamera.getScanResult()
776+
777-
		lx = x
777+
778-
		ly = y
778+
779-
		lz = z
779+
780-
		ship.command("MANUAL", false)
780+
781-
		local success, maxJumpDistance = ship.getMaxJumpDistance()
781+
782-
		if success ~= true then
782+
783-
			w.status_showWarning("" .. maxJumpDistance)
783+
784-
			return
784+
785
  for i, laserCamera in pairs(laserCameras) do
786-
		local rx, ry, rz = ship.getOrientation()
786+
    if laserCamera ~= nil and laserCamera.isInterfaced() then
787-
		minForwardBack = math.abs(ship_front+ship_back+1)
787+
      if (miningLaser == nil or miningLaser.isInterfaced() == nil) then
788-
		minLeftRight = math.abs(ship_left+ship_right+1)
788+
        useMiningLaserOffset = false
789
      end
790-
			local mx, my, mz = miningLaser.getLocalPosition()
790+
      local resType, x, y, z, id, meta, res = laserCamera.getScanResult()
791-
			dx = x-mx
791+
      lx = x
792-
			dz = z-mz
792+
      ly = y
793
      lz = z
794-
			local mx, my, mz = ship.getLocalPosition()
794+
      ship.command("MANUAL", false)
795-
			dx = x-mx
795+
      local success, maxJumpDistance = ship.getMaxJumpDistance()
796-
			dz = z-mz
796+
      if success ~= true then
797
        w.status_showWarning("" .. maxJumpDistance)
798
        return
799-
		forwardBackMov = 0
799+
800-
		leftRightMov = 0
800+
      local rx, ry, rz = ship.getOrientation()
801
      minForwardBack = math.abs(ship_front+ship_back+1)
802-
		if rx == 1 then
802+
      minLeftRight = math.abs(ship_left+ship_right+1)
803-
			forwardBackMov = dx
803+
      if useMiningLaserOffset then
804-
			leftRightMov = dz
804+
        local mx, my, mz = miningLaser.getLocalPosition()
805-
		elseif rx == -1 then
805+
        dx = x-mx
806-
			forwardBackMov = -dx
806+
        dz = z-mz
807-
			leftRightMov = -dz
807+
808-
		elseif rz == 1 then
808+
        local mx, my, mz = ship.getLocalPosition()
809-
			forwardBackMov = dz
809+
        dx = x-mx
810-
			leftRightMov = -dx
810+
        dz = z-mz
811-
		elseif rz == -1 then
811+
812-
			forwardBackMov = -dz
812+
813-
			leftRightMov = dx
813+
      forwardBackMov = 0
814
      leftRightMov = 0
815
816-
		if math.abs(forwardBackMov) < minForwardBack and math.abs(leftRightMov) < minLeftRight then
816+
      if rx == 1 then
817-
			w.status_showWarning("The movement is too small!")
817+
        forwardBackMov = dx
818-
			return
818+
        leftRightMov = dz
819
      elseif rx == -1 then
820
        forwardBackMov = -dx
821-
		leftRightMov = leftRightMov*1
821+
        leftRightMov = -dz
822-
		if laserGuideEnabled then
822+
      elseif rz == 1 then
823-
			ship.movement(forwardBackMov, 0, leftRightMov)
823+
        forwardBackMov = dz
824-
			ship.rotationSteps(0)
824+
        leftRightMov = -dx
825-
			ship.command("MANUAL", true)
825+
      elseif rz == -1 then
826
        forwardBackMov = -dz
827
        leftRightMov = dx
828
      end
829
830
      if math.abs(forwardBackMov) < minForwardBack and math.abs(leftRightMov) < minLeftRight then
831
        w.status_showWarning("The movement is too small!")
832
        return
833
      end
834
835
      leftRightMov = leftRightMov*1
836
      if laserGuideEnabled then
837
        ship.movement(forwardBackMov, 0, leftRightMov)
838
        ship.rotationSteps(0)
839
        ship.command("MANUAL", true)
840
      end
841
    end
842
  end
843
end
844
845
----------- Boot sequence
846
847
w.page_setEndText("Home(0),Controls(1),Crew(2),Navigation(3),Laser(4)")
848
w.page_register('0', connections_page, nil)
849
w.page_register('1', ship_page_controls, ship_key_controls)
850
w.page_register('2', ship_page_crew, ship_key_crew)
851
w.page_register('3', ship_page_navigation, ship_key_navigation)
852
w.page_register('4', laser_guide_page, laser_key)
853
ship_register()
854
855
w.boot()
856
local success, message = pcall(w.run)
857
if not success then
858
  print("failed with message")
859
  print(message)
860
  w.sleep(3.0)
861
  print("rebooting...")
862
  w.reboot()
863
else
864
  if ship ~= nil then
865
    ship.command("OFFLINE", true)
866
    ship.enable(false)
867
  end
868
  
869
  w.close()
870
end