├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md └── boot_kos_utils.ks /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | #kOS Utils Changelog 2 | 3 | ##v1.2 4 | * Adjusted selection menu loop time for better responsiveness 5 | * Functionality added to panel util and RT antenna util to allow each to open when the vessel is landed and stationary 6 | * Optimized RT antenna util's setup 7 | * Implemented a function that shuts down the kOS core if the vessel's electric charge is below 10% capacity and falling 8 | 9 | ##v1.1 10 | * Added small `WAIT` to utility loop to prevent it from running multiple times per physics tick 11 | * Selection menu now loops back to start when scrolling past the last selection (TDW89) 12 | * Added Fairing Util and LES Util (TDW89) 13 | * Added Autobrake Util 14 | * Extended selection menu length to 9 total utils, 7 are active and 2 are empty 15 | * General optimization 16 | 17 | ##v1.0 18 | * Initial Release 19 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010-2015 Google, Inc. http://angularjs.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #kOS Utils v1.2 2 | 3 | **This boot script is designed to offer some useful utilities to otherwise normal gameplay via the powers of the [Kerbal Operating System mod](http://forum.kerbalspaceprogram.com/threads/68089). Using it requires absolutely no coding skills whatsoever, however the script itself is well-commented and designed to be an example of how you can use kOS to automate various tasks in Kerbal Space Program.** 4 | 5 | ##How to install 6 | 7 | 1. Download and install kOS ([CKAN](http://forum.kerbalspaceprogram.com/threads/100067) is great for this!) 8 | 2. Download the kOS Utilities Script and place it in your [KSP install location]/Ships/Script folder (kOS will create this folder, however if you haven't run KSP with kOS installed, you may create it yourself). 9 | 3. Attach a kOS CPU to your craft of choice 10 | 4. In the tweakable menu for the CPU, select *boot_kos_utils* as the boot script 11 | 5. Launch your ship and follow the instructions! 12 | 13 | ##Utilities included 14 | 15 | * Panel Util - Opens and closes your ship's solar panels based on whether you're in atmosphere or not. This prevents you from forgetting to open them and running out of power, or forgetting to close them and breaking them off in flight. Also opens the panels if the ship is landed and stationary. 16 | * Gear Util - Raises and lowers your ship's landing gear and/or landing legs based on how high you are off the ground. 100m is the default setting, although that can be changed in the script if you so desire. 17 | * Chute Util - Automatically deploys your ship's parachutes if you're descending below 10km and the chutes show as 'Safe To Deploy' in the right-click menu. Best used for capsules returning from orbit. 18 | * RT Antenna Util - Automatically deploys any extendable RemoteTech antennas once you leave the atmosphere and retracts them when you re-enter. This prevents you from forgetting to open your antennas and losing contact with your probe. Also opens the antennas if the ship is landed and stationary. Will continue to function even if there's no RT connection! 19 | * Fairing Util - Automatically jettisons all fairings on the vessel when you reach 95% of the current body's atmosphere height. This utility will automatically disable itself once it is fired. Compatible with stock, KW, and procedural fairings. 20 | * LES Util - Automatically jettisons the stock Launch Escape Tower when exiting the atmosphere or three seconds after a manual abort. This utility automatically disables itself once it is fired. 21 | * Autobrake Util - Automatically activates the wheel brakes on landing and releases them during takeoff. 22 | * Low Power Shutdown (always-on) - Automatically shuts down the kOS core if the ship's electric charge is below 10% and still falling. 23 | 24 | I also left room in the menu for two more utilities for you to write! You can use the current utilities as an example of how to write one. Be sure to consult the [kOS documentation](http://ksp-kos.github.io/KOS_DOC/) and feel free to ask questions in the [/r/kOS](https://www.reddit.com/r/Kos) subreddit. 25 | 26 | If you write a utility that you feel should be included with this release, I'll happily entertain a pull request! -------------------------------------------------------------------------------- /boot_kos_utils.ks: -------------------------------------------------------------------------------- 1 | //boot_kos_utils 2 | //Created by space_is_hard 3 | //Additional functions provided by TDW89 4 | //This file is distributed under the terms of the MIT license 5 | 6 | //This script is a multifunction utility script. It allows the user to select from 7 | //multiple utilities that will continuously run during flight. It can be set as a boot 8 | //script and is designed for ease-of-use. 9 | 10 | SET versionNumber TO "v1.2". 11 | 12 | CLEARSCREEN. 13 | SET TERMINAL:WIDTH TO 64. 14 | SET TERMINAL:HEIGHT TO 44. 15 | 16 | //Open the terminal for the user. 17 | CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). 18 | 19 | //Header for our menu 20 | PRINT "------------------------kOS Utility Menu------------------------". //Line 0 21 | PRINT "----------------------------------------------------------------". //64 dashes to match terminal width 22 | 23 | //Selection menu. Use OVR typing mode for easy editing. 24 | PRINT "Please select the utilities you would like to run | I = Up ". 25 | PRINT " | K = Down ". 26 | PRINT ">[ ]Panel Util - Opens solar panels when not | H = Select". //Line 4 27 | PRINT " in atmosphere. Closes retractable |____________". 28 | PRINT " panels when entering atmosphere. ". 29 | PRINT " ". 30 | PRINT " [ ]Gear Util - Raises landing gear and landing legs when above". //Line 8 31 | PRINT " 100 meters radar altitude. Lowers gear and legs". 32 | PRINT " when below 100 meters radar altitude. ". 33 | PRINT " ". 34 | PRINT " [ ]Chutes - Arms parachutes when descending and when safe ". //Line 12 35 | PRINT " Util to do so. Will not open chutes if no ". 36 | PRINT " atmosphere is present. Stock chutes only. ". 37 | PRINT " ". 38 | PRINT " [ ]RT Antenna - Opens RemoteTech extendible antennas when not ". //Line 16 39 | PRINT " Util in atmosphere and closes them when in ". 40 | PRINT " atmosphere. Requires RemoteTech. ". 41 | PRINT " ". 42 | PRINT " [ ]Fairing - Jettisons fairings when above 95% atmosphere ". //Line 20 43 | PRINT " Util height. It is done at 95% to avoid smashing ". 44 | PRINT " solar panels if the Panels Util is selected. ". 45 | PRINT " ". 46 | PRINT " [ ]LES Util - Jettisons the Launch Escape System when above ". //Line 24 47 | PRINT " the atmosphere or 3 secs after an abort if the ". 48 | PRINT " LES is attached via decoupler or docking port. ". 49 | PRINT " ". 50 | PRINT " [ ]Autobrake - Automatically turns on the wheel brakes ". //Line 28 51 | PRINT " Util and air brakes when on the ground and the ". 52 | PRINT " throttle is zero. Lets them go otherwise. ". 53 | PRINT " ". 54 | PRINT " [ ]Empty Slot - Write your own utility and put it here! ". //Line 32 55 | PRINT " ". 56 | PRINT " ". 57 | PRINT " ". 58 | PRINT " [ ]Empty Slot - Write your own utility and put it here! ". //Line 36 59 | PRINT " ". 60 | PRINT " ". 61 | PRINT " ". 62 | PRINT " [ ]RUN SELECTED UTILITIES ". //Line 40 63 | PRINT " ". 64 | PRINT versionNumber. 65 | 66 | //Variable to tell whether we're ready to exit the selection loop 67 | SET selectionMade TO FALSE. 68 | 69 | //Variable to tell whether we've just made an input. Will be set to false once an input 70 | //is recognized, disallowing further input until no more input is recognized. This will 71 | //keep the user from pressing down once and scrolling a bunch of times as the loop cycles 72 | //faster than the user can let go of the key 73 | SET inputMade TO FALSE. 74 | 75 | //Variable to hold the current selection 76 | SET currentSelection TO 1. 77 | 78 | //A list that will hold which utilities we've selected 79 | SET selectionList TO LIST( 80 | FALSE, //Panel Util 81 | FALSE, //Gear Util 82 | FALSE, //Chutes Util 83 | FALSE, //Antenna Util 84 | FALSE, //Fairing Util 85 | FALSE, //LES Util 86 | FALSE, //Autobrake Util 87 | FALSE, //Empty Slot 88 | FALSE, //Empty Slot 89 | FALSE //Run Utilities 90 | ). 91 | 92 | //We'll call this function when we want to scroll down 93 | FUNCTION scrollDown { 94 | 95 | //Clear the selector arrow from its current position 96 | PRINT " " AT(0, currentSelection * 4). //Four lines between each selection 97 | 98 | //Increment our current selection 99 | SET currentSelection TO MOD(currentSelection + selectionList:length , selectionList:length) + 1. 100 | 101 | //Print a new arrow at the next checkbox down 102 | PRINT ">" AT(0, currentSelection * 4). //Four lines between each selection 103 | 104 | }. 105 | 106 | //We'll call this function when we want to scroll up 107 | FUNCTION scrollUp { 108 | 109 | //Clear the selector arrow from its current position 110 | PRINT " " AT(0, currentSelection * 4). //Four lines between each selection 111 | 112 | //Decrement our current selection 113 | SET currentSelection TO MOD(currentSelection + selectionList:length - 2, selectionList:length) + 1. 114 | 115 | //Print a new arrow at the next checkbox up 116 | PRINT ">" AT(0, currentSelection * 4). //Four lines between each selection 117 | 118 | }. 119 | 120 | //We'll call this function when we want to make a selection 121 | FUNCTION makeSelection { 122 | 123 | //Check if the current selection is false 124 | IF selectionList[currentSelection - 1] = FALSE { //Index starts at 0, hence "- 1" 125 | 126 | //Check it 127 | PRINT "X" AT(2, currentSelection * 4). //Four lines between each selection 128 | 129 | //Change the list to reflect this 130 | SET selectionList[currentSelection - 1] TO TRUE. //Index starts at 0, hence "- 1" 131 | 132 | //Do the opposite of above 133 | } ELSE { 134 | 135 | //Uncheck it 136 | PRINT " " AT(2, currentSelection * 4). //Four lines between each selection 137 | 138 | //Change the list to reflect this 139 | SET selectionList[currentSelection - 1] TO FALSE. //Index starts at 0, hence "- 1" 140 | 141 | }. 142 | 143 | //If the 'Run Utilities' option was the one selected, exit the menu loop and continue 144 | //on with the rest of the script 145 | IF selectionList[selectionList:LENGTH - 1] = TRUE { //Last item in the list will be the "Run" option 146 | 147 | //Exit the menu/selection loop and move on to the utility loop 148 | SET selectionMade TO TRUE. 149 | 150 | }. 151 | 152 | }. 153 | 154 | //This loop will check for menu inputs and perform the necessary menu operations 155 | UNTIL selectionMade = TRUE { 156 | 157 | //If the user has pressed 'up' and we're ready for a new input 158 | IF inputMade = FALSE AND SHIP:CONTROL:PILOTTOP < 0 { 159 | 160 | //Prevent the script from recognizing more inputs 161 | SET inputMade TO TRUE. 162 | 163 | //Call the scroll up function that we made earlier 164 | scrollUp(). 165 | 166 | //If the user has pressed 'down' and we're ready for a new input 167 | } ELSE IF inputMade = FALSE AND SHIP:CONTROL:PILOTTOP > 0 { 168 | 169 | //Prevent the script from recognizing more inputs 170 | SET inputMade TO TRUE. 171 | 172 | //Call the scroll down function that we made earlier 173 | scrollDown(). 174 | 175 | //If the user has pressed 'select' and we're ready for a new input 176 | } ELSE IF inputMade = FALSE AND SHIP:CONTROL:PILOTFORE > 0 { 177 | 178 | //Prevent the script from recognizing more inputs 179 | SET inputMade TO TRUE. 180 | 181 | //Call the selection function that we made earlier 182 | makeSelection(). 183 | 184 | //If no inputs are recognized 185 | } ELSE IF inputMade = TRUE 186 | AND SHIP:CONTROL:PILOTTOP = 0 187 | AND SHIP:CONTROL:PILOTFORE = 0 { 188 | 189 | //No input detected, ready the loop for another input 190 | SET inputMade TO FALSE. 191 | 192 | }. 193 | 194 | //Keeps our loop from running too fast but still is able to keep up with the user's 195 | //potential for rapid keypresses 196 | WAIT 0.01. 197 | 198 | }. 199 | 200 | //From here, we want to prep the terminal for the utilities themselves 201 | CLEARSCREEN. 202 | SET TERMINAL:WIDTH TO 36. 203 | SET TERMINAL:HEIGHT TO 18. 204 | 205 | //And we'll print some info to the terminal to let the user know what's active 206 | IF selectionList[0] = TRUE { 207 | PRINT "- Panel Utility Active". 208 | }. 209 | 210 | IF selectionList[1] = TRUE { 211 | PRINT "- Gear Utility Active". 212 | }. 213 | 214 | IF selectionList[2] = TRUE { 215 | PRINT "- Chute Utility Active". 216 | }. 217 | 218 | IF selectionList[3] = TRUE { 219 | 220 | //Since RemoteTech may not be installed, we'll check for it first 221 | IF ADDONS:RT:AVAILABLE = TRUE { 222 | 223 | PRINT "- RemoteTech Antenna Utility Active". 224 | 225 | //If it isn't installed, we'll say so and go ahead and disable that function 226 | } ELSE { 227 | 228 | PRINT "- RemoteTech not installed;". 229 | PRINT " Antenna Utility Disabled". 230 | 231 | SET selectionList[3] TO FALSE. 232 | 233 | }. 234 | 235 | }. 236 | 237 | IF selectionList[4] = TRUE { 238 | PRINT "- Fairing Utility Active". 239 | }. 240 | 241 | IF selectionList[5] = TRUE { 242 | PRINT "- LES Utility Active". 243 | }. 244 | 245 | IF selectionList[6] = TRUE { 246 | PRINT "- Autobrake Utility Active". 247 | }. 248 | 249 | //Visual separator 250 | PRINT "-------------------------------" + versionNumber. 251 | 252 | //The following functions will be used to perform the utilities. We'll initialize each 253 | //function's variables just above the variable's parent function to keep things organized 254 | 255 | //=====Panel Utility===== 256 | //by space_is_hard 257 | 258 | //This variable will allow us to track the status of the panels since we can't get 259 | //their status 260 | SET panelsOpen TO FALSE. 261 | 262 | FUNCTION panelUtil { 263 | 264 | //Only performs the checks within if the panels aren't already open 265 | IF NOT panelsOpen { 266 | 267 | //Checks if we're out of the atmosphere 268 | IF SHIP:ALTITUDE > BODY:ATM:HEIGHT { 269 | 270 | //Opens the panels 271 | PANELS ON. 272 | 273 | //Changes the variable so we can track the status of the panels 274 | SET panelsOpen TO TRUE. 275 | 276 | //Informs the user that we're taking action 277 | HUDTEXT("Panel Utility: Leaving Atmosphere; Opening Panels", 3, 2, 30, YELLOW, FALSE). 278 | PRINT "Opening Panels". 279 | 280 | }. 281 | 282 | //Checks if we're landed and stationary 283 | IF SHIP:STATUS = "Landed" AND SHIP:VELOCITY:SURFACE:MAG < 0.01 { 284 | 285 | //Opens the panels 286 | PANELS ON. 287 | 288 | //Changes the variable so we can track the status 289 | SET panelsOpen TO TRUE. 290 | 291 | //Informs the user that we're taking action 292 | HUDTEXT("Panel Utility: Landed and stationary; Opening Panels", 3, 2, 30, YELLOW, FALSE). 293 | PRINT "Opening Panels". 294 | 295 | }. 296 | 297 | //Only performs the checks within if the panels are already open 298 | } ELSE IF panelsOpen { 299 | 300 | //Checks to see if we're in the atmosphere; doesn't close the panels if we're 301 | //stationary to prevent it and the stationary check from fighting for control of 302 | //the panels. 303 | IF SHIP:ALTITUDE < BODY:ATM:HEIGHT 304 | AND SHIP:VELOCITY:SURFACE:MAG >= 0.01 { 305 | 306 | //Closes the panels 307 | PANELS OFF. 308 | 309 | //Changes the variable so we can track the status of the panels 310 | SET panelsOpen TO FALSE. 311 | 312 | //Informs the user why we're taking action based on which situation we're in 313 | IF SHIP:STATUS = "Landed" { 314 | 315 | //If we're landed, we're probably starting to move from a standstill 316 | HUDTEXT("Panel Utility: Landed and moving; Closing Panels", 3, 2, 30, YELLOW, FALSE). 317 | PRINT "Closing Panels". 318 | 319 | } ELSE { 320 | 321 | //If we're not landed, we're probably re-entering 322 | HUDTEXT("Panel Utility: Entering Atmosphere; Closing Panels", 3, 2, 30, YELLOW, FALSE). 323 | PRINT "Closing Panels". 324 | 325 | }. 326 | 327 | }. 328 | 329 | }. 330 | 331 | }. 332 | 333 | //=====Gear Util===== 334 | //by space_is_hard 335 | 336 | //Variable used to determine if we're below 100m. Assumes that we start out on the ground 337 | //but will get immediately corrected if not 338 | SET belowAlt TO TRUE. 339 | 340 | FUNCTION gearUtil { 341 | 342 | //Determines whether the vessel is below 100m. Only attempts to change the value if 343 | //it's different than the current value 344 | IF ALT:RADAR < 100 { 345 | 346 | IF NOT belowAlt { 347 | 348 | SET belowAlt TO TRUE. 349 | 350 | //Lowers the gear and legs 351 | GEAR ON. 352 | LEGS ON. 353 | 354 | //Informs the user that we're taking action 355 | HUDTEXT("Gear Utility: Below 100m; Lowering Gear", 3, 2, 30, YELLOW, FALSE). 356 | PRINT "Lowering Gear and Legs". 357 | 358 | }. 359 | 360 | } ELSE { 361 | 362 | //Only attempts to change the value if it's different than the current value 363 | IF belowAlt = TRUE { 364 | 365 | SET belowAlt TO FALSE. 366 | 367 | //Lowers the gear and legs 368 | GEAR OFF. 369 | LEGS OFF. 370 | 371 | //Informs the user that we're taking action 372 | HUDTEXT("Gear Utility: Above 100m; Raising Gear", 3, 2, 30, YELLOW, FALSE). 373 | PRINT "Raising Gear and Legs". 374 | 375 | }. 376 | 377 | }. 378 | 379 | }. 380 | 381 | //=====Chutes Util===== 382 | //by space_is_hard 383 | 384 | //List that we'll store all of the parachute parts in 385 | SET chuteList TO LIST(). 386 | 387 | //Gets all of the parts on the craft 388 | LIST PARTS IN partList. 389 | 390 | //Goes over the part list we just made 391 | FOR item IN partList { 392 | 393 | //Gets all of the modules of the part we're going over; local variable that gets 394 | //dumped every time the FOR loop is finished 395 | LOCAL moduleList TO item:MODULES. 396 | 397 | //Goes over moduleList to find the parachute module 398 | FOR module IN moduleList { 399 | 400 | //Checks the name of the module, and stores the part being gone over if the 401 | //parachute module shows up 402 | IF module = "ModuleParachute" { 403 | 404 | //Stores the part in the chuteList 405 | chuteList:ADD(item). 406 | 407 | }. 408 | 409 | }. 410 | 411 | }. 412 | 413 | FUNCTION chutesUtil { 414 | 415 | //Determines whether we're in atmosphere, and below 10km, and descending 416 | IF SHIP:ALTITUDE < BODY:ATM:HEIGHT 417 | AND SHIP:ALTITUDE < 10000 418 | AND SHIP:VERTICALSPEED < -1 { 419 | 420 | //Goes over the chute list 421 | FOR chute IN chuteList { 422 | 423 | //Checks to see if the chute is already deployed 424 | IF chute:GETMODULE("ModuleParachute"):HASEVENT("Deploy Chute") { 425 | 426 | //Checks to see if the chute is safe to deploy 427 | IF chute:GETMODULE("ModuleParachute"):GETFIELD("Safe To Deploy?") = "Safe" { 428 | 429 | //Deploy/arm this chute that has shown up as safe and ready 430 | //to deploy 431 | chute:GETMODULE("ModuleParachute"):DOACTION("Deploy", TRUE). 432 | 433 | //Inform the user that we did so 434 | HUDTEXT("Chute Utility: Safe to deploy; Arming parachute", 3, 2, 30, YELLOW, FALSE). 435 | 436 | }. 437 | 438 | }. 439 | 440 | }. 441 | 442 | }. 443 | 444 | }. 445 | 446 | //=====RT Antenna Util===== 447 | //by space_is_hard 448 | //Variable to keep track of whether we've opened the antennas or not 449 | SET antennasOpen TO FALSE. 450 | 451 | //List that we'll store all of the antenna parts in 452 | SET antennaList TO LIST(). 453 | 454 | //Goes over all of the modules on the entire ship, and lists the ones named 455 | //"ModuleRTAntenna" in a list called "RTmodule". This should produce a list of all of the 456 | //RemoteTech antenna modules 457 | FOR RTmodule IN SHIP:MODULESNAMED("ModuleRTAntenna") { 458 | 459 | //Checks to see if the part that the antenna module is attached to *also* contains 460 | //an animation module 461 | IF RTmodule:PART:MODULES:CONTAINS("ModuleAnimateGeneric") { 462 | 463 | //If so, it adds that part to the antenna list 464 | antennaList:ADD(RTmodule:PART). 465 | 466 | }. 467 | 468 | }. 469 | 470 | FUNCTION RTAntennaUtil { //TODO: Implement same landed check as panel util 471 | 472 | //Only performs the checks within if the antennas aren't already open 473 | IF NOT antennasOpen { 474 | 475 | //Checks if we're out of the atmosphere 476 | IF SHIP:ALTITUDE > BODY:ATM:HEIGHT { 477 | 478 | //Goes over our previously-built antenna list 479 | FOR antenna IN antennaList { 480 | 481 | //Opens each antenna 482 | antenna:GETMODULE("ModuleRTAntenna"):DOACTION("Activate", TRUE). 483 | 484 | }. 485 | 486 | //Changes the variable so we can track the status of the panels 487 | SET antennasOpen TO TRUE. 488 | 489 | //Informs the user that we're taking action 490 | HUDTEXT("RT Antenna Utility: Leaving Atmosphere; Opening Antennas", 3, 2, 30, YELLOW, FALSE). 491 | PRINT "Opening Antennas". 492 | 493 | }. 494 | 495 | //Checks if we're landed and stationary 496 | IF SHIP:STATUS = "Landed" AND SHIP:VELOCITY:SURFACE:MAG < 0.1 { 497 | 498 | //Goes over our previously-built antenna list 499 | FOR antenna IN antennaList { 500 | 501 | //Opens each antenna 502 | antenna:GETMODULE("ModuleRTAntenna"):DOACTION("Activate", TRUE). 503 | 504 | }. 505 | 506 | //Changes the variable so we can track the status 507 | SET antennasOpen TO TRUE. 508 | 509 | //Informs the user that we're taking action 510 | HUDTEXT("RT Antenna Utility: Landed and Stationary; Opening Antennas", 3, 2, 30, YELLOW, FALSE). 511 | PRINT "Opening Antennas". 512 | 513 | }. 514 | 515 | //Only performs the checks within if the antennas are already open 516 | } ELSE IF antennasOpen { 517 | 518 | //Checks to see if we're in the atmosphere; doesn't close the antennas if we're 519 | //stationary to prevent it and the stationary check from fighting for control of 520 | //the antennas. 521 | IF SHIP:ALTITUDE < BODY:ATM:HEIGHT 522 | AND SHIP:VELOCITY:SURFACE:MAG >= 0.1 { 523 | 524 | //Goes over our previously-built antenna list 525 | FOR antenna IN antennaList { 526 | 527 | //Closes the antenna 528 | antenna:GETMODULE("ModuleRTAntenna"):DOACTION("Deactivate", TRUE). 529 | 530 | }. 531 | 532 | //Changes the variable so we can track the status of the antennas 533 | SET antennasOpen TO FALSE. 534 | 535 | //Informs the user why we're taking action based on which situation we're in 536 | IF SHIP:STATUS = "Landed" { 537 | 538 | //If we're landed, we're probably starting to move from a standstill 539 | HUDTEXT("RT Antenna Utility: Landed and moving; Closing Antennas", 3, 2, 30, YELLOW, FALSE). 540 | PRINT "Closing Antennas". 541 | 542 | } ELSE { 543 | 544 | //If we're not landed, we're probably re-entering 545 | HUDTEXT("RT Antenna Utility: Entering Atmosphere; Closing Antennas", 3, 2, 30, YELLOW, FALSE). 546 | PRINT "Closing Antennas". 547 | 548 | }. 549 | 550 | }. 551 | 552 | }. 553 | 554 | }. 555 | 556 | //=====Fairing Util===== 557 | //by TDW89 558 | 559 | 560 | FUNCTION fairingUtil { 561 | 562 | // This uses 95% of the atmosphere height so that it happens before the solar panels start to deploy. 563 | IF SHIP:ALTITUDE > 0.95 * BODY:ATM:HEIGHT { 564 | 565 | // Iterates over a list of all parts with the stock fairings module 566 | FOR module IN SHIP:MODULESNAMED("ModuleProceduralFairing") { // Stock and KW Fairings 567 | 568 | // and deploys them 569 | module:DOEVENT("deploy"). 570 | HUDTEXT("Fairing Utility: Aproaching edge of atmosphere; Deploying Fairings", 3, 2, 30, YELLOW, FALSE). 571 | PRINT "Deploying Fairings". 572 | 573 | }. 574 | 575 | // Iterates over a list of all parts using the fairing module from the Procedural Fairings Mod 576 | FOR module IN SHIP:MODULESNAMED("ProceduralFairingDecoupler") { // Procedural Fairings 577 | 578 | // and jettisons them (PF uses the word jettison in the right click menu instead of deploy) 579 | module:DOEVENT("jettison"). 580 | HUDTEXT("Fairing Utility: Approaching edge of atmosphere; Jettisoning Fairings", 3, 2, 30, YELLOW, FALSE). 581 | PRINT "Jettisoning Fairings". 582 | 583 | }. 584 | 585 | // Deploying fairings is a one time thing so it disables the module after running it 586 | SET selectionList[4] TO FALSE. 587 | PRINT "Fairings Utility disabled". 588 | 589 | }. 590 | 591 | }. 592 | 593 | //=====LES Util===== 594 | //by TDW89 595 | 596 | //We'll use this variable to track when the abort command was issued. We'll set it to a 597 | //bogus value to help with debugging. This will also let us check to see if the timer has 598 | //been set, as the game's Universal Time is never below 0. 599 | SET abortTimer TO -1. 600 | 601 | FUNCTION LESUtil { 602 | 603 | //Here we'll check if the abort action group has been triggered and if it's the first 604 | //time we've triggered it since running the script 605 | IF ABORT AND abortTimer < 0 { 606 | 607 | //And here we'll set the abort timer to our current time 608 | SET abortTimer TO TIME:SECONDS. 609 | 610 | //And we'll let the user know that we've detected a manual abort 611 | HUDTEXT("LES Util: Manual abort detected; standby for LES jettison", 3, 2, 30, YELLOW, FALSE). 612 | PRINT "Manual abort detected". 613 | 614 | }. 615 | 616 | // Is the vessel above the atmosphere, or are we three seconds past a detected manual abort? 617 | IF SHIP:ALTITUDE > BODY:ATM:HEIGHT OR (abortTimer > 0 AND TIME:SECONDS > abortTimer + 3) { 618 | 619 | // Iterates over a list of all parts with the name "LaunchEscapeSystem" (the stock LES) 620 | FOR les IN SHIP:PARTSNAMED("LaunchEscapeSystem") { 621 | 622 | // Sets the point part that will detach the LES to the part the LES is attached to 623 | LOCAL detach_part IS les:PARENT. 624 | 625 | // Then if that part is not capable of detaching it continues up the part tree until 626 | // it finds a valid part or a part with resources or it gets to the root part and cant go any further 627 | UNTIL detach_part:MODULES:CONTAINS("ModuleDockingNode") //the LES is attached via a docking node 628 | OR detach_part:MODULES:CONTAINS("ModuleAnchoredDecoupler") //the LES is attached via a decoupler 629 | OR detach_part:MODULES:CONTAINS("ModuleDecouple") //the LES is attached via a stack separator 630 | OR NOT detach_part:RESOURCES:EMPTY //the LES is attached to a resource containing part and wont be jettisoned 631 | OR detach_part = SHIP:ROOTPART //the root part has no parent so needs to be protected against. 632 | { 633 | 634 | SET detach_part TO detach_part:PARENT. 635 | 636 | }. 637 | 638 | // If it is a docking port... 639 | IF detach_part:MODULES:CONTAINS("ModuleDockingNode") { 640 | 641 | // ...it triggers the LES engine... 642 | les:GETMODULE("ModuleEnginesFX"):DOACTION("activate engine",TRUE). 643 | 644 | // ...then undocks it 645 | detach_part:GETMODULE("ModuleDockingNode"):DOEVENT("decouple node"). 646 | 647 | //Informs the user that we just took action 648 | HUDTEXT("LES Utility: Leaving Atmosphere; Jettisoning LES", 3, 2, 30, YELLOW, FALSE). 649 | PRINT "Jettisoning LES". 650 | 651 | // If it is a decoupler... 652 | } ELSE IF detach_part:MODULES:CONTAINS("ModuleAnchoredDecoupler") { 653 | 654 | // ...it triggers the LES engine... 655 | les:GETMODULE("ModuleEnginesFX"):DOACTION("activate engine",TRUE). 656 | 657 | // ...then decouples it 658 | detach_part:GETMODULE("ModuleAnchoredDecoupler"):DOEVENT("decouple"). 659 | 660 | HUDTEXT("LES Utility: Leaving Atmosphere; Jettisoning LES", 3, 2, 30, YELLOW, FALSE). 661 | PRINT "Jettisoning LES". 662 | 663 | } ELSE IF detach_part:MODULES:CONTAINS("ModuleDecouple") { 664 | 665 | // ... it triggers the LES engine... 666 | les:GETMODULE("ModuleEnginesFX"):DOACTION("activate engine",TRUE). 667 | 668 | // ... then separates it 669 | detach_part:GETMODULE("ModuleDecouple"):DOEVENT("decouple"). 670 | 671 | HUDTEXT("LES Utility: Leaving Atmosphere; Jettisoning LES", 3, 2, 30, YELLOW, FALSE). 672 | PRINT "Jettisoning LES". 673 | 674 | } ELSE { 675 | 676 | HUDTEXT("LES Utility: [ERR] Unable to identify point to separate from.", 3, 2, 30, RED, FALSE). 677 | PRINT "LES Utility error; no valid means of detaching found". 678 | 679 | }. 680 | 681 | }. 682 | 683 | // This is a one use utility so it disables the module after running 684 | SET selectionList[5] to FALSE. 685 | PRINT "LES Utility disabled". 686 | 687 | }. 688 | 689 | }. 690 | 691 | //=====Autobrake Util===== 692 | //by space_is_hard 693 | 694 | //This variable will be used to track if the Autobrake Util is the one triggering the 695 | //brakes. This will prevent the util from turning off the brakes when the user wants them 696 | //on or vice versa 697 | SET autoBrake TO FALSE. 698 | 699 | FUNCTION autoBrakeUtil { 700 | 701 | //If we're landed, the throttle is zero, the brakes aren't already on, and the 702 | //autobrake utility has not already tried to turn on the brakes 703 | IF SHIP:STATUS = "Landed" 704 | AND SHIP:CONTROL:PILOTMAINTHROTTLE = 0 705 | AND NOT BRAKES 706 | AND autoBrake = FALSE { 707 | 708 | BRAKES ON. 709 | 710 | //We'll note that the utility is the one activating the brakes instead of the 711 | //user 712 | SET autoBrake TO TRUE. 713 | 714 | //And then we'll notify the user that we're taking action 715 | HUDTEXT("Autobrake Util: Brakes on", 3, 2, 30, YELLOW, FALSE). 716 | PRINT "Autobrakes on". 717 | 718 | //If we detect liftoff or an increase in throttle, we'll let go of the brakes, but 719 | //not if the user has deactivated the brakes manually (we don't want to override the 720 | //user) 721 | } ELSE IF ( 722 | SHIP:STATUS <> "Landed" 723 | OR SHIP:CONTROL:PILOTMAINTHROTTLE > 0 724 | ) 725 | AND BRAKES 726 | AND autoBrake = TRUE { 727 | 728 | BRAKES OFF. 729 | 730 | //We'll note that the utility is no longer trying to activate the brakes 731 | SET autoBrake TO FALSE. 732 | 733 | //And then we'll notify the user that we're taking action 734 | HUDTEXT("Autobrake Util: Brakes off", 3, 2, 30, YELLOW, FALSE). 735 | PRINT "Autobrakes off". 736 | 737 | }. 738 | 739 | }. 740 | 741 | //=====Empty Slot [7]===== 742 | 743 | //=====Empty Slot [8]===== 744 | 745 | //=====Auto Low Charge Shutdown===== 746 | //by space_is_hard 747 | 748 | //This function is always-on, and designed to prevent the kOS core from eating up all of 749 | //the electric charge on a ship, leaving it stranded with no power. It shuts off the core 750 | //when the ship is below 10% power capacity and the charge rate is falling. There is no 751 | //way to turn the core back on via code, it will have to be done manually. Once turned 752 | //back on, the user will have to re-select the desired utilities. 753 | 754 | //We'll use this variable to track the previous level of electric charge. 755 | //`SHIP:ELECTRICCHARGE` is a bound variable; a shortcut that can only get us the current 756 | //amount of charge on the ship. We'll set it now and update it every loop. 757 | SET previousCharge TO SHIP:ELECTRICCHARGE. 758 | 759 | FUNCTION lowChargeShutdown { 760 | 761 | //Here, we'll list all of the consumable resources on the entire ship 762 | LIST RESOURCES IN resourceList. 763 | 764 | //We'll then go over every one.. 765 | FOR resource IN resourceList { 766 | 767 | //And find the one named "ElectricCharge" 768 | IF resource:NAME = "ElectricCharge" { 769 | 770 | //We'll only perform the shutdown if the charge is both below 10% of the 771 | //ship's capacity *and* if the current charge is less than it was the last 772 | //time we performed this function. This tells us if it's decreasing. 773 | IF resource:AMOUNT / resource:CAPACITY <= 0.1 AND resource:AMOUNT < previousCharge { 774 | 775 | //Shuts down the core that we're running the code on 776 | CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Toggle Power"). 777 | 778 | //Informs the user of the action we took 779 | HUDTEXT("kOS Utils: Low power, shutting down", 3, 2, 30, YELLOW, FALSE). 780 | PRINT "Low power, shutting down". 781 | 782 | }. 783 | 784 | }. 785 | 786 | }. 787 | 788 | //Stores the current charge in this variable so that we can check it the next time 789 | //that we run the function. The `WAIT` in the main loop will ensure that the next 790 | //time we poll this variable occurs in a new physics tick. 791 | SET previousCharge TO SHIP:ELECTRICCHARGE. 792 | 793 | }. 794 | 795 | //This will be the main operation loop. Each cycle, it will perform the utilities that 796 | //were selected in the menu loop and set using the selection list. The loop will never 797 | //exit unless the user CTRL+C's the program. 798 | UNTIL 1 = 2 { 799 | 800 | IF selectionList[0] = TRUE { 801 | 802 | panelUtil(). 803 | 804 | }. 805 | 806 | IF selectionList[1] = TRUE { 807 | 808 | gearUtil(). 809 | 810 | }. 811 | 812 | IF selectionList[2] = TRUE { 813 | 814 | chutesUtil(). 815 | 816 | }. 817 | 818 | IF selectionList[3] = TRUE { 819 | 820 | RTAntennaUtil(). 821 | 822 | }. 823 | 824 | IF selectionList[4] = TRUE { 825 | 826 | fairingUtil(). 827 | 828 | }. 829 | 830 | IF selectionList[5] = TRUE { 831 | 832 | LESUtil(). 833 | 834 | }. 835 | 836 | IF selectionList[6] = TRUE { 837 | 838 | autoBrakeUtil(). 839 | 840 | }. 841 | 842 | //IF selectionList[7] = TRUE { 843 | 844 | //Empty Slot 845 | 846 | //}. 847 | 848 | //IF selectionList[8] = TRUE { 849 | 850 | //Empty Slot 851 | 852 | //}. 853 | 854 | //Index number 9 was our checkbox for running the utilities 855 | 856 | lowChargeShutdown(). 857 | 858 | //Small wait to keep our script from running multiple times per physics tick 859 | WAIT 0.01. 860 | 861 | }. 862 | --------------------------------------------------------------------------------