forked from Otixa/horizon1
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Elevator.json
1110 lines (1110 loc) · 154 KB
/
Elevator.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{
"slots": {
"0": {
"name": "slot1",
"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": []
}
},
"10": {
"name": "slot11",
"type": {
"events": [],
"methods": []
}
},
"11": {
"name": "slot12",
"type": {
"events": [],
"methods": []
}
},
"12": {
"name": "slot13",
"type": {
"events": [],
"methods": []
}
},
"13": {
"name": "slot14",
"type": {
"events": [],
"methods": []
}
},
"14": {
"name": "slot15",
"type": {
"events": [],
"methods": []
}
},
"15": {
"name": "slot16",
"type": {
"events": [],
"methods": []
}
},
"16": {
"name": "slot17",
"type": {
"events": [],
"methods": []
}
},
"17": {
"name": "slot18",
"type": {
"events": [],
"methods": []
}
},
"18": {
"name": "slot19",
"type": {
"events": [],
"methods": []
}
},
"19": {
"name": "slot20",
"type": {
"events": [],
"methods": []
}
},
"20": {
"name": "slot21",
"type": {
"events": [],
"methods": []
}
},
"-3": {
"name": "library",
"type": {
"events": [],
"methods": []
}
},
"-2": {
"name": "system",
"type": {
"events": [],
"methods": []
}
},
"-1": {
"name": "unit",
"type": {
"events": [],
"methods": []
}
}
},
"handlers": [
{
"code": "--@class SimpleSlotDetector\r\ncore = nil\r\nantigrav = nil\r\nwarpDrive = nil\r\nradarUnitAtmo = nil\r\nradarUnitSpace = nil\r\nflightModeDb = nil\r\nmanualSwitches = {}\r\nforceFields = {}\r\nlasers = {}\r\nscreen = nil\r\nsettingsActive = false\r\nemitter = nil\r\ntelemeter = nil\r\n\r\nfunction getElements()\r\n\tfor _,var in pairs(_G) do\r\n\t\tif type(var) == \"table\" and var[\"getClass\"] then\r\n\t\t\tlocal class = string.lower(var[\"getClass\"]())\r\n\t\t\t--system.print(class)\r\n\t\t\tif class == \"coreunitdynamic\" or class == \"coreunitstatic\" or class == \"coreunitspace\" then\r\n\t\t\t\tcore = var\r\n\t\t\tend\r\n\t\t\t-- if class == \"atmofuelcontainer\" or class == \"spacefuelcontainer\" then\r\n\t\t\t-- \tvar.showWidget()\r\n\t\t\t-- end\r\n\t\t\tif class == \"warpdriveunit\" then\r\n\t\t\t\twarpDrive = var\r\n\t\t\t\tvar.showWidget()\r\n\t\t\tend\r\n\t\t\tif class == \"radarpvpatmospheric\" then\r\n\t\t\t\tradarUnitAtmo = var\r\n\t\t\t\tradarUnitAtmo.showWidget()\r\n\t\t\tend\r\n\t\t\tif class == \"radarpvpspace\" then\r\n\t\t\t\tradarUnitSpace = var\r\n\t\t\t\tradarUnitSpace.showWidget()\r\n\t\t\tend\r\n\t\t\tif class == \"databankunit\" then\r\n\t\t\t\tflightModeDb = var\r\n\t\t\tend\r\n\t\t\tif class == \"antigravitygeneratorunit\" then\r\n\t\t\t\tantigrav = var\r\n\t\t\tend\r\n\t\t\tif class == \"manualswitchunit\" then\r\n\t\t\t\ttable.insert(manualSwitches, var)\r\n\t\t\tend\r\n\t\t\tif class == \"forcefieldunit\" then\r\n\t\t\t\ttable.insert(forceFields, var)\r\n\t\t\tend\r\n\t\t\tif class == \"screenunit\" then\r\n\t\t\t\tscreen = var\r\n\t\t\tend\r\n\t\t\tif class == \"laseremitterunit\" then\r\n\t\t\t\ttable.insert(lasers, var)\r\n\t\t\tend\r\n\t\t\tif class == \"emitterunit\" then\r\n\t\t\t\temitter = var\r\n\t\t\tend\r\n\t\t\tif class == \"telemeterunit\" then\r\n\t\t\t\ttelemeter = var\r\n\t\t\tend\r\n\t\tend\r\n\tend\r\nend\r\n\r\nfunction toggleForceFields(state)\r\n\tif next(forceFields) then\r\n\t\tfor _, ff in ipairs(forceFields) do\r\n\t\t\tif state then\r\n\t\t\t\tff.deploy()\r\n\t\t\telse\r\n\t\t\t\tff.retract()\r\n\t\t\tend\r\n\t\tend\r\n\tend\r\nend\r\n\r\nfunction toggleLasers(state)\r\n\tif next(lasers) then\r\n\t\tfor _, laser in ipairs(lasers) do\r\n\t\t\tif state then\r\n\t\t\t\tlaser.activate()\r\n\t\t\telse\r\n\t\t\t\tlaser.deactivate()\r\n\t\t\tend\r\n\t\tend\r\n\tend\r\nend\r\n\r\nfunction toggleSwitches(state)\r\n\tif next(manualSwitches) then\r\n\t\tfor _, sw in ipairs(manualSwitches) do\r\n\t\t\tif state then\r\n\t\t\t\tsw.activate()\r\n\t\t\telse\r\n\t\t\t\tsw.deactivate()\r\n\t\t\tend\r\n\t\tend\r\n\tend\r\nend\r\n\r\ngetElements()\r\n",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "0"
},
{
"code": "--@class ExportedVariables\n\nshipName = \"\"\nupdateSettings = false --export: Use these settings\naltHoldPreset1 = 150000 --export: Altitude Hold Preset 1\naltHoldPreset2 = 1000 --export: Altitude Hold Preset 2\naltHoldPreset3 = 500 --export: Altitude Hold Preset 3\naltHoldPreset4 = 2 --export: Altitude Hold Preset 4\ndeviationThreshold = 0.5 --export: Deviation tolerace in m\ninertialDampening = true --export: Start with inertial dampening on/off\nfollowGravity = true --export: Start with gravity follow on/off\nminRotationSpeed = 0.01 --export: Minimum speed rotation scales from\nmaxRotationSpeed = 5 --export: Maximum speed rotation scales to\nrotationStep = 0.025 --export: Depermines how quickly rotation scales up\nverticalSpeedLimitAtmo = 1100 --export: Max vertical speed in atmosphere\nverticalSpeedLimitSpace = 4000 --export: Max vertical speed in space (100-10000)\napproachSpeed = 200 --export: Max final approach speed (50-300)\nautoShutdown = true --export: Auto shutoff on RTB landing\nbreadCrumbDist = 1000 --export: Distance of vector breadcrumbs for elevator control\nContainerOptimization = 0 --export: Container ContainerOptimization (0-5)\nFuelTankOptimization = 0 --export: Fuel Tank FuelTankOptimization (0-5)\nfuelTankHandlingAtmo = 0 --export: Fuel Tank Handling Atmo (0-5)\nfuelTankHandlingSpace = 0 --export: Fuel Tank Handling Space (0-5)\n\nprimaryColor = \"b80000\" --export: Primary color of HUD\nsecondaryColor = \"e30000\" --export: Secondary color of HUD\ntextShadow = \"e81313\" --export: Color of text shadow for speedometer\nfuelFontSize = 1.8 --export: Fuel Gauge Font Size\n\ndockingMode = 1 --export: Set docking mode (1:Manual, 2:Automatic, 3:Semi-Automatic)\nshowDockingWidget = false --export: Show Docking Widget\n\nsetBaseOnStart = false --export: Set RTB location on start\nuseGEAS = false --export: use ground engine altitude stabilization (GEAS)?\nGEAS_Alt = 10 --export: default hover altitude for GEAS in meters\n\nactivateFFonStart = false\nsetactivateFFonStart = false --export: Activate force field(s) on start (if linked directly)?\nactivateFFonStop = true\nsetactivateFFonStop = true --export: Deactivate force field(s) on stop (if linked directly)?\n\nactivateLasersOnStart = false\nsetactivateLasersOnStart = false --export: Activate laser(s) on start (if linked directly)?\nactivateLasersOnStop = true\nsetactivateLasersOnStop = true --export: Deactivate laser(s) on stop (if linked directly)?\n\nactivateSwitchOnStart = false\nsetactivateSwitchOnStart = false --export: Activate linked switch(es) on start?\nactivateSwitchOnStop = false\nsetactivateSwitchOnStop = false --export: Deactivate linked switch(es) on stop?\n\npocket = false\nsetpocket = false --export: Pocket ship?\nmouseSensitivity = 1 --export: Enter your mouse sensativity setting\n\nlockVerticalToBase = true --export: FOR ELEVATORS ONLY!\n\n--charMovement = true --export: Enable/Disable Character Movement",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "1"
},
{
"code": "--@class PlanetRef\nfunction PlanetRef()\n\tlocal function isNumber(n) return type(n) == 'number' end\n\tlocal function isSNumber(n) return type(tonumber(n)) == 'number' end\n\tlocal function isTable(t) return type(t) == 'table' end\n\tlocal function isString(s) return type(s) == 'string' end\n\tlocal function isVector(v) return isTable(v)\n\t\t\t\t\t\t\t\t\t\tand isNumber(v.x and v.y and v.z) end\n\n\tlocal function isMapPosition(m) return isTable(m) and isNumber(m.latitude and\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.longitude and\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.altitude and\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.bodyId and\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.systemId) end\n\n\t-- Constants\n\n\tlocal deg2rad = math.pi/180\n\tlocal rad2deg = 180/math.pi\n\tlocal epsilon = 1e-10\n\tlocal num = ' *([+-]?%d+%.?%d*e?[+-]?%d*)'\n\tlocal posPattern = '::pos{' .. num .. ',' .. num .. ',' .. num .. ',' ..\n\t\t\t\t\tnum .. ',' .. num .. '}'\n\n\t-- Utilities\n\n\tlocal utils = require('cpml.utils')\n\tlocal vec3 = require('cpml.vec3')\n\tlocal clamp = utils.clamp\n\n\tlocal function float_eq(a,b)\n\t\tif a == 0 then return math.abs(b) < 1e-09 end\n\t\tif b == 0 then return math.abs(a) < 1e-09 end\n\t\treturn math.abs(a - b) < math.max(math.abs(a),math.abs(b))*epsilon\n\tend\n\n\tlocal function formatNumber(n)\n\t\tlocal result = string.gsub(\n\t\t\t\t\t\tstring.reverse(string.format('%.4f',n)),\n\t\t\t\t\t\t'^0*%.?','')\n\t\treturn result == '' and '0' or string.reverse(result)\n\tend\n\n\tlocal function formatValue(obj)\n\t\tif isVector(obj) then\n\t\t\treturn string.format('{x=%.3f,y=%.3f,z=%.3f}', obj.x, obj.y, obj.z)\n\t\tend\n\n\t\tif isTable(obj) and not getmetatable(obj) then\n\t\t\tlocal list = {}\n\t\t\tlocal nxt = next(obj)\n\n\t\t\tif type(nxt) == 'nil' or nxt == 1 then -- assume this is an array\n\t\t\t\tfor i,a in ipairs(obj) do\n\t\t\t\t\tlist[i] = formatValue(a)\n\t\t\t\tend\n\t\t\telse\n\t\t\t\tfor k,v in pairs(obj) do\n\t\t\t\t\tlocal value = formatValue(v)\n\t\t\t\t\tif type(k) == 'number' then\n\t\t\t\t\t\ttable.insert(list, string.format('[%s]=%s', k, value))\n\t\t\t\t\telse\n\t\t\t\t\t\ttable.insert(list, string.format('%s=%s', k, value))\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\tend\n\t\t\treturn string.format('{%s}', table.concat(list, ','))\n\t\tend\n\n\t\tif isString(obj) then\n\t\t\treturn string.format(\"[[%s]]\", obj)\n\t\tend\n\t\treturn tostring(obj)\n\tend\n\n\t-- CLASSES\n\n\t-- BodyParameters: Attributes of planetary bodies (planets and moons)\n\n\tlocal BodyParameters = {}\n\tBodyParameters.__index = BodyParameters\n\tBodyParameters.__tostring =\n\t\tfunction(obj, indent)\n\t\t\tlocal keys = {}\n\t\t\tfor k in pairs(obj) do table.insert(keys, k) end\n\t\t\ttable.sort(keys)\n\t\t\tlocal list = {}\n\t\t\tfor _, k in ipairs(keys) do\n\t\t\t\tlocal value = formatValue(obj[k])\n\t\t\t\tif type(k) == 'number' then\n\t\t\t\t\ttable.insert(list, string.format('[%s]=%s', k, value))\n\t\t\t\telse\n\t\t\t\t\ttable.insert(list, string.format('%s=%s', k, value))\n\t\t\t\tend\n\t\t\tend\n\t\t\tif indent then\n\t\t\t\treturn string.format('%s%s',\n\t\t\t\t\t\t\t\t\tindent,\n\t\t\t\t\t\t\t\t\ttable.concat(list, ',\\n' .. indent))\n\t\t\tend\n\t\t\treturn string.format('{%s}', table.concat(list, ','))\n\t\tend\n\tBodyParameters.__eq = function(lhs, rhs)\n\t\t\treturn lhs.planetarySystemId == rhs.planetarySystemId and\n\t\t\t\tlhs.bodyId == rhs.bodyId and\n\t\t\t\tfloat_eq(lhs.radius, rhs.radius) and\n\t\t\t\tfloat_eq(lhs.center.x, rhs.center.x) and\n\t\t\t\tfloat_eq(lhs.center.y, rhs.center.y) and\n\t\t\t\tfloat_eq(lhs.center.z, rhs.center.z) and\n\t\t\t\tfloat_eq(lhs.GM, rhs.GM)\n\t\tend\n\n\tlocal function mkBodyParameters(systemId, bodyId, radius, worldCoordinates, GM)\n\t\t-- 'worldCoordinates' can be either table or vec3\n\t\tassert(isSNumber(systemId),\n\t\t\t'Argument 1 (planetarySystemId) must be a number:' .. type(systemId))\n\t\tassert(isSNumber(bodyId),\n\t\t\t'Argument 2 (bodyId) must be a number:' .. type(bodyId))\n\t\tassert(isSNumber(radius),\n\t\t\t'Argument 3 (radius) must be a number:' .. type(radius))\n\t\tassert(isTable(worldCoordinates),\n\t\t\t'Argument 4 (worldCoordinates) must be a array or vec3.' ..\n\t\t\ttype(worldCoordinates))\n\t\tassert(isSNumber(GM),\n\t\t\t'Argument 5 (GM) must be a number:' .. type(GM))\n\t\treturn setmetatable({planetarySystemId = tonumber(systemId),\n\t\t\t\t\t\t\tbodyId = tonumber(bodyId),\n\t\t\t\t\t\t\tradius = tonumber(radius),\n\t\t\t\t\t\t\tcenter = vec3(worldCoordinates),\n\t\t\t\t\t\t\tGM = tonumber(GM) }, BodyParameters)\n\tend\n\n\t-- MapPosition: Geographical coordinates of a point on a planetary body.\n\n\tlocal MapPosition = {}\n\tMapPosition.__index = MapPosition\n\tMapPosition.__tostring = function(p)\n\t\t\treturn string.format('::pos{%d,%d,%s,%s,%s}',\n\t\t\t\t\t\t\t\tp.systemId,\n\t\t\t\t\t\t\t\tp.bodyId,\n\t\t\t\t\t\t\t\tformatNumber(p.latitude*rad2deg),\n\t\t\t\t\t\t\t\tformatNumber(p.longitude*rad2deg),\n\t\t\t\t\t\t\t\tformatNumber(p.altitude))\n\t\tend\n\tMapPosition.__eq = function(lhs, rhs)\n\t\t\treturn lhs.bodyId == rhs.bodyId and\n\t\t\t\tlhs.systemId == rhs.systemId and\n\t\t\t\tfloat_eq(lhs.latitude, rhs.latitude) and\n\t\t\t\tfloat_eq(lhs.altitude, rhs.altitude) and\n\t\t\t\t(float_eq(lhs.longitude, rhs.longitude) or\n\t\t\t\t\tfloat_eq(lhs.latitude, math.pi/2) or\n\t\t\t\t\tfloat_eq(lhs.latitude, -math.pi/2))\n\t\tend\n\n\t-- latitude and longitude are in degrees while altitude is in meters\n\n\tlocal function mkMapPosition(overload, bodyId, latitude, longitude, altitude)\n\t\tlocal systemId = overload -- Id or '::pos{...}' string\n\n\t\tif isString(overload) and not longitude and not altitude and\n\t\t\t\t\t\t\t\tnot bodyId and not latitude then\n\t\t\tsystemId, bodyId, latitude, longitude, altitude =\n\t\t\t\t\t\t\t\t\t\t\t\tstring.match(overload, posPattern)\n\t\t\tassert(systemId, 'Argument 1 (position string) is malformed.')\n\t\telse\n\t\t\tassert(isSNumber(systemId),\n\t\t\t\t'Argument 1 (systemId) must be a number:' .. type(systemId))\n\t\t\tassert(isSNumber(bodyId),\n\t\t\t\t'Argument 2 (bodyId) must be a number:' .. type(bodyId))\n\t\t\tassert(isSNumber(latitude),\n\t\t\t\t'Argument 3 (latitude) must be in degrees:' .. type(latitude))\n\t\t\tassert(isSNumber(longitude),\n\t\t\t\t'Argument 4 (longitude) must be in degrees:' .. type(longitude))\n\t\t\tassert(isSNumber(altitude),\n\t\t\t\t'Argument 5 (altitude) must be in meters:' .. type(altitude))\n\t\tend\n\t\tsystemId = tonumber(systemId)\n\t\tbodyId = tonumber(bodyId)\n\t\tlatitude = tonumber(latitude)\n\t\tlongitude = tonumber(longitude)\n\t\taltitude = tonumber(altitude)\n\n\t\tif bodyId == 0 then -- this is a hack to represent points in space\n\t\t\treturn setmetatable({latitude = latitude,\n\t\t\t\t\t\t\t\tlongitude = longitude,\n\t\t\t\t\t\t\t\taltitude = altitude,\n\t\t\t\t\t\t\t\tbodyId = bodyId,\n\t\t\t\t\t\t\t\tsystemId = systemId}, MapPosition)\n\t\tend\n\t\treturn setmetatable({latitude = deg2rad*clamp(latitude, -90, 90),\n\t\t\t\t\t\t\tlongitude = deg2rad*(longitude % 360),\n\t\t\t\t\t\t\taltitude = altitude,\n\t\t\t\t\t\t\tbodyId = bodyId,\n\t\t\t\t\t\t\tsystemId = systemId}, MapPosition)\n\tend\n\n\t-- PlanetarySystem - map body IDs to BodyParameters\n\n\tlocal PlanetarySystem = {}\n\tPlanetarySystem.__index = PlanetarySystem\n\n\tPlanetarySystem.__tostring =\n\t\tfunction (obj, indent)\n\t\t\tlocal sep = indent and (indent .. ' ' )\n\t\t\tlocal bdylist = {}\n\t\t\tlocal keys = {}\n\t\t\tfor k in pairs(obj) do table.insert(keys, k) end\n\t\t\ttable.sort(keys)\n\t\t\tfor _, bi in ipairs(keys) do\n\t\t\t\tbdy = obj[bi]\n\t\t\t\tlocal bdys = BodyParameters.__tostring(bdy, sep)\n\t\t\t\tif indent then\n\t\t\t\t\ttable.insert(bdylist,\n\t\t\t\t\t\t\t\tstring.format('[%s]={\\n%s\\n%s}',\n\t\t\t\t\t\t\t\t\t\t\tbi, bdys, indent))\n\t\t\t\telse\n\t\t\t\t\ttable.insert(bdylist, string.format(' [%s]=%s', bi, bdys))\n\t\t\t\tend\n\t\t\tend\n\t\t\tif indent then\n\t\t\t\treturn string.format('\\n%s%s%s',\n\t\t\t\t\t\t\t\t\tindent,\n\t\t\t\t\t\t\t\t\ttable.concat(bdylist, ',\\n' .. indent),\n\t\t\t\t\t\t\t\t\tindent)\n\t\t\tend\n\t\t\treturn string.format('{\\n%s\\n}', table.concat(bdylist, ',\\n'))\n\t\tend\n\n\tlocal function mkPlanetarySystem(systemReferenceTable)\n\t\tlocal atlas = {}\n\t\tlocal pid\n\t\tfor _, v in pairs(systemReferenceTable) do\n\t\t\tlocal id = v.planetarySystemId\n\n\t\t\tif id == nil then\n\t\t\t\tid = 0\n\t\t\t\tv.planetarySystemId = id\n\t\t\tend\n\n\t\t\tif type(id) ~= 'number' then\n\t\t\t\terror('Invalid planetary system ID: ' .. tostring(id))\n\t\t\telseif pid and id ~= pid then\n\t\t\t\terror('Mismatch planetary system IDs: ' .. id .. ' and '\n\t\t\t\t\t.. pid)\n\t\t\tend\n\t\t\tlocal bid = v.bodyId\n\n\t\t\tif bid == nil then\n\t\t\t\tbid = v.id\n\t\t\t\tv.bodyId = bid\n\t\t\tend\n\t\t\tif type(bid) ~= 'number' then\n\t\t\t\terror('Invalid body ID: ' .. tostring(bid))\n\t\t\telseif atlas[bid] then\n\t\t\t\terror('Duplicate body ID: ' .. tostring(bid))\n\t\t\tend\n\t\t\tv.center = vec3(v.center)\n\t\t\tatlas[bid] = setmetatable(v, BodyParameters)\n\t\t\tpid = id\n\t\tend\n\t\treturn setmetatable(atlas, PlanetarySystem)\n\tend\n\n\t-- PlanetaryReference - map planetary system ID to PlanetarySystem\n\n\tPlanetaryReference = {}\n\n\tlocal function mkPlanetaryReference(referenceTable)\n\t\treturn setmetatable({ galaxyAtlas = referenceTable or {} },\n\t\t\t\t\t\t\tPlanetaryReference)\n\tend\n\n\tPlanetaryReference.__index =\n\t\tfunction(t,i)\n\t\t\tif type(i) == 'number' then\n\t\t\t\tlocal system = t.galaxyAtlas[i]\n\t\t\t\treturn mkPlanetarySystem(system)\n\t\t\tend\n\t\t\treturn rawget(PlanetaryReference, i)\n\t\tend\n\tPlanetaryReference.__pairs =\n\t\tfunction(obj)\n\t\t\treturn function(t, k)\n\t\t\t\t\t\tlocal nk, nv = next(t, k)\n\t\t\t\t\t\treturn nk, nv and mkPlanetarySystem(nv)\n\t\t\t\t\tend, obj.galaxyAtlas, nil\n\t\tend\n\tPlanetaryReference.__tostring =\n\t\tfunction (obj)\n\t\t\tlocal pslist = {}\n\t\t\tfor _,ps in pairs(obj or {}) do\n\t\t\t\tlocal psi = ps:getPlanetarySystemId()\n\t\t\t\tlocal pss = PlanetarySystem.__tostring(ps, ' ')\n\t\t\t\ttable.insert(pslist,\n\t\t\t\t\t\t\tstring.format(' [%s]={%s\\n }', psi, pss))\n\t\t\tend\n\t\t\treturn string.format('{\\n%s\\n}\\n', table.concat(pslist,',\\n'))\n\t\tend\n\tPlanetaryReference.BodyParameters = mkBodyParameters\n\tPlanetaryReference.MapPosition = mkMapPosition\n\tPlanetaryReference.PlanetarySystem = mkPlanetarySystem\n\n\tfunction PlanetaryReference.createBodyParameters(planetarySystemId,\n\t\t\t\t\t\t\t\t\t\t\t\t\tbodyId,\n\t\t\t\t\t\t\t\t\t\t\t\t\tsurfaceArea,\n\t\t\t\t\t\t\t\t\t\t\t\t\taPosition,\n\t\t\t\t\t\t\t\t\t\t\t\t\tverticalAtPosition,\n\t\t\t\t\t\t\t\t\t\t\t\t\taltitudeAtPosition,\n\t\t\t\t\t\t\t\t\t\t\t\t\tgravityAtPosition)\n\t\tassert(isSNumber(planetarySystemId),\n\t\t\t'Argument 1 (planetarySystemId) must be a number:' ..\n\t\t\ttype(planetarySystemId))\n\t\tassert(isSNumber(bodyId),\n\t\t\t'Argument 2 (bodyId) must be a number:' .. type(bodyId))\n\t\tassert(isSNumber(surfaceArea),\n\t\t\t'Argument 3 (surfaceArea) must be a number:' .. type(surfaceArea))\n\t\tassert(isTable(aPosition),\n\t\t\t'Argument 4 (aPosition) must be an array or vec3:' ..\n\t\t\ttype(aPosition))\n\t\tassert(isTable(verticalAtPosition),\n\t\t\t'Argument 5 (verticalAtPosition) must be an array or vec3:' ..\n\t\t\ttype(verticalAtPosition))\n\t\tassert(isSNumber(altitudeAtPosition),\n\t\t\t'Argument 6 (altitude) must be in meters:' ..\n\t\t\ttype(altitudeAtPosition))\n\t\tassert(isSNumber(gravityAtPosition),\n\t\t\t'Argument 7 (gravityAtPosition) must be number:' ..\n\t\t\ttype(gravityAtPosition))\n\t\tlocal radius = math.sqrt(surfaceArea/4/math.pi)\n\t\tlocal distance = radius + altitudeAtPosition\n\t\tlocal center = vec3(aPosition) + distance*vec3(verticalAtPosition)\n\t\tlocal GM = gravityAtPosition * distance * distance\n\t\treturn mkBodyParameters(planetarySystemId, bodyId, radius, center, GM)\n\tend\n\tPlanetaryReference.isMapPosition = isMapPosition\n\tfunction PlanetaryReference:getPlanetarySystem(overload)\n\t\tif self.galaxyAtlas then\n\t\t\tlocal planetarySystemId = overload\n\n\t\t\tif isMapPosition(overload) then\n\t\t\t\tplanetarySystemId = overload.systemId\n\t\t\tend\n\n\t\t\tif type(planetarySystemId) == 'number' then\n\t\t\t\tlocal system = self.galaxyAtlas[planetarySystemId]\n\t\t\t\tif system then\n\t\t\t\t\tif getmetatable(system) ~= PlanetarySystem then\n\t\t\t\t\t\tsystem = mkPlanetarySystem(system)\n\t\t\t\t\tend\n\t\t\t\t\treturn system\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\t\treturn nil\n\tend\n\n\tfunction PlanetarySystem:castIntersections(origin,\n\t\t\t\t\t\t\t\t\t\t\tdirection,\n\t\t\t\t\t\t\t\t\t\t\tsizeCalculator,\n\t\t\t\t\t\t\t\t\t\t\tbodyIds)\n\t\tlocal sizeCalculator = sizeCalculator or\n\t\t\t\t\t\t\t\tfunction (body) return 1.05*body.radius end\n\t\tlocal candidates = {}\n\n\t\tif bodyIds then\n\t\t\tfor _,i in ipairs(bodyIds) do candidates[i] = self[i] end\n\t\telse\n\t\t\tbodyIds = {}\n\t\t\tfor k,body in pairs(self) do\n\t\t\t\ttable.insert(bodyIds, k)\n\t\t\t\tcandidates[k] = body\n\t\t\tend\n\t\tend\n\t\tlocal function compare(b1,b2)\n\t\t\tlocal v1 = candidates[b1].center - origin\n\t\t\tlocal v2 = candidates[b2].center - origin\n\t\t\treturn v1:len() < v2:len()\n\t\tend\n\t\ttable.sort(bodyIds, compare)\n\t\tlocal dir = direction:normalize()\n\n\t\tfor i, id in ipairs(bodyIds) do\n\t\t\tlocal body = candidates[id]\n\t\t\tlocal c_oV3 = body.center - origin\n\t\t\tlocal radius = sizeCalculator(body)\n\t\t\tlocal dot = c_oV3:dot(dir)\n\t\t\tlocal desc = dot^2 - (c_oV3:len2() - radius^2)\n\n\t\t\tif desc >= 0 then\n\t\t\t\tlocal root = math.sqrt(desc)\n\t\t\t\tlocal farSide = dot + root\n\t\t\t\tlocal nearSide = dot - root\n\t\t\t\tif nearSide > 0 then\n\t\t\t\t\treturn body, farSide, nearSide\n\t\t\t\telseif farSide > 0 then\n\t\t\t\t\treturn body, farSide, nil\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\t\treturn nil, nil, nil\n\tend\n\n\tfunction PlanetarySystem:closestBody(coordinates)\n\t\tassert(type(coordinates) == 'table', 'Invalid coordinates.')\n\t\tlocal minDistance2, body\n\t\tlocal coord = vec3(coordinates)\n\n\t\tfor _,params in pairs(self) do\n\t\t\tlocal distance2 = (params.center - coord):len2()\n\t\t\tif not body or distance2 < minDistance2 then\n\t\t\t\tbody = params\n\t\t\t\tminDistance2 = distance2\n\t\t\tend\n\t\tend\n\t\treturn body\n\tend\n\n\tfunction PlanetarySystem:convertToBodyIdAndWorldCoordinates(overload)\n\t\tlocal mapPosition = overload\n\t\tif isString(overload) then\n\t\t\tmapPosition = mkMapPosition(overload)\n\t\tend\n\n\t\tif mapPosition.bodyId == 0 then\n\t\t\treturn 0, vec3(mapPosition.latitude,\n\t\t\t\t\t\tmapPosition.longitude,\n\t\t\t\t\t\tmapPosition.altitude)\n\t\tend\n\t\tlocal params = self:getBodyParameters(mapPosition)\n\n\t\tif params then\n\t\t\treturn mapPosition.bodyId,\n\t\t\t\tparams:convertToWorldCoordinates(mapPosition)\n\t\tend\n\tend\n\n\tfunction PlanetarySystem:getBodyParameters(overload)\n\t\tlocal bodyId = overload\n\n\t\tif isMapPosition(overload) then\n\t\t\tbodyId = overload.bodyId\n\t\tend\n\t\tassert(isSNumber(bodyId),'Argument 1 (bodyId) must be a number:' .. type(bodyId))\n\n\t\treturn self[bodyId]\n\tend\n\n\tfunction PlanetarySystem:getPlanetarySystemId()\n\t\tlocal _, v = next(self)\n\t\treturn v and v.planetarySystemId\n\tend\n\n\tfunction PlanetarySystem:netGravity(coordinates)\n\t\tassert(type(coordinates) == 'table', 'Invalid coordinates.')\n\t\tlocal netGravity = vec3()\n\t\tlocal coord = vec3(coordinates)\n\t\tlocal maxG, body\n\n\t\tfor _,params in pairs(self) do\n\t\t\tlocal radial = params.center - coord\n\t\t\tlocal len2 = radial:len2()\n\t\t\tlocal g = params.GM/len2\n\t\t\tif not body or g > maxG then\n\t\t\t\tbody = params\n\t\t\t\tmaxG = g\n\t\t\tend\n\t\t\tnetGravity = netGravity + g/math.sqrt(len2)*radial\n\t\tend\n\t\treturn body, netGravity\n\tend\n\n\tfunction BodyParameters:convertToMapPosition(worldCoordinates)\n\t\tassert(isTable(worldCoordinates),\n\t\t\t'Argument 1 (worldCoordinates) must be an array or vec3:' ..\n\t\t\ttype(worldCoordinates))\n\t\tlocal worldVec = vec3(worldCoordinates)\n\n\t\tif self.bodyId == 0 then\n\t\t\treturn setmetatable({latitude = worldVec.x,\n\t\t\t\t\t\t\t\tlongitude = worldVec.y,\n\t\t\t\t\t\t\t\taltitude = worldVec.z,\n\t\t\t\t\t\t\t\tbodyId = 0,\n\t\t\t\t\t\t\t\tsystemId = self.planetarySystemId}, MapPosition)\n\t\tend\n\t\tlocal coords = worldVec - self.center\n\t\tlocal distance = coords:len()\n\t\tlocal altitude = distance - self.radius\n\t\tlocal latitude = 0\n\t\tlocal longitude = 0\n\n\t\tif not float_eq(distance, 0) then\n\t\t\tlocal phi = math.atan(coords.y, coords.x)\n\t\t\tlongitude = phi >= 0 and phi or (2*math.pi + phi)\n\t\t\tlatitude = math.pi/2 - math.acos(coords.z/distance)\n\t\tend\n\t\treturn setmetatable({latitude = latitude,\n\t\t\t\t\t\t\tlongitude = longitude,\n\t\t\t\t\t\t\taltitude = altitude,\n\t\t\t\t\t\t\tbodyId = self.bodyId,\n\t\t\t\t\t\t\tsystemId = self.planetarySystemId}, MapPosition)\n\tend\n\n\tfunction BodyParameters:convertToWorldCoordinates(overload)\n\t\tlocal mapPosition = isString(overload) and\n\t\t\t\t\t\t\tmkMapPosition(overload) or overload\n\t\tif mapPosition.bodyId == 0 then -- support deep space map position\n\t\t\treturn vec3(mapPosition.latitude,\n\t\t\t\t\t\tmapPosition.longitude,\n\t\t\t\t\t\tmapPosition.altitude)\n\t\tend\n\t\tassert(isMapPosition(mapPosition),\n\t\t\t'Argument 1 (mapPosition) is not an instance of \"MapPosition\".')\n\t\tassert(mapPosition.systemId == self.planetarySystemId,\n\t\t\t'Argument 1 (mapPosition) has a different planetary system ID.')\n\t\tassert(mapPosition.bodyId == self.bodyId,\n\t\t\t'Argument 1 (mapPosition) has a different planetary body ID.')\n\t\tlocal xproj = math.cos(mapPosition.latitude)\n\t\treturn self.center + (self.radius + mapPosition.altitude) *\n\t\t\tvec3(xproj*math.cos(mapPosition.longitude),\n\t\t\t\t\txproj*math.sin(mapPosition.longitude),\n\t\t\t\t\tmath.sin(mapPosition.latitude))\n\tend\n\n\tfunction BodyParameters:getAltitude(worldCoordinates)\n\t\treturn (vec3(worldCoordinates) - self.center):len() - self.radius\n\tend\n\n\tfunction BodyParameters:getDistance(worldCoordinates)\n\t\treturn (vec3(worldCoordinates) - self.center):len()\n\tend\n\n\tfunction BodyParameters:getGravity(worldCoordinates)\n\t\tlocal radial = self.center - vec3(worldCoordinates) -- directed towards body\n\t\tlocal len2 = radial:len2()\n\t\treturn (self.GM/len2) * radial/math.sqrt(len2)\n\tend\n\n\treturn setmetatable(PlanetaryReference,\n\t\t{ __call = function(_,...)\n\t\t\treturn mkPlanetaryReference(...)\n\t\tend })\nend",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "2"
},
{
"code": "--@class KinematicsMin\nfunction Kinematics()local a={}local b=30000000/3600;local c=b*b;local d=100;local function e(f)return 1/math.sqrt(1-f*f/c)end;function a.computeAccelerationTime(g,h,i)local j=b*math.asin(g/b)return(b*math.asin(i/b)-j)/h end;function a.computeDistanceAndTime(g,i,k,l,m,n)m=m or 0;n=n or 0;local o=e(g)local p=g<=i;local q=l*(p and 1 or-1)/k;local r=-n/k;local s=q+r;if p and s<=0 or not p and s>=0 then return-1,-1 end;local t,u=0,0;if q~=0 and m>0 then local j=math.asin(g/b)local v=math.pi*(q/2+r)local w=q*m;local x=b*math.pi;local f=function(y)local z=(v*y-w*math.sin(math.pi*y/2/m)+x*j)/x;local A=math.tan(z)return b*A/math.sqrt(A*A+1)end;local B=p and function(C)return C>=i end or function(C)return C<=i end;u=2*m;if B(f(u))then local D=0;while math.abs(u-D)>0.5 do local y=(u+D)/2;if B(f(y))then u=y else D=y end end end;local E=g;local F=u/d;for G=1,d do local H=f(G*F)t=t+(H+E)*F/2;E=H end;if u<2*m then return t,u end;g=E end;local j=b*math.asin(g/b)local I=(b*math.asin(i/b)-j)/s;local J=c*math.cos(j/b)/s;local K=J-c*math.cos((s*I+j)/b)/s;return K+t,I+u end;function a.computeTravelTime(g,h,K)if K==0 then return 0 end;if h>0 then local j=b*math.asin(g/b)local J=c*math.cos(j/b)/h;return(b*math.acos(h*(J-K)/c)-j)/h end;assert(g>0,'Acceleration and initial speed are both zero.')return K/g end;function a.lorentz(f)return e(f)end;return a end",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "3"
},
{
"code": "--@class Serializer\nlocal concat = table.concat\nlocal sFormat = string.format\nlocal function internalSerialize(v,tC,t) local check = type(v) local intSerial=internalSerialize if check=='table' then t[tC]='{' local tempC=tC+1 if #v==0 then for k,e in pairs(v) do if type(k)~='number' then t[tempC]=k t[tempC+1]='=' tempC=tempC+2 else t[tempC]='[' t[tempC+1]=k t[tempC+2]=']=' tempC=tempC+3 end tempC=intSerial(e,tempC,t) t[tempC]=',' tempC=tempC+1 end else for k,e in pairs(v) do tempC=intSerial(e,tempC,t) t[tempC]=',' tempC=tempC+1 end end if tempC==(tC+1) then t[tempC]='}' return tempC+1 else t[tempC-1]='}' return tempC end elseif check=='string' then t[tC]=sFormat(\"%q\",v) return tC+1 elseif check=='number' then t[tC]=tostring(v) return tC+1 else t[tC]=v and 'true' or 'false' return tC+1 end end\nfunction serialize(v) local t={} local tC=1 local check = type(v) local intSerial=internalSerialize if check=='table' then t[tC]='{' tC=tC+1 local tempC=tC if #v==0 then for k,e in pairs(v) do if type(k)~='number' then t[tempC]=k t[tempC+1]='=' tempC=tempC+2 else t[tempC]='[' t[tempC+1]=k t[tempC+2]=']=' tempC=tempC+3 end tempC=intSerial(e,tempC,t) t[tempC]=',' tempC=tempC+1 end else for k,e in pairs(v) do tempC=intSerial(e,tempC,t) t[tempC]=',' tempC=tempC+1 end end if tempC==tC then t[tempC]='}' else t[tempC-1]='}' end elseif check=='string' then t[tC]=sFormat(\"%q\",v) elseif check=='number' then t[tC]=tostring(v) else t[tC]=v and 'true' or 'false' end return concat(t) end\nfunction deserialize(s) local f=load('t='..s) f() return t end\nfunction tryDeserialize(s) local f=load('t='..s) if f then f() return true, t else return false end end\nfunction mToKm(n)\n if n >= 10000 then\n return round2((n / 1000),2) .. \" km\"\n end\n return round2(n,2) .. \" m\"\nend\nfunction round2(num, numDecimalPlaces)\n if num ~= nil then\n \treturn tonumber(string.format(\"%.\" .. (numDecimalPlaces or 0) .. \"f\", num))\n end\nend\nconfig = {\n dataType = \"config\",\n floors = {\n floor1 = 0,\n floor2 = 0,\n floor3 = 0,\n floor4 = 0,\n },\n elevatorName = construct.getName(),\n rtb = 0,\n targetAlt = 0,\n estop = false,\n settingsActive = false,\n setBaseActive = false,\n setBaseReq = false,\n manualControl = false,\n destination = nil,\n shutDown = false,\n updateReq = false,\n }\n\nstats = {\n\tdataType = \"stats\",\n\tdata = {\n\t\televation = 0,\n\t\ttarget = config.targetAlt,\n\t\tvelocity = 0,\n\t\tmass = 0,\n\t\tgravity = 0,\n\t\ttarget_dist = 0,\n\t\tbrake_dist = 0,\n\t\tdeviation = 0,\n\t\tdeviationVec = vec3(),\n\t\tdeviationRot = vec3(),\n\t\tdeviationRotAngle = 0,\n\t\tstate = \"Idle\",\n\t\tdelta = 0,\n\t\tgrounddistance = 0,\n\t\tbase = nil,\n \tagl = 0,\n\t}\n}\nfuelAtmo = {\n dataType = \"fuelAtmo\",\n tanks = {}\n}\n\nfuelSpace = {\n dataType = \"fuelSpace\",\n tanks = {}\n}\n\nfunction fuelTank(tm,pct)\n local mt = {}\n mt.__index = mt\n return setmetatable({\n tm = tm,\n pct = pct\n },mt)\nend",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "4"
},
{
"code": "--@class EventDelegateMin\nfunction EventDelegate()local a={}a.Delegates={}function a.Add(b)if type(b)~=\"function\"then error(\"[EventDelegate] Unable to add callback - not a function\")return end;for c=1,#a.Delegates do if a.Delegates[c]==b then return false end end;table.insert(a.Delegates,b)return true end;function a.Remove(b)if type(b)~=\"function\"then error(\"[EventDelegate] Unable to remove callback - not a function\")return end;for c=1,#a.Delegates do if a.Delegates[c]==b then table.remove(a.Delegates,c)return true end end;return false end;function a.Call(...)for c=1,#a.Delegates do a.Delegates[c](...)end end;function a.Count()return#a.Delegates end;setmetatable(a,{__call=function(d,...)a.Call(...)end,__add=function(e,f)if e==a then a.Add(f)return a end;if f==a then a.Add(e)return a end;return a end,__sub=function(e,f)if e==a then a.Remove(f)return a end;if f==a then a.Remove(e)return a end;return a end,__tostring=function()return\"EventDelegate(#\"..#a.Delegates..\")\"end})return a end;Events={Update=EventDelegate(),Flush=EventDelegate()}",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "5"
},
{
"code": "--@class TaskManagerMin\nTaskManager=(function()local self={}self.Stack={}function self.Register(a)if not a.Coroutine then error(\"[TaskManager] Trying to register a non-Task\")end;table.insert(self.Stack,a)end;function self.Update()for b=1,#self.Stack do local a=self.Stack[b]if a and a.Coroutine~=nil then if coroutine.status(a.Coroutine)~=\"dead\"then local c,d=coroutine.resume(a.Coroutine)a.Error=not c;a.LastReturn=d else table.remove(self.Stack,b)if a.Error and a._Catch then a._Catch(a.LastReturn)elseif a._Then~=nil then a._Then(a.LastReturn)end;if a._Finally~=nil then a._Finally()end;a.Finished=true end end end end;return self end)()function Task(e)local self={}self.LastReturn=nil;self.Error=nil;self.Finished=false;if type(e)~=\"function\"then error(\"[Task] Not a function.\")end;self.Coroutine=coroutine.create(e)function self.Then(e)if type(e)~=\"function\"then error(\"[Task] Then callback not a function.\")end;self._Then=e;return self end;function self.Finally(e)if type(e)~=\"function\"then error(\"[Task] Finally callback not a function.\")end;self._Finally=e;return self end;function self.Catch(e)if type(e)~=\"function\"then error(\"[Task] Catch callback not a function.\")end;self._Catch=e;return self end;TaskManager.Register(self)return self end;function await(a)if not a or not a.Coroutine then error(\"Trying to await non-task object\")end;while not a.Finished do coroutine.yield()end;return a.LastReturn end",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "6"
},
{
"code": "--@class DynamicDocumentMin\nfunction DynamicDocument(a)local self={}self.template=a or\"\"local b=\"\"local c={}self.tree={}local d={br=true,hr=true,img=true,embed=true,param=true,area=true,col=true,input=true,meta=true,link=true,base=true,basefont=true,iframe=true,isindex=true,circle=true,polygon=true,polyline=true,ellipse=true,path=true,line=true,rect=true,use=true}function table.indexOf(val,table)for e,f in ipairs(table)do if f==val then return e end end;return nil end;function self.makeFunc(string)local val=\"nil\"if c[string]==nil then local g,h=pcall(load(\"return function() return \"..string..\" end\",nil,\"t\",_ENV))if g then c[string]=h;val=h()if type(val)==\"function\"then c[string]=h()val=val()end end else val=c[string]()end;return val end;local function i(a)local j=0;local k={}local l={}l.dd={}table.insert(k,l)local node={}for m,n,o,p,q,r,val,s in string.gmatch(a,\"(<)(%/?!?)([%w:_-'\\\\\\\"%[]+)(.-)(%/?%-?)>([%s\\r\\n\\t]*)([^<]*)([%s\\r\\n\\t]*)\")do o=string.lower(o)if n==\"/\"then if j==0 then return l end;j=j-1;table.remove(k)else local function t(u)local v=\"dd-\"return u:sub(1,#v)==v end;j=j+1;node={}node.name=o;node.children={}node.attr={}if k[j-1]then node.parent=k[j-1][#k[j-1]]else node.parent=nil end;if p~=\"\"then for w,f in string.gmatch(p,\"%s([^%s=]+)=\\\"([^\\\"]+)\\\"\")do node.attr[w]=string.gsub(f,'\"','[^\\\\]\\\\\"')if t(w)then if not l.dd[w]then l.dd[w]={}end;table.insert(l.dd[w],node)end end;for w,f in string.gmatch(p,\"%s([^%s=]+)='([^']+)'\")do node.attr[w]=string.gsub(f,'\"','[^\\\\]\\\\\"')if t(w)then if not l.dd[w]then l.dd[w]={}end;table.insert(l.dd[w],node)end end end;if not k[j]then k[j]={}end;table.insert(k[j],node)if d[o]then if val~=\"\"then table.insert(k[j],{name=\"textNode\",value=val})end;node.children={}j=j-1 else if val~=\"\"then table.insert(node.children,{name=\"textNode\",value=val})end;table.insert(k,node.children)end end end;return l end;local function x(y,z)local k={y}local A=\"\"local function B(C)local D=0;for E in pairs(C)do D=D+1 end;return D end;if not z and B(y.dd)>0 then if y.dd[\"dd-repeat\"]then for F=#y.dd[\"dd-repeat\"],1,-1 do local node=y.dd[\"dd-repeat\"][F]var,array=string.match(node.attr[\"dd-repeat\"],\"(.*) in (.*)\")node.attr[\"dd-repeat\"]=nil;local G=x({node},true)local H=string.gmatch(G,\"{{([^}}]+)}}\")local I={}for J in H do if string.match(J,var)then table.insert(I,J)end end;local b=\"\"local K=self.makeFunc(array)for F=1,#K do _ENV[var]=K[F]local L=G;local M=i(L:gsub(\"^%s*(.-)%s*$\",\"%1\"))b=b..x(M)end;node.children={}node.name=\"textNode\"node.value=b end end;if y.dd[\"dd-if\"]then for F=#y.dd[\"dd-if\"],1,-1 do local node=y.dd[\"dd-if\"][F]local N=self.makeFunc(node.attr[\"dd-if\"])if N then node.attr[\"dd-if\"]=nil else local O=table.indexOf(node,node.parent.children)if O then table.remove(node.parent.children,O)end;node=nil;table.remove(y.dd[\"dd-if\"],F)y.dd[\"dd-if\"][F]=nil end end end;if y.dd[\"dd-init\"]then for F=#y.dd[\"dd-init\"],1,-1 do local node=y.dd[\"dd-init\"][F]pcall(load(node.attr[\"dd-init\"],nil,\"t\",_ENV))node.attr[\"dd-init\"]=nil end end end;while#k~=0 do node=k[#k][1]if not node then break end;if node.name==\"textNode\"then local val=node.value:gsub(\"^%s*(.-)%s*$\",\"%1\")if not z then val=self.transformClosures(val)end;A=A..val else A=A..\"\\n\"..string.rep(\" \",#k-1)A=A..\"<\"..node.name;if node.attr then for P,f in pairs(node.attr)do if not z then P=self.transformClosures(P)f=self.transformClosures(f)end;A=A..\" \"..P..'=\"'..f..'\"'end end;if d[node.name]then A=A..\"/>\"else A=A..\">\"end end;if node.children and#node.children>0 then table.insert(k,node.children)else table.remove(k[#k],1)if node.children and#node.children==0 and not d[node.name]and not node.name==\"textNode\"then A=A..\"</\"..node.name..\">\"end;while#k>0 and#k[#k]==0 do table.remove(k)if#k>0 then if#k[#k][1].children>1 then A=A..\"\\n\"..string.rep(\" \",#k-1)..\"</\"..k[#k][1].name..\">\"else A=A..\"</\"..k[#k][1].name..\">\"end;table.remove(k[#k],1)end end end end;return A:match\"^%s*(.-)%s*$\"end;function self.transformClosures(Q)local R={}local S=string.gmatch(Q,\"{{([^}}]+)}}\")for F in S do table.insert(R,F)end;if#R>0 then for F=1,#R do local T=R[F]val=self.makeFunc(T)Q=string.gsub(Q,self.literalize(\"{{\"..T..\"}}\"),tostring(val))end end;return Q end;function self.literalize(u)return u:gsub(\"[%(%)%.%%%+%-%*%?%[%]%^%$]\",function(J)return\"%\"..J end)end;function self.Read()return x(i(self.template))end;return self end",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "7"
},
{
"code": "--@class DUTTYMin\nDUTTY={}local a={}local b={}local function c(d,e)return d:sub(e,e)end;local function f(d)local g={}local h=false;local i=''local j=false;for k=1,#d do local l=c(d,k)if j==false and h and l==h then table.insert(g,i)h=false;i=''elseif j==false and#i==0 and(not h and(l=='\"'or l==\"'\"))then h=l elseif j==false and l==' 'and h==false then if#i>0 then table.insert(g,i)i=''end elseif j==false and l=='\\\\'then j=true else if j then j=false end;i=i..l end end;if#i>0 then table.insert(g,i)end;return g end;function DUTTY.input(d)for k,m in pairs(a)do if'function'==type(m)then m(d)end end;local n=f(d)if#n>0 then local o=''local p={}for k,d in pairs(n)do if k==1 then o=d:lower()else table.insert(p,d)end end;if b[o]and'function'==type(b[o])then b[o](table.unpack(p))end end end;function DUTTY.onInput(m)if not'function'==type(m)then error('Event handler must be of type function')end;table.insert(a,m)end;function DUTTY.onCommand(g,m)if not'function'==type(m)then error('Event handler must be of type function')end;b[g:lower()]=m end",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "8"
},
{
"code": "--@class FuelTankHelper\n-- system.print(\"ContainerOp\"..ContainerOptimization)\nfuelTanks = {}\nFuelMass = {}\nFuelTime = {}\nfuelTypes = {\n atmo = {\n\tdensity = 4.000,\n },\n space = {\n\tdensity = 6.000,\n },\n rocket = {\n\tdensity = 0.800,\n },\n}\nlocal function calcAtmoVolume(baseCap)\n if fuelTankHandlingAtmo > 0 then\n\treturn baseCap + (baseCap * (fuelTankHandlingAtmo * 0.2))\n end\n return baseCap\nend\nlocal function calcSpaceVolume(baseCap)\n if fuelTankHandlingSpace > 0 then\n\treturn baseCap + (baseCap * (fuelTankHandlingSpace * 0.2))\n end\n return baseCap\nend\nlocal function calcMaxMass(cap, type)\n local maxMass = cap * fuelTypes[type].density\n\n local adjustedMaxMass = maxMass\n if ContainerOptimization > 0 then adjustedMaxMass = maxMass - (maxMass * ContainerOptimization * 0.05) end\n if FuelTankOptimization > 0 then adjustedMaxMass = adjustedMaxMass - (maxMass * FuelTankOptimization * 0.05) end\n\n return adjustedMaxMass\nend\nfunction normalizeHp(type,hp)\n local adjHp = 0\n\n if type == \"atmo\" then\n\tif hp >= 50 and hp < 163 then adjHp = 50\n\telseif hp >= 163 and hp < 1315 then adjHp = 163\n\telseif hp >= 1315 and hp < 10461 then adjHp = 1315\n\telseif hp >= 10461 then adjHp = 10461 end\n elseif type == \"space\" then\n\tif hp >= 50 and hp < 187 then adjHp = 50\n\telseif hp >= 187 and hp < 1496 then adjHp = 187\n\telseif hp >= 1496 and hp < 15933 then adjHp = 1496\n\telseif hp >= 15933 then adjHp = 15933 end\n elseif type == \"rocket\" then\n\tif hp >= 366 and hp < 736 then adjHp = 366\n\telseif hp >= 736 and hp < 6231 then adjHp = 736\n\telseif hp >= 6231 and hp < 68824 then adjHp = 6231\n\telseif hp >= 68824 then adjHp = 68824 end\n end\n\n return adjHp\nend\nfunction normalizeHpAtmo(hp)\n\nend\nfunction normalizeHpSpace(hp)\n -- 187\n -- 1496\n -- 15933\nend\n\nfunction normalizeHpRocket(hp)\n -- 366\n -- 736\n -- 6231\n -- 68824\nend\n\nfuelTankSpecsByMaxHP = {\n -- Atmo Tanks\n atmo = {\n\t_50 = {\n\t type = \"atmo\",\n\t size = \"XS\",\n\t capacity = function() return calcAtmoVolume(100) end,\n\t baseWeight = 35.030,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(100),\"atmo\") end,\n\t},\n\t_163 = {\n\t type = \"atmo\",\n\t size = \"S\",\n\t capacity = function() return calcAtmoVolume(400) end,\n\t baseWeight = 182.670,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(400),\"atmo\") end,\n\t},\n\t_1315 = {\n\t type = \"atmo\",\n\t size = \"M\",\n\t capacity = function() return calcAtmoVolume(1600) end,\n\t baseWeight = 988.670,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(1600),\"atmo\") end,\n\t},\n\t_10461 = {\n\t type = \"atmo\",\n\t size = \"L\",\n\t capacity = function() return calcAtmoVolume(12800) end,\n\t baseWeight = 5480.000,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(12800),\"atmo\") end,\n\t},\n },\n\n -- Space Tanks\n space = {\n\t_50 = {\n\t type = \"space\",\n\t size = \"XS\",\n\t capacity = function() return calcAtmoVolume(100) end,\n\t baseWeight = 35.030,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(100),\"space\") end,\n\t},\n\t_187 = {\n\t type = \"space\",\n\t size = \"S\",\n\t capacity = function() return calcSpaceVolume(400) end,\n\t baseWeight = 182.670,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(400),\"space\") end,\n\t},\n\t_1496 = {\n\t type = \"space\",\n\t size = \"M\",\n\t capacity = function() return calcSpaceVolume(1600) end,\n\t baseWeight = 988.670,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(1600),\"space\") end,\n\t},\n\t_15933 = {\n\t type = \"space\",\n\t size = \"L\",\n\t capacity = function() return calcSpaceVolume(12800) end,\n\t baseWeight = 5480.000,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(12800),\"space\") end,\n\t},\n },\n\n -- Rocket Tanks\n rocket = {\n\t_366 = {\n\t type = \"rocket\",\n\t size = \"XS\",\n\t capacity = function() return 400 end,\n\t baseWeight = 173.420,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(400),\"rocket\") end,\n\t},\n\t_736 = {\n\t type = \"rocket\",\n\t size = \"S\",\n\t capacity = function() return 800 end,\n\t baseWeight = 886.720,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(800),\"rocket\") end,\n\t},\n\t_6231 = {\n\t type = \"rocket\",\n\t size = \"M\",\n\t capacity = function() return 6400 end,\n\t baseWeight = 4720.000,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(6400),\"rocket\") end,\n\t},\n\t_68824 = {\n\t type = \"rocket\",\n\t size = \"L\",\n\t capacity = function() return 50000 end,\n\t baseWeight = 25740.000,\n\t maxWeight = function() return calcMaxMass(calcAtmoVolume(50000),\"rocket\") end,\n\t},\n },\n}\n\nlocal function isINF(value)\n return value == math.huge or value == -math.huge\nend\n\nlocal function isNAN(value)\n return value ~= value\nend\n\nfunction disp_time(time)\n if isINF(time) or isNAN(time) then return \"-:-\" end\n local days = math.floor(time/86400)\n local hours = math.floor(math.fmod(time, 86400)/3600)\n local minutes = math.floor(math.fmod(time,3600)/60)\n local seconds = math.floor(math.fmod(time,60))\n if time >= 86400 then\n\t return string.format(\"%dd:%02dh\",days,hours)\n elseif time < 86400 and time > 3600 then\n\t return string.format(\"%02dh:%02dm:%02ds\",hours,minutes,seconds)\n elseif time < 3600 and time > 60 then\n\t return string.format(\"%02dm:%02ds\",minutes,seconds)\n else\n\t return string.format(\"%02ds\",seconds)\n end\nend\n\nlocal unpack = table.unpack\n\nfunction fuelUsed(period)\n\tlocal t = {}\n\tfunction sum(a, ...)\n\t\tif a then\n\t\t\treturn a-sum(...)\n\t\telse\n\t\t\treturn 0\n\t\tend\n\tend\n\tfunction average(n)\n\t\tif #t == period then table.remove(t, 1) end\n\t\tif n ~= 0 and n ~= nil then t[#t + 1] = n end\n\t\treturn sum(unpack(t))\n\tend\n\treturn average\nend\n\nlocal function sort(tanks)\n\tif next(tanks) then\n\t\ttable.sort(tanks, function(a,b) return a.name < b.name end)\n\tend\nend\n\nfunction getFuelSituation()\n local tanks = {\n\tatmo = {},\n\tspace = {},\n\trocket = {},\n }\n\n for id, specs in pairs(fuelTanks) do\n\ttable.insert(tanks[specs.type], {\n\t name = core.getElementNameById(id),\n\t level = getFuelTankLevel(id),\n\t time = getFuelTime(id),\n\t specs = specs,\n\t})\n end\n\n sort(tanks.atmo)\n sort(tanks.space)\n sort(tanks.rocket)\n return tanks\nend\n\nfunction getFuelTankSpecs(fuelTankType, fuelTankId)\n local maxHP = math.floor(core.getElementMaxHitPointsById(fuelTankId))\n-- system.print(fuelTankType..\"........\"..maxHP)\n return fuelTankSpecsByMaxHP[fuelTankType]['_' .. normalizeHp(fuelTankType,maxHP)]\nend\n\nfunction getFuelTankLiters(fuelTankId)\n local fuelTankSpecs = fuelTanks[fuelTankId]\n local massTotal = core.getElementMassById(fuelTankId)\n local massContents = massTotal - fuelTankSpecs.baseWeight\n return massContents\nend\n--vanillaMaxVolume = vanillaMaxVolume - (vanillaMaxVolume * ContainerOptimization * 0.05)\nfunction getFuelTankLevel(fuelTankId)\n local fuelTankSpecs = fuelTanks[fuelTankId]\n local adjustedMaxMass = fuelTankSpecs.maxWeight()\n return getFuelTankLiters(fuelTankId) / adjustedMaxMass\nend\n\nfunction getFuelTime(fuelTankId)\n local fuelTankSpecs = fuelTanks[fuelTankId]\n local lastUpdate = FuelTime[fuelTankId] or system.getArkTime()\n local deltaTime = math.max(system.getArkTime() - lastUpdate, 0.001)\n local massTotal = core.getElementMassById(fuelTankId)\n local minMass = fuelTankSpecs.baseWeight\n local fuelUsed = FuelMass[fuelTankId](massTotal)\n local fuelTime = (deltaTime / fuelUsed) * (massTotal - minMass)\n local fuelTimeFormatted = disp_time(fuelTime)\n FuelTime[fuelTankId] = system.getArkTime()\n return fuelTimeFormatted\nend\n\nfunction getFuelTanks()\n local elementIds = core.getElementIdList()\n for k, elementId in pairs(elementIds) do\n\tlocal elementType = core.getElementDisplayNameById(elementId)\n\t-- Fuel tank configuration routine\n\tif elementType == \"Atmospheric Fuel Tank\" then\n\t --system.print(elementType..\"_\"..elementId)\n\t local tank = getFuelTankSpecs(\"atmo\", elementId)\n\t fuelTanks[elementId] = tank\n\t FuelMass[elementId] = fuelUsed(2)\n\telseif elementType == \"Space Fuel Tank\" then\n\t fuelTanks[elementId] = getFuelTankSpecs(\"space\", elementId)\n\t FuelMass[elementId] = fuelUsed(2)\n\telseif elementType == \"Rocket Fuel Tank\" then\n\t fuelTanks[elementId] = getFuelTankSpecs(\"rocket\", elementId)\n\t FuelMass[elementId] = fuelUsed(2)\n\tend\n end\n\n-- for _, v in ipairs(fuelTankSpecsByMaxHP) do\n-- --system.print(\"Fuel Tank: \"..v)\n-- for k,t in ipairs(v) do\n-- for x,y in pairs(t) do\n-- --system.print(\"Capacity: \"..y.capacity())\n-- end\n-- end\n-- end\nend\n\ngetFuelTanks()\n",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "9"
},
{
"code": "--@class KeybindControllerMin\nfunction Keybind(a)local self={}self.Key=a;local b={}function self.Add(c,d)if type(c)~=\"function\"then error(\"[Keybind] Unable to add callback - not a function\")end;table.insert(b,{Function=c,Name=d})end;function self.Remove(c)if type(c)~=\"function\"then error(\"[Keybind] Unable to remove callback - not a function\")end;local e={}for f,g in pairs(b)do e[g.Function]=f end;for f,g in pairs(e)do if f==c then b[g]=nil end end end;function self.GetNames()local h={}for f,g in pairs(b)do if g.Name then table.insert(h,g.Name)end end;return h end;function self.Call()for f,g in pairs(b)do g.Function(self.Key)end end;return self end;function KeybindController()local self={}local i={\"forward\",\"backward\",\"left\",\"right\",\"yawleft\",\"yawright\",\"up\",\"down\",\"gear\",\"light\",\"landing\",\"brake\",\"option1\",\"option2\",\"option3\",\"option4\",\"option5\",\"option6\",\"option7\",\"option8\",\"option9\",\"stopengines\",\"speedup\",\"speeddown\",\"antigravity\",\"booster\",\"lshift\",\"lalt\",\"lalt\",\"strafeleft\",\"straferight\"}self.keyUp={}self.keyDown={}self.keyLoop={}function self.Call(j,type)if type==\"up\"then if self.keyUp[j]then self.keyUp[j].Call(j)end elseif type==\"down\"then if self.keyDown[j]then self.keyDown[j].Call(j)end else if self.keyLoop[j]then self.keyDown[j].Call(j)end;system.print(j)end end;function self.GetNamedKeybinds()local h={}for f,g in pairs(self.keyUp)do local k=g.GetNames()if#k>0 then for l=1,#k do table.insert(h,{Key=g.Key,Name=k[l]})end end end;for f,g in pairs(self.keyDown)do local k=g.GetNames()if#k>0 then for l=1,#k do table.insert(h,{Key=g.Key,Name=k[l]})end end end;for f,g in pairs(self.keyLoop)do local k=g.GetNames()if#k>0 then for l=1,#k do table.insert(h,{Key=g.Key,Name=k[l]})end end end;table.sort(h,function(m,n)return m.Key<n.Key end)return h end;self.Init=function()end;local function o()for l=1,#i do self.keyUp[i[l]]=Keybind(i[l])self.keyDown[i[l]]=Keybind(i[l])self.keyLoop[i[l]]=Keybind(i[l])end end;o()return self end;keybindPresets={}",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "10"
},
{
"code": "--@class IOScheduler\n\n--[[\nCustom IO scheduler to deal with limited data packet size\nand tick rate of screen send/receive. IOScheduler.defaultData\nwill send as fast as possible, while IOScheduler.queueData()\nwill interrupt default send and to send queued data.\n--]]\n\nIOScheduler = (function()\n local self = {}\n\n self.defaultData = nil\n self.currentTask = nil\n self.taskQueue = {}\n function self.queueData(data)\n table.insert(self.taskQueue, data)\n end\n --Send queued data to screen\n function self.send(T)\n\t\tif not screen then return end\n output = screen.getScriptOutput()\n screen.clearScriptOutput()\n if output ~= \"ack\" then\n if output and output ~= \"\" then\n handleOutput.Read(output)\n end\n coroutine.yield()\n self.send(T)\n else\n screen.setScriptInput(serialize(T))\n end\n end\n --Queue data to send or send self.defaultData\n function self.runQueue()\n if #self.taskQueue == 0 then\n --Send default table\n if self.defaultData ~= nil then\n\t\t\t\tself.currentTask = coroutine.create(function()\n\t\t\t\t\tself.send(self.defaultData)\n\t\t\t\tend)\n coroutine.resume(self.currentTask)\n end\n else\n --Iterate over self.taskQueue and send each to screen\n self.currentTask = coroutine.create(function()\n for i=1, #self.taskQueue do\n local data = self.taskQueue[i]\n if type(data) == \"table\" then\n self.send(data)\n end\n table.remove(self.taskQueue,i)\n end\n end)\n coroutine.resume(self.currentTask)\n end\n end\n\n --Add to system.update()\n function self.update()\n if self.currentTask then\n if coroutine.status(self.currentTask) ~= \"dead\" then\n coroutine.resume(self.currentTask)\n else\n self.runQueue()\n end\n else\n self.runQueue()\n end\n end\n\n return self\nend)()\n\nHandleOutput = (function()\n local self = {}\n function self.Read(output)\n\t\tif type(output) ~= \"string\" or output == \"\" then\n\t\t\treturn\n\t\tend\n\t\tlocal s = deserialize(output)\n\t\tif type(s) ~= \"table\" then\n\t\t\tsystem.print('[E] Communication error!')\n\t\t\treturn\n\t\tend\n\t\tif s.dataType == \"config\" then\n\t\t\tconfig = s\n\t\t\t-- fix for +/- 10m buttons: use \"delta\" as altitude-delta\n\t\t\tlocal delta = tonumber(config.delta)\n\t\t\tif delta ~= nil then\n\t\t\t\tconfig.targetAlt = ship.altitude + delta\n\t\t\tend\n\t\t\tstats.data.target = config.targetAlt\n\t\t\tself.Execute()\n\t\telseif s.updateReq then\n\t\t\tioScheduler.queueData(config)\n\t\t-- else\n\t\t-- \tsystem.print(tostring(s))\n\t\tend\n end\n\n function self.Execute()\n ship.baseAltitude = helios:closestBody(ship.baseLoc):getAltitude(ship.baseLoc)\n\n ship.altitudeHold = config.targetAlt\n\n if config.estop then\n config.targetAlt = 0\n ship.altitudeHold = 0\n ship.brake = true\n ship.elevatorActive = false\n ship.verticalLock = false\n ship.stateMessage = \"EMERGENCY STOP\"\n system.print(ship.stateMessage)\n ioScheduler.queueData(config)\n else\n ship.brake = false\n end\n manualControlSwitch()\n if not config.manualControl and ship.altitudeHold > 0 then\n ship.elevatorActive = true\n ship.targetDestination = moveWaypointZ(ship.baseLoc, config.targetAlt - ship.baseAltitude)\n end\n if config.setBaseReq then\n setBase()\n config.setBaseReq = false\n ioScheduler.queueData(config)\n end\n --if config.updateReq then\n -- config.updateReq = false\n -- ioScheduler.queue(config)\n --end\n end\n\n return self\nend)()\n\nioScheduler = IOScheduler\nhandleOutput = HandleOutput",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "11"
},
{
"code": "--@class Utils3D\n\n-- safe version\nfunction angle_between(vec1, vec2)\n if not(vec3.isvector(vec1) and vec3.isvector(vec2)) then return 0 end\n\tlocal len1 = vec1:len()\n\tlocal len2 = vec2:len()\n\tif len1 ~= 0 and len2 ~= 0 then\n local dotProd = vec1:dot(vec2)\n return math.acos(dotProd / (len1 * len2))\n end\n return 0\nend\n\nUtils3d = (function ()\n local this = {}\n local mat4 = require(\"cpml/mat4\")\n\n -- function this.worldToLocal(pos, up, right, forward)\n -- return vec3(\n -- library.systemResolution3(\n -- {right:unpack()},\n -- {forward:unpack()},\n -- {up:unpack()},\n -- {pos:unpack()}\n -- )\n -- )\n -- end\n\n function this.localToRelative(pos, up, right, forward)\n -- this is horrible, can optimize?\n local rightX, rightY, rightZ = right:unpack()\n local forwardX, forwardY, forwardZ = forward:unpack()\n local upX, upY, upZ = up:unpack()\n local rfuX, rfuY, rfuZ = pos:unpack()\n local relX = rfuX * rightX + rfuY * forwardX + rfuZ * upX\n local relY = rfuX * rightY + rfuY * forwardY + rfuZ * upY\n local relZ = rfuX * rightZ + rfuY * forwardZ + rfuZ * upZ\n return vec3(relX, relY, relZ)\n end\n\n function this.worldToScreen(selfPos, targetPos, forward, up, fov, aspect)\n -- see https://github.com/rgrams/rendercam/blob/master/rendercam/rendercam.lua for ideas\n\n local P = mat4():perspective(fov, aspect or (1920/1080), 0.1, 100000)\n local V = mat4():look_at(selfPos, selfPos + forward, up)\n\n local pos = V * P * { targetPos.x, targetPos.y, targetPos.z, 1 }\n\n pos[1] = pos[1] / pos[4] * 0.5 + 0.5\n pos[2] = pos[2] / pos[4] * 0.5 + 0.5\n\n pos[1] = pos[1] * 100\n pos[2] = pos[2] * 100\n\n return vec3(pos[1], pos[2], pos[3])\n end\n\n return this\nend)()",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "12"
},
{
"code": "--@class STEC\n--[[\n\tShadow Templar Engine Control\n\tVersion: 1.17\n\n\tSetup:\n\t\t- Put this file in system.start\n\t\t- Replace system.flush with: engines.apply()\n\t\t- Replace all controls with the appropriate STEC equivalent:\n\t\t\t- ship.direction.x - left/right\n\t\t\t- ship.direction.y - forward/back\n\t\t\t- ship.direction.z - forward/back\n\t\t\t- ship.rotation.x - pitch\n\t\t\t- ship.rotation.y - roll\n\t\t\t- ship.rotation.z - yaw\n\t\t- See comments for additional functionality\n]]\nlocal atlas = require('atlas')\njson = require('dkjson')\nplanetaryReference = PlanetRef()\ngalaxyReference = planetaryReference(atlas)\nhelios = galaxyReference[0]\nkinematics = Kinematics()\n\nfunction STEC(core, control)\n\tlocal self = {}\n\tself.core = core\n\tself.construct = construct\n\tself.control = control\n\tlocal wp = vec3(construct.getWorldPosition())\n\tself.nearestPlanet = helios:closestBody(wp)\n\tself.world = {\n\t\tup = vec3(self.construct.getWorldOrientationUp()),\n\t\tdown = -vec3(self.construct.getWorldOrientationUp()),\n\t\tleft = -vec3(self.construct.getWorldOrientationRight()),\n\t\tright = vec3(self.construct.getWorldOrientationRight()),\n\t\tforward = vec3(self.construct.getWorldOrientationForward()),\n\t\tback = -vec3(self.construct.getWorldOrientationForward()),\n\t\tvelocity = vec3(self.construct.getWorldVelocity()),\n\t\tacceleration = vec3(self.construct.getWorldAcceleration()),\n\t\tposition = wp,\n\t\tgravity = vec3(self.core.getWorldGravity()),\n\t\tvertical = vec3(self.core.getWorldVertical()),\n\t\tatmosphericDensity = self.control.getAtmosphereDensity(),\n\t\tnearPlanet = unit.getClosestPlanetInfluence() > 0\n\t}\n\tlocal gravNorm = self.world.gravity:normalize()\n\tlocal velNorm = self.world.velocity:normalize()\n\tself.target = {\n\t\tprograde = function() return velNorm end,\n\t\tretrograde = function() return -velNorm end,\n\t\tradial = function() return gravNorm end,\n\t\tantiradial = function() return -gravNorm end,\n\t\tnormal = function() return velNorm:cross(gravNorm):normalize() end,\n\t\tantinormal = function() return velNorm:cross(-gravNorm):normalize() end,\n\t}\n\t-- Current altitude\n\tself.altitude = core.getAltitude()\n\tif self.nearestPlanet then\n\t\tself.altitude = self.nearestPlanet:getAltitude(wp)\n\tend\n\tself.rot = vec3()\n\tself.deviationRot = vec3()\n\t-- Construct id\n\tself.id = construct.getId()\n\t-- Control Mode - Travel (0) or Cruise (1)\n\tself.controlMode = unit.getControlMode()\n\t-- Alternate Control Mode for remote control\n\tself.alternateCM = false\n\t-- Active engine tags\n\t-- self.tags = TagManager(\"all,brake\")\n\t-- Target vector to face if non-0. Can take in a vec3 or function which returns a vec3\n\tself.targetDestination = nil\n\tself.baseLoc = vec3()\n\tself.baseAltitude = 0\n\tself.verticalLock = false\n\tself.lockVector = vec3()\n\tself.lockPos = vec3()\n\t-- Hint: presets are validated and assigned in STEC_config.lua during startup\n\tself.altHoldPreset1 = 0\n\tself.altHoldPreset2 = 0\n\tself.altHoldPreset3 = 0\n\tself.altHoldPreset4 = 0\n\tself.deviation = 0\n\tself.deviationVec = vec3()\n\tself.stateMessage = \"\"\n\tself.pocket = false\n\tself.autoShutdown = false\n\tself.dockingClamps = false\n\tself.IDIntensity = 5\n\tself.deviationThreshold = 0.05\n\tself.targetVectorVertical = nil\n\tself.breadCrumbDist = 1000\n\tself.deviated = false\n\tself.breadCrumbs = {}\n\tself.hoverHeight = 10\n\t-- Whether the target vector should unlock automatically if the ship is rotated by the pilot\n\tself.targetVectorAutoUnlock = true\n\t-- Current mass of the vessel, in kilograms\n\tself.mass = self.construct.getTotalMass()\n\t-- Amount of thrust to apply in world space, in Newton. Stacks with {{direction}}\n\tself.thrust = vec3()\n\t-- Amount of thrust to apply in local space, in percentage of fMax 0-1\n\tself.direction = vec3()\n\t-- Amount of rotation to apply in local space\n\tself.rotation = vec3()\n\t-- Speed scale factor for rotations\n\tself.rotationSpeed = 2\n\t-- Minimum rotation speed for auto-scale\n\tself.rotationSpeedzMin = 0.01\n\t-- Rotation Speed on x axis\n\tself.rotationSpeedz = 0.01\n\t-- Max rotation speed for auto-scale\n\tself.maxRotationSpeedz = 3\n\t-- Auto-scale rotation Setup\n\tself.rotationStep = 0.03\n\t-- Breaking speed multiplier\n\tself.brakingFactor = 10\n\t-- Amount of angular thrust to apply, in world space\n\tself.angularThrust = vec3()\n\t-- Whether or not the vessel should attempt to cancel out its current velocity in directions that are not being accelerated towards\n\tself.inertialDampening = false\n\t-- Desired state of inertialDampening\n\tself.inertialDampeningDesired = false\n\t-- Whether or not the vessel should attempt to completely cancel out its current velocity\n\tself.brake = false\n\t-- Whether or not the vessel should attempt to counter gravity influence\n\tself.counterGravity = true\n\t-- Whether or not the vessel should attempt to face perpendicular to the gravity vector\n\tself.followGravity = true\n\t-- Aggressiveness of the gravity follow adjustment\n\tself.gravityFollowSpeed = 10\n\t-- Speed (in km/h) in which to limit the velocity of the ship\n\tself.speedLimiter = 1100\n\t-- Variable speed limit based on delta distance in altitude hold mode\n\tself.variableSpeedLimit = 1100\n\t-- Toggle speed limiter on/off\n\tself.speedLimiterToggle = true\n\t-- Vertical Speed Limit (Atmo)\n\tself.verticalSpeedLimitAtmo = 1100\n\t-- Vertical Speed Limit (Space)\n\tself.verticalSpeedLimitSpace = 4000\n\t-- Final approach speed\n\tself.approachSpeed = 200\n\t-- Amount of throttle to apply. 0-1 range\n\tself.throttle = 1\n\t-- Maximum thrust which the vessel is capable of producing\n\tself.fMax = 0\n\tself.vMax = 0\n\tself.hMax = 0\n\t-- Toggle altitude hold on/off\n\tself.elevatorActive = false\n\t-- Altitude which the vessel should attempt to hold\n\tself.altitudeHold = 0\n\t-- Atmosphere density threshold\n\tself.atmosphereThreshold = 0\n\t-- Speed which the vessel should attempt to maintain\n\tself.cruiseSpeed = 0\n\t-- Whether or not to ignore throttle for vertical thrust calculations\n\tself.ignoreVerticalThrottle = false\n\t-- Local velocity\n\tself.localVelocity = vec3(construct.getVelocity())\n\tself.brakeDistance = 0\n\tself.accelTime = nil\n\tself.viewY = 0\n\tself.viewX = 0\n\t-- Roll Degrees\n\tself.rollDegrees = self.world.vertical:angle_between(self.world.left) / math.pi * 180 - 90\n\tif self.world.vertical:dot(self.world.up) > 0 then self.rollDegrees = 180 - self.rollDegrees end\n\t-- Pitch\n\tself.pitchRatio = self.world.vertical:angle_between(self.world.forward) / math.pi - 0.5\n\t--Vertical Cruise Toggle (for elevator stuff)\n\t-- self.verticalCruise = false\n\t--Vertical Cruise Speed (for elevator stuff)\n\t-- self.verticalCruiseSpeed = 0\n\tself.priorityTags1 = \"brake,airfoil,torque,vertical,lateral,longitudinal\"\n\tself.priorityTags2 = \"atmospheric_engine,space_engine\"\n\tself.priorityTags3 = \"\"\n\tself.bodyGravity = 0\n\n\tlocal lastUpdate = system.getArkTime()\n\n\tfunction self.checkGrndDist()\n\t\tself.hasGndDet = false\n\t\tself.isLanded = false\n\t\tself.telemeterDist = nil\n\t\tself.GrndDist = nil\n\t\tif not telemeter then return end\n\n\t\tself.hasGndDet = true\n\t\t---@TODO support hovers+vertical boosters\n\t\t-- telemeter has precedence with detection of up to 100m\n\t\tlocal ray = telemeter.raycast()\n\t\tif ray.hit then\n\t\t\tself.telemeterDist = ray.distance\n\t\t\tself.GrndDist = ray.distance - (self.agl or 0)\n\t\t\tself.isLanded = self.GrndDist <= 0.5 and vec3(construct.getWorldVelocity()):len() < 1\n\t\tend\n\tend\n\tself.checkGrndDist()\n\n\tfunction self.updateWorld()\n\t\tlocal cwp = vec3(construct.getWorldPosition())\n\t\tself.world = {\n\t\t\tup = vec3(construct.getWorldOrientationUp()),\n\t\t\tdown = -vec3(construct.getWorldOrientationUp()),\n\t\t\tleft = -vec3(construct.getWorldOrientationRight()),\n\t\t\tright = vec3(construct.getWorldOrientationRight()),\n\t\t\tforward = vec3(construct.getWorldOrientationForward()),\n\t\t\tback = -vec3(construct.getWorldOrientationForward()),\n\t\t\tvelocity = vec3(construct.getWorldVelocity()),\n\t\t\tacceleration = vec3(construct.getWorldAcceleration()),\n\t\t\tposition = cwp,\n\t\t\tgravity = vec3(core.getWorldGravity()),\n\t\t\tvertical = vec3(core.getWorldVertical()),\n\t\t\tatmosphericDensity = control.getAtmosphereDensity(),\n\t\t\tnearPlanet = unit.getClosestPlanetInfluence() > 0,\n\t\t}\n\t -- Roll Degrees\n\t\tself.rollDegrees = self.world.vertical:angle_between(self.world.left) / math.pi * 180 - 90\n\t\tif self.world.vertical:dot(self.world.up) > 0 then self.rollDegrees = 180 - self.rollDegrees end\n\t\t-- Pitch\n\t\tself.pitchRatio = self.world.vertical:angle_between(self.world.forward) / math.pi - 0.5\n\n\t\tself.AngularVelocity = vec3(construct.getWorldAngularVelocity())\n\t\tself.AngularAcceleration = vec3(construct.getWorldAngularAcceleration())\n\t\tself.AngularAirFriction = vec3(construct.getWorldAirFrictionAngularAcceleration())\n\t\tself.airFriction = vec3(construct.getWorldAirFrictionAcceleration())\n\n\t\tself.altitude = core.getAltitude()\n\t\tself.atmosphereThreshold = 0\n\t\tself.bodyGravity = 0\n\t\tself.nearestPlanet = helios:closestBody(cwp)\n\t\tif self.nearestPlanet then\n\t\t\tself.altitude = self.nearestPlanet:getAltitude(cwp)\n\t\t\tself.atmosphereThreshold = self.nearestPlanet.atmosphereRadius - self.nearestPlanet.radius\n\t\t\tself.bodyGravity = self.nearestPlanet:getGravity(self.world.position)\n\t\tend\n\n\t\tself.mass = self.construct.getTotalMass()\n\t\tself.localVelocity = vec3(construct.getVelocity())\n\t\tself.maxBrake = json.decode(unit.getWidgetData()).maxBrake\n\t\tlocal hMax = construct.getMaxThrustAlongAxis(\"all\", {vec3(1,0,0):unpack()})\n\t\tlocal fMax = construct.getMaxThrustAlongAxis(\"all\", {vec3(0,1,0):unpack()})\n\t\tlocal vMax = construct.getMaxThrustAlongAxis(\"all\", {vec3(0,0,1):unpack()})\n\t\t--system.print(\"vMax[1]: \"..round2(vMax[1],0))\n\t\t--system.print(\"vMax[2]: \"..round2(vMax[2],0))\n\t\t--system.print(\"vMax[3]: \"..round2(vMax[3],0))\n\t\t--system.print(\"vMax[4]: \"..round2(vMax[4],0))\n\t\tif self.world.atmosphericDensity > 0.1 then\n\t\t\tself.fMax = math.max(fMax[1], -fMax[2])\n\t\telse\n\t\t\tself.fMax = math.max(fMax[3], -fMax[4])\n\t\tend\n\t\tif self.world.atmosphericDensity > 0.1 then\n\t\t\tself.vMax = math.max(vMax[1], -vMax[2])\n\t\telse\n\t\t\tself.vMax = math.min(vMax[3], -vMax[4])\n\t\tend\n\t\tif self.world.atmosphericDensity > 0.1 then\n\t\t\tself.hMax = math.max(hMax[1], -hMax[2])\n\t\telse\n\t\t\tself.hMax = math.max(hMax[3], -hMax[4])\n\t\tend\n\t\t--system.print(self.world.velocity:dot(-self.world.gravity:normalize()))\n\t\tlocal gravN = self.mass * core.getGravityIntensity()\n\t\tlocal correctedThrust = self.vMax\n\t\tlocal correctedBrake = self.maxBrake\n\t\tlocal sign = 1\n\n\t\tif self.maxBrake ~= nil and core.getGravityIntensity() >= 1 then\n\t\t\tif self.world.velocity:dot(-self.world.gravity:normalize()) < 1 then\n\t\t\t\tsign = -1\n\t\t\tend\n\t\t\tgravN = gravN * sign\n\t\t\tcorrectedThrust = self.vMax + gravN\n\t\t\tcorrectedBrake = self.maxBrake + gravN\n\t\tend\n\t\tself.brakeDistance, self.accelTime = kinematics.computeDistanceAndTime(self.world.velocity:len(), 0, self.mass, correctedThrust,20,correctedBrake)\n\n\t\tself.checkGrndDist()\n\tend\n\n\tfunction self.calculateAccelerationForce(acceleration, time)\n\t\treturn self.mass * (acceleration / time)\n\tend\n\n\tfunction clamp(n, min, max)\n\t\treturn math.min(max, math.max(n, min))\n\tend\n\tfunction round(num, numDecimalPlaces)\n\t\tlocal mult = 10^(numDecimalPlaces or 0)\n\t\treturn math.floor(num * mult + 0.5) / mult\n\tend\n\tfunction self.throttleUp()\n\t\tself.throttle = clamp(self.throttle + 0.05, 0, 1)\n\tend\n\n\tfunction self.throttleDown()\n\t\tself.throttle = clamp(self.throttle - 0.05, 0, 1)\n\tend\n\n\tfunction moveWaypointZ(vector, altitude)\n\t\tif not ship.nearestPlanet then return vector end\n\t\treturn (vector - (ship.nearestPlanet:getGravity(vector)):normalize() * (altitude))\n\tend\n\n\tfunction self.worldToLocal(vector)\n\t\tif not vec3.isvector(vector) then return nil end\n\t\treturn vec3(\n\t\t\tlibrary.systemResolution3(\n\t\t\t\t{self.world.right:unpack()},\n\t\t\t\t{self.world.forward:unpack()},\n\t\t\t\t{self.world.up:unpack()},\n\t\t\t\t{vector:unpack()}\n\t\t\t)\n\t\t)\n\tend\n\n\tfunction self.localToRelative(pos, up, right, forward)\n\t\t-- this is horrible, can optimize?\n\t\tlocal rightX, rightY, rightZ = right:unpack()\n\t\tlocal forwardX, forwardY, forwardZ = forward:unpack()\n\t\tlocal upX, upY, upZ = up:unpack()\n\t\tlocal rfuX, rfuY, rfuZ = pos:unpack()\n\t\tlocal relX = rfuX * rightX + rfuY * forwardX + rfuZ * upX\n\t\tlocal relY = rfuX * rightY + rfuY * forwardY + rfuZ * upY\n\t\tlocal relZ = rfuX * rightZ + rfuY * forwardZ + rfuZ * upZ\n\t\treturn vec3(relX, relY, relZ)\n\tend\n\n\tfunction MsToKmh(ms)\n\t\treturn ms * 3.6\n\tend\n\tfunction KmhToMs(kmh)\n\t\treturn kmh / 3.6\n\tend\n\n\tfunction self.apply()\n\t\t-- local deltaTime = math.max(system.getArkTime() - lastUpdate, 0.001) --If delta is below 0.001 then something went wrong in game engine.\n\t\tself.updateWorld()\n\n\t\tlocal tmp = self.thrust\n\t\tlocal atmp = self.angularThrust\n\t\t-- local gravityCorrection = false\n\t\tlocal fMax = construct.getMaxThrustAlongAxis(\"all\", {vec3(0,1,0):unpack()})\n\t\tlocal hMax = construct.getMaxThrustAlongAxis(\"all\", {vec3(1,0,0):unpack()})\n\t\t-- local vMaxUp = construct.getMaxThrustAlongAxis(\"all\", {vec3(0,0,1):unpack()})\n\t\t-- local vMaxDown = construct.getMaxThrustAlongAxis(\"all\", {vec3(0,0,-1):unpack()})\n\n\t\t-- Elevator stuff\n\t\t-- lets make this easier in apply(): if baseLoc isn't usable,\n\t\t-- then nil it, thus a simple, consistent check is sufficient!\n\t\tif not vec3.isvector(self.baseLoc) or self.baseLoc == vec3() then\n\t\t\tself.baseLoc = nil\n\t\tend\n\t\tlocal baseBody = self.baseLoc and helios:closestBody(self.baseLoc) or nil\n\t\tif lockVerticalToBase and baseBody then\n\t\t\tself.nearestPlanet = baseBody\n\t\t\tself.altitude = self.nearestPlanet:getAltitude(self.world.position)\n\t\t\tself.atmosphereThreshold = self.nearestPlanet.atmosphereRadius - self.nearestPlanet.radius\n\t\tend\n\t\tif not self.elevatorActive then\n\t\t\tself.inertialDampening = self.inertialDampeningDesired\n\t\tend\n\n\t\tif self.direction.x ~= 0 then\n\t\t\tlocal dot = (1 - self.world.up:dot(-self.world.gravity:normalize())) * (self.mass * 0.000095) -- Magic number is magic\n\t\t\tlocal gravCorrection = -self.world.vertical * dot\n\n\t\t\tif self.direction.x < 0 and math.abs(round2(hMax[2],0)) < 500 then\n\t\t\t\t-- gravityCorrection = true\n\t\t\t\ttmp = tmp + ((((self.world.right * self.direction.x) + gravCorrection):normalize() * self.fMax) * self.throttle)\n\t\t\telseif self.direction.x > 0 and math.abs(round2(hMax[1],0)) < 500 then\n\t\t\t\t-- gravityCorrection = true\n\t\t\t\ttmp = tmp + ((((self.world.right * self.direction.x) + gravCorrection):normalize() * self.fMax) * self.throttle)\n\t\t\telse\n\t\t\t\ttmp = tmp + (((self.world.right * self.direction.x) * self.fMax) * self.throttle) -- OG code\n\t\t\tend\n\t\tend\n\n\t\tif self.direction.y ~= 0 then\n\t\t\t--tmp = tmp + (((self.world.forward * self.direction.y) * self.fMax) * self.throttle)\n\t\t\t--tmp = tmp + (((self.world.gravity:normalize():cross(-self.world.right) * self.direction.y) * self.fMax) * self.throttle)\n\t\t\tlocal dot = (1 - self.world.up:dot(-self.world.gravity:normalize())) * (self.mass * 0.000095)\n\t\t\tlocal gravCorrection = -self.world.vertical * dot\n\t\t\t--system.print(math.abs(round2(fMax[2],0)))\n\t\t\tif self.direction.y < 0 and math.abs(round2(fMax[2],0)) == 0 then\n\t\t\t\t-- gravityCorrection = true\n\t\t\t\ttmp = tmp + ((((self.world.forward * self.direction.y) + gravCorrection):normalize() * self.fMax) * self.throttle)\n\t\t\telse\n\t\t\t\ttmp = tmp + (((self.world.forward * self.direction.y) * self.fMax) * self.throttle)\n\t\t\tend\n\t\tend\n\t\tif self.direction.z ~= 0 then\n\t\t\tlocal a = ((self.world.up * self.direction.z) * self.fMax)\n\t\t\tif not self.ignoreVerticalThrottle then a = a * self.throttle end\n\t\t\ttmp = tmp + a\n\t\tend\n\t\tif self.rotation.y ~= 0 then\n\t\t\tatmp = atmp + ((self.world.up:cross(self.world.right) * self.rotation.y) * self.rotationSpeed)\n\t\tend\n\t\tif self.rotation.z ~= 0 then\n\t\t\tif self.rotationSpeedz <= self.maxRotationSpeedz then self.rotationSpeedz = self.rotationSpeedz + self.rotationStep end\n\t\t\t--system.print(\"Rotation Speed: \"..self.rotationSpeedz)\n\t\t\tatmp = atmp + ((self.world.forward:cross(self.world.right) * self.rotation.z) * clamp(self.rotationSpeedz, 0.01, self.maxRotationSpeedz))\n\t\t\tif self.targetVectorAutoUnlock then\n\t\t\t\tself.targetVector = nil\n\t\t\tend\n\t\tend\n\t\tif self.rotation.x ~= 0 then\n\t\t\tatmp = atmp + ((self.world.forward:cross(self.world.up) * self.rotation.x) * self.rotationSpeed)\n\t\t\tif self.targetVectorAutoUnlock then\n\t\t\t\tself.targetVector = nil\n\t\t\tend\n\t\telseif self.followGravity then\n\t\t\t--local current = self.localVelocity:len() * self.mass\n\t\t\t--if ship.localVelocity:len() > 10 then\n\t\t\t-- scale = self.gravityFollowSpeed * math.min(math.max(current / self.fMax, 0.1), 1) * 10\n\t\t\t--else\n\t\t\t-- scale = self.gravityFollowSpeed\n\t\t\t--end\n\t\t\t--and self.nearestPlanet\n\t\t\tlocal scale, grav, gFollow = 1, vec3(), vec3()\n\t\t\tif lockVerticalToBase and baseBody then\n\t\t\t\tgrav = -baseBody:getGravity(self.baseLoc)\n\t\t\telseif self.bodyGravity then\n\t\t\t\tgrav = -self.bodyGravity\n\t\t\tend\n\t\t\tgFollow = self.world.up:cross(grav)\n\t\t\tif self.pocket then\n\t\t\t\tif self.direction.x < 0 then\n\t\t\t\t\tscale = 0.25\n\t\t\t\t\tgFollow = gFollow + ship.world.right:cross(grav * scale)\n\t\t\t\telseif self.direction.x > 0 then\n\t\t\t\t\tscale = 0.25\n\t\t\t\t\tgFollow = gFollow - ship.world.right:cross(grav * scale)\n\t\t\t\telseif self.direction.y < 0 then\n\t\t\t\t\tgFollow = gFollow + ship.world.forward:cross(grav * 0.25)\n\t\t\t\tend\n\t\t\tend\n\t\t\tatmp = atmp + gFollow * scale\n\t\tend\n\n\t\t-- keep engines off when landed and resting with no target set?\n\t\t-- if config.manualControl and self.isLanded and self.direction.z == 0 then return end\n\n\t\tif config.manualControl and self.isLanded and self.localVelocity:len() < 1 and\n\t\t\t(self.direction.z == 0 and self.direction.y == 0 and self.direction.x == 0) then\n\t\t\tself.brake = false\n\t\t\tself.control.setEngineCommand(\"atmospheric_engine,space_engine,airfoil,brake,torque,vertical,lateral,longitudinal\",\n\t\t\t\t{vec3():unpack()}, {vec3():unpack()}, false, false,\n\t\t\t\tself.priorityTags1,\n\t\t\t\tself.priorityTags2,\n\t\t\t\tself.priorityTags3)\n\t\t\treturn\n\t\tend\n\n\t\tself.deviation = 0\n\t\tself.deviationVec = vec3()\n\t\tself.deviationRot = vec3()\n\t\tif self.baseLoc then\n\t\t\tself.deviationVec = (moveWaypointZ(self.baseLoc, self.altitude - self.baseAltitude) - self.world.position)\n\t\t\tself.deviation = self.deviationVec:len()\n\t\t\tif vec3.isvector(self.rot) then\n\t\t\t\tself.deviationRot = self.world.forward:cross(self.rot)\n\t\t\tend\n\t\tend\n\n\t\tif self.elevatorActive and self.targetDestination and baseBody then\n\t\t\tself.inertialDampening = true\n\t\t\tself.counterGravity = true\n\t\t\tself.targetVector = self.rot\n\t\t\tif self.world.velocity:len() > (2000 / 3.6) then deviation = 0 end\n\n\t\t\tlocal deltaAltitude = self.altitudeHold - self.altitude\n\t\t\tlocal brakeBuffer, speed = 1000, 0\n\t\t\tlocal distance = (self.world.position - self.targetDestination):len()\n\t\t\tlocal realDistance = baseBody:getAltitude(self.targetDestination) - self.altitude\n\t\t\tlocal destination = self.targetDestination\n\t\t\tlocal verticalSpeedLimit = 0\n\n\t\t\tverticalSpeedLimit = self.verticalSpeedLimitSpace\n\t\t\tif self.altitude <= (self.atmosphereThreshold + self.brakeDistance) or self.altitude <= self.brakeDistance then\n\t\t\t\tverticalSpeedLimit = self.verticalSpeedLimitAtmo\n\t\t\tend\n\t\t\tif (self.brakeDistance + brakeBuffer) >= math.abs(deltaAltitude) then\n\t\t\t\tverticalSpeedLimit = self.approachSpeed\n\t\t\tend\n\n\t\t\tlocal deviationThreshold = self.deviationThreshold\n\t\t\tif self.deviated or self.world.velocity:len() < 1 then deviationThreshold = 0.05 end\n\t\t\t--system.print(\"Deviation threshold: \"..deviationThreshold)\n\t\t\tself.deviated = self.deviation > (deviationThreshold + self.world.velocity:len() * 10^-2)\n\t\t\tif self.deviated then\n\t\t\t\tlocal altDiff = self.altitude - self.baseAltitude\n\t\t\t\tif altDiff ~= 0 and not self.isLanded then\n\t\t\t\t\tdestination = moveWaypointZ(self.baseLoc, altDiff)\n\t\t\t\tend\n\t\t\t\tspeed = self.deviation * self.IDIntensity\n\t\t\t\tself.stateMessage = \"Correcting Deviation\"\n\t\t\tend\n\n\t\t\tif math.abs(deltaAltitude) > self.brakeDistance and math.abs(deltaAltitude) > 500 and not self.deviated then\n\t\t\t\tself.stateMessage = \"Traveling\"\n\t\t\t\tspeed = round2((clamp(deltaAltitude, -verticalSpeedLimit, verticalSpeedLimit)), 1)\n\t\t\telseif not self.deviated then\n\t\t\t\tself.stateMessage = \"Final approach\"\n\t\t\t\tspeed = self.approachSpeed\n\t\t\t\tif self.brakeDistance * 1.5 >= math.abs(distance) then speed = 5 end\n\t\t\tend\n\t\t\t--system.print(\"realDistance: \"..realDistance)\n\t\t\tlocal breadCrumb\n\t\t\t--local breadCrumbDist = utils.clamp(math.abs(self.world.velocity:len()),10,self.breadCrumbDist - (self.deviation * 100))\n\t\t\t--system.print(breadCrumbDist)\n\t\t\tif ship.nearestPlanet then\n\t\t\t\tif realDistance > self.breadCrumbDist and not self.deviated then\n\t\t\t\t\tbreadCrumb = moveWaypointZ(self.baseLoc, (self.altitude - self.baseAltitude) + self.breadCrumbDist)\n\t\t\t\t\tdestination = breadCrumb\n\t\t\t\t\tlocal waypointString = ship.nearestPlanet:convertToMapPosition(destination)\n\t\t\t\t\tsystem.setWaypoint(waypointString,false)\n\t\t\t\telseif realDistance < -self.breadCrumbDist and not self.deviated then\n\t\t\t\t\tbreadCrumb = moveWaypointZ(self.baseLoc, (self.altitude - self.baseAltitude) - self.breadCrumbDist)\n\t\t\t\t\tdestination = breadCrumb\n\t\t\t\t\tlocal waypointString = ship.nearestPlanet:convertToMapPosition(destination)\n\t\t\t\t\tsystem.setWaypoint(waypointString,false)\n\t\t\t\tend\n\t\t\tend\n\n\t\t\tlocal elevatorDestination = (self.world.position - destination):normalize()\n\t\t\ttmp = tmp - elevatorDestination * self.mass * utils.clamp(distance * 3.6,0.3,((math.abs(speed)/3.6) * self.IDIntensity))\n\t\t\t--if breadCrumb then system.print(\"Breadcrumb distance: \"..(self.world.position - breadCrumb):len()) end\n\t\t\tself.dockingClamps = false\n\t\t\tif (distance < 0.01 and not config.manualControl) or\n\t\t\t (distance < 2 and not config.manualControl and self.world.velocity:len() == 0) then\n\t\t\t\tself.elevatorActive = false\n\t\t\t\tself.targetVector = nil\n\t\t\t\tself.stateMessage = \"Idle\"\n\t\t\t\tself.dockingClamps = true\n\t\t\tend\n\t\telse\n\t\t\tself.targetDestination = nil\n\t\tend\n\n\t\tif self.inertialDampening then\n\t\t\tlocal currentShipMomentum = self.localVelocity\n\t\t\tlocal delta = vec3(0,0,0)\n\t\t\tlocal moveDirection = self.direction or vec3(0,0,0)\n\n\t\t\tif moveDirection.x == 0 then delta.x = currentShipMomentum.x end\n\t\t\tif moveDirection.y == 0 then delta.y = currentShipMomentum.y end\n\t\t\tif moveDirection.z == 0 then delta.z = currentShipMomentum.z end\n\n\t\t\tdelta = self.localToRelative(delta, self.world.up, self.world.right, self.world.forward)\n\t\t\ttmp = tmp - (delta * (self.mass * self.IDIntensity))\n\t\tend\n\n\t\tif self.brake then\n\t\t\tlocal velocityLen = self.world.velocity:len()\n\t\t\ttmp = -self.world.velocity * self.mass *\n\t\t\t\t\tmath.max(self.brakingFactor * math.max(1, velocityLen * 0.5), velocityLen * velocityLen)\n\t\tend\n\n\t\tif self.targetVector ~= nil then\n\t\t\tlocal vec = vec3(self.world.forward.x, self.world.forward.y, self.world.forward.z)\n\t\t\tif type(self.targetVector) == \"function\" then\n\t\t\t\tvec = self.targetVector()\n\t\t\telseif type(self.targetVector) == \"table\" then\n\t\t\t\tvec = self.targetVector\n\t\t\tend\n\t\t\tatmp = atmp + (self.world.forward:cross(vec) * (self.rotationSpeed / 4)) - ((self.AngularVelocity * 2) - (self.AngularAirFriction * 2))\n\t\tend\n\n\t\tif self.targetVectorVertical ~= nil then\n\t\t\tlocal vec = vec3(self.world.up.x, self.world.up.y, self.world.up.z)\n\t\t\tif type(self.targetVector) == \"function\" then\n\t\t\t\tvec = self.targetVector()\n\t\t\telseif type(self.targetVector) == \"table\" then\n\t\t\t\tvec = self.targetVector\n\t\t\tend\n\t\t\tif (self.world.up - self.targetVectorVertical):len() < 0 then\n\t\t\t\tatmp = atmp + (-self.world.up:cross(vec) * (self.rotationSpeed / 4)) - ((self.AngularVelocity * 2) - (self.AngularAirFriction * 2))\n\t\t\telse\n\t\t\t\tatmp = atmp + (self.world.up:cross(vec) * (self.rotationSpeed / 4)) - ((self.AngularVelocity * 2) - (self.AngularAirFriction * 2))\n\t\t\tend\n\t\tend\n\n\t\t-- must be applied last\n\t\tif self.counterGravity then\n\t\t\ttmp = tmp - self.world.gravity * self.mass\n\t\tend\n\n\t\tif self.verticalLock then\n\t\t\tlocal localPos = (self.world.position + self.world.up) - self.lockPos\n\t\t\tlocal intersectionPos = self.lockVector * self.lockVector:dot(localPos)\n\t\t\tlocal intersectionVec = intersectionPos - localPos\n\t\t\tlocal thrustForce = intersectionVec * (self.mass * 0.3)-- * deltaTime\n\t\t\ttmp = tmp + thrustForce * self.mass\n\t\tend\n\n\t\tatmp = atmp - ((self.AngularVelocity * 2) - (self.AngularAirFriction * 2))\n\t\ttmp = tmp / self.mass\n\n\t\tif self.controlMode ~= unit.getControlMode() then\n\t\t\tself.controlMode = unit.getControlMode()\n\t\t\tself.alternateCM = unit.getControlMode() == 1\n\t\tend\n\n\t\t--self.control.setEngineCommand(tostring(self.tags), {tmp:unpack()}, {atmp:unpack()})\n\t\tself.control.setEngineCommand(\"atmospheric_engine,space_engine,airfoil,brake,torque,vertical,lateral,longitudinal\",\n\t\t\t{tmp:unpack()}, {atmp:unpack()}, false, false,\n\t\t\tself.priorityTags1,\n\t\t\tself.priorityTags2,\n\t\t\tself.priorityTags3)\n\n\t\tlastUpdate = system.getArkTime()\n\tend\n\n\treturn self\nend\n\nship = STEC(core, unit)\n",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "13"
},
{
"code": "--@class CSS_SHUD\ndisplaySize = 0.85\nprimaryColor = primaryColor or \"b80000\"\nsecondaryColor = secondaryColor or \"e30000\"\ntextShadowColor = textShadowColor or \"e81313\"\n\n--system.print(fuelFontSize)\nCSS_SHUD = [[\n#horizon {\n\tleft: 0;\n\ttop: 0;\n\tposition: fixed;\n\twidth: 100vw;\n\theight: 100vh;\n\tbackground: radial-gradient(ellipse 27vw 11vw at 50% 51vw, rgba(1,5,8,0.6) 50%,rgba(1,5,8,0) 90%);\n\tfont-family: Montserrat, Roboto, Verdana;\n}\n#fuelTanks {\n\tposition: absolute;\n\ttop: 2%;\n\tleft: 2%;\n\tmargin: 2%;\n\tdisplay: flex;\n\tflex-wrap: wrap;\n}\n.fuel-tanks {\n\twidth: 12vw;\n\tmargin-right: 1vw;\n\tdisplay: inline-block;\n\tvertical-align: top;\n}\n.fuel-meter {\n\theight: 1.8vh;\n\tbackground-color: #222;\n\tborder: 1px solid #fff;\n\tborder-radius: 0.6vh;\n\tfont-size: 0.9vh;\n\ttext-align: left;\n\toverflow: hidden;\n\tpadding: 0;\n}\n.fuel-meter hr.fuel-level {\n\theight: 1.6vh;\n\tborder: none;\n\tborder-radius: 0.6vh;\n\tmargin: 0;\n\tmargin-top: 0.1vh;\n\tpadding: 0;\n}\n.fuel-meter hr.fuel-level + span {\n\tfont-family: Montserrat, Roboto, Verdana;\n\tposition: relative;\n\ttop: -1.4vh;\n\tleft: 0.4vw;\n\tz-index: 1;\n\tcolor: #fff;\n\tfont-weight: bold;\n\tfont-size: 0.9vh;\n\tpadding 0;\n\ttext-shadow: 0.25vw 0.25vw 1.05vw #000;\n}\n.fuel-meter span:first-child {display: none;}\n.fuel-type-atmo .fuel-level {background: #1dd1f9;}\n.fuel-type-space .fuel-level {background: #ea5409;}\n.fuel-type-rocket .fuel-level {background: #bfa6ff;}\n\n#speedometer::before {\n\tdisplay: block;\n\tposition: absolute;\n\tcontent: ' ';\n\ttop: 0.25vh;\n\tbottom: -17vh;\n\tleft: 50%;\n\twidth: 31vw;\n\tborder: 10px solid #]]..primaryColor..[[;\n\tborder-bottom: 0;\n\tborder-right: 0;\n\tborder-left: 0;\n\tborder-radius: 100%;\n\ttransform: translateX(-50%);\n\tbackground-color: transparent;\n\tfilter: blur(100vw);\n}\n\n#speedometerBar {\n\tdisplay: block;\n\tposition: fixed;\n\tleft: 50%;\n\ttop: 77.2vh;\n\twidth: 30vw;\n\theight: 24.5vh;\n\ttransform: translate(-50%);\n\tcontent: ' ';\n\tborder: 10px solid #]]..primaryColor..[[;\n\tborder-bottom: 0;\n\tborder-right: 0;\n\tborder-left: 0;\n\tborder-radius: 100%;\n\tbackground-size: contain;\n\tbackground-color: transparent;\n\tfilter: blur(0.1vw);\n}\n\n#speedometer {\n\tfont-family: 'Montserrat', 'Roboto', 'Verdana';\n\tfont-weight: normal;\n\tfont-style: normal;\n\tposition: fixed;\n\tleft: 50%;\n\tbottom: 14vh;\n\tfont-size: 2.5vw;\n\ttransform: translate(-50%);\n\tbackground-color: transparent;\n\twidth: 30vw;\n\theight: 10vh;\n\ttext-align: center;\n}\n\n#speedometer .display {\n\tposition: absolute;\n\ttop: calc(50% + 1vh);\n\tleft: calc(50% + 0.25em);\n\ttransform: translate(-50%, -50%);\n\tfont-weight: bold;\n\ttext-shadow: 0 0 0.75vw #]]..textShadow..[[;\n\tpadding: 0;\n\tmargin: 0;\n\tfont-size: 2.8vw;\n}\n\n#speedometer .display .minor, #speedometer .unit {\n\tposition: relative;\n\tleft: -0.5em;\n\tvertical-align: super;\n\tfont-size: 40%;\n}\n\n#speedometer .unit {\n\tvertical-align: 50%;\n\tfont-size: 23%;\n\tleft: -1.33em;\n}\n\n#speedometer .accel {\n\tfont-size: 1.2vw;\n\ttext-shadow: 0 0 0.15vw #000000;\n\tposition: absolute;\n\tleft: 12.5%;\n\tbottom: 0;\n\topacity: 0.75;\n}\n\n#speedometer .accel .major::before {\n\tcontent: 'Δ';\n\tfont-size: 40%;\n}\n\n#speedometer .accel .unit {\n\tleft: -0.66em;\n}\n\n#speedometer .alt {\n\tposition: absolute;\n\tleft: 50%;\n\tbottom: -0.65vh;\n\ttransform: translateX(-50%);\n\tfont-size: 0.65vw;\n\ttext-align: center;\n}\n\n#speedometer .misc {\n\tposition: absolute;\n\tleft: 50%;\n\tbottom: -1.5vh;\n\ttransform: translateX(-50%);\n\tfont-size: 0.4vw;\n\ttext-align: center;\n}\n\n#speedometer .throttle {\n\tposition: absolute;\n\tleft: 50%;\n\tbottom: -3vh;\n\ttransform: translateX(-50%);\n\tfont-size: 0.7vw;\n\ttext-align: center;\n}\n\n#speedometer .vertical {\n\tfont-size: 1.3vw;\n\ttext-shadow: 0 0 0.15vw #000000;\n\tposition: absolute;\n\tright: 12.5%;\n\tbottom: 0;\n\topacity: 0.75;\n\ttext-align: right;\n}\n\n#speedometer .vertical::after {\n\tcontent: '↕ m/s';\n\tvertical-align: 50%;\n\tfont-size: 33%;\n}\n\n#speedometer::after {\n\tdisplay: block;\n\tfont-size: 0;\n\tbackground-size: contain;\n\tcontent: ' ';\n\tposition: absolute;\n\ttop: 0.5vh;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tz-index: 666;\n\topacity: 0.5;\n}\n\n#horizon-menu {\n\ttext-transform: uppercase;\n\tfont-family: 'Verdana';\n\tfont-size: ]] .. displaySize .. [[vw;\n\tdisplay: flex;\n\tflex-direction: column;\n\tposition: fixed;\n\tbottom: 35%;\n\tleft: 2vw;\n\twidth: 18vw;\n\tpadding: 1vw;\n\ttransform: perspective(50vw) rotateY(35deg);\n\ttext-shadow: 0.1vw 0 0.25vw #000000;\n}\n#horizon-menu .item {\n\tcolor: #fff;\n\tpadding: 0.2vw 0.5vw;\n\tz-index: 99999;\n}\n#horizon-menu .item .right {\n\tfloat: right;\n}\n#horizon-menu .item .red {\n\tcolor: #]]..secondaryColor..[[;\n}\n#horizon-menu .item.active {\n\tposition: relative;\n\ttext-shadow: 0 0 0.75vw #]]..secondaryColor..[[;\n\ttransform: translateZ(0.33vw);\n\tfont-size: 1.15em;\n\ttransform-style: preserve-3d;\n}\n\n#horizon-menu .item.active::before {\n\tdisplay: block;\n\tcontent: ' ';\n\tposition: absolute;\n\ttop: 15%;\n\tbottom: 15%;\n\tleft: 0.1vw;\n\tright: 0.1vw;\n\tbackground: #]]..secondaryColor..[[aa;\n\tz-index: -50;\n\tfilter: blur(1vw);\n\topacity: 0.2;\n}\n\n#horizon-menu .item.active::after {\n\tdisplay: block;\n\tcontent: ' ';\n\tposition: absolute;\n\ttop: 20%;\n\tbottom: 40%;\n\tleft: 0.1vw;\n\tright: 0.1vw;\n\tbackground: #]]..secondaryColor..[[aa;\n\tz-index: -50;\n\tfilter: blur(0.2vw);\n\topacity: 0.3;\n}\n#horizon-menu .item.locked {\n\tpadding-left: 0.4vw;\n}\n#horizon-menu .item.locked::before {\n\tdisplay: block;\n\tcontent: ' ';\n\tposition: absolute;\n\ttop: 15%;\n\tbottom: 15%;\n\tleft: 0.1vw;\n\tright: 0.1vw;\n\tbackground: #]]..primaryColor..[[aa;\n\tz-index: -50;\n\tfilter: blur(1vw);\n\topacity: 0.2;\n}\n#horizon-menu .item.locked::after {\n\tdisplay: block;\n\tcontent: ' ';\n\tposition: absolute;\n\ttop: 20%;\n\tbottom: 40%;\n\tleft: 0.1vw;\n\tright: 0.1vw;\n\tbackground: #]]..primaryColor..[[aa;\n\tz-index: -50;\n\tfilter: blur(0.2vw);\n\topacity: 0.6;\n}\n\n#horizon-menu::after {\n\tcontent: ' ';\n\tfilter: blur(1vw);\n\tdisplay: block;\n\tborder-top-left-radius: 1vw;\n\tborder-top-right-radius: 1vw;\n\tborder-image: linear-gradient(to bottom, #]]..primaryColor..[[ff, #]]..primaryColor..[[00) 1 100%;\n\tbackground: linear-gradient(to bottom, rgba(0,0,0,0.65) 50%,rgba(0,0,0,0) 100%);\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tleft: 0;\n\tright: 0;\n\tz-index: -99;\n}\n\n#horizon-menu::before {\n\tcontent: ' ';\n\tfilter: blur(0.05vw);\n\tdisplay: block;\n\tborder-top-left-radius: 1vw;\n\tborder-top-right-radius: 1vw;\n\tborder-top: 0.25vw solid #]]..primaryColor..[[;\n\tborder-left: 0.25vw solid #]]..primaryColor..[[;\n\tborder-right: 0.25vw solid #]]..primaryColor..[[;\n\tborder-image: linear-gradient(to bottom, #]]..primaryColor..[[ff, #]]..primaryColor..[[00) 1 100%;\n\tbackground: radial-gradient(ellipse at top, rgba(0,0,0,0.65) 0%,rgba(0,0,0,0) 100%);\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tleft: 0;\n\tright: 0;\n\tz-index: -100;\n}\n\n/* ORE TRILATERATE STYLE */\n\np {\t/*color:#eca943;*/\n\tfont-size:100%;\n}\n\n.block {\n\tborder: 1px solid DimGray;\n\tborder-radius:10px;\n\tbackground-color: rgba(0,0,0,.5)\n}\n\n#main_block{\n\ttext-align: center;\n\tpadding: 10px 10px 10px 10px;\n}\n\n#help_block{\n\ttext-align: left;\n\tpadding: 10px 10px 10px 10px;\n\twidth: 320px;\n}\n\n#pause_block{\n\ttext-align: center;\n\tfont-size:90%;\n}\n\n#panel_left {\n\tposition: absolute;\n\ttop: 0%;\n\tleft: 0%;\n\t/*width: 310px;*/\n}\n#slider_header {\n\tposition: absolute;\n\ttop: 0vh;\n\tfont-size:110%;\n\twidth: 100%;\n\ttext-align: center;\n}\n\n#slider_main {\n\tposition: relative;\n\tfont-size:105%;\n\tcolor:#eca943;\n\t/*left: -51%;/*0%*/*/\n}\n\n#slider_footer{\n\tposition: relative;\n\tfont-size:120%;\n\ttop:80%;\n\tleft:10%;\n}\n\n#panel_slider {\n\tposition: absolute;\n\ttop: 54.5vh; ;\n\tleft: 66.8vw;/*66.8vw;*/\n\twidth: 9vw;/*9vw;*/\n\theight: 28.5vh;\n\ttransform: skew(15.85deg); /*15.85deg*/\n\tborder-bottom: 28.5vh solid rgba(0,0,0,.25);\n\tborder-right: 1vw solid transparent;\n\t/*background-color:rgba(0,0,0,.75)*/\n}\n\n#panel_test {\n\tposition: fixed;\n\ttop: 100px; /* or whatever top you need */\n\tleft: 50%;\n\twidth: auto;\n\t-webkit-transform: translateX(-50%);\n\t-moz-transform: translateX(-50%);\n\t-ms-transform: translateX(-50%);\n\t-o-transform: translateX(-50%);\n\ttransform: translateX(-50%);\n}\n\n.shadow {\n\t-webkit-filter: drop-shadow( 3px 3px 2px rgba(0, 0, 0, .7));\n\tfilter: drop-shadow( 3px 3px 2px rgba(0, 0, 0, .7));\n}\n]]\n\n--system.print([[Shadow Templar Mining Chair H1R3<style>#custom_screen_click_layer{ display: none !important; }</style>]])",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "14"
},
{
"code": "--@class SHUD\n\nvec2 = require('cpml/vec2')\nmat4 = require(\"cpml/mat4\")\n\naltHoldAdjustment = 0.1\naltAdjustment = 3\nlocal P = system.print\n\nfunction SpeedConvert(value)\n\tif not value or value == 0 then return {0,\"00\",\"km/h\"} end\n\tif value > 5000 then\n\t\tlocal endnum = tonumber(tostring(round2(value/55.55, 2)):match(\"%.(%d+)\"))\n\t\tlocal ending = string.format(\"%02d\",endnum)\n\t\treturn {round2(value/55.55),ending,\"su/h\"}\n\tend\n\tlocal endnum = tonumber(tostring(round2(value/3.6, 2)):match(\"%.(%d+)\"))\n\tlocal ending = string.format(\"%02d\",endnum)\n\treturn {round2(value*3.6),ending,\"km/h\"}\nend\n\nfunction CruiseControl(value)\n\tlocal appliedCruise = 0\n\n\tif ship.cruiseSpeed < 500 then appliedCruise = value * 10\n\telseif ship.cruiseSpeed >= 500 and ship.cruiseSpeed <= 1999 then appliedCruise = value * 50\n\telseif ship.cruiseSpeed >= 2000 and ship.cruiseSpeed <= 9999 then appliedCruise = value * 100\n\telseif ship.cruiseSpeed >= 10000 then appliedCruise = value * 1000 end\n\n\tship.cruiseSpeed = utils.clamp(ship.cruiseSpeed + appliedCruise,-29990,29990)\nend\n\nfunction getControlMode()\n\treturn ship.alternateCM and \"Cruise\" or \"Travel\"\nend\n\nfunction altHoldAdjustmentSetting()\n\treturn altHoldAdjustment * (10^altAdjustment)\nend\n\nfunction setAltHoldAdjustment()\nend\n\nfunction SHUDMenuItem(content, action, update)\n\tlocal self = {}\n\tself.Enabled = true\n\tself.Active = false\n\tself.Content = content\n\tself.Class = \"\"\n\tself.Action = action or function(system, unit, self) end\n\tself.Update = update or function(system, unit, self) end\n\n\tfunction self.Disable()\n\t\tself.Enabled = false\n\t\treturn self\n\tend\n\n\tfunction self.Enable()\n\t\tself.Enabled = true\n\t\treturn self\n\tend\n\n\tfunction self.Lock()\n\t\tSHUD.ScrollLock = true\n\t\tself.Active = true\n\t\tself.Class = \"locked\"\n\t\treturn self\n\tend\n\n\tfunction self.Unlock()\n\t\tSHUD.ScrollLock = false\n\t\tself.Active = false\n\t\tself.Class = \"\"\n\t\treturn self\n\tend\n\n\treturn self\nend\n\nSHUD =\n(function()\n\tlocal self = {}\n\tself.Enabled = false\n\tself.FreezeUpdate = false\n\tself.IntroPassed = false\n\n\tself.FOV = system.getCameraHorizontalFov()\n\tself.ScreenW = system.getScreenWidth()\n\tself.ScreenH = system.getScreenHeight()\n\tself.Resolution = vec2(self.ScreenW, self.ScreenH)\n\n\tself.SvgMinX = -round((self.ScreenW / 4) / 2,0)\n\tself.SvgMinY = -round((self.ScreenH / 4) / 2,0)\n\tself.SvgWidth = round(self.ScreenW / 4,0)\n\tself.SvgHeight = round(self.ScreenH / 4,0)\n\n\tfunction scaleViewBounds(input)\n\t\tlocal rMin = -0.5\n\t\tlocal rMax = 0.5\n\t\tlocal tMin = -90\n\t\tlocal tMax = 90\n\t\treturn -(((input - rMin) / (rMax - rMin)) * (tMax - tMin) + tMin)\n\tend\n\n\tshipPitch = scaleViewBounds(ship.pitchRatio)\n\n\tself.SHUDAtmoFuelHtml = \"\"\n\tself.SHUDSpaceFuelHtml = \"\"\n\n\tself.Markers = {}\n\n\tself.MarkerBuffer = {}\n\n\tfunction self.worldToScreen(position)\n\t\tlocal P = mat4():perspective(self.FOV, self.ScreenW/self.ScreenH, 0.1, 100000)\n\t\t--local adjustedPos = ship.world.position - vec3(system.getPlayerWorldPos())\n\t\tlocal adjustedPos = ship.world.position - vec3(player.getWorldHeadPosition())\n\t\tlocal V = mat4():look_at(adjustedPos, adjustedPos + ship.world.forward, ship.world.up)\n\n\t\tlocal pos = V * P * { position.x, position.y, position.z, 1 }\n\n\t\tpos[1] = pos[1] / pos[4] * 0.5 + 0.5\n\t\tpos[2] = pos[2] / pos[4] * 0.5 + 0.5\n\n\t\tpos[1] = pos[1] * 100\n\t\tpos[2] = pos[2] * 100\n\n\t\treturn vec3(pos[1], pos[2], pos[3])\n\tend\n\n\tlocal SMI = SHUDMenuItem\n\tlocal DD = DynamicDocument\n\n\tfunction self.UpdateMarkers()\n\t\tself.MarkerBuffer = {}\n\t\tfor i=1,#self.Markers do\n\t\t\tlocal m = self.Markers[i]\n\t\t\tlocal marker = {}\n\t\t\tlocal p = vec3(0,0,0)\n\t\t\tif type(m.Position) == \"function\" then marker.pos = m.Position() p = m.Position() else marker.pos = m.Position p = m.Position end\n\t\t\tmarker.pos = self.worldToScreen(marker.pos)\n\t\t\tmarker.class = m.Class\n\t\t\tmarker.content = ' '\n\t\t\tif m.Name then marker.content = [[<div class=\"name\">]] .. m.Name .. [[</div>]] end\n\t\t\tif m.ShowDistance then marker.content = marker.content .. [[<div class=\"distance\">]] .. round2((ship.world.position - p):len()) .. [[m</div>]] end\n\t\t\tif marker.pos.z > 0 then self.MarkerBuffer[#self.MarkerBuffer + 1] = marker end\n\t\tend\n\tend\n\n\tlocal function esc(x)\n\t\treturn (x:gsub(\"%%\", \"%%%%\"))\n\tend\n\n\tfunction self.MakeBooleanIndicator(varName)\n\t\tlocal tmpl = [[<span class=\"right\">\n\t\t\t<i dd-if=\"varName == true\">✓ </i>\n\t\t\t<i dd-if=\"varName == false\">✘ </i>\n\t\t</span>]]\n\t\treturn tmpl:gsub(\"varName\", esc(varName))\n\tend\n\n\tfunction self.MakeSliderIndicator(varName, suffix)\n\t\tsuffix = suffix or \"\"\n\t\tlocal tmpl = [[<span class=\"right\">{{varName}}{{suffix}}<i>⇅ </i></span>]]\n\t\treturn tmpl:gsub(\"varName\", esc(varName)):gsub(\"{{suffix}}\", esc(suffix))\n\tend\n\n\tfunction self.GenerateMenuLink(text, link)\n\t\treturn SMI(text..self.MenuIcon, function() self.SelectMenu(link) end)\n\tend\n\n\tself.MenuIcon = [[<span class=\"right\"><i>> </i></span>]]\n\tself.BackButton = SMI([[<i>< </i> ]]..\"Back\", function() SHUD.Menu = SHUD.MenuList.prev SHUD.CurrentIndex = 1 end)\n\tself.Menu = {\n\t\tSMI(DD([[<span>Throttle<span>]]..self.MakeSliderIndicator(\"round2(ship.throttle * 100)\", \"%\")),\n\t\t\tfunction(_, _, w) if w.Active then w.Unlock() else w.Lock() end end,\n\t\t\tfunction(system, _ , w) ship.throttle = utils.clamp(ship.throttle + (system.getMouseWheel() * 0.05),-1,1) end),\n\n\t\tself.GenerateMenuLink(\"Stability Assist\", \"stability\"),\n\t\tself.GenerateMenuLink(\"Altitude Hold\", \"altHold\"),\n\t\tself.GenerateMenuLink(\"Ship Stats\", \"shipStats\"),\n\t\tSMI([[<i>ⓘ </i><span> Hotkeys</span>]]..self.MenuIcon, function() self.SelectMenu(\"hotkeys\") end)\n\t}\n\tself.MenuList = {}\n\tself.MenuList.flightMode = {}\n\tself.MenuList.shipStats = {\n\t\tSMI(DD([[<span>Core ID:</span><span class=\"right\">{{ship.id}}</span>]])).Disable(),\n\t\tSMI(DD([[<span>Mass:</span><span class=\"right\">{{round2(ship.mass/1000,2)}} Ton</span>]])).Disable(),\n\t\tSMI(DD([[<span>FMax:</span><span class=\"right\">{{round2(ship.fMax/1000,2)}} KN</span>]])).Disable(),\n\t\tSMI(DD([[<span>Pos X:</span><span class=\"right\">{{round2(ship.world.position.x)}}</span>]])).Disable(),\n\t\tSMI(DD([[<span>Pos Y:</span><span class=\"right\">{{round2(ship.world.position.y)}}</span>]])).Disable(),\n\t\tSMI(DD([[<span>Pos Z:</span><span class=\"right\">{{round2(ship.world.position.z)}}</span>]])).Disable(),\n\t}\n\n\tself.MenuList.stability = {\n\t\tSMI(DD(\"<span>Gravity Suppression<span>\" .. self.MakeBooleanIndicator(\"ship.counterGravity\")), function() ship.counterGravity = not ship.counterGravity end),\n\t\tSMI(DD(\"<span>Gravity Follow</span>\" .. self.MakeBooleanIndicator(\"ship.followGravity\")), function() ship.followGravity = not ship.followGravity end),\n\t\tSMI(DD(\"<span>Inertial Dampening<span>\" .. self.MakeBooleanIndicator(\"ship.inertialDampening\")), function() ship.inertialDampeningDesired = not ship.inertialDampeningDesired end),\n\t\tSMI(DD([[<span>Hover Height<span>]]..self.MakeSliderIndicator(\"ship.hoverHeight\", \"m\")),\n\t\t\t function(_, _, w) if w.Active then w.Unlock() else w.Lock() end end,\n\t\t\t function(system, _ , w) ship.hoverHeight = utils.clamp(ship.hoverHeight + (system.getMouseWheel()),0,35) end),\n\t}\n\tfunction self.updateTargetDest()\n\t\tship.targetDestination = moveWaypointZ(ship.baseLoc, utils.clamp(ship.altitudeHold + (system.getMouseWheel() * altHoldAdjustmentSetting()),0,2000000) - ship.baseAltitude)\n\t\tship.altitudeHold = utils.clamp(ship.altitudeHold + (system.getMouseWheel() * altHoldAdjustmentSetting()),0,2000000)\n\tend\n\n\tfunction self.updateAltHoldMenu()\n\t\tself.MenuList.altHold = {\n\t\t\tSMI(DD(\"<span>Altitude Hold<span>\" .. self.MakeBooleanIndicator(\"ship.elevatorActive\")), function() ship.elevatorActive = not ship.elevatorActive end),\n\t\t\tSMI(DD([[<span>Multiplier<span>]]..self.MakeSliderIndicator(\"round2(altHoldAdjustmentSetting(),3)\", \"\")),\n\t\t\t\tfunction(_, _, w) if w.Active then w.Unlock() else w.Lock() end end,\n\t\t\t\tfunction(system, _ , w) altAdjustment = utils.clamp(altAdjustment + (system.getMouseWheel()),-1,4) end),\n\t\t\tSMI(DD([[<span>Alt Setpoint<span>]]..self.MakeSliderIndicator(\"round2(ship.altitudeHold,3)\", \"m\")),\n\t\t\t\tfunction(_, _, w) if w.Active then w.Unlock() else w.Lock() end end,\n\t\t\t\tfunction(system, _ , w) self.updateTargetDest() end),\n\t\t\tSMI(DD([[<span>Preset 1:</span><span class=\"right\">]].. mToKm(ship.altHoldPreset1)..\"</span>\"), function() ship.altitudeHold = ship.altHoldPreset1 ship.elevatorActive = true end),\n\t\t\tSMI(DD([[<span>Preset 2:</span><span class=\"right\">]].. mToKm(ship.altHoldPreset2)..\"</span>\"), function() ship.altitudeHold = ship.altHoldPreset2 ship.elevatorActive = true end),\n\t\t\tSMI(DD([[<span>Preset 3:</span><span class=\"right\">]].. mToKm(ship.altHoldPreset3)..\"</span>\"), function() ship.altitudeHold = ship.altHoldPreset3 ship.elevatorActive = true end),\n\t\t\tSMI(DD([[<span>Preset 4:</span><span class=\"right\">]].. mToKm(ship.altHoldPreset4)..\"</span>\"), function() ship.altitudeHold = ship.altHoldPreset4 ship.elevatorActive = true end),\n\t\t\tSMI(DD([[<span>Altitude:</span><span class=\"right\">{{round2(ship.altitude,4)}}</span>]])).Disable(),\n\t\t}\n\tend\n\n\tself.MenuList.hotkeys = {}\n\n\tlocal fa = \"<style>\" .. CSS_SHUD .. \"</style>\"\n\tself.fuel = nil\n\tfunction getFuelRenderedHtml()\n\t\tself.fuel = getFuelSituation()\n\n\t\tlocal mkTankHtml = (function (type, tank)\n\t\t\tlocal tankLevel = 100 * tank.level\n\t\t\tlocal tankLiters = tank.level * tank.specs.capacity()\n\n\t\t\treturn '<div class=\"fuel-meter fuel-type-' .. type ..'\"><hr class=\"fuel-level\" style=\"width:'..\n\t\t\t\ttankLevel..'%%;\" /><span>'..tank.name..': '..tank.time..' ('..\n\t\t\t\tmath.floor(tankLevel)..'%%, '..math.floor(tankLiters)..'L)</span></div>'\n\t\tend)\n\n\t\tself.SHUDAtmoFuelHtml = ''\n\t\tself.SHUDSpaceFuelHtml = ''\n\t\tif next(self.fuel.atmo) then\n\t\t\tlocal fuelHtml = '<div class=\"fuel-tanks fuel-type-atmo\">'\n\t\t\tfor _, tank in pairs(self.fuel.atmo) do fuelHtml = fuelHtml .. mkTankHtml(\"atmo\", tank) end\n\t\t\tself.SHUDAtmoFuelHtml = fuelHtml ..'</div>'\n\t\tend\n\t\tif next(self.fuel.space) then\n\t\t\tfuelHtml = '<div class=\"fuel-tanks fuel-type-space\">'\n\t\t\tfor _, tank in pairs(self.fuel.space) do fuelHtml = fuelHtml .. mkTankHtml(\"space\", tank) end\n\t\t\tself.SHUDSpaceFuelHtml = fuelHtml ..'</div>'\n\t\tend\n\n\t\t-- we ignore rocket tanks for now\n\t\t-- fuelHtml = '<div class=\"fuel-tanks fuel-type-rocket\">'\n\t\t-- for _, tank in pairs(self.fuel.rocket) do fuelHtml = fuelHtml .. mkTankHtml(\"rocket\", tank) end\n\t\t-- self.SHUDRocketFuelHtml = fuelHtml ..'</div>'\n\tend\n\n\topacity = 0.5\n\tlocal template = DD(fa..[[\n\t<div id=\"horizon\" style=\"opacity: {{opacity}};\">\n\t\t<div id=\"speedometerBar\"> </div>\n\t\t\t<div id=\"speedometer\">\n\t\t\t\t<span class=\"display\">\n\t\t\t\t\t<span class=\"major\">{{SpeedConvert(ship.world.velocity:len())[1]}}</span>\n\t\t\t\t\t<span class=\"minor\">{{SpeedConvert(ship.world.velocity:len())[2]}}</span>\n\t\t\t\t\t<span class=\"unit\">{{SpeedConvert(ship.world.velocity:len())[3]}}</span>\n\t\t\t\t</span>\n\t\t\t\t<span class=\"accel\">\n\t\t\t\t\t<span class=\"major\">{{round2(ship.world.acceleration:len(), 1)}}</span>\n\t\t\t\t\t<span class=\"unit\">m/s</span>\n\t\t\t\t</span>\n\t\t\t\t\t<span class=\"vertical\">\n\t\t\t\t\t{{round2(ship.world.velocity:dot(-ship.world.gravity:normalize()), 1)}}\n\t\t\t\t</span>\n\t\t\t\t<span class=\"alt\">{{round2(ship.altitude)}}m</span>\n\n\t\t\t\t<span class=\"misc\">ATM {{round2(ship.world.atmosphericDensity, 2)}} | G {{round2(ship.world.gravity:len(), 2)}}m/s</span>\n\t\t\t\t<span dd-if=\"not ship.alternateCM\" class=\"throttle\">Throttle {{round2(ship.throttle * 100)}}%</span>\n\t\t\t\t<span dd-if=\"ship.alternateCM\" class=\"throttle\">Cruise {{round2(ship.cruiseSpeed)}} km/h</span>\n\t\t\t</div>\n\n\t\t\t<div id=\"horizon-menu\">{{_SHUDBUFFER}}</div>\n\n\t\t</div>\n\t\t<div id=\"fuelTanks\">\n\t\t\t{{ SHUD.SHUDAtmoFuelHtml }}\n\t\t\t{{ SHUD.SHUDSpaceFuelHtml }}\n\t\t</div>\n\t</div>\n\t]])\n\tlocal itemTemplate = [[<div class=\"item {{class}}\">{{content}}</div>]]\n\tfunction self.SelectMenu(menuName)\n\t\tif not SHUD.MenuList[menuName] then error(\"[SHUD] Undefined menu: \" .. menuName) end\n\t\tSHUD.MenuList.prev = SHUD.Menu\n\t\tSHUD.Menu = SHUD.MenuList[menuName]\n\t\tSHUD.CurrentIndex = 1\n\t\tif SHUD.Menu[#SHUD.Menu] ~= SHUD.BackButton then table.insert(SHUD.Menu, SHUD.BackButton) end\n\tend\n\n\tfunction self.Select()\n\t\tif not self.Enabled then return end\n\t\tif #self.Menu < 1 then\n\t\t\treturn\n\t\tend\n\t\tself.Menu[self.CurrentIndex].Action(self.system, self.unit, self.Menu[self.CurrentIndex])\n\tend\n\n\tfunction self.Render()\n\t\tlocal buffer = \"\"\n\t\tif self.Enabled then\n\t\t\tfor i = 1, #self.Menu do\n\t\t\t\tlocal item = self.Menu[i]\n\t\t\t\tif item.Active then item.Update(self.system, self.unit, item) end\n\t\t\t\tlocal lb = itemTemplate\n\t\t\t\tlocal cls = \"\"\n\t\t\t\tlocal content = item.Content\n\t\t\t\tif content.Read then\n\t\t\t\t\tcontent = content.Read()\n\t\t\t\tend\n\t\t\t\tcontent = esc(content)\n\t\t\t\tif self.CurrentIndex == i then\n\t\t\t\t\tcls = \"active\"\n\t\t\t\tend\n\t\t\t\tif not item.Enabled then cls = cls .. \" disabled\" end\n\t\t\t\tlb = lb:gsub(\"{{class}}\", cls .. \" \" .. item.Class)\n\t\t\t\tlb = lb:gsub(\"{{content}}\", content)\n\t\t\t\tbuffer = buffer .. lb\n\t\t\tend\n\t\t\t_ENV[\"_SHUDBUFFER\"] = esc(buffer)\n\t\telse\n\t\t\tship.frozen = player.isFrozen()\n\t\t\t_ENV[\"_SHUDBUFFER\"] = DD([[<div class=\"item helpText\">Press ]] .. \"[\" .. self.system.getActionKeyName(\"speedup\") .. \"]\" .. [[ to toggle menu</div>\n\t\t\t\t<div class=\"item helpText\"><span>Character Movement:</span>]].. self.MakeBooleanIndicator(\"ship.frozen\") .. [[</div>\n\t\t\t\t<div class=\"item helpText\"><span>Vertical Lock:</span>]].. self.MakeBooleanIndicator(\"ship.verticalLock\") .. [[</div>\n\t\t\t\t<div class=\"item helpText\"><span>Inertial Dampening:</span>]].. self.MakeBooleanIndicator(\"ship.inertialDampening\") .. [[</div>\n\t\t\t\t<div class=\"item helpText\"><span>Gravity Follow:</span>]].. self.MakeBooleanIndicator(\"ship.followGravity\") .. [[</div>\n\t\t\t\t<div class=\"item helpText\"><span>Gravity Supression:</span>]].. self.MakeBooleanIndicator(\"ship.counterGravity\") .. [[</div>\n\t\t\t\t<div class=\"item helpText\"><span>Open Door:</span><span class=\"right\">F5</span></div>\n\t\t\t\t<div class=\"item helpText\"><span>Close Door:</span><span class=\"right\">F6</span></div>\n\t\t\t\t]]).Read()\n\t\tend\n\t\tif not self.FreezeUpdate then\n\t\t\tself.system.setScreen(template.Read())\n\t\tend\n\tend\n\n\tfunction self.Update()\n\t\tupdateGEAS()\n\t\t-- if useGEAS then\n\t\t-- \tunit.activateGroundEngineAltitudeStabilization(ship.hoverHeight)\n\t\t-- end\n\t\tif self.Enabled then\n\t\t\topacity = 1\n\t\telse\n\t\t\topacity = 0.5\n\t\tend\n\t\tif not self.ScrollLock and self.Enabled then\n\t\t\tlocal wheel = system.getMouseWheel()\n\t\t\tif wheel ~= 0 then\n\t\t\t\tself.CurrentIndex = self.CurrentIndex - wheel\n\t\t\t\tif self.CurrentIndex > #self.Menu then self.CurrentIndex = 1\n\t\t\t\telseif self.CurrentIndex < 1 then self.CurrentIndex = #self.Menu end\n\t\t\tend\n\t\telseif not self.Enabled then\n\t\t\tif player.isFrozen() and unit.isRemoteControlled() then\n\t\t\t\tship.throttle = utils.clamp(ship.throttle + (system.getMouseWheel() * 0.05),-1,1)\n\t\t\tend\n\t\t\tself.UpdateMarkers()\n\t\tend\n\tend\n\n\tfunction self.Init(system, unit, keybinds)\n\t\tself.system = system\n\t\tself.unit = unit\n\t\tself.CurrentIndex = 1\n\t\tself.ScrollLock = false\n\t\tsystem.showScreen(true)\n\t\tunit.hideWidget()\n\t\tlocal keys = keybinds.GetNamedKeybinds()\n\t\tself.updateAltHoldMenu()\n\t\tself.MenuList.hotkeys = {}\n\t\tfor i=1,#keys do\n\t\t\tlocal key = keys[i]\n\t\t\ttable.insert(self.MenuList.hotkeys, SMI([[<span>]]..key.Name..[[</span><span class=\"right\">]]..self.system.getActionKeyName(key.Key)..[[</span>]]).Disable())\n\t\tend\n\n\t\tself.MenuList.flightMode = {}\n\t\tfor k,v in pairs(keybindPresets) do\n\t\t\ttable.insert(self.MenuList.flightMode,\n\t\t\tSMI(string.upper(k), function()\n\t\t\t\tself.Init(self.system, self.unit, v)\n\t\t\t\tkeybindPreset = k\n\t\t\t\tkeybindPresets[keybindPreset].Init()\n\t\t\tend))\n\t\tend\n\t\tkeybinds.Init()\n\tend\n\n\treturn self\nend)()\n",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "15"
},
{
"code": "--@class STEC_Config\nlocal P, clamp = system.print, utils.clamp\n\nship.hoverHeight = tonumber(GEAS_Alt) or 10\nship.autoShutdown = autoShutdown == true\nship.altitudeHold = round2(ship.altitude,2)\nship.inertialDampeningDesired = inertialDampening == true\nship.followGravity = followGravity == true\nship.minRotationSpeed = tonumber(minRotationSpeed) or 0.01\nship.maxRotationSpeedz = tonumber(maxRotationSpeed) or 5\nship.rotationStep = tonumber(rotationStep) or 0.025\n\nship.verticalSpeedLimitAtmo = tonumber(verticalSpeedLimitAtmo) or 1100\nship.verticalSpeedLimitSpace = tonumber(verticalSpeedLimitSpace) or 4000\nship.approachSpeed = tonumber(approachSpeed) or 100\n\nship.deviationThreshold = tonumber(deviationThreshold) or 0.5\nship.pocket = pocket == true\nship.breadCrumbDist = tonumber(breadCrumbDist) or 1000\n\nContainerOptimization = clamp(tonumber(ContainerOptimization) or 0, 0, 5)\nFuelTankOptimization = clamp(tonumber(FuelTankOptimization) or 0, 0, 5)\nfuelTankHandlingAtmo = clamp(tonumber(fuelTankHandlingAtmo) or 0, 0, 5)\nfuelTankHandlingSpace = clamp(tonumber(fuelTankHandlingSpace) or 0, 0, 5)\ndockingMode = clamp(tonumber(dockingMode) or 1, 1, 3)\n\ncontrolStateChange = true\n\nlocal shiftLock = false\n\nlocal bool_to_number={ [true]=1, [false]=0 }\nlocal number_to_bool={ [1]=true, [0]=false }\n\nlocal function validatePresets()\n\tship.altHoldPreset1 = tonumber(ship.altHoldPreset1) or 0\n\tship.altHoldPreset2 = tonumber(ship.altHoldPreset2) or 0\n\tship.altHoldPreset3 = tonumber(ship.altHoldPreset3) or 0\n\tship.altHoldPreset4 = tonumber(ship.altHoldPreset4) or 0\nend\n\nlocal function validateBool(key, default)\n\tif not flightModeDb.hasKey(key) or updateSettings then\n\t\tflightModeDb.setIntValue(key, bool_to_number[default == true])\n\tend\n\treturn number_to_bool[clamp(flightModeDb.getIntValue(key),0,1)]\nend\n\nlocal function validateFloat(key, default, clampMin, clampMax)\n\tif tonumber(clampMin) and tonumber(clampMax) then\n\t\tdefault = clamp(tonumber(default) or clampMin, clampMin, clampMax)\n\tend\n\tif not flightModeDb.hasKey(key) or updateSettings then\n\t\tflightModeDb.setFloatValue(key, default)\n\tend\n\tif not (tonumber(clampMin) and tonumber(clampMax)) then\n\t\treturn flightModeDb.getFloatValue(key)\n\tend\n\treturn clamp(flightModeDb.getFloatValue(key),clampMin,clampMax)\nend\n\nlocal function validateInt(key, default, clampMin, clampMax)\n\tif tonumber(clampMin) and tonumber(clampMax) then\n\t\tdefault = clamp(tonumber(default) or clampMin, clampMin, clampMax)\n\tend\n\tif not flightModeDb.hasKey(key) or updateSettings then\n\t\tflightModeDb.setIntValue(key, default)\n\tend\n\tif not (tonumber(clampMin) and tonumber(clampMax)) then\n\t\treturn flightModeDb.getIntValue(key)\n\tend\n\treturn clamp(flightModeDb.getIntValue(key),clampMin,clampMax)\nend\n\nfunction writeVecToDb(cVector, name)\n\tif flightModeDb and name and vec3.isvector(cVector) then\n\t\tsettingsActive = false\n\t\tflightModeDb.setFloatValue(name..\"X\", cVector.x)\n\t\tflightModeDb.setFloatValue(name..\"Y\", cVector.y)\n\t\tflightModeDb.setFloatValue(name..\"Z\", cVector.z)\n\t\t-- P(\"[I] Wrote \"..name..\": \"..tostring(cVector))\n\tend\nend\n\nfunction readVecFromDb(name)\n\tif flightModeDb and name then\n\t\tlocal v = vec3(0,0,0)\n\t\tv.x = flightModeDb.getFloatValue(name..\"X\")\n\t\tv.y = flightModeDb.getFloatValue(name..\"Y\")\n\t\tv.z = flightModeDb.getFloatValue(name..\"Z\")\n\t\t-- P(\"[I] Read \"..name..\": \"..tostring(v))\n\t\treturn v\n\tend\nend\n\nfunction gearToggle()\n\tif unit.isAnyLandingGearExtended() then\n\t\tunit.retractLandingGears()\n\telse\n\t\tunit.extendLandingGears()\n\tend\nend\nfunction scaleViewBound(rMin,rMax,tMin,tMax,input)\n\treturn ((input - rMin) / (rMax - rMin)) * (tMax - tMin) + tMin\nend\nfunction switchFlightMode(flightMode)\n\tSHUD.Init(system, unit, keybindPresets[flightMode])\n\tkeybindPreset = flightMode\n\tif flightModeDb then flightModeDb.setStringValue(\"flightMode\",flightMode) end\nend\nfunction switchControlMode()\n\tship.alternateCM = not ship.alternateCM\nend\nfunction swapSwitchesAndFF()\n\ttoggleForceFields(player.isFrozen())\n\ttoggleSwitches(player.isFrozen())\nend\n\nfunction setAgl(a)\n\tlocal num = tonumber(a)\n\tif num then\n\t\tship.agl = num\n\tend\n\tif flightModeDb then flightModeDb.setFloatValue(\"agl\",ship.agl) end\n\tconfig.agl = ship.agl\n\tP('AGL: '..ship.agl)\nend\n\nfunction setBase(a)\n\tif not ship.nearestPlanet then return P'[E] No gravity well for setting base!' end\n\tship.rot = ship.world.right:cross(ship.nearestPlanet:getGravity(construct.getWorldPosition()))\n\tif type(a) ~= \"string\" or a == \"\" then\n\t\tship.baseLoc = ship.world.position\n\telseif string.find(a, \"::pos\") ~= nil then\n\t\tlocal locTmp = ship.nearestPlanet:convertToWorldCoordinates(a)\n\t\tif not vec3.isvector(locTmp) then\n\t\t\tP(\"[E] Invalid location string: \"..a)\n\t\t\treturn\n\t\tend\n\t\tship.baseLoc = locTmp\n\tend\n\twriteVecToDb(ship.baseLoc,\"BaseLoc\")\n\twriteVecToDb(ship.rot, \"BaseRot\")\n\tconfig.rtb = helios:closestBody(ship.baseLoc):getAltitude(ship.baseLoc)\n\tioScheduler.queueData(config)\nend\n\nfunction updateGEAS()\n\tif useGEAS and not config.manualControl then\n\t\tunit.activateGroundEngineAltitudeStabilization(ship.hoverHeight)\n\telse\n\t\tunit.deactivateGroundEngineAltitudeStabilization()\n\tend\nend\n\nfunction normalizeTravelMode()\n\tif ship.controlMode == 1 and controlStateChange then\n\t\tship.cruiseSpeed = round(ship.world.velocity:len() * 3.6,-1)\n\t\tship.throttle = 0\n\t\tcontrolStateChange = false\n\telseif ship.controlMode == 0 then\n\t\tcontrolStateChange = true\n\tend\nend\n\nfunction autoLandingGear()\n\tif ship.world.velocity:len() >= 83.3333 then\n\t\tunit.retractLandingGears()\n\telse\n\t\tunit.extendLandingGears()\n\tend\nend\n\nfunction STEC_configInit()\n\t-- default to current location/rotation\n\tship.baseLoc = ship.world.position\n\tship.rot = ship.world.forward\n\n\tvalidatePresets()\n\n\tif not flightModeDb then\n\t\tP(\"[E] No databank found!\")\n\telse\n\t\tP(\"[I] Databank found.\")\n\t\t-- assure that keys exist in the databank for each saved setting\n\t\tdockingMode = validateInt(\"dockingMode\", dockingMode, 1, 3)\n\n\t\tactivateFFonStart = validateBool(\"activateFFonStart\", setactivateFFonStart)\n\t\tactivateFFonStop = validateBool(\"activateFFonStop\", setactivateFFonStop)\n\n\t\tactivateLasersOnStart = validateBool(\"activateLasersOnStart\", setactivateLasersOnStart)\n\t\tactivateLasersOnStop = validateBool(\"activateLasersOnStop\", setactivateLasersOnStop)\n\n\t\tactivateSwitchOnStart = validateBool(\"activateSwitchOnStart\", setactivateSwitchOnStart)\n\t\tactivateSwitchOnStop = validateBool(\"activateSwitchOnStop\", setactivateSwitchOnStop)\n\n\t\tlockVerticalToBase = validateBool(\"lockVerticalToBase\", lockVerticalToBase)\n\n\t\tpocket = validateBool(\"pocket\", setpocket)\n\n\t\tship.verticalSpeedLimitAtmo = validateFloat(\"verticalSpeedLimitAtmo\", verticalSpeedLimitAtmo, 0, 1100)\n\n\t\tverticalSpeedLimitSpace = clamp(tonumber(verticalSpeedLimitSpace) or 4000, 100, 10000)\n\t\tship.verticalSpeedLimitSpace = validateFloat(\"verticalSpeedLimitSpace\", verticalSpeedLimitSpace, 100, 10000)\n\n\t\tship.approachSpeed = validateFloat(\"approachSpeed\", approachSpeed, 50, 300)\n\n\t\tship.altHoldPreset1 = validateFloat(\"altHoldPreset1\", altHoldPreset1, 0, 200000000)\n\t\tship.altHoldPreset2 = validateFloat(\"altHoldPreset2\", altHoldPreset2, 0, 200000000)\n\t\tship.altHoldPreset3 = validateFloat(\"altHoldPreset3\", altHoldPreset3, 0, 200000000)\n\t\tship.altHoldPreset4 = validateFloat(\"altHoldPreset4\", altHoldPreset4, 0, 200000000)\n\n\t\tif flightModeDb.hasKey(\"BaseLocX\") then\n\t\t\tship.baseLoc = readVecFromDb(\"BaseLoc\")\n\t\t\t-- only load rotation if location exists\n\t\t\tif flightModeDb.hasKey(\"BaseRotX\") then\n\t\t\t\tship.rot = readVecFromDb(\"BaseRot\")\n\t\t\telse\n\t\t\t\tconfig.setBaseActive = true\n\t\t\tend\n\t\telse\n\t\t\tconfig.setBaseActive = true\n\t\tend\n\n\t\t-- validate settings that do not originate from LUA parameters\n\t\t-- need to turn off updateSetting\n\t\tupdateSettings = false\n\t\tship.agl = validateFloat(\"agl\", ship.agl, 0, 10)\n\tend\nend\n\nfunction ElevatorInit()\n\televatorName = construct.getName()\n\tconfig.floors.floor1 = ship.altHoldPreset1\n\tconfig.floors.floor2 = ship.altHoldPreset2\n\tconfig.floors.floor3 = ship.altHoldPreset3\n\tconfig.floors.floor4 = ship.altHoldPreset4\n\tconfig.targetAlt = 0\n\n\tP(\"Preset 1: \"..config.floors.floor1)\n\tP(\"Preset 2: \"..config.floors.floor2)\n\tP(\"Preset 3: \"..config.floors.floor3)\n\tP(\"Preset 4: \"..config.floors.floor4)\n\n\tioScheduler.defaultData = stats\n\tioScheduler.queueData(config)\n\t-- ioScheduler.queueData(fuelAtmo)\n\t-- ioScheduler.queueData(fuelSpace)\nend\n\nlocal function doAlt7() -- RTB\n\tif elevatorScreen and vec3.isvector(ship.baseLoc) and ship.baseLoc ~= vec3() and ship.baseAltitude and ship.baseAltitude > 0 then\n\t\tship.altitudeHold = ship.baseAltitude\n\t\tship.targetDestination = moveWaypointZ(ship.baseLoc, 0)\n\t\tship.elevatorActive = true\n\tend\nend\n\nlocal function doAlt9() -- Manual Mode Toggle\n\tif shiftLock then\n\t\tif flightModeDb then\n\t\t\tflightModeDb.clear() P(\"[I] DB cleared!\")\n\t\tend\n\telse\n\t\tconfig.manualControl = not config.manualControl\n\t\tmanualControlSwitch()\n\tend\nend\n\nlocal function sendDoorCommand(cmd)\n\tif emitter then\n\t\temitter.send(\"door_control\",cmd)\n\tend\nend\n\nlocal tty = DUTTY\ntty.onCommand('setbase', function(a) setBase(a) end)\ntty.onCommand('setagl', function(a) setAgl(a) end)\n\nkeybindPresets[\"keyboard\"] = KeybindController()\nkeybindPresets[\"keyboard\"].Init = function()\n\tkeybindPreset = \"keyboard\"\n\t--mouse.enabled = false\n\t--mouse.unlock()\n\tship.ignoreVerticalThrottle = true\n\tship.throttle = 1\n\t--ship.direction.y = 0\nend\n\n-- keyboard\nkeybindPresets[\"keyboard\"].keyDown.up.Add(function () ship.direction.z = 1 if not ship.counterGravity then ship.counterGravity = true end end)\nkeybindPresets[\"keyboard\"].keyUp.up.Add(function () ship.direction.z = 0 end)\nkeybindPresets[\"keyboard\"].keyDown.down.Add(function () ship.direction.z = -1 end)\nkeybindPresets[\"keyboard\"].keyUp.down.Add(function () ship.direction.z = 0 end)\n\nkeybindPresets[\"keyboard\"].keyDown.yawleft.Add(function () ship.rotation.z = -1 end)\nkeybindPresets[\"keyboard\"].keyUp.yawleft.Add(function () ship.rotation.z = 0 ship.rotationSpeedz = ship.minRotationSpeed end)\nkeybindPresets[\"keyboard\"].keyDown.yawright.Add(function () ship.rotation.z = 1 end)\nkeybindPresets[\"keyboard\"].keyUp.yawright.Add(function () ship.rotation.z = 0 ship.rotationSpeedz = ship.minRotationSpeed end)\n\nkeybindPresets[\"keyboard\"].keyDown.forward.Add(function () ship.direction.y = 1 end)\nkeybindPresets[\"keyboard\"].keyUp.forward.Add(function () ship.direction.y = 0 end)\n\nkeybindPresets[\"keyboard\"].keyDown.backward.Add(function () ship.direction.y = -1 end)\nkeybindPresets[\"keyboard\"].keyUp.backward.Add(function () ship.direction.y = 0 end)\n\nkeybindPresets[\"keyboard\"].keyDown.backward.Add(function () ship.direction.y = -1 end)\nkeybindPresets[\"keyboard\"].keyUp.backward.Add(function () ship.direction.y = 0 end)\n\nkeybindPresets[\"keyboard\"].keyDown.left.Add(function () ship.direction.x = -1 end) --q\nkeybindPresets[\"keyboard\"].keyUp.left.Add(function () ship.direction.x = 0 end) --q\nkeybindPresets[\"keyboard\"].keyDown.right.Add(function () ship.direction.x = 1 end) --e\nkeybindPresets[\"keyboard\"].keyUp.right.Add(function () ship.direction.x = 0 end) --e\n\nkeybindPresets[\"keyboard\"].keyDown.lshift.Add(function () shiftLock = true end,\"Shift Modifier\")\nkeybindPresets[\"keyboard\"].keyUp.lshift.Add(function () shiftLock = false end)\n\nkeybindPresets[\"keyboard\"].keyDown.brake.Add(function () ship.brake = true end)\nkeybindPresets[\"keyboard\"].keyUp.brake.Add(function () ship.brake = false end)\n\nkeybindPresets[\"keyboard\"].keyUp.stopengines.Add(function ()\n\tSHUD.Select()\n\tif not SHUD.Enabled then\n\t\tif ship.direction.y ~= 0 then ship.direction.y = 0\n\t\telse ship.direction.y = 1 end\n\tend\nend, \"Cruise\")\n\nkeybindPresets[\"keyboard\"].keyUp.gear.Add(function () useGEAS = not useGEAS; updateGEAS() end)\nkeybindPresets[\"keyboard\"].keyUp.speedup.Add(function () SHUD.Enabled = not SHUD.Enabled end)\nkeybindPresets[\"keyboard\"].keyUp[\"option1\"].Add(function () ship.inertialDampeningDesired = not ship.inertialDampeningDesired end, \"Inertial Dampening\")\nkeybindPresets[\"keyboard\"].keyUp[\"option2\"].Add(function () player.freeze(not player.isFrozen()); swapSwitchesAndFF() end,\"Freeze character\")\nkeybindPresets[\"keyboard\"].keyUp[\"option3\"].Add(function () ship.followGravity = not ship.followGravity end, \"Gravity Follow\")\nkeybindPresets[\"keyboard\"].keyUp[\"option4\"].Add(function () ship.counterGravity = not ship.counterGravity end, \"Counter Gravity\")\nkeybindPresets[\"keyboard\"].keyUp[\"option5\"].Add(function ()\n\tship.verticalLock = true\n\tship.lockVector = vec3(construct.getWorldOrientationUp())\n\tship.lockPos = vec3(construct.getWorldPosition()) + (vec3(construct.getWorldOrientationUp()))\n\twriteVecToDb(ship.lockVector,\"lockVector\")\n\twriteVecToDb(ship.lockPos,\"lockPos\")\nend,\"Set Vertical Lock\")\nkeybindPresets[\"keyboard\"].keyUp[\"option6\"].Add(function () ship.verticalLock = not ship.verticalLock end,\"Toggle Vertical Lock\")\n--keybindPresets[\"keyboard\"].keyUp[\"option7\"].Add(function () ship.verticalCruise = not ship.verticalCruise end, \"Vertical Cruise\")\nkeybindPresets[\"keyboard\"].keyUp[\"option7\"].Add(function() doAlt7() end, \"RTB\")\nkeybindPresets[\"keyboard\"].keyUp[\"option8\"].Add(function () construct.setDockingMode(1); if construct.undock() then P('[I] Undocked') end end,\"Undock\")\n--keybindPresets[\"keyboard\"].keyUp[\"option8\"].Add(function () sendDoorCommand(shiftLock and \"close\" or \"open\") end, \"Open Door\")\n--keybindPresets[\"keyboard\"].keyUp[\"option9\"].Add(function () if ship.targetDestination == nil then ship.targetDestination = moveWaypointZ(ship.baseLoc, 10000 - baseAltitude) else ship.targetDestination = nil end end, \"Preset 2\")\n--keybindPresets[\"keyboard\"].keyUp.option9.Add(function () if flightModeDb ~= nil then flightModeDb.clear() P(\"DB Cleared\") end end,\"Clear Databank\")\nkeybindPresets[\"keyboard\"].keyUp[\"option9\"].Add(function () doAlt9() end,\"Manual Mode Toggle\")\n\nkeybindPresets[\"screenui\"] = KeybindController()\nkeybindPresets[\"screenui\"].Init = function()\n\tkeybindPreset = \"screenui\"\n\tship.frozen = false\n\tship.ignoreVerticalThrottle = true\n\tship.throttle = 1\n\tplayer.freeze(ship.frozen)\nend\nkeybindPresets[\"screenui\"].keyUp.speedup.Add(function () SHUD.Enabled = not SHUD.Enabled end)\nkeybindPresets[\"screenui\"].keyDown.lshift.Add(function () shiftLock = true end,\"Shift Modifier\")\nkeybindPresets[\"screenui\"].keyUp.lshift.Add(function () shiftLock = false end)\nkeybindPresets[\"screenui\"].keyDown.brake.Add(function () ship.brake = true end)\nkeybindPresets[\"screenui\"].keyUp.brake.Add(function () ship.brake = false end)\nif next(forceFields) then\n\tkeybindPresets[\"screenui\"].keyUp[\"option2\"].Add(function () toggleForceFields(not shiftLock) end, \"De-/Activate Forcefields\")\nend\nif next(manualSwitches) then\n\tkeybindPresets[\"screenui\"].keyUp[\"option3\"].Add(function () toggleSwitches(not shiftLock) end, \"De-/Activate Switches\")\nend\nif next(lasers) then\n\tkeybindPresets[\"screenui\"].keyUp[\"option4\"].Add(function () toggleLasers(not shiftLock) end, \"De-/Activate Lasers\")\nend\nif emitter then\n\tkeybindPresets[\"screenui\"].keyUp[\"option5\"].Add(function () sendDoorCommand(\"open\") end, \"Open Door\")\n\tkeybindPresets[\"screenui\"].keyUp[\"option6\"].Add(function () sendDoorCommand(\"close\") end, \"Close Door\")\nend\nkeybindPresets[\"screenui\"].keyUp[\"option7\"].Add(function() doAlt7() end, \"RTB\")\nkeybindPresets[\"screenui\"].keyUp[\"option8\"].Add(function () construct.setDockingMode(1); construct.undock() end,\"Undock\")\nkeybindPresets[\"screenui\"].keyUp[\"option9\"].Add(function () doAlt9() end,\"Manual Mode Toggle\")\n\n-- Note: in this elevator script version, the flight mode still contains \"keyboard\",\n-- which in later versions of Horizon is replaced with Standard/Maneuver\nkeybindPreset = \"keyboard\"\nif flightModeDb then\n if not flightModeDb.hasKey(\"flightMode\") then flightModeDb.setStringValue(\"flightMode\",\"keyboard\") end\n keybindPreset = flightModeDb.getStringValue(\"flightMode\")\n if keybindPreset ~= 'keyboard' and keybindPreset ~= 'screenui' then\n\t keybindPreset = 'keyboard'\n end\nend\n\nSHUD.Init(system, unit, keybindPresets[keybindPreset])\n\nTask(function()\n\tcoroutine.yield()\n\tSHUD.FreezeUpdate = true\n\t-- artificial pause to let system initialize\n\tlocal endTime = system.getArkTime() + 2\n\twhile system.getArkTime() < endTime do\n\t\tcoroutine.yield()\n\tend\n\tSHUD.FreezeUpdate = false\n\tSHUD.IntroPassed = true\nend)\n\nship.frozen = false\nplayer.freeze(ship.frozen)\n\nupdateGEAS()\n",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "16"
},
{
"code": "--@class ElevatorScreen\nElevatorScreen = (function ()\n local self = {}\n\n function self.updateStats()\n stats.data.elevation = ship.altitude\n stats.data.target = config.targetAlt\n stats.data.velocity = ship.world.velocity:len()\n stats.data.mass = ship.mass\n stats.data.gravity = ship.world.gravity:len()\n stats.data.target_dist = math.abs(ship.altitude - ship.altitudeHold)\n stats.data.brake_dist = ship.brakeDistance\n stats.data.deviation = ship.deviation\n stats.data.deviationVec = ship.worldToLocal(ship.deviationVec)\n stats.data.deviationRot = ship.worldToLocal(ship.deviationRot)\n\t\t\tstats.data.deviationRotAngle = angle_between(ship.world.forward, ship.rot) * (180 / math.pi)\n stats.data.state = ship.stateMessage\n\t\t\tstats.data.delta = nil\n\t\t\tstats.data.grounddistance = ship.GrndDist\n\t\t\tstats.data.agl = ship.agl\n\t\t\tstats.data.base = nil\n\t\t\tif vec3.isvector(ship.baseLoc) and ship.baseLoc ~= vec3() then\n\t\t\t\tstats.data.base = ship.baseLoc\n\t\t\tend\n end\n self.updateStats()\n -- function self.updateScreenFuel()\n -- fuelAtmo.tanks = {}\n -- fuelSpace.tanks = {}\n\n\t\t-- \tif next(SHUD.fuel.atmo) then\n\t\t-- \t\tfor _, tank in pairs(SHUD.fuel.atmo) do\n\t\t-- \t\t\ttable.insert(fuelAtmo.tanks,fuelTank(tank.time,math.ceil(100 * tank.level)))\n\t\t-- \t\tend\n\t\t-- \tend\n\t\t-- \tif next(SHUD.fuel.space) then\n\t\t-- \t\tfor _, tank in pairs(SHUD.fuel.space) do\n\t\t-- \t\t\ttable.insert(fuelSpace.tanks,fuelTank(tank.time,math.ceil(100 * tank.level)))\n\t\t-- \t\tend\n -- end\n -- ioScheduler.queueData(fuelAtmo)\n -- ioScheduler.queueData(fuelSpace)\n -- end\n if screen then screen.clearScriptOutput() end\n return self\nend)()",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "17"
},
{
"code": "--@require SimpleSlotDetector\n--@require ExportedVariables\n--@require PlanetRef\n--@require KinematicsMin\n--@require Serializer\n--@require EventDelegateMin\n--@require TaskManagerMin\n--@require DynamicDocumentMin\n--@require DUTTYMin\n--@require FuelTankHelper\n--@require KeybindControllerMin\n--@require IOScheduler\n--@require Utils3D\n--@require STEC\n--@require CSS_SHUD\n--@require SHUD\n--@require STEC_Config\n--@require ElevatorScreen\n--@timer SHUDRender\n--@timer FuelStatus\n--@timer DockingTrigger\n-- timer Debug\n--@outFilename Elevator.json\n--@class Main\n\n_G.BuildUnit = {}\nlocal Unit = _G.BuildUnit\n_G.BuildSystem = {}\nlocal System = _G.BuildSystem\n_G.BuildScreen = {}\nlocal buildScreen = _G.BuildScreen\n_G.BuildEmitter = {}\nlocal buildEmitter = _G.BuildEmitter\n\nlocal P = system.print\n\nelevatorScreen = nil -- global!\n\nfunction manualControlSwitch()\n\tlocal c = config.manualControl == true\n\tship.frozen = unit.isRemoteControlled() and c\n\tship.elevatorActive = not c\n\tship.counterGravity = true\n\tship.followGravity = true\n\tship.inertialDampening = true\n\tship.verticalLock = lockVerticalToBase and not c\n\tplayer.freeze(ship.frozen)\n\tif c then\n\t\tconfig.targetAlt = ship.baseAltitude\n\t\tship.altitudeHold = ship.baseAltitude\n\t\tship.targetDestination = nil\n\t\tship.stateMessage = \"Manual Control\"\n\t\tswitchFlightMode(\"keyboard\")\n\telse\n\t\tship.stateMessage = \"Idle\"\n\t\tswitchFlightMode(\"screenui\")\n\tend\nend\n\nfunction Unit.onStart()\n\t--Events.Flush.Add(mouse.apply)\n\tEvents.Flush.Add(ship.apply)\n\tEvents.Update.Add(SHUD.Update)\n\tgetFuelRenderedHtml()\n\tif system.showHelper then system.showHelper(false) end\n\n\tP('Horizon Elevator 1.1.2')\n\tP('Created by ShadowTemplar')\n\tP('Customized by tobitege, v2024-05-02')\n\n\tif construct.setDockingMode(dockingMode) then\n\t\tP(\"[I] Docking mode set to: \"..dockingMode)\n\telse\n\t\tP(\"[W] Could not set docking mode to: \"..dockingMode)\n\tend\n\n\tif telemeter then\n\t\tP(\"[I] Telemeter found.\")\n\telse\n\t\tP(\"[E] Telemeter not found!\")\n\tend\n\tif screen then\n\t\tP(\"[I] Screen found.\")\n\telse\n\t\tP(\"[E] No screen found!\")\n\tend\n\n\tSTEC_configInit()\n\n\t-- STARTUP Sanity Checks\n\t-- E.g. do not allow elevator mode if required element(s) are missing\n\t-- or we are in space without a gravity well\n\tship.elevatorActive = false\n\tconfig.manualControl = true\n\tlocal body = ship.nearestPlanet\n\tif screen and telemeter and flightModeDb then\n\t\tif not body then\n\t\t\tP'[E] Elevator disabled: no planetary body as gravity well!'\n\t\telse\n\t\t\tif setBaseOnStart then setBase() end\n\n\t\t\t-- in STEC_config the flag for setBaseActive could already be set:\n\t\t\tif config.setBaseActive or not vec3.isvector(ship.baseLoc) then\n\t\t\t\tconfig.setBaseActive = false\n\t\t\t\tconfig.rtb = body:getAltitude(ship.world.position)\n\t\t\t\tP(\"[I] No base location set, using current location!\")\n\t\t\telse\n\t\t\t\tconfig.rtb = helios:closestBody(ship.baseLoc):getAltitude(ship.baseLoc)\n\t\t\t\tship.baseAltitude = helios:closestBody(ship.baseLoc):getAltitude(ship.baseLoc)\n\t\t\t\tP(\"Base location: \"..tostring(ship.baseLoc))\n\t\t\tend\n\n\t\t\tif ship.baseLoc and ship.baseLoc ~= vec3() then\n\t\t\t\tbody = helios:closestBody(ship.baseLoc)\n\t\t\t\tif body then\n\t\t\t\t\tconfig.manualControl = false\n\t\t\t\t\tship.altitudeHold = body:getAltitude(ship.world.position)\n\t\t\t\t\tship.baseAltitude = body:getAltitude(ship.baseLoc)\n\t\t\t\t\televatorScreen = ElevatorScreen\n\t\t\t\t\tP(\"[I] Altitude: \"..round2(ship.baseAltitude,2))\n\t\t\t\tend\n\t\t\tend\n\t\t\tif not elevatorScreen then\n\t\t\t\tP'[E] Elevator disabled: no body of gravity influence!'\n\t\t\tend\n\t\tend\n\telse\n\t\tP'[E] Elevator disabled: elements missing!'\n\t\tP'Check links for core, databank, telemeter and a screen!'\n\tend\n\tif vec3.isvector(ship.baseLoc) and ship.baseLoc ~= vec3() then\n\t\tP(\"Base: \"..tostring(ship.baseLoc))\n\t\tlocal mapPos = tostring(ship.nearestPlanet:convertToMapPosition(ship.baseLoc))\n\t\tP(\"Map location: \"..mapPos)\n\t\tsystem.setWaypoint(mapPos,false)\n\tend\n\n\tship.brake = true\n\tif elevatorScreen then\n\t\tElevatorInit()\n\telse\n\t\tship.throttle = 0\n\t\tship.verticalLock = false\n\t\tship.followGravity = true\n\t\tship.inertialDampening = true\n\tend\n\tship.followGravity = true\n\tship.inertialDampening = true\n\n\tif emitter then\n\t\tP(\"[I] Emitter range: \"..emitter.getRange())\n\tend\n\n\tif ship.isLanded then\n\t\tP('Landed: '..(round2(ship.GrndDist or 0, 2)..' m'))\n\t\tconfig.manualControl = true\n\tend\n\tP('Manual Control: '..(config.manualControl and 'On' or 'Off'))\n\tmanualControlSwitch()\n\n\tunit.setTimer(\"SHUDRender\", 0.02)\n\tunit.setTimer(\"FuelStatus\", 3)\n\tunit.setTimer(\"DockingTrigger\", 1)\n\n\ttoggleForceFields(activateFFonStart)\n\ttoggleLasers(activateLasersOnStart)\n\ttoggleSwitches(activateSwitchOnStart)\n\n\tif showDockingWidget then\n\t\tparentingPanelId = system.createWidgetPanel(\"Docking\")\n\t\tparentingWidgetId = system.createWidget(parentingPanelId,\"parenting\")\n\t\tsystem.addDataToWidget(unit.getWidgetDataId(),parentingWidgetId)\n\tend\n\n\t--ioScheduler.queueData(config)\nend\n\nfunction Unit.onStop()\n\ttoggleForceFields(activateFFonStop)\n\ttoggleLasers(activateLasersOnStop)\n\ttoggleSwitches(activateSwitchOnStop)\n\n\tconfig.shutDown = true\n\tif screen then screen.setScriptInput(serialize(config)) end\n\tsystem.showScreen(false)\nend\n\nfunction Unit.onTimer(timer)\n\tif timer == \"SHUDRender\" then\n\t\tif SHUD then SHUD.Render() end\n\telseif timer == \"FuelStatus\" then\n\t\tgetFuelRenderedHtml()\n\t\t-- Fix: do NOT send fuel data, it corrupts the screen ui!\n\t\t-- if elevatorScreen then elevatorScreen.updateScreenFuel() end\n\telseif timer == \"DockingTrigger\" then\n\t\tlocal telDistance\n\t\tif telemeter then telDistance = telemeter.raycast().distance end\n\t\tif ship.dockingClamps then\n\t\t\ttoggleLasers(true)\n\t\t\tif telDistance and telDistance > 0 and telDistance < 1 then\n\t\t\t\tif ship.autoShutdown and not config.manualControl then\n\t\t\t\t\tunit.exit()\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\tend\nend\n\nfunction System.onActionStart(action)\n\tkeybindPresets[keybindPreset].Call(action, \"down\")\nend\n\nfunction System.onActionStop(action)\n\tkeybindPresets[keybindPreset].Call(action, \"up\")\nend\n\nfunction System.onInputText(action)\n\tif DUTTY then DUTTY.input(action) end\nend\n\nfunction System.onActionLoop(action)\nend\n\nfunction System.onUpdate()\n\t--P(\"Target: \"..tostring(vec3(ship.baseLoc))..\" | alt: \"..ship.altitude..\" | baseAlt: \"..ship.baseAltitude..\" | worldPos: \"..tostring(vec3(ship.world.position))..\" | \")\n\t--self.deviationVec = (moveWaypointZ(self.baseLoc, self.altitude - self.baseAltitude) - self.world.position)\n\tioScheduler.update()\n\tif elevatorScreen then elevatorScreen.updateStats() end\n\tif Events then Events.Update() end\n\tif TaskManager then TaskManager.Update() end\nend\n\nfunction System.onFlush()\n\tif Events then Events.Flush() end\nend\n\nfunction buildEmitter.onSent(channel, message, slot)\n\tP(\"Sent: \"..channel..\" | \"..message)\nend\n\n-- function createBreadcrumbTrail(endAlt)\n-- \t--Create a set of waypoints starting from the current position to the destination spaced 1km apart\n-- \tlocal startPosition = moveWaypointZ(ship.baseLoc, ship.world.altitude - ship.baseAltitude)\n-- \tlocal endPosition = moveWaypointZ(ship.baseLoc, endAlt)\n-- \tlocal distance = (startPosition - endAlt):len()\n-- \tif distance > 1000 then\n-- \t\tfor i = 1, round2(distance / 1000,0), 1 do\n-- \t\t\tif ship.nearestPlanet:getAltitude(startPosition) < ship.nearestPlanet:getAltitude(endPosition) then\n-- \t\t\t\ttable.insert(ship.breadCrumbs, moveWaypointZ(startPosition, 1000 * i))\n-- \t\t\telse\n-- \t\t\t\ttable.insert(ship.breadCrumbs, moveWaypointZ(startPosition, -1000 * i))\n-- \t\t\tend\n-- \t\tend\n-- \tend\n-- end\n--local btrail = createBreadcrumbTrail(3)\n--P(\"Breadcrumbs:\")\n--for _, sw in ipairs(ship.breadCrumbs) do\n--\tP(\"POS: \"..tostring(sw))\n--end\n\nfunction buildScreen.onMouseUp(x,y,slot)\n--\tship.baseAltitude = helios:closestBody(ship.baseLoc):getAltitude(ship.baseLoc)\n--\tif settingsActive then\n--\t\tif mousex >= 0.1515 and mousex <= 0.4934 and mousey >= 0.5504 and mousey <= 0.7107 then --Setbase button\n--\t\t\tsetBase()\n--\t\t\tsettingsActive = false\n--\t\tend\n--\t\tif mousex >= 0.5097 and mousex <= 0.8511 and mousey >= 0.5504 and mousey <= 0.7134 then --Cancel button\n--\t\t\tsettingsActive = false\n--\t\tend\n--\t\tif mousex >= 0.0277 and mousex <= 0.0868 and mousey >= 0.8515 and mousey <= 0.9484 then --Settings button\n--\t\t\tsettingsActive = false\n--\t\tend\n\n--\t\tif mousex >= 0.0277 and mousex <= 0.0868 and mousey >= 0.8515 and mousey <= 0.9484 then --Settings button\n--\t\t\tsettingsActive = true\n--\t\tend\n--\tend\nend\nfunction buildScreen.onMouseDown(x,y,slot)\n\t--P(\"Mouse X: \"..x..\", Mouse Y: \"..y)\nend\n",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "18"
},
{
"code": "_G.BuildUnit.onStart()",
"filter": {
"args": [],
"signature": "onStart",
"slotKey": "-1"
},
"key": "19"
},
{
"code": "_G.BuildUnit.onStop()",
"filter": {
"args": [],
"signature": "onStop",
"slotKey": "-1"
},
"key": "20"
},
{
"code": "_G.BuildSystem.onActionStart(action)",
"filter": {
"args": [
{
"variable": "*"
}
],
"signature": "onActionStart(action)",
"slotKey": "-2"
},
"key": "21"
},
{
"code": "_G.BuildSystem.onActionStop(action)",
"filter": {
"args": [
{
"variable": "*"
}
],
"signature": "onActionStop(action)",
"slotKey": "-2"
},
"key": "22"
},
{
"code": "_G.BuildSystem.onInputText(action)",
"filter": {
"args": [
{
"variable": "*"
}
],
"signature": "onInputText(action)",
"slotKey": "-2"
},
"key": "23"
},
{
"code": "_G.BuildSystem.onUpdate()",
"filter": {
"args": [],
"signature": "onUpdate",
"slotKey": "-2"
},
"key": "24"
},
{
"code": "_G.BuildSystem.onFlush()",
"filter": {
"args": [],
"signature": "onFlush",
"slotKey": "-2"
},
"key": "25"
},
{
"code": "_G.BuildUnit.onTimer(\"SHUDRender\")",
"filter": {
"args": [
{
"variable": "SHUDRender"
}
],
"signature": "onTimer(timerId)",
"slotKey": "-1"
},
"key": "26"
},
{
"code": "_G.BuildUnit.onTimer(\"FuelStatus\")",
"filter": {
"args": [
{
"variable": "FuelStatus"
}
],
"signature": "onTimer(timerId)",
"slotKey": "-1"
},
"key": "27"
},
{
"code": "_G.BuildUnit.onTimer(\"DockingTrigger\")",
"filter": {
"args": [
{
"variable": "DockingTrigger"
}
],
"signature": "onTimer(timerId)",
"slotKey": "-1"
},
"key": "28"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot1)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "0"
},
"key": "29"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot1)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "0"
},
"key": "30"
},
{
"code": "_G.BuildScreen.onMouseDown(x, y, slot1)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseDown(x,y)",
"slotKey": "0"
},
"key": "31"
},
{
"code": "_G.BuildScreen.onMouseUp(x, y, slot1)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseUp(x,y)",
"slotKey": "0"
},
"key": "32"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot2)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "1"
},
"key": "33"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot2)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "1"
},
"key": "34"
},
{
"code": "_G.BuildScreen.onMouseDown(x, y, slot2)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseDown(x,y)",
"slotKey": "1"
},
"key": "35"
},
{
"code": "_G.BuildScreen.onMouseUp(x, y, slot2)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseUp(x,y)",
"slotKey": "1"
},
"key": "36"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot3)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "2"
},
"key": "37"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot3)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "2"
},
"key": "38"
},
{
"code": "_G.BuildScreen.onMouseDown(x, y, slot3)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseDown(x,y)",
"slotKey": "2"
},
"key": "39"
},
{
"code": "_G.BuildScreen.onMouseUp(x, y, slot3)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseUp(x,y)",
"slotKey": "2"
},
"key": "40"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot4)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "3"
},
"key": "41"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot4)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "3"
},
"key": "42"
},
{
"code": "_G.BuildScreen.onMouseDown(x, y, slot4)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseDown(x,y)",
"slotKey": "3"
},
"key": "43"
},
{
"code": "_G.BuildScreen.onMouseUp(x, y, slot4)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseUp(x,y)",
"slotKey": "3"
},
"key": "44"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot5)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "4"
},
"key": "45"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot5)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "4"
},
"key": "46"
},
{
"code": "_G.BuildScreen.onMouseDown(x, y, slot5)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseDown(x,y)",
"slotKey": "4"
},
"key": "47"
},
{
"code": "_G.BuildScreen.onMouseUp(x, y, slot5)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseUp(x,y)",
"slotKey": "4"
},
"key": "48"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot6)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "5"
},
"key": "49"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot6)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "5"
},
"key": "50"
},
{
"code": "_G.BuildScreen.onMouseDown(x, y, slot6)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseDown(x,y)",
"slotKey": "5"
},
"key": "51"
},
{
"code": "_G.BuildScreen.onMouseUp(x, y, slot6)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseUp(x,y)",
"slotKey": "5"
},
"key": "52"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot7)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "6"
},
"key": "53"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot7)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "6"
},
"key": "54"
},
{
"code": "_G.BuildScreen.onMouseDown(x, y, slot7)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseDown(x,y)",
"slotKey": "6"
},
"key": "55"
},
{
"code": "_G.BuildScreen.onMouseUp(x, y, slot7)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseUp(x,y)",
"slotKey": "6"
},
"key": "56"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot8)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "7"
},
"key": "57"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot8)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "7"
},
"key": "58"
},
{
"code": "_G.BuildScreen.onMouseDown(x, y, slot8)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseDown(x,y)",
"slotKey": "7"
},
"key": "59"
},
{
"code": "_G.BuildScreen.onMouseUp(x, y, slot8)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onMouseUp(x,y)",
"slotKey": "7"
},
"key": "60"
},
{
"code": "_G.BuildEmitter.onSent(channel, message, slot9)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onSent(channel,message)",
"slotKey": "8"
},
"key": "61"
},
{
"code": "_G.BuildReceiver.onReceived(channel, message, slot9)",
"filter": {
"args": [
{
"variable": "*"
},
{
"variable": "*"
}
],
"signature": "onReceived(channel,message)",
"slotKey": "8"
},
"key": "62"